brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.9 KiB · 7e26b87 Raw
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