519 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s3 4declare void @llvm.assume(i1)5declare i32 @llvm.abs.i32(i32, i1)6declare i8 @llvm.abs.i8(i8, i1)7declare i1 @llvm.abs.i1(i1, i1)8 9; If we don't know anything about the argument, we can't do anything.10 11define i8 @test0(i8 %x) {12; CHECK-LABEL: @test0(13; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)14; CHECK-NEXT: ret i8 [[R]]15;16 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)17 ret i8 %r18}19define i8 @test1(i8 %x) {20; CHECK-LABEL: @test1(21; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)22; CHECK-NEXT: ret i8 [[R]]23;24 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)25 ret i8 %r26}27 28; But if we know that the argument is always positive, we can bypass @llvm.abs.29 30define i8 @test2(i8 %x) {31; CHECK-LABEL: @test2(32; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -133; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])34; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)35; CHECK-NEXT: ret i8 [[R]]36;37 38 %lim = icmp sge i8 %x, -139 call void @llvm.assume(i1 %lim)40 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)41 ret i8 %r42}43define i8 @test3(i8 %x) {44; CHECK-LABEL: @test3(45; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -146; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])47; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)48; CHECK-NEXT: ret i8 [[R]]49;50 51 %lim = icmp sge i8 %x, -152 call void @llvm.assume(i1 %lim)53 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)54 ret i8 %r55}56 57define i8 @test4(i8 %x) {58; CHECK-LABEL: @test4(59; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 060; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])61; CHECK-NEXT: ret i8 [[X]]62;63 64 %lim = icmp sge i8 %x, 065 call void @llvm.assume(i1 %lim)66 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)67 ret i8 %r68}69define i8 @test5(i8 %x) {70; CHECK-LABEL: @test5(71; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 072; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])73; CHECK-NEXT: ret i8 [[X]]74;75 76 %lim = icmp sge i8 %x, 077 call void @llvm.assume(i1 %lim)78 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)79 ret i8 %r80}81 82define i8 @test6(i8 %x) {83; CHECK-LABEL: @test6(84; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 185; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])86; CHECK-NEXT: ret i8 [[X]]87;88 89 %lim = icmp sge i8 %x, 190 call void @llvm.assume(i1 %lim)91 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)92 ret i8 %r93}94define i8 @test7(i8 %x) {95; CHECK-LABEL: @test7(96; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 197; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])98; CHECK-NEXT: ret i8 [[X]]99;100 101 %lim = icmp sge i8 %x, 1102 call void @llvm.assume(i1 %lim)103 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)104 ret i8 %r105}106 107; Likewise, INT_MIN is fine for otherwise-positive value.108 109define i8 @test8(i8 %x) {110; CHECK-LABEL: @test8(111; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127112; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])113; CHECK-NEXT: ret i8 [[X]]114;115 116 %lim = icmp ule i8 %x, 127117 call void @llvm.assume(i1 %lim)118 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)119 ret i8 %r120}121define i8 @test9(i8 %x) {122; CHECK-LABEL: @test9(123; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127124; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])125; CHECK-NEXT: ret i8 [[X]]126;127 128 %lim = icmp ule i8 %x, 127129 call void @llvm.assume(i1 %lim)130 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)131 ret i8 %r132}133 134define i8 @test10(i8 %x) {135; CHECK-LABEL: @test10(136; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128137; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])138; CHECK-NEXT: ret i8 [[X]]139;140 141 %lim = icmp ule i8 %x, 128142 call void @llvm.assume(i1 %lim)143 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)144 ret i8 %r145}146define i8 @test11(i8 %x) {147; CHECK-LABEL: @test11(148; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128149; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])150; CHECK-NEXT: ret i8 [[X]]151;152 153 %lim = icmp ule i8 %x, 128154 call void @llvm.assume(i1 %lim)155 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)156 ret i8 %r157}158 159define i8 @test12(i8 %x) {160; CHECK-LABEL: @test12(161; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127162; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])163; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)164; CHECK-NEXT: ret i8 [[R]]165;166 167 %lim = icmp ule i8 %x, 129168 call void @llvm.assume(i1 %lim)169 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)170 ret i8 %r171}172define i8 @test13(i8 %x) {173; CHECK-LABEL: @test13(174; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127175; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])176; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)177; CHECK-NEXT: ret i8 [[R]]178;179 180 %lim = icmp ule i8 %x, 129181 call void @llvm.assume(i1 %lim)182 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)183 ret i8 %r184}185 186; Likewise, if we know that argument is always negative,187; we can expand @llvm.abs into a direct negation.188; For negative arguments, we must be careful to include 0 though.189 190define i8 @test14(i8 %x) {191; CHECK-LABEL: @test14(192; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1193; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])194; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]]195; CHECK-NEXT: ret i8 [[R1]]196;197 198 %lim = icmp sle i8 %x, -1199 call void @llvm.assume(i1 %lim)200 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)201 ret i8 %r202}203define i8 @test15(i8 %x) {204; CHECK-LABEL: @test15(205; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1206; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])207; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]]208; CHECK-NEXT: ret i8 [[R1]]209;210 211 %lim = icmp sle i8 %x, -1212 call void @llvm.assume(i1 %lim)213 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)214 ret i8 %r215}216 217define i8 @test16(i8 %x) {218; CHECK-LABEL: @test16(219; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0220; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])221; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]]222; CHECK-NEXT: ret i8 [[R1]]223;224 225 %lim = icmp sle i8 %x, 0226 call void @llvm.assume(i1 %lim)227 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)228 ret i8 %r229}230define i8 @test17(i8 %x) {231; CHECK-LABEL: @test17(232; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0233; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])234; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]]235; CHECK-NEXT: ret i8 [[R1]]236;237 238 %lim = icmp sle i8 %x, 0239 call void @llvm.assume(i1 %lim)240 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)241 ret i8 %r242}243 244define i8 @test18(i8 %x) {245; CHECK-LABEL: @test18(246; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1247; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])248; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)249; CHECK-NEXT: ret i8 [[R]]250;251 252 %lim = icmp sle i8 %x, 1253 call void @llvm.assume(i1 %lim)254 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)255 ret i8 %r256}257define i8 @test19(i8 %x) {258; CHECK-LABEL: @test19(259; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1260; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])261; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)262; CHECK-NEXT: ret i8 [[R]]263;264 265 %lim = icmp sle i8 %x, 1266 call void @llvm.assume(i1 %lim)267 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)268 ret i8 %r269}270 271; And again, INT_MIN is also fine for otherwise-negative range.272 273define i8 @test20(i8 %x) {274; CHECK-LABEL: @test20(275; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127276; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])277; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)278; CHECK-NEXT: ret i8 [[R]]279;280 281 %lim = icmp uge i8 %x, 127282 call void @llvm.assume(i1 %lim)283 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)284 ret i8 %r285}286define i8 @test21(i8 %x) {287; CHECK-LABEL: @test21(288; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127289; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])290; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)291; CHECK-NEXT: ret i8 [[R]]292;293 294 %lim = icmp uge i8 %x, 127295 call void @llvm.assume(i1 %lim)296 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)297 ret i8 %r298}299 300define i8 @test22(i8 %x) {301; CHECK-LABEL: @test22(302; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128303; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])304; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]]305; CHECK-NEXT: ret i8 [[R1]]306;307 308 %lim = icmp uge i8 %x, 128309 call void @llvm.assume(i1 %lim)310 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)311 ret i8 %r312}313define i8 @test23(i8 %x) {314; CHECK-LABEL: @test23(315; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128316; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])317; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]]318; CHECK-NEXT: ret i8 [[R1]]319;320 321 %lim = icmp uge i8 %x, 128322 call void @llvm.assume(i1 %lim)323 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)324 ret i8 %r325}326 327define i8 @test24(i8 %x) {328; CHECK-LABEL: @test24(329; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127330; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])331; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]]332; CHECK-NEXT: ret i8 [[R1]]333;334 335 %lim = icmp uge i8 %x, 129336 call void @llvm.assume(i1 %lim)337 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)338 ret i8 %r339}340define i8 @test25(i8 %x) {341; CHECK-LABEL: @test25(342; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127343; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])344; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]]345; CHECK-NEXT: ret i8 [[R1]]346;347 348 %lim = icmp uge i8 %x, 129349 call void @llvm.assume(i1 %lim)350 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)351 ret i8 %r352}353 354; If all else fails, we can sometimes at least inferr NSW.355 356define i8 @test26(i8 %x) {357; CHECK-LABEL: @test26(358; CHECK-NEXT: [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128359; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])360; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)361; CHECK-NEXT: ret i8 [[R]]362;363 %lim = icmp ne i8 %x, 128364 call void @llvm.assume(i1 %lim)365 %r = call i8 @llvm.abs.i8(i8 %x, i1 0)366 ret i8 %r367}368define i8 @test27(i8 %x) {369; CHECK-LABEL: @test27(370; CHECK-NEXT: [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128371; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])372; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)373; CHECK-NEXT: ret i8 [[R]]374;375 %lim = icmp ne i8 %x, 128376 call void @llvm.assume(i1 %lim)377 %r = call i8 @llvm.abs.i8(i8 %x, i1 1)378 ret i8 %r379}380 381define i1 @pr59887(i1 %x, i1 %c) {382; CHECK-LABEL: @pr59887(383; CHECK-NEXT: [[RES:%.*]] = select i1 [[C:%.*]], i1 [[X:%.*]], i1 false384; CHECK-NEXT: ret i1 [[RES]]385;386 %abs = call i1 @llvm.abs.i1(i1 %x, i1 false)387 %res = select i1 %c, i1 %abs, i1 false388 ret i1 %res389}390 391; Because of `undef`, We can't delete `abs`.392; We can't replace the `abs` argument with true either.393define i32 @pr68381_undef_abs_false(i1 %c0, i1 %c1, i8 %v1) {394; CHECK-LABEL: @pr68381_undef_abs_false(395; CHECK-NEXT: start:396; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]397; CHECK: bb0:398; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32399; CHECK-NEXT: br label [[BB1]]400; CHECK: bb1:401; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ]402; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]403; CHECK: bb2:404; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false)405; CHECK-NEXT: ret i32 [[Z]]406;407start:408 br i1 %c0, label %bb0, label %bb1409 410bb0:411 %v1_i32 = zext i8 %v1 to i32412 br label %bb1413 414bb1:415 %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ]416 br i1 %c1, label %bb0, label %bb2417 418bb2:419 %z = call i32 @llvm.abs.i32(i32 %x, i1 false)420 ret i32 %z421}422 423; Because of `and`, we can delete `abs`.424define i32 @pr68381_undef_abs_false_and(i1 %c0, i1 %c1, i8 %v1) {425; CHECK-LABEL: @pr68381_undef_abs_false_and(426; CHECK-NEXT: start:427; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]428; CHECK: bb0:429; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32430; CHECK-NEXT: br label [[BB1]]431; CHECK: bb1:432; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ]433; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]434; CHECK: bb2:435; CHECK-NEXT: [[Y:%.*]] = and i32 [[X]], 255436; CHECK-NEXT: ret i32 [[Y]]437;438start:439 br i1 %c0, label %bb0, label %bb1440 441bb0:442 %v1_i32 = zext i8 %v1 to i32443 br label %bb1444 445bb1:446 %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ]447 br i1 %c1, label %bb0, label %bb2448 449bb2:450 %y = and i32 %x, 255451 %z = call i32 @llvm.abs.i32(i32 %y, i1 false)452 ret i32 %z453}454 455; Because of `undef`, we can't replace `abs` with `sub`.456define i32 @pr68381_undef_abs_false_sub(i1 %c0, i1 %c1, i32 %v1, i32 %v2) {457; CHECK-LABEL: @pr68381_undef_abs_false_sub(458; CHECK-NEXT: start:459; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]460; CHECK: bb0:461; CHECK-NEXT: [[V3:%.*]] = add i32 [[V1:%.*]], [[V2:%.*]]462; CHECK-NEXT: [[LIM:%.*]] = icmp sle i32 [[V3]], -1463; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])464; CHECK-NEXT: br label [[BB1]]465; CHECK: bb1:466; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V3]], [[BB0]] ], [ undef, [[START:%.*]] ]467; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]468; CHECK: bb2:469; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false)470; CHECK-NEXT: ret i32 [[Z]]471;472start:473 br i1 %c0, label %bb0, label %bb1474 475bb0:476 %v3 = add i32 %v1, %v2477 %lim = icmp sle i32 %v3, -1478 call void @llvm.assume(i1 %lim)479 br label %bb1480 481bb1:482 %x = phi i32 [ %v3, %bb0 ], [ undef, %start ]483 br i1 %c1, label %bb0, label %bb2484 485bb2:486 %z = call i32 @llvm.abs.i32(i32 %x, i1 false)487 ret i32 %z488}489 490; We can delete `abs`.491define i32 @pr68381_undef_abs_true(i1 %c0, i1 %c1, i8 %v1) {492; CHECK-LABEL: @pr68381_undef_abs_true(493; CHECK-NEXT: start:494; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]495; CHECK: bb0:496; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32497; CHECK-NEXT: br label [[BB1]]498; CHECK: bb1:499; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ]500; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]501; CHECK: bb2:502; CHECK-NEXT: ret i32 [[X]]503;504start:505 br i1 %c0, label %bb0, label %bb1506 507bb0:508 %v1_i32 = zext i8 %v1 to i32509 br label %bb1510 511bb1:512 %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ]513 br i1 %c1, label %bb0, label %bb2514 515bb2:516 %z = call i32 @llvm.abs.i32(i32 %x, i1 true)517 ret i32 %z518}519