1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG
3 ; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG
5 define i32 @alloca_used_in_call(ptr %data, i64 %n) {
6 ; CHECK-LABEL: @alloca_used_in_call(
8 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
9 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
10 ; CHECK-NEXT: br label [[LOOP:%.*]]
12 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
13 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
14 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
15 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
16 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
17 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
18 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
19 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
20 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
22 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
23 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
24 ; CHECK-NEXT: ret i32 [[I1]]
27 %retval = alloca i32, align 4
28 store i32 0, ptr %retval, align 4
32 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
33 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
34 %ld = load i32, ptr %arrayidx, align 4
35 %rdx = load i32, ptr %retval, align 4
36 %rdx.inc = add nsw i32 %rdx, %ld
37 store i32 %rdx.inc, ptr %retval, align 4
38 %indvars.iv.next = add nsw i64 %indvars.iv, 1
39 %exitcond = icmp ne i64 %indvars.iv.next, %n
40 br i1 %exitcond, label %loop, label %exit
43 %i0 = call i32 @user_of_alloca(ptr %retval)
44 %i1 = load i32, ptr %retval, align 4
48 define i32 @alloca_captured_in_call(ptr %data, i64 %n) {
49 ; CHECK-LABEL: @alloca_captured_in_call(
51 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
52 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
53 ; CHECK-NEXT: br label [[LOOP:%.*]]
55 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
56 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
57 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
58 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
59 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
60 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
61 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
62 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
63 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
65 ; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr [[RETVAL]])
66 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
67 ; CHECK-NEXT: ret i32 [[I1]]
70 %retval = alloca i32, align 4
71 store i32 0, ptr %retval, align 4
75 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
76 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
77 %ld = load i32, ptr %arrayidx, align 4
78 %rdx = load i32, ptr %retval, align 4
79 %rdx.inc = add nsw i32 %rdx, %ld
80 store i32 %rdx.inc, ptr %retval, align 4
81 %indvars.iv.next = add nsw i64 %indvars.iv, 1
82 %exitcond = icmp ne i64 %indvars.iv.next, %n
83 br i1 %exitcond, label %loop, label %exit
86 %i0 = call i32 @capture_of_alloca(ptr %retval)
87 %i1 = load i32, ptr %retval, align 4
91 define i32 @alloca_not_captured_as_per_operand_attr(ptr %data, i64 %n) {
92 ; CHECK-LABEL: @alloca_not_captured_as_per_operand_attr(
94 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
95 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
96 ; CHECK-NEXT: br label [[LOOP:%.*]]
98 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
99 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
100 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
101 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
102 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
103 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
104 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
105 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
106 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
108 ; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr nocapture [[RETVAL]])
109 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
110 ; CHECK-NEXT: ret i32 [[I1]]
113 %retval = alloca i32, align 4
114 store i32 0, ptr %retval, align 4
118 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
119 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
120 %ld = load i32, ptr %arrayidx, align 4
121 %rdx = load i32, ptr %retval, align 4
122 %rdx.inc = add nsw i32 %rdx, %ld
123 store i32 %rdx.inc, ptr %retval, align 4
124 %indvars.iv.next = add nsw i64 %indvars.iv, 1
125 %exitcond = icmp ne i64 %indvars.iv.next, %n
126 br i1 %exitcond, label %loop, label %exit
129 %i0 = call i32 @capture_of_alloca(ptr nocapture %retval)
130 %i1 = load i32, ptr %retval, align 4
134 define i32 @alloca_not_captured_and_readonly_as_per_operand_attr(ptr %data, i64 %n) {
135 ; CHECK-LABEL: @alloca_not_captured_and_readonly_as_per_operand_attr(
137 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
138 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
139 ; CHECK-NEXT: br label [[LOOP:%.*]]
141 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
142 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
143 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
144 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
145 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
146 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
147 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
148 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
149 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
151 ; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr nocapture readonly [[RETVAL]])
152 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
153 ; CHECK-NEXT: ret i32 [[I1]]
156 %retval = alloca i32, align 4
157 store i32 0, ptr %retval, align 4
161 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
162 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
163 %ld = load i32, ptr %arrayidx, align 4
164 %rdx = load i32, ptr %retval, align 4
165 %rdx.inc = add nsw i32 %rdx, %ld
166 store i32 %rdx.inc, ptr %retval, align 4
167 %indvars.iv.next = add nsw i64 %indvars.iv, 1
168 %exitcond = icmp ne i64 %indvars.iv.next, %n
169 br i1 %exitcond, label %loop, label %exit
172 %i0 = call i32 @capture_of_alloca(ptr nocapture readonly %retval)
173 %i1 = load i32, ptr %retval, align 4
177 define i32 @alloca_not_captured_as_per_operand_attr_and_readonly_as_per_callbase_attr(ptr %data, i64 %n) {
178 ; CHECK-LABEL: @alloca_not_captured_as_per_operand_attr_and_readonly_as_per_callbase_attr(
180 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
181 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
182 ; CHECK-NEXT: br label [[LOOP:%.*]]
184 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
185 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
186 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
187 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
188 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
189 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
190 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
191 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
192 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
194 ; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr nocapture [[RETVAL]]) #[[ATTR2:[0-9]+]]
195 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
196 ; CHECK-NEXT: ret i32 [[I1]]
199 %retval = alloca i32, align 4
200 store i32 0, ptr %retval, align 4
204 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
205 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
206 %ld = load i32, ptr %arrayidx, align 4
207 %rdx = load i32, ptr %retval, align 4
208 %rdx.inc = add nsw i32 %rdx, %ld
209 store i32 %rdx.inc, ptr %retval, align 4
210 %indvars.iv.next = add nsw i64 %indvars.iv, 1
211 %exitcond = icmp ne i64 %indvars.iv.next, %n
212 br i1 %exitcond, label %loop, label %exit
215 %i0 = call i32 @capture_of_alloca(ptr nocapture %retval) readonly
216 %i1 = load i32, ptr %retval, align 4
220 define i32 @alloca_not_readonly_as_per_operand_attr(ptr %data, i64 %n) {
221 ; CHECK-LABEL: @alloca_not_readonly_as_per_operand_attr(
223 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
224 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
225 ; CHECK-NEXT: br label [[LOOP:%.*]]
227 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
228 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
229 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
230 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
231 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
232 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
233 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
234 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
235 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
237 ; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr readonly [[RETVAL]])
238 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
239 ; CHECK-NEXT: ret i32 [[I1]]
242 %retval = alloca i32, align 4
243 store i32 0, ptr %retval, align 4
247 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
248 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
249 %ld = load i32, ptr %arrayidx, align 4
250 %rdx = load i32, ptr %retval, align 4
251 %rdx.inc = add nsw i32 %rdx, %ld
252 store i32 %rdx.inc, ptr %retval, align 4
253 %indvars.iv.next = add nsw i64 %indvars.iv, 1
254 %exitcond = icmp ne i64 %indvars.iv.next, %n
255 br i1 %exitcond, label %loop, label %exit
258 %i0 = call i32 @capture_of_alloca(ptr readonly %retval)
259 %i1 = load i32, ptr %retval, align 4
263 define i32 @alloca_with_gep_used_in_call(ptr %data, i64 %n) {
264 ; CHECK-LABEL: @alloca_with_gep_used_in_call(
266 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
267 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
268 ; CHECK-NEXT: br label [[LOOP:%.*]]
270 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
271 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
272 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
273 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
274 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
275 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
276 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
277 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
278 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
280 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
281 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
282 ; CHECK-NEXT: ret i32 [[I1]]
285 %retval = alloca i32, align 4
286 store i32 0, ptr %retval, align 4
290 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
291 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
292 %ld = load i32, ptr %arrayidx, align 4
293 %rdx = load i32, ptr %retval, align 4
294 %rdx.inc = add nsw i32 %rdx, %ld
295 store i32 %rdx.inc, ptr %retval, align 4
296 %indvars.iv.next = add nsw i64 %indvars.iv, 1
297 %exitcond = icmp ne i64 %indvars.iv.next, %n
298 br i1 %exitcond, label %loop, label %exit
301 %i0 = call i32 @user_of_alloca(ptr %retval)
302 %i1 = load i32, ptr %retval, align 4
306 define i32 @alloca_captured_second_arg(ptr %data, i64 %n) {
307 ; CHECK-LABEL: @alloca_captured_second_arg(
309 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
310 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
311 ; CHECK-NEXT: br label [[LOOP:%.*]]
313 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
314 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
315 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
316 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
317 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
318 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
319 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
320 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
321 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
323 ; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL]])
324 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
325 ; CHECK-NEXT: ret i32 [[I1]]
328 %retval = alloca i32, align 4
329 store i32 0, ptr %retval, align 4
333 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
334 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
335 %ld = load i32, ptr %arrayidx, align 4
336 %rdx = load i32, ptr %retval, align 4
337 %rdx.inc = add nsw i32 %rdx, %ld
338 store i32 %rdx.inc, ptr %retval, align 4
339 %indvars.iv.next = add nsw i64 %indvars.iv, 1
340 %exitcond = icmp ne i64 %indvars.iv.next, %n
341 br i1 %exitcond, label %loop, label %exit
344 %i0 = call i32 @capture_with_multiple_args(ptr %retval, ptr %retval)
345 %i1 = load i32, ptr %retval, align 4
349 define i32 @alloca_used_in_maybe_throwing_call(ptr %data, i64 %n) personality ptr @__gxx_personality_v0 {
350 ; CHECK-LABEL: @alloca_used_in_maybe_throwing_call(
352 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
353 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
354 ; CHECK-NEXT: br label [[LOOP:%.*]]
356 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
357 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
358 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
359 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
360 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
361 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
362 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
363 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
364 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
366 ; CHECK-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(ptr [[RETVAL]])
367 ; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[UW:%.*]]
369 ; CHECK-NEXT: br label [[END:%.*]]
371 ; CHECK-NEXT: [[I1:%.*]] = landingpad { ptr, i32 }
372 ; CHECK-NEXT: catch ptr null
373 ; CHECK-NEXT: br label [[END]]
375 ; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
376 ; CHECK-NEXT: ret i32 [[I2]]
379 %retval = alloca i32, align 4
380 store i32 0, ptr %retval, align 4
384 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
385 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
386 %ld = load i32, ptr %arrayidx, align 4
387 %rdx = load i32, ptr %retval, align 4
388 %rdx.inc = add nsw i32 %rdx, %ld
389 store i32 %rdx.inc, ptr %retval, align 4
390 %indvars.iv.next = add nsw i64 %indvars.iv, 1
391 %exitcond = icmp ne i64 %indvars.iv.next, %n
392 br i1 %exitcond, label %loop, label %exit
395 %i0 = invoke i32 @user_of_alloca(ptr %retval) to label %cont unwind label %uw
401 %i1 = landingpad { ptr, i32 } catch ptr null
405 %i2 = load i32, ptr %retval, align 4
409 define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(ptr %data, i64 %n) personality ptr @__gxx_personality_v0 {
410 ; CHECK-LABEL: @alloca_used_in_maybe_throwing_call_with_same_dests(
412 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
413 ; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
414 ; CHECK-NEXT: br label [[LOOP:%.*]]
416 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
417 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
418 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
419 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
420 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
421 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
422 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
423 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
424 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
426 ; CHECK-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(ptr [[RETVAL]])
427 ; CHECK-NEXT: to label [[END:%.*]] unwind label [[UW:%.*]]
429 ; CHECK-NEXT: [[I1:%.*]] = landingpad { ptr, i32 }
430 ; CHECK-NEXT: catch ptr null
431 ; CHECK-NEXT: br label [[END]]
433 ; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
434 ; CHECK-NEXT: ret i32 [[I2]]
437 %retval = alloca i32, align 4
438 store i32 0, ptr %retval, align 4
442 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
443 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
444 %ld = load i32, ptr %arrayidx, align 4
445 %rdx = load i32, ptr %retval, align 4
446 %rdx.inc = add nsw i32 %rdx, %ld
447 store i32 %rdx.inc, ptr %retval, align 4
448 %indvars.iv.next = add nsw i64 %indvars.iv, 1
449 %exitcond = icmp ne i64 %indvars.iv.next, %n
450 br i1 %exitcond, label %loop, label %exit
453 %i0 = invoke i32 @user_of_alloca(ptr %retval) to label %end unwind label %uw
456 %i1 = landingpad { ptr, i32 } catch ptr null
460 %i2 = load i32, ptr %retval, align 4
464 define [2 x i32] @part_of_alloca_used_in_call(ptr %data, i64 %n) {
465 ; CHECK-LABEL: @part_of_alloca_used_in_call(
467 ; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
468 ; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
469 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4
470 ; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
471 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4
472 ; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
473 ; CHECK-NEXT: br label [[LOOP:%.*]]
475 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
476 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
477 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
478 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
479 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
480 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
481 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
482 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
483 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
485 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
486 ; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
487 ; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
488 ; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
489 ; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
490 ; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
491 ; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
492 ; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
495 %retval.full = alloca [2 x i32], align 4
496 store [2 x i32] zeroinitializer, ptr %retval.full, align 4
497 %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
501 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
502 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
503 %ld = load i32, ptr %arrayidx, align 4
504 %rdx = load i32, ptr %retval, align 4
505 %rdx.inc = add nsw i32 %rdx, %ld
506 store i32 %rdx.inc, ptr %retval, align 4
507 %indvars.iv.next = add nsw i64 %indvars.iv, 1
508 %exitcond = icmp ne i64 %indvars.iv.next, %n
509 br i1 %exitcond, label %loop, label %exit
512 %i0 = call i32 @user_of_alloca(ptr %retval)
513 %i1 = load [2 x i32], ptr %retval.full, align 4
517 define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args(ptr %data, i64 %n) {
518 ; CHECK-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args(
520 ; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
521 ; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
522 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4
523 ; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
524 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4
525 ; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
526 ; CHECK-NEXT: br label [[LOOP:%.*]]
528 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
529 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
530 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
531 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
532 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
533 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
534 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
535 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
536 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
538 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
539 ; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
540 ; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
541 ; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
542 ; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
543 ; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
544 ; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
545 ; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
548 %retval.full = alloca [2 x i32], align 4
549 store [2 x i32] zeroinitializer, ptr %retval.full, align 4
550 %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
554 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
555 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
556 %ld = load i32, ptr %arrayidx, align 4
557 %rdx = load i32, ptr %retval, align 4
558 %rdx.inc = add nsw i32 %rdx, %ld
559 store i32 %rdx.inc, ptr %retval, align 4
560 %indvars.iv.next = add nsw i64 %indvars.iv, 1
561 %exitcond = icmp ne i64 %indvars.iv.next, %n
562 br i1 %exitcond, label %loop, label %exit
565 %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
566 %i1 = load [2 x i32], ptr %retval.full, align 4
570 define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_before_call(ptr %data, i64 %n) {
571 ; CHECK-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_before_call(
573 ; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
574 ; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
575 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4
576 ; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
577 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4
578 ; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
579 ; CHECK-NEXT: br label [[LOOP:%.*]]
581 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
582 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
583 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
584 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
585 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
586 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
587 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
588 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
589 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
591 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[RETVAL_FULL]], ptr [[RETVAL]], i32 4, i1 false)
592 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
593 ; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
594 ; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
595 ; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
596 ; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
597 ; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
598 ; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
599 ; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
602 %retval.full = alloca [2 x i32], align 4
603 store [2 x i32] zeroinitializer, ptr %retval.full, align 4
604 %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
608 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
609 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
610 %ld = load i32, ptr %arrayidx, align 4
611 %rdx = load i32, ptr %retval, align 4
612 %rdx.inc = add nsw i32 %rdx, %ld
613 store i32 %rdx.inc, ptr %retval, align 4
614 %indvars.iv.next = add nsw i64 %indvars.iv, 1
615 %exitcond = icmp ne i64 %indvars.iv.next, %n
616 br i1 %exitcond, label %loop, label %exit
619 call void @llvm.memcpy.p0.p0.i32(ptr %retval.full, ptr %retval, i32 4, i1 false)
620 %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
621 %i1 = load [2 x i32], ptr %retval.full, align 4
625 define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_after_call(ptr %data, i64 %n) {
626 ; CHECK-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_after_call(
628 ; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
629 ; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
630 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4
631 ; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
632 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4
633 ; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
634 ; CHECK-NEXT: br label [[LOOP:%.*]]
636 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
637 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
638 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
639 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
640 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
641 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
642 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
643 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
644 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
646 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
647 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[RETVAL_FULL]], ptr [[RETVAL]], i32 4, i1 false)
648 ; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
649 ; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
650 ; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
651 ; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
652 ; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
653 ; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
654 ; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
657 %retval.full = alloca [2 x i32], align 4
658 store [2 x i32] zeroinitializer, ptr %retval.full, align 4
659 %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
663 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
664 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
665 %ld = load i32, ptr %arrayidx, align 4
666 %rdx = load i32, ptr %retval, align 4
667 %rdx.inc = add nsw i32 %rdx, %ld
668 store i32 %rdx.inc, ptr %retval, align 4
669 %indvars.iv.next = add nsw i64 %indvars.iv, 1
670 %exitcond = icmp ne i64 %indvars.iv.next, %n
671 br i1 %exitcond, label %loop, label %exit
674 %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
675 call void @llvm.memcpy.p0.p0.i32(ptr %retval.full, ptr %retval, i32 4, i1 false)
676 %i1 = load [2 x i32], ptr %retval.full, align 4
680 define [2 x i32] @part_of_alloca_used_in_call_with_multiple_args(ptr %data, i64 %n) {
681 ; CHECK-LABEL: @part_of_alloca_used_in_call_with_multiple_args(
683 ; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
684 ; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
685 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4
686 ; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
687 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4
688 ; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
689 ; CHECK-NEXT: br label [[LOOP:%.*]]
691 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
692 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
693 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
694 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
695 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
696 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
697 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
698 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
699 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
701 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL]])
702 ; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
703 ; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
704 ; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
705 ; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
706 ; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
707 ; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
708 ; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
711 %retval.full = alloca [2 x i32], align 4
712 store [2 x i32] zeroinitializer, ptr %retval.full, align 4
713 %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
717 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
718 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
719 %ld = load i32, ptr %arrayidx, align 4
720 %rdx = load i32, ptr %retval, align 4
721 %rdx.inc = add nsw i32 %rdx, %ld
722 store i32 %rdx.inc, ptr %retval, align 4
723 %indvars.iv.next = add nsw i64 %indvars.iv, 1
724 %exitcond = icmp ne i64 %indvars.iv.next, %n
725 br i1 %exitcond, label %loop, label %exit
728 %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval)
729 %i1 = load [2 x i32], ptr %retval.full, align 4
733 define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(ptr %data, i64 %n) {
734 ; CHECK-LABEL: @all_parts_of_alloca_used_in_calls_with_multiple_args(
736 ; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
737 ; CHECK-NEXT: [[SOME_ANOTHER_ALLOCA_FULL:%.*]] = alloca [42 x i32], align 4
738 ; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
739 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4
740 ; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
741 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4
742 ; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
743 ; CHECK-NEXT: br label [[LOOP:%.*]]
745 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
746 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
747 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
748 ; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
749 ; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
750 ; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
751 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
752 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
753 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
755 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
756 ; CHECK-NEXT: [[I1:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL_FULL]], ptr [[RETVAL]])
757 ; CHECK-NEXT: [[I2:%.*]] = call i32 @capture_of_alloca(ptr [[SOME_ANOTHER_ALLOCA_FULL]])
758 ; CHECK-NEXT: [[I3_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
759 ; CHECK-NEXT: [[I3_FCA_0_LOAD:%.*]] = load i32, ptr [[I3_FCA_0_GEP]], align 4
760 ; CHECK-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I3_FCA_0_LOAD]], 0
761 ; CHECK-NEXT: [[I3_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
762 ; CHECK-NEXT: [[I3_FCA_1_LOAD:%.*]] = load i32, ptr [[I3_FCA_1_GEP]], align 4
763 ; CHECK-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[I3_FCA_1_LOAD]], 1
764 ; CHECK-NEXT: ret [2 x i32] [[I3_FCA_1_INSERT]]
767 %retval.full = alloca [2 x i32], align 4
768 %some.another.alloca.full = alloca [42 x i32], align 4
769 store [2 x i32] zeroinitializer, ptr %retval.full, align 4
770 %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
774 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
775 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
776 %ld = load i32, ptr %arrayidx, align 4
777 %rdx = load i32, ptr %retval, align 4
778 %rdx.inc = add nsw i32 %rdx, %ld
779 store i32 %rdx.inc, ptr %retval, align 4
780 %indvars.iv.next = add nsw i64 %indvars.iv, 1
781 %exitcond = icmp ne i64 %indvars.iv.next, %n
782 br i1 %exitcond, label %loop, label %exit
785 %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
786 %i1 = call i32 @user_of_alloca_with_multiple_args(ptr %retval.full, ptr %retval)
787 %i2 = call i32 @capture_of_alloca(ptr %some.another.alloca.full)
788 %i3 = load [2 x i32], ptr %retval.full, align 4
792 define i32 @all_uses_of_alloca_are_calls(ptr %data, i64 %n) {
793 ; CHECK-LABEL: @all_uses_of_alloca_are_calls(
795 ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
796 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
797 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
798 ; CHECK-NEXT: ret i32 0
801 %retval = alloca i32, align 4
802 call i32 @user_of_alloca(ptr %retval)
803 call i32 @user_of_alloca(ptr %retval)
807 declare void @llvm.lifetime.start.p0(i64 immarg, ptr)
809 define i64 @do_schedule_instrs_for_dce_after_fixups() {
810 ; CHECK-LABEL: @do_schedule_instrs_for_dce_after_fixups(
812 ; CHECK-NEXT: [[C:%.*]] = alloca i64, align 2
813 ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1, ptr [[C]])
814 ; CHECK-NEXT: store i64 0, ptr [[C]], align 4
815 ; CHECK-NEXT: br label [[IF_END:%.*]]
817 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 1
818 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @user_of_alloca(ptr [[ADD_PTR]])
819 ; CHECK-NEXT: [[LD:%.*]] = load i64, ptr [[C]], align 4
820 ; CHECK-NEXT: ret i64 [[LD]]
823 %c = alloca i64, align 2
824 call void @llvm.lifetime.start.p0(i64 1, ptr %c)
828 if.end: ; preds = %entry
829 %add.ptr = getelementptr inbounds i32, ptr %c, i64 1
830 call i32 @user_of_alloca(ptr %add.ptr)
831 %ld = load i64, ptr %c
835 define void @dont_transform_store_only() {
836 ; CHECK-LABEL: @dont_transform_store_only(
838 ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
839 ; CHECK-NEXT: store i8 0, ptr [[A]], align 1
840 ; CHECK-NEXT: call void @byte_user_of_alloca(ptr [[A]])
841 ; CHECK-NEXT: ret void
846 call void @byte_user_of_alloca(ptr %a)
849 define i8 @dont_transform_load_only() {
850 ; CHECK-LABEL: @dont_transform_load_only(
852 ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
853 ; CHECK-NEXT: call void @byte_user_of_alloca(ptr [[A]])
854 ; CHECK-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1
855 ; CHECK-NEXT: ret i8 [[R]]
859 call void @byte_user_of_alloca(ptr %a)
863 define i8 @transform_load_and_store() {
864 ; CHECK-LABEL: @transform_load_and_store(
866 ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
867 ; CHECK-NEXT: store i8 0, ptr [[A]], align 1
868 ; CHECK-NEXT: call void @byte_user_of_alloca(ptr [[A]])
869 ; CHECK-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1
870 ; CHECK-NEXT: ret i8 [[R]]
875 call void @byte_user_of_alloca(ptr %a)
880 define [2 x i32] @select_of_ptrs(ptr %data, i1 %c, i32 %v) {
881 ; CHECK-LABEL: @select_of_ptrs(
883 ; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
884 ; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
885 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4
886 ; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
887 ; CHECK-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4
888 ; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
889 ; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr [[RETVAL_FULL]], ptr [[RETVAL]]
890 ; CHECK-NEXT: store i32 [[V:%.*]], ptr [[PTR]], align 4
891 ; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL_FULL]])
892 ; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
893 ; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
894 ; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
895 ; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
896 ; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
897 ; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
898 ; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
901 %retval.full = alloca [2 x i32], align 4
902 store [2 x i32] zeroinitializer, ptr %retval.full, align 4
903 %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
904 %ptr = select i1 %c, ptr %retval.full, ptr %retval
905 store i32 %v, ptr %ptr
906 %i0 = call i32 @user_of_alloca(ptr %retval.full)
907 %i1 = load [2 x i32], ptr %retval.full, align 4
911 declare dso_local i32 @user_of_alloca(ptr nocapture readonly)
912 declare dso_local i32 @user_of_alloca_with_multiple_args(ptr nocapture readonly, ptr nocapture readonly)
913 declare dso_local i32 @capture_of_alloca(ptr)
914 declare dso_local i32 @capture_with_multiple_args(ptr nocapture readonly, ptr)
916 declare dso_local void @byte_user_of_alloca(ptr nocapture readonly)
918 declare dso_local i32 @__gxx_personality_v0(...)
920 declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1)
921 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
922 ; CHECK-MODIFY-CFG: {{.*}}
923 ; CHECK-PRESERVE-CFG: {{.*}}