diff options
Diffstat (limited to 'llvm/lib/Analysis/InlineCost.cpp')
-rw-r--r-- | llvm/lib/Analysis/InlineCost.cpp | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index 7bd1f18..fe1ceb7 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -391,7 +391,8 @@ protected: /// likely simplifications post-inlining. The most important aspect we track /// is CFG altering simplifications -- when we prove a basic block dead, that /// can cause dramatic shifts in the cost of inlining a function. - DenseMap<Value *, Constant *> SimplifiedValues; + /// Note: The simplified Value may be owned by the caller function. + DenseMap<Value *, Value *> SimplifiedValues; /// Keep track of the values which map back (through function arguments) to /// allocas on the caller stack which could be simplified through SROA. @@ -432,7 +433,7 @@ protected: template <typename T> T *getDirectOrSimplifiedValue(Value *V) const { if (auto *Direct = dyn_cast<T>(V)) return Direct; - return dyn_cast_if_present<T>(SimplifiedValues.lookup(V)); + return getSimplifiedValue<T>(V); } // Custom simplification helper routines. @@ -525,11 +526,33 @@ public: InlineResult analyze(); - std::optional<Constant *> getSimplifiedValue(Instruction *I) { - auto It = SimplifiedValues.find(I); - if (It != SimplifiedValues.end()) - return It->second; - return std::nullopt; + /// Lookup simplified Value. May return a value owned by the caller. + Value *getSimplifiedValueUnchecked(Value *V) const { + return SimplifiedValues.lookup(V); + } + + /// Lookup simplified Value, but return nullptr if the simplified value is + /// owned by the caller. + template <typename T> T *getSimplifiedValue(Value *V) const { + Value *SimpleV = SimplifiedValues.lookup(V); + if (!SimpleV) + return nullptr; + + // Skip checks if we know T is a global. This has a small, but measurable + // impact on compile-time. + if constexpr (std::is_base_of_v<Constant, T>) + return dyn_cast<T>(SimpleV); + + // Make sure the simplified Value is owned by this function + if (auto *I = dyn_cast<Instruction>(SimpleV)) { + if (I->getFunction() != &F) + return nullptr; + } else if (auto *Arg = dyn_cast<Argument>(SimpleV)) { + if (Arg->getParent() != &F) + return nullptr; + } else if (!isa<Constant>(SimpleV)) + return nullptr; + return dyn_cast<T>(SimpleV); } // Keep a bunch of stats about the cost savings found so we can print them @@ -921,12 +944,11 @@ 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() && - isa_and_nonnull<ConstantInt>( - SimplifiedValues.lookup(BI->getCondition()))) { + getSimplifiedValue<ConstantInt>(BI->getCondition())) { CurrentSavings += InstrCost; } } else if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) { - if (isa_and_present<ConstantInt>(SimplifiedValues.lookup(SI->getCondition()))) + if (getSimplifiedValue<ConstantInt>(SI->getCondition())) CurrentSavings += InstrCost; } else if (Value *V = dyn_cast<Value>(&I)) { // Count an instruction as savings if we can fold it. @@ -1423,10 +1445,17 @@ void InlineCostAnnotationWriter::emitInstructionAnnot( if (Record->hasThresholdChanged()) OS << ", threshold delta = " << Record->getThresholdDelta(); } - auto C = ICCA->getSimplifiedValue(const_cast<Instruction *>(I)); - if (C) { + auto *V = ICCA->getSimplifiedValueUnchecked(const_cast<Instruction *>(I)); + if (V) { OS << ", simplified to "; - (*C)->print(OS, true); + V->print(OS, true); + if (auto *VI = dyn_cast<Instruction>(V)) { + if (VI->getFunction() != I->getFunction()) + OS << " (caller instruction)"; + } else if (auto *VArg = dyn_cast<Argument>(V)) { + if (VArg->getParent() != I->getFunction()) + OS << " (caller argument)"; + } } OS << "\n"; } @@ -1483,7 +1512,7 @@ bool CallAnalyzer::isGEPFree(GetElementPtrInst &GEP) { SmallVector<Value *, 4> Operands; Operands.push_back(GEP.getOperand(0)); for (const Use &Op : GEP.indices()) - if (Constant *SimpleOp = SimplifiedValues.lookup(Op)) + if (Constant *SimpleOp = getSimplifiedValue<Constant>(Op)) Operands.push_back(SimpleOp); else Operands.push_back(Op); @@ -1498,7 +1527,7 @@ bool CallAnalyzer::visitAlloca(AllocaInst &I) { // Check whether inlining will turn a dynamic alloca into a static // alloca and handle that case. if (I.isArrayAllocation()) { - Constant *Size = SimplifiedValues.lookup(I.getArraySize()); + Constant *Size = getSimplifiedValue<Constant>(I.getArraySize()); if (auto *AllocSize = dyn_cast_or_null<ConstantInt>(Size)) { // Sometimes a dynamic alloca could be converted into a static alloca // after this constant prop, and become a huge static alloca on an @@ -2388,7 +2417,7 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) { // Check if this happens to be an indirect function call to a known function // in this inline context. If not, we've done all we can. Value *Callee = Call.getCalledOperand(); - F = dyn_cast_or_null<Function>(SimplifiedValues.lookup(Callee)); + F = getSimplifiedValue<Function>(Callee); if (!F || F->getFunctionType() != Call.getFunctionType()) { onCallArgumentSetup(Call); @@ -2483,8 +2512,7 @@ bool CallAnalyzer::visitSelectInst(SelectInst &SI) { Constant *TrueC = getDirectOrSimplifiedValue<Constant>(TrueVal); Constant *FalseC = getDirectOrSimplifiedValue<Constant>(FalseVal); - Constant *CondC = - dyn_cast_or_null<Constant>(SimplifiedValues.lookup(SI.getCondition())); + Constant *CondC = getSimplifiedValue<Constant>(SI.getCondition()); if (!CondC) { // Select C, X, X => X @@ -2833,8 +2861,9 @@ InlineResult CallAnalyzer::analyze() { auto CAI = CandidateCall.arg_begin(); for (Argument &FAI : F.args()) { assert(CAI != CandidateCall.arg_end()); - if (Constant *C = dyn_cast<Constant>(CAI)) - SimplifiedValues[&FAI] = C; + SimplifiedValues[&FAI] = *CAI; + if (isa<Constant>(*CAI)) + ++NumConstantArgs; Value *PtrArg = *CAI; if (ConstantInt *C = stripAndComputeInBoundsConstantOffsets(PtrArg)) { @@ -2849,7 +2878,6 @@ InlineResult CallAnalyzer::analyze() { } ++CAI; } - NumConstantArgs = SimplifiedValues.size(); NumConstantOffsetPtrArgs = ConstantOffsetPtrs.size(); NumAllocaArgs = SROAArgValues.size(); @@ -2911,8 +2939,7 @@ InlineResult CallAnalyzer::analyze() { if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { if (BI->isConditional()) { Value *Cond = BI->getCondition(); - if (ConstantInt *SimpleCond = - dyn_cast_or_null<ConstantInt>(SimplifiedValues.lookup(Cond))) { + if (ConstantInt *SimpleCond = getSimplifiedValue<ConstantInt>(Cond)) { BasicBlock *NextBB = BI->getSuccessor(SimpleCond->isZero() ? 1 : 0); BBWorklist.insert(NextBB); KnownSuccessors[BB] = NextBB; @@ -2922,8 +2949,7 @@ InlineResult CallAnalyzer::analyze() { } } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { Value *Cond = SI->getCondition(); - if (ConstantInt *SimpleCond = - dyn_cast_or_null<ConstantInt>(SimplifiedValues.lookup(Cond))) { + if (ConstantInt *SimpleCond = getSimplifiedValue<ConstantInt>(Cond)) { BasicBlock *NextBB = SI->findCaseValue(SimpleCond)->getCaseSuccessor(); BBWorklist.insert(NextBB); KnownSuccessors[BB] = NextBB; |