568 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 42; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s3 4define void @test0(i32 %a) {5; CHECK-LABEL: define void @test0(6; CHECK-SAME: i32 [[A:%.*]]) {7; CHECK-NEXT: entry:8; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 1009; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]10; CHECK: bb:11; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 112; CHECK-NEXT: br label [[EXIT]]13; CHECK: exit:14; CHECK-NEXT: ret void15;16entry:17 %cmp = icmp slt i32 %a, 10018 br i1 %cmp, label %bb, label %exit19 20bb:21 %add = add i32 %a, 122 br label %exit23 24exit:25 ret void26}27 28define void @test1(i32 %a) {29; CHECK-LABEL: define void @test1(30; CHECK-SAME: i32 [[A:%.*]]) {31; CHECK-NEXT: entry:32; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], 10033; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]34; CHECK: bb:35; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 136; CHECK-NEXT: br label [[EXIT]]37; CHECK: exit:38; CHECK-NEXT: ret void39;40entry:41 %cmp = icmp ult i32 %a, 10042 br i1 %cmp, label %bb, label %exit43 44bb:45 %add = add i32 %a, 146 br label %exit47 48exit:49 ret void50}51 52define void @test2(i32 %a) {53; CHECK-LABEL: define void @test2(54; CHECK-SAME: i32 [[A:%.*]]) {55; CHECK-NEXT: entry:56; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], -157; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]58; CHECK: bb:59; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 160; CHECK-NEXT: br label [[EXIT]]61; CHECK: exit:62; CHECK-NEXT: ret void63;64entry:65 %cmp = icmp ult i32 %a, -166 br i1 %cmp, label %bb, label %exit67 68bb:69 %add = add i32 %a, 170 br label %exit71 72exit:73 ret void74}75 76define void @test3(i32 %a) {77; CHECK-LABEL: define void @test3(78; CHECK-SAME: i32 [[A:%.*]]) {79; CHECK-NEXT: entry:80; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[A]], -181; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]82; CHECK: bb:83; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 184; CHECK-NEXT: br label [[EXIT]]85; CHECK: exit:86; CHECK-NEXT: ret void87;88entry:89 %cmp = icmp ule i32 %a, -190 br i1 %cmp, label %bb, label %exit91 92bb:93 %add = add i32 %a, 194 br label %exit95 96exit:97 ret void98}99 100define void @test4(i32 %a) {101; CHECK-LABEL: define void @test4(102; CHECK-SAME: i32 [[A:%.*]]) {103; CHECK-NEXT: entry:104; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 2147483647105; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]106; CHECK: bb:107; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1108; CHECK-NEXT: br label [[EXIT]]109; CHECK: exit:110; CHECK-NEXT: ret void111;112entry:113 %cmp = icmp slt i32 %a, 2147483647114 br i1 %cmp, label %bb, label %exit115 116bb:117 %add = add i32 %a, 1118 br label %exit119 120exit:121 ret void122}123 124define void @test5(i32 %a) {125; CHECK-LABEL: define void @test5(126; CHECK-SAME: i32 [[A:%.*]]) {127; CHECK-NEXT: entry:128; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 2147483647129; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]130; CHECK: bb:131; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1132; CHECK-NEXT: br label [[EXIT]]133; CHECK: exit:134; CHECK-NEXT: ret void135;136entry:137 %cmp = icmp sle i32 %a, 2147483647138 br i1 %cmp, label %bb, label %exit139 140bb:141 %add = add i32 %a, 1142 br label %exit143 144exit:145 ret void146}147 148; Check for a corner case where an integer value is represented with a constant149; LVILatticeValue instead of constantrange. Check that we don't fail with an150; assertion in this case.151@b = global i32 0, align 4152define void @test6(i32 %a) {153; CHECK-LABEL: define void @test6(154; CHECK-SAME: i32 [[A:%.*]]) {155; CHECK-NEXT: bb:156; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], ptrtoint (ptr @b to i32)157; CHECK-NEXT: ret void158;159bb:160 %add = add i32 %a, ptrtoint (ptr @b to i32)161 ret void162}163 164; Check that we can gather information for conditions is the form of165; and ( i s< 100, Unknown )166define void @test7(i32 %a, i1 %flag) {167; CHECK-LABEL: define void @test7(168; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {169; CHECK-NEXT: entry:170; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100171; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG]]172; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]173; CHECK: bb:174; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1175; CHECK-NEXT: br label [[EXIT]]176; CHECK: exit:177; CHECK-NEXT: ret void178;179entry:180 %cmp.1 = icmp slt i32 %a, 100181 %cmp = and i1 %cmp.1, %flag182 br i1 %cmp, label %bb, label %exit183 184bb:185 %add = add i32 %a, 1186 br label %exit187 188exit:189 ret void190}191 192; Check that we can gather information for conditions is the form of193; and ( i s< 100, i s> 0 )194define void @test8(i32 %a) {195; CHECK-LABEL: define void @test8(196; CHECK-SAME: i32 [[A:%.*]]) {197; CHECK-NEXT: entry:198; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100199; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0200; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]201; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]202; CHECK: bb:203; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1204; CHECK-NEXT: br label [[EXIT]]205; CHECK: exit:206; CHECK-NEXT: ret void207;208entry:209 %cmp.1 = icmp slt i32 %a, 100210 %cmp.2 = icmp sgt i32 %a, 0211 %cmp = and i1 %cmp.1, %cmp.2212 br i1 %cmp, label %bb, label %exit213 214bb:215 %add = add i32 %a, 1216 br label %exit217 218exit:219 ret void220}221 222; Check that for conditions is the form of cond1 && cond2 we don't mistakenly223; assume that !cond1 && !cond2 holds down to false path.224define void @test8_neg(i32 %a) {225; CHECK-LABEL: define void @test8_neg(226; CHECK-SAME: i32 [[A:%.*]]) {227; CHECK-NEXT: entry:228; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100229; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0230; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]231; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]232; CHECK: bb:233; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1234; CHECK-NEXT: br label [[EXIT]]235; CHECK: exit:236; CHECK-NEXT: ret void237;238entry:239 %cmp.1 = icmp sge i32 %a, 100240 %cmp.2 = icmp sle i32 %a, 0241 %cmp = and i1 %cmp.1, %cmp.2242 br i1 %cmp, label %exit, label %bb243 244bb:245 %add = add i32 %a, 1246 br label %exit247 248exit:249 ret void250}251 252; Check that we can gather information for conditions is the form of253; and ( i s< 100, and (i s> 0, Unknown )254define void @test9(i32 %a, i1 %flag) {255; CHECK-LABEL: define void @test9(256; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {257; CHECK-NEXT: entry:258; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100259; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0260; CHECK-NEXT: [[CMP_3:%.*]] = and i1 [[CMP_2]], [[FLAG]]261; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_3]]262; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]263; CHECK: bb:264; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1265; CHECK-NEXT: br label [[EXIT]]266; CHECK: exit:267; CHECK-NEXT: ret void268;269entry:270 %cmp.1 = icmp slt i32 %a, 100271 %cmp.2 = icmp sgt i32 %a, 0272 %cmp.3 = and i1 %cmp.2, %flag273 %cmp = and i1 %cmp.1, %cmp.3274 br i1 %cmp, label %bb, label %exit275 276bb:277 %add = add i32 %a, 1278 br label %exit279 280exit:281 ret void282}283 284; Check that we can gather information for conditions is the form of285; and ( i s< Unknown, ... )286define void @test10(i32 %a, i32 %b, i1 %flag) {287; CHECK-LABEL: define void @test10(288; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i1 [[FLAG:%.*]]) {289; CHECK-NEXT: entry:290; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], [[B]]291; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG]]292; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]293; CHECK: bb:294; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1295; CHECK-NEXT: br label [[EXIT]]296; CHECK: exit:297; CHECK-NEXT: ret void298;299entry:300 %cmp.1 = icmp slt i32 %a, %b301 %cmp = and i1 %cmp.1, %flag302 br i1 %cmp, label %bb, label %exit303 304bb:305 %add = add i32 %a, 1306 br label %exit307 308exit:309 ret void310}311 312@limit = external global i32313define i32 @test11(ptr %p, i32 %i) {314; CHECK-LABEL: define range(i32 0, 2147483645) i32 @test11(315; CHECK-SAME: ptr [[P:%.*]], i32 [[I:%.*]]) {316; CHECK-NEXT: [[LIMIT:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]]317; CHECK-NEXT: [[WITHIN_1:%.*]] = icmp ugt i32 [[LIMIT]], [[I]]318; CHECK-NEXT: [[I_PLUS_7:%.*]] = add i32 [[I]], 7319; CHECK-NEXT: [[WITHIN_2:%.*]] = icmp ugt i32 [[LIMIT]], [[I_PLUS_7]]320; CHECK-NEXT: [[WITHIN:%.*]] = and i1 [[WITHIN_1]], [[WITHIN_2]]321; CHECK-NEXT: br i1 [[WITHIN]], label [[THEN:%.*]], label [[ELSE:%.*]]322; CHECK: then:323; CHECK-NEXT: [[I_PLUS_6:%.*]] = add nuw nsw i32 [[I]], 6324; CHECK-NEXT: ret i32 [[I_PLUS_6]]325; CHECK: else:326; CHECK-NEXT: ret i32 0327;328 %limit = load i32, ptr %p, !range !{i32 0, i32 2147483647}329 %within.1 = icmp ugt i32 %limit, %i330 %i.plus.7 = add i32 %i, 7331 %within.2 = icmp ugt i32 %limit, %i.plus.7332 %within = and i1 %within.1, %within.2333 br i1 %within, label %then, label %else334 335then:336 %i.plus.6 = add i32 %i, 6337 ret i32 %i.plus.6338 339else:340 ret i32 0341}342 343; Check that we can gather information for conditions is the form of344; or ( i s>= 100, Unknown )345define void @test12(i32 %a, i1 %flag) {346; CHECK-LABEL: define void @test12(347; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {348; CHECK-NEXT: entry:349; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100350; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG]]351; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]352; CHECK: bb:353; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1354; CHECK-NEXT: br label [[EXIT]]355; CHECK: exit:356; CHECK-NEXT: ret void357;358entry:359 %cmp.1 = icmp sge i32 %a, 100360 %cmp = or i1 %cmp.1, %flag361 br i1 %cmp, label %exit, label %bb362 363bb:364 %add = add i32 %a, 1365 br label %exit366 367exit:368 ret void369}370 371; Check that we can gather information for conditions is the form of372; or ( i s>= 100, i s<= 0 )373define void @test13(i32 %a) {374; CHECK-LABEL: define void @test13(375; CHECK-SAME: i32 [[A:%.*]]) {376; CHECK-NEXT: entry:377; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100378; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0379; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]380; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]381; CHECK: bb:382; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1383; CHECK-NEXT: br label [[EXIT]]384; CHECK: exit:385; CHECK-NEXT: ret void386;387entry:388 %cmp.1 = icmp sge i32 %a, 100389 %cmp.2 = icmp sle i32 %a, 0390 %cmp = or i1 %cmp.1, %cmp.2391 br i1 %cmp, label %exit, label %bb392 393bb:394 %add = add i32 %a, 1395 br label %exit396 397exit:398 ret void399}400 401; Check that for conditions is the form of cond1 || cond2 we don't mistakenly402; assume that cond1 || cond2 holds down to true path.403define void @test13_neg(i32 %a) {404; CHECK-LABEL: define void @test13_neg(405; CHECK-SAME: i32 [[A:%.*]]) {406; CHECK-NEXT: entry:407; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100408; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0409; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]410; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]411; CHECK: bb:412; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1413; CHECK-NEXT: br label [[EXIT]]414; CHECK: exit:415; CHECK-NEXT: ret void416;417entry:418 %cmp.1 = icmp slt i32 %a, 100419 %cmp.2 = icmp sgt i32 %a, 0420 %cmp = or i1 %cmp.1, %cmp.2421 br i1 %cmp, label %bb, label %exit422 423bb:424 %add = add i32 %a, 1425 br label %exit426 427exit:428 ret void429}430 431; Check that we can gather information for conditions is the form of432; or ( i s>=100, or (i s<= 0, Unknown )433define void @test14(i32 %a, i1 %flag) {434; CHECK-LABEL: define void @test14(435; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {436; CHECK-NEXT: entry:437; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100438; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0439; CHECK-NEXT: [[CMP_3:%.*]] = or i1 [[CMP_2]], [[FLAG]]440; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_3]]441; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]442; CHECK: bb:443; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1444; CHECK-NEXT: br label [[EXIT]]445; CHECK: exit:446; CHECK-NEXT: ret void447;448entry:449 %cmp.1 = icmp sge i32 %a, 100450 %cmp.2 = icmp sle i32 %a, 0451 %cmp.3 = or i1 %cmp.2, %flag452 %cmp = or i1 %cmp.1, %cmp.3453 br i1 %cmp, label %exit, label %bb454 455bb:456 %add = add i32 %a, 1457 br label %exit458 459exit:460 ret void461}462 463; Check that we can gather information for conditions is the form of464; or ( i s>= Unknown, ... )465define void @test15(i32 %a, i32 %b, i1 %flag) {466; CHECK-LABEL: define void @test15(467; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i1 [[FLAG:%.*]]) {468; CHECK-NEXT: entry:469; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], [[B]]470; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG]]471; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]472; CHECK: bb:473; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1474; CHECK-NEXT: br label [[EXIT]]475; CHECK: exit:476; CHECK-NEXT: ret void477;478entry:479 %cmp.1 = icmp sge i32 %a, %b480 %cmp = or i1 %cmp.1, %flag481 br i1 %cmp, label %exit, label %bb482 483bb:484 %add = add i32 %a, 1485 br label %exit486 487exit:488 ret void489}490 491; single basic block loop492; because the loop exit condition is SLT, we can supplement the iv add493; (iv.next def) with an nsw.494define i32 @test16(ptr %n, ptr %a) {495; CHECK-LABEL: define i32 @test16(496; CHECK-SAME: ptr [[N:%.*]], ptr [[A:%.*]]) {497; CHECK-NEXT: preheader:498; CHECK-NEXT: br label [[LOOP:%.*]]499; CHECK: loop:500; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]501; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ACC_CURR:%.*]], [[LOOP]] ]502; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr [[A]] unordered, align 8503; CHECK-NEXT: fence acquire504; CHECK-NEXT: [[ACC_CURR]] = add i32 [[ACC]], [[X]]505; CHECK-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1506; CHECK-NEXT: [[NVAL:%.*]] = load atomic i32, ptr [[N]] unordered, align 8507; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_NEXT]], [[NVAL]]508; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]509; CHECK: exit:510; CHECK-NEXT: ret i32 [[ACC_CURR]]511;512preheader:513 br label %loop514 515loop:516 %iv = phi i32 [ 0, %preheader ], [ %iv.next, %loop ]517 %acc = phi i32 [ 0, %preheader ], [ %acc.curr, %loop ]518 %x = load atomic i32, ptr %a unordered, align 8519 fence acquire520 %acc.curr = add i32 %acc, %x521 %iv.next = add i32 %iv, 1522 %nval = load atomic i32, ptr %n unordered, align 8523 %cmp = icmp slt i32 %iv.next, %nval524 br i1 %cmp, label %loop, label %exit525 526exit:527 ret i32 %acc.curr528}529 530define i32 @test_undef_range(i32 %x) {531; CHECK-LABEL: define i32 @test_undef_range(532; CHECK-SAME: i32 [[X:%.*]]) {533; CHECK-NEXT: entry:534; CHECK-NEXT: switch i32 [[X]], label [[JOIN:%.*]] [535; CHECK-NEXT: i32 1, label [[CASE1:%.*]]536; CHECK-NEXT: i32 2, label [[CASE2:%.*]]537; CHECK-NEXT: ]538; CHECK: case1:539; CHECK-NEXT: br label [[JOIN]]540; CHECK: case2:541; CHECK-NEXT: br label [[JOIN]]542; CHECK: join:543; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[CASE1]] ], [ 2, [[CASE2]] ], [ undef, [[ENTRY:%.*]] ]544; CHECK-NEXT: [[ADD:%.*]] = add i32 [[PHI]], 1545; CHECK-NEXT: ret i32 [[ADD]]546;547entry:548 switch i32 %x, label %join [549 i32 1, label %case1550 i32 2, label %case2551 ]552 553case1:554 br label %join555 556case2:557 br label %join558 559join:560 %phi = phi i32 [ 1, %case1 ], [ 2, %case2 ], [ undef, %entry ]561 %add = add i32 %phi, 1562 ret i32 %add563}564 565;.566; CHECK: [[RNG0]] = !{i32 0, i32 2147483647}567;.568