forked from OSchip/llvm-project
Move getStrideFromPointer and friends from LoopVectorize to VectorUtils
The following functions are moved from the LoopVectorizer to VectorUtils: - getGEPInductionOperand - stripGetElementPtr - getUniqueCastUse - getStrideFromPointer These used to be static functions in LoopVectorize, but will also be used by the upcoming loop versioning LICM transformation. Patch by Ashutosh Nema! llvm-svn: 241980
This commit is contained in:
parent
39d662f7ba
commit
9cf58c4095
|
@ -20,6 +20,12 @@
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class GetElementPtrInst;
|
||||||
|
class Loop;
|
||||||
|
class ScalarEvolution;
|
||||||
|
class Type;
|
||||||
|
class Value;
|
||||||
|
|
||||||
/// \brief Identify if the intrinsic is trivially vectorizable.
|
/// \brief Identify if the intrinsic is trivially vectorizable.
|
||||||
/// This method returns true if the intrinsic's argument types are all
|
/// This method returns true if the intrinsic's argument types are all
|
||||||
/// scalars for the scalar form of the intrinsic and all vectors for
|
/// scalars for the scalar form of the intrinsic and all vectors for
|
||||||
|
@ -51,6 +57,23 @@ Intrinsic::ID checkBinaryFloatSignature(const CallInst &I,
|
||||||
/// its intrinsic ID, in case it does not found it return not_intrinsic.
|
/// its intrinsic ID, in case it does not found it return not_intrinsic.
|
||||||
Intrinsic::ID getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI);
|
Intrinsic::ID getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
|
/// \brief Find the operand of the GEP that should be checked for consecutive
|
||||||
|
/// stores. This ignores trailing indices that have no effect on the final
|
||||||
|
/// pointer.
|
||||||
|
unsigned getGEPInductionOperand(const GetElementPtrInst *Gep);
|
||||||
|
|
||||||
|
/// \brief If the argument is a GEP, then returns the operand identified by
|
||||||
|
/// getGEPInductionOperand. However, if there is some other non-loop-invariant
|
||||||
|
/// operand, it returns that instead.
|
||||||
|
Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp);
|
||||||
|
|
||||||
|
/// \brief If a value has only one user that is a CastInst, return it.
|
||||||
|
Value *getUniqueCastUse(Value *Ptr, Loop *Lp, Type *Ty);
|
||||||
|
|
||||||
|
/// \brief Get the stride of a pointer access in a loop. Looks for symbolic
|
||||||
|
/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise.
|
||||||
|
Value *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp);
|
||||||
|
|
||||||
} // llvm namespace
|
} // llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,7 +11,13 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
|
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
||||||
|
#include "llvm/Analysis/ScalarEvolution.h"
|
||||||
#include "llvm/Analysis/VectorUtils.h"
|
#include "llvm/Analysis/VectorUtils.h"
|
||||||
|
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
||||||
|
#include "llvm/IR/PatternMatch.h"
|
||||||
|
#include "llvm/IR/Value.h"
|
||||||
|
|
||||||
/// \brief Identify if the intrinsic is trivially vectorizable.
|
/// \brief Identify if the intrinsic is trivially vectorizable.
|
||||||
/// This method returns true if the intrinsic's argument types are all
|
/// This method returns true if the intrinsic's argument types are all
|
||||||
|
@ -211,3 +217,143 @@ llvm::Intrinsic::ID llvm::getIntrinsicIDForCall(CallInst *CI,
|
||||||
|
|
||||||
return Intrinsic::not_intrinsic;
|
return Intrinsic::not_intrinsic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Find the operand of the GEP that should be checked for consecutive
|
||||||
|
/// stores. This ignores trailing indices that have no effect on the final
|
||||||
|
/// pointer.
|
||||||
|
unsigned llvm::getGEPInductionOperand(const GetElementPtrInst *Gep) {
|
||||||
|
const DataLayout &DL = Gep->getModule()->getDataLayout();
|
||||||
|
unsigned LastOperand = Gep->getNumOperands() - 1;
|
||||||
|
unsigned GEPAllocSize = DL.getTypeAllocSize(
|
||||||
|
cast<PointerType>(Gep->getType()->getScalarType())->getElementType());
|
||||||
|
|
||||||
|
// Walk backwards and try to peel off zeros.
|
||||||
|
while (LastOperand > 1 &&
|
||||||
|
match(Gep->getOperand(LastOperand), llvm::PatternMatch::m_Zero())) {
|
||||||
|
// Find the type we're currently indexing into.
|
||||||
|
gep_type_iterator GEPTI = gep_type_begin(Gep);
|
||||||
|
std::advance(GEPTI, LastOperand - 1);
|
||||||
|
|
||||||
|
// If it's a type with the same allocation size as the result of the GEP we
|
||||||
|
// can peel off the zero index.
|
||||||
|
if (DL.getTypeAllocSize(*GEPTI) != GEPAllocSize)
|
||||||
|
break;
|
||||||
|
--LastOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LastOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief If the argument is a GEP, then returns the operand identified by
|
||||||
|
/// getGEPInductionOperand. However, if there is some other non-loop-invariant
|
||||||
|
/// operand, it returns that instead.
|
||||||
|
llvm::Value *llvm::stripGetElementPtr(llvm::Value *Ptr, ScalarEvolution *SE,
|
||||||
|
Loop *Lp) {
|
||||||
|
GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr);
|
||||||
|
if (!GEP)
|
||||||
|
return Ptr;
|
||||||
|
|
||||||
|
unsigned InductionOperand = getGEPInductionOperand(GEP);
|
||||||
|
|
||||||
|
// Check that all of the gep indices are uniform except for our induction
|
||||||
|
// operand.
|
||||||
|
for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i)
|
||||||
|
if (i != InductionOperand &&
|
||||||
|
!SE->isLoopInvariant(SE->getSCEV(GEP->getOperand(i)), Lp))
|
||||||
|
return Ptr;
|
||||||
|
return GEP->getOperand(InductionOperand);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief If a value has only one user that is a CastInst, return it.
|
||||||
|
llvm::Value *llvm::getUniqueCastUse(llvm::Value *Ptr, Loop *Lp, Type *Ty) {
|
||||||
|
llvm::Value *UniqueCast = nullptr;
|
||||||
|
for (User *U : Ptr->users()) {
|
||||||
|
CastInst *CI = dyn_cast<CastInst>(U);
|
||||||
|
if (CI && CI->getType() == Ty) {
|
||||||
|
if (!UniqueCast)
|
||||||
|
UniqueCast = CI;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UniqueCast;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Get the stride of a pointer access in a loop. Looks for symbolic
|
||||||
|
/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise.
|
||||||
|
llvm::Value *llvm::getStrideFromPointer(llvm::Value *Ptr, ScalarEvolution *SE,
|
||||||
|
Loop *Lp) {
|
||||||
|
const PointerType *PtrTy = dyn_cast<PointerType>(Ptr->getType());
|
||||||
|
if (!PtrTy || PtrTy->isAggregateType())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Try to remove a gep instruction to make the pointer (actually index at this
|
||||||
|
// point) easier analyzable. If OrigPtr is equal to Ptr we are analzying the
|
||||||
|
// pointer, otherwise, we are analyzing the index.
|
||||||
|
llvm::Value *OrigPtr = Ptr;
|
||||||
|
|
||||||
|
// The size of the pointer access.
|
||||||
|
int64_t PtrAccessSize = 1;
|
||||||
|
|
||||||
|
Ptr = stripGetElementPtr(Ptr, SE, Lp);
|
||||||
|
const SCEV *V = SE->getSCEV(Ptr);
|
||||||
|
|
||||||
|
if (Ptr != OrigPtr)
|
||||||
|
// Strip off casts.
|
||||||
|
while (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(V))
|
||||||
|
V = C->getOperand();
|
||||||
|
|
||||||
|
const SCEVAddRecExpr *S = dyn_cast<SCEVAddRecExpr>(V);
|
||||||
|
if (!S)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
V = S->getStepRecurrence(*SE);
|
||||||
|
if (!V)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Strip off the size of access multiplication if we are still analyzing the
|
||||||
|
// pointer.
|
||||||
|
if (OrigPtr == Ptr) {
|
||||||
|
const DataLayout &DL = Lp->getHeader()->getModule()->getDataLayout();
|
||||||
|
DL.getTypeAllocSize(PtrTy->getElementType());
|
||||||
|
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(V)) {
|
||||||
|
if (M->getOperand(0)->getSCEVType() != scConstant)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const APInt &APStepVal =
|
||||||
|
cast<SCEVConstant>(M->getOperand(0))->getValue()->getValue();
|
||||||
|
|
||||||
|
// Huge step value - give up.
|
||||||
|
if (APStepVal.getBitWidth() > 64)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
int64_t StepVal = APStepVal.getSExtValue();
|
||||||
|
if (PtrAccessSize != StepVal)
|
||||||
|
return nullptr;
|
||||||
|
V = M->getOperand(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip off casts.
|
||||||
|
Type *StripedOffRecurrenceCast = nullptr;
|
||||||
|
if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(V)) {
|
||||||
|
StripedOffRecurrenceCast = C->getType();
|
||||||
|
V = C->getOperand();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for the loop invariant symbolic value.
|
||||||
|
const SCEVUnknown *U = dyn_cast<SCEVUnknown>(V);
|
||||||
|
if (!U)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
llvm::Value *Stride = U->getValue();
|
||||||
|
if (!Lp->isLoopInvariant(Stride))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// If we have stripped off the recurrence cast we have to make sure that we
|
||||||
|
// return the value that is used in this loop so that we can replace it later.
|
||||||
|
if (StripedOffRecurrenceCast)
|
||||||
|
Stride = getUniqueCastUse(Stride, Lp, StripedOffRecurrenceCast);
|
||||||
|
|
||||||
|
return Stride;
|
||||||
|
}
|
||||||
|
|
|
@ -1771,31 +1771,6 @@ Value *InnerLoopVectorizer::getStepVector(Value *Val, int StartIdx,
|
||||||
return Builder.CreateAdd(Val, Step, "induction");
|
return Builder.CreateAdd(Val, Step, "induction");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Find the operand of the GEP that should be checked for consecutive
|
|
||||||
/// stores. This ignores trailing indices that have no effect on the final
|
|
||||||
/// pointer.
|
|
||||||
static unsigned getGEPInductionOperand(const GetElementPtrInst *Gep) {
|
|
||||||
const DataLayout &DL = Gep->getModule()->getDataLayout();
|
|
||||||
unsigned LastOperand = Gep->getNumOperands() - 1;
|
|
||||||
unsigned GEPAllocSize = DL.getTypeAllocSize(
|
|
||||||
cast<PointerType>(Gep->getType()->getScalarType())->getElementType());
|
|
||||||
|
|
||||||
// Walk backwards and try to peel off zeros.
|
|
||||||
while (LastOperand > 1 && match(Gep->getOperand(LastOperand), m_Zero())) {
|
|
||||||
// Find the type we're currently indexing into.
|
|
||||||
gep_type_iterator GEPTI = gep_type_begin(Gep);
|
|
||||||
std::advance(GEPTI, LastOperand - 1);
|
|
||||||
|
|
||||||
// If it's a type with the same allocation size as the result of the GEP we
|
|
||||||
// can peel off the zero index.
|
|
||||||
if (DL.getTypeAllocSize(*GEPTI) != GEPAllocSize)
|
|
||||||
break;
|
|
||||||
--LastOperand;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LastOperand;
|
|
||||||
}
|
|
||||||
|
|
||||||
int LoopVectorizationLegality::isConsecutivePtr(Value *Ptr) {
|
int LoopVectorizationLegality::isConsecutivePtr(Value *Ptr) {
|
||||||
assert(Ptr->getType()->isPointerTy() && "Unexpected non-ptr");
|
assert(Ptr->getType()->isPointerTy() && "Unexpected non-ptr");
|
||||||
// Make sure that the pointer does not point to structs.
|
// Make sure that the pointer does not point to structs.
|
||||||
|
@ -4131,118 +4106,6 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///\brief Remove GEPs whose indices but the last one are loop invariant and
|
|
||||||
/// return the induction operand of the gep pointer.
|
|
||||||
static Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp) {
|
|
||||||
GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr);
|
|
||||||
if (!GEP)
|
|
||||||
return Ptr;
|
|
||||||
|
|
||||||
unsigned InductionOperand = getGEPInductionOperand(GEP);
|
|
||||||
|
|
||||||
// Check that all of the gep indices are uniform except for our induction
|
|
||||||
// operand.
|
|
||||||
for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i)
|
|
||||||
if (i != InductionOperand &&
|
|
||||||
!SE->isLoopInvariant(SE->getSCEV(GEP->getOperand(i)), Lp))
|
|
||||||
return Ptr;
|
|
||||||
return GEP->getOperand(InductionOperand);
|
|
||||||
}
|
|
||||||
|
|
||||||
///\brief Look for a cast use of the passed value.
|
|
||||||
static Value *getUniqueCastUse(Value *Ptr, Loop *Lp, Type *Ty) {
|
|
||||||
Value *UniqueCast = nullptr;
|
|
||||||
for (User *U : Ptr->users()) {
|
|
||||||
CastInst *CI = dyn_cast<CastInst>(U);
|
|
||||||
if (CI && CI->getType() == Ty) {
|
|
||||||
if (!UniqueCast)
|
|
||||||
UniqueCast = CI;
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return UniqueCast;
|
|
||||||
}
|
|
||||||
|
|
||||||
///\brief Get the stride of a pointer access in a loop.
|
|
||||||
/// Looks for symbolic strides "a[i*stride]". Returns the symbolic stride as a
|
|
||||||
/// pointer to the Value, or null otherwise.
|
|
||||||
static Value *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp) {
|
|
||||||
const PointerType *PtrTy = dyn_cast<PointerType>(Ptr->getType());
|
|
||||||
if (!PtrTy || PtrTy->isAggregateType())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// Try to remove a gep instruction to make the pointer (actually index at this
|
|
||||||
// point) easier analyzable. If OrigPtr is equal to Ptr we are analzying the
|
|
||||||
// pointer, otherwise, we are analyzing the index.
|
|
||||||
Value *OrigPtr = Ptr;
|
|
||||||
|
|
||||||
// The size of the pointer access.
|
|
||||||
int64_t PtrAccessSize = 1;
|
|
||||||
|
|
||||||
Ptr = stripGetElementPtr(Ptr, SE, Lp);
|
|
||||||
const SCEV *V = SE->getSCEV(Ptr);
|
|
||||||
|
|
||||||
if (Ptr != OrigPtr)
|
|
||||||
// Strip off casts.
|
|
||||||
while (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(V))
|
|
||||||
V = C->getOperand();
|
|
||||||
|
|
||||||
const SCEVAddRecExpr *S = dyn_cast<SCEVAddRecExpr>(V);
|
|
||||||
if (!S)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
V = S->getStepRecurrence(*SE);
|
|
||||||
if (!V)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// Strip off the size of access multiplication if we are still analyzing the
|
|
||||||
// pointer.
|
|
||||||
if (OrigPtr == Ptr) {
|
|
||||||
const DataLayout &DL = Lp->getHeader()->getModule()->getDataLayout();
|
|
||||||
DL.getTypeAllocSize(PtrTy->getElementType());
|
|
||||||
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(V)) {
|
|
||||||
if (M->getOperand(0)->getSCEVType() != scConstant)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
const APInt &APStepVal =
|
|
||||||
cast<SCEVConstant>(M->getOperand(0))->getValue()->getValue();
|
|
||||||
|
|
||||||
// Huge step value - give up.
|
|
||||||
if (APStepVal.getBitWidth() > 64)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
int64_t StepVal = APStepVal.getSExtValue();
|
|
||||||
if (PtrAccessSize != StepVal)
|
|
||||||
return nullptr;
|
|
||||||
V = M->getOperand(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip off casts.
|
|
||||||
Type *StripedOffRecurrenceCast = nullptr;
|
|
||||||
if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(V)) {
|
|
||||||
StripedOffRecurrenceCast = C->getType();
|
|
||||||
V = C->getOperand();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the loop invariant symbolic value.
|
|
||||||
const SCEVUnknown *U = dyn_cast<SCEVUnknown>(V);
|
|
||||||
if (!U)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
Value *Stride = U->getValue();
|
|
||||||
if (!Lp->isLoopInvariant(Stride))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// If we have stripped off the recurrence cast we have to make sure that we
|
|
||||||
// return the value that is used in this loop so that we can replace it later.
|
|
||||||
if (StripedOffRecurrenceCast)
|
|
||||||
Stride = getUniqueCastUse(Stride, Lp, StripedOffRecurrenceCast);
|
|
||||||
|
|
||||||
return Stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoopVectorizationLegality::collectStridedAccess(Value *MemAccess) {
|
void LoopVectorizationLegality::collectStridedAccess(Value *MemAccess) {
|
||||||
Value *Ptr = nullptr;
|
Value *Ptr = nullptr;
|
||||||
if (LoadInst *LI = dyn_cast<LoadInst>(MemAccess))
|
if (LoadInst *LI = dyn_cast<LoadInst>(MemAccess))
|
||||||
|
|
Loading…
Reference in New Issue