Skip to content

Commit 4911235

Browse files
authored
[ctx_prof] Automatically convert available external linkage to local for modules with contextual roots (llvm#109203)
For the modules containing context roots, the way IPO happens will potentially result in imported functions that are differently specialized (even if themselves not inlined) than their originals. So we want to convert them to local rather than elide them. Eventually we'd perform this as a ThinLTO directive.
1 parent 38371a1 commit 4911235

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

llvm/lib/Transforms/IPO/ElimAvailExtern.cpp

+14-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/Transforms/IPO/ElimAvailExtern.h"
1515
#include "llvm/ADT/STLExtras.h"
1616
#include "llvm/ADT/Statistic.h"
17+
#include "llvm/Analysis/CtxProfAnalysis.h"
1718
#include "llvm/IR/Constant.h"
1819
#include "llvm/IR/DebugInfoMetadata.h"
1920
#include "llvm/IR/Function.h"
@@ -88,7 +89,7 @@ static void convertToLocalCopy(Module &M, Function &F) {
8889
++NumConversions;
8990
}
9091

91-
static bool eliminateAvailableExternally(Module &M) {
92+
static bool eliminateAvailableExternally(Module &M, bool Convert) {
9293
bool Changed = false;
9394

9495
// Drop initializers of available externally global variables.
@@ -112,7 +113,7 @@ static bool eliminateAvailableExternally(Module &M) {
112113
if (F.isDeclaration() || !F.hasAvailableExternallyLinkage())
113114
continue;
114115

115-
if (ConvertToLocal)
116+
if (Convert || ConvertToLocal)
116117
convertToLocalCopy(M, F);
117118
else
118119
deleteFunction(F);
@@ -125,8 +126,16 @@ static bool eliminateAvailableExternally(Module &M) {
125126
}
126127

127128
PreservedAnalyses
128-
EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
129-
if (!eliminateAvailableExternally(M))
130-
return PreservedAnalyses::all();
129+
EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &MAM) {
130+
auto *CtxProf = MAM.getCachedResult<CtxProfAnalysis>(M);
131+
// Convert to local instead of eliding if we use contextual profiling in this
132+
// module. This is because the IPO decisions performed with contextual
133+
// information will likely differ from decisions made without. For a function
134+
// that's imported, its optimizations will, thus, differ, and be specialized
135+
// for this contextual information. Eliding it in favor of the original would
136+
// undo these optimizations.
137+
if (!eliminateAvailableExternally(M, /*Convert=*/(CtxProf && !!(*CtxProf))))
138+
;
139+
return PreservedAnalyses::all();
131140
return PreservedAnalyses::none();
132141
}

llvm/test/Transforms/EliminateAvailableExternally/transform-to-local.ll

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
; REQUIRES: asserts
22
; RUN: opt -passes=elim-avail-extern -avail-extern-to-local -stats -S 2>&1 < %s | FileCheck %s
3+
;
4+
; RUN: echo '[{"Guid":1234, "Counters": [1]}]' | llvm-ctxprof-util fromJSON --input=- --output=%t_profile.ctxprofdata
5+
;
6+
; Because we pass a contextual profile with a root defined in this module, we expect the outcome to be the same as-if
7+
; we passed -avail-extern-to-local, i.e. available_externally don't get elided and instead get converted to local linkage
8+
; RUN: opt -passes='assign-guid,require<ctx-prof-analysis>,elim-avail-extern' -use-ctx-profile=%t_profile.ctxprofdata -stats -S 2>&1 < %s | FileCheck %s
39

10+
; If the profile doesn't apply to this module, available_externally won't get converted to internal linkage, and will be
11+
; removed instead.
12+
; RUN: echo '[{"Guid":5678, "Counters": [1]}]' | llvm-ctxprof-util fromJSON --input=- --output=%t_profile_bad.ctxprofdata
13+
; RUN: opt -passes='assign-guid,require<ctx-prof-analysis>,elim-avail-extern' -use-ctx-profile=%t_profile_bad.ctxprofdata -stats -S 2>&1 < %s | FileCheck %s --check-prefix=NOOP
414

515
declare void @call_out(ptr %fct)
616

@@ -12,18 +22,22 @@ define available_externally hidden void @g() {
1222
ret void
1323
}
1424

15-
define void @hello(ptr %g) {
25+
define void @hello(ptr %g) !guid !0 {
1626
call void @f()
1727
%f = load ptr, ptr @f
1828
call void @call_out(ptr %f)
1929
ret void
2030
}
2131

32+
!0 = !{i64 1234}
33+
2234
; CHECK: define internal void @f.__uniq.{{[0-9|a-f]*}}()
2335
; CHECK: declare hidden void @g()
2436
; CHECK: call void @f.__uniq.{{[0-9|a-f]*}}()
2537
; CHECK-NEXT: load ptr, ptr @f
2638
; CHECK-NEXT: call void @call_out(ptr %f)
2739
; CHECK: Statistics Collected
2840
; CHECK: 1 elim-avail-extern - Number of functions converted
29-
; CHECK: 1 elim-avail-extern - Number of functions removed
41+
; CHECK: 1 elim-avail-extern - Number of functions removed
42+
43+
; NOOP: 2 elim-avail-extern - Number of functions removed

0 commit comments

Comments
 (0)