Skip to content

Commit 0f607f3

Browse files
committed
[VPlan] Simplify 'or x, true' -> true.
Add additional OR simplification to fix a divergence between legacy and VPlan-based cost model. This adds a new m_AllOnes matcher by generalizing specific_intval to int_pred_ty, which takes a predicate to check to support matching both specific APInts and other APInt predices, like isAllOnes. Fixes #131359.
1 parent 09588e9 commit 0f607f3

File tree

4 files changed

+258
-12
lines changed

4 files changed

+258
-12
lines changed

llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,15 @@ struct deferredval_ty {
8484
/// whichever value m_VPValue(X) populated.
8585
inline deferredval_ty m_Deferred(VPValue *const &V) { return V; }
8686

87-
/// Match a specified integer value or vector of all elements of that
88-
/// value. \p BitWidth optionally specifies the bitwidth the matched constant
89-
/// must have. If it is 0, the matched constant can have any bitwidth.
90-
template <unsigned BitWidth = 0> struct specific_intval {
91-
APInt Val;
87+
/// Match an integer constant or vector of constants if Pred::isValue returns
88+
/// true for the APInt. \p BitWidth optionally specifies the bitwidth the
89+
/// matched constant must have. If it is 0, the matched constant can have any
90+
/// bitwidth.
91+
template <typename Pred, unsigned BitWidth = 0> struct int_pred_ty {
92+
Pred P;
9293

93-
specific_intval(APInt V) : Val(std::move(V)) {}
94+
int_pred_ty(Pred P) : P(std::move(P)) {}
95+
int_pred_ty() : P() {}
9496

9597
bool match(VPValue *VPV) const {
9698
if (!VPV->isLiveIn())
@@ -108,17 +110,45 @@ template <unsigned BitWidth = 0> struct specific_intval {
108110

109111
if (BitWidth != 0 && CI->getBitWidth() != BitWidth)
110112
return false;
111-
return APInt::isSameValue(CI->getValue(), Val);
113+
return P.isValue(CI->getValue());
112114
}
113115
};
114116

117+
/// Match a specified integer value or vector of all elements of that
118+
/// value. \p BitWidth optionally specifies the bitwidth the matched constant
119+
/// must have. If it is 0, the matched constant can have any bitwidth.
120+
struct is_specific_int {
121+
APInt Val;
122+
123+
is_specific_int(APInt Val) : Val(std::move(Val)) {}
124+
125+
bool isValue(const APInt &C) const { return APInt::isSameValue(Val, C); }
126+
};
127+
128+
template <unsigned Bitwidth = 0>
129+
using specific_intval = int_pred_ty<is_specific_int, Bitwidth>;
130+
115131
inline specific_intval<0> m_SpecificInt(uint64_t V) {
116-
return specific_intval<0>(APInt(64, V));
132+
return specific_intval<0>(is_specific_int(APInt(64, V)));
117133
}
118134

119-
inline specific_intval<1> m_False() { return specific_intval<1>(APInt(64, 0)); }
135+
inline specific_intval<1> m_False() {
136+
return specific_intval<1>(is_specific_int(APInt(64, 0)));
137+
}
120138

121-
inline specific_intval<1> m_True() { return specific_intval<1>(APInt(64, 1)); }
139+
inline specific_intval<1> m_True() {
140+
return specific_intval<1>(is_specific_int(APInt(64, 1)));
141+
}
142+
143+
struct is_all_ones {
144+
bool isValue(const APInt &C) const { return C.isAllOnes(); }
145+
};
146+
147+
/// Match an integer or vector with all bits set.
148+
/// For vectors, this includes constants with undefined elements.
149+
inline int_pred_ty<is_all_ones> m_AllOnes() {
150+
return int_pred_ty<is_all_ones>();
151+
}
122152

123153
/// Matching combinators
124154
template <typename LTy, typename RTy> struct match_combine_or {

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,13 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
994994
return;
995995
}
996996

997+
if (match(&R, m_c_BinaryOr(m_VPValue(X), m_AllOnes()))) {
998+
R.getVPSingleValue()->replaceAllUsesWith(
999+
R.getOperand(0) == Y ? R.getOperand(1) : R.getOperand(0));
1000+
R.eraseFromParent();
1001+
return;
1002+
}
1003+
9971004
if (match(&R, m_Select(m_VPValue(), m_VPValue(X), m_Deferred(X))))
9981005
return R.getVPSingleValue()->replaceAllUsesWith(X);
9991006

llvm/test/Transforms/LoopVectorize/SystemZ/pr47665.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ define void @test(ptr %p, i40 %a) {
1515
; CHECK-NEXT: [[TMP4:%.*]] = trunc <16 x i32> [[TMP3]] to <16 x i1>
1616
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <16 x i1> [[TMP4]], zeroinitializer
1717
; CHECK-NEXT: [[TMP6:%.*]] = icmp ult <16 x i1> zeroinitializer, [[TMP5]]
18-
; CHECK-NEXT: [[TMP7:%.*]] = or <16 x i1> [[TMP6]], splat (i1 true)
19-
; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt <16 x i1> [[TMP7]], zeroinitializer
18+
; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt <16 x i1> [[TMP6]], zeroinitializer
2019
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
2120
; CHECK: vector.body:
2221
; CHECK-NEXT: br i1 true, label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]]

llvm/test/Transforms/LoopVectorize/X86/constant-fold.ll

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,213 @@ bb2:
5858
bb3:
5959
ret void
6060
}
61+
62+
; Test case for https://github.com/llvm/llvm-project/issues/131359.
63+
define void @redundant_or_1(ptr %dst, i1 %c.0, i1 %c.1) {
64+
; CHECK-LABEL: @redundant_or_1(
65+
; CHECK-NEXT: entry:
66+
; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
67+
; CHECK: vector.ph:
68+
; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[C_0:%.*]], i64 0
69+
; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer
70+
; CHECK-NEXT: [[TMP0:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true)
71+
; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i1> poison, i1 [[C_1:%.*]], i64 0
72+
; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT1]], <4 x i1> poison, <4 x i32> zeroinitializer
73+
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
74+
; CHECK: vector.body:
75+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE8:%.*]] ]
76+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i32> [ <i32 0, i32 1, i32 2, i32 3>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[PRED_STORE_CONTINUE8]] ]
77+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ule <4 x i32> [[VEC_IND]], splat (i32 2)
78+
; CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x i1> [[TMP0]], <4 x i1> zeroinitializer
79+
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <4 x i32> [[VEC_IND]], splat (i32 2)
80+
; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP3]], <4 x i1> [[BROADCAST_SPLAT2]], <4 x i1> zeroinitializer
81+
; CHECK-NEXT: [[TMP5:%.*]] = select <4 x i1> [[TMP2]], <4 x i1> [[TMP4]], <4 x i1> zeroinitializer
82+
; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[TMP5]], i32 0
83+
; CHECK-NEXT: br i1 [[TMP6]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]]
84+
; CHECK: pred.store.if:
85+
; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[INDEX]], 0
86+
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i32 [[TMP7]]
87+
; CHECK-NEXT: store i32 0, ptr [[TMP8]], align 4
88+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]]
89+
; CHECK: pred.store.continue:
90+
; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i1> [[TMP5]], i32 1
91+
; CHECK-NEXT: br i1 [[TMP9]], label [[PRED_STORE_IF3:%.*]], label [[PRED_STORE_CONTINUE4:%.*]]
92+
; CHECK: pred.store.if3:
93+
; CHECK-NEXT: [[TMP10:%.*]] = add i32 [[INDEX]], 1
94+
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[TMP10]]
95+
; CHECK-NEXT: store i32 0, ptr [[TMP11]], align 4
96+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE4]]
97+
; CHECK: pred.store.continue4:
98+
; CHECK-NEXT: [[TMP12:%.*]] = extractelement <4 x i1> [[TMP5]], i32 2
99+
; CHECK-NEXT: br i1 [[TMP12]], label [[PRED_STORE_IF5:%.*]], label [[PRED_STORE_CONTINUE6:%.*]]
100+
; CHECK: pred.store.if5:
101+
; CHECK-NEXT: [[TMP13:%.*]] = add i32 [[INDEX]], 2
102+
; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[TMP13]]
103+
; CHECK-NEXT: store i32 0, ptr [[TMP14]], align 4
104+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE6]]
105+
; CHECK: pred.store.continue6:
106+
; CHECK-NEXT: [[TMP15:%.*]] = extractelement <4 x i1> [[TMP5]], i32 3
107+
; CHECK-NEXT: br i1 [[TMP15]], label [[PRED_STORE_IF7:%.*]], label [[PRED_STORE_CONTINUE8]]
108+
; CHECK: pred.store.if7:
109+
; CHECK-NEXT: [[TMP16:%.*]] = add i32 [[INDEX]], 3
110+
; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[TMP16]]
111+
; CHECK-NEXT: store i32 0, ptr [[TMP17]], align 4
112+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE8]]
113+
; CHECK: pred.store.continue8:
114+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i32> [[VEC_IND]], splat (i32 4)
115+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4
116+
; CHECK-NEXT: br i1 true, label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]]
117+
; CHECK: middle.block:
118+
; CHECK-NEXT: br label [[EXIT:%.*]]
119+
; CHECK: scalar.ph:
120+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
121+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
122+
; CHECK: loop.header:
123+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
124+
; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[THEN_1:%.*]]
125+
; CHECK: then.1:
126+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[IV]], 2
127+
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP]], true
128+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR]], i1 [[C_1]], i1 false
129+
; CHECK-NEXT: br i1 [[COND]], label [[THEN_2:%.*]], label [[LOOP_LATCH]]
130+
; CHECK: then.2:
131+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[IV]]
132+
; CHECK-NEXT: store i32 0, ptr [[GEP]], align 4
133+
; CHECK-NEXT: br label [[LOOP_LATCH]]
134+
; CHECK: loop.latch:
135+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
136+
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV_NEXT]], 3
137+
; CHECK-NEXT: br i1 [[EC]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP4:![0-9]+]]
138+
; CHECK: exit:
139+
; CHECK-NEXT: ret void
140+
;
141+
entry:
142+
br label %loop.header
143+
144+
loop.header:
145+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
146+
br i1 %c.0, label %loop.latch, label %then.1
147+
148+
then.1:
149+
%cmp = icmp eq i32 %iv, 2
150+
%or = or i1 %cmp, true
151+
%cond = select i1 %or, i1 %c.1, i1 false
152+
br i1 %cond, label %then.2, label %loop.latch
153+
154+
then.2:
155+
%gep = getelementptr inbounds i32, ptr %dst, i32 %iv
156+
store i32 0, ptr %gep, align 4
157+
br label %loop.latch
158+
159+
loop.latch:
160+
%iv.next = add nuw nsw i32 %iv, 1
161+
%ec = icmp eq i32 %iv.next, 3
162+
br i1 %ec, label %exit, label %loop.header
163+
164+
exit:
165+
ret void
166+
}
167+
168+
define void @redundant_or_2(ptr %dst, i1 %c.0, i1 %c.1) {
169+
; CHECK-LABEL: @redundant_or_2(
170+
; CHECK-NEXT: entry:
171+
; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
172+
; CHECK: vector.ph:
173+
; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[C_1:%.*]], i64 0
174+
; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer
175+
; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i1> poison, i1 [[C_0:%.*]], i64 0
176+
; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT1]], <4 x i1> poison, <4 x i32> zeroinitializer
177+
; CHECK-NEXT: [[TMP0:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT2]], splat (i1 true)
178+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 true, <4 x i1> [[BROADCAST_SPLAT]], <4 x i1> zeroinitializer
179+
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
180+
; CHECK: vector.body:
181+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE8:%.*]] ]
182+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i8> [ <i8 0, i8 1, i8 2, i8 3>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[PRED_STORE_CONTINUE8]] ]
183+
; CHECK-NEXT: [[TMP2:%.*]] = icmp ule <4 x i8> [[VEC_IND]], splat (i8 2)
184+
; CHECK-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i1> [[TMP0]], <4 x i1> zeroinitializer
185+
; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP3]], <4 x i1> [[TMP1]], <4 x i1> zeroinitializer
186+
; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i1> [[TMP4]], i32 0
187+
; CHECK-NEXT: br i1 [[TMP5]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]]
188+
; CHECK: pred.store.if:
189+
; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[INDEX]], 0
190+
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i32 [[TMP6]]
191+
; CHECK-NEXT: store i32 0, ptr [[TMP7]], align 4
192+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]]
193+
; CHECK: pred.store.continue:
194+
; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP4]], i32 1
195+
; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF3:%.*]], label [[PRED_STORE_CONTINUE4:%.*]]
196+
; CHECK: pred.store.if3:
197+
; CHECK-NEXT: [[TMP9:%.*]] = add i32 [[INDEX]], 1
198+
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[TMP9]]
199+
; CHECK-NEXT: store i32 0, ptr [[TMP10]], align 4
200+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE4]]
201+
; CHECK: pred.store.continue4:
202+
; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[TMP4]], i32 2
203+
; CHECK-NEXT: br i1 [[TMP11]], label [[PRED_STORE_IF5:%.*]], label [[PRED_STORE_CONTINUE6:%.*]]
204+
; CHECK: pred.store.if5:
205+
; CHECK-NEXT: [[TMP12:%.*]] = add i32 [[INDEX]], 2
206+
; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[TMP12]]
207+
; CHECK-NEXT: store i32 0, ptr [[TMP13]], align 4
208+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE6]]
209+
; CHECK: pred.store.continue6:
210+
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <4 x i1> [[TMP4]], i32 3
211+
; CHECK-NEXT: br i1 [[TMP14]], label [[PRED_STORE_IF7:%.*]], label [[PRED_STORE_CONTINUE8]]
212+
; CHECK: pred.store.if7:
213+
; CHECK-NEXT: [[TMP15:%.*]] = add i32 [[INDEX]], 3
214+
; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[TMP15]]
215+
; CHECK-NEXT: store i32 0, ptr [[TMP16]], align 4
216+
; CHECK-NEXT: br label [[PRED_STORE_CONTINUE8]]
217+
; CHECK: pred.store.continue8:
218+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i8> [[VEC_IND]], splat (i8 4)
219+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4
220+
; CHECK-NEXT: br i1 true, label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
221+
; CHECK: middle.block:
222+
; CHECK-NEXT: br label [[EXIT:%.*]]
223+
; CHECK: scalar.ph:
224+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
225+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
226+
; CHECK: loop.header:
227+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
228+
; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[THEN_1:%.*]]
229+
; CHECK: then.1:
230+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[IV]], 2
231+
; CHECK-NEXT: [[OR:%.*]] = or i1 true, [[CMP]]
232+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR]], i1 [[C_1]], i1 false
233+
; CHECK-NEXT: br i1 [[COND]], label [[THEN_2:%.*]], label [[LOOP_LATCH]]
234+
; CHECK: then.2:
235+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[IV]]
236+
; CHECK-NEXT: store i32 0, ptr [[GEP]], align 4
237+
; CHECK-NEXT: br label [[LOOP_LATCH]]
238+
; CHECK: loop.latch:
239+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
240+
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV_NEXT]], 3
241+
; CHECK-NEXT: br i1 [[EC]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP6:![0-9]+]]
242+
; CHECK: exit:
243+
; CHECK-NEXT: ret void
244+
;
245+
entry:
246+
br label %loop.header
247+
248+
loop.header:
249+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
250+
br i1 %c.0, label %loop.latch, label %then.1
251+
252+
then.1:
253+
%cmp = icmp eq i32 %iv, 2
254+
%or = or i1 true, %cmp
255+
%cond = select i1 %or, i1 %c.1, i1 false
256+
br i1 %cond, label %then.2, label %loop.latch
257+
258+
then.2:
259+
%gep = getelementptr inbounds i32, ptr %dst, i32 %iv
260+
store i32 0, ptr %gep, align 4
261+
br label %loop.latch
262+
263+
loop.latch:
264+
%iv.next = add nuw nsw i32 %iv, 1
265+
%ec = icmp eq i32 %iv.next, 3
266+
br i1 %ec, label %exit, label %loop.header
267+
268+
exit:
269+
ret void
270+
}

0 commit comments

Comments
 (0)