aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/InlineCost.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/InlineCost.cpp')
-rw-r--r--llvm/lib/Analysis/InlineCost.cpp76
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;