602 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s3 4define void @test0(i32 %a) {5; CHECK-LABEL: @test0(6; CHECK-NEXT: entry:7; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 1008; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]9; CHECK: bb:10; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 111; CHECK-NEXT: br label [[EXIT]]12; CHECK: exit:13; CHECK-NEXT: ret void14;15entry:16 %cmp = icmp sgt i32 %a, 10017 br i1 %cmp, label %bb, label %exit18 19bb:20 %sub = sub i32 %a, 121 br label %exit22 23exit:24 ret void25}26 27define void @test1(i32 %a) {28; CHECK-LABEL: @test1(29; CHECK-NEXT: entry:30; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 10031; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]32; CHECK: bb:33; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[A]], 134; CHECK-NEXT: br label [[EXIT]]35; CHECK: exit:36; CHECK-NEXT: ret void37;38entry:39 %cmp = icmp ugt i32 %a, 10040 br i1 %cmp, label %bb, label %exit41 42bb:43 %sub = sub i32 %a, 144 br label %exit45 46exit:47 ret void48}49 50define void @test2(i32 %a) {51; CHECK-LABEL: @test2(52; CHECK-NEXT: entry:53; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], -154; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]55; CHECK: bb:56; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 157; CHECK-NEXT: br label [[EXIT]]58; CHECK: exit:59; CHECK-NEXT: ret void60;61entry:62 %cmp = icmp ugt i32 %a, -163 br i1 %cmp, label %bb, label %exit64 65bb:66 %sub = sub i32 %a, 167 br label %exit68 69exit:70 ret void71}72 73define void @test3(i32 %a) {74; CHECK-LABEL: @test3(75; CHECK-NEXT: entry:76; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], -177; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]78; CHECK: bb:79; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 180; CHECK-NEXT: br label [[EXIT]]81; CHECK: exit:82; CHECK-NEXT: ret void83;84entry:85 %cmp = icmp sgt i32 %a, -186 br i1 %cmp, label %bb, label %exit87 88bb:89 %sub = sub i32 %a, 190 br label %exit91 92exit:93 ret void94}95 96define void @test4(i32 %a) {97; CHECK-LABEL: @test4(98; CHECK-NEXT: entry:99; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 2147483647100; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]101; CHECK: bb:102; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[A]], 1103; CHECK-NEXT: br label [[EXIT]]104; CHECK: exit:105; CHECK-NEXT: ret void106;107entry:108 %cmp = icmp ugt i32 %a, 2147483647109 br i1 %cmp, label %bb, label %exit110 111bb:112 %sub = sub i32 %a, 1113 br label %exit114 115exit:116 ret void117}118 119define void @test5(i32 %a) {120; CHECK-LABEL: @test5(121; CHECK-NEXT: entry:122; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 2147483647123; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]124; CHECK: bb:125; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], 1126; CHECK-NEXT: br label [[EXIT]]127; CHECK: exit:128; CHECK-NEXT: ret void129;130entry:131 %cmp = icmp sle i32 %a, 2147483647132 br i1 %cmp, label %bb, label %exit133 134bb:135 %sub = sub i32 %a, 1136 br label %exit137 138exit:139 ret void140}141 142; Check for a corner case where an integer value is represented with a constant143; LVILatticeValue instead of constantrange. Check that we don't fail with an144; assertion in this case.145@b = global i32 0, align 4146define void @test6(i32 %a) {147; CHECK-LABEL: @test6(148; CHECK-NEXT: bb:149; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A:%.*]], ptrtoint (ptr @b to i32)150; CHECK-NEXT: ret void151;152bb:153 %sub = sub i32 %a, ptrtoint (ptr @b to i32)154 ret void155}156 157; Check that we can gather information for conditions in the form of158; and ( i s< 100, Unknown )159define void @test7(i32 %a, i1 %flag) {160; CHECK-LABEL: @test7(161; CHECK-NEXT: entry:162; CHECK-NEXT: [[CMP_1:%.*]] = icmp ugt i32 [[A:%.*]], 100163; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG:%.*]]164; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]165; CHECK: bb:166; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[A]], 1167; CHECK-NEXT: br label [[EXIT]]168; CHECK: exit:169; CHECK-NEXT: ret void170;171entry:172 %cmp.1 = icmp ugt i32 %a, 100173 %cmp = and i1 %cmp.1, %flag174 br i1 %cmp, label %bb, label %exit175 176bb:177 %sub = sub i32 %a, 1178 br label %exit179 180exit:181 ret void182}183 184; Check that we can gather information for conditions in the form of185; and ( i s< 100, i s> 0 )186define void @test8(i32 %a) {187; CHECK-LABEL: @test8(188; CHECK-NEXT: entry:189; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A:%.*]], 100190; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0191; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]192; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]193; CHECK: bb:194; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1195; CHECK-NEXT: br label [[EXIT]]196; CHECK: exit:197; CHECK-NEXT: ret void198;199entry:200 %cmp.1 = icmp slt i32 %a, 100201 %cmp.2 = icmp sgt i32 %a, 0202 %cmp = and i1 %cmp.1, %cmp.2203 br i1 %cmp, label %bb, label %exit204 205bb:206 %sub = sub i32 %a, 1207 br label %exit208 209exit:210 ret void211}212 213; Check that for conditions in the form of cond1 && cond2 we don't mistakenly214; assume that !cond1 && !cond2 holds down to false path.215define void @test8_neg(i32 %a) {216; CHECK-LABEL: @test8_neg(217; CHECK-NEXT: entry:218; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A:%.*]], 100219; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0220; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]221; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]222; CHECK: bb:223; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], 1224; CHECK-NEXT: br label [[EXIT]]225; CHECK: exit:226; CHECK-NEXT: ret void227;228entry:229 %cmp.1 = icmp sge i32 %a, 100230 %cmp.2 = icmp sle i32 %a, 0231 %cmp = and i1 %cmp.1, %cmp.2232 br i1 %cmp, label %exit, label %bb233 234bb:235 %sub = sub i32 %a, 1236 br label %exit237 238exit:239 ret void240}241 242; Check that we can gather information for conditions in the form of243; and ( i s< 100, and (i s> 0, Unknown )244define void @test9(i32 %a, i1 %flag) {245; CHECK-LABEL: @test9(246; CHECK-NEXT: entry:247; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A:%.*]], 100248; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0249; CHECK-NEXT: [[CMP_3:%.*]] = and i1 [[CMP_2]], [[FLAG:%.*]]250; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_3]]251; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]252; CHECK: bb:253; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1254; CHECK-NEXT: br label [[EXIT]]255; CHECK: exit:256; CHECK-NEXT: ret void257;258entry:259 %cmp.1 = icmp slt i32 %a, 100260 %cmp.2 = icmp sgt i32 %a, 0261 %cmp.3 = and i1 %cmp.2, %flag262 %cmp = and i1 %cmp.1, %cmp.3263 br i1 %cmp, label %bb, label %exit264 265bb:266 %sub = sub i32 %a, 1267 br label %exit268 269exit:270 ret void271}272 273; Check that we can gather information for conditions in the form of274; and ( i s> Unknown, ... )275define void @test10(i32 %a, i32 %b, i1 %flag) {276; CHECK-LABEL: @test10(277; CHECK-NEXT: entry:278; CHECK-NEXT: [[CMP_1:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]279; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG:%.*]]280; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]281; CHECK: bb:282; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1283; CHECK-NEXT: br label [[EXIT]]284; CHECK: exit:285; CHECK-NEXT: ret void286;287entry:288 %cmp.1 = icmp sgt i32 %a, %b289 %cmp = and i1 %cmp.1, %flag290 br i1 %cmp, label %bb, label %exit291 292bb:293 %sub = sub i32 %a, 1294 br label %exit295 296exit:297 ret void298}299 300@limit = external global i32301define i32 @test11(ptr %p, i32 %i) {302; CHECK-LABEL: @test11(303; CHECK-NEXT: [[LIMIT:%.*]] = load i32, ptr [[P:%.*]], !range !0304; CHECK-NEXT: [[WITHIN_1:%.*]] = icmp slt i32 [[LIMIT]], [[I:%.*]]305; CHECK-NEXT: [[I_MINUS_7:%.*]] = add i32 [[I]], -7306; CHECK-NEXT: [[WITHIN_2:%.*]] = icmp slt i32 [[LIMIT]], [[I_MINUS_7]]307; CHECK-NEXT: [[WITHIN:%.*]] = and i1 [[WITHIN_1]], [[WITHIN_2]]308; CHECK-NEXT: br i1 [[WITHIN]], label [[THEN:%.*]], label [[ELSE:%.*]]309; CHECK: then:310; CHECK-NEXT: [[I_MINUS_6:%.*]] = sub nuw nsw i32 [[I]], 6311; CHECK-NEXT: ret i32 [[I_MINUS_6]]312; CHECK: else:313; CHECK-NEXT: ret i32 0314;315 %limit = load i32, ptr %p, !range !{i32 0, i32 2147483647}316 %within.1 = icmp slt i32 %limit, %i317 %i.minus.7 = add i32 %i, -7318 %within.2 = icmp slt i32 %limit, %i.minus.7319 %within = and i1 %within.1, %within.2320 br i1 %within, label %then, label %else321 322then:323 %i.minus.6 = sub i32 %i, 6324 ret i32 %i.minus.6325 326else:327 ret i32 0328}329 330; Check that we can gather information for conditions is the form of331; or ( i s<= -100, Unknown )332define void @test12(i32 %a, i1 %flag) {333; CHECK-LABEL: @test12(334; CHECK-NEXT: entry:335; CHECK-NEXT: [[CMP_1:%.*]] = icmp sle i32 [[A:%.*]], -100336; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG:%.*]]337; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]338; CHECK: bb:339; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1340; CHECK-NEXT: br label [[EXIT]]341; CHECK: exit:342; CHECK-NEXT: ret void343;344entry:345 %cmp.1 = icmp sle i32 %a, -100346 %cmp = or i1 %cmp.1, %flag347 br i1 %cmp, label %exit, label %bb348 349bb:350 %sub = sub i32 %a, 1351 br label %exit352 353exit:354 ret void355}356 357; Check that we can gather information for conditions is the form of358; or ( i s>= 100, i s<= 0 )359define void @test13(i32 %a) {360; CHECK-LABEL: @test13(361; CHECK-NEXT: entry:362; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A:%.*]], 100363; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0364; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]365; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]366; CHECK: bb:367; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1368; CHECK-NEXT: br label [[EXIT]]369; CHECK: exit:370; CHECK-NEXT: ret void371;372entry:373 %cmp.1 = icmp sge i32 %a, 100374 %cmp.2 = icmp sle i32 %a, 0375 %cmp = or i1 %cmp.1, %cmp.2376 br i1 %cmp, label %exit, label %bb377 378bb:379 %sub = sub i32 %a, 1380 br label %exit381 382exit:383 ret void384}385 386; Check that for conditions is the form of cond1 || cond2 we don't mistakenly387; assume that cond1 || cond2 holds down to true path.388define void @test13_neg(i32 %a) {389; CHECK-LABEL: @test13_neg(390; CHECK-NEXT: entry:391; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A:%.*]], 100392; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0393; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]394; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]395; CHECK: bb:396; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], 1397; CHECK-NEXT: br label [[EXIT]]398; CHECK: exit:399; CHECK-NEXT: ret void400;401entry:402 %cmp.1 = icmp slt i32 %a, 100403 %cmp.2 = icmp sgt i32 %a, 0404 %cmp = or i1 %cmp.1, %cmp.2405 br i1 %cmp, label %bb, label %exit406 407bb:408 %sub = sub i32 %a, 1409 br label %exit410 411exit:412 ret void413}414 415; Check that we can gather information for conditions is the form of416; or ( i s>=100, or (i s<= 0, Unknown )417define void @test14(i32 %a, i1 %flag) {418; CHECK-LABEL: @test14(419; CHECK-NEXT: entry:420; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A:%.*]], 100421; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0422; CHECK-NEXT: [[CMP_3:%.*]] = or i1 [[CMP_2]], [[FLAG:%.*]]423; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_3]]424; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]425; CHECK: bb:426; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1427; CHECK-NEXT: br label [[EXIT]]428; CHECK: exit:429; CHECK-NEXT: ret void430;431entry:432 %cmp.1 = icmp sge i32 %a, 100433 %cmp.2 = icmp sle i32 %a, 0434 %cmp.3 = or i1 %cmp.2, %flag435 %cmp = or i1 %cmp.1, %cmp.3436 br i1 %cmp, label %exit, label %bb437 438bb:439 %sub = sub i32 %a, 1440 br label %exit441 442exit:443 ret void444}445 446; Check that we can gather information for conditions is the form of447; or ( i s<= Unknown, ... )448define void @test15(i32 %a, i32 %b, i1 %flag) {449; CHECK-LABEL: @test15(450; CHECK-NEXT: entry:451; CHECK-NEXT: [[CMP_1:%.*]] = icmp sle i32 [[A:%.*]], [[B:%.*]]452; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG:%.*]]453; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]454; CHECK: bb:455; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1456; CHECK-NEXT: br label [[EXIT]]457; CHECK: exit:458; CHECK-NEXT: ret void459;460entry:461 %cmp.1 = icmp sle i32 %a, %b462 %cmp = or i1 %cmp.1, %flag463 br i1 %cmp, label %exit, label %bb464 465bb:466 %sub = sub i32 %a, 1467 br label %exit468 469exit:470 ret void471}472 473; single basic block loop474; because the loop exit condition is SLT, we can supplement the iv sub475; (iv.next def) with an nsw.476define i32 @test16(ptr %n, ptr %a) {477; CHECK-LABEL: @test16(478; CHECK-NEXT: preheader:479; CHECK-NEXT: br label [[LOOP:%.*]]480; CHECK: loop:481; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]482; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ACC_CURR:%.*]], [[LOOP]] ]483; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr [[A:%.*]] unordered, align 8484; CHECK-NEXT: fence acquire485; CHECK-NEXT: [[ACC_CURR]] = sub i32 [[ACC]], [[X]]486; CHECK-NEXT: [[IV_NEXT]] = sub nsw i32 [[IV]], -1487; CHECK-NEXT: [[NVAL:%.*]] = load atomic i32, ptr [[N:%.*]] unordered, align 8488; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_NEXT]], [[NVAL]]489; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]490; CHECK: exit:491; CHECK-NEXT: ret i32 [[ACC_CURR]]492;493preheader:494 br label %loop495 496loop:497 %iv = phi i32 [ 0, %preheader ], [ %iv.next, %loop ]498 %acc = phi i32 [ 0, %preheader ], [ %acc.curr, %loop ]499 %x = load atomic i32, ptr %a unordered, align 8500 fence acquire501 %acc.curr = sub i32 %acc, %x502 %iv.next = sub i32 %iv, -1503 %nval = load atomic i32, ptr %n unordered, align 8504 %cmp = icmp slt i32 %iv.next, %nval505 br i1 %cmp, label %loop, label %exit506 507exit:508 ret i32 %acc.curr509}510 511define void @test17(i32 %a) {512; CHECK-LABEL: @test17(513; CHECK-NEXT: entry:514; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 100515; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]516; CHECK: bb:517; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 1, [[A]]518; CHECK-NEXT: br label [[EXIT]]519; CHECK: exit:520; CHECK-NEXT: ret void521;522entry:523 %cmp = icmp sgt i32 %a, 100524 br i1 %cmp, label %bb, label %exit525 526bb:527 %sub = sub i32 1, %a528 br label %exit529 530exit:531 ret void532}533 534define void @test18(i32 %a) {535; CHECK-LABEL: @test18(536; CHECK-NEXT: entry:537; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 10000538; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]539; CHECK: bb:540; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 -2, [[A]]541; CHECK-NEXT: br label [[EXIT]]542; CHECK: exit:543; CHECK-NEXT: ret void544;545entry:546 %cmp = icmp sgt i32 %a, 10000547 br i1 %cmp, label %bb, label %exit548 549bb:550 %sub = sub i32 -2, %a551 br label %exit552 553exit:554 ret void555}556 557define void @test19(i32 %a) {558; CHECK-LABEL: @test19(559; CHECK-NEXT: entry:560; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 100561; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]562; CHECK: bb:563; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 -1, [[A]]564; CHECK-NEXT: br label [[EXIT]]565; CHECK: exit:566; CHECK-NEXT: ret void567;568entry:569 %cmp = icmp ult i32 %a, 100570 br i1 %cmp, label %bb, label %exit571 572bb:573 %sub = sub i32 -1, %a574 br label %exit575 576exit:577 ret void578}579 580define void @test20(i32 %a) {581; CHECK-LABEL: @test20(582; CHECK-NEXT: entry:583; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 2147483647584; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]585; CHECK: bb:586; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A]]587; CHECK-NEXT: br label [[EXIT]]588; CHECK: exit:589; CHECK-NEXT: ret void590;591entry:592 %cmp = icmp ugt i32 %a, 2147483647593 br i1 %cmp, label %bb, label %exit594 595bb:596 %sub = sub i32 0, %a597 br label %exit598 599exit:600 ret void601}602