Index: llvm/include/llvm/Analysis/InlineCost.h =================================================================== --- llvm/include/llvm/Analysis/InlineCost.h +++ llvm/include/llvm/Analysis/InlineCost.h @@ -269,6 +269,17 @@ /// Minimal filter to detect invalid constructs for inlining. InlineResult isInlineViable(Function &Callee); + +// This pass is used to annotate instructions during the inline process for +// debugging and analysis +struct InlineCostAnnotationPrinterPass + : PassInfoMixin { + raw_ostream &OS; + +public: + explicit InlineCostAnnotationPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); +}; } // namespace llvm #endif Index: llvm/lib/Analysis/InlineCost.cpp =================================================================== --- llvm/lib/Analysis/InlineCost.cpp +++ llvm/lib/Analysis/InlineCost.cpp @@ -2509,3 +2509,35 @@ Params.LocallyHotCallSiteThreshold = LocallyHotCallSiteThreshold; return Params; } + +PreservedAnalyses +InlineCostAnnotationPrinterPass::run(Function &F, + FunctionAnalysisManager &FAM) { + PrintInstructionComments = true; + std::function GetAssumptionCache = [&]( + Function &F) -> AssumptionCache & { + return FAM.getResult(F); + }; + Module *M = F.getParent(); + ProfileSummaryInfo PSI(*M); + DataLayout DL(M); + TargetTransformInfo TTI(DL); + const InlineParams Params = llvm::getInlineParams(InlineThreshold); + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + if (CallInst *CI = dyn_cast(&I)) { + Function *CalledFunction = CI->getCalledFunction(); + if (!CalledFunction || CalledFunction->isDeclaration()) + continue; + OptimizationRemarkEmitter ORE(CalledFunction); + InlineCostCallAnalyzer ICCA(*CalledFunction, *CI, Params, TTI, + GetAssumptionCache, nullptr, &PSI, &ORE); + ICCA.analyze(); + OS << " Analyzing call of " << CalledFunction->getName() + << "... (caller:" << CI->getCaller()->getName() << ")\n"; + ICCA.dump(); + } + } + } + return PreservedAnalyses::all(); +} \ No newline at end of file Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -233,6 +233,7 @@ FUNCTION_PASS("print", PostDominatorTreePrinterPass(dbgs())) FUNCTION_PASS("print", DemandedBitsPrinterPass(dbgs())) FUNCTION_PASS("print", DominanceFrontierPrinterPass(dbgs())) +FUNCTION_PASS("print", InlineCostAnnotationPrinterPass(dbgs())) FUNCTION_PASS("print", LoopPrinterPass(dbgs())) FUNCTION_PASS("print", MemorySSAPrinterPass(dbgs())) FUNCTION_PASS("print", PhiValuesPrinterPass(dbgs())) Index: llvm/test/Transforms/Inline/debuginline-cost-delta.ll =================================================================== --- llvm/test/Transforms/Inline/debuginline-cost-delta.ll +++ llvm/test/Transforms/Inline/debuginline-cost-delta.ll @@ -1,32 +1,16 @@ -; Require asserts for -debug-only -; REQUIRES: asserts - -; RUN: opt < %s -inline -debug-only=inline-cost -disable-output -print-instruction-comments 2>&1 | FileCheck %s +; RUN: opt < %s -passes="print" 2>&1 | FileCheck %s ; CHECK: Analyzing call of callee1... (caller:foo) -; CHECK: define i32 @callee1(i32 %x) { -; CHECK: ; cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = 5 -; CHECK: %x1 = add i32 %x, 1 -; CHECK: ; cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = 5 -; CHECK: %x2 = add i32 %x1, 1 -; CHECK: ; cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = 5 -; CHECK: %x3 = add i32 %x2, 1 -; CHECK: ; cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = 0 -; CHECK: ret i32 %x3 -; CHECK: } -; CHECK: NumConstantArgs: 0 -; CHECK: NumConstantOffsetPtrArgs: 0 -; CHECK: NumAllocaArgs: 0 -; CHECK: NumConstantPtrCmps: 0 -; CHECK: NumConstantPtrDiffs: 0 -; CHECK: NumInstructionsSimplified: 1 -; CHECK: NumInstructions: 4 -; CHECK: SROACostSavings: 0 -; CHECK: SROACostSavingsLost: 0 -; CHECK: LoadEliminationCost: 0 -; CHECK: ContainsNoDuplicateCall: 0 -; CHECK: Cost: {{.*}} -; CHECK: Threshold: {{.*}} +; CHECK-NEXT: define i32 @callee1(i32 %x) { +; CHECK-NEXT: cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = {{.*}} +; CHECK-NEXT: %x1 = add i32 %x, 1 +; CHECK-NEXT: cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = {{.*}} +; CHECK-NEXT: %x2 = add i32 %x1, 1 +; CHECK-NEXT: cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = {{.*}} +; CHECK-NEXT: %x3 = add i32 %x2, 1 +; CHECK-NEXT: cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = {{.*}} +; CHECK-NEXT: ret i32 %x3 +; CHECK-NEXT: } define i32 @foo(i32 %y) { %x = call i32 @callee1(i32 %y) Index: llvm/test/Transforms/Inline/inline-cost-annotation-pass.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Inline/inline-cost-annotation-pass.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -passes="print" 2>&1 | FileCheck %s + +; CHECK: Analyzing call of foo... (caller:main) +; CHECK: define i8 addrspace(1)** @foo() { +; CHECK: cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = {{.*}} +; CHECK: %1 = inttoptr i64 754974720 to i8 addrspace(1)** +; CHECK: cost before = {{.*}}, cost after = {{.*}}, threshold before = {{.*}}, threshold after = {{.*}}, cost delta = {{.*}} +; CHECK: ret i8 addrspace(1)** %1 +; CHECK: } +; CHECK: NumConstantArgs: {{.*}} +; CHECK: NumConstantOffsetPtrArgs: {{.*}} +; CHECK: NumAllocaArgs: {{.*}} +; CHECK: NumConstantPtrCmps: {{.*}} +; CHECK: NumConstantPtrDiffs: {{.*}} +; CHECK: NumInstructionsSimplified: {{.*}} +; CHECK: NumInstructions: {{.*}} +; CHECK: SROACostSavings: {{.*}} +; CHECK: SROACostSavingsLost: {{.*}} +; CHECK: LoadEliminationCost: {{.*}} +; CHECK: ContainsNoDuplicateCall: {{.*}} +; CHECK: Cost: {{.*}} +; CHECK: Threshold: {{.*}} + +define i8 addrspace(1)** @foo() { + %1 = inttoptr i64 754974720 to i8 addrspace(1)** + ret i8 addrspace(1)** %1 +} + +define i8 addrspace(1)** @main() { + %1 = call i8 addrspace(1)** @foo() + ret i8 addrspace(1)** %1 +} Index: llvm/test/Transforms/Inline/print-instructions-deltas-unfinished.ll =================================================================== --- llvm/test/Transforms/Inline/print-instructions-deltas-unfinished.ll +++ /dev/null @@ -1,22 +0,0 @@ -; Require asserts for -debug-only -; REQUIRES: asserts - -; 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-comments -inline-threshold=0 2>&1 | FileCheck %s - -; CHECK: No analysis for the instruction -; CHECK: ret void - -declare void @callee1() - -define void @bar() { - call void @callee1() - ret void -} - -define void @foo() { - call void @bar() - ret void -}