1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes='loop-mssa(loop-predication)' -loop-predication-insert-assumes-of-predicated-guards-conditions=false < %s 2>&1 | FileCheck %s 3 4define i32 @test_ult(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 5; CHECK-LABEL: @test_ult( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0:![0-9]+]], !noundef !1 8; CHECK-NEXT: br label [[LOOP:%.*]] 9; CHECK: loop: 10; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 11; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 12; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 13; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 14; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 15; CHECK: do_range_check: 16; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 17; CHECK-NEXT: [[RANGE_CHECK_ULT:%.*]] = icmp ult i32 [[EL]], [[LEN]] 18; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 19; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_ULT]], [[WC]] 20; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 21; CHECK: backedge: 22; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 23; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 24; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 25; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]] 26; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 27; CHECK: deopt: 28; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 29; CHECK-NEXT: ret i32 [[DEOPT_RES]] 30; CHECK: exit: 31; CHECK-NEXT: ret i32 0 32; CHECK: bound_check_failed: 33; CHECK-NEXT: ret i32 -1 34; 35entry: 36 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 37 br label %loop 38 39loop: 40 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 41 %el.ptr = getelementptr i32, ptr %p, i32 %iv 42 %el = load i32, ptr %el.ptr, align 4 43 %bound_check = icmp ult i32 %el, 128 44 br i1 %bound_check, label %do_range_check, label %bound_check_failed 45 46do_range_check: 47 call void @llvm.assume(i1 %bound_check) 48 %range_check.ult = icmp ult i32 %el, %len 49 %wc = call i1 @llvm.experimental.widenable.condition() 50 %explicit_guard_cond = and i1 %range_check.ult, %wc 51 br i1 %explicit_guard_cond, label %backedge, label %deopt 52 53backedge: 54 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 55 store i32 %iv, ptr %arr.ptr, align 4 56 %iv.next = add i32 %iv, 1 57 %loop_cond = icmp slt i32 %iv.next, %n 58 br i1 %loop_cond, label %loop, label %exit 59 60deopt: 61 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 62 ret i32 %deopt_res 63 64exit: 65 ret i32 0 66 67bound_check_failed: 68 ret i32 -1 69} 70 71define i32 @test_slt(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 72; CHECK-LABEL: @test_slt( 73; CHECK-NEXT: entry: 74; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 75; CHECK-NEXT: br label [[LOOP:%.*]] 76; CHECK: loop: 77; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 78; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 79; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 80; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 81; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 82; CHECK: do_range_check: 83; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 84; CHECK-NEXT: [[RANGE_CHECK_SLT:%.*]] = icmp slt i32 [[EL]], [[LEN]] 85; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 86; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLT]], [[WC]] 87; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 88; CHECK: backedge: 89; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 90; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 91; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 92; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]] 93; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 94; CHECK: deopt: 95; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 96; CHECK-NEXT: ret i32 [[DEOPT_RES]] 97; CHECK: exit: 98; CHECK-NEXT: ret i32 0 99; CHECK: bound_check_failed: 100; CHECK-NEXT: ret i32 -1 101; 102entry: 103 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 104 br label %loop 105 106loop: 107 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 108 %el.ptr = getelementptr i32, ptr %p, i32 %iv 109 %el = load i32, ptr %el.ptr, align 4 110 %bound_check = icmp slt i32 %el, 128 111 br i1 %bound_check, label %do_range_check, label %bound_check_failed 112 113do_range_check: 114 call void @llvm.assume(i1 %bound_check) 115 %range_check.slt = icmp slt i32 %el, %len 116 %wc = call i1 @llvm.experimental.widenable.condition() 117 %explicit_guard_cond = and i1 %range_check.slt, %wc 118 br i1 %explicit_guard_cond, label %backedge, label %deopt 119 120backedge: 121 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 122 store i32 %iv, ptr %arr.ptr, align 4 123 %iv.next = add i32 %iv, 1 124 %loop_cond = icmp ult i32 %iv.next, %n 125 br i1 %loop_cond, label %loop, label %exit 126 127deopt: 128 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 129 ret i32 %deopt_res 130 131exit: 132 ret i32 0 133 134bound_check_failed: 135 ret i32 -1 136} 137 138define i32 @test_ule(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 139; CHECK-LABEL: @test_ule( 140; CHECK-NEXT: entry: 141; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 142; CHECK-NEXT: br label [[LOOP:%.*]] 143; CHECK: loop: 144; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 145; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 146; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 147; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 148; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 149; CHECK: do_range_check: 150; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 151; CHECK-NEXT: [[RANGE_CHECK_ULE:%.*]] = icmp ule i32 [[EL]], [[LEN]] 152; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 153; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_ULE]], [[WC]] 154; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 155; CHECK: backedge: 156; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 157; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 158; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 159; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]] 160; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 161; CHECK: deopt: 162; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 163; CHECK-NEXT: ret i32 [[DEOPT_RES]] 164; CHECK: exit: 165; CHECK-NEXT: ret i32 0 166; CHECK: bound_check_failed: 167; CHECK-NEXT: ret i32 -1 168; 169entry: 170 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 171 br label %loop 172 173loop: 174 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 175 %el.ptr = getelementptr i32, ptr %p, i32 %iv 176 %el = load i32, ptr %el.ptr, align 4 177 %bound_check = icmp ult i32 %el, 128 178 br i1 %bound_check, label %do_range_check, label %bound_check_failed 179 180do_range_check: 181 call void @llvm.assume(i1 %bound_check) 182 %range_check.ule = icmp ule i32 %el, %len 183 %wc = call i1 @llvm.experimental.widenable.condition() 184 %explicit_guard_cond = and i1 %range_check.ule, %wc 185 br i1 %explicit_guard_cond, label %backedge, label %deopt 186 187backedge: 188 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 189 store i32 %iv, ptr %arr.ptr, align 4 190 %iv.next = add i32 %iv, 1 191 %loop_cond = icmp ult i32 %iv.next, %n 192 br i1 %loop_cond, label %loop, label %exit 193 194deopt: 195 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 196 ret i32 %deopt_res 197 198exit: 199 ret i32 0 200 201bound_check_failed: 202 ret i32 -1 203} 204 205define i32 @test_sle(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 206; CHECK-LABEL: @test_sle( 207; CHECK-NEXT: entry: 208; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 209; CHECK-NEXT: br label [[LOOP:%.*]] 210; CHECK: loop: 211; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 212; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 213; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 214; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 215; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 216; CHECK: do_range_check: 217; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 218; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sle i32 [[EL]], [[LEN]] 219; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 220; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] 221; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 222; CHECK: backedge: 223; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 224; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 225; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 226; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]] 227; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 228; CHECK: deopt: 229; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 230; CHECK-NEXT: ret i32 [[DEOPT_RES]] 231; CHECK: exit: 232; CHECK-NEXT: ret i32 0 233; CHECK: bound_check_failed: 234; CHECK-NEXT: ret i32 -1 235; 236entry: 237 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 238 br label %loop 239 240loop: 241 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 242 %el.ptr = getelementptr i32, ptr %p, i32 %iv 243 %el = load i32, ptr %el.ptr, align 4 244 %bound_check = icmp slt i32 %el, 128 245 br i1 %bound_check, label %do_range_check, label %bound_check_failed 246 247do_range_check: 248 call void @llvm.assume(i1 %bound_check) 249 %range_check.sle = icmp sle i32 %el, %len 250 %wc = call i1 @llvm.experimental.widenable.condition() 251 %explicit_guard_cond = and i1 %range_check.sle, %wc 252 br i1 %explicit_guard_cond, label %backedge, label %deopt 253 254backedge: 255 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 256 store i32 %iv, ptr %arr.ptr, align 4 257 %iv.next = add i32 %iv, 1 258 %loop_cond = icmp ult i32 %iv.next, %n 259 br i1 %loop_cond, label %loop, label %exit 260 261deopt: 262 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 263 ret i32 %deopt_res 264 265exit: 266 ret i32 0 267 268bound_check_failed: 269 ret i32 -1 270} 271 272define i32 @test_ugt(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 273; CHECK-LABEL: @test_ugt( 274; CHECK-NEXT: entry: 275; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 276; CHECK-NEXT: br label [[LOOP:%.*]] 277; CHECK: loop: 278; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 279; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 280; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 281; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 282; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 283; CHECK: do_range_check: 284; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 285; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp ugt i32 [[LEN]], [[EL]] 286; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 287; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] 288; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 289; CHECK: backedge: 290; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 291; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 292; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 293; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]] 294; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 295; CHECK: deopt: 296; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 297; CHECK-NEXT: ret i32 [[DEOPT_RES]] 298; CHECK: exit: 299; CHECK-NEXT: ret i32 0 300; CHECK: bound_check_failed: 301; CHECK-NEXT: ret i32 -1 302; 303entry: 304 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 305 br label %loop 306 307loop: 308 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 309 %el.ptr = getelementptr i32, ptr %p, i32 %iv 310 %el = load i32, ptr %el.ptr, align 4 311 %bound_check = icmp ult i32 %el, 128 312 br i1 %bound_check, label %do_range_check, label %bound_check_failed 313 314do_range_check: 315 call void @llvm.assume(i1 %bound_check) 316 %range_check.sle = icmp ugt i32 %len, %el 317 %wc = call i1 @llvm.experimental.widenable.condition() 318 %explicit_guard_cond = and i1 %range_check.sle, %wc 319 br i1 %explicit_guard_cond, label %backedge, label %deopt 320 321backedge: 322 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 323 store i32 %iv, ptr %arr.ptr, align 4 324 %iv.next = add i32 %iv, 1 325 %loop_cond = icmp ult i32 %iv.next, %n 326 br i1 %loop_cond, label %loop, label %exit 327 328deopt: 329 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 330 ret i32 %deopt_res 331 332exit: 333 ret i32 0 334 335bound_check_failed: 336 ret i32 -1 337} 338 339define i32 @test_uge(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 340; CHECK-LABEL: @test_uge( 341; CHECK-NEXT: entry: 342; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 343; CHECK-NEXT: br label [[LOOP:%.*]] 344; CHECK: loop: 345; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 346; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 347; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 348; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 349; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 350; CHECK: do_range_check: 351; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 352; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp uge i32 [[LEN]], [[EL]] 353; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 354; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] 355; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 356; CHECK: backedge: 357; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 358; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 359; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 360; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]] 361; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 362; CHECK: deopt: 363; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 364; CHECK-NEXT: ret i32 [[DEOPT_RES]] 365; CHECK: exit: 366; CHECK-NEXT: ret i32 0 367; CHECK: bound_check_failed: 368; CHECK-NEXT: ret i32 -1 369; 370entry: 371 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 372 br label %loop 373 374loop: 375 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 376 %el.ptr = getelementptr i32, ptr %p, i32 %iv 377 %el = load i32, ptr %el.ptr, align 4 378 %bound_check = icmp ult i32 %el, 128 379 br i1 %bound_check, label %do_range_check, label %bound_check_failed 380 381do_range_check: 382 call void @llvm.assume(i1 %bound_check) 383 %range_check.sle = icmp uge i32 %len, %el 384 %wc = call i1 @llvm.experimental.widenable.condition() 385 %explicit_guard_cond = and i1 %range_check.sle, %wc 386 br i1 %explicit_guard_cond, label %backedge, label %deopt 387 388backedge: 389 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 390 store i32 %iv, ptr %arr.ptr, align 4 391 %iv.next = add i32 %iv, 1 392 %loop_cond = icmp ult i32 %iv.next, %n 393 br i1 %loop_cond, label %loop, label %exit 394 395deopt: 396 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 397 ret i32 %deopt_res 398 399exit: 400 ret i32 0 401 402bound_check_failed: 403 ret i32 -1 404} 405 406define i32 @test_sgt(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 407; CHECK-LABEL: @test_sgt( 408; CHECK-NEXT: entry: 409; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 410; CHECK-NEXT: br label [[LOOP:%.*]] 411; CHECK: loop: 412; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 413; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 414; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 415; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 416; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 417; CHECK: do_range_check: 418; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 419; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sgt i32 [[LEN]], [[EL]] 420; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 421; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] 422; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 423; CHECK: backedge: 424; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 425; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 426; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 427; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]] 428; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 429; CHECK: deopt: 430; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 431; CHECK-NEXT: ret i32 [[DEOPT_RES]] 432; CHECK: exit: 433; CHECK-NEXT: ret i32 0 434; CHECK: bound_check_failed: 435; CHECK-NEXT: ret i32 -1 436; 437entry: 438 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 439 br label %loop 440 441loop: 442 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 443 %el.ptr = getelementptr i32, ptr %p, i32 %iv 444 %el = load i32, ptr %el.ptr, align 4 445 %bound_check = icmp slt i32 %el, 128 446 br i1 %bound_check, label %do_range_check, label %bound_check_failed 447 448do_range_check: 449 call void @llvm.assume(i1 %bound_check) 450 %range_check.sle = icmp sgt i32 %len, %el 451 %wc = call i1 @llvm.experimental.widenable.condition() 452 %explicit_guard_cond = and i1 %range_check.sle, %wc 453 br i1 %explicit_guard_cond, label %backedge, label %deopt 454 455backedge: 456 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 457 store i32 %iv, ptr %arr.ptr, align 4 458 %iv.next = add i32 %iv, 1 459 %loop_cond = icmp ult i32 %iv.next, %n 460 br i1 %loop_cond, label %loop, label %exit 461 462deopt: 463 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 464 ret i32 %deopt_res 465 466exit: 467 ret i32 0 468 469bound_check_failed: 470 ret i32 -1 471} 472 473define i32 @test_sge(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { 474; CHECK-LABEL: @test_sge( 475; CHECK-NEXT: entry: 476; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 477; CHECK-NEXT: br label [[LOOP:%.*]] 478; CHECK: loop: 479; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 480; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 481; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 482; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 483; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] 484; CHECK: do_range_check: 485; CHECK-NEXT: call void @llvm.assume(i1 [[BOUND_CHECK]]) 486; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sge i32 [[LEN]], [[EL]] 487; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() 488; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] 489; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] 490; CHECK: backedge: 491; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] 492; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 493; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 494; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]] 495; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 496; CHECK: deopt: 497; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 498; CHECK-NEXT: ret i32 [[DEOPT_RES]] 499; CHECK: exit: 500; CHECK-NEXT: ret i32 0 501; CHECK: bound_check_failed: 502; CHECK-NEXT: ret i32 -1 503; 504entry: 505 %len = load i32, ptr %len_p, align 4, !noundef !0, !range !1 506 br label %loop 507 508loop: 509 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 510 %el.ptr = getelementptr i32, ptr %p, i32 %iv 511 %el = load i32, ptr %el.ptr, align 4 512 %bound_check = icmp slt i32 %el, 128 513 br i1 %bound_check, label %do_range_check, label %bound_check_failed 514 515do_range_check: 516 call void @llvm.assume(i1 %bound_check) 517 %range_check.sle = icmp sge i32 %len, %el 518 %wc = call i1 @llvm.experimental.widenable.condition() 519 %explicit_guard_cond = and i1 %range_check.sle, %wc 520 br i1 %explicit_guard_cond, label %backedge, label %deopt 521 522backedge: 523 %arr.ptr = getelementptr i32, ptr %arr, i32 %el 524 store i32 %iv, ptr %arr.ptr, align 4 525 %iv.next = add i32 %iv, 1 526 %loop_cond = icmp ult i32 %iv.next, %n 527 br i1 %loop_cond, label %loop, label %exit 528 529deopt: 530 %deopt_res = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] 531 ret i32 %deopt_res 532 533exit: 534 ret i32 0 535 536bound_check_failed: 537 ret i32 -1 538} 539 540; Function Attrs: inaccessiblememonly nocallback nofree nosync nounwind speculatable willreturn 541declare i1 @llvm.experimental.widenable.condition() #1 542 543declare i32 @llvm.experimental.deoptimize.i32(...) 544 545declare void @llvm.assume(i1) 546 547attributes #1 = { inaccessiblememonly nocallback nofree nosync nounwind speculatable willreturn } 548 549!0 = !{} 550!1 = !{i32 0, i32 2147483646} 551