1033 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=aarch64 | FileCheck %s3; RUN: llc < %s -mtriple=aarch64 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefix=GISEL4 5; Convert mul x, pow2 to shift.6; Convert mul x, pow2 +/- 1 to shift + add/sub.7; Convert mul x, (pow2 + 1) * pow2 to shift + add + shift.8; Lowering other positive constants are not supported yet.9 10define i32 @test2(i32 %x) {11; CHECK-LABEL: test2:12; CHECK: // %bb.0:13; CHECK-NEXT: lsl w0, w0, #114; CHECK-NEXT: ret15;16; GISEL-LABEL: test2:17; GISEL: // %bb.0:18; GISEL-NEXT: lsl w0, w0, #119; GISEL-NEXT: ret20 21 %mul = shl nsw i32 %x, 122 ret i32 %mul23}24 25define i32 @test3(i32 %x) {26; CHECK-LABEL: test3:27; CHECK: // %bb.0:28; CHECK-NEXT: add w0, w0, w0, lsl #129; CHECK-NEXT: ret30;31; GISEL-LABEL: test3:32; GISEL: // %bb.0:33; GISEL-NEXT: add w0, w0, w0, lsl #134; GISEL-NEXT: ret35 36 %mul = mul nsw i32 %x, 337 ret i32 %mul38}39 40define i32 @test4(i32 %x) {41; CHECK-LABEL: test4:42; CHECK: // %bb.0:43; CHECK-NEXT: lsl w0, w0, #244; CHECK-NEXT: ret45;46; GISEL-LABEL: test4:47; GISEL: // %bb.0:48; GISEL-NEXT: lsl w0, w0, #249; GISEL-NEXT: ret50 51 %mul = shl nsw i32 %x, 252 ret i32 %mul53}54 55define i32 @test5(i32 %x) {56; CHECK-LABEL: test5:57; CHECK: // %bb.0:58; CHECK-NEXT: add w0, w0, w0, lsl #259; CHECK-NEXT: ret60;61; GISEL-LABEL: test5:62; GISEL: // %bb.0:63; GISEL-NEXT: add w0, w0, w0, lsl #264; GISEL-NEXT: ret65 66 67 %mul = mul nsw i32 %x, 568 ret i32 %mul69}70 71define i32 @test6_32b(i32 %x) {72; CHECK-LABEL: test6_32b:73; CHECK: // %bb.0:74; CHECK-NEXT: add w8, w0, w0, lsl #175; CHECK-NEXT: lsl w0, w8, #176; CHECK-NEXT: ret77;78; GISEL-LABEL: test6_32b:79; GISEL: // %bb.0:80; GISEL-NEXT: add w8, w0, w0, lsl #181; GISEL-NEXT: lsl w0, w8, #182; GISEL-NEXT: ret83 84 %mul = mul nsw i32 %x, 685 ret i32 %mul86}87 88define i64 @test6_64b(i64 %x) {89; CHECK-LABEL: test6_64b:90; CHECK: // %bb.0:91; CHECK-NEXT: add x8, x0, x0, lsl #192; CHECK-NEXT: lsl x0, x8, #193; CHECK-NEXT: ret94;95; GISEL-LABEL: test6_64b:96; GISEL: // %bb.0:97; GISEL-NEXT: add x8, x0, x0, lsl #198; GISEL-NEXT: lsl x0, x8, #199; GISEL-NEXT: ret100 101 %mul = mul nsw i64 %x, 6102 ret i64 %mul103}104 105; mul that appears together with add, sub, s(z)ext is not supported to be106; converted to the combination of lsl, add/sub yet.107define i64 @test6_umull(i32 %x) {108; CHECK-LABEL: test6_umull:109; CHECK: // %bb.0:110; CHECK-NEXT: mov w8, #6 // =0x6111; CHECK-NEXT: umull x0, w0, w8112; CHECK-NEXT: ret113;114; GISEL-LABEL: test6_umull:115; GISEL: // %bb.0:116; GISEL-NEXT: mov w8, #6 // =0x6117; GISEL-NEXT: umull x0, w0, w8118; GISEL-NEXT: ret119 120 %ext = zext i32 %x to i64121 %mul = mul nsw i64 %ext, 6122 ret i64 %mul123}124 125define i64 @test6_smull(i32 %x) {126; CHECK-LABEL: test6_smull:127; CHECK: // %bb.0:128; CHECK-NEXT: mov w8, #6 // =0x6129; CHECK-NEXT: smull x0, w0, w8130; CHECK-NEXT: ret131;132; GISEL-LABEL: test6_smull:133; GISEL: // %bb.0:134; GISEL-NEXT: mov w8, #6 // =0x6135; GISEL-NEXT: smull x0, w0, w8136; GISEL-NEXT: ret137 138 %ext = sext i32 %x to i64139 %mul = mul nsw i64 %ext, 6140 ret i64 %mul141}142 143define i32 @test6_madd(i32 %x, i32 %y) {144; CHECK-LABEL: test6_madd:145; CHECK: // %bb.0:146; CHECK-NEXT: mov w8, #6 // =0x6147; CHECK-NEXT: madd w0, w0, w8, w1148; CHECK-NEXT: ret149;150; GISEL-LABEL: test6_madd:151; GISEL: // %bb.0:152; GISEL-NEXT: mov w8, #6 // =0x6153; GISEL-NEXT: madd w0, w0, w8, w1154; GISEL-NEXT: ret155 156 %mul = mul nsw i32 %x, 6157 %add = add i32 %mul, %y158 ret i32 %add159}160 161define i32 @test6_msub(i32 %x, i32 %y) {162; CHECK-LABEL: test6_msub:163; CHECK: // %bb.0:164; CHECK-NEXT: mov w8, #6 // =0x6165; CHECK-NEXT: msub w0, w0, w8, w1166; CHECK-NEXT: ret167;168; GISEL-LABEL: test6_msub:169; GISEL: // %bb.0:170; GISEL-NEXT: mov w8, #6 // =0x6171; GISEL-NEXT: msub w0, w0, w8, w1172; GISEL-NEXT: ret173 174 %mul = mul nsw i32 %x, 6175 %sub = sub i32 %y, %mul176 ret i32 %sub177}178 179define i64 @test6_umaddl(i32 %x, i64 %y) {180; CHECK-LABEL: test6_umaddl:181; CHECK: // %bb.0:182; CHECK-NEXT: mov w8, #6 // =0x6183; CHECK-NEXT: umaddl x0, w0, w8, x1184; CHECK-NEXT: ret185;186; GISEL-LABEL: test6_umaddl:187; GISEL: // %bb.0:188; GISEL-NEXT: mov w8, #6 // =0x6189; GISEL-NEXT: umaddl x0, w0, w8, x1190; GISEL-NEXT: ret191 192 %ext = zext i32 %x to i64193 %mul = mul nsw i64 %ext, 6194 %add = add i64 %mul, %y195 ret i64 %add196}197 198define i64 @test6_smaddl(i32 %x, i64 %y) {199; CHECK-LABEL: test6_smaddl:200; CHECK: // %bb.0:201; CHECK-NEXT: mov w8, #6 // =0x6202; CHECK-NEXT: smaddl x0, w0, w8, x1203; CHECK-NEXT: ret204;205; GISEL-LABEL: test6_smaddl:206; GISEL: // %bb.0:207; GISEL-NEXT: mov w8, #6 // =0x6208; GISEL-NEXT: smaddl x0, w0, w8, x1209; GISEL-NEXT: ret210 211 %ext = sext i32 %x to i64212 %mul = mul nsw i64 %ext, 6213 %add = add i64 %mul, %y214 ret i64 %add215}216 217define i64 @test6_umsubl(i32 %x, i64 %y) {218; CHECK-LABEL: test6_umsubl:219; CHECK: // %bb.0:220; CHECK-NEXT: mov w8, #6 // =0x6221; CHECK-NEXT: umsubl x0, w0, w8, x1222; CHECK-NEXT: ret223;224; GISEL-LABEL: test6_umsubl:225; GISEL: // %bb.0:226; GISEL-NEXT: mov w8, #6 // =0x6227; GISEL-NEXT: umsubl x0, w0, w8, x1228; GISEL-NEXT: ret229 230 %ext = zext i32 %x to i64231 %mul = mul nsw i64 %ext, 6232 %sub = sub i64 %y, %mul233 ret i64 %sub234}235 236define i64 @test6_smsubl(i32 %x, i64 %y) {237; CHECK-LABEL: test6_smsubl:238; CHECK: // %bb.0:239; CHECK-NEXT: mov w8, #6 // =0x6240; CHECK-NEXT: smsubl x0, w0, w8, x1241; CHECK-NEXT: ret242;243; GISEL-LABEL: test6_smsubl:244; GISEL: // %bb.0:245; GISEL-NEXT: mov w8, #6 // =0x6246; GISEL-NEXT: smsubl x0, w0, w8, x1247; GISEL-NEXT: ret248 249 %ext = sext i32 %x to i64250 %mul = mul nsw i64 %ext, 6251 %sub = sub i64 %y, %mul252 ret i64 %sub253}254 255define i64 @test6_umnegl(i32 %x) {256; CHECK-LABEL: test6_umnegl:257; CHECK: // %bb.0:258; CHECK-NEXT: mov w8, #6 // =0x6259; CHECK-NEXT: umnegl x0, w0, w8260; CHECK-NEXT: ret261;262; GISEL-LABEL: test6_umnegl:263; GISEL: // %bb.0:264; GISEL-NEXT: mov w8, #6 // =0x6265; GISEL-NEXT: umnegl x0, w0, w8266; GISEL-NEXT: ret267 268 %ext = zext i32 %x to i64269 %mul = mul nsw i64 %ext, 6270 %sub = sub i64 0, %mul271 ret i64 %sub272}273 274define i64 @test6_smnegl(i32 %x) {275; CHECK-LABEL: test6_smnegl:276; CHECK: // %bb.0:277; CHECK-NEXT: mov w8, #6 // =0x6278; CHECK-NEXT: smnegl x0, w0, w8279; CHECK-NEXT: ret280;281; GISEL-LABEL: test6_smnegl:282; GISEL: // %bb.0:283; GISEL-NEXT: mov w8, #6 // =0x6284; GISEL-NEXT: smnegl x0, w0, w8285; GISEL-NEXT: ret286 287 %ext = sext i32 %x to i64288 %mul = mul nsw i64 %ext, 6289 %sub = sub i64 0, %mul290 ret i64 %sub291}292 293; We may hoist the "mov" instructions out of a loop294define i32 @mull6_sub(i32 %x) {295; CHECK-LABEL: mull6_sub:296; CHECK: // %bb.0:297; CHECK-NEXT: mov w8, #6 // =0x6298; CHECK-NEXT: mov w9, #-1 // =0xffffffff299; CHECK-NEXT: madd w0, w0, w8, w9300; CHECK-NEXT: ret301;302; GISEL-LABEL: mull6_sub:303; GISEL: // %bb.0:304; GISEL-NEXT: mov w8, #6 // =0x6305; GISEL-NEXT: mov w9, #-1 // =0xffffffff306; GISEL-NEXT: madd w0, w0, w8, w9307; GISEL-NEXT: ret308 %mul = mul nsw i32 %x, 6309 %sub = add nsw i32 %mul, -1310 ret i32 %sub311}312 313define i64 @mull6_sub_orr(i64 %x) {314; CHECK-LABEL: mull6_sub_orr:315; CHECK: // %bb.0:316; CHECK-NEXT: mov w8, #6 // =0x6317; CHECK-NEXT: mov x9, #16773120 // =0xfff000318; CHECK-NEXT: madd x0, x0, x8, x9319; CHECK-NEXT: ret320;321; GISEL-LABEL: mull6_sub_orr:322; GISEL: // %bb.0:323; GISEL-NEXT: mov w8, #6 // =0x6324; GISEL-NEXT: mov x9, #16773120 // =0xfff000325; GISEL-NEXT: madd x0, x0, x8, x9326; GISEL-NEXT: ret327 %mul = mul nsw i64 %x, 6328 %sub = add nsw i64 %mul, 16773120329 ret i64 %sub330}331 332define i32 @test7(i32 %x) {333; CHECK-LABEL: test7:334; CHECK: // %bb.0:335; CHECK-NEXT: lsl w8, w0, #3336; CHECK-NEXT: sub w0, w8, w0337; CHECK-NEXT: ret338;339; GISEL-LABEL: test7:340; GISEL: // %bb.0:341; GISEL-NEXT: lsl w8, w0, #3342; GISEL-NEXT: sub w0, w8, w0343; GISEL-NEXT: ret344 345 %mul = mul nsw i32 %x, 7346 ret i32 %mul347}348 349define i32 @test8(i32 %x) {350; CHECK-LABEL: test8:351; CHECK: // %bb.0:352; CHECK-NEXT: lsl w0, w0, #3353; CHECK-NEXT: ret354;355; GISEL-LABEL: test8:356; GISEL: // %bb.0:357; GISEL-NEXT: lsl w0, w0, #3358; GISEL-NEXT: ret359 360 %mul = shl nsw i32 %x, 3361 ret i32 %mul362}363 364define i32 @test9(i32 %x) {365; CHECK-LABEL: test9:366; CHECK: // %bb.0:367; CHECK-NEXT: add w0, w0, w0, lsl #3368; CHECK-NEXT: ret369;370; GISEL-LABEL: test9:371; GISEL: // %bb.0:372; GISEL-NEXT: add w0, w0, w0, lsl #3373; GISEL-NEXT: ret374 375 %mul = mul nsw i32 %x, 9376 ret i32 %mul377}378 379define i32 @test10(i32 %x) {380; CHECK-LABEL: test10:381; CHECK: // %bb.0:382; CHECK-NEXT: add w8, w0, w0, lsl #2383; CHECK-NEXT: lsl w0, w8, #1384; CHECK-NEXT: ret385;386; GISEL-LABEL: test10:387; GISEL: // %bb.0:388; GISEL-NEXT: add w8, w0, w0, lsl #2389; GISEL-NEXT: lsl w0, w8, #1390; GISEL-NEXT: ret391 392 %mul = mul nsw i32 %x, 10393 ret i32 %mul394}395 396define i32 @test11(i32 %x) {397; CHECK-LABEL: test11:398; CHECK: // %bb.0:399; CHECK-NEXT: mov w8, #11 // =0xb400; CHECK-NEXT: mul w0, w0, w8401; CHECK-NEXT: ret402;403; GISEL-LABEL: test11:404; GISEL: // %bb.0:405; GISEL-NEXT: mov w8, #11 // =0xb406; GISEL-NEXT: mul w0, w0, w8407; GISEL-NEXT: ret408 409 %mul = mul nsw i32 %x, 11410 ret i32 %mul411}412 413define i32 @test11_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {414; CHECK-LABEL: test11_fast_shift:415; CHECK: // %bb.0:416; CHECK-NEXT: add w8, w0, w0, lsl #2417; CHECK-NEXT: add w0, w0, w8, lsl #1418; CHECK-NEXT: ret419;420; GISEL-LABEL: test11_fast_shift:421; GISEL: // %bb.0:422; GISEL-NEXT: mov w8, #11 // =0xb423; GISEL-NEXT: mul w0, w0, w8424; GISEL-NEXT: ret425 426 %mul = mul nsw i32 %x, 11 ; 11 = (((1<<2) + 1) << 1) + 1427 ret i32 %mul428}429 430define i32 @test12(i32 %x) {431; CHECK-LABEL: test12:432; CHECK: // %bb.0:433; CHECK-NEXT: add w8, w0, w0, lsl #1434; CHECK-NEXT: lsl w0, w8, #2435; CHECK-NEXT: ret436;437; GISEL-LABEL: test12:438; GISEL: // %bb.0:439; GISEL-NEXT: add w8, w0, w0, lsl #1440; GISEL-NEXT: lsl w0, w8, #2441; GISEL-NEXT: ret442 443 %mul = mul nsw i32 %x, 12444 ret i32 %mul445}446 447define i32 @test13(i32 %x) {448; CHECK-LABEL: test13:449; CHECK: // %bb.0:450; CHECK-NEXT: mov w8, #13 // =0xd451; CHECK-NEXT: mul w0, w0, w8452; CHECK-NEXT: ret453;454; GISEL-LABEL: test13:455; GISEL: // %bb.0:456; GISEL-NEXT: mov w8, #13 // =0xd457; GISEL-NEXT: mul w0, w0, w8458; GISEL-NEXT: ret459 460 %mul = mul nsw i32 %x, 13461 ret i32 %mul462}463 464define i32 @test14(i32 %x) {465; CHECK-LABEL: test14:466; CHECK: // %bb.0:467; CHECK-NEXT: lsl w8, w0, #4468; CHECK-NEXT: sub w0, w8, w0, lsl #1469; CHECK-NEXT: ret470;471; GISEL-LABEL: test14:472; GISEL: // %bb.0:473; GISEL-NEXT: mov w8, #14 // =0xe474; GISEL-NEXT: mul w0, w0, w8475; GISEL-NEXT: ret476 477 %mul = mul nsw i32 %x, 14478 ret i32 %mul479}480 481define i32 @test15(i32 %x) {482; CHECK-LABEL: test15:483; CHECK: // %bb.0:484; CHECK-NEXT: lsl w8, w0, #4485; CHECK-NEXT: sub w0, w8, w0486; CHECK-NEXT: ret487;488; GISEL-LABEL: test15:489; GISEL: // %bb.0:490; GISEL-NEXT: lsl w8, w0, #4491; GISEL-NEXT: sub w0, w8, w0492; GISEL-NEXT: ret493 494 %mul = mul nsw i32 %x, 15495 ret i32 %mul496}497 498define i32 @test16(i32 %x) {499; CHECK-LABEL: test16:500; CHECK: // %bb.0:501; CHECK-NEXT: lsl w0, w0, #4502; CHECK-NEXT: ret503;504; GISEL-LABEL: test16:505; GISEL: // %bb.0:506; GISEL-NEXT: lsl w0, w0, #4507; GISEL-NEXT: ret508 509 %mul = mul nsw i32 %x, 16510 ret i32 %mul511}512 513define i32 @test25_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {514; CHECK-LABEL: test25_fast_shift:515; CHECK: // %bb.0:516; CHECK-NEXT: add w8, w0, w0, lsl #2517; CHECK-NEXT: add w0, w8, w8, lsl #2518; CHECK-NEXT: ret519;520; GISEL-LABEL: test25_fast_shift:521; GISEL: // %bb.0:522; GISEL-NEXT: mov w8, #25 // =0x19523; GISEL-NEXT: mul w0, w0, w8524; GISEL-NEXT: ret525 526 %mul = mul nsw i32 %x, 25 ; 25 = (1+4)*(1+4)527 ret i32 %mul528}529 530define i32 @test29_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {531; CHECK-LABEL: test29_fast_shift:532; CHECK: // %bb.0:533; CHECK-NEXT: sub w8, w0, w0, lsl #3534; CHECK-NEXT: sub w0, w0, w8, lsl #2535; CHECK-NEXT: ret536;537; GISEL-LABEL: test29_fast_shift:538; GISEL: // %bb.0:539; GISEL-NEXT: mov w8, #29 // =0x1d540; GISEL-NEXT: mul w0, w0, w8541; GISEL-NEXT: ret542 543 %mul = mul nsw i32 %x, 29 ; 29 = 1 - (1-8) * 4544 ret i32 %mul545}546 547define i32 @test45_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {548; CHECK-LABEL: test45_fast_shift:549; CHECK: // %bb.0:550; CHECK-NEXT: add w8, w0, w0, lsl #2551; CHECK-NEXT: add w0, w8, w8, lsl #3552; CHECK-NEXT: ret553;554; GISEL-LABEL: test45_fast_shift:555; GISEL: // %bb.0:556; GISEL-NEXT: mov w8, #45 // =0x2d557; GISEL-NEXT: mul w0, w0, w8558; GISEL-NEXT: ret559 560 %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)561 ret i32 %mul562}563 564; Negative test: Keep MUL as don't have the feature LSLFast565define i32 @test45(i32 %x) {566; CHECK-LABEL: test45:567; CHECK: // %bb.0:568; CHECK-NEXT: mov w8, #45 // =0x2d569; CHECK-NEXT: mul w0, w0, w8570; CHECK-NEXT: ret571;572; GISEL-LABEL: test45:573; GISEL: // %bb.0:574; GISEL-NEXT: mov w8, #45 // =0x2d575; GISEL-NEXT: mul w0, w0, w8576; GISEL-NEXT: ret577 578 %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)579 ret i32 %mul580}581 582; Negative test: The shift number 5 is out of bound583define i32 @test67_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {584; CHECK-LABEL: test67_fast_shift:585; CHECK: // %bb.0:586; CHECK-NEXT: mov w8, #67 // =0x43587; CHECK-NEXT: mul w0, w0, w8588; CHECK-NEXT: ret589;590; GISEL-LABEL: test67_fast_shift:591; GISEL: // %bb.0:592; GISEL-NEXT: mov w8, #67 // =0x43593; GISEL-NEXT: mul w0, w0, w8594; GISEL-NEXT: ret595 596 %mul = mul nsw i32 %x, 67 ; 67 = (((1<<5) + 1) << 1) + 1597 ret i32 %mul598}599 600define i32 @test85_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {601; CHECK-LABEL: test85_fast_shift:602; CHECK: // %bb.0:603; CHECK-NEXT: add w8, w0, w0, lsl #2604; CHECK-NEXT: add w0, w8, w8, lsl #4605; CHECK-NEXT: ret606;607; GISEL-LABEL: test85_fast_shift:608; GISEL: // %bb.0:609; GISEL-NEXT: mov w8, #85 // =0x55610; GISEL-NEXT: mul w0, w0, w8611; GISEL-NEXT: ret612 613 %mul = mul nsw i32 %x, 85 ; 85 = (1+4)*(1+16)614 ret i32 %mul615}616 617; Negative test: The shift number 5 is out of bound618define i32 @test97_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {619; CHECK-LABEL: test97_fast_shift:620; CHECK: // %bb.0:621; CHECK-NEXT: mov w8, #97 // =0x61622; CHECK-NEXT: mul w0, w0, w8623; CHECK-NEXT: ret624;625; GISEL-LABEL: test97_fast_shift:626; GISEL: // %bb.0:627; GISEL-NEXT: mov w8, #97 // =0x61628; GISEL-NEXT: mul w0, w0, w8629; GISEL-NEXT: ret630 631 %mul = mul nsw i32 %x, 97 ; 97 = ((2 + 1) << 5) + 1632 ret i32 %mul633}634 635; Negative test: The shift number 5 is out of bound636define i32 @test125_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {637; CHECK-LABEL: test125_fast_shift:638; CHECK: // %bb.0:639; CHECK-NEXT: mov w8, #125 // =0x7d640; CHECK-NEXT: mul w0, w0, w8641; CHECK-NEXT: ret642;643; GISEL-LABEL: test125_fast_shift:644; GISEL: // %bb.0:645; GISEL-NEXT: mov w8, #125 // =0x7d646; GISEL-NEXT: mul w0, w0, w8647; GISEL-NEXT: ret648 649 %mul = mul nsw i32 %x, 125 ; 125 = 1 - ((1-32) << 2)650 ret i32 %mul651}652 653; TODO: (1 - 2^M) * (1 - 2^N)654define i32 @test225_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {655; CHECK-LABEL: test225_fast_shift:656; CHECK: // %bb.0:657; CHECK-NEXT: mov w8, #225 // =0xe1658; CHECK-NEXT: mul w0, w0, w8659; CHECK-NEXT: ret660;661; GISEL-LABEL: test225_fast_shift:662; GISEL: // %bb.0:663; GISEL-NEXT: mov w8, #225 // =0xe1664; GISEL-NEXT: mul w0, w0, w8665; GISEL-NEXT: ret666 667 %mul = mul nsw i32 %x, 225 ; 225 = (1-16)*(1-16)668 ret i32 %mul669}670 671; Negative test: The shift amount 5 larger than 4672define i32 @test297_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {673; CHECK-LABEL: test297_fast_shift:674; CHECK: // %bb.0:675; CHECK-NEXT: mov w8, #297 // =0x129676; CHECK-NEXT: mul w0, w0, w8677; CHECK-NEXT: ret678;679; GISEL-LABEL: test297_fast_shift:680; GISEL: // %bb.0:681; GISEL-NEXT: mov w8, #297 // =0x129682; GISEL-NEXT: mul w0, w0, w8683; GISEL-NEXT: ret684 685 %mul = mul nsw i32 %x, 297 ; 297 = (1+8)*(1+32)686 ret i32 %mul687}688 689; Negative test: The shift number 5 is out of bound690define i32 @test481_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {691; CHECK-LABEL: test481_fast_shift:692; CHECK: // %bb.0:693; CHECK-NEXT: mov w8, #481 // =0x1e1694; CHECK-NEXT: mul w0, w0, w8695; CHECK-NEXT: ret696;697; GISEL-LABEL: test481_fast_shift:698; GISEL: // %bb.0:699; GISEL-NEXT: mov w8, #481 // =0x1e1700; GISEL-NEXT: mul w0, w0, w8701; GISEL-NEXT: ret702 703 %mul = mul nsw i32 %x, 481 ; 481 = 1 - ((1-16) << 5)704 ret i32 %mul705}706 707; Convert mul x, -pow2 to shift.708; Convert mul x, -(pow2 +/- 1) to shift + add/sub.709; Lowering other negative constants are not supported yet.710 711define i32 @ntest2(i32 %x) {712; CHECK-LABEL: ntest2:713; CHECK: // %bb.0:714; CHECK-NEXT: neg w0, w0, lsl #1715; CHECK-NEXT: ret716;717; GISEL-LABEL: ntest2:718; GISEL: // %bb.0:719; GISEL-NEXT: mov w8, #-2 // =0xfffffffe720; GISEL-NEXT: mul w0, w0, w8721; GISEL-NEXT: ret722 723 %mul = mul nsw i32 %x, -2724 ret i32 %mul725}726 727define i32 @ntest3(i32 %x) {728; CHECK-LABEL: ntest3:729; CHECK: // %bb.0:730; CHECK-NEXT: sub w0, w0, w0, lsl #2731; CHECK-NEXT: ret732;733; GISEL-LABEL: ntest3:734; GISEL: // %bb.0:735; GISEL-NEXT: sub w0, w0, w0, lsl #2736; GISEL-NEXT: ret737 738 %mul = mul nsw i32 %x, -3739 ret i32 %mul740}741 742define i32 @ntest4(i32 %x) {743; CHECK-LABEL: ntest4:744; CHECK: // %bb.0:745; CHECK-NEXT: neg w0, w0, lsl #2746; CHECK-NEXT: ret747;748; GISEL-LABEL: ntest4:749; GISEL: // %bb.0:750; GISEL-NEXT: mov w8, #-4 // =0xfffffffc751; GISEL-NEXT: mul w0, w0, w8752; GISEL-NEXT: ret753 754 %mul = mul nsw i32 %x, -4755 ret i32 %mul756}757 758define i32 @ntest5(i32 %x) {759; CHECK-LABEL: ntest5:760; CHECK: // %bb.0:761; CHECK-NEXT: add w8, w0, w0, lsl #2762; CHECK-NEXT: neg w0, w8763; CHECK-NEXT: ret764;765; GISEL-LABEL: ntest5:766; GISEL: // %bb.0:767; GISEL-NEXT: add w8, w0, w0, lsl #2768; GISEL-NEXT: neg w0, w8769; GISEL-NEXT: ret770 %mul = mul nsw i32 %x, -5771 ret i32 %mul772}773 774define i32 @ntest6(i32 %x) {775; CHECK-LABEL: ntest6:776; CHECK: // %bb.0:777; CHECK-NEXT: lsl w8, w0, #1778; CHECK-NEXT: sub w0, w8, w0, lsl #3779; CHECK-NEXT: ret780;781; GISEL-LABEL: ntest6:782; GISEL: // %bb.0:783; GISEL-NEXT: mov w8, #-6 // =0xfffffffa784; GISEL-NEXT: mul w0, w0, w8785; GISEL-NEXT: ret786 787 %mul = mul nsw i32 %x, -6788 ret i32 %mul789}790 791define i32 @ntest7(i32 %x) {792; CHECK-LABEL: ntest7:793; CHECK: // %bb.0:794; CHECK-NEXT: sub w0, w0, w0, lsl #3795; CHECK-NEXT: ret796;797; GISEL-LABEL: ntest7:798; GISEL: // %bb.0:799; GISEL-NEXT: sub w0, w0, w0, lsl #3800; GISEL-NEXT: ret801 802 %mul = mul nsw i32 %x, -7803 ret i32 %mul804}805 806define i32 @ntest8(i32 %x) {807; CHECK-LABEL: ntest8:808; CHECK: // %bb.0:809; CHECK-NEXT: neg w0, w0, lsl #3810; CHECK-NEXT: ret811;812; GISEL-LABEL: ntest8:813; GISEL: // %bb.0:814; GISEL-NEXT: mov w8, #-8 // =0xfffffff8815; GISEL-NEXT: mul w0, w0, w8816; GISEL-NEXT: ret817 818 %mul = mul nsw i32 %x, -8819 ret i32 %mul820}821 822define i32 @ntest9(i32 %x) {823; CHECK-LABEL: ntest9:824; CHECK: // %bb.0:825; CHECK-NEXT: add w8, w0, w0, lsl #3826; CHECK-NEXT: neg w0, w8827; CHECK-NEXT: ret828;829; GISEL-LABEL: ntest9:830; GISEL: // %bb.0:831; GISEL-NEXT: add w8, w0, w0, lsl #3832; GISEL-NEXT: neg w0, w8833; GISEL-NEXT: ret834 835 %mul = mul nsw i32 %x, -9836 ret i32 %mul837}838 839define i32 @ntest10(i32 %x) {840; CHECK-LABEL: ntest10:841; CHECK: // %bb.0:842; CHECK-NEXT: mov w8, #-10 // =0xfffffff6843; CHECK-NEXT: mul w0, w0, w8844; CHECK-NEXT: ret845;846; GISEL-LABEL: ntest10:847; GISEL: // %bb.0:848; GISEL-NEXT: mov w8, #-10 // =0xfffffff6849; GISEL-NEXT: mul w0, w0, w8850; GISEL-NEXT: ret851 852 %mul = mul nsw i32 %x, -10853 ret i32 %mul854}855 856define i32 @ntest11(i32 %x) {857; CHECK-LABEL: ntest11:858; CHECK: // %bb.0:859; CHECK-NEXT: mov w8, #-11 // =0xfffffff5860; CHECK-NEXT: mul w0, w0, w8861; CHECK-NEXT: ret862;863; GISEL-LABEL: ntest11:864; GISEL: // %bb.0:865; GISEL-NEXT: mov w8, #-11 // =0xfffffff5866; GISEL-NEXT: mul w0, w0, w8867; GISEL-NEXT: ret868 869 %mul = mul nsw i32 %x, -11870 ret i32 %mul871}872 873define i32 @ntest12(i32 %x) {874; CHECK-LABEL: ntest12:875; CHECK: // %bb.0:876; CHECK-NEXT: lsl w8, w0, #2877; CHECK-NEXT: sub w0, w8, w0, lsl #4878; CHECK-NEXT: ret879;880; GISEL-LABEL: ntest12:881; GISEL: // %bb.0:882; GISEL-NEXT: mov w8, #-12 // =0xfffffff4883; GISEL-NEXT: mul w0, w0, w8884; GISEL-NEXT: ret885 886 %mul = mul nsw i32 %x, -12887 ret i32 %mul888}889 890define i32 @ntest13(i32 %x) {891; CHECK-LABEL: ntest13:892; CHECK: // %bb.0:893; CHECK-NEXT: mov w8, #-13 // =0xfffffff3894; CHECK-NEXT: mul w0, w0, w8895; CHECK-NEXT: ret896;897; GISEL-LABEL: ntest13:898; GISEL: // %bb.0:899; GISEL-NEXT: mov w8, #-13 // =0xfffffff3900; GISEL-NEXT: mul w0, w0, w8901; GISEL-NEXT: ret902 %mul = mul nsw i32 %x, -13903 ret i32 %mul904}905 906define i32 @ntest14(i32 %x) {907; CHECK-LABEL: ntest14:908; CHECK: // %bb.0:909; CHECK-NEXT: lsl w8, w0, #1910; CHECK-NEXT: sub w0, w8, w0, lsl #4911; CHECK-NEXT: ret912;913; GISEL-LABEL: ntest14:914; GISEL: // %bb.0:915; GISEL-NEXT: mov w8, #-14 // =0xfffffff2916; GISEL-NEXT: mul w0, w0, w8917; GISEL-NEXT: ret918 919 %mul = mul nsw i32 %x, -14920 ret i32 %mul921}922 923define i32 @ntest15(i32 %x) {924; CHECK-LABEL: ntest15:925; CHECK: // %bb.0:926; CHECK-NEXT: sub w0, w0, w0, lsl #4927; CHECK-NEXT: ret928;929; GISEL-LABEL: ntest15:930; GISEL: // %bb.0:931; GISEL-NEXT: sub w0, w0, w0, lsl #4932; GISEL-NEXT: ret933 934 %mul = mul nsw i32 %x, -15935 ret i32 %mul936}937 938define i32 @ntest16(i32 %x) {939; CHECK-LABEL: ntest16:940; CHECK: // %bb.0:941; CHECK-NEXT: neg w0, w0, lsl #4942; CHECK-NEXT: ret943;944; GISEL-LABEL: ntest16:945; GISEL: // %bb.0:946; GISEL-NEXT: mov w8, #-16 // =0xfffffff0947; GISEL-NEXT: mul w0, w0, w8948; GISEL-NEXT: ret949 950 %mul = mul nsw i32 %x, -16951 ret i32 %mul952}953 954define i32 @muladd_demand(i32 %x, i32 %y) {955; CHECK-LABEL: muladd_demand:956; CHECK: // %bb.0:957; CHECK-NEXT: sub w8, w1, w0, lsl #6958; CHECK-NEXT: and w0, w8, #0x1ffc0959; CHECK-NEXT: ret960;961; GISEL-LABEL: muladd_demand:962; GISEL: // %bb.0:963; GISEL-NEXT: mov w8, #131008 // =0x1ffc0964; GISEL-NEXT: madd w8, w0, w8, w1965; GISEL-NEXT: and w0, w8, #0x1ffc0966; GISEL-NEXT: ret967 %m = mul i32 %x, 131008 ; 0x0001ffc0968 %a = add i32 %y, %m969 %r = and i32 %a, 131008970 ret i32 %r971}972 973define <4 x i32> @muladd_demand_commute(<4 x i32> %x, <4 x i32> %y) {974; CHECK-LABEL: muladd_demand_commute:975; CHECK: // %bb.0:976; CHECK-NEXT: shl v0.4s, v0.4s, #6977; CHECK-NEXT: movi v2.4s, #1, msl #16978; CHECK-NEXT: sub v0.4s, v1.4s, v0.4s979; CHECK-NEXT: and v0.16b, v0.16b, v2.16b980; CHECK-NEXT: ret981;982; GISEL-LABEL: muladd_demand_commute:983; GISEL: // %bb.0:984; GISEL-NEXT: adrp x8, .LCPI56_0985; GISEL-NEXT: movi v3.4s, #1, msl #16986; GISEL-NEXT: ldr q2, [x8, :lo12:.LCPI56_0]987; GISEL-NEXT: mla v1.4s, v0.4s, v2.4s988; GISEL-NEXT: and v0.16b, v1.16b, v3.16b989; GISEL-NEXT: ret990 %m = mul <4 x i32> %x, <i32 131008, i32 131008, i32 131008, i32 131008>991 %a = add <4 x i32> %m, %y992 %r = and <4 x i32> %a, <i32 131071, i32 131071, i32 131071, i32 131071>993 ret <4 x i32> %r994}995 996; Transforming `(mul x, -(2^(N-M) - 1) * 2^M)` to `(sub (shl x, M), (shl x, N))`997; will cause overflow when N is 32 and M is 31.998define i32 @shift_overflow(i32 %x) {999; CHECK-LABEL: shift_overflow:1000; CHECK: // %bb.0:1001; CHECK-NEXT: mov w8, #-2147483648 // =0x800000001002; CHECK-NEXT: mul w0, w0, w81003; CHECK-NEXT: ret1004;1005; GISEL-LABEL: shift_overflow:1006; GISEL: // %bb.0:1007; GISEL-NEXT: mov w8, #-2147483648 // =0x800000001008; GISEL-NEXT: mul w0, w0, w81009; GISEL-NEXT: ret1010 %const = bitcast i32 2147483648 to i321011 %r = mul i32 %x, %const1012 ret i32 %r1013}1014 1015; Transforming `(mul x, -(2^(N-M) - 1) * 2^M)` to `(sub (shl x, M), (shl x, N))`1016; will not cause overflow when N is 31 and M is 30.1017define i32 @shift_no_overflow(i32 %x) {1018; CHECK-LABEL: shift_no_overflow:1019; CHECK: // %bb.0:1020; CHECK-NEXT: lsl w8, w0, #311021; CHECK-NEXT: sub w0, w8, w0, lsl #301022; CHECK-NEXT: ret1023;1024; GISEL-LABEL: shift_no_overflow:1025; GISEL: // %bb.0:1026; GISEL-NEXT: mov w8, #1073741824 // =0x400000001027; GISEL-NEXT: mul w0, w0, w81028; GISEL-NEXT: ret1029 %const = bitcast i32 1073741824 to i321030 %r = mul i32 %x, %const1031 ret i32 %r1032}1033