Skip to content

Commit ea40919

Browse files
[ThinLTO]Import global variable declaration
1 parent 9270328 commit ea40919

File tree

5 files changed

+73
-11
lines changed

5 files changed

+73
-11
lines changed

llvm/include/llvm/IR/ModuleSummaryIndex.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,11 @@ class ModuleSummaryIndex {
19091909

19101910
/// Checks if we can import global variable from another module.
19111911
bool canImportGlobalVar(const GlobalValueSummary *S, bool AnalyzeRefs) const;
1912+
1913+
/// Same as above but checks whether the global var is importable as a
1914+
/// declaration.
1915+
bool canImportGlobalVar(const GlobalValueSummary *S, bool AnalyzeRefs,
1916+
bool &CanImportDecl) const;
19121917
};
19131918

19141919
/// GraphTraits definition to build SCC for the index

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4764,7 +4764,8 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
47644764
NameVals.push_back(*ValueId);
47654765
assert(ModuleIdMap.count(VS->modulePath()));
47664766
NameVals.push_back(ModuleIdMap[VS->modulePath()]);
4767-
NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
4767+
NameVals.push_back(
4768+
getEncodedGVSummaryFlags(VS->flags(), shouldImportValueAsDecl(VS)));
47684769
NameVals.push_back(getEncodedGVarFlags(VS->varflags()));
47694770
for (auto &RI : VS->refs()) {
47704771
auto RefValueId = getValueId(RI.getGUID());

llvm/lib/IR/ModuleSummaryIndex.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,13 @@ void ModuleSummaryIndex::propagateAttributes(
328328

329329
bool ModuleSummaryIndex::canImportGlobalVar(const GlobalValueSummary *S,
330330
bool AnalyzeRefs) const {
331+
bool CanImportDecl;
332+
return canImportGlobalVar(S, AnalyzeRefs, CanImportDecl);
333+
}
334+
335+
bool ModuleSummaryIndex::canImportGlobalVar(const GlobalValueSummary *S,
336+
bool AnalyzeRefs,
337+
bool &CanImportDecl) const {
331338
auto HasRefsPreventingImport = [this](const GlobalVarSummary *GVS) {
332339
// We don't analyze GV references during attribute propagation, so
333340
// GV with non-trivial initializer can be marked either read or
@@ -348,13 +355,20 @@ bool ModuleSummaryIndex::canImportGlobalVar(const GlobalValueSummary *S,
348355
};
349356
auto *GVS = cast<GlobalVarSummary>(S->getBaseObject());
350357

358+
const bool nonInterposable =
359+
!GlobalValue::isInterposableLinkage(S->linkage());
360+
const bool eligibleToImport = !S->notEligibleToImport();
361+
362+
// It's correct to import a global variable only when it is not interposable
363+
// and eligible to import.
364+
CanImportDecl = (nonInterposable && eligibleToImport);
365+
351366
// Global variable with non-trivial initializer can be imported
352367
// if it's readonly. This gives us extra opportunities for constant
353368
// folding and converting indirect calls to direct calls. We don't
354369
// analyze GV references during attribute propagation, because we
355370
// don't know yet if it is readonly or not.
356-
return !GlobalValue::isInterposableLinkage(S->linkage()) &&
357-
!S->notEligibleToImport() &&
371+
return nonInterposable && eligibleToImport &&
358372
(!AnalyzeRefs || !HasRefsPreventingImport(GVS));
359373
}
360374

llvm/lib/Transforms/IPO/FunctionImport.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,18 @@ class GlobalsImporter final {
430430
// than as part of the logic deciding which functions to import (i.e.
431431
// based on profile information). Should we decide to handle them here,
432432
// we can refactor accordingly at that time.
433-
if (!GVS || !Index.canImportGlobalVar(GVS, /* AnalyzeRefs */ true) ||
433+
bool CanImportDecl = false;
434+
if (!GVS ||
434435
shouldSkipLocalInAnotherModule(GVS, VI.getSummaryList().size(),
435-
Summary.modulePath()))
436+
Summary.modulePath()) ||
437+
!Index.canImportGlobalVar(GVS, /* AnalyzeRefs */ true,
438+
CanImportDecl)) {
439+
if (ImportDeclaration && CanImportDecl)
440+
ImportList.maybeAddDeclaration(RefSummary->modulePath(),
441+
VI.getGUID());
442+
436443
continue;
444+
}
437445

438446
// If there isn't an entry for GUID, insert <GUID, Definition> pair.
439447
// Otherwise, definition should take precedence over declaration.

llvm/test/ThinLTO/X86/import_callee_declaration.ll

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,23 @@
3434
; RUN: -r=main.bc,main,px \
3535
; RUN: -r=main.bc,small_func, \
3636
; RUN: -r=main.bc,large_func, \
37+
; RUN: -r=main.bc,read_write_global_vars, \
38+
; RUN: -r=main.bc,external_func, \
3739
; RUN: -r=lib.bc,callee,pl \
3840
; RUN: -r=lib.bc,large_indirect_callee,px \
3941
; RUN: -r=lib.bc,large_indirect_bar,px \
4042
; RUN: -r=lib.bc,small_func,px \
4143
; RUN: -r=lib.bc,large_func,px \
44+
; RUN: -r=lib.bc,read_write_global_vars,px \
45+
; RUN: -r=lib.bc,external_func, \
4246
; RUN: -r=lib.bc,large_indirect_callee_alias,px \
4347
; RUN: -r=lib.bc,large_indirect_bar_alias,px \
4448
; RUN: -r=lib.bc,calleeAddrs,px -r=lib.bc,calleeAddrs2,px -o summary main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP
4549
;
4650
; RUN: llvm-lto -thinlto-action=thinlink -import-declaration -import-instr-limit=7 -import-instr-evolution-factor=1.0 -o combined.index.bc main.bc lib.bc
4751
; RUN: llvm-lto -thinlto-action=distributedindexes -debug-only=function-import -import-declaration -import-instr-limit=7 -import-instr-evolution-factor=1.0 -thinlto-index combined.index.bc main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP
4852

49-
; DUMP: - 2 function definitions and 4 function declarations imported from lib.bc
53+
; DUMP: - 2 function definitions and 3 function declarations imported from lib.bc
5054

5155
; First disassemble per-module summary and find out the GUID for {large_func, large_indirect_callee}.
5256
;
@@ -67,17 +71,25 @@
6771
; MAIN-DIS: gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}})))
6872
; When alias is imported as a copy of the aliasee, but the aliasee is not being
6973
; imported by itself, the aliasee should be null.
70-
; MAIN-DIS: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: null)))
74+
; MAIN-DIS-NOT: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: null)))
7175
; MAIN-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}})))
7276
; MAIN-DIS: gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: [[LARGEINDIRECT]])))
7377

