Skip to content

Commit 7c0834f

Browse files
tmandryteresajohnson
authored andcommitted
[ThinLTO] Handle variable with twice promoted name (Rust) (#31)
Summary: Ensure that we can internalize values produced from two rounds of promotion. Note that this cannot happen currently via clang, but in other use cases such as the Rust compiler which does a first round of ThinLTO on library code, producing bitcode, and a second round on the final binary. In particular this can happen if a function is exported and promoted, ending up with a ".llvm.${hash}" suffix, and then goes through a round of optimization creating an internal switch table expansion variable that is internal and contains the promoted name of the enclosing function. This variable will be promoted in the second round of ThinLTO if @foo is imported again, and therefore ends up with two ".llvm.${hash}" suffixes. Only the final one should be stripped when consulting the index to locate the summary. Reviewers: wmi Subscribers: mehdi_amini, inglorion, hiraditya, JDevlieghere, steven_wu, dexonsmith, arphaman, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D72711 Co-authored-by: Teresa Johnson <[email protected]>
1 parent 24100f0 commit 7c0834f

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

llvm/include/llvm/IR/ModuleSummaryIndex.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -1239,9 +1239,11 @@ class ModuleSummaryIndex {
12391239
}
12401240

12411241
/// Helper to obtain the unpromoted name for a global value (or the original
1242-
/// name if not promoted).
1242+
/// name if not promoted). Split off the rightmost ".llvm.${hash}" suffix,
1243+
/// because it is possible in certain clients (not clang at the moment) for
1244+
/// two rounds of ThinLTO optimization and therefore promotion to occur.
12431245
static StringRef getOriginalNameBeforePromote(StringRef Name) {
1244-
std::pair<StringRef, StringRef> Pair = Name.split(".llvm.");
1246+
std::pair<StringRef, StringRef> Pair = Name.rsplit(".llvm.");
12451247
return Pair.first;
12461248
}
12471249

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-apple-macosx10.15.0"
3+
4+
define i32 @main() {
5+
entry:
6+
call void @foo.llvm.123()
7+
ret i32 0
8+
}
9+
10+
declare void @foo.llvm.123()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; Test to ensure that we can internalize values produced from two rounds
2+
; of ThinLTO promotion, so they end up with two ".llvm.${hash}" suffixes.
3+
; Only the second should be stripped when consulting the index to locate the
4+
; summary.
5+
;
6+
; Note that this cannot happen currently via clang, but in other use cases such
7+
; as the Rust compiler which does a first round of ThinLTO on library code,
8+
; producing bitcode, and a second round on the final binary.
9+
;
10+
; In this case we assume a prior round of ThinLTO has promoted @foo, and
11+
; subsequent optimization created an internal switch table expansion variable
12+
; that is internal and contains the promoted name of the enclosing function.
13+
; This variable will be promoted in the second round of ThinLTO if @foo is
14+
; imported again.
15+
16+
; RUN: opt -module-summary -o %t.bc %s
17+
; RUN: opt -module-summary -o %t-main.bc %S/Inputs/thinlto-internalize-doublepromoted.ll
18+
; RUN: llvm-lto -thinlto-action=thinlink %t.bc %t-main.bc -o %t-index.bc
19+
; RUN: llvm-lto -thinlto-action=internalize -exported-symbol=main -thinlto-index %t-index.bc %t.bc -o %t.internalize.bc
20+
; RUN: llvm-dis %t.internalize.bc -o - | FileCheck %s
21+
22+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
23+
target triple = "x86_64-apple-macosx10.15.0"
24+
25+
; CHECK: @switch.table.foo.llvm.123.llvm.0 = hidden unnamed_addr constant
26+
@switch.table.foo.llvm.123 = private unnamed_addr constant [10 x i8] c"\00\01\02\03\00\00\00\00\00\09", align 1
27+
28+
; CHECK: define hidden void @foo.llvm.123()
29+
define hidden void @foo.llvm.123() {
30+
%1 = getelementptr inbounds [10 x i8], [10 x i8]* @switch.table.foo.llvm.123, i64 0, i64 0
31+
store i8 1, i8* %1, align 8
32+
ret void
33+
}

0 commit comments

Comments
 (0)