xref: /llvm-project/llvm/test/Transforms/SROA/non-capturing-call-readonly.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
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
4
5define i32 @alloca_used_in_call(ptr %data, i64 %n) {
6; CHECK-LABEL: @alloca_used_in_call(
7; CHECK-NEXT:  entry:
8; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
9; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
10; CHECK-NEXT:    br label [[LOOP:%.*]]
11; CHECK:       loop:
12; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
13; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
14; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
15; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], 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:%.*]]
21; CHECK:       exit:
22; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
23; CHECK-NEXT:    ret i32 [[RDX_INC]]
24;
25entry:
26  %retval = alloca i32, align 4
27  store i32 0, ptr %retval, align 4
28  br label %loop
29
30loop:
31  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
32  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
33  %ld = load i32, ptr %arrayidx, align 4
34  %rdx = load i32, ptr %retval, align 4
35  %rdx.inc = add nsw i32 %rdx, %ld
36  store i32 %rdx.inc, ptr %retval, align 4
37  %indvars.iv.next = add nsw i64 %indvars.iv, 1
38  %exitcond = icmp ne i64 %indvars.iv.next, %n
39  br i1 %exitcond, label %loop, label %exit
40
41exit:
42  %i0 = call i32 @user_of_alloca(ptr %retval)
43  %i1 = load i32, ptr %retval, align 4
44  ret i32 %i1
45}
46
47define i32 @alloca_captured_in_call(ptr %data, i64 %n) {
48; CHECK-LABEL: @alloca_captured_in_call(
49; CHECK-NEXT:  entry:
50; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
51; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
52; CHECK-NEXT:    br label [[LOOP:%.*]]
53; CHECK:       loop:
54; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
55; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
56; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
57; CHECK-NEXT:    [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
58; CHECK-NEXT:    [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
59; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
60; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
61; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
62; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
63; CHECK:       exit:
64; CHECK-NEXT:    [[I0:%.*]] = call i32 @capture_of_alloca(ptr [[RETVAL]])
65; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
66; CHECK-NEXT:    ret i32 [[I1]]
67;
68entry:
69  %retval = alloca i32, align 4
70  store i32 0, ptr %retval, align 4
71  br label %loop
72
73loop:
74  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
75  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
76  %ld = load i32, ptr %arrayidx, align 4
77  %rdx = load i32, ptr %retval, align 4
78  %rdx.inc = add nsw i32 %rdx, %ld
79  store i32 %rdx.inc, ptr %retval, align 4
80  %indvars.iv.next = add nsw i64 %indvars.iv, 1
81  %exitcond = icmp ne i64 %indvars.iv.next, %n
82  br i1 %exitcond, label %loop, label %exit
83
84exit:
85  %i0 = call i32 @capture_of_alloca(ptr %retval)
86  %i1 = load i32, ptr %retval, align 4
87  ret i32 %i1
88}
89
90define i32 @alloca_not_captured_as_per_operand_attr(ptr %data, i64 %n) {
91; CHECK-LABEL: @alloca_not_captured_as_per_operand_attr(
92; CHECK-NEXT:  entry:
93; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
94; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
95; CHECK-NEXT:    br label [[LOOP:%.*]]
96; CHECK:       loop:
97; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
98; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
99; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
100; CHECK-NEXT:    [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
101; CHECK-NEXT:    [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
102; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
103; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
104; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
105; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
106; CHECK:       exit:
107; CHECK-NEXT:    [[I0:%.*]] = call i32 @capture_of_alloca(ptr captures(none) [[RETVAL]])
108; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
109; CHECK-NEXT:    ret i32 [[I1]]
110;
111entry:
112  %retval = alloca i32, align 4
113  store i32 0, ptr %retval, align 4
114  br label %loop
115
116loop:
117  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
118  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
119  %ld = load i32, ptr %arrayidx, align 4
120  %rdx = load i32, ptr %retval, align 4
121  %rdx.inc = add nsw i32 %rdx, %ld
122  store i32 %rdx.inc, ptr %retval, align 4
123  %indvars.iv.next = add nsw i64 %indvars.iv, 1
124  %exitcond = icmp ne i64 %indvars.iv.next, %n
125  br i1 %exitcond, label %loop, label %exit
126
127exit:
128  %i0 = call i32 @capture_of_alloca(ptr nocapture %retval)
129  %i1 = load i32, ptr %retval, align 4
130  ret i32 %i1
131}
132
133define i32 @alloca_not_captured_and_readonly_as_per_operand_attr(ptr %data, i64 %n) {
134; CHECK-LABEL: @alloca_not_captured_and_readonly_as_per_operand_attr(
135; CHECK-NEXT:  entry:
136; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
137; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
138; CHECK-NEXT:    br label [[LOOP:%.*]]
139; CHECK:       loop:
140; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[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_INC]] = add nsw i32 [[RDX]], [[LD]]
145; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
146; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
147; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
148; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
149; CHECK:       exit:
150; CHECK-NEXT:    [[I0:%.*]] = call i32 @capture_of_alloca(ptr readonly captures(none) [[RETVAL]])
151; CHECK-NEXT:    ret i32 [[RDX_INC]]
152;
153entry:
154  %retval = alloca i32, align 4
155  store i32 0, ptr %retval, align 4
156  br label %loop
157
158loop:
159  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
160  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
161  %ld = load i32, ptr %arrayidx, align 4
162  %rdx = load i32, ptr %retval, align 4
163  %rdx.inc = add nsw i32 %rdx, %ld
164  store i32 %rdx.inc, ptr %retval, align 4
165  %indvars.iv.next = add nsw i64 %indvars.iv, 1
166  %exitcond = icmp ne i64 %indvars.iv.next, %n
167  br i1 %exitcond, label %loop, label %exit
168
169exit:
170  %i0 = call i32 @capture_of_alloca(ptr nocapture readonly %retval)
171  %i1 = load i32, ptr %retval, align 4
172  ret i32 %i1
173}
174
175define i32 @alloca_not_captured_as_per_operand_attr_and_readonly_as_per_callbase_attr(ptr %data, i64 %n) {
176; CHECK-LABEL: @alloca_not_captured_as_per_operand_attr_and_readonly_as_per_callbase_attr(
177; CHECK-NEXT:  entry:
178; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
179; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
180; CHECK-NEXT:    br label [[LOOP:%.*]]
181; CHECK:       loop:
182; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
183; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
184; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
185; CHECK-NEXT:    [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
186; CHECK-NEXT:    [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
187; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
188; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
189; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
190; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
191; CHECK:       exit:
192; CHECK-NEXT:    [[I0:%.*]] = call i32 @capture_of_alloca(ptr captures(none) [[RETVAL]]) #[[ATTR2:[0-9]+]]
193; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
194; CHECK-NEXT:    ret i32 [[I1]]
195;
196entry:
197  %retval = alloca i32, align 4
198  store i32 0, ptr %retval, align 4
199  br label %loop
200
201loop:
202  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
203  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
204  %ld = load i32, ptr %arrayidx, align 4
205  %rdx = load i32, ptr %retval, align 4
206  %rdx.inc = add nsw i32 %rdx, %ld
207  store i32 %rdx.inc, ptr %retval, align 4
208  %indvars.iv.next = add nsw i64 %indvars.iv, 1
209  %exitcond = icmp ne i64 %indvars.iv.next, %n
210  br i1 %exitcond, label %loop, label %exit
211
212exit:
213  %i0 = call i32 @capture_of_alloca(ptr nocapture %retval) readonly
214  %i1 = load i32, ptr %retval, align 4
215  ret i32 %i1
216}
217
218define i32 @alloca_not_readonly_as_per_operand_attr(ptr %data, i64 %n) {
219; CHECK-LABEL: @alloca_not_readonly_as_per_operand_attr(
220; CHECK-NEXT:  entry:
221; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
222; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
223; CHECK-NEXT:    br label [[LOOP:%.*]]
224; CHECK:       loop:
225; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
226; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
227; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
228; CHECK-NEXT:    [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
229; CHECK-NEXT:    [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
230; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
231; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
232; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
233; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
234; CHECK:       exit:
235; CHECK-NEXT:    [[I0:%.*]] = call i32 @capture_of_alloca(ptr readonly [[RETVAL]])
236; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
237; CHECK-NEXT:    ret i32 [[I1]]
238;
239entry:
240  %retval = alloca i32, align 4
241  store i32 0, ptr %retval, align 4
242  br label %loop
243
244loop:
245  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
246  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
247  %ld = load i32, ptr %arrayidx, align 4
248  %rdx = load i32, ptr %retval, align 4
249  %rdx.inc = add nsw i32 %rdx, %ld
250  store i32 %rdx.inc, ptr %retval, align 4
251  %indvars.iv.next = add nsw i64 %indvars.iv, 1
252  %exitcond = icmp ne i64 %indvars.iv.next, %n
253  br i1 %exitcond, label %loop, label %exit
254
255exit:
256  %i0 = call i32 @capture_of_alloca(ptr readonly %retval)
257  %i1 = load i32, ptr %retval, align 4
258  ret i32 %i1
259}
260
261define i32 @alloca_with_gep_used_in_call(ptr %data, i64 %n) {
262; CHECK-LABEL: @alloca_with_gep_used_in_call(
263; CHECK-NEXT:  entry:
264; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
265; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
266; CHECK-NEXT:    br label [[LOOP:%.*]]
267; CHECK:       loop:
268; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
269; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
270; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
271; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
272; CHECK-NEXT:    [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
273; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
274; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
275; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
276; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
277; CHECK:       exit:
278; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
279; CHECK-NEXT:    ret i32 [[RDX_INC]]
280;
281entry:
282  %retval = alloca i32, align 4
283  store i32 0, ptr %retval, align 4
284  br label %loop
285
286loop:
287  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
288  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
289  %ld = load i32, ptr %arrayidx, align 4
290  %rdx = load i32, ptr %retval, align 4
291  %rdx.inc = add nsw i32 %rdx, %ld
292  store i32 %rdx.inc, ptr %retval, align 4
293  %indvars.iv.next = add nsw i64 %indvars.iv, 1
294  %exitcond = icmp ne i64 %indvars.iv.next, %n
295  br i1 %exitcond, label %loop, label %exit
296
297exit:
298  %i0 = call i32 @user_of_alloca(ptr %retval)
299  %i1 = load i32, ptr %retval, align 4
300  ret i32 %i1
301}
302
303define i32 @alloca_captured_second_arg(ptr %data, i64 %n) {
304; CHECK-LABEL: @alloca_captured_second_arg(
305; CHECK-NEXT:  entry:
306; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
307; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
308; CHECK-NEXT:    br label [[LOOP:%.*]]
309; CHECK:       loop:
310; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
311; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
312; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
313; CHECK-NEXT:    [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
314; CHECK-NEXT:    [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
315; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
316; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
317; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
318; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
319; CHECK:       exit:
320; CHECK-NEXT:    [[I0:%.*]] = call i32 @capture_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL]])
321; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
322; CHECK-NEXT:    ret i32 [[I1]]
323;
324entry:
325  %retval = alloca i32, align 4
326  store i32 0, ptr %retval, align 4
327  br label %loop
328
329loop:
330  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
331  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
332  %ld = load i32, ptr %arrayidx, align 4
333  %rdx = load i32, ptr %retval, align 4
334  %rdx.inc = add nsw i32 %rdx, %ld
335  store i32 %rdx.inc, ptr %retval, align 4
336  %indvars.iv.next = add nsw i64 %indvars.iv, 1
337  %exitcond = icmp ne i64 %indvars.iv.next, %n
338  br i1 %exitcond, label %loop, label %exit
339
340exit:
341  %i0 = call i32 @capture_with_multiple_args(ptr %retval, ptr %retval)
342  %i1 = load i32, ptr %retval, align 4
343  ret i32 %i1
344}
345
346define i32 @alloca_used_in_maybe_throwing_call(ptr %data, i64 %n) personality ptr @__gxx_personality_v0  {
347; CHECK-LABEL: @alloca_used_in_maybe_throwing_call(
348; CHECK-NEXT:  entry:
349; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
350; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
351; CHECK-NEXT:    br label [[LOOP:%.*]]
352; CHECK:       loop:
353; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
354; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
355; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
356; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
357; CHECK-NEXT:    [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
358; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
359; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
360; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
361; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
362; CHECK:       exit:
363; CHECK-NEXT:    [[I0:%.*]] = invoke i32 @user_of_alloca(ptr [[RETVAL]])
364; CHECK-NEXT:            to label [[CONT:%.*]] unwind label [[UW:%.*]]
365; CHECK:       cont:
366; CHECK-NEXT:    br label [[END:%.*]]
367; CHECK:       uw:
368; CHECK-NEXT:    [[I1:%.*]] = landingpad { ptr, i32 }
369; CHECK-NEXT:            catch ptr null
370; CHECK-NEXT:    br label [[END]]
371; CHECK:       end:
372; CHECK-NEXT:    ret i32 [[RDX_INC]]
373;
374entry:
375  %retval = alloca i32, align 4
376  store i32 0, ptr %retval, align 4
377  br label %loop
378
379loop:
380  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
381  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
382  %ld = load i32, ptr %arrayidx, align 4
383  %rdx = load i32, ptr %retval, align 4
384  %rdx.inc = add nsw i32 %rdx, %ld
385  store i32 %rdx.inc, ptr %retval, align 4
386  %indvars.iv.next = add nsw i64 %indvars.iv, 1
387  %exitcond = icmp ne i64 %indvars.iv.next, %n
388  br i1 %exitcond, label %loop, label %exit
389
390exit:
391  %i0 = invoke i32 @user_of_alloca(ptr %retval) to label %cont unwind label %uw
392
393cont:
394  br label %end
395
396uw:
397  %i1 = landingpad { ptr, i32 } catch ptr null
398  br label %end
399
400end:
401  %i2 = load i32, ptr %retval, align 4
402  ret i32 %i2
403}
404
405define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(ptr %data, i64 %n) personality ptr @__gxx_personality_v0  {
406; CHECK-LABEL: @alloca_used_in_maybe_throwing_call_with_same_dests(
407; CHECK-NEXT:  entry:
408; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
409; CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
410; CHECK-NEXT:    br label [[LOOP:%.*]]
411; CHECK:       loop:
412; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
413; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
414; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
415; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
416; CHECK-NEXT:    [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
417; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
418; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
419; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
420; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
421; CHECK:       exit:
422; CHECK-NEXT:    [[I0:%.*]] = invoke i32 @user_of_alloca(ptr [[RETVAL]])
423; CHECK-NEXT:            to label [[END:%.*]] unwind label [[UW:%.*]]
424; CHECK:       uw:
425; CHECK-NEXT:    [[I1:%.*]] = landingpad { ptr, i32 }
426; CHECK-NEXT:            catch ptr null
427; CHECK-NEXT:    br label [[END]]
428; CHECK:       end:
429; CHECK-NEXT:    ret i32 [[RDX_INC]]
430;
431entry:
432  %retval = alloca i32, align 4
433  store i32 0, ptr %retval, align 4
434  br label %loop
435
436loop:
437  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
438  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
439  %ld = load i32, ptr %arrayidx, align 4
440  %rdx = load i32, ptr %retval, align 4
441  %rdx.inc = add nsw i32 %rdx, %ld
442  store i32 %rdx.inc, ptr %retval, align 4
443  %indvars.iv.next = add nsw i64 %indvars.iv, 1
444  %exitcond = icmp ne i64 %indvars.iv.next, %n
445  br i1 %exitcond, label %loop, label %exit
446
447exit:
448  %i0 = invoke i32 @user_of_alloca(ptr %retval) to label %end unwind label %uw
449
450uw:
451  %i1 = landingpad { ptr, i32 } catch ptr null
452  br label %end
453
454end:
455  %i2 = load i32, ptr %retval, align 4
456  ret i32 %i2
457}
458
459define [2 x i32] @part_of_alloca_used_in_call(ptr %data, i64 %n) {
460; CHECK-LABEL: @part_of_alloca_used_in_call(
461; CHECK-NEXT:  entry:
462; CHECK-NEXT:    [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
463; CHECK-NEXT:    [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
464; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_0_GEP]], align 4
465; CHECK-NEXT:    [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
466; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_1_GEP]], align 4
467; CHECK-NEXT:    [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
468; CHECK-NEXT:    br label [[LOOP:%.*]]
469; CHECK:       loop:
470; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
471; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
472; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
473; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
474; CHECK-NEXT:    [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
475; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
476; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
477; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
478; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
479; CHECK:       exit:
480; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
481; CHECK-NEXT:    [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
482; CHECK-NEXT:    [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
483; CHECK-NEXT:    [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
484; CHECK-NEXT:    [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
485; CHECK-NEXT:    ret [2 x i32] [[I1_FCA_1_INSERT]]
486;
487entry:
488  %retval.full = alloca [2 x i32], align 4
489  store [2 x i32] zeroinitializer, ptr %retval.full, align 4
490  %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
491  br label %loop
492
493loop:
494  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
495  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
496  %ld = load i32, ptr %arrayidx, align 4
497  %rdx = load i32, ptr %retval, align 4
498  %rdx.inc = add nsw i32 %rdx, %ld
499  store i32 %rdx.inc, ptr %retval, align 4
500  %indvars.iv.next = add nsw i64 %indvars.iv, 1
501  %exitcond = icmp ne i64 %indvars.iv.next, %n
502  br i1 %exitcond, label %loop, label %exit
503
504exit:
505  %i0 = call i32 @user_of_alloca(ptr %retval)
506  %i1 = load [2 x i32], ptr %retval.full, align 4
507  ret [2 x i32] %i1
508}
509
510define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args(ptr %data, i64 %n) {
511; CHECK-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args(
512; CHECK-NEXT:  entry:
513; CHECK-NEXT:    [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
514; CHECK-NEXT:    [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
515; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_0_GEP]], align 4
516; CHECK-NEXT:    [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
517; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_1_GEP]], align 4
518; CHECK-NEXT:    [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
519; CHECK-NEXT:    br label [[LOOP:%.*]]
520; CHECK:       loop:
521; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
522; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
523; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
524; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
525; CHECK-NEXT:    [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
526; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
527; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
528; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
529; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
530; CHECK:       exit:
531; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
532; CHECK-NEXT:    [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
533; CHECK-NEXT:    [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
534; CHECK-NEXT:    [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
535; CHECK-NEXT:    [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
536; CHECK-NEXT:    ret [2 x i32] [[I1_FCA_1_INSERT]]
537;
538entry:
539  %retval.full = alloca [2 x i32], align 4
540  store [2 x i32] zeroinitializer, ptr %retval.full, align 4
541  %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
542  br label %loop
543
544loop:
545  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
546  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
547  %ld = load i32, ptr %arrayidx, align 4
548  %rdx = load i32, ptr %retval, align 4
549  %rdx.inc = add nsw i32 %rdx, %ld
550  store i32 %rdx.inc, ptr %retval, align 4
551  %indvars.iv.next = add nsw i64 %indvars.iv, 1
552  %exitcond = icmp ne i64 %indvars.iv.next, %n
553  br i1 %exitcond, label %loop, label %exit
554
555exit:
556  %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
557  %i1 = load [2 x i32], ptr %retval.full, align 4
558  ret [2 x i32] %i1
559}
560
561define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_before_call(ptr %data, i64 %n) {
562; CHECK-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_before_call(
563; CHECK-NEXT:  entry:
564; CHECK-NEXT:    [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
565; CHECK-NEXT:    [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
566; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_0_GEP]], align 4
567; CHECK-NEXT:    [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
568; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_1_GEP]], align 4
569; CHECK-NEXT:    [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
570; CHECK-NEXT:    br label [[LOOP:%.*]]
571; CHECK:       loop:
572; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
573; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
574; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
575; CHECK-NEXT:    [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
576; CHECK-NEXT:    [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
577; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
578; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
579; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
580; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
581; CHECK:       exit:
582; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr [[RETVAL_FULL]], ptr [[RETVAL]], i32 4, i1 false)
583; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
584; CHECK-NEXT:    [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
585; CHECK-NEXT:    [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
586; CHECK-NEXT:    [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
587; CHECK-NEXT:    [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
588; CHECK-NEXT:    [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
589; CHECK-NEXT:    [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
590; CHECK-NEXT:    ret [2 x i32] [[I1_FCA_1_INSERT]]
591;
592entry:
593  %retval.full = alloca [2 x i32], align 4
594  store [2 x i32] zeroinitializer, ptr %retval.full, align 4
595  %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
596  br label %loop
597
598loop:
599  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
600  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
601  %ld = load i32, ptr %arrayidx, align 4
602  %rdx = load i32, ptr %retval, align 4
603  %rdx.inc = add nsw i32 %rdx, %ld
604  store i32 %rdx.inc, ptr %retval, align 4
605  %indvars.iv.next = add nsw i64 %indvars.iv, 1
606  %exitcond = icmp ne i64 %indvars.iv.next, %n
607  br i1 %exitcond, label %loop, label %exit
608
609exit:
610  call void @llvm.memcpy.p0.p0.i32(ptr %retval.full, ptr %retval, i32 4, i1 false)
611  %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
612  %i1 = load [2 x i32], ptr %retval.full, align 4
613  ret [2 x i32] %i1
614}
615
616define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_after_call(ptr %data, i64 %n) {
617; CHECK-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_after_call(
618; CHECK-NEXT:  entry:
619; CHECK-NEXT:    [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
620; CHECK-NEXT:    [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
621; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_0_GEP]], align 4
622; CHECK-NEXT:    [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
623; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_1_GEP]], align 4
624; CHECK-NEXT:    [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
625; CHECK-NEXT:    br label [[LOOP:%.*]]
626; CHECK:       loop:
627; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
628; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
629; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
630; CHECK-NEXT:    [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
631; CHECK-NEXT:    [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
632; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
633; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
634; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
635; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
636; CHECK:       exit:
637; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
638; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr [[RETVAL_FULL]], ptr [[RETVAL]], i32 4, i1 false)
639; CHECK-NEXT:    [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
640; CHECK-NEXT:    [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
641; CHECK-NEXT:    [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
642; CHECK-NEXT:    [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
643; CHECK-NEXT:    [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
644; CHECK-NEXT:    [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
645; CHECK-NEXT:    ret [2 x i32] [[I1_FCA_1_INSERT]]
646;
647entry:
648  %retval.full = alloca [2 x i32], align 4
649  store [2 x i32] zeroinitializer, ptr %retval.full, align 4
650  %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
651  br label %loop
652
653loop:
654  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
655  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
656  %ld = load i32, ptr %arrayidx, align 4
657  %rdx = load i32, ptr %retval, align 4
658  %rdx.inc = add nsw i32 %rdx, %ld
659  store i32 %rdx.inc, ptr %retval, align 4
660  %indvars.iv.next = add nsw i64 %indvars.iv, 1
661  %exitcond = icmp ne i64 %indvars.iv.next, %n
662  br i1 %exitcond, label %loop, label %exit
663
664exit:
665  %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
666  call void @llvm.memcpy.p0.p0.i32(ptr %retval.full, ptr %retval, i32 4, i1 false)
667  %i1 = load [2 x i32], ptr %retval.full, align 4
668  ret [2 x i32] %i1
669}
670
671define [2 x i32] @part_of_alloca_used_in_call_with_multiple_args(ptr %data, i64 %n) {
672; CHECK-LABEL: @part_of_alloca_used_in_call_with_multiple_args(
673; CHECK-NEXT:  entry:
674; CHECK-NEXT:    [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
675; CHECK-NEXT:    [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
676; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_0_GEP]], align 4
677; CHECK-NEXT:    [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
678; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_1_GEP]], align 4
679; CHECK-NEXT:    [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
680; CHECK-NEXT:    br label [[LOOP:%.*]]
681; CHECK:       loop:
682; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
683; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
684; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
685; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
686; CHECK-NEXT:    [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
687; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
688; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
689; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
690; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
691; CHECK:       exit:
692; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL]])
693; CHECK-NEXT:    [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
694; CHECK-NEXT:    [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
695; CHECK-NEXT:    [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
696; CHECK-NEXT:    [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
697; CHECK-NEXT:    ret [2 x i32] [[I1_FCA_1_INSERT]]
698;
699entry:
700  %retval.full = alloca [2 x i32], align 4
701  store [2 x i32] zeroinitializer, ptr %retval.full, align 4
702  %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
703  br label %loop
704
705loop:
706  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
707  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
708  %ld = load i32, ptr %arrayidx, align 4
709  %rdx = load i32, ptr %retval, align 4
710  %rdx.inc = add nsw i32 %rdx, %ld
711  store i32 %rdx.inc, ptr %retval, align 4
712  %indvars.iv.next = add nsw i64 %indvars.iv, 1
713  %exitcond = icmp ne i64 %indvars.iv.next, %n
714  br i1 %exitcond, label %loop, label %exit
715
716exit:
717  %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval)
718  %i1 = load [2 x i32], ptr %retval.full, align 4
719  ret [2 x i32] %i1
720}
721
722define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(ptr %data, i64 %n) {
723; CHECK-LABEL: @all_parts_of_alloca_used_in_calls_with_multiple_args(
724; CHECK-NEXT:  entry:
725; CHECK-NEXT:    [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
726; CHECK-NEXT:    [[SOME_ANOTHER_ALLOCA_FULL:%.*]] = alloca [42 x i32], align 4
727; CHECK-NEXT:    [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
728; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_0_GEP]], align 4
729; CHECK-NEXT:    [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
730; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_1_GEP]], align 4
731; CHECK-NEXT:    [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
732; CHECK-NEXT:    br label [[LOOP:%.*]]
733; CHECK:       loop:
734; CHECK-NEXT:    [[RDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
735; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
736; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
737; CHECK-NEXT:    [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
738; CHECK-NEXT:    [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
739; CHECK-NEXT:    store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
740; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
741; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
742; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
743; CHECK:       exit:
744; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
745; CHECK-NEXT:    [[I1:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL_FULL]], ptr [[RETVAL]])
746; CHECK-NEXT:    [[I2:%.*]] = call i32 @capture_of_alloca(ptr [[SOME_ANOTHER_ALLOCA_FULL]])
747; CHECK-NEXT:    [[I3_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
748; CHECK-NEXT:    [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
749; CHECK-NEXT:    [[I3_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
750; CHECK-NEXT:    [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[RDX_INC]], 1
751; CHECK-NEXT:    ret [2 x i32] [[I3_FCA_1_INSERT]]
752;
753entry:
754  %retval.full = alloca [2 x i32], align 4
755  %some.another.alloca.full = alloca [42 x i32], align 4
756  store [2 x i32] zeroinitializer, ptr %retval.full, align 4
757  %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
758  br label %loop
759
760loop:
761  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ]
762  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
763  %ld = load i32, ptr %arrayidx, align 4
764  %rdx = load i32, ptr %retval, align 4
765  %rdx.inc = add nsw i32 %rdx, %ld
766  store i32 %rdx.inc, ptr %retval, align 4
767  %indvars.iv.next = add nsw i64 %indvars.iv, 1
768  %exitcond = icmp ne i64 %indvars.iv.next, %n
769  br i1 %exitcond, label %loop, label %exit
770
771exit:
772  %i0 = call i32 @user_of_alloca_with_multiple_args(ptr %retval, ptr %retval.full)
773  %i1 = call i32 @user_of_alloca_with_multiple_args(ptr %retval.full, ptr %retval)
774  %i2 = call i32 @capture_of_alloca(ptr %some.another.alloca.full)
775  %i3 = load [2 x i32], ptr %retval.full, align 4
776  ret [2 x i32] %i3
777}
778
779define i32 @all_uses_of_alloca_are_calls(ptr %data, i64 %n) {
780; CHECK-LABEL: @all_uses_of_alloca_are_calls(
781; CHECK-NEXT:  entry:
782; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
783; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
784; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
785; CHECK-NEXT:    ret i32 0
786;
787entry:
788  %retval = alloca i32, align 4
789  call i32 @user_of_alloca(ptr %retval)
790  call i32 @user_of_alloca(ptr %retval)
791  ret i32 0
792}
793
794declare void @llvm.lifetime.start.p0(i64 immarg, ptr)
795
796define i64 @do_schedule_instrs_for_dce_after_fixups() {
797; CHECK-LABEL: @do_schedule_instrs_for_dce_after_fixups(
798; CHECK-NEXT:  entry:
799; CHECK-NEXT:    [[C:%.*]] = alloca i64, align 2
800; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 1, ptr [[C]])
801; CHECK-NEXT:    store i64 0, ptr [[C]], align 4
802; CHECK-NEXT:    br label [[IF_END:%.*]]
803; CHECK:       if.end:
804; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 1
805; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @user_of_alloca(ptr [[ADD_PTR]])
806; CHECK-NEXT:    [[LD:%.*]] = load i64, ptr [[C]], align 4
807; CHECK-NEXT:    ret i64 [[LD]]
808;
809entry:
810  %c = alloca i64, align 2
811  call void @llvm.lifetime.start.p0(i64 1, ptr %c)
812  store i64 0, ptr %c
813  br label %if.end
814
815if.end:                                           ; preds = %entry
816  %add.ptr = getelementptr inbounds i32, ptr %c, i64 1
817  call i32 @user_of_alloca(ptr %add.ptr)
818  %ld = load i64, ptr %c
819  ret i64 %ld
820}
821
822define void @dont_transform_store_only() {
823; CHECK-LABEL: @dont_transform_store_only(
824; CHECK-NEXT:  entry:
825; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 1
826; CHECK-NEXT:    store i8 0, ptr [[A]], align 1
827; CHECK-NEXT:    call void @byte_user_of_alloca(ptr [[A]])
828; CHECK-NEXT:    ret void
829;
830entry:
831  %a = alloca i8
832  store i8 0, ptr %a
833  call void @byte_user_of_alloca(ptr %a)
834  ret void
835}
836define i8 @dont_transform_load_only() {
837; CHECK-LABEL: @dont_transform_load_only(
838; CHECK-NEXT:  entry:
839; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 1
840; CHECK-NEXT:    call void @byte_user_of_alloca(ptr [[A]])
841; CHECK-NEXT:    ret i8 undef
842;
843entry:
844  %a = alloca i8
845  call void @byte_user_of_alloca(ptr %a)
846  %r = load i8, ptr %a
847  ret i8 %r
848}
849define i8 @transform_load_and_store() {
850; CHECK-LABEL: @transform_load_and_store(
851; CHECK-NEXT:  entry:
852; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 1
853; CHECK-NEXT:    store i8 0, ptr [[A]], align 1
854; CHECK-NEXT:    call void @byte_user_of_alloca(ptr [[A]])
855; CHECK-NEXT:    ret i8 0
856;
857entry:
858  %a = alloca i8
859  store i8 0, ptr %a
860  call void @byte_user_of_alloca(ptr %a)
861  %r = load i8, ptr %a
862  ret i8 %r
863}
864
865define [2 x i32] @select_of_ptrs(ptr %data, i1 %c, i32 %v) {
866; CHECK-LABEL: @select_of_ptrs(
867; CHECK-NEXT:  entry:
868; CHECK-NEXT:    [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4
869; CHECK-NEXT:    [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
870; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_0_GEP]], align 4
871; CHECK-NEXT:    [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
872; CHECK-NEXT:    store i32 0, ptr [[DOTFCA_1_GEP]], align 4
873; CHECK-NEXT:    [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
874; CHECK-NEXT:    [[PTR:%.*]] = select i1 [[C:%.*]], ptr [[RETVAL_FULL]], ptr [[RETVAL]]
875; CHECK-NEXT:    store i32 [[V:%.*]], ptr [[PTR]], align 4
876; CHECK-NEXT:    [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL_FULL]])
877; CHECK-NEXT:    [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
878; CHECK-NEXT:    [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
879; CHECK-NEXT:    [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
880; CHECK-NEXT:    [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
881; CHECK-NEXT:    [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
882; CHECK-NEXT:    [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
883; CHECK-NEXT:    ret [2 x i32] [[I1_FCA_1_INSERT]]
884;
885entry:
886  %retval.full = alloca [2 x i32], align 4
887  store [2 x i32] zeroinitializer, ptr %retval.full, align 4
888  %retval = getelementptr inbounds [2 x i32], ptr %retval.full, i64 0, i64 1
889  %ptr = select i1 %c, ptr %retval.full, ptr %retval
890  store i32 %v, ptr %ptr
891  %i0 = call i32 @user_of_alloca(ptr %retval.full)
892  %i1 = load [2 x i32], ptr %retval.full, align 4
893  ret [2 x i32] %i1
894}
895
896declare dso_local i32 @user_of_alloca(ptr nocapture readonly)
897declare dso_local i32 @user_of_alloca_with_multiple_args(ptr nocapture readonly, ptr nocapture readonly)
898declare dso_local i32 @capture_of_alloca(ptr)
899declare dso_local i32 @capture_with_multiple_args(ptr nocapture readonly, ptr)
900
901declare dso_local void @byte_user_of_alloca(ptr nocapture readonly)
902
903declare dso_local i32 @__gxx_personality_v0(...)
904
905declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1)
906;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
907; CHECK-MODIFY-CFG: {{.*}}
908; CHECK-PRESERVE-CFG: {{.*}}
909