2205 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3; RUN: opt < %s -passes=instcombine -use-constant-int-for-fixed-length-splat -S | FileCheck %s4 5declare i32 @llvm.abs.i32(i32, i1)6 7define i32 @pow2_multiplier(i32 %A) {8; CHECK-LABEL: @pow2_multiplier(9; CHECK-NEXT: [[B:%.*]] = shl i32 [[A:%.*]], 110; CHECK-NEXT: ret i32 [[B]]11;12 %B = mul i32 %A, 213 ret i32 %B14}15 16define <2 x i32> @pow2_multiplier_vec(<2 x i32> %A) {17; CHECK-LABEL: @pow2_multiplier_vec(18; CHECK-NEXT: [[B:%.*]] = shl <2 x i32> [[A:%.*]], splat (i32 3)19; CHECK-NEXT: ret <2 x i32> [[B]]20;21 %B = mul <2 x i32> %A, <i32 8, i32 8>22 ret <2 x i32> %B23}24 25define i8 @combine_shl(i8 %A) {26; CHECK-LABEL: @combine_shl(27; CHECK-NEXT: [[C:%.*]] = shl i8 [[A:%.*]], 628; CHECK-NEXT: ret i8 [[C]]29;30 %B = mul i8 %A, 831 %C = mul i8 %B, 832 ret i8 %C33}34 35define i32 @neg(i32 %i) {36; CHECK-LABEL: @neg(37; CHECK-NEXT: [[T:%.*]] = sub i32 0, [[I:%.*]]38; CHECK-NEXT: ret i32 [[T]]39;40 %t = mul i32 %i, -141 ret i32 %t42}43 44; Use the sign-bit as a mask:45; (zext (A < 0)) * B --> (A >> 31) & B46 47define i32 @test10(i32 %a, i32 %b) {48; CHECK-LABEL: @test10(49; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 050; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 051; CHECK-NEXT: ret i32 [[E]]52;53 %c = icmp slt i32 %a, 054 %d = zext i1 %c to i3255 %e = mul i32 %d, %b56 ret i32 %e57}58 59define i32 @test11(i32 %a, i32 %b) {60; CHECK-LABEL: @test11(61; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 062; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 063; CHECK-NEXT: ret i32 [[E]]64;65 %c = icmp sle i32 %a, -166 %d = zext i1 %c to i3267 %e = mul i32 %d, %b68 ret i32 %e69}70 71declare void @use32(i32)72 73define i32 @test12(i32 %a, i32 %b) {74; CHECK-LABEL: @test12(75; CHECK-NEXT: [[A_LOBIT:%.*]] = lshr i32 [[A:%.*]], 3176; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A]], 077; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 078; CHECK-NEXT: call void @use32(i32 [[A_LOBIT]])79; CHECK-NEXT: ret i32 [[E]]80;81 %c = icmp ugt i32 %a, 214748364782 %d = zext i1 %c to i3283 %e = mul i32 %d, %b84 call void @use32(i32 %d)85 ret i32 %e86}87 88; rdar://729352789define i32 @shl1(i32 %a, i32 %b) {90; CHECK-LABEL: @shl1(91; CHECK-NEXT: [[M1:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]92; CHECK-NEXT: ret i32 [[M1]]93;94 %shl = shl i32 1, %b95 %m = mul i32 %shl, %a96 ret i32 %m97}98 99define i32 @shl1_nsw_nsw(i32 %A, i32 %B) {100; CHECK-LABEL: @shl1_nsw_nsw(101; CHECK-NEXT: [[D1:%.*]] = shl nsw i32 [[A:%.*]], [[B:%.*]]102; CHECK-NEXT: ret i32 [[D1]]103;104 %shl = shl nsw i32 1, %B105 %D = mul nsw i32 %A, %shl106 ret i32 %D107}108 109define <2 x i32> @shl1_nsw_nsw_commute(<2 x i32> %A, <2 x i32> %B) {110; CHECK-LABEL: @shl1_nsw_nsw_commute(111; CHECK-NEXT: [[D1:%.*]] = shl nsw <2 x i32> [[A:%.*]], [[B:%.*]]112; CHECK-NEXT: ret <2 x i32> [[D1]]113;114 %shl = shl nsw <2 x i32> <i32 1, i32 poison>, %B115 %D = mul nsw <2 x i32> %shl, %A116 ret <2 x i32> %D117}118 119define i32 @shl1_nuw(i32 %A, i32 %B) {120; CHECK-LABEL: @shl1_nuw(121; CHECK-NEXT: [[D1:%.*]] = shl nuw i32 [[A:%.*]], [[B:%.*]]122; CHECK-NEXT: ret i32 [[D1]]123;124 %shl = shl i32 1, %B125 %D = mul nuw i32 %A, %shl126 ret i32 %D127}128 129define i32 @shl1_nuw_commute(i32 %A, i32 %B) {130; CHECK-LABEL: @shl1_nuw_commute(131; CHECK-NEXT: [[D1:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]132; CHECK-NEXT: ret i32 [[D1]]133;134 %shl = shl nuw i32 1, %B135 %D = mul i32 %shl, %A136 ret i32 %D137}138 139define i32 @shl1_nsw(i32 %A) {140; CHECK-LABEL: @shl1_nsw(141; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[A:%.*]]142; CHECK-NEXT: [[C1:%.*]] = shl i32 [[SHL]], [[A]]143; CHECK-NEXT: ret i32 [[C1]]144;145 %shl = shl i32 1, %A146 %C = mul nsw i32 %shl, %shl147 ret i32 %C148}149 150define i5 @shl1_increment(i5 %x, i5 %y) {151; CHECK-LABEL: @shl1_increment(152; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]153; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]]154; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]]155; CHECK-NEXT: ret i5 [[M1]]156;157 %pow2x = shl i5 1, %x158 %x1 = add i5 %pow2x, 1159 %m = mul i5 %x1, %y160 ret i5 %m161}162 163define <3 x i5> @shl1_nuw_increment_commute(<3 x i5> %x, <3 x i5> noundef %p) {164; CHECK-LABEL: @shl1_nuw_increment_commute(165; CHECK-NEXT: [[Y:%.*]] = ashr <3 x i5> [[P:%.*]], splat (i5 1)166; CHECK-NEXT: [[MULSHL:%.*]] = shl nuw <3 x i5> [[Y]], [[X:%.*]]167; CHECK-NEXT: [[M1:%.*]] = add nuw <3 x i5> [[MULSHL]], [[Y]]168; CHECK-NEXT: ret <3 x i5> [[M1]]169;170 %y = ashr <3 x i5> %p, <i5 1, i5 1, i5 1> ; thwart complexity-based canonicalization171 %pow2x = shl <3 x i5> <i5 1, i5 poison, i5 1>, %x172 %x1 = add <3 x i5> %pow2x, <i5 1, i5 poison, i5 1>173 %m = mul nuw <3 x i5> %y, %x1174 ret <3 x i5> %m175}176 177define i5 @shl1_nsw_increment(i5 %x, i5 %y) {178; CHECK-LABEL: @shl1_nsw_increment(179; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]180; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]]181; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]]182; CHECK-NEXT: ret i5 [[M1]]183;184 %pow2x = shl i5 1, %x185 %x1 = add i5 %pow2x, 1186 %m = mul nsw i5 %x1, %y187 ret i5 %m188}189 190define i5 @shl1_nsw_nsw_increment(i5 %x, i5 %y) {191; CHECK-LABEL: @shl1_nsw_nsw_increment(192; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]193; CHECK-NEXT: [[MULSHL:%.*]] = shl nsw i5 [[Y_FR]], [[X:%.*]]194; CHECK-NEXT: [[M1:%.*]] = add nsw i5 [[MULSHL]], [[Y_FR]]195; CHECK-NEXT: ret i5 [[M1]]196;197 %pow2x = shl nsw i5 1, %x198 %x1 = add i5 %pow2x, 1199 %m = mul nsw i5 %y, %x1200 ret i5 %m201}202 203define i5 @shl1_nsw_nsw_increment_commute(i5 %x, i5 %y) {204; CHECK-LABEL: @shl1_nsw_nsw_increment_commute(205; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]]206; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]]207; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]]208; CHECK-NEXT: ret i5 [[M1]]209;210 %pow2x = shl nsw i5 1, %x211 %x1 = add nsw i5 %pow2x, 1212 %m = mul i5 %x1, %y213 ret i5 %m214}215 216define i32 @shl1_increment_use(i32 %x, i32 %y) {217; CHECK-LABEL: @shl1_increment_use(218; CHECK-NEXT: [[POW2X:%.*]] = shl nuw i32 1, [[X:%.*]]219; CHECK-NEXT: call void @use32(i32 [[POW2X]])220; CHECK-NEXT: [[X1:%.*]] = add nuw i32 [[POW2X]], 1221; CHECK-NEXT: [[M:%.*]] = mul i32 [[X1]], [[Y:%.*]]222; CHECK-NEXT: ret i32 [[M]]223;224 %pow2x = shl i32 1, %x225 call void @use32(i32 %pow2x)226 %x1 = add i32 %pow2x, 1227 %m = mul i32 %x1, %y228 ret i32 %m229}230 231; ((-1 << x) ^ -1) * y --> (y << x) - y232 233define i8 @shl1_decrement(i8 %x, i8 %y) {234; CHECK-LABEL: @shl1_decrement(235; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]236; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]237; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]]238; CHECK-NEXT: ret i8 [[M1]]239;240 %pow2x = shl i8 -1, %x241 %x1 = xor i8 %pow2x, -1242 %m = mul i8 %x1, %y243 ret i8 %m244}245 246define i8 @shl1_decrement_commute(i8 %x, i8 noundef %p) {247; CHECK-LABEL: @shl1_decrement_commute(248; CHECK-NEXT: [[Y:%.*]] = ashr i8 [[P:%.*]], 1249; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y]], [[X:%.*]]250; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y]]251; CHECK-NEXT: ret i8 [[M1]]252;253 %y = ashr i8 %p, 1 ; thwart complexity-based canonicalization254 %pow2x = shl i8 1, %x255 %x1 = add i8 %pow2x, -1256 %m = mul i8 %y, %x1257 ret i8 %m258}259 260define i8 @shl1_nuw_decrement(i8 %x, i8 %y) {261; CHECK-LABEL: @shl1_nuw_decrement(262; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]263; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]264; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]]265; CHECK-NEXT: ret i8 [[M1]]266;267 %pow2x = shl i8 -1, %x268 %x1 = xor i8 %pow2x, -1269 %m = mul nuw i8 %x1, %y270 ret i8 %m271}272 273define i8 @shl1_nsw_decrement(i8 %x, i8 %y) {274; CHECK-LABEL: @shl1_nsw_decrement(275; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]276; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]277; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]]278; CHECK-NEXT: ret i8 [[M1]]279;280 %pow2x = shl nsw i8 -1, %x281 %x1 = xor i8 %pow2x, -1282 %m = mul nsw i8 %x1, %y283 ret i8 %m284}285 286; negative test - extra use would require more instructions287 288define i32 @shl1_decrement_use(i32 %x, i32 %y) {289; CHECK-LABEL: @shl1_decrement_use(290; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[X:%.*]]291; CHECK-NEXT: [[X1:%.*]] = xor i32 [[NOTMASK]], -1292; CHECK-NEXT: call void @use32(i32 [[X1]])293; CHECK-NEXT: [[M:%.*]] = mul i32 [[Y:%.*]], [[X1]]294; CHECK-NEXT: ret i32 [[M]]295;296 %pow2x = shl i32 1, %x297 %x1 = add i32 %pow2x, -1298 call void @use32(i32 %x1)299 %m = mul i32 %x1, %y300 ret i32 %m301}302 303; the fold works for vectors too and if 'y' is a constant, sub becomes add304 305define <2 x i8> @shl1_decrement_vec(<2 x i8> %x) {306; CHECK-LABEL: @shl1_decrement_vec(307; CHECK-NEXT: [[MULSHL:%.*]] = shl <2 x i8> <i8 42, i8 -3>, [[X:%.*]]308; CHECK-NEXT: [[M1:%.*]] = add <2 x i8> [[MULSHL]], <i8 -42, i8 3>309; CHECK-NEXT: ret <2 x i8> [[M1]]310;311 %pow2x = shl <2 x i8> <i8 -1, i8 -1>, %x312 %x1 = xor <2 x i8> %pow2x, <i8 -1, i8 -1>313 %m = mul <2 x i8> %x1, <i8 42, i8 -3>314 ret <2 x i8> %m315}316 317; X * Y (when Y is a boolean) --> Y ? X : 0318 319define i32 @mul_bool(i32 %x, i1 %y) {320; CHECK-LABEL: @mul_bool(321; CHECK-NEXT: [[M:%.*]] = select i1 [[Y:%.*]], i32 [[X:%.*]], i32 0322; CHECK-NEXT: ret i32 [[M]]323;324 %z = zext i1 %y to i32325 %m = mul i32 %z, %x326 ret i32 %m327}328 329define <2 x i32> @mul_bool_vec(<2 x i32> %x, <2 x i1> %y) {330; CHECK-LABEL: @mul_bool_vec(331; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X:%.*]], <2 x i32> zeroinitializer332; CHECK-NEXT: ret <2 x i32> [[M]]333;334 %z = zext <2 x i1> %y to <2 x i32>335 %m = mul <2 x i32> %z, %x336 ret <2 x i32> %m337}338 339define <2 x i32> @mul_bool_vec_commute(<2 x i32> %px, <2 x i1> %y) {340; CHECK-LABEL: @mul_bool_vec_commute(341; CHECK-NEXT: [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]342; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X]], <2 x i32> zeroinitializer343; CHECK-NEXT: ret <2 x i32> [[M]]344;345 %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization346 %z = zext <2 x i1> %y to <2 x i32>347 %m = mul <2 x i32> %x, %z348 ret <2 x i32> %m349}350 351; X * C (when X is a sext boolean) --> X ? -C : 0352 353define i32 @mul_sext_bool(i1 %x) {354; CHECK-LABEL: @mul_sext_bool(355; CHECK-NEXT: [[M:%.*]] = select i1 [[X:%.*]], i32 -42, i32 0356; CHECK-NEXT: ret i32 [[M]]357;358 %s = sext i1 %x to i32359 %m = mul i32 %s, 42360 ret i32 %m361}362 363define i32 @mul_sext_bool_use(i1 %x) {364; CHECK-LABEL: @mul_sext_bool_use(365; CHECK-NEXT: [[S:%.*]] = sext i1 [[X:%.*]] to i32366; CHECK-NEXT: call void @use32(i32 [[S]])367; CHECK-NEXT: [[M:%.*]] = select i1 [[X]], i32 -42, i32 0368; CHECK-NEXT: ret i32 [[M]]369;370 %s = sext i1 %x to i32371 call void @use32(i32 %s)372 %m = mul i32 %s, 42373 ret i32 %m374}375 376define <2 x i8> @mul_sext_bool_vec(<2 x i1> %x) {377; CHECK-LABEL: @mul_sext_bool_vec(378; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[X:%.*]], <2 x i8> <i8 -42, i8 -128>, <2 x i8> zeroinitializer379; CHECK-NEXT: ret <2 x i8> [[M]]380;381 %s = sext <2 x i1> %x to <2 x i8>382 %m = mul <2 x i8> %s, <i8 42, i8 -128>383 ret <2 x i8> %m384}385 386define <3 x i7> @mul_bools(<3 x i1> %x, <3 x i1> %y) {387; CHECK-LABEL: @mul_bools(388; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]389; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i7>390; CHECK-NEXT: ret <3 x i7> [[R]]391;392 %zx = zext <3 x i1> %x to <3 x i7>393 %zy = zext <3 x i1> %y to <3 x i7>394 %r = mul <3 x i7> %zx, %zy395 ret <3 x i7> %r396}397 398define i32 @mul_bools_use1(i1 %x, i1 %y) {399; CHECK-LABEL: @mul_bools_use1(400; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32401; CHECK-NEXT: call void @use32(i32 [[ZY]])402; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]403; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32404; CHECK-NEXT: ret i32 [[R]]405;406 %zx = zext i1 %x to i32407 %zy = zext i1 %y to i32408 call void @use32(i32 %zy)409 %r = mul i32 %zx, %zy410 ret i32 %r411}412 413define i32 @mul_bools_use2(i1 %x, i1 %y) {414; CHECK-LABEL: @mul_bools_use2(415; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32416; CHECK-NEXT: call void @use32(i32 [[ZY]])417; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]418; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32419; CHECK-NEXT: ret i32 [[R]]420;421 %zx = zext i1 %x to i32422 %zy = zext i1 %y to i32423 call void @use32(i32 %zy)424 %r = mul i32 %zy, %zx425 ret i32 %r426}427 428define i32 @mul_bools_use3(i1 %x, i1 %y) {429; CHECK-LABEL: @mul_bools_use3(430; CHECK-NEXT: [[ZX:%.*]] = zext i1 [[X:%.*]] to i32431; CHECK-NEXT: call void @use32(i32 [[ZX]])432; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32433; CHECK-NEXT: call void @use32(i32 [[ZY]])434; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i32 [[ZY]], i32 0435; CHECK-NEXT: ret i32 [[R]]436;437 %zx = zext i1 %x to i32438 call void @use32(i32 %zx)439 %zy = zext i1 %y to i32440 call void @use32(i32 %zy)441 %r = mul i32 %zx, %zy442 ret i32 %r443}444 445define <3 x i32> @mul_bools_sext(<3 x i1> %x, <3 x i1> %y) {446; CHECK-LABEL: @mul_bools_sext(447; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]448; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i32>449; CHECK-NEXT: ret <3 x i32> [[R]]450;451 %sx = sext <3 x i1> %x to <3 x i32>452 %sy = sext <3 x i1> %y to <3 x i32>453 %r = mul <3 x i32> %sx, %sy454 ret <3 x i32> %r455}456 457define i32 @mul_bools_sext_use1(i1 %x, i1 %y) {458; CHECK-LABEL: @mul_bools_sext_use1(459; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32460; CHECK-NEXT: call void @use32(i32 [[SY]])461; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]462; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32463; CHECK-NEXT: ret i32 [[R]]464;465 %sx = sext i1 %x to i32466 %sy = sext i1 %y to i32467 call void @use32(i32 %sy)468 %r = mul i32 %sx, %sy469 ret i32 %r470}471 472define i32 @mul_bools_sext_use2(i1 %x, i1 %y) {473; CHECK-LABEL: @mul_bools_sext_use2(474; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32475; CHECK-NEXT: call void @use32(i32 [[SY]])476; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]477; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32478; CHECK-NEXT: ret i32 [[R]]479;480 %sx = sext i1 %x to i32481 %sy = sext i1 %y to i32482 call void @use32(i32 %sy)483 %r = mul i32 %sy, %sx484 ret i32 %r485}486 487define i32 @mul_bools_sext_use3(i1 %x, i1 %y) {488; CHECK-LABEL: @mul_bools_sext_use3(489; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32490; CHECK-NEXT: call void @use32(i32 [[SX]])491; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32492; CHECK-NEXT: call void @use32(i32 [[SY]])493; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SY]], [[SX]]494; CHECK-NEXT: ret i32 [[R]]495;496 %sx = sext i1 %x to i32497 call void @use32(i32 %sx)498 %sy = sext i1 %y to i32499 call void @use32(i32 %sy)500 %r = mul i32 %sy, %sx501 ret i32 %r502}503 504define i32 @mul_bools_sext_one_use_per_op(i1 %x, i1 %y) {505; CHECK-LABEL: @mul_bools_sext_one_use_per_op(506; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]507; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32508; CHECK-NEXT: ret i32 [[R]]509;510 %sx = sext i1 %x to i32511 %sy = sext i1 %y to i32512 %r = mul i32 %sx, %sy513 ret i32 %r514}515 516define i32 @mul_bool_sext_one_user(i1 %x) {517; CHECK-LABEL: @mul_bool_sext_one_user(518; CHECK-NEXT: [[R:%.*]] = zext i1 [[X:%.*]] to i32519; CHECK-NEXT: ret i32 [[R]]520;521 %sx = sext i1 %x to i32522 %r = mul i32 %sx, %sx523 ret i32 %r524}525 526define i32 @mul_bools_zext_one_use_per_op(i1 %x, i1 %y) {527; CHECK-LABEL: @mul_bools_zext_one_use_per_op(528; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]529; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32530; CHECK-NEXT: ret i32 [[R]]531;532 %zx = zext i1 %x to i32533 %zy = zext i1 %y to i32534 %r = mul i32 %zx, %zy535 ret i32 %r536}537 538define i32 @mul_bool_zext_one_user(i1 %x) {539; CHECK-LABEL: @mul_bool_zext_one_user(540; CHECK-NEXT: [[R:%.*]] = zext i1 [[X:%.*]] to i32541; CHECK-NEXT: ret i32 [[R]]542;543 %sx = zext i1 %x to i32544 %r = mul i32 %sx, %sx545 ret i32 %r546}547 548define i32 @mul_bool_sext_one_extra_user(i1 %x) {549; CHECK-LABEL: @mul_bool_sext_one_extra_user(550; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32551; CHECK-NEXT: call void @use32(i32 [[SX]])552; CHECK-NEXT: [[R:%.*]] = zext i1 [[X]] to i32553; CHECK-NEXT: ret i32 [[R]]554;555 %sx = sext i1 %x to i32556 call void @use32(i32 %sx)557 %r = mul i32 %sx, %sx558 ret i32 %r559}560 561define i32 @mul_bool_zext_one_extra_user(i1 %x) {562; CHECK-LABEL: @mul_bool_zext_one_extra_user(563; CHECK-NEXT: [[SX:%.*]] = zext i1 [[X:%.*]] to i32564; CHECK-NEXT: call void @use32(i32 [[SX]])565; CHECK-NEXT: [[R:%.*]] = zext i1 [[X]] to i32566; CHECK-NEXT: ret i32 [[R]]567;568 %sx = zext i1 %x to i32569 call void @use32(i32 %sx)570 %r = mul i32 %sx, %sx571 ret i32 %r572}573 574define <3 x i32> @mul_bools_mixed_ext(<3 x i1> %x, <3 x i1> %y) {575; CHECK-LABEL: @mul_bools_mixed_ext(576; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]577; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32>578; CHECK-NEXT: ret <3 x i32> [[R]]579;580 %zx = zext <3 x i1> %x to <3 x i32>581 %sy = sext <3 x i1> %y to <3 x i32>582 %r = mul <3 x i32> %zx, %sy583 ret <3 x i32> %r584}585 586define i32 @mul_bools_mixed_ext_use1(i1 %x, i1 %y) {587; CHECK-LABEL: @mul_bools_mixed_ext_use1(588; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32589; CHECK-NEXT: call void @use32(i32 [[ZY]])590; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]591; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32592; CHECK-NEXT: ret i32 [[R]]593;594 %sx = sext i1 %x to i32595 %zy = zext i1 %y to i32596 call void @use32(i32 %zy)597 %r = mul i32 %sx, %zy598 ret i32 %r599}600 601define i32 @mul_bools_mixed_ext_use2(i1 %x, i1 %y) {602; CHECK-LABEL: @mul_bools_mixed_ext_use2(603; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32604; CHECK-NEXT: call void @use32(i32 [[SY]])605; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]606; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32607; CHECK-NEXT: ret i32 [[R]]608;609 %zx = zext i1 %x to i32610 %sy = sext i1 %y to i32611 call void @use32(i32 %sy)612 %r = mul i32 %sy, %zx613 ret i32 %r614}615 616define i32 @mul_bools_mixed_ext_use3(i1 %x, i1 %y) {617; CHECK-LABEL: @mul_bools_mixed_ext_use3(618; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32619; CHECK-NEXT: call void @use32(i32 [[SX]])620; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32621; CHECK-NEXT: call void @use32(i32 [[ZY]])622; CHECK-NEXT: [[R:%.*]] = select i1 [[Y]], i32 [[SX]], i32 0623; CHECK-NEXT: ret i32 [[R]]624;625 %sx = sext i1 %x to i32626 call void @use32(i32 %sx)627 %zy = zext i1 %y to i32628 call void @use32(i32 %zy)629 %r = mul i32 %zy, %sx630 ret i32 %r631}632 633; (A >>u 31) * B --> (A >>s 31) & B --> A < 0 ? B : 0634 635define i32 @signbit_mul(i32 %a, i32 %b) {636; CHECK-LABEL: @signbit_mul(637; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 0638; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0639; CHECK-NEXT: ret i32 [[E]]640;641 %d = lshr i32 %a, 31642 %e = mul i32 %d, %b643 ret i32 %e644}645 646define i32 @signbit_mul_commute_extra_use(i32 %a, i32 %b) {647; CHECK-LABEL: @signbit_mul_commute_extra_use(648; CHECK-NEXT: [[D:%.*]] = lshr i32 [[A:%.*]], 31649; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A]], 0650; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0651; CHECK-NEXT: call void @use32(i32 [[D]])652; CHECK-NEXT: ret i32 [[E]]653;654 %d = lshr i32 %a, 31655 %e = mul i32 %b, %d656 call void @use32(i32 %d)657 ret i32 %e658}659 660; (A >>u 31)) * B --> (A >>s 31) & B --> A < 0 ? B : 0661 662define <2 x i32> @signbit_mul_vec(<2 x i32> %a, <2 x i32> %b) {663; CHECK-LABEL: @signbit_mul_vec(664; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[A:%.*]], zeroinitializer665; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer666; CHECK-NEXT: ret <2 x i32> [[E]]667;668 %d = lshr <2 x i32> %a, <i32 31, i32 31>669 %e = mul <2 x i32> %d, %b670 ret <2 x i32> %e671}672 673define <2 x i32> @signbit_mul_vec_commute(<2 x i32> %a, <2 x i32> %b) {674; CHECK-LABEL: @signbit_mul_vec_commute(675; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[A:%.*]], zeroinitializer676; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer677; CHECK-NEXT: ret <2 x i32> [[E]]678;679 %d = lshr <2 x i32> %a, <i32 31, i32 31>680 %e = mul <2 x i32> %b, %d681 ret <2 x i32> %e682}683 684; (A & 1) * B --> (lowbit A) ? B : 0685 686define i32 @lowbit_mul(i32 %a, i32 %b) {687; CHECK-LABEL: @lowbit_mul(688; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[A:%.*]] to i1689; CHECK-NEXT: [[E:%.*]] = select i1 [[TMP1]], i32 [[B:%.*]], i32 0690; CHECK-NEXT: ret i32 [[E]]691;692 %d = and i32 %a, 1693 %e = mul i32 %d, %b694 ret i32 %e695}696 697; (A & 1) * B --> (lowbit A) ? B : 0698 699define <2 x i17> @lowbit_mul_commute(<2 x i17> %a, <2 x i17> %p) {700; CHECK-LABEL: @lowbit_mul_commute(701; CHECK-NEXT: [[B:%.*]] = xor <2 x i17> [[P:%.*]], <i17 42, i17 43>702; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i17> [[A:%.*]] to <2 x i1>703; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[TMP1]], <2 x i17> [[B]], <2 x i17> zeroinitializer704; CHECK-NEXT: ret <2 x i17> [[E]]705;706 %b = xor <2 x i17> %p, <i17 42, i17 43> ; thwart complexity-based canonicalization707 %d = and <2 x i17> %a, <i17 1, i17 1>708 %e = mul <2 x i17> %b, %d709 ret <2 x i17> %e710}711 712; negative test - extra use713 714define i32 @lowbit_mul_use(i32 %a, i32 %b) {715; CHECK-LABEL: @lowbit_mul_use(716; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], 1717; CHECK-NEXT: call void @use32(i32 [[D]])718; CHECK-NEXT: [[E:%.*]] = mul nuw i32 [[D]], [[B:%.*]]719; CHECK-NEXT: ret i32 [[E]]720;721 %d = and i32 %a, 1722 call void @use32(i32 %d)723 %e = mul i32 %d, %b724 ret i32 %e725}726 727; negative test - wrong mask728 729define i32 @not_lowbit_mul(i32 %a, i32 %b) {730; CHECK-LABEL: @not_lowbit_mul(731; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], 2732; CHECK-NEXT: [[E:%.*]] = mul i32 [[D]], [[B:%.*]]733; CHECK-NEXT: ret i32 [[E]]734;735 %d = and i32 %a, 2736 %e = mul i32 %d, %b737 ret i32 %e738}739 740define i32 @signsplat_mul(i32 %x) {741; CHECK-LABEL: @signsplat_mul(742; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0743; CHECK-NEXT: [[MUL:%.*]] = select i1 [[ISNEG]], i32 -42, i32 0744; CHECK-NEXT: ret i32 [[MUL]]745;746 %ash = ashr i32 %x, 31747 %mul = mul i32 %ash, 42748 ret i32 %mul749}750 751define <2 x i32> @signsplat_mul_vec(<2 x i32> %x) {752; CHECK-LABEL: @signsplat_mul_vec(753; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer754; CHECK-NEXT: [[MUL:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> <i32 -42, i32 3>, <2 x i32> zeroinitializer755; CHECK-NEXT: ret <2 x i32> [[MUL]]756;757 %ash = ashr <2 x i32> %x, <i32 31, i32 31>758 %mul = mul <2 x i32> %ash, <i32 42, i32 -3>759 ret <2 x i32> %mul760}761 762; negative test - wrong shift amount763 764define i32 @not_signsplat_mul(i32 %x) {765; CHECK-LABEL: @not_signsplat_mul(766; CHECK-NEXT: [[ASH:%.*]] = ashr i32 [[X:%.*]], 30767; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ASH]], 42768; CHECK-NEXT: ret i32 [[MUL]]769;770 %ash = ashr i32 %x, 30771 %mul = mul i32 %ash, 42772 ret i32 %mul773}774 775; negative test - extra use776 777define i32 @signsplat_mul_use(i32 %x) {778; CHECK-LABEL: @signsplat_mul_use(779; CHECK-NEXT: [[ASH:%.*]] = ashr i32 [[X:%.*]], 31780; CHECK-NEXT: call void @use32(i32 [[ASH]])781; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ASH]], -42782; CHECK-NEXT: ret i32 [[MUL]]783;784 %ash = ashr i32 %x, 31785 call void @use32(i32 %ash)786 %mul = mul i32 %ash, -42787 ret i32 %mul788}789 790define i32 @test18(i32 %A, i32 %B) {791; CHECK-LABEL: @test18(792; CHECK-NEXT: ret i32 0793;794 %C = and i32 %A, 1795 %D = and i32 %B, 1796 %E = mul i32 %C, %D797 %F = and i32 %E, 16798 ret i32 %F799}800 801declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32)802declare void @use(i1)803 804define i32 @test19(i32 %A, i32 %B) {805; CHECK-LABEL: @test19(806; CHECK-NEXT: call void @use(i1 false)807; CHECK-NEXT: ret i32 0808;809 %C = and i32 %A, 1810 %D = and i32 %B, 1811 812; It would be nice if we also started proving that this doesn't overflow.813 %E = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %C, i32 %D)814 %F = extractvalue {i32, i1} %E, 0815 %G = extractvalue {i32, i1} %E, 1816 call void @use(i1 %G)817 %H = and i32 %F, 16818 ret i32 %H819}820 821define <2 x i64> @test20(<2 x i64> %A) {822; CHECK-LABEL: @test20(823; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i64> [[A:%.*]], <i64 3, i64 2>824; CHECK-NEXT: [[C:%.*]] = add <2 x i64> [[TMP1]], <i64 36, i64 28>825; CHECK-NEXT: ret <2 x i64> [[C]]826;827 %B = add <2 x i64> %A, <i64 12, i64 14>828 %C = mul <2 x i64> %B, <i64 3, i64 2>829 ret <2 x i64> %C830}831 832@g = internal global i32 0, align 4833 834define i32 @PR20079(i32 %a) {835; CHECK-LABEL: @PR20079(836; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A:%.*]], -1837; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], ptrtoint (ptr @g to i32)838; CHECK-NEXT: ret i32 [[MUL]]839;840 %add = add i32 %a, -1841 %mul = mul nsw i32 %add, ptrtoint (ptr @g to i32)842 ret i32 %mul843}844 845; Keep nuw flag in this change, https://alive2.llvm.org/ce/z/-Wowpk846define i32 @add_mul_nuw(i32 %a) {847; CHECK-LABEL: @add_mul_nuw(848; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 3849; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9850; CHECK-NEXT: ret i32 [[MUL]]851;852 %add = add nuw i32 %a, 3853 %mul = mul nuw i32 %add, 3854 ret i32 %mul855}856 857; Don't propagate nsw flag in this change858define i32 @add_mul_nsw(i32 %a) {859; CHECK-LABEL: @add_mul_nsw(860; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3861; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9862; CHECK-NEXT: ret i32 [[MUL]]863;864 %add = add nsw i32 %a, 3865 %mul = mul nsw i32 %add, 3866 ret i32 %mul867}868 869; Only the add or only the mul has nuw, https://alive2.llvm.org/ce/z/vPwbEa870define i32 @only_add_nuw(i32 %a) {871; CHECK-LABEL: @only_add_nuw(872; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3873; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9874; CHECK-NEXT: ret i32 [[MUL]]875;876 %add = add nuw i32 %a, 3877 %mul = mul i32 %add, 3878 ret i32 %mul879}880 881define i32 @only_mul_nuw(i32 %a) {882; CHECK-LABEL: @only_mul_nuw(883; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3884; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9885; CHECK-NEXT: ret i32 [[MUL]]886;887 %add = add i32 %a, 3888 %mul = mul nuw i32 %add, 3889 ret i32 %mul890}891 892; Don't propagate nsw flag in this change, https://alive2.llvm.org/ce/z/jJ8rZd893define i32 @PR57278_shl(i32 %a) {894; CHECK-LABEL: @PR57278_shl(895; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 12896; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9897; CHECK-NEXT: ret i32 [[MUL]]898;899 %shl = shl nsw i32 %a, 2900 %add = or i32 %shl, 3901 %mul = mul nsw i32 %add, 3902 ret i32 %mul903}904 905; Negative test: Have common bits set906define i32 @PR57278_shl_1(i32 %a) {907; CHECK-LABEL: @PR57278_shl_1(908; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[A:%.*]], 2909; CHECK-NEXT: [[ADD:%.*]] = or i32 [[SHL]], 4910; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], 3911; CHECK-NEXT: ret i32 [[MUL]]912;913 %shl = shl nsw i32 %a, 2914 %add = or i32 %shl, 4915 %mul = mul nsw i32 %add, 3916 ret i32 %mul917}918 919; Keep nuw flag in this change, https://alive2.llvm.org/ce/z/awsQrx920define i32 @PR57278_mul(i32 %a) {921; CHECK-LABEL: @PR57278_mul(922; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 36923; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9924; CHECK-NEXT: ret i32 [[MUL]]925;926 %mul0 = mul nuw i32 %a, 12927 %add = or i32 %mul0, 3928 %mul = mul nuw i32 %add, 3929 ret i32 %mul930}931 932; Negative test: Have common bits set, https://alive2.llvm.org/ce/z/bHZRh5933define i32 @PR57278_mul_1(i32 %a) {934; CHECK-LABEL: @PR57278_mul_1(935; CHECK-NEXT: [[MUL0:%.*]] = mul nuw i32 [[A:%.*]], 12936; CHECK-NEXT: [[ADD:%.*]] = or i32 [[MUL0]], 4937; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[ADD]], 3938; CHECK-NEXT: ret i32 [[MUL]]939;940 %mul0 = mul nuw i32 %a, 12941 %add = or i32 %mul0, 4942 %mul = mul nuw i32 %add, 3943 ret i32 %mul944}945 946; Test the haveNoCommonBitsSet with assume, https://alive2.llvm.org/ce/z/AXKBjK947define i32 @PR57278_mul_assume(i32 %a) {948; CHECK-LABEL: @PR57278_mul_assume(949; CHECK-NEXT: [[COMBITS:%.*]] = and i32 [[A:%.*]], 3950; CHECK-NEXT: [[NOCOMBITS:%.*]] = icmp eq i32 [[COMBITS]], 0951; CHECK-NEXT: call void @llvm.assume(i1 [[NOCOMBITS]])952; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A]], 5953; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 15954; CHECK-NEXT: ret i32 [[MUL]]955;956 %combits = and i32 %a , 3957 %nocombits = icmp eq i32 %combits, 0958 call void @llvm.assume(i1 %nocombits)959 960 %add = or i32 %a, 3961 %mul = mul i32 %add, 5962 ret i32 %mul963}964 965declare void @llvm.assume(i1)966 967define i32 @PR57278_or_disjoint_nuw(i32 %a) {968; CHECK-LABEL: @PR57278_or_disjoint_nuw(969; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 3970; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9971; CHECK-NEXT: ret i32 [[MUL]]972;973 %add = or disjoint i32 %a, 3974 %mul = mul nuw i32 %add, 3975 ret i32 %mul976}977 978define i32 @PR57278_or_disjoint_nsw(i32 %a) {979; CHECK-LABEL: @PR57278_or_disjoint_nsw(980; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3981; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9982; CHECK-NEXT: ret i32 [[MUL]]983;984 %add = or disjoint i32 %a, 3985 %mul = mul nsw i32 %add, 3986 ret i32 %mul987}988 989; https://alive2.llvm.org/ce/z/XYpv9q990define <2 x i32> @PR57278_shl_vec(<2 x i32> %v1) {991; CHECK-LABEL: @PR57278_shl_vec(992; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <2 x i32> [[V1:%.*]], <i32 12, i32 24>993; CHECK-NEXT: [[MUL:%.*]] = add nuw <2 x i32> [[TMP1]], splat (i32 9)994; CHECK-NEXT: ret <2 x i32> [[MUL]]995;996 %shl = shl nuw <2 x i32> %v1, <i32 2, i32 3>997 %add = or <2 x i32> %shl, <i32 3, i32 3>998 %mul = mul nuw <2 x i32> %add, <i32 3, i32 3>999 ret <2 x i32> %mul1000}1001 1002; TODO: vector with poison should also be supported, https://alive2.llvm.org/ce/z/XYpv9q1003define <2 x i32> @PR57278_shl_vec_poison(<2 x i32> %v1) {1004; CHECK-LABEL: @PR57278_shl_vec_poison(1005; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i32> [[V1:%.*]], <i32 2, i32 poison>1006; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <2 x i32> [[SHL]], <i32 3, i32 poison>1007; CHECK-NEXT: [[MUL:%.*]] = add nuw <2 x i32> [[TMP1]], <i32 9, i32 poison>1008; CHECK-NEXT: ret <2 x i32> [[MUL]]1009;1010 %shl = shl nuw <2 x i32> %v1, <i32 2, i32 poison>1011 %add = or <2 x i32> %shl, <i32 3, i32 poison>1012 %mul = mul nuw <2 x i32> %add, <i32 3, i32 poison>1013 ret <2 x i32> %mul1014}1015 1016define <2 x i1> @test21(<2 x i1> %A, <2 x i1> %B) {1017; CHECK-LABEL: @test21(1018; CHECK-NEXT: [[C:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]1019; CHECK-NEXT: ret <2 x i1> [[C]]1020;1021 %C = mul <2 x i1> %A, %B1022 ret <2 x i1> %C1023}1024 1025define i32 @test22(i32 %A) {1026; CHECK-LABEL: @test22(1027; CHECK-NEXT: [[B:%.*]] = sub nsw i32 0, [[A:%.*]]1028; CHECK-NEXT: ret i32 [[B]]1029;1030 %B = mul nsw i32 %A, -11031 ret i32 %B1032}1033 1034define i32 @test23(i32 %A) {1035; CHECK-LABEL: @test23(1036; CHECK-NEXT: [[C:%.*]] = mul nuw i32 [[A:%.*]], 61037; CHECK-NEXT: ret i32 [[C]]1038;1039 %B = shl nuw i32 %A, 11040 %C = mul nuw i32 %B, 31041 ret i32 %C1042}1043 1044define i32 @test24(i32 %A) {1045; CHECK-LABEL: @test24(1046; CHECK-NEXT: [[C:%.*]] = mul nsw i32 [[A:%.*]], 61047; CHECK-NEXT: ret i32 [[C]]1048;1049 %B = shl nsw i32 %A, 11050 %C = mul nsw i32 %B, 31051 ret i32 %C1052}1053 1054define i32 @neg_neg_mul(i32 %A, i32 %B) {1055; CHECK-LABEL: @neg_neg_mul(1056; CHECK-NEXT: [[E:%.*]] = mul i32 [[A:%.*]], [[B:%.*]]1057; CHECK-NEXT: ret i32 [[E]]1058;1059 %C = sub i32 0, %A1060 %D = sub i32 0, %B1061 %E = mul i32 %C, %D1062 ret i32 %E1063}1064 1065define i32 @neg_neg_mul_nsw(i32 %A, i32 %B) {1066; CHECK-LABEL: @neg_neg_mul_nsw(1067; CHECK-NEXT: [[E:%.*]] = mul nsw i32 [[A:%.*]], [[B:%.*]]1068; CHECK-NEXT: ret i32 [[E]]1069;1070 %C = sub nsw i32 0, %A1071 %D = sub nsw i32 0, %B1072 %E = mul nsw i32 %C, %D1073 ret i32 %E1074}1075 1076define i124 @neg_neg_mul_apint(i124 %A, i124 %B) {1077; CHECK-LABEL: @neg_neg_mul_apint(1078; CHECK-NEXT: [[E:%.*]] = mul i124 [[A:%.*]], [[B:%.*]]1079; CHECK-NEXT: ret i124 [[E]]1080;1081 %C = sub i124 0, %A1082 %D = sub i124 0, %B1083 %E = mul i124 %C, %D1084 ret i124 %E1085}1086 1087define i32 @neg_mul_constant(i32 %A) {1088; CHECK-LABEL: @neg_mul_constant(1089; CHECK-NEXT: [[E:%.*]] = mul i32 [[A:%.*]], -71090; CHECK-NEXT: ret i32 [[E]]1091;1092 %C = sub i32 0, %A1093 %E = mul i32 %C, 71094 ret i32 %E1095}1096 1097define i55 @neg_mul_constant_apint(i55 %A) {1098; CHECK-LABEL: @neg_mul_constant_apint(1099; CHECK-NEXT: [[E:%.*]] = mul i55 [[A:%.*]], -71100; CHECK-NEXT: ret i55 [[E]]1101;1102 %C = sub i55 0, %A1103 %E = mul i55 %C, 71104 ret i55 %E1105}1106 1107define <3 x i8> @neg_mul_constant_vec(<3 x i8> %a) {1108; CHECK-LABEL: @neg_mul_constant_vec(1109; CHECK-NEXT: [[B:%.*]] = mul <3 x i8> [[A:%.*]], splat (i8 -5)1110; CHECK-NEXT: ret <3 x i8> [[B]]1111;1112 %A = sub <3 x i8> zeroinitializer, %a1113 %B = mul <3 x i8> %A, <i8 5, i8 5, i8 5>1114 ret <3 x i8> %B1115}1116 1117define <3 x i4> @neg_mul_constant_vec_weird(<3 x i4> %a) {1118; CHECK-LABEL: @neg_mul_constant_vec_weird(1119; CHECK-NEXT: [[B:%.*]] = mul <3 x i4> [[A:%.*]], splat (i4 -5)1120; CHECK-NEXT: ret <3 x i4> [[B]]1121;1122 %A = sub <3 x i4> zeroinitializer, %a1123 %B = mul <3 x i4> %A, <i4 5, i4 5, i4 5>1124 ret <3 x i4> %B1125}1126 1127define i64 @test29(i31 %A, i31 %B) {1128; CHECK-LABEL: @test29(1129; CHECK-NEXT: [[C:%.*]] = sext i31 [[A:%.*]] to i641130; CHECK-NEXT: [[D:%.*]] = sext i31 [[B:%.*]] to i641131; CHECK-NEXT: [[E:%.*]] = mul nsw i64 [[C]], [[D]]1132; CHECK-NEXT: ret i64 [[E]]1133;1134 %C = sext i31 %A to i641135 %D = sext i31 %B to i641136 %E = mul i64 %C, %D1137 ret i64 %E1138}1139 1140define i64 @test30(i32 %A, i32 %B) {1141; CHECK-LABEL: @test30(1142; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i641143; CHECK-NEXT: [[D:%.*]] = zext i32 [[B:%.*]] to i641144; CHECK-NEXT: [[E:%.*]] = mul nuw i64 [[C]], [[D]]1145; CHECK-NEXT: ret i64 [[E]]1146;1147 %C = zext i32 %A to i641148 %D = zext i32 %B to i641149 %E = mul i64 %C, %D1150 ret i64 %E1151}1152 1153@PR22087 = external global i321154define i32 @test31(i32 %V) {1155; CHECK-LABEL: @test31(1156; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr inttoptr (i64 4 to ptr), @PR220871157; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[CMP]] to i321158; CHECK-NEXT: [[MUL1:%.*]] = shl i32 [[V:%.*]], [[EXT]]1159; CHECK-NEXT: ret i32 [[MUL1]]1160;1161 %cmp = icmp ne ptr inttoptr (i64 4 to ptr), @PR220871162 %ext = zext i1 %cmp to i321163 %shl = shl i32 1, %ext1164 %mul = mul i32 %V, %shl1165 ret i32 %mul1166}1167 1168define i32 @test32(i32 %X) {1169; CHECK-LABEL: @test32(1170; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X:%.*]], 311171; CHECK-NEXT: ret i32 [[MUL]]1172;1173 %mul = mul nsw i32 %X, -21474836481174 ret i32 %mul1175}1176 1177define <2 x i32> @test32vec(<2 x i32> %X) {1178; CHECK-LABEL: @test32vec(1179; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[X:%.*]], splat (i32 31)1180; CHECK-NEXT: ret <2 x i32> [[MUL]]1181;1182 %mul = mul nsw <2 x i32> %X, <i32 -2147483648, i32 -2147483648>1183 ret <2 x i32> %mul1184}1185 1186define i32 @test33(i32 %X) {1187; CHECK-LABEL: @test33(1188; CHECK-NEXT: [[MUL:%.*]] = shl nsw i32 [[X:%.*]], 301189; CHECK-NEXT: ret i32 [[MUL]]1190;1191 %mul = mul nsw i32 %X, 10737418241192 ret i32 %mul1193}1194 1195define <2 x i32> @test33vec(<2 x i32> %X) {1196; CHECK-LABEL: @test33vec(1197; CHECK-NEXT: [[MUL:%.*]] = shl nsw <2 x i32> [[X:%.*]], splat (i32 30)1198; CHECK-NEXT: ret <2 x i32> [[MUL]]1199;1200 %mul = mul nsw <2 x i32> %X, <i32 1073741824, i32 1073741824>1201 ret <2 x i32> %mul1202}1203 1204define i128 @test34(i128 %X) {1205; CHECK-LABEL: @test34(1206; CHECK-NEXT: [[MUL:%.*]] = shl nsw i128 [[X:%.*]], 11207; CHECK-NEXT: ret i128 [[MUL]]1208;1209 %mul = mul nsw i128 %X, 21210 ret i128 %mul1211}1212 1213define i32 @test_mul_canonicalize_op0(i32 %x, i32 %y) {1214; CHECK-LABEL: @test_mul_canonicalize_op0(1215; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]1216; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]]1217; CHECK-NEXT: ret i32 [[MUL]]1218;1219 %neg = sub i32 0, %x1220 %mul = mul i32 %neg, %y1221 ret i32 %mul1222}1223 1224define i32 @test_mul_canonicalize_op1(i32 %x, i32 %z) {1225; CHECK-LABEL: @test_mul_canonicalize_op1(1226; CHECK-NEXT: [[Y_NEG:%.*]] = mul i32 [[Z:%.*]], -31227; CHECK-NEXT: [[DOTNEG:%.*]] = mul i32 [[Y_NEG]], [[X:%.*]]1228; CHECK-NEXT: ret i32 [[DOTNEG]]1229;1230 %y = mul i32 %z, 31231 %neg = sub i32 0, %x1232 %mul = mul i32 %y, %neg1233 ret i32 %mul1234}1235 1236define i32 @test_mul_canonicalize_nsw(i32 %x, i32 %y) {1237; CHECK-LABEL: @test_mul_canonicalize_nsw(1238; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]1239; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]]1240; CHECK-NEXT: ret i32 [[MUL]]1241;1242 %neg = sub nsw i32 0, %x1243 %mul = mul nsw i32 %neg, %y1244 ret i32 %mul1245}1246 1247define <2 x i32> @test_mul_canonicalize_vec(<2 x i32> %x, <2 x i32> %y) {1248; CHECK-LABEL: @test_mul_canonicalize_vec(1249; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], [[Y:%.*]]1250; CHECK-NEXT: [[MUL:%.*]] = sub <2 x i32> zeroinitializer, [[TMP1]]1251; CHECK-NEXT: ret <2 x i32> [[MUL]]1252;1253 %neg = sub <2 x i32> <i32 0, i32 0>, %x1254 %mul = mul <2 x i32> %neg, %y1255 ret <2 x i32> %mul1256}1257 1258define i32 @test_mul_canonicalize_multiple_uses(i32 %x, i32 %y) {1259; CHECK-LABEL: @test_mul_canonicalize_multiple_uses(1260; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]1261; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]1262; CHECK-NEXT: ret i32 [[MUL2]]1263;1264 %neg = sub i32 0, %x1265 %mul = mul i32 %neg, %y1266 %mul2 = mul i32 %mul, %neg1267 ret i32 %mul21268}1269 1270define i32 @mul_nsw_mul_nsw_neg(i32 %x, i32 %y) {1271; CHECK-LABEL: @mul_nsw_mul_nsw_neg(1272; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]1273; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]1274; CHECK-NEXT: ret i32 [[MUL2]]1275;1276 %neg = sub i32 0, %x1277 %mul = mul nsw i32 %neg, %y1278 %mul2 = mul nsw i32 %mul, %neg1279 ret i32 %mul21280}1281 1282define i32 @mul_mul_nsw_neg(i32 %x,i32 %y) {1283; CHECK-LABEL: @mul_mul_nsw_neg(1284; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]1285; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]1286; CHECK-NEXT: ret i32 [[MUL2]]1287;1288 %neg = sub i32 0, %x1289 %mul = mul nsw i32 %neg, %y1290 %mul2 = mul i32 %mul, %neg1291 ret i32 %mul21292}1293 1294define i32 @mul_nsw_mul_neg(i32 %x,i32 %y) {1295; CHECK-LABEL: @mul_nsw_mul_neg(1296; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]1297; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]1298; CHECK-NEXT: ret i32 [[MUL2]]1299;1300 %neg = sub i32 0, %x1301 %mul = mul i32 %neg, %y1302 %mul2 = mul nsw i32 %mul, %neg1303 ret i32 %mul21304}1305 1306define i32 @mul_nsw_mul_neg_onearg(i32 %x) {1307; CHECK-LABEL: @mul_nsw_mul_neg_onearg(1308; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]]1309; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]1310; CHECK-NEXT: ret i32 [[MUL2]]1311;1312 %neg = sub i32 0, %x1313 %mul = mul i32 %neg, %x1314 %mul2 = mul nsw i32 %mul, %neg1315 ret i32 %mul21316}1317 1318define i8 @mul_mul_nsw_neg_onearg(i8 %x) {1319; CHECK-LABEL: @mul_mul_nsw_neg_onearg(1320; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i8 [[X:%.*]], [[X]]1321; CHECK-NEXT: [[MUL2:%.*]] = mul i8 [[MUL_NEG]], [[X]]1322; CHECK-NEXT: ret i8 [[MUL2]]1323;1324 %neg = sub i8 0, %x1325 %mul = mul nsw i8 %neg, %x1326 %mul2 = mul i8 %mul, %neg1327 ret i8 %mul21328}1329 1330define i32 @mul_nsw_mul_nsw_neg_onearg(i32 %x) {1331; CHECK-LABEL: @mul_nsw_mul_nsw_neg_onearg(1332; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]]1333; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]]1334; CHECK-NEXT: ret i32 [[MUL2]]1335;1336 %neg = sub i32 0, %x1337 %mul = mul nsw i32 %neg, %x1338 %mul2 = mul nsw i32 %mul, %neg1339 ret i32 %mul21340}1341 1342define i32 @mul_nsw_shl_nsw_neg(i32 %x, i32 %y) {1343; CHECK-LABEL: @mul_nsw_shl_nsw_neg(1344; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]1345; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]1346; CHECK-NEXT: ret i32 [[MUL]]1347;1348 %neg = sub i32 0, %x1349 %shl = shl nsw i32 %neg, %y1350 %mul = mul nsw i32 %shl, %neg1351 ret i32 %mul1352}1353 1354define i32 @mul_shl_nsw_neg(i32 %x,i32 %y) {1355; CHECK-LABEL: @mul_shl_nsw_neg(1356; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]1357; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]1358; CHECK-NEXT: ret i32 [[MUL]]1359;1360 %neg = sub i32 0, %x1361 %shl = shl nsw i32 %neg, %y1362 %mul = mul i32 %shl, %neg1363 ret i32 %mul1364}1365 1366define i32 @mul_nsw_shl_neg(i32 %x,i32 %y) {1367; CHECK-LABEL: @mul_nsw_shl_neg(1368; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]1369; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]1370; CHECK-NEXT: ret i32 [[MUL]]1371;1372 %neg = sub i32 0, %x1373 %shl = shl i32 %neg, %y1374 %mul = mul nsw i32 %shl, %neg1375 ret i32 %mul1376}1377 1378define i32 @mul_nsw_shl_neg_onearg(i32 %x) {1379; CHECK-LABEL: @mul_nsw_shl_neg_onearg(1380; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[X]]1381; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]1382; CHECK-NEXT: ret i32 [[MUL]]1383;1384 %neg = sub i32 0, %x1385 %shl = shl i32 %neg, %x1386 %mul = mul nsw i32 %shl, %neg1387 ret i32 %mul1388}1389 1390define i8 @mul_shl_nsw_neg_onearg(i8 %x) {1391; CHECK-LABEL: @mul_shl_nsw_neg_onearg(1392; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i8 [[X:%.*]], [[X]]1393; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[SHL_NEG]], [[X]]1394; CHECK-NEXT: ret i8 [[MUL]]1395;1396 %neg = sub i8 0, %x1397 %shl = shl nsw i8 %neg, %x1398 %mul = mul i8 %shl, %neg1399 ret i8 %mul1400}1401 1402define i32 @mul_nsw_shl_nsw_neg_onearg(i32 %x) {1403; CHECK-LABEL: @mul_nsw_shl_nsw_neg_onearg(1404; CHECK-NEXT: [[SHL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]]1405; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]]1406; CHECK-NEXT: ret i32 [[MUL]]1407;1408 %neg = sub i32 0, %x1409 %shl = mul nsw i32 %neg, %x1410 %mul = mul nsw i32 %shl, %neg1411 ret i32 %mul1412}1413 1414define i32 @mul_use_mul_neg(i32 %x,i32 %y) {1415; CHECK-LABEL: @mul_use_mul_neg(1416; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]1417; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[NEG]]1418; CHECK-NEXT: call void @use32(i32 [[MUL]])1419; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL]], [[NEG]]1420; CHECK-NEXT: ret i32 [[MUL2]]1421;1422 %neg = sub i32 0, %x1423 %mul = mul i32 %neg, %y1424 call void @use32(i32 %mul)1425 %mul2 = mul i32 %mul, %neg1426 ret i32 %mul21427}1428 1429define i32 @mul_shl_use_mul_neg(i32 %x,i32 %y) {1430; CHECK-LABEL: @mul_shl_use_mul_neg(1431; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]1432; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[NEG]], [[Y:%.*]]1433; CHECK-NEXT: call void @use32(i32 [[SHL]])1434; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[SHL]], [[NEG]]1435; CHECK-NEXT: ret i32 [[MUL2]]1436;1437 %neg = sub i32 0, %x1438 %shl = shl i32 %neg, %y1439 call void @use32(i32 %shl)1440 %mul2 = mul i32 %shl, %neg1441 ret i32 %mul21442}1443 1444@X = global i32 51445 1446define i64 @test_mul_canonicalize_neg_is_not_undone(i64 %L1) {1447; Check we do not undo the canonicalization of 0 - (X * Y), if Y is a constant1448; expr.1449; CHECK-LABEL: @test_mul_canonicalize_neg_is_not_undone(1450; CHECK-NEXT: [[B4:%.*]] = mul i64 [[L1:%.*]], sub (i64 0, i64 ptrtoint (ptr @X to i64))1451; CHECK-NEXT: ret i64 [[B4]]1452;1453 %v1 = ptrtoint ptr @X to i641454 %B8 = sub i64 0, %v11455 %B4 = mul i64 %B8, %L11456 ret i64 %B41457}1458 1459define i32 @negate_if_true(i32 %x, i1 %cond) {1460; CHECK-LABEL: @negate_if_true(1461; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]]1462; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[X]]1463; CHECK-NEXT: ret i32 [[R]]1464;1465 %sel = select i1 %cond, i32 -1, i32 11466 %r = mul i32 %sel, %x1467 ret i32 %r1468}1469 1470define i32 @negate_if_false(i32 %x, i1 %cond) {1471; CHECK-LABEL: @negate_if_false(1472; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]]1473; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i32 [[X]], i32 [[TMP1]]1474; CHECK-NEXT: ret i32 [[R]]1475;1476 %sel = select i1 %cond, i32 1, i32 -11477 %r = mul i32 %sel, %x1478 ret i32 %r1479}1480 1481define <2 x i8> @negate_if_true_commute(<2 x i8> %px, i1 %cond) {1482; CHECK-LABEL: @negate_if_true_commute(1483; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> splat (i8 42), [[PX:%.*]]1484; CHECK-NEXT: [[TMP1:%.*]] = sub nsw <2 x i8> zeroinitializer, [[X]]1485; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[TMP1]], <2 x i8> [[X]]1486; CHECK-NEXT: ret <2 x i8> [[R]]1487;1488 %x = sdiv <2 x i8> <i8 42, i8 42>, %px ; thwart complexity-based canonicalization1489 %sel = select i1 %cond, <2 x i8> <i8 -1, i8 -1>, <2 x i8> <i8 1, i8 1>1490 %r = mul <2 x i8> %x, %sel1491 ret <2 x i8> %r1492}1493 1494define <2 x i8> @negate_if_false_commute(<2 x i8> %px, <2 x i1> %cond) {1495; CHECK-LABEL: @negate_if_false_commute(1496; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> <i8 42, i8 5>, [[PX:%.*]]1497; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> zeroinitializer, [[X]]1498; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i8> [[X]], <2 x i8> [[TMP1]]1499; CHECK-NEXT: ret <2 x i8> [[R]]1500;1501 %x = sdiv <2 x i8> <i8 42, i8 5>, %px ; thwart complexity-based canonicalization1502 %sel = select <2 x i1> %cond, <2 x i8> <i8 1, i8 poison>, <2 x i8> <i8 -1, i8 -1>1503 %r = mul <2 x i8> %x, %sel1504 ret <2 x i8> %r1505}1506 1507; Negative test1508 1509define i32 @negate_if_true_extra_use(i32 %x, i1 %cond) {1510; CHECK-LABEL: @negate_if_true_extra_use(1511; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 -1, i32 11512; CHECK-NEXT: call void @use32(i32 [[SEL]])1513; CHECK-NEXT: [[R:%.*]] = mul i32 [[SEL]], [[X:%.*]]1514; CHECK-NEXT: ret i32 [[R]]1515;1516 %sel = select i1 %cond, i32 -1, i32 11517 call void @use32(i32 %sel)1518 %r = mul i32 %sel, %x1519 ret i32 %r1520}1521 1522; Negative test1523 1524define <2 x i8> @negate_if_true_wrong_constant(<2 x i8> %px, i1 %cond) {1525; CHECK-LABEL: @negate_if_true_wrong_constant(1526; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> splat (i8 42), [[PX:%.*]]1527; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> <i8 -1, i8 0>, <2 x i8> splat (i8 1)1528; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[X]], [[SEL]]1529; CHECK-NEXT: ret <2 x i8> [[R]]1530;1531 %x = sdiv <2 x i8> <i8 42, i8 42>, %px ; thwart complexity-based canonicalization1532 %sel = select i1 %cond, <2 x i8> <i8 -1, i8 0>, <2 x i8> <i8 1, i8 1>1533 %r = mul <2 x i8> %x, %sel1534 ret <2 x i8> %r1535}1536 1537; (C ? (X /exact Y) : 1) * Y -> C ? X : Y1538define i32 @mul_div_select(i32 %x, i32 %y, i1 %c) {1539; CHECK-LABEL: @mul_div_select(1540; CHECK-NEXT: [[MUL:%.*]] = select i1 [[C:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]1541; CHECK-NEXT: ret i32 [[MUL]]1542;1543 %div = udiv exact i32 %x, %y1544 %sel = select i1 %c, i32 %div, i32 11545 %mul = mul i32 %sel, %y1546 ret i32 %mul1547}1548 1549; fold mul(abs(x),abs(x)) -> mul(x,x)1550define i31 @combine_mul_abs_i31(i31 %0) {1551; CHECK-LABEL: @combine_mul_abs_i31(1552; CHECK-NEXT: [[M:%.*]] = mul i31 [[TMP0:%.*]], [[TMP0]]1553; CHECK-NEXT: ret i31 [[M]]1554;1555 %c = icmp slt i31 %0, 01556 %s = sub nsw i31 0, %01557 %r = select i1 %c, i31 %s, i31 %01558 %m = mul i31 %r, %r1559 ret i31 %m1560}1561 1562define i32 @combine_mul_abs_i32(i32 %0) {1563; CHECK-LABEL: @combine_mul_abs_i32(1564; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]1565; CHECK-NEXT: ret i32 [[M]]1566;1567 %c = icmp slt i32 %0, 01568 %s = sub nsw i32 0, %01569 %r = select i1 %c, i32 %s, i32 %01570 %m = mul i32 %r, %r1571 ret i32 %m1572}1573 1574define <4 x i32> @combine_mul_abs_v4i32(<4 x i32> %0) {1575; CHECK-LABEL: @combine_mul_abs_v4i32(1576; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]1577; CHECK-NEXT: ret <4 x i32> [[M]]1578;1579 %c = icmp slt <4 x i32> %0, zeroinitializer1580 %s = sub nsw <4 x i32> zeroinitializer, %01581 %r = select <4 x i1> %c, <4 x i32> %s, <4 x i32> %01582 %m = mul <4 x i32> %r, %r1583 ret <4 x i32> %m1584}1585 1586; fold mul(nabs(x),nabs(x)) -> mul(x,x)1587define i31 @combine_mul_nabs_i31(i31 %0) {1588; CHECK-LABEL: @combine_mul_nabs_i31(1589; CHECK-NEXT: [[M:%.*]] = mul i31 [[TMP0:%.*]], [[TMP0]]1590; CHECK-NEXT: ret i31 [[M]]1591;1592 %c = icmp slt i31 %0, 01593 %s = sub nsw i31 0, %01594 %r = select i1 %c, i31 %0, i31 %s1595 %m = mul i31 %r, %r1596 ret i31 %m1597}1598 1599define i32 @combine_mul_nabs_i32(i32 %0) {1600; CHECK-LABEL: @combine_mul_nabs_i32(1601; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]1602; CHECK-NEXT: ret i32 [[M]]1603;1604 %c = icmp slt i32 %0, 01605 %s = sub nsw i32 0, %01606 %r = select i1 %c, i32 %0, i32 %s1607 %m = mul i32 %r, %r1608 ret i32 %m1609}1610 1611define <4 x i32> @combine_mul_nabs_v4i32(<4 x i32> %0) {1612; CHECK-LABEL: @combine_mul_nabs_v4i32(1613; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]1614; CHECK-NEXT: ret <4 x i32> [[M]]1615;1616 %c = icmp slt <4 x i32> %0, zeroinitializer1617 %s = sub nsw <4 x i32> zeroinitializer, %01618 %r = select <4 x i1> %c, <4 x i32> %0, <4 x i32> %s1619 %m = mul <4 x i32> %r, %r1620 ret <4 x i32> %m1621}1622 1623define i32 @combine_mul_abs_intrin(i32 %x) {1624; CHECK-LABEL: @combine_mul_abs_intrin(1625; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]1626; CHECK-NEXT: ret i32 [[MUL]]1627;1628 %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)1629 %mul = mul i32 %abs, %abs1630 ret i32 %mul1631}1632 1633define i32 @combine_mul_nabs_intrin(i32 %x) {1634; CHECK-LABEL: @combine_mul_nabs_intrin(1635; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]1636; CHECK-NEXT: ret i32 [[MUL]]1637;1638 %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)1639 %neg = sub i32 0, %abs1640 %mul = mul i32 %neg, %neg1641 ret i32 %mul1642}1643 1644; z * splat(0) = splat(0), even for scalable vectors1645define <vscale x 2 x i64> @mul_scalable_splat_zero(<vscale x 2 x i64> %z) {1646; CHECK-LABEL: @mul_scalable_splat_zero(1647; CHECK-NEXT: ret <vscale x 2 x i64> zeroinitializer1648;1649 %shuf = shufflevector <vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 0, i32 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer1650 %t3 = mul <vscale x 2 x i64> %shuf, %z1651 ret <vscale x 2 x i64> %t31652}1653 1654; fold mul(abs(x),abs(y)) -> abs(mul(x,y))1655define i32 @combine_mul_abs_x_abs_y(i32 %x, i32 %y) {1656; CHECK-LABEL: @combine_mul_abs_x_abs_y(1657; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i32 [[X:%.*]], [[Y:%.*]]1658; CHECK-NEXT: [[MUL:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true)1659; CHECK-NEXT: ret i32 [[MUL]]1660;1661 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)1662 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)1663 %mul = mul nsw i32 %abs_x, %abs_y1664 ret i32 %mul1665}1666 1667define i32 @combine_mul_abs_x_abs_y_no_nsw(i32 %x, i32 %y) {1668; CHECK-LABEL: @combine_mul_abs_x_abs_y_no_nsw(1669; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)1670; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)1671; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ABS_X]], [[ABS_Y]]1672; CHECK-NEXT: ret i32 [[MUL]]1673;1674 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)1675 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)1676 %mul = mul i32 %abs_x, %abs_y1677 ret i32 %mul1678}1679 1680define i32 @combine_mul_abs_x_abs_y_poison_1(i32 %x, i32 %y) {1681; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_1(1682; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)1683; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)1684; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]1685; CHECK-NEXT: ret i32 [[MUL]]1686;1687 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)1688 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)1689 %mul = mul nsw i32 %abs_x, %abs_y1690 ret i32 %mul1691}1692 1693define i32 @combine_mul_abs_x_abs_y_poison_2(i32 %x, i32 %y) {1694; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_2(1695; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)1696; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)1697; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]1698; CHECK-NEXT: ret i32 [[MUL]]1699;1700 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 false)1701 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)1702 %mul = mul nsw i32 %abs_x, %abs_y1703 ret i32 %mul1704}1705 1706define i32 @combine_mul_abs_x_abs_y_not_oneuse(i32 %x, i32 %y) {1707; CHECK-LABEL: @combine_mul_abs_x_abs_y_not_oneuse(1708; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)1709; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)1710; CHECK-NEXT: [[ABS_X1:%.*]] = add nuw i32 [[ABS_Y]], 11711; CHECK-NEXT: [[RET:%.*]] = mul i32 [[ABS_X]], [[ABS_X1]]1712; CHECK-NEXT: ret i32 [[RET]]1713;1714 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)1715 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)1716 %mul = mul nsw i32 %abs_x, %abs_y1717 %ret = add i32 %mul, %abs_x1718 ret i32 %ret1719}1720 1721;1722; fold mul(sub(x,y),negpow2) -> shl(sub(y,x),log2(pow2))1723;1724 1725define i32 @mulsub1(i32 %a0, i32 %a1) {1726; CHECK-LABEL: @mulsub1(1727; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i32 [[A0:%.*]], [[A1:%.*]]1728; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[SUB_NEG]], 21729; CHECK-NEXT: ret i32 [[MUL]]1730;1731 %sub = sub i32 %a1, %a01732 %mul = mul i32 %sub, -41733 ret i32 %mul1734}1735 1736define <2 x i32> @mulsub1_vec(<2 x i32> %a0, <2 x i32> %a1) {1737; CHECK-LABEL: @mulsub1_vec(1738; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]]1739; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], splat (i32 2)1740; CHECK-NEXT: ret <2 x i32> [[MUL]]1741;1742 %sub = sub <2 x i32> %a1, %a01743 %mul = mul <2 x i32> %sub, <i32 -4, i32 -4>1744 ret <2 x i32> %mul1745}1746 1747define <2 x i32> @mulsub1_vec_nonuniform(<2 x i32> %a0, <2 x i32> %a1) {1748; CHECK-LABEL: @mulsub1_vec_nonuniform(1749; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]]1750; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 3>1751; CHECK-NEXT: ret <2 x i32> [[MUL]]1752;1753 %sub = sub <2 x i32> %a1, %a01754 %mul = mul <2 x i32> %sub, <i32 -4, i32 -8>1755 ret <2 x i32> %mul1756}1757 1758define <2 x i32> @mulsub1_vec_nonuniform_poison(<2 x i32> %a0, <2 x i32> %a1) {1759; CHECK-LABEL: @mulsub1_vec_nonuniform_poison(1760; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]]1761; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 0>1762; CHECK-NEXT: ret <2 x i32> [[MUL]]1763;1764 %sub = sub <2 x i32> %a1, %a01765 %mul = mul <2 x i32> %sub, <i32 -4, i32 poison>1766 ret <2 x i32> %mul1767}1768 1769define i32 @mulsub2(i32 %a0) {1770; CHECK-LABEL: @mulsub2(1771; CHECK-NEXT: [[SUB_NEG:%.*]] = shl i32 [[A0:%.*]], 21772; CHECK-NEXT: [[MUL:%.*]] = add i32 [[SUB_NEG]], -641773; CHECK-NEXT: ret i32 [[MUL]]1774;1775 %sub = sub i32 16, %a01776 %mul = mul i32 %sub, -41777 ret i32 %mul1778}1779 1780define <2 x i32> @mulsub2_vec(<2 x i32> %a0) {1781; CHECK-LABEL: @mulsub2_vec(1782; CHECK-NEXT: [[SUB_NEG:%.*]] = shl <2 x i32> [[A0:%.*]], splat (i32 2)1783; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[SUB_NEG]], splat (i32 -64)1784; CHECK-NEXT: ret <2 x i32> [[MUL]]1785;1786 %sub = sub <2 x i32> <i32 16, i32 16>, %a01787 %mul = mul <2 x i32> %sub, <i32 -4, i32 -4>1788 ret <2 x i32> %mul1789}1790 1791define <2 x i32> @mulsub2_vec_nonuniform(<2 x i32> %a0) {1792; CHECK-LABEL: @mulsub2_vec_nonuniform(1793; CHECK-NEXT: [[SUB_NEG:%.*]] = add <2 x i32> [[A0:%.*]], <i32 -16, i32 -32>1794; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 3>1795; CHECK-NEXT: ret <2 x i32> [[MUL]]1796;1797 %sub = sub <2 x i32> <i32 16, i32 32>, %a01798 %mul = mul <2 x i32> %sub, <i32 -4, i32 -8>1799 ret <2 x i32> %mul1800}1801 1802define <2 x i32> @mulsub2_vec_nonuniform_poison(<2 x i32> %a0) {1803; CHECK-LABEL: @mulsub2_vec_nonuniform_poison(1804; CHECK-NEXT: [[SUB_NEG:%.*]] = add <2 x i32> [[A0:%.*]], <i32 -16, i32 -32>1805; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 0>1806; CHECK-NEXT: ret <2 x i32> [[MUL]]1807;1808 %sub = sub <2 x i32> <i32 16, i32 32>, %a01809 %mul = mul <2 x i32> %sub, <i32 -4, i32 poison>1810 ret <2 x i32> %mul1811}1812 1813define i8 @mulsub_nsw(i8 %a1, i8 %a2) {1814; CHECK-LABEL: @mulsub_nsw(1815; CHECK-NEXT: [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]]1816; CHECK-NEXT: [[MUL:%.*]] = shl nsw i8 [[A_NEG]], 11817; CHECK-NEXT: ret i8 [[MUL]]1818;1819 %a = sub nsw i8 %a1, %a21820 %mul = mul nsw i8 %a, -21821 ret i8 %mul1822}1823 1824; It would be safe to keep the nsw on the shl here, but only because the mul1825; to shl transform happens to replace poison with 0.1826define <2 x i8> @mulsub_nsw_poison(<2 x i8> %a1, <2 x i8> %a2) {1827; CHECK-LABEL: @mulsub_nsw_poison(1828; CHECK-NEXT: [[A_NEG:%.*]] = sub nsw <2 x i8> [[A2:%.*]], [[A1:%.*]]1829; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i8> [[A_NEG]], <i8 1, i8 0>1830; CHECK-NEXT: ret <2 x i8> [[MUL]]1831;1832 %a = sub nsw <2 x i8> %a1, %a21833 %mul = mul nsw <2 x i8> %a, <i8 -2, i8 poison>1834 ret <2 x i8> %mul1835}1836 1837define i32 @muladd2(i32 %a0) {1838; CHECK-LABEL: @muladd2(1839; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A0:%.*]], 21840; CHECK-NEXT: [[MUL:%.*]] = sub i32 -64, [[TMP1]]1841; CHECK-NEXT: ret i32 [[MUL]]1842;1843 %add = add i32 %a0, 161844 %mul = mul i32 %add, -41845 ret i32 %mul1846}1847 1848define <2 x i32> @muladd2_vec(<2 x i32> %a0) {1849; CHECK-LABEL: @muladd2_vec(1850; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[A0:%.*]], splat (i32 2)1851; CHECK-NEXT: [[MUL:%.*]] = sub <2 x i32> splat (i32 -64), [[TMP1]]1852; CHECK-NEXT: ret <2 x i32> [[MUL]]1853;1854 %add = add <2 x i32> %a0, <i32 16, i32 16>1855 %mul = mul <2 x i32> %add, <i32 -4, i32 -4>1856 ret <2 x i32> %mul1857}1858 1859define <2 x i32> @muladd2_vec_nonuniform(<2 x i32> %a0) {1860; CHECK-LABEL: @muladd2_vec_nonuniform(1861; CHECK-NEXT: [[ADD_NEG:%.*]] = sub <2 x i32> <i32 -16, i32 -32>, [[A0:%.*]]1862; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[ADD_NEG]], <i32 2, i32 3>1863; CHECK-NEXT: ret <2 x i32> [[MUL]]1864;1865 %add = add <2 x i32> %a0, <i32 16, i32 32>1866 %mul = mul <2 x i32> %add, <i32 -4, i32 -8>1867 ret <2 x i32> %mul1868}1869 1870define <2 x i32> @muladd2_vec_nonuniform_poison(<2 x i32> %a0) {1871; CHECK-LABEL: @muladd2_vec_nonuniform_poison(1872; CHECK-NEXT: [[ADD_NEG:%.*]] = sub <2 x i32> <i32 -16, i32 -32>, [[A0:%.*]]1873; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[ADD_NEG]], <i32 2, i32 0>1874; CHECK-NEXT: ret <2 x i32> [[MUL]]1875;1876 %add = add <2 x i32> %a0, <i32 16, i32 32>1877 %mul = mul <2 x i32> %add, <i32 -4, i32 poison>1878 ret <2 x i32> %mul1879}1880 1881define i32 @mulmuladd2(i32 %a0, i32 %a1) {1882; CHECK-LABEL: @mulmuladd2(1883; CHECK-NEXT: [[ADD_NEG:%.*]] = sub i32 1073741808, [[A0:%.*]]1884; CHECK-NEXT: [[MUL1_NEG:%.*]] = mul i32 [[ADD_NEG]], [[A1:%.*]]1885; CHECK-NEXT: [[MUL2:%.*]] = shl i32 [[MUL1_NEG]], 21886; CHECK-NEXT: ret i32 [[MUL2]]1887;1888 %add = add i32 %a0, 161889 %mul1 = mul i32 %add, %a11890 %mul2 = mul i32 %mul1, -41891 ret i32 %mul21892}1893define i32 @mulmuladd2_extrause0(i32 %a0, i32 %a1) {1894; CHECK-LABEL: @mulmuladd2_extrause0(1895; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 161896; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]]1897; CHECK-NEXT: call void @use32(i32 [[MUL1]])1898; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -41899; CHECK-NEXT: ret i32 [[MUL2]]1900;1901 %add = add i32 %a0, 161902 %mul1 = mul i32 %add, %a11903 call void @use32(i32 %mul1)1904 %mul2 = mul i32 %mul1, -41905 ret i32 %mul21906}1907define i32 @mulmuladd2_extrause1(i32 %a0, i32 %a1) {1908; CHECK-LABEL: @mulmuladd2_extrause1(1909; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 161910; CHECK-NEXT: call void @use32(i32 [[ADD]])1911; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]]1912; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -41913; CHECK-NEXT: ret i32 [[MUL2]]1914;1915 %add = add i32 %a0, 161916 call void @use32(i32 %add)1917 %mul1 = mul i32 %add, %a11918 %mul2 = mul i32 %mul1, -41919 ret i32 %mul21920}1921define i32 @mulmuladd2_extrause2(i32 %a0, i32 %a1) {1922; CHECK-LABEL: @mulmuladd2_extrause2(1923; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 161924; CHECK-NEXT: call void @use32(i32 [[ADD]])1925; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]]1926; CHECK-NEXT: call void @use32(i32 [[MUL1]])1927; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -41928; CHECK-NEXT: ret i32 [[MUL2]]1929;1930 %add = add i32 %a0, 161931 call void @use32(i32 %add)1932 %mul1 = mul i32 %add, %a11933 call void @use32(i32 %mul1)1934 %mul2 = mul i32 %mul1, -41935 ret i32 %mul21936}1937 1938define i32 @mulnot(i32 %a0) {1939; CHECK-LABEL: @mulnot(1940; CHECK-NEXT: [[ADD_NEG:%.*]] = shl i32 [[A0:%.*]], 21941; CHECK-NEXT: [[MUL:%.*]] = add i32 [[ADD_NEG]], 41942; CHECK-NEXT: ret i32 [[MUL]]1943;1944 %add = xor i32 %a0, -11945 %mul = mul i32 %add, -41946 ret i32 %mul1947}1948 1949define i32 @mulnot_extrause(i32 %a0) {1950; CHECK-LABEL: @mulnot_extrause(1951; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A0:%.*]], -11952; CHECK-NEXT: call void @use32(i32 [[NOT]])1953; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[NOT]], -41954; CHECK-NEXT: ret i32 [[MUL]]1955;1956 %not = xor i32 %a0, -11957 call void @use32(i32 %not)1958 %mul = mul i32 %not, -41959 ret i32 %mul1960}1961 1962define i32 @zext_negpow2(i8 %x) {1963; CHECK-LABEL: @zext_negpow2(1964; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]1965; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext i8 [[X_NEG]] to i321966; CHECK-NEXT: [[R:%.*]] = shl nuw i32 [[X_NEG_Z]], 241967; CHECK-NEXT: ret i32 [[R]]1968;1969 %zx = zext i8 %x to i321970 %r = mul i32 %zx, -16777216 ; -1 << 241971 ret i32 %r1972}1973 1974; splat constant1975 1976define <2 x i14> @zext_negpow2_vec(<2 x i5> %x) {1977; CHECK-LABEL: @zext_negpow2_vec(1978; CHECK-NEXT: [[X_NEG:%.*]] = sub <2 x i5> zeroinitializer, [[X:%.*]]1979; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext <2 x i5> [[X_NEG]] to <2 x i14>1980; CHECK-NEXT: [[R:%.*]] = shl <2 x i14> [[X_NEG_Z]], splat (i14 11)1981; CHECK-NEXT: ret <2 x i14> [[R]]1982;1983 %zx = zext <2 x i5> %x to <2 x i14>1984 %r = mul <2 x i14> %zx, <i14 -2048, i14 -2048> ; -1 << 111985 ret <2 x i14> %r1986}1987 1988; negative test - mul must be big enough to cover bitwidth diff1989 1990define i32 @zext_negpow2_too_small(i8 %x) {1991; CHECK-LABEL: @zext_negpow2_too_small(1992; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i321993; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[ZX]], -83886081994; CHECK-NEXT: ret i32 [[R]]1995;1996 %zx = zext i8 %x to i321997 %r = mul i32 %zx, -8388608 ; -1 << 231998 ret i32 %r1999}2000 2001define i16 @sext_negpow2(i9 %x) {2002; CHECK-LABEL: @sext_negpow2(2003; CHECK-NEXT: [[X_NEG:%.*]] = sub i9 0, [[X:%.*]]2004; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext i9 [[X_NEG]] to i162005; CHECK-NEXT: [[R:%.*]] = shl i16 [[X_NEG_Z]], 102006; CHECK-NEXT: ret i16 [[R]]2007;2008 %sx = sext i9 %x to i162009 %r = mul i16 %sx, -1024 ; -1 << 102010 ret i16 %r2011}2012 2013; splat constant with poison element(s)2014 2015define <2 x i16> @sext_negpow2_vec(<2 x i8> %x) {2016; CHECK-LABEL: @sext_negpow2_vec(2017; CHECK-NEXT: [[X_NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]]2018; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext <2 x i8> [[X_NEG]] to <2 x i16>2019; CHECK-NEXT: [[R:%.*]] = shl nuw <2 x i16> [[X_NEG_Z]], splat (i16 8)2020; CHECK-NEXT: ret <2 x i16> [[R]]2021;2022 %sx = sext <2 x i8> %x to <2 x i16>2023 %r = mul <2 x i16> %sx, <i16 -256, i16 poison> ; -1 << 82024 ret <2 x i16> %r2025}2026 2027; negative test - mul must be big enough to cover bitwidth diff2028 2029define <2 x i16> @sext_negpow2_too_small_vec(<2 x i8> %x) {2030; CHECK-LABEL: @sext_negpow2_too_small_vec(2031; CHECK-NEXT: [[SX:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i16>2032; CHECK-NEXT: [[R:%.*]] = mul nsw <2 x i16> [[SX]], <i16 -128, i16 poison>2033; CHECK-NEXT: ret <2 x i16> [[R]]2034;2035 %sx = sext <2 x i8> %x to <2 x i16>2036 %r = mul <2 x i16> %sx, <i16 -128, i16 poison> ; -1 << 72037 ret <2 x i16> %r2038}2039 2040; negative test - too many uses2041 2042define i32 @zext_negpow2_use(i8 %x) {2043; CHECK-LABEL: @zext_negpow2_use(2044; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i322045; CHECK-NEXT: call void @use32(i32 [[ZX]])2046; CHECK-NEXT: [[R:%.*]] = mul i32 [[ZX]], -167772162047; CHECK-NEXT: ret i32 [[R]]2048;2049 %zx = zext i8 %x to i322050 call void @use32(i32 %zx)2051 %r = mul i32 %zx, -16777216 ; -1 << 242052 ret i32 %r2053}2054 2055define i32 @mul_sext_icmp_with_zero(i32 %x) {2056; CHECK-LABEL: @mul_sext_icmp_with_zero(2057; CHECK-NEXT: ret i32 02058;2059 %cmp = icmp eq i32 %x, 02060 %sext = sext i1 %cmp to i322061 %mul = mul i32 %sext, %x2062 ret i32 %mul2063}2064 2065define i32 @test_mul_sext_bool(i1 %x, i32 %y) {2066; CHECK-LABEL: @test_mul_sext_bool(2067; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]2068; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 02069; CHECK-NEXT: ret i32 [[MUL]]2070;2071 %sext = sext i1 %x to i322072 %mul = mul i32 %sext, %y2073 ret i32 %mul2074}2075 2076define i32 @test_mul_sext_bool_nuw(i1 %x, i32 %y) {2077; CHECK-LABEL: @test_mul_sext_bool_nuw(2078; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]]2079; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 02080; CHECK-NEXT: ret i32 [[MUL]]2081;2082 %sext = sext i1 %x to i322083 %mul = mul nuw i32 %sext, %y2084 ret i32 %mul2085}2086 2087define i32 @test_mul_sext_bool_nsw(i1 %x, i32 %y) {2088; CHECK-LABEL: @test_mul_sext_bool_nsw(2089; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[Y:%.*]]2090; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 02091; CHECK-NEXT: ret i32 [[MUL]]2092;2093 %sext = sext i1 %x to i322094 %mul = mul nsw i32 %sext, %y2095 ret i32 %mul2096}2097 2098define i32 @test_mul_sext_bool_nuw_nsw(i1 %x, i32 %y) {2099; CHECK-LABEL: @test_mul_sext_bool_nuw_nsw(2100; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[Y:%.*]]2101; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 02102; CHECK-NEXT: ret i32 [[MUL]]2103;2104 %sext = sext i1 %x to i322105 %mul = mul nuw nsw i32 %sext, %y2106 ret i32 %mul2107}2108 2109define i32 @test_mul_sext_bool_commuted(i1 %x, i32 %y) {2110; CHECK-LABEL: @test_mul_sext_bool_commuted(2111; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[Y:%.*]], -22112; CHECK-NEXT: [[YY_NEG:%.*]] = add i32 [[TMP1]], 12113; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[YY_NEG]], i32 02114; CHECK-NEXT: ret i32 [[MUL]]2115;2116 %yy = xor i32 %y, 12117 %sext = sext i1 %x to i322118 %mul = mul i32 %yy, %sext2119 ret i32 %mul2120}2121 2122define i32 @test_mul_sext_nonbool(i2 %x, i32 %y) {2123; CHECK-LABEL: @test_mul_sext_nonbool(2124; CHECK-NEXT: [[SEXT:%.*]] = sext i2 [[X:%.*]] to i322125; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[SEXT]]2126; CHECK-NEXT: ret i32 [[MUL]]2127;2128 %sext = sext i2 %x to i322129 %mul = mul i32 %sext, %y2130 ret i32 %mul2131}2132 2133define i32 @test_mul_sext_multiuse(i1 %x, i32 %y) {2134; CHECK-LABEL: @test_mul_sext_multiuse(2135; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i322136; CHECK-NEXT: tail call void @use(i32 [[SEXT]])2137; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[SEXT]]2138; CHECK-NEXT: ret i32 [[MUL]]2139;2140 %sext = sext i1 %x to i322141 tail call void @use(i32 %sext)2142 %mul = mul i32 %sext, %y2143 ret i32 %mul2144}2145 2146define i8 @mul_nsw_nonneg(i8 %x, i8 %y) {2147; CHECK-LABEL: @mul_nsw_nonneg(2148; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -12149; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]])2150; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -12151; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]])2152; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i8 [[X]], [[Y]]2153; CHECK-NEXT: ret i8 [[MUL]]2154;2155 %x.nneg = icmp sge i8 %x, 02156 call void @llvm.assume(i1 %x.nneg)2157 %y.nneg = icmp sge i8 %y, 02158 call void @llvm.assume(i1 %y.nneg)2159 %mul = mul nsw i8 %x, %y2160 ret i8 %mul2161}2162 2163define i8 @mul_nsw_not_nonneg1(i8 %x, i8 %y) {2164; CHECK-LABEL: @mul_nsw_not_nonneg1(2165; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -12166; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]])2167; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[X:%.*]], [[Y]]2168; CHECK-NEXT: ret i8 [[MUL]]2169;2170 %y.nneg = icmp sge i8 %y, 02171 call void @llvm.assume(i1 %y.nneg)2172 %mul = mul nsw i8 %x, %y2173 ret i8 %mul2174}2175 2176define i8 @mul_nsw_not_nonneg2(i8 %x, i8 %y) {2177; CHECK-LABEL: @mul_nsw_not_nonneg2(2178; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -12179; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]])2180; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[X]], [[Y:%.*]]2181; CHECK-NEXT: ret i8 [[MUL]]2182;2183 %x.nneg = icmp sge i8 %x, 02184 call void @llvm.assume(i1 %x.nneg)2185 %mul = mul nsw i8 %x, %y2186 ret i8 %mul2187}2188 2189define i8 @mul_not_nsw_nonneg(i8 %x, i8 %y) {2190; CHECK-LABEL: @mul_not_nsw_nonneg(2191; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -12192; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]])2193; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -12194; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]])2195; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[X]], [[Y]]2196; CHECK-NEXT: ret i8 [[MUL]]2197;2198 %x.nneg = icmp sge i8 %x, 02199 call void @llvm.assume(i1 %x.nneg)2200 %y.nneg = icmp sge i8 %y, 02201 call void @llvm.assume(i1 %y.nneg)2202 %mul = mul i8 %x, %y2203 ret i8 %mul2204}2205