Skip to content

Commit

Permalink
[InlineCost] InlineCostAnnotationWriterPass introduced
Browse files Browse the repository at this point in the history
This class allows to see the inliner's decisions for better
optimization verifications and tests. To use, use flag
"-passes="print<inline-cost>"".

This is the second attempt to integrate the patch.
The problem from the first try has been discussed and
fixed in D82205.

Reviewers: apilipenko, mtrofin, davidxl, fedor.sergeev

Reviewed By: mtrofin

Differential revision: https://reviews.llvm.org/D81743
  • Loading branch information
Kirill Naumov committed Jun 24, 2020
1 parent a61c73d commit 6a5d7d4
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 49 deletions.
12 changes: 12 additions & 0 deletions llvm/include/llvm/Analysis/InlineCost.h
Expand Up @@ -269,6 +269,18 @@ Optional<int> getInliningCostEstimate(

/// 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. The main purpose of the pass is to see and test
// inliner's decisions when creating new optimizations to InlineCost.
struct InlineCostAnnotationPrinterPass
: PassInfoMixin<InlineCostAnnotationPrinterPass> {
raw_ostream &OS;

public:
explicit InlineCostAnnotationPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
};
} // namespace llvm

#endif
37 changes: 37 additions & 0 deletions llvm/lib/Analysis/InlineCost.cpp
Expand Up @@ -2518,3 +2518,40 @@ InlineParams llvm::getInlineParams(unsigned OptLevel, unsigned SizeOptLevel) {
Params.LocallyHotCallSiteThreshold = LocallyHotCallSiteThreshold;
return Params;
}

PreservedAnalyses
InlineCostAnnotationPrinterPass::run(Function &F,
FunctionAnalysisManager &FAM) {
PrintInstructionComments = true;
std::function<AssumptionCache &(Function &)> GetAssumptionCache = [&](
Function &F) -> AssumptionCache & {
return FAM.getResult<AssumptionAnalysis>(F);
};
Module *M = F.getParent();
ProfileSummaryInfo PSI(*M);
DataLayout DL(M);
TargetTransformInfo TTI(DL);
// FIXME: Redesign the usage of InlineParams to expand the scope of this pass.
// In the current implementation, the type of InlineParams doesn't matter as
// the pass serves only for verification of inliner's decisions.
// We can add a flag which determines InlineParams for this run. Right now,
// the default InlineParams are used.
const InlineParams Params = llvm::getInlineParams();
for (BasicBlock &BB : F) {
for (Instruction &I : BB) {
if (CallInst *CI = dyn_cast<CallInst>(&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.print();
}
}
}
return PreservedAnalyses::all();
}
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassRegistry.def
Expand Up @@ -233,6 +233,7 @@ FUNCTION_PASS("print<domtree>", DominatorTreePrinterPass(dbgs()))
FUNCTION_PASS("print<postdomtree>", PostDominatorTreePrinterPass(dbgs()))
FUNCTION_PASS("print<demanded-bits>", DemandedBitsPrinterPass(dbgs()))
FUNCTION_PASS("print<domfrontier>", DominanceFrontierPrinterPass(dbgs()))
FUNCTION_PASS("print<inline-cost>", InlineCostAnnotationPrinterPass(dbgs()))
FUNCTION_PASS("print<loops>", LoopPrinterPass(dbgs()))
FUNCTION_PASS("print<memoryssa>", MemorySSAPrinterPass(dbgs()))
FUNCTION_PASS("print<phi-values>", PhiValuesPrinterPass(dbgs()))
Expand Down
38 changes: 11 additions & 27 deletions 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<inline-cost>" 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)
Expand Down
32 changes: 32 additions & 0 deletions llvm/test/Transforms/Inline/inline-cost-annotation-pass.ll
@@ -0,0 +1,32 @@
; RUN: opt < %s -passes="print<inline-cost>" 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
}

This file was deleted.

0 comments on commit 6a5d7d4

Please sign in to comment.