Skip to content

Commit 60a890d

Browse files
committed
[LoopPeel] Add pre-commit test for min/max intrinsics
1 parent de32a3d commit 60a890d

File tree

1 file changed

+257
-0
lines changed

1 file changed

+257
-0
lines changed
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt < %s -S -passes=loop-unroll -unroll-peel-max-count=3 | FileCheck %s
3+
4+
declare void @foo(i32)
5+
declare void @bar(i8)
6+
7+
define void @test_umin(i32 %N) {
8+
; CHECK-LABEL: define void @test_umin(
9+
; CHECK-SAME: i32 [[N:%.*]]) {
10+
; CHECK-NEXT: entry:
11+
; CHECK-NEXT: [[CMP5_NOT:%.*]] = icmp eq i32 [[N]], 0
12+
; CHECK-NEXT: br i1 [[CMP5_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
13+
; CHECK: for.body.preheader:
14+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
15+
; CHECK: for.body:
16+
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
17+
; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.umin.i32(i32 [[I_06]], i32 2)
18+
; CHECK-NEXT: tail call void @foo(i32 [[COND]])
19+
; CHECK-NEXT: [[INC]] = add nuw i32 [[I_06]], 1
20+
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]]
21+
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
22+
; CHECK: for.cond.cleanup.loopexit:
23+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
24+
; CHECK: for.cond.cleanup:
25+
; CHECK-NEXT: ret void
26+
;
27+
entry:
28+
%cmp5.not = icmp eq i32 %N, 0
29+
br i1 %cmp5.not, label %for.cond.cleanup, label %for.body
30+
31+
for.body:
32+
%i.06 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
33+
%cond = tail call i32 @llvm.umin.i32(i32 %i.06, i32 2)
34+
tail call void @foo(i32 %cond)
35+
%inc = add nuw i32 %i.06, 1
36+
%exitcond.not = icmp eq i32 %inc, %N
37+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
38+
39+
for.cond.cleanup:
40+
ret void
41+
}
42+
43+
define void @test_umax(i32 %N) {
44+
; CHECK-LABEL: define void @test_umax(
45+
; CHECK-SAME: i32 [[N:%.*]]) {
46+
; CHECK-NEXT: entry:
47+
; CHECK-NEXT: [[CMP5_NOT:%.*]] = icmp eq i32 [[N]], 0
48+
; CHECK-NEXT: br i1 [[CMP5_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
49+
; CHECK: for.body.preheader:
50+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
51+
; CHECK: for.body:
52+
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
53+
; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.umax.i32(i32 [[I_06]], i32 2)
54+
; CHECK-NEXT: tail call void @foo(i32 [[COND]])
55+
; CHECK-NEXT: [[INC]] = add nuw i32 [[I_06]], 1
56+
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]]
57+
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
58+
; CHECK: for.cond.cleanup.loopexit:
59+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
60+
; CHECK: for.cond.cleanup:
61+
; CHECK-NEXT: ret void
62+
;
63+
entry:
64+
%cmp5.not = icmp eq i32 %N, 0
65+
br i1 %cmp5.not, label %for.cond.cleanup, label %for.body
66+
67+
for.body:
68+
%i.06 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
69+
%cond = tail call i32 @llvm.umax.i32(i32 %i.06, i32 2)
70+
tail call void @foo(i32 %cond)
71+
%inc = add nuw i32 %i.06, 1
72+
%exitcond.not = icmp eq i32 %inc, %N
73+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
74+
75+
for.cond.cleanup:
76+
ret void
77+
}
78+
79+
define void @test_smax(i32 %N) {
80+
; CHECK-LABEL: define void @test_smax(
81+
; CHECK-SAME: i32 [[N:%.*]]) {
82+
; CHECK-NEXT: entry:
83+
; CHECK-NEXT: [[CMP5:%.*]] = icmp slt i32 [[N]], 0
84+
; CHECK-NEXT: br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
85+
; CHECK: for.body.preheader:
86+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
87+
; CHECK: for.body:
88+
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ [[DEC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
89+
; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I_06]], i32 -2)
90+
; CHECK-NEXT: tail call void @foo(i32 [[COND]])
91+
; CHECK-NEXT: [[DEC]] = add nsw i32 [[I_06]], -1
92+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC]], [[N]]
93+
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
94+
; CHECK: for.cond.cleanup.loopexit:
95+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
96+
; CHECK: for.cond.cleanup:
97+
; CHECK-NEXT: ret void
98+
;
99+
entry:
100+
%cmp5 = icmp slt i32 %N, 0
101+
br i1 %cmp5, label %for.body, label %for.cond.cleanup
102+
103+
for.body:
104+
%i.06 = phi i32 [ %dec, %for.body ], [ 0, %entry ]
105+
%cond = tail call i32 @llvm.smax.i32(i32 %i.06, i32 -2)
106+
tail call void @foo(i32 %cond)
107+
%dec = add nsw i32 %i.06, -1
108+
%cmp = icmp sgt i32 %dec, %N
109+
br i1 %cmp, label %for.body, label %for.cond.cleanup
110+
111+
for.cond.cleanup:
112+
ret void
113+
}
114+
115+
define void @test_smin(i32 %N) {
116+
; CHECK-LABEL: define void @test_smin(
117+
; CHECK-SAME: i32 [[N:%.*]]) {
118+
; CHECK-NEXT: entry:
119+
; CHECK-NEXT: [[CMP5:%.*]] = icmp slt i32 [[N]], 0
120+
; CHECK-NEXT: br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
121+
; CHECK: for.body.preheader:
122+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
123+
; CHECK: for.body:
124+
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ [[DEC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
125+
; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.smin.i32(i32 [[I_06]], i32 -2)
126+
; CHECK-NEXT: tail call void @foo(i32 noundef signext [[COND]])
127+
; CHECK-NEXT: [[DEC]] = add nsw i32 [[I_06]], -1
128+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC]], [[N]]
129+
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
130+
; CHECK: for.cond.cleanup.loopexit:
131+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
132+
; CHECK: for.cond.cleanup:
133+
; CHECK-NEXT: ret void
134+
;
135+
entry:
136+
%cmp5 = icmp slt i32 %N, 0
137+
br i1 %cmp5, label %for.body, label %for.cond.cleanup
138+
139+
for.body:
140+
%i.06 = phi i32 [ %dec, %for.body ], [ 0, %entry ]
141+
%cond = tail call i32 @llvm.smin.i32(i32 %i.06, i32 -2)
142+
tail call void @foo(i32 noundef signext %cond)
143+
%dec = add nsw i32 %i.06, -1
144+
%cmp = icmp sgt i32 %dec, %N
145+
br i1 %cmp, label %for.body, label %for.cond.cleanup
146+
147+
for.cond.cleanup:
148+
ret void
149+
}
150+
151+
define void @test_negative(i32 %End, i32 %Step) {
152+
; CHECK-LABEL: define void @test_negative(
153+
; CHECK-SAME: i32 [[END:%.*]], i32 [[STEP:%.*]]) {
154+
; CHECK-NEXT: entry:
155+
; CHECK-NEXT: [[CMP_NOT5:%.*]] = icmp eq i32 [[END]], 0
156+
; CHECK-NEXT: br i1 [[CMP_NOT5]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
157+
; CHECK: for.body.preheader:
158+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
159+
; CHECK: for.body:
160+
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
161+
; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.smin.i32(i32 [[I_06]], i32 2)
162+
; CHECK-NEXT: tail call void @foo(i32 [[COND]])
163+
; CHECK-NEXT: [[ADD]] = add nsw i32 [[I_06]], [[STEP]]
164+
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[ADD]], [[END]]
165+
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
166+
; CHECK: for.cond.cleanup.loopexit:
167+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
168+
; CHECK: for.cond.cleanup:
169+
; CHECK-NEXT: ret void
170+
;
171+
entry:
172+
%cmp.not5 = icmp eq i32 %End, 0
173+
br i1 %cmp.not5, label %for.cond.cleanup, label %for.body
174+
175+
for.body:
176+
%i.06 = phi i32 [ %add, %for.body ], [ 0, %entry ]
177+
%cond = tail call i32 @llvm.smin.i32(i32 %i.06, i32 2)
178+
tail call void @foo(i32 %cond)
179+
%add = add nsw i32 %i.06, %Step
180+
%cmp.not = icmp eq i32 %add, %End
181+
br i1 %cmp.not, label %for.cond.cleanup, label %for.body
182+
183+
for.cond.cleanup:
184+
ret void
185+
}
186+
187+
define void @test_max_count_threshold(i32 %N) {
188+
; CHECK-LABEL: define void @test_max_count_threshold(
189+
; CHECK-SAME: i32 [[N:%.*]]) {
190+
; CHECK-NEXT: entry:
191+
; CHECK-NEXT: [[CMP5_NOT:%.*]] = icmp eq i32 [[N]], 0
192+
; CHECK-NEXT: br i1 [[CMP5_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
193+
; CHECK: for.body.preheader:
194+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
195+
; CHECK: for.body:
196+
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
197+
; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.umin.i32(i32 [[I_06]], i32 5)
198+
; CHECK-NEXT: tail call void @foo(i32 [[COND]])
199+
; CHECK-NEXT: [[INC]] = add nuw i32 [[I_06]], 1
200+
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]]
201+
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
202+
; CHECK: for.cond.cleanup.loopexit:
203+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
204+
; CHECK: for.cond.cleanup:
205+
; CHECK-NEXT: ret void
206+
;
207+
entry:
208+
%cmp5.not = icmp eq i32 %N, 0
209+
br i1 %cmp5.not, label %for.cond.cleanup, label %for.body
210+
211+
for.body:
212+
%i.06 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
213+
%cond = tail call i32 @llvm.umin.i32(i32 %i.06, i32 5)
214+
tail call void @foo(i32 %cond)
215+
%inc = add nuw i32 %i.06, 1
216+
%exitcond.not = icmp eq i32 %inc, %N
217+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
218+
219+
for.cond.cleanup:
220+
ret void
221+
}
222+
223+
define void @test_wrap(i8 %N) {
224+
; CHECK-LABEL: define void @test_wrap(
225+
; CHECK-SAME: i8 [[N:%.*]]) {
226+
; CHECK-NEXT: entry:
227+
; CHECK-NEXT: [[CMP5_NOT:%.*]] = icmp eq i8 [[N]], 0
228+
; CHECK-NEXT: br i1 [[CMP5_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
229+
; CHECK: for.body.preheader:
230+
; CHECK-NEXT: br label [[FOR_BODY1:%.*]]
231+
; CHECK: for.body:
232+
; CHECK-NEXT: [[I_06:%.*]] = phi i8 [ [[INC1:%.*]], [[FOR_BODY1]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
233+
; CHECK-NEXT: [[COND1:%.*]] = tail call i8 @llvm.umin.i8(i8 [[I_06]], i8 -2)
234+
; CHECK-NEXT: tail call void @bar(i8 [[COND1]])
235+
; CHECK-NEXT: [[INC1]] = add i8 [[I_06]], 127
236+
; CHECK-NEXT: [[EXITCOND_NOT1:%.*]] = icmp eq i8 [[INC1]], [[N]]
237+
; CHECK-NEXT: br i1 [[EXITCOND_NOT1]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY1]]
238+
; CHECK: for.cond.cleanup.loopexit:
239+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
240+
; CHECK: for.cond.cleanup:
241+
; CHECK-NEXT: ret void
242+
;
243+
entry:
244+
%cmp5.not = icmp eq i8 %N, 0
245+
br i1 %cmp5.not, label %for.cond.cleanup, label %for.body
246+
247+
for.body:
248+
%i.06 = phi i8 [ %inc, %for.body ], [ 0, %entry ]
249+
%cond = tail call i8 @llvm.umin.i8(i8 %i.06, i8 254)
250+
tail call void @bar(i8 %cond)
251+
%inc = add i8 %i.06, 127
252+
%exitcond.not = icmp eq i8 %inc, %N
253+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
254+
255+
for.cond.cleanup:
256+
ret void
257+
}

0 commit comments

Comments
 (0)