[LoongArch] Optimize multiplication with immediates
authorBen Shi <powerman1st@163.com>
Sun, 2 Apr 2023 05:06:11 +0000 (13:06 +0800)
committerBen Shi <powerman1st@163.com>
Sun, 2 Apr 2023 14:12:49 +0000 (22:12 +0800)
Optimize multiplication with some specific immediates to
a pair of `alsl`.

Reviewed By: SixWeining, xen0n

Differential Revision: https://reviews.llvm.org/D147400

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll

index 011e623..db19dd4 100644 (file)
@@ -951,8 +951,17 @@ foreach Idx0 = 1...4 in {
   foreach Idx1 = 1...4 in {
     defvar CImm = !add(1, !shl(!add(1, !shl(1, Idx0)), Idx1));
     def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)),
-          (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)),
-                  GPR:$r, (i32 Idx1))>;
+              (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)),
+                      GPR:$r, (i32 Idx1))>;
+  }
+}
+foreach Idx0 = 1...4 in {
+  foreach Idx1 = 1...4 in {
+    defvar Cb = !add(1, !shl(1, Idx0));
+    defvar CImm = !add(Cb, !shl(Cb, Idx1));
+    def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)),
+              (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)),
+                      (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), (i32 Idx1))>;
   }
 }
 } // Predicates = [IsLA32]
@@ -969,6 +978,18 @@ foreach Idx0 = 1...4 in {
                       GPR:$r, (i64 Idx1))>;
   }
 }
+foreach Idx0 = 1...4 in {
+  foreach Idx1 = 1...4 in {
+    defvar Cb = !add(1, !shl(1, Idx0));
+    defvar CImm = !add(Cb, !shl(Cb, Idx1));
+    def : Pat<(sext_inreg (mul_const_oneuse GPR:$r, (i64 CImm)), i32),
+              (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)),
+                      (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>;
+    def : Pat<(mul_const_oneuse GPR:$r, (i64 CImm)),
+              (ALSL_D (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)),
+                      (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>;
+  }
+}
 } // Predicates = [IsLA64]
 
 foreach Idx = 1...7 in {
index bf9f0e9..79bea7b 100644 (file)
@@ -368,15 +368,14 @@ define signext i32 @mul_i32_25(i32 %a) {
 define signext i32 @mul_i32_27(i32 %a) {
 ; LA32-LABEL: mul_i32_27:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a1, $zero, 27
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 3
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_27:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 27
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 1
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 3
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 27
   ret i32 %b
@@ -433,15 +432,14 @@ define signext i32 @mul_i32_41(i32 %a) {
 define signext i32 @mul_i32_45(i32 %a) {
 ; LA32-LABEL: mul_i32_45:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a1, $zero, 45
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 2
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 3
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_45:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 45
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 2
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 3
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 45
   ret i32 %b
@@ -466,15 +464,14 @@ define signext i32 @mul_i32_49(i32 %a) {
 define signext i32 @mul_i32_51(i32 %a) {
 ; LA32-LABEL: mul_i32_51:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a1, $zero, 51
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_51:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 51
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 1
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 51
   ret i32 %b
@@ -531,15 +528,14 @@ define signext i32 @mul_i32_81(i32 %a) {
 define signext i32 @mul_i32_85(i32 %a) {
 ; LA32-LABEL: mul_i32_85:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a1, $zero, 85
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 2
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_85:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 85
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 2
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 85
   ret i32 %b
@@ -580,15 +576,14 @@ define signext i32 @mul_i32_145(i32 %a) {
 define signext i32 @mul_i32_153(i32 %a) {
 ; LA32-LABEL: mul_i32_153:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a1, $zero, 153
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 3
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_153:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 153
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 3
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 153
   ret i32 %b
@@ -613,15 +608,14 @@ define signext i32 @mul_i32_273(i32 %a) {
 define signext i32 @mul_i32_289(i32 %a) {
 ; LA32-LABEL: mul_i32_289:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a1, $zero, 289
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 4
+; LA32-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_289:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 289
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 4
+; LA64-NEXT:    alsl.w $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 289
   ret i32 %b
@@ -734,8 +728,8 @@ define i64 @mul_i64_27(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_27:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 27
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 3
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 27
   ret i64 %b
@@ -810,8 +804,8 @@ define i64 @mul_i64_45(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_45:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 45
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 2
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 3
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 45
   ret i64 %b
@@ -848,8 +842,8 @@ define i64 @mul_i64_51(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_51:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 51
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 51
   ret i64 %b
@@ -924,8 +918,8 @@ define i64 @mul_i64_85(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_85:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 85
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 2
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 85
   ret i64 %b
@@ -981,8 +975,8 @@ define i64 @mul_i64_153(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_153:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 153
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 3
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 153
   ret i64 %b
@@ -1019,8 +1013,8 @@ define i64 @mul_i64_289(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_289:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a1, $zero, 289
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 4
+; LA64-NEXT:    alsl.d $a0, $a0, $a0, 4
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 289
   ret i64 %b