xref: /llvm-project/llvm/test/CodeGen/BPF/sink-min-max.ll (revision 18e13739b8c02e0b82e3e587c33e8731c8a46b0a)
1; RUN: opt --bpf-check-and-opt-ir -S -mtriple=bpf-pc-linux %s | FileCheck %s
2
3; Test plan:
4; @test1: x <  umin(i64 a, i64 b)
5; @test2: x <  umax(i64 a, i64 b)
6; @test3: x >= umin(i64 a, i64 b)
7; @test4: x >= umax(i64 a, i64 b)
8; @test5: umin(i64 a, i64 b) >= x
9; @test6: x <  smin(i64 a, i64 b)
10; @test7: x <  umin(i32 a, i32 b)
11; @test8: x <  zext i64 umin(i32 a, i32 b)
12; @test9: x <  sext i64 umin(i32 a, i32 b)
13; @test10: check that umin belonging to the same loop is not touched
14; @test11: check that nested loops are processed
15
16define i32 @test1(i64 %a, i64 %b, i64 %x) {
17entry:
18  %min = tail call i64 @llvm.umin.i64(i64 %a, i64 %b)
19  br label %loop
20loop:
21  %cmp = icmp ult i64 %x, %min
22  br i1 %cmp, label %loop, label %ret
23ret: ret i32 0
24}
25
26; CHECK:       @test1
27; CHECK-NEXT:  entry:
28; CHECK-NEXT:    br label %loop
29; CHECK-EMPTY:
30; CHECK-NEXT:  loop:
31; CHECK-NEXT:    %0 = icmp ult i64 %x, %a
32; CHECK-NEXT:    %1 = icmp ult i64 %x, %b
33; CHECK-NEXT:    %2 = select i1 %0, i1 %1, i1 false
34; CHECK-NEXT:    br i1 %2, label %loop, label %ret
35
36define i32 @test2(i64 %a, i64 %b, i64 %x) {
37entry:
38  %max = tail call i64 @llvm.umax.i64(i64 %a, i64 %b)
39  br label %loop
40loop:
41  %cmp = icmp ult i64 %x, %max
42  br i1 %cmp, label %loop, label %ret
43ret: ret i32 0
44}
45
46; CHECK:       @test2
47; CHECK-NEXT:  entry:
48; CHECK-NEXT:    br label %loop
49; CHECK-EMPTY:
50; CHECK-NEXT:  loop:
51; CHECK-NEXT:    %0 = icmp ult i64 %x, %a
52; CHECK-NEXT:    %1 = icmp ult i64 %x, %b
53; CHECK-NEXT:    %2 = select i1 %0, i1 true, i1 %1
54; CHECK-NEXT:    br i1 %2, label %loop, label %ret
55
56define i32 @test3(i64 %a, i64 %b, i64 %x) {
57entry:
58  %min = tail call i64 @llvm.umin.i64(i64 %a, i64 %b)
59  br label %loop
60loop:
61  %cmp = icmp uge i64 %x, %min
62  br i1 %cmp, label %loop, label %ret
63ret: ret i32 0
64}
65
66; CHECK:       @test3
67; CHECK-NEXT:  entry:
68; CHECK-NEXT:    br label %loop
69; CHECK-EMPTY:
70; CHECK-NEXT:  loop:
71; CHECK-NEXT:    %0 = icmp uge i64 %x, %a
72; CHECK-NEXT:    %1 = icmp uge i64 %x, %b
73; CHECK-NEXT:    %2 = select i1 %0, i1 true, i1 %1
74; CHECK-NEXT:    br i1 %2, label %loop, label %ret
75
76define i32 @test4(i64 %a, i64 %b, i64 %x) {
77entry:
78  %max = tail call i64 @llvm.umax.i64(i64 %a, i64 %b)
79  br label %loop
80loop:
81  %cmp = icmp uge i64 %x, %max
82  br i1 %cmp, label %loop, label %ret
83ret: ret i32 0
84}
85
86; CHECK:       @test4
87; CHECK-NEXT:  entry:
88; CHECK-NEXT:    br label %loop
89; CHECK-EMPTY:
90; CHECK-NEXT:  loop:
91; CHECK-NEXT:    %0 = icmp uge i64 %x, %a
92; CHECK-NEXT:    %1 = icmp uge i64 %x, %b
93; CHECK-NEXT:    %2 = select i1 %0, i1 %1, i1 false
94; CHECK-NEXT:    br i1 %2, label %loop, label %ret
95
96define i32 @test5(i64 %a, i64 %b, i64 %x) {
97entry:
98  %min = tail call i64 @llvm.umin.i64(i64 %a, i64 %b)
99  br label %loop
100loop:
101  %cmp = icmp uge i64 %min, %x
102  br i1 %cmp, label %loop, label %ret
103ret: ret i32 0
104}
105
106; CHECK:       @test5
107; CHECK-NEXT:  entry:
108; CHECK-NEXT:    br label %loop
109; CHECK-EMPTY:
110; CHECK-NEXT:  loop:
111; CHECK:         %0 = icmp ule i64 %x, %a
112; CHECK-NEXT:    %1 = icmp ule i64 %x, %b
113; CHECK-NEXT:    %2 = select i1 %0, i1 %1, i1 false
114; CHECK-NEXT:    br i1 %2, label %loop, label %ret
115
116define i32 @test6(i64 %a, i64 %b, i64 %x) {
117entry:
118  %min = tail call i64 @llvm.smin.i64(i64 %a, i64 %b)
119  br label %loop
120loop:
121  %cmp = icmp slt i64 %x, %min
122  br i1 %cmp, label %loop, label %ret
123ret: ret i32 0
124}
125
126; CHECK:       @test6
127; CHECK-NEXT:  entry:
128; CHECK-NEXT:    br label %loop
129; CHECK-EMPTY:
130; CHECK-NEXT:  loop:
131; CHECK:         %0 = icmp slt i64 %x, %a
132; CHECK-NEXT:    %1 = icmp slt i64 %x, %b
133; CHECK-NEXT:    %2 = select i1 %0, i1 %1, i1 false
134; CHECK-NEXT:    br i1 %2, label %loop, label %ret
135
136define i32 @test7(i32 %a, i32 %b, i32 %x) {
137entry:
138  %min = tail call i32 @llvm.umin.i32(i32 %a, i32 %b)
139  br label %loop
140loop:
141  %cmp = icmp ult i32 %x, %min
142  br i1 %cmp, label %loop, label %ret
143ret: ret i32 0
144}
145
146; CHECK:       @test7
147; CHECK-NEXT:  entry:
148; CHECK-NEXT:    br label %loop
149; CHECK-EMPTY:
150; CHECK-NEXT:  loop:
151; CHECK:         %0 = icmp ult i32 %x, %a
152; CHECK-NEXT:    %1 = icmp ult i32 %x, %b
153; CHECK-NEXT:    %2 = select i1 %0, i1 %1, i1 false
154; CHECK-NEXT:    br i1 %2, label %loop, label %ret
155
156define i32 @test8(i32 %a, i32 %b, i64 %x) {
157entry:
158  %min = tail call i32 @llvm.umin.i32(i32 %a, i32 %b)
159  br label %loop
160loop:
161  %ext = zext i32 %min to i64
162  %cmp = icmp ult i64 %x, %ext
163  br i1 %cmp, label %loop, label %ret
164ret: ret i32 0
165}
166
167; CHECK:       @test8
168; CHECK-NEXT:  entry:
169; CHECK-NEXT:    br label %loop
170; CHECK-EMPTY:
171; CHECK-NEXT:  loop:
172; CHECK-NEXT:    %0 = zext i32 %a to i64
173; CHECK-NEXT:    %1 = zext i32 %b to i64
174; CHECK-NEXT:    %2 = icmp ult i64 %x, %0
175; CHECK-NEXT:    %3 = icmp ult i64 %x, %1
176; CHECK-NEXT:    %4 = select i1 %2, i1 %3, i1 false
177; CHECK-NEXT:    br i1 %4, label %loop, label %ret
178
179define i32 @test9(i32 %a, i32 %b, i64 %x) {
180entry:
181  %min = tail call i32 @llvm.umin.i32(i32 %a, i32 %b)
182  br label %loop
183loop:
184  %ext = sext i32 %min to i64
185  %cmp = icmp ult i64 %x, %ext
186  br i1 %cmp, label %loop, label %ret
187ret: ret i32 0
188}
189
190; CHECK:       @test9
191; CHECK-NEXT:  entry:
192; CHECK-NEXT:    br label %loop
193; CHECK-EMPTY:
194; CHECK-NEXT:  loop:
195; CHECK-NEXT:    %0 = sext i32 %a to i64
196; CHECK-NEXT:    %1 = sext i32 %b to i64
197; CHECK-NEXT:    %2 = icmp ult i64 %x, %0
198; CHECK-NEXT:    %3 = icmp ult i64 %x, %1
199; CHECK-NEXT:    %4 = select i1 %2, i1 %3, i1 false
200; CHECK-NEXT:    br i1 %4, label %loop, label %ret
201
202; umin within the loop body is unchanged
203define i32 @test10(i64 %a, i64 %b, i64 %x) {
204entry:
205  br label %loop
206loop:
207  %min = tail call i64 @llvm.umin.i64(i64 %a, i64 %b)
208  %cmp = icmp ult i64 %x, %min
209  br i1 %cmp, label %loop, label %ret
210ret: ret i32 0
211}
212
213; CHECK:       @test10
214; CHECK-NEXT:  entry:
215; CHECK-NEXT:    br label %loop
216; CHECK-EMPTY:
217; CHECK-NEXT:  loop:
218; CHECK-NEXT:    %min = tail call i64 @llvm.umin.i64(i64 %a, i64 %b)
219; CHECK-NEXT:    %cmp = icmp ult i64 %x, %min
220; CHECK-NEXT:    br i1 %cmp, label %loop, label %ret
221
222; umin from outer loop body is processed
223define i32 @test11(i64 %a, i64 %b, i64 %x) {
224entry:
225  br label %loop
226
227loop:
228  %min = tail call i64 @llvm.umin.i64(i64 %a, i64 %b)
229  br label %nested.loop
230nested.loop:
231  %cmp = icmp ult i64 %x, %min
232  br i1 %cmp, label %nested.loop, label %loop
233
234ret: ret i32 0
235}
236
237; CHECK:       @test11
238; CHECK-NEXT:  entry:
239; CHECK-NEXT:    br label %loop
240; CHECK-EMPTY:
241; CHECK-NEXT:  loop:
242; CHECK-NEXT:    br label %nested.loop
243; CHECK-EMPTY:
244; CHECK-NEXT:  nested.loop:
245; CHECK-NEXT:    %0 = icmp ult i64 %x, %a
246; CHECK-NEXT:    %1 = icmp ult i64 %x, %b
247; CHECK-NEXT:    %2 = select i1 %0, i1 %1, i1 false
248; CHECK-NEXT:    br i1 %2, label %nested.loop, label %loop
249
250declare i64 @llvm.umin.i64(i64, i64)
251declare i64 @llvm.smin.i64(i64, i64)
252declare i64 @llvm.umax.i64(i64, i64)
253declare i64 @llvm.smax.i64(i64, i64)
254
255declare i32 @llvm.umin.i32(i32, i32)
256declare i32 @llvm.smin.i32(i32, i32)
257declare i32 @llvm.umax.i32(i32, i32)
258declare i32 @llvm.smax.i32(i32, i32)
259