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