[Loads] Move generic code out of vectorizer into a location it might be reused [NFC]
llvm-svn: 371558
This commit is contained in:
parent
045b2270ce
commit
cffa630c80
|
@ -20,7 +20,9 @@
|
|||
namespace llvm {
|
||||
|
||||
class DataLayout;
|
||||
class Loop;
|
||||
class MDNode;
|
||||
class ScalarEvolution;
|
||||
|
||||
/// Return true if this is always a dereferenceable pointer. If the context
|
||||
/// instruction is specified perform context-sensitive analysis and return true
|
||||
|
@ -61,6 +63,17 @@ bool isSafeToLoadUnconditionally(Value *V, unsigned Align, APInt &Size,
|
|||
Instruction *ScanFrom = nullptr,
|
||||
const DominatorTree *DT = nullptr);
|
||||
|
||||
/// Return true if we can prove that the given load (which is assumed to be
|
||||
/// within the specified loop) would access only dereferenceable memory, and
|
||||
/// be properly aligned on every iteration of the specified loop regardless of
|
||||
/// its placement within the loop. (i.e. does not require predication beyond
|
||||
/// that required by the the header itself and could be hoisted into the header
|
||||
/// if desired.) This is more powerful than the variants above when the
|
||||
/// address loaded from is analyzeable by SCEV.
|
||||
bool isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L,
|
||||
ScalarEvolution &SE,
|
||||
DominatorTree &DT);
|
||||
|
||||
/// Return true if we know that executing a load from this value cannot trap.
|
||||
///
|
||||
/// If DT and ScanFrom are specified this method performs context-sensitive
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
#include "llvm/Analysis/Loads.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/GlobalAlias.h"
|
||||
|
@ -190,6 +193,53 @@ static bool AreEquivalentAddressValues(const Value *A, const Value *B) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool llvm::isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L,
|
||||
ScalarEvolution &SE,
|
||||
DominatorTree &DT) {
|
||||
auto &DL = LI->getModule()->getDataLayout();
|
||||
Value *Ptr = LI->getPointerOperand();
|
||||
auto *AddRec = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(Ptr));
|
||||
if (!AddRec || AddRec->getLoop() != L || !AddRec->isAffine())
|
||||
return false;
|
||||
auto* Step = dyn_cast<SCEVConstant>(AddRec->getStepRecurrence(SE));
|
||||
if (!Step)
|
||||
return false;
|
||||
APInt StepC = Step->getAPInt();
|
||||
APInt EltSize(DL.getIndexTypeSizeInBits(Ptr->getType()),
|
||||
DL.getTypeStoreSize(LI->getType()));
|
||||
// TODO: generalize to access patterns which have gaps
|
||||
// TODO: handle uniform addresses (if not already handled by LICM)
|
||||
if (StepC != EltSize)
|
||||
return false;
|
||||
|
||||
// TODO: If the symbolic trip count has a small bound (max count), we might
|
||||
// be able to prove safety.
|
||||
auto TC = SE.getSmallConstantTripCount(L);
|
||||
if (!TC)
|
||||
return false;
|
||||
|
||||
const APInt AccessSize = TC * EltSize;
|
||||
|
||||
auto *StartS = dyn_cast<SCEVUnknown>(AddRec->getStart());
|
||||
if (!StartS)
|
||||
return false;
|
||||
assert(SE.isLoopInvariant(StartS, L) && "implied by addrec definition");
|
||||
Value *Base = StartS->getValue();
|
||||
|
||||
Instruction *HeaderFirstNonPHI = L->getHeader()->getFirstNonPHI();
|
||||
|
||||
unsigned Align = LI->getAlignment();
|
||||
if (Align == 0)
|
||||
Align = DL.getABITypeAlignment(LI->getType());
|
||||
// For the moment, restrict ourselves to the case where the access size is a
|
||||
// multiple of the requested alignment and the base is aligned.
|
||||
// TODO: generalize if a case found which warrants
|
||||
if (EltSize.urem(Align) != 0)
|
||||
return false;
|
||||
return isDereferenceableAndAlignedPointer(Base, Align, AccessSize,
|
||||
DL, HeaderFirstNonPHI, &DT);
|
||||
}
|
||||
|
||||
/// Check if executing a load of this pointer value cannot trap.
|
||||
///
|
||||
/// If DT and ScanFrom are specified this method performs context-sensitive
|
||||
|
|
|
@ -918,57 +918,6 @@ bool LoopVectorizationLegality::blockCanBePredicated(
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Return true if we can prove that the given load would access only
|
||||
/// dereferenceable memory, and be properly aligned on every iteration.
|
||||
/// (i.e. does not require predication beyond that required by the the header
|
||||
/// itself) TODO: Move to Loads.h/cpp in a separate change
|
||||
static bool isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L,
|
||||
ScalarEvolution &SE,
|
||||
DominatorTree &DT) {
|
||||
auto &DL = LI->getModule()->getDataLayout();
|
||||
Value *Ptr = LI->getPointerOperand();
|
||||
auto *AddRec = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(Ptr));
|
||||
if (!AddRec || AddRec->getLoop() != L || !AddRec->isAffine())
|
||||
return false;
|
||||
auto* Step = dyn_cast<SCEVConstant>(AddRec->getStepRecurrence(SE));
|
||||
if (!Step)
|
||||
return false;
|
||||
APInt StepC = Step->getAPInt();
|
||||
APInt EltSize(DL.getIndexTypeSizeInBits(Ptr->getType()),
|
||||
DL.getTypeStoreSize(LI->getType()));
|
||||
// TODO: generalize to access patterns which have gaps
|
||||
// TODO: handle uniform addresses (if not already handled by LICM)
|
||||
if (StepC != EltSize)
|
||||
return false;
|
||||
|
||||
// TODO: If the symbolic trip count has a small bound (max count), we might
|
||||
// be able to prove safety.
|
||||
auto TC = SE.getSmallConstantTripCount(L);
|
||||
if (!TC)
|
||||
return false;
|
||||
|
||||
const APInt AccessSize = TC * EltSize;
|
||||
|
||||
auto *StartS = dyn_cast<SCEVUnknown>(AddRec->getStart());
|
||||
if (!StartS)
|
||||
return false;
|
||||
assert(SE.isLoopInvariant(StartS, L) && "implied by addrec definition");
|
||||
Value *Base = StartS->getValue();
|
||||
|
||||
Instruction *HeaderFirstNonPHI = L->getHeader()->getFirstNonPHI();
|
||||
|
||||
unsigned Align = LI->getAlignment();
|
||||
if (Align == 0)
|
||||
Align = DL.getABITypeAlignment(LI->getType());
|
||||
// For the moment, restrict ourselves to the case where the access size is a
|
||||
// multiple of the requested alignment and the base is aligned.
|
||||
// TODO: generalize if a case found which warrants
|
||||
if (EltSize.urem(Align) != 0)
|
||||
return false;
|
||||
return isDereferenceableAndAlignedPointer(Base, Align, AccessSize,
|
||||
DL, HeaderFirstNonPHI, &DT);
|
||||
}
|
||||
|
||||
bool LoopVectorizationLegality::canVectorizeWithIfConvert() {
|
||||
if (!EnableIfConversion) {
|
||||
reportVectorizationFailure("If-conversion is disabled",
|
||||
|
|
Loading…
Reference in New Issue