[AArch64,ELF] Restrict MOVZ/MOVK to non-PIC large code model (#70178)
[llvm-project.git] / llvm / test / CodeGen / X86 / tls-loads-control.ll
blob8d9bf61c53fa5736f40a0e8f10a29638ea39f26b
1 ; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --tls-load-hoist=true --stop-after=tlshoist -o - %s | FileCheck %s
2 ; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --stop-after=tlshoist -o - %s | FileCheck %s
4 ; This test come from compiling clang/test/CodeGen/intel/tls_loads.cpp with:
5 ; (clang tls_loads.cpp -fPIC -ftls-model=global-dynamic -O2 -S -emit-llvm)
7 ; // Variable declaration and definition:
8 ; thread_local int thl_x;
9 ; thread_local int thl_x2;
11 ; struct SS {
12 ;   char thl_c;
13 ;   int num;
14 ; };
16 ; int gfunc();
17 ; int gfunc2(int);
19 ; // First function (@_Z2f1i):
20 ; int f1(int c) {
21 ;   while (c)
22 ;     c++;
24 ;   int *px = &thl_x;
25 ;   c -= gfunc();
27 ;   while(c++) {
28 ;     c = gfunc();
29 ;     while (c--)
30 ;       *px += gfunc2(thl_x2);
31 ;   }
32 ;   return *px;
33 ; }
35 $_ZTW5thl_x = comdat any
37 $_ZTW6thl_x2 = comdat any
39 @thl_x = thread_local global i32 0, align 4
40 @thl_x2 = thread_local global i32 0, align 4
41 @_ZZ2f2iE2st.0 = internal thread_local unnamed_addr global i8 0, align 4
42 @_ZZ2f2iE2st.1 = internal thread_local unnamed_addr global i32 0, align 4
44 ; Function Attrs: mustprogress uwtable
45 define noundef i32 @_Z2f1i(i32 noundef %c) local_unnamed_addr #0 {
46 ; CHECK-LABEL: _Z2f1i
47 ; CHECK:      entry:
48 ; CHECK-NEXT:   %call = tail call noundef i32 @_Z5gfuncv()
49 ; CHECK-NEXT:   %phi.cmp = icmp eq i32 %call, 0
50 ; CHECK-NEXT:   %tls_bitcast1 = bitcast ptr @thl_x to ptr
51 ; CHECK-NEXT:   br i1 %phi.cmp, label %while.end11, label %while.body4.preheader
53 ; CHECK:      while.body4.preheader:
54 ; CHECK-NEXT:   %tls_bitcast = bitcast ptr @thl_x2 to ptr
55 ; CHECK-NEXT:   br label %while.body4
57 ; CHECK:      while.body4:
58 ; CHECK-NEXT:   %call5 = tail call noundef i32 @_Z5gfuncv()
59 ; CHECK-NEXT:   %tobool7.not18 = icmp eq i32 %call5, 0
60 ; CHECK-NEXT:   br i1 %tobool7.not18, label %while.body4.backedge, label %while.body8.preheader
62 ; CHECK:      while.body8.preheader:
63 ; CHECK-NEXT:   br label %while.body8
65 ; CHECK:      while.body4.backedge.loopexit:
66 ; CHECK-NEXT:   br label %while.body4.backedge
68 ; CHECK:      while.body4.backedge:
69 ; CHECK-NEXT:   br label %while.body4, !llvm.loop !4
71 ; CHECK:      while.body8:
72 ; CHECK-NEXT:   %c.addr.219 = phi i32 [ %dec, %while.body8 ], [ %call5, %while.body8.preheader ]
73 ; CHECK-NEXT:   %dec = add i32 %c.addr.219, -1
74 ; CHECK-NEXT:   %0 = load i32, ptr %tls_bitcast, align 4
75 ; CHECK-NEXT:   %call9 = tail call noundef i32 @_Z6gfunc2i(i32 noundef %0)
76 ; CHECK-NEXT:   %1 = load i32, ptr %tls_bitcast1, align 4
77 ; CHECK-NEXT:   %add = add nsw i32 %1, %call9
78 ; CHECK-NEXT:   store i32 %add, ptr %tls_bitcast1, align 4
79 ; CHECK-NEXT:   %tobool7.not = icmp eq i32 %dec, 0
80 ; CHECK-NEXT:   br i1 %tobool7.not, label %while.body4.backedge.loopexit, label %while.body8, !llvm.loop !4
82 ; CHECK:      while.end11:
83 ; CHECK-NEXT:   %2 = load i32, ptr %tls_bitcast1, align 4
84 ; CHECK-NEXT:   ret i32 %2
86 entry:
87   %call = tail call noundef i32 @_Z5gfuncv()
88   %phi.cmp = icmp eq i32 %call, 0
89   br i1 %phi.cmp, label %while.end11, label %while.body4
91 while.body4:                                      ; preds = %entry, %while.body4.backedge
92   %call5 = tail call noundef i32 @_Z5gfuncv()
93   %tobool7.not18 = icmp eq i32 %call5, 0
94   br i1 %tobool7.not18, label %while.body4.backedge, label %while.body8
96 while.body4.backedge:                             ; preds = %while.body8, %while.body4
97   br label %while.body4, !llvm.loop !4
99 while.body8:                                      ; preds = %while.body4, %while.body8
100   %c.addr.219 = phi i32 [ %dec, %while.body8 ], [ %call5, %while.body4 ]
101   %dec = add nsw i32 %c.addr.219, -1
102   %0 = load i32, ptr @thl_x2, align 4
103   %call9 = tail call noundef i32 @_Z6gfunc2i(i32 noundef %0)
104   %1 = load i32, ptr @thl_x, align 4
105   %add = add nsw i32 %1, %call9
106   store i32 %add, ptr @thl_x, align 4
107   %tobool7.not = icmp eq i32 %dec, 0
108   br i1 %tobool7.not, label %while.body4.backedge, label %while.body8, !llvm.loop !4
110 while.end11:                                      ; preds = %entry
111   %2 = load i32, ptr @thl_x, align 4
112   ret i32 %2
115 ; // Sencond function (@_Z2f2i):
116 ; int f2(int c) {
117 ;   thread_local struct SS st;
118 ;   c += gfunc();
119 ;   while (c--) {
120 ;     thl_x += gfunc();
121 ;     st.thl_c += (char)gfunc();
122 ;     st.num += gfunc();
123 ;   }
124 ;   return thl_x;
125 ; }
126 declare noundef i32 @_Z5gfuncv() local_unnamed_addr #1
128 declare noundef i32 @_Z6gfunc2i(i32 noundef) local_unnamed_addr #1
130 ; Function Attrs: mustprogress uwtable
131 define noundef i32 @_Z2f2i(i32 noundef %c) local_unnamed_addr #0 {
132 ; CHECK-LABEL: _Z2f2i
133 ; CHECK:      entry:
134 ; CHECK-NEXT:   %call = tail call noundef i32 @_Z5gfuncv()
135 ; CHECK-NEXT:   %add = add nsw i32 %call, %c
136 ; CHECK-NEXT:   %tobool.not12 = icmp eq i32 %add, 0
137 ; CHECK-NEXT:   %tls_bitcast = bitcast ptr @thl_x to ptr
138 ; CHECK-NEXT:   br i1 %tobool.not12, label %while.end, label %while.body.preheader
140 ; CHECK:      while.body.preheader:
141 ; CHECK-NEXT:   %tls_bitcast1 = bitcast ptr @_ZZ2f2iE2st.0 to ptr
142 ; CHECK-NEXT:   %tls_bitcast2 = bitcast ptr @_ZZ2f2iE2st.1 to ptr
143 ; CHECK-NEXT:   br label %while.body
145 ; CHECK:      while.body:
146 ; CHECK-NEXT:   %c.addr.013 = phi i32 [ %dec, %while.body ], [ %add, %while.body.preheader ]
147 ; CHECK-NEXT:   %dec = add i32 %c.addr.013, -1
148 ; CHECK-NEXT:   %call1 = tail call noundef i32 @_Z5gfuncv()
149 ; CHECK-NEXT:   %0 = load i32, ptr %tls_bitcast, align 4
150 ; CHECK-NEXT:   %add2 = add nsw i32 %0, %call1
151 ; CHECK-NEXT:   store i32 %add2, ptr %tls_bitcast, align 4
152 ; CHECK-NEXT:   %call3 = tail call noundef i32 @_Z5gfuncv()
153 ; CHECK-NEXT:   %1 = load i8, ptr %tls_bitcast1, align 4
154 ; CHECK-NEXT:   %2 = trunc i32 %call3 to i8
155 ; CHECK-NEXT:   %conv7 = add i8 %1, %2
156 ; CHECK-NEXT:   store i8 %conv7, ptr %tls_bitcast1, align 4
157 ; CHECK-NEXT:   %call8 = tail call noundef i32 @_Z5gfuncv()
158 ; CHECK-NEXT:   %3 = load i32, ptr %tls_bitcast2, align 4
159 ; CHECK-NEXT:   %add9 = add nsw i32 %3, %call8
160 ; CHECK-NEXT:   store i32 %add9, ptr %tls_bitcast2, align 4
161 ; CHECK-NEXT:   %tobool.not = icmp eq i32 %dec, 0
162 ; CHECK-NEXT:   br i1 %tobool.not, label %while.end.loopexit, label %while.body
164 ; CHECK:      while.end.loopexit:
165 ; CHECK-NEXT:   br label %while.end
167 ; CHECK:      while.end:
168 ; CHECK-NEXT:   %4 = load i32, ptr %tls_bitcast, align 4
169 ; CHECK-NEXT:   ret i32 %4
170 entry:
171   %call = tail call noundef i32 @_Z5gfuncv()
172   %add = add nsw i32 %call, %c
173   %tobool.not12 = icmp eq i32 %add, 0
174   br i1 %tobool.not12, label %while.end, label %while.body
176 while.body:                                       ; preds = %entry, %while.body
177   %c.addr.013 = phi i32 [ %dec, %while.body ], [ %add, %entry ]
178   %dec = add nsw i32 %c.addr.013, -1
179   %call1 = tail call noundef i32 @_Z5gfuncv()
180   %0 = load i32, ptr @thl_x, align 4
181   %add2 = add nsw i32 %0, %call1
182   store i32 %add2, ptr @thl_x, align 4
183   %call3 = tail call noundef i32 @_Z5gfuncv()
184   %1 = load i8, ptr @_ZZ2f2iE2st.0, align 4
185   %2 = trunc i32 %call3 to i8
186   %conv7 = add i8 %1, %2
187   store i8 %conv7, ptr @_ZZ2f2iE2st.0, align 4
188   %call8 = tail call noundef i32 @_Z5gfuncv()
189   %3 = load i32, ptr @_ZZ2f2iE2st.1, align 4
190   %add9 = add nsw i32 %3, %call8
191   store i32 %add9, ptr @_ZZ2f2iE2st.1, align 4
192   %tobool.not = icmp eq i32 %dec, 0
193   br i1 %tobool.not, label %while.end, label %while.body
195 while.end:                                        ; preds = %while.body, %entry
196   %4 = load i32, ptr @thl_x, align 4
197   ret i32 %4
200 ; // Third function (@_Z2f3i):
201 ; int f3(int c) {
202 ;   int *px = &thl_x;
203 ;   gfunc2(*px);
204 ;   gfunc2(*px);
205 ;   return 1;
206 ; }
208 ; Function Attrs: mustprogress uwtable
209 define noundef i32 @_Z2f3i(i32 noundef %c) local_unnamed_addr #0 {
210 ; CHECK-LABEL: _Z2f3i
211 ; CHECK:      entry:
212 ; CHECK-NEXT:   %tls_bitcast = bitcast ptr @thl_x to ptr
213 ; CHECK-NEXT:   %0 = load i32, ptr %tls_bitcast, align 4
214 ; CHECK-NEXT:   %call = tail call noundef i32 @_Z6gfunc2i(i32 noundef %0)
215 ; CHECK-NEXT:   %1 = load i32, ptr %tls_bitcast, align 4
216 ; CHECK-NEXT:   %call1 = tail call noundef i32 @_Z6gfunc2i(i32 noundef %1)
217 ; CHECK-NEXT:   ret i32 1
218 entry:
219   %0 = load i32, ptr @thl_x, align 4
220   %call = tail call noundef i32 @_Z6gfunc2i(i32 noundef %0)
221   %1 = load i32, ptr @thl_x, align 4
222   %call1 = tail call noundef i32 @_Z6gfunc2i(i32 noundef %1)
223   ret i32 1
226 ; Function Attrs: uwtable
227 define weak_odr hidden noundef ptr @_ZTW5thl_x() local_unnamed_addr #2 comdat {
228   ret ptr @thl_x
231 ; Function Attrs: uwtable
232 define weak_odr hidden noundef ptr @_ZTW6thl_x2() local_unnamed_addr #2 comdat {
233   ret ptr @thl_x2
236 attributes #0 = { mustprogress uwtable "tls-load-hoist" "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
237 attributes #1 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
238 attributes #2 = { uwtable "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
240 !llvm.module.flags = !{!0, !1, !2}
241 !llvm.ident = !{!3}
243 !0 = !{i32 1, !"wchar_size", i32 4}
244 !1 = !{i32 7, !"PIC Level", i32 2}
245 !2 = !{i32 7, !"uwtable", i32 2}
246 !3 = !{!"clang version 15.0.0"}
247 !4 = distinct !{!4, !5}
248 !5 = !{!"llvm.loop.mustprogress"}