[llvm] 7d541eb - [inliner] Mandatory inlining decisions produce remarks
Mircea Trofin via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 5 14:01:34 PDT 2021
Author: Mircea Trofin
Date: 2021-10-05T14:01:25-07:00
New Revision: 7d541eb4d49aaaab6a51a3568b9214fd8691e2d3
URL: https://github.com/llvm/llvm-project/commit/7d541eb4d49aaaab6a51a3568b9214fd8691e2d3
DIFF: https://github.com/llvm/llvm-project/commit/7d541eb4d49aaaab6a51a3568b9214fd8691e2d3.diff
LOG: [inliner] Mandatory inlining decisions produce remarks
This also removes the need to disable the mandatory inlining phase in
tests.
In a departure from the previous remark, we don't output a 'cost' in
this case, because there's no such thing. We just report that inlining
happened because of the attribute.
Differential Revision: https://reviews.llvm.org/D110891
Added:
llvm/test/Transforms/Inline/inline-remark-mandatory.ll
Modified:
clang/test/Frontend/optimization-remark-line-directive.c
clang/test/Frontend/optimization-remark-new-pm.c
clang/test/Frontend/optimization-remark-with-hotness-new-pm.c
clang/test/Frontend/optimization-remark.c
llvm/include/llvm/Analysis/InlineAdvisor.h
llvm/lib/Analysis/InlineAdvisor.cpp
llvm/lib/Transforms/IPO/AlwaysInliner.cpp
llvm/lib/Transforms/IPO/Inliner.cpp
llvm/lib/Transforms/IPO/SampleProfile.cpp
Removed:
################################################################################
diff --git a/clang/test/Frontend/optimization-remark-line-directive.c b/clang/test/Frontend/optimization-remark-line-directive.c
index 13a197c109a5f..32b098916e6fe 100644
--- a/clang/test/Frontend/optimization-remark-line-directive.c
+++ b/clang/test/Frontend/optimization-remark-line-directive.c
@@ -6,7 +6,7 @@
// The new PM inliner is not added to the default pipeline at O0, so we add
// some optimizations to trigger it.
-// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -debug-info-kind=line-tables-only -emit-llvm-only -mllvm -mandatory-inlining-first=false -verify
+// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -debug-info-kind=line-tables-only -emit-llvm-only -verify
int foo(int x, int y) __attribute__((always_inline));
int foo(int x, int y) { return x + y; }
diff --git a/clang/test/Frontend/optimization-remark-new-pm.c b/clang/test/Frontend/optimization-remark-new-pm.c
index e2c198a305303..1a9adae437ef4 100644
--- a/clang/test/Frontend/optimization-remark-new-pm.c
+++ b/clang/test/Frontend/optimization-remark-new-pm.c
@@ -1,8 +1,8 @@
// Verify that remarks for the inliner appear. The remarks under the new PM will
// be slightly
diff erent than those emitted by the legacy PM. The new PM inliner
// also doesnot appear to be added at O0, so we test at O1.
-// RUN: %clang_cc1 %s -Rpass=inline -Rpass-analysis=inline -Rpass-missed=inline -O1 -fexperimental-new-pass-manager -emit-llvm-only -mllvm -mandatory-inlining-first=false -verify
-// RUN: %clang_cc1 %s -Rpass=inline -Rpass-analysis=inline -Rpass-missed=inline -O1 -fexperimental-new-pass-manager -emit-llvm-only -debug-info-kind=line-tables-only -mllvm -mandatory-inlining-first=false -verify
+// RUN: %clang_cc1 %s -Rpass=inline -Rpass-analysis=inline -Rpass-missed=inline -O1 -fexperimental-new-pass-manager -emit-llvm-only -verify
+// RUN: %clang_cc1 %s -Rpass=inline -Rpass-analysis=inline -Rpass-missed=inline -O1 -fexperimental-new-pass-manager -emit-llvm-only -debug-info-kind=line-tables-only -verify
int foo(int x, int y) __attribute__((always_inline));
int foo(int x, int y) { return x + y; }
diff --git a/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c b/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c
index 84fb44d86d126..7090055cc41ea 100644
--- a/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c
+++ b/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c
@@ -18,47 +18,47 @@
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -fexperimental-new-pass-manager -O1 \
// RUN: -Rpass-analysis=inline -Rpass-missed=inline \
-// RUN: -fdiagnostics-show-hotness -verify -mllvm -mandatory-inlining-first=false
+// RUN: -fdiagnostics-show-hotness -verify
// The clang version of the previous test.
// RUN: %clang -target x86_64-apple-macosx10.9 %s -c -emit-llvm -o /dev/null \
// RUN: -fprofile-instr-use=%t.profdata -Rpass=inline \
// RUN: -fexperimental-new-pass-manager -O1 \
// RUN: -Rpass-analysis=inline -Rpass-missed=inline \
-// RUN: -fdiagnostics-show-hotness -Xclang -verify -mllvm -mandatory-inlining-first=false
+// RUN: -fdiagnostics-show-hotness -Xclang -verify
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-sample-use=%t-sample.profdata -Rpass=inline \
// RUN: -fexperimental-new-pass-manager -O1 \
// RUN: -Rpass-analysis=inline -Rpass-missed=inline \
// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 \
-// RUN: -verify -mllvm -mandatory-inlining-first=false
+// RUN: -verify
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -fexperimental-new-pass-manager -O1 \
// RUN: -Rpass-analysis=inline -Rpass-missed=inline \
-// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 -verify -mllvm -mandatory-inlining-first=false
+// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 -verify
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -fexperimental-new-pass-manager -O1 \
-// RUN: -Rpass-analysis=inline -mllvm -mandatory-inlining-first=false 2>&1 | FileCheck -check-prefix=HOTNESS_OFF %s
+// RUN: -Rpass-analysis=inline 2>&1 | FileCheck -check-prefix=HOTNESS_OFF %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -fexperimental-new-pass-manager -O1 \
-// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness -mllvm -mandatory-inlining-first=false 2>&1 | FileCheck \
+// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness 2>&1 | FileCheck \
// RUN: -check-prefix=HOTNESS_OFF %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -Rpass-analysis=inline -fdiagnostics-show-hotness \
-// RUN: -fdiagnostics-hotness-threshold=100 -mllvm -mandatory-inlining-first=false 2>&1 \
+// RUN: -fdiagnostics-hotness-threshold=100 2>&1 \
// RUN: | FileCheck -allow-empty -check-prefix=THRESHOLD %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -Rpass=inline -Rpass-analysis=inline \
-// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 -mllvm -mandatory-inlining-first=false 2>&1 \
+// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 2>&1 \
// RUN: | FileCheck -check-prefix=NO_PGO %s
int foo(int x, int y) __attribute__((always_inline));
@@ -73,7 +73,7 @@ void bar(int x) {
// THRESHOLD-NOT: hotness
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
// NO_PGO: '-fdiagnostics-hotness-threshold=' requires profile-guided optimization information
- // expected-remark at +1 {{'foo' inlined into 'bar' with (cost=always): always inline attribute at callsite bar:8:10; (hotness:}}
+ // expected-remark at +1 {{'foo' inlined into 'bar': always inline attribute at callsite bar:8:10; (hotness:}}
sum += foo(x, x - 2);
}
diff --git a/clang/test/Frontend/optimization-remark.c b/clang/test/Frontend/optimization-remark.c
index 950980e397787..d1b0dfa9d6d8d 100644
--- a/clang/test/Frontend/optimization-remark.c
+++ b/clang/test/Frontend/optimization-remark.c
@@ -20,12 +20,12 @@
//
// The inliner for the new PM does not seem to be enabled at O0, but we still
// get the same remarks with at least O1.
-// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -emit-llvm -mllvm -mandatory-inlining-first=false -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
-// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -Rno-everything -Reverything -emit-llvm -mllvm -mandatory-inlining-first=false -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -Rno-everything -Reverything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
//
// Check that -w doesn't disable remarks.
// RUN: %clang_cc1 %s -Rpass=inline -fno-experimental-new-pass-manager -w -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
-// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -w -emit-llvm -mllvm -mandatory-inlining-first=false -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+// RUN: %clang_cc1 %s -Rpass=inline -fexperimental-new-pass-manager -O1 -w -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
//
// -Reverything implies -Rpass=.*.
// RUN: %clang_cc1 %s -Reverything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h
index c27aaf0db8f2f..02ddf98ae17a7 100644
--- a/llvm/include/llvm/Analysis/InlineAdvisor.h
+++ b/llvm/include/llvm/Analysis/InlineAdvisor.h
@@ -263,10 +263,17 @@ shouldInline(CallBase &CB, function_ref<InlineCost(CallBase &CB)> GetInlineCost,
/// Emit ORE message.
void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
const BasicBlock *Block, const Function &Callee,
- const Function &Caller, const InlineCost &IC,
- bool ForProfileContext = false,
+ const Function &Caller, bool IsMandatory,
+ function_ref<void(OptimizationRemark &)> ExtraContext = {},
const char *PassName = nullptr);
+/// Emit ORE message based in cost (default heuristic).
+void emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
+ const BasicBlock *Block, const Function &Callee,
+ const Function &Caller, const InlineCost &IC,
+ bool ForProfileContext = false,
+ const char *PassName = nullptr);
+
/// get call site location as string
std::string getCallSiteLocation(DebugLoc DLoc);
diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp
index 81529332c8c19..f1695db6117c1 100644
--- a/llvm/lib/Analysis/InlineAdvisor.cpp
+++ b/llvm/lib/Analysis/InlineAdvisor.cpp
@@ -49,6 +49,42 @@ static cl::opt<int>
extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats;
+namespace {
+using namespace llvm::ore;
+class MandatoryInlineAdvice : public InlineAdvice {
+public:
+ MandatoryInlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
+ OptimizationRemarkEmitter &ORE,
+ bool IsInliningMandatory)
+ : InlineAdvice(Advisor, CB, ORE, IsInliningMandatory) {}
+
+private:
+ void recordInliningWithCalleeDeletedImpl() override { recordInliningImpl(); }
+
+ void recordInliningImpl() override {
+ if (IsInliningRecommended)
+ emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, IsInliningRecommended,
+ [&](OptimizationRemark &Remark) {
+ Remark << ": always inline attribute";
+ });
+ }
+
+ void recordUnsuccessfulInliningImpl(const InlineResult &Result) override {
+ if (IsInliningRecommended)
+ ORE.emit([&]() {
+ return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
+ << "'" << NV("Callee", Callee) << "' is not AlwaysInline into '"
+ << NV("Caller", Caller)
+ << "': " << NV("Reason", Result.getFailureReason());
+ });
+ }
+
+ void recordUnattemptedInliningImpl() override {
+ assert(!IsInliningRecommended && "Expected to attempt inlining");
+ }
+};
+} // namespace
+
void DefaultInlineAdvice::recordUnsuccessfulInliningImpl(
const InlineResult &Result) {
using namespace ore;
@@ -64,12 +100,12 @@ void DefaultInlineAdvice::recordUnsuccessfulInliningImpl(
void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() {
if (EmitRemarks)
- emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC);
+ emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC);
}
void DefaultInlineAdvice::recordInliningImpl() {
if (EmitRemarks)
- emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC);
+ emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC);
}
llvm::Optional<llvm::InlineCost> static getDefaultInlineAdvice(
@@ -435,25 +471,38 @@ void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) {
Remark << ";";
}
-void llvm::emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
- const BasicBlock *Block, const Function &Callee,
- const Function &Caller, const InlineCost &IC,
- bool ForProfileContext, const char *PassName) {
+void llvm::emitInlinedInto(
+ OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block,
+ const Function &Callee, const Function &Caller, bool AlwaysInline,
+ function_ref<void(OptimizationRemark &)> ExtraContext,
+ const char *PassName) {
ORE.emit([&]() {
- bool AlwaysInline = IC.isAlways();
StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName,
DLoc, Block);
Remark << "'" << ore::NV("Callee", &Callee) << "' inlined into '"
<< ore::NV("Caller", &Caller) << "'";
- if (ForProfileContext)
- Remark << " to match profiling context";
- Remark << " with " << IC;
+ if (ExtraContext)
+ ExtraContext(Remark);
addLocationToRemarks(Remark, DLoc);
return Remark;
});
}
+void llvm::emitInlinedIntoBasedOnCost(
+ OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block,
+ const Function &Callee, const Function &Caller, const InlineCost &IC,
+ bool ForProfileContext, const char *PassName) {
+ llvm::emitInlinedInto(
+ ORE, DLoc, Block, Callee, Caller, IC.isAlways(),
+ [&](OptimizationRemark &Remark) {
+ if (ForProfileContext)
+ Remark << " to match profiling context";
+ Remark << " with " << IC;
+ },
+ PassName);
+}
+
InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM)
: M(M), FAM(FAM) {
if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
@@ -475,7 +524,8 @@ InlineAdvisor::~InlineAdvisor() {
std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB,
bool Advice) {
- return std::make_unique<InlineAdvice>(this, CB, getCallerORE(CB), Advice);
+ return std::make_unique<MandatoryInlineAdvice>(this, CB, getCallerORE(CB),
+ Advice);
}
InlineAdvisor::MandatoryInliningKind
diff --git a/llvm/lib/Transforms/IPO/AlwaysInliner.cpp b/llvm/lib/Transforms/IPO/AlwaysInliner.cpp
index 532599b42e0dc..e7df2ce757047 100644
--- a/llvm/lib/Transforms/IPO/AlwaysInliner.cpp
+++ b/llvm/lib/Transforms/IPO/AlwaysInliner.cpp
@@ -73,8 +73,8 @@ PreservedAnalyses AlwaysInlinerPass::run(Module &M,
},
ORE);
assert(OIC);
- emitInlinedInto(ORE, CB->getDebugLoc(), CB->getParent(), F, *Caller,
- *OIC, false, DEBUG_TYPE);
+ emitInlinedIntoBasedOnCost(ORE, CB->getDebugLoc(), CB->getParent(), F,
+ *Caller, *OIC, false, DEBUG_TYPE);
InlineFunctionInfo IFI(
/*cg=*/nullptr, GetAssumptionCache, &PSI,
diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp
index 03f40f7fc169e..a72a4224bb18c 100644
--- a/llvm/lib/Transforms/IPO/Inliner.cpp
+++ b/llvm/lib/Transforms/IPO/Inliner.cpp
@@ -464,7 +464,7 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
}
++NumInlined;
- emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC);
+ emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC);
// If inlining this function gave us any new call sites, throw them
// onto our worklist to process. They are useful inline candidates.
diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp
index 23e3c94f9f288..90cc38d80e0ec 100644
--- a/llvm/lib/Transforms/IPO/SampleProfile.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp
@@ -1204,8 +1204,8 @@ bool SampleProfileLoader::tryInlineCandidate(
*CalledFunction);
// The call to InlineFunction erases I, so we can't pass it here.
- emitInlinedInto(*ORE, DLoc, BB, *CalledFunction, *BB->getParent(), Cost,
- true, CSINLINE_DEBUG);
+ emitInlinedIntoBasedOnCost(*ORE, DLoc, BB, *CalledFunction,
+ *BB->getParent(), Cost, true, CSINLINE_DEBUG);
// Now populate the list of newly exposed call sites.
if (InlinedCallSites) {
diff --git a/llvm/test/Transforms/Inline/inline-remark-mandatory.ll b/llvm/test/Transforms/Inline/inline-remark-mandatory.ll
new file mode 100644
index 0000000000000..1b4a022a214f5
--- /dev/null
+++ b/llvm/test/Transforms/Inline/inline-remark-mandatory.ll
@@ -0,0 +1,16 @@
+; RUN: opt -passes="cgscc(inline<only-mandatory>)" -pass-remarks-missed=inline -S < %s 2>&1 | FileCheck %s
+
+declare void @personalityFn1();
+declare void @personalityFn2();
+
+define i32 @a() personality void ()* @personalityFn1 {
+ ret i32 1
+}
+
+define i32 @b() personality void ()* @personalityFn2 {
+ %r = call i32 @a() alwaysinline
+ ret i32 %r
+}
+
+; CHECK: remark: {{.*}} 'a' is not AlwaysInline into 'b': incompatible personality
+
More information about the llvm-commits
mailing list