diff options
Diffstat (limited to 'llvm/lib/Analysis')
55 files changed, 4225 insertions, 2381 deletions
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp index e7445e225d52..d030f74481cf 100644 --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -119,7 +119,7 @@ bool AAResults::invalidate(Function &F, const PreservedAnalyses &PA, AliasResult AAResults::alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return alias(LocA, LocB, AAQIP); } @@ -162,7 +162,7 @@ AliasResult AAResults::alias(const MemoryLocation &LocA, bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return pointsToConstantMemory(Loc, AAQIP, OrLocal); } @@ -190,7 +190,7 @@ ModRefInfo AAResults::getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { } ModRefInfo AAResults::getModRefInfo(Instruction *I, const CallBase *Call2) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(I, Call2, AAQIP); } @@ -200,25 +200,24 @@ ModRefInfo AAResults::getModRefInfo(Instruction *I, const CallBase *Call2, if (const auto *Call1 = dyn_cast<CallBase>(I)) { // Check if the two calls modify the same memory. return getModRefInfo(Call1, Call2, AAQI); - } else if (I->isFenceLike()) { - // If this is a fence, just return ModRef. - return ModRefInfo::ModRef; - } else { - // Otherwise, check if the call modifies or references the - // location this memory access defines. The best we can say - // is that if the call references what this instruction - // defines, it must be clobbered by this location. - const MemoryLocation DefLoc = MemoryLocation::get(I); - ModRefInfo MR = getModRefInfo(Call2, DefLoc, AAQI); - if (isModOrRefSet(MR)) - return setModAndRef(MR); } + // If this is a fence, just return ModRef. + if (I->isFenceLike()) + return ModRefInfo::ModRef; + // Otherwise, check if the call modifies or references the + // location this memory access defines. The best we can say + // is that if the call references what this instruction + // defines, it must be clobbered by this location. + const MemoryLocation DefLoc = MemoryLocation::get(I); + ModRefInfo MR = getModRefInfo(Call2, DefLoc, AAQI); + if (isModOrRefSet(MR)) + return setModAndRef(MR); return ModRefInfo::NoModRef; } ModRefInfo AAResults::getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(Call, Loc, AAQIP); } @@ -285,7 +284,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call, ModRefInfo AAResults::getModRefInfo(const CallBase *Call1, const CallBase *Call2) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(Call1, Call2, AAQIP); } @@ -475,7 +474,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, AliasResult AR) { ModRefInfo AAResults::getModRefInfo(const LoadInst *L, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(L, Loc, AAQIP); } ModRefInfo AAResults::getModRefInfo(const LoadInst *L, @@ -500,7 +499,7 @@ ModRefInfo AAResults::getModRefInfo(const LoadInst *L, ModRefInfo AAResults::getModRefInfo(const StoreInst *S, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(S, Loc, AAQIP); } ModRefInfo AAResults::getModRefInfo(const StoreInst *S, @@ -532,7 +531,7 @@ ModRefInfo AAResults::getModRefInfo(const StoreInst *S, } ModRefInfo AAResults::getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(S, Loc, AAQIP); } @@ -548,7 +547,7 @@ ModRefInfo AAResults::getModRefInfo(const FenceInst *S, ModRefInfo AAResults::getModRefInfo(const VAArgInst *V, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(V, Loc, AAQIP); } @@ -578,7 +577,7 @@ ModRefInfo AAResults::getModRefInfo(const VAArgInst *V, ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(CatchPad, Loc, AAQIP); } @@ -598,7 +597,7 @@ ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad, ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(CatchRet, Loc, AAQIP); } @@ -618,7 +617,7 @@ ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet, ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(CX, Loc, AAQIP); } @@ -646,7 +645,7 @@ ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX, ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(RMW, Loc, AAQIP); } @@ -746,7 +745,7 @@ ModRefInfo AAResults::callCapturesBefore(const Instruction *I, // pointer were passed to arguments that were neither of these, then it // couldn't be no-capture. if (!(*CI)->getType()->isPointerTy() || - (!Call->doesNotCapture(ArgNo) && ArgNo < Call->getNumArgOperands() && + (!Call->doesNotCapture(ArgNo) && ArgNo < Call->arg_size() && !Call->isByValArgument(ArgNo))) continue; @@ -808,11 +807,6 @@ AAResults::Concept::~Concept() = default; // Provide a definition for the static object used to identify passes. AnalysisKey AAManager::Key; -namespace { - - -} // end anonymous namespace - ExternalAAWrapperPass::ExternalAAWrapperPass() : ImmutablePass(ID) { initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry()); } diff --git a/llvm/lib/Analysis/AssumeBundleQueries.cpp b/llvm/lib/Analysis/AssumeBundleQueries.cpp index dee044346f02..9d4fe1225b33 100644 --- a/llvm/lib/Analysis/AssumeBundleQueries.cpp +++ b/llvm/lib/Analysis/AssumeBundleQueries.cpp @@ -84,7 +84,7 @@ void llvm::fillMapFromAssume(AssumeInst &Assume, RetainedKnowledgeMap &Result) { getValueFromBundleOpInfo(Assume, Bundles, ABA_Argument)); if (!CI) continue; - unsigned Val = CI->getZExtValue(); + uint64_t Val = CI->getZExtValue(); auto Lookup = Result.find(Key); if (Lookup == Result.end() || !Lookup->second.count(&Assume)) { Result[Key][&Assume] = {Val, Val}; @@ -102,7 +102,7 @@ llvm::getKnowledgeFromBundle(AssumeInst &Assume, Result.AttrKind = Attribute::getAttrKindFromName(BOI.Tag->getKey()); if (bundleHasArgument(BOI, ABA_WasOn)) Result.WasOn = getValueFromBundleOpInfo(Assume, BOI, ABA_WasOn); - auto GetArgOr1 = [&](unsigned Idx) -> unsigned { + auto GetArgOr1 = [&](unsigned Idx) -> uint64_t { if (auto *ConstInt = dyn_cast<ConstantInt>( getValueFromBundleOpInfo(Assume, BOI, ABA_Argument + Idx))) return ConstInt->getZExtValue(); diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp index 0d95b33601f9..3e0214e21ecd 100644 --- a/llvm/lib/Analysis/AssumptionCache.cpp +++ b/llvm/lib/Analysis/AssumptionCache.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -56,7 +57,7 @@ AssumptionCache::getOrInsertAffectedValues(Value *V) { } static void -findAffectedValues(CallBase *CI, +findAffectedValues(CallBase *CI, TargetTransformInfo *TTI, SmallVectorImpl<AssumptionCache::ResultElem> &Affected) { // Note: This code must be kept in-sync with the code in // computeKnownBitsFromAssume in ValueTracking. @@ -124,24 +125,32 @@ findAffectedValues(CallBase *CI, match(B, m_ConstantInt())) AddAffected(X); } + + if (TTI) { + const Value *Ptr; + unsigned AS; + std::tie(Ptr, AS) = TTI->getPredicatedAddrSpace(Cond); + if (Ptr) + AddAffected(const_cast<Value *>(Ptr->stripInBoundsOffsets())); + } } void AssumptionCache::updateAffectedValues(AssumeInst *CI) { SmallVector<AssumptionCache::ResultElem, 16> Affected; - findAffectedValues(CI, Affected); + findAffectedValues(CI, TTI, Affected); for (auto &AV : Affected) { auto &AVV = getOrInsertAffectedValues(AV.Assume); - if (std::find_if(AVV.begin(), AVV.end(), [&](ResultElem &Elem) { + if (llvm::none_of(AVV, [&](ResultElem &Elem) { return Elem.Assume == CI && Elem.Index == AV.Index; - }) == AVV.end()) + })) AVV.push_back({CI, AV.Index}); } } void AssumptionCache::unregisterAssumption(AssumeInst *CI) { SmallVector<AssumptionCache::ResultElem, 16> Affected; - findAffectedValues(CI, Affected); + findAffectedValues(CI, TTI, Affected); for (auto &AV : Affected) { auto AVI = AffectedValues.find_as(AV.Assume); @@ -248,6 +257,12 @@ void AssumptionCache::registerAssumption(AssumeInst *CI) { updateAffectedValues(CI); } +AssumptionCache AssumptionAnalysis::run(Function &F, + FunctionAnalysisManager &FAM) { + auto &TTI = FAM.getResult<TargetIRAnalysis>(F); + return AssumptionCache(F, &TTI); +} + AnalysisKey AssumptionAnalysis::Key; PreservedAnalyses AssumptionPrinterPass::run(Function &F, @@ -278,10 +293,13 @@ AssumptionCache &AssumptionCacheTracker::getAssumptionCache(Function &F) { if (I != AssumptionCaches.end()) return *I->second; + auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>(); + auto *TTI = TTIWP ? &TTIWP->getTTI(F) : nullptr; + // Ok, build a new cache by scanning the function, insert it and the value // handle into our map, and return the newly populated cache. auto IP = AssumptionCaches.insert(std::make_pair( - FunctionCallbackVH(&F, this), std::make_unique<AssumptionCache>(F))); + FunctionCallbackVH(&F, this), std::make_unique<AssumptionCache>(F, TTI))); assert(IP.second && "Scanning function already in the map?"); return *IP.first->second; } diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp index 357772c9c4f2..88b0f37b1d48 100644 --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -31,6 +31,7 @@ #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -68,15 +69,6 @@ using namespace llvm; static cl::opt<bool> EnableRecPhiAnalysis("basic-aa-recphi", cl::Hidden, cl::init(true)); -/// By default, even on 32-bit architectures we use 64-bit integers for -/// calculations. This will allow us to more-aggressively decompose indexing -/// expressions calculated using i64 values (e.g., long long in C) which is -/// common enough to worry about. -static cl::opt<bool> ForceAtLeast64Bits("basic-aa-force-at-least-64b", - cl::Hidden, cl::init(true)); -static cl::opt<bool> DoubleCalcBits("basic-aa-double-calc-bits", - cl::Hidden, cl::init(false)); - /// SearchLimitReached / SearchTimes shows how often the limit of /// to decompose GEPs is reached. It will affect the precision /// of basic alias analysis. @@ -91,8 +83,7 @@ STATISTIC(SearchTimes, "Number of times a GEP is decomposed"); const unsigned MaxNumPhiBBsValueReachabilityCheck = 20; // The max limit of the search depth in DecomposeGEPExpression() and -// getUnderlyingObject(), both functions need to use the same search -// depth otherwise the algorithm in aliasGEP will assert. +// getUnderlyingObject(). static const unsigned MaxLookupSearchDepth = 6; bool BasicAAResult::invalidate(Function &Fn, const PreservedAnalyses &PA, @@ -120,9 +111,6 @@ static bool isEscapeSource(const Value *V) { if (isa<CallBase>(V)) return true; - if (isa<Argument>(V)) - return true; - // The load case works because isNonEscapingLocalObject considers all // stores to be escapes (it passes true for the StoreCaptures argument // to PointerMayBeCaptured). @@ -206,12 +194,12 @@ static uint64_t getMinimalExtentFrom(const Value &V, bool NullIsValidLoc) { // If we have dereferenceability information we know a lower bound for the // extent as accesses for a lower offset would be valid. We need to exclude - // the "or null" part if null is a valid pointer. + // the "or null" part if null is a valid pointer. We can ignore frees, as an + // access after free would be undefined behavior. bool CanBeNull, CanBeFreed; uint64_t DerefBytes = V.getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed); DerefBytes = (CanBeNull && NullIsValidLoc) ? 0 : DerefBytes; - DerefBytes = CanBeFreed ? 0 : DerefBytes; // If queried with a precise location size, we assume that location size to be // accessed, thus valid. if (LocSize.isPrecise()) @@ -227,82 +215,163 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL, } //===----------------------------------------------------------------------===// +// CaptureInfo implementations +//===----------------------------------------------------------------------===// + +CaptureInfo::~CaptureInfo() = default; + +bool SimpleCaptureInfo::isNotCapturedBeforeOrAt(const Value *Object, + const Instruction *I) { + return isNonEscapingLocalObject(Object, &IsCapturedCache); +} + +bool EarliestEscapeInfo::isNotCapturedBeforeOrAt(const Value *Object, + const Instruction *I) { + if (!isIdentifiedFunctionLocal(Object)) + return false; + + auto Iter = EarliestEscapes.insert({Object, nullptr}); + if (Iter.second) { + Instruction *EarliestCapture = FindEarliestCapture( + Object, *const_cast<Function *>(I->getFunction()), + /*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT); + if (EarliestCapture) { + auto Ins = Inst2Obj.insert({EarliestCapture, {}}); + Ins.first->second.push_back(Object); + } + Iter.first->second = EarliestCapture; + } + + // No capturing instruction. + if (!Iter.first->second) + return true; + + return I != Iter.first->second && + !isPotentiallyReachable(Iter.first->second, I, nullptr, &DT, &LI); +} + +void EarliestEscapeInfo::removeInstruction(Instruction *I) { + auto Iter = Inst2Obj.find(I); + if (Iter != Inst2Obj.end()) { + for (const Value *Obj : Iter->second) + EarliestEscapes.erase(Obj); + Inst2Obj.erase(I); + } +} + +//===----------------------------------------------------------------------===// // GetElementPtr Instruction Decomposition and Analysis //===----------------------------------------------------------------------===// namespace { -/// Represents zext(sext(V)). -struct ExtendedValue { +/// Represents zext(sext(trunc(V))). +struct CastedValue { const Value *V; - unsigned ZExtBits; - unsigned SExtBits; + unsigned ZExtBits = 0; + unsigned SExtBits = 0; + unsigned TruncBits = 0; - explicit ExtendedValue(const Value *V, unsigned ZExtBits = 0, - unsigned SExtBits = 0) - : V(V), ZExtBits(ZExtBits), SExtBits(SExtBits) {} + explicit CastedValue(const Value *V) : V(V) {} + explicit CastedValue(const Value *V, unsigned ZExtBits, unsigned SExtBits, + unsigned TruncBits) + : V(V), ZExtBits(ZExtBits), SExtBits(SExtBits), TruncBits(TruncBits) {} unsigned getBitWidth() const { - return V->getType()->getPrimitiveSizeInBits() + ZExtBits + SExtBits; + return V->getType()->getPrimitiveSizeInBits() - TruncBits + ZExtBits + + SExtBits; } - ExtendedValue withValue(const Value *NewV) const { - return ExtendedValue(NewV, ZExtBits, SExtBits); + CastedValue withValue(const Value *NewV) const { + return CastedValue(NewV, ZExtBits, SExtBits, TruncBits); } - ExtendedValue withZExtOfValue(const Value *NewV) const { + /// Replace V with zext(NewV) + CastedValue withZExtOfValue(const Value *NewV) const { unsigned ExtendBy = V->getType()->getPrimitiveSizeInBits() - NewV->getType()->getPrimitiveSizeInBits(); + if (ExtendBy <= TruncBits) + return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy); + // zext(sext(zext(NewV))) == zext(zext(zext(NewV))) - return ExtendedValue(NewV, ZExtBits + SExtBits + ExtendBy, 0); + ExtendBy -= TruncBits; + return CastedValue(NewV, ZExtBits + SExtBits + ExtendBy, 0, 0); } - ExtendedValue withSExtOfValue(const Value *NewV) const { + /// Replace V with sext(NewV) + CastedValue withSExtOfValue(const Value *NewV) const { unsigned ExtendBy = V->getType()->getPrimitiveSizeInBits() - NewV->getType()->getPrimitiveSizeInBits(); + if (ExtendBy <= TruncBits) + return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy); + // zext(sext(sext(NewV))) - return ExtendedValue(NewV, ZExtBits, SExtBits + ExtendBy); + ExtendBy -= TruncBits; + return CastedValue(NewV, ZExtBits, SExtBits + ExtendBy, 0); } APInt evaluateWith(APInt N) const { assert(N.getBitWidth() == V->getType()->getPrimitiveSizeInBits() && "Incompatible bit width"); + if (TruncBits) N = N.trunc(N.getBitWidth() - TruncBits); if (SExtBits) N = N.sext(N.getBitWidth() + SExtBits); if (ZExtBits) N = N.zext(N.getBitWidth() + ZExtBits); return N; } + ConstantRange evaluateWith(ConstantRange N) const { + assert(N.getBitWidth() == V->getType()->getPrimitiveSizeInBits() && + "Incompatible bit width"); + if (TruncBits) N = N.truncate(N.getBitWidth() - TruncBits); + if (SExtBits) N = N.signExtend(N.getBitWidth() + SExtBits); + if (ZExtBits) N = N.zeroExtend(N.getBitWidth() + ZExtBits); + return N; + } + bool canDistributeOver(bool NUW, bool NSW) const { // zext(x op<nuw> y) == zext(x) op<nuw> zext(y) // sext(x op<nsw> y) == sext(x) op<nsw> sext(y) + // trunc(x op y) == trunc(x) op trunc(y) return (!ZExtBits || NUW) && (!SExtBits || NSW); } + + bool hasSameCastsAs(const CastedValue &Other) const { + return ZExtBits == Other.ZExtBits && SExtBits == Other.SExtBits && + TruncBits == Other.TruncBits; + } }; -/// Represents zext(sext(V)) * Scale + Offset. +/// Represents zext(sext(trunc(V))) * Scale + Offset. struct LinearExpression { - ExtendedValue Val; + CastedValue Val; APInt Scale; APInt Offset; /// True if all operations in this expression are NSW. bool IsNSW; - LinearExpression(const ExtendedValue &Val, const APInt &Scale, + LinearExpression(const CastedValue &Val, const APInt &Scale, const APInt &Offset, bool IsNSW) : Val(Val), Scale(Scale), Offset(Offset), IsNSW(IsNSW) {} - LinearExpression(const ExtendedValue &Val) : Val(Val), IsNSW(true) { + LinearExpression(const CastedValue &Val) : Val(Val), IsNSW(true) { unsigned BitWidth = Val.getBitWidth(); Scale = APInt(BitWidth, 1); Offset = APInt(BitWidth, 0); } + + LinearExpression mul(const APInt &Other, bool MulIsNSW) const { + // The check for zero offset is necessary, because generally + // (X +nsw Y) *nsw Z does not imply (X *nsw Z) +nsw (Y *nsw Z). + bool NSW = IsNSW && (Other.isOne() || (MulIsNSW && Offset.isZero())); + return LinearExpression(Val, Scale * Other, Offset * Other, NSW); + } }; } /// Analyzes the specified value as a linear expression: "A*V + B", where A and /// B are constant integers. static LinearExpression GetLinearExpression( - const ExtendedValue &Val, const DataLayout &DL, unsigned Depth, + const CastedValue &Val, const DataLayout &DL, unsigned Depth, AssumptionCache *AC, DominatorTree *DT) { // Limit our recursion depth. if (Depth == 6) @@ -325,6 +394,11 @@ static LinearExpression GetLinearExpression( if (!Val.canDistributeOver(NUW, NSW)) return Val; + // While we can distribute over trunc, we cannot preserve nowrap flags + // in that case. + if (Val.TruncBits) + NUW = NSW = false; + LinearExpression E(Val); switch (BOp->getOpcode()) { default: @@ -353,14 +427,11 @@ static LinearExpression GetLinearExpression( E.IsNSW &= NSW; break; } - case Instruction::Mul: { + case Instruction::Mul: E = GetLinearExpression(Val.withValue(BOp->getOperand(0)), DL, - Depth + 1, AC, DT); - E.Offset *= RHS; - E.Scale *= RHS; - E.IsNSW &= NSW; + Depth + 1, AC, DT) + .mul(RHS, NSW); break; - } case Instruction::Shl: // We're trying to linearize an expression of the kind: // shl i8 -128, 36 @@ -394,25 +465,75 @@ static LinearExpression GetLinearExpression( return Val; } -/// To ensure a pointer offset fits in an integer of size PointerSize -/// (in bits) when that size is smaller than the maximum pointer size. This is +/// To ensure a pointer offset fits in an integer of size IndexSize +/// (in bits) when that size is smaller than the maximum index size. This is /// an issue, for example, in particular for 32b pointers with negative indices /// that rely on two's complement wrap-arounds for precise alias information -/// where the maximum pointer size is 64b. -static APInt adjustToPointerSize(const APInt &Offset, unsigned PointerSize) { - assert(PointerSize <= Offset.getBitWidth() && "Invalid PointerSize!"); - unsigned ShiftBits = Offset.getBitWidth() - PointerSize; +/// where the maximum index size is 64b. +static APInt adjustToIndexSize(const APInt &Offset, unsigned IndexSize) { + assert(IndexSize <= Offset.getBitWidth() && "Invalid IndexSize!"); + unsigned ShiftBits = Offset.getBitWidth() - IndexSize; return (Offset << ShiftBits).ashr(ShiftBits); } -static unsigned getMaxPointerSize(const DataLayout &DL) { - unsigned MaxPointerSize = DL.getMaxPointerSizeInBits(); - if (MaxPointerSize < 64 && ForceAtLeast64Bits) MaxPointerSize = 64; - if (DoubleCalcBits) MaxPointerSize *= 2; +namespace { +// A linear transformation of a Value; this class represents +// ZExt(SExt(Trunc(V, TruncBits), SExtBits), ZExtBits) * Scale. +struct VariableGEPIndex { + CastedValue Val; + APInt Scale; + + // Context instruction to use when querying information about this index. + const Instruction *CxtI; - return MaxPointerSize; + /// True if all operations in this expression are NSW. + bool IsNSW; + + void dump() const { + print(dbgs()); + dbgs() << "\n"; + } + void print(raw_ostream &OS) const { + OS << "(V=" << Val.V->getName() + << ", zextbits=" << Val.ZExtBits + << ", sextbits=" << Val.SExtBits + << ", truncbits=" << Val.TruncBits + << ", scale=" << Scale << ")"; + } +}; } +// Represents the internal structure of a GEP, decomposed into a base pointer, +// constant offsets, and variable scaled indices. +struct BasicAAResult::DecomposedGEP { + // Base pointer of the GEP + const Value *Base; + // Total constant offset from base. + APInt Offset; + // Scaled variable (non-constant) indices. + SmallVector<VariableGEPIndex, 4> VarIndices; + // Are all operations inbounds GEPs or non-indexing operations? + // (None iff expression doesn't involve any geps) + Optional<bool> InBounds; + + void dump() const { + print(dbgs()); + dbgs() << "\n"; + } + void print(raw_ostream &OS) const { + OS << "(DecomposedGEP Base=" << Base->getName() + << ", Offset=" << Offset + << ", VarIndices=["; + for (size_t i = 0; i < VarIndices.size(); i++) { + if (i != 0) + OS << ", "; + VarIndices[i].print(OS); + } + OS << "])"; + } +}; + + /// If V is a symbolic pointer expression, decompose it into a base pointer /// with a constant offset and a number of scaled symbolic offsets. /// @@ -420,11 +541,6 @@ static unsigned getMaxPointerSize(const DataLayout &DL) { /// in the VarIndices vector) are Value*'s that are known to be scaled by the /// specified amount, but which may have other unrepresented high bits. As /// such, the gep cannot necessarily be reconstructed from its decomposed form. -/// -/// This function is capable of analyzing everything that getUnderlyingObject -/// can look through. To be able to do that getUnderlyingObject and -/// DecomposeGEPExpression must use the same search depth -/// (MaxLookupSearchDepth). BasicAAResult::DecomposedGEP BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT) { @@ -433,10 +549,9 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL, SearchTimes++; const Instruction *CxtI = dyn_cast<Instruction>(V); - unsigned MaxPointerSize = getMaxPointerSize(DL); + unsigned MaxIndexSize = DL.getMaxIndexSizeInBits(); DecomposedGEP Decomposed; - Decomposed.Offset = APInt(MaxPointerSize, 0); - Decomposed.HasCompileTimeConstantScale = true; + Decomposed.Offset = APInt(MaxIndexSize, 0); do { // See if this is a bitcast or GEP. const Operator *Op = dyn_cast<Operator>(V); @@ -493,24 +608,19 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL, else if (!GEPOp->isInBounds()) Decomposed.InBounds = false; - // Don't attempt to analyze GEPs over unsized objects. - if (!GEPOp->getSourceElementType()->isSized()) { - Decomposed.Base = V; - return Decomposed; - } + assert(GEPOp->getSourceElementType()->isSized() && "GEP must be sized"); // Don't attempt to analyze GEPs if index scale is not a compile-time // constant. if (isa<ScalableVectorType>(GEPOp->getSourceElementType())) { Decomposed.Base = V; - Decomposed.HasCompileTimeConstantScale = false; return Decomposed; } unsigned AS = GEPOp->getPointerAddressSpace(); // Walk the indices of the GEP, accumulating them into BaseOff/VarIndices. gep_type_iterator GTI = gep_type_begin(GEPOp); - unsigned PointerSize = DL.getPointerSizeInBits(AS); + unsigned IndexSize = DL.getIndexSizeInBits(AS); // Assume all GEP operands are constants until proven otherwise. bool GepHasConstantOffset = true; for (User::const_op_iterator I = GEPOp->op_begin() + 1, E = GEPOp->op_end(); @@ -533,49 +643,34 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL, continue; Decomposed.Offset += DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize() * - CIdx->getValue().sextOrTrunc(MaxPointerSize); + CIdx->getValue().sextOrTrunc(MaxIndexSize); continue; } GepHasConstantOffset = false; - APInt Scale(MaxPointerSize, - DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize()); - // If the integer type is smaller than the pointer size, it is implicitly - // sign extended to pointer size. + // If the integer type is smaller than the index size, it is implicitly + // sign extended or truncated to index size. unsigned Width = Index->getType()->getIntegerBitWidth(); - unsigned SExtBits = PointerSize > Width ? PointerSize - Width : 0; + unsigned SExtBits = IndexSize > Width ? IndexSize - Width : 0; + unsigned TruncBits = IndexSize < Width ? Width - IndexSize : 0; LinearExpression LE = GetLinearExpression( - ExtendedValue(Index, 0, SExtBits), DL, 0, AC, DT); - - // The GEP index scale ("Scale") scales C1*V+C2, yielding (C1*V+C2)*Scale. - // This gives us an aggregate computation of (C1*Scale)*V + C2*Scale. + CastedValue(Index, 0, SExtBits, TruncBits), DL, 0, AC, DT); - // It can be the case that, even through C1*V+C2 does not overflow for - // relevant values of V, (C2*Scale) can overflow. In that case, we cannot - // decompose the expression in this way. - // - // FIXME: C1*Scale and the other operations in the decomposed - // (C1*Scale)*V+C2*Scale can also overflow. We should check for this - // possibility. - bool Overflow; - APInt ScaledOffset = LE.Offset.sextOrTrunc(MaxPointerSize) - .smul_ov(Scale, Overflow); - if (Overflow) { - LE = LinearExpression(ExtendedValue(Index, 0, SExtBits)); - } else { - Decomposed.Offset += ScaledOffset; - Scale *= LE.Scale.sextOrTrunc(MaxPointerSize); - } + // Scale by the type size. + unsigned TypeSize = + DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize(); + LE = LE.mul(APInt(IndexSize, TypeSize), GEPOp->isInBounds()); + Decomposed.Offset += LE.Offset.sextOrSelf(MaxIndexSize); + APInt Scale = LE.Scale.sextOrSelf(MaxIndexSize); // If we already had an occurrence of this index variable, merge this // scale into it. For example, we want to handle: // A[x][x] -> x*16 + x*4 -> x*20 // This also ensures that 'x' only appears in the index list once. for (unsigned i = 0, e = Decomposed.VarIndices.size(); i != e; ++i) { - if (Decomposed.VarIndices[i].V == LE.Val.V && - Decomposed.VarIndices[i].ZExtBits == LE.Val.ZExtBits && - Decomposed.VarIndices[i].SExtBits == LE.Val.SExtBits) { + if (Decomposed.VarIndices[i].Val.V == LE.Val.V && + Decomposed.VarIndices[i].Val.hasSameCastsAs(LE.Val)) { Scale += Decomposed.VarIndices[i].Scale; Decomposed.VarIndices.erase(Decomposed.VarIndices.begin() + i); break; @@ -583,19 +678,18 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL, } // Make sure that we have a scale that makes sense for this target's - // pointer size. - Scale = adjustToPointerSize(Scale, PointerSize); + // index size. + Scale = adjustToIndexSize(Scale, IndexSize); if (!!Scale) { - VariableGEPIndex Entry = { - LE.Val.V, LE.Val.ZExtBits, LE.Val.SExtBits, Scale, CxtI, LE.IsNSW}; + VariableGEPIndex Entry = {LE.Val, Scale, CxtI, LE.IsNSW}; Decomposed.VarIndices.push_back(Entry); } } // Take care of wrap-arounds if (GepHasConstantOffset) - Decomposed.Offset = adjustToPointerSize(Decomposed.Offset, PointerSize); + Decomposed.Offset = adjustToIndexSize(Decomposed.Offset, IndexSize); // Analyze the base pointer next. V = GEPOp->getOperand(0); @@ -838,7 +932,7 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call, // then the call can not mod/ref the pointer unless the call takes the pointer // as an argument, and itself doesn't capture it. if (!isa<Constant>(Object) && Call != Object && - isNonEscapingLocalObject(Object, &AAQI.IsCapturedCache)) { + AAQI.CI->isNotCapturedBeforeOrAt(Object, Call)) { // Optimistically assume that call doesn't touch Object and check this // assumption in the following loop. @@ -852,8 +946,7 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call, // pointer were passed to arguments that were neither of these, then it // couldn't be no-capture. if (!(*CI)->getType()->isPointerTy() || - (!Call->doesNotCapture(OperandNo) && - OperandNo < Call->getNumArgOperands() && + (!Call->doesNotCapture(OperandNo) && OperandNo < Call->arg_size() && !Call->isByValArgument(OperandNo))) continue; @@ -1046,20 +1139,13 @@ AliasResult BasicAAResult::aliasGEP( DecomposedGEP DecompGEP1 = DecomposeGEPExpression(GEP1, DL, &AC, DT); DecomposedGEP DecompGEP2 = DecomposeGEPExpression(V2, DL, &AC, DT); - // Don't attempt to analyze the decomposed GEP if index scale is not a - // compile-time constant. - if (!DecompGEP1.HasCompileTimeConstantScale || - !DecompGEP2.HasCompileTimeConstantScale) + // Bail if we were not able to decompose anything. + if (DecompGEP1.Base == GEP1 && DecompGEP2.Base == V2) return AliasResult::MayAlias; - assert(DecompGEP1.Base == UnderlyingV1 && DecompGEP2.Base == UnderlyingV2 && - "DecomposeGEPExpression returned a result different from " - "getUnderlyingObject"); - // Subtract the GEP2 pointer from the GEP1 pointer to find out their // symbolic difference. - DecompGEP1.Offset -= DecompGEP2.Offset; - GetIndexDifference(DecompGEP1.VarIndices, DecompGEP2.VarIndices); + subtractDecomposedGEPs(DecompGEP1, DecompGEP2); // If an inbounds GEP would have to start from an out of bounds address // for the two to alias, then we can assume noalias. @@ -1079,14 +1165,14 @@ AliasResult BasicAAResult::aliasGEP( // For GEPs with identical offsets, we can preserve the size and AAInfo // when performing the alias check on the underlying objects. if (DecompGEP1.Offset == 0 && DecompGEP1.VarIndices.empty()) - return getBestAAResults().alias( - MemoryLocation(UnderlyingV1, V1Size), - MemoryLocation(UnderlyingV2, V2Size), AAQI); + return getBestAAResults().alias(MemoryLocation(DecompGEP1.Base, V1Size), + MemoryLocation(DecompGEP2.Base, V2Size), + AAQI); // Do the base pointers alias? AliasResult BaseAlias = getBestAAResults().alias( - MemoryLocation::getBeforeOrAfter(UnderlyingV1), - MemoryLocation::getBeforeOrAfter(UnderlyingV2), AAQI); + MemoryLocation::getBeforeOrAfter(DecompGEP1.Base), + MemoryLocation::getBeforeOrAfter(DecompGEP2.Base), AAQI); // If we get a No or May, then return it immediately, no amount of analysis // will improve this situation. @@ -1100,7 +1186,7 @@ AliasResult BasicAAResult::aliasGEP( // is less than the size of the associated memory object, then we know // that the objects are partially overlapping. If the difference is // greater, we know they do not overlap. - if (DecompGEP1.Offset != 0 && DecompGEP1.VarIndices.empty()) { + if (DecompGEP1.VarIndices.empty()) { APInt &Off = DecompGEP1.Offset; // Initialize for Off >= 0 (V2 <= GEP1) case. @@ -1122,133 +1208,124 @@ AliasResult BasicAAResult::aliasGEP( Off = -Off; } - if (VLeftSize.hasValue()) { - const uint64_t LSize = VLeftSize.getValue(); - if (Off.ult(LSize)) { - // Conservatively drop processing if a phi was visited and/or offset is - // too big. - AliasResult AR = AliasResult::PartialAlias; - if (VRightSize.hasValue() && Off.ule(INT32_MAX) && - (Off + VRightSize.getValue()).ule(LSize)) { - // Memory referenced by right pointer is nested. Save the offset in - // cache. Note that originally offset estimated as GEP1-V2, but - // AliasResult contains the shift that represents GEP1+Offset=V2. - AR.setOffset(-Off.getSExtValue()); - AR.swap(Swapped); - } - return AR; + if (!VLeftSize.hasValue()) + return AliasResult::MayAlias; + + const uint64_t LSize = VLeftSize.getValue(); + if (Off.ult(LSize)) { + // Conservatively drop processing if a phi was visited and/or offset is + // too big. + AliasResult AR = AliasResult::PartialAlias; + if (VRightSize.hasValue() && Off.ule(INT32_MAX) && + (Off + VRightSize.getValue()).ule(LSize)) { + // Memory referenced by right pointer is nested. Save the offset in + // cache. Note that originally offset estimated as GEP1-V2, but + // AliasResult contains the shift that represents GEP1+Offset=V2. + AR.setOffset(-Off.getSExtValue()); + AR.swap(Swapped); } - return AliasResult::NoAlias; + return AR; } + return AliasResult::NoAlias; } - if (!DecompGEP1.VarIndices.empty()) { - APInt GCD; - bool AllNonNegative = DecompGEP1.Offset.isNonNegative(); - bool AllNonPositive = DecompGEP1.Offset.isNonPositive(); - for (unsigned i = 0, e = DecompGEP1.VarIndices.size(); i != e; ++i) { - APInt Scale = DecompGEP1.VarIndices[i].Scale; - APInt ScaleForGCD = DecompGEP1.VarIndices[i].Scale; - if (!DecompGEP1.VarIndices[i].IsNSW) - ScaleForGCD = APInt::getOneBitSet(Scale.getBitWidth(), - Scale.countTrailingZeros()); - - if (i == 0) - GCD = ScaleForGCD.abs(); - else - GCD = APIntOps::GreatestCommonDivisor(GCD, ScaleForGCD.abs()); - - if (AllNonNegative || AllNonPositive) { - // If the Value could change between cycles, then any reasoning about - // the Value this cycle may not hold in the next cycle. We'll just - // give up if we can't determine conditions that hold for every cycle: - const Value *V = DecompGEP1.VarIndices[i].V; - const Instruction *CxtI = DecompGEP1.VarIndices[i].CxtI; + // We need to know both acess sizes for all the following heuristics. + if (!V1Size.hasValue() || !V2Size.hasValue()) + return AliasResult::MayAlias; - KnownBits Known = computeKnownBits(V, DL, 0, &AC, CxtI, DT); - bool SignKnownZero = Known.isNonNegative(); - bool SignKnownOne = Known.isNegative(); + APInt GCD; + ConstantRange OffsetRange = ConstantRange(DecompGEP1.Offset); + for (unsigned i = 0, e = DecompGEP1.VarIndices.size(); i != e; ++i) { + const VariableGEPIndex &Index = DecompGEP1.VarIndices[i]; + const APInt &Scale = Index.Scale; + APInt ScaleForGCD = Scale; + if (!Index.IsNSW) + ScaleForGCD = APInt::getOneBitSet(Scale.getBitWidth(), + Scale.countTrailingZeros()); - // Zero-extension widens the variable, and so forces the sign - // bit to zero. - bool IsZExt = DecompGEP1.VarIndices[i].ZExtBits > 0 || isa<ZExtInst>(V); - SignKnownZero |= IsZExt; - SignKnownOne &= !IsZExt; + if (i == 0) + GCD = ScaleForGCD.abs(); + else + GCD = APIntOps::GreatestCommonDivisor(GCD, ScaleForGCD.abs()); - AllNonNegative &= (SignKnownZero && Scale.isNonNegative()) || - (SignKnownOne && Scale.isNonPositive()); - AllNonPositive &= (SignKnownZero && Scale.isNonPositive()) || - (SignKnownOne && Scale.isNonNegative()); - } - } + ConstantRange CR = + computeConstantRange(Index.Val.V, true, &AC, Index.CxtI); + KnownBits Known = + computeKnownBits(Index.Val.V, DL, 0, &AC, Index.CxtI, DT); + CR = CR.intersectWith( + ConstantRange::fromKnownBits(Known, /* Signed */ true), + ConstantRange::Signed); + CR = Index.Val.evaluateWith(CR).sextOrTrunc(OffsetRange.getBitWidth()); - // We now have accesses at two offsets from the same base: - // 1. (...)*GCD + DecompGEP1.Offset with size V1Size - // 2. 0 with size V2Size - // Using arithmetic modulo GCD, the accesses are at - // [ModOffset..ModOffset+V1Size) and [0..V2Size). If the first access fits - // into the range [V2Size..GCD), then we know they cannot overlap. - APInt ModOffset = DecompGEP1.Offset.srem(GCD); - if (ModOffset.isNegative()) - ModOffset += GCD; // We want mod, not rem. - if (V1Size.hasValue() && V2Size.hasValue() && - ModOffset.uge(V2Size.getValue()) && - (GCD - ModOffset).uge(V1Size.getValue())) - return AliasResult::NoAlias; + assert(OffsetRange.getBitWidth() == Scale.getBitWidth() && + "Bit widths are normalized to MaxIndexSize"); + if (Index.IsNSW) + OffsetRange = OffsetRange.add(CR.smul_sat(ConstantRange(Scale))); + else + OffsetRange = OffsetRange.add(CR.smul_fast(ConstantRange(Scale))); + } - // If we know all the variables are non-negative, then the total offset is - // also non-negative and >= DecompGEP1.Offset. We have the following layout: - // [0, V2Size) ... [TotalOffset, TotalOffer+V1Size] - // If DecompGEP1.Offset >= V2Size, the accesses don't alias. - if (AllNonNegative && V2Size.hasValue() && - DecompGEP1.Offset.uge(V2Size.getValue())) - return AliasResult::NoAlias; - // Similarly, if the variables are non-positive, then the total offset is - // also non-positive and <= DecompGEP1.Offset. We have the following layout: - // [TotalOffset, TotalOffset+V1Size) ... [0, V2Size) - // If -DecompGEP1.Offset >= V1Size, the accesses don't alias. - if (AllNonPositive && V1Size.hasValue() && - (-DecompGEP1.Offset).uge(V1Size.getValue())) - return AliasResult::NoAlias; + // We now have accesses at two offsets from the same base: + // 1. (...)*GCD + DecompGEP1.Offset with size V1Size + // 2. 0 with size V2Size + // Using arithmetic modulo GCD, the accesses are at + // [ModOffset..ModOffset+V1Size) and [0..V2Size). If the first access fits + // into the range [V2Size..GCD), then we know they cannot overlap. + APInt ModOffset = DecompGEP1.Offset.srem(GCD); + if (ModOffset.isNegative()) + ModOffset += GCD; // We want mod, not rem. + if (ModOffset.uge(V2Size.getValue()) && + (GCD - ModOffset).uge(V1Size.getValue())) + return AliasResult::NoAlias; - if (V1Size.hasValue() && V2Size.hasValue()) { - // Try to determine whether abs(VarIndex) > 0. - Optional<APInt> MinAbsVarIndex; - if (DecompGEP1.VarIndices.size() == 1) { - // VarIndex = Scale*V. If V != 0 then abs(VarIndex) >= abs(Scale). - const VariableGEPIndex &Var = DecompGEP1.VarIndices[0]; - if (isKnownNonZero(Var.V, DL, 0, &AC, Var.CxtI, DT)) - MinAbsVarIndex = Var.Scale.abs(); - } else if (DecompGEP1.VarIndices.size() == 2) { - // VarIndex = Scale*V0 + (-Scale)*V1. - // If V0 != V1 then abs(VarIndex) >= abs(Scale). - // Check that VisitedPhiBBs is empty, to avoid reasoning about - // inequality of values across loop iterations. - const VariableGEPIndex &Var0 = DecompGEP1.VarIndices[0]; - const VariableGEPIndex &Var1 = DecompGEP1.VarIndices[1]; - if (Var0.Scale == -Var1.Scale && Var0.ZExtBits == Var1.ZExtBits && - Var0.SExtBits == Var1.SExtBits && VisitedPhiBBs.empty() && - isKnownNonEqual(Var0.V, Var1.V, DL, &AC, /* CxtI */ nullptr, DT)) - MinAbsVarIndex = Var0.Scale.abs(); - } + // Compute ranges of potentially accessed bytes for both accesses. If the + // interseciton is empty, there can be no overlap. + unsigned BW = OffsetRange.getBitWidth(); + ConstantRange Range1 = OffsetRange.add( + ConstantRange(APInt(BW, 0), APInt(BW, V1Size.getValue()))); + ConstantRange Range2 = + ConstantRange(APInt(BW, 0), APInt(BW, V2Size.getValue())); + if (Range1.intersectWith(Range2).isEmptySet()) + return AliasResult::NoAlias; - if (MinAbsVarIndex) { - // The constant offset will have added at least +/-MinAbsVarIndex to it. - APInt OffsetLo = DecompGEP1.Offset - *MinAbsVarIndex; - APInt OffsetHi = DecompGEP1.Offset + *MinAbsVarIndex; - // Check that an access at OffsetLo or lower, and an access at OffsetHi - // or higher both do not alias. - if (OffsetLo.isNegative() && (-OffsetLo).uge(V1Size.getValue()) && - OffsetHi.isNonNegative() && OffsetHi.uge(V2Size.getValue())) - return AliasResult::NoAlias; - } + // Try to determine the range of values for VarIndex such that + // VarIndex <= -MinAbsVarIndex || MinAbsVarIndex <= VarIndex. + Optional<APInt> MinAbsVarIndex; + if (DecompGEP1.VarIndices.size() == 1) { + // VarIndex = Scale*V. + const VariableGEPIndex &Var = DecompGEP1.VarIndices[0]; + if (Var.Val.TruncBits == 0 && + isKnownNonZero(Var.Val.V, DL, 0, &AC, Var.CxtI, DT)) { + // If V != 0 then abs(VarIndex) >= abs(Scale). + MinAbsVarIndex = Var.Scale.abs(); } + } else if (DecompGEP1.VarIndices.size() == 2) { + // VarIndex = Scale*V0 + (-Scale)*V1. + // If V0 != V1 then abs(VarIndex) >= abs(Scale). + // Check that VisitedPhiBBs is empty, to avoid reasoning about + // inequality of values across loop iterations. + const VariableGEPIndex &Var0 = DecompGEP1.VarIndices[0]; + const VariableGEPIndex &Var1 = DecompGEP1.VarIndices[1]; + if (Var0.Scale == -Var1.Scale && Var0.Val.TruncBits == 0 && + Var0.Val.hasSameCastsAs(Var1.Val) && VisitedPhiBBs.empty() && + isKnownNonEqual(Var0.Val.V, Var1.Val.V, DL, &AC, /* CxtI */ nullptr, + DT)) + MinAbsVarIndex = Var0.Scale.abs(); + } - if (constantOffsetHeuristic(DecompGEP1.VarIndices, V1Size, V2Size, - DecompGEP1.Offset, &AC, DT)) + if (MinAbsVarIndex) { + // The constant offset will have added at least +/-MinAbsVarIndex to it. + APInt OffsetLo = DecompGEP1.Offset - *MinAbsVarIndex; + APInt OffsetHi = DecompGEP1.Offset + *MinAbsVarIndex; + // We know that Offset <= OffsetLo || Offset >= OffsetHi + if (OffsetLo.isNegative() && (-OffsetLo).uge(V1Size.getValue()) && + OffsetHi.isNonNegative() && OffsetHi.uge(V2Size.getValue())) return AliasResult::NoAlias; } + if (constantOffsetHeuristic(DecompGEP1, V1Size, V2Size, &AC, DT)) + return AliasResult::NoAlias; + // Statically, we can see that the base objects are the same, but the // pointers have dynamic offsets which we can't resolve. And none of our // little tricks above worked. @@ -1517,10 +1594,10 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size, // location if that memory location doesn't escape. Or it may pass a // nocapture value to other functions as long as they don't capture it. if (isEscapeSource(O1) && - isNonEscapingLocalObject(O2, &AAQI.IsCapturedCache)) + AAQI.CI->isNotCapturedBeforeOrAt(O2, cast<Instruction>(O1))) return AliasResult::NoAlias; if (isEscapeSource(O2) && - isNonEscapingLocalObject(O1, &AAQI.IsCapturedCache)) + AAQI.CI->isNotCapturedBeforeOrAt(O1, cast<Instruction>(O2))) return AliasResult::NoAlias; } @@ -1692,62 +1769,54 @@ bool BasicAAResult::isValueEqualInPotentialCycles(const Value *V, } /// Computes the symbolic difference between two de-composed GEPs. -/// -/// Dest and Src are the variable indices from two decomposed GetElementPtr -/// instructions GEP1 and GEP2 which have common base pointers. -void BasicAAResult::GetIndexDifference( - SmallVectorImpl<VariableGEPIndex> &Dest, - const SmallVectorImpl<VariableGEPIndex> &Src) { - if (Src.empty()) - return; - - for (unsigned i = 0, e = Src.size(); i != e; ++i) { - const Value *V = Src[i].V; - unsigned ZExtBits = Src[i].ZExtBits, SExtBits = Src[i].SExtBits; - APInt Scale = Src[i].Scale; - +void BasicAAResult::subtractDecomposedGEPs(DecomposedGEP &DestGEP, + const DecomposedGEP &SrcGEP) { + DestGEP.Offset -= SrcGEP.Offset; + for (const VariableGEPIndex &Src : SrcGEP.VarIndices) { // Find V in Dest. This is N^2, but pointer indices almost never have more // than a few variable indexes. - for (unsigned j = 0, e = Dest.size(); j != e; ++j) { - if (!isValueEqualInPotentialCycles(Dest[j].V, V) || - Dest[j].ZExtBits != ZExtBits || Dest[j].SExtBits != SExtBits) + bool Found = false; + for (auto I : enumerate(DestGEP.VarIndices)) { + VariableGEPIndex &Dest = I.value(); + if (!isValueEqualInPotentialCycles(Dest.Val.V, Src.Val.V) || + !Dest.Val.hasSameCastsAs(Src.Val)) continue; // If we found it, subtract off Scale V's from the entry in Dest. If it // goes to zero, remove the entry. - if (Dest[j].Scale != Scale) { - Dest[j].Scale -= Scale; - Dest[j].IsNSW = false; - } else - Dest.erase(Dest.begin() + j); - Scale = 0; + if (Dest.Scale != Src.Scale) { + Dest.Scale -= Src.Scale; + Dest.IsNSW = false; + } else { + DestGEP.VarIndices.erase(DestGEP.VarIndices.begin() + I.index()); + } + Found = true; break; } // If we didn't consume this entry, add it to the end of the Dest list. - if (!!Scale) { - VariableGEPIndex Entry = {V, ZExtBits, SExtBits, - -Scale, Src[i].CxtI, Src[i].IsNSW}; - Dest.push_back(Entry); + if (!Found) { + VariableGEPIndex Entry = {Src.Val, -Src.Scale, Src.CxtI, Src.IsNSW}; + DestGEP.VarIndices.push_back(Entry); } } } bool BasicAAResult::constantOffsetHeuristic( - const SmallVectorImpl<VariableGEPIndex> &VarIndices, - LocationSize MaybeV1Size, LocationSize MaybeV2Size, const APInt &BaseOffset, - AssumptionCache *AC, DominatorTree *DT) { - if (VarIndices.size() != 2 || !MaybeV1Size.hasValue() || + const DecomposedGEP &GEP, LocationSize MaybeV1Size, + LocationSize MaybeV2Size, AssumptionCache *AC, DominatorTree *DT) { + if (GEP.VarIndices.size() != 2 || !MaybeV1Size.hasValue() || !MaybeV2Size.hasValue()) return false; const uint64_t V1Size = MaybeV1Size.getValue(); const uint64_t V2Size = MaybeV2Size.getValue(); - const VariableGEPIndex &Var0 = VarIndices[0], &Var1 = VarIndices[1]; + const VariableGEPIndex &Var0 = GEP.VarIndices[0], &Var1 = GEP.VarIndices[1]; - if (Var0.ZExtBits != Var1.ZExtBits || Var0.SExtBits != Var1.SExtBits || - Var0.Scale != -Var1.Scale || Var0.V->getType() != Var1.V->getType()) + if (Var0.Val.TruncBits != 0 || !Var0.Val.hasSameCastsAs(Var1.Val) || + Var0.Scale != -Var1.Scale || + Var0.Val.V->getType() != Var1.Val.V->getType()) return false; // We'll strip off the Extensions of Var0 and Var1 and do another round @@ -1755,11 +1824,10 @@ bool BasicAAResult::constantOffsetHeuristic( // is zext(%x + 1) we should get V1 == %x and V1Offset == 1. LinearExpression E0 = - GetLinearExpression(ExtendedValue(Var0.V), DL, 0, AC, DT); + GetLinearExpression(CastedValue(Var0.Val.V), DL, 0, AC, DT); LinearExpression E1 = - GetLinearExpression(ExtendedValue(Var1.V), DL, 0, AC, DT); - if (E0.Scale != E1.Scale || E0.Val.ZExtBits != E1.Val.ZExtBits || - E0.Val.SExtBits != E1.Val.SExtBits || + GetLinearExpression(CastedValue(Var1.Val.V), DL, 0, AC, DT); + if (E0.Scale != E1.Scale || !E0.Val.hasSameCastsAs(E1.Val) || !isValueEqualInPotentialCycles(E0.Val.V, E1.Val.V)) return false; @@ -1779,8 +1847,8 @@ bool BasicAAResult::constantOffsetHeuristic( // arithmetic (i.e. for some values of GEP1 and V2 GEP1 < V2, and for other // values GEP1 > V2). We'll therefore only declare NoAlias if both V1Size and // V2Size can fit in the MinDiffBytes gap. - return MinDiffBytes.uge(V1Size + BaseOffset.abs()) && - MinDiffBytes.uge(V2Size + BaseOffset.abs()); + return MinDiffBytes.uge(V1Size + GEP.Offset.abs()) && + MinDiffBytes.uge(V2Size + GEP.Offset.abs()); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp index e4e45b3076be..2a5e1f65d731 100644 --- a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp +++ b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp @@ -602,7 +602,7 @@ BlockFrequencyInfoImplBase::getProfileCountFromFreq(const Function &F, if (!EntryCount) return None; // Use 128 bit APInt to do the arithmetic to avoid overflow. - APInt BlockCount(128, EntryCount.getCount()); + APInt BlockCount(128, EntryCount->getCount()); APInt BlockFreq(128, Freq); APInt EntryFreq(128, getEntryFreq()); BlockCount *= BlockFreq; diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp index aa6b93fe3f07..33fdc8b628c5 100644 --- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp +++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp @@ -190,7 +190,7 @@ void BranchProbabilityInfo::SccInfo::getSccExitBlocks( if (isSCCExitingBlock(BB, SccNum)) for (const auto *Succ : successors(BB)) if (getSCCNum(Succ) != SccNum) - Exits.push_back(const_cast<BasicBlock *>(BB)); + Exits.push_back(const_cast<BasicBlock *>(Succ)); } } diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp index 253cc0b0a579..c60b70ae5b69 100644 --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -38,12 +38,13 @@ using namespace llvm; // Explicit template instantiations and specialization definitions for core // template typedefs. namespace llvm { - static cl::opt<bool> AbortOnMaxDevirtIterationsReached( "abort-on-max-devirt-iterations-reached", cl::desc("Abort when the max iterations for devirtualization CGSCC repeat " "pass is reached")); +AnalysisKey ShouldNotRunFunctionPassesAnalysis::Key; + // Explicit instantiations for the core proxy templates. template class AllAnalysesOn<LazyCallGraph::SCC>; template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>; @@ -119,12 +120,6 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, // Finally, we intersect the final preserved analyses to compute the // aggregate preserved set for this pass manager. PA.intersect(std::move(PassPA)); - - // FIXME: Historically, the pass managers all called the LLVM context's - // yield function here. We don't have a generic way to acquire the - // context and it isn't yet clear what the right pattern is for yielding - // in the new pass manager so it is currently omitted. - // ...getContext().yield(); } // Before we mark all of *this* SCC's analyses as preserved below, intersect @@ -547,6 +542,9 @@ PreservedAnalyses CGSCCToFunctionPassAdaptor::run(LazyCallGraph::SCC &C, Function &F = N->getFunction(); + if (NoRerun && FAM.getCachedResult<ShouldNotRunFunctionPassesAnalysis>(F)) + continue; + PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F); if (!PI.runBeforePass<Function>(*Pass, F)) continue; @@ -562,7 +560,9 @@ PreservedAnalyses CGSCCToFunctionPassAdaptor::run(LazyCallGraph::SCC &C, // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. - FAM.invalidate(F, PassPA); + FAM.invalidate(F, EagerlyInvalidate ? PreservedAnalyses::none() : PassPA); + if (NoRerun) + (void)FAM.getResult<ShouldNotRunFunctionPassesAnalysis>(F); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -863,7 +863,7 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G, // split-off SCCs. // We know however that this will preserve any FAM proxy so go ahead and mark // that. - PreservedAnalyses PA; + auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>(); PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); AM.invalidate(*OldC, PA); diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp index 5fe4f9befc86..8955658cb9e7 100644 --- a/llvm/lib/Analysis/CaptureTracking.cpp +++ b/llvm/lib/Analysis/CaptureTracking.cpp @@ -98,10 +98,10 @@ namespace { /// as the given instruction and the use. struct CapturesBefore : public CaptureTracker { - CapturesBefore(bool ReturnCaptures, const Instruction *I, const DominatorTree *DT, - bool IncludeI) - : BeforeHere(I), DT(DT), - ReturnCaptures(ReturnCaptures), IncludeI(IncludeI), Captured(false) {} + CapturesBefore(bool ReturnCaptures, const Instruction *I, + const DominatorTree *DT, bool IncludeI, const LoopInfo *LI) + : BeforeHere(I), DT(DT), ReturnCaptures(ReturnCaptures), + IncludeI(IncludeI), Captured(false), LI(LI) {} void tooManyUses() override { Captured = true; } @@ -115,7 +115,7 @@ namespace { return true; // Check whether there is a path from I to BeforeHere. - return !isPotentiallyReachable(I, BeforeHere, nullptr, DT); + return !isPotentiallyReachable(I, BeforeHere, nullptr, DT, LI); } bool captured(const Use *U) override { @@ -140,6 +140,68 @@ namespace { bool IncludeI; bool Captured; + + const LoopInfo *LI; + }; + + /// Find the 'earliest' instruction before which the pointer is known not to + /// be captured. Here an instruction A is considered earlier than instruction + /// B, if A dominates B. If 2 escapes do not dominate each other, the + /// terminator of the common dominator is chosen. If not all uses cannot be + /// analyzed, the earliest escape is set to the first instruction in the + /// function entry block. + // NOTE: Users have to make sure instructions compared against the earliest + // escape are not in a cycle. + struct EarliestCaptures : public CaptureTracker { + + EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT) + : DT(DT), ReturnCaptures(ReturnCaptures), Captured(false), F(F) {} + + void tooManyUses() override { + Captured = true; + EarliestCapture = &*F.getEntryBlock().begin(); + } + + bool captured(const Use *U) override { + Instruction *I = cast<Instruction>(U->getUser()); + if (isa<ReturnInst>(I) && !ReturnCaptures) + return false; + + if (!EarliestCapture) { + EarliestCapture = I; + } else if (EarliestCapture->getParent() == I->getParent()) { + if (I->comesBefore(EarliestCapture)) + EarliestCapture = I; + } else { + BasicBlock *CurrentBB = I->getParent(); + BasicBlock *EarliestBB = EarliestCapture->getParent(); + if (DT.dominates(EarliestBB, CurrentBB)) { + // EarliestCapture already comes before the current use. + } else if (DT.dominates(CurrentBB, EarliestBB)) { + EarliestCapture = I; + } else { + // Otherwise find the nearest common dominator and use its terminator. + auto *NearestCommonDom = + DT.findNearestCommonDominator(CurrentBB, EarliestBB); + EarliestCapture = NearestCommonDom->getTerminator(); + } + } + Captured = true; + + // Return false to continue analysis; we need to see all potential + // captures. + return false; + } + + Instruction *EarliestCapture = nullptr; + + const DominatorTree &DT; + + bool ReturnCaptures; + + bool Captured; + + Function &F; }; } @@ -183,7 +245,8 @@ bool llvm::PointerMayBeCaptured(const Value *V, bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, const DominatorTree *DT, bool IncludeI, - unsigned MaxUsesToExplore) { + unsigned MaxUsesToExplore, + const LoopInfo *LI) { assert(!isa<GlobalValue>(V) && "It doesn't make sense to ask whether a global is captured."); @@ -194,7 +257,7 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, // TODO: See comment in PointerMayBeCaptured regarding what could be done // with StoreCaptures. - CapturesBefore CB(ReturnCaptures, I, DT, IncludeI); + CapturesBefore CB(ReturnCaptures, I, DT, IncludeI, LI); PointerMayBeCaptured(V, &CB, MaxUsesToExplore); if (CB.Captured) ++NumCapturedBefore; @@ -203,6 +266,22 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, return CB.Captured; } +Instruction *llvm::FindEarliestCapture(const Value *V, Function &F, + bool ReturnCaptures, bool StoreCaptures, + const DominatorTree &DT, + unsigned MaxUsesToExplore) { + assert(!isa<GlobalValue>(V) && + "It doesn't make sense to ask whether a global is captured."); + + EarliestCaptures CB(ReturnCaptures, F, DT); + PointerMayBeCaptured(V, &CB, MaxUsesToExplore); + if (CB.Captured) + ++NumCapturedBefore; + else + ++NumNotCapturedBefore; + return CB.EarliestCapture; +} + void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker, unsigned MaxUsesToExplore) { assert(V->getType()->isPointerTy() && "Capture is for pointers only!"); diff --git a/llvm/lib/Analysis/CmpInstAnalysis.cpp b/llvm/lib/Analysis/CmpInstAnalysis.cpp index a5757be2c4f4..5b951980a0aa 100644 --- a/llvm/lib/Analysis/CmpInstAnalysis.cpp +++ b/llvm/lib/Analysis/CmpInstAnalysis.cpp @@ -77,28 +77,28 @@ bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS, return false; case ICmpInst::ICMP_SLT: // X < 0 is equivalent to (X & SignMask) != 0. - if (!C->isNullValue()) + if (!C->isZero()) return false; Mask = APInt::getSignMask(C->getBitWidth()); Pred = ICmpInst::ICMP_NE; break; case ICmpInst::ICMP_SLE: // X <= -1 is equivalent to (X & SignMask) != 0. - if (!C->isAllOnesValue()) + if (!C->isAllOnes()) return false; Mask = APInt::getSignMask(C->getBitWidth()); Pred = ICmpInst::ICMP_NE; break; case ICmpInst::ICMP_SGT: // X > -1 is equivalent to (X & SignMask) == 0. - if (!C->isAllOnesValue()) + if (!C->isAllOnes()) return false; Mask = APInt::getSignMask(C->getBitWidth()); Pred = ICmpInst::ICMP_EQ; break; case ICmpInst::ICMP_SGE: // X >= 0 is equivalent to (X & SignMask) == 0. - if (!C->isNullValue()) + if (!C->isZero()) return false; Mask = APInt::getSignMask(C->getBitWidth()); Pred = ICmpInst::ICMP_EQ; diff --git a/llvm/lib/Analysis/CodeMetrics.cpp b/llvm/lib/Analysis/CodeMetrics.cpp index 8c8e2ee6627f..27c52506352f 100644 --- a/llvm/lib/Analysis/CodeMetrics.cpp +++ b/llvm/lib/Analysis/CodeMetrics.cpp @@ -34,8 +34,9 @@ appendSpeculatableOperands(const Value *V, for (const Value *Operand : U->operands()) if (Visited.insert(Operand).second) - if (isSafeToSpeculativelyExecute(Operand)) - Worklist.push_back(Operand); + if (const auto *I = dyn_cast<Instruction>(Operand)) + if (!I->mayHaveSideEffects() && !I->isTerminator()) + Worklist.push_back(I); } static void completeEphemeralValues(SmallPtrSetImpl<const Value *> &Visited, diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index b28a0d6c78cd..3ed3b8902343 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -63,11 +63,6 @@ using namespace llvm; namespace { -Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, - ArrayRef<Constant *> Ops, - const DataLayout &DL, - const TargetLibraryInfo *TLI, - bool ForLoadOperand); //===----------------------------------------------------------------------===// // Constant Folding internal helper functions @@ -357,9 +352,9 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, const DataLayout &DL) { do { Type *SrcTy = C->getType(); - uint64_t DestSize = DL.getTypeSizeInBits(DestTy); - uint64_t SrcSize = DL.getTypeSizeInBits(SrcTy); - if (SrcSize < DestSize) + TypeSize DestSize = DL.getTypeSizeInBits(DestTy); + TypeSize SrcSize = DL.getTypeSizeInBits(SrcTy); + if (!TypeSize::isKnownGE(SrcSize, DestSize)) return nullptr; // Catch the obvious splat cases (since all-zeros can coerce non-integral @@ -550,19 +545,16 @@ bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, unsigned char *CurPtr, return false; } -Constant *FoldReinterpretLoadFromConstPtr(Constant *C, Type *LoadTy, - const DataLayout &DL) { +Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy, + int64_t Offset, const DataLayout &DL) { // Bail out early. Not expect to load from scalable global variable. if (isa<ScalableVectorType>(LoadTy)) return nullptr; - auto *PTy = cast<PointerType>(C->getType()); auto *IntType = dyn_cast<IntegerType>(LoadTy); // If this isn't an integer load we can't fold it directly. if (!IntType) { - unsigned AS = PTy->getAddressSpace(); - // If this is a float/double load, we can try folding it as an int32/64 load // and then bitcast the result. This can be useful for union cases. Note // that address spaces don't matter here since we're not going to result in @@ -580,8 +572,7 @@ Constant *FoldReinterpretLoadFromConstPtr(Constant *C, Type *LoadTy, } else return nullptr; - C = FoldBitCast(C, MapTy->getPointerTo(AS), DL); - if (Constant *Res = FoldReinterpretLoadFromConstPtr(C, MapTy, DL)) { + if (Constant *Res = FoldReinterpretLoadFromConst(C, MapTy, Offset, DL)) { if (Res->isNullValue() && !LoadTy->isX86_MMXTy() && !LoadTy->isX86_AMXTy()) // Materializing a zero can be done trivially without a bitcast @@ -607,19 +598,7 @@ Constant *FoldReinterpretLoadFromConstPtr(Constant *C, Type *LoadTy, if (BytesLoaded > 32 || BytesLoaded == 0) return nullptr; - GlobalValue *GVal; - APInt OffsetAI; - if (!IsConstantOffsetFromGlobal(C, GVal, OffsetAI, DL)) - return nullptr; - - auto *GV = dyn_cast<GlobalVariable>(GVal); - if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer() || - !GV->getInitializer()->getType()->isSized()) - return nullptr; - - int64_t Offset = OffsetAI.getSExtValue(); - int64_t InitializerSize = - DL.getTypeAllocSize(GV->getInitializer()->getType()).getFixedSize(); + int64_t InitializerSize = DL.getTypeAllocSize(C->getType()).getFixedSize(); // If we're not accessing anything in this constant, the result is undefined. if (Offset <= -1 * static_cast<int64_t>(BytesLoaded)) @@ -640,7 +619,7 @@ Constant *FoldReinterpretLoadFromConstPtr(Constant *C, Type *LoadTy, Offset = 0; } - if (!ReadDataFromGlobal(GV->getInitializer(), Offset, CurPtr, BytesLeft, DL)) + if (!ReadDataFromGlobal(C, Offset, CurPtr, BytesLeft, DL)) return nullptr; APInt ResultVal = APInt(IntType->getBitWidth(), 0); @@ -661,111 +640,70 @@ Constant *FoldReinterpretLoadFromConstPtr(Constant *C, Type *LoadTy, return ConstantInt::get(IntType->getContext(), ResultVal); } -Constant *ConstantFoldLoadThroughBitcastExpr(ConstantExpr *CE, Type *DestTy, - const DataLayout &DL) { - auto *SrcPtr = CE->getOperand(0); - if (!SrcPtr->getType()->isPointerTy()) +/// If this Offset points exactly to the start of an aggregate element, return +/// that element, otherwise return nullptr. +Constant *getConstantAtOffset(Constant *Base, APInt Offset, + const DataLayout &DL) { + if (Offset.isZero()) + return Base; + + if (!isa<ConstantAggregate>(Base) && !isa<ConstantDataSequential>(Base)) + return nullptr; + + Type *ElemTy = Base->getType(); + SmallVector<APInt> Indices = DL.getGEPIndicesForOffset(ElemTy, Offset); + if (!Offset.isZero() || !Indices[0].isZero()) return nullptr; - return ConstantFoldLoadFromConstPtr(SrcPtr, DestTy, DL); + Constant *C = Base; + for (const APInt &Index : drop_begin(Indices)) { + if (Index.isNegative() || Index.getActiveBits() >= 32) + return nullptr; + + C = C->getAggregateElement(Index.getZExtValue()); + if (!C) + return nullptr; + } + + return C; } } // end anonymous namespace -Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, - const DataLayout &DL) { - // First, try the easy cases: - if (auto *GV = dyn_cast<GlobalVariable>(C)) - if (GV->isConstant() && GV->hasDefinitiveInitializer()) - return ConstantFoldLoadThroughBitcast(GV->getInitializer(), Ty, DL); - - if (auto *GA = dyn_cast<GlobalAlias>(C)) - if (GA->getAliasee() && !GA->isInterposable()) - return ConstantFoldLoadFromConstPtr(GA->getAliasee(), Ty, DL); +Constant *llvm::ConstantFoldLoadFromConst(Constant *C, Type *Ty, + const APInt &Offset, + const DataLayout &DL) { + if (Constant *AtOffset = getConstantAtOffset(C, Offset, DL)) + if (Constant *Result = ConstantFoldLoadThroughBitcast(AtOffset, Ty, DL)) + return Result; - // If the loaded value isn't a constant expr, we can't handle it. - auto *CE = dyn_cast<ConstantExpr>(C); - if (!CE) - return nullptr; + // Try hard to fold loads from bitcasted strange and non-type-safe things. + if (Offset.getMinSignedBits() <= 64) + return FoldReinterpretLoadFromConst(C, Ty, Offset.getSExtValue(), DL); - if (CE->getOpcode() == Instruction::GetElementPtr) { - if (auto *GV = dyn_cast<GlobalVariable>(CE->getOperand(0))) { - if (GV->isConstant() && GV->hasDefinitiveInitializer()) { - if (Constant *V = ConstantFoldLoadThroughGEPConstantExpr( - GV->getInitializer(), CE, Ty, DL)) - return V; - } - } else { - // Try to simplify GEP if the pointer operand wasn't a GlobalVariable. - // SymbolicallyEvaluateGEP() with `ForLoadOperand = true` can potentially - // simplify the GEP more than it normally would have been, but should only - // be used for const folding loads. - SmallVector<Constant *> Ops; - for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I) - Ops.push_back(cast<Constant>(CE->getOperand(I))); - if (auto *Simplified = dyn_cast_or_null<ConstantExpr>( - SymbolicallyEvaluateGEP(cast<GEPOperator>(CE), Ops, DL, nullptr, - /*ForLoadOperand*/ true))) { - // If the symbolically evaluated GEP is another GEP, we can only const - // fold it if the resulting pointer operand is a GlobalValue. Otherwise - // there is nothing else to simplify since the GEP is already in the - // most simplified form. - if (isa<GEPOperator>(Simplified)) { - if (auto *GV = dyn_cast<GlobalVariable>(Simplified->getOperand(0))) { - if (GV->isConstant() && GV->hasDefinitiveInitializer()) { - if (Constant *V = ConstantFoldLoadThroughGEPConstantExpr( - GV->getInitializer(), Simplified, Ty, DL)) - return V; - } - } - } else { - return ConstantFoldLoadFromConstPtr(Simplified, Ty, DL); - } - } - } - } + return nullptr; +} - if (CE->getOpcode() == Instruction::BitCast) - if (Constant *LoadedC = ConstantFoldLoadThroughBitcastExpr(CE, Ty, DL)) - return LoadedC; +Constant *llvm::ConstantFoldLoadFromConst(Constant *C, Type *Ty, + const DataLayout &DL) { + return ConstantFoldLoadFromConst(C, Ty, APInt(64, 0), DL); +} - // Instead of loading constant c string, use corresponding integer value - // directly if string length is small enough. - StringRef Str; - if (getConstantStringInfo(CE, Str) && !Str.empty()) { - size_t StrLen = Str.size(); - unsigned NumBits = Ty->getPrimitiveSizeInBits(); - // Replace load with immediate integer if the result is an integer or fp - // value. - if ((NumBits >> 3) == StrLen + 1 && (NumBits & 7) == 0 && - (isa<IntegerType>(Ty) || Ty->isFloatingPointTy())) { - APInt StrVal(NumBits, 0); - APInt SingleChar(NumBits, 0); - if (DL.isLittleEndian()) { - for (unsigned char C : reverse(Str.bytes())) { - SingleChar = static_cast<uint64_t>(C); - StrVal = (StrVal << 8) | SingleChar; - } - } else { - for (unsigned char C : Str.bytes()) { - SingleChar = static_cast<uint64_t>(C); - StrVal = (StrVal << 8) | SingleChar; - } - // Append NULL at the end. - SingleChar = 0; - StrVal = (StrVal << 8) | SingleChar; - } +Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, + APInt Offset, + const DataLayout &DL) { + C = cast<Constant>(C->stripAndAccumulateConstantOffsets( + DL, Offset, /* AllowNonInbounds */ true)); - Constant *Res = ConstantInt::get(CE->getContext(), StrVal); - if (Ty->isFloatingPointTy()) - Res = ConstantExpr::getBitCast(Res, Ty); - return Res; - } - } + if (auto *GV = dyn_cast<GlobalVariable>(C)) + if (GV->isConstant() && GV->hasDefinitiveInitializer()) + if (Constant *Result = ConstantFoldLoadFromConst(GV->getInitializer(), Ty, + Offset, DL)) + return Result; // If this load comes from anywhere in a constant global, and if the global // is all undef or zero, we know what it loads. - if (auto *GV = dyn_cast<GlobalVariable>(getUnderlyingObject(CE))) { + if (auto *GV = dyn_cast<GlobalVariable>(getUnderlyingObject(C))) { if (GV->isConstant() && GV->hasDefinitiveInitializer()) { if (GV->getInitializer()->isNullValue()) return Constant::getNullValue(Ty); @@ -774,8 +712,13 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, } } - // Try hard to fold loads from bitcasted strange and non-type-safe things. - return FoldReinterpretLoadFromConstPtr(CE, Ty, DL); + return nullptr; +} + +Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, + const DataLayout &DL) { + APInt Offset(DL.getIndexTypeSizeInBits(C->getType()), 0); + return ConstantFoldLoadFromConstPtr(C, Ty, Offset, DL); } namespace { @@ -795,11 +738,11 @@ Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, Constant *Op1, if (Opc == Instruction::And) { KnownBits Known0 = computeKnownBits(Op0, DL); KnownBits Known1 = computeKnownBits(Op1, DL); - if ((Known1.One | Known0.Zero).isAllOnesValue()) { + if ((Known1.One | Known0.Zero).isAllOnes()) { // All the bits of Op0 that the 'and' could be masking are already zero. return Op0; } - if ((Known0.One | Known1.Zero).isAllOnesValue()) { + if ((Known0.One | Known1.Zero).isAllOnes()) { // All the bits of Op1 that the 'and' could be masking are already zero. return Op1; } @@ -867,17 +810,10 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops, } /// Strip the pointer casts, but preserve the address space information. -Constant *StripPtrCastKeepAS(Constant *Ptr, bool ForLoadOperand) { +Constant *StripPtrCastKeepAS(Constant *Ptr) { assert(Ptr->getType()->isPointerTy() && "Not a pointer type"); auto *OldPtrTy = cast<PointerType>(Ptr->getType()); Ptr = cast<Constant>(Ptr->stripPointerCasts()); - if (ForLoadOperand) { - while (isa<GlobalAlias>(Ptr) && !cast<GlobalAlias>(Ptr)->isInterposable() && - !cast<GlobalAlias>(Ptr)->getBaseObject()->isInterposable()) { - Ptr = cast<GlobalAlias>(Ptr)->getAliasee(); - } - } - auto *NewPtrTy = cast<PointerType>(Ptr->getType()); // Preserve the address space number of the pointer. @@ -893,8 +829,7 @@ Constant *StripPtrCastKeepAS(Constant *Ptr, bool ForLoadOperand) { Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, ArrayRef<Constant *> Ops, const DataLayout &DL, - const TargetLibraryInfo *TLI, - bool ForLoadOperand) { + const TargetLibraryInfo *TLI) { const GEPOperator *InnermostGEP = GEP; bool InBounds = GEP->isInBounds(); @@ -939,7 +874,7 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, DL.getIndexedOffsetInType( SrcElemTy, makeArrayRef((Value * const *)Ops.data() + 1, Ops.size() - 1))); - Ptr = StripPtrCastKeepAS(Ptr, ForLoadOperand); + Ptr = StripPtrCastKeepAS(Ptr); // If this is a GEP of a GEP, fold it all into a single GEP. while (auto *GEP = dyn_cast<GEPOperator>(Ptr)) { @@ -961,7 +896,7 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, Ptr = cast<Constant>(GEP->getOperand(0)); SrcElemTy = GEP->getSourceElementType(); Offset += APInt(BitWidth, DL.getIndexedOffsetInType(SrcElemTy, NestedOps)); - Ptr = StripPtrCastKeepAS(Ptr, ForLoadOperand); + Ptr = StripPtrCastKeepAS(Ptr); } // If the base value for this address is a literal integer value, fold the @@ -985,72 +920,41 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, // we eliminate over-indexing of the notional static type array bounds. // This makes it easy to determine if the getelementptr is "inbounds". // Also, this helps GlobalOpt do SROA on GlobalVariables. - SmallVector<Constant *, 32> NewIdxs; - Type *Ty = PTy; - SrcElemTy = PTy->getElementType(); - do { - if (!Ty->isStructTy()) { - if (Ty->isPointerTy()) { - // The only pointer indexing we'll do is on the first index of the GEP. - if (!NewIdxs.empty()) - break; + // For GEPs of GlobalValues, use the value type even for opaque pointers. + // Otherwise use an i8 GEP. + if (auto *GV = dyn_cast<GlobalValue>(Ptr)) + SrcElemTy = GV->getValueType(); + else if (!PTy->isOpaque()) + SrcElemTy = PTy->getElementType(); + else + SrcElemTy = Type::getInt8Ty(Ptr->getContext()); - Ty = SrcElemTy; + if (!SrcElemTy->isSized()) + return nullptr; - // Only handle pointers to sized types, not pointers to functions. - if (!Ty->isSized()) - return nullptr; - } else { - Type *NextTy = GetElementPtrInst::getTypeAtIndex(Ty, (uint64_t)0); - if (!NextTy) - break; - Ty = NextTy; - } + Type *ElemTy = SrcElemTy; + SmallVector<APInt> Indices = DL.getGEPIndicesForOffset(ElemTy, Offset); + if (Offset != 0) + return nullptr; - // Determine which element of the array the offset points into. - APInt ElemSize(BitWidth, DL.getTypeAllocSize(Ty)); - if (ElemSize == 0) { - // The element size is 0. This may be [0 x Ty]*, so just use a zero - // index for this level and proceed to the next level to see if it can - // accommodate the offset. - NewIdxs.push_back(ConstantInt::get(IntIdxTy, 0)); - } else { - // The element size is non-zero divide the offset by the element - // size (rounding down), to compute the index at this level. - bool Overflow; - APInt NewIdx = Offset.sdiv_ov(ElemSize, Overflow); - if (Overflow) - break; - Offset -= NewIdx * ElemSize; - NewIdxs.push_back(ConstantInt::get(IntIdxTy, NewIdx)); - } - } else { - auto *STy = cast<StructType>(Ty); - // If we end up with an offset that isn't valid for this struct type, we - // can't re-form this GEP in a regular form, so bail out. The pointer - // operand likely went through casts that are necessary to make the GEP - // sensible. - const StructLayout &SL = *DL.getStructLayout(STy); - if (Offset.isNegative() || Offset.uge(SL.getSizeInBytes())) - break; + // Try to add additional zero indices to reach the desired result element + // type. + // TODO: Should we avoid extra zero indices if ResElemTy can't be reached and + // we'll have to insert a bitcast anyway? + while (ElemTy != ResElemTy) { + Type *NextTy = GetElementPtrInst::getTypeAtIndex(ElemTy, (uint64_t)0); + if (!NextTy) + break; - // Determine which field of the struct the offset points into. The - // getZExtValue is fine as we've already ensured that the offset is - // within the range representable by the StructLayout API. - unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue()); - NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()), - ElIdx)); - Offset -= APInt(BitWidth, SL.getElementOffset(ElIdx)); - Ty = STy->getTypeAtIndex(ElIdx); - } - } while (Ty != ResElemTy); + Indices.push_back(APInt::getZero(isa<StructType>(ElemTy) ? 32 : BitWidth)); + ElemTy = NextTy; + } - // If we haven't used up the entire offset by descending the static - // type, then the offset is pointing into the middle of an indivisible - // member, so we can't simplify it. - if (Offset != 0) - return nullptr; + SmallVector<Constant *, 32> NewIdxs; + for (const APInt &Index : Indices) + NewIdxs.push_back(ConstantInt::get( + Type::getIntNTy(Ptr->getContext(), Index.getBitWidth()), Index)); // Preserve the inrange index from the innermost GEP if possible. We must // have calculated the same indices up to and including the inrange index. @@ -1067,8 +971,9 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, // Create a GEP. Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs, InBounds, InRangeIndex); - assert(C->getType()->getPointerElementType() == Ty && - "Computed GetElementPtr has unexpected type!"); + assert( + cast<PointerType>(C->getType())->isOpaqueOrPointeeTypeMatches(ElemTy) && + "Computed GetElementPtr has unexpected type!"); // If we ended up indexing a member with a type that doesn't match // the type of what the original indices indexed, add a cast. @@ -1099,8 +1004,7 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode, return ConstantFoldCastOperand(Opcode, Ops[0], DestTy, DL); if (auto *GEP = dyn_cast<GEPOperator>(InstOrCE)) { - if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI, - /*ForLoadOperand*/ false)) + if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI)) return C; return ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), Ops[0], @@ -1375,21 +1279,31 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C, default: llvm_unreachable("Missing case"); case Instruction::PtrToInt: - // If the input is a inttoptr, eliminate the pair. This requires knowing - // the width of a pointer, so it can't be done in ConstantExpr::getCast. if (auto *CE = dyn_cast<ConstantExpr>(C)) { + Constant *FoldedValue = nullptr; + // If the input is a inttoptr, eliminate the pair. This requires knowing + // the width of a pointer, so it can't be done in ConstantExpr::getCast. if (CE->getOpcode() == Instruction::IntToPtr) { - Constant *Input = CE->getOperand(0); - unsigned InWidth = Input->getType()->getScalarSizeInBits(); - unsigned PtrWidth = DL.getPointerTypeSizeInBits(CE->getType()); - if (PtrWidth < InWidth) { - Constant *Mask = - ConstantInt::get(CE->getContext(), - APInt::getLowBitsSet(InWidth, PtrWidth)); - Input = ConstantExpr::getAnd(Input, Mask); + // zext/trunc the inttoptr to pointer size. + FoldedValue = ConstantExpr::getIntegerCast( + CE->getOperand(0), DL.getIntPtrType(CE->getType()), + /*IsSigned=*/false); + } else if (auto *GEP = dyn_cast<GEPOperator>(CE)) { + // If we have GEP, we can perform the following folds: + // (ptrtoint (gep null, x)) -> x + // (ptrtoint (gep (gep null, x), y) -> x + y, etc. + unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType()); + APInt BaseOffset(BitWidth, 0); + auto *Base = cast<Constant>(GEP->stripAndAccumulateConstantOffsets( + DL, BaseOffset, /*AllowNonInbounds=*/true)); + if (Base->isNullValue()) { + FoldedValue = ConstantInt::get(CE->getContext(), BaseOffset); } - // Do a zext or trunc to get to the dest size. - return ConstantExpr::getIntegerCast(Input, DestTy, false); + } + if (FoldedValue) { + // Do a zext or trunc to get to the ptrtoint dest size. + return ConstantExpr::getIntegerCast(FoldedValue, DestTy, + /*IsSigned=*/false); } } return ConstantExpr::getCast(Opcode, C, DestTy); @@ -1446,19 +1360,6 @@ Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C, return ConstantFoldLoadThroughBitcast(C, Ty, DL); } -Constant * -llvm::ConstantFoldLoadThroughGEPIndices(Constant *C, - ArrayRef<Constant *> Indices) { - // Loop over all of the operands, tracking down which value we are - // addressing. - for (Constant *Index : Indices) { - C = C->getAggregateElement(Index); - if (!C) - return nullptr; - } - return C; -} - //===----------------------------------------------------------------------===// // Constant Folding for Calls // @@ -1879,7 +1780,7 @@ static bool mayFoldConstrained(ConstrainedFPIntrinsic *CI, // know that its evaluation does not raise exceptions, so side effect // is absent. To allow removing the call, mark it as not accessing memory. if (EB && *EB != fp::ExceptionBehavior::ebIgnore) - CI->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); + CI->addFnAttr(Attribute::ReadNone); return true; } @@ -2112,7 +2013,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, /// the host native double versions. Float versions are not called /// directly but for all these it is true (float)(f((double)arg)) == /// f(arg). Long double not supported yet. - APFloat APF = Op->getValueAPF(); + const APFloat &APF = Op->getValueAPF(); switch (IntrinsicID) { default: break; @@ -2163,7 +2064,9 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, return nullptr; LibFunc Func = NotLibFunc; - TLI->getLibFunc(Name, Func); + if (!TLI->getLibFunc(Name, Func)) + return nullptr; + switch (Func) { default: break; @@ -2416,12 +2319,12 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, if (const auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) { if (!Ty->isFloatingPointTy()) return nullptr; - APFloat Op1V = Op1->getValueAPF(); + const APFloat &Op1V = Op1->getValueAPF(); if (const auto *Op2 = dyn_cast<ConstantFP>(Operands[1])) { if (Op2->getType() != Op1->getType()) return nullptr; - APFloat Op2V = Op2->getValueAPF(); + const APFloat &Op2V = Op2->getValueAPF(); if (const auto *ConstrIntr = dyn_cast<ConstrainedFPIntrinsic>(Call)) { RoundingMode RM = getEvaluationRoundingMode(ConstrIntr); @@ -2487,7 +2390,9 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, return nullptr; LibFunc Func = NotLibFunc; - TLI->getLibFunc(Name, Func); + if (!TLI->getLibFunc(Name, Func)) + return nullptr; + switch (Func) { default: break; @@ -2671,7 +2576,7 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, assert(C1 && "Must be constant int"); // cttz(0, 1) and ctlz(0, 1) are undef. - if (C1->isOneValue() && (!C0 || C0->isNullValue())) + if (C1->isOne() && (!C0 || C0->isZero())) return UndefValue::get(Ty); if (!C0) return Constant::getNullValue(Ty); @@ -2683,11 +2588,11 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, case Intrinsic::abs: // Undef or minimum val operand with poison min --> undef assert(C1 && "Must be constant int"); - if (C1->isOneValue() && (!C0 || C0->isMinSignedValue())) + if (C1->isOne() && (!C0 || C0->isMinSignedValue())) return UndefValue::get(Ty); // Undef operand with no poison min --> 0 (sign bit must be clear) - if (C1->isNullValue() && !C0) + if (C1->isZero() && !C0) return Constant::getNullValue(Ty); return ConstantInt::get(Ty, C0->abs()); @@ -3191,7 +3096,7 @@ bool llvm::isMathLibCallNoop(const CallBase *Call, if (!TLI || !TLI->getLibFunc(*F, Func)) return false; - if (Call->getNumArgOperands() == 1) { + if (Call->arg_size() == 1) { if (ConstantFP *OpC = dyn_cast<ConstantFP>(Call->getArgOperand(0))) { const APFloat &Op = OpC->getValueAPF(); switch (Func) { @@ -3280,7 +3185,7 @@ bool llvm::isMathLibCallNoop(const CallBase *Call, } } - if (Call->getNumArgOperands() == 2) { + if (Call->arg_size() == 2) { ConstantFP *Op0C = dyn_cast<ConstantFP>(Call->getArgOperand(0)); ConstantFP *Op1C = dyn_cast<ConstantFP>(Call->getArgOperand(1)); if (Op0C && Op1C) { diff --git a/llvm/lib/Analysis/CostModel.cpp b/llvm/lib/Analysis/CostModel.cpp index 83b7d5cbfc3e..f407ec0d017a 100644 --- a/llvm/lib/Analysis/CostModel.cpp +++ b/llvm/lib/Analysis/CostModel.cpp @@ -16,10 +16,12 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Analysis/CostModel.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" @@ -113,3 +115,23 @@ void CostModelAnalysis::print(raw_ostream &OS, const Module*) const { } } } + +PreservedAnalyses CostModelPrinterPass::run(Function &F, + FunctionAnalysisManager &AM) { + auto &TTI = AM.getResult<TargetIRAnalysis>(F); + OS << "Cost Model for function '" << F.getName() << "'\n"; + for (BasicBlock &B : F) { + for (Instruction &Inst : B) { + // TODO: Use a pass parameter instead of cl::opt CostKind to determine + // which cost kind to print. + InstructionCost Cost = TTI.getInstructionCost(&Inst, CostKind); + if (auto CostVal = Cost.getValue()) + OS << "Cost Model: Found an estimated cost of " << *CostVal; + else + OS << "Cost Model: Invalid cost"; + + OS << " for instruction: " << Inst << "\n"; + } + } + return PreservedAnalyses::all(); +} diff --git a/llvm/lib/Analysis/Delinearization.cpp b/llvm/lib/Analysis/Delinearization.cpp index 448e970e9bcc..670532c6d9a8 100644 --- a/llvm/lib/Analysis/Delinearization.cpp +++ b/llvm/lib/Analysis/Delinearization.cpp @@ -17,6 +17,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionDivision.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -36,6 +37,492 @@ using namespace llvm; #define DL_NAME "delinearize" #define DEBUG_TYPE DL_NAME +// Return true when S contains at least an undef value. +static inline bool containsUndefs(const SCEV *S) { + return SCEVExprContains(S, [](const SCEV *S) { + if (const auto *SU = dyn_cast<SCEVUnknown>(S)) + return isa<UndefValue>(SU->getValue()); + return false; + }); +} + +namespace { + +// Collect all steps of SCEV expressions. +struct SCEVCollectStrides { + ScalarEvolution &SE; + SmallVectorImpl<const SCEV *> &Strides; + + SCEVCollectStrides(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &S) + : SE(SE), Strides(S) {} + + bool follow(const SCEV *S) { + if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) + Strides.push_back(AR->getStepRecurrence(SE)); + return true; + } + + bool isDone() const { return false; } +}; + +// Collect all SCEVUnknown and SCEVMulExpr expressions. +struct SCEVCollectTerms { + SmallVectorImpl<const SCEV *> &Terms; + + SCEVCollectTerms(SmallVectorImpl<const SCEV *> &T) : Terms(T) {} + + bool follow(const SCEV *S) { + if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S) || + isa<SCEVSignExtendExpr>(S)) { + if (!containsUndefs(S)) + Terms.push_back(S); + + // Stop recursion: once we collected a term, do not walk its operands. + return false; + } + + // Keep looking. + return true; + } + + bool isDone() const { return false; } +}; + +// Check if a SCEV contains an AddRecExpr. +struct SCEVHasAddRec { + bool &ContainsAddRec; + + SCEVHasAddRec(bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) { + ContainsAddRec = false; + } + + bool follow(const SCEV *S) { + if (isa<SCEVAddRecExpr>(S)) { + ContainsAddRec = true; + + // Stop recursion: once we collected a term, do not walk its operands. + return false; + } + + // Keep looking. + return true; + } + + bool isDone() const { return false; } +}; + +// Find factors that are multiplied with an expression that (possibly as a +// subexpression) contains an AddRecExpr. In the expression: +// +// 8 * (100 + %p * %q * (%a + {0, +, 1}_loop)) +// +// "%p * %q" are factors multiplied by the expression "(%a + {0, +, 1}_loop)" +// that contains the AddRec {0, +, 1}_loop. %p * %q are likely to be array size +// parameters as they form a product with an induction variable. +// +// This collector expects all array size parameters to be in the same MulExpr. +// It might be necessary to later add support for collecting parameters that are +// spread over different nested MulExpr. +struct SCEVCollectAddRecMultiplies { + SmallVectorImpl<const SCEV *> &Terms; + ScalarEvolution &SE; + + SCEVCollectAddRecMultiplies(SmallVectorImpl<const SCEV *> &T, + ScalarEvolution &SE) + : Terms(T), SE(SE) {} + + bool follow(const SCEV *S) { + if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) { + bool HasAddRec = false; + SmallVector<const SCEV *, 0> Operands; + for (auto Op : Mul->operands()) { + const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op); + if (Unknown && !isa<CallInst>(Unknown->getValue())) { + Operands.push_back(Op); + } else if (Unknown) { + HasAddRec = true; + } else { + bool ContainsAddRec = false; + SCEVHasAddRec ContiansAddRec(ContainsAddRec); + visitAll(Op, ContiansAddRec); + HasAddRec |= ContainsAddRec; + } + } + if (Operands.size() == 0) + return true; + + if (!HasAddRec) + return false; + + Terms.push_back(SE.getMulExpr(Operands)); + // Stop recursion: once we collected a term, do not walk its operands. + return false; + } + + // Keep looking. + return true; + } + + bool isDone() const { return false; } +}; + +} // end anonymous namespace + +/// Find parametric terms in this SCEVAddRecExpr. We first for parameters in +/// two places: +/// 1) The strides of AddRec expressions. +/// 2) Unknowns that are multiplied with AddRec expressions. +void llvm::collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, + SmallVectorImpl<const SCEV *> &Terms) { + SmallVector<const SCEV *, 4> Strides; + SCEVCollectStrides StrideCollector(SE, Strides); + visitAll(Expr, StrideCollector); + + LLVM_DEBUG({ + dbgs() << "Strides:\n"; + for (const SCEV *S : Strides) + dbgs() << *S << "\n"; + }); + + for (const SCEV *S : Strides) { + SCEVCollectTerms TermCollector(Terms); + visitAll(S, TermCollector); + } + + LLVM_DEBUG({ + dbgs() << "Terms:\n"; + for (const SCEV *T : Terms) + dbgs() << *T << "\n"; + }); + + SCEVCollectAddRecMultiplies MulCollector(Terms, SE); + visitAll(Expr, MulCollector); +} + +static bool findArrayDimensionsRec(ScalarEvolution &SE, + SmallVectorImpl<const SCEV *> &Terms, + SmallVectorImpl<const SCEV *> &Sizes) { + int Last = Terms.size() - 1; + const SCEV *Step = Terms[Last]; + + // End of recursion. + if (Last == 0) { + if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) { + SmallVector<const SCEV *, 2> Qs; + for (const SCEV *Op : M->operands()) + if (!isa<SCEVConstant>(Op)) + Qs.push_back(Op); + + Step = SE.getMulExpr(Qs); + } + + Sizes.push_back(Step); + return true; + } + + for (const SCEV *&Term : Terms) { + // Normalize the terms before the next call to findArrayDimensionsRec. + const SCEV *Q, *R; + SCEVDivision::divide(SE, Term, Step, &Q, &R); + + // Bail out when GCD does not evenly divide one of the terms. + if (!R->isZero()) + return false; + + Term = Q; + } + + // Remove all SCEVConstants. + erase_if(Terms, [](const SCEV *E) { return isa<SCEVConstant>(E); }); + + if (Terms.size() > 0) + if (!findArrayDimensionsRec(SE, Terms, Sizes)) + return false; + + Sizes.push_back(Step); + return true; +} + +// Returns true when one of the SCEVs of Terms contains a SCEVUnknown parameter. +static inline bool containsParameters(SmallVectorImpl<const SCEV *> &Terms) { + for (const SCEV *T : Terms) + if (SCEVExprContains(T, [](const SCEV *S) { return isa<SCEVUnknown>(S); })) + return true; + + return false; +} + +// Return the number of product terms in S. +static inline int numberOfTerms(const SCEV *S) { + if (const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S)) + return Expr->getNumOperands(); + return 1; +} + +static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) { + if (isa<SCEVConstant>(T)) + return nullptr; + + if (isa<SCEVUnknown>(T)) + return T; + + if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) { + SmallVector<const SCEV *, 2> Factors; + for (const SCEV *Op : M->operands()) + if (!isa<SCEVConstant>(Op)) + Factors.push_back(Op); + + return SE.getMulExpr(Factors); + } + + return T; +} + +void llvm::findArrayDimensions(ScalarEvolution &SE, + SmallVectorImpl<const SCEV *> &Terms, + SmallVectorImpl<const SCEV *> &Sizes, + const SCEV *ElementSize) { + if (Terms.size() < 1 || !ElementSize) + return; + + // Early return when Terms do not contain parameters: we do not delinearize + // non parametric SCEVs. + if (!containsParameters(Terms)) + return; + + LLVM_DEBUG({ + dbgs() << "Terms:\n"; + for (const SCEV *T : Terms) + dbgs() << *T << "\n"; + }); + + // Remove duplicates. + array_pod_sort(Terms.begin(), Terms.end()); + Terms.erase(std::unique(Terms.begin(), Terms.end()), Terms.end()); + + // Put larger terms first. + llvm::sort(Terms, [](const SCEV *LHS, const SCEV *RHS) { + return numberOfTerms(LHS) > numberOfTerms(RHS); + }); + + // Try to divide all terms by the element size. If term is not divisible by + // element size, proceed with the original term. + for (const SCEV *&Term : Terms) { + const SCEV *Q, *R; + SCEVDivision::divide(SE, Term, ElementSize, &Q, &R); + if (!Q->isZero()) + Term = Q; + } + + SmallVector<const SCEV *, 4> NewTerms; + + // Remove constant factors. + for (const SCEV *T : Terms) + if (const SCEV *NewT = removeConstantFactors(SE, T)) + NewTerms.push_back(NewT); + + LLVM_DEBUG({ + dbgs() << "Terms after sorting:\n"; + for (const SCEV *T : NewTerms) + dbgs() << *T << "\n"; + }); + + if (NewTerms.empty() || !findArrayDimensionsRec(SE, NewTerms, Sizes)) { + Sizes.clear(); + return; + } + + // The last element to be pushed into Sizes is the size of an element. + Sizes.push_back(ElementSize); + + LLVM_DEBUG({ + dbgs() << "Sizes:\n"; + for (const SCEV *S : Sizes) + dbgs() << *S << "\n"; + }); +} + +void llvm::computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, + SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<const SCEV *> &Sizes) { + // Early exit in case this SCEV is not an affine multivariate function. + if (Sizes.empty()) + return; + + if (auto *AR = dyn_cast<SCEVAddRecExpr>(Expr)) + if (!AR->isAffine()) + return; + + const SCEV *Res = Expr; + int Last = Sizes.size() - 1; + for (int i = Last; i >= 0; i--) { + const SCEV *Q, *R; + SCEVDivision::divide(SE, Res, Sizes[i], &Q, &R); + + LLVM_DEBUG({ + dbgs() << "Res: " << *Res << "\n"; + dbgs() << "Sizes[i]: " << *Sizes[i] << "\n"; + dbgs() << "Res divided by Sizes[i]:\n"; + dbgs() << "Quotient: " << *Q << "\n"; + dbgs() << "Remainder: " << *R << "\n"; + }); + + Res = Q; + + // Do not record the last subscript corresponding to the size of elements in + // the array. + if (i == Last) { + + // Bail out if the byte offset is non-zero. + if (!R->isZero()) { + Subscripts.clear(); + Sizes.clear(); + return; + } + + continue; + } + + // Record the access function for the current subscript. + Subscripts.push_back(R); + } + + // Also push in last position the remainder of the last division: it will be + // the access function of the innermost dimension. + Subscripts.push_back(Res); + + std::reverse(Subscripts.begin(), Subscripts.end()); + + LLVM_DEBUG({ + dbgs() << "Subscripts:\n"; + for (const SCEV *S : Subscripts) + dbgs() << *S << "\n"; + }); +} + +/// Splits the SCEV into two vectors of SCEVs representing the subscripts and +/// sizes of an array access. Returns the remainder of the delinearization that +/// is the offset start of the array. The SCEV->delinearize algorithm computes +/// the multiples of SCEV coefficients: that is a pattern matching of sub +/// expressions in the stride and base of a SCEV corresponding to the +/// computation of a GCD (greatest common divisor) of base and stride. When +/// SCEV->delinearize fails, it returns the SCEV unchanged. +/// +/// For example: when analyzing the memory access A[i][j][k] in this loop nest +/// +/// void foo(long n, long m, long o, double A[n][m][o]) { +/// +/// for (long i = 0; i < n; i++) +/// for (long j = 0; j < m; j++) +/// for (long k = 0; k < o; k++) +/// A[i][j][k] = 1.0; +/// } +/// +/// the delinearization input is the following AddRec SCEV: +/// +/// AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k> +/// +/// From this SCEV, we are able to say that the base offset of the access is %A +/// because it appears as an offset that does not divide any of the strides in +/// the loops: +/// +/// CHECK: Base offset: %A +/// +/// and then SCEV->delinearize determines the size of some of the dimensions of +/// the array as these are the multiples by which the strides are happening: +/// +/// CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double) +/// bytes. +/// +/// Note that the outermost dimension remains of UnknownSize because there are +/// no strides that would help identifying the size of the last dimension: when +/// the array has been statically allocated, one could compute the size of that +/// dimension by dividing the overall size of the array by the size of the known +/// dimensions: %m * %o * 8. +/// +/// Finally delinearize provides the access functions for the array reference +/// that does correspond to A[i][j][k] of the above C testcase: +/// +/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>] +/// +/// The testcases are checking the output of a function pass: +/// DelinearizationPass that walks through all loads and stores of a function +/// asking for the SCEV of the memory access with respect to all enclosing +/// loops, calling SCEV->delinearize on that and printing the results. +void llvm::delinearize(ScalarEvolution &SE, const SCEV *Expr, + SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<const SCEV *> &Sizes, + const SCEV *ElementSize) { + // First step: collect parametric terms. + SmallVector<const SCEV *, 4> Terms; + collectParametricTerms(SE, Expr, Terms); + + if (Terms.empty()) + return; + + // Second step: find subscript sizes. + findArrayDimensions(SE, Terms, Sizes, ElementSize); + + if (Sizes.empty()) + return; + + // Third step: compute the access functions for each subscript. + computeAccessFunctions(SE, Expr, Subscripts, Sizes); + + if (Subscripts.empty()) + return; + + LLVM_DEBUG({ + dbgs() << "succeeded to delinearize " << *Expr << "\n"; + dbgs() << "ArrayDecl[UnknownSize]"; + for (const SCEV *S : Sizes) + dbgs() << "[" << *S << "]"; + + dbgs() << "\nArrayRef"; + for (const SCEV *S : Subscripts) + dbgs() << "[" << *S << "]"; + dbgs() << "\n"; + }); +} + +bool llvm::getIndexExpressionsFromGEP(ScalarEvolution &SE, + const GetElementPtrInst *GEP, + SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<int> &Sizes) { + assert(Subscripts.empty() && Sizes.empty() && + "Expected output lists to be empty on entry to this function."); + assert(GEP && "getIndexExpressionsFromGEP called with a null GEP"); + Type *Ty = nullptr; + bool DroppedFirstDim = false; + for (unsigned i = 1; i < GEP->getNumOperands(); i++) { + const SCEV *Expr = SE.getSCEV(GEP->getOperand(i)); + if (i == 1) { + Ty = GEP->getSourceElementType(); + if (auto *Const = dyn_cast<SCEVConstant>(Expr)) + if (Const->getValue()->isZero()) { + DroppedFirstDim = true; + continue; + } + Subscripts.push_back(Expr); + continue; + } + + auto *ArrayTy = dyn_cast<ArrayType>(Ty); + if (!ArrayTy) { + Subscripts.clear(); + Sizes.clear(); + return false; + } + + Subscripts.push_back(Expr); + if (!(DroppedFirstDim && i == 2)) + Sizes.push_back(ArrayTy->getNumElements()); + + Ty = ArrayTy->getElementType(); + } + return !Subscripts.empty(); +} + namespace { class Delinearization : public FunctionPass { @@ -84,7 +571,7 @@ void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI, O << "AccessFunction: " << *AccessFn << "\n"; SmallVector<const SCEV *, 3> Subscripts, Sizes; - SE->delinearize(AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst)); + delinearize(*SE, AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst)); if (Subscripts.size() == 0 || Sizes.size() == 0 || Subscripts.size() != Sizes.size()) { O << "failed to delinearize\n"; diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp index ca6d58fac825..117b12fc0701 100644 --- a/llvm/lib/Analysis/DemandedBits.cpp +++ b/llvm/lib/Analysis/DemandedBits.cpp @@ -362,7 +362,7 @@ void DemandedBits::performAnalysis() { if (Instruction *J = dyn_cast<Instruction>(OI)) { Type *T = J->getType(); if (T->isIntOrIntVectorTy()) - AliveBits[J] = APInt::getAllOnesValue(T->getScalarSizeInBits()); + AliveBits[J] = APInt::getAllOnes(T->getScalarSizeInBits()); else Visited.insert(J); Worklist.insert(J); @@ -407,7 +407,7 @@ void DemandedBits::performAnalysis() { Type *T = OI->getType(); if (T->isIntOrIntVectorTy()) { unsigned BitWidth = T->getScalarSizeInBits(); - APInt AB = APInt::getAllOnesValue(BitWidth); + APInt AB = APInt::getAllOnes(BitWidth); if (InputIsKnownDead) { AB = APInt(BitWidth, 0); } else { @@ -417,7 +417,7 @@ void DemandedBits::performAnalysis() { Known, Known2, KnownBitsComputed); // Keep track of uses which have no demanded bits. - if (AB.isNullValue()) + if (AB.isZero()) DeadUses.insert(&OI); else DeadUses.erase(&OI); @@ -448,8 +448,7 @@ APInt DemandedBits::getDemandedBits(Instruction *I) { return Found->second; const DataLayout &DL = I->getModule()->getDataLayout(); - return APInt::getAllOnesValue( - DL.getTypeSizeInBits(I->getType()->getScalarType())); + return APInt::getAllOnes(DL.getTypeSizeInBits(I->getType()->getScalarType())); } APInt DemandedBits::getDemandedBits(Use *U) { @@ -461,7 +460,7 @@ APInt DemandedBits::getDemandedBits(Use *U) { // We only track integer uses, everything else produces a mask with all bits // set if (!T->isIntOrIntVectorTy()) - return APInt::getAllOnesValue(BitWidth); + return APInt::getAllOnes(BitWidth); if (isUseDead(U)) return APInt(BitWidth, 0); @@ -469,7 +468,7 @@ APInt DemandedBits::getDemandedBits(Use *U) { performAnalysis(); APInt AOut = getDemandedBits(UserI); - APInt AB = APInt::getAllOnesValue(BitWidth); + APInt AB = APInt::getAllOnes(BitWidth); KnownBits Known, Known2; bool KnownBitsComputed = false; @@ -504,7 +503,7 @@ bool DemandedBits::isUseDead(Use *U) { // is dead. These uses might not be explicitly present in the DeadUses map. if (UserI->getType()->isIntOrIntVectorTy()) { auto Found = AliveBits.find(UserI); - if (Found != AliveBits.end() && Found->second.isNullValue()) + if (Found != AliveBits.end() && Found->second.isZero()) return true; } diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index 9564cfb2aa45..f827f74d5367 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -53,6 +53,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Delinearization.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" @@ -119,6 +120,11 @@ static cl::opt<bool> DisableDelinearizationChecks( "dependence vectors for languages that allow the subscript of one " "dimension to underflow or overflow into another dimension.")); +static cl::opt<unsigned> MIVMaxLevelThreshold( + "da-miv-max-level-threshold", cl::init(7), cl::Hidden, cl::ZeroOrMore, + cl::desc("Maximum depth allowed for the recursive algorithm used to " + "explore MIV direction vectors.")); + //===----------------------------------------------------------------------===// // basics @@ -2319,7 +2325,7 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst, LLVM_DEBUG(dbgs() << "starting gcd\n"); ++GCDapplications; unsigned BitWidth = SE->getTypeSizeInBits(Src->getType()); - APInt RunningGCD = APInt::getNullValue(BitWidth); + APInt RunningGCD = APInt::getZero(BitWidth); // Examine Src coefficients. // Compute running GCD and record source constant. @@ -2359,7 +2365,7 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst, } const SCEV *DstConst = Coefficients; - APInt ExtraGCD = APInt::getNullValue(BitWidth); + APInt ExtraGCD = APInt::getZero(BitWidth); const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst); LLVM_DEBUG(dbgs() << " Delta = " << *Delta << "\n"); const SCEVConstant *Constant = dyn_cast<SCEVConstant>(Delta); @@ -2602,6 +2608,19 @@ unsigned DependenceInfo::exploreDirections(unsigned Level, CoefficientInfo *A, const SmallBitVector &Loops, unsigned &DepthExpanded, const SCEV *Delta) const { + // This algorithm has worst case complexity of O(3^n), where 'n' is the number + // of common loop levels. To avoid excessive compile-time, pessimize all the + // results and immediately return when the number of common levels is beyond + // the given threshold. + if (CommonLevels > MIVMaxLevelThreshold) { + LLVM_DEBUG(dbgs() << "Number of common levels exceeded the threshold. MIV " + "direction exploration is terminated.\n"); + for (unsigned K = 1; K <= CommonLevels; ++K) + if (Loops[K]) + Bound[K].DirSet = Dependence::DVEntry::ALL; + return 1; + } + if (Level > CommonLevels) { // record result LLVM_DEBUG(dbgs() << "\t["); @@ -3320,8 +3339,8 @@ bool DependenceInfo::tryDelinearizeFixedSize( return false; SmallVector<int, 4> SrcSizes, DstSizes; - SE->getIndexExpressionsFromGEP(SrcGEP, SrcSubscripts, SrcSizes); - SE->getIndexExpressionsFromGEP(DstGEP, DstSubscripts, DstSizes); + getIndexExpressionsFromGEP(*SE, SrcGEP, SrcSubscripts, SrcSizes); + getIndexExpressionsFromGEP(*SE, DstGEP, DstSubscripts, DstSizes); // Check that the two size arrays are non-empty and equal in length and // value. @@ -3421,16 +3440,16 @@ bool DependenceInfo::tryDelinearizeParametricSize( // First step: collect parametric terms in both array references. SmallVector<const SCEV *, 4> Terms; - SE->collectParametricTerms(SrcAR, Terms); - SE->collectParametricTerms(DstAR, Terms); + collectParametricTerms(*SE, SrcAR, Terms); + collectParametricTerms(*SE, DstAR, Terms); // Second step: find subscript sizes. SmallVector<const SCEV *, 4> Sizes; - SE->findArrayDimensions(Terms, Sizes, ElementSize); + findArrayDimensions(*SE, Terms, Sizes, ElementSize); // Third step: compute the access functions for each subscript. - SE->computeAccessFunctions(SrcAR, SrcSubscripts, Sizes); - SE->computeAccessFunctions(DstAR, DstSubscripts, Sizes); + computeAccessFunctions(*SE, SrcAR, SrcSubscripts, Sizes); + computeAccessFunctions(*SE, DstAR, DstSubscripts, Sizes); // Fail when there is only a subscript: that's a linearized access function. if (SrcSubscripts.size() < 2 || DstSubscripts.size() < 2 || diff --git a/llvm/lib/Analysis/DevelopmentModeInlineAdvisor.cpp b/llvm/lib/Analysis/DevelopmentModeInlineAdvisor.cpp index ecfefa36918c..d87fa849d839 100644 --- a/llvm/lib/Analysis/DevelopmentModeInlineAdvisor.cpp +++ b/llvm/lib/Analysis/DevelopmentModeInlineAdvisor.cpp @@ -1,9 +1,8 @@ //===- DevelopmentModeInlineAdvisor.cpp - runtime-loadable model runner --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -228,6 +227,8 @@ private: (*CallerSizeEstimateBefore + *CalleeSizeEstimateBefore); getAdvisor()->updateNativeSizeEstimate(Reward); log(Reward, /*Success=*/true); + } else { + log(NoReward, /*Success=*/true); } } @@ -377,7 +378,7 @@ void TrainingLogger::logInlineEvent(const InlineEvent &Event, void TrainingLogger::print() { std::error_code EC; raw_fd_ostream OutFile(LogFileName, EC); - L->print(OutFile); + L->flush(OutFile); } DevelopmentModeMLInlineAdvisor::DevelopmentModeMLInlineAdvisor( diff --git a/llvm/lib/Analysis/HeatUtils.cpp b/llvm/lib/Analysis/HeatUtils.cpp index a1a11be5fee3..0057de322cac 100644 --- a/llvm/lib/Analysis/HeatUtils.cpp +++ b/llvm/lib/Analysis/HeatUtils.cpp @@ -1,9 +1,8 @@ //===-- HeatUtils.cpp - Utility for printing heat colors --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp b/llvm/lib/Analysis/IRSimilarityIdentifier.cpp index a6298afb66f5..f22c6aa04f5e 100644 --- a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp +++ b/llvm/lib/Analysis/IRSimilarityIdentifier.cpp @@ -23,13 +23,23 @@ using namespace llvm; using namespace IRSimilarity; +cl::opt<bool> + DisableBranches("no-ir-sim-branch-matching", cl::init(false), + cl::ReallyHidden, + cl::desc("disable similarity matching, and outlining, " + "across branches for debugging purposes.")); + IRInstructionData::IRInstructionData(Instruction &I, bool Legality, IRInstructionDataList &IDList) : Inst(&I), Legal(Legality), IDL(&IDList) { + initializeInstruction(); +} + +void IRInstructionData::initializeInstruction() { // We check for whether we have a comparison instruction. If it is, we // find the "less than" version of the predicate for consistency for // comparison instructions throught the program. - if (CmpInst *C = dyn_cast<CmpInst>(&I)) { + if (CmpInst *C = dyn_cast<CmpInst>(Inst)) { CmpInst::Predicate Predicate = predicateForConsistency(C); if (Predicate != C->getPredicate()) RevisedPredicate = Predicate; @@ -37,8 +47,8 @@ IRInstructionData::IRInstructionData(Instruction &I, bool Legality, // Here we collect the operands and their types for determining whether // the structure of the operand use matches between two different candidates. - for (Use &OI : I.operands()) { - if (isa<CmpInst>(I) && RevisedPredicate.hasValue()) { + for (Use &OI : Inst->operands()) { + if (isa<CmpInst>(Inst) && RevisedPredicate.hasValue()) { // If we have a CmpInst where the predicate is reversed, it means the // operands must be reversed as well. OperVals.insert(OperVals.begin(), OI.get()); @@ -49,6 +59,33 @@ IRInstructionData::IRInstructionData(Instruction &I, bool Legality, } } +IRInstructionData::IRInstructionData(IRInstructionDataList &IDList) + : Inst(nullptr), Legal(false), IDL(&IDList) {} + +void IRInstructionData::setBranchSuccessors( + DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger) { + assert(isa<BranchInst>(Inst) && "Instruction must be branch"); + + BranchInst *BI = cast<BranchInst>(Inst); + DenseMap<BasicBlock *, unsigned>::iterator BBNumIt; + + BBNumIt = BasicBlockToInteger.find(BI->getParent()); + assert(BBNumIt != BasicBlockToInteger.end() && + "Could not find location for BasicBlock!"); + + int CurrentBlockNumber = static_cast<int>(BBNumIt->second); + + for (BasicBlock *Successor : BI->successors()) { + BBNumIt = BasicBlockToInteger.find(Successor); + assert(BBNumIt != BasicBlockToInteger.end() && + "Could not find number for BasicBlock!"); + int OtherBlockNumber = static_cast<int>(BBNumIt->second); + + int Relative = OtherBlockNumber - CurrentBlockNumber; + RelativeBlockLocations.push_back(Relative); + } +} + CmpInst::Predicate IRInstructionData::predicateForConsistency(CmpInst *CI) { switch (CI->getPredicate()) { case CmpInst::FCMP_OGT: @@ -143,6 +180,10 @@ bool IRSimilarity::isClose(const IRInstructionData &A, return false; } + if (isa<BranchInst>(A.Inst) && isa<BranchInst>(B.Inst) && + A.RelativeBlockLocations.size() != B.RelativeBlockLocations.size()) + return false; + return true; } @@ -156,10 +197,6 @@ void IRInstructionMapper::convertToUnsignedVec( std::vector<unsigned> IntegerMappingForBB; std::vector<IRInstructionData *> InstrListForBB; - HaveLegalRange = false; - CanCombineWithPrevInstr = false; - AddedIllegalLastTime = true; - for (BasicBlock::iterator Et = BB.end(); It != Et; ++It) { switch (InstClassifier.visit(*It)) { case InstrType::Legal: @@ -175,7 +212,8 @@ void IRInstructionMapper::convertToUnsignedVec( } if (HaveLegalRange) { - mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB, true); + if (AddedIllegalLastTime) + mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB, true); for (IRInstructionData *ID : InstrListForBB) this->IDL->push_back(*ID); llvm::append_range(InstrList, InstrListForBB); @@ -203,6 +241,9 @@ unsigned IRInstructionMapper::mapToLegalUnsigned( IRInstructionData *ID = allocateIRInstructionData(*It, true, *IDL); InstrListForBB.push_back(ID); + if (isa<BranchInst>(*It)) + ID->setBranchSuccessors(BasicBlockToInteger); + // Add to the instruction list bool WasInserted; DenseMap<IRInstructionData *, unsigned, IRInstructionDataTraits>::iterator @@ -235,6 +276,11 @@ IRInstructionMapper::allocateIRInstructionData(Instruction &I, bool Legality, return new (InstDataAllocator->Allocate()) IRInstructionData(I, Legality, IDL); } +IRInstructionData * +IRInstructionMapper::allocateIRInstructionData(IRInstructionDataList &IDL) { + return new (InstDataAllocator->Allocate()) IRInstructionData(IDL); +} + IRInstructionDataList * IRInstructionMapper::allocateIRInstructionDataList() { return new (IDLAllocator->Allocate()) IRInstructionDataList(); @@ -255,6 +301,8 @@ unsigned IRInstructionMapper::mapToIllegalUnsigned( IRInstructionData *ID = nullptr; if (!End) ID = allocateIRInstructionData(*It, false, *IDL); + else + ID = allocateIRInstructionData(*IDL); InstrListForBB.push_back(ID); // Remember that we added an illegal number last time. @@ -563,8 +611,50 @@ bool IRSimilarityCandidate::compareCommutativeOperandMapping( return true; } +bool IRSimilarityCandidate::checkRelativeLocations(RelativeLocMapping A, + RelativeLocMapping B) { + // Get the basic blocks the label refers to. + BasicBlock *ABB = static_cast<BasicBlock *>(A.OperVal); + BasicBlock *BBB = static_cast<BasicBlock *>(B.OperVal); + + // Get the basic blocks contained in each region. + DenseSet<BasicBlock *> BasicBlockA; + DenseSet<BasicBlock *> BasicBlockB; + A.IRSC.getBasicBlocks(BasicBlockA); + B.IRSC.getBasicBlocks(BasicBlockB); + + // Determine if the block is contained in the region. + bool AContained = BasicBlockA.contains(ABB); + bool BContained = BasicBlockB.contains(BBB); + + // Both blocks need to be contained in the region, or both need to be outside + // the reigon. + if (AContained != BContained) + return false; + + // If both are contained, then we need to make sure that the relative + // distance to the target blocks are the same. + if (AContained) + return A.RelativeLocation == B.RelativeLocation; + return true; +} + bool IRSimilarityCandidate::compareStructure(const IRSimilarityCandidate &A, const IRSimilarityCandidate &B) { + DenseMap<unsigned, DenseSet<unsigned>> MappingA; + DenseMap<unsigned, DenseSet<unsigned>> MappingB; + return IRSimilarityCandidate::compareStructure(A, B, MappingA, MappingB); +} + +typedef detail::zippy<detail::zip_shortest, SmallVector<int, 4> &, + SmallVector<int, 4> &, ArrayRef<Value *> &, + ArrayRef<Value *> &> + ZippedRelativeLocationsT; + +bool IRSimilarityCandidate::compareStructure( + const IRSimilarityCandidate &A, const IRSimilarityCandidate &B, + DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingA, + DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingB) { if (A.getLength() != B.getLength()) return false; @@ -574,15 +664,12 @@ bool IRSimilarityCandidate::compareStructure(const IRSimilarityCandidate &A, iterator ItA = A.begin(); iterator ItB = B.begin(); - // These sets create a create a mapping between the values in one candidate - // to values in the other candidate. If we create a set with one element, - // and that same element maps to the original element in the candidate - // we have a good mapping. - DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingA; - DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingB; + // These ValueNumber Mapping sets create a create a mapping between the values + // in one candidate to values in the other candidate. If we create a set with + // one element, and that same element maps to the original element in the + // candidate we have a good mapping. DenseMap<unsigned, DenseSet<unsigned>>::iterator ValueMappingIt; - bool WasInserted; // Iterate over the instructions contained in each candidate unsigned SectionLength = A.getStartIdx() + A.getLength(); @@ -605,6 +692,7 @@ bool IRSimilarityCandidate::compareStructure(const IRSimilarityCandidate &A, unsigned InstValA = A.ValueToNumber.find(IA)->second; unsigned InstValB = B.ValueToNumber.find(IB)->second; + bool WasInserted; // Ensure that the mappings for the instructions exists. std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert( std::make_pair(InstValA, DenseSet<unsigned>({InstValB}))); @@ -632,6 +720,37 @@ bool IRSimilarityCandidate::compareStructure(const IRSimilarityCandidate &A, {A, OperValsA, ValueNumberMappingA}, {B, OperValsB, ValueNumberMappingB})) return false; + + // Here we check that between two corresponding instructions, + // when referring to a basic block in the same region, the + // relative locations are the same. And, that the instructions refer to + // basic blocks outside the region in the same corresponding locations. + + // We are able to make the assumption about blocks outside of the region + // since the target block labels are considered values and will follow the + // same number matching that we defined for the other instructions in the + // region. So, at this point, in each location we target a specific block + // outside the region, we are targeting a corresponding block in each + // analagous location in the region we are comparing to. + if (!(isa<BranchInst>(IA) && isa<BranchInst>(IB)) && + !(isa<PHINode>(IA) && isa<PHINode>(IB))) + continue; + + SmallVector<int, 4> &RelBlockLocsA = ItA->RelativeBlockLocations; + SmallVector<int, 4> &RelBlockLocsB = ItB->RelativeBlockLocations; + if (RelBlockLocsA.size() != RelBlockLocsB.size() && + OperValsA.size() != OperValsB.size()) + return false; + + ZippedRelativeLocationsT ZippedRelativeLocations = + zip(RelBlockLocsA, RelBlockLocsB, OperValsA, OperValsB); + if (any_of(ZippedRelativeLocations, + [&A, &B](std::tuple<int, int, Value *, Value *> R) { + return !checkRelativeLocations( + {A, std::get<0>(R), std::get<2>(R)}, + {B, std::get<1>(R), std::get<3>(R)}); + })) + return false; } return true; } @@ -657,6 +776,8 @@ void IRSimilarityIdentifier::populateMapper( std::vector<unsigned> IntegerMappingForModule; // Iterate over the functions in the module to map each Instruction in each // BasicBlock to an unsigned integer. + Mapper.initializeForBBs(M); + for (Function &F : M) { if (F.empty()) @@ -664,15 +785,18 @@ void IRSimilarityIdentifier::populateMapper( for (BasicBlock &BB : F) { - if (BB.sizeWithoutDebug() < 2) - continue; - // BB has potential to have similarity since it has a size greater than 2 // and can therefore match other regions greater than 2. Map it to a list // of unsigned integers. Mapper.convertToUnsignedVec(BB, InstrListForModule, IntegerMappingForModule); } + + BasicBlock::iterator It = F.begin()->end(); + Mapper.mapToIllegalUnsigned(It, IntegerMappingForModule, InstrListForModule, + true); + if (InstrListForModule.size() > 0) + Mapper.IDL->push_back(*InstrListForModule.back()); } // Insert the InstrListForModule at the end of the overall InstrList so that @@ -707,6 +831,8 @@ static void createCandidatesFromSuffixTree( std::vector<IRSimilarityCandidate> &CandsForRepSubstring) { unsigned StringLen = RS.Length; + if (StringLen < 2) + return; // Create an IRSimilarityCandidate for instance of this subsequence \p RS. for (const unsigned &StartIdx : RS.StartIndices) { @@ -739,6 +865,84 @@ static void createCandidatesFromSuffixTree( } } +void IRSimilarityCandidate::createCanonicalRelationFrom( + IRSimilarityCandidate &SourceCand, + DenseMap<unsigned, DenseSet<unsigned>> &ToSourceMapping, + DenseMap<unsigned, DenseSet<unsigned>> &FromSourceMapping) { + assert(SourceCand.CanonNumToNumber.size() != 0 && + "Base canonical relationship is empty!"); + assert(SourceCand.NumberToCanonNum.size() != 0 && + "Base canonical relationship is empty!"); + + assert(CanonNumToNumber.size() == 0 && "Canonical Relationship is non-empty"); + assert(NumberToCanonNum.size() == 0 && "Canonical Relationship is non-empty"); + + DenseSet<unsigned> UsedGVNs; + // Iterate over the mappings provided from this candidate to SourceCand. We + // are then able to map the GVN in this candidate to the same canonical number + // given to the corresponding GVN in SourceCand. + for (std::pair<unsigned, DenseSet<unsigned>> &GVNMapping : ToSourceMapping) { + unsigned SourceGVN = GVNMapping.first; + + assert(GVNMapping.second.size() != 0 && "Possible GVNs is 0!"); + + unsigned ResultGVN; + // We need special handling if we have more than one potential value. This + // means that there are at least two GVNs that could correspond to this GVN. + // This could lead to potential swapping later on, so we make a decision + // here to ensure a one-to-one mapping. + if (GVNMapping.second.size() > 1) { + bool Found = false; + for (unsigned Val : GVNMapping.second) { + // We make sure the target value number hasn't already been reserved. + if (UsedGVNs.contains(Val)) + continue; + + // We make sure that the opposite mapping is still consistent. + DenseMap<unsigned, DenseSet<unsigned>>::iterator It = + FromSourceMapping.find(Val); + + if (!It->second.contains(SourceGVN)) + continue; + + // We pick the first item that satisfies these conditions. + Found = true; + ResultGVN = Val; + break; + } + + assert(Found && "Could not find matching value for source GVN"); + (void)Found; + + } else + ResultGVN = *GVNMapping.second.begin(); + + // Whatever GVN is found, we mark it as used. + UsedGVNs.insert(ResultGVN); + + unsigned CanonNum = *SourceCand.getCanonicalNum(ResultGVN); + CanonNumToNumber.insert(std::make_pair(CanonNum, SourceGVN)); + NumberToCanonNum.insert(std::make_pair(SourceGVN, CanonNum)); + } +} + +void IRSimilarityCandidate::createCanonicalMappingFor( + IRSimilarityCandidate &CurrCand) { + assert(CurrCand.CanonNumToNumber.size() == 0 && + "Canonical Relationship is non-empty"); + assert(CurrCand.NumberToCanonNum.size() == 0 && + "Canonical Relationship is non-empty"); + + unsigned CanonNum = 0; + // Iterate over the value numbers found, the order does not matter in this + // case. + for (std::pair<unsigned, Value *> &NumToVal : CurrCand.NumberToValue) { + CurrCand.NumberToCanonNum.insert(std::make_pair(NumToVal.first, CanonNum)); + CurrCand.CanonNumToNumber.insert(std::make_pair(CanonNum, NumToVal.first)); + CanonNum++; + } +} + /// From the list of IRSimilarityCandidates, perform a comparison between each /// IRSimilarityCandidate to determine if there are overlapping /// IRInstructionData, or if they do not have the same structure. @@ -774,6 +978,8 @@ static void findCandidateStructures( // Iterate over the candidates to determine its structural and overlapping // compatibility with other instructions + DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingA; + DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingB; for (CandIt = CandsForRepSubstring.begin(), CandEndIt = CandsForRepSubstring.end(); CandIt != CandEndIt; CandIt++) { @@ -792,9 +998,11 @@ static void findCandidateStructures( // Check if we already have a list of IRSimilarityCandidates for the current // structural group. Create one if one does not exist. CurrentGroupPair = StructuralGroups.find(OuterGroupNum); - if (CurrentGroupPair == StructuralGroups.end()) + if (CurrentGroupPair == StructuralGroups.end()) { + IRSimilarityCandidate::createCanonicalMappingFor(*CandIt); std::tie(CurrentGroupPair, Inserted) = StructuralGroups.insert( std::make_pair(OuterGroupNum, SimilarityGroup({*CandIt}))); + } // Iterate over the IRSimilarityCandidates following the current // IRSimilarityCandidate in the list to determine whether the two @@ -811,11 +1019,15 @@ static void findCandidateStructures( // Otherwise we determine if they have the same structure and add it to // vector if they match. - SameStructure = - IRSimilarityCandidate::compareStructure(*CandIt, *InnerCandIt); + ValueNumberMappingA.clear(); + ValueNumberMappingB.clear(); + SameStructure = IRSimilarityCandidate::compareStructure( + *CandIt, *InnerCandIt, ValueNumberMappingA, ValueNumberMappingB); if (!SameStructure) continue; + InnerCandIt->createCanonicalRelationFrom(*CandIt, ValueNumberMappingA, + ValueNumberMappingB); CandToGroup.insert(std::make_pair(&*InnerCandIt, OuterGroupNum)); CurrentGroupPair->second.push_back(*InnerCandIt); } @@ -862,6 +1074,7 @@ SimilarityGroupList &IRSimilarityIdentifier::findSimilarity( std::vector<IRInstructionData *> InstrList; std::vector<unsigned> IntegerMapping; + Mapper.InstClassifier.EnableBranches = this->EnableBranches; populateMapper(Modules, InstrList, IntegerMapping); findCandidates(InstrList, IntegerMapping); @@ -871,6 +1084,7 @@ SimilarityGroupList &IRSimilarityIdentifier::findSimilarity( SimilarityGroupList &IRSimilarityIdentifier::findSimilarity(Module &M) { resetSimilarityCandidates(); + Mapper.InstClassifier.EnableBranches = this->EnableBranches; std::vector<IRInstructionData *> InstrList; std::vector<unsigned> IntegerMapping; @@ -891,7 +1105,7 @@ IRSimilarityIdentifierWrapperPass::IRSimilarityIdentifierWrapperPass() } bool IRSimilarityIdentifierWrapperPass::doInitialization(Module &M) { - IRSI.reset(new IRSimilarityIdentifier()); + IRSI.reset(new IRSimilarityIdentifier(!DisableBranches)); return false; } @@ -907,9 +1121,9 @@ bool IRSimilarityIdentifierWrapperPass::runOnModule(Module &M) { AnalysisKey IRSimilarityAnalysis::Key; IRSimilarityIdentifier IRSimilarityAnalysis::run(Module &M, - ModuleAnalysisManager &) { + ModuleAnalysisManager &) { - auto IRSI = IRSimilarityIdentifier(); + auto IRSI = IRSimilarityIdentifier(!DisableBranches); IRSI.findSimilarity(M); return IRSI; } diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp index fc6051b35efc..c4b7239b43ab 100644 --- a/llvm/lib/Analysis/IVDescriptors.cpp +++ b/llvm/lib/Analysis/IVDescriptors.cpp @@ -43,8 +43,8 @@ using namespace llvm::PatternMatch; bool RecurrenceDescriptor::areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set) { - for (User::op_iterator Use = I->op_begin(), E = I->op_end(); Use != E; ++Use) - if (!Set.count(dyn_cast<Instruction>(*Use))) + for (const Use &Use : I->operands()) + if (!Set.count(dyn_cast<Instruction>(Use))) return false; return true; } @@ -62,6 +62,8 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) { case RecurKind::SMin: case RecurKind::UMax: case RecurKind::UMin: + case RecurKind::SelectICmp: + case RecurKind::SelectFCmp: return true; } return false; @@ -144,12 +146,9 @@ static std::pair<Type *, bool> computeRecurrenceType(Instruction *Exit, // meaning that we will use sext instructions instead of zext // instructions to restore the original type. IsSigned = true; - if (!Bits.isNegative()) - // If the value is not known to be negative, we don't known what the - // upper bit is, and therefore, we don't know what kind of extend we - // will need. In this case, just increase the bit width by one bit and - // use sext. - ++MaxBitWidth; + // Make sure at at least one sign bit is included in the result, so it + // will get properly sign-extended. + ++MaxBitWidth; } } if (!isPowerOf2_64(MaxBitWidth)) @@ -199,7 +198,10 @@ static bool checkOrderedReduction(RecurKind Kind, Instruction *ExactFPMathInst, if (Kind != RecurKind::FAdd) return false; - if (Exit->getOpcode() != Instruction::FAdd || Exit != ExactFPMathInst) + // Ensure the exit instruction is an FAdd, and that it only has one user + // other than the reduction PHI + if (Exit->getOpcode() != Instruction::FAdd || Exit->hasNUsesOrMore(3) || + Exit != ExactFPMathInst) return false; // The only pattern accepted is the one in which the reduction PHI @@ -272,7 +274,7 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind, } else if (RecurrenceType->isIntegerTy()) { if (!isIntegerRecurrenceKind(Kind)) return false; - if (isArithmeticRecurrenceKind(Kind)) + if (!isMinMaxRecurrenceKind(Kind)) Start = lookThroughAnd(Phi, RecurrenceType, VisitedInsts, CastInsts); } else { // Pointer min/max may exist, but it is not supported as a reduction op. @@ -327,7 +329,8 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind, // the starting value (the Phi or an AND instruction if the Phi has been // type-promoted). if (Cur != Start) { - ReduxDesc = isRecurrenceInstr(Cur, Kind, ReduxDesc, FuncFMF); + ReduxDesc = + isRecurrenceInstr(TheLoop, Phi, Cur, Kind, ReduxDesc, FuncFMF); if (!ReduxDesc.isRecurrence()) return false; // FIXME: FMF is allowed on phi, but propagation is not handled correctly. @@ -360,6 +363,7 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind, // A reduction operation must only have one use of the reduction value. if (!IsAPhi && !IsASelect && !isMinMaxRecurrenceKind(Kind) && + !isSelectCmpRecurrenceKind(Kind) && hasMultipleUsesOf(Cur, VisitedInsts, 1)) return false; @@ -367,10 +371,10 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind, if (IsAPhi && Cur != Phi && !areAllUsesIn(Cur, VisitedInsts)) return false; - if (isIntMinMaxRecurrenceKind(Kind) && + if ((isIntMinMaxRecurrenceKind(Kind) || Kind == RecurKind::SelectICmp) && (isa<ICmpInst>(Cur) || isa<SelectInst>(Cur))) ++NumCmpSelectPatternInst; - if (isFPMinMaxRecurrenceKind(Kind) && + if ((isFPMinMaxRecurrenceKind(Kind) || Kind == RecurKind::SelectFCmp) && (isa<FCmpInst>(Cur) || isa<SelectInst>(Cur))) ++NumCmpSelectPatternInst; @@ -423,7 +427,9 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind, ((!isa<FCmpInst>(UI) && !isa<ICmpInst>(UI) && !isa<SelectInst>(UI)) || (!isConditionalRdxPattern(Kind, UI).isRecurrence() && - !isMinMaxSelectCmpPattern(UI, IgnoredVal).isRecurrence()))) + !isSelectCmpPattern(TheLoop, Phi, UI, IgnoredVal) + .isRecurrence() && + !isMinMaxPattern(UI, Kind, IgnoredVal).isRecurrence()))) return false; // Remember that we completed the cycle. @@ -435,8 +441,13 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind, } // This means we have seen one but not the other instruction of the - // pattern or more than just a select and cmp. - if (isMinMaxRecurrenceKind(Kind) && NumCmpSelectPatternInst != 2) + // pattern or more than just a select and cmp. Zero implies that we saw a + // llvm.min/max instrinsic, which is always OK. + if (isMinMaxRecurrenceKind(Kind) && NumCmpSelectPatternInst != 2 && + NumCmpSelectPatternInst != 0) + return false; + + if (isSelectCmpRecurrenceKind(Kind) && NumCmpSelectPatternInst != 1) return false; if (!FoundStartPHI || !FoundReduxOp || !ExitInstruction) @@ -505,11 +516,70 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind, return true; } +// We are looking for loops that do something like this: +// int r = 0; +// for (int i = 0; i < n; i++) { +// if (src[i] > 3) +// r = 3; +// } +// where the reduction value (r) only has two states, in this example 0 or 3. +// The generated LLVM IR for this type of loop will be like this: +// for.body: +// %r = phi i32 [ %spec.select, %for.body ], [ 0, %entry ] +// ... +// %cmp = icmp sgt i32 %5, 3 +// %spec.select = select i1 %cmp, i32 3, i32 %r +// ... +// In general we can support vectorization of loops where 'r' flips between +// any two non-constants, provided they are loop invariant. The only thing +// we actually care about at the end of the loop is whether or not any lane +// in the selected vector is different from the start value. The final +// across-vector reduction after the loop simply involves choosing the start +// value if nothing changed (0 in the example above) or the other selected +// value (3 in the example above). RecurrenceDescriptor::InstDesc -RecurrenceDescriptor::isMinMaxSelectCmpPattern(Instruction *I, - const InstDesc &Prev) { - assert((isa<CmpInst>(I) || isa<SelectInst>(I)) && - "Expected a cmp or select instruction"); +RecurrenceDescriptor::isSelectCmpPattern(Loop *Loop, PHINode *OrigPhi, + Instruction *I, InstDesc &Prev) { + // We must handle the select(cmp(),x,y) as a single instruction. Advance to + // the select. + CmpInst::Predicate Pred; + if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) { + if (auto *Select = dyn_cast<SelectInst>(*I->user_begin())) + return InstDesc(Select, Prev.getRecKind()); + } + + // Only match select with single use cmp condition. + if (!match(I, m_Select(m_OneUse(m_Cmp(Pred, m_Value(), m_Value())), m_Value(), + m_Value()))) + return InstDesc(false, I); + + SelectInst *SI = cast<SelectInst>(I); + Value *NonPhi = nullptr; + + if (OrigPhi == dyn_cast<PHINode>(SI->getTrueValue())) + NonPhi = SI->getFalseValue(); + else if (OrigPhi == dyn_cast<PHINode>(SI->getFalseValue())) + NonPhi = SI->getTrueValue(); + else + return InstDesc(false, I); + + // We are looking for selects of the form: + // select(cmp(), phi, loop_invariant) or + // select(cmp(), loop_invariant, phi) + if (!Loop->isLoopInvariant(NonPhi)) + return InstDesc(false, I); + + return InstDesc(I, isa<ICmpInst>(I->getOperand(0)) ? RecurKind::SelectICmp + : RecurKind::SelectFCmp); +} + +RecurrenceDescriptor::InstDesc +RecurrenceDescriptor::isMinMaxPattern(Instruction *I, RecurKind Kind, + const InstDesc &Prev) { + assert((isa<CmpInst>(I) || isa<SelectInst>(I) || isa<CallInst>(I)) && + "Expected a cmp or select or call instruction"); + if (!isMinMaxRecurrenceKind(Kind)) + return InstDesc(false, I); // We must handle the select(cmp()) as a single instruction. Advance to the // select. @@ -519,28 +589,33 @@ RecurrenceDescriptor::isMinMaxSelectCmpPattern(Instruction *I, return InstDesc(Select, Prev.getRecKind()); } - // Only match select with single use cmp condition. - if (!match(I, m_Select(m_OneUse(m_Cmp(Pred, m_Value(), m_Value())), m_Value(), + // Only match select with single use cmp condition, or a min/max intrinsic. + if (!isa<IntrinsicInst>(I) && + !match(I, m_Select(m_OneUse(m_Cmp(Pred, m_Value(), m_Value())), m_Value(), m_Value()))) return InstDesc(false, I); // Look for a min/max pattern. if (match(I, m_UMin(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::UMin); + return InstDesc(Kind == RecurKind::UMin, I); if (match(I, m_UMax(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::UMax); + return InstDesc(Kind == RecurKind::UMax, I); if (match(I, m_SMax(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::SMax); + return InstDesc(Kind == RecurKind::SMax, I); if (match(I, m_SMin(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::SMin); + return InstDesc(Kind == RecurKind::SMin, I); if (match(I, m_OrdFMin(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::FMin); + return InstDesc(Kind == RecurKind::FMin, I); if (match(I, m_OrdFMax(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::FMax); + return InstDesc(Kind == RecurKind::FMax, I); if (match(I, m_UnordFMin(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::FMin); + return InstDesc(Kind == RecurKind::FMin, I); if (match(I, m_UnordFMax(m_Value(), m_Value()))) - return InstDesc(I, RecurKind::FMax); + return InstDesc(Kind == RecurKind::FMax, I); + if (match(I, m_Intrinsic<Intrinsic::minnum>(m_Value(), m_Value()))) + return InstDesc(Kind == RecurKind::FMin, I); + if (match(I, m_Intrinsic<Intrinsic::maxnum>(m_Value(), m_Value()))) + return InstDesc(Kind == RecurKind::FMax, I); return InstDesc(false, I); } @@ -592,8 +667,10 @@ RecurrenceDescriptor::isConditionalRdxPattern(RecurKind Kind, Instruction *I) { } RecurrenceDescriptor::InstDesc -RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurKind Kind, - InstDesc &Prev, FastMathFlags FMF) { +RecurrenceDescriptor::isRecurrenceInstr(Loop *L, PHINode *OrigPhi, + Instruction *I, RecurKind Kind, + InstDesc &Prev, FastMathFlags FuncFMF) { + assert(Prev.getRecKind() == RecurKind::None || Prev.getRecKind() == Kind); switch (I->getOpcode()) { default: return InstDesc(false, I); @@ -624,9 +701,15 @@ RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurKind Kind, LLVM_FALLTHROUGH; case Instruction::FCmp: case Instruction::ICmp: + case Instruction::Call: + if (isSelectCmpRecurrenceKind(Kind)) + return isSelectCmpPattern(L, OrigPhi, I, Prev); if (isIntMinMaxRecurrenceKind(Kind) || - (FMF.noNaNs() && FMF.noSignedZeros() && isFPMinMaxRecurrenceKind(Kind))) - return isMinMaxSelectCmpPattern(I, Prev); + (((FuncFMF.noNaNs() && FuncFMF.noSignedZeros()) || + (isa<FPMathOperator>(I) && I->hasNoNaNs() && + I->hasNoSignedZeros())) && + isFPMinMaxRecurrenceKind(Kind))) + return isMinMaxPattern(I, Kind, Prev); return InstDesc(false, I); } } @@ -649,7 +732,6 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop, RecurrenceDescriptor &RedDes, DemandedBits *DB, AssumptionCache *AC, DominatorTree *DT) { - BasicBlock *Header = TheLoop->getHeader(); Function &F = *Header->getParent(); FastMathFlags FMF; @@ -694,6 +776,12 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop, LLVM_DEBUG(dbgs() << "Found a UMIN reduction PHI." << *Phi << "\n"); return true; } + if (AddReductionVar(Phi, RecurKind::SelectICmp, TheLoop, FMF, RedDes, DB, AC, + DT)) { + LLVM_DEBUG(dbgs() << "Found an integer conditional select reduction PHI." + << *Phi << "\n"); + return true; + } if (AddReductionVar(Phi, RecurKind::FMul, TheLoop, FMF, RedDes, DB, AC, DT)) { LLVM_DEBUG(dbgs() << "Found an FMult reduction PHI." << *Phi << "\n"); return true; @@ -710,6 +798,12 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop, LLVM_DEBUG(dbgs() << "Found a float MIN reduction PHI." << *Phi << "\n"); return true; } + if (AddReductionVar(Phi, RecurKind::SelectFCmp, TheLoop, FMF, RedDes, DB, AC, + DT)) { + LLVM_DEBUG(dbgs() << "Found a float conditional select reduction PHI." + << " PHI." << *Phi << "\n"); + return true; + } // Not a reduction of known type. return false; } @@ -816,8 +910,8 @@ bool RecurrenceDescriptor::isFirstOrderRecurrence( /// This function returns the identity element (or neutral element) for /// the operation K. -Constant *RecurrenceDescriptor::getRecurrenceIdentity(RecurKind K, Type *Tp, - FastMathFlags FMF) { +Value *RecurrenceDescriptor::getRecurrenceIdentity(RecurKind K, Type *Tp, + FastMathFlags FMF) { switch (K) { case RecurKind::Xor: case RecurKind::Add: @@ -857,6 +951,10 @@ Constant *RecurrenceDescriptor::getRecurrenceIdentity(RecurKind K, Type *Tp, return ConstantFP::getInfinity(Tp, true); case RecurKind::FMax: return ConstantFP::getInfinity(Tp, false); + case RecurKind::SelectICmp: + case RecurKind::SelectFCmp: + return getRecurrenceStartValue(); + break; default: llvm_unreachable("Unknown recurrence kind"); } @@ -882,9 +980,11 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) { case RecurKind::SMin: case RecurKind::UMax: case RecurKind::UMin: + case RecurKind::SelectICmp: return Instruction::ICmp; case RecurKind::FMax: case RecurKind::FMin: + case RecurKind::SelectFCmp: return Instruction::FCmp; default: llvm_unreachable("Unknown recurrence operation"); @@ -963,8 +1063,10 @@ RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const { InductionDescriptor::InductionDescriptor(Value *Start, InductionKind K, const SCEV *Step, BinaryOperator *BOp, + Type *ElementType, SmallVectorImpl<Instruction *> *Casts) - : StartValue(Start), IK(K), Step(Step), InductionBinOp(BOp) { + : StartValue(Start), IK(K), Step(Step), InductionBinOp(BOp), + ElementType(ElementType) { assert(IK != IK_NoInduction && "Not an induction"); // Start value type should match the induction kind and the value @@ -992,6 +1094,11 @@ InductionDescriptor::InductionDescriptor(Value *Start, InductionKind K, InductionBinOp->getOpcode() == Instruction::FSub))) && "Binary opcode should be specified for FP induction"); + if (IK == IK_PtrInduction) + assert(ElementType && "Pointer induction must have element type"); + else + assert(!ElementType && "Non-pointer induction cannot have element type"); + if (Casts) { for (auto &Inst : *Casts) { RedundantCasts.push_back(Inst); @@ -1239,8 +1346,6 @@ bool InductionDescriptor::isInductionPHI( BasicBlock *Latch = AR->getLoop()->getLoopLatch(); if (!Latch) return false; - BinaryOperator *BOp = - dyn_cast<BinaryOperator>(Phi->getIncomingValueForBlock(Latch)); const SCEV *Step = AR->getStepRecurrence(*SE); // Calculate the pointer stride and check if it is consecutive. @@ -1250,8 +1355,10 @@ bool InductionDescriptor::isInductionPHI( return false; if (PhiTy->isIntegerTy()) { + BinaryOperator *BOp = + dyn_cast<BinaryOperator>(Phi->getIncomingValueForBlock(Latch)); D = InductionDescriptor(StartValue, IK_IntInduction, Step, BOp, - CastsToIgnore); + /* ElementType */ nullptr, CastsToIgnore); return true; } @@ -1260,15 +1367,16 @@ bool InductionDescriptor::isInductionPHI( if (!ConstStep) return false; - ConstantInt *CV = ConstStep->getValue(); - Type *PointerElementType = PhiTy->getPointerElementType(); - // The pointer stride cannot be determined if the pointer element type is not - // sized. - if (!PointerElementType->isSized()) + // Always use i8 element type for opaque pointer inductions. + PointerType *PtrTy = cast<PointerType>(PhiTy); + Type *ElementType = PtrTy->isOpaque() ? Type::getInt8Ty(PtrTy->getContext()) + : PtrTy->getElementType(); + if (!ElementType->isSized()) return false; + ConstantInt *CV = ConstStep->getValue(); const DataLayout &DL = Phi->getModule()->getDataLayout(); - int64_t Size = static_cast<int64_t>(DL.getTypeAllocSize(PointerElementType)); + int64_t Size = static_cast<int64_t>(DL.getTypeAllocSize(ElementType)); if (!Size) return false; @@ -1277,6 +1385,7 @@ bool InductionDescriptor::isInductionPHI( return false; auto *StepValue = SE->getConstant(CV->getType(), CVSize / Size, true /* signed */); - D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue, BOp); + D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue, + /* BinOp */ nullptr, ElementType); return true; } diff --git a/llvm/lib/Analysis/IVUsers.cpp b/llvm/lib/Analysis/IVUsers.cpp index db6cff720642..d7b202f83189 100644 --- a/llvm/lib/Analysis/IVUsers.cpp +++ b/llvm/lib/Analysis/IVUsers.cpp @@ -90,34 +90,6 @@ static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, return false; } -/// Return true if all loop headers that dominate this block are in simplified -/// form. -static bool isSimplifiedLoopNest(BasicBlock *BB, const DominatorTree *DT, - const LoopInfo *LI, - SmallPtrSetImpl<Loop*> &SimpleLoopNests) { - Loop *NearestLoop = nullptr; - for (DomTreeNode *Rung = DT->getNode(BB); - Rung; Rung = Rung->getIDom()) { - BasicBlock *DomBB = Rung->getBlock(); - Loop *DomLoop = LI->getLoopFor(DomBB); - if (DomLoop && DomLoop->getHeader() == DomBB) { - // If we have already checked this loop nest, stop checking. - if (SimpleLoopNests.count(DomLoop)) - break; - // If the domtree walk reaches a loop with no preheader, return false. - if (!DomLoop->isLoopSimplifyForm()) - return false; - // If we have not already checked this loop nest, remember the loop - // header nearest to BB. The nearest loop may not contain BB. - if (!NearestLoop) - NearestLoop = DomLoop; - } - } - if (NearestLoop) - SimpleLoopNests.insert(NearestLoop); - return true; -} - /// IVUseShouldUsePostIncValue - We have discovered a "User" of an IV expression /// and now we need to decide whether the user should use the preinc or post-inc /// value. If this user should use the post-inc version of the IV, return true. @@ -162,11 +134,10 @@ static bool IVUseShouldUsePostIncValue(Instruction *User, Value *Operand, return true; } -/// AddUsersImpl - Inspect the specified instruction. If it is a -/// reducible SCEV, recursively add its users to the IVUsesByStride set and -/// return true. Otherwise, return false. -bool IVUsers::AddUsersImpl(Instruction *I, - SmallPtrSetImpl<Loop*> &SimpleLoopNests) { +/// Inspect the specified instruction. If it is a reducible SCEV, recursively +/// add its users to the IVUsesByStride set and return true. Otherwise, return +/// false. +bool IVUsers::AddUsersIfInteresting(Instruction *I) { const DataLayout &DL = I->getModule()->getDataLayout(); // Add this IV user to the Processed set before returning false to ensure that @@ -213,18 +184,6 @@ bool IVUsers::AddUsersImpl(Instruction *I, if (isa<PHINode>(User) && Processed.count(User)) continue; - // Only consider IVUsers that are dominated by simplified loop - // headers. Otherwise, SCEVExpander will crash. - BasicBlock *UseBB = User->getParent(); - // A phi's use is live out of its predecessor block. - if (PHINode *PHI = dyn_cast<PHINode>(User)) { - unsigned OperandNo = U.getOperandNo(); - unsigned ValNo = PHINode::getIncomingValueNumForOperand(OperandNo); - UseBB = PHI->getIncomingBlock(ValNo); - } - if (!isSimplifiedLoopNest(UseBB, DT, LI, SimpleLoopNests)) - return false; - // Descend recursively, but not into PHI nodes outside the current loop. // It's important to see the entire expression outside the loop to get // choices that depend on addressing mode use right, although we won't @@ -234,12 +193,12 @@ bool IVUsers::AddUsersImpl(Instruction *I, bool AddUserToIVUsers = false; if (LI->getLoopFor(User->getParent()) != L) { if (isa<PHINode>(User) || Processed.count(User) || - !AddUsersImpl(User, SimpleLoopNests)) { + !AddUsersIfInteresting(User)) { LLVM_DEBUG(dbgs() << "FOUND USER in other loop: " << *User << '\n' << " OF SCEV: " << *ISE << '\n'); AddUserToIVUsers = true; } - } else if (Processed.count(User) || !AddUsersImpl(User, SimpleLoopNests)) { + } else if (Processed.count(User) || !AddUsersIfInteresting(User)) { LLVM_DEBUG(dbgs() << "FOUND USER: " << *User << '\n' << " OF SCEV: " << *ISE << '\n'); AddUserToIVUsers = true; @@ -288,15 +247,6 @@ bool IVUsers::AddUsersImpl(Instruction *I, return true; } -bool IVUsers::AddUsersIfInteresting(Instruction *I) { - // SCEVExpander can only handle users that are dominated by simplified loop - // entries. Keep track of all loops that are only dominated by other simple - // loops so we don't traverse the domtree for each user. - SmallPtrSet<Loop*,16> SimpleLoopNests; - - return AddUsersImpl(I, SimpleLoopNests); -} - IVStrideUse &IVUsers::AddUser(Instruction *User, Value *Operand) { IVUses.push_back(new IVStrideUse(this, User, Operand)); return IVUses.back(); diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp index a8ad2d6696bf..73d1eff1b968 100644 --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -49,6 +49,42 @@ static cl::opt<int> extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats; +namespace { +using namespace llvm::ore; +class MandatoryInlineAdvice : public InlineAdvice { +public: + MandatoryInlineAdvice(InlineAdvisor *Advisor, CallBase &CB, + OptimizationRemarkEmitter &ORE, + bool IsInliningMandatory) + : InlineAdvice(Advisor, CB, ORE, IsInliningMandatory) {} + +private: + void recordInliningWithCalleeDeletedImpl() override { recordInliningImpl(); } + + void recordInliningImpl() override { + if (IsInliningRecommended) + emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, IsInliningRecommended, + [&](OptimizationRemark &Remark) { + Remark << ": always inline attribute"; + }); + } + + void recordUnsuccessfulInliningImpl(const InlineResult &Result) override { + if (IsInliningRecommended) + ORE.emit([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block) + << "'" << NV("Callee", Callee) << "' is not AlwaysInline into '" + << NV("Caller", Caller) + << "': " << NV("Reason", Result.getFailureReason()); + }); + } + + void recordUnattemptedInliningImpl() override { + assert(!IsInliningRecommended && "Expected to attempt inlining"); + } +}; +} // namespace + void DefaultInlineAdvice::recordUnsuccessfulInliningImpl( const InlineResult &Result) { using namespace ore; @@ -56,20 +92,20 @@ void DefaultInlineAdvice::recordUnsuccessfulInliningImpl( "; " + inlineCostStr(*OIC)); ORE.emit([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block) - << NV("Callee", Callee) << " will not be inlined into " - << NV("Caller", Caller) << ": " - << NV("Reason", Result.getFailureReason()); + << "'" << NV("Callee", Callee) << "' is not inlined into '" + << NV("Caller", Caller) + << "': " << NV("Reason", Result.getFailureReason()); }); } void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() { if (EmitRemarks) - emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC); + emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC); } void DefaultInlineAdvice::recordInliningImpl() { if (EmitRemarks) - emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC); + emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC); } llvm::Optional<llvm::InlineCost> static getDefaultInlineAdvice( @@ -151,9 +187,9 @@ void InlineAdvice::recordInliningWithCalleeDeleted() { AnalysisKey InlineAdvisorAnalysis::Key; -bool InlineAdvisorAnalysis::Result::tryCreate(InlineParams Params, - InliningAdvisorMode Mode, - StringRef ReplayFile) { +bool InlineAdvisorAnalysis::Result::tryCreate( + InlineParams Params, InliningAdvisorMode Mode, + const ReplayInlinerSettings &ReplaySettings) { auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); switch (Mode) { case InliningAdvisorMode::Default: @@ -161,10 +197,10 @@ bool InlineAdvisorAnalysis::Result::tryCreate(InlineParams Params, Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params)); // Restrict replay to default advisor, ML advisors are stateful so // replay will need augmentations to interleave with them correctly. - if (!ReplayFile.empty()) { - Advisor = std::make_unique<ReplayInlineAdvisor>( - M, FAM, M.getContext(), std::move(Advisor), ReplayFile, - /* EmitRemarks =*/true); + if (!ReplaySettings.ReplayFile.empty()) { + Advisor = llvm::getReplayInlineAdvisor(M, FAM, M.getContext(), + std::move(Advisor), ReplaySettings, + /* EmitRemarks =*/true); } break; case InliningAdvisorMode::Development: @@ -313,7 +349,7 @@ void llvm::setInlineRemark(CallBase &CB, StringRef Message) { return; Attribute Attr = Attribute::get(CB.getContext(), "inline-remark", Message); - CB.addAttribute(AttributeList::FunctionIndex, Attr); + CB.addFnAttr(Attr); } /// Return the cost only if the inliner should attempt to inline at the given @@ -343,15 +379,15 @@ llvm::shouldInline(CallBase &CB, if (IC.isNever()) { ORE.emit([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call) - << NV("Callee", Callee) << " not inlined into " - << NV("Caller", Caller) << " because it should never be inlined " - << IC; + << "'" << NV("Callee", Callee) << "' not inlined into '" + << NV("Caller", Caller) + << "' because it should never be inlined " << IC; }); } else { ORE.emit([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call) - << NV("Callee", Callee) << " not inlined into " - << NV("Caller", Caller) << " because too costly to inline " + << "'" << NV("Callee", Callee) << "' not inlined into '" + << NV("Caller", Caller) << "' because too costly to inline " << IC; }); } @@ -368,9 +404,9 @@ llvm::shouldInline(CallBase &CB, ORE.emit([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "IncreaseCostInOtherContexts", Call) - << "Not inlining. Cost of inlining " << NV("Callee", Callee) - << " increases the cost of inlining " << NV("Caller", Caller) - << " in other contexts"; + << "Not inlining. Cost of inlining '" << NV("Callee", Callee) + << "' increases the cost of inlining '" << NV("Caller", Caller) + << "' in other contexts"; }); setInlineRemark(CB, "deferred"); // IC does not bool() to false, so get an InlineCost that will. @@ -383,7 +419,8 @@ llvm::shouldInline(CallBase &CB, return IC; } -std::string llvm::getCallSiteLocation(DebugLoc DLoc) { +std::string llvm::formatCallSiteLocation(DebugLoc DLoc, + const CallSiteFormat &Format) { std::string Buffer; raw_string_ostream CallSiteLoc(Buffer); bool First = true; @@ -399,9 +436,10 @@ std::string llvm::getCallSiteLocation(DebugLoc DLoc) { StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName(); if (Name.empty()) Name = DIL->getScope()->getSubprogram()->getName(); - CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset) << ":" - << llvm::utostr(DIL->getColumn()); - if (Discriminator) + CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset); + if (Format.outputColumn()) + CallSiteLoc << ":" << llvm::utostr(DIL->getColumn()); + if (Format.outputDiscriminator() && Discriminator) CallSiteLoc << "." << llvm::utostr(Discriminator); First = false; } @@ -435,25 +473,38 @@ void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) { Remark << ";"; } -void llvm::emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, - const BasicBlock *Block, const Function &Callee, - const Function &Caller, const InlineCost &IC, - bool ForProfileContext, const char *PassName) { +void llvm::emitInlinedInto( + OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block, + const Function &Callee, const Function &Caller, bool AlwaysInline, + function_ref<void(OptimizationRemark &)> ExtraContext, + const char *PassName) { ORE.emit([&]() { - bool AlwaysInline = IC.isAlways(); StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined"; OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName, DLoc, Block); - Remark << ore::NV("Callee", &Callee) << " inlined into "; - Remark << ore::NV("Caller", &Caller); - if (ForProfileContext) - Remark << " to match profiling context"; - Remark << " with " << IC; + Remark << "'" << ore::NV("Callee", &Callee) << "' inlined into '" + << ore::NV("Caller", &Caller) << "'"; + if (ExtraContext) + ExtraContext(Remark); addLocationToRemarks(Remark, DLoc); return Remark; }); } +void llvm::emitInlinedIntoBasedOnCost( + OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block, + const Function &Callee, const Function &Caller, const InlineCost &IC, + bool ForProfileContext, const char *PassName) { + llvm::emitInlinedInto( + ORE, DLoc, Block, Callee, Caller, IC.isAlways(), + [&](OptimizationRemark &Remark) { + if (ForProfileContext) + Remark << " to match profiling context"; + Remark << " with " << IC; + }, + PassName); +} + InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM) : M(M), FAM(FAM) { if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) { @@ -475,7 +526,8 @@ InlineAdvisor::~InlineAdvisor() { std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB, bool Advice) { - return std::make_unique<InlineAdvice>(this, CB, getCallerORE(CB), Advice); + return std::make_unique<MandatoryInlineAdvice>(this, CB, getCallerORE(CB), + Advice); } InlineAdvisor::MandatoryInliningKind diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index 4c2413e14435..ff31e81aad08 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -135,6 +135,31 @@ static cl::opt<bool> DisableGEPConstOperand( namespace { class InlineCostCallAnalyzer; +/// This function behaves more like CallBase::hasFnAttr: when it looks for the +/// requested attribute, it check both the call instruction and the called +/// function (if it's available and operand bundles don't prohibit that). +Attribute getFnAttr(CallBase &CB, StringRef AttrKind) { + Attribute CallAttr = CB.getFnAttr(AttrKind); + if (CallAttr.isValid()) + return CallAttr; + + // Operand bundles override attributes on the called function, but don't + // override attributes directly present on the call instruction. + if (!CB.isFnAttrDisallowedByOpBundle(AttrKind)) + if (const Function *F = CB.getCalledFunction()) + return F->getFnAttribute(AttrKind); + + return {}; +} + +Optional<int> getStringFnAttrAsInt(CallBase &CB, StringRef AttrKind) { + Attribute Attr = getFnAttr(CB, AttrKind); + int AttrValue; + if (Attr.getValueAsString().getAsInteger(10, AttrValue)) + return None; + return AttrValue; +} + // This struct is used to store information about inline cost of a // particular instruction struct InstructionCostDetail { @@ -235,6 +260,10 @@ protected: /// Called the analysis engine determines load elimination won't happen. virtual void onDisableLoadElimination() {} + /// Called when we visit a CallBase, before the analysis starts. Return false + /// to stop further processing of the instruction. + virtual bool onCallBaseVisitStart(CallBase &Call) { return true; } + /// Called to account for a call. virtual void onCallPenalty() {} @@ -333,6 +362,10 @@ protected: /// whenever we simplify away the stores that would otherwise cause them to be /// loads. bool EnableLoadElimination; + + /// Whether we allow inlining for recursive call. + bool AllowRecursiveCall; + SmallPtrSet<Value *, 16> LoadAddrSet; AllocaInst *getSROAArgForValueOrNull(Value *V) const { @@ -354,6 +387,7 @@ protected: bool simplifyCallSite(Function *F, CallBase &Call); template <typename Callable> bool simplifyInstruction(Instruction &I, Callable Evaluate); + bool simplifyIntrinsicCallIsConstant(CallBase &CB); ConstantInt *stripAndComputeInBoundsConstantOffsets(Value *&V); /// Return true if the given argument to the function being considered for @@ -421,7 +455,8 @@ public: OptimizationRemarkEmitter *ORE = nullptr) : TTI(TTI), GetAssumptionCache(GetAssumptionCache), GetBFI(GetBFI), PSI(PSI), F(Callee), DL(F.getParent()->getDataLayout()), ORE(ORE), - CandidateCall(Call), EnableLoadElimination(true) {} + CandidateCall(Call), EnableLoadElimination(true), + AllowRecursiveCall(false) {} InlineResult analyze(); @@ -510,6 +545,9 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { // sense that it's not weighted by profile counts at all. int ColdSize = 0; + // Whether inlining is decided by cost-threshold analysis. + bool DecidedByCostThreshold = false; + // Whether inlining is decided by cost-benefit analysis. bool DecidedByCostBenefit = false; @@ -558,6 +596,22 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { addCost(LoadEliminationCost); LoadEliminationCost = 0; } + + bool onCallBaseVisitStart(CallBase &Call) override { + if (Optional<int> AttrCallThresholdBonus = + getStringFnAttrAsInt(Call, "call-threshold-bonus")) + Threshold += *AttrCallThresholdBonus; + + if (Optional<int> AttrCallCost = + getStringFnAttrAsInt(Call, "call-inline-cost")) { + addCost(*AttrCallCost); + // Prevent further processing of the call since we want to override its + // inline cost, not just add to it. + return false; + } + return true; + } + void onCallPenalty() override { addCost(CallPenalty); } void onCallArgumentSetup(const CallBase &Call) override { // Pay the price of the argument setup. We account for the average 1 @@ -717,7 +771,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { // Make sure we have a nonzero entry count. auto EntryCount = F.getEntryCount(); - if (!EntryCount || !EntryCount.getCount()) + if (!EntryCount || !EntryCount->getCount()) return false; BlockFrequencyInfo *CalleeBFI = &(GetBFI(F)); @@ -763,7 +817,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { if (BranchInst *BI = dyn_cast<BranchInst>(&I)) { // Count a conditional branch as savings if it becomes unconditional. if (BI->isConditional() && - dyn_cast_or_null<ConstantInt>( + isa_and_nonnull<ConstantInt>( SimplifiedValues.lookup(BI->getCondition()))) { CurrentSavings += InlineConstants::InstrCost; } @@ -783,8 +837,8 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { // Compute the cycle savings per call. auto EntryProfileCount = F.getEntryCount(); - assert(EntryProfileCount.hasValue() && EntryProfileCount.getCount()); - auto EntryCount = EntryProfileCount.getCount(); + assert(EntryProfileCount.hasValue() && EntryProfileCount->getCount()); + auto EntryCount = EntryProfileCount->getCount(); CycleSavings += EntryCount / 2; CycleSavings = CycleSavings.udiv(EntryCount); @@ -847,6 +901,14 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { else if (NumVectorInstructions <= NumInstructions / 2) Threshold -= VectorBonus / 2; + if (Optional<int> AttrCost = + getStringFnAttrAsInt(CandidateCall, "function-inline-cost")) + Cost = *AttrCost; + + if (Optional<int> AttrThreshold = + getStringFnAttrAsInt(CandidateCall, "function-inline-threshold")) + Threshold = *AttrThreshold; + if (auto Result = costBenefitAnalysis()) { DecidedByCostBenefit = true; if (Result.getValue()) @@ -855,14 +917,24 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { return InlineResult::failure("Cost over threshold."); } - if (IgnoreThreshold || Cost < std::max(1, Threshold)) + if (IgnoreThreshold) return InlineResult::success(); - return InlineResult::failure("Cost over threshold."); + + DecidedByCostThreshold = true; + return Cost < std::max(1, Threshold) + ? InlineResult::success() + : InlineResult::failure("Cost over threshold."); } + bool shouldStop() override { + if (IgnoreThreshold || ComputeFullInlineCost) + return false; // Bail out the moment we cross the threshold. This means we'll under-count // the cost, but only when undercounting doesn't matter. - return !IgnoreThreshold && Cost >= Threshold && !ComputeFullInlineCost; + if (Cost < Threshold) + return false; + DecidedByCostThreshold = true; + return true; } void onLoadEliminationOpportunity() override { @@ -930,7 +1002,9 @@ public: Params(Params), Threshold(Params.DefaultThreshold), BoostIndirectCalls(BoostIndirect), IgnoreThreshold(IgnoreThreshold), CostBenefitAnalysisEnabled(isCostBenefitAnalysisEnabled()), - Writer(this) {} + Writer(this) { + AllowRecursiveCall = Params.AllowRecursiveCall.getValue(); + } /// Annotation Writer for instruction details InlineCostAnnotationWriter Writer; @@ -939,7 +1013,7 @@ public: // Prints the same analysis as dump(), but its definition is not dependent // on the build. - void print(); + void print(raw_ostream &OS); Optional<InstructionCostDetail> getCostDetails(const Instruction *I) { if (InstructionCostDetailMap.find(I) != InstructionCostDetailMap.end()) @@ -952,6 +1026,7 @@ public: int getCost() const { return Cost; } Optional<CostBenefitPair> getCostBenefitPair() { return CostBenefit; } bool wasDecidedByCostBenefit() const { return DecidedByCostBenefit; } + bool wasDecidedByCostThreshold() const { return DecidedByCostThreshold; } }; class InlineCostFeaturesAnalyzer final : public CallAnalyzer { @@ -1310,7 +1385,7 @@ bool CallAnalyzer::visitPHI(PHINode &I) { // Or could we skip the getPointerSizeInBits call completely? As far as I can // see the ZeroOffset is used as a dummy value, so we can probably use any // bit width for the ZeroOffset? - APInt ZeroOffset = APInt::getNullValue(DL.getPointerSizeInBits(0)); + APInt ZeroOffset = APInt::getZero(DL.getPointerSizeInBits(0)); bool CheckSROA = I.getType()->isPointerTy(); // Track the constant or pointer with constant offset we've seen so far. @@ -1471,6 +1546,27 @@ bool CallAnalyzer::simplifyInstruction(Instruction &I, Callable Evaluate) { return true; } +/// Try to simplify a call to llvm.is.constant. +/// +/// Duplicate the argument checking from CallAnalyzer::simplifyCallSite since +/// we expect calls of this specific intrinsic to be infrequent. +/// +/// FIXME: Given that we know CB's parent (F) caller +/// (CandidateCall->getParent()->getParent()), we might be able to determine +/// whether inlining F into F's caller would change how the call to +/// llvm.is.constant would evaluate. +bool CallAnalyzer::simplifyIntrinsicCallIsConstant(CallBase &CB) { + Value *Arg = CB.getArgOperand(0); + auto *C = dyn_cast<Constant>(Arg); + + if (!C) + C = dyn_cast_or_null<Constant>(SimplifiedValues.lookup(Arg)); + + Type *RT = CB.getFunctionType()->getReturnType(); + SimplifiedValues[&CB] = ConstantInt::get(RT, C ? 1 : 0); + return true; +} + bool CallAnalyzer::visitBitCast(BitCastInst &I) { // Propagate constants through bitcasts. if (simplifyInstruction(I, [&](SmallVectorImpl<Constant *> &COps) { @@ -1799,8 +1895,8 @@ void InlineCostCallAnalyzer::updateThreshold(CallBase &Call, Function &Callee) { SingleBBBonus = Threshold * SingleBBBonusPercent / 100; VectorBonus = Threshold * VectorBonusPercent / 100; - bool OnlyOneCallAndLocalLinkage = - F.hasLocalLinkage() && F.hasOneUse() && &F == Call.getCalledFunction(); + bool OnlyOneCallAndLocalLinkage = F.hasLocalLinkage() && F.hasOneLiveUse() && + &F == Call.getCalledFunction(); // If there is only one call of the function, and it has internal linkage, // the cost of inlining it drops dramatically. It may seem odd to update // Cost in updateThreshold, but the bonus depends on the logic in this method. @@ -2029,6 +2125,9 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallBase &Call) { } bool CallAnalyzer::visitCallBase(CallBase &Call) { + if (!onCallBaseVisitStart(Call)) + return true; + if (Call.hasFnAttr(Attribute::ReturnsTwice) && !F.hasFnAttribute(Attribute::ReturnsTwice)) { // This aborts the entire analysis. @@ -2091,6 +2190,8 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) { if (auto *SROAArg = getSROAArgForValueOrNull(II->getOperand(0))) SROAArgValues[II] = SROAArg; return true; + case Intrinsic::is_constant: + return simplifyIntrinsicCallIsConstant(Call); } } @@ -2098,7 +2199,8 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) { // This flag will fully abort the analysis, so don't bother with anything // else. IsRecursiveCall = true; - return false; + if (!AllowRecursiveCall) + return false; } if (TTI.isLoweredToCall(F)) { @@ -2123,7 +2225,7 @@ bool CallAnalyzer::visitBranchInst(BranchInst &BI) { // inliner more regular and predictable. Interestingly, conditional branches // which will fold away are also free. return BI.isUnconditional() || isa<ConstantInt>(BI.getCondition()) || - dyn_cast_or_null<ConstantInt>( + isa_and_nonnull<ConstantInt>( SimplifiedValues.lookup(BI.getCondition())); } @@ -2305,11 +2407,8 @@ CallAnalyzer::analyzeBlock(BasicBlock *BB, // inlining due to debug symbols. Eventually, the number of unsimplified // instructions shouldn't factor into the cost computation, but until then, // hack around it here. - if (isa<DbgInfoIntrinsic>(I)) - continue; - - // Skip pseudo-probes. - if (isa<PseudoProbeInst>(I)) + // Similarly, skip pseudo-probes. + if (I.isDebugOrPseudoInst()) continue; // Skip ephemeral values. @@ -2336,7 +2435,7 @@ CallAnalyzer::analyzeBlock(BasicBlock *BB, using namespace ore; // If the visit this instruction detected an uninlinable pattern, abort. InlineResult IR = InlineResult::success(); - if (IsRecursiveCall) + if (IsRecursiveCall && !AllowRecursiveCall) IR = InlineResult::failure("recursive"); else if (ExposesReturnsTwice) IR = InlineResult::failure("exposes returns twice"); @@ -2398,7 +2497,7 @@ ConstantInt *CallAnalyzer::stripAndComputeInBoundsConstantOffsets(Value *&V) { unsigned AS = V->getType()->getPointerAddressSpace(); unsigned IntPtrWidth = DL.getIndexSizeInBits(AS); - APInt Offset = APInt::getNullValue(IntPtrWidth); + APInt Offset = APInt::getZero(IntPtrWidth); // Even though we don't look through PHI nodes, we could be called on an // instruction in an unreachable block, which may be on a cycle. @@ -2601,7 +2700,7 @@ InlineResult CallAnalyzer::analyze() { onBlockAnalyzed(BB); } - bool OnlyOneCallAndLocalLinkage = F.hasLocalLinkage() && F.hasOneUse() && + bool OnlyOneCallAndLocalLinkage = F.hasLocalLinkage() && F.hasOneLiveUse() && &F == CandidateCall.getCalledFunction(); // If this is a noduplicate call, we can still inline as long as // inlining this would cause the removal of the caller (so the instruction @@ -2612,10 +2711,10 @@ InlineResult CallAnalyzer::analyze() { return finalizeAnalysis(); } -void InlineCostCallAnalyzer::print() { -#define DEBUG_PRINT_STAT(x) dbgs() << " " #x ": " << x << "\n" +void InlineCostCallAnalyzer::print(raw_ostream &OS) { +#define DEBUG_PRINT_STAT(x) OS << " " #x ": " << x << "\n" if (PrintInstructionComments) - F.print(dbgs(), &Writer); + F.print(OS, &Writer); DEBUG_PRINT_STAT(NumConstantArgs); DEBUG_PRINT_STAT(NumConstantOffsetPtrArgs); DEBUG_PRINT_STAT(NumAllocaArgs); @@ -2634,7 +2733,7 @@ void InlineCostCallAnalyzer::print() { #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// Dump stats about this call's analysis. -LLVM_DUMP_METHOD void InlineCostCallAnalyzer::dump() { print(); } +LLVM_DUMP_METHOD void InlineCostCallAnalyzer::dump() { print(dbgs()); } #endif /// Test that there are no attribute conflicts between Caller and Callee @@ -2849,13 +2948,13 @@ InlineCost llvm::getInlineCost( return InlineCost::getNever("cost over benefit", CA.getCostBenefitPair()); } - // Check if there was a reason to force inlining or no inlining. - if (!ShouldInline.isSuccess() && CA.getCost() < CA.getThreshold()) - return InlineCost::getNever(ShouldInline.getFailureReason()); - if (ShouldInline.isSuccess() && CA.getCost() >= CA.getThreshold()) - return InlineCost::getAlways("empty function"); + if (CA.wasDecidedByCostThreshold()) + return InlineCost::get(CA.getCost(), CA.getThreshold()); - return llvm::InlineCost::get(CA.getCost(), CA.getThreshold()); + // No details on how the decision was made, simply return always or never. + return ShouldInline.isSuccess() + ? InlineCost::getAlways("empty function") + : InlineCost::getNever(ShouldInline.getFailureReason()); } InlineResult llvm::isInlineViable(Function &F) { @@ -3028,7 +3127,8 @@ InlineCostAnnotationPrinterPass::run(Function &F, ICCA.analyze(); OS << " Analyzing call of " << CalledFunction->getName() << "... (caller:" << CI->getCaller()->getName() << ")\n"; - ICCA.print(); + ICCA.print(OS); + OS << "\n"; } } } diff --git a/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp b/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp index 3c90e82fb952..a2e231e2d0f4 100644 --- a/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp +++ b/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp @@ -1,9 +1,8 @@ //===- InlineSizeEstimatorAnalysis.cpp - IR to native size from ML model --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp index 7d1e630e6e80..9fee57c54b85 100644 --- a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp +++ b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp @@ -19,11 +19,15 @@ #include "llvm/Analysis/InstructionPrecedenceTracking.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/ADT/Statistic.h" #include "llvm/IR/PatternMatch.h" #include "llvm/Support/CommandLine.h" using namespace llvm; +#define DEBUG_TYPE "ipt" +STATISTIC(NumInstScanned, "Number of insts scanned while updating ibt"); + #ifndef NDEBUG static cl::opt<bool> ExpensiveAsserts( "ipt-expensive-asserts", @@ -64,11 +68,13 @@ bool InstructionPrecedenceTracking::isPreceededBySpecialInstruction( void InstructionPrecedenceTracking::fill(const BasicBlock *BB) { FirstSpecialInsts.erase(BB); - for (auto &I : *BB) + for (auto &I : *BB) { + NumInstScanned++; if (isSpecialInstruction(&I)) { FirstSpecialInsts[BB] = &I; return; } + } // Mark this block as having no special instructions. FirstSpecialInsts[BB] = nullptr; @@ -107,8 +113,10 @@ void InstructionPrecedenceTracking::insertInstructionTo(const Instruction *Inst, } void InstructionPrecedenceTracking::removeInstruction(const Instruction *Inst) { - if (isSpecialInstruction(Inst)) - FirstSpecialInsts.erase(Inst->getParent()); + auto *BB = Inst->getParent(); + assert(BB && "must be called before instruction is actually removed"); + if (FirstSpecialInsts.count(BB) && FirstSpecialInsts[BB] == Inst) + FirstSpecialInsts.erase(BB); } void InstructionPrecedenceTracking::removeUsersOf(const Instruction *Inst) { diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 23083bc8178e..864eeea4f8bf 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -70,8 +70,8 @@ static Value *SimplifyOrInst(Value *, Value *, const SimplifyQuery &, unsigned); static Value *SimplifyXorInst(Value *, Value *, const SimplifyQuery &, unsigned); static Value *SimplifyCastInst(unsigned, Value *, Type *, const SimplifyQuery &, unsigned); -static Value *SimplifyGEPInst(Type *, ArrayRef<Value *>, const SimplifyQuery &, - unsigned); +static Value *SimplifyGEPInst(Type *, ArrayRef<Value *>, bool, + const SimplifyQuery &, unsigned); static Value *SimplifySelectInst(Value *, Value *, Value *, const SimplifyQuery &, unsigned); @@ -698,13 +698,12 @@ static Constant *stripAndComputeConstantOffsets(const DataLayout &DL, Value *&V, bool AllowNonInbounds = false) { assert(V->getType()->isPtrOrPtrVectorTy()); - Type *IntIdxTy = DL.getIndexType(V->getType())->getScalarType(); - APInt Offset = APInt::getNullValue(IntIdxTy->getIntegerBitWidth()); + APInt Offset = APInt::getZero(DL.getIndexTypeSizeInBits(V->getType())); V = V->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds); // As that strip may trace through `addrspacecast`, need to sext or trunc // the offset calculated. - IntIdxTy = DL.getIndexType(V->getType())->getScalarType(); + Type *IntIdxTy = DL.getIndexType(V->getType())->getScalarType(); Offset = Offset.sextOrTrunc(IntIdxTy->getIntegerBitWidth()); Constant *OffsetIntPtr = ConstantInt::get(IntIdxTy, Offset); @@ -1407,8 +1406,7 @@ static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, match(Op0, m_c_Or(m_NUWShl(m_Value(X), m_APInt(ShLAmt)), m_Value(Y))) && *ShRAmt == *ShLAmt) { const KnownBits YKnown = computeKnownBits(Y, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); - const unsigned Width = Op0->getType()->getScalarSizeInBits(); - const unsigned EffWidthY = Width - YKnown.countMinLeadingZeros(); + const unsigned EffWidthY = YKnown.countMaxActiveBits(); if (ShRAmt->uge(EffWidthY)) return X; } @@ -1429,9 +1427,11 @@ static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, MaxRecurse)) return V; - // all ones >>a X -> -1 + // -1 >>a X --> -1 + // (-1 << X) a>> X --> -1 // Do not return Op0 because it may contain undef elements if it's a vector. - if (match(Op0, m_AllOnes())) + if (match(Op0, m_AllOnes()) || + match(Op0, m_Shl(m_AllOnes(), m_Specific(Op1)))) return Constant::getAllOnesValue(Op0->getType()); // (X << A) >> A -> X @@ -1765,7 +1765,7 @@ static Value *simplifyAndOrOfICmpsWithLimitConst(ICmpInst *Cmp0, ICmpInst *Cmp1, if (match(Cmp0->getOperand(1), m_APInt(C))) MinMaxC = HasNotOp ? ~*C : *C; else if (isa<ConstantPointerNull>(Cmp0->getOperand(1))) - MinMaxC = APInt::getNullValue(8); + MinMaxC = APInt::getZero(8); else return nullptr; @@ -2040,24 +2040,32 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, if (match(Op1, m_c_Or(m_Specific(Op0), m_Value()))) return Op0; + // (X | Y) & (X | ~Y) --> X (commuted 8 ways) + Value *X, *Y; + if (match(Op0, m_c_Or(m_Value(X), m_Not(m_Value(Y)))) && + match(Op1, m_c_Or(m_Deferred(X), m_Deferred(Y)))) + return X; + if (match(Op1, m_c_Or(m_Value(X), m_Not(m_Value(Y)))) && + match(Op0, m_c_Or(m_Deferred(X), m_Deferred(Y)))) + return X; + if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::And)) return V; // A mask that only clears known zeros of a shifted value is a no-op. - Value *X; const APInt *Mask; const APInt *ShAmt; if (match(Op1, m_APInt(Mask))) { // If all bits in the inverted and shifted mask are clear: // and (shl X, ShAmt), Mask --> shl X, ShAmt if (match(Op0, m_Shl(m_Value(X), m_APInt(ShAmt))) && - (~(*Mask)).lshr(*ShAmt).isNullValue()) + (~(*Mask)).lshr(*ShAmt).isZero()) return Op0; // If all bits in the inverted and shifted mask are clear: // and (lshr X, ShAmt), Mask --> lshr X, ShAmt if (match(Op0, m_LShr(m_Value(X), m_APInt(ShAmt))) && - (~(*Mask)).shl(*ShAmt).isNullValue()) + (~(*Mask)).shl(*ShAmt).isZero()) return Op0; } @@ -2141,7 +2149,7 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, // if Mask = ((1 << effective_width_of(X)) - 1) << A // SimplifyDemandedBits in InstCombine can optimize the general case. // This pattern aims to help other passes for a common case. - Value *Y, *XShifted; + Value *XShifted; if (match(Op1, m_APInt(Mask)) && match(Op0, m_c_Or(m_CombineAnd(m_NUWShl(m_Value(X), m_APInt(ShAmt)), m_Value(XShifted)), @@ -2149,11 +2157,11 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, const unsigned Width = Op0->getType()->getScalarSizeInBits(); const unsigned ShftCnt = ShAmt->getLimitedValue(Width); const KnownBits YKnown = computeKnownBits(Y, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); - const unsigned EffWidthY = Width - YKnown.countMinLeadingZeros(); + const unsigned EffWidthY = YKnown.countMaxActiveBits(); if (EffWidthY <= ShftCnt) { const KnownBits XKnown = computeKnownBits(X, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); - const unsigned EffWidthX = Width - XKnown.countMinLeadingZeros(); + const unsigned EffWidthX = XKnown.countMaxActiveBits(); const APInt EffBitsY = APInt::getLowBitsSet(Width, EffWidthY); const APInt EffBitsX = APInt::getLowBitsSet(Width, EffWidthX) << ShftCnt; // If the mask is extracting all bits from X or Y as is, we can skip @@ -2257,6 +2265,19 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B))))) return Op0; + // (A | B) | (A ^ B) --> A | B + // (B | A) | (A ^ B) --> B | A + if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && + match(Op0, m_c_Or(m_Specific(A), m_Specific(B)))) + return Op0; + + // Commute the outer 'or' operands. + // (A ^ B) | (A | B) --> A | B + // (A ^ B) | (B | A) --> B | A + if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && + match(Op1, m_c_Or(m_Specific(A), m_Specific(B)))) + return Op1; + // (~A & B) | ~(A | B) --> ~A // (~A & B) | ~(B | A) --> ~A // (B & ~A) | ~(A | B) --> ~A @@ -2276,6 +2297,23 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, match(Op0, m_Not(m_c_Or(m_Specific(A), m_Specific(B))))) return NotA; + // Rotated -1 is still -1: + // (-1 << X) | (-1 >> (C - X)) --> -1 + // (-1 >> X) | (-1 << (C - X)) --> -1 + // ...with C <= bitwidth (and commuted variants). + Value *X, *Y; + if ((match(Op0, m_Shl(m_AllOnes(), m_Value(X))) && + match(Op1, m_LShr(m_AllOnes(), m_Value(Y)))) || + (match(Op1, m_Shl(m_AllOnes(), m_Value(X))) && + match(Op0, m_LShr(m_AllOnes(), m_Value(Y))))) { + const APInt *C; + if ((match(X, m_Sub(m_APInt(C), m_Specific(Y))) || + match(Y, m_Sub(m_APInt(C), m_Specific(X)))) && + C->ule(X->getType()->getScalarSizeInBits())) { + return ConstantInt::getAllOnesValue(X->getType()); + } + } + if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false)) return V; @@ -3090,7 +3128,7 @@ static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS, // - C isn't zero. if (Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(LBO)) || Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(LBO)) || - match(LHS, m_Shl(m_One(), m_Value())) || !C->isNullValue()) { + match(LHS, m_Shl(m_One(), m_Value())) || !C->isZero()) { if (Pred == ICmpInst::ICMP_EQ) return ConstantInt::getFalse(GetCompareTy(RHS)); if (Pred == ICmpInst::ICMP_NE) @@ -3640,30 +3678,6 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, CRHS->getPointerOperand(), Q)) return C; - if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) { - if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) { - if (GLHS->getPointerOperand() == GRHS->getPointerOperand() && - GLHS->hasAllConstantIndices() && GRHS->hasAllConstantIndices() && - (ICmpInst::isEquality(Pred) || - (GLHS->isInBounds() && GRHS->isInBounds() && - Pred == ICmpInst::getSignedPredicate(Pred)))) { - // The bases are equal and the indices are constant. Build a constant - // expression GEP with the same indices and a null base pointer to see - // what constant folding can make out of it. - Constant *Null = Constant::getNullValue(GLHS->getPointerOperandType()); - SmallVector<Value *, 4> IndicesLHS(GLHS->indices()); - Constant *NewLHS = ConstantExpr::getGetElementPtr( - GLHS->getSourceElementType(), Null, IndicesLHS); - - SmallVector<Value *, 4> IndicesRHS(GRHS->idx_begin(), GRHS->idx_end()); - Constant *NewRHS = ConstantExpr::getGetElementPtr( - GLHS->getSourceElementType(), Null, IndicesRHS); - Constant *NewICmp = ConstantExpr::getICmp(Pred, NewLHS, NewRHS); - return ConstantFoldConstant(NewICmp, Q.DL); - } - } - } - // If the comparison is with the result of a select instruction, check whether // comparing with either branch of the select always yields the same value. if (isa<SelectInst>(LHS) || isa<SelectInst>(RHS)) @@ -3966,7 +3980,8 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) return PreventSelfSimplify(SimplifyGEPInst(GEP->getSourceElementType(), - NewOps, Q, MaxRecurse - 1)); + NewOps, GEP->isInBounds(), Q, + MaxRecurse - 1)); if (isa<SelectInst>(I)) return PreventSelfSimplify( @@ -4080,6 +4095,22 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal, std::swap(TrueVal, FalseVal); } + // Check for integer min/max with a limit constant: + // X > MIN_INT ? X : MIN_INT --> X + // X < MAX_INT ? X : MAX_INT --> X + if (TrueVal->getType()->isIntOrIntVectorTy()) { + Value *X, *Y; + SelectPatternFlavor SPF = + matchDecomposedSelectPattern(cast<ICmpInst>(CondVal), TrueVal, FalseVal, + X, Y).Flavor; + if (SelectPatternResult::isMinOrMax(SPF) && Pred == getMinMaxPred(SPF)) { + APInt LimitC = getMinMaxLimit(getInverseMinMaxFlavor(SPF), + X->getType()->getScalarSizeInBits()); + if (match(Y, m_SpecificInt(LimitC))) + return X; + } + } + if (Pred == ICmpInst::ICMP_EQ && match(CmpRHS, m_Zero())) { Value *X; const APInt *Y; @@ -4210,14 +4241,27 @@ static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, return FalseVal; } - // select i1 Cond, i1 true, i1 false --> i1 Cond assert(Cond->getType()->isIntOrIntVectorTy(1) && "Select must have bool or bool vector condition"); assert(TrueVal->getType() == FalseVal->getType() && "Select must have same types for true/false ops"); - if (Cond->getType() == TrueVal->getType() && - match(TrueVal, m_One()) && match(FalseVal, m_ZeroInt())) - return Cond; + + if (Cond->getType() == TrueVal->getType()) { + // select i1 Cond, i1 true, i1 false --> i1 Cond + if (match(TrueVal, m_One()) && match(FalseVal, m_ZeroInt())) + return Cond; + + // (X || Y) && (X || !Y) --> X (commuted 8 ways) + Value *X, *Y; + if (match(FalseVal, m_ZeroInt())) { + if (match(Cond, m_c_LogicalOr(m_Value(X), m_Not(m_Value(Y)))) && + match(TrueVal, m_c_LogicalOr(m_Specific(X), m_Specific(Y)))) + return X; + if (match(TrueVal, m_c_LogicalOr(m_Value(X), m_Not(m_Value(Y)))) && + match(Cond, m_c_LogicalOr(m_Specific(X), m_Specific(Y)))) + return X; + } + } // select ?, X, X -> X if (TrueVal == FalseVal) @@ -4295,7 +4339,7 @@ Value *llvm::SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, /// Given operands for an GetElementPtrInst, see if we can fold the result. /// If not, this returns null. -static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, +static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, bool InBounds, const SimplifyQuery &Q, unsigned) { // The type of the GEP pointer operand. unsigned AS = @@ -4396,14 +4440,14 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, // gep (gep V, C), (sub 0, V) -> C if (match(Ops.back(), m_Sub(m_Zero(), m_PtrToInt(m_Specific(StrippedBasePtr)))) && - !BasePtrOffset.isNullValue()) { + !BasePtrOffset.isZero()) { auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset); return ConstantExpr::getIntToPtr(CI, GEPTy); } // gep (gep V, C), (xor V, -1) -> C-1 if (match(Ops.back(), m_Xor(m_PtrToInt(m_Specific(StrippedBasePtr)), m_AllOnes())) && - !BasePtrOffset.isOneValue()) { + !BasePtrOffset.isOne()) { auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset - 1); return ConstantExpr::getIntToPtr(CI, GEPTy); } @@ -4415,13 +4459,13 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, return nullptr; auto *CE = ConstantExpr::getGetElementPtr(SrcTy, cast<Constant>(Ops[0]), - Ops.slice(1)); + Ops.slice(1), InBounds); return ConstantFoldConstant(CE, Q.DL); } -Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, +Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, bool InBounds, const SimplifyQuery &Q) { - return ::SimplifyGEPInst(SrcTy, Ops, Q, RecursionLimit); + return ::SimplifyGEPInst(SrcTy, Ops, InBounds, Q, RecursionLimit); } /// Given operands for an InsertValueInst, see if we can fold the result. @@ -4891,6 +4935,11 @@ static Constant *simplifyFPOp(ArrayRef<Value *> Ops, FastMathFlags FMF, return nullptr; } +// TODO: Move this out to a header file: +static inline bool canIgnoreSNaN(fp::ExceptionBehavior EB, FastMathFlags FMF) { + return (EB == fp::ebIgnore || FMF.noNaNs()); +} + /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. static Value * @@ -4905,17 +4954,25 @@ SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; - if (!isDefaultFPEnvironment(ExBehavior, Rounding)) - return nullptr; - // fadd X, -0 ==> X - if (match(Op1, m_NegZeroFP())) - return Op0; + // With strict/constrained FP, we have these possible edge cases that do + // not simplify to Op0: + // fadd SNaN, -0.0 --> QNaN + // fadd +0.0, -0.0 --> -0.0 (but only with round toward negative) + if (canIgnoreSNaN(ExBehavior, FMF) && + (!canRoundingModeBe(Rounding, RoundingMode::TowardNegative) || + FMF.noSignedZeros())) + if (match(Op1, m_NegZeroFP())) + return Op0; // fadd X, 0 ==> X, when we know X is not -0 - if (match(Op1, m_PosZeroFP()) && - (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) - return Op0; + if (canIgnoreSNaN(ExBehavior, FMF)) + if (match(Op1, m_PosZeroFP()) && + (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) + return Op0; + + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; // With nnan: -X + X --> 0.0 (and commuted variant) // We don't have to explicitly exclude infinities (ninf): INF + -INF == NaN. @@ -5457,6 +5514,9 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0, if (match(Op0, m_Intrinsic<Intrinsic::experimental_vector_reverse>(m_Value(X)))) return X; + // experimental.vector.reverse(splat(X)) -> splat(X) + if (isSplatValue(Op0)) + return Op0; break; default: break; @@ -5772,13 +5832,32 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) { - // Intrinsics with no operands have some kind of side effect. Don't simplify. - unsigned NumOperands = Call->getNumArgOperands(); - if (!NumOperands) - return nullptr; - + unsigned NumOperands = Call->arg_size(); Function *F = cast<Function>(Call->getCalledFunction()); Intrinsic::ID IID = F->getIntrinsicID(); + + // Most of the intrinsics with no operands have some kind of side effect. + // Don't simplify. + if (!NumOperands) { + switch (IID) { + case Intrinsic::vscale: { + // Call may not be inserted into the IR yet at point of calling simplify. + if (!Call->getParent() || !Call->getParent()->getParent()) + return nullptr; + auto Attr = Call->getFunction()->getFnAttribute(Attribute::VScaleRange); + if (!Attr.isValid()) + return nullptr; + unsigned VScaleMin, VScaleMax; + std::tie(VScaleMin, VScaleMax) = Attr.getVScaleRangeArgs(); + if (VScaleMin == VScaleMax && VScaleMax != 0) + return ConstantInt::get(F->getReturnType(), VScaleMin); + return nullptr; + } + default: + return nullptr; + } + } + if (NumOperands == 1) return simplifyUnaryIntrinsic(F, Call->getArgOperand(0), Q); @@ -5814,9 +5893,18 @@ static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) { if (match(ShAmtArg, m_APInt(ShAmtC))) { // If there's effectively no shift, return the 1st arg or 2nd arg. APInt BitWidth = APInt(ShAmtC->getBitWidth(), ShAmtC->getBitWidth()); - if (ShAmtC->urem(BitWidth).isNullValue()) + if (ShAmtC->urem(BitWidth).isZero()) return Call->getArgOperand(IID == Intrinsic::fshl ? 0 : 1); } + + // Rotating zero by anything is zero. + if (match(Op0, m_Zero()) && match(Op1, m_Zero())) + return ConstantInt::getNullValue(F->getReturnType()); + + // Rotating -1 by anything is -1. + if (match(Op0, m_AllOnes()) && match(Op1, m_AllOnes())) + return ConstantInt::getAllOnesValue(F->getReturnType()); + return nullptr; } case Intrinsic::experimental_constrained_fma: { @@ -5939,7 +6027,7 @@ static Value *tryConstantFoldCall(CallBase *Call, const SimplifyQuery &Q) { return nullptr; SmallVector<Constant *, 4> ConstantArgs; - unsigned NumArgs = Call->getNumArgOperands(); + unsigned NumArgs = Call->arg_size(); ConstantArgs.reserve(NumArgs); for (auto &Arg : Call->args()) { Constant *C = dyn_cast<Constant>(&Arg); @@ -5990,73 +6078,27 @@ Value *llvm::SimplifyFreezeInst(Value *Op0, const SimplifyQuery &Q) { return ::SimplifyFreezeInst(Op0, Q); } -static Constant *ConstructLoadOperandConstant(Value *Op) { - SmallVector<Value *, 4> Worklist; - // Invalid IR in unreachable code may contain self-referential values. Don't infinitely loop. - SmallPtrSet<Value *, 4> Visited; - Worklist.push_back(Op); - while (true) { - Value *CurOp = Worklist.back(); - if (!Visited.insert(CurOp).second) - return nullptr; - if (isa<Constant>(CurOp)) - break; - if (auto *BC = dyn_cast<BitCastOperator>(CurOp)) { - Worklist.push_back(BC->getOperand(0)); - } else if (auto *GEP = dyn_cast<GEPOperator>(CurOp)) { - for (unsigned I = 1; I != GEP->getNumOperands(); ++I) { - if (!isa<Constant>(GEP->getOperand(I))) - return nullptr; - } - Worklist.push_back(GEP->getOperand(0)); - } else if (auto *II = dyn_cast<IntrinsicInst>(CurOp)) { - if (II->isLaunderOrStripInvariantGroup()) - Worklist.push_back(II->getOperand(0)); - else - return nullptr; - } else { - return nullptr; - } - } - - Constant *NewOp = cast<Constant>(Worklist.pop_back_val()); - while (!Worklist.empty()) { - Value *CurOp = Worklist.pop_back_val(); - if (isa<BitCastOperator>(CurOp)) { - NewOp = ConstantExpr::getBitCast(NewOp, CurOp->getType()); - } else if (auto *GEP = dyn_cast<GEPOperator>(CurOp)) { - SmallVector<Constant *> Idxs; - Idxs.reserve(GEP->getNumOperands() - 1); - for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I) { - Idxs.push_back(cast<Constant>(GEP->getOperand(I))); - } - NewOp = ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), NewOp, - Idxs, GEP->isInBounds(), - GEP->getInRangeIndex()); - } else { - assert(isa<IntrinsicInst>(CurOp) && - cast<IntrinsicInst>(CurOp)->isLaunderOrStripInvariantGroup() && - "expected invariant group intrinsic"); - NewOp = ConstantExpr::getBitCast(NewOp, CurOp->getType()); - } - } - return NewOp; -} - static Value *SimplifyLoadInst(LoadInst *LI, Value *PtrOp, const SimplifyQuery &Q) { if (LI->isVolatile()) return nullptr; - // Try to make the load operand a constant, specifically handle - // invariant.group intrinsics. + APInt Offset(Q.DL.getIndexTypeSizeInBits(PtrOp->getType()), 0); auto *PtrOpC = dyn_cast<Constant>(PtrOp); - if (!PtrOpC) - PtrOpC = ConstructLoadOperandConstant(PtrOp); + // Try to convert operand into a constant by stripping offsets while looking + // through invariant.group intrinsics. Don't bother if the underlying object + // is not constant, as calculating GEP offsets is expensive. + if (!PtrOpC && isa<Constant>(getUnderlyingObject(PtrOp))) { + PtrOp = PtrOp->stripAndAccumulateConstantOffsets( + Q.DL, Offset, /* AllowNonInbounts */ true, + /* AllowInvariantGroup */ true); + // Index size may have changed due to address space casts. + Offset = Offset.sextOrTrunc(Q.DL.getIndexTypeSizeInBits(PtrOp->getType())); + PtrOpC = dyn_cast<Constant>(PtrOp); + } if (PtrOpC) - return ConstantFoldLoadFromConstPtr(PtrOpC, LI->getType(), Q.DL); - + return ConstantFoldLoadFromConstPtr(PtrOpC, LI->getType(), Offset, Q.DL); return nullptr; } @@ -6156,8 +6198,9 @@ static Value *simplifyInstructionWithOperands(Instruction *I, Result = SimplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q); break; case Instruction::GetElementPtr: { - Result = SimplifyGEPInst(cast<GetElementPtrInst>(I)->getSourceElementType(), - NewOps, Q); + auto *GEPI = cast<GetElementPtrInst>(I); + Result = SimplifyGEPInst(GEPI->getSourceElementType(), NewOps, + GEPI->isInBounds(), Q); break; } case Instruction::InsertValue: { diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp index 8f87552fca1f..0007c54b16d0 100644 --- a/llvm/lib/Analysis/LazyCallGraph.cpp +++ b/llvm/lib/Analysis/LazyCallGraph.cpp @@ -220,8 +220,7 @@ bool LazyCallGraph::invalidate(Module &, const PreservedAnalyses &PA, // Check whether the analysis, all analyses on functions, or the function's // CFG have been preserved. auto PAC = PA.getChecker<llvm::LazyCallGraphAnalysis>(); - return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>() || - PAC.preservedSet<CFGAnalyses>()); + return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>()); } LazyCallGraph &LazyCallGraph::operator=(LazyCallGraph &&G) { @@ -1962,6 +1961,29 @@ void LazyCallGraph::buildRefSCCs() { }); } +void LazyCallGraph::visitReferences(SmallVectorImpl<Constant *> &Worklist, + SmallPtrSetImpl<Constant *> &Visited, + function_ref<void(Function &)> Callback) { + while (!Worklist.empty()) { + Constant *C = Worklist.pop_back_val(); + + if (Function *F = dyn_cast<Function>(C)) { + if (!F->isDeclaration()) + Callback(*F); + continue; + } + + // blockaddresses are weird and don't participate in the call graph anyway, + // skip them. + if (isa<BlockAddress>(C)) + continue; + + for (Value *Op : C->operand_values()) + if (Visited.insert(cast<Constant>(Op)).second) + Worklist.push_back(cast<Constant>(Op)); + } +} + AnalysisKey LazyCallGraphAnalysis::Key; LazyCallGraphPrinterPass::LazyCallGraphPrinterPass(raw_ostream &OS) : OS(OS) {} diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 1dababafb8a6..50fa169c2081 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -126,7 +126,7 @@ static ValueLatticeElement intersect(const ValueLatticeElement &A, // Note: An empty range is implicitly converted to unknown or undef depending // on MayIncludeUndef internally. return ValueLatticeElement::getRange( - std::move(Range), /*MayIncludeUndef=*/A.isConstantRangeIncludingUndef() | + std::move(Range), /*MayIncludeUndef=*/A.isConstantRangeIncludingUndef() || B.isConstantRangeIncludingUndef()); } @@ -832,7 +832,7 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueSelect( }; }(); return ValueLatticeElement::getRange( - ResultCR, TrueVal.isConstantRangeIncludingUndef() | + ResultCR, TrueVal.isConstantRangeIncludingUndef() || FalseVal.isConstantRangeIncludingUndef()); } @@ -846,7 +846,7 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueSelect( } if (SPR.Flavor == SPF_NABS) { - ConstantRange Zero(APInt::getNullValue(TrueCR.getBitWidth())); + ConstantRange Zero(APInt::getZero(TrueCR.getBitWidth())); if (LHS == SI->getTrueValue()) return ValueLatticeElement::getRange( Zero.sub(TrueCR.abs()), FalseVal.isConstantRangeIncludingUndef()); @@ -1117,12 +1117,11 @@ static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI, } // If (Val & Mask) != 0 then the value must be larger than the lowest set // bit of Mask. - if (EdgePred == ICmpInst::ICMP_NE && !Mask->isNullValue() && - C->isNullValue()) { + if (EdgePred == ICmpInst::ICMP_NE && !Mask->isZero() && C->isZero()) { unsigned BitWidth = Ty->getIntegerBitWidth(); return ValueLatticeElement::getRange(ConstantRange::getNonEmpty( APInt::getOneBitSet(BitWidth, Mask->countTrailingZeros()), - APInt::getNullValue(BitWidth))); + APInt::getZero(BitWidth))); } } @@ -1780,62 +1779,62 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C, // We could consider extending this to search further backwards through the // CFG and/or value graph, but there are non-obvious compile time vs quality // tradeoffs. - if (CxtI) { - BasicBlock *BB = CxtI->getParent(); + BasicBlock *BB = CxtI->getParent(); - // Function entry or an unreachable block. Bail to avoid confusing - // analysis below. - pred_iterator PI = pred_begin(BB), PE = pred_end(BB); - if (PI == PE) - return Unknown; + // Function entry or an unreachable block. Bail to avoid confusing + // analysis below. + pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + if (PI == PE) + return Unknown; - // If V is a PHI node in the same block as the context, we need to ask - // questions about the predicate as applied to the incoming value along - // each edge. This is useful for eliminating cases where the predicate is - // known along all incoming edges. - if (auto *PHI = dyn_cast<PHINode>(V)) - if (PHI->getParent() == BB) { - Tristate Baseline = Unknown; - for (unsigned i = 0, e = PHI->getNumIncomingValues(); i < e; i++) { - Value *Incoming = PHI->getIncomingValue(i); - BasicBlock *PredBB = PHI->getIncomingBlock(i); - // Note that PredBB may be BB itself. - Tristate Result = getPredicateOnEdge(Pred, Incoming, C, PredBB, BB, - CxtI); + // If V is a PHI node in the same block as the context, we need to ask + // questions about the predicate as applied to the incoming value along + // each edge. This is useful for eliminating cases where the predicate is + // known along all incoming edges. + if (auto *PHI = dyn_cast<PHINode>(V)) + if (PHI->getParent() == BB) { + Tristate Baseline = Unknown; + for (unsigned i = 0, e = PHI->getNumIncomingValues(); i < e; i++) { + Value *Incoming = PHI->getIncomingValue(i); + BasicBlock *PredBB = PHI->getIncomingBlock(i); + // Note that PredBB may be BB itself. + Tristate Result = + getPredicateOnEdge(Pred, Incoming, C, PredBB, BB, CxtI); - // Keep going as long as we've seen a consistent known result for - // all inputs. - Baseline = (i == 0) ? Result /* First iteration */ - : (Baseline == Result ? Baseline : Unknown); /* All others */ - if (Baseline == Unknown) - break; - } - if (Baseline != Unknown) - return Baseline; + // Keep going as long as we've seen a consistent known result for + // all inputs. + Baseline = (i == 0) ? Result /* First iteration */ + : (Baseline == Result ? Baseline + : Unknown); /* All others */ + if (Baseline == Unknown) + break; } + if (Baseline != Unknown) + return Baseline; + } - // For a comparison where the V is outside this block, it's possible - // that we've branched on it before. Look to see if the value is known - // on all incoming edges. - if (!isa<Instruction>(V) || - cast<Instruction>(V)->getParent() != BB) { - // For predecessor edge, determine if the comparison is true or false - // on that edge. If they're all true or all false, we can conclude - // the value of the comparison in this block. - Tristate Baseline = getPredicateOnEdge(Pred, V, C, *PI, BB, CxtI); - if (Baseline != Unknown) { - // Check that all remaining incoming values match the first one. - while (++PI != PE) { - Tristate Ret = getPredicateOnEdge(Pred, V, C, *PI, BB, CxtI); - if (Ret != Baseline) break; - } - // If we terminated early, then one of the values didn't match. - if (PI == PE) { - return Baseline; - } + // For a comparison where the V is outside this block, it's possible + // that we've branched on it before. Look to see if the value is known + // on all incoming edges. + if (!isa<Instruction>(V) || cast<Instruction>(V)->getParent() != BB) { + // For predecessor edge, determine if the comparison is true or false + // on that edge. If they're all true or all false, we can conclude + // the value of the comparison in this block. + Tristate Baseline = getPredicateOnEdge(Pred, V, C, *PI, BB, CxtI); + if (Baseline != Unknown) { + // Check that all remaining incoming values match the first one. + while (++PI != PE) { + Tristate Ret = getPredicateOnEdge(Pred, V, C, *PI, BB, CxtI); + if (Ret != Baseline) + break; + } + // If we terminated early, then one of the values didn't match. + if (PI == PE) { + return Baseline; } } } + return Unknown; } diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp index 4de5e1e06c7e..f9a7a5bdf434 100644 --- a/llvm/lib/Analysis/Lint.cpp +++ b/llvm/lib/Analysis/Lint.cpp @@ -235,7 +235,7 @@ void Lint::visitCallBase(CallBase &I) { for (auto BI = I.arg_begin(); BI != AE; ++BI, ++ArgNo) { // Skip ByVal arguments since they will be memcpy'd to the callee's // stack so we're not really passing the pointer anyway. - if (PAL.hasParamAttribute(ArgNo, Attribute::ByVal)) + if (PAL.hasParamAttr(ArgNo, Attribute::ByVal)) continue; // If both arguments are readonly, they have no dependence. if (Formal->onlyReadsMemory() && I.onlyReadsMemory(ArgNo)) @@ -268,7 +268,7 @@ void Lint::visitCallBase(CallBase &I) { for (Value *Arg : I.args()) { // Skip ByVal arguments since they will be memcpy'd to the callee's // stack anyway. - if (PAL.hasParamAttribute(ArgNo++, Attribute::ByVal)) + if (PAL.hasParamAttr(ArgNo++, Attribute::ByVal)) continue; Value *Obj = findValue(Arg, /*OffsetOk=*/true); Assert(!isa<AllocaInst>(Obj), @@ -715,6 +715,7 @@ PreservedAnalyses LintPass::run(Function &F, FunctionAnalysisManager &AM) { return PreservedAnalyses::all(); } +namespace { class LintLegacyPass : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid @@ -733,6 +734,7 @@ public: } void print(raw_ostream &O, const Module *M) const override {} }; +} // namespace char LintLegacyPass::ID = 0; INITIALIZE_PASS_BEGIN(LintLegacyPass, "lint", "Statically lint-checks LLVM IR", diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 1c55f485aa76..0fbf1db0685d 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -147,7 +147,7 @@ static bool isDereferenceableAndAlignedPointer( Alignment, Size, DL, CtxI, DT, TLI, Visited, MaxDepth); - if (const AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(V)) + if (const AddrSpaceCastOperator *ASC = dyn_cast<AddrSpaceCastOperator>(V)) return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Alignment, Size, DL, CtxI, DT, TLI, Visited, MaxDepth); @@ -451,8 +451,8 @@ static bool areNonOverlapSameBaseLoadAndStore(const Value *LoadPtr, const Value *StorePtr, Type *StoreTy, const DataLayout &DL) { - APInt LoadOffset(DL.getTypeSizeInBits(LoadPtr->getType()), 0); - APInt StoreOffset(DL.getTypeSizeInBits(StorePtr->getType()), 0); + APInt LoadOffset(DL.getIndexTypeSizeInBits(LoadPtr->getType()), 0); + APInt StoreOffset(DL.getIndexTypeSizeInBits(StorePtr->getType()), 0); const Value *LoadBase = LoadPtr->stripAndAccumulateConstantOffsets( DL, LoadOffset, /* AllowNonInbounds */ false); const Value *StoreBase = StorePtr->stripAndAccumulateConstantOffsets( @@ -511,8 +511,11 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr, if (CastInst::isBitOrNoopPointerCastable(Val->getType(), AccessTy, DL)) return Val; - if (auto *C = dyn_cast<Constant>(Val)) - return ConstantFoldLoadThroughBitcast(C, AccessTy, DL); + TypeSize StoreSize = DL.getTypeStoreSize(Val->getType()); + TypeSize LoadSize = DL.getTypeStoreSize(AccessTy); + if (TypeSize::isKnownLE(LoadSize, StoreSize)) + if (auto *C = dyn_cast<Constant>(Val)) + return ConstantFoldLoadFromConst(C, AccessTy, DL); } return nullptr; diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index a239928ecf38..f9bd7167317f 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -142,13 +142,12 @@ Value *llvm::stripIntegerCast(Value *V) { const SCEV *llvm::replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE, const ValueToValueMap &PtrToStride, - Value *Ptr, Value *OrigPtr) { + Value *Ptr) { const SCEV *OrigSCEV = PSE.getSCEV(Ptr); // If there is an entry in the map return the SCEV of the pointer with the // symbolic stride replaced by one. - ValueToValueMap::const_iterator SI = - PtrToStride.find(OrigPtr ? OrigPtr : Ptr); + ValueToValueMap::const_iterator SI = PtrToStride.find(Ptr); if (SI == PtrToStride.end()) // For a non-symbolic stride, just return the original expression. return OrigSCEV; @@ -659,7 +658,8 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, if (PSE.getSE()->isLoopInvariant(PtrScev, L)) return true; - int64_t Stride = getPtrStride(PSE, Ptr, L, Strides); + Type *AccessTy = Ptr->getType()->getPointerElementType(); + int64_t Stride = getPtrStride(PSE, AccessTy, Ptr, L, Strides); if (Stride == 1 || PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW)) return true; @@ -1026,15 +1026,17 @@ static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR, } /// Check whether the access through \p Ptr has a constant stride. -int64_t llvm::getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, - const Loop *Lp, const ValueToValueMap &StridesMap, - bool Assume, bool ShouldCheckWrap) { +int64_t llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, + Value *Ptr, const Loop *Lp, + const ValueToValueMap &StridesMap, bool Assume, + bool ShouldCheckWrap) { Type *Ty = Ptr->getType(); assert(Ty->isPointerTy() && "Unexpected non-ptr"); + unsigned AddrSpace = Ty->getPointerAddressSpace(); - // Make sure that the pointer does not point to aggregate types. - auto *PtrTy = cast<PointerType>(Ty); - if (PtrTy->getElementType()->isAggregateType()) { + // Make sure we're not accessing an aggregate type. + // TODO: Why? This doesn't make any sense. + if (AccessTy->isAggregateType()) { LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not a pointer to a scalar type" << *Ptr << "\n"); return 0; @@ -1071,8 +1073,7 @@ int64_t llvm::getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW) || isNoWrapAddRec(Ptr, AR, PSE, Lp); if (!IsNoWrapAddRec && !IsInBoundsGEP && - NullPointerIsDefined(Lp->getHeader()->getParent(), - PtrTy->getAddressSpace())) { + NullPointerIsDefined(Lp->getHeader()->getParent(), AddrSpace)) { if (Assume) { PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW); IsNoWrapAddRec = true; @@ -1100,7 +1101,7 @@ int64_t llvm::getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, } auto &DL = Lp->getHeader()->getModule()->getDataLayout(); - int64_t Size = DL.getTypeAllocSize(PtrTy->getElementType()); + int64_t Size = DL.getTypeAllocSize(AccessTy); const APInt &APStepVal = C->getAPInt(); // Huge step value - give up. @@ -1120,7 +1121,7 @@ int64_t llvm::getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, // zero we know that this won't happen without triggering undefined behavior. if (!IsNoWrapAddRec && Stride != 1 && Stride != -1 && (IsInBoundsGEP || !NullPointerIsDefined(Lp->getHeader()->getParent(), - PtrTy->getAddressSpace()))) { + AddrSpace))) { if (Assume) { // We can avoid this case by adding a run-time check. LLVM_DEBUG(dbgs() << "LAA: Non unit strided pointer which is not either " @@ -1262,6 +1263,47 @@ bool llvm::isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL, return Diff && *Diff == 1; } +static void visitPointers(Value *StartPtr, const Loop &InnermostLoop, + function_ref<void(Value *)> AddPointer) { + SmallPtrSet<Value *, 8> Visited; + SmallVector<Value *> WorkList; + WorkList.push_back(StartPtr); + + while (!WorkList.empty()) { + Value *Ptr = WorkList.pop_back_val(); + if (!Visited.insert(Ptr).second) + continue; + auto *PN = dyn_cast<PHINode>(Ptr); + // SCEV does not look through non-header PHIs inside the loop. Such phis + // can be analyzed by adding separate accesses for each incoming pointer + // value. + if (PN && InnermostLoop.contains(PN->getParent()) && + PN->getParent() != InnermostLoop.getHeader()) { + for (const Use &Inc : PN->incoming_values()) + WorkList.push_back(Inc); + } else + AddPointer(Ptr); + } +} + +void MemoryDepChecker::addAccess(StoreInst *SI) { + visitPointers(SI->getPointerOperand(), *InnermostLoop, + [this, SI](Value *Ptr) { + Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx); + InstMap.push_back(SI); + ++AccessIdx; + }); +} + +void MemoryDepChecker::addAccess(LoadInst *LI) { + visitPointers(LI->getPointerOperand(), *InnermostLoop, + [this, LI](Value *Ptr) { + Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx); + InstMap.push_back(LI); + ++AccessIdx; + }); +} + MemoryDepChecker::VectorizationSafetyStatus MemoryDepChecker::Dependence::isSafeForVectorization(DepType Type) { switch (Type) { @@ -1478,6 +1520,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx, Value *BPtr = B.getPointer(); bool AIsWrite = A.getInt(); bool BIsWrite = B.getInt(); + Type *ATy = APtr->getType()->getPointerElementType(); + Type *BTy = BPtr->getType()->getPointerElementType(); // Two reads are independent. if (!AIsWrite && !BIsWrite) @@ -1488,8 +1532,10 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx, BPtr->getType()->getPointerAddressSpace()) return Dependence::Unknown; - int64_t StrideAPtr = getPtrStride(PSE, APtr, InnermostLoop, Strides, true); - int64_t StrideBPtr = getPtrStride(PSE, BPtr, InnermostLoop, Strides, true); + int64_t StrideAPtr = + getPtrStride(PSE, ATy, APtr, InnermostLoop, Strides, true); + int64_t StrideBPtr = + getPtrStride(PSE, BTy, BPtr, InnermostLoop, Strides, true); const SCEV *Src = PSE.getSCEV(APtr); const SCEV *Sink = PSE.getSCEV(BPtr); @@ -1498,6 +1544,7 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx, // dependence. if (StrideAPtr < 0) { std::swap(APtr, BPtr); + std::swap(ATy, BTy); std::swap(Src, Sink); std::swap(AIsWrite, BIsWrite); std::swap(AIdx, BIdx); @@ -1519,8 +1566,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx, return Dependence::Unknown; } - Type *ATy = APtr->getType()->getPointerElementType(); - Type *BTy = BPtr->getType()->getPointerElementType(); auto &DL = InnermostLoop->getHeader()->getModule()->getDataLayout(); uint64_t TypeByteSize = DL.getTypeAllocSize(ATy); uint64_t Stride = std::abs(StrideAPtr); @@ -1958,7 +2003,11 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI, if (blockNeedsPredication(ST->getParent(), TheLoop, DT)) Loc.AATags.TBAA = nullptr; - Accesses.addStore(Loc); + visitPointers(const_cast<Value *>(Loc.Ptr), *TheLoop, + [&Accesses, Loc](Value *Ptr) { + MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr); + Accesses.addStore(NewLoc); + }); } } @@ -1982,7 +2031,7 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI, // words may be written to the same address. bool IsReadOnlyPtr = false; if (Seen.insert(Ptr).second || - !getPtrStride(*PSE, Ptr, TheLoop, SymbolicStrides)) { + !getPtrStride(*PSE, LD->getType(), Ptr, TheLoop, SymbolicStrides)) { ++NumReads; IsReadOnlyPtr = true; } @@ -2002,7 +2051,11 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI, if (blockNeedsPredication(LD->getParent(), TheLoop, DT)) Loc.AATags.TBAA = nullptr; - Accesses.addLoad(Loc, IsReadOnlyPtr); + visitPointers(const_cast<Value *>(Loc.Ptr), *TheLoop, + [&Accesses, Loc, IsReadOnlyPtr](Value *Ptr) { + MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr); + Accesses.addLoad(NewLoc, IsReadOnlyPtr); + }); } // If we write (or read-write) to a single destination and there are no diff --git a/llvm/lib/Analysis/LoopCacheAnalysis.cpp b/llvm/lib/Analysis/LoopCacheAnalysis.cpp index 8a613647bbea..7b895d8a5dc2 100644 --- a/llvm/lib/Analysis/LoopCacheAnalysis.cpp +++ b/llvm/lib/Analysis/LoopCacheAnalysis.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Delinearization.h" #include "llvm/Analysis/DependenceAnalysis.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" @@ -290,8 +291,8 @@ CacheCostTy IndexedReference::computeRefCost(const Loop &L, const SCEV *Coeff = getLastCoefficient(); const SCEV *ElemSize = Sizes.back(); const SCEV *Stride = SE.getMulExpr(Coeff, ElemSize); - const SCEV *CacheLineSize = SE.getConstant(Stride->getType(), CLS); Type *WiderType = SE.getWiderType(Stride->getType(), TripCount->getType()); + const SCEV *CacheLineSize = SE.getConstant(WiderType, CLS); if (SE.isKnownNegative(Stride)) Stride = SE.getNegativeSCEV(Stride); Stride = SE.getNoopOrAnyExtend(Stride, WiderType); @@ -344,8 +345,8 @@ bool IndexedReference::delinearize(const LoopInfo &LI) { LLVM_DEBUG(dbgs().indent(2) << "In Loop '" << L->getName() << "', AccessFn: " << *AccessFn << "\n"); - SE.delinearize(AccessFn, Subscripts, Sizes, - SE.getElementSize(&StoreOrLoadInst)); + llvm::delinearize(SE, AccessFn, Subscripts, Sizes, + SE.getElementSize(&StoreOrLoadInst)); if (Subscripts.empty() || Sizes.empty() || Subscripts.size() != Sizes.size()) { @@ -425,9 +426,7 @@ bool IndexedReference::isConsecutive(const Loop &L, unsigned CLS) const { const SCEV *IndexedReference::getLastCoefficient() const { const SCEV *LastSubscript = getLastSubscript(); - assert(isa<SCEVAddRecExpr>(LastSubscript) && - "Expecting a SCEV add recurrence expression"); - const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(LastSubscript); + auto *AR = cast<SCEVAddRecExpr>(LastSubscript); return AR->getStepRecurrence(SE); } @@ -522,10 +521,9 @@ void CacheCost::calculateCacheFootprint() { LLVM_DEBUG(dbgs() << "COMPUTING LOOP CACHE COSTS\n"); for (const Loop *L : Loops) { - assert((std::find_if(LoopCosts.begin(), LoopCosts.end(), - [L](const LoopCacheCostTy &LCC) { - return LCC.first == L; - }) == LoopCosts.end()) && + assert(llvm::none_of( + LoopCosts, + [L](const LoopCacheCostTy &LCC) { return LCC.first == L; }) && "Should not add duplicate element"); CacheCostTy LoopCost = computeLoopCacheCost(*L, RefGroups); LoopCosts.push_back(std::make_pair(L, LoopCost)); diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index 66aab4c195c8..b35fb2a190f6 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -301,15 +301,16 @@ PHINode *Loop::getInductionVariable(ScalarEvolution &SE) const { if (!CmpInst) return nullptr; - Instruction *LatchCmpOp0 = dyn_cast<Instruction>(CmpInst->getOperand(0)); - Instruction *LatchCmpOp1 = dyn_cast<Instruction>(CmpInst->getOperand(1)); + Value *LatchCmpOp0 = CmpInst->getOperand(0); + Value *LatchCmpOp1 = CmpInst->getOperand(1); for (PHINode &IndVar : Header->phis()) { InductionDescriptor IndDesc; if (!InductionDescriptor::isInductionPHI(&IndVar, this, &SE, IndDesc)) continue; - Instruction *StepInst = IndDesc.getInductionBinOp(); + BasicBlock *Latch = getLoopLatch(); + Value *StepInst = IndVar.getIncomingValueForBlock(Latch); // case 1: // IndVar = phi[{InitialValue, preheader}, {StepInst, latch}] @@ -1102,6 +1103,11 @@ llvm::Optional<int> llvm::getOptionalIntLoopAttribute(const Loop *TheLoop, return IntMD->getSExtValue(); } +int llvm::getIntLoopAttribute(const Loop *TheLoop, StringRef Name, + int Default) { + return getOptionalIntLoopAttribute(TheLoop, Name).getValueOr(Default); +} + static const char *LLVMLoopMustProgress = "llvm.loop.mustprogress"; bool llvm::hasMustProgress(const Loop *L) { diff --git a/llvm/lib/Analysis/LoopNestAnalysis.cpp b/llvm/lib/Analysis/LoopNestAnalysis.cpp index 2649ed60f762..675bb7a7749c 100644 --- a/llvm/lib/Analysis/LoopNestAnalysis.cpp +++ b/llvm/lib/Analysis/LoopNestAnalysis.cpp @@ -50,8 +50,66 @@ std::unique_ptr<LoopNest> LoopNest::getLoopNest(Loop &Root, return std::make_unique<LoopNest>(Root, SE); } +static CmpInst *getOuterLoopLatchCmp(const Loop &OuterLoop) { + + const BasicBlock *Latch = OuterLoop.getLoopLatch(); + assert(Latch && "Expecting a valid loop latch"); + + const BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator()); + assert(BI && BI->isConditional() && + "Expecting loop latch terminator to be a branch instruction"); + + CmpInst *OuterLoopLatchCmp = dyn_cast<CmpInst>(BI->getCondition()); + DEBUG_WITH_TYPE( + VerboseDebug, if (OuterLoopLatchCmp) { + dbgs() << "Outer loop latch compare instruction: " << *OuterLoopLatchCmp + << "\n"; + }); + return OuterLoopLatchCmp; +} + +static CmpInst *getInnerLoopGuardCmp(const Loop &InnerLoop) { + + BranchInst *InnerGuard = InnerLoop.getLoopGuardBranch(); + CmpInst *InnerLoopGuardCmp = + (InnerGuard) ? dyn_cast<CmpInst>(InnerGuard->getCondition()) : nullptr; + + DEBUG_WITH_TYPE( + VerboseDebug, if (InnerLoopGuardCmp) { + dbgs() << "Inner loop guard compare instruction: " << *InnerLoopGuardCmp + << "\n"; + }); + return InnerLoopGuardCmp; +} + +static bool checkSafeInstruction(const Instruction &I, + const CmpInst *InnerLoopGuardCmp, + const CmpInst *OuterLoopLatchCmp, + Optional<Loop::LoopBounds> OuterLoopLB) { + + bool IsAllowed = + isSafeToSpeculativelyExecute(&I) || isa<PHINode>(I) || isa<BranchInst>(I); + if (!IsAllowed) + return false; + // The only binary instruction allowed is the outer loop step instruction, + // the only comparison instructions allowed are the inner loop guard + // compare instruction and the outer loop latch compare instruction. + if ((isa<BinaryOperator>(I) && &I != &OuterLoopLB->getStepInst()) || + (isa<CmpInst>(I) && &I != OuterLoopLatchCmp && &I != InnerLoopGuardCmp)) { + return false; + } + return true; +} + bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop, ScalarEvolution &SE) { + return (analyzeLoopNestForPerfectNest(OuterLoop, InnerLoop, SE) == + PerfectLoopNest); +} + +LoopNest::LoopNestEnum LoopNest::analyzeLoopNestForPerfectNest( + const Loop &OuterLoop, const Loop &InnerLoop, ScalarEvolution &SE) { + assert(!OuterLoop.isInnermost() && "Outer loop should have subloops"); assert(!InnerLoop.isOutermost() && "Inner loop should have a parent"); LLVM_DEBUG(dbgs() << "Checking whether loop '" << OuterLoop.getName() @@ -66,7 +124,7 @@ bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop, // the outer loop latch. if (!checkLoopsStructure(OuterLoop, InnerLoop, SE)) { LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure.\n"); - return false; + return InvalidLoopStructure; } // Bail out if we cannot retrieve the outer loop bounds. @@ -74,33 +132,11 @@ bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop, if (OuterLoopLB == None) { LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: " << OuterLoop << "\n";); - return false; + return OuterLoopLowerBoundUnknown; } - // Identify the outer loop latch comparison instruction. - const BasicBlock *Latch = OuterLoop.getLoopLatch(); - assert(Latch && "Expecting a valid loop latch"); - const BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator()); - assert(BI && BI->isConditional() && - "Expecting loop latch terminator to be a branch instruction"); - - const CmpInst *OuterLoopLatchCmp = dyn_cast<CmpInst>(BI->getCondition()); - DEBUG_WITH_TYPE( - VerboseDebug, if (OuterLoopLatchCmp) { - dbgs() << "Outer loop latch compare instruction: " << *OuterLoopLatchCmp - << "\n"; - }); - - // Identify the inner loop guard instruction. - BranchInst *InnerGuard = InnerLoop.getLoopGuardBranch(); - const CmpInst *InnerLoopGuardCmp = - (InnerGuard) ? dyn_cast<CmpInst>(InnerGuard->getCondition()) : nullptr; - - DEBUG_WITH_TYPE( - VerboseDebug, if (InnerLoopGuardCmp) { - dbgs() << "Inner loop guard compare instruction: " << *InnerLoopGuardCmp - << "\n"; - }); + CmpInst *OuterLoopLatchCmp = getOuterLoopLatchCmp(OuterLoop); + CmpInst *InnerLoopGuardCmp = getInnerLoopGuardCmp(InnerLoop); // Determine whether instructions in a basic block are one of: // - the inner loop guard comparison @@ -109,29 +145,15 @@ bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop, // - a phi node, a cast or a branch auto containsOnlySafeInstructions = [&](const BasicBlock &BB) { return llvm::all_of(BB, [&](const Instruction &I) { - bool isAllowed = isSafeToSpeculativelyExecute(&I) || isa<PHINode>(I) || - isa<BranchInst>(I); - if (!isAllowed) { - DEBUG_WITH_TYPE(VerboseDebug, { - dbgs() << "Instruction: " << I << "\nin basic block: " << BB - << " is considered unsafe.\n"; - }); - return false; - } - - // The only binary instruction allowed is the outer loop step instruction, - // the only comparison instructions allowed are the inner loop guard - // compare instruction and the outer loop latch compare instruction. - if ((isa<BinaryOperator>(I) && &I != &OuterLoopLB->getStepInst()) || - (isa<CmpInst>(I) && &I != OuterLoopLatchCmp && - &I != InnerLoopGuardCmp)) { + bool IsSafeInstr = checkSafeInstruction(I, InnerLoopGuardCmp, + OuterLoopLatchCmp, OuterLoopLB); + if (IsSafeInstr) { DEBUG_WITH_TYPE(VerboseDebug, { dbgs() << "Instruction: " << I << "\nin basic block:" << BB << "is unsafe.\n"; }); - return false; } - return true; + return IsSafeInstr; }); }; @@ -148,13 +170,72 @@ bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop, !containsOnlySafeInstructions(*InnerLoop.getExitBlock())) { LLVM_DEBUG(dbgs() << "Not perfectly nested: code surrounding inner loop is " "unsafe\n";); - return false; + return ImperfectLoopNest; } LLVM_DEBUG(dbgs() << "Loop '" << OuterLoop.getName() << "' and '" << InnerLoop.getName() << "' are perfectly nested.\n"); - return true; + return PerfectLoopNest; +} + +LoopNest::InstrVectorTy LoopNest::getInterveningInstructions( + const Loop &OuterLoop, const Loop &InnerLoop, ScalarEvolution &SE) { + InstrVectorTy Instr; + switch (analyzeLoopNestForPerfectNest(OuterLoop, InnerLoop, SE)) { + case PerfectLoopNest: + LLVM_DEBUG(dbgs() << "The loop Nest is Perfect, returning empty " + "instruction vector. \n";); + return Instr; + + case InvalidLoopStructure: + LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure. " + "Instruction vector is empty.\n";); + return Instr; + + case OuterLoopLowerBoundUnknown: + LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: " + << OuterLoop << "\nInstruction vector is empty.\n";); + return Instr; + + case ImperfectLoopNest: + break; + } + + // Identify the outer loop latch comparison instruction. + auto OuterLoopLB = OuterLoop.getBounds(SE); + + CmpInst *OuterLoopLatchCmp = getOuterLoopLatchCmp(OuterLoop); + CmpInst *InnerLoopGuardCmp = getInnerLoopGuardCmp(InnerLoop); + + auto GetUnsafeInstructions = [&](const BasicBlock &BB) { + for (const Instruction &I : BB) { + if (!checkSafeInstruction(I, InnerLoopGuardCmp, OuterLoopLatchCmp, + OuterLoopLB)) { + Instr.push_back(&I); + DEBUG_WITH_TYPE(VerboseDebug, { + dbgs() << "Instruction: " << I << "\nin basic block:" << BB + << "is unsafe.\n"; + }); + } + } + }; + + // Check the code surrounding the inner loop for instructions that are deemed + // unsafe. + const BasicBlock *OuterLoopHeader = OuterLoop.getHeader(); + const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch(); + const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader(); + const BasicBlock *InnerLoopExitBlock = InnerLoop.getExitBlock(); + + GetUnsafeInstructions(*OuterLoopHeader); + GetUnsafeInstructions(*OuterLoopLatch); + GetUnsafeInstructions(*InnerLoopExitBlock); + + if (InnerLoopPreHeader != OuterLoopHeader) { + GetUnsafeInstructions(*InnerLoopPreHeader); + } + return Instr; } SmallVector<LoopVectorTy, 4> diff --git a/llvm/lib/Analysis/MLInlineAdvisor.cpp b/llvm/lib/Analysis/MLInlineAdvisor.cpp index 5b95ed223fd9..6fc4c42bdd71 100644 --- a/llvm/lib/Analysis/MLInlineAdvisor.cpp +++ b/llvm/lib/Analysis/MLInlineAdvisor.cpp @@ -116,6 +116,8 @@ MLInlineAdvisor::MLInlineAdvisor(Module &M, ModuleAnalysisManager &MAM, void MLInlineAdvisor::onPassEntry() { // Function passes executed between InlinerPass runs may have changed the // module-wide features. + if (!Invalid) + return; NodeCount = 0; EdgeCount = 0; for (auto &F : M) @@ -123,6 +125,7 @@ void MLInlineAdvisor::onPassEntry() { ++NodeCount; EdgeCount += getLocalCalls(F); } + Invalid = false; } int64_t MLInlineAdvisor::getLocalCalls(Function &F) { diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 68e997656d84..4f2b5b34304d 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -111,7 +111,7 @@ static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = { {LibFunc_reallocf, {ReallocLike, 2, 1, -1}}, {LibFunc_strdup, {StrDupLike, 1, -1, -1}}, {LibFunc_strndup, {StrDupLike, 2, 1, -1}}, - {LibFunc___kmpc_alloc_shared, {MallocLike, 1, 0, -1}} + {LibFunc___kmpc_alloc_shared, {MallocLike, 1, 0, -1}}, // TODO: Handle "int posix_memalign(void **, size_t, size_t)" }; @@ -135,9 +135,8 @@ static const Function *getCalledFunction(const Value *V, bool LookThroughBitCast return nullptr; } -/// Returns the allocation data for the given value if it's either a call to a -/// known allocation function, or a call to a function with the allocsize -/// attribute. +/// Returns the allocation data for the given value if it's a call to a known +/// allocation function. static Optional<AllocFnsTy> getAllocationDataForFunction(const Function *Callee, AllocType AllocTy, const TargetLibraryInfo *TLI) { @@ -610,7 +609,7 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL, SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) { IntTyBits = DL.getIndexTypeSizeInBits(V->getType()); - Zero = APInt::getNullValue(IntTyBits); + Zero = APInt::getZero(IntTyBits); V = V->stripPointerCasts(); if (Instruction *I = dyn_cast<Instruction>(V)) { diff --git a/llvm/lib/Analysis/MemoryLocation.cpp b/llvm/lib/Analysis/MemoryLocation.cpp index ef9cda37ce35..7f2d04c49565 100644 --- a/llvm/lib/Analysis/MemoryLocation.cpp +++ b/llvm/lib/Analysis/MemoryLocation.cpp @@ -35,54 +35,44 @@ void LocationSize::print(raw_ostream &OS) const { } MemoryLocation MemoryLocation::get(const LoadInst *LI) { - AAMDNodes AATags; - LI->getAAMetadata(AATags); const auto &DL = LI->getModule()->getDataLayout(); return MemoryLocation( LI->getPointerOperand(), - LocationSize::precise(DL.getTypeStoreSize(LI->getType())), AATags); + LocationSize::precise(DL.getTypeStoreSize(LI->getType())), + LI->getAAMetadata()); } MemoryLocation MemoryLocation::get(const StoreInst *SI) { - AAMDNodes AATags; - SI->getAAMetadata(AATags); const auto &DL = SI->getModule()->getDataLayout(); return MemoryLocation(SI->getPointerOperand(), LocationSize::precise(DL.getTypeStoreSize( SI->getValueOperand()->getType())), - AATags); + SI->getAAMetadata()); } MemoryLocation MemoryLocation::get(const VAArgInst *VI) { - AAMDNodes AATags; - VI->getAAMetadata(AATags); - return MemoryLocation(VI->getPointerOperand(), - LocationSize::afterPointer(), AATags); + LocationSize::afterPointer(), VI->getAAMetadata()); } MemoryLocation MemoryLocation::get(const AtomicCmpXchgInst *CXI) { - AAMDNodes AATags; - CXI->getAAMetadata(AATags); const auto &DL = CXI->getModule()->getDataLayout(); return MemoryLocation(CXI->getPointerOperand(), LocationSize::precise(DL.getTypeStoreSize( CXI->getCompareOperand()->getType())), - AATags); + CXI->getAAMetadata()); } MemoryLocation MemoryLocation::get(const AtomicRMWInst *RMWI) { - AAMDNodes AATags; - RMWI->getAAMetadata(AATags); const auto &DL = RMWI->getModule()->getDataLayout(); return MemoryLocation(RMWI->getPointerOperand(), LocationSize::precise(DL.getTypeStoreSize( RMWI->getValOperand()->getType())), - AATags); + RMWI->getAAMetadata()); } Optional<MemoryLocation> MemoryLocation::getOrNone(const Instruction *Inst) { @@ -117,10 +107,7 @@ MemoryLocation MemoryLocation::getForSource(const AnyMemTransferInst *MTI) { // memcpy/memmove can have AA tags. For memcpy, they apply // to both the source and the destination. - AAMDNodes AATags; - MTI->getAAMetadata(AATags); - - return MemoryLocation(MTI->getRawSource(), Size, AATags); + return MemoryLocation(MTI->getRawSource(), Size, MTI->getAAMetadata()); } MemoryLocation MemoryLocation::getForDest(const MemIntrinsic *MI) { @@ -138,17 +125,13 @@ MemoryLocation MemoryLocation::getForDest(const AnyMemIntrinsic *MI) { // memcpy/memmove can have AA tags. For memcpy, they apply // to both the source and the destination. - AAMDNodes AATags; - MI->getAAMetadata(AATags); - - return MemoryLocation(MI->getRawDest(), Size, AATags); + return MemoryLocation(MI->getRawDest(), Size, MI->getAAMetadata()); } MemoryLocation MemoryLocation::getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI) { - AAMDNodes AATags; - Call->getAAMetadata(AATags); + AAMDNodes AATags = Call->getAAMetadata(); const Value *Arg = Call->getArgOperand(ArgIdx); // We may be able to produce an exact size for known intrinsics. diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp index b402b0467f5d..ac20e20f0c0d 100644 --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -90,22 +90,18 @@ bool llvm::VerifyMemorySSA = true; #else bool llvm::VerifyMemorySSA = false; #endif -/// Enables memory ssa as a dependency for loop passes in legacy pass manager. -cl::opt<bool> llvm::EnableMSSALoopDependency( - "enable-mssa-loop-dependency", cl::Hidden, cl::init(true), - cl::desc("Enable MemorySSA dependency for loop pass manager")); static cl::opt<bool, true> VerifyMemorySSAX("verify-memoryssa", cl::location(VerifyMemorySSA), cl::Hidden, cl::desc("Enable verification of MemorySSA.")); -namespace llvm { +const static char LiveOnEntryStr[] = "liveOnEntry"; + +namespace { /// An assembly annotator class to print Memory SSA information in /// comments. class MemorySSAAnnotatedWriter : public AssemblyAnnotationWriter { - friend class MemorySSA; - const MemorySSA *MSSA; public: @@ -124,7 +120,34 @@ public: } }; -} // end namespace llvm +/// An assembly annotator class to print Memory SSA information in +/// comments. +class MemorySSAWalkerAnnotatedWriter : public AssemblyAnnotationWriter { + MemorySSA *MSSA; + MemorySSAWalker *Walker; + +public: + MemorySSAWalkerAnnotatedWriter(MemorySSA *M) + : MSSA(M), Walker(M->getWalker()) {} + + void emitInstructionAnnot(const Instruction *I, + formatted_raw_ostream &OS) override { + if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) { + MemoryAccess *Clobber = Walker->getClobberingMemoryAccess(MA); + OS << "; " << *MA; + if (Clobber) { + OS << " - clobbered by "; + if (MSSA->isLiveOnEntryDef(Clobber)) + OS << LiveOnEntryStr; + else + OS << *Clobber; + } + OS << "\n"; + } + } +}; + +} // namespace namespace { @@ -286,6 +309,7 @@ instructionClobbersQuery(const MemoryDef *MD, const MemoryLocation &UseLoc, case Intrinsic::invariant_end: case Intrinsic::assume: case Intrinsic::experimental_noalias_scope_decl: + case Intrinsic::pseudoprobe: return {false, AliasResult(AliasResult::NoAlias)}; case Intrinsic::dbg_addr: case Intrinsic::dbg_declare: @@ -1016,7 +1040,8 @@ public: // updated if a new clobber is found by this SkipSelf search. If this // additional query becomes heavily used we may decide to cache the result. // Walker instantiations will decide how to set the SkipSelf bool. - MemoryAccess *getClobberingMemoryAccessBase(MemoryAccess *, unsigned &, bool); + MemoryAccess *getClobberingMemoryAccessBase(MemoryAccess *, unsigned &, bool, + bool UseInvariantGroup = true); }; /// A MemorySSAWalker that does AA walks to disambiguate accesses. It no @@ -1041,6 +1066,11 @@ public: unsigned &UWL) { return Walker->getClobberingMemoryAccessBase(MA, Loc, UWL); } + // This method is not accessible outside of this file. + MemoryAccess *getClobberingMemoryAccessWithoutInvariantGroup(MemoryAccess *MA, + unsigned &UWL) { + return Walker->getClobberingMemoryAccessBase(MA, UWL, false, false); + } MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA) override { unsigned UpwardWalkLimit = MaxCheckLimit; @@ -1437,10 +1467,13 @@ void MemorySSA::OptimizeUses::optimizeUsesInBlock( unsigned UpwardWalkLimit = MaxCheckLimit; while (UpperBound > LocInfo.LowerBound) { if (isa<MemoryPhi>(VersionStack[UpperBound])) { - // For phis, use the walker, see where we ended up, go there + // For phis, use the walker, see where we ended up, go there. + // The invariant.group handling in MemorySSA is ad-hoc and doesn't + // support updates, so don't use it to optimize uses. MemoryAccess *Result = - Walker->getClobberingMemoryAccess(MU, UpwardWalkLimit); - // We are guaranteed to find it or something is wrong + Walker->getClobberingMemoryAccessWithoutInvariantGroup( + MU, UpwardWalkLimit); + // We are guaranteed to find it or something is wrong. while (VersionStack[UpperBound] != Result) { assert(UpperBound != 0); --UpperBound; @@ -1750,6 +1783,7 @@ MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I, break; case Intrinsic::assume: case Intrinsic::experimental_noalias_scope_decl: + case Intrinsic::pseudoprobe: return nullptr; } } @@ -1864,10 +1898,17 @@ void MemorySSA::print(raw_ostream &OS) const { LLVM_DUMP_METHOD void MemorySSA::dump() const { print(dbgs()); } #endif -void MemorySSA::verifyMemorySSA() const { - verifyOrderingDominationAndDefUses(F); +void MemorySSA::verifyMemorySSA(VerificationLevel VL) const { +#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS) + VL = VerificationLevel::Full; +#endif + +#ifndef NDEBUG + verifyOrderingDominationAndDefUses(F, VL); verifyDominationNumbers(F); - verifyPrevDefInPhis(F); + if (VL == VerificationLevel::Full) + verifyPrevDefInPhis(F); +#endif // Previously, the verification used to also verify that the clobberingAccess // cached by MemorySSA is the same as the clobberingAccess found at a later // query to AA. This does not hold true in general due to the current fragility @@ -1881,7 +1922,6 @@ void MemorySSA::verifyMemorySSA() const { } void MemorySSA::verifyPrevDefInPhis(Function &F) const { -#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS) for (const BasicBlock &BB : F) { if (MemoryPhi *Phi = getMemoryAccess(&BB)) { for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) { @@ -1896,6 +1936,8 @@ void MemorySSA::verifyPrevDefInPhis(Function &F) const { auto *LastAcc = &*(--DefList->end()); assert(LastAcc == IncAcc && "Incorrect incoming access into phi."); + (void)IncAcc; + (void)LastAcc; break; } DTNode = DTNode->getIDom(); @@ -1911,13 +1953,11 @@ void MemorySSA::verifyPrevDefInPhis(Function &F) const { } } } -#endif } /// Verify that all of the blocks we believe to have valid domination numbers /// actually have valid domination numbers. void MemorySSA::verifyDominationNumbers(const Function &F) const { -#ifndef NDEBUG if (BlockNumberingValid.empty()) return; @@ -1943,13 +1983,13 @@ void MemorySSA::verifyDominationNumbers(const Function &F) const { unsigned long ThisNumber = ThisNumberIter->second; assert(ThisNumber > LastNumber && "Domination numbers should be strictly increasing!"); + (void)LastNumber; LastNumber = ThisNumber; } } assert(ValidBlocks.empty() && "All valid BasicBlocks should exist in F -- dangling pointers?"); -#endif } /// Verify ordering: the order and existence of MemoryAccesses matches the @@ -1958,8 +1998,8 @@ void MemorySSA::verifyDominationNumbers(const Function &F) const { /// Verify def-uses: the immediate use information - walk all the memory /// accesses and verifying that, for each use, it appears in the appropriate /// def's use list -void MemorySSA::verifyOrderingDominationAndDefUses(Function &F) const { -#if !defined(NDEBUG) +void MemorySSA::verifyOrderingDominationAndDefUses(Function &F, + VerificationLevel VL) const { // Walk all the blocks, comparing what the lookups think and what the access // lists think, as well as the order in the blocks vs the order in the access // lists. @@ -1974,19 +2014,21 @@ void MemorySSA::verifyOrderingDominationAndDefUses(Function &F) const { ActualAccesses.push_back(Phi); ActualDefs.push_back(Phi); // Verify domination - for (const Use &U : Phi->uses()) + for (const Use &U : Phi->uses()) { assert(dominates(Phi, U) && "Memory PHI does not dominate it's uses"); -#if defined(EXPENSIVE_CHECKS) - // Verify def-uses. - assert(Phi->getNumOperands() == static_cast<unsigned>(std::distance( - pred_begin(&B), pred_end(&B))) && - "Incomplete MemoryPhi Node"); - for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) { - verifyUseInDefs(Phi->getIncomingValue(I), Phi); - assert(is_contained(predecessors(&B), Phi->getIncomingBlock(I)) && - "Incoming phi block not a block predecessor"); + (void)U; + } + // Verify def-uses for full verify. + if (VL == VerificationLevel::Full) { + assert(Phi->getNumOperands() == static_cast<unsigned>(std::distance( + pred_begin(&B), pred_end(&B))) && + "Incomplete MemoryPhi Node"); + for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) { + verifyUseInDefs(Phi->getIncomingValue(I), Phi); + assert(is_contained(predecessors(&B), Phi->getIncomingBlock(I)) && + "Incoming phi block not a block predecessor"); + } } -#endif } for (Instruction &I : B) { @@ -2002,14 +2044,15 @@ void MemorySSA::verifyOrderingDominationAndDefUses(Function &F) const { // Verify ordering. ActualDefs.push_back(MA); // Verify domination. - for (const Use &U : MD->uses()) + for (const Use &U : MD->uses()) { assert(dominates(MD, U) && "Memory Def does not dominate it's uses"); + (void)U; + } } -#if defined(EXPENSIVE_CHECKS) - // Verify def-uses. - verifyUseInDefs(MA->getDefiningAccess(), MA); -#endif + // Verify def-uses for full verify. + if (VL == VerificationLevel::Full) + verifyUseInDefs(MA->getDefiningAccess(), MA); } } // Either we hit the assert, really have no accesses, or we have both @@ -2044,13 +2087,11 @@ void MemorySSA::verifyOrderingDominationAndDefUses(Function &F) const { } ActualDefs.clear(); } -#endif } /// Verify the def-use lists in MemorySSA, by verifying that \p Use /// appears in the use list of \p Def. void MemorySSA::verifyUseInDefs(MemoryAccess *Def, MemoryAccess *Use) const { -#ifndef NDEBUG // The live on entry use may cause us to get a NULL def here if (!Def) assert(isLiveOnEntryDef(Use) && @@ -2058,7 +2099,6 @@ void MemorySSA::verifyUseInDefs(MemoryAccess *Def, MemoryAccess *Use) const { else assert(is_contained(Def->users(), Use) && "Did not find use in def's use list"); -#endif } /// Perform a local numbering on blocks so that instruction ordering can be @@ -2138,8 +2178,6 @@ bool MemorySSA::dominates(const MemoryAccess *Dominator, return dominates(Dominator, cast<MemoryAccess>(Dominatee.getUser())); } -const static char LiveOnEntryStr[] = "liveOnEntry"; - void MemoryAccess::print(raw_ostream &OS) const { switch (getValueID()) { case MemoryPhiVal: return static_cast<const MemoryPhi *>(this)->print(OS); @@ -2355,6 +2393,16 @@ PreservedAnalyses MemorySSAPrinterPass::run(Function &F, return PreservedAnalyses::all(); } +PreservedAnalyses MemorySSAWalkerPrinterPass::run(Function &F, + FunctionAnalysisManager &AM) { + auto &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA(); + OS << "MemorySSA (walker) for function: " << F.getName() << "\n"; + MemorySSAWalkerAnnotatedWriter Writer(&MSSA); + F.print(OS, &Writer); + + return PreservedAnalyses::all(); +} + PreservedAnalyses MemorySSAVerifierPass::run(Function &F, FunctionAnalysisManager &AM) { AM.getResult<MemorySSAAnalysis>(F).getMSSA().verifyMemorySSA(); @@ -2438,15 +2486,88 @@ MemorySSA::ClobberWalkerBase<AliasAnalysisType>::getClobberingMemoryAccessBase( return Clobber; } +static const Instruction * +getInvariantGroupClobberingInstruction(Instruction &I, DominatorTree &DT) { + if (!I.hasMetadata(LLVMContext::MD_invariant_group) || I.isVolatile()) + return nullptr; + + // We consider bitcasts and zero GEPs to be the same pointer value. Start by + // stripping bitcasts and zero GEPs, then we will recursively look at loads + // and stores through bitcasts and zero GEPs. + Value *PointerOperand = getLoadStorePointerOperand(&I)->stripPointerCasts(); + + // It's not safe to walk the use list of a global value because function + // passes aren't allowed to look outside their functions. + // FIXME: this could be fixed by filtering instructions from outside of + // current function. + if (isa<Constant>(PointerOperand)) + return nullptr; + + // Queue to process all pointers that are equivalent to load operand. + SmallVector<const Value *, 8> PointerUsesQueue; + PointerUsesQueue.push_back(PointerOperand); + + const Instruction *MostDominatingInstruction = &I; + + // FIXME: This loop is O(n^2) because dominates can be O(n) and in worst case + // we will see all the instructions. It may not matter in practice. If it + // does, we will have to support MemorySSA construction and updates. + while (!PointerUsesQueue.empty()) { + const Value *Ptr = PointerUsesQueue.pop_back_val(); + assert(Ptr && !isa<GlobalValue>(Ptr) && + "Null or GlobalValue should not be inserted"); + + for (const User *Us : Ptr->users()) { + auto *U = dyn_cast<Instruction>(Us); + if (!U || U == &I || !DT.dominates(U, MostDominatingInstruction)) + continue; + + // Add bitcasts and zero GEPs to queue. + if (isa<BitCastInst>(U)) { + PointerUsesQueue.push_back(U); + continue; + } + if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) { + if (GEP->hasAllZeroIndices()) + PointerUsesQueue.push_back(U); + continue; + } + + // If we hit a load/store with an invariant.group metadata and the same + // pointer operand, we can assume that value pointed to by the pointer + // operand didn't change. + if (U->hasMetadata(LLVMContext::MD_invariant_group) && + getLoadStorePointerOperand(U) == Ptr && !U->isVolatile()) { + MostDominatingInstruction = U; + } + } + } + return MostDominatingInstruction == &I ? nullptr : MostDominatingInstruction; +} + template <typename AliasAnalysisType> MemoryAccess * MemorySSA::ClobberWalkerBase<AliasAnalysisType>::getClobberingMemoryAccessBase( - MemoryAccess *MA, unsigned &UpwardWalkLimit, bool SkipSelf) { + MemoryAccess *MA, unsigned &UpwardWalkLimit, bool SkipSelf, + bool UseInvariantGroup) { auto *StartingAccess = dyn_cast<MemoryUseOrDef>(MA); // If this is a MemoryPhi, we can't do anything. if (!StartingAccess) return MA; + if (UseInvariantGroup) { + if (auto *I = getInvariantGroupClobberingInstruction( + *StartingAccess->getMemoryInst(), MSSA->getDomTree())) { + assert(isa<LoadInst>(I) || isa<StoreInst>(I)); + + auto *ClobberMA = MSSA->getMemoryAccess(I); + assert(ClobberMA); + if (isa<MemoryUse>(ClobberMA)) + return ClobberMA->getDefiningAccess(); + return ClobberMA; + } + } + bool IsOptimized = false; // If this is an already optimized use or def, return the optimized result. diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp index 616864f360bf..9c841883de6d 100644 --- a/llvm/lib/Analysis/MemorySSAUpdater.cpp +++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp @@ -296,9 +296,8 @@ static void setMemoryPhiValueForBlock(MemoryPhi *MP, const BasicBlock *BB, assert(i != -1 && "Should have found the basic block in the phi"); // We can't just compare i against getNumOperands since one is signed and the // other not. So use it to index into the block iterator. - for (auto BBIter = MP->block_begin() + i; BBIter != MP->block_end(); - ++BBIter) { - if (*BBIter != BB) + for (const BasicBlock *BlockBB : llvm::drop_begin(MP->blocks(), i)) { + if (BlockBB != BB) break; MP->setIncomingValue(i, NewDef); ++i; @@ -491,8 +490,7 @@ void MemorySSAUpdater::fixupDefs(const SmallVectorImpl<WeakVH> &Vars) { } while (!Worklist.empty()) { - const BasicBlock *FixupBlock = Worklist.back(); - Worklist.pop_back(); + const BasicBlock *FixupBlock = Worklist.pop_back_val(); // Get the first def in the block that isn't a phi node. if (auto *Defs = MSSA->getWritableBlockDefs(FixupBlock)) { @@ -822,25 +820,30 @@ void MemorySSAUpdater::applyUpdates(ArrayRef<CFGUpdate> Updates, } if (!DeleteUpdates.empty()) { - if (!UpdateDT) { - SmallVector<CFGUpdate, 0> Empty; - // Deletes are reversed applied, because this CFGView is pretending the - // deletes did not happen yet, hence the edges still exist. - DT.applyUpdates(Empty, RevDeleteUpdates); + if (!InsertUpdates.empty()) { + if (!UpdateDT) { + SmallVector<CFGUpdate, 0> Empty; + // Deletes are reversed applied, because this CFGView is pretending the + // deletes did not happen yet, hence the edges still exist. + DT.applyUpdates(Empty, RevDeleteUpdates); + } else { + // Apply all updates, with the RevDeleteUpdates as PostCFGView. + DT.applyUpdates(Updates, RevDeleteUpdates); + } + + // Note: the MSSA update below doesn't distinguish between a GD with + // (RevDelete,false) and (Delete, true), but this matters for the DT + // updates above; for "children" purposes they are equivalent; but the + // updates themselves convey the desired update, used inside DT only. + GraphDiff<BasicBlock *> GD(RevDeleteUpdates); + applyInsertUpdates(InsertUpdates, DT, &GD); + // Update DT to redelete edges; this matches the real CFG so we can + // perform the standard update without a postview of the CFG. + DT.applyUpdates(DeleteUpdates); } else { - // Apply all updates, with the RevDeleteUpdates as PostCFGView. - DT.applyUpdates(Updates, RevDeleteUpdates); + if (UpdateDT) + DT.applyUpdates(DeleteUpdates); } - - // Note: the MSSA update below doesn't distinguish between a GD with - // (RevDelete,false) and (Delete, true), but this matters for the DT - // updates above; for "children" purposes they are equivalent; but the - // updates themselves convey the desired update, used inside DT only. - GraphDiff<BasicBlock *> GD(RevDeleteUpdates); - applyInsertUpdates(InsertUpdates, DT, &GD); - // Update DT to redelete edges; this matches the real CFG so we can perform - // the standard update without a postview of the CFG. - DT.applyUpdates(DeleteUpdates); } else { if (UpdateDT) DT.applyUpdates(Updates); @@ -1131,11 +1134,7 @@ void MemorySSAUpdater::applyInsertUpdates(ArrayRef<CFGUpdate> Updates, if (auto DefsList = MSSA->getWritableBlockDefs(BlockWithDefsToReplace)) { for (auto &DefToReplaceUses : *DefsList) { BasicBlock *DominatingBlock = DefToReplaceUses.getBlock(); - Value::use_iterator UI = DefToReplaceUses.use_begin(), - E = DefToReplaceUses.use_end(); - for (; UI != E;) { - Use &U = *UI; - ++UI; + for (Use &U : llvm::make_early_inc_range(DefToReplaceUses.uses())) { MemoryAccess *Usr = cast<MemoryAccess>(U.getUser()); if (MemoryPhi *UsrPhi = dyn_cast<MemoryPhi>(Usr)) { BasicBlock *DominatedBlock = UsrPhi->getIncomingBlock(U); diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index e43553222128..d80814852e19 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -264,11 +264,27 @@ static void computeFunctionSummary( std::vector<const Instruction *> NonVolatileStores; bool HasInlineAsmMaybeReferencingInternal = false; - for (const BasicBlock &BB : F) + bool HasIndirBranchToBlockAddress = false; + bool HasUnknownCall = false; + bool MayThrow = false; + for (const BasicBlock &BB : F) { + // We don't allow inlining of function with indirect branch to blockaddress. + // If the blockaddress escapes the function, e.g., via a global variable, + // inlining may lead to an invalid cross-function reference. So we shouldn't + // import such function either. + if (BB.hasAddressTaken()) { + for (User *U : BlockAddress::get(const_cast<BasicBlock *>(&BB))->users()) + if (!isa<CallBrInst>(*U)) { + HasIndirBranchToBlockAddress = true; + break; + } + } + for (const Instruction &I : BB) { - if (isa<DbgInfoIntrinsic>(I)) + if (I.isDebugOrPseudoInst()) continue; ++NumInsts; + // Regular LTO module doesn't participate in ThinLTO import, // so no reference from it can be read/writeonly, since this // would require importing variable as local copy @@ -300,8 +316,11 @@ static void computeFunctionSummary( } findRefEdges(Index, &I, RefEdges, Visited); const auto *CB = dyn_cast<CallBase>(&I); - if (!CB) + if (!CB) { + if (I.mayThrow()) + MayThrow = true; continue; + } const auto *CI = dyn_cast<CallInst>(&I); // Since we don't know exactly which local values are referenced in inline @@ -323,7 +342,7 @@ static void computeFunctionSummary( // called aliasee for the checks below. if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) { assert(!CalledFunction && "Expected null called function in callsite for alias"); - CalledFunction = dyn_cast<Function>(GA->getBaseObject()); + CalledFunction = dyn_cast<Function>(GA->getAliaseeObject()); } // Check if this is a direct call to a known function or a known // intrinsic, or an indirect call with profile data. @@ -357,6 +376,7 @@ static void computeFunctionSummary( ValueInfo.updateRelBlockFreq(BBFreq, EntryFreq); } } else { + HasUnknownCall = true; // Skip inline assembly calls. if (CI && CI->isInlineAsm()) continue; @@ -386,6 +406,7 @@ static void computeFunctionSummary( .updateHotness(getHotness(Candidate.Count, PSI)); } } + } Index.addBlockCount(F.size()); std::vector<ValueInfo> Refs; @@ -452,8 +473,9 @@ static void computeFunctionSummary( : CalleeInfo::HotnessType::Critical); bool NonRenamableLocal = isNonRenamableLocal(F); - bool NotEligibleForImport = - NonRenamableLocal || HasInlineAsmMaybeReferencingInternal; + bool NotEligibleForImport = NonRenamableLocal || + HasInlineAsmMaybeReferencingInternal || + HasIndirBranchToBlockAddress; GlobalValueSummary::GVFlags Flags( F.getLinkage(), F.getVisibility(), NotEligibleForImport, /* Live = */ false, F.isDSOLocal(), @@ -464,8 +486,9 @@ static void computeFunctionSummary( F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(), // FIXME: refactor this to use the same code that inliner is using. // Don't try to import functions with noinline attribute. - F.getAttributes().hasFnAttribute(Attribute::NoInline), - F.hasFnAttribute(Attribute::AlwaysInline)}; + F.getAttributes().hasFnAttr(Attribute::NoInline), + F.hasFnAttribute(Attribute::AlwaysInline), + F.hasFnAttribute(Attribute::NoUnwind), MayThrow, HasUnknownCall}; std::vector<FunctionSummary::ParamAccess> ParamAccesses; if (auto *SSI = GetSSICallback(F)) ParamAccesses = SSI->getParamAccesses(Index); @@ -622,7 +645,7 @@ computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, /* Live = */ false, A.isDSOLocal(), A.hasLinkOnceODRLinkage() && A.hasGlobalUnnamedAddr()); auto AS = std::make_unique<AliasSummary>(Flags); - auto *Aliasee = A.getBaseObject(); + auto *Aliasee = A.getAliaseeObject(); auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID()); assert(AliaseeVI && "Alias expects aliasee summary to be available"); assert(AliaseeVI.getSummaryList().size() == 1 && @@ -711,7 +734,10 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( F->hasFnAttribute(Attribute::NoRecurse), F->returnDoesNotAlias(), /* NoInline = */ false, - F->hasFnAttribute(Attribute::AlwaysInline)}, + F->hasFnAttribute(Attribute::AlwaysInline), + F->hasFnAttribute(Attribute::NoUnwind), + /* MayThrow */ true, + /* HasUnknownCall */ true}, /*EntryCount=*/0, ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{}, ArrayRef<GlobalValue::GUID>{}, diff --git a/llvm/lib/Analysis/ObjCARCInstKind.cpp b/llvm/lib/Analysis/ObjCARCInstKind.cpp index 704d15f3280d..f74a9f7f104f 100644 --- a/llvm/lib/Analysis/ObjCARCInstKind.cpp +++ b/llvm/lib/Analysis/ObjCARCInstKind.cpp @@ -296,9 +296,8 @@ ARCInstKind llvm::objcarc::GetARCInstKind(const Value *V) { // operand isn't actually being dereferenced, it is being stored to // memory where we can no longer track who might read it and dereference // it, so we have to consider it potentially used. - for (User::const_op_iterator OI = I->op_begin(), OE = I->op_end(); - OI != OE; ++OI) - if (IsPotentialRetainableObjPtr(*OI)) + for (const Use &U : I->operands()) + if (IsPotentialRetainableObjPtr(U)) return ARCInstKind::User; } } diff --git a/llvm/lib/Analysis/OverflowInstAnalysis.cpp b/llvm/lib/Analysis/OverflowInstAnalysis.cpp index 9f17d5b2064d..87a85e6a7364 100644 --- a/llvm/lib/Analysis/OverflowInstAnalysis.cpp +++ b/llvm/lib/Analysis/OverflowInstAnalysis.cpp @@ -69,4 +69,4 @@ bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd) { Use *Y; return isCheckForZeroAndMulWithOverflow(Op0, Op1, IsAnd, Y); -}
\ No newline at end of file +} diff --git a/llvm/lib/Analysis/PHITransAddr.cpp b/llvm/lib/Analysis/PHITransAddr.cpp index 7f77ab146c4c..c73e1fd82915 100644 --- a/llvm/lib/Analysis/PHITransAddr.cpp +++ b/llvm/lib/Analysis/PHITransAddr.cpp @@ -226,8 +226,8 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, return GEP; // Simplify the GEP to handle 'gep x, 0' -> x etc. - if (Value *V = SimplifyGEPInst(GEP->getSourceElementType(), - GEPOps, {DL, TLI, DT, AC})) { + if (Value *V = SimplifyGEPInst(GEP->getSourceElementType(), GEPOps, + GEP->isInBounds(), {DL, TLI, DT, AC})) { for (unsigned i = 0, e = GEPOps.size(); i != e; ++i) RemoveInstInputs(GEPOps[i], InstInputs); diff --git a/llvm/lib/Analysis/ProfileSummaryInfo.cpp b/llvm/lib/Analysis/ProfileSummaryInfo.cpp index 6dda0bf0a1b4..268ed9d04741 100644 --- a/llvm/lib/Analysis/ProfileSummaryInfo.cpp +++ b/llvm/lib/Analysis/ProfileSummaryInfo.cpp @@ -103,7 +103,7 @@ bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) const { // FIXME: The heuristic used below for determining hotness is based on // preliminary SPEC tuning for inliner. This will eventually be a // convenience method that calls isHotCount. - return FunctionCount && isHotCount(FunctionCount.getCount()); + return FunctionCount && isHotCount(FunctionCount->getCount()); } /// Returns true if the function contains hot code. This can include a hot @@ -116,7 +116,7 @@ bool ProfileSummaryInfo::isFunctionHotInCallGraph( if (!F || !hasProfileSummary()) return false; if (auto FunctionCount = F->getEntryCount()) - if (isHotCount(FunctionCount.getCount())) + if (isHotCount(FunctionCount->getCount())) return true; if (hasSampleProfile()) { @@ -145,7 +145,7 @@ bool ProfileSummaryInfo::isFunctionColdInCallGraph( if (!F || !hasProfileSummary()) return false; if (auto FunctionCount = F->getEntryCount()) - if (!isColdCount(FunctionCount.getCount())) + if (!isColdCount(FunctionCount->getCount())) return false; if (hasSampleProfile()) { @@ -176,10 +176,10 @@ bool ProfileSummaryInfo::isFunctionHotOrColdInCallGraphNthPercentile( return false; if (auto FunctionCount = F->getEntryCount()) { if (isHot && - isHotCountNthPercentile(PercentileCutoff, FunctionCount.getCount())) + isHotCountNthPercentile(PercentileCutoff, FunctionCount->getCount())) return true; if (!isHot && - !isColdCountNthPercentile(PercentileCutoff, FunctionCount.getCount())) + !isColdCountNthPercentile(PercentileCutoff, FunctionCount->getCount())) return false; } if (hasSampleProfile()) { @@ -230,7 +230,7 @@ bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) const { // FIXME: The heuristic used below for determining coldness is based on // preliminary SPEC tuning for inliner. This will eventually be a // convenience method that calls isHotCount. - return FunctionCount && isColdCount(FunctionCount.getCount()); + return FunctionCount && isColdCount(FunctionCount->getCount()); } /// Compute the hot and cold thresholds. @@ -316,11 +316,11 @@ bool ProfileSummaryInfo::isColdCountNthPercentile(int PercentileCutoff, } uint64_t ProfileSummaryInfo::getOrCompHotCountThreshold() const { - return HotCountThreshold ? HotCountThreshold.getValue() : UINT64_MAX; + return HotCountThreshold.getValueOr(UINT64_MAX); } uint64_t ProfileSummaryInfo::getOrCompColdCountThreshold() const { - return ColdCountThreshold ? ColdCountThreshold.getValue() : 0; + return ColdCountThreshold.getValueOr(0); } bool ProfileSummaryInfo::isHotBlock(const BasicBlock *BB, diff --git a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp index b9dac2f3ff11..f83d8b0fd230 100644 --- a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp +++ b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp @@ -17,18 +17,21 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/LineIterator.h" +#include <memory> using namespace llvm; -#define DEBUG_TYPE "inline-replay" +#define DEBUG_TYPE "replay-inline" ReplayInlineAdvisor::ReplayInlineAdvisor( Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context, - std::unique_ptr<InlineAdvisor> OriginalAdvisor, StringRef RemarksFile, - bool EmitRemarks) + std::unique_ptr<InlineAdvisor> OriginalAdvisor, + const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks) : InlineAdvisor(M, FAM), OriginalAdvisor(std::move(OriginalAdvisor)), - HasReplayRemarks(false), EmitRemarks(EmitRemarks) { - auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(RemarksFile); + HasReplayRemarks(false), ReplaySettings(ReplaySettings), + EmitRemarks(EmitRemarks) { + + auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(ReplaySettings.ReplayFile); std::error_code EC = BufferOrErr.getError(); if (EC) { Context.emitError("Could not open remarks file: " + EC.message()); @@ -36,47 +39,112 @@ ReplayInlineAdvisor::ReplayInlineAdvisor( } // Example for inline remarks to parse: - // main:3:1.1: _Z3subii inlined into main at callsite sum:1 @ main:3:1.1 + // main:3:1.1: '_Z3subii' inlined into 'main' at callsite sum:1 @ + // main:3:1.1; // We use the callsite string after `at callsite` to replay inlining. line_iterator LineIt(*BufferOrErr.get(), /*SkipBlanks=*/true); + const std::string PositiveRemark = "' inlined into '"; + const std::string NegativeRemark = "' will not be inlined into '"; + for (; !LineIt.is_at_eof(); ++LineIt) { StringRef Line = *LineIt; auto Pair = Line.split(" at callsite "); - auto Callee = Pair.first.split(" inlined into").first.rsplit(": ").second; + bool IsPositiveRemark = true; + if (Pair.first.contains(NegativeRemark)) + IsPositiveRemark = false; + + auto CalleeCaller = + Pair.first.split(IsPositiveRemark ? PositiveRemark : NegativeRemark); + + StringRef Callee = CalleeCaller.first.rsplit(": '").second; + StringRef Caller = CalleeCaller.second.rsplit("'").first; auto CallSite = Pair.second.split(";").first; - if (Callee.empty() || CallSite.empty()) - continue; + if (Callee.empty() || Caller.empty() || CallSite.empty()) { + Context.emitError("Invalid remark format: " + Line); + return; + } std::string Combined = (Callee + CallSite).str(); - InlineSitesFromRemarks.insert(Combined); + InlineSitesFromRemarks[Combined] = IsPositiveRemark; + if (ReplaySettings.ReplayScope == ReplayInlinerSettings::Scope::Function) + CallersToReplay.insert(Caller); } HasReplayRemarks = true; } +std::unique_ptr<InlineAdvisor> llvm::getReplayInlineAdvisor( + Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context, + std::unique_ptr<InlineAdvisor> OriginalAdvisor, + const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks) { + auto Advisor = std::make_unique<ReplayInlineAdvisor>( + M, FAM, Context, std::move(OriginalAdvisor), ReplaySettings, EmitRemarks); + if (!Advisor->areReplayRemarksLoaded()) + Advisor.reset(); + return Advisor; +} + std::unique_ptr<InlineAdvice> ReplayInlineAdvisor::getAdviceImpl(CallBase &CB) { assert(HasReplayRemarks); Function &Caller = *CB.getCaller(); auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller); - if (InlineSitesFromRemarks.empty()) - return std::make_unique<DefaultInlineAdvice>(this, CB, None, ORE, - EmitRemarks); + // Decision not made by replay system + if (!hasInlineAdvice(*CB.getFunction())) { + // If there's a registered original advisor, return its decision + if (OriginalAdvisor) + return OriginalAdvisor->getAdvice(CB); - std::string CallSiteLoc = getCallSiteLocation(CB.getDebugLoc()); + // If no decision is made above, return non-decision + return {}; + } + + std::string CallSiteLoc = + formatCallSiteLocation(CB.getDebugLoc(), ReplaySettings.ReplayFormat); StringRef Callee = CB.getCalledFunction()->getName(); std::string Combined = (Callee + CallSiteLoc).str(); - auto Iter = InlineSitesFromRemarks.find(Combined); - Optional<InlineCost> InlineRecommended = None; + // Replay decision, if it has one + auto Iter = InlineSitesFromRemarks.find(Combined); if (Iter != InlineSitesFromRemarks.end()) { - InlineRecommended = llvm::InlineCost::getAlways("found in replay"); + if (InlineSitesFromRemarks[Combined]) { + LLVM_DEBUG(dbgs() << "Replay Inliner: Inlined " << Callee << " @ " + << CallSiteLoc << "\n"); + return std::make_unique<DefaultInlineAdvice>( + this, CB, llvm::InlineCost::getAlways("previously inlined"), ORE, + EmitRemarks); + } else { + LLVM_DEBUG(dbgs() << "Replay Inliner: Not Inlined " << Callee << " @ " + << CallSiteLoc << "\n"); + // A negative inline is conveyed by "None" Optional<InlineCost> + return std::make_unique<DefaultInlineAdvice>(this, CB, None, ORE, + EmitRemarks); + } + } + + // Fallback decisions + if (ReplaySettings.ReplayFallback == + ReplayInlinerSettings::Fallback::AlwaysInline) + return std::make_unique<DefaultInlineAdvice>( + this, CB, llvm::InlineCost::getAlways("AlwaysInline Fallback"), ORE, + EmitRemarks); + else if (ReplaySettings.ReplayFallback == + ReplayInlinerSettings::Fallback::NeverInline) + // A negative inline is conveyed by "None" Optional<InlineCost> + return std::make_unique<DefaultInlineAdvice>(this, CB, None, ORE, + EmitRemarks); + else { + assert(ReplaySettings.ReplayFallback == + ReplayInlinerSettings::Fallback::Original); + // If there's a registered original advisor, return its decision + if (OriginalAdvisor) + return OriginalAdvisor->getAdvice(CB); } - return std::make_unique<DefaultInlineAdvice>(this, CB, InlineRecommended, ORE, - EmitRemarks); + // If no decision is made above, return non-decision + return {}; } diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index f22d834b5e57..f7c22cfb0310 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -139,8 +139,6 @@ using namespace PatternMatch; #define DEBUG_TYPE "scalar-evolution" -STATISTIC(NumArrayLenItCounts, - "Number of trip counts computed with array length"); STATISTIC(NumTripCountsComputed, "Number of loops with predictable loop counts"); STATISTIC(NumTripCountsNotComputed, @@ -1100,7 +1098,7 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op, SCEV *S = new (SCEVAllocator) SCEVPtrToIntExpr(ID.Intern(SCEVAllocator), Op, IntPtrTy); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Op); return S; } @@ -1220,7 +1218,7 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty, SCEV *S = new (SCEVAllocator) SCEVTruncateExpr(ID.Intern(SCEVAllocator), Op, Ty); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Op); return S; } @@ -1274,7 +1272,7 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty, SCEV *S = new (SCEVAllocator) SCEVTruncateExpr(ID.Intern(SCEVAllocator), Op, Ty); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Op); return S; } @@ -1603,7 +1601,7 @@ ScalarEvolution::getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) { SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator), Op, Ty); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Op); return S; } @@ -1872,7 +1870,7 @@ ScalarEvolution::getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) { SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator), Op, Ty); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Op); return S; } @@ -1911,7 +1909,7 @@ ScalarEvolution::getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) { SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator), Op, Ty); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Op); return S; } @@ -2108,7 +2106,7 @@ ScalarEvolution::getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) { SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator), Op, Ty); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, { Op }); return S; } @@ -2390,6 +2388,24 @@ StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type, } } + // <0,+,nonnegative><nw> is also nuw + // TODO: Add corresponding nsw case + if (Type == scAddRecExpr && ScalarEvolution::hasFlags(Flags, SCEV::FlagNW) && + !ScalarEvolution::hasFlags(Flags, SCEV::FlagNUW) && Ops.size() == 2 && + Ops[0]->isZero() && IsKnownNonNegative(Ops[1])) + Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW); + + // both (udiv X, Y) * Y and Y * (udiv X, Y) are always NUW + if (Type == scMulExpr && !ScalarEvolution::hasFlags(Flags, SCEV::FlagNUW) && + Ops.size() == 2) { + if (auto *UDiv = dyn_cast<SCEVUDivExpr>(Ops[0])) + if (UDiv->getOperand(1) == Ops[1]) + Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW); + if (auto *UDiv = dyn_cast<SCEVUDivExpr>(Ops[1])) + if (UDiv->getOperand(1) == Ops[0]) + Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW); + } + return Flags; } @@ -2449,7 +2465,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, if (Depth > MaxArithDepth || hasHugeExpression(Ops)) return getOrCreateAddExpr(Ops, ComputeFlags(Ops)); - if (SCEV *S = std::get<0>(findExistingSCEVInCache(scAddExpr, Ops))) { + if (SCEV *S = findExistingSCEVInCache(scAddExpr, Ops)) { // Don't strengthen flags if we have no new information. SCEVAddExpr *Add = static_cast<SCEVAddExpr *>(S); if (Add->getNoWrapFlags(OrigFlags) != OrigFlags) @@ -2562,8 +2578,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, APInt ConstAdd = C1 + C2; auto AddFlags = AddExpr->getNoWrapFlags(); // Adding a smaller constant is NUW if the original AddExpr was NUW. - if (ScalarEvolution::maskFlags(AddFlags, SCEV::FlagNUW) == - SCEV::FlagNUW && + if (ScalarEvolution::hasFlags(AddFlags, SCEV::FlagNUW) && ConstAdd.ule(C1)) { PreservedFlags = ScalarEvolution::setFlags(PreservedFlags, SCEV::FlagNUW); @@ -2571,8 +2586,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, // Adding a constant with the same sign and small magnitude is NSW, if the // original AddExpr was NSW. - if (ScalarEvolution::maskFlags(AddFlags, SCEV::FlagNSW) == - SCEV::FlagNSW && + if (ScalarEvolution::hasFlags(AddFlags, SCEV::FlagNSW) && C1.isSignBitSet() == ConstAdd.isSignBitSet() && ConstAdd.abs().ule(C1.abs())) { PreservedFlags = @@ -2580,14 +2594,26 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, } if (PreservedFlags != SCEV::FlagAnyWrap) { - SmallVector<const SCEV *, 4> NewOps(AddExpr->op_begin(), - AddExpr->op_end()); + SmallVector<const SCEV *, 4> NewOps(AddExpr->operands()); NewOps[0] = getConstant(ConstAdd); return getAddExpr(NewOps, PreservedFlags); } } } + // Canonicalize (-1 * urem X, Y) + X --> (Y * X/Y) + if (Ops.size() == 2) { + const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[0]); + if (Mul && Mul->getNumOperands() == 2 && + Mul->getOperand(0)->isAllOnesValue()) { + const SCEV *X; + const SCEV *Y; + if (matchURem(Mul->getOperand(1), X, Y) && X == Ops[1]) { + return getMulExpr(Y, getUDivExpr(X, Y)); + } + } + } + // Skip past any other cast SCEVs. while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddExpr) ++Idx; @@ -2766,7 +2792,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, // If we found some loop invariants, fold them into the recurrence. if (!LIOps.empty()) { // Compute nowrap flags for the addition of the loop-invariant ops and - // the addrec. Temporarily push it as an operand for that purpose. + // the addrec. Temporarily push it as an operand for that purpose. These + // flags are valid in the scope of the addrec only. LIOps.push_back(AddRec); SCEV::NoWrapFlags Flags = ComputeFlags(LIOps); LIOps.pop_back(); @@ -2775,10 +2802,25 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, LIOps.push_back(AddRec->getStart()); SmallVector<const SCEV *, 4> AddRecOps(AddRec->operands()); - // This follows from the fact that the no-wrap flags on the outer add - // expression are applicable on the 0th iteration, when the add recurrence - // will be equal to its start value. - AddRecOps[0] = getAddExpr(LIOps, Flags, Depth + 1); + + // It is not in general safe to propagate flags valid on an add within + // the addrec scope to one outside it. We must prove that the inner + // scope is guaranteed to execute if the outer one does to be able to + // safely propagate. We know the program is undefined if poison is + // produced on the inner scoped addrec. We also know that *for this use* + // the outer scoped add can't overflow (because of the flags we just + // computed for the inner scoped add) without the program being undefined. + // Proving that entry to the outer scope neccesitates entry to the inner + // scope, thus proves the program undefined if the flags would be violated + // in the outer scope. + SCEV::NoWrapFlags AddFlags = Flags; + if (AddFlags != SCEV::FlagAnyWrap) { + auto *DefI = getDefiningScopeBound(LIOps); + auto *ReachI = &*AddRecLoop->getHeader()->begin(); + if (!isGuaranteedToTransferExecutionTo(DefI, ReachI)) + AddFlags = SCEV::FlagAnyWrap; + } + AddRecOps[0] = getAddExpr(LIOps, AddFlags, Depth + 1); // Build the new addrec. Propagate the NUW and NSW flags if both the // outer add and the inner addrec are guaranteed to have no overflow. @@ -2862,7 +2904,7 @@ ScalarEvolution::getOrCreateAddExpr(ArrayRef<const SCEV *> Ops, S = new (SCEVAllocator) SCEVAddExpr(ID.Intern(SCEVAllocator), O, Ops.size()); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Ops); } S->setNoWrapFlags(Flags); return S; @@ -2885,7 +2927,8 @@ ScalarEvolution::getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops, S = new (SCEVAllocator) SCEVAddRecExpr(ID.Intern(SCEVAllocator), O, Ops.size(), L); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + LoopUsers[L].push_back(S); + registerUser(S, Ops); } setNoWrapFlags(S, Flags); return S; @@ -2907,7 +2950,7 @@ ScalarEvolution::getOrCreateMulExpr(ArrayRef<const SCEV *> Ops, S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator), O, Ops.size()); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Ops); } S->setNoWrapFlags(Flags); return S; @@ -3022,7 +3065,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, if (Depth > MaxArithDepth || hasHugeExpression(Ops)) return getOrCreateMulExpr(Ops, ComputeFlags(Ops)); - if (SCEV *S = std::get<0>(findExistingSCEVInCache(scMulExpr, Ops))) { + if (SCEV *S = findExistingSCEVInCache(scMulExpr, Ops)) { // Don't strengthen flags if we have no new information. SCEVMulExpr *Mul = static_cast<SCEVMulExpr *>(S); if (Mul->getNoWrapFlags(OrigFlags) != OrigFlags) @@ -3416,7 +3459,7 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, SCEV *S = new (SCEVAllocator) SCEVUDivExpr(ID.Intern(SCEVAllocator), LHS, RHS); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, {LHS, RHS}); return S; } @@ -3593,13 +3636,21 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP, // getSCEV(Base)->getType() has the same address space as Base->getType() // because SCEV::getType() preserves the address space. Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType()); - // FIXME(PR23527): Don't blindly transfer the inbounds flag from the GEP - // instruction to its SCEV, because the Instruction may be guarded by control - // flow and the no-overflow bits may not be valid for the expression in any - // context. This can be fixed similarly to how these flags are handled for - // adds. + const bool AssumeInBoundsFlags = [&]() { + if (!GEP->isInBounds()) + return false; + + // We'd like to propagate flags from the IR to the corresponding SCEV nodes, + // but to do that, we have to ensure that said flag is valid in the entire + // defined scope of the SCEV. + auto *GEPI = dyn_cast<Instruction>(GEP); + // TODO: non-instructions have global scope. We might be able to prove + // some global scope cases + return GEPI && isSCEVExprNeverPoison(GEPI); + }(); + SCEV::NoWrapFlags OffsetWrap = - GEP->isInBounds() ? SCEV::FlagNSW : SCEV::FlagAnyWrap; + AssumeInBoundsFlags ? SCEV::FlagNSW : SCEV::FlagAnyWrap; Type *CurTy = GEP->getType(); bool FirstIter = true; @@ -3645,21 +3696,22 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP, // Add the base address and the offset. We cannot use the nsw flag, as the // base address is unsigned. However, if we know that the offset is // non-negative, we can use nuw. - SCEV::NoWrapFlags BaseWrap = GEP->isInBounds() && isKnownNonNegative(Offset) + SCEV::NoWrapFlags BaseWrap = AssumeInBoundsFlags && isKnownNonNegative(Offset) ? SCEV::FlagNUW : SCEV::FlagAnyWrap; - return getAddExpr(BaseExpr, Offset, BaseWrap); + auto *GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap); + assert(BaseExpr->getType() == GEPExpr->getType() && + "GEP should not change type mid-flight."); + return GEPExpr; } -std::tuple<SCEV *, FoldingSetNodeID, void *> -ScalarEvolution::findExistingSCEVInCache(SCEVTypes SCEVType, - ArrayRef<const SCEV *> Ops) { +SCEV *ScalarEvolution::findExistingSCEVInCache(SCEVTypes SCEVType, + ArrayRef<const SCEV *> Ops) { FoldingSetNodeID ID; - void *IP = nullptr; ID.AddInteger(SCEVType); for (unsigned i = 0, e = Ops.size(); i != e; ++i) ID.AddPointer(Ops[i]); - return std::tuple<SCEV *, FoldingSetNodeID, void *>( - UniqueSCEVs.FindNodeOrInsertPos(ID, IP), std::move(ID), IP); + void *IP = nullptr; + return UniqueSCEVs.FindNodeOrInsertPos(ID, IP); } const SCEV *ScalarEvolution::getAbsExpr(const SCEV *Op, bool IsNSW) { @@ -3689,7 +3741,7 @@ const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind, GroupByComplexity(Ops, &LI, DT); // Check if we have created the same expression before. - if (const SCEV *S = std::get<0>(findExistingSCEVInCache(Kind, Ops))) { + if (const SCEV *S = findExistingSCEVInCache(Kind, Ops)) { return S; } @@ -3787,10 +3839,12 @@ const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind, // Okay, it looks like we really DO need an expr. Check to see if we // already have one, otherwise create a new one. - const SCEV *ExistingSCEV; FoldingSetNodeID ID; - void *IP; - std::tie(ExistingSCEV, ID, IP) = findExistingSCEVInCache(Kind, Ops); + ID.AddInteger(Kind); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = nullptr; + const SCEV *ExistingSCEV = UniqueSCEVs.FindNodeOrInsertPos(ID, IP); if (ExistingSCEV) return ExistingSCEV; const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size()); @@ -3799,7 +3853,7 @@ const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind, SCEVMinMaxExpr(ID.Intern(SCEVAllocator), Kind, O, Ops.size()); UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); + registerUser(S, Ops); return S; } @@ -3943,6 +3997,21 @@ Type *ScalarEvolution::getWiderType(Type *T1, Type *T2) const { return getTypeSizeInBits(T1) >= getTypeSizeInBits(T2) ? T1 : T2; } +bool ScalarEvolution::instructionCouldExistWitthOperands(const SCEV *A, + const SCEV *B) { + /// For a valid use point to exist, the defining scope of one operand + /// must dominate the other. + bool PreciseA, PreciseB; + auto *ScopeA = getDefiningScopeBound({A}, PreciseA); + auto *ScopeB = getDefiningScopeBound({B}, PreciseB); + if (!PreciseA || !PreciseB) + // Can't tell. + return false; + return (ScopeA == ScopeB) || DT.dominates(ScopeA, ScopeB) || + DT.dominates(ScopeB, ScopeA); +} + + const SCEV *ScalarEvolution::getCouldNotCompute() { return CouldNotCompute.get(); } @@ -4025,24 +4094,6 @@ void ScalarEvolution::eraseValueFromMap(Value *V) { } } -/// Check whether value has nuw/nsw/exact set but SCEV does not. -/// TODO: In reality it is better to check the poison recursively -/// but this is better than nothing. -static bool SCEVLostPoisonFlags(const SCEV *S, const Value *V) { - if (auto *I = dyn_cast<Instruction>(V)) { - if (isa<OverflowingBinaryOperator>(I)) { - if (auto *NS = dyn_cast<SCEVNAryExpr>(S)) { - if (I->hasNoSignedWrap() && !NS->hasNoSignedWrap()) - return true; - if (I->hasNoUnsignedWrap() && !NS->hasNoUnsignedWrap()) - return true; - } - } else if (isa<PossiblyExactOperator>(I) && I->isExact()) - return true; - } - return false; -} - /// Return an existing SCEV if it exists, otherwise analyze the expression and /// create a new one. const SCEV *ScalarEvolution::getSCEV(Value *V) { @@ -4056,7 +4107,7 @@ const SCEV *ScalarEvolution::getSCEV(Value *V) { // ValueExprMap before insert S->{V, 0} into ExprValueMap. std::pair<ValueExprMapType::iterator, bool> Pair = ValueExprMap.insert({SCEVCallbackVH(V, this), S}); - if (Pair.second && !SCEVLostPoisonFlags(S, V)) { + if (Pair.second) { ExprValueMap[S].insert({V, nullptr}); // If S == Stripped + Offset, add Stripped -> {V, Offset} into @@ -4120,6 +4171,8 @@ static const SCEV *MatchNotExpr(const SCEV *Expr) { /// Return a SCEV corresponding to ~V = -1-V const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { + assert(!V->getType()->isPointerTy() && "Can't negate pointer"); + if (const SCEVConstant *VC = dyn_cast<SCEVConstant>(V)) return getConstant( cast<ConstantInt>(ConstantExpr::getNot(VC->getValue()))); @@ -4146,17 +4199,16 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { return getMinusSCEV(getMinusOne(Ty), V); } -/// Compute an expression equivalent to S - getPointerBase(S). -static const SCEV *removePointerBase(ScalarEvolution *SE, const SCEV *P) { +const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) { assert(P->getType()->isPointerTy()); if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(P)) { // The base of an AddRec is the first operand. SmallVector<const SCEV *> Ops{AddRec->operands()}; - Ops[0] = removePointerBase(SE, Ops[0]); + Ops[0] = removePointerBase(Ops[0]); // Don't try to transfer nowrap flags for now. We could in some cases // (for example, if pointer operand of the AddRec is a SCEVUnknown). - return SE->getAddRecExpr(Ops, AddRec->getLoop(), SCEV::FlagAnyWrap); + return getAddRecExpr(Ops, AddRec->getLoop(), SCEV::FlagAnyWrap); } if (auto *Add = dyn_cast<SCEVAddExpr>(P)) { // The base of an Add is the pointer operand. @@ -4164,21 +4216,17 @@ static const SCEV *removePointerBase(ScalarEvolution *SE, const SCEV *P) { const SCEV **PtrOp = nullptr; for (const SCEV *&AddOp : Ops) { if (AddOp->getType()->isPointerTy()) { - // If we find an Add with multiple pointer operands, treat it as a - // pointer base to be consistent with getPointerBase. Eventually - // we should be able to assert this is impossible. - if (PtrOp) - return SE->getZero(P->getType()); + assert(!PtrOp && "Cannot have multiple pointer ops"); PtrOp = &AddOp; } } - *PtrOp = removePointerBase(SE, *PtrOp); + *PtrOp = removePointerBase(*PtrOp); // Don't try to transfer nowrap flags for now. We could in some cases // (for example, if the pointer operand of the Add is a SCEVUnknown). - return SE->getAddExpr(Ops); + return getAddExpr(Ops); } // Any other expression must be a pointer base. - return SE->getZero(P->getType()); + return getZero(P->getType()); } const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, @@ -4195,8 +4243,8 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, if (!LHS->getType()->isPointerTy() || getPointerBase(LHS) != getPointerBase(RHS)) return getCouldNotCompute(); - LHS = removePointerBase(this, LHS); - RHS = removePointerBase(this, RHS); + LHS = removePointerBase(LHS); + RHS = removePointerBase(RHS); } // We represent LHS - RHS as LHS + (-1)*RHS. This transformation @@ -4204,7 +4252,7 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, auto AddFlags = SCEV::FlagAnyWrap; const bool RHSIsNotMinSigned = !getSignedRangeMin(RHS).isMinSignedValue(); - if (maskFlags(Flags, SCEV::FlagNSW) == SCEV::FlagNSW) { + if (hasFlags(Flags, SCEV::FlagNSW)) { // Let M be the minimum representable signed value. Then (-1)*RHS // signed-wraps if and only if RHS is M. That can happen even for // a NSW subtraction because e.g. (-1)*M signed-wraps even though @@ -4359,14 +4407,11 @@ const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) { const SCEV *PtrOp = nullptr; for (const SCEV *AddOp : Add->operands()) { if (AddOp->getType()->isPointerTy()) { - // Cannot find the base of an expression with multiple pointer ops. - if (PtrOp) - return V; + assert(!PtrOp && "Cannot have multiple pointer ops"); PtrOp = AddOp; } } - if (!PtrOp) // All operands were non-pointer. - return V; + assert(PtrOp && "Must have pointer op"); V = PtrOp; } else // Not something we can look further into. return V; @@ -4374,24 +4419,25 @@ const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) { } /// Push users of the given Instruction onto the given Worklist. -static void -PushDefUseChildren(Instruction *I, - SmallVectorImpl<Instruction *> &Worklist) { +static void PushDefUseChildren(Instruction *I, + SmallVectorImpl<Instruction *> &Worklist, + SmallPtrSetImpl<Instruction *> &Visited) { // Push the def-use children onto the Worklist stack. - for (User *U : I->users()) - Worklist.push_back(cast<Instruction>(U)); + for (User *U : I->users()) { + auto *UserInsn = cast<Instruction>(U); + if (Visited.insert(UserInsn).second) + Worklist.push_back(UserInsn); + } } void ScalarEvolution::forgetSymbolicName(Instruction *PN, const SCEV *SymName) { SmallVector<Instruction *, 16> Worklist; - PushDefUseChildren(PN, Worklist); - SmallPtrSet<Instruction *, 8> Visited; + SmallVector<const SCEV *, 8> ToForget; Visited.insert(PN); + Worklist.push_back(PN); while (!Worklist.empty()) { Instruction *I = Worklist.pop_back_val(); - if (!Visited.insert(I).second) - continue; auto It = ValueExprMap.find_as(static_cast<Value *>(I)); if (It != ValueExprMap.end()) { @@ -4413,12 +4459,13 @@ void ScalarEvolution::forgetSymbolicName(Instruction *PN, const SCEV *SymName) { !isa<SCEVUnknown>(Old) || (I != PN && Old == SymName)) { eraseValueFromMap(It->first); - forgetMemoizedResults(Old); + ToForget.push_back(Old); } } - PushDefUseChildren(I, Worklist); + PushDefUseChildren(I, Worklist, Visited); } + forgetMemoizedResults(ToForget); } namespace { @@ -6109,7 +6156,7 @@ ScalarEvolution::getRangeRef(const SCEV *S, // initial value. if (AddRec->hasNoUnsignedWrap()) { APInt UnsignedMinValue = getUnsignedRangeMin(AddRec->getStart()); - if (!UnsignedMinValue.isNullValue()) + if (!UnsignedMinValue.isZero()) ConservativeResult = ConservativeResult.intersectWith( ConstantRange(UnsignedMinValue, APInt(BitWidth, 0)), RangeType); } @@ -6211,9 +6258,9 @@ ScalarEvolution::getRangeRef(const SCEV *S, if (NS > 1) { // If we know any of the sign bits, we know all of the sign bits. - if (!Known.Zero.getHiBits(NS).isNullValue()) + if (!Known.Zero.getHiBits(NS).isZero()) Known.Zero.setHighBits(NS); - if (!Known.One.getHiBits(NS).isNullValue()) + if (!Known.One.getHiBits(NS).isZero()) Known.One.setHighBits(NS); } @@ -6549,17 +6596,99 @@ SCEV::NoWrapFlags ScalarEvolution::getNoWrapFlagsFromUB(const Value *V) { return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap; } -bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) { - // Here we check that I is in the header of the innermost loop containing I, - // since we only deal with instructions in the loop header. The actual loop we - // need to check later will come from an add recurrence, but getting that - // requires computing the SCEV of the operands, which can be expensive. This - // check we can do cheaply to rule out some cases early. - Loop *InnermostContainingLoop = LI.getLoopFor(I->getParent()); - if (InnermostContainingLoop == nullptr || - InnermostContainingLoop->getHeader() != I->getParent()) - return false; +const Instruction * +ScalarEvolution::getNonTrivialDefiningScopeBound(const SCEV *S) { + if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S)) + return &*AddRec->getLoop()->getHeader()->begin(); + if (auto *U = dyn_cast<SCEVUnknown>(S)) + if (auto *I = dyn_cast<Instruction>(U->getValue())) + return I; + return nullptr; +} +/// Fills \p Ops with unique operands of \p S, if it has operands. If not, +/// \p Ops remains unmodified. +static void collectUniqueOps(const SCEV *S, + SmallVectorImpl<const SCEV *> &Ops) { + SmallPtrSet<const SCEV *, 4> Unique; + auto InsertUnique = [&](const SCEV *S) { + if (Unique.insert(S).second) + Ops.push_back(S); + }; + if (auto *S2 = dyn_cast<SCEVCastExpr>(S)) + for (auto *Op : S2->operands()) + InsertUnique(Op); + else if (auto *S2 = dyn_cast<SCEVNAryExpr>(S)) + for (auto *Op : S2->operands()) + InsertUnique(Op); + else if (auto *S2 = dyn_cast<SCEVUDivExpr>(S)) + for (auto *Op : S2->operands()) + InsertUnique(Op); +} + +const Instruction * +ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops, + bool &Precise) { + Precise = true; + // Do a bounded search of the def relation of the requested SCEVs. + SmallSet<const SCEV *, 16> Visited; + SmallVector<const SCEV *> Worklist; + auto pushOp = [&](const SCEV *S) { + if (!Visited.insert(S).second) + return; + // Threshold of 30 here is arbitrary. + if (Visited.size() > 30) { + Precise = false; + return; + } + Worklist.push_back(S); + }; + + for (auto *S : Ops) + pushOp(S); + + const Instruction *Bound = nullptr; + while (!Worklist.empty()) { + auto *S = Worklist.pop_back_val(); + if (auto *DefI = getNonTrivialDefiningScopeBound(S)) { + if (!Bound || DT.dominates(Bound, DefI)) + Bound = DefI; + } else { + SmallVector<const SCEV *, 4> Ops; + collectUniqueOps(S, Ops); + for (auto *Op : Ops) + pushOp(Op); + } + } + return Bound ? Bound : &*F.getEntryBlock().begin(); +} + +const Instruction * +ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops) { + bool Discard; + return getDefiningScopeBound(Ops, Discard); +} + +bool ScalarEvolution::isGuaranteedToTransferExecutionTo(const Instruction *A, + const Instruction *B) { + if (A->getParent() == B->getParent() && + isGuaranteedToTransferExecutionToSuccessor(A->getIterator(), + B->getIterator())) + return true; + + auto *BLoop = LI.getLoopFor(B->getParent()); + if (BLoop && BLoop->getHeader() == B->getParent() && + BLoop->getLoopPreheader() == A->getParent() && + isGuaranteedToTransferExecutionToSuccessor(A->getIterator(), + A->getParent()->end()) && + isGuaranteedToTransferExecutionToSuccessor(B->getParent()->begin(), + B->getIterator())) + return true; + return false; +} + + +bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) { // Only proceed if we can prove that I does not yield poison. if (!programUndefinedIfPoison(I)) return false; @@ -6570,39 +6699,20 @@ bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) { // instructions can map to the same SCEV. If we apply NSW or NUW from I to // the SCEV, we must guarantee no wrapping for that SCEV also when it is // derived from other instructions that map to the same SCEV. We cannot make - // that guarantee for cases where I is not executed. So we need to find the - // loop that I is considered in relation to and prove that I is executed for - // every iteration of that loop. That implies that the value that I - // calculates does not wrap anywhere in the loop, so then we can apply the - // flags to the SCEV. - // - // We check isLoopInvariant to disambiguate in case we are adding recurrences - // from different loops, so that we know which loop to prove that I is - // executed in. - for (unsigned OpIndex = 0; OpIndex < I->getNumOperands(); ++OpIndex) { + // that guarantee for cases where I is not executed. So we need to find a + // upper bound on the defining scope for the SCEV, and prove that I is + // executed every time we enter that scope. When the bounding scope is a + // loop (the common case), this is equivalent to proving I executes on every + // iteration of that loop. + SmallVector<const SCEV *> SCEVOps; + for (const Use &Op : I->operands()) { // I could be an extractvalue from a call to an overflow intrinsic. // TODO: We can do better here in some cases. - if (!isSCEVable(I->getOperand(OpIndex)->getType())) - return false; - const SCEV *Op = getSCEV(I->getOperand(OpIndex)); - if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(Op)) { - bool AllOtherOpsLoopInvariant = true; - for (unsigned OtherOpIndex = 0; OtherOpIndex < I->getNumOperands(); - ++OtherOpIndex) { - if (OtherOpIndex != OpIndex) { - const SCEV *OtherOp = getSCEV(I->getOperand(OtherOpIndex)); - if (!isLoopInvariant(OtherOp, AddRec->getLoop())) { - AllOtherOpsLoopInvariant = false; - break; - } - } - } - if (AllOtherOpsLoopInvariant && - isGuaranteedToExecuteForEveryIteration(I, AddRec->getLoop())) - return true; - } + if (isSCEVable(Op->getType())) + SCEVOps.push_back(getSCEV(Op)); } - return false; + auto *DefI = getDefiningScopeBound(SCEVOps); + return isGuaranteedToTransferExecutionTo(DefI, I); } bool ScalarEvolution::isAddRecNeverPoison(const Instruction *I, const Loop *L) { @@ -7144,10 +7254,21 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { // Iteration Count Computation Code // -const SCEV *ScalarEvolution::getTripCountFromExitCount(const SCEV *ExitCount) { - // Get the trip count from the BE count by adding 1. Overflow, results - // in zero which means "unknown". - return getAddExpr(ExitCount, getOne(ExitCount->getType())); +const SCEV *ScalarEvolution::getTripCountFromExitCount(const SCEV *ExitCount, + bool Extend) { + if (isa<SCEVCouldNotCompute>(ExitCount)) + return getCouldNotCompute(); + + auto *ExitCountType = ExitCount->getType(); + assert(ExitCountType->isIntegerTy()); + + if (!Extend) + return getAddExpr(ExitCount, getOne(ExitCountType)); + + auto *WiderType = Type::getIntNTy(ExitCountType->getContext(), + 1 + ExitCountType->getScalarSizeInBits()); + return getAddExpr(getNoopOrZeroExtend(ExitCount, WiderType), + getOne(WiderType)); } static unsigned getConstantTripCount(const SCEVConstant *ExitCount) { @@ -7186,6 +7307,131 @@ unsigned ScalarEvolution::getSmallConstantMaxTripCount(const Loop *L) { return getConstantTripCount(MaxExitCount); } +const SCEV *ScalarEvolution::getConstantMaxTripCountFromArray(const Loop *L) { + // We can't infer from Array in Irregular Loop. + // FIXME: It's hard to infer loop bound from array operated in Nested Loop. + if (!L->isLoopSimplifyForm() || !L->isInnermost()) + return getCouldNotCompute(); + + // FIXME: To make the scene more typical, we only analysis loops that have + // one exiting block and that block must be the latch. To make it easier to + // capture loops that have memory access and memory access will be executed + // in each iteration. + const BasicBlock *LoopLatch = L->getLoopLatch(); + assert(LoopLatch && "See defination of simplify form loop."); + if (L->getExitingBlock() != LoopLatch) + return getCouldNotCompute(); + + const DataLayout &DL = getDataLayout(); + SmallVector<const SCEV *> InferCountColl; + for (auto *BB : L->getBlocks()) { + // Go here, we can know that Loop is a single exiting and simplified form + // loop. Make sure that infer from Memory Operation in those BBs must be + // executed in loop. First step, we can make sure that max execution time + // of MemAccessBB in loop represents latch max excution time. + // If MemAccessBB does not dom Latch, skip. + // Entry + // │ + // ┌─────▼─────┐ + // │Loop Header◄─────┐ + // └──┬──────┬─┘ │ + // │ │ │ + // ┌────────▼──┐ ┌─▼─────┐ │ + // │MemAccessBB│ │OtherBB│ │ + // └────────┬──┘ └─┬─────┘ │ + // │ │ │ + // ┌─▼──────▼─┐ │ + // │Loop Latch├─────┘ + // └────┬─────┘ + // ▼ + // Exit + if (!DT.dominates(BB, LoopLatch)) + continue; + + for (Instruction &Inst : *BB) { + // Find Memory Operation Instruction. + auto *GEP = getLoadStorePointerOperand(&Inst); + if (!GEP) + continue; + + auto *ElemSize = dyn_cast<SCEVConstant>(getElementSize(&Inst)); + // Do not infer from scalar type, eg."ElemSize = sizeof()". + if (!ElemSize) + continue; + + // Use a existing polynomial recurrence on the trip count. + auto *AddRec = dyn_cast<SCEVAddRecExpr>(getSCEV(GEP)); + if (!AddRec) + continue; + auto *ArrBase = dyn_cast<SCEVUnknown>(getPointerBase(AddRec)); + auto *Step = dyn_cast<SCEVConstant>(AddRec->getStepRecurrence(*this)); + if (!ArrBase || !Step) + continue; + assert(isLoopInvariant(ArrBase, L) && "See addrec definition"); + + // Only handle { %array + step }, + // FIXME: {(SCEVAddRecExpr) + step } could not be analysed here. + if (AddRec->getStart() != ArrBase) + continue; + + // Memory operation pattern which have gaps. + // Or repeat memory opreation. + // And index of GEP wraps arround. + if (Step->getAPInt().getActiveBits() > 32 || + Step->getAPInt().getZExtValue() != + ElemSize->getAPInt().getZExtValue() || + Step->isZero() || Step->getAPInt().isNegative()) + continue; + + // Only infer from stack array which has certain size. + // Make sure alloca instruction is not excuted in loop. + AllocaInst *AllocateInst = dyn_cast<AllocaInst>(ArrBase->getValue()); + if (!AllocateInst || L->contains(AllocateInst->getParent())) + continue; + + // Make sure only handle normal array. + auto *Ty = dyn_cast<ArrayType>(AllocateInst->getAllocatedType()); + auto *ArrSize = dyn_cast<ConstantInt>(AllocateInst->getArraySize()); + if (!Ty || !ArrSize || !ArrSize->isOne()) + continue; + // Also make sure step was increased the same with sizeof allocated + // element type. + const PointerType *GEPT = dyn_cast<PointerType>(GEP->getType()); + if (Ty->getElementType() != GEPT->getElementType()) + continue; + + // FIXME: Since gep indices are silently zext to the indexing type, + // we will have a narrow gep index which wraps around rather than + // increasing strictly, we shoule ensure that step is increasing + // strictly by the loop iteration. + // Now we can infer a max execution time by MemLength/StepLength. + const SCEV *MemSize = + getConstant(Step->getType(), DL.getTypeAllocSize(Ty)); + auto *MaxExeCount = + dyn_cast<SCEVConstant>(getUDivCeilSCEV(MemSize, Step)); + if (!MaxExeCount || MaxExeCount->getAPInt().getActiveBits() > 32) + continue; + + // If the loop reaches the maximum number of executions, we can not + // access bytes starting outside the statically allocated size without + // being immediate UB. But it is allowed to enter loop header one more + // time. + auto *InferCount = dyn_cast<SCEVConstant>( + getAddExpr(MaxExeCount, getOne(MaxExeCount->getType()))); + // Discard the maximum number of execution times under 32bits. + if (!InferCount || InferCount->getAPInt().getActiveBits() > 32) + continue; + + InferCountColl.push_back(InferCount); + } + } + + if (InferCountColl.size() == 0) + return getCouldNotCompute(); + + return getUMinFromMismatchedTypes(InferCountColl); +} + unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L) { SmallVector<BasicBlock *, 8> ExitingBlocks; L->getExitingBlocks(ExitingBlocks); @@ -7287,13 +7533,15 @@ bool ScalarEvolution::isBackedgeTakenCountMaxOrZero(const Loop *L) { } /// Push PHI nodes in the header of the given loop onto the given Worklist. -static void -PushLoopPHIs(const Loop *L, SmallVectorImpl<Instruction *> &Worklist) { +static void PushLoopPHIs(const Loop *L, + SmallVectorImpl<Instruction *> &Worklist, + SmallPtrSetImpl<Instruction *> &Visited) { BasicBlock *Header = L->getHeader(); // Push all Loop-header PHIs onto the Worklist stack. for (PHINode &PN : Header->phis()) - Worklist.push_back(&PN); + if (Visited.insert(&PN).second) + Worklist.push_back(&PN); } const ScalarEvolution::BackedgeTakenInfo & @@ -7354,9 +7602,9 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // it handles SCEVUnknown PHI nodes specially. if (Result.hasAnyInfo()) { SmallVector<Instruction *, 16> Worklist; - PushLoopPHIs(L, Worklist); - SmallPtrSet<Instruction *, 8> Discovered; + SmallVector<const SCEV *, 8> ToForget; + PushLoopPHIs(L, Worklist, Discovered); while (!Worklist.empty()) { Instruction *I = Worklist.pop_back_val(); @@ -7373,7 +7621,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // own when it gets to that point. if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) { eraseValueFromMap(It->first); - forgetMemoizedResults(Old); + ToForget.push_back(Old); } if (PHINode *PN = dyn_cast<PHINode>(I)) ConstantEvolutionLoopExitValue.erase(PN); @@ -7405,6 +7653,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { Worklist.push_back(I); } } + forgetMemoizedResults(ToForget); } // Re-lookup the insert position, since the call to @@ -7441,6 +7690,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) { SmallVector<const Loop *, 16> LoopWorklist(1, L); SmallVector<Instruction *, 32> Worklist; SmallPtrSet<Instruction *, 16> Visited; + SmallVector<const SCEV *, 16> ToForget; // Iterate over all the loops and sub-loops to drop SCEV information. while (!LoopWorklist.empty()) { @@ -7462,29 +7712,27 @@ void ScalarEvolution::forgetLoop(const Loop *L) { auto LoopUsersItr = LoopUsers.find(CurrL); if (LoopUsersItr != LoopUsers.end()) { - for (auto *S : LoopUsersItr->second) - forgetMemoizedResults(S); + ToForget.insert(ToForget.end(), LoopUsersItr->second.begin(), + LoopUsersItr->second.end()); LoopUsers.erase(LoopUsersItr); } // Drop information about expressions based on loop-header PHIs. - PushLoopPHIs(CurrL, Worklist); + PushLoopPHIs(CurrL, Worklist, Visited); while (!Worklist.empty()) { Instruction *I = Worklist.pop_back_val(); - if (!Visited.insert(I).second) - continue; ValueExprMapType::iterator It = ValueExprMap.find_as(static_cast<Value *>(I)); if (It != ValueExprMap.end()) { eraseValueFromMap(It->first); - forgetMemoizedResults(It->second); + ToForget.push_back(It->second); if (PHINode *PN = dyn_cast<PHINode>(I)) ConstantEvolutionLoopExitValue.erase(PN); } - PushDefUseChildren(I, Worklist); + PushDefUseChildren(I, Worklist, Visited); } LoopPropertiesCache.erase(CurrL); @@ -7492,6 +7740,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) { // ValuesAtScopes map. LoopWorklist.append(CurrL->begin(), CurrL->end()); } + forgetMemoizedResults(ToForget); } void ScalarEvolution::forgetTopmostLoop(const Loop *L) { @@ -7506,25 +7755,25 @@ void ScalarEvolution::forgetValue(Value *V) { // Drop information about expressions based on loop-header PHIs. SmallVector<Instruction *, 16> Worklist; + SmallPtrSet<Instruction *, 8> Visited; + SmallVector<const SCEV *, 8> ToForget; Worklist.push_back(I); + Visited.insert(I); - SmallPtrSet<Instruction *, 8> Visited; while (!Worklist.empty()) { I = Worklist.pop_back_val(); - if (!Visited.insert(I).second) - continue; - ValueExprMapType::iterator It = ValueExprMap.find_as(static_cast<Value *>(I)); if (It != ValueExprMap.end()) { eraseValueFromMap(It->first); - forgetMemoizedResults(It->second); + ToForget.push_back(It->second); if (PHINode *PN = dyn_cast<PHINode>(I)) ConstantEvolutionLoopExitValue.erase(PN); } - PushDefUseChildren(I, Worklist); + PushDefUseChildren(I, Worklist, Visited); } + forgetMemoizedResults(ToForget); } void ScalarEvolution::forgetLoopDispositions(const Loop *L) { @@ -7598,7 +7847,7 @@ ScalarEvolution::BackedgeTakenInfo::getConstantMax(ScalarEvolution *SE) const { return !ENT.hasAlwaysTruePredicate(); }; - if (any_of(ExitNotTaken, PredicateNotAlwaysTrue) || !getConstantMax()) + if (!getConstantMax() || any_of(ExitNotTaken, PredicateNotAlwaysTrue)) return SE->getCouldNotCompute(); assert((isa<SCEVCouldNotCompute>(getConstantMax()) || @@ -7635,6 +7884,12 @@ ScalarEvolution::ExitLimit::ExitLimit( const SCEV *E, const SCEV *M, bool MaxOrZero, ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *> PredSetList) : ExactNotTaken(E), MaxNotTaken(M), MaxOrZero(MaxOrZero) { + // If we prove the max count is zero, so is the symbolic bound. This happens + // in practice due to differences in a) how context sensitive we've chosen + // to be and b) how we reason about bounds impied by UB. + if (MaxNotTaken->isZero()) + ExactNotTaken = MaxNotTaken; + assert((isa<SCEVCouldNotCompute>(ExactNotTaken) || !isa<SCEVCouldNotCompute>(MaxNotTaken)) && "Exact is not allowed to be less precise than Max"); @@ -7740,7 +7995,7 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L, if (auto *BI = dyn_cast<BranchInst>(ExitBB->getTerminator())) if (auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) { bool ExitIfTrue = !L->contains(BI->getSuccessor(0)); - if ((ExitIfTrue && CI->isZero()) || (!ExitIfTrue && CI->isOne())) + if (ExitIfTrue == CI->isZero()) continue; } @@ -8030,15 +8285,6 @@ ScalarEvolution::computeExitLimitFromICmp(const Loop *L, Pred = ExitCond->getInversePredicate(); const ICmpInst::Predicate OriginalPred = Pred; - // Handle common loops like: for (X = "string"; *X; ++X) - if (LoadInst *LI = dyn_cast<LoadInst>(ExitCond->getOperand(0))) - if (Constant *RHS = dyn_cast<Constant>(ExitCond->getOperand(1))) { - ExitLimit ItCnt = - computeLoadConstantCompareExitLimit(LI, RHS, L, Pred); - if (ItCnt.hasAnyInfo()) - return ItCnt; - } - const SCEV *LHS = getSCEV(ExitCond->getOperand(0)); const SCEV *RHS = getSCEV(ExitCond->getOperand(1)); @@ -8070,6 +8316,32 @@ ScalarEvolution::computeExitLimitFromICmp(const Loop *L, if (!isa<SCEVCouldNotCompute>(Ret)) return Ret; } + // If this loop must exit based on this condition (or execute undefined + // behaviour), and we can prove the test sequence produced must repeat + // the same values on self-wrap of the IV, then we can infer that IV + // doesn't self wrap because if it did, we'd have an infinite (undefined) + // loop. + if (ControlsExit && isLoopInvariant(RHS, L) && loopHasNoAbnormalExits(L) && + loopIsFiniteByAssumption(L)) { + + // TODO: We can peel off any functions which are invertible *in L*. Loop + // invariant terms are effectively constants for our purposes here. + auto *InnerLHS = LHS; + if (auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(LHS)) + InnerLHS = ZExt->getOperand(); + if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(InnerLHS)) { + auto *StrideC = dyn_cast<SCEVConstant>(AR->getStepRecurrence(*this)); + if (!AR->hasNoSelfWrap() && AR->getLoop() == L && AR->isAffine() && + StrideC && StrideC->getAPInt().isPowerOf2()) { + auto Flags = AR->getNoWrapFlags(); + Flags = setFlags(Flags, SCEV::FlagNW); + SmallVector<const SCEV*> Operands{AR->operands()}; + Flags = StrengthenNoWrapFlags(this, scAddRecExpr, Operands, Flags); + setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), Flags); + } + } + } + switch (Pred) { case ICmpInst::ICMP_NE: { // while (X != Y) // Convert to: while (X-Y != 0) @@ -8169,85 +8441,6 @@ EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C, return cast<SCEVConstant>(Val)->getValue(); } -/// Given an exit condition of 'icmp op load X, cst', try to see if we can -/// compute the backedge execution count. -ScalarEvolution::ExitLimit -ScalarEvolution::computeLoadConstantCompareExitLimit( - LoadInst *LI, - Constant *RHS, - const Loop *L, - ICmpInst::Predicate predicate) { - if (LI->isVolatile()) return getCouldNotCompute(); - - // Check to see if the loaded pointer is a getelementptr of a global. - // TODO: Use SCEV instead of manually grubbing with GEPs. - GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(LI->getOperand(0)); - if (!GEP) return getCouldNotCompute(); - - // Make sure that it is really a constant global we are gepping, with an - // initializer, and make sure the first IDX is really 0. - GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)); - if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer() || - GEP->getNumOperands() < 3 || !isa<Constant>(GEP->getOperand(1)) || - !cast<Constant>(GEP->getOperand(1))->isNullValue()) - return getCouldNotCompute(); - - // Okay, we allow one non-constant index into the GEP instruction. - Value *VarIdx = nullptr; - std::vector<Constant*> Indexes; - unsigned VarIdxNum = 0; - for (unsigned i = 2, e = GEP->getNumOperands(); i != e; ++i) - if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(i))) { - Indexes.push_back(CI); - } else if (!isa<ConstantInt>(GEP->getOperand(i))) { - if (VarIdx) return getCouldNotCompute(); // Multiple non-constant idx's. - VarIdx = GEP->getOperand(i); - VarIdxNum = i-2; - Indexes.push_back(nullptr); - } - - // Loop-invariant loads may be a byproduct of loop optimization. Skip them. - if (!VarIdx) - return getCouldNotCompute(); - - // Okay, we know we have a (load (gep GV, 0, X)) comparison with a constant. - // Check to see if X is a loop variant variable value now. - const SCEV *Idx = getSCEV(VarIdx); - Idx = getSCEVAtScope(Idx, L); - - // We can only recognize very limited forms of loop index expressions, in - // particular, only affine AddRec's like {C1,+,C2}<L>. - const SCEVAddRecExpr *IdxExpr = dyn_cast<SCEVAddRecExpr>(Idx); - if (!IdxExpr || IdxExpr->getLoop() != L || !IdxExpr->isAffine() || - isLoopInvariant(IdxExpr, L) || - !isa<SCEVConstant>(IdxExpr->getOperand(0)) || - !isa<SCEVConstant>(IdxExpr->getOperand(1))) - return getCouldNotCompute(); - - unsigned MaxSteps = MaxBruteForceIterations; - for (unsigned IterationNum = 0; IterationNum != MaxSteps; ++IterationNum) { - ConstantInt *ItCst = ConstantInt::get( - cast<IntegerType>(IdxExpr->getType()), IterationNum); - ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst, *this); - - // Form the GEP offset. - Indexes[VarIdxNum] = Val; - - Constant *Result = ConstantFoldLoadThroughGEPIndices(GV->getInitializer(), - Indexes); - if (!Result) break; // Cannot compute! - - // Evaluate the condition for this iteration. - Result = ConstantExpr::getICmp(predicate, Result, RHS); - if (!isa<ConstantInt>(Result)) break; // Couldn't decide for sure - if (cast<ConstantInt>(Result)->getValue().isMinValue()) { - ++NumArrayLenItCounts; - return getConstant(ItCst); // Found terminating iteration! - } - } - return getCouldNotCompute(); -} - ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit( Value *LHS, Value *RHSV, const Loop *L, ICmpInst::Predicate Pred) { ConstantInt *RHS = dyn_cast<ConstantInt>(RHSV); @@ -9160,7 +9353,7 @@ GetQuadraticEquation(const SCEVAddRecExpr *AddRec) { APInt L = LC->getAPInt(); APInt M = MC->getAPInt(); APInt N = NC->getAPInt(); - assert(!N.isNullValue() && "This is not a quadratic addrec"); + assert(!N.isZero() && "This is not a quadratic addrec"); unsigned BitWidth = LC->getAPInt().getBitWidth(); unsigned NewWidth = BitWidth + 1; @@ -9486,9 +9679,7 @@ ScalarEvolution::howFarToZero(const SCEV *V, const Loop *L, bool ControlsExit, // N = Distance (as unsigned) if (StepC->getValue()->isOne() || StepC->getValue()->isMinusOne()) { APInt MaxBECount = getUnsignedRangeMax(applyLoopGuards(Distance, L)); - APInt MaxBECountBase = getUnsignedRangeMax(Distance); - if (MaxBECountBase.ult(MaxBECount)) - MaxBECount = MaxBECountBase; + MaxBECount = APIntOps::umin(MaxBECount, getUnsignedRangeMax(Distance)); // When a loop like "for (int i = 0; i != n; ++i) { /* body */ }" is rotated, // we end up with a loop whose backedge-taken count is n - 1. Detect this @@ -9521,11 +9712,7 @@ ScalarEvolution::howFarToZero(const SCEV *V, const Loop *L, bool ControlsExit, const SCEV *Max = getCouldNotCompute(); if (Exact != getCouldNotCompute()) { APInt MaxInt = getUnsignedRangeMax(applyLoopGuards(Exact, L)); - APInt BaseMaxInt = getUnsignedRangeMax(Exact); - if (BaseMaxInt.ult(MaxInt)) - Max = getConstant(BaseMaxInt); - else - Max = getConstant(MaxInt); + Max = getConstant(APIntOps::umin(MaxInt, getUnsignedRangeMax(Exact))); } return ExitLimit(Exact, Max, false, Predicates); } @@ -9533,9 +9720,12 @@ ScalarEvolution::howFarToZero(const SCEV *V, const Loop *L, bool ControlsExit, // Solve the general equation. const SCEV *E = SolveLinEquationWithOverflow(StepC->getAPInt(), getNegativeSCEV(Start), *this); - const SCEV *M = E == getCouldNotCompute() - ? E - : getConstant(getUnsignedRangeMax(E)); + + const SCEV *M = E; + if (E != getCouldNotCompute()) { + APInt MaxWithGuards = getUnsignedRangeMax(applyLoopGuards(E, L)); + M = getConstant(APIntOps::umin(MaxWithGuards, getUnsignedRangeMax(E))); + } return ExitLimit(E, M, false, Predicates); } @@ -9911,23 +10101,23 @@ Optional<bool> ScalarEvolution::evaluatePredicate(ICmpInst::Predicate Pred, bool ScalarEvolution::isKnownPredicateAt(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, - const Instruction *Context) { + const Instruction *CtxI) { // TODO: Analyze guards and assumes from Context's block. return isKnownPredicate(Pred, LHS, RHS) || - isBasicBlockEntryGuardedByCond(Context->getParent(), Pred, LHS, RHS); + isBasicBlockEntryGuardedByCond(CtxI->getParent(), Pred, LHS, RHS); } -Optional<bool> -ScalarEvolution::evaluatePredicateAt(ICmpInst::Predicate Pred, const SCEV *LHS, - const SCEV *RHS, - const Instruction *Context) { +Optional<bool> ScalarEvolution::evaluatePredicateAt(ICmpInst::Predicate Pred, + const SCEV *LHS, + const SCEV *RHS, + const Instruction *CtxI) { Optional<bool> KnownWithoutContext = evaluatePredicate(Pred, LHS, RHS); if (KnownWithoutContext) return KnownWithoutContext; - if (isBasicBlockEntryGuardedByCond(Context->getParent(), Pred, LHS, RHS)) + if (isBasicBlockEntryGuardedByCond(CtxI->getParent(), Pred, LHS, RHS)) return true; - else if (isBasicBlockEntryGuardedByCond(Context->getParent(), + else if (isBasicBlockEntryGuardedByCond(CtxI->getParent(), ICmpInst::getInversePredicate(Pred), LHS, RHS)) return false; @@ -10057,7 +10247,7 @@ ScalarEvolution::getLoopInvariantPredicate(ICmpInst::Predicate Pred, Optional<ScalarEvolution::LoopInvariantPredicate> ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations( ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const Loop *L, - const Instruction *Context, const SCEV *MaxIter) { + const Instruction *CtxI, const SCEV *MaxIter) { // Try to prove the following set of facts: // - The predicate is monotonic in the iteration space. // - If the check does not fail on the 1st iteration: @@ -10111,7 +10301,7 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations( if (Step == MinusOne) NoOverflowPred = CmpInst::getSwappedPredicate(NoOverflowPred); const SCEV *Start = AR->getStart(); - if (!isKnownPredicateAt(NoOverflowPred, Start, Last, Context)) + if (!isKnownPredicateAt(NoOverflowPred, Start, Last, CtxI)) return None; // Everything is fine. @@ -10448,12 +10638,12 @@ bool ScalarEvolution::isBasicBlockEntryGuardedByCond(const BasicBlock *BB, // Try to prove (Pred, LHS, RHS) using isImpliedCond. auto ProveViaCond = [&](const Value *Condition, bool Inverse) { - const Instruction *Context = &BB->front(); - if (isImpliedCond(Pred, LHS, RHS, Condition, Inverse, Context)) + const Instruction *CtxI = &BB->front(); + if (isImpliedCond(Pred, LHS, RHS, Condition, Inverse, CtxI)) return true; if (ProvingStrictComparison) { auto ProofFn = [&](ICmpInst::Predicate P) { - return isImpliedCond(P, LHS, RHS, Condition, Inverse, Context); + return isImpliedCond(P, LHS, RHS, Condition, Inverse, CtxI); }; if (SplitAndProve(ProofFn)) return true; @@ -10525,7 +10715,7 @@ bool ScalarEvolution::isLoopEntryGuardedByCond(const Loop *L, bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const Value *FoundCondValue, bool Inverse, - const Instruction *Context) { + const Instruction *CtxI) { // False conditions implies anything. Do not bother analyzing it further. if (FoundCondValue == ConstantInt::getBool(FoundCondValue->getContext(), Inverse)) @@ -10541,12 +10731,12 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const Value *Op0, *Op1; if (match(FoundCondValue, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) { if (!Inverse) - return isImpliedCond(Pred, LHS, RHS, Op0, Inverse, Context) || - isImpliedCond(Pred, LHS, RHS, Op1, Inverse, Context); + return isImpliedCond(Pred, LHS, RHS, Op0, Inverse, CtxI) || + isImpliedCond(Pred, LHS, RHS, Op1, Inverse, CtxI); } else if (match(FoundCondValue, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) { if (Inverse) - return isImpliedCond(Pred, LHS, RHS, Op0, Inverse, Context) || - isImpliedCond(Pred, LHS, RHS, Op1, Inverse, Context); + return isImpliedCond(Pred, LHS, RHS, Op0, Inverse, CtxI) || + isImpliedCond(Pred, LHS, RHS, Op1, Inverse, CtxI); } const ICmpInst *ICI = dyn_cast<ICmpInst>(FoundCondValue); @@ -10563,14 +10753,14 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *FoundLHS = getSCEV(ICI->getOperand(0)); const SCEV *FoundRHS = getSCEV(ICI->getOperand(1)); - return isImpliedCond(Pred, LHS, RHS, FoundPred, FoundLHS, FoundRHS, Context); + return isImpliedCond(Pred, LHS, RHS, FoundPred, FoundLHS, FoundRHS, CtxI); } bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, ICmpInst::Predicate FoundPred, const SCEV *FoundLHS, const SCEV *FoundRHS, - const Instruction *Context) { + const Instruction *CtxI) { // Balance the types. if (getTypeSizeInBits(LHS->getType()) < getTypeSizeInBits(FoundLHS->getType())) { @@ -10583,12 +10773,14 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, auto BitWidth = getTypeSizeInBits(NarrowType); const SCEV *MaxValue = getZeroExtendExpr( getConstant(APInt::getMaxValue(BitWidth)), WideType); - if (isKnownPredicate(ICmpInst::ICMP_ULE, FoundLHS, MaxValue) && - isKnownPredicate(ICmpInst::ICMP_ULE, FoundRHS, MaxValue)) { + if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, FoundLHS, + MaxValue) && + isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, FoundRHS, + MaxValue)) { const SCEV *TruncFoundLHS = getTruncateExpr(FoundLHS, NarrowType); const SCEV *TruncFoundRHS = getTruncateExpr(FoundRHS, NarrowType); if (isImpliedCondBalancedTypes(Pred, LHS, RHS, FoundPred, TruncFoundLHS, - TruncFoundRHS, Context)) + TruncFoundRHS, CtxI)) return true; } } @@ -10615,13 +10807,13 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, } } return isImpliedCondBalancedTypes(Pred, LHS, RHS, FoundPred, FoundLHS, - FoundRHS, Context); + FoundRHS, CtxI); } bool ScalarEvolution::isImpliedCondBalancedTypes( ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, ICmpInst::Predicate FoundPred, const SCEV *FoundLHS, const SCEV *FoundRHS, - const Instruction *Context) { + const Instruction *CtxI) { assert(getTypeSizeInBits(LHS->getType()) == getTypeSizeInBits(FoundLHS->getType()) && "Types should be balanced!"); @@ -10647,7 +10839,7 @@ bool ScalarEvolution::isImpliedCondBalancedTypes( // Check whether the found predicate is the same as the desired predicate. if (FoundPred == Pred) - return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, Context); + return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI); // Check whether swapping the found predicate makes it the same as the // desired predicate. @@ -10663,27 +10855,70 @@ bool ScalarEvolution::isImpliedCondBalancedTypes( // do this if it would break canonical constant/addrec ordering. if (!isa<SCEVConstant>(RHS) && !isa<SCEVAddRecExpr>(LHS)) return isImpliedCondOperands(FoundPred, RHS, LHS, FoundLHS, FoundRHS, - Context); + CtxI); if (!isa<SCEVConstant>(FoundRHS) && !isa<SCEVAddRecExpr>(FoundLHS)) - return isImpliedCondOperands(Pred, LHS, RHS, FoundRHS, FoundLHS, Context); + return isImpliedCondOperands(Pred, LHS, RHS, FoundRHS, FoundLHS, CtxI); - // Don't try to getNotSCEV pointers. - if (LHS->getType()->isPointerTy() || FoundLHS->getType()->isPointerTy()) - return false; + // There's no clear preference between forms 3. and 4., try both. Avoid + // forming getNotSCEV of pointer values as the resulting subtract is + // not legal. + if (!LHS->getType()->isPointerTy() && !RHS->getType()->isPointerTy() && + isImpliedCondOperands(FoundPred, getNotSCEV(LHS), getNotSCEV(RHS), + FoundLHS, FoundRHS, CtxI)) + return true; - // There's no clear preference between forms 3. and 4., try both. - return isImpliedCondOperands(FoundPred, getNotSCEV(LHS), getNotSCEV(RHS), - FoundLHS, FoundRHS, Context) || - isImpliedCondOperands(Pred, LHS, RHS, getNotSCEV(FoundLHS), - getNotSCEV(FoundRHS), Context); + if (!FoundLHS->getType()->isPointerTy() && + !FoundRHS->getType()->isPointerTy() && + isImpliedCondOperands(Pred, LHS, RHS, getNotSCEV(FoundLHS), + getNotSCEV(FoundRHS), CtxI)) + return true; + + return false; } - // Unsigned comparison is the same as signed comparison when both the operands - // are non-negative. - if (CmpInst::isUnsigned(FoundPred) && - CmpInst::getSignedPredicate(FoundPred) == Pred && - isKnownNonNegative(FoundLHS) && isKnownNonNegative(FoundRHS)) - return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, Context); + auto IsSignFlippedPredicate = [](CmpInst::Predicate P1, + CmpInst::Predicate P2) { + assert(P1 != P2 && "Handled earlier!"); + return CmpInst::isRelational(P2) && + P1 == CmpInst::getFlippedSignednessPredicate(P2); + }; + if (IsSignFlippedPredicate(Pred, FoundPred)) { + // Unsigned comparison is the same as signed comparison when both the + // operands are non-negative or negative. + if ((isKnownNonNegative(FoundLHS) && isKnownNonNegative(FoundRHS)) || + (isKnownNegative(FoundLHS) && isKnownNegative(FoundRHS))) + return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI); + // Create local copies that we can freely swap and canonicalize our + // conditions to "le/lt". + ICmpInst::Predicate CanonicalPred = Pred, CanonicalFoundPred = FoundPred; + const SCEV *CanonicalLHS = LHS, *CanonicalRHS = RHS, + *CanonicalFoundLHS = FoundLHS, *CanonicalFoundRHS = FoundRHS; + if (ICmpInst::isGT(CanonicalPred) || ICmpInst::isGE(CanonicalPred)) { + CanonicalPred = ICmpInst::getSwappedPredicate(CanonicalPred); + CanonicalFoundPred = ICmpInst::getSwappedPredicate(CanonicalFoundPred); + std::swap(CanonicalLHS, CanonicalRHS); + std::swap(CanonicalFoundLHS, CanonicalFoundRHS); + } + assert((ICmpInst::isLT(CanonicalPred) || ICmpInst::isLE(CanonicalPred)) && + "Must be!"); + assert((ICmpInst::isLT(CanonicalFoundPred) || + ICmpInst::isLE(CanonicalFoundPred)) && + "Must be!"); + if (ICmpInst::isSigned(CanonicalPred) && isKnownNonNegative(CanonicalRHS)) + // Use implication: + // x <u y && y >=s 0 --> x <s y. + // If we can prove the left part, the right part is also proven. + return isImpliedCondOperands(CanonicalFoundPred, CanonicalLHS, + CanonicalRHS, CanonicalFoundLHS, + CanonicalFoundRHS); + if (ICmpInst::isUnsigned(CanonicalPred) && isKnownNegative(CanonicalRHS)) + // Use implication: + // x <s y && y <s 0 --> x <u y. + // If we can prove the left part, the right part is also proven. + return isImpliedCondOperands(CanonicalFoundPred, CanonicalLHS, + CanonicalRHS, CanonicalFoundLHS, + CanonicalFoundRHS); + } // Check if we can make progress by sharpening ranges. if (FoundPred == ICmpInst::ICMP_NE && @@ -10721,7 +10956,7 @@ bool ScalarEvolution::isImpliedCondBalancedTypes( // We know V `Pred` SharperMin. If this implies LHS `Pred` // RHS, we're done. if (isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(SharperMin), - Context)) + CtxI)) return true; LLVM_FALLTHROUGH; @@ -10736,8 +10971,7 @@ bool ScalarEvolution::isImpliedCondBalancedTypes( // // If V `Pred` Min implies LHS `Pred` RHS, we're done. - if (isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(Min), - Context)) + if (isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(Min), CtxI)) return true; break; @@ -10745,14 +10979,14 @@ bool ScalarEvolution::isImpliedCondBalancedTypes( case ICmpInst::ICMP_SLE: case ICmpInst::ICMP_ULE: if (isImpliedCondOperands(CmpInst::getSwappedPredicate(Pred), RHS, - LHS, V, getConstant(SharperMin), Context)) + LHS, V, getConstant(SharperMin), CtxI)) return true; LLVM_FALLTHROUGH; case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_ULT: if (isImpliedCondOperands(CmpInst::getSwappedPredicate(Pred), RHS, - LHS, V, getConstant(Min), Context)) + LHS, V, getConstant(Min), CtxI)) return true; break; @@ -10766,12 +11000,11 @@ bool ScalarEvolution::isImpliedCondBalancedTypes( // Check whether the actual condition is beyond sufficient. if (FoundPred == ICmpInst::ICMP_EQ) if (ICmpInst::isTrueWhenEqual(Pred)) - if (isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, Context)) + if (isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI)) return true; if (Pred == ICmpInst::ICMP_NE) if (!ICmpInst::isTrueWhenEqual(FoundPred)) - if (isImpliedCondOperands(FoundPred, LHS, RHS, FoundLHS, FoundRHS, - Context)) + if (isImpliedCondOperands(FoundPred, LHS, RHS, FoundLHS, FoundRHS, CtxI)) return true; // Otherwise assume the worst. @@ -10852,7 +11085,7 @@ Optional<APInt> ScalarEvolution::computeConstantDifference(const SCEV *More, bool ScalarEvolution::isImpliedCondOperandsViaAddRecStart( ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, - const SCEV *FoundLHS, const SCEV *FoundRHS, const Instruction *Context) { + const SCEV *FoundLHS, const SCEV *FoundRHS, const Instruction *CtxI) { // Try to recognize the following pattern: // // FoundRHS = ... @@ -10866,9 +11099,9 @@ bool ScalarEvolution::isImpliedCondOperandsViaAddRecStart( // each iteration of this loop, including the first iteration. Therefore, in // this case, `FoundLHS Pred FoundRHS` implies `Start Pred FoundRHS`. Try to // prove the original pred using this fact. - if (!Context) + if (!CtxI) return false; - const BasicBlock *ContextBB = Context->getParent(); + const BasicBlock *ContextBB = CtxI->getParent(); // Make sure AR varies in the context block. if (auto *AR = dyn_cast<SCEVAddRecExpr>(FoundLHS)) { const Loop *L = AR->getLoop(); @@ -11090,7 +11323,7 @@ bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const SCEV *FoundLHS, const SCEV *FoundRHS, - const Instruction *Context) { + const Instruction *CtxI) { if (isImpliedCondOperandsViaRanges(Pred, LHS, RHS, FoundLHS, FoundRHS)) return true; @@ -11098,7 +11331,7 @@ bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred, return true; if (isImpliedCondOperandsViaAddRecStart(Pred, LHS, RHS, FoundLHS, FoundRHS, - Context)) + CtxI)) return true; return isImpliedCondOperandsHelper(Pred, LHS, RHS, @@ -11534,6 +11767,12 @@ const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start, if (IsSigned && BitWidth == 1) return getZero(Stride->getType()); + // This code has only been closely audited for negative strides in the + // unsigned comparison case, it may be correct for signed comparison, but + // that needs to be established. + assert((!IsSigned || !isKnownNonPositive(Stride)) && + "Stride is expected strictly positive for signed case!"); + // Calculate the maximum backedge count based on the range of values // permitted by Start, End, and Stride. APInt MinStart = @@ -11576,6 +11815,80 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, const SCEVAddRecExpr *IV = dyn_cast<SCEVAddRecExpr>(LHS); bool PredicatedIV = false; + auto canAssumeNoSelfWrap = [&](const SCEVAddRecExpr *AR) { + // Can we prove this loop *must* be UB if overflow of IV occurs? + // Reasoning goes as follows: + // * Suppose the IV did self wrap. + // * If Stride evenly divides the iteration space, then once wrap + // occurs, the loop must revisit the same values. + // * We know that RHS is invariant, and that none of those values + // caused this exit to be taken previously. Thus, this exit is + // dynamically dead. + // * If this is the sole exit, then a dead exit implies the loop + // must be infinite if there are no abnormal exits. + // * If the loop were infinite, then it must either not be mustprogress + // or have side effects. Otherwise, it must be UB. + // * It can't (by assumption), be UB so we have contradicted our + // premise and can conclude the IV did not in fact self-wrap. + if (!isLoopInvariant(RHS, L)) + return false; + + auto *StrideC = dyn_cast<SCEVConstant>(AR->getStepRecurrence(*this)); + if (!StrideC || !StrideC->getAPInt().isPowerOf2()) + return false; + + if (!ControlsExit || !loopHasNoAbnormalExits(L)) + return false; + + return loopIsFiniteByAssumption(L); + }; + + if (!IV) { + if (auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(LHS)) { + const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(ZExt->getOperand()); + if (AR && AR->getLoop() == L && AR->isAffine()) { + auto canProveNUW = [&]() { + if (!isLoopInvariant(RHS, L)) + return false; + + if (!isKnownNonZero(AR->getStepRecurrence(*this))) + // We need the sequence defined by AR to strictly increase in the + // unsigned integer domain for the logic below to hold. + return false; + + const unsigned InnerBitWidth = getTypeSizeInBits(AR->getType()); + const unsigned OuterBitWidth = getTypeSizeInBits(RHS->getType()); + // If RHS <=u Limit, then there must exist a value V in the sequence + // defined by AR (e.g. {Start,+,Step}) such that V >u RHS, and + // V <=u UINT_MAX. Thus, we must exit the loop before unsigned + // overflow occurs. This limit also implies that a signed comparison + // (in the wide bitwidth) is equivalent to an unsigned comparison as + // the high bits on both sides must be zero. + APInt StrideMax = getUnsignedRangeMax(AR->getStepRecurrence(*this)); + APInt Limit = APInt::getMaxValue(InnerBitWidth) - (StrideMax - 1); + Limit = Limit.zext(OuterBitWidth); + return getUnsignedRangeMax(applyLoopGuards(RHS, L)).ule(Limit); + }; + auto Flags = AR->getNoWrapFlags(); + if (!hasFlags(Flags, SCEV::FlagNUW) && canProveNUW()) + Flags = setFlags(Flags, SCEV::FlagNUW); + + setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), Flags); + if (AR->hasNoUnsignedWrap()) { + // Emulate what getZeroExtendExpr would have done during construction + // if we'd been able to infer the fact just above at that time. + const SCEV *Step = AR->getStepRecurrence(*this); + Type *Ty = ZExt->getType(); + auto *S = getAddRecExpr( + getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, 0), + getZeroExtendExpr(Step, Ty, 0), L, AR->getNoWrapFlags()); + IV = dyn_cast<SCEVAddRecExpr>(S); + } + } + } + } + + if (!IV && AllowPredicates) { // Try to make this an AddRec using runtime tests, in the first X // iterations of this loop, where X is the SCEV expression found by the @@ -11626,32 +11939,29 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, // // a) IV is either nuw or nsw depending upon signedness (indicated by the // NoWrap flag). - // b) loop is single exit with no side effects. - // + // b) the loop is guaranteed to be finite (e.g. is mustprogress and has + // no side effects within the loop) + // c) loop has a single static exit (with no abnormal exits) // // Precondition a) implies that if the stride is negative, this is a single // trip loop. The backedge taken count formula reduces to zero in this case. // - // Precondition b) implies that if rhs is invariant in L, then unknown - // stride being zero means the backedge can't be taken without UB. + // Precondition b) and c) combine to imply that if rhs is invariant in L, + // then a zero stride means the backedge can't be taken without executing + // undefined behavior. // // The positive stride case is the same as isKnownPositive(Stride) returning // true (original behavior of the function). // - // We want to make sure that the stride is truly unknown as there are edge - // cases where ScalarEvolution propagates no wrap flags to the - // post-increment/decrement IV even though the increment/decrement operation - // itself is wrapping. The computed backedge taken count may be wrong in - // such cases. This is prevented by checking that the stride is not known to - // be either positive or non-positive. For example, no wrap flags are - // propagated to the post-increment IV of this loop with a trip count of 2 - - // - // unsigned char i; - // for(i=127; i<128; i+=129) - // A[i] = i; - // - if (PredicatedIV || !NoWrap || isKnownNonPositive(Stride) || - !loopIsFiniteByAssumption(L)) + if (PredicatedIV || !NoWrap || !loopIsFiniteByAssumption(L) || + !loopHasNoAbnormalExits(L)) + return getCouldNotCompute(); + + // This bailout is protecting the logic in computeMaxBECountForLT which + // has not yet been sufficiently auditted or tested with negative strides. + // We used to filter out all known-non-positive cases here, we're in the + // process of being less restrictive bit by bit. + if (IsSigned && isKnownNonPositive(Stride)) return getCouldNotCompute(); if (!isKnownNonZero(Stride)) { @@ -11687,37 +11997,12 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, } } else if (!Stride->isOne() && !NoWrap) { auto isUBOnWrap = [&]() { - // Can we prove this loop *must* be UB if overflow of IV occurs? - // Reasoning goes as follows: - // * Suppose the IV did self wrap. - // * If Stride evenly divides the iteration space, then once wrap - // occurs, the loop must revisit the same values. - // * We know that RHS is invariant, and that none of those values - // caused this exit to be taken previously. Thus, this exit is - // dynamically dead. - // * If this is the sole exit, then a dead exit implies the loop - // must be infinite if there are no abnormal exits. - // * If the loop were infinite, then it must either not be mustprogress - // or have side effects. Otherwise, it must be UB. - // * It can't (by assumption), be UB so we have contradicted our - // premise and can conclude the IV did not in fact self-wrap. // From no-self-wrap, we need to then prove no-(un)signed-wrap. This // follows trivially from the fact that every (un)signed-wrapped, but // not self-wrapped value must be LT than the last value before // (un)signed wrap. Since we know that last value didn't exit, nor // will any smaller one. - - if (!isLoopInvariant(RHS, L)) - return false; - - auto *StrideC = dyn_cast<SCEVConstant>(Stride); - if (!StrideC || !StrideC->getAPInt().isPowerOf2()) - return false; - - if (!ControlsExit || !loopHasNoAbnormalExits(L)) - return false; - - return loopIsFiniteByAssumption(L); + return canAssumeNoSelfWrap(IV); }; // Avoid proven overflow cases: this will ensure that the backedge taken @@ -11740,7 +12025,9 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, const SCEV *Start = IV->getStart(); // Preserve pointer-typed Start/RHS to pass to isLoopEntryGuardedByCond. - // Use integer-typed versions for actual computation. + // If we convert to integers, isLoopEntryGuardedByCond will miss some cases. + // Use integer-typed versions for actual computation; we can't subtract + // pointers in general. const SCEV *OrigStart = Start; const SCEV *OrigRHS = RHS; if (Start->getType()->isPointerTy()) { @@ -11771,10 +12058,13 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, // is End and so the result is as above, and if not max(End,Start) is Start // so we get a backedge count of zero. const SCEV *BECount = nullptr; - auto *StartMinusStride = getMinusSCEV(OrigStart, Stride); + auto *OrigStartMinusStride = getMinusSCEV(OrigStart, Stride); + assert(isAvailableAtLoopEntry(OrigStartMinusStride, L) && "Must be!"); + assert(isAvailableAtLoopEntry(OrigStart, L) && "Must be!"); + assert(isAvailableAtLoopEntry(OrigRHS, L) && "Must be!"); // Can we prove (max(RHS,Start) > Start - Stride? - if (isLoopEntryGuardedByCond(L, Cond, StartMinusStride, Start) && - isLoopEntryGuardedByCond(L, Cond, StartMinusStride, RHS)) { + if (isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigStart) && + isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigRHS)) { // In this case, we can use a refined formula for computing backedge taken // count. The general formula remains: // "End-Start /uceiling Stride" where "End = max(RHS,Start)" @@ -11795,10 +12085,8 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, // Our preconditions trivially imply no overflow in that form. const SCEV *MinusOne = getMinusOne(Stride->getType()); const SCEV *Numerator = - getMinusSCEV(getAddExpr(RHS, MinusOne), StartMinusStride); - if (!isa<SCEVCouldNotCompute>(Numerator)) { - BECount = getUDivExpr(Numerator, Stride); - } + getMinusSCEV(getAddExpr(RHS, MinusOne), getMinusSCEV(Start, Stride)); + BECount = getUDivExpr(Numerator, Stride); } const SCEV *BECountIfBackedgeTaken = nullptr; @@ -12141,7 +12429,7 @@ SCEVAddRecExpr::getPostIncExpr(ScalarEvolution &SE) const { } // Return true when S contains at least an undef value. -static inline bool containsUndefs(const SCEV *S) { +bool ScalarEvolution::containsUndefs(const SCEV *S) const { return SCEVExprContains(S, [](const SCEV *S) { if (const auto *SU = dyn_cast<SCEVUnknown>(S)) return isa<UndefValue>(SU->getValue()); @@ -12149,237 +12437,6 @@ static inline bool containsUndefs(const SCEV *S) { }); } -namespace { - -// Collect all steps of SCEV expressions. -struct SCEVCollectStrides { - ScalarEvolution &SE; - SmallVectorImpl<const SCEV *> &Strides; - - SCEVCollectStrides(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &S) - : SE(SE), Strides(S) {} - - bool follow(const SCEV *S) { - if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) - Strides.push_back(AR->getStepRecurrence(SE)); - return true; - } - - bool isDone() const { return false; } -}; - -// Collect all SCEVUnknown and SCEVMulExpr expressions. -struct SCEVCollectTerms { - SmallVectorImpl<const SCEV *> &Terms; - - SCEVCollectTerms(SmallVectorImpl<const SCEV *> &T) : Terms(T) {} - - bool follow(const SCEV *S) { - if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S) || - isa<SCEVSignExtendExpr>(S)) { - if (!containsUndefs(S)) - Terms.push_back(S); - - // Stop recursion: once we collected a term, do not walk its operands. - return false; - } - - // Keep looking. - return true; - } - - bool isDone() const { return false; } -}; - -// Check if a SCEV contains an AddRecExpr. -struct SCEVHasAddRec { - bool &ContainsAddRec; - - SCEVHasAddRec(bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) { - ContainsAddRec = false; - } - - bool follow(const SCEV *S) { - if (isa<SCEVAddRecExpr>(S)) { - ContainsAddRec = true; - - // Stop recursion: once we collected a term, do not walk its operands. - return false; - } - - // Keep looking. - return true; - } - - bool isDone() const { return false; } -}; - -// Find factors that are multiplied with an expression that (possibly as a -// subexpression) contains an AddRecExpr. In the expression: -// -// 8 * (100 + %p * %q * (%a + {0, +, 1}_loop)) -// -// "%p * %q" are factors multiplied by the expression "(%a + {0, +, 1}_loop)" -// that contains the AddRec {0, +, 1}_loop. %p * %q are likely to be array size -// parameters as they form a product with an induction variable. -// -// This collector expects all array size parameters to be in the same MulExpr. -// It might be necessary to later add support for collecting parameters that are -// spread over different nested MulExpr. -struct SCEVCollectAddRecMultiplies { - SmallVectorImpl<const SCEV *> &Terms; - ScalarEvolution &SE; - - SCEVCollectAddRecMultiplies(SmallVectorImpl<const SCEV *> &T, ScalarEvolution &SE) - : Terms(T), SE(SE) {} - - bool follow(const SCEV *S) { - if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) { - bool HasAddRec = false; - SmallVector<const SCEV *, 0> Operands; - for (auto Op : Mul->operands()) { - const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op); - if (Unknown && !isa<CallInst>(Unknown->getValue())) { - Operands.push_back(Op); - } else if (Unknown) { - HasAddRec = true; - } else { - bool ContainsAddRec = false; - SCEVHasAddRec ContiansAddRec(ContainsAddRec); - visitAll(Op, ContiansAddRec); - HasAddRec |= ContainsAddRec; - } - } - if (Operands.size() == 0) - return true; - - if (!HasAddRec) - return false; - - Terms.push_back(SE.getMulExpr(Operands)); - // Stop recursion: once we collected a term, do not walk its operands. - return false; - } - - // Keep looking. - return true; - } - - bool isDone() const { return false; } -}; - -} // end anonymous namespace - -/// Find parametric terms in this SCEVAddRecExpr. We first for parameters in -/// two places: -/// 1) The strides of AddRec expressions. -/// 2) Unknowns that are multiplied with AddRec expressions. -void ScalarEvolution::collectParametricTerms(const SCEV *Expr, - SmallVectorImpl<const SCEV *> &Terms) { - SmallVector<const SCEV *, 4> Strides; - SCEVCollectStrides StrideCollector(*this, Strides); - visitAll(Expr, StrideCollector); - - LLVM_DEBUG({ - dbgs() << "Strides:\n"; - for (const SCEV *S : Strides) - dbgs() << *S << "\n"; - }); - - for (const SCEV *S : Strides) { - SCEVCollectTerms TermCollector(Terms); - visitAll(S, TermCollector); - } - - LLVM_DEBUG({ - dbgs() << "Terms:\n"; - for (const SCEV *T : Terms) - dbgs() << *T << "\n"; - }); - - SCEVCollectAddRecMultiplies MulCollector(Terms, *this); - visitAll(Expr, MulCollector); -} - -static bool findArrayDimensionsRec(ScalarEvolution &SE, - SmallVectorImpl<const SCEV *> &Terms, - SmallVectorImpl<const SCEV *> &Sizes) { - int Last = Terms.size() - 1; - const SCEV *Step = Terms[Last]; - - // End of recursion. - if (Last == 0) { - if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) { - SmallVector<const SCEV *, 2> Qs; - for (const SCEV *Op : M->operands()) - if (!isa<SCEVConstant>(Op)) - Qs.push_back(Op); - - Step = SE.getMulExpr(Qs); - } - - Sizes.push_back(Step); - return true; - } - - for (const SCEV *&Term : Terms) { - // Normalize the terms before the next call to findArrayDimensionsRec. - const SCEV *Q, *R; - SCEVDivision::divide(SE, Term, Step, &Q, &R); - - // Bail out when GCD does not evenly divide one of the terms. - if (!R->isZero()) - return false; - - Term = Q; - } - - // Remove all SCEVConstants. - erase_if(Terms, [](const SCEV *E) { return isa<SCEVConstant>(E); }); - - if (Terms.size() > 0) - if (!findArrayDimensionsRec(SE, Terms, Sizes)) - return false; - - Sizes.push_back(Step); - return true; -} - -// Returns true when one of the SCEVs of Terms contains a SCEVUnknown parameter. -static inline bool containsParameters(SmallVectorImpl<const SCEV *> &Terms) { - for (const SCEV *T : Terms) - if (SCEVExprContains(T, [](const SCEV *S) { return isa<SCEVUnknown>(S); })) - return true; - - return false; -} - -// Return the number of product terms in S. -static inline int numberOfTerms(const SCEV *S) { - if (const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S)) - return Expr->getNumOperands(); - return 1; -} - -static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) { - if (isa<SCEVConstant>(T)) - return nullptr; - - if (isa<SCEVUnknown>(T)) - return T; - - if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) { - SmallVector<const SCEV *, 2> Factors; - for (const SCEV *Op : M->operands()) - if (!isa<SCEVConstant>(Op)) - Factors.push_back(Op); - - return SE.getMulExpr(Factors); - } - - return T; -} - /// Return the size of an element read or written by Inst. const SCEV *ScalarEvolution::getElementSize(Instruction *Inst) { Type *Ty; @@ -12394,248 +12451,6 @@ const SCEV *ScalarEvolution::getElementSize(Instruction *Inst) { return getSizeOfExpr(ETy, Ty); } -void ScalarEvolution::findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms, - SmallVectorImpl<const SCEV *> &Sizes, - const SCEV *ElementSize) { - if (Terms.size() < 1 || !ElementSize) - return; - - // Early return when Terms do not contain parameters: we do not delinearize - // non parametric SCEVs. - if (!containsParameters(Terms)) - return; - - LLVM_DEBUG({ - dbgs() << "Terms:\n"; - for (const SCEV *T : Terms) - dbgs() << *T << "\n"; - }); - - // Remove duplicates. - array_pod_sort(Terms.begin(), Terms.end()); - Terms.erase(std::unique(Terms.begin(), Terms.end()), Terms.end()); - - // Put larger terms first. - llvm::sort(Terms, [](const SCEV *LHS, const SCEV *RHS) { - return numberOfTerms(LHS) > numberOfTerms(RHS); - }); - - // Try to divide all terms by the element size. If term is not divisible by - // element size, proceed with the original term. - for (const SCEV *&Term : Terms) { - const SCEV *Q, *R; - SCEVDivision::divide(*this, Term, ElementSize, &Q, &R); - if (!Q->isZero()) - Term = Q; - } - - SmallVector<const SCEV *, 4> NewTerms; - - // Remove constant factors. - for (const SCEV *T : Terms) - if (const SCEV *NewT = removeConstantFactors(*this, T)) - NewTerms.push_back(NewT); - - LLVM_DEBUG({ - dbgs() << "Terms after sorting:\n"; - for (const SCEV *T : NewTerms) - dbgs() << *T << "\n"; - }); - - if (NewTerms.empty() || !findArrayDimensionsRec(*this, NewTerms, Sizes)) { - Sizes.clear(); - return; - } - - // The last element to be pushed into Sizes is the size of an element. - Sizes.push_back(ElementSize); - - LLVM_DEBUG({ - dbgs() << "Sizes:\n"; - for (const SCEV *S : Sizes) - dbgs() << *S << "\n"; - }); -} - -void ScalarEvolution::computeAccessFunctions( - const SCEV *Expr, SmallVectorImpl<const SCEV *> &Subscripts, - SmallVectorImpl<const SCEV *> &Sizes) { - // Early exit in case this SCEV is not an affine multivariate function. - if (Sizes.empty()) - return; - - if (auto *AR = dyn_cast<SCEVAddRecExpr>(Expr)) - if (!AR->isAffine()) - return; - - const SCEV *Res = Expr; - int Last = Sizes.size() - 1; - for (int i = Last; i >= 0; i--) { - const SCEV *Q, *R; - SCEVDivision::divide(*this, Res, Sizes[i], &Q, &R); - - LLVM_DEBUG({ - dbgs() << "Res: " << *Res << "\n"; - dbgs() << "Sizes[i]: " << *Sizes[i] << "\n"; - dbgs() << "Res divided by Sizes[i]:\n"; - dbgs() << "Quotient: " << *Q << "\n"; - dbgs() << "Remainder: " << *R << "\n"; - }); - - Res = Q; - - // Do not record the last subscript corresponding to the size of elements in - // the array. - if (i == Last) { - - // Bail out if the remainder is too complex. - if (isa<SCEVAddRecExpr>(R)) { - Subscripts.clear(); - Sizes.clear(); - return; - } - - continue; - } - - // Record the access function for the current subscript. - Subscripts.push_back(R); - } - - // Also push in last position the remainder of the last division: it will be - // the access function of the innermost dimension. - Subscripts.push_back(Res); - - std::reverse(Subscripts.begin(), Subscripts.end()); - - LLVM_DEBUG({ - dbgs() << "Subscripts:\n"; - for (const SCEV *S : Subscripts) - dbgs() << *S << "\n"; - }); -} - -/// Splits the SCEV into two vectors of SCEVs representing the subscripts and -/// sizes of an array access. Returns the remainder of the delinearization that -/// is the offset start of the array. The SCEV->delinearize algorithm computes -/// the multiples of SCEV coefficients: that is a pattern matching of sub -/// expressions in the stride and base of a SCEV corresponding to the -/// computation of a GCD (greatest common divisor) of base and stride. When -/// SCEV->delinearize fails, it returns the SCEV unchanged. -/// -/// For example: when analyzing the memory access A[i][j][k] in this loop nest -/// -/// void foo(long n, long m, long o, double A[n][m][o]) { -/// -/// for (long i = 0; i < n; i++) -/// for (long j = 0; j < m; j++) -/// for (long k = 0; k < o; k++) -/// A[i][j][k] = 1.0; -/// } -/// -/// the delinearization input is the following AddRec SCEV: -/// -/// AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k> -/// -/// From this SCEV, we are able to say that the base offset of the access is %A -/// because it appears as an offset that does not divide any of the strides in -/// the loops: -/// -/// CHECK: Base offset: %A -/// -/// and then SCEV->delinearize determines the size of some of the dimensions of -/// the array as these are the multiples by which the strides are happening: -/// -/// CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double) bytes. -/// -/// Note that the outermost dimension remains of UnknownSize because there are -/// no strides that would help identifying the size of the last dimension: when -/// the array has been statically allocated, one could compute the size of that -/// dimension by dividing the overall size of the array by the size of the known -/// dimensions: %m * %o * 8. -/// -/// Finally delinearize provides the access functions for the array reference -/// that does correspond to A[i][j][k] of the above C testcase: -/// -/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>] -/// -/// The testcases are checking the output of a function pass: -/// DelinearizationPass that walks through all loads and stores of a function -/// asking for the SCEV of the memory access with respect to all enclosing -/// loops, calling SCEV->delinearize on that and printing the results. -void ScalarEvolution::delinearize(const SCEV *Expr, - SmallVectorImpl<const SCEV *> &Subscripts, - SmallVectorImpl<const SCEV *> &Sizes, - const SCEV *ElementSize) { - // First step: collect parametric terms. - SmallVector<const SCEV *, 4> Terms; - collectParametricTerms(Expr, Terms); - - if (Terms.empty()) - return; - - // Second step: find subscript sizes. - findArrayDimensions(Terms, Sizes, ElementSize); - - if (Sizes.empty()) - return; - - // Third step: compute the access functions for each subscript. - computeAccessFunctions(Expr, Subscripts, Sizes); - - if (Subscripts.empty()) - return; - - LLVM_DEBUG({ - dbgs() << "succeeded to delinearize " << *Expr << "\n"; - dbgs() << "ArrayDecl[UnknownSize]"; - for (const SCEV *S : Sizes) - dbgs() << "[" << *S << "]"; - - dbgs() << "\nArrayRef"; - for (const SCEV *S : Subscripts) - dbgs() << "[" << *S << "]"; - dbgs() << "\n"; - }); -} - -bool ScalarEvolution::getIndexExpressionsFromGEP( - const GetElementPtrInst *GEP, SmallVectorImpl<const SCEV *> &Subscripts, - SmallVectorImpl<int> &Sizes) { - assert(Subscripts.empty() && Sizes.empty() && - "Expected output lists to be empty on entry to this function."); - assert(GEP && "getIndexExpressionsFromGEP called with a null GEP"); - Type *Ty = nullptr; - bool DroppedFirstDim = false; - for (unsigned i = 1; i < GEP->getNumOperands(); i++) { - const SCEV *Expr = getSCEV(GEP->getOperand(i)); - if (i == 1) { - Ty = GEP->getSourceElementType(); - if (auto *Const = dyn_cast<SCEVConstant>(Expr)) - if (Const->getValue()->isZero()) { - DroppedFirstDim = true; - continue; - } - Subscripts.push_back(Expr); - continue; - } - - auto *ArrayTy = dyn_cast<ArrayType>(Ty); - if (!ArrayTy) { - Subscripts.clear(); - Sizes.clear(); - return false; - } - - Subscripts.push_back(Expr); - if (!(DroppedFirstDim && i == 2)) - Sizes.push_back(ArrayTy->getNumElements()); - - Ty = ArrayTy->getElementType(); - } - return !Subscripts.empty(); -} - //===----------------------------------------------------------------------===// // SCEVCallbackVH Class Implementation //===----------------------------------------------------------------------===// @@ -12722,6 +12537,7 @@ ScalarEvolution::ScalarEvolution(ScalarEvolution &&Arg) LoopDispositions(std::move(Arg.LoopDispositions)), LoopPropertiesCache(std::move(Arg.LoopPropertiesCache)), BlockDispositions(std::move(Arg.BlockDispositions)), + SCEVUsers(std::move(Arg.SCEVUsers)), UnsignedRanges(std::move(Arg.UnsignedRanges)), SignedRanges(std::move(Arg.SignedRanges)), UniqueSCEVs(std::move(Arg.UniqueSCEVs)), @@ -12934,7 +12750,7 @@ ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) { Values.emplace_back(L, LoopVariant); LoopDisposition D = computeLoopDisposition(S, L); auto &Values2 = LoopDispositions[S]; - for (auto &V : make_range(Values2.rbegin(), Values2.rend())) { + for (auto &V : llvm::reverse(Values2)) { if (V.getPointer() == L) { V.setInt(D); break; @@ -13042,7 +12858,7 @@ ScalarEvolution::getBlockDisposition(const SCEV *S, const BasicBlock *BB) { Values.emplace_back(BB, DoesNotDominateBlock); BlockDisposition D = computeBlockDisposition(S, BB); auto &Values2 = BlockDispositions[S]; - for (auto &V : make_range(Values2.rbegin(), Values2.rend())) { + for (auto &V : llvm::reverse(Values2)) { if (V.getPointer() == BB) { V.setInt(D); break; @@ -13130,41 +12946,58 @@ bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const { return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; }); } -void -ScalarEvolution::forgetMemoizedResults(const SCEV *S) { - ValuesAtScopes.erase(S); - LoopDispositions.erase(S); - BlockDispositions.erase(S); - UnsignedRanges.erase(S); - SignedRanges.erase(S); - ExprValueMap.erase(S); - HasRecMap.erase(S); - MinTrailingZerosCache.erase(S); +void ScalarEvolution::forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs) { + SmallPtrSet<const SCEV *, 8> ToForget(SCEVs.begin(), SCEVs.end()); + SmallVector<const SCEV *, 8> Worklist(ToForget.begin(), ToForget.end()); + + while (!Worklist.empty()) { + const SCEV *Curr = Worklist.pop_back_val(); + auto Users = SCEVUsers.find(Curr); + if (Users != SCEVUsers.end()) + for (auto *User : Users->second) + if (ToForget.insert(User).second) + Worklist.push_back(User); + } + + for (auto *S : ToForget) + forgetMemoizedResultsImpl(S); for (auto I = PredicatedSCEVRewrites.begin(); I != PredicatedSCEVRewrites.end();) { std::pair<const SCEV *, const Loop *> Entry = I->first; - if (Entry.first == S) + if (ToForget.count(Entry.first)) PredicatedSCEVRewrites.erase(I++); else ++I; } - auto RemoveSCEVFromBackedgeMap = - [S](DenseMap<const Loop *, BackedgeTakenInfo> &Map) { + auto RemoveSCEVFromBackedgeMap = [&ToForget]( + DenseMap<const Loop *, BackedgeTakenInfo> &Map) { for (auto I = Map.begin(), E = Map.end(); I != E;) { BackedgeTakenInfo &BEInfo = I->second; - if (BEInfo.hasOperand(S)) + if (any_of(ToForget, + [&BEInfo](const SCEV *S) { return BEInfo.hasOperand(S); })) Map.erase(I++); else ++I; } - }; + }; RemoveSCEVFromBackedgeMap(BackedgeTakenCounts); RemoveSCEVFromBackedgeMap(PredicatedBackedgeTakenCounts); } +void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) { + ValuesAtScopes.erase(S); + LoopDispositions.erase(S); + BlockDispositions.erase(S); + UnsignedRanges.erase(S); + SignedRanges.erase(S); + ExprValueMap.erase(S); + HasRecMap.erase(S); + MinTrailingZerosCache.erase(S); +} + void ScalarEvolution::getUsedLoops(const SCEV *S, SmallPtrSetImpl<const Loop *> &LoopsUsed) { @@ -13185,13 +13018,6 @@ ScalarEvolution::getUsedLoops(const SCEV *S, SCEVTraversal<FindUsedLoops>(F).visitAll(S); } -void ScalarEvolution::addToLoopUseLists(const SCEV *S) { - SmallPtrSet<const Loop *, 8> LoopsUsed; - getUsedLoops(S, LoopsUsed); - for (auto *L : LoopsUsed) - LoopUsers[L].push_back(S); -} - void ScalarEvolution::verify() const { ScalarEvolution &SE = *const_cast<ScalarEvolution *>(this); ScalarEvolution SE2(F, TLI, AC, DT, LI); @@ -13282,6 +13108,23 @@ void ScalarEvolution::verify() const { assert(ValidLoops.contains(AR->getLoop()) && "AddRec references invalid loop"); } + + // Verify intergity of SCEV users. + for (const auto &S : UniqueSCEVs) { + SmallVector<const SCEV *, 4> Ops; + collectUniqueOps(&S, Ops); + for (const auto *Op : Ops) { + // We do not store dependencies of constants. + if (isa<SCEVConstant>(Op)) + continue; + auto It = SCEVUsers.find(Op); + if (It != SCEVUsers.end() && It->second.count(&S)) + continue; + dbgs() << "Use of operand " << *Op << " by user " << S + << " is not being tracked!\n"; + std::abort(); + } + } } bool ScalarEvolution::invalidate( @@ -13685,6 +13528,16 @@ PredicatedScalarEvolution::PredicatedScalarEvolution(ScalarEvolution &SE, Loop &L) : SE(SE), L(L) {} +void ScalarEvolution::registerUser(const SCEV *User, + ArrayRef<const SCEV *> Ops) { + for (auto *Op : Ops) + // We do not expect that forgetting cached data for SCEVConstants will ever + // open any prospects for sharpening or introduce any correctness issues, + // so we don't bother storing their dependencies. + if (!isa<SCEVConstant>(Op)) + SCEVUsers[Op].insert(User); +} + const SCEV *PredicatedScalarEvolution::getSCEV(Value *V) { const SCEV *Expr = SE.getSCEV(V); RewriteEntry &Entry = RewriteMap[Expr]; @@ -13897,52 +13750,51 @@ ScalarEvolution::computeSymbolicMaxBackedgeTakenCount(const Loop *L) { return getUMinFromMismatchedTypes(ExitCounts); } -/// This rewriter is similar to SCEVParameterRewriter (it replaces SCEVUnknown -/// components following the Map (Value -> SCEV)), but skips AddRecExpr because -/// we cannot guarantee that the replacement is loop invariant in the loop of -/// the AddRec. +/// A rewriter to replace SCEV expressions in Map with the corresponding entry +/// in the map. It skips AddRecExpr because we cannot guarantee that the +/// replacement is loop invariant in the loop of the AddRec. +/// +/// At the moment only rewriting SCEVUnknown and SCEVZeroExtendExpr is +/// supported. class SCEVLoopGuardRewriter : public SCEVRewriteVisitor<SCEVLoopGuardRewriter> { - ValueToSCEVMapTy ⤅ + const DenseMap<const SCEV *, const SCEV *> ⤅ public: - SCEVLoopGuardRewriter(ScalarEvolution &SE, ValueToSCEVMapTy &M) + SCEVLoopGuardRewriter(ScalarEvolution &SE, + DenseMap<const SCEV *, const SCEV *> &M) : SCEVRewriteVisitor(SE), Map(M) {} const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { return Expr; } const SCEV *visitUnknown(const SCEVUnknown *Expr) { - auto I = Map.find(Expr->getValue()); + auto I = Map.find(Expr); if (I == Map.end()) return Expr; return I->second; } + + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + auto I = Map.find(Expr); + if (I == Map.end()) + return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitZeroExtendExpr( + Expr); + return I->second; + } }; const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) { + SmallVector<const SCEV *> ExprsToRewrite; auto CollectCondition = [&](ICmpInst::Predicate Predicate, const SCEV *LHS, - const SCEV *RHS, ValueToSCEVMapTy &RewriteMap) { - // If we have LHS == 0, check if LHS is computing a property of some unknown - // SCEV %v which we can rewrite %v to express explicitly. - const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS); - if (Predicate == CmpInst::ICMP_EQ && RHSC && - RHSC->getValue()->isNullValue()) { - // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to - // explicitly express that. - const SCEV *URemLHS = nullptr; - const SCEV *URemRHS = nullptr; - if (matchURem(LHS, URemLHS, URemRHS)) { - if (const SCEVUnknown *LHSUnknown = dyn_cast<SCEVUnknown>(URemLHS)) { - Value *V = LHSUnknown->getValue(); - auto Multiple = - getMulExpr(getUDivExpr(URemLHS, URemRHS), URemRHS, - (SCEV::NoWrapFlags)(SCEV::FlagNUW | SCEV::FlagNSW)); - RewriteMap[V] = Multiple; - return; - } - } - } + const SCEV *RHS, + DenseMap<const SCEV *, const SCEV *> + &RewriteMap) { + // WARNING: It is generally unsound to apply any wrap flags to the proposed + // replacement SCEV which isn't directly implied by the structure of that + // SCEV. In particular, using contextual facts to imply flags is *NOT* + // legal. See the scoping rules for flags in the header to understand why. - if (!isa<SCEVUnknown>(LHS) && isa<SCEVUnknown>(RHS)) { + // If LHS is a constant, apply information to the other expression. + if (isa<SCEVConstant>(LHS)) { std::swap(LHS, RHS); Predicate = CmpInst::getSwappedPredicate(Predicate); } @@ -13950,7 +13802,8 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) { // Check for a condition of the form (-C1 + X < C2). InstCombine will // create this form when combining two checks of the form (X u< C2 + C1) and // (X >=u C1). - auto MatchRangeCheckIdiom = [this, Predicate, LHS, RHS, &RewriteMap]() { + auto MatchRangeCheckIdiom = [this, Predicate, LHS, RHS, &RewriteMap, + &ExprsToRewrite]() { auto *AddExpr = dyn_cast<SCEVAddExpr>(LHS); if (!AddExpr || AddExpr->getNumOperands() != 2) return false; @@ -13968,26 +13821,55 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) { // Bail out, unless we have a non-wrapping, monotonic range. if (ExactRegion.isWrappedSet() || ExactRegion.isFullSet()) return false; - auto I = RewriteMap.find(LHSUnknown->getValue()); - const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : LHS; - RewriteMap[LHSUnknown->getValue()] = getUMaxExpr( + auto I = RewriteMap.find(LHSUnknown); + const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : LHSUnknown; + RewriteMap[LHSUnknown] = getUMaxExpr( getConstant(ExactRegion.getUnsignedMin()), getUMinExpr(RewrittenLHS, getConstant(ExactRegion.getUnsignedMax()))); + ExprsToRewrite.push_back(LHSUnknown); return true; }; if (MatchRangeCheckIdiom()) return; - // For now, limit to conditions that provide information about unknown - // expressions. RHS also cannot contain add recurrences. - auto *LHSUnknown = dyn_cast<SCEVUnknown>(LHS); - if (!LHSUnknown || containsAddRecurrence(RHS)) + // If we have LHS == 0, check if LHS is computing a property of some unknown + // SCEV %v which we can rewrite %v to express explicitly. + const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS); + if (Predicate == CmpInst::ICMP_EQ && RHSC && + RHSC->getValue()->isNullValue()) { + // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to + // explicitly express that. + const SCEV *URemLHS = nullptr; + const SCEV *URemRHS = nullptr; + if (matchURem(LHS, URemLHS, URemRHS)) { + if (const SCEVUnknown *LHSUnknown = dyn_cast<SCEVUnknown>(URemLHS)) { + auto Multiple = getMulExpr(getUDivExpr(URemLHS, URemRHS), URemRHS); + RewriteMap[LHSUnknown] = Multiple; + ExprsToRewrite.push_back(LHSUnknown); + return; + } + } + } + + // Do not apply information for constants or if RHS contains an AddRec. + if (isa<SCEVConstant>(LHS) || containsAddRecurrence(RHS)) + return; + + // If RHS is SCEVUnknown, make sure the information is applied to it. + if (!isa<SCEVUnknown>(LHS) && isa<SCEVUnknown>(RHS)) { + std::swap(LHS, RHS); + Predicate = CmpInst::getSwappedPredicate(Predicate); + } + + // Limit to expressions that can be rewritten. + if (!isa<SCEVUnknown>(LHS) && !isa<SCEVZeroExtendExpr>(LHS)) return; // Check whether LHS has already been rewritten. In that case we want to // chain further rewrites onto the already rewritten value. - auto I = RewriteMap.find(LHSUnknown->getValue()); + auto I = RewriteMap.find(LHS); const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : LHS; + const SCEV *RewrittenRHS = nullptr; switch (Predicate) { case CmpInst::ICMP_ULT: @@ -14031,14 +13913,17 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) { break; } - if (RewrittenRHS) - RewriteMap[LHSUnknown->getValue()] = RewrittenRHS; + if (RewrittenRHS) { + RewriteMap[LHS] = RewrittenRHS; + if (LHS == RewrittenLHS) + ExprsToRewrite.push_back(LHS); + } }; // Starting at the loop predecessor, climb up the predecessor chain, as long // as there are predecessors that can be found that have unique successors // leading to the original header. // TODO: share this logic with isLoopEntryGuardedByCond. - ValueToSCEVMapTy RewriteMap; + DenseMap<const SCEV *, const SCEV *> RewriteMap; for (std::pair<const BasicBlock *, const BasicBlock *> Pair( L->getLoopPredecessor(), L->getHeader()); Pair.first; Pair = getPredecessorWithUniqueSuccessorForBB(Pair.first)) { @@ -14088,6 +13973,19 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) { if (RewriteMap.empty()) return Expr; + + // Now that all rewrite information is collect, rewrite the collected + // expressions with the information in the map. This applies information to + // sub-expressions. + if (ExprsToRewrite.size() > 1) { + for (const SCEV *Expr : ExprsToRewrite) { + const SCEV *RewriteTo = RewriteMap[Expr]; + RewriteMap.erase(Expr); + SCEVLoopGuardRewriter Rewriter(*this, RewriteMap); + RewriteMap.insert({Expr, Rewriter.visit(RewriteTo)}); + } + } + SCEVLoopGuardRewriter Rewriter(*this, RewriteMap); return Rewriter.visit(Expr); } diff --git a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp index 2262fc9d7913..f4fa159d1ec7 100644 --- a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp +++ b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -23,6 +23,15 @@ #include "llvm/InitializePasses.h" using namespace llvm; +static bool canComputePointerDiff(ScalarEvolution &SE, + const SCEV *A, const SCEV *B) { + if (SE.getEffectiveSCEVType(A->getType()) != + SE.getEffectiveSCEVType(B->getType())) + return false; + + return SE.instructionCouldExistWitthOperands(A, B); +} + AliasResult SCEVAAResult::alias(const MemoryLocation &LocA, const MemoryLocation &LocB, AAQueryInfo &AAQI) { // If either of the memory references is empty, it doesn't matter what the @@ -41,8 +50,7 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA, // If something is known about the difference between the two addresses, // see if it's enough to prove a NoAlias. - if (SE.getEffectiveSCEVType(AS->getType()) == - SE.getEffectiveSCEVType(BS->getType())) { + if (canComputePointerDiff(SE, AS, BS)) { unsigned BitWidth = SE.getTypeSizeInBits(AS->getType()); APInt ASizeInt(BitWidth, LocA.Size.hasValue() ? LocA.Size.getValue() diff --git a/llvm/lib/Analysis/StackLifetime.cpp b/llvm/lib/Analysis/StackLifetime.cpp index ab5f2db7d1cd..9056cc01484d 100644 --- a/llvm/lib/Analysis/StackLifetime.cpp +++ b/llvm/lib/Analysis/StackLifetime.cpp @@ -257,14 +257,12 @@ void StackLifetime::calculateLiveIntervals() { unsigned AllocaNo = It.second.AllocaNo; if (IsStart) { - assert(!Started.test(AllocaNo) || Start[AllocaNo] == BBStart); if (!Started.test(AllocaNo)) { Started.set(AllocaNo); Ended.reset(AllocaNo); Start[AllocaNo] = InstNo; } } else { - assert(!Ended.test(AllocaNo)); if (Started.test(AllocaNo)) { LiveRanges[AllocaNo].addRange(Start[AllocaNo], InstNo); Started.reset(AllocaNo); @@ -400,3 +398,19 @@ PreservedAnalyses StackLifetimePrinterPass::run(Function &F, SL.print(OS); return PreservedAnalyses::all(); } + +void StackLifetimePrinterPass::printPipeline( + raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { + static_cast<PassInfoMixin<StackLifetimePrinterPass> *>(this)->printPipeline( + OS, MapClassName2PassName); + OS << "<"; + switch (Type) { + case StackLifetime::LivenessType::May: + OS << "may"; + break; + case StackLifetime::LivenessType::Must: + OS << "must"; + break; + } + OS << ">"; +} diff --git a/llvm/lib/Analysis/StackSafetyAnalysis.cpp b/llvm/lib/Analysis/StackSafetyAnalysis.cpp index 76f195fedf31..74cc39b7f2c0 100644 --- a/llvm/lib/Analysis/StackSafetyAnalysis.cpp +++ b/llvm/lib/Analysis/StackSafetyAnalysis.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <memory> +#include <tuple> using namespace llvm; @@ -116,6 +117,7 @@ template <typename CalleeTy> struct UseInfo { // Access range if the address (alloca or parameters). // It is allowed to be empty-set when there are no known accesses. ConstantRange Range; + std::map<const Instruction *, ConstantRange> Accesses; // List of calls which pass address as an argument. // Value is offset range of address from base address (alloca or calling @@ -129,6 +131,12 @@ template <typename CalleeTy> struct UseInfo { UseInfo(unsigned PointerSize) : Range{PointerSize, false} {} void updateRange(const ConstantRange &R) { Range = unionNoWrap(Range, R); } + void addRange(const Instruction *I, const ConstantRange &R) { + auto Ins = Accesses.emplace(I, R); + if (!Ins.second) + Ins.first->second = unionNoWrap(Ins.first->second, R); + updateRange(R); + } }; template <typename CalleeTy> @@ -146,7 +154,7 @@ raw_ostream &operator<<(raw_ostream &OS, const UseInfo<CalleeTy> &U) { ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) { const DataLayout &DL = AI.getModule()->getDataLayout(); TypeSize TS = DL.getTypeAllocSize(AI.getAllocatedType()); - unsigned PointerSize = DL.getMaxPointerSizeInBits(); + unsigned PointerSize = DL.getPointerTypeSizeInBits(AI.getType()); // Fallback to empty range for alloca size. ConstantRange R = ConstantRange::getEmpty(PointerSize); if (TS.isScalable()) @@ -167,7 +175,7 @@ ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) { if (Overflow) return R; } - R = ConstantRange(APInt::getNullValue(PointerSize), APSize); + R = ConstantRange(APInt::getZero(PointerSize), APSize); assert(!isUnsafe(R)); return R; } @@ -208,7 +216,6 @@ template <typename CalleeTy> struct FunctionInfo { } else { assert(Allocas.empty()); } - O << "\n"; } }; @@ -223,6 +230,7 @@ struct StackSafetyInfo::InfoTy { struct StackSafetyGlobalInfo::InfoTy { GVToSSI Info; SmallPtrSet<const AllocaInst *, 8> SafeAllocas; + std::map<const Instruction *, bool> AccessIsUnsafe; }; namespace { @@ -242,7 +250,7 @@ class StackSafetyLocalAnalysis { ConstantRange getMemIntrinsicAccessRange(const MemIntrinsic *MI, const Use &U, Value *Base); - bool analyzeAllUses(Value *Ptr, UseInfo<GlobalValue> &AS, + void analyzeAllUses(Value *Ptr, UseInfo<GlobalValue> &AS, const StackLifetime &SL); public: @@ -297,8 +305,8 @@ ConstantRange StackSafetyLocalAnalysis::getAccessRange(Value *Addr, Value *Base, APInt APSize(PointerSize, Size.getFixedSize(), true); if (APSize.isNegative()) return UnknownRange; - return getAccessRange( - Addr, Base, ConstantRange(APInt::getNullValue(PointerSize), APSize)); + return getAccessRange(Addr, Base, + ConstantRange(APInt::getZero(PointerSize), APSize)); } ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange( @@ -321,14 +329,13 @@ ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange( if (Sizes.getUpper().isNegative() || isUnsafe(Sizes)) return UnknownRange; Sizes = Sizes.sextOrTrunc(PointerSize); - ConstantRange SizeRange(APInt::getNullValue(PointerSize), - Sizes.getUpper() - 1); + ConstantRange SizeRange(APInt::getZero(PointerSize), Sizes.getUpper() - 1); return getAccessRange(U, Base, SizeRange); } /// The function analyzes all local uses of Ptr (alloca or argument) and /// calculates local access range and all function calls where it was used. -bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, +void StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, UseInfo<GlobalValue> &US, const StackLifetime &SL) { SmallPtrSet<const Value *, 16> Visited; @@ -349,11 +356,11 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, switch (I->getOpcode()) { case Instruction::Load: { if (AI && !SL.isAliveAfter(AI, I)) { - US.updateRange(UnknownRange); - return false; + US.addRange(I, UnknownRange); + break; } - US.updateRange( - getAccessRange(UI, Ptr, DL.getTypeStoreSize(I->getType()))); + US.addRange(I, + getAccessRange(UI, Ptr, DL.getTypeStoreSize(I->getType()))); break; } @@ -363,15 +370,16 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, case Instruction::Store: { if (V == I->getOperand(0)) { // Stored the pointer - conservatively assume it may be unsafe. - US.updateRange(UnknownRange); - return false; + US.addRange(I, UnknownRange); + break; } if (AI && !SL.isAliveAfter(AI, I)) { - US.updateRange(UnknownRange); - return false; + US.addRange(I, UnknownRange); + break; } - US.updateRange(getAccessRange( - UI, Ptr, DL.getTypeStoreSize(I->getOperand(0)->getType()))); + US.addRange( + I, getAccessRange( + UI, Ptr, DL.getTypeStoreSize(I->getOperand(0)->getType()))); break; } @@ -379,8 +387,8 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, // Information leak. // FIXME: Process parameters correctly. This is a leak only if we return // alloca. - US.updateRange(UnknownRange); - return false; + US.addRange(I, UnknownRange); + break; case Instruction::Call: case Instruction::Invoke: { @@ -388,25 +396,31 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, break; if (AI && !SL.isAliveAfter(AI, I)) { - US.updateRange(UnknownRange); - return false; + US.addRange(I, UnknownRange); + break; } if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { - US.updateRange(getMemIntrinsicAccessRange(MI, UI, Ptr)); + US.addRange(I, getMemIntrinsicAccessRange(MI, UI, Ptr)); break; } const auto &CB = cast<CallBase>(*I); + if (CB.getReturnedArgOperand() == V) { + if (Visited.insert(I).second) + WorkList.push_back(cast<const Instruction>(I)); + } + if (!CB.isArgOperand(&UI)) { - US.updateRange(UnknownRange); - return false; + US.addRange(I, UnknownRange); + break; } unsigned ArgNo = CB.getArgOperandNo(&UI); if (CB.isByValArgument(ArgNo)) { - US.updateRange(getAccessRange( - UI, Ptr, DL.getTypeStoreSize(CB.getParamByValType(ArgNo)))); + US.addRange(I, getAccessRange( + UI, Ptr, + DL.getTypeStoreSize(CB.getParamByValType(ArgNo)))); break; } @@ -416,8 +430,8 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, const GlobalValue *Callee = dyn_cast<GlobalValue>(CB.getCalledOperand()->stripPointerCasts()); if (!Callee) { - US.updateRange(UnknownRange); - return false; + US.addRange(I, UnknownRange); + break; } assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee)); @@ -435,8 +449,6 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, } } } - - return true; } FunctionInfo<GlobalValue> StackSafetyLocalAnalysis::run() { @@ -468,7 +480,7 @@ FunctionInfo<GlobalValue> StackSafetyLocalAnalysis::run() { } LLVM_DEBUG(Info.print(dbgs(), F.getName(), &F)); - LLVM_DEBUG(dbgs() << "[StackSafety] done\n"); + LLVM_DEBUG(dbgs() << "\n[StackSafety] done\n"); return Info; } @@ -588,8 +600,7 @@ void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() { updateAllNodes(); while (!WorkList.empty()) { - const CalleeTy *Callee = WorkList.back(); - WorkList.pop_back(); + const CalleeTy *Callee = WorkList.pop_back_val(); updateOneNode(Callee); } } @@ -674,7 +685,7 @@ const Function *findCalleeInModule(const GlobalValue *GV) { const GlobalAlias *A = dyn_cast<GlobalAlias>(GV); if (!A) return nullptr; - GV = A->getBaseObject(); + GV = A->getAliaseeObject(); if (GV == A) return nullptr; } @@ -741,10 +752,8 @@ GVToSSI createGlobalStackSafetyInfo( KV.second.Calls.clear(); } - uint32_t PointerSize = Copy.begin() - ->first->getParent() - ->getDataLayout() - .getMaxPointerSizeInBits(); + uint32_t PointerSize = + Copy.begin()->first->getParent()->getDataLayout().getPointerSizeInBits(); StackSafetyDataFlowAnalysis<GlobalValue> SSDFA(PointerSize, std::move(Copy)); for (auto &F : SSDFA.run()) { @@ -794,6 +803,7 @@ const StackSafetyInfo::InfoTy &StackSafetyInfo::getInfo() const { void StackSafetyInfo::print(raw_ostream &O) const { getInfo().Info.print(O, F->getName(), dyn_cast<Function>(F)); + O << "\n"; } const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const { @@ -806,17 +816,22 @@ const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const { } } Info.reset(new InfoTy{ - createGlobalStackSafetyInfo(std::move(Functions), Index), {}}); + createGlobalStackSafetyInfo(std::move(Functions), Index), {}, {}}); + for (auto &FnKV : Info->Info) { for (auto &KV : FnKV.second.Allocas) { ++NumAllocaTotal; const AllocaInst *AI = KV.first; - if (getStaticAllocaSizeRange(*AI).contains(KV.second.Range)) { + auto AIRange = getStaticAllocaSizeRange(*AI); + if (AIRange.contains(KV.second.Range)) { Info->SafeAllocas.insert(AI); ++NumAllocaStackSafe; } + for (const auto &A : KV.second.Accesses) + Info->AccessIsUnsafe[A.first] |= !AIRange.contains(A.second); } } + if (StackSafetyPrint) print(errs()); } @@ -886,6 +901,15 @@ bool StackSafetyGlobalInfo::isSafe(const AllocaInst &AI) const { return Info.SafeAllocas.count(&AI); } +bool StackSafetyGlobalInfo::stackAccessIsSafe(const Instruction &I) const { + const auto &Info = getInfo(); + auto It = Info.AccessIsUnsafe.find(&I); + if (It == Info.AccessIsUnsafe.end()) { + return true; + } + return !It->second; +} + void StackSafetyGlobalInfo::print(raw_ostream &O) const { auto &SSI = getInfo().Info; if (SSI.empty()) @@ -894,6 +918,16 @@ void StackSafetyGlobalInfo::print(raw_ostream &O) const { for (auto &F : M.functions()) { if (!F.isDeclaration()) { SSI.find(&F)->second.print(O, F.getName(), &F); + O << " safe accesses:" + << "\n"; + for (const auto &I : instructions(F)) { + const CallInst *Call = dyn_cast<CallInst>(&I); + if ((isa<StoreInst>(I) || isa<LoadInst>(I) || isa<MemIntrinsic>(I) || + (Call && Call->hasByValArgument())) && + stackAccessIsSafe(I)) { + O << " " << I << "\n"; + } + } O << "\n"; } } diff --git a/llvm/lib/Analysis/TFUtils.cpp b/llvm/lib/Analysis/TFUtils.cpp index e93dc303ae63..3d10479c4544 100644 --- a/llvm/lib/Analysis/TFUtils.cpp +++ b/llvm/lib/Analysis/TFUtils.cpp @@ -1,9 +1,8 @@ //===- TFUtils.cpp - tensorflow evaluation utilities ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -262,29 +261,58 @@ private: class LoggerDataImpl { const std::vector<LoggedFeatureSpec> LoggedFeatureSpecs; const TensorSpec RewardSpec; + const bool IncludeReward; - tensorflow::SequenceExample SE; - std::vector<tensorflow::FeatureList *> FeatureLists; - tensorflow::FeatureList *Reward = nullptr; + std::vector<tensorflow::FeatureList> FeatureLists; + tensorflow::FeatureList Reward; -public: - LoggerDataImpl(const std::vector<LoggedFeatureSpec> &LoggedSpecs, - const TensorSpec &RewardSpec, bool IncludeReward) - : LoggedFeatureSpecs(LoggedSpecs), RewardSpec(RewardSpec) { + bool isSelfConsistent(const tensorflow::SequenceExample &SE, + size_t NrRecords) const { + bool Ret = true; + for (const auto &TSpecs : LoggedFeatureSpecs) { + const auto &Name = TSpecs.getLoggingName(); + const auto &FL = SE.feature_lists().feature_list().at(Name).feature(); + if (NrRecords != static_cast<size_t>(FL.size())) { + dbgs() << "[TF-UTILS]: " << Name << " has missing records. Expected " + << NrRecords << " got " << FL.size() << "\n"; + Ret = false; + } + } + if (IncludeReward && static_cast<size_t>(SE.feature_lists() + .feature_list() + .at(RewardSpec.name()) + .feature() + .size()) != NrRecords) { + dbgs() << "[TF-UTILS]: reward is missing records.\n"; + Ret = false; + } + return Ret; + } + + void transferLog(tensorflow::SequenceExample &SE) { auto *FL = SE.mutable_feature_lists()->mutable_feature_list(); if (IncludeReward) - Reward = &(*FL)[RewardSpec.name()]; - // Allocate first the map entries, then capture their address. We will not - // mutate the set of features after this (i.e. the pointers won't dangle). - for (const auto &LFS : LoggedSpecs) { - (*FL)[LFS.LoggingName ? *LFS.LoggingName : LFS.Spec.name()] = {}; + (*FL)[RewardSpec.name()] = std::move(Reward); + assert(FeatureLists.size() == LoggedFeatureSpecs.size()); + for (size_t I = 0; I < FeatureLists.size(); ++I) { + const auto &LFS = LoggedFeatureSpecs[I]; + (*FL)[LFS.getLoggingName()] = std::move(FeatureLists[I]); } - for (const auto &LFS : LoggedSpecs) - FeatureLists.push_back( - &(*FL)[LFS.LoggingName ? *LFS.LoggingName : LFS.Spec.name()]); } - void print(raw_ostream &OS) { +public: + LoggerDataImpl(const std::vector<LoggedFeatureSpec> &LoggedSpecs, + const TensorSpec &RewardSpec, bool IncludeReward) + : LoggedFeatureSpecs(LoggedSpecs), RewardSpec(RewardSpec), + IncludeReward(IncludeReward), FeatureLists(LoggedFeatureSpecs.size()) {} + + // flush the logged info to a stream and clear the log contents. + void flush(raw_ostream &OS) { + size_t NrRecords = getNrRecords(); + (void)NrRecords; + tensorflow::SequenceExample SE; + transferLog(SE); + assert(isSelfConsistent(SE, NrRecords)); std::string OutStr; if (ProtobufTextMode) google::protobuf::TextFormat::PrintToString(SE, &OutStr); @@ -298,14 +326,14 @@ public: const auto &Spec = LoggedFeatureSpecs[FeatureID].Spec; if (Spec.isElementType<float>()) { auto *RF = FeatureLists[FeatureID] - ->add_feature() + .add_feature() ->mutable_float_list() ->mutable_value(); RF->Resize(Spec.getElementCount(), 0.0); return reinterpret_cast<char *>(RF->mutable_data()); } else if (Spec.isElementType<int32_t>() || Spec.isElementType<int64_t>()) { auto *RF = FeatureLists[FeatureID] - ->add_feature() + .add_feature() ->mutable_int64_list() ->mutable_value(); RF->Resize(Spec.getElementCount(), 0); @@ -315,17 +343,18 @@ public: } template <typename T> void logReward(T Value) { + assert(IncludeReward); if (RewardSpec.isElementType<float>()) - Reward->add_feature()->mutable_float_list()->add_value(Value); + Reward.add_feature()->mutable_float_list()->add_value(Value); else if (RewardSpec.isElementType<int32_t>() || RewardSpec.isElementType<int64_t>()) - Reward->add_feature()->mutable_int64_list()->add_value(Value); + Reward.add_feature()->mutable_int64_list()->add_value(Value); else llvm_unreachable("Unsupported tensor type."); } size_t getNrRecords() const { - return FeatureLists.empty() ? 0 : FeatureLists[0]->feature().size(); + return FeatureLists.empty() ? 0 : FeatureLists[0].feature().size(); } }; } // namespace llvm @@ -538,5 +567,5 @@ char *Logger::addEntryAndGetFloatOrInt64Buffer(size_t FeatureID) { return reinterpret_cast<char *>(LoggerData->addNewTensor(FeatureID)); } -void Logger::print(raw_ostream &OS) { LoggerData->print(OS); } +void Logger::flush(raw_ostream &OS) { LoggerData->flush(OS); } #endif // defined(LLVM_HAVE_TF_API) diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 4a8818f2e2a8..7326ba74c071 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -123,6 +123,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, // Set IO unlocked variants as unavailable // Set them as available per system below + TLI.setUnavailable(LibFunc_getc_unlocked); TLI.setUnavailable(LibFunc_getchar_unlocked); TLI.setUnavailable(LibFunc_putc_unlocked); TLI.setUnavailable(LibFunc_putchar_unlocked); @@ -156,15 +157,10 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, // isn't true for a target those defaults should be overridden below. TLI.setIntSize(T.isArch16Bit() ? 16 : 32); - if (T.isAMDGPU()) - TLI.disableAllFunctions(); - - // There are no library implementations of memcpy and memset for AMD gpus and - // these can be difficult to lower in the backend. + // There is really no runtime library on AMDGPU, apart from + // __kmpc_alloc/free_shared. if (T.isAMDGPU()) { - TLI.setUnavailable(LibFunc_memcpy); - TLI.setUnavailable(LibFunc_memset); - TLI.setUnavailable(LibFunc_memset_pattern16); + TLI.disableAllFunctions(); TLI.setAvailable(llvm::LibFunc___kmpc_alloc_shared); TLI.setAvailable(llvm::LibFunc___kmpc_free_shared); return; @@ -418,6 +414,65 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_utimes); } + // Pick just one set of new/delete variants. + if (T.isOSMSVCRT()) { + // MSVC, doesn't have the Itanium new/delete. + TLI.setUnavailable(LibFunc_ZdaPv); + TLI.setUnavailable(LibFunc_ZdaPvRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZdaPvSt11align_val_t); + TLI.setUnavailable(LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZdaPvj); + TLI.setUnavailable(LibFunc_ZdaPvjSt11align_val_t); + TLI.setUnavailable(LibFunc_ZdaPvm); + TLI.setUnavailable(LibFunc_ZdaPvmSt11align_val_t); + TLI.setUnavailable(LibFunc_ZdlPv); + TLI.setUnavailable(LibFunc_ZdlPvRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZdlPvSt11align_val_t); + TLI.setUnavailable(LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZdlPvj); + TLI.setUnavailable(LibFunc_ZdlPvjSt11align_val_t); + TLI.setUnavailable(LibFunc_ZdlPvm); + TLI.setUnavailable(LibFunc_ZdlPvmSt11align_val_t); + TLI.setUnavailable(LibFunc_Znaj); + TLI.setUnavailable(LibFunc_ZnajRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnajSt11align_val_t); + TLI.setUnavailable(LibFunc_ZnajSt11align_val_tRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_Znam); + TLI.setUnavailable(LibFunc_ZnamRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnamSt11align_val_t); + TLI.setUnavailable(LibFunc_ZnamSt11align_val_tRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_Znwj); + TLI.setUnavailable(LibFunc_ZnwjRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnwjSt11align_val_t); + TLI.setUnavailable(LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_Znwm); + TLI.setUnavailable(LibFunc_ZnwmRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnwmSt11align_val_t); + TLI.setUnavailable(LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t); + } else { + // Not MSVC, assume it's Itanium. + TLI.setUnavailable(LibFunc_msvc_new_int); + TLI.setUnavailable(LibFunc_msvc_new_int_nothrow); + TLI.setUnavailable(LibFunc_msvc_new_longlong); + TLI.setUnavailable(LibFunc_msvc_new_longlong_nothrow); + TLI.setUnavailable(LibFunc_msvc_delete_ptr32); + TLI.setUnavailable(LibFunc_msvc_delete_ptr32_nothrow); + TLI.setUnavailable(LibFunc_msvc_delete_ptr32_int); + TLI.setUnavailable(LibFunc_msvc_delete_ptr64); + TLI.setUnavailable(LibFunc_msvc_delete_ptr64_nothrow); + TLI.setUnavailable(LibFunc_msvc_delete_ptr64_longlong); + TLI.setUnavailable(LibFunc_msvc_new_array_int); + TLI.setUnavailable(LibFunc_msvc_new_array_int_nothrow); + TLI.setUnavailable(LibFunc_msvc_new_array_longlong); + TLI.setUnavailable(LibFunc_msvc_new_array_longlong_nothrow); + TLI.setUnavailable(LibFunc_msvc_delete_array_ptr32); + TLI.setUnavailable(LibFunc_msvc_delete_array_ptr32_nothrow); + TLI.setUnavailable(LibFunc_msvc_delete_array_ptr32_int); + TLI.setUnavailable(LibFunc_msvc_delete_array_ptr64); + TLI.setUnavailable(LibFunc_msvc_delete_array_ptr64_nothrow); + TLI.setUnavailable(LibFunc_msvc_delete_array_ptr64_longlong); + } + switch (T.getOS()) { case Triple::MacOSX: // exp10 and exp10f are not available on OS X until 10.9 and iOS until 7.0 @@ -572,6 +627,9 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_sinh_finite); TLI.setUnavailable(LibFunc_sinhf_finite); TLI.setUnavailable(LibFunc_sinhl_finite); + TLI.setUnavailable(LibFunc_sqrt_finite); + TLI.setUnavailable(LibFunc_sqrtf_finite); + TLI.setUnavailable(LibFunc_sqrtl_finite); } if ((T.isOSLinux() && T.isGNUEnvironment()) || @@ -589,6 +647,140 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setAvailable(LibFunc_fgets_unlocked); } + if (T.isAndroid() && T.isAndroidVersionLT(21)) { + TLI.setUnavailable(LibFunc_stpcpy); + TLI.setUnavailable(LibFunc_stpncpy); + } + + if (T.isPS4()) { + // PS4 does have memalign. + TLI.setAvailable(LibFunc_memalign); + + // PS4 does not have new/delete with "unsigned int" size parameter; + // it only has the "unsigned long" versions. + TLI.setUnavailable(LibFunc_ZdaPvj); + TLI.setUnavailable(LibFunc_ZdaPvjSt11align_val_t); + TLI.setUnavailable(LibFunc_ZdlPvj); + TLI.setUnavailable(LibFunc_ZdlPvjSt11align_val_t); + TLI.setUnavailable(LibFunc_Znaj); + TLI.setUnavailable(LibFunc_ZnajRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnajSt11align_val_t); + TLI.setUnavailable(LibFunc_ZnajSt11align_val_tRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_Znwj); + TLI.setUnavailable(LibFunc_ZnwjRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnwjSt11align_val_t); + TLI.setUnavailable(LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t); + + // None of the *_chk functions. + TLI.setUnavailable(LibFunc_memccpy_chk); + TLI.setUnavailable(LibFunc_memcpy_chk); + TLI.setUnavailable(LibFunc_memmove_chk); + TLI.setUnavailable(LibFunc_mempcpy_chk); + TLI.setUnavailable(LibFunc_memset_chk); + TLI.setUnavailable(LibFunc_snprintf_chk); + TLI.setUnavailable(LibFunc_sprintf_chk); + TLI.setUnavailable(LibFunc_stpcpy_chk); + TLI.setUnavailable(LibFunc_stpncpy_chk); + TLI.setUnavailable(LibFunc_strcat_chk); + TLI.setUnavailable(LibFunc_strcpy_chk); + TLI.setUnavailable(LibFunc_strlcat_chk); + TLI.setUnavailable(LibFunc_strlcat_chk); + TLI.setUnavailable(LibFunc_strlcpy_chk); + TLI.setUnavailable(LibFunc_strlen_chk); + TLI.setUnavailable(LibFunc_strncat_chk); + TLI.setUnavailable(LibFunc_strncpy_chk); + TLI.setUnavailable(LibFunc_vsnprintf_chk); + TLI.setUnavailable(LibFunc_vsprintf_chk); + + // Various Posix system functions. + TLI.setUnavailable(LibFunc_access); + TLI.setUnavailable(LibFunc_chmod); + TLI.setUnavailable(LibFunc_chown); + TLI.setUnavailable(LibFunc_closedir); + TLI.setUnavailable(LibFunc_ctermid); + TLI.setUnavailable(LibFunc_execl); + TLI.setUnavailable(LibFunc_execle); + TLI.setUnavailable(LibFunc_execlp); + TLI.setUnavailable(LibFunc_execv); + TLI.setUnavailable(LibFunc_execvP); + TLI.setUnavailable(LibFunc_execve); + TLI.setUnavailable(LibFunc_execvp); + TLI.setUnavailable(LibFunc_execvpe); + TLI.setUnavailable(LibFunc_fork); + TLI.setUnavailable(LibFunc_fstat); + TLI.setUnavailable(LibFunc_fstatvfs); + TLI.setUnavailable(LibFunc_getenv); + TLI.setUnavailable(LibFunc_getitimer); + TLI.setUnavailable(LibFunc_getlogin_r); + TLI.setUnavailable(LibFunc_getpwnam); + TLI.setUnavailable(LibFunc_gettimeofday); + TLI.setUnavailable(LibFunc_lchown); + TLI.setUnavailable(LibFunc_lstat); + TLI.setUnavailable(LibFunc_mkdir); + TLI.setUnavailable(LibFunc_open); + TLI.setUnavailable(LibFunc_opendir); + TLI.setUnavailable(LibFunc_pclose); + TLI.setUnavailable(LibFunc_popen); + TLI.setUnavailable(LibFunc_pread); + TLI.setUnavailable(LibFunc_pwrite); + TLI.setUnavailable(LibFunc_read); + TLI.setUnavailable(LibFunc_readlink); + TLI.setUnavailable(LibFunc_realpath); + TLI.setUnavailable(LibFunc_rename); + TLI.setUnavailable(LibFunc_rmdir); + TLI.setUnavailable(LibFunc_setitimer); + TLI.setUnavailable(LibFunc_stat); + TLI.setUnavailable(LibFunc_statvfs); + TLI.setUnavailable(LibFunc_system); + TLI.setUnavailable(LibFunc_times); + TLI.setUnavailable(LibFunc_tmpfile); + TLI.setUnavailable(LibFunc_unlink); + TLI.setUnavailable(LibFunc_uname); + TLI.setUnavailable(LibFunc_unsetenv); + TLI.setUnavailable(LibFunc_utime); + TLI.setUnavailable(LibFunc_utimes); + TLI.setUnavailable(LibFunc_valloc); + TLI.setUnavailable(LibFunc_write); + + // Miscellaneous other functions not provided. + TLI.setUnavailable(LibFunc_atomic_load); + TLI.setUnavailable(LibFunc_atomic_store); + TLI.setUnavailable(LibFunc___kmpc_alloc_shared); + TLI.setUnavailable(LibFunc___kmpc_free_shared); + TLI.setUnavailable(LibFunc_dunder_strndup); + TLI.setUnavailable(LibFunc_bcmp); + TLI.setUnavailable(LibFunc_bcopy); + TLI.setUnavailable(LibFunc_bzero); + TLI.setUnavailable(LibFunc_cabs); + TLI.setUnavailable(LibFunc_cabsf); + TLI.setUnavailable(LibFunc_cabsl); + TLI.setUnavailable(LibFunc_ffs); + TLI.setUnavailable(LibFunc_flockfile); + TLI.setUnavailable(LibFunc_fseeko); + TLI.setUnavailable(LibFunc_ftello); + TLI.setUnavailable(LibFunc_ftrylockfile); + TLI.setUnavailable(LibFunc_funlockfile); + TLI.setUnavailable(LibFunc_htonl); + TLI.setUnavailable(LibFunc_htons); + TLI.setUnavailable(LibFunc_isascii); + TLI.setUnavailable(LibFunc_memccpy); + TLI.setUnavailable(LibFunc_mempcpy); + TLI.setUnavailable(LibFunc_memrchr); + TLI.setUnavailable(LibFunc_ntohl); + TLI.setUnavailable(LibFunc_ntohs); + TLI.setUnavailable(LibFunc_reallocf); + TLI.setUnavailable(LibFunc_roundeven); + TLI.setUnavailable(LibFunc_roundevenf); + TLI.setUnavailable(LibFunc_roundevenl); + TLI.setUnavailable(LibFunc_stpcpy); + TLI.setUnavailable(LibFunc_stpncpy); + TLI.setUnavailable(LibFunc_strlcat); + TLI.setUnavailable(LibFunc_strlcpy); + TLI.setUnavailable(LibFunc_strndup); + TLI.setUnavailable(LibFunc_strnlen); + TLI.setUnavailable(LibFunc_toascii); + } + // As currently implemented in clang, NVPTX code has no standard library to // speak of. Headers provide a standard-ish library implementation, but many // of the signatures are wrong -- for example, many libm functions are not @@ -691,7 +883,7 @@ TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(TargetLibraryInfoImpl && static StringRef sanitizeFunctionName(StringRef funcName) { // Filter out empty names and names containing null bytes, those can't be in // our table. - if (funcName.empty() || funcName.find('\0') != StringRef::npos) + if (funcName.empty() || funcName.contains('\0')) return StringRef(); // Check for \01 prefix that is used to mangle __asm declarations and @@ -716,12 +908,12 @@ bool TargetLibraryInfoImpl::getLibFunc(StringRef funcName, LibFunc &F) const { bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F, - const DataLayout *DL) const { - LLVMContext &Ctx = FTy.getContext(); - Type *SizeTTy = DL ? DL->getIntPtrType(Ctx, /*AddressSpace=*/0) : nullptr; - auto IsSizeTTy = [SizeTTy](Type *Ty) { - return SizeTTy ? Ty == SizeTTy : Ty->isIntegerTy(); - }; + const Module &M) const { + // FIXME: There is really no guarantee that sizeof(size_t) is equal to + // sizeof(int*) for every target. So the assumption used here to derive the + // SizeTBits based on the size of an integer pointer in address space zero + // isn't always valid. + unsigned SizeTBits = M.getDataLayout().getPointerSizeInBits(/*AddrSpace=*/0); unsigned NumParams = FTy.getNumParams(); switch (F) { @@ -745,12 +937,12 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, FTy.getReturnType()->isIntegerTy(32)); case LibFunc_strlen_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_strlen: - return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() && - FTy.getReturnType()->isIntegerTy()); + return NumParams == 1 && FTy.getParamType(0)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(SizeTBits); case LibFunc_strchr: case LibFunc_strrchr: @@ -770,7 +962,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, FTy.getParamType(1)->isPointerTy()); case LibFunc_strcat_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_strcat: @@ -780,19 +972,19 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_strncat_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_strncat: return (NumParams == 3 && FTy.getReturnType()->isPointerTy() && FTy.getParamType(0) == FTy.getReturnType() && FTy.getParamType(1) == FTy.getReturnType() && - IsSizeTTy(FTy.getParamType(2))); + FTy.getParamType(2)->isIntegerTy(SizeTBits)); case LibFunc_strcpy_chk: case LibFunc_stpcpy_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_strcpy: @@ -804,20 +996,20 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_strlcat_chk: case LibFunc_strlcpy_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_strlcat: case LibFunc_strlcpy: - return NumParams == 3 && IsSizeTTy(FTy.getReturnType()) && + return NumParams == 3 && FTy.getReturnType()->isIntegerTy(SizeTBits) && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1)->isPointerTy() && - IsSizeTTy(FTy.getParamType(2)); + FTy.getParamType(2)->isIntegerTy(SizeTBits); case LibFunc_strncpy_chk: case LibFunc_stpncpy_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_strncpy: @@ -825,7 +1017,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && FTy.getParamType(0) == FTy.getParamType(1) && FTy.getParamType(0)->isPointerTy() && - IsSizeTTy(FTy.getParamType(2))); + FTy.getParamType(2)->isIntegerTy(SizeTBits)); case LibFunc_strxfrm: return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && @@ -840,7 +1032,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, return (NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(0) == FTy.getParamType(1) && - IsSizeTTy(FTy.getParamType(2))); + FTy.getParamType(2)->isIntegerTy(SizeTBits)); case LibFunc_strspn: case LibFunc_strcspn: @@ -888,20 +1080,21 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_sprintf_chk: return NumParams == 4 && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1)->isIntegerTy(32) && - IsSizeTTy(FTy.getParamType(2)) && + FTy.getParamType(2)->isIntegerTy(SizeTBits) && FTy.getParamType(3)->isPointerTy() && FTy.getReturnType()->isIntegerTy(32); case LibFunc_snprintf: - return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && - FTy.getParamType(2)->isPointerTy() && - FTy.getReturnType()->isIntegerTy(32)); + return NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy(SizeTBits) && + FTy.getParamType(2)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(32); case LibFunc_snprintf_chk: return NumParams == 5 && FTy.getParamType(0)->isPointerTy() && - IsSizeTTy(FTy.getParamType(1)) && + FTy.getParamType(1)->isIntegerTy(SizeTBits) && FTy.getParamType(2)->isIntegerTy(32) && - IsSizeTTy(FTy.getParamType(3)) && + FTy.getParamType(3)->isIntegerTy(SizeTBits) && FTy.getParamType(4)->isPointerTy() && FTy.getReturnType()->isIntegerTy(32); @@ -915,16 +1108,17 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_vec_malloc: return (NumParams == 1 && FTy.getReturnType()->isPointerTy()); case LibFunc_memcmp: - return (NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) && - FTy.getParamType(0)->isPointerTy() && - FTy.getParamType(1)->isPointerTy()); + return NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isIntegerTy(SizeTBits); case LibFunc_memchr: case LibFunc_memrchr: return (NumParams == 3 && FTy.getReturnType()->isPointerTy() && FTy.getReturnType() == FTy.getParamType(0) && FTy.getParamType(1)->isIntegerTy(32) && - IsSizeTTy(FTy.getParamType(2))); + FTy.getParamType(2)->isIntegerTy(SizeTBits)); case LibFunc_modf: case LibFunc_modff: case LibFunc_modfl: @@ -934,7 +1128,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_mempcpy_chk: case LibFunc_memmove_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_memcpy: @@ -943,22 +1137,22 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1)->isPointerTy() && - IsSizeTTy(FTy.getParamType(2))); + FTy.getParamType(2)->isIntegerTy(SizeTBits)); case LibFunc_memset_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_memset: return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1)->isIntegerTy() && - IsSizeTTy(FTy.getParamType(2))); + FTy.getParamType(2)->isIntegerTy(SizeTBits)); case LibFunc_memccpy_chk: --NumParams; - if (!IsSizeTTy(FTy.getParamType(NumParams))) + if (!FTy.getParamType(NumParams)->isIntegerTy(SizeTBits)) return false; LLVM_FALLTHROUGH; case LibFunc_memccpy: @@ -970,7 +1164,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_vec_realloc: return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && FTy.getParamType(0) == FTy.getReturnType() && - IsSizeTTy(FTy.getParamType(1))); + FTy.getParamType(1)->isIntegerTy(SizeTBits)); case LibFunc_read: return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); case LibFunc_rewind: @@ -1051,7 +1245,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, return (NumParams != 0 && FTy.getParamType(0)->isPointerTy()); case LibFunc___kmpc_free_shared: return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && - IsSizeTTy(FTy.getParamType(1))); + FTy.getParamType(1)->isIntegerTy(SizeTBits)); case LibFunc_fopen: return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && @@ -1141,14 +1335,14 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_vsprintf_chk: return NumParams == 5 && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1)->isIntegerTy(32) && - IsSizeTTy(FTy.getParamType(2)) && FTy.getParamType(3)->isPointerTy(); + FTy.getParamType(2)->isIntegerTy(SizeTBits) && FTy.getParamType(3)->isPointerTy(); case LibFunc_vsnprintf: return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(2)->isPointerTy()); case LibFunc_vsnprintf_chk: return NumParams == 6 && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(2)->isIntegerTy(32) && - IsSizeTTy(FTy.getParamType(3)) && FTy.getParamType(4)->isPointerTy(); + FTy.getParamType(3)->isIntegerTy(SizeTBits) && FTy.getParamType(4)->isPointerTy(); case LibFunc_open: return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy()); case LibFunc_opendir: @@ -1560,12 +1754,13 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_strnlen: return (NumParams == 2 && FTy.getReturnType() == FTy.getParamType(1) && FTy.getParamType(0)->isPointerTy() && - IsSizeTTy(FTy.getParamType(1))); + FTy.getParamType(1)->isIntegerTy(SizeTBits)); case LibFunc_posix_memalign: return (NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) && FTy.getParamType(0)->isPointerTy() && - IsSizeTTy(FTy.getParamType(1)) && IsSizeTTy(FTy.getParamType(2))); + FTy.getParamType(1)->isIntegerTy(SizeTBits) && + FTy.getParamType(2)->isIntegerTy(SizeTBits)); case LibFunc_wcslen: return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() && @@ -1605,10 +1800,11 @@ bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl, // avoid string normalization and comparison. if (FDecl.isIntrinsic()) return false; - const DataLayout *DL = - FDecl.getParent() ? &FDecl.getParent()->getDataLayout() : nullptr; + const Module *M = FDecl.getParent(); + assert(M && "Expecting FDecl to be connected to a Module."); + return getLibFunc(FDecl.getName(), F) && - isValidProtoForLibFunc(*FDecl.getFunctionType(), F, DL); + isValidProtoForLibFunc(*FDecl.getFunctionType(), F, *M); } void TargetLibraryInfoImpl::disableAllFunctions() { diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index 304d24fe8e4a..5067f493f02d 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -167,11 +167,7 @@ bool HardwareLoopInfo::isHardwareLoopCandidate(ScalarEvolution &SE, // Note that this block may not be the loop latch block, even if the loop // has a latch block. ExitBlock = BB; - TripCount = SE.getAddExpr(EC, SE.getOne(EC->getType())); - - if (!EC->getType()->isPointerTy() && EC->getType() != CountType) - TripCount = SE.getZeroExtendExpr(TripCount, CountType); - + ExitCount = EC; break; } @@ -263,10 +259,20 @@ bool TargetTransformInfo::isNoopAddrSpaceCast(unsigned FromAS, return TTIImpl->isNoopAddrSpaceCast(FromAS, ToAS); } +bool TargetTransformInfo::canHaveNonUndefGlobalInitializerInAddressSpace( + unsigned AS) const { + return TTIImpl->canHaveNonUndefGlobalInitializerInAddressSpace(AS); +} + unsigned TargetTransformInfo::getAssumedAddrSpace(const Value *V) const { return TTIImpl->getAssumedAddrSpace(V); } +std::pair<const Value *, unsigned> +TargetTransformInfo::getPredicatedAddrSpace(const Value *V) const { + return TTIImpl->getPredicatedAddrSpace(V); +} + Value *TargetTransformInfo::rewriteIntrinsicWithAddressSpace( IntrinsicInst *II, Value *OldV, Value *NewV) const { return TTIImpl->rewriteIntrinsicWithAddressSpace(II, OldV, NewV); @@ -317,8 +323,9 @@ Optional<Value *> TargetTransformInfo::simplifyDemandedVectorEltsIntrinsic( } void TargetTransformInfo::getUnrollingPreferences( - Loop *L, ScalarEvolution &SE, UnrollingPreferences &UP) const { - return TTIImpl->getUnrollingPreferences(L, SE, UP); + Loop *L, ScalarEvolution &SE, UnrollingPreferences &UP, + OptimizationRemarkEmitter *ORE) const { + return TTIImpl->getUnrollingPreferences(L, SE, UP, ORE); } void TargetTransformInfo::getPeelingPreferences(Loop *L, ScalarEvolution &SE, @@ -409,6 +416,10 @@ bool TargetTransformInfo::isLegalMaskedExpandLoad(Type *DataType) const { return TTIImpl->isLegalMaskedExpandLoad(DataType); } +bool TargetTransformInfo::enableOrderedReductions() const { + return TTIImpl->enableOrderedReductions(); +} + bool TargetTransformInfo::hasDivRemOp(Type *DataType, bool IsSigned) const { return TTIImpl->hasDivRemOp(DataType, IsSigned); } @@ -598,6 +609,10 @@ Optional<unsigned> TargetTransformInfo::getMaxVScale() const { return TTIImpl->getMaxVScale(); } +Optional<unsigned> TargetTransformInfo::getVScaleForTuning() const { + return TTIImpl->getVScaleForTuning(); +} + bool TargetTransformInfo::shouldMaximizeVectorBandwidth() const { return TTIImpl->shouldMaximizeVectorBandwidth(); } @@ -818,6 +833,15 @@ InstructionCost TargetTransformInfo::getVectorInstrCost(unsigned Opcode, return Cost; } +InstructionCost TargetTransformInfo::getReplicationShuffleCost( + Type *EltTy, int ReplicationFactor, int VF, const APInt &DemandedDstElts, + TTI::TargetCostKind CostKind) { + InstructionCost Cost = TTIImpl->getReplicationShuffleCost( + EltTy, ReplicationFactor, VF, DemandedDstElts, CostKind); + assert(Cost >= 0 && "TTI should not produce negative costs!"); + return Cost; +} + InstructionCost TargetTransformInfo::getMemoryOpCost( unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, const Instruction *I) const { diff --git a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp index 20d718f4fad3..23dbb32f38de 100644 --- a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp +++ b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -521,21 +521,21 @@ static const MDNode *getLeastCommonType(const MDNode *A, const MDNode *B) { return Ret; } -void Instruction::getAAMetadata(AAMDNodes &N, bool Merge) const { - if (Merge) { - N.TBAA = - MDNode::getMostGenericTBAA(N.TBAA, getMetadata(LLVMContext::MD_tbaa)); - N.TBAAStruct = nullptr; - N.Scope = MDNode::getMostGenericAliasScope( - N.Scope, getMetadata(LLVMContext::MD_alias_scope)); - N.NoAlias = - MDNode::intersect(N.NoAlias, getMetadata(LLVMContext::MD_noalias)); - } else { - N.TBAA = getMetadata(LLVMContext::MD_tbaa); - N.TBAAStruct = getMetadata(LLVMContext::MD_tbaa_struct); - N.Scope = getMetadata(LLVMContext::MD_alias_scope); - N.NoAlias = getMetadata(LLVMContext::MD_noalias); - } +AAMDNodes AAMDNodes::merge(const AAMDNodes &Other) const { + AAMDNodes Result; + Result.TBAA = MDNode::getMostGenericTBAA(TBAA, Other.TBAA); + Result.TBAAStruct = nullptr; + Result.Scope = MDNode::getMostGenericAliasScope(Scope, Other.Scope); + Result.NoAlias = MDNode::intersect(NoAlias, Other.NoAlias); + return Result; +} + +AAMDNodes AAMDNodes::concat(const AAMDNodes &Other) const { + AAMDNodes Result; + Result.TBAA = Result.TBAAStruct = nullptr; + Result.Scope = MDNode::getMostGenericAliasScope(Scope, Other.Scope); + Result.NoAlias = MDNode::intersect(NoAlias, Other.NoAlias); + return Result; } static const MDNode *createAccessTag(const MDNode *AccessType) { diff --git a/llvm/lib/Analysis/TypeMetadataUtils.cpp b/llvm/lib/Analysis/TypeMetadataUtils.cpp index f015ba9a09ca..80051fd5f7c1 100644 --- a/llvm/lib/Analysis/TypeMetadataUtils.cpp +++ b/llvm/lib/Analysis/TypeMetadataUtils.cpp @@ -126,7 +126,8 @@ void llvm::findDevirtualizableCallsForTypeCheckedLoad( Offset->getZExtValue(), CI, DT); } -Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M) { +Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M, + Constant *TopLevelGlobal) { if (I->getType()->isPointerTy()) { if (Offset == 0) return I; @@ -142,7 +143,8 @@ Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M) { unsigned Op = SL->getElementContainingOffset(Offset); return getPointerAtOffset(cast<Constant>(I->getOperand(Op)), - Offset - SL->getElementOffset(Op), M); + Offset - SL->getElementOffset(Op), M, + TopLevelGlobal); } if (auto *C = dyn_cast<ConstantArray>(I)) { ArrayType *VTableTy = C->getType(); @@ -153,7 +155,62 @@ Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M) { return nullptr; return getPointerAtOffset(cast<Constant>(I->getOperand(Op)), - Offset % ElemSize, M); + Offset % ElemSize, M, TopLevelGlobal); + } + + // (Swift-specific) relative-pointer support starts here. + if (auto *CI = dyn_cast<ConstantInt>(I)) { + if (Offset == 0 && CI->getZExtValue() == 0) { + return I; + } + } + if (auto *C = dyn_cast<ConstantExpr>(I)) { + switch (C->getOpcode()) { + case Instruction::Trunc: + case Instruction::PtrToInt: + return getPointerAtOffset(cast<Constant>(C->getOperand(0)), Offset, M, + TopLevelGlobal); + case Instruction::Sub: { + auto *Operand0 = cast<Constant>(C->getOperand(0)); + auto *Operand1 = cast<Constant>(C->getOperand(1)); + + auto StripGEP = [](Constant *C) { + auto *CE = dyn_cast<ConstantExpr>(C); + if (!CE) + return C; + if (CE->getOpcode() != Instruction::GetElementPtr) + return C; + return CE->getOperand(0); + }; + auto *Operand1TargetGlobal = StripGEP(getPointerAtOffset(Operand1, 0, M)); + + // Check that in the "sub (@a, @b)" expression, @b points back to the top + // level global (or a GEP thereof) that we're processing. Otherwise bail. + if (Operand1TargetGlobal != TopLevelGlobal) + return nullptr; + + return getPointerAtOffset(Operand0, Offset, M, TopLevelGlobal); + } + default: + return nullptr; + } } return nullptr; } + +void llvm::replaceRelativePointerUsersWithZero(Function *F) { + for (auto *U : F->users()) { + auto *PtrExpr = dyn_cast<ConstantExpr>(U); + if (!PtrExpr || PtrExpr->getOpcode() != Instruction::PtrToInt) + continue; + + for (auto *PtrToIntUser : PtrExpr->users()) { + auto *SubExpr = dyn_cast<ConstantExpr>(PtrToIntUser); + if (!SubExpr || SubExpr->getOpcode() != Instruction::Sub) + continue; + + SubExpr->replaceNonMetadataUsesWith( + ConstantInt::get(SubExpr->getType(), 0)); + } + } +} diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 522d21812c6a..1c41c77a8cfb 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -84,6 +84,17 @@ using namespace llvm::PatternMatch; static cl::opt<unsigned> DomConditionsMaxUses("dom-conditions-max-uses", cl::Hidden, cl::init(20)); +// According to the LangRef, branching on a poison condition is absolutely +// immediate full UB. However, historically we haven't implemented that +// consistently as we have an important transformation (non-trivial unswitch) +// which introduces instances of branch on poison/undef to otherwise well +// defined programs. This flag exists to let us test optimization benefit +// of exploiting the specified behavior (in combination with enabling the +// unswitch fix.) +static cl::opt<bool> BranchOnPoisonAsUB("branch-on-poison-as-ub", + cl::Hidden, cl::init(false)); + + /// Returns the bitwidth of the given scalar or pointer type. For vector types, /// returns the element type's bitwidth. static unsigned getBitWidth(Type *Ty, const DataLayout &DL) { @@ -165,8 +176,8 @@ static bool getShuffleDemandedElts(const ShuffleVectorInst *Shuf, int NumElts = cast<FixedVectorType>(Shuf->getOperand(0)->getType())->getNumElements(); int NumMaskElts = cast<FixedVectorType>(Shuf->getType())->getNumElements(); - DemandedLHS = DemandedRHS = APInt::getNullValue(NumElts); - if (DemandedElts.isNullValue()) + DemandedLHS = DemandedRHS = APInt::getZero(NumElts); + if (DemandedElts.isZero()) return true; // Simple case of a shuffle with zeroinitializer. if (all_of(Shuf->getShuffleMask(), [](int Elt) { return Elt == 0; })) { @@ -206,7 +217,7 @@ static void computeKnownBits(const Value *V, KnownBits &Known, unsigned Depth, auto *FVTy = dyn_cast<FixedVectorType>(V->getType()); APInt DemandedElts = - FVTy ? APInt::getAllOnesValue(FVTy->getNumElements()) : APInt(1, 1); + FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1); computeKnownBits(V, DemandedElts, Known, Depth, Q); } @@ -279,16 +290,11 @@ bool llvm::haveNoCommonBitsSet(const Value *LHS, const Value *RHS, return KnownBits::haveNoCommonBitsSet(LHSKnown, RHSKnown); } -bool llvm::isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI) { - for (const User *U : CxtI->users()) { - if (const ICmpInst *IC = dyn_cast<ICmpInst>(U)) - if (IC->isEquality()) - if (Constant *C = dyn_cast<Constant>(IC->getOperand(1))) - if (C->isNullValue()) - continue; - return false; - } - return true; +bool llvm::isOnlyUsedInZeroEqualityComparison(const Instruction *I) { + return !I->user_empty() && all_of(I->users(), [](const User *U) { + ICmpInst::Predicate P; + return match(U, m_ICmp(P, m_Value(), m_Zero())) && ICmpInst::isEquality(P); + }); } static bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth, @@ -378,7 +384,7 @@ static unsigned ComputeNumSignBits(const Value *V, unsigned Depth, auto *FVTy = dyn_cast<FixedVectorType>(V->getType()); APInt DemandedElts = - FVTy ? APInt::getAllOnesValue(FVTy->getNumElements()) : APInt(1, 1); + FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1); return ComputeNumSignBits(V, DemandedElts, Depth, Q); } @@ -390,6 +396,14 @@ unsigned llvm::ComputeNumSignBits(const Value *V, const DataLayout &DL, V, Depth, Query(DL, AC, safeCxtI(V, CxtI), DT, UseInstrInfo)); } +unsigned llvm::ComputeMinSignedBits(const Value *V, const DataLayout &DL, + unsigned Depth, AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT) { + unsigned SignBits = ComputeNumSignBits(V, DL, Depth, AC, CxtI, DT); + return V->getType()->getScalarSizeInBits() - SignBits + 1; +} + static void computeKnownBitsAddSub(bool Add, const Value *Op0, const Value *Op1, bool NSW, const APInt &DemandedElts, KnownBits &KnownOut, KnownBits &Known2, @@ -499,7 +513,9 @@ static bool isEphemeralValueOf(const Instruction *I, const Value *E) { if (V == E) return true; - if (V == I || isSafeToSpeculativelyExecute(V)) { + if (V == I || (isa<Instruction>(V) && + !cast<Instruction>(V)->mayHaveSideEffects() && + !cast<Instruction>(V)->isTerminator())) { EphValues.insert(V); if (const User *U = dyn_cast<User>(V)) append_range(WorkSet, U->operands()); @@ -547,10 +563,9 @@ bool llvm::isValidAssumeForContext(const Instruction *Inv, // We limit the scan distance between the assume and its context instruction // to avoid a compile-time explosion. This limit is chosen arbitrarily, so // it can be adjusted if needed (could be turned into a cl::opt). - unsigned ScanLimit = 15; - for (BasicBlock::const_iterator I(CxtI), IE(Inv); I != IE; ++I) - if (!isGuaranteedToTransferExecutionToSuccessor(&*I) || --ScanLimit == 0) - return false; + auto Range = make_range(CxtI->getIterator(), Inv->getIterator()); + if (!isGuaranteedToTransferExecutionToSuccessor(Range, 15)) + return false; return !isEphemeralValueOf(Inv, CxtI); } @@ -582,7 +597,7 @@ static bool cmpExcludesZero(CmpInst::Predicate Pred, const Value *RHS) { return false; ConstantRange TrueValues = ConstantRange::makeExactICmpRegion(Pred, *C); - return !TrueValues.contains(APInt::getNullValue(C->getBitWidth())); + return !TrueValues.contains(APInt::getZero(C->getBitWidth())); } static bool isKnownNonZeroFromAssume(const Value *V, const Query &Q) { @@ -641,7 +656,7 @@ static void computeKnownBitsFromAssume(const Value *V, KnownBits &Known, if (V->getType()->isPointerTy()) { if (RetainedKnowledge RK = getKnowledgeValidInContext( V, {Attribute::Alignment}, Q.CxtI, Q.DT, Q.AC)) { - Known.Zero.setLowBits(Log2_32(RK.ArgValue)); + Known.Zero.setLowBits(Log2_64(RK.ArgValue)); } } @@ -1210,7 +1225,7 @@ static void computeKnownBitsFromOperator(const Operator *I, // (dependent on endian) to form the full result of known bits. unsigned NumElts = DemandedElts.getBitWidth(); unsigned SubScale = BitWidth / SubBitWidth; - APInt SubDemandedElts = APInt::getNullValue(NumElts * SubScale); + APInt SubDemandedElts = APInt::getZero(NumElts * SubScale); for (unsigned i = 0; i != NumElts; ++i) { if (DemandedElts[i]) SubDemandedElts.setBit(i * SubScale); @@ -1383,7 +1398,7 @@ static void computeKnownBitsFromOperator(const Operator *I, Known = KnownBits::computeForAddSub( /*Add=*/true, /*NSW=*/false, Known, IndexBits); } - if (!Known.isUnknown() && !AccConstIndices.isNullValue()) { + if (!Known.isUnknown() && !AccConstIndices.isZero()) { KnownBits Index = KnownBits::makeConstant(AccConstIndices); Known = KnownBits::computeForAddSub( /*Add=*/true, /*NSW=*/false, Known, Index); @@ -1512,7 +1527,7 @@ static void computeKnownBitsFromOperator(const Operator *I, // taking conservative care to avoid excessive recursion. if (Depth < MaxAnalysisRecursionDepth - 1 && !Known.Zero && !Known.One) { // Skip if every incoming value references to ourself. - if (dyn_cast_or_null<UndefValue>(P->hasConstantValue())) + if (isa_and_nonnull<UndefValue>(P->hasConstantValue())) break; Known.Zero.setAllBits(); @@ -1689,6 +1704,33 @@ static void computeKnownBitsFromOperator(const Operator *I, if (BitWidth >= 32) Known.Zero.setBitsFrom(31); break; + case Intrinsic::vscale: { + if (!II->getParent() || !II->getFunction() || + !II->getFunction()->hasFnAttribute(Attribute::VScaleRange)) + break; + + auto VScaleRange = II->getFunction() + ->getFnAttribute(Attribute::VScaleRange) + .getVScaleRangeArgs(); + + if (VScaleRange.second == 0) + break; + + // If vscale min = max then we know the exact value at compile time + // and hence we know the exact bits. + if (VScaleRange.first == VScaleRange.second) { + Known.One = VScaleRange.first; + Known.Zero = VScaleRange.first; + Known.Zero.flipAllBits(); + break; + } + + unsigned FirstZeroHighBit = 32 - countLeadingZeros(VScaleRange.second); + if (FirstZeroHighBit < BitWidth) + Known.Zero.setBitsFrom(FirstZeroHighBit); + + break; + } } } break; @@ -1763,7 +1805,7 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements(); - APInt DemandedVecElts = APInt::getAllOnesValue(NumElts); + APInt DemandedVecElts = APInt::getAllOnes(NumElts); if (CIdx && CIdx->getValue().ult(NumElts)) DemandedVecElts = APInt::getOneBitSet(NumElts, CIdx->getZExtValue()); computeKnownBits(Vec, DemandedVecElts, Known, Depth + 1, Q); @@ -2248,7 +2290,7 @@ static bool isNonZeroRecurrence(const PHINode *PN) { Value *Start = nullptr, *Step = nullptr; const APInt *StartC, *StepC; if (!matchSimpleRecurrence(PN, BO, Start, Step) || - !match(Start, m_APInt(StartC)) || StartC->isNullValue()) + !match(Start, m_APInt(StartC)) || StartC->isZero()) return false; switch (BO->getOpcode()) { @@ -2260,7 +2302,7 @@ static bool isNonZeroRecurrence(const PHINode *PN) { StartC->isNegative() == StepC->isNegative()); case Instruction::Mul: return (BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap()) && - match(Step, m_APInt(StepC)) && !StepC->isNullValue(); + match(Step, m_APInt(StepC)) && !StepC->isZero(); case Instruction::Shl: return BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap(); case Instruction::AShr: @@ -2532,7 +2574,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth, auto *CIdx = dyn_cast<ConstantInt>(Idx); if (auto *VecTy = dyn_cast<FixedVectorType>(Vec->getType())) { unsigned NumElts = VecTy->getNumElements(); - APInt DemandedVecElts = APInt::getAllOnesValue(NumElts); + APInt DemandedVecElts = APInt::getAllOnes(NumElts); if (CIdx && CIdx->getValue().ult(NumElts)) DemandedVecElts = APInt::getOneBitSet(NumElts, CIdx->getZExtValue()); return isKnownNonZero(Vec, DemandedVecElts, Depth, Q); @@ -2559,7 +2601,7 @@ bool isKnownNonZero(const Value* V, unsigned Depth, const Query& Q) { auto *FVTy = dyn_cast<FixedVectorType>(V->getType()); APInt DemandedElts = - FVTy ? APInt::getAllOnesValue(FVTy->getNumElements()) : APInt(1, 1); + FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1); return isKnownNonZero(V, DemandedElts, Depth, Q); } @@ -2694,8 +2736,7 @@ static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth, const APInt *C; return match(OBO, m_Mul(m_Specific(V1), m_APInt(C))) && (OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) && - !C->isNullValue() && !C->isOneValue() && - isKnownNonZero(V1, Depth + 1, Q); + !C->isZero() && !C->isOne() && isKnownNonZero(V1, Depth + 1, Q); } return false; } @@ -2708,7 +2749,7 @@ static bool isNonEqualShl(const Value *V1, const Value *V2, unsigned Depth, const APInt *C; return match(OBO, m_Shl(m_Specific(V1), m_APInt(C))) && (OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) && - !C->isNullValue() && isKnownNonZero(V1, Depth + 1, Q); + !C->isZero() && isKnownNonZero(V1, Depth + 1, Q); } return false; } @@ -3051,7 +3092,7 @@ static unsigned ComputeNumSignBitsImpl(const Value *V, // If the input is known to be 0 or 1, the output is 0/-1, which is // all sign bits set. - if ((Known.Zero | 1).isAllOnesValue()) + if ((Known.Zero | 1).isAllOnes()) return TyBits; // If we are subtracting one from a positive number, there is no carry @@ -3075,7 +3116,7 @@ static unsigned ComputeNumSignBitsImpl(const Value *V, computeKnownBits(U->getOperand(1), Known, Depth + 1, Q); // If the input is known to be 0 or 1, the output is 0/-1, which is // all sign bits set. - if ((Known.Zero | 1).isAllOnesValue()) + if ((Known.Zero | 1).isAllOnes()) return TyBits; // If the input is known to be positive (the sign bit is known clear), @@ -4533,6 +4574,12 @@ AllocaInst *llvm::findAllocaForValue(Value *V, bool OffsetZero) { if (OffsetZero && !GEP->hasAllZeroIndices()) return nullptr; AddWork(GEP->getPointerOperand()); + } else if (CallBase *CB = dyn_cast<CallBase>(V)) { + Value *Returned = CB->getReturnedArgOperand(); + if (Returned) + AddWork(Returned); + else + return nullptr; } else { return nullptr; } @@ -4614,7 +4661,7 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V, if (*Denominator == 0) return false; // It's safe to hoist if the denominator is not 0 or -1. - if (!Denominator->isAllOnesValue()) + if (!Denominator->isAllOnes()) return true; // At this point we know that the denominator is -1. It is safe to hoist as // long we know that the numerator is not INT_MIN. @@ -4922,15 +4969,14 @@ bool llvm::isOverflowIntrinsicNoWrap(const WithOverflowInst *WO, return llvm::any_of(GuardingBranches, AllUsesGuardedByBranch); } -static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly) { - // See whether I has flags that may create poison - if (const auto *OvOp = dyn_cast<OverflowingBinaryOperator>(Op)) { - if (OvOp->hasNoSignedWrap() || OvOp->hasNoUnsignedWrap()) - return true; - } - if (const auto *ExactOp = dyn_cast<PossiblyExactOperator>(Op)) - if (ExactOp->isExact()) - return true; +static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly, + bool ConsiderFlags) { + + if (ConsiderFlags && Op->hasPoisonGeneratingFlags()) + return true; + + // TODO: this should really be under the ConsiderFlags block, but currently + // these are not dropped by dropPoisonGeneratingFlags if (const auto *FP = dyn_cast<FPMathOperator>(Op)) { auto FMF = FP->getFastMathFlags(); if (FMF.noNaNs() || FMF.noInfs()) @@ -5019,10 +5065,10 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly) { case Instruction::ICmp: case Instruction::FCmp: return false; - case Instruction::GetElementPtr: { - const auto *GEP = cast<GEPOperator>(Op); - return GEP->isInBounds(); - } + case Instruction::GetElementPtr: + // inbounds is handled above + // TODO: what about inrange on constexpr? + return false; default: { const auto *CE = dyn_cast<ConstantExpr>(Op); if (isa<CastInst>(Op) || (CE && CE->isCast())) @@ -5035,12 +5081,12 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly) { } } -bool llvm::canCreateUndefOrPoison(const Operator *Op) { - return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false); +bool llvm::canCreateUndefOrPoison(const Operator *Op, bool ConsiderFlags) { + return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false, ConsiderFlags); } -bool llvm::canCreatePoison(const Operator *Op) { - return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true); +bool llvm::canCreatePoison(const Operator *Op, bool ConsiderFlags) { + return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true, ConsiderFlags); } static bool directlyImpliesPoison(const Value *ValAssumedPoison, @@ -5068,7 +5114,7 @@ static bool directlyImpliesPoison(const Value *ValAssumedPoison, const WithOverflowInst *II; if (match(I, m_ExtractValue(m_WithOverflowInst(II))) && (match(ValAssumedPoison, m_ExtractValue(m_Specific(II))) || - llvm::is_contained(II->arg_operands(), ValAssumedPoison))) + llvm::is_contained(II->args(), ValAssumedPoison))) return true; } return false; @@ -5225,8 +5271,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V, Dominator = Dominator->getIDom(); } - SmallVector<Attribute::AttrKind, 2> AttrKinds{Attribute::NoUndef}; - if (getKnowledgeValidInContext(V, AttrKinds, CtxI, DT, AC)) + if (getKnowledgeValidInContext(V, {Attribute::NoUndef}, CtxI, DT, AC)) return true; return false; @@ -5304,6 +5349,27 @@ bool llvm::isGuaranteedToTransferExecutionToSuccessor(const BasicBlock *BB) { return true; } +bool llvm::isGuaranteedToTransferExecutionToSuccessor( + BasicBlock::const_iterator Begin, BasicBlock::const_iterator End, + unsigned ScanLimit) { + return isGuaranteedToTransferExecutionToSuccessor(make_range(Begin, End), + ScanLimit); +} + +bool llvm::isGuaranteedToTransferExecutionToSuccessor( + iterator_range<BasicBlock::const_iterator> Range, unsigned ScanLimit) { + assert(ScanLimit && "scan limit must be non-zero"); + for (const Instruction &I : Range) { + if (isa<DbgInfoIntrinsic>(I)) + continue; + if (--ScanLimit == 0) + return false; + if (!isGuaranteedToTransferExecutionToSuccessor(&I)) + return false; + } + return true; +} + bool llvm::isGuaranteedToExecuteForEveryIteration(const Instruction *I, const Loop *L) { // The loop header is guaranteed to be executed for every iteration. @@ -5391,7 +5457,10 @@ void llvm::getGuaranteedWellDefinedOps( } break; } - + case Instruction::Ret: + if (I->getFunction()->hasRetAttribute(Attribute::NoUndef)) + Operands.insert(I->getOperand(0)); + break; default: break; } @@ -5408,7 +5477,16 @@ void llvm::getGuaranteedNonPoisonOps(const Instruction *I, case Instruction::SRem: Operands.insert(I->getOperand(1)); break; - + case Instruction::Switch: + if (BranchOnPoisonAsUB) + Operands.insert(cast<SwitchInst>(I)->getCondition()); + break; + case Instruction::Br: { + auto *BR = cast<BranchInst>(I); + if (BranchOnPoisonAsUB && BR->isConditional()) + Operands.insert(BR->getCondition()); + break; + } default: break; } @@ -5835,15 +5913,13 @@ static SelectPatternResult matchMinMax(CmpInst::Predicate Pred, // Is the sign bit set? // (X <s 0) ? X : MAXVAL ==> (X >u MAXVAL) ? X : MAXVAL ==> UMAX // (X <s 0) ? MAXVAL : X ==> (X >u MAXVAL) ? MAXVAL : X ==> UMIN - if (Pred == CmpInst::ICMP_SLT && C1->isNullValue() && - C2->isMaxSignedValue()) + if (Pred == CmpInst::ICMP_SLT && C1->isZero() && C2->isMaxSignedValue()) return {CmpLHS == TrueVal ? SPF_UMAX : SPF_UMIN, SPNB_NA, false}; // Is the sign bit clear? // (X >s -1) ? MINVAL : X ==> (X <u MINVAL) ? MINVAL : X ==> UMAX // (X >s -1) ? X : MINVAL ==> (X <u MINVAL) ? X : MINVAL ==> UMIN - if (Pred == CmpInst::ICMP_SGT && C1->isAllOnesValue() && - C2->isMinSignedValue()) + if (Pred == CmpInst::ICMP_SGT && C1->isAllOnes() && C2->isMinSignedValue()) return {CmpLHS == FalseVal ? SPF_UMAX : SPF_UMIN, SPNB_NA, false}; } @@ -6253,6 +6329,16 @@ CmpInst::Predicate llvm::getInverseMinMaxPred(SelectPatternFlavor SPF) { return getMinMaxPred(getInverseMinMaxFlavor(SPF)); } +APInt llvm::getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth) { + switch (SPF) { + case SPF_SMAX: return APInt::getSignedMaxValue(BitWidth); + case SPF_SMIN: return APInt::getSignedMinValue(BitWidth); + case SPF_UMAX: return APInt::getMaxValue(BitWidth); + case SPF_UMIN: return APInt::getMinValue(BitWidth); + default: llvm_unreachable("Unexpected flavor"); + } +} + std::pair<Intrinsic::ID, bool> llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) { // Check if VL contains select instructions that can be folded into a min/max @@ -6681,7 +6767,7 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower, const APInt *C; switch (BO.getOpcode()) { case Instruction::Add: - if (match(BO.getOperand(1), m_APInt(C)) && !C->isNullValue()) { + if (match(BO.getOperand(1), m_APInt(C)) && !C->isZero()) { // FIXME: If we have both nuw and nsw, we should reduce the range further. if (IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(&BO))) { // 'add nuw x, C' produces [C, UINT_MAX]. @@ -6719,7 +6805,7 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower, Upper = APInt::getSignedMaxValue(Width).ashr(*C) + 1; } else if (match(BO.getOperand(0), m_APInt(C))) { unsigned ShiftAmount = Width - 1; - if (!C->isNullValue() && IIQ.isExact(&BO)) + if (!C->isZero() && IIQ.isExact(&BO)) ShiftAmount = C->countTrailingZeros(); if (C->isNegative()) { // 'ashr C, x' produces [C, C >> (Width-1)] @@ -6736,11 +6822,11 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower, case Instruction::LShr: if (match(BO.getOperand(1), m_APInt(C)) && C->ult(Width)) { // 'lshr x, C' produces [0, UINT_MAX >> C]. - Upper = APInt::getAllOnesValue(Width).lshr(*C) + 1; + Upper = APInt::getAllOnes(Width).lshr(*C) + 1; } else if (match(BO.getOperand(0), m_APInt(C))) { // 'lshr C, x' produces [C >> (Width-1), C]. unsigned ShiftAmount = Width - 1; - if (!C->isNullValue() && IIQ.isExact(&BO)) + if (!C->isZero() && IIQ.isExact(&BO)) ShiftAmount = C->countTrailingZeros(); Lower = C->lshr(ShiftAmount); Upper = *C + 1; @@ -6773,7 +6859,7 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower, if (match(BO.getOperand(1), m_APInt(C))) { APInt IntMin = APInt::getSignedMinValue(Width); APInt IntMax = APInt::getSignedMaxValue(Width); - if (C->isAllOnesValue()) { + if (C->isAllOnes()) { // 'sdiv x, -1' produces [INT_MIN + 1, INT_MAX] // where C != -1 and C != 0 and C != 1 Lower = IntMin + 1; @@ -6802,7 +6888,7 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower, break; case Instruction::UDiv: - if (match(BO.getOperand(1), m_APInt(C)) && !C->isNullValue()) { + if (match(BO.getOperand(1), m_APInt(C)) && !C->isZero()) { // 'udiv x, C' produces [0, UINT_MAX / C]. Upper = APInt::getMaxValue(Width).udiv(*C) + 1; } else if (match(BO.getOperand(0), m_APInt(C))) { @@ -6946,7 +7032,7 @@ static void setLimitsForSelectPattern(const SelectInst &SI, APInt &Lower, // If the negation part of the abs (in RHS) has the NSW flag, // then the result of abs(X) is [0..SIGNED_MAX], // otherwise it is [0..SIGNED_MIN], as -SIGNED_MIN == SIGNED_MIN. - Lower = APInt::getNullValue(BitWidth); + Lower = APInt::getZero(BitWidth); if (match(RHS, m_Neg(m_Specific(LHS))) && IIQ.hasNoSignedWrap(cast<Instruction>(RHS))) Upper = APInt::getSignedMaxValue(BitWidth) + 1; @@ -6986,9 +7072,27 @@ static void setLimitsForSelectPattern(const SelectInst &SI, APInt &Lower, } } +static void setLimitForFPToI(const Instruction *I, APInt &Lower, APInt &Upper) { + // The maximum representable value of a half is 65504. For floats the maximum + // value is 3.4e38 which requires roughly 129 bits. + unsigned BitWidth = I->getType()->getScalarSizeInBits(); + if (!I->getOperand(0)->getType()->getScalarType()->isHalfTy()) + return; + if (isa<FPToSIInst>(I) && BitWidth >= 17) { + Lower = APInt(BitWidth, -65504); + Upper = APInt(BitWidth, 65505); + } + + if (isa<FPToUIInst>(I) && BitWidth >= 16) { + // For a fptoui the lower limit is left as 0. + Upper = APInt(BitWidth, 65505); + } +} + ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo, AssumptionCache *AC, const Instruction *CtxI, + const DominatorTree *DT, unsigned Depth) { assert(V->getType()->isIntOrIntVectorTy() && "Expected integer instruction"); @@ -7009,6 +7113,8 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo, setLimitsForIntrinsic(*II, Lower, Upper); else if (auto *SI = dyn_cast<SelectInst>(V)) setLimitsForSelectPattern(*SI, Lower, Upper, IIQ); + else if (isa<FPToUIInst>(V) || isa<FPToSIInst>(V)) + setLimitForFPToI(cast<Instruction>(V), Lower, Upper); ConstantRange CR = ConstantRange::getNonEmpty(Lower, Upper); @@ -7027,7 +7133,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo, assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume && "must be an assume intrinsic"); - if (!isValidAssumeForContext(I, CtxI, nullptr)) + if (!isValidAssumeForContext(I, CtxI, DT)) continue; Value *Arg = I->getArgOperand(0); ICmpInst *Cmp = dyn_cast<ICmpInst>(Arg); @@ -7035,9 +7141,9 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo, if (!Cmp || Cmp->getOperand(0) != V) continue; ConstantRange RHS = computeConstantRange(Cmp->getOperand(1), UseInstrInfo, - AC, I, Depth + 1); + AC, I, DT, Depth + 1); CR = CR.intersectWith( - ConstantRange::makeSatisfyingICmpRegion(Cmp->getPredicate(), RHS)); + ConstantRange::makeAllowedICmpRegion(Cmp->getPredicate(), RHS)); } } diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp index 0a14a1432934..655c248907f6 100644 --- a/llvm/lib/Analysis/VectorUtils.cpp +++ b/llvm/lib/Analysis/VectorUtils.cpp @@ -331,6 +331,12 @@ Value *llvm::findScalarElement(Value *V, unsigned EltNo) { if (Elt->isNullValue()) return findScalarElement(Val, EltNo); + // If the vector is a splat then we can trivially find the scalar element. + if (isa<ScalableVectorType>(VTy)) + if (Value *Splat = getSplatValue(V)) + if (EltNo < VTy->getElementCount().getKnownMinValue()) + return Splat; + // Otherwise, we don't know. return nullptr; } @@ -824,6 +830,23 @@ llvm::SmallVector<int, 16> llvm::createSequentialMask(unsigned Start, return Mask; } +llvm::SmallVector<int, 16> llvm::createUnaryMask(ArrayRef<int> Mask, + unsigned NumElts) { + // Avoid casts in the loop and make sure we have a reasonable number. + int NumEltsSigned = NumElts; + assert(NumEltsSigned > 0 && "Expected smaller or non-zero element count"); + + // If the mask chooses an element from operand 1, reduce it to choose from the + // corresponding element of operand 0. Undef mask elements are unchanged. + SmallVector<int, 16> UnaryMask; + for (int MaskElt : Mask) { + assert((MaskElt < NumEltsSigned * 2) && "Expected valid shuffle mask"); + int UnaryElt = MaskElt >= NumEltsSigned ? MaskElt - NumEltsSigned : MaskElt; + UnaryMask.push_back(UnaryElt); + } + return UnaryMask; +} + /// A helper function for concatenating vectors. This function concatenates two /// vectors having the same element type. If the second vector has fewer /// elements than the first, it is padded with undefs. @@ -940,7 +963,7 @@ APInt llvm::possiblyDemandedEltsInMask(Value *Mask) { const unsigned VWidth = cast<FixedVectorType>(Mask->getType())->getNumElements(); - APInt DemandedElts = APInt::getAllOnesValue(VWidth); + APInt DemandedElts = APInt::getAllOnes(VWidth); if (auto *CV = dyn_cast<ConstantVector>(Mask)) for (unsigned i = 0; i < VWidth; i++) if (CV->getAggregateElement(i)->isNullValue()) @@ -980,7 +1003,7 @@ void InterleavedAccessInfo::collectConstStrideAccesses( // wrap around the address space we would do a memory access at nullptr // even without the transformation. The wrapping checks are therefore // deferred until after we've formed the interleaved groups. - int64_t Stride = getPtrStride(PSE, Ptr, TheLoop, Strides, + int64_t Stride = getPtrStride(PSE, ElementTy, Ptr, TheLoop, Strides, /*Assume=*/true, /*ShouldCheckWrap=*/false); const SCEV *Scev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr); @@ -1193,15 +1216,24 @@ void InterleavedAccessInfo::analyzeInterleaving( } // Iteration over A accesses. } // Iteration over B accesses. - // Remove interleaved store groups with gaps. - for (auto *Group : StoreGroups) - if (Group->getNumMembers() != Group->getFactor()) { - LLVM_DEBUG( - dbgs() << "LV: Invalidate candidate interleaved store group due " - "to gaps.\n"); - releaseGroup(Group); - } - // Remove interleaved groups with gaps (currently only loads) whose memory + auto InvalidateGroupIfMemberMayWrap = [&](InterleaveGroup<Instruction> *Group, + int Index, + std::string FirstOrLast) -> bool { + Instruction *Member = Group->getMember(Index); + assert(Member && "Group member does not exist"); + Value *MemberPtr = getLoadStorePointerOperand(Member); + Type *AccessTy = getLoadStoreType(Member); + if (getPtrStride(PSE, AccessTy, MemberPtr, TheLoop, Strides, + /*Assume=*/false, /*ShouldCheckWrap=*/true)) + return false; + LLVM_DEBUG(dbgs() << "LV: Invalidate candidate interleaved group due to " + << FirstOrLast + << " group member potentially pointer-wrapping.\n"); + releaseGroup(Group); + return true; + }; + + // Remove interleaved groups with gaps whose memory // accesses may wrap around. We have to revisit the getPtrStride analysis, // this time with ShouldCheckWrap=true, since collectConstStrideAccesses does // not check wrapping (see documentation there). @@ -1227,26 +1259,12 @@ void InterleavedAccessInfo::analyzeInterleaving( // So we check only group member 0 (which is always guaranteed to exist), // and group member Factor - 1; If the latter doesn't exist we rely on // peeling (if it is a non-reversed accsess -- see Case 3). - Value *FirstMemberPtr = getLoadStorePointerOperand(Group->getMember(0)); - if (!getPtrStride(PSE, FirstMemberPtr, TheLoop, Strides, /*Assume=*/false, - /*ShouldCheckWrap=*/true)) { - LLVM_DEBUG( - dbgs() << "LV: Invalidate candidate interleaved group due to " - "first group member potentially pointer-wrapping.\n"); - releaseGroup(Group); + if (InvalidateGroupIfMemberMayWrap(Group, 0, std::string("first"))) continue; - } - Instruction *LastMember = Group->getMember(Group->getFactor() - 1); - if (LastMember) { - Value *LastMemberPtr = getLoadStorePointerOperand(LastMember); - if (!getPtrStride(PSE, LastMemberPtr, TheLoop, Strides, /*Assume=*/false, - /*ShouldCheckWrap=*/true)) { - LLVM_DEBUG( - dbgs() << "LV: Invalidate candidate interleaved group due to " - "last group member potentially pointer-wrapping.\n"); - releaseGroup(Group); - } - } else { + if (Group->getMember(Group->getFactor() - 1)) + InvalidateGroupIfMemberMayWrap(Group, Group->getFactor() - 1, + std::string("last")); + else { // Case 3: A non-reversed interleaved load group with gaps: We need // to execute at least one scalar epilogue iteration. This will ensure // we don't speculatively access memory out-of-bounds. We only need @@ -1264,6 +1282,39 @@ void InterleavedAccessInfo::analyzeInterleaving( RequiresScalarEpilogue = true; } } + + for (auto *Group : StoreGroups) { + // Case 1: A full group. Can Skip the checks; For full groups, if the wide + // store would wrap around the address space we would do a memory access at + // nullptr even without the transformation. + if (Group->getNumMembers() == Group->getFactor()) + continue; + + // Interleave-store-group with gaps is implemented using masked wide store. + // Remove interleaved store groups with gaps if + // masked-interleaved-accesses are not enabled by the target. + if (!EnablePredicatedInterleavedMemAccesses) { + LLVM_DEBUG( + dbgs() << "LV: Invalidate candidate interleaved store group due " + "to gaps.\n"); + releaseGroup(Group); + continue; + } + + // Case 2: If first and last members of the group don't wrap this implies + // that all the pointers in the group don't wrap. + // So we check only group member 0 (which is always guaranteed to exist), + // and the last group member. Case 3 (scalar epilog) is not relevant for + // stores with gaps, which are implemented with masked-store (rather than + // speculative access, as in loads). + if (InvalidateGroupIfMemberMayWrap(Group, 0, std::string("first"))) + continue; + for (int Index = Group->getFactor() - 1; Index > 0; Index--) + if (Group->getMember(Index)) { + InvalidateGroupIfMemberMayWrap(Group, Index, std::string("last")); + break; + } + } } void InterleavedAccessInfo::invalidateGroupsRequiringScalarEpilogue() { @@ -1325,9 +1376,7 @@ std::string VFABI::mangleTLIVectorName(StringRef VectorName, void VFABI::getVectorVariantNames( const CallInst &CI, SmallVectorImpl<std::string> &VariantMappings) { - const StringRef S = - CI.getAttribute(AttributeList::FunctionIndex, VFABI::MappingsAttrName) - .getValueAsString(); + const StringRef S = CI.getFnAttr(VFABI::MappingsAttrName).getValueAsString(); if (S.empty()) return; |
