Skip to content

Commit 5be6092

Browse files
committed
[PowerPC] Do not merge TLS constants within PPCMergeStringPool.cpp
This patch prevents thread-local constants to be merged within PPCMergeStringPool.cpp. The PPCMergeStringPool pass primarily merges non-thread-local constants together, and thread-local constants should not be mixed together with other (non-thread-local) constants. In the event that thread-local and other non-thread-local constants are pooled together, the llvm.threadlocal.address intrinsic can fail as it expects its argument to be a thread-local global value, but the merged string structure created by the PPCMergeStringPool pass is not thread-local as a whole.
1 parent 2adc012 commit 5be6092

File tree

2 files changed

+265
-0
lines changed

2 files changed

+265
-0
lines changed

llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ void PPCMergeStringPool::collectCandidateConstants(Module &M) {
215215
Global.getLinkage() != GlobalValue::InternalLinkage)
216216
continue;
217217

218+
// Do not pool thread-local constants, as the pooled strings can contain
219+
// non-thread-local constants, and these should not be mixed together.
220+
if (Global.isThreadLocal())
221+
continue;
222+
218223
LLVM_DEBUG(dbgs() << "Constant data of Global: ");
219224
LLVM_DEBUG(ConstData->dump());
220225
LLVM_DEBUG(dbgs() << "\n\n");
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr8 \
3+
; RUN: -ppc-asm-full-reg-names < %s | FileCheck %s \
4+
; RUN: --check-prefix=CHECK64
5+
; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr8 \
6+
; RUN: -ppc-asm-full-reg-names < %s | FileCheck %s \
7+
; RUN: --check-prefix=CHECK32
8+
; RUN: llc -verify-machineinstrs -mtriple powerpc64le-unknown-linux -mcpu=pwr8 \
9+
; RUN: -ppc-asm-full-reg-names < %s | FileCheck %s \
10+
; RUN: --check-prefix=LINUX64LE
11+
; RUN: llc -verify-machineinstrs -mtriple powerpc64-unknown-linux -mcpu=pwr8 \
12+
; RUN: -ppc-asm-full-reg-names < %s | FileCheck %s \
13+
; RUN: --check-prefix=LINUX64BE
14+
15+
@.str = private unnamed_addr constant [47 x i8] c"TLS variable 1, 2 and non-TLS var: %s, %s, %s\0A\00", align 1
16+
@a = internal thread_local constant [5 x i8] c"tls1\00", align 1
17+
@b = internal thread_local constant [5 x i8] c"tls2\00", align 1
18+
@c = internal constant [15 x i8] c"Regular global\00", align 1
19+
@d = internal constant [10 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10], align 4
20+
@e = internal constant [4 x float] [float 0x4055F33340000000, float 0x4056333340000000, float 0x40567999A0000000, float 0x4056B33340000000], align 4
21+
22+
declare noundef signext i32 @printf(ptr nocapture noundef readonly, ...) local_unnamed_addr #0
23+
declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1
24+
declare void @callee(ptr noundef) local_unnamed_addr #3
25+
declare void @callee2(ptr noundef) local_unnamed_addr #3
26+
27+
define void @print_tls_func() {
28+
; CHECK64-LABEL: print_tls_func:
29+
; CHECK64: # %bb.0: # %entry
30+
; CHECK64-NEXT: mflr r0
31+
; CHECK64-NEXT: stdu r1, -112(r1)
32+
; CHECK64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML"
33+
; CHECK64-NEXT: std r0, 128(r1)
34+
; CHECK64-NEXT: ld r6, L..C1(r2) # @__ModuleStringPool
35+
; CHECK64-NEXT: bla .__tls_get_mod[PR]
36+
; CHECK64-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsld) @a
37+
; CHECK64-NEXT: ld r5, L..C3(r2) # target-flags(ppc-tlsld) @b
38+
; CHECK64-NEXT: add r4, r3, r4
39+
; CHECK64-NEXT: add r5, r3, r5
40+
; CHECK64-NEXT: addi r3, r6, 71
41+
; CHECK64-NEXT: addi r6, r6, 56
42+
; CHECK64-NEXT: bl .printf[PR]
43+
; CHECK64-NEXT: nop
44+
; CHECK64-NEXT: addi r1, r1, 112
45+
; CHECK64-NEXT: ld r0, 16(r1)
46+
; CHECK64-NEXT: mtlr r0
47+
; CHECK64-NEXT: blr
48+
;
49+
; CHECK32-LABEL: print_tls_func:
50+
; CHECK32: # %bb.0: # %entry
51+
; CHECK32-NEXT: mflr r0
52+
; CHECK32-NEXT: stwu r1, -64(r1)
53+
; CHECK32-NEXT: lwz r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML"
54+
; CHECK32-NEXT: stw r0, 72(r1)
55+
; CHECK32-NEXT: lwz r6, L..C1(r2) # @__ModuleStringPool
56+
; CHECK32-NEXT: bla .__tls_get_mod[PR]
57+
; CHECK32-NEXT: lwz r4, L..C2(r2) # target-flags(ppc-tlsld) @a
58+
; CHECK32-NEXT: lwz r5, L..C3(r2) # target-flags(ppc-tlsld) @b
59+
; CHECK32-NEXT: add r4, r3, r4
60+
; CHECK32-NEXT: add r5, r3, r5
61+
; CHECK32-NEXT: addi r3, r6, 71
62+
; CHECK32-NEXT: addi r6, r6, 56
63+
; CHECK32-NEXT: bl .printf[PR]
64+
; CHECK32-NEXT: nop
65+
; CHECK32-NEXT: addi r1, r1, 64
66+
; CHECK32-NEXT: lwz r0, 8(r1)
67+
; CHECK32-NEXT: mtlr r0
68+
; CHECK32-NEXT: blr
69+
;
70+
; LINUX64LE-LABEL: print_tls_func:
71+
; LINUX64LE: # %bb.0: # %entry
72+
; LINUX64LE-NEXT: mflr r0
73+
; LINUX64LE-NEXT: stdu r1, -96(r1)
74+
; LINUX64LE-NEXT: std r0, 112(r1)
75+
; LINUX64LE-NEXT: .cfi_def_cfa_offset 96
76+
; LINUX64LE-NEXT: .cfi_offset lr, 16
77+
; LINUX64LE-NEXT: addis r3, r13, a@tprel@ha
78+
; LINUX64LE-NEXT: addi r4, r3, a@tprel@l
79+
; LINUX64LE-NEXT: addis r3, r13, b@tprel@ha
80+
; LINUX64LE-NEXT: addi r5, r3, b@tprel@l
81+
; LINUX64LE-NEXT: addis r3, r2, .L__ModuleStringPool@toc@ha
82+
; LINUX64LE-NEXT: addi r6, r3, .L__ModuleStringPool@toc@l
83+
; LINUX64LE-NEXT: addi r3, r6, 71
84+
; LINUX64LE-NEXT: addi r6, r6, 56
85+
; LINUX64LE-NEXT: bl printf
86+
; LINUX64LE-NEXT: nop
87+
; LINUX64LE-NEXT: addi r1, r1, 96
88+
; LINUX64LE-NEXT: ld r0, 16(r1)
89+
; LINUX64LE-NEXT: mtlr r0
90+
; LINUX64LE-NEXT: blr
91+
;
92+
; LINUX64BE-LABEL: print_tls_func:
93+
; LINUX64BE: # %bb.0: # %entry
94+
; LINUX64BE-NEXT: mflr r0
95+
; LINUX64BE-NEXT: stdu r1, -128(r1)
96+
; LINUX64BE-NEXT: std r0, 144(r1)
97+
; LINUX64BE-NEXT: .cfi_def_cfa_offset 128
98+
; LINUX64BE-NEXT: .cfi_offset lr, 16
99+
; LINUX64BE-NEXT: .cfi_offset r30, -16
100+
; LINUX64BE-NEXT: addis r3, r2, a@got@tlsld@ha
101+
; LINUX64BE-NEXT: std r30, 112(r1) # 8-byte Folded Spill
102+
; LINUX64BE-NEXT: addi r3, r3, a@got@tlsld@l
103+
; LINUX64BE-NEXT: bl __tls_get_addr(a@tlsld)
104+
; LINUX64BE-NEXT: nop
105+
; LINUX64BE-NEXT: addis r3, r3, a@dtprel@ha
106+
; LINUX64BE-NEXT: addi r30, r3, a@dtprel@l
107+
; LINUX64BE-NEXT: addis r3, r2, b@got@tlsld@ha
108+
; LINUX64BE-NEXT: addi r3, r3, b@got@tlsld@l
109+
; LINUX64BE-NEXT: bl __tls_get_addr(b@tlsld)
110+
; LINUX64BE-NEXT: nop
111+
; LINUX64BE-NEXT: addis r3, r3, b@dtprel@ha
112+
; LINUX64BE-NEXT: addi r5, r3, b@dtprel@l
113+
; LINUX64BE-NEXT: addis r3, r2, .L__ModuleStringPool@toc@ha
114+
; LINUX64BE-NEXT: addi r4, r3, .L__ModuleStringPool@toc@l
115+
; LINUX64BE-NEXT: addi r3, r4, 71
116+
; LINUX64BE-NEXT: addi r6, r4, 56
117+
; LINUX64BE-NEXT: mr r4, r30
118+
; LINUX64BE-NEXT: bl printf
119+
; LINUX64BE-NEXT: nop
120+
; LINUX64BE-NEXT: ld r30, 112(r1) # 8-byte Folded Reload
121+
; LINUX64BE-NEXT: addi r1, r1, 128
122+
; LINUX64BE-NEXT: ld r0, 16(r1)
123+
; LINUX64BE-NEXT: mtlr r0
124+
; LINUX64BE-NEXT: blr
125+
entry:
126+
%0 = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @a)
127+
%1 = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @b)
128+
%call = tail call signext i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str, ptr noundef nonnull %0, ptr noundef nonnull %1, ptr noundef nonnull @c)
129+
ret void
130+
}
131+
132+
define void @test_func() {
133+
; CHECK64-LABEL: test_func:
134+
; CHECK64: # %bb.0: # %entry
135+
; CHECK64-NEXT: mflr r0
136+
; CHECK64-NEXT: stdu r1, -112(r1)
137+
; CHECK64-NEXT: ld r3, L..C1(r2) # @__ModuleStringPool
138+
; CHECK64-NEXT: std r0, 128(r1)
139+
; CHECK64-NEXT: addi r3, r3, 16
140+
; CHECK64-NEXT: bl .callee[PR]
141+
; CHECK64-NEXT: nop
142+
; CHECK64-NEXT: addi r1, r1, 112
143+
; CHECK64-NEXT: ld r0, 16(r1)
144+
; CHECK64-NEXT: mtlr r0
145+
; CHECK64-NEXT: blr
146+
;
147+
; CHECK32-LABEL: test_func:
148+
; CHECK32: # %bb.0: # %entry
149+
; CHECK32-NEXT: mflr r0
150+
; CHECK32-NEXT: stwu r1, -64(r1)
151+
; CHECK32-NEXT: lwz r3, L..C1(r2) # @__ModuleStringPool
152+
; CHECK32-NEXT: stw r0, 72(r1)
153+
; CHECK32-NEXT: addi r3, r3, 16
154+
; CHECK32-NEXT: bl .callee[PR]
155+
; CHECK32-NEXT: nop
156+
; CHECK32-NEXT: addi r1, r1, 64
157+
; CHECK32-NEXT: lwz r0, 8(r1)
158+
; CHECK32-NEXT: mtlr r0
159+
; CHECK32-NEXT: blr
160+
;
161+
; LINUX64LE-LABEL: test_func:
162+
; LINUX64LE: # %bb.0: # %entry
163+
; LINUX64LE-NEXT: mflr r0
164+
; LINUX64LE-NEXT: stdu r1, -32(r1)
165+
; LINUX64LE-NEXT: std r0, 48(r1)
166+
; LINUX64LE-NEXT: .cfi_def_cfa_offset 32
167+
; LINUX64LE-NEXT: .cfi_offset lr, 16
168+
; LINUX64LE-NEXT: addis r3, r2, .L__ModuleStringPool@toc@ha
169+
; LINUX64LE-NEXT: addi r3, r3, .L__ModuleStringPool@toc@l
170+
; LINUX64LE-NEXT: addi r3, r3, 16
171+
; LINUX64LE-NEXT: bl callee
172+
; LINUX64LE-NEXT: nop
173+
; LINUX64LE-NEXT: addi r1, r1, 32
174+
; LINUX64LE-NEXT: ld r0, 16(r1)
175+
; LINUX64LE-NEXT: mtlr r0
176+
; LINUX64LE-NEXT: blr
177+
;
178+
; LINUX64BE-LABEL: test_func:
179+
; LINUX64BE: # %bb.0: # %entry
180+
; LINUX64BE-NEXT: mflr r0
181+
; LINUX64BE-NEXT: stdu r1, -112(r1)
182+
; LINUX64BE-NEXT: std r0, 128(r1)
183+
; LINUX64BE-NEXT: .cfi_def_cfa_offset 112
184+
; LINUX64BE-NEXT: .cfi_offset lr, 16
185+
; LINUX64BE-NEXT: addis r3, r2, .L__ModuleStringPool@toc@ha
186+
; LINUX64BE-NEXT: addi r3, r3, .L__ModuleStringPool@toc@l
187+
; LINUX64BE-NEXT: addi r3, r3, 16
188+
; LINUX64BE-NEXT: bl callee
189+
; LINUX64BE-NEXT: nop
190+
; LINUX64BE-NEXT: addi r1, r1, 112
191+
; LINUX64BE-NEXT: ld r0, 16(r1)
192+
; LINUX64BE-NEXT: mtlr r0
193+
; LINUX64BE-NEXT: blr
194+
entry:
195+
tail call void @callee(ptr noundef nonnull @d) #4
196+
ret void
197+
}
198+
199+
define void @test_func2() {
200+
; CHECK64-LABEL: test_func2:
201+
; CHECK64: # %bb.0: # %entry
202+
; CHECK64-NEXT: mflr r0
203+
; CHECK64-NEXT: stdu r1, -112(r1)
204+
; CHECK64-NEXT: ld r3, L..C1(r2) # @__ModuleStringPool
205+
; CHECK64-NEXT: std r0, 128(r1)
206+
; CHECK64-NEXT: bl .callee2[PR]
207+
; CHECK64-NEXT: nop
208+
; CHECK64-NEXT: addi r1, r1, 112
209+
; CHECK64-NEXT: ld r0, 16(r1)
210+
; CHECK64-NEXT: mtlr r0
211+
; CHECK64-NEXT: blr
212+
;
213+
; CHECK32-LABEL: test_func2:
214+
; CHECK32: # %bb.0: # %entry
215+
; CHECK32-NEXT: mflr r0
216+
; CHECK32-NEXT: stwu r1, -64(r1)
217+
; CHECK32-NEXT: lwz r3, L..C1(r2) # @__ModuleStringPool
218+
; CHECK32-NEXT: stw r0, 72(r1)
219+
; CHECK32-NEXT: bl .callee2[PR]
220+
; CHECK32-NEXT: nop
221+
; CHECK32-NEXT: addi r1, r1, 64
222+
; CHECK32-NEXT: lwz r0, 8(r1)
223+
; CHECK32-NEXT: mtlr r0
224+
; CHECK32-NEXT: blr
225+
;
226+
; LINUX64LE-LABEL: test_func2:
227+
; LINUX64LE: # %bb.0: # %entry
228+
; LINUX64LE-NEXT: mflr r0
229+
; LINUX64LE-NEXT: stdu r1, -32(r1)
230+
; LINUX64LE-NEXT: std r0, 48(r1)
231+
; LINUX64LE-NEXT: .cfi_def_cfa_offset 32
232+
; LINUX64LE-NEXT: .cfi_offset lr, 16
233+
; LINUX64LE-NEXT: addis r3, r2, .L__ModuleStringPool@toc@ha
234+
; LINUX64LE-NEXT: addi r3, r3, .L__ModuleStringPool@toc@l
235+
; LINUX64LE-NEXT: bl callee2
236+
; LINUX64LE-NEXT: nop
237+
; LINUX64LE-NEXT: addi r1, r1, 32
238+
; LINUX64LE-NEXT: ld r0, 16(r1)
239+
; LINUX64LE-NEXT: mtlr r0
240+
; LINUX64LE-NEXT: blr
241+
;
242+
; LINUX64BE-LABEL: test_func2:
243+
; LINUX64BE: # %bb.0: # %entry
244+
; LINUX64BE-NEXT: mflr r0
245+
; LINUX64BE-NEXT: stdu r1, -112(r1)
246+
; LINUX64BE-NEXT: std r0, 128(r1)
247+
; LINUX64BE-NEXT: .cfi_def_cfa_offset 112
248+
; LINUX64BE-NEXT: .cfi_offset lr, 16
249+
; LINUX64BE-NEXT: addis r3, r2, .L__ModuleStringPool@toc@ha
250+
; LINUX64BE-NEXT: addi r3, r3, .L__ModuleStringPool@toc@l
251+
; LINUX64BE-NEXT: bl callee2
252+
; LINUX64BE-NEXT: nop
253+
; LINUX64BE-NEXT: addi r1, r1, 112
254+
; LINUX64BE-NEXT: ld r0, 16(r1)
255+
; LINUX64BE-NEXT: mtlr r0
256+
; LINUX64BE-NEXT: blr
257+
entry:
258+
tail call void @callee2(ptr noundef nonnull @e) #4
259+
ret void
260+
}

0 commit comments

Comments
 (0)