78+
; RUN: opt -passes=function-import -summary-file=main.bc.thinlto.bc main.bc -o main-after-import.bc
79+
; RUN: llvm-dis -o - main-after-import.bc | FileCheck %s --check-prefix=MAIN-IMPORT
80+
81+
MAIN-IMPORT: @read_write_global_vars = external dso_local global [1 x ptr]
82+
7483
; Run in-process ThinLTO and tests that
7584
; 1. `callee` remains internalized even if the symbols of its callers
7685
; (large_func, large_indirect_callee, large_indirect_bar) are exported as
7786
; declarations and visible to main module.
7887
; 2. the debugging logs from `function-import` pass are expected.
88+
; Set relocation model to static so the dso_local attribute from a summary is
89+
; applied on the global variable declaration.
7990

8091
; RUN: llvm-lto2 run \
92+
; RUN: -relocation-model=static \
8193
; RUN: -debug-only=function-import \
8294
; RUN: -save-temps \
8395
; RUN: -thinlto-threads=1 \
@@ -87,11 +99,15 @@
8799
; RUN: -r=main.bc,main,px \
88100
; RUN: -r=main.bc,small_func, \
89101
; RUN: -r=main.bc,large_func, \
102+
; RUN: -r=main.bc,read_write_global_vars, \
103+
; RUN: -r=main.bc,external_func, \
90104
; RUN: -r=lib.bc,callee,pl \
91105
; RUN: -r=lib.bc,large_indirect_callee,px \
92106
; RUN: -r=lib.bc,large_indirect_bar,px \
93107
; RUN: -r=lib.bc,small_func,px \
94108
; RUN: -r=lib.bc,large_func,px \
109+
; RUN: -r=lib.bc,read_write_global_vars,px \
110+
; RUN: -r=lib.bc,external_func, \
95111
; RUN: -r=lib.bc,large_indirect_callee_alias,px \
96112
; RUN: -r=lib.bc,large_indirect_bar_alias,px \
97113
; RUN: -r=lib.bc,calleeAddrs,px -r=lib.bc,calleeAddrs2,px -o in-process main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=IMPORTDUMP
@@ -103,15 +119,16 @@
103119
; IMPORTDUMP-DAG: Is importing function definition 13568239288960714650 small_indirect_callee from lib.cc
104120
; IMPORTDUMP-DAG: Is importing function definition 6976996067367342685 small_func from lib.cc
105121
; IMPORTDUMP-DAG: Is importing function declaration 2418497564662708935 large_func from lib.cc
106-
; IMPORTDUMP-DAG: Not importing global 7680325410415171624 calleeAddrs from lib.cc
122+
; IMPORTDUMP-DAG: Is importing global declaration 7680325410415171624 calleeAddrs from lib.cc
107123
; IMPORTDUMP-DAG: Is importing alias declaration 16730173943625350469 large_indirect_callee_alias from lib.cc
108-
; IMPORTDUMP-DAG: Is importing alias declaration 13590951773474913315 large_indirect_bar_alias from lib.cc
124+
; IMPORTDUMP-DAG: Not importing alias 13590951773474913315 large_indirect_bar_alias from lib.cc
109125
; IMPORTDUMP-DAG: Not importing function 13770917885399536773 large_indirect_bar
110126

