1300 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S %s -passes='loop-mssa(licm)' -verify-memoryssa | FileCheck %s3 4; turn to %iv <u umin(inv_1, inv_2) and hoist it out of loop.5define i32 @test_ult(i32 %start, i32 %inv_1, i32 %inv_2) {6; CHECK-LABEL: @test_ult(7; CHECK-NEXT: entry:8; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])9; CHECK-NEXT: br label [[LOOP:%.*]]10; CHECK: loop:11; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]12; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]13; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 114; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]15; CHECK: exit:16; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]17; CHECK-NEXT: ret i32 [[IV_LCSSA]]18;19entry:20 br label %loop21 22loop:23 %iv = phi i32 [%start, %entry], [%iv.next, %loop]24 %cmp_1 = icmp ult i32 %iv, %inv_125 %cmp_2 = icmp ult i32 %iv, %inv_226 %loop_cond = and i1 %cmp_1, %cmp_227 %iv.next = add i32 %iv, 128 br i1 %loop_cond, label %loop, label %exit29 30exit:31 ret i32 %iv32}33 34; Do not optimize: pointer types.35define ptr @test_ult_ptr_neg(ptr %start, ptr %inv_1, ptr %inv_2) {36; CHECK-LABEL: @test_ult_ptr_neg(37; CHECK-NEXT: entry:38; CHECK-NEXT: br label [[LOOP:%.*]]39; CHECK: loop:40; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]41; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult ptr [[IV]], [[INV_1:%.*]]42; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult ptr [[IV]], [[INV_2:%.*]]43; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]44; CHECK-NEXT: [[IV_NEXT]] = getelementptr i32, ptr [[IV]], i64 445; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]46; CHECK: exit:47; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi ptr [ [[IV]], [[LOOP]] ]48; CHECK-NEXT: ret ptr [[IV_LCSSA]]49;50entry:51 br label %loop52 53loop:54 %iv = phi ptr [%start, %entry], [%iv.next, %loop]55 %cmp_1 = icmp ult ptr %iv, %inv_156 %cmp_2 = icmp ult ptr %iv, %inv_257 %loop_cond = and i1 %cmp_1, %cmp_258 %iv.next = getelementptr i32, ptr %iv, i64 459 br i1 %loop_cond, label %loop, label %exit60 61exit:62 ret ptr %iv63}64 65; turn to %iv <=u umin(inv_1, inv_2) and hoist it out of loop.66define i32 @test_ule(i32 %start, i32 %inv_1, i32 %inv_2) {67; CHECK-LABEL: @test_ule(68; CHECK-NEXT: entry:69; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])70; CHECK-NEXT: br label [[LOOP:%.*]]71; CHECK: loop:72; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]73; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ule i32 [[IV]], [[INVARIANT_UMIN]]74; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 175; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]76; CHECK: exit:77; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]78; CHECK-NEXT: ret i32 [[IV_LCSSA]]79;80entry:81 br label %loop82 83loop:84 %iv = phi i32 [%start, %entry], [%iv.next, %loop]85 %cmp_1 = icmp ule i32 %iv, %inv_186 %cmp_2 = icmp ule i32 %iv, %inv_287 %loop_cond = and i1 %cmp_1, %cmp_288 %iv.next = add i32 %iv, 189 br i1 %loop_cond, label %loop, label %exit90 91exit:92 ret i32 %iv93}94 95; turn to %iv <s smin(inv_1, inv_2) and hoist it out of loop.96define i32 @test_slt(i32 %start, i32 %inv_1, i32 %inv_2) {97; CHECK-LABEL: @test_slt(98; CHECK-NEXT: entry:99; CHECK-NEXT: [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])100; CHECK-NEXT: br label [[LOOP:%.*]]101; CHECK: loop:102; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]103; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_SMIN]]104; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1105; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]106; CHECK: exit:107; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]108; CHECK-NEXT: ret i32 [[IV_LCSSA]]109;110entry:111 br label %loop112 113loop:114 %iv = phi i32 [%start, %entry], [%iv.next, %loop]115 %cmp_1 = icmp slt i32 %iv, %inv_1116 %cmp_2 = icmp slt i32 %iv, %inv_2117 %loop_cond = and i1 %cmp_1, %cmp_2118 %iv.next = add i32 %iv, 1119 br i1 %loop_cond, label %loop, label %exit120 121exit:122 ret i32 %iv123}124 125; turn to %iv <=s smin(inv_1, inv_2) and hoist it out of loop.126define i32 @test_sle(i32 %start, i32 %inv_1, i32 %inv_2) {127; CHECK-LABEL: @test_sle(128; CHECK-NEXT: entry:129; CHECK-NEXT: [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])130; CHECK-NEXT: br label [[LOOP:%.*]]131; CHECK: loop:132; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]133; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sle i32 [[IV]], [[INVARIANT_SMIN]]134; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1135; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]136; CHECK: exit:137; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]138; CHECK-NEXT: ret i32 [[IV_LCSSA]]139;140entry:141 br label %loop142 143loop:144 %iv = phi i32 [%start, %entry], [%iv.next, %loop]145 %cmp_1 = icmp sle i32 %iv, %inv_1146 %cmp_2 = icmp sle i32 %iv, %inv_2147 %loop_cond = and i1 %cmp_1, %cmp_2148 %iv.next = add i32 %iv, 1149 br i1 %loop_cond, label %loop, label %exit150 151exit:152 ret i32 %iv153}154 155; turn to %iv >u umax(inv_1, inv_2) and hoist it out of loop.156define i32 @test_ugt(i32 %start, i32 %inv_1, i32 %inv_2) {157; CHECK-LABEL: @test_ugt(158; CHECK-NEXT: entry:159; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])160; CHECK-NEXT: br label [[LOOP:%.*]]161; CHECK: loop:162; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]163; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ugt i32 [[IV]], [[INVARIANT_UMAX]]164; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1165; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]166; CHECK: exit:167; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]168; CHECK-NEXT: ret i32 [[IV_LCSSA]]169;170entry:171 br label %loop172 173loop:174 %iv = phi i32 [%start, %entry], [%iv.next, %loop]175 %cmp_1 = icmp ugt i32 %iv, %inv_1176 %cmp_2 = icmp ugt i32 %iv, %inv_2177 %loop_cond = and i1 %cmp_1, %cmp_2178 %iv.next = add i32 %iv, 1179 br i1 %loop_cond, label %loop, label %exit180 181exit:182 ret i32 %iv183}184 185; turn to %iv >=u umax(inv_1, inv_2) and hoist it out of loop.186define i32 @test_uge(i32 %start, i32 %inv_1, i32 %inv_2) {187; CHECK-LABEL: @test_uge(188; CHECK-NEXT: entry:189; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])190; CHECK-NEXT: br label [[LOOP:%.*]]191; CHECK: loop:192; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]193; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp uge i32 [[IV]], [[INVARIANT_UMAX]]194; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1195; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]196; CHECK: exit:197; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]198; CHECK-NEXT: ret i32 [[IV_LCSSA]]199;200entry:201 br label %loop202 203loop:204 %iv = phi i32 [%start, %entry], [%iv.next, %loop]205 %cmp_1 = icmp uge i32 %iv, %inv_1206 %cmp_2 = icmp uge i32 %iv, %inv_2207 %loop_cond = and i1 %cmp_1, %cmp_2208 %iv.next = add i32 %iv, 1209 br i1 %loop_cond, label %loop, label %exit210 211exit:212 ret i32 %iv213}214 215; turn to %iv >s smax(inv_1, inv_2) and hoist it out of loop.216define i32 @test_sgt(i32 %start, i32 %inv_1, i32 %inv_2) {217; CHECK-LABEL: @test_sgt(218; CHECK-NEXT: entry:219; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])220; CHECK-NEXT: br label [[LOOP:%.*]]221; CHECK: loop:222; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]223; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMAX]]224; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1225; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]226; CHECK: exit:227; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]228; CHECK-NEXT: ret i32 [[IV_LCSSA]]229;230entry:231 br label %loop232 233loop:234 %iv = phi i32 [%start, %entry], [%iv.next, %loop]235 %cmp_1 = icmp sgt i32 %iv, %inv_1236 %cmp_2 = icmp sgt i32 %iv, %inv_2237 %loop_cond = and i1 %cmp_1, %cmp_2238 %iv.next = add i32 %iv, 1239 br i1 %loop_cond, label %loop, label %exit240 241exit:242 ret i32 %iv243}244 245define i32 @test_sgt_samesign(i32 %start, i32 %inv_1, i32 %inv_2) {246; CHECK-LABEL: @test_sgt_samesign(247; CHECK-NEXT: entry:248; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])249; CHECK-NEXT: br label [[LOOP:%.*]]250; CHECK: loop:251; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]252; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMAX]]253; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1254; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]255; CHECK: exit:256; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]257; CHECK-NEXT: ret i32 [[IV_LCSSA]]258;259entry:260 br label %loop261 262loop:263 %iv = phi i32 [%start, %entry], [%iv.next, %loop]264 %cmp_1 = icmp samesign ugt i32 %iv, %inv_1265 %cmp_2 = icmp sgt i32 %iv, %inv_2266 %loop_cond = and i1 %cmp_1, %cmp_2267 %iv.next = add i32 %iv, 1268 br i1 %loop_cond, label %loop, label %exit269 270exit:271 ret i32 %iv272}273 274; turn to %iv >=s smax(inv_1, inv_2) and hoist it out of loop.275define i32 @test_sge(i32 %start, i32 %inv_1, i32 %inv_2) {276; CHECK-LABEL: @test_sge(277; CHECK-NEXT: entry:278; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])279; CHECK-NEXT: br label [[LOOP:%.*]]280; CHECK: loop:281; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]282; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMAX]]283; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1284; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]285; CHECK: exit:286; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]287; CHECK-NEXT: ret i32 [[IV_LCSSA]]288;289entry:290 br label %loop291 292loop:293 %iv = phi i32 [%start, %entry], [%iv.next, %loop]294 %cmp_1 = icmp sge i32 %iv, %inv_1295 %cmp_2 = icmp sge i32 %iv, %inv_2296 %loop_cond = and i1 %cmp_1, %cmp_2297 %iv.next = add i32 %iv, 1298 br i1 %loop_cond, label %loop, label %exit299 300exit:301 ret i32 %iv302}303 304define i32 @test_sge_samesign(i32 %start, i32 %inv_1, i32 %inv_2) {305; CHECK-LABEL: @test_sge_samesign(306; CHECK-NEXT: entry:307; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])308; CHECK-NEXT: br label [[LOOP:%.*]]309; CHECK: loop:310; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]311; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMAX]]312; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1313; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]314; CHECK: exit:315; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]316; CHECK-NEXT: ret i32 [[IV_LCSSA]]317;318entry:319 br label %loop320 321loop:322 %iv = phi i32 [%start, %entry], [%iv.next, %loop]323 %cmp_1 = icmp sge i32 %iv, %inv_1324 %cmp_2 = icmp samesign uge i32 %iv, %inv_2325 %loop_cond = and i1 %cmp_1, %cmp_2326 %iv.next = add i32 %iv, 1327 br i1 %loop_cond, label %loop, label %exit328 329exit:330 ret i32 %iv331}332 333; Turn OR to AND and handle accordingly.334define i32 @test_ult_inv(i32 %start, i32 %inv_1, i32 %inv_2) {335; CHECK-LABEL: @test_ult_inv(336; CHECK-NEXT: entry:337; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])338; CHECK-NEXT: br label [[LOOP:%.*]]339; CHECK: loop:340; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]341; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMAX]]342; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1343; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]344; CHECK: exit:345; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]346; CHECK-NEXT: ret i32 [[IV_LCSSA]]347;348entry:349 br label %loop350 351loop:352 %iv = phi i32 [%start, %entry], [%iv.next, %loop]353 %cmp_1 = icmp ult i32 %iv, %inv_1354 %cmp_2 = icmp ult i32 %iv, %inv_2355 %loop_cond = or i1 %cmp_1, %cmp_2356 %iv.next = add i32 %iv, 1357 br i1 %loop_cond, label %loop, label %exit358 359exit:360 ret i32 %iv361}362 363; Turn OR to AND and handle accordingly.364define i32 @test_ule_inv(i32 %start, i32 %inv_1, i32 %inv_2) {365; CHECK-LABEL: @test_ule_inv(366; CHECK-NEXT: entry:367; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])368; CHECK-NEXT: br label [[LOOP:%.*]]369; CHECK: loop:370; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]371; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ule i32 [[IV]], [[INVARIANT_UMAX]]372; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1373; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]374; CHECK: exit:375; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]376; CHECK-NEXT: ret i32 [[IV_LCSSA]]377;378entry:379 br label %loop380 381loop:382 %iv = phi i32 [%start, %entry], [%iv.next, %loop]383 %cmp_1 = icmp ule i32 %iv, %inv_1384 %cmp_2 = icmp ule i32 %iv, %inv_2385 %loop_cond = or i1 %cmp_1, %cmp_2386 %iv.next = add i32 %iv, 1387 br i1 %loop_cond, label %loop, label %exit388 389exit:390 ret i32 %iv391}392 393; Turn OR to AND and handle accordingly.394define i32 @test_slt_inv(i32 %start, i32 %inv_1, i32 %inv_2) {395; CHECK-LABEL: @test_slt_inv(396; CHECK-NEXT: entry:397; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])398; CHECK-NEXT: br label [[LOOP:%.*]]399; CHECK: loop:400; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]401; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_SMAX]]402; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1403; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]404; CHECK: exit:405; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]406; CHECK-NEXT: ret i32 [[IV_LCSSA]]407;408entry:409 br label %loop410 411loop:412 %iv = phi i32 [%start, %entry], [%iv.next, %loop]413 %cmp_1 = icmp slt i32 %iv, %inv_1414 %cmp_2 = icmp slt i32 %iv, %inv_2415 %loop_cond = or i1 %cmp_1, %cmp_2416 %iv.next = add i32 %iv, 1417 br i1 %loop_cond, label %loop, label %exit418 419exit:420 ret i32 %iv421}422 423; Turn OR to AND and handle accordingly.424define i32 @test_sle_inv(i32 %start, i32 %inv_1, i32 %inv_2) {425; CHECK-LABEL: @test_sle_inv(426; CHECK-NEXT: entry:427; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])428; CHECK-NEXT: br label [[LOOP:%.*]]429; CHECK: loop:430; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]431; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sle i32 [[IV]], [[INVARIANT_SMAX]]432; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1433; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]434; CHECK: exit:435; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]436; CHECK-NEXT: ret i32 [[IV_LCSSA]]437;438entry:439 br label %loop440 441loop:442 %iv = phi i32 [%start, %entry], [%iv.next, %loop]443 %cmp_1 = icmp sle i32 %iv, %inv_1444 %cmp_2 = icmp sle i32 %iv, %inv_2445 %loop_cond = or i1 %cmp_1, %cmp_2446 %iv.next = add i32 %iv, 1447 br i1 %loop_cond, label %loop, label %exit448 449exit:450 ret i32 %iv451}452 453; Turn OR to AND and handle accordingly.454define i32 @test_ugt_inv(i32 %start, i32 %inv_1, i32 %inv_2) {455; CHECK-LABEL: @test_ugt_inv(456; CHECK-NEXT: entry:457; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])458; CHECK-NEXT: br label [[LOOP:%.*]]459; CHECK: loop:460; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]461; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ugt i32 [[IV]], [[INVARIANT_UMIN]]462; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1463; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]464; CHECK: exit:465; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]466; CHECK-NEXT: ret i32 [[IV_LCSSA]]467;468entry:469 br label %loop470 471loop:472 %iv = phi i32 [%start, %entry], [%iv.next, %loop]473 %cmp_1 = icmp ugt i32 %iv, %inv_1474 %cmp_2 = icmp ugt i32 %iv, %inv_2475 %loop_cond = or i1 %cmp_1, %cmp_2476 %iv.next = add i32 %iv, 1477 br i1 %loop_cond, label %loop, label %exit478 479exit:480 ret i32 %iv481}482 483; Turn OR to AND and handle accordingly.484define i32 @test_uge_inv(i32 %start, i32 %inv_1, i32 %inv_2) {485; CHECK-LABEL: @test_uge_inv(486; CHECK-NEXT: entry:487; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])488; CHECK-NEXT: br label [[LOOP:%.*]]489; CHECK: loop:490; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]491; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp uge i32 [[IV]], [[INVARIANT_UMIN]]492; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1493; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]494; CHECK: exit:495; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]496; CHECK-NEXT: ret i32 [[IV_LCSSA]]497;498entry:499 br label %loop500 501loop:502 %iv = phi i32 [%start, %entry], [%iv.next, %loop]503 %cmp_1 = icmp uge i32 %iv, %inv_1504 %cmp_2 = icmp uge i32 %iv, %inv_2505 %loop_cond = or i1 %cmp_1, %cmp_2506 %iv.next = add i32 %iv, 1507 br i1 %loop_cond, label %loop, label %exit508 509exit:510 ret i32 %iv511}512 513; Turn OR to AND and handle accordingly.514define i32 @test_sgt_inv(i32 %start, i32 %inv_1, i32 %inv_2) {515; CHECK-LABEL: @test_sgt_inv(516; CHECK-NEXT: entry:517; CHECK-NEXT: [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])518; CHECK-NEXT: br label [[LOOP:%.*]]519; CHECK: loop:520; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]521; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMIN]]522; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1523; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]524; CHECK: exit:525; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]526; CHECK-NEXT: ret i32 [[IV_LCSSA]]527;528entry:529 br label %loop530 531loop:532 %iv = phi i32 [%start, %entry], [%iv.next, %loop]533 %cmp_1 = icmp sgt i32 %iv, %inv_1534 %cmp_2 = icmp sgt i32 %iv, %inv_2535 %loop_cond = or i1 %cmp_1, %cmp_2536 %iv.next = add i32 %iv, 1537 br i1 %loop_cond, label %loop, label %exit538 539exit:540 ret i32 %iv541}542 543; Turn OR to AND and handle accordingly.544define i32 @test_sge_inv(i32 %start, i32 %inv_1, i32 %inv_2) {545; CHECK-LABEL: @test_sge_inv(546; CHECK-NEXT: entry:547; CHECK-NEXT: [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])548; CHECK-NEXT: br label [[LOOP:%.*]]549; CHECK: loop:550; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]551; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMIN]]552; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1553; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]554; CHECK: exit:555; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]556; CHECK-NEXT: ret i32 [[IV_LCSSA]]557;558entry:559 br label %loop560 561loop:562 %iv = phi i32 [%start, %entry], [%iv.next, %loop]563 %cmp_1 = icmp sge i32 %iv, %inv_1564 %cmp_2 = icmp sge i32 %iv, %inv_2565 %loop_cond = or i1 %cmp_1, %cmp_2566 %iv.next = add i32 %iv, 1567 br i1 %loop_cond, label %loop, label %exit568 569exit:570 ret i32 %iv571}572 573; turn to %iv <u umin(inv_1, inv_2) and hoist it out of loop.574define i32 @test_ult_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {575; CHECK-LABEL: @test_ult_swapped(576; CHECK-NEXT: entry:577; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])578; CHECK-NEXT: br label [[LOOP:%.*]]579; CHECK: loop:580; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]581; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]582; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1583; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]584; CHECK: exit:585; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]586; CHECK-NEXT: ret i32 [[IV_LCSSA]]587;588entry:589 br label %loop590 591loop:592 %iv = phi i32 [%start, %entry], [%iv.next, %loop]593 %cmp_1 = icmp ugt i32 %inv_1, %iv594 %cmp_2 = icmp ugt i32 %inv_2, %iv595 %loop_cond = and i1 %cmp_1, %cmp_2596 %iv.next = add i32 %iv, 1597 br i1 %loop_cond, label %loop, label %exit598 599exit:600 ret i32 %iv601}602 603; turn to %iv <=u umin(inv_1, inv_2) and hoist it out of loop.604define i32 @test_ule_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {605; CHECK-LABEL: @test_ule_swapped(606; CHECK-NEXT: entry:607; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])608; CHECK-NEXT: br label [[LOOP:%.*]]609; CHECK: loop:610; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]611; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ule i32 [[IV]], [[INVARIANT_UMIN]]612; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1613; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]614; CHECK: exit:615; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]616; CHECK-NEXT: ret i32 [[IV_LCSSA]]617;618entry:619 br label %loop620 621loop:622 %iv = phi i32 [%start, %entry], [%iv.next, %loop]623 %cmp_1 = icmp uge i32 %inv_1, %iv624 %cmp_2 = icmp uge i32 %inv_2, %iv625 %loop_cond = and i1 %cmp_1, %cmp_2626 %iv.next = add i32 %iv, 1627 br i1 %loop_cond, label %loop, label %exit628 629exit:630 ret i32 %iv631}632 633; turn to %iv <s smin(inv_1, inv_2) and hoist it out of loop.634define i32 @test_slt_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {635; CHECK-LABEL: @test_slt_swapped(636; CHECK-NEXT: entry:637; CHECK-NEXT: [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])638; CHECK-NEXT: br label [[LOOP:%.*]]639; CHECK: loop:640; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]641; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_SMIN]]642; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1643; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]644; CHECK: exit:645; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]646; CHECK-NEXT: ret i32 [[IV_LCSSA]]647;648entry:649 br label %loop650 651loop:652 %iv = phi i32 [%start, %entry], [%iv.next, %loop]653 %cmp_1 = icmp sgt i32 %inv_1, %iv654 %cmp_2 = icmp sgt i32 %inv_2, %iv655 %loop_cond = and i1 %cmp_1, %cmp_2656 %iv.next = add i32 %iv, 1657 br i1 %loop_cond, label %loop, label %exit658 659exit:660 ret i32 %iv661}662 663; turn to %iv <=s smin(inv_1, inv_2) and hoist it out of loop.664define i32 @test_sle_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {665; CHECK-LABEL: @test_sle_swapped(666; CHECK-NEXT: entry:667; CHECK-NEXT: [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])668; CHECK-NEXT: br label [[LOOP:%.*]]669; CHECK: loop:670; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]671; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sle i32 [[IV]], [[INVARIANT_SMIN]]672; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1673; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]674; CHECK: exit:675; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]676; CHECK-NEXT: ret i32 [[IV_LCSSA]]677;678entry:679 br label %loop680 681loop:682 %iv = phi i32 [%start, %entry], [%iv.next, %loop]683 %cmp_1 = icmp sge i32 %inv_1, %iv684 %cmp_2 = icmp sge i32 %inv_2, %iv685 %loop_cond = and i1 %cmp_1, %cmp_2686 %iv.next = add i32 %iv, 1687 br i1 %loop_cond, label %loop, label %exit688 689exit:690 ret i32 %iv691}692 693; turn to %iv >u umax(inv_1, inv_2) and hoist it out of loop.694define i32 @test_ugt_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {695; CHECK-LABEL: @test_ugt_swapped(696; CHECK-NEXT: entry:697; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])698; CHECK-NEXT: br label [[LOOP:%.*]]699; CHECK: loop:700; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]701; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ugt i32 [[IV]], [[INVARIANT_UMAX]]702; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1703; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]704; CHECK: exit:705; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]706; CHECK-NEXT: ret i32 [[IV_LCSSA]]707;708entry:709 br label %loop710 711loop:712 %iv = phi i32 [%start, %entry], [%iv.next, %loop]713 %cmp_1 = icmp ult i32 %inv_1, %iv714 %cmp_2 = icmp ult i32 %inv_2, %iv715 %loop_cond = and i1 %cmp_1, %cmp_2716 %iv.next = add i32 %iv, 1717 br i1 %loop_cond, label %loop, label %exit718 719exit:720 ret i32 %iv721}722 723; turn to %iv >=u umax(inv_1, inv_2) and hoist it out of loop.724define i32 @test_uge_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {725; CHECK-LABEL: @test_uge_swapped(726; CHECK-NEXT: entry:727; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])728; CHECK-NEXT: br label [[LOOP:%.*]]729; CHECK: loop:730; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]731; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp uge i32 [[IV]], [[INVARIANT_UMAX]]732; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1733; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]734; CHECK: exit:735; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]736; CHECK-NEXT: ret i32 [[IV_LCSSA]]737;738entry:739 br label %loop740 741loop:742 %iv = phi i32 [%start, %entry], [%iv.next, %loop]743 %cmp_1 = icmp ule i32 %inv_1, %iv744 %cmp_2 = icmp ule i32 %inv_2, %iv745 %loop_cond = and i1 %cmp_1, %cmp_2746 %iv.next = add i32 %iv, 1747 br i1 %loop_cond, label %loop, label %exit748 749exit:750 ret i32 %iv751}752 753; turn to %iv >s smax(inv_1, inv_2) and hoist it out of loop.754define i32 @test_sgt_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {755; CHECK-LABEL: @test_sgt_swapped(756; CHECK-NEXT: entry:757; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])758; CHECK-NEXT: br label [[LOOP:%.*]]759; CHECK: loop:760; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]761; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMAX]]762; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1763; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]764; CHECK: exit:765; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]766; CHECK-NEXT: ret i32 [[IV_LCSSA]]767;768entry:769 br label %loop770 771loop:772 %iv = phi i32 [%start, %entry], [%iv.next, %loop]773 %cmp_1 = icmp slt i32 %inv_1, %iv774 %cmp_2 = icmp slt i32 %inv_2, %iv775 %loop_cond = and i1 %cmp_1, %cmp_2776 %iv.next = add i32 %iv, 1777 br i1 %loop_cond, label %loop, label %exit778 779exit:780 ret i32 %iv781}782 783; turn to %iv >=s smax(inv_1, inv_2) and hoist it out of loop.784define i32 @test_sge_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {785; CHECK-LABEL: @test_sge_swapped(786; CHECK-NEXT: entry:787; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])788; CHECK-NEXT: br label [[LOOP:%.*]]789; CHECK: loop:790; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]791; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMAX]]792; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1793; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]794; CHECK: exit:795; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]796; CHECK-NEXT: ret i32 [[IV_LCSSA]]797;798entry:799 br label %loop800 801loop:802 %iv = phi i32 [%start, %entry], [%iv.next, %loop]803 %cmp_1 = icmp sle i32 %inv_1, %iv804 %cmp_2 = icmp sle i32 %inv_2, %iv805 %loop_cond = and i1 %cmp_1, %cmp_2806 %iv.next = add i32 %iv, 1807 br i1 %loop_cond, label %loop, label %exit808 809exit:810 ret i32 %iv811}812 813; inv_2 needs freeze because hoisted umax would create a new use that didn't exist before.814; Counter-example: %cmp_1 = false, %inv_2 = poison.815define i32 @test_logical_and_ult_needs_freeze(i32 %start, i32 %inv_1, i32 %inv_2) {816; CHECK-LABEL: @test_logical_and_ult_needs_freeze(817; CHECK-NEXT: entry:818; CHECK-NEXT: [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]819; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])820; CHECK-NEXT: br label [[LOOP:%.*]]821; CHECK: loop:822; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]823; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]824; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1825; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]826; CHECK: exit:827; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]828; CHECK-NEXT: ret i32 [[IV_LCSSA]]829;830entry:831 br label %loop832 833loop:834 %iv = phi i32 [%start, %entry], [%iv.next, %loop]835 %cmp_1 = icmp ult i32 %iv, %inv_1836 %cmp_2 = icmp ult i32 %iv, %inv_2837 %loop_cond = select i1 %cmp_1, i1 %cmp_2, i1 false838 %iv.next = add i32 %iv, 1839 br i1 %loop_cond, label %loop, label %exit840 841exit:842 ret i32 %iv843}844 845; turn to %iv <u umin(inv_1, inv_2) and hoist it out of loop.846; https://alive2.llvm.org/ce/z/mhKGtT847define i32 @test_logical_and_ult_pos(i32 %start, i32 %inv_1, i32 noundef %inv_2) {848; CHECK-LABEL: @test_logical_and_ult_pos(849; CHECK-NEXT: entry:850; CHECK-NEXT: [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]851; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])852; CHECK-NEXT: br label [[LOOP:%.*]]853; CHECK: loop:854; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]855; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]856; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1857; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]858; CHECK: exit:859; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]860; CHECK-NEXT: ret i32 [[IV_LCSSA]]861;862entry:863 br label %loop864 865loop:866 %iv = phi i32 [%start, %entry], [%iv.next, %loop]867 %cmp_1 = icmp ult i32 %iv, %inv_1868 %cmp_2 = icmp ult i32 %iv, %inv_2869 %loop_cond = select i1 %cmp_1, i1 %cmp_2, i1 false870 %iv.next = add i32 %iv, 1871 br i1 %loop_cond, label %loop, label %exit872 873exit:874 ret i32 %iv875}876 877; inv_2 needs freeze because hoisted umax would create a new use that didn't exist before.878define i32 @test_logical_or_ult_inv_needs_freeze(i32 %start, i32 %inv_1, i32 %inv_2) {879; CHECK-LABEL: @test_logical_or_ult_inv_needs_freeze(880; CHECK-NEXT: entry:881; CHECK-NEXT: [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]882; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])883; CHECK-NEXT: br label [[LOOP:%.*]]884; CHECK: loop:885; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]886; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMAX]]887; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1888; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]889; CHECK: exit:890; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]891; CHECK-NEXT: ret i32 [[IV_LCSSA]]892;893entry:894 br label %loop895 896loop:897 %iv = phi i32 [%start, %entry], [%iv.next, %loop]898 %cmp_1 = icmp ult i32 %iv, %inv_1899 %cmp_2 = icmp ult i32 %iv, %inv_2900 %loop_cond = select i1 %cmp_1, i1 true, i1 %cmp_2901 %iv.next = add i32 %iv, 1902 br i1 %loop_cond, label %loop, label %exit903 904exit:905 ret i32 %iv906}907 908; turn to %iv <u umax(inv_1, inv_2) and hoist it out of loop.909; https://alive2.llvm.org/ce/z/zgyG5N910define i32 @test_logical_or_ult_inv_pos(i32 %start, i32 %inv_1, i32 noundef %inv_2) {911; CHECK-LABEL: @test_logical_or_ult_inv_pos(912; CHECK-NEXT: entry:913; CHECK-NEXT: [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]914; CHECK-NEXT: [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])915; CHECK-NEXT: br label [[LOOP:%.*]]916; CHECK: loop:917; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]918; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMAX]]919; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1920; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]921; CHECK: exit:922; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]923; CHECK-NEXT: ret i32 [[IV_LCSSA]]924;925entry:926 br label %loop927 928loop:929 %iv = phi i32 [%start, %entry], [%iv.next, %loop]930 %cmp_1 = icmp ult i32 %iv, %inv_1931 %cmp_2 = icmp ult i32 %iv, %inv_2932 %loop_cond = select i1 %cmp_1, i1 true, i1 %cmp_2933 %iv.next = add i32 %iv, 1934 br i1 %loop_cond, label %loop, label %exit935 936exit:937 ret i32 %iv938}939 940; Mismatched predicates, do not optimize.941define i32 @test_mismatched_predicates_neg(i32 %start, i32 %inv_1, i32 %inv_2) {942; CHECK-LABEL: @test_mismatched_predicates_neg(943; CHECK-NEXT: entry:944; CHECK-NEXT: br label [[LOOP:%.*]]945; CHECK: loop:946; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]947; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]948; CHECK-NEXT: [[CMP_2:%.*]] = icmp ule i32 [[IV]], [[INV_2:%.*]]949; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]950; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1951; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]952; CHECK: exit:953; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]954; CHECK-NEXT: ret i32 [[IV_LCSSA]]955;956entry:957 br label %loop958 959loop:960 %iv = phi i32 [%start, %entry], [%iv.next, %loop]961 %cmp_1 = icmp ult i32 %iv, %inv_1962 %cmp_2 = icmp ule i32 %iv, %inv_2963 %loop_cond = and i1 %cmp_1, %cmp_2964 %iv.next = add i32 %iv, 1965 br i1 %loop_cond, label %loop, label %exit966 967exit:968 ret i32 %iv969}970 971; TODO: Turn ule against constant into ult against constant, then do the same as in test_ult.972; https://alive2.llvm.org/ce/z/rucunQ973define i32 @test_mismatched_predicates_constant_pos_1(i32 %start, i32 %inv_1, i32 %inv_2) {974; CHECK-LABEL: @test_mismatched_predicates_constant_pos_1(975; CHECK-NEXT: entry:976; CHECK-NEXT: br label [[LOOP:%.*]]977; CHECK: loop:978; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]979; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]980; CHECK-NEXT: [[CMP_2:%.*]] = icmp ule i32 [[IV]], 100981; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]982; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1983; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]984; CHECK: exit:985; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]986; CHECK-NEXT: ret i32 [[IV_LCSSA]]987;988entry:989 br label %loop990 991loop:992 %iv = phi i32 [%start, %entry], [%iv.next, %loop]993 %cmp_1 = icmp ult i32 %iv, %inv_1994 %cmp_2 = icmp ule i32 %iv, 100995 %loop_cond = and i1 %cmp_1, %cmp_2996 %iv.next = add i32 %iv, 1997 br i1 %loop_cond, label %loop, label %exit998 999exit:1000 ret i32 %iv1001}1002 1003; TODO: Turn ult against a constant into ule, then do the same as in test_ule.1004; https://alive2.llvm.org/ce/z/-ht-pU1005define i32 @test_mismatched_predicates_constant_pos_2(i32 %start, i32 %inv_1, i32 %inv_2) {1006; CHECK-LABEL: @test_mismatched_predicates_constant_pos_2(1007; CHECK-NEXT: entry:1008; CHECK-NEXT: br label [[LOOP:%.*]]1009; CHECK: loop:1010; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]1011; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV]], 1001012; CHECK-NEXT: [[CMP_2:%.*]] = icmp ule i32 [[IV]], [[INV_2:%.*]]1013; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1014; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 11015; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1016; CHECK: exit:1017; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]1018; CHECK-NEXT: ret i32 [[IV_LCSSA]]1019;1020entry:1021 br label %loop1022 1023loop:1024 %iv = phi i32 [%start, %entry], [%iv.next, %loop]1025 %cmp_1 = icmp ult i32 %iv, 1001026 %cmp_2 = icmp ule i32 %iv, %inv_21027 %loop_cond = and i1 %cmp_1, %cmp_21028 %iv.next = add i32 %iv, 11029 br i1 %loop_cond, label %loop, label %exit1030 1031exit:1032 ret i32 %iv1033}1034 1035; Do not optimize: `ule -1` cannot be turned into `ult 0` because of overflow.1036; However, this condition is trivially true anyways, so do not bother about it.1037define i32 @test_mismatched_predicates_constant_neg(i32 %start, i32 %inv_1, i32 %inv_2) {1038; CHECK-LABEL: @test_mismatched_predicates_constant_neg(1039; CHECK-NEXT: entry:1040; CHECK-NEXT: br label [[LOOP:%.*]]1041; CHECK: loop:1042; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]1043; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]1044; CHECK-NEXT: [[CMP_2:%.*]] = icmp ule i32 [[IV]], -11045; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1046; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 11047; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1048; CHECK: exit:1049; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]1050; CHECK-NEXT: ret i32 [[IV_LCSSA]]1051;1052entry:1053 br label %loop1054 1055loop:1056 %iv = phi i32 [%start, %entry], [%iv.next, %loop]1057 %cmp_1 = icmp ult i32 %iv, %inv_11058 %cmp_2 = icmp ule i32 %iv, -11059 %loop_cond = and i1 %cmp_1, %cmp_21060 %iv.next = add i32 %iv, 11061 br i1 %loop_cond, label %loop, label %exit1062 1063exit:1064 ret i32 %iv1065}1066 1067; Do not optimize: predicate eq.1068define i32 @test_eq_neg(i32 %start, i32 %inv_1, i32 %inv_2) {1069; CHECK-LABEL: @test_eq_neg(1070; CHECK-NEXT: entry:1071; CHECK-NEXT: br label [[LOOP:%.*]]1072; CHECK: loop:1073; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]1074; CHECK-NEXT: [[CMP_1:%.*]] = icmp eq i32 [[IV]], [[INV_1:%.*]]1075; CHECK-NEXT: [[CMP_2:%.*]] = icmp eq i32 [[IV]], [[INV_2:%.*]]1076; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1077; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 11078; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1079; CHECK: exit:1080; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]1081; CHECK-NEXT: ret i32 [[IV_LCSSA]]1082;1083entry:1084 br label %loop1085 1086loop:1087 %iv = phi i32 [%start, %entry], [%iv.next, %loop]1088 %cmp_1 = icmp eq i32 %iv, %inv_11089 %cmp_2 = icmp eq i32 %iv, %inv_21090 %loop_cond = and i1 %cmp_1, %cmp_21091 %iv.next = add i32 %iv, 11092 br i1 %loop_cond, label %loop, label %exit1093 1094exit:1095 ret i32 %iv1096}1097 1098; Do not optimize: predicate ne.1099define i32 @test_ne_neg(i32 %start, i32 %inv_1, i32 %inv_2) {1100; CHECK-LABEL: @test_ne_neg(1101; CHECK-NEXT: entry:1102; CHECK-NEXT: br label [[LOOP:%.*]]1103; CHECK: loop:1104; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]1105; CHECK-NEXT: [[CMP_1:%.*]] = icmp ne i32 [[IV]], [[INV_1:%.*]]1106; CHECK-NEXT: [[CMP_2:%.*]] = icmp ne i32 [[IV]], [[INV_2:%.*]]1107; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1108; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 11109; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1110; CHECK: exit:1111; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]1112; CHECK-NEXT: ret i32 [[IV_LCSSA]]1113;1114entry:1115 br label %loop1116 1117loop:1118 %iv = phi i32 [%start, %entry], [%iv.next, %loop]1119 %cmp_1 = icmp ne i32 %iv, %inv_11120 %cmp_2 = icmp ne i32 %iv, %inv_21121 %loop_cond = and i1 %cmp_1, %cmp_21122 %iv.next = add i32 %iv, 11123 br i1 %loop_cond, label %loop, label %exit1124 1125exit:1126 ret i32 %iv1127}1128 1129; Do not optimize: extra use.1130define i32 @test_ult_extra_use_1_neg(i32 %start, i32 %inv_1, i32 %inv_2) {1131; CHECK-LABEL: @test_ult_extra_use_1_neg(1132; CHECK-NEXT: entry:1133; CHECK-NEXT: br label [[LOOP:%.*]]1134; CHECK: loop:1135; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]1136; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]1137; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i32 [[IV]], [[INV_2:%.*]]1138; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1139; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 11140; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1141; CHECK: exit:1142; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]1143; CHECK-NEXT: [[CMP_1_LCSSA:%.*]] = phi i1 [ [[CMP_1]], [[LOOP]] ]1144; CHECK-NEXT: call void @use(i1 [[CMP_1_LCSSA]])1145; CHECK-NEXT: ret i32 [[IV_LCSSA]]1146;1147entry:1148 br label %loop1149 1150loop:1151 %iv = phi i32 [%start, %entry], [%iv.next, %loop]1152 %cmp_1 = icmp ult i32 %iv, %inv_11153 %cmp_2 = icmp ult i32 %iv, %inv_21154 %loop_cond = and i1 %cmp_1, %cmp_21155 %iv.next = add i32 %iv, 11156 br i1 %loop_cond, label %loop, label %exit1157 1158exit:1159 call void @use(i1 %cmp_1)1160 ret i32 %iv1161}1162 1163define i32 @test_ult_extra_use_2_neg(i32 %start, i32 %inv_1, i32 %inv_2) {1164; CHECK-LABEL: @test_ult_extra_use_2_neg(1165; CHECK-NEXT: entry:1166; CHECK-NEXT: br label [[LOOP:%.*]]1167; CHECK: loop:1168; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]1169; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]1170; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i32 [[IV]], [[INV_2:%.*]]1171; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1172; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 11173; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1174; CHECK: exit:1175; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]1176; CHECK-NEXT: [[CMP_2_LCSSA:%.*]] = phi i1 [ [[CMP_2]], [[LOOP]] ]1177; CHECK-NEXT: call void @use(i1 [[CMP_2_LCSSA]])1178; CHECK-NEXT: ret i32 [[IV_LCSSA]]1179;1180entry:1181 br label %loop1182 1183loop:1184 %iv = phi i32 [%start, %entry], [%iv.next, %loop]1185 %cmp_1 = icmp ult i32 %iv, %inv_11186 %cmp_2 = icmp ult i32 %iv, %inv_21187 %loop_cond = and i1 %cmp_1, %cmp_21188 %iv.next = add i32 %iv, 11189 br i1 %loop_cond, label %loop, label %exit1190 1191exit:1192 call void @use(i1 %cmp_2)1193 ret i32 %iv1194}1195 1196; This can be optimized, despite the fact that loop_cond has other uses.1197define i32 @test_ult_extra_use_result_pos(i32 %start, i32 %inv_1, i32 %inv_2) {1198; CHECK-LABEL: @test_ult_extra_use_result_pos(1199; CHECK-NEXT: entry:1200; CHECK-NEXT: [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])1201; CHECK-NEXT: br label [[LOOP:%.*]]1202; CHECK: loop:1203; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]1204; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]1205; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 11206; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1207; CHECK: exit:1208; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]1209; CHECK-NEXT: [[LOOP_COND_LCSSA:%.*]] = phi i1 [ [[LOOP_COND]], [[LOOP]] ]1210; CHECK-NEXT: call void @use(i1 [[LOOP_COND_LCSSA]])1211; CHECK-NEXT: ret i32 [[IV_LCSSA]]1212;1213entry:1214 br label %loop1215 1216loop:1217 %iv = phi i32 [%start, %entry], [%iv.next, %loop]1218 %cmp_1 = icmp ult i32 %iv, %inv_11219 %cmp_2 = icmp ult i32 %iv, %inv_21220 %loop_cond = and i1 %cmp_1, %cmp_21221 %iv.next = add i32 %iv, 11222 br i1 %loop_cond, label %loop, label %exit1223 1224exit:1225 call void @use(i1 %loop_cond)1226 ret i32 %iv1227}1228 1229; Do not optimize: comparison against different variant values.1230define i32 @test_ult_different_variants_neg(i32 %start_1, i32 %start_2, i32 %inv_1, i32 %inv_2) {1231; CHECK-LABEL: @test_ult_different_variants_neg(1232; CHECK-NEXT: entry:1233; CHECK-NEXT: br label [[LOOP:%.*]]1234; CHECK: loop:1235; CHECK-NEXT: [[IV_1:%.*]] = phi i32 [ [[START_1:%.*]], [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP]] ]1236; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[START_2:%.*]], [[ENTRY]] ], [ [[IV_2_NEXT:%.*]], [[LOOP]] ]1237; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV_1]], [[INV_1:%.*]]1238; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i32 [[IV_2]], [[INV_2:%.*]]1239; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1240; CHECK-NEXT: [[IV_1_NEXT]] = add i32 [[IV_1]], 11241; CHECK-NEXT: [[IV_2_NEXT]] = add i32 [[IV_2]], 11242; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1243; CHECK: exit:1244; CHECK-NEXT: [[IV_1_LCSSA:%.*]] = phi i32 [ [[IV_1]], [[LOOP]] ]1245; CHECK-NEXT: ret i32 [[IV_1_LCSSA]]1246;1247entry:1248 br label %loop1249 1250loop:1251 %iv_1 = phi i32 [%start_1, %entry], [%iv_1.next, %loop]1252 %iv_2 = phi i32 [%start_2, %entry], [%iv_2.next, %loop]1253 %cmp_1 = icmp ult i32 %iv_1, %inv_11254 %cmp_2 = icmp ult i32 %iv_2, %inv_21255 %loop_cond = and i1 %cmp_1, %cmp_21256 %iv_1.next = add i32 %iv_1, 11257 %iv_2.next = add i32 %iv_2, 11258 br i1 %loop_cond, label %loop, label %exit1259 1260exit:1261 ret i32 %iv_11262}1263 1264; Do not optimize: one of comparisons is against loop-variant.1265define i32 @test_ult_compare_against_variant_neg(i32 %start_1, i32 %start_2, i32 %inv_1, i32 %inv_2) {1266; CHECK-LABEL: @test_ult_compare_against_variant_neg(1267; CHECK-NEXT: entry:1268; CHECK-NEXT: br label [[LOOP:%.*]]1269; CHECK: loop:1270; CHECK-NEXT: [[IV_1:%.*]] = phi i32 [ [[START_1:%.*]], [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP]] ]1271; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[START_2:%.*]], [[ENTRY]] ], [ [[IV_2_NEXT:%.*]], [[LOOP]] ]1272; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[IV_1]], [[INV_1:%.*]]1273; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i32 [[IV_1]], [[IV_2]]1274; CHECK-NEXT: [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]1275; CHECK-NEXT: [[IV_1_NEXT]] = add i32 [[IV_1]], 11276; CHECK-NEXT: [[IV_2_NEXT]] = add i32 [[IV_2]], 11277; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]1278; CHECK: exit:1279; CHECK-NEXT: [[IV_1_LCSSA:%.*]] = phi i32 [ [[IV_1]], [[LOOP]] ]1280; CHECK-NEXT: ret i32 [[IV_1_LCSSA]]1281;1282entry:1283 br label %loop1284 1285loop:1286 %iv_1 = phi i32 [%start_1, %entry], [%iv_1.next, %loop]1287 %iv_2 = phi i32 [%start_2, %entry], [%iv_2.next, %loop]1288 %cmp_1 = icmp ult i32 %iv_1, %inv_11289 %cmp_2 = icmp ult i32 %iv_1, %iv_21290 %loop_cond = and i1 %cmp_1, %cmp_21291 %iv_1.next = add i32 %iv_1, 11292 %iv_2.next = add i32 %iv_2, 11293 br i1 %loop_cond, label %loop, label %exit1294 1295exit:1296 ret i32 %iv_11297}1298 1299declare void @use(i1)1300