diff options
Diffstat (limited to 'llvm/lib/Analysis/Loads.cpp')
| -rw-r--r-- | llvm/lib/Analysis/Loads.cpp | 278 |
1 files changed, 191 insertions, 87 deletions
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 8f373f70f216..1c55f485aa76 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -12,11 +12,14 @@ #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AssumeBundleQueries.h" #include "llvm/Analysis/CaptureTracking.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/GlobalAlias.h" @@ -25,7 +28,6 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" -#include "llvm/IR/Statepoint.h" using namespace llvm; @@ -42,7 +44,8 @@ static bool isAligned(const Value *Base, const APInt &Offset, Align Alignment, static bool isDereferenceableAndAlignedPointer( const Value *V, Align Alignment, const APInt &Size, const DataLayout &DL, const Instruction *CtxI, const DominatorTree *DT, - SmallPtrSetImpl<const Value *> &Visited, unsigned MaxDepth) { + const TargetLibraryInfo *TLI, SmallPtrSetImpl<const Value *> &Visited, + unsigned MaxDepth) { assert(V->getType()->isPointerTy() && "Base must be pointer"); // Recursion limit. @@ -56,17 +59,30 @@ static bool isDereferenceableAndAlignedPointer( // Note that it is not safe to speculate into a malloc'd region because // malloc may return null. + // Recurse into both hands of select. + if (const SelectInst *Sel = dyn_cast<SelectInst>(V)) { + return isDereferenceableAndAlignedPointer(Sel->getTrueValue(), Alignment, + Size, DL, CtxI, DT, TLI, Visited, + MaxDepth) && + isDereferenceableAndAlignedPointer(Sel->getFalseValue(), Alignment, + Size, DL, CtxI, DT, TLI, Visited, + MaxDepth); + } + // bitcast instructions are no-ops as far as dereferenceability is concerned. if (const BitCastOperator *BC = dyn_cast<BitCastOperator>(V)) { if (BC->getSrcTy()->isPointerTy()) return isDereferenceableAndAlignedPointer( - BC->getOperand(0), Alignment, Size, DL, CtxI, DT, Visited, MaxDepth); + BC->getOperand(0), Alignment, Size, DL, CtxI, DT, TLI, + Visited, MaxDepth); } - bool CheckForNonNull = false; + bool CheckForNonNull, CheckForFreed; APInt KnownDerefBytes(Size.getBitWidth(), - V->getPointerDereferenceableBytes(DL, CheckForNonNull)); - if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size)) + V->getPointerDereferenceableBytes(DL, CheckForNonNull, + CheckForFreed)); + if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) && + !CheckForFreed) if (!CheckForNonNull || isKnownNonZero(V, DL, 0, nullptr, CtxI, DT)) { // As we recursed through GEPs to get here, we've incrementally checked // that each step advanced by a multiple of the alignment. If our base is @@ -77,6 +93,31 @@ static bool isDereferenceableAndAlignedPointer( return isAligned(V, Offset, Alignment, DL); } + if (CtxI) { + /// Look through assumes to see if both dereferencability and alignment can + /// be provent by an assume + RetainedKnowledge AlignRK; + RetainedKnowledge DerefRK; + if (getKnowledgeForValue( + V, {Attribute::Dereferenceable, Attribute::Alignment}, nullptr, + [&](RetainedKnowledge RK, Instruction *Assume, auto) { + if (!isValidAssumeForContext(Assume, CtxI)) + return false; + if (RK.AttrKind == Attribute::Alignment) + AlignRK = std::max(AlignRK, RK); + if (RK.AttrKind == Attribute::Dereferenceable) + DerefRK = std::max(DerefRK, RK); + if (AlignRK && DerefRK && AlignRK.ArgValue >= Alignment.value() && + DerefRK.ArgValue >= Size.getZExtValue()) + return true; // We have found what we needed so we stop looking + return false; // Other assumes may have better information. so + // keep looking + })) + return true; + } + /// TODO refactor this function to be able to search independently for + /// Dereferencability and Alignment requirements. + // For GEPs, determine if the indexing lands within the allocated object. if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { const Value *Base = GEP->getPointerOperand(); @@ -97,22 +138,24 @@ static bool isDereferenceableAndAlignedPointer( // addrspacecast, so we can't do arithmetic directly on the APInt values. return isDereferenceableAndAlignedPointer( Base, Alignment, Offset + Size.sextOrTrunc(Offset.getBitWidth()), DL, - CtxI, DT, Visited, MaxDepth); + CtxI, DT, TLI, Visited, MaxDepth); } // For gc.relocate, look through relocations if (const GCRelocateInst *RelocateInst = dyn_cast<GCRelocateInst>(V)) - return isDereferenceableAndAlignedPointer( - RelocateInst->getDerivedPtr(), Alignment, Size, DL, CtxI, DT, Visited, MaxDepth); + return isDereferenceableAndAlignedPointer(RelocateInst->getDerivedPtr(), + Alignment, Size, DL, CtxI, DT, + TLI, Visited, MaxDepth); if (const AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(V)) return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Alignment, - Size, DL, CtxI, DT, Visited, MaxDepth); + Size, DL, CtxI, DT, TLI, + Visited, MaxDepth); if (const auto *Call = dyn_cast<CallBase>(V)) { if (auto *RP = getArgumentAliasingToReturnedPointer(Call, true)) return isDereferenceableAndAlignedPointer(RP, Alignment, Size, DL, CtxI, - DT, Visited, MaxDepth); + DT, TLI, Visited, MaxDepth); // If we have a call we can't recurse through, check to see if this is an // allocation function for which we can establish an minimum object size. @@ -128,19 +171,10 @@ static bool isDereferenceableAndAlignedPointer( Opts.RoundToAlign = false; Opts.NullIsUnknownSize = true; uint64_t ObjSize; - // TODO: Plumb through TLI so that malloc routines and such working. - if (getObjectSize(V, ObjSize, DL, nullptr, Opts)) { + if (getObjectSize(V, ObjSize, DL, TLI, Opts)) { APInt KnownDerefBytes(Size.getBitWidth(), ObjSize); if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) && - isKnownNonZero(V, DL, 0, nullptr, CtxI, DT) && - // TODO: We're currently inconsistent about whether deref(N) is a - // global fact or a point in time fact. Once D61652 eventually - // lands, this check will be restricted to the point in time - // variant. For that variant, we need to prove that object hasn't - // been conditionally freed before ontext instruction - if it has, we - // might be hoisting over the inverse conditional and creating a - // dynamic use after free. - !PointerMayBeCapturedBefore(V, true, true, CtxI, DT, true)) { + isKnownNonZero(V, DL, 0, nullptr, CtxI, DT) && !V->canBeFreed()) { // As we recursed through GEPs to get here, we've incrementally // checked that each step advanced by a multiple of the alignment. If // our base is properly aligned, then the original offset accessed @@ -161,7 +195,8 @@ bool llvm::isDereferenceableAndAlignedPointer(const Value *V, Align Alignment, const APInt &Size, const DataLayout &DL, const Instruction *CtxI, - const DominatorTree *DT) { + const DominatorTree *DT, + const TargetLibraryInfo *TLI) { // Note: At the moment, Size can be zero. This ends up being interpreted as // a query of whether [Base, V] is dereferenceable and V is aligned (since // that's what the implementation happened to do). It's unclear if this is @@ -169,14 +204,15 @@ bool llvm::isDereferenceableAndAlignedPointer(const Value *V, Align Alignment, SmallPtrSet<const Value *, 32> Visited; return ::isDereferenceableAndAlignedPointer(V, Alignment, Size, DL, CtxI, DT, - Visited, 16); + TLI, Visited, 16); } bool llvm::isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, MaybeAlign MA, const DataLayout &DL, const Instruction *CtxI, - const DominatorTree *DT) { + const DominatorTree *DT, + const TargetLibraryInfo *TLI) { // For unsized types or scalable vectors we don't know exactly how many bytes // are dereferenced, so bail out. if (!Ty->isSized() || isa<ScalableVectorType>(Ty)) @@ -192,14 +228,15 @@ bool llvm::isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, APInt AccessSize(DL.getPointerTypeSizeInBits(V->getType()), DL.getTypeStoreSize(Ty)); return isDereferenceableAndAlignedPointer(V, Alignment, AccessSize, DL, CtxI, - DT); + DT, TLI); } bool llvm::isDereferenceablePointer(const Value *V, Type *Ty, const DataLayout &DL, const Instruction *CtxI, - const DominatorTree *DT) { - return isDereferenceableAndAlignedPointer(V, Ty, Align(1), DL, CtxI, DT); + const DominatorTree *DT, + const TargetLibraryInfo *TLI) { + return isDereferenceableAndAlignedPointer(V, Ty, Align(1), DL, CtxI, DT, TLI); } /// Test if A and B will obviously have the same value. @@ -298,10 +335,11 @@ bool llvm::isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L, bool llvm::isSafeToLoadUnconditionally(Value *V, Align Alignment, APInt &Size, const DataLayout &DL, Instruction *ScanFrom, - const DominatorTree *DT) { + const DominatorTree *DT, + const TargetLibraryInfo *TLI) { // If DT is not specified we can't make context-sensitive query const Instruction* CtxI = DT ? ScanFrom : nullptr; - if (isDereferenceableAndAlignedPointer(V, Alignment, Size, DL, CtxI, DT)) + if (isDereferenceableAndAlignedPointer(V, Alignment, Size, DL, CtxI, DT, TLI)) return true; if (!ScanFrom) @@ -372,12 +410,13 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Align Alignment, APInt &Size, bool llvm::isSafeToLoadUnconditionally(Value *V, Type *Ty, Align Alignment, const DataLayout &DL, Instruction *ScanFrom, - const DominatorTree *DT) { + const DominatorTree *DT, + const TargetLibraryInfo *TLI) { APInt Size(DL.getIndexTypeSizeInBits(V->getType()), DL.getTypeStoreSize(Ty)); - return isSafeToLoadUnconditionally(V, Alignment, Size, DL, ScanFrom, DT); + return isSafeToLoadUnconditionally(V, Alignment, Size, DL, ScanFrom, DT, TLI); } - /// DefMaxInstsToScan - the default number of maximum instructions +/// DefMaxInstsToScan - the default number of maximum instructions /// to scan in the block, used by FindAvailableLoadedValue(). /// FindAvailableLoadedValue() was introduced in r60148, to improve jump /// threading in part by eliminating partially redundant loads. @@ -399,21 +438,24 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, if (!Load->isUnordered()) return nullptr; - return FindAvailablePtrLoadStore( - Load->getPointerOperand(), Load->getType(), Load->isAtomic(), ScanBB, - ScanFrom, MaxInstsToScan, AA, IsLoad, NumScanedInst); + MemoryLocation Loc = MemoryLocation::get(Load); + return findAvailablePtrLoadStore(Loc, Load->getType(), Load->isAtomic(), + ScanBB, ScanFrom, MaxInstsToScan, AA, IsLoad, + NumScanedInst); } // Check if the load and the store have the same base, constant offsets and // non-overlapping access ranges. -static bool AreNonOverlapSameBaseLoadAndStore( - Value *LoadPtr, Type *LoadTy, Value *StorePtr, Type *StoreTy, - const DataLayout &DL) { +static bool areNonOverlapSameBaseLoadAndStore(const Value *LoadPtr, + Type *LoadTy, + const Value *StorePtr, + Type *StoreTy, + const DataLayout &DL) { APInt LoadOffset(DL.getTypeSizeInBits(LoadPtr->getType()), 0); APInt StoreOffset(DL.getTypeSizeInBits(StorePtr->getType()), 0); - Value *LoadBase = LoadPtr->stripAndAccumulateConstantOffsets( + const Value *LoadBase = LoadPtr->stripAndAccumulateConstantOffsets( DL, LoadOffset, /* AllowNonInbounds */ false); - Value *StoreBase = StorePtr->stripAndAccumulateConstantOffsets( + const Value *StoreBase = StorePtr->stripAndAccumulateConstantOffsets( DL, StoreOffset, /* AllowNonInbounds */ false); if (LoadBase != StoreBase) return false; @@ -426,23 +468,71 @@ static bool AreNonOverlapSameBaseLoadAndStore( return LoadRange.intersectWith(StoreRange).isEmptySet(); } -Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, - bool AtLeastAtomic, BasicBlock *ScanBB, - BasicBlock::iterator &ScanFrom, - unsigned MaxInstsToScan, - AAResults *AA, bool *IsLoadCSE, - unsigned *NumScanedInst) { +static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr, + Type *AccessTy, bool AtLeastAtomic, + const DataLayout &DL, bool *IsLoadCSE) { + // If this is a load of Ptr, the loaded value is available. + // (This is true even if the load is volatile or atomic, although + // those cases are unlikely.) + if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) { + // We can value forward from an atomic to a non-atomic, but not the + // other way around. + if (LI->isAtomic() < AtLeastAtomic) + return nullptr; + + Value *LoadPtr = LI->getPointerOperand()->stripPointerCasts(); + if (!AreEquivalentAddressValues(LoadPtr, Ptr)) + return nullptr; + + if (CastInst::isBitOrNoopPointerCastable(LI->getType(), AccessTy, DL)) { + if (IsLoadCSE) + *IsLoadCSE = true; + return LI; + } + } + + // If this is a store through Ptr, the value is available! + // (This is true even if the store is volatile or atomic, although + // those cases are unlikely.) + if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { + // We can value forward from an atomic to a non-atomic, but not the + // other way around. + if (SI->isAtomic() < AtLeastAtomic) + return nullptr; + + Value *StorePtr = SI->getPointerOperand()->stripPointerCasts(); + if (!AreEquivalentAddressValues(StorePtr, Ptr)) + return nullptr; + + if (IsLoadCSE) + *IsLoadCSE = false; + + Value *Val = SI->getValueOperand(); + if (CastInst::isBitOrNoopPointerCastable(Val->getType(), AccessTy, DL)) + return Val; + + if (auto *C = dyn_cast<Constant>(Val)) + return ConstantFoldLoadThroughBitcast(C, AccessTy, DL); + } + + return nullptr; +} + +Value *llvm::findAvailablePtrLoadStore( + const MemoryLocation &Loc, Type *AccessTy, bool AtLeastAtomic, + BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan, + AAResults *AA, bool *IsLoadCSE, unsigned *NumScanedInst) { if (MaxInstsToScan == 0) MaxInstsToScan = ~0U; const DataLayout &DL = ScanBB->getModule()->getDataLayout(); - Value *StrippedPtr = Ptr->stripPointerCasts(); + const Value *StrippedPtr = Loc.Ptr->stripPointerCasts(); while (ScanFrom != ScanBB->begin()) { // We must ignore debug info directives when counting (otherwise they // would affect codegen). Instruction *Inst = &*--ScanFrom; - if (isa<DbgInfoIntrinsic>(Inst)) + if (Inst->isDebugOrPseudoInst()) continue; // Restore ScanFrom to expected value in case next test succeeds @@ -456,45 +546,14 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, return nullptr; --ScanFrom; - // If this is a load of Ptr, the loaded value is available. - // (This is true even if the load is volatile or atomic, although - // those cases are unlikely.) - if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) - if (AreEquivalentAddressValues( - LI->getPointerOperand()->stripPointerCasts(), StrippedPtr) && - CastInst::isBitOrNoopPointerCastable(LI->getType(), AccessTy, DL)) { - - // We can value forward from an atomic to a non-atomic, but not the - // other way around. - if (LI->isAtomic() < AtLeastAtomic) - return nullptr; - if (IsLoadCSE) - *IsLoadCSE = true; - return LI; - } + if (Value *Available = getAvailableLoadStore(Inst, StrippedPtr, AccessTy, + AtLeastAtomic, DL, IsLoadCSE)) + return Available; // Try to get the store size for the type. - auto AccessSize = LocationSize::precise(DL.getTypeStoreSize(AccessTy)); - if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { Value *StorePtr = SI->getPointerOperand()->stripPointerCasts(); - // If this is a store through Ptr, the value is available! - // (This is true even if the store is volatile or atomic, although - // those cases are unlikely.) - if (AreEquivalentAddressValues(StorePtr, StrippedPtr) && - CastInst::isBitOrNoopPointerCastable(SI->getValueOperand()->getType(), - AccessTy, DL)) { - - // We can value forward from an atomic to a non-atomic, but not the - // other way around. - if (SI->isAtomic() < AtLeastAtomic) - return nullptr; - - if (IsLoadCSE) - *IsLoadCSE = false; - return SI->getOperand(0); - } // If both StrippedPtr and StorePtr reach all the way to an alloca or // global and they are different, ignore the store. This is a trivial form @@ -509,14 +568,14 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, // base, constant offsets and non-overlapping access ranges, ignore the // store. This is a simple form of alias analysis that is used by the // inliner. FIXME: use BasicAA if possible. - if (AreNonOverlapSameBaseLoadAndStore( - Ptr, AccessTy, SI->getPointerOperand(), + if (areNonOverlapSameBaseLoadAndStore( + Loc.Ptr, AccessTy, SI->getPointerOperand(), SI->getValueOperand()->getType(), DL)) continue; } else { // If we have alias analysis and it says the store won't modify the // loaded value, ignore the store. - if (!isModSet(AA->getModRefInfo(SI, StrippedPtr, AccessSize))) + if (!isModSet(AA->getModRefInfo(SI, Loc))) continue; } @@ -529,7 +588,7 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, if (Inst->mayWriteToMemory()) { // If alias analysis claims that it really won't modify the load, // ignore it. - if (AA && !isModSet(AA->getModRefInfo(Inst, StrippedPtr, AccessSize))) + if (AA && !isModSet(AA->getModRefInfo(Inst, Loc))) continue; // May modify the pointer, bail out. @@ -543,6 +602,51 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, return nullptr; } +Value *llvm::FindAvailableLoadedValue(LoadInst *Load, AAResults &AA, + bool *IsLoadCSE, + unsigned MaxInstsToScan) { + const DataLayout &DL = Load->getModule()->getDataLayout(); + Value *StrippedPtr = Load->getPointerOperand()->stripPointerCasts(); + BasicBlock *ScanBB = Load->getParent(); + Type *AccessTy = Load->getType(); + bool AtLeastAtomic = Load->isAtomic(); + + if (!Load->isUnordered()) + return nullptr; + + // Try to find an available value first, and delay expensive alias analysis + // queries until later. + Value *Available = nullptr;; + SmallVector<Instruction *> MustNotAliasInsts; + for (Instruction &Inst : make_range(++Load->getReverseIterator(), + ScanBB->rend())) { + if (Inst.isDebugOrPseudoInst()) + continue; + + if (MaxInstsToScan-- == 0) + return nullptr; + + Available = getAvailableLoadStore(&Inst, StrippedPtr, AccessTy, + AtLeastAtomic, DL, IsLoadCSE); + if (Available) + break; + + if (Inst.mayWriteToMemory()) + MustNotAliasInsts.push_back(&Inst); + } + + // If we found an available value, ensure that the instructions in between + // did not modify the memory location. + if (Available) { + MemoryLocation Loc = MemoryLocation::get(Load); + for (Instruction *Inst : MustNotAliasInsts) + if (isModSet(AA.getModRefInfo(Inst, Loc))) + return nullptr; + } + + return Available; +} + bool llvm::canReplacePointersIfEqual(Value *A, Value *B, const DataLayout &DL, Instruction *CtxI) { Type *Ty = A->getType(); |
