diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index 9eea2e945a851..ba327ca6ce2d1 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -54,9 +54,9 @@ static cl::opt cl::ZeroOrMore, cl::desc("Default amount of inlining to perform")); -static cl::opt PrintDebugInstructionDeltas( - "print-instruction-deltas", cl::Hidden, cl::init(false), - cl::desc("Prints deltas of cost and threshold per instruction")); +static cl::opt PrintInstructionComments( + "print-instruction-comments", cl::Hidden, cl::init(false), + cl::desc("Prints comments for instruction based on inline cost analysis")); static cl::opt InlineThreshold( "inline-threshold", cl::Hidden, cl::init(225), cl::ZeroOrMore, @@ -128,14 +128,14 @@ struct InstructionCostDetail { bool hasThresholdChanged() const { return ThresholdAfter != ThresholdBefore; } }; -class CostAnnotationWriter : public AssemblyAnnotationWriter { -public: - // This DenseMap stores the delta change in cost and threshold after - // accounting for the given instruction. - DenseMap CostThresholdMap; +class InlineCostAnnotationWriter : public AssemblyAnnotationWriter { +private: + InlineCostCallAnalyzer *const ICCA; +public: + InlineCostAnnotationWriter(InlineCostCallAnalyzer *ICCA) : ICCA(ICCA) {} virtual void emitInstructionAnnot(const Instruction *I, - formatted_raw_ostream &OS); + formatted_raw_ostream &OS) override; }; /// Carry out call site analysis, in order to evaluate inlinability. @@ -429,6 +429,11 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { /// Tunable parameters that control the analysis. const InlineParams &Params; + // This DenseMap stores the delta change in cost and threshold after + // accounting for the given instruction. The map is filled only with the + // flag PrintInstructionComments on. + DenseMap InstructionCostDetailMap; + /// Upper bound for the inlining cost. Bonuses are being applied to account /// for speculative "expected profit" of the inlining decision. int Threshold = 0; @@ -598,19 +603,19 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { void onInstructionAnalysisStart(const Instruction *I) override { // This function is called to store the initial cost of inlining before // the given instruction was assessed. - if (!PrintDebugInstructionDeltas) + if (!PrintInstructionComments) return; - Writer.CostThresholdMap[I].CostBefore = Cost; - Writer.CostThresholdMap[I].ThresholdBefore = Threshold; + InstructionCostDetailMap[I].CostBefore = Cost; + InstructionCostDetailMap[I].ThresholdBefore = Threshold; } void onInstructionAnalysisFinish(const Instruction *I) override { // This function is called to find new values of cost and threshold after // the instruction has been assessed. - if (!PrintDebugInstructionDeltas) + if (!PrintInstructionComments) return; - Writer.CostThresholdMap[I].CostAfter = Cost; - Writer.CostThresholdMap[I].ThresholdAfter = Threshold; + InstructionCostDetailMap[I].CostAfter = Cost; + InstructionCostDetailMap[I].ThresholdAfter = Threshold; } InlineResult finalizeAnalysis() override { @@ -713,13 +718,20 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { ComputeFullInlineCost(OptComputeFullInlineCost || Params.ComputeFullInlineCost || ORE), Params(Params), Threshold(Params.DefaultThreshold), - BoostIndirectCalls(BoostIndirect), IgnoreThreshold(IgnoreThreshold) {} + BoostIndirectCalls(BoostIndirect), IgnoreThreshold(IgnoreThreshold), + Writer(this) {} - /// Annotation Writer for cost annotation - CostAnnotationWriter Writer; + /// Annotation Writer for instruction details + InlineCostAnnotationWriter Writer; void dump(); + Optional getCostDetails(const Instruction *I) { + if (InstructionCostDetailMap.find(I) != InstructionCostDetailMap.end()) + return InstructionCostDetailMap[I]; + return None; + } + virtual ~InlineCostCallAnalyzer() {} int getThreshold() { return Threshold; } int getCost() { return Cost; } @@ -737,23 +749,23 @@ void CallAnalyzer::disableSROAForArg(AllocaInst *SROAArg) { disableLoadElimination(); } -void CostAnnotationWriter::emitInstructionAnnot(const Instruction *I, +void InlineCostAnnotationWriter::emitInstructionAnnot(const Instruction *I, formatted_raw_ostream &OS) { // The cost of inlining of the given instruction is printed always. // The threshold delta is printed only when it is non-zero. It happens // when we decided to give a bonus at a particular instruction. - if (CostThresholdMap.count(I) == 0) { - OS << "; No analysis for the instruction\n"; - return; + Optional Record = ICCA->getCostDetails(I); + if (!Record) + OS << "; No analysis for the instruction"; + else { + OS << "; cost before = " << Record->CostBefore + << ", cost after = " << Record->CostAfter + << ", threshold before = " << Record->ThresholdBefore + << ", threshold after = " << Record->ThresholdAfter << ", "; + OS << "cost delta = " << Record->getCostDelta(); + if (Record->hasThresholdChanged()) + OS << ", threshold delta = " << Record->getThresholdDelta(); } - const auto &Record = CostThresholdMap[I]; - OS << "; cost before = " << Record.CostBefore - << ", cost after = " << Record.CostAfter - << ", threshold before = " << Record.ThresholdBefore - << ", threshold after = " << Record.ThresholdAfter << ", "; - OS << "cost delta = " << Record.getCostDelta(); - if (Record.hasThresholdChanged()) - OS << ", threshold delta = " << Record.getThresholdDelta(); OS << "\n"; } @@ -2159,7 +2171,7 @@ InlineResult CallAnalyzer::analyze() { /// Dump stats about this call's analysis. LLVM_DUMP_METHOD void InlineCostCallAnalyzer::dump() { #define DEBUG_PRINT_STAT(x) dbgs() << " " #x ": " << x << "\n" - if (PrintDebugInstructionDeltas) + if (PrintInstructionComments) F.print(dbgs(), &Writer); DEBUG_PRINT_STAT(NumConstantArgs); DEBUG_PRINT_STAT(NumConstantOffsetPtrArgs); diff --git a/llvm/test/Transforms/Inline/debuginline-cost-delta.ll b/llvm/test/Transforms/Inline/debuginline-cost-delta.ll index 4776dad21ff98..2ef604d05bc35 100644 --- a/llvm/test/Transforms/Inline/debuginline-cost-delta.ll +++ b/llvm/test/Transforms/Inline/debuginline-cost-delta.ll @@ -1,7 +1,7 @@ ; Require asserts for -debug-only ; REQUIRES: asserts -; RUN: opt < %s -inline -debug-only=inline-cost -disable-output -print-instruction-deltas 2>&1 | FileCheck %s +; RUN: opt < %s -inline -debug-only=inline-cost -disable-output -print-instruction-comments 2>&1 | FileCheck %s ; CHECK: Analyzing call of callee1... (caller:foo) ; CHECK: define i32 @callee1(i32 %x) { diff --git a/llvm/test/Transforms/Inline/print-instructions-deltas-unfinished.ll b/llvm/test/Transforms/Inline/print-instructions-deltas-unfinished.ll index cd7ef830460ca..70e223c951e3c 100644 --- a/llvm/test/Transforms/Inline/print-instructions-deltas-unfinished.ll +++ b/llvm/test/Transforms/Inline/print-instructions-deltas-unfinished.ll @@ -4,7 +4,7 @@ ; This test ensures that the hadling of instructions which were not analyzed by ; '-print-instruction-deltas' flag due to the early exit was done correctly. -; RUN: opt < %s -inline -debug-only=inline-cost -disable-output -print-instruction-deltas -inline-threshold=0 2>&1 | FileCheck %s +; RUN: opt < %s -inline -debug-only=inline-cost -disable-output -print-instruction-comments -inline-threshold=0 2>&1 | FileCheck %s ; CHECK: No analysis for the instruction ; CHECK: ret void