diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Analysis/Loads.cpp | 29 | ||||
| -rw-r--r-- | llvm/lib/Analysis/MemDerefPrinter.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Transforms/IPO/ArgumentPromotion.cpp | 52 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/LICM.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/MergeICmps.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/SROA.cpp | 16 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp | 2 |
11 files changed, 91 insertions, 36 deletions
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 7da9bd718a5..31da4e9ec78 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -125,7 +125,8 @@ bool llvm::isDereferenceableAndAlignedPointer(const Value *V, unsigned Align, Visited); } -bool llvm::isDereferenceableAndAlignedPointer(const Value *V, unsigned Align, +bool llvm::isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, + unsigned Align, const DataLayout &DL, const Instruction *CtxI, const DominatorTree *DT) { @@ -133,8 +134,6 @@ bool llvm::isDereferenceableAndAlignedPointer(const Value *V, unsigned Align, // attribute, we know exactly how many bytes are dereferenceable. If we can // determine the exact offset to the attributed variable, we can use that // information here. - Type *VTy = V->getType(); - Type *Ty = VTy->getPointerElementType(); // Require ABI alignment for loads without alignment specification if (Align == 0) @@ -145,14 +144,16 @@ bool llvm::isDereferenceableAndAlignedPointer(const Value *V, unsigned Align, SmallPtrSet<const Value *, 32> Visited; return ::isDereferenceableAndAlignedPointer( - V, Align, APInt(DL.getIndexTypeSizeInBits(VTy), DL.getTypeStoreSize(Ty)), DL, - CtxI, DT, Visited); + V, Align, + APInt(DL.getIndexTypeSizeInBits(V->getType()), DL.getTypeStoreSize(Ty)), + DL, CtxI, DT, Visited); } -bool llvm::isDereferenceablePointer(const Value *V, const DataLayout &DL, +bool llvm::isDereferenceablePointer(const Value *V, Type *Ty, + const DataLayout &DL, const Instruction *CtxI, const DominatorTree *DT) { - return isDereferenceableAndAlignedPointer(V, 1, DL, CtxI, DT); + return isDereferenceableAndAlignedPointer(V, Ty, 1, DL, CtxI, DT); } /// Test if A and B will obviously have the same value. @@ -197,7 +198,7 @@ static bool AreEquivalentAddressValues(const Value *A, const Value *B) { /// /// This uses the pointee type to determine how many bytes need to be safe to /// load from the pointer. -bool llvm::isSafeToLoadUnconditionally(Value *V, unsigned Align, +bool llvm::isSafeToLoadUnconditionally(Value *V, unsigned Align, APInt &Size, const DataLayout &DL, Instruction *ScanFrom, const DominatorTree *DT) { @@ -208,7 +209,7 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, unsigned Align, // If DT is not specified we can't make context-sensitive query const Instruction* CtxI = DT ? ScanFrom : nullptr; - if (isDereferenceableAndAlignedPointer(V, Align, DL, CtxI, DT)) + if (isDereferenceableAndAlignedPointer(V, Align, Size, DL, CtxI, DT)) return true; int64_t ByteOffset = 0; @@ -313,7 +314,15 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, unsigned Align, return false; } -/// DefMaxInstsToScan - the default number of maximum instructions +bool llvm::isSafeToLoadUnconditionally(Value *V, Type *Ty, unsigned Align, + const DataLayout &DL, + Instruction *ScanFrom, + const DominatorTree *DT) { + APInt Size(DL.getIndexTypeSizeInBits(V->getType()), DL.getTypeStoreSize(Ty)); + return isSafeToLoadUnconditionally(V, Align, Size, DL, ScanFrom, DT); +} + + /// 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. diff --git a/llvm/lib/Analysis/MemDerefPrinter.cpp b/llvm/lib/Analysis/MemDerefPrinter.cpp index 5f95a18b8a1..77ebf89d9a0 100644 --- a/llvm/lib/Analysis/MemDerefPrinter.cpp +++ b/llvm/lib/Analysis/MemDerefPrinter.cpp @@ -53,9 +53,10 @@ bool MemDerefPrinter::runOnFunction(Function &F) { for (auto &I: instructions(F)) { if (LoadInst *LI = dyn_cast<LoadInst>(&I)) { Value *PO = LI->getPointerOperand(); - if (isDereferenceablePointer(PO, DL)) + if (isDereferenceablePointer(PO, LI->getType(), DL)) Deref.push_back(PO); - if (isDereferenceableAndAlignedPointer(PO, LI->getAlignment(), DL)) + if (isDereferenceableAndAlignedPointer(PO, LI->getType(), + LI->getAlignment(), DL)) DerefAndAligned.insert(PO); } } diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 3ff5bf08599..39827831b79 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -3949,7 +3949,8 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V, return false; const DataLayout &DL = LI->getModule()->getDataLayout(); return isDereferenceableAndAlignedPointer(LI->getPointerOperand(), - LI->getAlignment(), DL, CtxI, DT); + LI->getType(), LI->getAlignment(), + DL, CtxI, DT); } case Instruction::Call: { auto *CI = cast<const CallInst>(Inst); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index cf5e9031478..adcb0b37547 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4004,7 +4004,8 @@ void SelectionDAGBuilder::visitLoad(const LoadInst &I) { bool isVolatile = I.isVolatile(); bool isNonTemporal = I.getMetadata(LLVMContext::MD_nontemporal) != nullptr; bool isInvariant = I.getMetadata(LLVMContext::MD_invariant_load) != nullptr; - bool isDereferenceable = isDereferenceablePointer(SV, DAG.getDataLayout()); + bool isDereferenceable = + isDereferenceablePointer(SV, I.getType(), DAG.getDataLayout()); unsigned Alignment = I.getAlignment(); AAMDNodes AAInfo; @@ -4629,7 +4630,8 @@ void SelectionDAGBuilder::visitAtomicLoad(const LoadInst &I) { Flags |= MachineMemOperand::MOVolatile; if (I.getMetadata(LLVMContext::MD_invariant_load) != nullptr) Flags |= MachineMemOperand::MOInvariant; - if (isDereferenceablePointer(I.getPointerOperand(), DAG.getDataLayout())) + if (isDereferenceablePointer(I.getPointerOperand(), I.getType(), + DAG.getDataLayout())) Flags |= MachineMemOperand::MODereferenceable; Flags |= TLI.getMMOFlags(I); diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index 8b77adc78f3..95a9f31cced 100644 --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -479,9 +479,9 @@ doPromotion(Function *F, SmallPtrSetImpl<Argument *> &ArgsToPromote, return NF; } -/// AllCallersPassInValidPointerForArgument - Return true if we can prove that -/// all callees pass in a valid pointer for the specified function argument. -static bool allCallersPassInValidPointerForArgument(Argument *Arg) { +/// Return true if we can prove that all callees pass in a valid pointer for the +/// specified function argument. +static bool allCallersPassValidPointerForArgument(Argument *Arg, Type *Ty) { Function *Callee = Arg->getParent(); const DataLayout &DL = Callee->getParent()->getDataLayout(); @@ -493,7 +493,7 @@ static bool allCallersPassInValidPointerForArgument(Argument *Arg) { CallSite CS(U); assert(CS && "Should only have direct calls!"); - if (!isDereferenceablePointer(CS.getArgument(ArgNo), DL)) + if (!isDereferenceablePointer(CS.getArgument(ArgNo), Ty, DL)) return false; } return true; @@ -566,7 +566,7 @@ static void markIndicesSafe(const IndicesVector &ToMark, /// This method limits promotion of aggregates to only promote up to three /// elements of the aggregate in order to avoid exploding the number of /// arguments passed in. -static bool isSafeToPromoteArgument(Argument *Arg, bool isByVal, AAResults &AAR, +static bool isSafeToPromoteArgument(Argument *Arg, Type *ByValTy, AAResults &AAR, unsigned MaxElements) { using GEPIndicesSet = std::set<IndicesVector>; @@ -596,9 +596,28 @@ static bool isSafeToPromoteArgument(Argument *Arg, bool isByVal, AAResults &AAR, GEPIndicesSet ToPromote; // If the pointer is always valid, any load with first index 0 is valid. - if (isByVal || allCallersPassInValidPointerForArgument(Arg)) + + if (ByValTy) SafeToUnconditionallyLoad.insert(IndicesVector(1, 0)); + // Whenever a new underlying type for the operand is found, make sure it's + // consistent with the GEPs and loads we've already seen and, if necessary, + // use it to see if all incoming pointers are valid (which implies the 0-index + // is safe). + Type *BaseTy = ByValTy; + auto UpdateBaseTy = [&](Type *NewBaseTy) { + if (BaseTy) + return BaseTy == NewBaseTy; + + BaseTy = NewBaseTy; + if (allCallersPassValidPointerForArgument(Arg, BaseTy)) { + assert(SafeToUnconditionallyLoad.empty()); + SafeToUnconditionallyLoad.insert(IndicesVector(1, 0)); + } + + return true; + }; + // First, iterate the entry block and mark loads of (geps of) arguments as // safe. BasicBlock &EntryBlock = Arg->getParent()->front(); @@ -621,6 +640,9 @@ static bool isSafeToPromoteArgument(Argument *Arg, bool isByVal, AAResults &AAR, // right away, can't promote this argument at all. return false; + if (!UpdateBaseTy(GEP->getSourceElementType())) + return false; + // Indices checked out, mark them as safe markIndicesSafe(Indices, SafeToUnconditionallyLoad); Indices.clear(); @@ -628,6 +650,11 @@ static bool isSafeToPromoteArgument(Argument *Arg, bool isByVal, AAResults &AAR, } else if (V == Arg) { // Direct loads are equivalent to a GEP with a single 0 index. markIndicesSafe(IndicesVector(1, 0), SafeToUnconditionallyLoad); + + if (BaseTy && LI->getType() != BaseTy) + return false; + + BaseTy = LI->getType(); } } @@ -645,6 +672,9 @@ static bool isSafeToPromoteArgument(Argument *Arg, bool isByVal, AAResults &AAR, Loads.push_back(LI); // Direct loads are equivalent to a GEP with a zero index and then a load. Operands.push_back(0); + + if (!UpdateBaseTy(LI->getType())) + return false; } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(UR)) { if (GEP->use_empty()) { // Dead GEP's cause trouble later. Just remove them if we run into @@ -653,9 +683,12 @@ static bool isSafeToPromoteArgument(Argument *Arg, bool isByVal, AAResults &AAR, // TODO: This runs the above loop over and over again for dead GEPs // Couldn't we just do increment the UI iterator earlier and erase the // use? - return isSafeToPromoteArgument(Arg, isByVal, AAR, MaxElements); + return isSafeToPromoteArgument(Arg, ByValTy, AAR, MaxElements); } + if (!UpdateBaseTy(GEP->getSourceElementType())) + return false; + // Ensure that all of the indices are constants. for (User::op_iterator i = GEP->idx_begin(), e = GEP->idx_end(); i != e; ++i) @@ -966,8 +999,9 @@ promoteArguments(Function *F, function_ref<AAResults &(Function &F)> AARGetter, } // Otherwise, see if we can promote the pointer to its value. - if (isSafeToPromoteArgument(PtrArg, PtrArg->hasByValAttr(), AAR, - MaxElements)) + Type *ByValTy = + PtrArg->hasByValAttr() ? PtrArg->getParamByValType() : nullptr; + if (isSafeToPromoteArgument(PtrArg, ByValTy, AAR, MaxElements)) ArgsToPromote.insert(PtrArg); } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 63f313e1f7f..4b3333affa7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1060,7 +1060,7 @@ Value *InstCombiner::simplifyMaskedLoad(IntrinsicInst &II) { // If we can unconditionally load from this address, replace with a // load/select idiom. TODO: use DT for context sensitive query - if (isDereferenceableAndAlignedPointer(LoadPtr, Alignment, + if (isDereferenceableAndAlignedPointer(LoadPtr, II.getType(), Alignment, II.getModule()->getDataLayout(), &II, nullptr)) { Value *LI = Builder.CreateAlignedLoad(II.getType(), LoadPtr, Alignment, diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 0df80e07e84..054fb7da09a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -1064,8 +1064,10 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { if (SelectInst *SI = dyn_cast<SelectInst>(Op)) { // load (select (Cond, &V1, &V2)) --> select(Cond, load &V1, load &V2). unsigned Align = LI.getAlignment(); - if (isSafeToLoadUnconditionally(SI->getOperand(1), Align, DL, SI) && - isSafeToLoadUnconditionally(SI->getOperand(2), Align, DL, SI)) { + if (isSafeToLoadUnconditionally(SI->getOperand(1), LI.getType(), Align, + DL, SI) && + isSafeToLoadUnconditionally(SI->getOperand(2), LI.getType(), Align, + DL, SI)) { LoadInst *V1 = Builder.CreateLoad(LI.getType(), SI->getOperand(1), SI->getOperand(1)->getName() + ".val"); diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 2d27a660102..3c5e773f793 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -2016,8 +2016,8 @@ bool llvm::promoteLoopAccessesToScalars( // deref info through it. if (!DereferenceableInPH) { DereferenceableInPH = isDereferenceableAndAlignedPointer( - Store->getPointerOperand(), Store->getAlignment(), MDL, - Preheader->getTerminator(), DT); + Store->getPointerOperand(), Store->getValueOperand()->getType(), + Store->getAlignment(), MDL, Preheader->getTerminator(), DT); } } else return false; // Not a load or store. diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp index 630f029850c..3d047a19326 100644 --- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp +++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp @@ -162,7 +162,7 @@ BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId) { return {}; } const auto &DL = GEP->getModule()->getDataLayout(); - if (!isDereferenceablePointer(GEP, DL)) { + if (!isDereferenceablePointer(GEP, LoadI->getType(), DL)) { LLVM_DEBUG(dbgs() << "not dereferenceable\n"); // We need to make sure that we can do comparison in any order, so we // require memory to be unconditionnally dereferencable. diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index cc79afdb05a..33f90d0b01e 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -1190,12 +1190,16 @@ static Type *findCommonType(AllocaSlices::const_iterator B, /// FIXME: This should be hoisted into a generic utility, likely in /// Transforms/Util/Local.h static bool isSafePHIToSpeculate(PHINode &PN) { + const DataLayout &DL = PN.getModule()->getDataLayout(); + // For now, we can only do this promotion if the load is in the same block // as the PHI, and if there are no stores between the phi and load. // TODO: Allow recursive phi users. // TODO: Allow stores. BasicBlock *BB = PN.getParent(); unsigned MaxAlign = 0; + uint64_t APWidth = DL.getIndexTypeSizeInBits(PN.getType()); + APInt MaxSize(APWidth, 0); bool HaveLoad = false; for (User *U : PN.users()) { LoadInst *LI = dyn_cast<LoadInst>(U); @@ -1214,15 +1218,15 @@ static bool isSafePHIToSpeculate(PHINode &PN) { if (BBI->mayWriteToMemory()) return false; + uint64_t Size = DL.getTypeStoreSizeInBits(LI->getType()); MaxAlign = std::max(MaxAlign, LI->getAlignment()); + MaxSize = MaxSize.ult(Size) ? APInt(APWidth, Size) : MaxSize; HaveLoad = true; } if (!HaveLoad) return false; - const DataLayout &DL = PN.getModule()->getDataLayout(); - // We can only transform this if it is safe to push the loads into the // predecessor blocks. The only thing to watch out for is that we can't put // a possibly trapping load in the predecessor if it is a critical edge. @@ -1244,7 +1248,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) { // If this pointer is always safe to load, or if we can prove that there // is already a load in the block, then we can move the load to the pred // block. - if (isSafeToLoadUnconditionally(InVal, MaxAlign, DL, TI)) + if (isSafeToLoadUnconditionally(InVal, MaxAlign, MaxSize, DL, TI)) continue; return false; @@ -1334,9 +1338,11 @@ static bool isSafeSelectToSpeculate(SelectInst &SI) { // Both operands to the select need to be dereferenceable, either // absolutely (e.g. allocas) or at this point because we can see other // accesses to it. - if (!isSafeToLoadUnconditionally(TValue, LI->getAlignment(), DL, LI)) + if (!isSafeToLoadUnconditionally(TValue, LI->getType(), LI->getAlignment(), + DL, LI)) return false; - if (!isSafeToLoadUnconditionally(FValue, LI->getAlignment(), DL, LI)) + if (!isSafeToLoadUnconditionally(FValue, LI->getType(), LI->getAlignment(), + DL, LI)) return false; } diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index c3ccfde8acc..f0b79079d81 100644 --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -340,7 +340,7 @@ static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA) { // being loaded from. const DataLayout &DL = L->getModule()->getDataLayout(); if (isModSet(AA->getModRefInfo(CI, MemoryLocation::get(L))) || - !isSafeToLoadUnconditionally(L->getPointerOperand(), + !isSafeToLoadUnconditionally(L->getPointerOperand(), L->getType(), L->getAlignment(), DL, L)) return false; } |

