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, ptr %var, align 4
11 %ret = load i32, ptr %var, align 4
15 ; CHECK-LABEL: constant_out_of_bounds:
16 ; CHECK: __stack_chk_guard
17 ; AIX: __ssp_canary_word
18 define i32 @constant_out_of_bounds() #0 {
19 %var = alloca i32, align 4
20 store i32 0, ptr %var, align 4
21 %gep = getelementptr inbounds i32, ptr %var, i32 1
22 %ret = load i32, ptr %gep, align 4
26 ; CHECK-LABEL: nonconstant_out_of_bounds:
27 ; CHECK: __stack_chk_guard
28 ; AIX: __ssp_canary_word
29 define i32 @nonconstant_out_of_bounds(i32 %n) #0 {
30 %var = alloca i32, align 4
31 store i32 0, ptr %var, align 4
32 %gep = getelementptr inbounds i32, ptr %var, i32 %n
33 %ret = load i32, ptr %gep, align 4
37 ; CHECK-LABEL: phi_before_gep_in_bounds:
38 ; CHECK-NOT: __stack_chk_guard
39 ; AIX-NOT: __ssp_canary_word
40 define i32 @phi_before_gep_in_bounds(i32 %k) #0 {
42 %var1 = alloca i32, align 4
43 %var2 = alloca i32, align 4
44 store i32 0, ptr %var1, align 4
45 store i32 0, ptr %var2, align 4
46 %cmp = icmp ne i32 %k, 0
47 br i1 %cmp, label %if, label %then
53 %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
54 %ret = load i32, ptr %ptr, align 4
58 ; CHECK-LABEL: phi_before_gep_constant_out_of_bounds:
59 ; CHECK: __stack_chk_guard
60 ; AIX: __ssp_canary_word
61 define i32 @phi_before_gep_constant_out_of_bounds(i32 %k) #0 {
63 %var1 = alloca i32, align 4
64 %var2 = alloca i32, align 4
65 store i32 0, ptr %var1, align 4
66 store i32 0, ptr %var2, align 4
67 %cmp = icmp ne i32 %k, 0
68 br i1 %cmp, label %if, label %then
74 %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
75 %gep = getelementptr inbounds i32, ptr %ptr, i32 1
76 %ret = load i32, ptr %gep, align 4
80 ; CHECK-LABEL: phi_before_gep_nonconstant_out_of_bounds:
81 ; CHECK: __stack_chk_guard
82 ; AIX: __ssp_canary_word
83 define i32 @phi_before_gep_nonconstant_out_of_bounds(i32 %k, i32 %n) #0 {
85 %var1 = alloca i32, align 4
86 %var2 = alloca i32, align 4
87 store i32 0, ptr %var1, align 4
88 store i32 0, ptr %var2, align 4
89 %cmp = icmp ne i32 %k, 0
90 br i1 %cmp, label %if, label %then
96 %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
97 %gep = getelementptr inbounds i32, ptr %ptr, i32 %n
98 %ret = load i32, ptr %gep, align 4
102 ; CHECK-LABEL: phi_after_gep_in_bounds:
103 ; CHECK-NOT: __stack_chk_guard
104 ; AIX-NOT: __ssp_canary_word
105 define i32 @phi_after_gep_in_bounds(i32 %k) #0 {
107 %var1 = alloca i32, align 4
108 %var2 = alloca i32, align 4
109 store i32 0, ptr %var1, align 4
110 store i32 0, ptr %var2, align 4
111 %cmp = icmp ne i32 %k, 0
112 br i1 %cmp, label %if, label %else
121 %ptr = phi ptr [ %var1, %if ], [ %var2, %else ]
122 %ret = load i32, ptr %ptr, align 4
126 ; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_a:
127 ; CHECK: __stack_chk_guard
128 ; AIX: __ssp_canary_word
129 define i32 @phi_after_gep_constant_out_of_bounds_a(i32 %k) #0 {
131 %var1 = alloca i32, align 4
132 %var2 = alloca i32, align 4
133 store i32 0, ptr %var1, align 4
134 store i32 0, ptr %var2, align 4
135 %cmp = icmp ne i32 %k, 0
136 br i1 %cmp, label %if, label %else
142 %gep2 = getelementptr inbounds i32, ptr %var2, i32 1
146 %ptr = phi ptr [ %var1, %if ], [ %gep2, %else ]
147 %ret = load i32, ptr %ptr, align 4
151 ; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_b:
152 ; CHECK: __stack_chk_guard
153 ; AIX: __ssp_canary_word
154 define i32 @phi_after_gep_constant_out_of_bounds_b(i32 %k) #0 {
156 %var1 = alloca i32, align 4
157 %var2 = alloca i32, align 4
158 store i32 0, ptr %var1, align 4
159 store i32 0, ptr %var2, align 4
160 %cmp = icmp ne i32 %k, 0
161 br i1 %cmp, label %if, label %else
164 %gep1 = getelementptr inbounds i32, ptr %var1, i32 1
171 %ptr = phi ptr [ %gep1, %if ], [ %var2, %else ]
172 %ret = load i32, ptr %ptr, align 4
176 ; CHECK-LABEL: phi_different_types_a:
177 ; CHECK: __stack_chk_guard
178 ; AIX: __ssp_canary_word
179 define i64 @phi_different_types_a(i32 %k) #0 {
181 %var1 = alloca i64, align 4
182 %var2 = alloca i32, align 4
183 store i64 0, ptr %var1, align 4
184 store i32 0, ptr %var2, align 4
185 %cmp = icmp ne i32 %k, 0
186 br i1 %cmp, label %if, label %then
192 %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
193 %ret = load i64, ptr %ptr, align 4
197 ; CHECK-LABEL: phi_different_types_b:
198 ; CHECK: __stack_chk_guard
199 ; AIX: __ssp_canary_word
200 define i64 @phi_different_types_b(i32 %k) #0 {
202 %var1 = alloca i32, align 4
203 %var2 = alloca i64, align 4
204 store i32 0, ptr %var1, align 4
205 store i64 0, ptr %var2, align 4
206 %cmp = icmp ne i32 %k, 0
207 br i1 %cmp, label %if, label %then
213 %ptr = phi ptr [ %var2, %entry ], [ %var1, %if ]
214 %ret = load i64, ptr %ptr, align 4
218 ; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_a:
219 ; CHECK: __stack_chk_guard
220 ; AIX: __ssp_canary_word
221 define i32 @phi_after_gep_nonconstant_out_of_bounds_a(i32 %k, i32 %n) #0 {
223 %var1 = alloca i32, align 4
224 %var2 = alloca i32, align 4
225 store i32 0, ptr %var1, align 4
226 store i32 0, ptr %var2, align 4
227 %cmp = icmp ne i32 %k, 0
228 br i1 %cmp, label %if, label %else
234 %gep2 = getelementptr inbounds i32, ptr %var2, i32 %n
238 %ptr = phi ptr [ %var1, %if ], [ %gep2, %else ]
239 %ret = load i32, ptr %ptr, align 4
243 ; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_b:
244 ; CHECK: __stack_chk_guard
245 ; AIX: __ssp_canary_word
246 define i32 @phi_after_gep_nonconstant_out_of_bounds_b(i32 %k, i32 %n) #0 {
248 %var1 = alloca i32, align 4
249 %var2 = alloca i32, align 4
250 store i32 0, ptr %var1, align 4
251 store i32 0, ptr %var2, align 4
252 %cmp = icmp ne i32 %k, 0
253 br i1 %cmp, label %if, label %else
256 %gep1 = getelementptr inbounds i32, ptr %var1, i32 %n
263 %ptr = phi ptr [ %gep1, %if ], [ %var2, %else ]
264 %ret = load i32, ptr %ptr, align 4
268 %struct.outer = type { %struct.inner, %struct.inner }
269 %struct.inner = type { i32, i32 }
271 ; CHECK-LABEL: struct_in_bounds:
272 ; CHECK-NOT: __stack_chk_guard
273 ; AIX-NOT: __ssp_canary_word
274 define void @struct_in_bounds() #0 {
275 %var = alloca %struct.outer, align 4
276 %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 0, i32 1
277 %innergep = getelementptr inbounds %struct.inner, ptr %outergep, i32 0, i32 1
278 store i32 0, ptr %innergep, align 4
282 ; CHECK-LABEL: struct_constant_out_of_bounds_a:
283 ; CHECK: __stack_chk_guard
284 ; AIX: __ssp_canary_word
285 define void @struct_constant_out_of_bounds_a() #0 {
286 %var = alloca %struct.outer, align 4
287 %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 1, i32 0
288 store i32 0, ptr %outergep, align 4
292 ; CHECK-LABEL: struct_constant_out_of_bounds_b:
293 ; Here the offset is out-of-bounds of the addressed struct.inner member, but
294 ; still within bounds of the outer struct so no stack guard is needed.
295 ; CHECK-NOT: __stack_chk_guard
296 ; AIX-NOT: __ssp_canary_word
297 define void @struct_constant_out_of_bounds_b() #0 {
298 %var = alloca %struct.outer, align 4
299 %innergep = getelementptr inbounds %struct.inner, ptr %var, i32 1, i32 0
300 store i32 0, ptr %innergep, align 4
304 ; CHECK-LABEL: struct_constant_out_of_bounds_c:
305 ; Here we are out-of-bounds of both the inner and outer struct.
306 ; CHECK: __stack_chk_guard
307 ; AIX: __ssp_canary_word
308 define void @struct_constant_out_of_bounds_c() #0 {
309 %var = alloca %struct.outer, align 4
310 %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 0, i32 1
311 %innergep = getelementptr inbounds %struct.inner, ptr %outergep, i32 1, i32 0
312 store i32 0, ptr %innergep, align 4
316 ; CHECK-LABEL: struct_nonconstant_out_of_bounds_a:
317 ; CHECK: __stack_chk_guard
318 ; AIX: __ssp_canary_word
319 define void @struct_nonconstant_out_of_bounds_a(i32 %n) #0 {
320 %var = alloca %struct.outer, align 4
321 %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 %n, i32 0
322 store i32 0, ptr %outergep, align 4
326 ; CHECK-LABEL: struct_nonconstant_out_of_bounds_b:
327 ; CHECK: __stack_chk_guard
328 ; AIX: __ssp_canary_word
329 define void @struct_nonconstant_out_of_bounds_b(i32 %n) #0 {
330 %var = alloca %struct.outer, align 4
331 %innergep = getelementptr inbounds %struct.inner, ptr %var, i32 %n, i32 0
332 store i32 0, ptr %innergep, align 4
336 ; CHECK-LABEL: bitcast_smaller_load
337 ; CHECK-NOT: __stack_chk_guard
338 ; AIX-NOT: __ssp_canary_word
339 define i32 @bitcast_smaller_load() #0 {
340 %var = alloca i64, align 4
341 store i64 0, ptr %var, align 4
342 %ret = load i32, ptr %var, align 4
346 ; CHECK-LABEL: bitcast_same_size_load
347 ; CHECK-NOT: __stack_chk_guard
348 ; AIX-NOT: __ssp_canary_word
349 define i32 @bitcast_same_size_load() #0 {
350 %var = alloca i64, align 4
351 store i64 0, ptr %var, align 4
352 %gep = getelementptr inbounds %struct.inner, ptr %var, i32 0, i32 1
353 %ret = load i32, ptr %gep, align 4
357 ; CHECK-LABEL: bitcast_larger_load
358 ; CHECK: __stack_chk_guard
359 ; AIX: __ssp_canary_word
360 define i64 @bitcast_larger_load() #0 {
361 %var = alloca i32, align 4
362 store i32 0, ptr %var, align 4
363 %ret = load i64, ptr %var, align 4
367 ; CHECK-LABEL: bitcast_larger_store
368 ; CHECK: __stack_chk_guard
369 ; AIX: __ssp_canary_word
370 define i32 @bitcast_larger_store() #0 {
371 %var = alloca i32, align 4
372 store i64 0, ptr %var, align 4
373 %ret = load i32, ptr %var, align 4
377 ; CHECK-LABEL: bitcast_larger_cmpxchg
378 ; CHECK: __stack_chk_guard
379 ; AIX: __ssp_canary_word
380 define i64 @bitcast_larger_cmpxchg(i64 %desired, i64 %new) #0 {
381 %var = alloca i32, align 4
382 %pair = cmpxchg ptr %var, i64 %desired, i64 %new seq_cst monotonic
383 %ret = extractvalue { i64, i1 } %pair, 0
387 ; CHECK-LABEL: bitcast_larger_atomic_rmw
388 ; CHECK: __stack_chk_guard
389 ; AIX: __ssp_canary_word
390 define i64 @bitcast_larger_atomic_rmw() #0 {
391 %var = alloca i32, align 4
392 %ret = atomicrmw add ptr %var, i64 1 monotonic
396 %struct.packed = type <{ i16, i32 }>
398 ; CHECK-LABEL: bitcast_overlap
399 ; CHECK: __stack_chk_guard
400 ; AIX: __ssp_canary_word
401 define i32 @bitcast_overlap() #0 {
402 %var = alloca i32, align 4
403 %gep = getelementptr inbounds %struct.packed, ptr %var, i32 0, i32 1
404 %ret = load i32, ptr %gep, align 2
408 %struct.multi_dimensional = type { [10 x [10 x i32]], i32 }
410 ; CHECK-LABEL: multi_dimensional_array
411 ; CHECK: __stack_chk_guard
412 ; AIX: __ssp_canary_word
413 define i32 @multi_dimensional_array() #0 {
414 %var = alloca %struct.multi_dimensional, align 4
415 %gep2 = getelementptr inbounds [10 x [10 x i32]], ptr %var, i32 0, i32 10
416 %gep3 = getelementptr inbounds [10 x i32], ptr %gep2, i32 0, i32 5
417 %ret = load i32, ptr %gep3, align 4
421 attributes #0 = { sspstrong }