111127
; RUN: llvm-dis in-process.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT
112128

113129
; RUN: llvm-dis in-process.2.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE
114130

131+
; IMPORT-DAG: @read_write_global_vars = external dso_local global [1 x ptr]
115132
; IMPORT-DAG: define available_externally void @small_func
116133
; IMPORT-DAG: define available_externally hidden void @small_indirect_callee
117134
; IMPORT-DAG: declare void @large_func
@@ -126,9 +143,14 @@
126143
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
127144
target triple = "x86_64-unknown-linux-gnu"
128145

146+
@read_write_global_vars = external global [1 x ptr]
147+
129148
define i32 @main() {
130149
call void @small_func()
131150
call void @large_func()
151+
%num = call ptr @external_func(ptr @read_write_global_vars)
152+
store ptr %num, ptr getelementptr inbounds ([1 x ptr], ptr @read_write_global_vars, i64 0, i64 0)
153+
%res1 = call i32 @external_func(ptr @read_write_global_vars)
132154
ret i32 0
133155
}
134156

@@ -137,6 +159,8 @@ declare void @small_func()
137159
; large_func without attributes
138160
declare void @large_func()
139161

162+
declare ptr @external_func(ptr)
163+
140164
;--- lib.ll
141165
source_filename = "lib.cc"
142166
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
@@ -149,6 +173,10 @@ target triple = "x86_64-unknown-linux-gnu"
149173
; large_indirect_bar_alias is visible to main.ll but its aliasee isn't.
150174
@calleeAddrs2 = global [1 x ptr] [ptr @large_indirect_bar_alias]
151175

176+
; @read_write_global_vars is not read-only nor write-only (in main.ll). It's not
177+
; a constant global var and has references, so it's not importable as a definition.
178+
@read_write_global_vars = dso_local global [1 x ptr] [ptr @large_indirect_callee]
179+
152180
define void @callee() #1 {
153181
ret void
154182
}
@@ -177,8 +205,12 @@ define void @large_indirect_bar()#2 {
177205

178206
define internal void @small_indirect_callee() #0 {
179207
entry:
180-
%0 = load ptr, ptr @calleeAddrs2
181-
call void %0(), !prof !3
208+
%0 = load ptr, ptr @calleeAddrs
209+
; The function-import pass crash (see pr/117584) when alias is imported but
210+
; aliasee isn't.
211+
; TODO: Update !prof to !3 (for @large_indirect_bar_alias) after alias/aliasee
212+
; import issue is handled.
213+
call void %0(), !prof !0
182214
ret void
183215
}
184216

@@ -197,6 +229,8 @@ entry:
197229
ret void
198230
}
199231

232+
declare void @external_func()
233+
200234
define void @large_func() #0 {
201235
entry:
202236
call void @callee()

0 commit comments

Comments
 (0)