Skip to content

Commit 30b16ec

Browse files
committed
[VPlan] Simplify trivial VPFirstOrderRecurrencePHI recipes.
VPFirstOrderRecurrencePHIRecipes where the incoming values are the same can be simplified and removed. Fixes #144212. The new test is added together with other related tests from first-order-recurrence.ll
1 parent a383b1a commit 30b16ec

File tree

3 files changed

+276
-452
lines changed

3 files changed

+276
-452
lines changed

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,12 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
11411141
return;
11421142
}
11431143

1144+
if (auto *Phi = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(Def)) {
1145+
if (Phi->getOperand(0) == Phi->getOperand(1))
1146+
Def->replaceAllUsesWith(Phi->getOperand(0));
1147+
return;
1148+
}
1149+
11441150
// Some simplifications can only be applied after unrolling. Perform them
11451151
// below.
11461152
if (!Plan->isUnrolled())
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 5
2+
; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=2 -S %s | FileCheck %s
3+
4+
; Test case for https://github.com/llvm/llvm-project/issues/144212.
5+
define i8 @recurrence_phi_with_same_incoming_values_after_simplifications(i8 %for.start, ptr %dst) {
6+
; CHECK-LABEL: define i8 @recurrence_phi_with_same_incoming_values_after_simplifications(
7+
; CHECK-SAME: i8 [[FOR_START:%.*]], ptr [[DST:%.*]]) {
8+
; CHECK-NEXT: [[ENTRY:.*]]:
9+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
10+
; CHECK: [[VECTOR_SCEVCHECK]]:
11+
; CHECK-NEXT: br i1 true, label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]]
12+
; CHECK: [[VECTOR_PH]]:
13+
; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i8> poison, i8 [[FOR_START]], i64 0
14+
; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i8> [[BROADCAST_SPLATINSERT]], <4 x i8> poison, <4 x i32> zeroinitializer
15+
; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x i8> [[BROADCAST_SPLAT]], <4 x i8> [[BROADCAST_SPLAT]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
16+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
17+
; CHECK: [[VECTOR_BODY]]:
18+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
19+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i32 1, [[INDEX]]
20+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[DST]], i32 [[OFFSET_IDX]]
21+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i32 0
22+
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i32 4
23+
; CHECK-NEXT: store <4 x i8> [[TMP0]], ptr [[TMP2]], align 1
24+
; CHECK-NEXT: store <4 x i8> [[TMP0]], ptr [[TMP3]], align 1
25+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 8
26+
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[INDEX_NEXT]], -8
27+
; CHECK-NEXT: br i1 [[TMP4]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
28+
; CHECK: [[MIDDLE_BLOCK]]:
29+
; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i8> [[BROADCAST_SPLAT]], i32 3
30+
; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i8> [[BROADCAST_SPLAT]], i32 3
31+
; CHECK-NEXT: br i1 false, label %[[EXIT:.*]], label %[[SCALAR_PH]]
32+
; CHECK: [[SCALAR_PH]]:
33+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ -7, %[[MIDDLE_BLOCK]] ], [ 1, %[[ENTRY]] ], [ 1, %[[VECTOR_SCEVCHECK]] ]
34+
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT]], %[[MIDDLE_BLOCK]] ], [ [[FOR_START]], %[[ENTRY]] ], [ [[FOR_START]], %[[VECTOR_SCEVCHECK]] ]
35+
; CHECK-NEXT: br label %[[LOOP:.*]]
36+
; CHECK: [[LOOP]]:
37+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
38+
; CHECK-NEXT: [[FOR:%.*]] = phi i8 [ [[SCALAR_RECUR_INIT]], %[[SCALAR_PH]] ], [ [[FOR_NEXT:%.*]], %[[LOOP]] ]
39+
; CHECK-NEXT: [[FOR_NEXT]] = and i8 [[FOR_START]], -1
40+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
41+
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i8, ptr [[DST]], i32 [[IV]]
42+
; CHECK-NEXT: store i8 [[FOR]], ptr [[GEP_DST]], align 1
43+
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV_NEXT]], 0
44+
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]]
45+
; CHECK: [[EXIT]]:
46+
; CHECK-NEXT: [[FOR_NEXT_LCSSA:%.*]] = phi i8 [ [[FOR_NEXT]], %[[LOOP]] ], [ [[TMP5]], %[[MIDDLE_BLOCK]] ]
47+
; CHECK-NEXT: ret i8 [[FOR_NEXT_LCSSA]]
48+
;
49+
entry:
50+
br label %loop
51+
52+
loop:
53+
%iv = phi i32 [ 1, %entry ], [ %iv.next, %loop ]
54+
%for = phi i8 [ %for.start, %entry ], [ %for.next, %loop ]
55+
%for.next = and i8 %for.start, -1
56+
%iv.next = add i32 %iv, 1
57+
%gep.dst = getelementptr inbounds i8, ptr %dst, i32 %iv
58+
store i8 %for, ptr %gep.dst
59+
%ec = icmp eq i32 %iv.next, 0
60+
br i1 %ec, label %exit, label %loop
61+
62+
exit:
63+
ret i8 %for.next
64+
}
65+
66+
; %vec.dead will be marked as dead instruction in the vector loop and no recipe
67+
; will be created for it. Make sure a valid sink target is used.
68+
define i32 @sink_after_dead_inst(ptr %A.ptr) {
69+
; CHECK-LABEL: define i32 @sink_after_dead_inst(
70+
; CHECK-SAME: ptr [[A_PTR:%.*]]) {
71+
; CHECK-NEXT: [[ENTRY:.*]]:
72+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
73+
; CHECK: [[VECTOR_PH]]:
74+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
75+
; CHECK: [[VECTOR_BODY]]:
76+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
77+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i16> [ <i16 0, i16 1, i16 2, i16 3>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY]] ]
78+
; CHECK-NEXT: [[STEP_ADD:%.*]] = add <4 x i16> [[VEC_IND]], splat (i16 4)
79+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = trunc i32 [[INDEX]] to i16
80+
; CHECK-NEXT: [[TMP0:%.*]] = add <4 x i16> [[STEP_ADD]], splat (i16 1)
81+
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i16> [[TMP0]], [[TMP0]]
82+
; CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
83+
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[A_PTR]], i16 [[OFFSET_IDX]]
84+
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[TMP3]], i32 0
85+
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[TMP3]], i32 4
86+
; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr [[TMP4]], align 4
87+
; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr [[TMP5]], align 4
88+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 8
89+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i16> [[STEP_ADD]], splat (i16 4)
90+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], 16
91+
; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
92+
; CHECK: [[MIDDLE_BLOCK]]:
93+
; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i32> [[TMP2]], i32 2
94+
; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i32> [[TMP2]], i32 3
95+
; CHECK-NEXT: br i1 true, label %[[FOR_END:.*]], label %[[SCALAR_PH]]
96+
; CHECK: [[SCALAR_PH]]:
97+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i16 [ 16, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
98+
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i32 [ [[VECTOR_RECUR_EXTRACT]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
99+
; CHECK-NEXT: br label %[[LOOP:.*]]
100+
; CHECK: [[LOOP]]:
101+
; CHECK-NEXT: [[IV:%.*]] = phi i16 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
102+
; CHECK-NEXT: [[FOR:%.*]] = phi i32 [ [[SCALAR_RECUR_INIT]], %[[SCALAR_PH]] ], [ [[FOR_PREV:%.*]], %[[LOOP]] ]
103+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[FOR]], 15
104+
; CHECK-NEXT: [[C:%.*]] = icmp eq i1 [[CMP]], true
105+
; CHECK-NEXT: [[VEC_DEAD:%.*]] = and i1 [[C]], true
106+
; CHECK-NEXT: [[IV_NEXT]] = add i16 [[IV]], 1
107+
; CHECK-NEXT: [[B1:%.*]] = or i16 [[IV_NEXT]], [[IV_NEXT]]
108+
; CHECK-NEXT: [[B3:%.*]] = and i1 [[CMP]], [[C]]
109+
; CHECK-NEXT: [[FOR_PREV]] = zext i16 [[B1]] to i32
110+
; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[B3]] to i32
111+
; CHECK-NEXT: [[A_GEP:%.*]] = getelementptr i32, ptr [[A_PTR]], i16 [[IV]]
112+
; CHECK-NEXT: store i32 0, ptr [[A_GEP]], align 4
113+
; CHECK-NEXT: br i1 [[VEC_DEAD]], label %[[FOR_END]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]]
114+
; CHECK: [[FOR_END]]:
115+
; CHECK-NEXT: [[FOR_LCSSA:%.*]] = phi i32 [ [[FOR]], %[[LOOP]] ], [ [[VECTOR_RECUR_EXTRACT_FOR_PHI]], %[[MIDDLE_BLOCK]] ]
116+
; CHECK-NEXT: ret i32 [[FOR_LCSSA]]
117+
;
118+
entry:
119+
br label %loop
120+
121+
loop:
122+
%iv = phi i16 [ 0, %entry ], [ %iv.next, %loop ]
123+
%for = phi i32 [ 0, %entry ], [ %for.prev, %loop ]
124+
%cmp = icmp eq i32 %for, 15
125+
%C = icmp eq i1 %cmp, true
126+
%vec.dead = and i1 %C, 1
127+
%iv.next = add i16 %iv, 1
128+
%B1 = or i16 %iv.next, %iv.next
129+
%B3 = and i1 %cmp, %C
130+
%for.prev = zext i16 %B1 to i32
131+
132+
%ext = zext i1 %B3 to i32
133+
%A.gep = getelementptr i32, ptr %A.ptr, i16 %iv
134+
store i32 0, ptr %A.gep
135+
br i1 %vec.dead, label %for.end, label %loop
136+
137+
for.end:
138+
ret i32 %for
139+
}
140+
141+
; Dead instructions, like the exit condition are not part of the actual VPlan
142+
; and do not need to be sunk. PR44634.
143+
define void @sink_dead_inst(ptr %a) {
144+
; CHECK-LABEL: define void @sink_dead_inst(
145+
; CHECK-SAME: ptr [[A:%.*]]) {
146+
; CHECK-NEXT: [[ENTRY:.*]]:
147+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
148+
; CHECK: [[VECTOR_PH]]:
149+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
150+
; CHECK: [[VECTOR_BODY]]:
151+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
152+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i16> [ <i16 -27, i16 -26, i16 -25, i16 -24>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY]] ]
153+
; CHECK-NEXT: [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 0>, %[[VECTOR_PH]] ], [ [[TMP4:%.*]], %[[VECTOR_BODY]] ]
154+
; CHECK-NEXT: [[STEP_ADD:%.*]] = add <4 x i16> [[VEC_IND]], splat (i16 4)
155+
; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16
156+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 -27, [[DOTCAST]]
157+
; CHECK-NEXT: [[TMP0:%.*]] = add <4 x i16> [[VEC_IND]], splat (i16 1)
158+
; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i16> [[STEP_ADD]], splat (i16 1)
159+
; CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
160+
; CHECK-NEXT: [[TMP3:%.*]] = add <4 x i16> [[TMP0]], splat (i16 5)
161+
; CHECK-NEXT: [[TMP4]] = add <4 x i16> [[TMP1]], splat (i16 5)
162+
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[TMP3]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
163+
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i16> [[TMP3]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
164+
; CHECK-NEXT: [[TMP7:%.*]] = sub <4 x i16> [[TMP5]], splat (i16 10)
165+
; CHECK-NEXT: [[TMP8:%.*]] = sub <4 x i16> [[TMP6]], splat (i16 10)
166+
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i16, ptr [[A]], i16 [[OFFSET_IDX]]
167+
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i16, ptr [[TMP9]], i32 0
168+
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i16, ptr [[TMP9]], i32 4
169+
; CHECK-NEXT: store <4 x i16> [[TMP7]], ptr [[TMP10]], align 2
170+
; CHECK-NEXT: store <4 x i16> [[TMP8]], ptr [[TMP11]], align 2
171+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 8
172+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i16> [[STEP_ADD]], splat (i16 4)
173+
; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[INDEX_NEXT]], 40
174+
; CHECK-NEXT: br i1 [[TMP12]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
175+
; CHECK: [[MIDDLE_BLOCK]]:
176+
; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
177+
; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT1:%.*]] = extractelement <4 x i32> [[TMP2]], i32 3
178+
; CHECK-NEXT: br i1 false, label %[[FOR_END:.*]], label %[[SCALAR_PH]]
179+
; CHECK: [[SCALAR_PH]]:
180+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i16 [ 13, %[[MIDDLE_BLOCK]] ], [ -27, %[[ENTRY]] ]
181+
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i16 [ [[VECTOR_RECUR_EXTRACT]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
182+
; CHECK-NEXT: [[SCALAR_RECUR_INIT2:%.*]] = phi i32 [ [[VECTOR_RECUR_EXTRACT1]], %[[MIDDLE_BLOCK]] ], [ -27, %[[ENTRY]] ]
183+
; CHECK-NEXT: br label %[[FOR_COND:.*]]
184+
; CHECK: [[FOR_COND]]:
185+
; CHECK-NEXT: [[IV:%.*]] = phi i16 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[FOR_COND]] ]
186+
; CHECK-NEXT: [[REC_1:%.*]] = phi i16 [ [[SCALAR_RECUR_INIT]], %[[SCALAR_PH]] ], [ [[REC_1_PREV:%.*]], %[[FOR_COND]] ]
187+
; CHECK-NEXT: [[REC_2:%.*]] = phi i32 [ [[SCALAR_RECUR_INIT2]], %[[SCALAR_PH]] ], [ [[REC_2_PREV:%.*]], %[[FOR_COND]] ]
188+
; CHECK-NEXT: [[USE_REC_1:%.*]] = sub i16 [[REC_1]], 10
189+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REC_2]], 15
190+
; CHECK-NEXT: [[IV_NEXT]] = add i16 [[IV]], 1
191+
; CHECK-NEXT: [[REC_2_PREV]] = zext i16 [[IV_NEXT]] to i32
192+
; CHECK-NEXT: [[REC_1_PREV]] = add i16 [[IV_NEXT]], 5
193+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[A]], i16 [[IV]]
194+
; CHECK-NEXT: store i16 [[USE_REC_1]], ptr [[GEP]], align 2
195+
; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_END]], label %[[FOR_COND]], !llvm.loop [[LOOP7:![0-9]+]]
196+
; CHECK: [[FOR_END]]:
197+
; CHECK-NEXT: ret void
198+
;
199+
entry:
200+
br label %for.cond
201+
202+
for.cond:
203+
%iv = phi i16 [ -27, %entry ], [ %iv.next, %for.cond ]
204+
%rec.1 = phi i16 [ 0, %entry ], [ %rec.1.prev, %for.cond ]
205+
%rec.2 = phi i32 [ -27, %entry ], [ %rec.2.prev, %for.cond ]
206+
%use.rec.1 = sub i16 %rec.1, 10
207+
%cmp = icmp eq i32 %rec.2, 15
208+
%iv.next = add i16 %iv, 1
209+
%rec.2.prev = zext i16 %iv.next to i32
210+
%rec.1.prev = add i16 %iv.next, 5
211+
%gep = getelementptr i16, ptr %a, i16 %iv
212+
store i16 %use.rec.1, ptr %gep
213+
br i1 %cmp, label %for.end, label %for.cond
214+
215+
for.end:
216+
ret void
217+
}
218+
219+
; %rec.1 only has %use.rec.1 as use, which can be removed. This enables %rec.1
220+
; to be removed also.
221+
define void @unused_recurrence(ptr %a) {
222+
; CHECK-LABEL: define void @unused_recurrence(
223+
; CHECK-SAME: ptr [[A:%.*]]) {
224+
; CHECK-NEXT: [[ENTRY:.*]]:
225+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
226+
; CHECK: [[VECTOR_PH]]:
227+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
228+
; CHECK: [[VECTOR_BODY]]:
229+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
230+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i16> [ <i16 -27, i16 -26, i16 -25, i16 -24>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY]] ]
231+
; CHECK-NEXT: [[STEP_ADD:%.*]] = add <4 x i16> [[VEC_IND]], splat (i16 4)
232+
; CHECK-NEXT: [[TMP0:%.*]] = add <4 x i16> [[STEP_ADD]], splat (i16 1)
233+
; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i16> [[TMP0]], splat (i16 5)
234+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 8
235+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i16> [[STEP_ADD]], splat (i16 4)
236+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[INDEX_NEXT]], 1024
237+
; CHECK-NEXT: br i1 [[TMP2]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]
238+
; CHECK: [[MIDDLE_BLOCK]]:
239+
; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[TMP1]], i32 3
240+
; CHECK-NEXT: br i1 false, label %[[FOR_END:.*]], label %[[SCALAR_PH]]
241+
; CHECK: [[SCALAR_PH]]:
242+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i16 [ 997, %[[MIDDLE_BLOCK]] ], [ -27, %[[ENTRY]] ]
243+
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i16 [ [[VECTOR_RECUR_EXTRACT]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
244+
; CHECK-NEXT: br label %[[FOR_COND:.*]]
245+
; CHECK: [[FOR_COND]]:
246+
; CHECK-NEXT: [[IV:%.*]] = phi i16 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[FOR_COND]] ]
247+
; CHECK-NEXT: [[REC_1:%.*]] = phi i16 [ [[SCALAR_RECUR_INIT]], %[[SCALAR_PH]] ], [ [[REC_1_PREV:%.*]], %[[FOR_COND]] ]
248+
; CHECK-NEXT: [[USE_REC_1:%.*]] = sub i16 [[REC_1]], 10
249+
; CHECK-NEXT: [[IV_NEXT]] = add i16 [[IV]], 1
250+
; CHECK-NEXT: [[REC_1_PREV]] = add i16 [[IV_NEXT]], 5
251+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[IV]], 1000
252+
; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_END]], label %[[FOR_COND]], !llvm.loop [[LOOP9:![0-9]+]]
253+
; CHECK: [[FOR_END]]:
254+
; CHECK-NEXT: ret void
255+
;
256+
entry:
257+
br label %for.cond
258+
259+
for.cond:
260+
%iv = phi i16 [ -27, %entry ], [ %iv.next, %for.cond ]
261+
%rec.1 = phi i16 [ 0, %entry ], [ %rec.1.prev, %for.cond ]
262+
%use.rec.1 = sub i16 %rec.1, 10
263+
%iv.next= add i16 %iv, 1
264+
%rec.1.prev = add i16 %iv.next, 5
265+
%cmp = icmp eq i16 %iv, 1000
266+
br i1 %cmp, label %for.end, label %for.cond
267+
268+
for.end:
269+
ret void
270+
}

0 commit comments

Comments
 (0)