742 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4declare i8 @use8(i8)5declare i16 @use16(i16)6declare i32 @use32(i32)7declare i64 @use64(i64)8declare i128 @use128(i128)9declare i130 @use130(i130)10declare <2 x i8> @use_v2i8(<2 x i8>)11 12; The following 16 cases are used for cover the commuted operand ADD and MUL13; with extra uses to more of these tests to exercise those cases.14; The different _Ax suffix hints the variety of combinations MUL15; The different _Bx suffix hints the variety of combinations ADD16; 4 tests that use in0/in1 with different commutes17define i8 @mul8_low_A0_B0(i8 %in0, i8 %in1) {18; CHECK-LABEL: @mul8_low_A0_B0(19; CHECK-NEXT: [[RETLO:%.*]] = mul i8 [[IN0:%.*]], [[IN1:%.*]]20; CHECK-NEXT: ret i8 [[RETLO]]21;22 %In0Lo = and i8 %in0, 1523 %In0Hi = lshr i8 %in0, 424 %In1Lo = and i8 %in1, 1525 %In1Hi = lshr i8 %in1, 426 %m10 = mul i8 %In1Hi, %in027 %m01 = mul i8 %In0Hi, %in128 %m00 = mul i8 %In1Lo, %In0Lo29 %addc = add i8 %m10, %m0130 %shl = shl i8 %addc, 431 %retLo = add i8 %shl, %m0032 ret i8 %retLo33}34 35define i8 @mul8_low_A0_B1(i8 %p, i8 %in1) {36; CHECK-LABEL: @mul8_low_A0_B1(37; CHECK-NEXT: [[IN0:%.*]] = call i8 @use8(i8 [[P:%.*]])38; CHECK-NEXT: [[RETLO:%.*]] = mul i8 [[IN0]], [[IN1:%.*]]39; CHECK-NEXT: ret i8 [[RETLO]]40;41 %in0 = call i8 @use8(i8 %p) ; thwart complexity-based canonicalization42 %In0Lo = and i8 %in0, 1543 %In0Hi = lshr i8 %in0, 444 %In1Lo = and i8 %in1, 1545 %In1Hi = lshr i8 %in1, 446 %m10 = mul i8 %in0, %In1Hi47 %m01 = mul i8 %In0Hi, %in148 %m00 = mul i8 %In1Lo, %In0Lo49 %addc = add i8 %m10, %m0150 %shl = shl i8 %addc, 451 %retLo = add i8 %m00, %shl52 ret i8 %retLo53}54 55define i8 @mul8_low_A0_B2(i8 %in0, i8 %p) {56; CHECK-LABEL: @mul8_low_A0_B2(57; CHECK-NEXT: [[IN1:%.*]] = call i8 @use8(i8 [[P:%.*]])58; CHECK-NEXT: [[RETLO:%.*]] = mul i8 [[IN0:%.*]], [[IN1]]59; CHECK-NEXT: ret i8 [[RETLO]]60;61 62 %in1 = call i8 @use8(i8 %p) ; thwart complexity-based canonicalization63 %In0Lo = and i8 %in0, 1564 %In0Hi = lshr i8 %in0, 465 %In1Lo = and i8 %in1, 1566 %In1Hi = lshr i8 %in1, 467 %m10 = mul i8 %In1Hi, %in068 %m01 = mul i8 %in1, %In0Hi69 %m00 = mul i8 %In1Lo, %In0Lo70 %addc = add i8 %m01, %m1071 %shl = shl i8 %addc, 472 %retLo = add i8 %shl, %m0073 ret i8 %retLo74}75 76define i8 @mul8_low_A0_B3(i8 %p, i8 %q) {77; CHECK-LABEL: @mul8_low_A0_B3(78; CHECK-NEXT: [[IN0:%.*]] = call i8 @use8(i8 [[P:%.*]])79; CHECK-NEXT: [[IN1:%.*]] = call i8 @use8(i8 [[Q:%.*]])80; CHECK-NEXT: [[RETLO:%.*]] = mul i8 [[IN0]], [[IN1]]81; CHECK-NEXT: ret i8 [[RETLO]]82;83 %in0 = call i8 @use8(i8 %p) ; thwart complexity-based canonicalization84 %in1 = call i8 @use8(i8 %q) ; thwart complexity-based canonicalization85 %In0Lo = and i8 %in0, 1586 %In0Hi = lshr i8 %in0, 487 %In1Lo = and i8 %in1, 1588 %In1Hi = lshr i8 %in1, 489 %m10 = mul i8 %in0, %In1Hi90 %m01 = mul i8 %in1, %In0Hi91 %m00 = mul i8 %In1Lo, %In0Lo92 %addc = add i8 %m01, %m1093 %shl = shl i8 %addc, 494 %retLo = add i8 %m00, %shl95 ret i8 %retLo96}97 98; 4 tests that use In0Lo/In1Lo with different commutes99define i16 @mul16_low_A1_B0(i16 %in0, i16 %in1) {100; CHECK-LABEL: @mul16_low_A1_B0(101; CHECK-NEXT: [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255102; CHECK-NEXT: [[IN0HI:%.*]] = lshr i16 [[IN0]], 8103; CHECK-NEXT: [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255104; CHECK-NEXT: [[IN1HI:%.*]] = lshr i16 [[IN1]], 8105; CHECK-NEXT: [[M10:%.*]] = mul nuw i16 [[IN0LO]], [[IN1HI]]106; CHECK-NEXT: call void @use16(i16 [[M10]])107; CHECK-NEXT: [[M01:%.*]] = mul nuw i16 [[IN1LO]], [[IN0HI]]108; CHECK-NEXT: call void @use16(i16 [[M01]])109; CHECK-NEXT: [[RETLO:%.*]] = mul i16 [[IN0]], [[IN1]]110; CHECK-NEXT: ret i16 [[RETLO]]111;112 %In0Lo = and i16 %in0, 255113 %In0Hi = lshr i16 %in0, 8114 %In1Lo = and i16 %in1, 255115 %In1Hi = lshr i16 %in1, 8116 %m10 = mul i16 %In0Lo, %In1Hi117 call void @use16(i16 %m10)118 %m01 = mul i16 %In1Lo, %In0Hi119 call void @use16(i16 %m01)120 %m00 = mul i16 %In1Lo, %In0Lo121 %addc = add i16 %m10, %m01122 %shl = shl i16 %addc, 8123 %retLo = add i16 %shl, %m00124 ret i16 %retLo125}126 127define i16 @mul16_low_A1_B1(i16 %in0, i16 %in1) {128; CHECK-LABEL: @mul16_low_A1_B1(129; CHECK-NEXT: [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255130; CHECK-NEXT: [[IN0HI:%.*]] = lshr i16 [[IN0]], 8131; CHECK-NEXT: [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255132; CHECK-NEXT: [[IN1HI:%.*]] = lshr i16 [[IN1]], 8133; CHECK-NEXT: [[M10:%.*]] = mul nuw i16 [[IN0LO]], [[IN1HI]]134; CHECK-NEXT: call void @use16(i16 [[M10]])135; CHECK-NEXT: [[M01:%.*]] = mul nuw i16 [[IN0HI]], [[IN1LO]]136; CHECK-NEXT: call void @use16(i16 [[M01]])137; CHECK-NEXT: [[RETLO:%.*]] = mul i16 [[IN0]], [[IN1]]138; CHECK-NEXT: ret i16 [[RETLO]]139;140 %In0Lo = and i16 %in0, 255141 %In0Hi = lshr i16 %in0, 8142 %In1Lo = and i16 %in1, 255143 %In1Hi = lshr i16 %in1, 8144 %m10 = mul i16 %In0Lo, %In1Hi145 call void @use16(i16 %m10)146 %m01 = mul i16 %In0Hi, %In1Lo147 call void @use16(i16 %m01)148 %m00 = mul i16 %In1Lo, %In0Lo149 %addc = add i16 %m10, %m01150 %shl = shl i16 %addc, 8151 %retLo = add i16 %m00, %shl152 ret i16 %retLo153}154 155define i16 @mul16_low_A1_B2(i16 %in0, i16 %in1) {156; CHECK-LABEL: @mul16_low_A1_B2(157; CHECK-NEXT: [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255158; CHECK-NEXT: [[IN0HI:%.*]] = lshr i16 [[IN0]], 8159; CHECK-NEXT: [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255160; CHECK-NEXT: [[IN1HI:%.*]] = lshr i16 [[IN1]], 8161; CHECK-NEXT: [[M10:%.*]] = mul nuw i16 [[IN1HI]], [[IN0LO]]162; CHECK-NEXT: call void @use16(i16 [[M10]])163; CHECK-NEXT: [[M01:%.*]] = mul nuw i16 [[IN1LO]], [[IN0HI]]164; CHECK-NEXT: call void @use16(i16 [[M01]])165; CHECK-NEXT: [[RETLO:%.*]] = mul i16 [[IN0]], [[IN1]]166; CHECK-NEXT: ret i16 [[RETLO]]167;168 %In0Lo = and i16 %in0, 255169 %In0Hi = lshr i16 %in0, 8170 %In1Lo = and i16 %in1, 255171 %In1Hi = lshr i16 %in1, 8172 %m10 = mul i16 %In1Hi, %In0Lo173 call void @use16(i16 %m10)174 %m01 = mul i16 %In1Lo, %In0Hi175 call void @use16(i16 %m01)176 %m00 = mul i16 %In1Lo, %In0Lo177 %addc = add i16 %m01, %m10178 %shl = shl i16 %addc, 8179 %retLo = add i16 %shl, %m00180 ret i16 %retLo181}182 183define i16 @mul16_low_A1_B3(i16 %in0, i16 %in1) {184; CHECK-LABEL: @mul16_low_A1_B3(185; CHECK-NEXT: [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255186; CHECK-NEXT: [[IN0HI:%.*]] = lshr i16 [[IN0]], 8187; CHECK-NEXT: [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255188; CHECK-NEXT: [[IN1HI:%.*]] = lshr i16 [[IN1]], 8189; CHECK-NEXT: [[M10:%.*]] = mul nuw i16 [[IN0LO]], [[IN1HI]]190; CHECK-NEXT: call void @use16(i16 [[M10]])191; CHECK-NEXT: [[M01:%.*]] = mul nuw i16 [[IN1LO]], [[IN0HI]]192; CHECK-NEXT: call void @use16(i16 [[M01]])193; CHECK-NEXT: [[RETLO:%.*]] = mul i16 [[IN0]], [[IN1]]194; CHECK-NEXT: ret i16 [[RETLO]]195;196 %In0Lo = and i16 %in0, 255197 %In0Hi = lshr i16 %in0, 8198 %In1Lo = and i16 %in1, 255199 %In1Hi = lshr i16 %in1, 8200 %m10 = mul i16 %In0Lo, %In1Hi201 call void @use16(i16 %m10)202 %m01 = mul i16 %In1Lo, %In0Hi203 call void @use16(i16 %m01)204 %m00 = mul i16 %In1Lo, %In0Lo205 %addc = add i16 %m01, %m10206 %shl = shl i16 %addc, 8207 %retLo = add i16 %m00, %shl208 ret i16 %retLo209}210 211; 4 tests that use In0Lo/in1 with different commutes212define i32 @mul32_low_A2_B0(i32 %in0, i32 %in1) {213; CHECK-LABEL: @mul32_low_A2_B0(214; CHECK-NEXT: [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535215; CHECK-NEXT: [[IN1HI:%.*]] = lshr i32 [[IN1:%.*]], 16216; CHECK-NEXT: [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]217; CHECK-NEXT: call void @use32(i32 [[M10]])218; CHECK-NEXT: [[RETLO:%.*]] = mul i32 [[IN0]], [[IN1]]219; CHECK-NEXT: ret i32 [[RETLO]]220;221 %In0Lo = and i32 %in0, 65535222 %In0Hi = lshr i32 %in0, 16223 %In1Lo = and i32 %in1, 65535224 %In1Hi = lshr i32 %in1, 16225 %m10 = mul i32 %In1Hi, %In0Lo226 call void @use32(i32 %m10)227 %m01 = mul i32 %In0Hi, %in1228 %m00 = mul i32 %In1Lo, %In0Lo229 %addc = add i32 %m10, %m01230 %shl = shl i32 %addc, 16231 %retLo = add i32 %shl, %m00232 ret i32 %retLo233}234 235define i32 @mul32_low_A2_B1(i32 %in0, i32 %in1) {236; CHECK-LABEL: @mul32_low_A2_B1(237; CHECK-NEXT: [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535238; CHECK-NEXT: [[IN1HI:%.*]] = lshr i32 [[IN1:%.*]], 16239; CHECK-NEXT: [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]240; CHECK-NEXT: call void @use32(i32 [[M10]])241; CHECK-NEXT: [[RETLO:%.*]] = mul i32 [[IN0]], [[IN1]]242; CHECK-NEXT: ret i32 [[RETLO]]243;244 %In0Lo = and i32 %in0, 65535245 %In0Hi = lshr i32 %in0, 16246 %In1Lo = and i32 %in1, 65535247 %In1Hi = lshr i32 %in1, 16248 %m10 = mul i32 %In1Hi, %In0Lo249 call void @use32(i32 %m10)250 %m01 = mul i32 %In0Hi, %in1251 %m00 = mul i32 %In1Lo, %In0Lo252 %addc = add i32 %m10, %m01253 %shl = shl i32 %addc, 16254 %retLo = add i32 %m00, %shl255 ret i32 %retLo256}257 258define i32 @mul32_low_A2_B2(i32 %in0, i32 %p) {259; CHECK-LABEL: @mul32_low_A2_B2(260; CHECK-NEXT: [[IN1:%.*]] = call i32 @use32(i32 [[P:%.*]])261; CHECK-NEXT: [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535262; CHECK-NEXT: [[IN1HI:%.*]] = lshr i32 [[IN1]], 16263; CHECK-NEXT: [[M10:%.*]] = mul nuw i32 [[IN0LO]], [[IN1HI]]264; CHECK-NEXT: call void @use32(i32 [[M10]])265; CHECK-NEXT: [[RETLO:%.*]] = mul i32 [[IN0]], [[IN1]]266; CHECK-NEXT: ret i32 [[RETLO]]267;268 %in1 = call i32 @use32(i32 %p) ; thwart complexity-based canonicalization269 %In0Lo = and i32 %in0, 65535270 %In0Hi = lshr i32 %in0, 16271 %In1Lo = and i32 %in1, 65535272 %In1Hi = lshr i32 %in1, 16273 %m10 = mul i32 %In0Lo, %In1Hi274 call void @use32(i32 %m10)275 %m01 = mul i32 %in1, %In0Hi276 %m00 = mul i32 %In1Lo, %In0Lo277 %addc = add i32 %m01, %m10278 %shl = shl i32 %addc, 16279 %retLo = add i32 %shl, %m00280 ret i32 %retLo281}282 283define i32 @mul32_low_A2_B3(i32 %in0, i32 %p) {284; CHECK-LABEL: @mul32_low_A2_B3(285; CHECK-NEXT: [[IN1:%.*]] = call i32 @use32(i32 [[P:%.*]])286; CHECK-NEXT: [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535287; CHECK-NEXT: [[IN1HI:%.*]] = lshr i32 [[IN1]], 16288; CHECK-NEXT: [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]289; CHECK-NEXT: call void @use32(i32 [[M10]])290; CHECK-NEXT: [[RETLO:%.*]] = mul i32 [[IN0]], [[IN1]]291; CHECK-NEXT: ret i32 [[RETLO]]292;293 %in1 = call i32 @use32(i32 %p) ; thwart complexity-based canonicalization294 %In0Lo = and i32 %in0, 65535295 %In0Hi = lshr i32 %in0, 16296 %In1Lo = and i32 %in1, 65535297 %In1Hi = lshr i32 %in1, 16298 %m10 = mul i32 %In1Hi, %In0Lo299 call void @use32(i32 %m10)300 %m01 = mul i32 %in1, %In0Hi301 %m00 = mul i32 %In1Lo, %In0Lo302 %addc = add i32 %m01, %m10303 %shl = shl i32 %addc, 16304 %retLo = add i32 %m00, %shl305 ret i32 %retLo306}307 308; 4 tests that use in0/In1Lo with different commutes309define i64 @mul64_low_A3_B0(i64 %in0, i64 %in1) {310; CHECK-LABEL: @mul64_low_A3_B0(311; CHECK-NEXT: [[IN0HI:%.*]] = lshr i64 [[IN0:%.*]], 32312; CHECK-NEXT: [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295313; CHECK-NEXT: [[M01:%.*]] = mul nuw i64 [[IN0HI]], [[IN1LO]]314; CHECK-NEXT: call void @use64(i64 [[M01]])315; CHECK-NEXT: [[RETLO:%.*]] = mul i64 [[IN0]], [[IN1]]316; CHECK-NEXT: ret i64 [[RETLO]]317;318 %In0Lo = and i64 %in0, 4294967295319 %In0Hi = lshr i64 %in0, 32320 %In1Lo = and i64 %in1, 4294967295321 %In1Hi = lshr i64 %in1, 32322 %m10 = mul i64 %In1Hi, %in0323 %m01 = mul i64 %In0Hi, %In1Lo324 call void @use64(i64 %m01)325 %m00 = mul i64 %In1Lo, %In0Lo326 %addc = add i64 %m10, %m01327 %shl = shl i64 %addc, 32328 %retLo = add i64 %shl, %m00329 ret i64 %retLo330}331 332define i64 @mul64_low_A3_B1(i64 %in0, i64 %in1) {333; CHECK-LABEL: @mul64_low_A3_B1(334; CHECK-NEXT: [[IN0HI:%.*]] = lshr i64 [[IN0:%.*]], 32335; CHECK-NEXT: [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295336; CHECK-NEXT: [[M01:%.*]] = mul nuw i64 [[IN0HI]], [[IN1LO]]337; CHECK-NEXT: call void @use64(i64 [[M01]])338; CHECK-NEXT: [[RETLO:%.*]] = mul i64 [[IN0]], [[IN1]]339; CHECK-NEXT: ret i64 [[RETLO]]340;341 %In0Lo = and i64 %in0, 4294967295342 %In0Hi = lshr i64 %in0, 32343 %In1Lo = and i64 %in1, 4294967295344 %In1Hi = lshr i64 %in1, 32345 %m10 = mul i64 %In1Hi, %in0346 %m01 = mul i64 %In0Hi, %In1Lo347 call void @use64(i64 %m01)348 %m00 = mul i64 %In1Lo, %In0Lo349 %addc = add i64 %m10, %m01350 %shl = shl i64 %addc, 32351 %retLo = add i64 %m00, %shl352 ret i64 %retLo353}354 355define i64 @mul64_low_A3_B2(i64 %p, i64 %in1) {356; CHECK-LABEL: @mul64_low_A3_B2(357; CHECK-NEXT: [[IN0:%.*]] = call i64 @use64(i64 [[P:%.*]])358; CHECK-NEXT: [[IN0HI:%.*]] = lshr i64 [[IN0]], 32359; CHECK-NEXT: [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295360; CHECK-NEXT: [[M01:%.*]] = mul nuw i64 [[IN0HI]], [[IN1LO]]361; CHECK-NEXT: call void @use64(i64 [[M01]])362; CHECK-NEXT: [[RETLO:%.*]] = mul i64 [[IN0]], [[IN1]]363; CHECK-NEXT: ret i64 [[RETLO]]364;365 %in0 = call i64 @use64(i64 %p) ; thwart complexity-based canonicalization366 %In0Lo = and i64 %in0, 4294967295367 %In0Hi = lshr i64 %in0, 32368 %In1Lo = and i64 %in1, 4294967295369 %In1Hi = lshr i64 %in1, 32370 %m10 = mul i64 %in0, %In1Hi371 %m01 = mul i64 %In0Hi, %In1Lo372 call void @use64(i64 %m01)373 %m00 = mul i64 %In1Lo, %In0Lo374 %addc = add i64 %m01, %m10375 %shl = shl i64 %addc, 32376 %retLo = add i64 %shl, %m00377 ret i64 %retLo378}379 380define i64 @mul64_low_A3_B3(i64 %p, i64 %in1) {381; CHECK-LABEL: @mul64_low_A3_B3(382; CHECK-NEXT: [[IN0:%.*]] = call i64 @use64(i64 [[P:%.*]])383; CHECK-NEXT: [[IN0HI:%.*]] = lshr i64 [[IN0]], 32384; CHECK-NEXT: [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295385; CHECK-NEXT: [[M01:%.*]] = mul nuw i64 [[IN1LO]], [[IN0HI]]386; CHECK-NEXT: call void @use64(i64 [[M01]])387; CHECK-NEXT: [[RETLO:%.*]] = mul i64 [[IN0]], [[IN1]]388; CHECK-NEXT: ret i64 [[RETLO]]389;390 %in0 = call i64 @use64(i64 %p) ; thwart complexity-based canonicalization391 %In0Lo = and i64 %in0, 4294967295392 %In0Hi = lshr i64 %in0, 32393 %In1Lo = and i64 %in1, 4294967295394 %In1Hi = lshr i64 %in1, 32395 %m10 = mul i64 %in0, %In1Hi396 %m01 = mul i64 %In1Lo, %In0Hi397 call void @use64(i64 %m01)398 %m00 = mul i64 %In1Lo, %In0Lo399 %addc = add i64 %m01, %m10400 %shl = shl i64 %addc, 32401 %retLo = add i64 %m00, %shl402 ret i64 %retLo403}404 405define i32 @mul32_low_one_extra_user(i32 %in0, i32 %in1) {406; CHECK-LABEL: @mul32_low_one_extra_user(407; CHECK-NEXT: [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535408; CHECK-NEXT: [[IN0HI:%.*]] = lshr i32 [[IN0]], 16409; CHECK-NEXT: [[IN1LO:%.*]] = and i32 [[IN1:%.*]], 65535410; CHECK-NEXT: [[IN1HI:%.*]] = lshr i32 [[IN1]], 16411; CHECK-NEXT: [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]412; CHECK-NEXT: [[M01:%.*]] = mul nuw i32 [[IN1LO]], [[IN0HI]]413; CHECK-NEXT: [[ADDC:%.*]] = add i32 [[M10]], [[M01]]414; CHECK-NEXT: call void @use32(i32 [[ADDC]])415; CHECK-NEXT: [[RETLO:%.*]] = mul i32 [[IN0]], [[IN1]]416; CHECK-NEXT: ret i32 [[RETLO]]417;418 %In0Lo = and i32 %in0, 65535419 %In0Hi = lshr i32 %in0, 16420 %In1Lo = and i32 %in1, 65535421 %In1Hi = lshr i32 %in1, 16422 %m10 = mul i32 %In1Hi, %In0Lo423 %m01 = mul i32 %In1Lo, %In0Hi424 %m00 = mul i32 %In1Lo, %In0Lo425 %addc = add i32 %m10, %m01426 call void @use32(i32 %addc)427 %shl = shl i32 %addc, 16428 %retLo = add i32 %shl, %m00429 ret i32 %retLo430}431 432; The following are variety types of target cases433; https://alive2.llvm.org/ce/z/2BqKLt434define i8 @mul8_low(i8 %in0, i8 %in1) {435; CHECK-LABEL: @mul8_low(436; CHECK-NEXT: [[RETLO:%.*]] = mul i8 [[IN0:%.*]], [[IN1:%.*]]437; CHECK-NEXT: ret i8 [[RETLO]]438;439 %In0Lo = and i8 %in0, 15440 %In0Hi = lshr i8 %in0, 4441 %In1Lo = and i8 %in1, 15442 %In1Hi = lshr i8 %in1, 4443 %m10 = mul i8 %In1Hi, %In0Lo444 %m01 = mul i8 %In1Lo, %In0Hi445 %m00 = mul i8 %In1Lo, %In0Lo446 %addc = add i8 %m10, %m01447 %shl = shl i8 %addc, 4448 %retLo = add i8 %shl, %m00449 ret i8 %retLo450}451 452define i16 @mul16_low(i16 %in0, i16 %in1) {453; CHECK-LABEL: @mul16_low(454; CHECK-NEXT: [[RETLO:%.*]] = mul i16 [[IN0:%.*]], [[IN1:%.*]]455; CHECK-NEXT: ret i16 [[RETLO]]456;457 %In0Lo = and i16 %in0, 255458 %In0Hi = lshr i16 %in0, 8459 %In1Lo = and i16 %in1, 255460 %In1Hi = lshr i16 %in1, 8461 %m10 = mul i16 %In1Hi, %In0Lo462 %m01 = mul i16 %In1Lo, %In0Hi463 %m00 = mul i16 %In1Lo, %In0Lo464 %addc = add i16 %m10, %m01465 %shl = shl i16 %addc, 8466 %retLo = add i16 %shl, %m00467 ret i16 %retLo468}469 470define i32 @mul32_low(i32 %in0, i32 %in1) {471; CHECK-LABEL: @mul32_low(472; CHECK-NEXT: [[RETLO:%.*]] = mul i32 [[IN0:%.*]], [[IN1:%.*]]473; CHECK-NEXT: ret i32 [[RETLO]]474;475 %In0Lo = and i32 %in0, 65535476 %In0Hi = lshr i32 %in0, 16477 %In1Lo = and i32 %in1, 65535478 %In1Hi = lshr i32 %in1, 16479 %m10 = mul i32 %In1Hi, %In0Lo480 %m01 = mul i32 %In1Lo, %In0Hi481 %m00 = mul i32 %In1Lo, %In0Lo482 %addc = add i32 %m10, %m01483 %shl = shl i32 %addc, 16484 %retLo = add i32 %shl, %m00485 ret i32 %retLo486}487 488define i64 @mul64_low(i64 %in0, i64 %in1) {489; CHECK-LABEL: @mul64_low(490; CHECK-NEXT: [[RETLO:%.*]] = mul i64 [[IN0:%.*]], [[IN1:%.*]]491; CHECK-NEXT: ret i64 [[RETLO]]492;493 %In0Lo = and i64 %in0, 4294967295494 %In0Hi = lshr i64 %in0, 32495 %In1Lo = and i64 %in1, 4294967295496 %In1Hi = lshr i64 %in1, 32497 %m10 = mul i64 %In1Hi, %In0Lo498 %m01 = mul i64 %In1Lo, %In0Hi499 %m00 = mul i64 %In1Lo, %In0Lo500 %addc = add i64 %m10, %m01501 %shl = shl i64 %addc, 32502 %retLo = add i64 %shl, %m00503 ret i64 %retLo504}505 506define i128 @mul128_low(i128 %in0, i128 %in1) {507; CHECK-LABEL: @mul128_low(508; CHECK-NEXT: [[RETLO:%.*]] = mul i128 [[IN0:%.*]], [[IN1:%.*]]509; CHECK-NEXT: ret i128 [[RETLO]]510;511 %In0Lo = and i128 %in0, 18446744073709551615512 %In0Hi = lshr i128 %in0, 64513 %In1Lo = and i128 %in1, 18446744073709551615514 %In1Hi = lshr i128 %in1, 64515 %m10 = mul i128 %In1Hi, %In0Lo516 %m01 = mul i128 %In1Lo, %In0Hi517 %m00 = mul i128 %In1Lo, %In0Lo518 %addc = add i128 %m10, %m01519 %shl = shl i128 %addc, 64520 %retLo = add i128 %shl, %m00521 ret i128 %retLo522}523 524; Support vector type525define <2 x i8> @mul_v2i8_low(<2 x i8> %in0, <2 x i8> %in1) {526; CHECK-LABEL: @mul_v2i8_low(527; CHECK-NEXT: [[RETLO:%.*]] = mul <2 x i8> [[IN0:%.*]], [[IN1:%.*]]528; CHECK-NEXT: ret <2 x i8> [[RETLO]]529;530 %In0Lo = and <2 x i8> %in0, <i8 15, i8 15>531 %In0Hi = lshr <2 x i8> %in0, <i8 4, i8 4>532 %In1Lo = and <2 x i8> %in1, <i8 15, i8 15>533 %In1Hi = lshr <2 x i8> %in1, <i8 4, i8 4>534 %m10 = mul <2 x i8> %In1Hi, %In0Lo535 %m01 = mul <2 x i8> %In1Lo, %In0Hi536 %m00 = mul <2 x i8> %In1Lo, %In0Lo537 %addc = add <2 x i8> %m10, %m01538 %shl = shl <2 x i8> %addc, <i8 4, i8 4>539 %retLo = add <2 x i8> %shl, %m00540 ret <2 x i8> %retLo541}542 543define <2 x i8> @mul_v2i8_low_one_extra_user(<2 x i8> %in0, <2 x i8> %in1) {544; CHECK-LABEL: @mul_v2i8_low_one_extra_user(545; CHECK-NEXT: [[IN0HI:%.*]] = lshr <2 x i8> [[IN0:%.*]], splat (i8 4)546; CHECK-NEXT: [[IN1LO:%.*]] = and <2 x i8> [[IN1:%.*]], splat (i8 15)547; CHECK-NEXT: [[M01:%.*]] = mul nuw <2 x i8> [[IN1LO]], [[IN0HI]]548; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[M01]])549; CHECK-NEXT: [[RETLO:%.*]] = mul <2 x i8> [[IN0]], [[IN1]]550; CHECK-NEXT: ret <2 x i8> [[RETLO]]551;552 %In0Lo = and <2 x i8> %in0, <i8 15, i8 15>553 %In0Hi = lshr <2 x i8> %in0, <i8 4, i8 4>554 %In1Lo = and <2 x i8> %in1, <i8 15, i8 15>555 %In1Hi = lshr <2 x i8> %in1, <i8 4, i8 4>556 %m10 = mul <2 x i8> %In1Hi, %In0Lo557 %m01 = mul <2 x i8> %In1Lo, %In0Hi558 call void @use_v2i8(<2 x i8> %m01)559 %m00 = mul <2 x i8> %In1Lo, %In0Lo560 %addc = add <2 x i8> %m10, %m01561 %shl = shl <2 x i8> %addc, <i8 4, i8 4>562 %retLo = add <2 x i8> %shl, %m00563 ret <2 x i8> %retLo564}565 566; Support wide width567define i130 @mul130_low(i130 %in0, i130 %in1) {568; CHECK-LABEL: @mul130_low(569; CHECK-NEXT: [[RETLO:%.*]] = mul i130 [[IN0:%.*]], [[IN1:%.*]]570; CHECK-NEXT: ret i130 [[RETLO]]571;572 %In0Lo = and i130 %in0, 36893488147419103231573 %In0Hi = lshr i130 %in0, 65574 %In1Lo = and i130 %in1, 36893488147419103231575 %In1Hi = lshr i130 %in1, 65576 %m10 = mul i130 %In1Hi, %In0Lo577 %m01 = mul i130 %In1Lo, %In0Hi578 %m00 = mul i130 %In1Lo, %In0Lo579 %addc = add i130 %m10, %m01580 %shl = shl i130 %addc, 65581 %retLo = add i130 %shl, %m00582 ret i130 %retLo583}584 585define i130 @mul130_low_one_extra_user(i130 %in0, i130 %in1) {586; CHECK-LABEL: @mul130_low_one_extra_user(587; CHECK-NEXT: [[IN0LO:%.*]] = and i130 [[IN0:%.*]], 36893488147419103231588; CHECK-NEXT: [[IN1HI:%.*]] = lshr i130 [[IN1:%.*]], 65589; CHECK-NEXT: [[M10:%.*]] = mul nuw i130 [[IN1HI]], [[IN0LO]]590; CHECK-NEXT: call void @use130(i130 [[M10]])591; CHECK-NEXT: [[RETLO:%.*]] = mul i130 [[IN0]], [[IN1]]592; CHECK-NEXT: ret i130 [[RETLO]]593;594 %In0Lo = and i130 %in0, 36893488147419103231595 %In0Hi = lshr i130 %in0, 65596 %In1Lo = and i130 %in1, 36893488147419103231597 %In1Hi = lshr i130 %in1, 65598 %m10 = mul i130 %In1Hi, %In0Lo599 call void @use130(i130 %m10)600 %m01 = mul i130 %In1Lo, %In0Hi601 %m00 = mul i130 %In1Lo, %In0Lo602 %addc = add i130 %m10, %m01603 %shl = shl i130 %addc, 65604 %retLo = add i130 %shl, %m00605 ret i130 %retLo606}607 608; Negative case: Skip odd bitwidth type609define i9 @mul9_low(i9 %in0, i9 %in1) {610; CHECK-LABEL: @mul9_low(611; CHECK-NEXT: [[IN0LO:%.*]] = and i9 [[IN0:%.*]], 15612; CHECK-NEXT: [[IN0HI:%.*]] = lshr i9 [[IN0]], 4613; CHECK-NEXT: [[IN1LO:%.*]] = and i9 [[IN1:%.*]], 15614; CHECK-NEXT: [[IN1HI:%.*]] = lshr i9 [[IN1]], 4615; CHECK-NEXT: [[M10:%.*]] = mul nuw i9 [[IN1HI]], [[IN0LO]]616; CHECK-NEXT: [[M01:%.*]] = mul nuw i9 [[IN1LO]], [[IN0HI]]617; CHECK-NEXT: [[M00:%.*]] = mul nuw nsw i9 [[IN1LO]], [[IN0LO]]618; CHECK-NEXT: [[ADDC:%.*]] = add i9 [[M10]], [[M01]]619; CHECK-NEXT: [[SHL:%.*]] = shl i9 [[ADDC]], 4620; CHECK-NEXT: [[RETLO:%.*]] = add i9 [[SHL]], [[M00]]621; CHECK-NEXT: ret i9 [[RETLO]]622;623 %In0Lo = and i9 %in0, 15624 %In0Hi = lshr i9 %in0, 4625 %In1Lo = and i9 %in1, 15626 %In1Hi = lshr i9 %in1, 4627 %m10 = mul i9 %In1Hi, %In0Lo628 %m01 = mul i9 %In1Lo, %In0Hi629 %m00 = mul i9 %In1Lo, %In0Lo630 %addc = add i9 %m10, %m01631 %shl = shl i9 %addc, 4632 %retLo = add i9 %shl, %m00633 ret i9 %retLo634}635 636; Negative test: Should not remote the "and", https://alive2.llvm.org/ce/z/JLmNU5637define i64 @mul64_low_no_and(i64 %in0, i64 %in1) {638; CHECK-LABEL: @mul64_low_no_and(639; CHECK-NEXT: [[IN0HI:%.*]] = lshr i64 [[IN0:%.*]], 32640; CHECK-NEXT: [[IN1HI:%.*]] = lshr i64 [[IN1:%.*]], 32641; CHECK-NEXT: [[M10:%.*]] = mul i64 [[IN1HI]], [[IN0]]642; CHECK-NEXT: [[M01:%.*]] = mul i64 [[IN1]], [[IN0HI]]643; CHECK-NEXT: [[M00:%.*]] = mul i64 [[IN1]], [[IN0]]644; CHECK-NEXT: [[ADDC:%.*]] = add i64 [[M10]], [[M01]]645; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[ADDC]], 32646; CHECK-NEXT: [[RETLO:%.*]] = add i64 [[SHL]], [[M00]]647; CHECK-NEXT: ret i64 [[RETLO]]648;649 %In0Hi = lshr i64 %in0, 32650 %In1Hi = lshr i64 %in1, 32651 %m10 = mul i64 %In1Hi, %in0652 %m01 = mul i64 %in1, %In0Hi653 %m00 = mul i64 %in1, %in0654 %addc = add i64 %m10, %m01655 %shl = shl i64 %addc, 32656 %retLo = add i64 %shl, %m00657 ret i64 %retLo658}659 660; Negative test: Miss match the shift amount661define i16 @mul16_low_miss_shift_amount(i16 %in0, i16 %in1) {662; CHECK-LABEL: @mul16_low_miss_shift_amount(663; CHECK-NEXT: [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 127664; CHECK-NEXT: [[IN0HI:%.*]] = lshr i16 [[IN0]], 8665; CHECK-NEXT: [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 127666; CHECK-NEXT: [[IN1HI:%.*]] = lshr i16 [[IN1]], 8667; CHECK-NEXT: [[M10:%.*]] = mul nuw nsw i16 [[IN1HI]], [[IN0LO]]668; CHECK-NEXT: [[M01:%.*]] = mul nuw nsw i16 [[IN1LO]], [[IN0HI]]669; CHECK-NEXT: [[M00:%.*]] = mul nuw nsw i16 [[IN1LO]], [[IN0LO]]670; CHECK-NEXT: [[ADDC:%.*]] = add nuw i16 [[M10]], [[M01]]671; CHECK-NEXT: [[SHL:%.*]] = shl i16 [[ADDC]], 8672; CHECK-NEXT: [[RETLO:%.*]] = add i16 [[SHL]], [[M00]]673; CHECK-NEXT: ret i16 [[RETLO]]674;675 %In0Lo = and i16 %in0, 127 ; Should be 255676 %In0Hi = lshr i16 %in0, 8677 %In1Lo = and i16 %in1, 127678 %In1Hi = lshr i16 %in1, 8679 %m10 = mul i16 %In1Hi, %In0Lo680 %m01 = mul i16 %In1Lo, %In0Hi681 %m00 = mul i16 %In1Lo, %In0Lo682 %addc = add i16 %m10, %m01683 %shl = shl i16 %addc, 8684 %retLo = add i16 %shl, %m00685 ret i16 %retLo686}687 688; Negative test: Miss match the half width689define i8 @mul8_low_miss_half_width(i8 %in0, i8 %in1) {690; CHECK-LABEL: @mul8_low_miss_half_width(691; CHECK-NEXT: [[IN0LO:%.*]] = and i8 [[IN0:%.*]], 15692; CHECK-NEXT: [[IN0HI:%.*]] = lshr i8 [[IN0]], 3693; CHECK-NEXT: [[IN1LO:%.*]] = and i8 [[IN1:%.*]], 15694; CHECK-NEXT: [[IN1HI:%.*]] = lshr i8 [[IN1]], 3695; CHECK-NEXT: [[M10:%.*]] = mul i8 [[IN1HI]], [[IN0LO]]696; CHECK-NEXT: [[M01:%.*]] = mul i8 [[IN1LO]], [[IN0HI]]697; CHECK-NEXT: [[M00:%.*]] = mul nuw i8 [[IN1LO]], [[IN0LO]]698; CHECK-NEXT: [[ADDC:%.*]] = add i8 [[M10]], [[M01]]699; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[ADDC]], 3700; CHECK-NEXT: [[RETLO:%.*]] = add i8 [[SHL]], [[M00]]701; CHECK-NEXT: ret i8 [[RETLO]]702;703 %In0Lo = and i8 %in0, 15704 %In0Hi = lshr i8 %in0, 3 ; Should be 4705 %In1Lo = and i8 %in1, 15706 %In1Hi = lshr i8 %in1, 3707 %m10 = mul i8 %In1Hi, %In0Lo708 %m01 = mul i8 %In1Lo, %In0Hi709 %m00 = mul i8 %In1Lo, %In0Lo710 %addc = add i8 %m10, %m01711 %shl = shl i8 %addc, 3712 %retLo = add i8 %shl, %m00713 ret i8 %retLo714}715 716; Test case to show shl doesn't need hasOneUse constraint717define i32 @mul32_low_extra_shl_use(i32 %in0, i32 %in1) {718; CHECK-LABEL: @mul32_low_extra_shl_use(719; CHECK-NEXT: [[IN0HI:%.*]] = lshr i32 [[IN0:%.*]], 16720; CHECK-NEXT: [[IN1HI:%.*]] = lshr i32 [[IN1:%.*]], 16721; CHECK-NEXT: [[M10:%.*]] = mul i32 [[IN1HI]], [[IN0]]722; CHECK-NEXT: [[M01:%.*]] = mul i32 [[IN1]], [[IN0HI]]723; CHECK-NEXT: [[ADDC:%.*]] = add i32 [[M10]], [[M01]]724; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[ADDC]], 16725; CHECK-NEXT: call void @use32(i32 [[SHL]])726; CHECK-NEXT: [[RETLO:%.*]] = mul i32 [[IN0]], [[IN1]]727; CHECK-NEXT: ret i32 [[RETLO]]728;729 %In0Lo = and i32 %in0, 65535730 %In0Hi = lshr i32 %in0, 16731 %In1Lo = and i32 %in1, 65535732 %In1Hi = lshr i32 %in1, 16733 %m10 = mul i32 %In1Hi, %In0Lo734 %m01 = mul i32 %In1Lo, %In0Hi735 %m00 = mul i32 %In1Lo, %In0Lo736 %addc = add i32 %m10, %m01737 %shl = shl i32 %addc, 16738 call void @use32(i32 %shl)739 %retLo = add i32 %shl, %m00740 ret i32 %retLo741}742