1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -verify-loop-info -irce-print-changed-loops -passes=irce -S < %s 2>&1 | FileCheck %s 3; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s 4 5; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 6; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 7; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 8; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 9; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 10; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 11; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 12; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 13 14; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed. 15define void @test_01(ptr %arr, ptr %a_len_ptr) { 16; CHECK-LABEL: define void @test_01 17; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 18; CHECK-NEXT: entry: 19; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]] 20; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 21; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 22; CHECK: loop.preheader: 23; CHECK-NEXT: br label [[LOOP:%.*]] 24; CHECK: loop: 25; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 26; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 7 27; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]] 28; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 29; CHECK: in.bounds: 30; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 31; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 32; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 100 33; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 34; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 35; CHECK: main.exit.selector: 36; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 37; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 100 38; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]] 39; CHECK: main.pseudo.exit: 40; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 41; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 42; CHECK-NEXT: br label [[POSTLOOP:%.*]] 43; CHECK: out.of.bounds.loopexit: 44; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 45; CHECK: out.of.bounds.loopexit1: 46; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 47; CHECK: out.of.bounds: 48; CHECK-NEXT: ret void 49; CHECK: exit.loopexit: 50; CHECK-NEXT: br label [[EXIT]] 51; CHECK: exit: 52; CHECK-NEXT: ret void 53; CHECK: postloop: 54; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 55; CHECK: loop.postloop: 56; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ] 57; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7 58; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]] 59; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 60; CHECK: in.bounds.postloop: 61; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]] 62; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4 63; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 100 64; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone !6 65; 66 67entry: 68 %len = load i32, ptr %a_len_ptr, !range !0 69 br label %loop 70 71loop: 72 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 73 %idx.next = add i32 %idx, 7 74 %abc = icmp slt i32 %idx, %len 75 br i1 %abc, label %in.bounds, label %out.of.bounds 76 77in.bounds: 78 %addr = getelementptr i32, ptr %arr, i32 %idx 79 store i32 0, ptr %addr 80 %next = icmp slt i32 %idx.next, 100 81 br i1 %next, label %loop, label %exit 82 83out.of.bounds: 84 ret void 85 86exit: 87 ret void 88} 89 90; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed. 91define void @test_02(ptr %arr, ptr %a_len_ptr) { 92; CHECK-LABEL: define void @test_02 93; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 94; CHECK-NEXT: entry: 95; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]] 96; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 97; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 98; CHECK: loop.preheader: 99; CHECK-NEXT: br label [[LOOP:%.*]] 100; CHECK: loop: 101; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 102; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 7 103; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]] 104; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 105; CHECK: in.bounds: 106; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 107; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 108; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483640 109; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 110; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 111; CHECK: main.exit.selector: 112; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 113; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483640 114; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]] 115; CHECK: main.pseudo.exit: 116; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 117; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 118; CHECK-NEXT: br label [[POSTLOOP:%.*]] 119; CHECK: out.of.bounds.loopexit: 120; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 121; CHECK: out.of.bounds.loopexit1: 122; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 123; CHECK: out.of.bounds: 124; CHECK-NEXT: ret void 125; CHECK: exit.loopexit: 126; CHECK-NEXT: br label [[EXIT]] 127; CHECK: exit: 128; CHECK-NEXT: ret void 129; CHECK: postloop: 130; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 131; CHECK: loop.postloop: 132; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ] 133; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7 134; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]] 135; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 136; CHECK: in.bounds.postloop: 137; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]] 138; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4 139; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483640 140; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !6 141; 142 143entry: 144 %len = load i32, ptr %a_len_ptr, !range !0 145 br label %loop 146 147loop: 148 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 149 %idx.next = add i32 %idx, 7 150 %abc = icmp slt i32 %idx, %len 151 br i1 %abc, label %in.bounds, label %out.of.bounds 152 153in.bounds: 154 %addr = getelementptr i32, ptr %arr, i32 %idx 155 store i32 0, ptr %addr 156 %next = icmp slt i32 %idx.next, 2147483640 157 br i1 %next, label %loop, label %exit 158 159out.of.bounds: 160 ret void 161 162exit: 163 ret void 164} 165 166; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 7. This is the greatest 167; value of Len for which IRCE is allowed. 168define void @test_03(ptr %arr, ptr %a_len_ptr) { 169; CHECK-LABEL: define void @test_03 170; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 171; CHECK-NEXT: entry: 172; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG8:![0-9]+]] 173; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 174; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 175; CHECK: loop.preheader: 176; CHECK-NEXT: br label [[LOOP:%.*]] 177; CHECK: loop: 178; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 179; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 7 180; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]] 181; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 182; CHECK: in.bounds: 183; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 184; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 185; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647 186; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 187; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 188; CHECK: main.exit.selector: 189; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 190; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647 191; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]] 192; CHECK: main.pseudo.exit: 193; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 194; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 195; CHECK-NEXT: br label [[POSTLOOP:%.*]] 196; CHECK: out.of.bounds.loopexit: 197; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 198; CHECK: out.of.bounds.loopexit1: 199; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 200; CHECK: out.of.bounds: 201; CHECK-NEXT: ret void 202; CHECK: exit.loopexit: 203; CHECK-NEXT: br label [[EXIT]] 204; CHECK: exit: 205; CHECK-NEXT: ret void 206; CHECK: postloop: 207; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 208; CHECK: loop.postloop: 209; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ] 210; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7 211; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]] 212; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 213; CHECK: in.bounds.postloop: 214; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]] 215; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4 216; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647 217; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone !6 218; 219 220entry: 221 %len = load i32, ptr %a_len_ptr, !range !1 222 br label %loop 223 224loop: 225 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 226 %idx.next = add i32 %idx, 7 227 %abc = icmp slt i32 %idx, %len 228 br i1 %abc, label %in.bounds, label %out.of.bounds 229 230in.bounds: 231 %addr = getelementptr i32, ptr %arr, i32 %idx 232 store i32 0, ptr %addr 233 %next = icmp slt i32 %idx.next, 2147483647 234 br i1 %next, label %loop, label %exit 235 236out.of.bounds: 237 ret void 238 239exit: 240 ret void 241} 242 243; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 6. IRCE is allowed 244; because the branch would fail once idx.next == MAX_INT - 1 keeping the 245; access in bounds. 246define void @test_04(ptr %arr, ptr %a_len_ptr) { 247; CHECK-LABEL: define void @test_04 248; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 249; CHECK-NEXT: entry: 250; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG10:![0-9]+]] 251; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 252; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 253; CHECK: loop.preheader: 254; CHECK-NEXT: br label [[LOOP:%.*]] 255; CHECK: loop: 256; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 257; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 7 258; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]] 259; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 260; CHECK: in.bounds: 261; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 262; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 263; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647 264; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 265; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 266; CHECK: main.exit.selector: 267; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 268; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647 269; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]] 270; CHECK: main.pseudo.exit: 271; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 272; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 273; CHECK-NEXT: br label [[POSTLOOP:%.*]] 274; CHECK: out.of.bounds.loopexit: 275; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 276; CHECK: out.of.bounds.loopexit1: 277; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 278; CHECK: out.of.bounds: 279; CHECK-NEXT: ret void 280; CHECK: exit.loopexit: 281; CHECK-NEXT: br label [[EXIT]] 282; CHECK: exit: 283; CHECK-NEXT: ret void 284; CHECK: postloop: 285; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 286; CHECK: loop.postloop: 287; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ] 288; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7 289; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]] 290; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 291; CHECK: in.bounds.postloop: 292; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]] 293; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4 294; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647 295; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP11:![0-9]+]], !loop_constrainer.loop.clone !6 296; 297 298 299 300entry: 301 %len = load i32, ptr %a_len_ptr, !range !2 302 br label %loop 303 304loop: 305 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 306 %idx.next = add i32 %idx, 7 307 %abc = icmp slt i32 %idx, %len 308 br i1 %abc, label %in.bounds, label %out.of.bounds 309 310in.bounds: 311 %addr = getelementptr i32, ptr %arr, i32 %idx 312 store i32 0, ptr %addr 313 %next = icmp slt i32 %idx.next, 2147483647 314 br i1 %next, label %loop, label %exit 315 316out.of.bounds: 317 ret void 318 319exit: 320 ret void 321} 322 323; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed. 324define void @test_05(ptr %arr, ptr %a_len_ptr) { 325; CHECK-LABEL: define void @test_05 326; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 327; CHECK-NEXT: entry: 328; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]] 329; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1 330; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 100, [[EXIT_PRELOOP_AT]] 331; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]] 332; CHECK: loop.preloop.preheader: 333; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]] 334; CHECK: mainloop: 335; CHECK-NEXT: br label [[LOOP:%.*]] 336; CHECK: loop: 337; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ] 338; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], -7 339; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]] 340; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 341; CHECK: in.bounds: 342; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 343; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 344; CHECK-NEXT: [[NEXT:%.*]] = icmp sgt i32 [[IDX_NEXT]], -1 345; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 346; CHECK: out.of.bounds.loopexit: 347; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 348; CHECK: out.of.bounds.loopexit1: 349; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 350; CHECK: out.of.bounds: 351; CHECK-NEXT: ret void 352; CHECK: exit.loopexit: 353; CHECK-NEXT: br label [[EXIT:%.*]] 354; CHECK: exit: 355; CHECK-NEXT: ret void 356; CHECK: loop.preloop: 357; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ] 358; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7 359; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]] 360; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 361; CHECK: in.bounds.preloop: 362; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]] 363; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4 364; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], -1 365; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]] 366; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP12:![0-9]+]], !loop_constrainer.loop.clone !6 367; CHECK: preloop.exit.selector: 368; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ] 369; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP_LCSSA]], -1 370; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]] 371; CHECK: preloop.pseudo.exit: 372; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 373; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 374; CHECK-NEXT: br label [[MAINLOOP]] 375; 376 377entry: 378 %len = load i32, ptr %a_len_ptr, !range !0 379 br label %loop 380 381loop: 382 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ] 383 %idx.next = add i32 %idx, -7 384 %abc = icmp slt i32 %idx, %len 385 br i1 %abc, label %in.bounds, label %out.of.bounds 386 387in.bounds: 388 %addr = getelementptr i32, ptr %arr, i32 %idx 389 store i32 0, ptr %addr 390 %next = icmp sgt i32 %idx.next, -1 391 br i1 %next, label %loop, label %exit 392 393out.of.bounds: 394 ret void 395 396exit: 397 ret void 398} 399 400; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed. 401define void @test_06(ptr %arr, ptr %a_len_ptr) { 402; CHECK-LABEL: define void @test_06 403; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 404; CHECK-NEXT: entry: 405; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13:![0-9]+]] 406; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1 407; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 2147483640, [[EXIT_PRELOOP_AT]] 408; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]] 409; CHECK: loop.preloop.preheader: 410; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]] 411; CHECK: mainloop: 412; CHECK-NEXT: br label [[LOOP:%.*]] 413; CHECK: loop: 414; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ] 415; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -7 416; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]] 417; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 418; CHECK: in.bounds: 419; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 420; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 421; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6 422; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 423; CHECK: out.of.bounds.loopexit: 424; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 425; CHECK: out.of.bounds.loopexit1: 426; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 427; CHECK: out.of.bounds: 428; CHECK-NEXT: ret void 429; CHECK: exit.loopexit: 430; CHECK-NEXT: br label [[EXIT:%.*]] 431; CHECK: exit: 432; CHECK-NEXT: ret void 433; CHECK: loop.preloop: 434; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483640, [[LOOP_PRELOOP_PREHEADER]] ] 435; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7 436; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]] 437; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 438; CHECK: in.bounds.preloop: 439; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]] 440; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4 441; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6 442; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]] 443; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP14:![0-9]+]], !loop_constrainer.loop.clone !6 444; CHECK: preloop.exit.selector: 445; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ] 446; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6 447; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]] 448; CHECK: preloop.pseudo.exit: 449; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 450; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2147483640, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 451; CHECK-NEXT: br label [[MAINLOOP]] 452; 453 454entry: 455 %len = load i32, ptr %a_len_ptr, !range !3 456 br label %loop 457 458loop: 459 %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ] 460 %idx.next = add i32 %idx, -7 461 %abc = icmp slt i32 %idx, %len 462 br i1 %abc, label %in.bounds, label %out.of.bounds 463 464in.bounds: 465 %addr = getelementptr i32, ptr %arr, i32 %idx 466 store i32 0, ptr %addr 467 %next = icmp ugt i32 %idx.next, 6 468 br i1 %next, label %loop, label %exit 469 470out.of.bounds: 471 ret void 472 473exit: 474 ret void 475} 476 477; IV = MAX_INT - 7; IV >u 5; IV -= 7; 10 <= Len <= 50. IRCE is not allowed, 478; because we can cross the 0 border. 479define void @test_07(ptr %arr, ptr %a_len_ptr) { 480; CHECK-LABEL: define void @test_07 481; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 482; CHECK-NEXT: entry: 483; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]] 484; CHECK-NEXT: br label [[LOOP:%.*]] 485; CHECK: loop: 486; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ] 487; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -7 488; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]] 489; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]] 490; CHECK: in.bounds: 491; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 492; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 493; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 5 494; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT:%.*]] 495; CHECK: out.of.bounds: 496; CHECK-NEXT: ret void 497; CHECK: exit: 498; CHECK-NEXT: ret void 499; 500 501entry: 502 %len = load i32, ptr %a_len_ptr, !range !3 503 br label %loop 504 505loop: 506 %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ] 507 %idx.next = add i32 %idx, -7 508 %abc = icmp slt i32 %idx, %len 509 br i1 %abc, label %in.bounds, label %out.of.bounds 510 511in.bounds: 512 %addr = getelementptr i32, ptr %arr, i32 %idx 513 store i32 0, ptr %addr 514 %next = icmp ugt i32 %idx.next, 5 515 br i1 %next, label %loop, label %exit 516 517out.of.bounds: 518 ret void 519 520exit: 521 ret void 522} 523 524; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed. 525define void @test_08(ptr %arr, ptr %a_len_ptr) { 526; CHECK-LABEL: define void @test_08 527; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) { 528; CHECK-NEXT: entry: 529; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]] 530; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1 531; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 2147483647, [[EXIT_PRELOOP_AT]] 532; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]] 533; CHECK: loop.preloop.preheader: 534; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]] 535; CHECK: mainloop: 536; CHECK-NEXT: br label [[LOOP:%.*]] 537; CHECK: loop: 538; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ] 539; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -7 540; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]] 541; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 542; CHECK: in.bounds: 543; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 544; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 545; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6 546; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 547; CHECK: out.of.bounds.loopexit: 548; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 549; CHECK: out.of.bounds.loopexit1: 550; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 551; CHECK: out.of.bounds: 552; CHECK-NEXT: ret void 553; CHECK: exit.loopexit: 554; CHECK-NEXT: br label [[EXIT:%.*]] 555; CHECK: exit: 556; CHECK-NEXT: ret void 557; CHECK: loop.preloop: 558; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483647, [[LOOP_PRELOOP_PREHEADER]] ] 559; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7 560; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]] 561; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 562; CHECK: in.bounds.preloop: 563; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]] 564; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4 565; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6 566; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]] 567; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP15:![0-9]+]], !loop_constrainer.loop.clone !6 568; CHECK: preloop.exit.selector: 569; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ] 570; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6 571; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]] 572; CHECK: preloop.pseudo.exit: 573; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 574; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2147483647, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 575; CHECK-NEXT: br label [[MAINLOOP]] 576; 577 578entry: 579 %len = load i32, ptr %a_len_ptr, !range !3 580 br label %loop 581 582loop: 583 %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ] 584 %idx.next = add i32 %idx, -7 585 %abc = icmp slt i32 %idx, %len 586 br i1 %abc, label %in.bounds, label %out.of.bounds 587 588in.bounds: 589 %addr = getelementptr i32, ptr %arr, i32 %idx 590 store i32 0, ptr %addr 591 %next = icmp ugt i32 %idx.next, 6 592 br i1 %next, label %loop, label %exit 593 594out.of.bounds: 595 ret void 596 597exit: 598 ret void 599} 600 601; IRCE is legal here. 602; Here how it is done if the step was 1: https://godbolt.org/z/jEqWaseWc 603; It is also legal for step 4. Proof: 604; - Capacity check ensures that iv < limit <= SINT_MAX - 3, meaning that 605; iv <= SINT_MAX - 4. 606; - Because of this, iv.next is always computed w/o overflow. 607; - The loop goes to backedge as long as iv < capacity - 3 && iv < num.elements - 4. 608; - So iterating up to smin(capacity - 3, num.elements - 4) should be safe. 609; - Proof by alive2: https://alive2.llvm.org/ce/z/vEhMxa 610define i32 @test_09(ptr %p, ptr %capacity_p, ptr %num_elements_p) { 611; CHECK-LABEL: define i32 @test_09 612; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) { 613; CHECK-NEXT: entry: 614; CHECK-NEXT: [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16:![0-9]+]] 615; CHECK-NEXT: [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]] 616; CHECK-NEXT: [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 3 617; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[CAPACITY]], -3 618; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646 619; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0) 620; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]] 621; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LIMIT]], i32 0) 622; CHECK-NEXT: [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1) 623; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[SMAX2]], 1 624; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]] 625; CHECK-NEXT: [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP4]]) 626; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0) 627; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 628; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 629; CHECK: loop.preheader: 630; CHECK-NEXT: br label [[LOOP:%.*]] 631; CHECK: loop: 632; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 633; CHECK-NEXT: [[CAPACITY_CHECK:%.*]] = icmp slt i32 [[IV]], [[LIMIT]] 634; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17:![0-9]+]] 635; CHECK: backedge: 636; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64 637; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]] 638; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4 639; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4 640; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]] 641; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]] 642; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 643; CHECK: main.exit.selector: 644; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ] 645; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 646; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]] 647; CHECK-NEXT: br i1 [[TMP7]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]] 648; CHECK: main.pseudo.exit: 649; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 650; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 651; CHECK-NEXT: br label [[POSTLOOP:%.*]] 652; CHECK: exit.loopexit: 653; CHECK-NEXT: [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ] 654; CHECK-NEXT: br label [[EXIT]] 655; CHECK: exit: 656; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ] 657; CHECK-NEXT: ret i32 [[IV_LCSSA1]] 658; CHECK: out_of_bounds.loopexit: 659; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 660; CHECK: out_of_bounds.loopexit5: 661; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 662; CHECK: out_of_bounds: 663; CHECK-NEXT: ret i32 -1 664; CHECK: postloop: 665; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 666; CHECK: loop.postloop: 667; CHECK-NEXT: [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ] 668; CHECK-NEXT: [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[LIMIT]] 669; CHECK-NEXT: br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]] 670; CHECK: backedge.postloop: 671; CHECK-NEXT: [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64 672; CHECK-NEXT: [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]] 673; CHECK-NEXT: store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4 674; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4 675; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]] 676; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP18:![0-9]+]], !loop_constrainer.loop.clone !6 677; 678entry: 679 %capacity = load i32, ptr %capacity_p, !range !4 680 %num_elements = load i32, ptr %num_elements_p, !range !4 681 %limit = sub i32 %capacity, 3 682 br label %loop 683 684loop: 685 %iv = phi i32 [0, %entry], [%iv.next, %backedge] 686 %capacity_check = icmp slt i32 %iv, %limit 687 br i1 %capacity_check, label %backedge, label %out_of_bounds, !prof !5 688 689backedge: 690 %iv.wide = zext i32 %iv to i64 691 %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide 692 store i32 1, ptr %el.ptr 693 %iv.next = add nuw nsw i32 %iv, 4 694 %loop_cond = icmp slt i32 %iv.next, %num_elements 695 br i1 %loop_cond, label %loop, label %exit 696 697exit: 698 ret i32 %iv 699 700out_of_bounds: 701 ret i32 -1 702} 703 704; Same as test_09 but range check comparison is inversed. 705; IRCE is allowed. 706define i32 @test_10(ptr %p, ptr %capacity_p, ptr %num_elements_p) { 707; CHECK-LABEL: define i32 @test_10 708; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) { 709; CHECK-NEXT: entry: 710; CHECK-NEXT: [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16]] 711; CHECK-NEXT: [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]] 712; CHECK-NEXT: [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 3 713; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[CAPACITY]], -3 714; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646 715; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0) 716; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]] 717; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LIMIT]], i32 0) 718; CHECK-NEXT: [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1) 719; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[SMAX2]], 1 720; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]] 721; CHECK-NEXT: [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP4]]) 722; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0) 723; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 724; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 725; CHECK: loop.preheader: 726; CHECK-NEXT: br label [[LOOP:%.*]] 727; CHECK: loop: 728; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 729; CHECK-NEXT: [[CAPACITY_CHECK:%.*]] = icmp slt i32 [[IV]], [[LIMIT]] 730; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17]] 731; CHECK: backedge: 732; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64 733; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]] 734; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4 735; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4 736; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]] 737; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]] 738; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 739; CHECK: main.exit.selector: 740; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ] 741; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 742; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]] 743; CHECK-NEXT: br i1 [[TMP7]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]] 744; CHECK: main.pseudo.exit: 745; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 746; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 747; CHECK-NEXT: br label [[POSTLOOP:%.*]] 748; CHECK: exit.loopexit: 749; CHECK-NEXT: [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ] 750; CHECK-NEXT: br label [[EXIT]] 751; CHECK: exit: 752; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ] 753; CHECK-NEXT: ret i32 [[IV_LCSSA1]] 754; CHECK: out_of_bounds.loopexit: 755; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 756; CHECK: out_of_bounds.loopexit5: 757; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 758; CHECK: out_of_bounds: 759; CHECK-NEXT: ret i32 -1 760; CHECK: postloop: 761; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 762; CHECK: loop.postloop: 763; CHECK-NEXT: [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ] 764; CHECK-NEXT: [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[LIMIT]] 765; CHECK-NEXT: br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]] 766; CHECK: backedge.postloop: 767; CHECK-NEXT: [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64 768; CHECK-NEXT: [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]] 769; CHECK-NEXT: store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4 770; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4 771; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]] 772; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP19:![0-9]+]], !loop_constrainer.loop.clone !6 773; 774entry: 775 %capacity = load i32, ptr %capacity_p, !range !4 776 %num_elements = load i32, ptr %num_elements_p, !range !4 777 %limit = sub i32 %capacity, 3 778 br label %loop 779 780loop: 781 %iv = phi i32 [0, %entry], [%iv.next, %backedge] 782 %capacity_check = icmp sge i32 %iv, %limit 783 br i1 %capacity_check, label %out_of_bounds, label %backedge, !prof !6 784 785backedge: 786 %iv.wide = zext i32 %iv to i64 787 %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide 788 store i32 1, ptr %el.ptr 789 %iv.next = add nuw nsw i32 %iv, 4 790 %loop_cond = icmp slt i32 %iv.next, %num_elements 791 br i1 %loop_cond, label %loop, label %exit 792 793exit: 794 ret i32 %iv 795 796out_of_bounds: 797 ret i32 -1 798} 799 800; Same as test_09 but range check comparison is non-strict: 801; IRCE is allowed. 802define i32 @test_11(ptr %p, ptr %capacity_p, ptr %num_elements_p) { 803; CHECK-LABEL: define i32 @test_11 804; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) { 805; CHECK-NEXT: entry: 806; CHECK-NEXT: [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16]] 807; CHECK-NEXT: [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]] 808; CHECK-NEXT: [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 4 809; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[CAPACITY]], -3 810; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646 811; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0) 812; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]] 813; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[CAPACITY]], -3 814; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP3]], i32 0) 815; CHECK-NEXT: [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1) 816; CHECK-NEXT: [[TMP4:%.*]] = add nsw i32 [[SMAX2]], 1 817; CHECK-NEXT: [[TMP5:%.*]] = mul i32 [[TMP2]], [[TMP4]] 818; CHECK-NEXT: [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP5]]) 819; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0) 820; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 821; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 822; CHECK: loop.preheader: 823; CHECK-NEXT: br label [[LOOP:%.*]] 824; CHECK: loop: 825; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 826; CHECK-NEXT: [[CAPACITY_CHECK:%.*]] = icmp sle i32 [[IV]], [[LIMIT]] 827; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17]] 828; CHECK: backedge: 829; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64 830; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]] 831; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4 832; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4 833; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]] 834; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]] 835; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 836; CHECK: main.exit.selector: 837; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ] 838; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 839; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]] 840; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]] 841; CHECK: main.pseudo.exit: 842; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 843; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 844; CHECK-NEXT: br label [[POSTLOOP:%.*]] 845; CHECK: exit.loopexit: 846; CHECK-NEXT: [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ] 847; CHECK-NEXT: br label [[EXIT]] 848; CHECK: exit: 849; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ] 850; CHECK-NEXT: ret i32 [[IV_LCSSA1]] 851; CHECK: out_of_bounds.loopexit: 852; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 853; CHECK: out_of_bounds.loopexit5: 854; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 855; CHECK: out_of_bounds: 856; CHECK-NEXT: ret i32 -1 857; CHECK: postloop: 858; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 859; CHECK: loop.postloop: 860; CHECK-NEXT: [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ] 861; CHECK-NEXT: [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp sle i32 [[IV_POSTLOOP]], [[LIMIT]] 862; CHECK-NEXT: br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]] 863; CHECK: backedge.postloop: 864; CHECK-NEXT: [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64 865; CHECK-NEXT: [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]] 866; CHECK-NEXT: store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4 867; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4 868; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]] 869; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP20:![0-9]+]], !loop_constrainer.loop.clone !6 870; 871entry: 872 %capacity = load i32, ptr %capacity_p, !range !4 873 %num_elements = load i32, ptr %num_elements_p, !range !4 874 %limit = sub i32 %capacity, 4 875 br label %loop 876 877loop: 878 %iv = phi i32 [0, %entry], [%iv.next, %backedge] 879 %capacity_check = icmp sle i32 %iv, %limit 880 br i1 %capacity_check, label %backedge, label %out_of_bounds, !prof !5 881 882backedge: 883 %iv.wide = zext i32 %iv to i64 884 %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide 885 store i32 1, ptr %el.ptr 886 %iv.next = add nuw nsw i32 %iv, 4 887 %loop_cond = icmp slt i32 %iv.next, %num_elements 888 br i1 %loop_cond, label %loop, label %exit 889 890exit: 891 ret i32 %iv 892 893out_of_bounds: 894 ret i32 -1 895} 896 897; Indvar base is non-overflowing binary 'or': 898; check that IRCE isn't trying to add NSW flag on it. 899define i32 @binop_or_is_iv_base(ptr %p, i32 %end) { 900; CHECK-LABEL: define i32 @binop_or_is_iv_base 901; CHECK-SAME: (ptr [[P:%.*]], i32 [[END:%.*]]) { 902; CHECK-NEXT: entry: 903; CHECK-NEXT: [[N:%.*]] = load atomic i32, ptr [[P]] unordered, align 8, !range [[RNG8]] 904; CHECK-NEXT: [[CMP0:%.*]] = icmp sgt i32 [[END]], 7 905; CHECK-NEXT: br i1 [[CMP0]], label [[LOOP_HEADER_PREHEADER:%.*]], label [[COMMON_RET:%.*]] 906; CHECK: loop.header.preheader: 907; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[N]], 7 908; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[END]], i32 [[TMP0]]) 909; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 7) 910; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 7, [[EXIT_MAINLOOP_AT]] 911; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_HEADER_PREHEADER1:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 912; CHECK: loop.header.preheader1: 913; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 914; CHECK: loop.header: 915; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_ADD:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_HEADER_PREHEADER1]] ] 916; CHECK-NEXT: [[CHECK:%.*]] = icmp ult i32 [[IV]], [[N]] 917; CHECK-NEXT: br i1 true, label [[GUARDED]], label [[DEOPT_LOOPEXIT2:%.*]] 918; CHECK: guarded: 919; CHECK-NEXT: [[IV_ADD]] = add i32 [[IV]], 8 920; CHECK-NEXT: [[IV_OR:%.*]] = or disjoint i32 [[IV_ADD]], 7 921; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_OR]], [[END]] 922; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IV_OR]], [[EXIT_MAINLOOP_AT]] 923; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_HEADER]], label [[MAIN_EXIT_SELECTOR:%.*]] 924; CHECK: main.exit.selector: 925; CHECK-NEXT: [[IV_ADD_LCSSA:%.*]] = phi i32 [ [[IV_ADD]], [[GUARDED]] ] 926; CHECK-NEXT: [[IV_OR_LCSSA:%.*]] = phi i32 [ [[IV_OR]], [[GUARDED]] ] 927; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[IV_OR_LCSSA]], [[END]] 928; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[COMMON_RET_LOOPEXIT:%.*]] 929; CHECK: main.pseudo.exit: 930; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[LOOP_HEADER_PREHEADER]] ], [ [[IV_ADD_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 931; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 7, [[LOOP_HEADER_PREHEADER]] ], [ [[IV_OR_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 932; CHECK-NEXT: br label [[POSTLOOP:%.*]] 933; CHECK: deopt.loopexit: 934; CHECK-NEXT: br label [[DEOPT:%.*]] 935; CHECK: deopt.loopexit2: 936; CHECK-NEXT: br label [[DEOPT]] 937; CHECK: deopt: 938; CHECK-NEXT: [[RV:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 13) [ "deopt"() ] 939; CHECK-NEXT: ret i32 [[RV]] 940; CHECK: common.ret.loopexit.loopexit: 941; CHECK-NEXT: br label [[COMMON_RET_LOOPEXIT]] 942; CHECK: common.ret.loopexit: 943; CHECK-NEXT: br label [[COMMON_RET]] 944; CHECK: common.ret: 945; CHECK-NEXT: ret i32 [[END]] 946; CHECK: postloop: 947; CHECK-NEXT: br label [[LOOP_HEADER_POSTLOOP:%.*]] 948; CHECK: loop.header.postloop: 949; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i32 [ [[IV_ADD_POSTLOOP:%.*]], [[GUARDED_POSTLOOP:%.*]] ], [ [[IV_COPY]], [[POSTLOOP]] ] 950; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp ult i32 [[IV_POSTLOOP]], [[N]] 951; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[GUARDED_POSTLOOP]], label [[DEOPT_LOOPEXIT:%.*]] 952; CHECK: guarded.postloop: 953; CHECK-NEXT: [[IV_ADD_POSTLOOP]] = add i32 [[IV_POSTLOOP]], 8 954; CHECK-NEXT: [[IV_OR_POSTLOOP:%.*]] = or disjoint i32 [[IV_ADD_POSTLOOP]], 7 955; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i32 [[IV_OR_POSTLOOP]], [[END]] 956; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_HEADER_POSTLOOP]], label [[COMMON_RET_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP21:![0-9]+]], !loop_constrainer.loop.clone !6 957; 958entry: 959 %n = load atomic i32, ptr %p unordered, align 8, !range !1 960 %cmp0 = icmp sgt i32 %end, 7 961 br i1 %cmp0, label %loop.header, label %common.ret 962 963loop.header: 964 %iv = phi i32 [ %iv.add, %guarded ], [ 0, %entry ] 965 %check = icmp ult i32 %iv, %n 966 br i1 %check, label %guarded, label %deopt 967 968guarded: 969 %iv.add = add i32 %iv, 8 970 %iv.or = or disjoint i32 %iv.add, 7 971 %cmp = icmp slt i32 %iv.or, %end 972 br i1 %cmp, label %loop.header, label %common.ret 973 974deopt: 975 %rv = call i32 (...) @llvm.experimental.deoptimize.i32(i32 13) [ "deopt"() ] 976 ret i32 %rv 977 978common.ret: 979 ret i32 %end 980} 981 982declare i32 @llvm.experimental.deoptimize.i32(...) 983 984!0 = !{i32 0, i32 50} 985!1 = !{i32 0, i32 2147483640} 986!2 = !{i32 0, i32 2147483641} 987!3 = !{i32 10, i32 50} 988!4 = !{i32 1, i32 2147483648} 989!5 = !{!"branch_weights", i32 1000, i32 1} 990!6 = !{!"branch_weights", i32 1, i32 1000} 991