brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.9 KiB · ced30b6 Raw
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