Skip to content

Commit eda0f33

Browse files
committed
[ctxprof] don't inline weak symbols after instrumentation
1 parent 01cc1d1 commit eda0f33

File tree

6 files changed

+75
-0
lines changed

6 files changed

+75
-0
lines changed

llvm/include/llvm/IR/GlobalValue.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,13 @@ class GlobalValue : public Constant {
550550
return isDiscardableIfUnused(getLinkage());
551551
}
552552

553+
// the symbol in this module may be replaced by a prevailing copy.
554+
bool mayBeReplacedByPrevailingCopy() const {
555+
return getLinkage() != GlobalValue::ExternalLinkage &&
556+
getLinkage() != GlobalValue::InternalLinkage &&
557+
getLinkage() != GlobalValue::PrivateLinkage;
558+
}
559+
553560
bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); }
554561

555562
protected:

llvm/include/llvm/Transforms/Instrumentation/PGOCtxProfLowering.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,20 @@ class PGOCtxProfLoweringPass : public PassInfoMixin<PGOCtxProfLoweringPass> {
2424

2525
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
2626
};
27+
28+
// Utility pass blocking inlining for any function that may be overridden during
29+
// linking by a prevailing copy.
30+
// This avoids confusingly collecting profiles for the same GUID corresponding
31+
// to different variants of the function. We could do like PGO and identify
32+
// functions by a (GUID, Hash) tuple, but since the ctxprof "use" waits for
33+
// thinlto to happen before performing any further optimizations, it's
34+
// unnecessary to collect profiles for non-prevailing copies.
35+
class NoinlineNonPrevailing : public PassInfoMixin<NoinlineNonPrevailing> {
36+
public:
37+
explicit NoinlineNonPrevailing() = default;
38+
39+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
40+
};
41+
2742
} // namespace llvm
2843
#endif

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,13 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
12491249
MPM.addPass(AssignGUIDPass());
12501250
if (IsCtxProfUse)
12511251
return MPM;
1252+
// Block further inlining in the instrumented ctxprof case. This avoids
1253+
// confusingly collecting profiles for the same GUID corresponding to
1254+
// different variants of the function. We could do like PGO and identify
1255+
// functions by a (GUID, Hash) tuple, but since the ctxprof "use" waits for
1256+
// thinlto to happen before performing any further optimizations, it's
1257+
// unnecessary to collect profiles for non-prevailing copies.
1258+
MPM.addPass(NoinlineNonPrevailing());
12521259
addPostPGOLoopRotation(MPM, Level);
12531260
MPM.addPass(PGOCtxProfLoweringPass());
12541261
} else if (IsColdFuncOnlyInstrGen) {

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass())
6262
MODULE_PASS("ctx-instr-gen",
6363
PGOInstrumentationGen(PGOInstrumentationType::CTXPROF))
6464
MODULE_PASS("ctx-prof-flatten", PGOCtxProfFlatteningPass())
65+
MODULE_PASS("noinline-nonprevailing", NoinlineNonPrevailing())
6566
MODULE_PASS("deadargelim", DeadArgumentEliminationPass())
6667
MODULE_PASS("debugify", NewPMDebugifyPass())
6768
MODULE_PASS("dfsan", DataFlowSanitizerPass())

llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,23 @@ bool CtxInstrumentationLowerer::lowerFunction(Function &F) {
351351
F.getName());
352352
return true;
353353
}
354+
355+
PreservedAnalyses NoinlineNonPrevailing::run(Module &M,
356+
ModuleAnalysisManager &MAM) {
357+
bool Changed = false;
358+
for (auto &F : M) {
359+
if (F.isDeclaration())
360+
continue;
361+
if (F.hasFnAttribute(Attribute::NoInline))
362+
continue;
363+
if (F.mayBeReplacedByPrevailingCopy()) {
364+
F.addFnAttr(Attribute::NoInline);
365+
if (F.hasFnAttribute(Attribute::AlwaysInline))
366+
F.removeFnAttr(Attribute::AlwaysInline);
367+
Changed = true;
368+
}
369+
}
370+
if (Changed)
371+
return PreservedAnalyses::none();
372+
return PreservedAnalyses::all();
373+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: opt -passes=noinline-nonprevailing -S < %s 2>&1 | FileCheck %s
2+
3+
define void @a() {
4+
ret void
5+
}
6+
7+
define void @b() #0 {
8+
ret void
9+
}
10+
11+
define weak_odr void @c() {
12+
ret void
13+
}
14+
15+
define weak_odr void @d() #0{
16+
ret void
17+
}
18+
19+
attributes #0 = { alwaysinline }
20+
21+
; CHECK: void @a() {
22+
; CHECK: void @b() #0
23+
; CHECK: void @c() #1
24+
; CHECK: void @d() #1
25+
; CHECK: attributes #1 = { noinline }

0 commit comments

Comments
 (0)