1 ; RUN: llc -mtriple=powerpc64le -O0 < %s | FileCheck %s
2 ; RUN: llc -mtriple=powerpc64-ibm-aix-xcoff -O0 < %s | FileCheck %s --check-prefix=AIX
3 ; RUN: llc -mtriple=powerpc-ibm-aix-xcoff -O0 < %s | FileCheck %s --check-prefix=AIX
5 ; CHECK-LABEL: in_bounds:
6 ; CHECK-NOT: __stack_chk_guard
7 ; AIX-NOT: __ssp_canary_word
8 define i32 @in_bounds() #0 {
9 %var = alloca i32, align 4
10 store i32 0, i32* %var, align 4
11 %gep = getelementptr inbounds i32, i32* %var, i32 0
12 %ret = load i32, i32* %gep, align 4
16 ; CHECK-LABEL: constant_out_of_bounds:
17 ; CHECK: __stack_chk_guard
18 ; AIX: __ssp_canary_word
19 define i32 @constant_out_of_bounds() #0 {
20 %var = alloca i32, align 4
21 store i32 0, i32* %var, align 4
22 %gep = getelementptr inbounds i32, i32* %var, i32 1
23 %ret = load i32, i32* %gep, align 4
27 ; CHECK-LABEL: nonconstant_out_of_bounds:
28 ; CHECK: __stack_chk_guard
29 ; AIX: __ssp_canary_word
30 define i32 @nonconstant_out_of_bounds(i32 %n) #0 {
31 %var = alloca i32, align 4
32 store i32 0, i32* %var, align 4
33 %gep = getelementptr inbounds i32, i32* %var, i32 %n
34 %ret = load i32, i32* %gep, align 4
38 ; CHECK-LABEL: phi_before_gep_in_bounds:
39 ; CHECK-NOT: __stack_chk_guard
40 ; AIX-NOT: __ssp_canary_word
41 define i32 @phi_before_gep_in_bounds(i32 %k) #0 {
43 %var1 = alloca i32, align 4
44 %var2 = alloca i32, align 4
45 store i32 0, i32* %var1, align 4
46 store i32 0, i32* %var2, align 4
47 %cmp = icmp ne i32 %k, 0
48 br i1 %cmp, label %if, label %then
54 %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
55 %gep = getelementptr inbounds i32, i32* %ptr, i32 0
56 %ret = load i32, i32* %gep, align 4
60 ; CHECK-LABEL: phi_before_gep_constant_out_of_bounds:
61 ; CHECK: __stack_chk_guard
62 ; AIX: __ssp_canary_word
63 define i32 @phi_before_gep_constant_out_of_bounds(i32 %k) #0 {
65 %var1 = alloca i32, align 4
66 %var2 = alloca i32, align 4
67 store i32 0, i32* %var1, align 4
68 store i32 0, i32* %var2, align 4
69 %cmp = icmp ne i32 %k, 0
70 br i1 %cmp, label %if, label %then
76 %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
77 %gep = getelementptr inbounds i32, i32* %ptr, i32 1
78 %ret = load i32, i32* %gep, align 4
82 ; CHECK-LABEL: phi_before_gep_nonconstant_out_of_bounds:
83 ; CHECK: __stack_chk_guard
84 ; AIX: __ssp_canary_word
85 define i32 @phi_before_gep_nonconstant_out_of_bounds(i32 %k, i32 %n) #0 {
87 %var1 = alloca i32, align 4
88 %var2 = alloca i32, align 4
89 store i32 0, i32* %var1, align 4
90 store i32 0, i32* %var2, align 4
91 %cmp = icmp ne i32 %k, 0
92 br i1 %cmp, label %if, label %then
98 %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
99 %gep = getelementptr inbounds i32, i32* %ptr, i32 %n
100 %ret = load i32, i32* %gep, align 4
104 ; CHECK-LABEL: phi_after_gep_in_bounds:
105 ; CHECK-NOT: __stack_chk_guard
106 ; AIX-NOT: __ssp_canary_word
107 define i32 @phi_after_gep_in_bounds(i32 %k) #0 {
109 %var1 = alloca i32, align 4
110 %var2 = alloca i32, align 4
111 store i32 0, i32* %var1, align 4
112 store i32 0, i32* %var2, align 4
113 %cmp = icmp ne i32 %k, 0
114 br i1 %cmp, label %if, label %else
117 %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
121 %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
125 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
126 %ret = load i32, i32* %ptr, align 4
130 ; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_a:
131 ; CHECK: __stack_chk_guard
132 ; AIX: __ssp_canary_word
133 define i32 @phi_after_gep_constant_out_of_bounds_a(i32 %k) #0 {
135 %var1 = alloca i32, align 4
136 %var2 = alloca i32, align 4
137 store i32 0, i32* %var1, align 4
138 store i32 0, i32* %var2, align 4
139 %cmp = icmp ne i32 %k, 0
140 br i1 %cmp, label %if, label %else
143 %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
147 %gep2 = getelementptr inbounds i32, i32* %var2, i32 1
151 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
152 %ret = load i32, i32* %ptr, align 4
156 ; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_b:
157 ; CHECK: __stack_chk_guard
158 ; AIX: __ssp_canary_word
159 define i32 @phi_after_gep_constant_out_of_bounds_b(i32 %k) #0 {
161 %var1 = alloca i32, align 4
162 %var2 = alloca i32, align 4
163 store i32 0, i32* %var1, align 4
164 store i32 0, i32* %var2, align 4
165 %cmp = icmp ne i32 %k, 0
166 br i1 %cmp, label %if, label %else
169 %gep1 = getelementptr inbounds i32, i32* %var1, i32 1
173 %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
177 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
178 %ret = load i32, i32* %ptr, align 4
182 ; CHECK-LABEL: phi_different_types_a:
183 ; CHECK: __stack_chk_guard
184 ; AIX: __ssp_canary_word
185 define i64 @phi_different_types_a(i32 %k) #0 {
187 %var1 = alloca i64, align 4
188 %var2 = alloca i32, align 4
189 store i64 0, i64* %var1, align 4
190 store i32 0, i32* %var2, align 4
191 %cmp = icmp ne i32 %k, 0
192 br i1 %cmp, label %if, label %then
195 %bitcast = bitcast i32* %var2 to i64*
199 %ptr = phi i64* [ %var1, %entry ], [ %bitcast, %if ]
200 %ret = load i64, i64* %ptr, align 4
204 ; CHECK-LABEL: phi_different_types_b:
205 ; CHECK: __stack_chk_guard
206 ; AIX: __ssp_canary_word
207 define i64 @phi_different_types_b(i32 %k) #0 {
209 %var1 = alloca i32, align 4
210 %var2 = alloca i64, align 4
211 store i32 0, i32* %var1, align 4
212 store i64 0, i64* %var2, align 4
213 %cmp = icmp ne i32 %k, 0
214 br i1 %cmp, label %if, label %then
217 %bitcast = bitcast i32* %var1 to i64*
221 %ptr = phi i64* [ %var2, %entry ], [ %bitcast, %if ]
222 %ret = load i64, i64* %ptr, align 4
226 ; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_a:
227 ; CHECK: __stack_chk_guard
228 ; AIX: __ssp_canary_word
229 define i32 @phi_after_gep_nonconstant_out_of_bounds_a(i32 %k, i32 %n) #0 {
231 %var1 = alloca i32, align 4
232 %var2 = alloca i32, align 4
233 store i32 0, i32* %var1, align 4
234 store i32 0, i32* %var2, align 4
235 %cmp = icmp ne i32 %k, 0
236 br i1 %cmp, label %if, label %else
239 %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
243 %gep2 = getelementptr inbounds i32, i32* %var2, i32 %n
247 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
248 %ret = load i32, i32* %ptr, align 4
252 ; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_b:
253 ; CHECK: __stack_chk_guard
254 ; AIX: __ssp_canary_word
255 define i32 @phi_after_gep_nonconstant_out_of_bounds_b(i32 %k, i32 %n) #0 {
257 %var1 = alloca i32, align 4
258 %var2 = alloca i32, align 4
259 store i32 0, i32* %var1, align 4
260 store i32 0, i32* %var2, align 4
261 %cmp = icmp ne i32 %k, 0
262 br i1 %cmp, label %if, label %else
265 %gep1 = getelementptr inbounds i32, i32* %var1, i32 %n
269 %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
273 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
274 %ret = load i32, i32* %ptr, align 4
278 %struct.outer = type { %struct.inner, %struct.inner }
279 %struct.inner = type { i32, i32 }
281 ; CHECK-LABEL: struct_in_bounds:
282 ; CHECK-NOT: __stack_chk_guard
283 ; AIX-NOT: __ssp_canary_word
284 define void @struct_in_bounds() #0 {
285 %var = alloca %struct.outer, align 4
286 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1
287 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 1
288 store i32 0, i32* %innergep, align 4
292 ; CHECK-LABEL: struct_constant_out_of_bounds_a:
293 ; CHECK: __stack_chk_guard
294 ; AIX: __ssp_canary_word
295 define void @struct_constant_out_of_bounds_a() #0 {
296 %var = alloca %struct.outer, align 4
297 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 1, i32 0
298 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0
299 store i32 0, i32* %innergep, align 4
303 ; CHECK-LABEL: struct_constant_out_of_bounds_b:
304 ; Here the offset is out-of-bounds of the addressed struct.inner member, but
305 ; still within bounds of the outer struct so no stack guard is needed.
306 ; CHECK-NOT: __stack_chk_guard
307 ; AIX-NOT: __ssp_canary_word
308 define void @struct_constant_out_of_bounds_b() #0 {
309 %var = alloca %struct.outer, align 4
310 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0
311 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0
312 store i32 0, i32* %innergep, align 4
316 ; CHECK-LABEL: struct_constant_out_of_bounds_c:
317 ; Here we are out-of-bounds of both the inner and outer struct.
318 ; CHECK: __stack_chk_guard
319 ; AIX: __ssp_canary_word
320 define void @struct_constant_out_of_bounds_c() #0 {
321 %var = alloca %struct.outer, align 4
322 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1
323 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0
324 store i32 0, i32* %innergep, align 4
328 ; CHECK-LABEL: struct_nonconstant_out_of_bounds_a:
329 ; CHECK: __stack_chk_guard
330 ; AIX: __ssp_canary_word
331 define void @struct_nonconstant_out_of_bounds_a(i32 %n) #0 {
332 %var = alloca %struct.outer, align 4
333 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 %n, i32 0
334 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0
335 store i32 0, i32* %innergep, align 4
339 ; CHECK-LABEL: struct_nonconstant_out_of_bounds_b:
340 ; CHECK: __stack_chk_guard
341 ; AIX: __ssp_canary_word
342 define void @struct_nonconstant_out_of_bounds_b(i32 %n) #0 {
343 %var = alloca %struct.outer, align 4
344 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0
345 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 %n, i32 0
346 store i32 0, i32* %innergep, align 4
350 ; CHECK-LABEL: bitcast_smaller_load
351 ; CHECK-NOT: __stack_chk_guard
352 ; AIX-NOT: __ssp_canary_word
353 define i32 @bitcast_smaller_load() #0 {
354 %var = alloca i64, align 4
355 store i64 0, i64* %var, align 4
356 %bitcast = bitcast i64* %var to i32*
357 %ret = load i32, i32* %bitcast, align 4
361 ; CHECK-LABEL: bitcast_same_size_load
362 ; CHECK-NOT: __stack_chk_guard
363 ; AIX-NOT: __ssp_canary_word
364 define i32 @bitcast_same_size_load() #0 {
365 %var = alloca i64, align 4
366 store i64 0, i64* %var, align 4
367 %bitcast = bitcast i64* %var to %struct.inner*
368 %gep = getelementptr inbounds %struct.inner, %struct.inner* %bitcast, i32 0, i32 1
369 %ret = load i32, i32* %gep, align 4
373 ; CHECK-LABEL: bitcast_larger_load
374 ; CHECK: __stack_chk_guard
375 ; AIX: __ssp_canary_word
376 define i64 @bitcast_larger_load() #0 {
377 %var = alloca i32, align 4
378 store i32 0, i32* %var, align 4
379 %bitcast = bitcast i32* %var to i64*
380 %ret = load i64, i64* %bitcast, align 4
384 ; CHECK-LABEL: bitcast_larger_store
385 ; CHECK: __stack_chk_guard
386 ; AIX: __ssp_canary_word
387 define i32 @bitcast_larger_store() #0 {
388 %var = alloca i32, align 4
389 %bitcast = bitcast i32* %var to i64*
390 store i64 0, i64* %bitcast, align 4
391 %ret = load i32, i32* %var, align 4
395 ; CHECK-LABEL: bitcast_larger_cmpxchg
396 ; CHECK: __stack_chk_guard
397 ; AIX: __ssp_canary_word
398 define i64 @bitcast_larger_cmpxchg(i64 %desired, i64 %new) #0 {
399 %var = alloca i32, align 4
400 %bitcast = bitcast i32* %var to i64*
401 %pair = cmpxchg i64* %bitcast, i64 %desired, i64 %new seq_cst monotonic
402 %ret = extractvalue { i64, i1 } %pair, 0
406 ; CHECK-LABEL: bitcast_larger_atomic_rmw
407 ; CHECK: __stack_chk_guard
408 ; AIX: __ssp_canary_word
409 define i64 @bitcast_larger_atomic_rmw() #0 {
410 %var = alloca i32, align 4
411 %bitcast = bitcast i32* %var to i64*
412 %ret = atomicrmw add i64* %bitcast, i64 1 monotonic
416 %struct.packed = type <{ i16, i32 }>
418 ; CHECK-LABEL: bitcast_overlap
419 ; CHECK: __stack_chk_guard
420 ; AIX: __ssp_canary_word
421 define i32 @bitcast_overlap() #0 {
422 %var = alloca i32, align 4
423 %bitcast = bitcast i32* %var to %struct.packed*
424 %gep = getelementptr inbounds %struct.packed, %struct.packed* %bitcast, i32 0, i32 1
425 %ret = load i32, i32* %gep, align 2
429 %struct.multi_dimensional = type { [10 x [10 x i32]], i32 }
431 ; CHECK-LABEL: multi_dimensional_array
432 ; CHECK: __stack_chk_guard
433 ; AIX: __ssp_canary_word
434 define i32 @multi_dimensional_array() #0 {
435 %var = alloca %struct.multi_dimensional, align 4
436 %gep1 = getelementptr inbounds %struct.multi_dimensional, %struct.multi_dimensional* %var, i32 0, i32 0
437 %gep2 = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* %gep1, i32 0, i32 10
438 %gep3 = getelementptr inbounds [10 x i32], [10 x i32]* %gep2, i32 0, i32 5
439 %ret = load i32, i32* %gep3, align 4
443 attributes #0 = { sspstrong }