Skip to content

Commit 44c4c3e

Browse files
committed
[RelLookupTableConverter] Drop unnamed_addr for GVs in entries to avoid generating GOTPCREL relocations (llvm#146068)
The entry in a relative lookup table is a global variable with a constant offset, such as `@gv`, `GEP @gv, 1`, and so on. We cannot only consider the case of a trivial global variable. This PR handles all cases using the existing `IsConstantOffsetFromGlobal` function. (cherry picked from commit c43282a)
1 parent 319a89e commit 44c4c3e

File tree

2 files changed

+66
-16
lines changed

2 files changed

+66
-16
lines changed

llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV) {
6767
if (!ElemType->isPointerTy() || DL.getPointerTypeSizeInBits(ElemType) != 64)
6868
return false;
6969

70+
SmallVector<GlobalVariable *, 4> GVOps;
71+
Triple TT(M.getTargetTriple());
72+
// FIXME: This should be removed in the future.
73+
bool ShouldDropUnnamedAddr =
74+
// Drop unnamed_addr to avoid matching pattern in
75+
// `handleIndirectSymViaGOTPCRel`, which generates GOTPCREL relocations
76+
// not supported by the GNU linker and LLD versions below 18 on aarch64.
77+
TT.isAArch64()
78+
// Apple's ld64 (and ld-prime on Xcode 15.2) miscompile something on
79+
// x86_64-apple-darwin. See
80+
// https://github.com/rust-lang/rust/issues/140686 and
81+
// https://github.com/rust-lang/rust/issues/141306.
82+
|| (TT.isX86() && TT.isOSDarwin());
83+
7084
for (const Use &Op : Array->operands()) {
7185
Constant *ConstOp = cast<Constant>(&Op);
7286
GlobalValue *GVOp;
@@ -86,8 +100,15 @@ static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV) {
86100
!GlovalVarOp->isDSOLocal() ||
87101
!GlovalVarOp->isImplicitDSOLocal())
88102
return false;
103+
104+
if (ShouldDropUnnamedAddr)
105+
GVOps.push_back(GlovalVarOp);
89106
}
90107

108+
if (ShouldDropUnnamedAddr)
109+
for (auto *GVOp : GVOps)
110+
GVOp->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
111+
91112
return true;
92113
}
93114

