[llvm] d88ffb0 - [LoongArch] Optimize multiplication with immediates

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 2 20:29:04 PDT 2023


Author: Ben Shi
Date: 2023-04-03T11:26:25+08:00
New Revision: d88ffb0dc5af42b15864e770600f1e812b9545c1

URL: https://github.com/llvm/llvm-project/commit/d88ffb0dc5af42b15864e770600f1e812b9545c1
DIFF: https://github.com/llvm/llvm-project/commit/d88ffb0dc5af42b15864e770600f1e812b9545c1.diff

LOG: [LoongArch] Optimize multiplication with immediates

Optimize 'x * c' to (ALSL x, (SLLI x, i0), i1) in which
c = (1 << i0) | (1 << i1).

Reviewed By: xen0n, SixWeining

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

Added: 
    

Modified: 
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/test/CodeGen/LoongArch/alsl.ll
    llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 73cbd63376fa4..4cf943ea5d1c5 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -3131,12 +3131,17 @@ bool LoongArchTargetLowering::decomposeMulByConstant(LLVMContext &Context,
   if (VT.getSizeInBits() > Subtarget.getGRLen())
     return false;
 
-  // Break MUL into (SLLI + ADD/SUB) or ALSL.
   if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) {
     const APInt &Imm = ConstNode->getAPIntValue();
+    // Break MUL into (SLLI + ADD/SUB) or ALSL.
     if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
         (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
       return true;
+    // Break MUL into (ALSL x, (SLLI x, imm0), imm1).
+    if (ConstNode->hasOneUse() &&
+        ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
+         (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
+      return true;
   }
 
   return false;

diff  --git a/llvm/test/CodeGen/LoongArch/alsl.ll b/llvm/test/CodeGen/LoongArch/alsl.ll
index e296dabb38362..650f504dcaf83 100644
--- a/llvm/test/CodeGen/LoongArch/alsl.ll
+++ b/llvm/test/CodeGen/LoongArch/alsl.ll
@@ -149,15 +149,15 @@ entry:
 define i16 @mul_add_i16(i16 signext %a, i16 signext %b) nounwind {
 ; LA32-LABEL: mul_add_i16:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    ori $a2, $zero, 10
-; LA32-NEXT:    mul.w $a0, $a0, $a2
+; LA32-NEXT:    slli.w $a2, $a0, 3
+; LA32-NEXT:    alsl.w $a0, $a0, $a2, 1
 ; LA32-NEXT:    add.w $a0, $a1, $a0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_add_i16:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    ori $a2, $zero, 10
-; LA64-NEXT:    mul.d $a0, $a0, $a2
+; LA64-NEXT:    slli.d $a2, $a0, 3
+; LA64-NEXT:    alsl.d $a0, $a0, $a2, 1
 ; LA64-NEXT:    add.d $a0, $a1, $a0
 ; LA64-NEXT:    ret
 entry:
@@ -169,15 +169,15 @@ entry:
 define i32 @mul_add_i32(i32 signext %a, i32 signext %b) nounwind {
 ; LA32-LABEL: mul_add_i32:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    ori $a2, $zero, 12
-; LA32-NEXT:    mul.w $a0, $a0, $a2
+; LA32-NEXT:    slli.w $a2, $a0, 3
+; LA32-NEXT:    alsl.w $a0, $a0, $a2, 2
 ; LA32-NEXT:    add.w $a0, $a1, $a0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_add_i32:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    ori $a2, $zero, 12
-; LA64-NEXT:    mul.d $a0, $a0, $a2
+; LA64-NEXT:    slli.d $a2, $a0, 3
+; LA64-NEXT:    alsl.d $a0, $a0, $a2, 2
 ; LA64-NEXT:    add.d $a0, $a1, $a0
 ; LA64-NEXT:    ret
 entry:

diff  --git a/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll
index e1ccdc67c4a75..c84fe1a7666f2 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll
@@ -1023,17 +1023,15 @@ define i64 @mul_i64_289(i64 %a) {
 define signext i32 @mul_i32_4098(i32 %a) {
 ; LA32-LABEL: mul_i32_4098:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    lu12i.w $a1, 1
-; LA32-NEXT:    ori $a1, $a1, 2
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    slli.w $a1, $a0, 12
+; LA32-NEXT:    alsl.w $a0, $a0, $a1, 1
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_4098:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 2
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    slli.d $a1, $a0, 1
+; LA64-NEXT:    slli.d $a0, $a0, 12
+; LA64-NEXT:    add.w $a0, $a0, $a1
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 4098
   ret i32 %b
@@ -1042,17 +1040,15 @@ define signext i32 @mul_i32_4098(i32 %a) {
 define signext i32 @mul_i32_4100(i32 %a) {
 ; LA32-LABEL: mul_i32_4100:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    lu12i.w $a1, 1
-; LA32-NEXT:    ori $a1, $a1, 4
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    slli.w $a1, $a0, 12
+; LA32-NEXT:    alsl.w $a0, $a0, $a1, 2
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_4100:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 4
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    slli.d $a1, $a0, 2
+; LA64-NEXT:    slli.d $a0, $a0, 12
+; LA64-NEXT:    add.w $a0, $a0, $a1
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 4100
   ret i32 %b
@@ -1061,17 +1057,15 @@ define signext i32 @mul_i32_4100(i32 %a) {
 define signext i32 @mul_i32_4104(i32 %a) {
 ; LA32-LABEL: mul_i32_4104:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    lu12i.w $a1, 1
-; LA32-NEXT:    ori $a1, $a1, 8
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    slli.w $a1, $a0, 12
+; LA32-NEXT:    alsl.w $a0, $a0, $a1, 3
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_4104:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 8
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    slli.d $a1, $a0, 3
+; LA64-NEXT:    slli.d $a0, $a0, 12
+; LA64-NEXT:    add.w $a0, $a0, $a1
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 4104
   ret i32 %b
@@ -1080,17 +1074,15 @@ define signext i32 @mul_i32_4104(i32 %a) {
 define signext i32 @mul_i32_4112(i32 %a) {
 ; LA32-LABEL: mul_i32_4112:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    lu12i.w $a1, 1
-; LA32-NEXT:    ori $a1, $a1, 16
-; LA32-NEXT:    mul.w $a0, $a0, $a1
+; LA32-NEXT:    slli.w $a1, $a0, 12
+; LA32-NEXT:    alsl.w $a0, $a0, $a1, 4
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: mul_i32_4112:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 16
-; LA64-NEXT:    mul.d $a0, $a0, $a1
-; LA64-NEXT:    addi.w $a0, $a0, 0
+; LA64-NEXT:    slli.d $a1, $a0, 4
+; LA64-NEXT:    slli.d $a0, $a0, 12
+; LA64-NEXT:    add.w $a0, $a0, $a1
 ; LA64-NEXT:    ret
   %b = mul i32 %a, 4112
   ret i32 %b
@@ -1109,9 +1101,8 @@ define i64 @mul_i64_4098(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_4098:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 2
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    slli.d $a1, $a0, 12
+; LA64-NEXT:    alsl.d $a0, $a0, $a1, 1
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 4098
   ret i64 %b
@@ -1130,9 +1121,8 @@ define i64 @mul_i64_4100(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_4100:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 4
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    slli.d $a1, $a0, 12
+; LA64-NEXT:    alsl.d $a0, $a0, $a1, 2
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 4100
   ret i64 %b
@@ -1151,9 +1141,8 @@ define i64 @mul_i64_4104(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_4104:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 8
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    slli.d $a1, $a0, 12
+; LA64-NEXT:    alsl.d $a0, $a0, $a1, 3
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 4104
   ret i64 %b
@@ -1172,9 +1161,8 @@ define i64 @mul_i64_4112(i64 %a) {
 ;
 ; LA64-LABEL: mul_i64_4112:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    lu12i.w $a1, 1
-; LA64-NEXT:    ori $a1, $a1, 16
-; LA64-NEXT:    mul.d $a0, $a0, $a1
+; LA64-NEXT:    slli.d $a1, $a0, 12
+; LA64-NEXT:    alsl.d $a0, $a0, $a1, 4
 ; LA64-NEXT:    ret
   %b = mul i64 %a, 4112
   ret i64 %b


        


More information about the llvm-commits mailing list