xref: /llvm-project/llvm/test/Transforms/DeadStoreElimination/multiblock-loops.ll (revision f497a00da968b0ff90d8c98caa184d14b9a92495)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=dse -S | FileCheck %s
3
4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
5declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i32, i1) nounwind
6
7define void @test13(ptr noalias %P) {
8; CHECK-LABEL: @test13(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    br label [[FOR:%.*]]
11; CHECK:       for:
12; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
13; CHECK-NEXT:    br i1 false, label [[FOR]], label [[END:%.*]]
14; CHECK:       end:
15; CHECK-NEXT:    ret void
16;
17entry:
18  br label %for
19for:
20  store i32 0, ptr %P
21  br i1 false, label %for, label %end
22end:
23  ret void
24}
25
26
27define void @test14(ptr noalias %P) {
28; CHECK-LABEL: @test14(
29; CHECK-NEXT:  entry:
30; CHECK-NEXT:    br label [[FOR:%.*]]
31; CHECK:       for:
32; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
33; CHECK-NEXT:    br i1 false, label [[FOR]], label [[END:%.*]]
34; CHECK:       end:
35; CHECK-NEXT:    ret void
36;
37entry:
38  store i32 1, ptr %P
39  br label %for
40for:
41  store i32 0, ptr %P
42  br i1 false, label %for, label %end
43end:
44  ret void
45}
46
47define void @test18(ptr noalias %P) {
48; CHECK-LABEL: @test18(
49; CHECK-NEXT:  entry:
50; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
51; CHECK-NEXT:    br label [[FOR:%.*]]
52; CHECK:       for:
53; CHECK-NEXT:    store i8 1, ptr [[P]], align 1
54; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P]], align 4
55; CHECK-NEXT:    store i8 2, ptr [[P]], align 1
56; CHECK-NEXT:    br i1 false, label [[FOR]], label [[END:%.*]]
57; CHECK:       end:
58; CHECK-NEXT:    ret void
59;
60entry:
61  store i32 0, ptr %P
62  br label %for
63for:
64  store i8 1, ptr %P
65  %x = load i32, ptr %P
66  store i8 2, ptr %P
67  br i1 false, label %for, label %end
68end:
69  ret void
70}
71
72define void @test21(ptr noalias %P) {
73; CHECK-LABEL: @test21(
74; CHECK-NEXT:  entry:
75; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
76; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
77; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i1 false)
78; CHECK-NEXT:    br label [[FOR:%.*]]
79; CHECK:       for:
80; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1
81; CHECK-NEXT:    store i32 1, ptr [[ARRAYIDX1]], align 4
82; CHECK-NEXT:    br i1 false, label [[FOR]], label [[END:%.*]]
83; CHECK:       end:
84; CHECK-NEXT:    ret void
85;
86entry:
87  %arrayidx0 = getelementptr inbounds i32, ptr %P, i64 1
88  call void @llvm.memset.p0.i64(ptr %arrayidx0, i8 0, i64 28, i32 4, i1 false)
89  br label %for
90for:
91  %arrayidx1 = getelementptr inbounds i32, ptr %P, i64 1
92  store i32 1, ptr %arrayidx1, align 4
93  br i1 false, label %for, label %end
94end:
95  ret void
96}
97
98define void @test_loop(i32 %N, ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %x, ptr noalias nocapture %b) local_unnamed_addr {
99; CHECK-LABEL: @test_loop(
100; CHECK-NEXT:  entry:
101; CHECK-NEXT:    [[CMP27:%.*]] = icmp sgt i32 [[N:%.*]], 0
102; CHECK-NEXT:    br i1 [[CMP27]], label [[FOR_BODY4_LR_PH_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
103; CHECK:       for.body4.lr.ph.preheader:
104; CHECK-NEXT:    br label [[FOR_BODY4_LR_PH:%.*]]
105; CHECK:       for.cond.cleanup:
106; CHECK-NEXT:    ret void
107; CHECK:       for.body4.lr.ph:
108; CHECK-NEXT:    [[I_028:%.*]] = phi i32 [ [[INC11:%.*]], [[FOR_COND_CLEANUP3:%.*]] ], [ 0, [[FOR_BODY4_LR_PH_PREHEADER]] ]
109; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i32 [[I_028]]
110; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[I_028]], [[N]]
111; CHECK-NEXT:    br label [[FOR_BODY4:%.*]]
112; CHECK:       for.body4:
113; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[FOR_BODY4_LR_PH]] ], [ [[ADD9:%.*]], [[FOR_BODY4]] ]
114; CHECK-NEXT:    [[J_026:%.*]] = phi i32 [ 0, [[FOR_BODY4_LR_PH]] ], [ [[INC:%.*]], [[FOR_BODY4]] ]
115; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[J_026]], [[MUL]]
116; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[ADD]]
117; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4
118; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i32 [[J_026]]
119; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX6]], align 4
120; CHECK-NEXT:    [[MUL7:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
121; CHECK-NEXT:    [[ADD9]] = add nsw i32 [[MUL7]], [[TMP0]]
122; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[J_026]], 1
123; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]]
124; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP3]], label [[FOR_BODY4]]
125; CHECK:       for.cond.cleanup3:
126; CHECK-NEXT:    store i32 [[ADD9]], ptr [[ARRAYIDX]], align 4
127; CHECK-NEXT:    [[INC11]] = add nuw nsw i32 [[I_028]], 1
128; CHECK-NEXT:    [[EXITCOND29:%.*]] = icmp eq i32 [[INC11]], [[N]]
129; CHECK-NEXT:    br i1 [[EXITCOND29]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY4_LR_PH]]
130;
131entry:
132  %cmp27 = icmp sgt i32 %N, 0
133  br i1 %cmp27, label %for.body4.lr.ph.preheader, label %for.cond.cleanup
134
135for.body4.lr.ph.preheader:                        ; preds = %entry
136  br label %for.body4.lr.ph
137
138for.cond.cleanup:                                 ; preds = %for.cond.cleanup3, %entry
139  ret void
140
141for.body4.lr.ph:                                  ; preds = %for.body4.lr.ph.preheader, %for.cond.cleanup3
142  %i.028 = phi i32 [ %inc11, %for.cond.cleanup3 ], [ 0, %for.body4.lr.ph.preheader ]
143  %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.028
144  store i32 0, ptr %arrayidx, align 4
145  %mul = mul nsw i32 %i.028, %N
146  br label %for.body4
147
148for.body4:                                        ; preds = %for.body4, %for.body4.lr.ph
149  %0 = phi i32 [ 0, %for.body4.lr.ph ], [ %add9, %for.body4 ]
150  %j.026 = phi i32 [ 0, %for.body4.lr.ph ], [ %inc, %for.body4 ]
151  %add = add nsw i32 %j.026, %mul
152  %arrayidx5 = getelementptr inbounds i32, ptr %A, i32 %add
153  %1 = load i32, ptr %arrayidx5, align 4
154  %arrayidx6 = getelementptr inbounds i32, ptr %x, i32 %j.026
155  %2 = load i32, ptr %arrayidx6, align 4
156  %mul7 = mul nsw i32 %2, %1
157  %add9 = add nsw i32 %mul7, %0
158  %inc = add nuw nsw i32 %j.026, 1
159  %exitcond = icmp eq i32 %inc, %N
160  br i1 %exitcond, label %for.cond.cleanup3, label %for.body4
161
162for.cond.cleanup3:                                ; preds = %for.body4
163  store i32 %add9, ptr %arrayidx, align 4
164  %inc11 = add nuw nsw i32 %i.028, 1
165  %exitcond29 = icmp eq i32 %inc11, %N
166  br i1 %exitcond29, label %for.cond.cleanup, label %for.body4.lr.ph
167}
168
169define i32 @test_if(i1 %c, ptr %p, i32 %i) {
170; CHECK-LABEL: @test_if(
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    br label [[BB1:%.*]]
173; CHECK:       bb1:
174; CHECK-NEXT:    [[PH:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[BB3:%.*]] ]
175; CHECK-NEXT:    [[INC]] = add i32 [[PH]], 1
176; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[PH]]
177; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB2:%.*]], label [[BB3]]
178; CHECK:       bb2:
179; CHECK-NEXT:    br label [[BB3]]
180; CHECK:       bb3:
181; CHECK-NEXT:    store i32 2, ptr [[GEP]], align 4
182; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[PH]], 10
183; CHECK-NEXT:    br i1 [[C1]], label [[BB1]], label [[EXIT:%.*]]
184; CHECK:       exit:
185; CHECK-NEXT:    ret i32 0
186;
187entry:
188  br label %bb1
189bb1:
190  %ph = phi i32 [ 0, %entry ], [ %inc, %bb3 ]
191  %inc = add i32 %ph, 1
192  %gep = getelementptr inbounds i32, ptr %p, i32 %ph
193  store i32 %i, ptr %gep, align 4
194  br i1 %c, label %bb2, label %bb3
195bb2:
196  br label %bb3
197bb3:
198  store i32 2, ptr %gep, align 4
199  %c1 = icmp slt i32 %ph, 10
200  br i1 %c1, label %bb1, label %exit
201exit:
202  ret i32 0
203}
204
205define i32 @test_if2(i1 %c, ptr %p, i32 %i) {
206; CHECK-LABEL: @test_if2(
207; CHECK-NEXT:  entry:
208; CHECK-NEXT:    br label [[BB1:%.*]]
209; CHECK:       bb1:
210; CHECK-NEXT:    [[PH:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[BB2:%.*]] ], [ [[INC]], [[BB3:%.*]] ]
211; CHECK-NEXT:    [[INC]] = add i32 [[PH]], 1
212; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[PH]]
213; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB2]], label [[BB3]]
214; CHECK:       bb2:
215; CHECK-NEXT:    store i32 2, ptr [[GEP]], align 4
216; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[PH]], 10
217; CHECK-NEXT:    br i1 [[C1]], label [[BB1]], label [[EXIT:%.*]]
218; CHECK:       bb3:
219; CHECK-NEXT:    store i32 3, ptr [[GEP]], align 4
220; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[PH]], 5
221; CHECK-NEXT:    br i1 [[C2]], label [[BB1]], label [[EXIT]]
222; CHECK:       exit:
223; CHECK-NEXT:    ret i32 0
224;
225entry:
226  br label %bb1
227bb1:
228  %ph = phi i32 [ 0, %entry ], [ %inc, %bb2 ], [ %inc, %bb3 ]
229  %inc = add i32 %ph, 1
230  %gep = getelementptr inbounds i32, ptr %p, i32 %ph
231  store i32 %i, ptr %gep, align 4
232  br i1 %c, label %bb2, label %bb3
233bb2:
234  store i32 2, ptr %gep, align 4
235  %c1 = icmp slt i32 %ph, 10
236  br i1 %c1, label %bb1, label %exit
237bb3:
238  store i32 3, ptr %gep, align 4
239  %c2 = icmp slt i32 %ph, 5
240  br i1 %c2, label %bb1, label %exit
241exit:
242  ret i32 0
243}
244
245define i32 @test_if3(i1 %c, ptr %p, i32 %i) {
246; CHECK-LABEL: @test_if3(
247; CHECK-NEXT:  entry:
248; CHECK-NEXT:    br label [[BB1:%.*]]
249; CHECK:       bb1:
250; CHECK-NEXT:    [[PH:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[BB3:%.*]] ]
251; CHECK-NEXT:    [[INC]] = add i32 [[PH]], 1
252; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[PH]]
253; CHECK-NEXT:    store i32 [[I:%.*]], ptr [[GEP]], align 4
254; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB2:%.*]], label [[BB3]]
255; CHECK:       bb2:
256; CHECK-NEXT:    store i32 2, ptr [[GEP]], align 4
257; CHECK-NEXT:    br label [[BB3]]
258; CHECK:       bb3:
259; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[PH]], 10
260; CHECK-NEXT:    br i1 [[C1]], label [[BB1]], label [[EXIT:%.*]]
261; CHECK:       exit:
262; CHECK-NEXT:    ret i32 0
263;
264entry:
265  br label %bb1
266bb1:
267  %ph = phi i32 [ 0, %entry ], [ %inc, %bb3 ]
268  %inc = add i32 %ph, 1
269  %gep = getelementptr inbounds i32, ptr %p, i32 %ph
270  store i32 %i, ptr %gep, align 4
271  br i1 %c, label %bb2, label %bb3
272bb2:
273  store i32 2, ptr %gep, align 4
274  br label %bb3
275bb3:
276  %c1 = icmp slt i32 %ph, 10
277  br i1 %c1, label %bb1, label %exit
278exit:
279  ret i32 0
280}
281
282define i32 @test_if4(i1 %c, ptr %p, i32 %i) {
283; CHECK-LABEL: @test_if4(
284; CHECK-NEXT:  entry:
285; CHECK-NEXT:    br label [[BB1:%.*]]
286; CHECK:       bb1:
287; CHECK-NEXT:    [[PH:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[BB1]] ], [ [[INC]], [[BB2:%.*]] ]
288; CHECK-NEXT:    [[INC]] = add i32 [[PH]], 1
289; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[PH]]
290; CHECK-NEXT:    store i32 [[I:%.*]], ptr [[GEP]], align 4
291; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB2]], label [[BB1]]
292; CHECK:       bb2:
293; CHECK-NEXT:    store i32 2, ptr [[GEP]], align 4
294; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[PH]], 10
295; CHECK-NEXT:    br i1 [[C1]], label [[BB1]], label [[EXIT:%.*]]
296; CHECK:       exit:
297; CHECK-NEXT:    ret i32 0
298;
299entry:
300  br label %bb1
301bb1:
302  %ph = phi i32 [ 0, %entry ], [ %inc, %bb1 ], [ %inc, %bb2 ]
303  %inc = add i32 %ph, 1
304  %gep = getelementptr inbounds i32, ptr %p, i32 %ph
305  store i32 %i, ptr %gep, align 4
306  br i1 %c, label %bb2, label %bb1
307bb2:
308  store i32 2, ptr %gep, align 4
309  %c1 = icmp slt i32 %ph, 10
310  br i1 %c1, label %bb1, label %exit
311exit:
312  ret i32 0
313}
314
315declare void @clobber()
316define i32 @test_self(i1 %c, ptr %p, i32 %i) {
317; CHECK-LABEL: @test_self(
318; CHECK-NEXT:  entry:
319; CHECK-NEXT:    br label [[BB1:%.*]]
320; CHECK:       bb1:
321; CHECK-NEXT:    [[PH:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[BB1]] ], [ [[INC]], [[BB2:%.*]] ]
322; CHECK-NEXT:    [[INC]] = add i32 [[PH]], 1
323; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[PH]]
324; CHECK-NEXT:    store i32 1, ptr [[GEP]], align 4
325; CHECK-NEXT:    call void @clobber()
326; CHECK-NEXT:    store i32 2, ptr [[GEP]], align 4
327; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB2]], label [[BB1]]
328; CHECK:       bb2:
329; CHECK-NEXT:    store i32 3, ptr [[GEP]], align 4
330; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[PH]], 10
331; CHECK-NEXT:    br i1 [[C1]], label [[BB1]], label [[EXIT:%.*]]
332; CHECK:       exit:
333; CHECK-NEXT:    ret i32 0
334;
335entry:
336  br label %bb1
337bb1:
338  %ph = phi i32 [ 0, %entry ], [ %inc, %bb1 ], [ %inc, %bb2 ]
339  %inc = add i32 %ph, 1
340  %gep = getelementptr inbounds i32, ptr %p, i32 %ph
341  store i32 1, ptr %gep, align 4
342  call void @clobber()
343  store i32 2, ptr %gep, align 4
344  br i1 %c, label %bb2, label %bb1
345bb2:
346  store i32 3, ptr %gep, align 4
347  %c1 = icmp slt i32 %ph, 10
348  br i1 %c1, label %bb1, label %exit
349exit:
350  ret i32 0
351}
352
353define i32 @test_selfalloca(i1 %c, i32 %i) {
354; CHECK-LABEL: @test_selfalloca(
355; CHECK-NEXT:  entry:
356; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
357; CHECK-NEXT:    br label [[BB1:%.*]]
358; CHECK:       bb1:
359; CHECK-NEXT:    [[PH:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[BB1]] ], [ [[INC]], [[BB2:%.*]] ]
360; CHECK-NEXT:    [[INC]] = add i32 [[PH]], 1
361; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 [[PH]]
362; CHECK-NEXT:    call void @clobber()
363; CHECK-NEXT:    store i32 2, ptr [[GEP]], align 4
364; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB2]], label [[BB1]]
365; CHECK:       bb2:
366; CHECK-NEXT:    store i32 3, ptr [[GEP]], align 4
367; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[PH]], 10
368; CHECK-NEXT:    br i1 [[C1]], label [[BB1]], label [[EXIT:%.*]]
369; CHECK:       exit:
370; CHECK-NEXT:    [[PG:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 [[I:%.*]]
371; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[PG]], align 4
372; CHECK-NEXT:    ret i32 [[L]]
373;
374entry:
375  %p = alloca i32, align 4
376  br label %bb1
377bb1:
378  %ph = phi i32 [ 0, %entry ], [ %inc, %bb1 ], [ %inc, %bb2 ]
379  %inc = add i32 %ph, 1
380  %gep = getelementptr inbounds i32, ptr %p, i32 %ph
381  store i32 1, ptr %gep, align 4
382  call void @clobber()
383  store i32 2, ptr %gep, align 4
384  br i1 %c, label %bb2, label %bb1
385bb2:
386  store i32 3, ptr %gep, align 4
387  %c1 = icmp slt i32 %ph, 10
388  br i1 %c1, label %bb1, label %exit
389exit:
390  %pg = getelementptr inbounds i32, ptr %p, i32 %i
391  %l = load i32, ptr %pg
392  ret i32 %l
393}
394
395declare i1 @cond() readnone nounwind
396
397define void @loop_multiple_def_uses(ptr noalias %P) {
398; CHECK-LABEL: @loop_multiple_def_uses(
399; CHECK-NEXT:  entry:
400; CHECK-NEXT:    br label [[FOR_HEADER:%.*]]
401; CHECK:       for.header:
402; CHECK-NEXT:    [[C1:%.*]] = call i1 @cond()
403; CHECK-NEXT:    br i1 [[C1]], label [[FOR_BODY:%.*]], label [[END:%.*]]
404; CHECK:       for.body:
405; CHECK-NEXT:    store i32 2, ptr [[P:%.*]], align 4
406; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[P]], align 4
407; CHECK-NEXT:    br label [[FOR_HEADER]]
408; CHECK:       end:
409; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
410; CHECK-NEXT:    ret void
411;
412entry:
413  br label %for.header
414
415for.header:
416  store i32 1, ptr %P, align 4
417  %c1 = call i1 @cond()
418  br i1 %c1, label %for.body, label %end
419
420for.body:
421  store i32 2, ptr %P, align 4
422  %lv = load i32, ptr %P
423  br label %for.header
424
425end:
426  store i32 3, ptr %P, align 4
427  ret void
428}
429
430; We cannot eliminate the store in for.header, as it is only partially
431; overwritten in for.body and read afterwards.
432define void @loop_multiple_def_uses_partial_write(ptr noalias %p) {
433; CHECK-LABEL: @loop_multiple_def_uses_partial_write(
434; CHECK-NEXT:  entry:
435; CHECK-NEXT:    br label [[FOR_HEADER:%.*]]
436; CHECK:       for.header:
437; CHECK-NEXT:    store i32 1239297, ptr [[P:%.*]], align 4
438; CHECK-NEXT:    [[C1:%.*]] = call i1 @cond()
439; CHECK-NEXT:    br i1 [[C1]], label [[FOR_BODY:%.*]], label [[END:%.*]]
440; CHECK:       for.body:
441; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[P]], align 4
442; CHECK-NEXT:    br label [[FOR_HEADER]]
443; CHECK:       end:
444; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
445; CHECK-NEXT:    ret void
446;
447entry:
448  br label %for.header
449
450for.header:
451  store i32 1239491, ptr %p, align 4
452  %c1 = call i1 @cond()
453  br i1 %c1, label %for.body, label %end
454
455for.body:
456  store i8 1, ptr %p, align 4
457  %lv = load i32, ptr %p
458  br label %for.header
459
460end:
461  store i32 3, ptr %p, align 4
462  ret void
463}
464
465; We cannot eliminate the store in for.header, as the location is not overwritten
466; in for.body and read afterwards.
467define void @loop_multiple_def_uses_mayalias_write(ptr %p, ptr %q) {
468; CHECK-LABEL: @loop_multiple_def_uses_mayalias_write(
469; CHECK-NEXT:  entry:
470; CHECK-NEXT:    br label [[FOR_HEADER:%.*]]
471; CHECK:       for.header:
472; CHECK-NEXT:    store i32 1239491, ptr [[P:%.*]], align 4
473; CHECK-NEXT:    [[C1:%.*]] = call i1 @cond()
474; CHECK-NEXT:    br i1 [[C1]], label [[FOR_BODY:%.*]], label [[END:%.*]]
475; CHECK:       for.body:
476; CHECK-NEXT:    store i32 1, ptr [[Q:%.*]], align 4
477; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[P]], align 4
478; CHECK-NEXT:    br label [[FOR_HEADER]]
479; CHECK:       end:
480; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
481; CHECK-NEXT:    ret void
482;
483entry:
484  br label %for.header
485
486for.header:
487  store i32 1239491, ptr %p, align 4
488  %c1 = call i1 @cond()
489  br i1 %c1, label %for.body, label %end
490
491for.body:
492  store i32 1, ptr %q, align 4
493  %lv = load i32, ptr %p
494  br label %for.header
495
496end:
497  store i32 3, ptr %p, align 4
498  ret void
499}
500
501%struct.hoge = type { i32, i32 }
502
503@global = external local_unnamed_addr global ptr, align 8
504
505define void @widget(ptr %tmp) {
506; CHECK-LABEL: @widget(
507; CHECK-NEXT:  bb:
508; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[TMP:%.*]], ptr nonnull align 16 undef, i64 64, i1 false)
509; CHECK-NEXT:    br label [[BB1:%.*]]
510; CHECK:       bb1:
511; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @global, align 8
512; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_HOGE:%.*]], ptr [[TMP2]], i64 undef, i32 1
513; CHECK-NEXT:    store i32 0, ptr [[TMP3]], align 4
514; CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr @global, align 8
515; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_HOGE]], ptr [[TMP4]], i64 undef, i32 1
516; CHECK-NEXT:    store i32 10, ptr [[TMP5]], align 4
517; CHECK-NEXT:    br label [[BB1]]
518;
519bb:
520  call void @llvm.memcpy.p0.p0.i64(ptr align 1 %tmp, ptr nonnull align 16 undef, i64 64, i1 false)
521  br label %bb1
522
523bb1:                                              ; preds = %bb1, %bb
524  %tmp2 = load ptr, ptr @global, align 8
525  %tmp3 = getelementptr inbounds %struct.hoge, ptr %tmp2, i64 undef, i32 1
526  store i32 0, ptr %tmp3, align 4
527  %tmp4 = load ptr, ptr @global, align 8
528  %tmp5 = getelementptr inbounds %struct.hoge, ptr %tmp4, i64 undef, i32 1
529  store i32 10, ptr %tmp5, align 4
530  br label %bb1
531}
532
533declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
534
535@x = global [10 x i16] zeroinitializer, align 1
536
537; Make sure we do not eliminate the store in %do.body, because it writes to
538; multiple locations in the loop and the store in %if.end10 only stores to
539; the last one.
540define i16 @test_loop_carried_dep() {
541; CHECK-LABEL: @test_loop_carried_dep(
542; CHECK-NEXT:  entry:
543; CHECK-NEXT:    br label [[DO_BODY:%.*]]
544; CHECK:       do.body:
545; CHECK-NEXT:    [[I_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[IF_END:%.*]] ]
546; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[I_0]]
547; CHECK-NEXT:    store i16 2, ptr [[ARRAYIDX2]], align 1
548; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i16 [[I_0]], 4
549; CHECK-NEXT:    br i1 [[EXITCOND]], label [[IF_END10:%.*]], label [[IF_END]]
550; CHECK:       if.end:
551; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[I_0]], 1
552; CHECK-NEXT:    br label [[DO_BODY]]
553; CHECK:       if.end10:
554; CHECK-NEXT:    store i16 1, ptr [[ARRAYIDX2]], align 1
555; CHECK-NEXT:    ret i16 0
556;
557entry:
558  br label %do.body
559
560do.body:                                          ; preds = %if.end, %entry
561  %i.0 = phi i16 [ 0, %entry ], [ %inc, %if.end ]
562  %arrayidx2 = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %i.0
563  store i16 2, ptr %arrayidx2, align 1
564  %exitcond = icmp eq i16 %i.0, 4
565  br i1 %exitcond, label %if.end10, label %if.end
566
567if.end:                                           ; preds = %do.body
568  %inc = add nuw nsw i16 %i.0, 1
569  br label %do.body
570
571if.end10:                                         ; preds = %do.body
572  store i16 1, ptr %arrayidx2, align 1
573  ret i16 0
574}
575
576; Similar to above, but with an irreducible loop. The stores should not be removed.
577define i16 @irreducible(i1 %c) {
578; CHECK-LABEL: @irreducible(
579; CHECK-NEXT:  entry:
580; CHECK-NEXT:    br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]]
581; CHECK:       A:
582; CHECK-NEXT:    [[I_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[B]] ]
583; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[I_0]]
584; CHECK-NEXT:    br label [[B]]
585; CHECK:       B:
586; CHECK-NEXT:    [[J_0:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[I_0]], [[A]] ]
587; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[J_0]]
588; CHECK-NEXT:    store i16 2, ptr [[ARRAYIDX]], align 1
589; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[J_0]], 1
590; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i16 [[J_0]], 4
591; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[A]]
592; CHECK:       exit:
593; CHECK-NEXT:    store i16 1, ptr [[ARRAYIDX]], align 1
594; CHECK-NEXT:    ret i16 0
595;
596entry:
597  br i1 %c, label %A, label %B
598
599A:
600  %i.0 = phi i16 [ 0, %entry ], [ %inc, %B ]
601  %arrayidx2 = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %i.0
602  br label %B
603
604B:
605  %j.0 = phi i16 [ 0, %entry ], [ %i.0, %A ]
606  %arrayidx = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %j.0
607  store i16 2, ptr %arrayidx, align 1
608  %inc = add nuw nsw i16 %j.0, 1
609  %exitcond = icmp eq i16 %j.0, 4
610  br i1 %exitcond, label %exit, label %A
611
612exit:
613  store i16 1, ptr %arrayidx, align 1
614  ret i16 0
615}
616
617define i16 @irreducible_entryblock_def(i1 %c) {
618; CHECK-LABEL: @irreducible_entryblock_def(
619; CHECK-NEXT:  entry:
620; CHECK-NEXT:    br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]]
621; CHECK:       A:
622; CHECK-NEXT:    br label [[B]]
623; CHECK:       B:
624; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[A]]
625; CHECK:       exit:
626; CHECK-NEXT:    ret i16 0
627;
628entry:
629  %obj = alloca i32, align 4
630  br i1 %c, label %A, label %B
631
632A:
633  store i32 1, ptr %obj, align 4
634  br label %B
635
636B:
637  br i1 %c, label %exit, label %A
638
639exit:
640  ret i16 0
641}
642
643; An irreducible loop inside another loop.
644define i16 @irreducible_nested() {
645; CHECK-LABEL: @irreducible_nested(
646; CHECK-NEXT:  entry:
647; CHECK-NEXT:    br label [[OUTER:%.*]]
648; CHECK:       outer:
649; CHECK-NEXT:    [[X:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INCX:%.*]], [[OUTERL:%.*]] ]
650; CHECK-NEXT:    [[C:%.*]] = icmp sgt i16 [[X]], 2
651; CHECK-NEXT:    br i1 [[C]], label [[A:%.*]], label [[B:%.*]]
652; CHECK:       A:
653; CHECK-NEXT:    [[I_0:%.*]] = phi i16 [ 0, [[OUTER]] ], [ [[INC:%.*]], [[B]] ]
654; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[I_0]]
655; CHECK-NEXT:    br label [[B]]
656; CHECK:       B:
657; CHECK-NEXT:    [[J_0:%.*]] = phi i16 [ 0, [[OUTER]] ], [ [[I_0]], [[A]] ]
658; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[J_0]]
659; CHECK-NEXT:    store i16 2, ptr [[ARRAYIDX]], align 1
660; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[J_0]], 1
661; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i16 [[J_0]], 4
662; CHECK-NEXT:    br i1 [[EXITCOND]], label [[OUTERL]], label [[A]]
663; CHECK:       outerl:
664; CHECK-NEXT:    store i16 1, ptr [[ARRAYIDX]], align 1
665; CHECK-NEXT:    [[INCX]] = add nuw nsw i16 [[X]], 1
666; CHECK-NEXT:    [[EXITCONDX:%.*]] = icmp eq i16 [[X]], 4
667; CHECK-NEXT:    br i1 [[EXITCONDX]], label [[END:%.*]], label [[OUTER]]
668; CHECK:       end:
669; CHECK-NEXT:    ret i16 0
670;
671entry:
672  br label %outer
673
674outer:
675  %x = phi i16 [ 0, %entry ], [ %incx, %outerl ]
676  %c = icmp sgt i16 %x, 2
677  br i1 %c, label %A, label %B
678
679A:
680  %i.0 = phi i16 [ 0, %outer ], [ %inc, %B ]
681  %arrayidx2 = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %i.0
682  br label %B
683
684B:
685  %j.0 = phi i16 [ 0, %outer ], [ %i.0, %A ]
686  %arrayidx = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %j.0
687  store i16 2, ptr %arrayidx, align 1
688  %inc = add nuw nsw i16 %j.0, 1
689  %exitcond = icmp eq i16 %j.0, 4
690  br i1 %exitcond, label %outerl, label %A
691
692outerl:
693  store i16 1, ptr %arrayidx, align 1
694  %incx = add nuw nsw i16 %x, 1
695  %exitcondx = icmp eq i16 %x, 4
696  br i1 %exitcondx, label %end, label %outer
697
698end:
699  ret i16 0
700}
701
702define i16 @multi_overwrite(i1 %cond) {
703; CHECK-LABEL: @multi_overwrite(
704; CHECK-NEXT:  entry:
705; CHECK-NEXT:    br label [[DO_BODY:%.*]]
706; CHECK:       do.body:
707; CHECK-NEXT:    [[I_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[IF_END2:%.*]] ]
708; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[I_0]]
709; CHECK-NEXT:    store i16 2, ptr [[ARRAYIDX2]], align 1
710; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i16 [[I_0]], 4
711; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[IF_END:%.*]]
712; CHECK:       if.end:
713; CHECK-NEXT:    br i1 [[COND:%.*]], label [[DO_STORE:%.*]], label [[IF_END2]]
714; CHECK:       do.store:
715; CHECK-NEXT:    store i16 3, ptr [[ARRAYIDX2]], align 1
716; CHECK-NEXT:    br label [[IF_END2]]
717; CHECK:       if.end2:
718; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[I_0]], 1
719; CHECK-NEXT:    br label [[DO_BODY]]
720; CHECK:       exit:
721; CHECK-NEXT:    store i16 1, ptr [[ARRAYIDX2]], align 1
722; CHECK-NEXT:    ret i16 0
723;
724entry:
725  br label %do.body
726
727do.body:
728  %i.0 = phi i16 [ 0, %entry ], [ %inc, %if.end2 ]
729  %arrayidx2 = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %i.0
730  store i16 2, ptr %arrayidx2, align 1
731  %exitcond = icmp eq i16 %i.0, 4
732  br i1 %exitcond, label %exit, label %if.end
733
734if.end:
735  br i1 %cond, label %do.store, label %if.end2
736
737do.store:
738  store i16 3, ptr %arrayidx2, align 1
739  br label %if.end2
740
741if.end2:
742  %inc = add nuw nsw i16 %i.0, 1
743  br label %do.body
744
745exit:
746  store i16 1, ptr %arrayidx2, align 1
747  ret i16 0
748}
749
750define void @test(ptr noalias %data1, ptr %data2, ptr %data3, i32 %i1)
751; CHECK-LABEL: @test(
752; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[I1:%.*]], 0
753; CHECK-NEXT:    br label [[PH0:%.*]]
754; CHECK:       ph0:
755; CHECK-NEXT:    br label [[HEADER0:%.*]]
756; CHECK:       header0:
757; CHECK-NEXT:    [[P1:%.*]] = phi i32 [ 0, [[PH0]] ], [ [[PN1:%.*]], [[END1:%.*]] ]
758; CHECK-NEXT:    [[PN1]] = add i32 [[P1]], 1
759; CHECK-NEXT:    [[PC1:%.*]] = icmp slt i32 [[PN1]], 5
760; CHECK-NEXT:    [[V2:%.*]] = getelementptr [10 x i16], ptr @x, i32 0, i32 [[P1]]
761; CHECK-NEXT:    store i16 1, ptr [[V2]], align 2
762; CHECK-NEXT:    br i1 [[C]], label [[THEN1:%.*]], label [[ELSE1:%.*]]
763; CHECK:       then1:
764; CHECK-NEXT:    store i16 2, ptr [[V2]], align 2
765; CHECK-NEXT:    br label [[END1]]
766; CHECK:       else1:
767; CHECK-NEXT:    br label [[END1]]
768; CHECK:       end1:
769; CHECK-NEXT:    br i1 [[PC1]], label [[HEADER0]], label [[END0:%.*]]
770; CHECK:       end0:
771; CHECK-NEXT:    br label [[HEADER2:%.*]]
772; CHECK:       header2:
773; CHECK-NEXT:    [[P3:%.*]] = phi i32 [ 0, [[END0]] ], [ [[PN3:%.*]], [[HEADER2]] ]
774; CHECK-NEXT:    [[PN3]] = add i32 [[P3]], 1
775; CHECK-NEXT:    [[PC3:%.*]] = icmp slt i32 [[PN3]], 5
776; CHECK-NEXT:    store i16 4, ptr [[V2]], align 2
777; CHECK-NEXT:    br i1 [[PC3]], label [[HEADER2]], label [[END2:%.*]]
778; CHECK:       end2:
779; CHECK-NEXT:    ret void
780;
781{
782  %c = icmp eq i32 %i1, 0
783  br label %ph0
784ph0:
785  br label %header0
786header0:
787  %p1 = phi i32 [0, %ph0], [%pn1, %end1]
788  %pn1 = add i32 %p1, 1
789  %pc1 = icmp slt i32 %pn1, 5
790  %v2 = getelementptr [10 x i16], ptr @x, i32 0, i32 %p1
791  store i16 1, ptr %v2
792  br i1 %c, label %then1, label %else1
793then1:
794  store i16 2, ptr %v2
795  br label %end1
796else1:
797  br label %end1
798end1:
799  br i1 %pc1, label %header0, label %end0
800end0:
801  br label %header2
802header2:
803  %p3 = phi i32 [0, %end0], [%pn3, %header2]
804  %pn3 = add i32 %p3, 1
805  %pc3 = icmp slt i32 %pn3, 5
806  store i16 4, ptr %v2
807  br i1 %pc3, label %header2, label %end2
808end2:
809  ret void
810}
811
812; Similar to above, but with multiple partial overlaps
813define i16 @partial_override_fromloop(i1 %c, i32 %i) {
814; CHECK-LABEL: @partial_override_fromloop(
815; CHECK-NEXT:  entry:
816; CHECK-NEXT:    br label [[DO_BODY:%.*]]
817; CHECK:       do.body:
818; CHECK-NEXT:    [[I_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[IF_END2:%.*]] ]
819; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[I_0]]
820; CHECK-NEXT:    store i16 2, ptr [[ARRAYIDX2]], align 1
821; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i16 [[I_0]], 4
822; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[IF_END:%.*]]
823; CHECK:       if.end:
824; CHECK-NEXT:    br i1 [[C:%.*]], label [[DO_STORE:%.*]], label [[IF_END2]]
825; CHECK:       do.store:
826; CHECK-NEXT:    store i16 3, ptr [[ARRAYIDX2]], align 1
827; CHECK-NEXT:    br label [[IF_END2]]
828; CHECK:       if.end2:
829; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[I_0]], 1
830; CHECK-NEXT:    br label [[DO_BODY]]
831; CHECK:       exit:
832; CHECK-NEXT:    [[BC2:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX2]], i32 1
833; CHECK-NEXT:    store i8 10, ptr [[ARRAYIDX2]], align 1
834; CHECK-NEXT:    store i8 11, ptr [[BC2]], align 1
835; CHECK-NEXT:    ret i16 0
836;
837entry:
838  br label %do.body
839
840do.body:
841  %i.0 = phi i16 [ 0, %entry ], [ %inc, %if.end2 ]
842  %arrayidx2 = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %i.0
843  store i16 2, ptr %arrayidx2, align 1
844  %exitcond = icmp eq i16 %i.0, 4
845  br i1 %exitcond, label %exit, label %if.end
846
847if.end:
848  br i1 %c, label %do.store, label %if.end2
849
850do.store:
851  store i16 3, ptr %arrayidx2, align 1
852  br label %if.end2
853
854if.end2:
855  %inc = add nuw nsw i16 %i.0, 1
856  br label %do.body
857
858exit:
859  %bc2 = getelementptr inbounds i8, ptr %arrayidx2, i32 1
860  store i8 10, ptr %arrayidx2, align 1
861  store i8 11, ptr %bc2, align 1
862  ret i16 0
863}
864
865
866define i16 @partial_override_overloop(i1 %c, i32 %i) {
867; CHECK-LABEL: @partial_override_overloop(
868; CHECK-NEXT:  entry:
869; CHECK-NEXT:    br label [[FIRST:%.*]]
870; CHECK:       first:
871; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i32 [[I:%.*]]
872; CHECK-NEXT:    br label [[DO_BODY:%.*]]
873; CHECK:       do.body:
874; CHECK-NEXT:    [[I_0:%.*]] = phi i16 [ 0, [[FIRST]] ], [ [[INC:%.*]], [[DO_BODY]] ]
875; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[I_0]]
876; CHECK-NEXT:    store i16 2, ptr [[ARRAYIDX2]], align 1
877; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i16 [[I_0]], 4
878; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[I_0]], 1
879; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[DO_BODY]]
880; CHECK:       exit:
881; CHECK-NEXT:    [[BC2:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX]], i32 1
882; CHECK-NEXT:    store i8 10, ptr [[ARRAYIDX]], align 1
883; CHECK-NEXT:    store i8 11, ptr [[BC2]], align 1
884; CHECK-NEXT:    ret i16 0
885;
886entry:
887  ; Branch to first so MemoryLoc is not in the entry block.
888  br label %first
889
890first:
891  %arrayidx = getelementptr inbounds [10 x i16], ptr @x, i16 0, i32 %i
892  store i16 1, ptr %arrayidx, align 1
893  br label %do.body
894
895do.body:
896  %i.0 = phi i16 [ 0, %first ], [ %inc, %do.body ]
897  %arrayidx2 = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %i.0
898  store i16 2, ptr %arrayidx2, align 1
899  %exitcond = icmp eq i16 %i.0, 4
900  %inc = add nuw nsw i16 %i.0, 1
901  br i1 %exitcond, label %exit, label %do.body
902
903exit:
904  %bc2 = getelementptr inbounds i8, ptr %arrayidx, i32 1
905  store i8 10, ptr %arrayidx, align 1
906  store i8 11, ptr %bc2, align 1
907  ret i16 0
908}
909
910define i16 @partial_override_multi(i1 %c, i32 %i) {
911; CHECK-LABEL: @partial_override_multi(
912; CHECK-NEXT:  entry:
913; CHECK-NEXT:    br label [[DO_BODY:%.*]]
914; CHECK:       do.body:
915; CHECK-NEXT:    [[I_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[DO_BODY]] ]
916; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 [[I_0]]
917; CHECK-NEXT:    store i16 10, ptr [[ARRAYIDX2]], align 1
918; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i16 [[I_0]], 4
919; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[I_0]], 1
920; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[DO_BODY]]
921; CHECK:       exit:
922; CHECK-NEXT:    [[BC2:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX2]], i32 1
923; CHECK-NEXT:    store i8 11, ptr [[BC2]], align 1
924; CHECK-NEXT:    ret i16 0
925;
926entry:
927  br label %do.body
928
929do.body:
930  %i.0 = phi i16 [ 0, %entry ], [ %inc, %do.body ]
931  %arrayidx2 = getelementptr inbounds [10 x i16], ptr @x, i16 0, i16 %i.0
932  store i16 2, ptr %arrayidx2, align 1
933  store i8 10, ptr %arrayidx2, align 1
934  %exitcond = icmp eq i16 %i.0, 4
935  %inc = add nuw nsw i16 %i.0, 1
936  br i1 %exitcond, label %exit, label %do.body
937
938exit:
939  %bc2 = getelementptr inbounds i8, ptr %arrayidx2, i32 1
940  store i8 11, ptr %bc2, align 1
941  ret i16 0
942}
943
944define void @InitializeMasks(ptr %p) {
945; CHECK-LABEL: @InitializeMasks(
946; CHECK-NEXT:  entry:
947; CHECK-NEXT:    br label [[FOR_BODY98:%.*]]
948; CHECK:       for.body98:
949; CHECK-NEXT:    [[INDVARS_IV377:%.*]] = phi i64 [ 8, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[FOR_INC140:%.*]] ], [ [[INC1:%.*]], [[FOR_INC140_THREAD:%.*]] ]
950; CHECK-NEXT:    [[ARRAYIDX106:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 [[INDVARS_IV377]]
951; CHECK-NEXT:    store i64 1, ptr [[ARRAYIDX106]], align 8
952; CHECK-NEXT:    [[CMP107:%.*]] = icmp ugt i64 [[INDVARS_IV377]], 15
953; CHECK-NEXT:    br i1 [[CMP107]], label [[IF_END:%.*]], label [[IF_END_THREAD:%.*]]
954; CHECK:       if.end.thread:
955; CHECK-NEXT:    br label [[FOR_INC140_THREAD]]
956; CHECK:       if.end:
957; CHECK-NEXT:    store i64 2, ptr [[ARRAYIDX106]], align 8
958; CHECK-NEXT:    [[CMP127:%.*]] = icmp ult i64 [[INDVARS_IV377]], 48
959; CHECK-NEXT:    br i1 [[CMP127]], label [[FOR_INC140_THREAD]], label [[FOR_INC140]]
960; CHECK:       for.inc140.thread:
961; CHECK-NEXT:    [[INC1]] = add i64 [[INDVARS_IV377]], 1
962; CHECK-NEXT:    br label [[FOR_BODY98]]
963; CHECK:       for.inc140:
964; CHECK-NEXT:    [[INC2]] = add i64 [[INDVARS_IV377]], 1
965; CHECK-NEXT:    [[EXITCOND384_NOT:%.*]] = icmp eq i64 [[INDVARS_IV377]], 56
966; CHECK-NEXT:    br i1 [[EXITCOND384_NOT]], label [[FOR_INC177:%.*]], label [[FOR_BODY98]]
967; CHECK:       for.inc177:
968; CHECK-NEXT:    ret void
969;
970entry:
971  br label %for.body98
972
973for.body98:                                       ; preds = %for.inc140, %for.inc140.thread, %entry
974  %indvars.iv377 = phi i64 [ 8, %entry ], [ %inc2, %for.inc140 ], [ %inc1, %for.inc140.thread ]
975  %arrayidx106 = getelementptr inbounds i64, ptr %p, i64 %indvars.iv377
976  store i64 1, ptr %arrayidx106, align 8
977  %cmp107 = icmp ugt i64 %indvars.iv377, 15
978  br i1 %cmp107, label %if.end, label %if.end.thread
979
980if.end.thread:                                    ; preds = %for.body98
981  br label %for.inc140.thread
982
983if.end:                                           ; preds = %for.body98
984  store i64 2, ptr %arrayidx106, align 8
985  %cmp127 = icmp ult i64 %indvars.iv377, 48
986  br i1 %cmp127, label %for.inc140.thread, label %for.inc140
987
988for.inc140.thread:                                ; preds = %if.end, %if.end.thread
989  %inc1 = add i64 %indvars.iv377, 1
990  br label %for.body98
991
992for.inc140:                                       ; preds = %if.end
993  %inc2 = add i64 %indvars.iv377, 1
994  %exitcond384.not = icmp eq i64 %indvars.iv377, 56
995  br i1 %exitcond384.not, label %for.inc177, label %for.body98
996
997for.inc177:                                       ; preds = %for.inc140
998  ret void
999}
1000