1; RUN: llc -mtriple=i686 -O0 < %s | FileCheck %s
2; RUN: llc -mtriple=x86_64 -O0 < %s | FileCheck %s
3
4; CHECK-LABEL: in_bounds:
5; CHECK-NOT: __stack_chk_guard
6define i32 @in_bounds() #0 {
7  %var = alloca i32, align 4
8  store i32 0, i32* %var, align 4
9  %gep = getelementptr inbounds i32, i32* %var, i32 0
10  %ret = load i32, i32* %gep, align 4
11  ret i32 %ret
12}
13
14; CHECK-LABEL: constant_out_of_bounds:
15; CHECK: __stack_chk_guard
16define i32 @constant_out_of_bounds() #0 {
17  %var = alloca i32, align 4
18  store i32 0, i32* %var, align 4
19  %gep = getelementptr inbounds i32, i32* %var, i32 1
20  %ret = load i32, i32* %gep, align 4
21  ret i32 %ret
22}
23
24; CHECK-LABEL: nonconstant_out_of_bounds:
25; CHECK: __stack_chk_guard
26define i32 @nonconstant_out_of_bounds(i32 %n) #0 {
27  %var = alloca i32, align 4
28  store i32 0, i32* %var, align 4
29  %gep = getelementptr inbounds i32, i32* %var, i32 %n
30  %ret = load i32, i32* %gep, align 4
31  ret i32 %ret
32}
33
34; CHECK-LABEL: phi_before_gep_in_bounds:
35; CHECK-NOT: __stack_chk_guard
36define i32 @phi_before_gep_in_bounds(i32 %k) #0 {
37entry:
38  %var1 = alloca i32, align 4
39  %var2 = alloca i32, align 4
40  store i32 0, i32* %var1, align 4
41  store i32 0, i32* %var2, align 4
42  %cmp = icmp ne i32 %k, 0
43  br i1 %cmp, label %if, label %then
44
45if:
46  br label %then
47
48then:
49  %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
50  %gep = getelementptr inbounds i32, i32* %ptr, i32 0
51  %ret = load i32, i32* %gep, align 4
52  ret i32 %ret
53}
54
55; CHECK-LABEL: phi_before_gep_constant_out_of_bounds:
56; CHECK: __stack_chk_guard
57define i32 @phi_before_gep_constant_out_of_bounds(i32 %k) #0 {
58entry:
59  %var1 = alloca i32, align 4
60  %var2 = alloca i32, align 4
61  store i32 0, i32* %var1, align 4
62  store i32 0, i32* %var2, align 4
63  %cmp = icmp ne i32 %k, 0
64  br i1 %cmp, label %if, label %then
65
66if:
67  br label %then
68
69then:
70  %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
71  %gep = getelementptr inbounds i32, i32* %ptr, i32 1
72  %ret = load i32, i32* %gep, align 4
73  ret i32 %ret
74}
75
76; CHECK-LABEL: phi_before_gep_nonconstant_out_of_bounds:
77; CHECK: __stack_chk_guard
78define i32 @phi_before_gep_nonconstant_out_of_bounds(i32 %k, i32 %n) #0 {
79entry:
80  %var1 = alloca i32, align 4
81  %var2 = alloca i32, align 4
82  store i32 0, i32* %var1, align 4
83  store i32 0, i32* %var2, align 4
84  %cmp = icmp ne i32 %k, 0
85  br i1 %cmp, label %if, label %then
86
87if:
88  br label %then
89
90then:
91  %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
92  %gep = getelementptr inbounds i32, i32* %ptr, i32 %n
93  %ret = load i32, i32* %gep, align 4
94  ret i32 %ret
95}
96
97; CHECK-LABEL: phi_after_gep_in_bounds:
98; CHECK-NOT: __stack_chk_guard
99define i32 @phi_after_gep_in_bounds(i32 %k) #0 {
100entry:
101  %var1 = alloca i32, align 4
102  %var2 = alloca i32, align 4
103  store i32 0, i32* %var1, align 4
104  store i32 0, i32* %var2, align 4
105  %cmp = icmp ne i32 %k, 0
106  br i1 %cmp, label %if, label %else
107
108if:
109  %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
110  br label %then
111
112else:
113  %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
114  br label %then
115
116then:
117  %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
118  %ret = load i32, i32* %ptr, align 4
119  ret i32 %ret
120}
121
122; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_a:
123; CHECK: __stack_chk_guard
124define i32 @phi_after_gep_constant_out_of_bounds_a(i32 %k) #0 {
125entry:
126  %var1 = alloca i32, align 4
127  %var2 = alloca i32, align 4
128  store i32 0, i32* %var1, align 4
129  store i32 0, i32* %var2, align 4
130  %cmp = icmp ne i32 %k, 0
131  br i1 %cmp, label %if, label %else
132
133if:
134  %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
135  br label %then
136
137else:
138  %gep2 = getelementptr inbounds i32, i32* %var2, i32 1
139  br label %then
140
141then:
142  %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
143  %ret = load i32, i32* %ptr, align 4
144  ret i32 %ret
145}
146
147; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_b:
148; CHECK: __stack_chk_guard
149define i32 @phi_after_gep_constant_out_of_bounds_b(i32 %k) #0 {
150entry:
151  %var1 = alloca i32, align 4
152  %var2 = alloca i32, align 4
153  store i32 0, i32* %var1, align 4
154  store i32 0, i32* %var2, align 4
155  %cmp = icmp ne i32 %k, 0
156  br i1 %cmp, label %if, label %else
157
158if:
159  %gep1 = getelementptr inbounds i32, i32* %var1, i32 1
160  br label %then
161
162else:
163  %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
164  br label %then
165
166then:
167  %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
168  %ret = load i32, i32* %ptr, align 4
169  ret i32 %ret
170}
171
172; CHECK-LABEL: phi_different_types_a:
173; CHECK: __stack_chk_guard
174define i64 @phi_different_types_a(i32 %k) #0 {
175entry:
176  %var1 = alloca i64, align 4
177  %var2 = alloca i32, align 4
178  store i64 0, i64* %var1, align 4
179  store i32 0, i32* %var2, align 4
180  %cmp = icmp ne i32 %k, 0
181  br i1 %cmp, label %if, label %then
182
183if:
184  %bitcast = bitcast i32* %var2 to i64*
185  br label %then
186
187then:
188  %ptr = phi i64* [ %var1, %entry ], [ %bitcast, %if ]
189  %ret = load i64, i64* %ptr, align 4
190  ret i64 %ret
191}
192
193; CHECK-LABEL: phi_different_types_b:
194; CHECK: __stack_chk_guard
195define i64 @phi_different_types_b(i32 %k) #0 {
196entry:
197  %var1 = alloca i32, align 4
198  %var2 = alloca i64, align 4
199  store i32 0, i32* %var1, align 4
200  store i64 0, i64* %var2, align 4
201  %cmp = icmp ne i32 %k, 0
202  br i1 %cmp, label %if, label %then
203
204if:
205  %bitcast = bitcast i32* %var1 to i64*
206  br label %then
207
208then:
209  %ptr = phi i64* [ %var2, %entry ], [ %bitcast, %if ]
210  %ret = load i64, i64* %ptr, align 4
211  ret i64 %ret
212}
213
214; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_a:
215; CHECK: __stack_chk_guard
216define i32 @phi_after_gep_nonconstant_out_of_bounds_a(i32 %k, i32 %n) #0 {
217entry:
218  %var1 = alloca i32, align 4
219  %var2 = alloca i32, align 4
220  store i32 0, i32* %var1, align 4
221  store i32 0, i32* %var2, align 4
222  %cmp = icmp ne i32 %k, 0
223  br i1 %cmp, label %if, label %else
224
225if:
226  %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
227  br label %then
228
229else:
230  %gep2 = getelementptr inbounds i32, i32* %var2, i32 %n
231  br label %then
232
233then:
234  %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
235  %ret = load i32, i32* %ptr, align 4
236  ret i32 %ret
237}
238
239; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_b:
240; CHECK: __stack_chk_guard
241define i32 @phi_after_gep_nonconstant_out_of_bounds_b(i32 %k, i32 %n) #0 {
242entry:
243  %var1 = alloca i32, align 4
244  %var2 = alloca i32, align 4
245  store i32 0, i32* %var1, align 4
246  store i32 0, i32* %var2, align 4
247  %cmp = icmp ne i32 %k, 0
248  br i1 %cmp, label %if, label %else
249
250if:
251  %gep1 = getelementptr inbounds i32, i32* %var1, i32 %n
252  br label %then
253
254else:
255  %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
256  br label %then
257
258then:
259  %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
260  %ret = load i32, i32* %ptr, align 4
261  ret i32 %ret
262}
263
264%struct.outer = type { %struct.inner, %struct.inner }
265%struct.inner = type { i32, i32 }
266
267; CHECK-LABEL: struct_in_bounds:
268; CHECK-NOT: __stack_chk_guard
269define void @struct_in_bounds() #0 {
270  %var = alloca %struct.outer, align 4
271  %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1
272  %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 1
273  store i32 0, i32* %innergep, align 4
274  ret void
275}
276
277; CHECK-LABEL: struct_constant_out_of_bounds_a:
278; CHECK: __stack_chk_guard
279define void @struct_constant_out_of_bounds_a() #0 {
280  %var = alloca %struct.outer, align 4
281  %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 1, i32 0
282  %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0
283  store i32 0, i32* %innergep, align 4
284  ret void
285}
286
287; CHECK-LABEL: struct_constant_out_of_bounds_b:
288; Here the offset is out-of-bounds of the addressed struct.inner member, but
289; still within bounds of the outer struct so no stack guard is needed.
290; CHECK-NOT: __stack_chk_guard
291define void @struct_constant_out_of_bounds_b() #0 {
292  %var = alloca %struct.outer, align 4
293  %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0
294  %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0
295  store i32 0, i32* %innergep, align 4
296  ret void
297}
298
299; CHECK-LABEL: struct_constant_out_of_bounds_c:
300; Here we are out-of-bounds of both the inner and outer struct.
301; CHECK: __stack_chk_guard
302define void @struct_constant_out_of_bounds_c() #0 {
303  %var = alloca %struct.outer, align 4
304  %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1
305  %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0
306  store i32 0, i32* %innergep, align 4
307  ret void
308}
309
310; CHECK-LABEL: struct_nonconstant_out_of_bounds_a:
311; CHECK: __stack_chk_guard
312define void @struct_nonconstant_out_of_bounds_a(i32 %n) #0 {
313  %var = alloca %struct.outer, align 4
314  %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 %n, i32 0
315  %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0
316  store i32 0, i32* %innergep, align 4
317  ret void
318}
319
320; CHECK-LABEL: struct_nonconstant_out_of_bounds_b:
321; CHECK: __stack_chk_guard
322define void @struct_nonconstant_out_of_bounds_b(i32 %n) #0 {
323  %var = alloca %struct.outer, align 4
324  %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0
325  %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 %n, i32 0
326  store i32 0, i32* %innergep, align 4
327  ret void
328}
329
330; CHECK-LABEL: bitcast_smaller_load
331; CHECK-NOT: __stack_chk_guard
332define i32 @bitcast_smaller_load() #0 {
333  %var = alloca i64, align 4
334  store i64 0, i64* %var, align 4
335  %bitcast = bitcast i64* %var to i32*
336  %ret = load i32, i32* %bitcast, align 4
337  ret i32 %ret
338}
339
340; CHECK-LABEL: bitcast_same_size_load
341; CHECK-NOT: __stack_chk_guard
342define i32 @bitcast_same_size_load() #0 {
343  %var = alloca i64, align 4
344  store i64 0, i64* %var, align 4
345  %bitcast = bitcast i64* %var to %struct.inner*
346  %gep = getelementptr inbounds %struct.inner, %struct.inner* %bitcast, i32 0, i32 1
347  %ret = load i32, i32* %gep, align 4
348  ret i32 %ret
349}
350
351; CHECK-LABEL: bitcast_larger_load
352; CHECK: __stack_chk_guard
353define i64 @bitcast_larger_load() #0 {
354  %var = alloca i32, align 4
355  store i32 0, i32* %var, align 4
356  %bitcast = bitcast i32* %var to i64*
357  %ret = load i64, i64* %bitcast, align 4
358  ret i64 %ret
359}
360
361; CHECK-LABEL: bitcast_larger_store
362; CHECK: __stack_chk_guard
363define i32 @bitcast_larger_store() #0 {
364  %var = alloca i32, align 4
365  %bitcast = bitcast i32* %var to i64*
366  store i64 0, i64* %bitcast, align 4
367  %ret = load i32, i32* %var, align 4
368  ret i32 %ret
369}
370
371; CHECK-LABEL: bitcast_larger_cmpxchg
372; CHECK: __stack_chk_guard
373define i64 @bitcast_larger_cmpxchg(i64 %desired, i64 %new) #0 {
374  %var = alloca i32, align 4
375  %bitcast = bitcast i32* %var to i64*
376  %pair = cmpxchg i64* %bitcast, i64 %desired, i64 %new seq_cst monotonic
377  %ret = extractvalue { i64, i1 } %pair, 0
378  ret i64 %ret
379}
380
381; CHECK-LABEL: bitcast_larger_atomic_rmw
382; CHECK: __stack_chk_guard
383define i64 @bitcast_larger_atomic_rmw() #0 {
384  %var = alloca i32, align 4
385  %bitcast = bitcast i32* %var to i64*
386  %ret = atomicrmw add i64* %bitcast, i64 1 monotonic
387  ret i64 %ret
388}
389
390%struct.packed = type <{ i16, i32 }>
391
392; CHECK-LABEL: bitcast_overlap
393; CHECK: __stack_chk_guard
394define i32 @bitcast_overlap() #0 {
395  %var = alloca i32, align 4
396  %bitcast = bitcast i32* %var to %struct.packed*
397  %gep = getelementptr inbounds %struct.packed, %struct.packed* %bitcast, i32 0, i32 1
398  %ret = load i32, i32* %gep, align 2
399  ret i32 %ret
400}
401
402%struct.multi_dimensional = type { [10 x [10 x i32]], i32 }
403
404; CHECK-LABEL: multi_dimensional_array
405; CHECK: __stack_chk_guard
406define i32 @multi_dimensional_array() #0 {
407  %var = alloca %struct.multi_dimensional, align 4
408  %gep1 = getelementptr inbounds %struct.multi_dimensional, %struct.multi_dimensional* %var, i32 0, i32 0
409  %gep2 = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* %gep1, i32 0, i32 10
410  %gep3 = getelementptr inbounds [10 x i32], [10 x i32]* %gep2, i32 0, i32 5
411  %ret = load i32, i32* %gep3, align 4
412  ret i32 %ret
413}
414
415attributes #0 = { sspstrong }
416