@@ -109,24 +130,8 @@ static GlobalVariable *createRelLookupTable(Function &Func,
109130
uint64_t Idx = 0;
110131
SmallVector<Constant *, 64> RelLookupTableContents(NumElts);
111132

112-
Triple TT(M.getTargetTriple());
113-
// FIXME: This should be removed in the future.
114-
bool ShouldDropUnnamedAddr =
115-
// Drop unnamed_addr to avoid matching pattern in
116-
// `handleIndirectSymViaGOTPCRel`, which generates GOTPCREL relocations
117-
// not supported by the GNU linker and LLD versions below 18 on aarch64.
118-
TT.isAArch64()
119-
// Apple's ld64 (and ld-prime on Xcode 15.2) miscompile something on
120-
// x86_64-apple-darwin. See
121-
// https://github.com/rust-lang/rust/issues/140686 and
122-
// https://github.com/rust-lang/rust/issues/141306.
123-
|| (TT.isX86() && TT.isOSDarwin());
124-
125133
for (Use &Operand : LookupTableArr->operands()) {
126134
Constant *Element = cast<Constant>(Operand);
127-
if (ShouldDropUnnamedAddr)
128-
if (auto *GlobalElement = dyn_cast<GlobalValue>(Element))
129-
GlobalElement->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
130135
Type *IntPtrTy = M.getDataLayout().getIntPtrType(M.getContext());
131136
Constant *Base = llvm::ConstantExpr::getPtrToInt(RelLookupTable, IntPtrTy);
132137
Constant *Target = llvm::ConstantExpr::getPtrToInt(Element, IntPtrTy);

llvm/test/Transforms/RelLookupTableConverter/unnamed_addr.ll

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
@y3 = internal unnamed_addr constant ptr @x0
2121
@load_relative_2.table = private unnamed_addr constant [4 x ptr] [ptr @y3, ptr @y2, ptr @y1, ptr @y0]
2222

23+
@b0 = private unnamed_addr constant [8 x i8] c"00000000"
24+
@b1 = private unnamed_addr constant [8 x i8] c"11111111"
25+
@b2 = private unnamed_addr constant [8 x i8] c"22222222"
26+
@load_relative_3.table = private unnamed_addr constant [3 x ptr] [
27+
ptr getelementptr inbounds (i8, ptr @b0, i64 8),
28+
ptr getelementptr inbounds (i8, ptr @b1, i64 8),
29+
ptr getelementptr inbounds (i8, ptr @b2, i64 8)]
30+
2331
;.
2432
; x86_64-apple-darwin: @a0 = private constant i32 0
2533
; x86_64-apple-darwin: @a1 = private constant i32 1
@@ -34,6 +42,10 @@
3442
; x86_64-apple-darwin: @y2 = internal constant ptr @x1
3543
; x86_64-apple-darwin: @y3 = internal constant ptr @x0
3644
; x86_64-apple-darwin: @load_relative_2.table.rel = private unnamed_addr constant [4 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @y3 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y2 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y1 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y0 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32)], align 4
45+
; x86_64-apple-darwin: @b0 = private constant [8 x i8] c"00000000"
46+
; x86_64-apple-darwin: @b1 = private constant [8 x i8] c"11111111"
47+
; x86_64-apple-darwin: @b2 = private constant [8 x i8] c"22222222"
48+
; x86_64-apple-darwin: @load_relative_3.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b0, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b1, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b2, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32)], align 4
3749
;.
3850
; aarch64: @a0 = private constant i32 0
3951
; aarch64: @a1 = private constant i32 1
@@ -48,6 +60,10 @@
4860
; aarch64: @y2 = internal constant ptr @x1
4961
; aarch64: @y3 = internal constant ptr @x0
5062
; aarch64: @load_relative_2.table.rel = private unnamed_addr constant [4 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @y3 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y2 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y1 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y0 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32)], align 4
63+
; aarch64: @b0 = private constant [8 x i8] c"00000000"
64+
; aarch64: @b1 = private constant [8 x i8] c"11111111"
65+
; aarch64: @b2 = private constant [8 x i8] c"22222222"
66+
; aarch64: @load_relative_3.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b0, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b1, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b2, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32)], align 4
5167
;.
5268
; x86_64: @a0 = private unnamed_addr constant i32 0
5369
; x86_64: @a1 = private unnamed_addr constant i32 1
@@ -62,6 +78,10 @@
6278
; x86_64: @y2 = internal unnamed_addr constant ptr @x1
6379
; x86_64: @y3 = internal unnamed_addr constant ptr @x0
6480
; x86_64: @load_relative_2.table.rel = private unnamed_addr constant [4 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @y3 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y2 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y1 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y0 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32)], align 4
81+
; x86_64: @b0 = private unnamed_addr constant [8 x i8] c"00000000"
82+
; x86_64: @b1 = private unnamed_addr constant [8 x i8] c"11111111"
83+
; x86_64: @b2 = private unnamed_addr constant [8 x i8] c"22222222"
84+
; x86_64: @load_relative_3.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b0, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b1, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b2, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32)], align 4
6585
;.
6686
define ptr @load_relative_1(i64 %offset) {
6787
; x86_64-apple-darwin-LABEL: define ptr @load_relative_1(
@@ -110,6 +130,31 @@ define ptr @load_relative_2(i64 %offset) {
110130
%load = load ptr, ptr %gep
111131
ret ptr %load
112132
}
133+
134+
define ptr @load_relative_3(i64 %offset) {
135+
; x86_64-apple-darwin-LABEL: define ptr @load_relative_3(
136+
; x86_64-apple-darwin-SAME: i64 [[OFFSET:%.*]]) {
137+
; x86_64-apple-darwin-NEXT: [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
138+
; x86_64-apple-darwin-NEXT: [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_3.table.rel, i64 [[RELTABLE_SHIFT]])
139+
; x86_64-apple-darwin-NEXT: ret ptr [[RELTABLE_INTRINSIC]]
140+
;
141+
; aarch64-LABEL: define ptr @load_relative_3(
142+
; aarch64-SAME: i64 [[OFFSET:%.*]]) {
143+
; aarch64-NEXT: [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
144+
; aarch64-NEXT: [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_3.table.rel, i64 [[RELTABLE_SHIFT]])
145+
; aarch64-NEXT: ret ptr [[RELTABLE_INTRINSIC]]
146+
;
147+
; x86_64-LABEL: define ptr @load_relative_3(
148+
; x86_64-SAME: i64 [[OFFSET:%.*]]) {
149+
; x86_64-NEXT: [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
150+
; x86_64-NEXT: [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_3.table.rel, i64 [[RELTABLE_SHIFT]])
151+
; x86_64-NEXT: ret ptr [[RELTABLE_INTRINSIC]]
152+
;
153+
%gep = getelementptr inbounds [3 x ptr], ptr @load_relative_3.table, i64 0, i64 %offset
154+
%load = load ptr, ptr %gep
155+
ret ptr %load
156+
}
157+
113158
;.
114159
; x86_64-apple-darwin: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
115160
;.

0 commit comments

Comments
 (0)