[llvm] c8a2301 - [LoongArch] Optimize multiplication with immediates
Ben Shi via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 6 17:47:05 PDT 2023
Author: Ben Shi
Date: 2023-04-07T08:46:49+08:00
New Revision: c8a2301555a2ce7fb2e0b8a0e3ad080c77403735
URL: https://github.com/llvm/llvm-project/commit/c8a2301555a2ce7fb2e0b8a0e3ad080c77403735
DIFF: https://github.com/llvm/llvm-project/commit/c8a2301555a2ce7fb2e0b8a0e3ad080c77403735.diff
LOG: [LoongArch] Optimize multiplication with immediates
Optimize "(mul r, c)" to "(SLLI (ALSL r, r, i0), i1)", in which
"c = (1 + (1 << i0)) << i1".
Reviewed By: SixWeining
Differential Revision: https://reviews.llvm.org/D147428
Added:
Modified:
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 31145ceeb9ab8..8ea8b76f6797c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -428,6 +428,38 @@ def AddiPairImmSmall : SDNodeXForm<imm, [{
N->getValueType(0));
}]>;
+// Check if (mul r, imm) can be optimized to (SLLI (ALSL r, r, i0), i1),
+// in which imm = (1 + (1 << i0)) << i1.
+def AlslSlliImm : PatLeaf<(imm), [{
+ if (!N->hasOneUse())
+ return false;
+ uint64_t Imm = N->getZExtValue();
+ unsigned I1 = llvm::countr_zero(Imm);
+ uint64_t Rem = Imm >> I1;
+ return Rem == 3 || Rem == 5 || Rem == 9 || Rem == 17;
+}]>;
+
+def AlslSlliImmI1 : SDNodeXForm<imm, [{
+ uint64_t Imm = N->getZExtValue();
+ unsigned I1 = llvm::countr_zero(Imm);
+ return CurDAG->getTargetConstant(I1, SDLoc(N),
+ N->getValueType(0));
+}]>;
+
+def AlslSlliImmI0 : SDNodeXForm<imm, [{
+ uint64_t Imm = N->getZExtValue();
+ unsigned I1 = llvm::countr_zero(Imm);
+ uint64_t I0;
+ switch (Imm >> I1) {
+ case 3: I0 = 1; break;
+ case 5: I0 = 2; break;
+ case 9: I0 = 3; break;
+ default: I0 = 4; break;
+ }
+ return CurDAG->getTargetConstant(I0, SDLoc(N),
+ N->getValueType(0));
+}]>;
+
//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
@@ -992,6 +1024,21 @@ foreach Idx0 = 1...4 in {
}
} // Predicates = [IsLA64]
+let Predicates = [IsLA32] in {
+def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)),
+ (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)),
+ (AlslSlliImmI1 AlslSlliImm:$im))>;
+} // Predicates = [IsLA32]
+
+let Predicates = [IsLA64] in {
+def : Pat<(sext_inreg (mul GPR:$rj, (AlslSlliImm:$im)), i32),
+ (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)),
+ (AlslSlliImmI1 AlslSlliImm:$im))>;
+def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)),
+ (SLLI_D (ALSL_D GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)),
+ (AlslSlliImmI1 AlslSlliImm:$im))>;
+} // Predicates = [IsLA64]
+
foreach Idx = 1...7 in {
defvar ShamtA = !mul(8, Idx);
defvar ShamtB = !mul(8, !sub(8, Idx));
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll
index c4a4bc310ddd7..8e18ec578f5fa 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll
@@ -1167,15 +1167,14 @@ define i64 @mul_i64_4112(i64 %a) {
define signext i32 @mul_i32_768(i32 %a) {
; LA32-LABEL: mul_i32_768:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a1, $zero, 768
-; LA32-NEXT: mul.w $a0, $a0, $a1
+; LA32-NEXT: alsl.w $a0, $a0, $a0, 1
+; LA32-NEXT: slli.w $a0, $a0, 8
; LA32-NEXT: ret
;
; LA64-LABEL: mul_i32_768:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 768
-; LA64-NEXT: mul.d $a0, $a0, $a1
-; LA64-NEXT: addi.w $a0, $a0, 0
+; LA64-NEXT: alsl.w $a0, $a0, $a0, 1
+; LA64-NEXT: slli.w $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i32 %a, 768
ret i32 %b
@@ -1184,15 +1183,14 @@ define signext i32 @mul_i32_768(i32 %a) {
define signext i32 @mul_i32_1280(i32 %a) {
; LA32-LABEL: mul_i32_1280:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a1, $zero, 1280
-; LA32-NEXT: mul.w $a0, $a0, $a1
+; LA32-NEXT: alsl.w $a0, $a0, $a0, 2
+; LA32-NEXT: slli.w $a0, $a0, 8
; LA32-NEXT: ret
;
; LA64-LABEL: mul_i32_1280:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 1280
-; LA64-NEXT: mul.d $a0, $a0, $a1
-; LA64-NEXT: addi.w $a0, $a0, 0
+; LA64-NEXT: alsl.w $a0, $a0, $a0, 2
+; LA64-NEXT: slli.w $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i32 %a, 1280
ret i32 %b
@@ -1201,15 +1199,14 @@ define signext i32 @mul_i32_1280(i32 %a) {
define signext i32 @mul_i32_2304(i32 %a) {
; LA32-LABEL: mul_i32_2304:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a1, $zero, 2304
-; LA32-NEXT: mul.w $a0, $a0, $a1
+; LA32-NEXT: alsl.w $a0, $a0, $a0, 3
+; LA32-NEXT: slli.w $a0, $a0, 8
; LA32-NEXT: ret
;
; LA64-LABEL: mul_i32_2304:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 2304
-; LA64-NEXT: mul.d $a0, $a0, $a1
-; LA64-NEXT: addi.w $a0, $a0, 0
+; LA64-NEXT: alsl.w $a0, $a0, $a0, 3
+; LA64-NEXT: slli.w $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i32 %a, 2304
ret i32 %b
@@ -1218,17 +1215,14 @@ define signext i32 @mul_i32_2304(i32 %a) {
define signext i32 @mul_i32_4352(i32 %a) {
; LA32-LABEL: mul_i32_4352:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a1, 1
-; LA32-NEXT: ori $a1, $a1, 256
-; LA32-NEXT: mul.w $a0, $a0, $a1
+; LA32-NEXT: alsl.w $a0, $a0, $a0, 4
+; LA32-NEXT: slli.w $a0, $a0, 8
; LA32-NEXT: ret
;
; LA64-LABEL: mul_i32_4352:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 1
-; LA64-NEXT: ori $a1, $a1, 256
-; LA64-NEXT: mul.d $a0, $a0, $a1
-; LA64-NEXT: addi.w $a0, $a0, 0
+; LA64-NEXT: alsl.w $a0, $a0, $a0, 4
+; LA64-NEXT: slli.w $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i32 %a, 4352
ret i32 %b
@@ -1246,8 +1240,8 @@ define i64 @mul_i64_768(i64 %a) {
;
; LA64-LABEL: mul_i64_768:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 768
-; LA64-NEXT: mul.d $a0, $a0, $a1
+; LA64-NEXT: alsl.d $a0, $a0, $a0, 1
+; LA64-NEXT: slli.d $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i64 %a, 768
ret i64 %b
@@ -1265,8 +1259,8 @@ define i64 @mul_i64_1280(i64 %a) {
;
; LA64-LABEL: mul_i64_1280:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 1280
-; LA64-NEXT: mul.d $a0, $a0, $a1
+; LA64-NEXT: alsl.d $a0, $a0, $a0, 2
+; LA64-NEXT: slli.d $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i64 %a, 1280
ret i64 %b
@@ -1284,8 +1278,8 @@ define i64 @mul_i64_2304(i64 %a) {
;
; LA64-LABEL: mul_i64_2304:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 2304
-; LA64-NEXT: mul.d $a0, $a0, $a1
+; LA64-NEXT: alsl.d $a0, $a0, $a0, 3
+; LA64-NEXT: slli.d $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i64 %a, 2304
ret i64 %b
@@ -1304,9 +1298,8 @@ define i64 @mul_i64_4352(i64 %a) {
;
; LA64-LABEL: mul_i64_4352:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 1
-; LA64-NEXT: ori $a1, $a1, 256
-; LA64-NEXT: mul.d $a0, $a0, $a1
+; LA64-NEXT: alsl.d $a0, $a0, $a0, 4
+; LA64-NEXT: slli.d $a0, $a0, 8
; LA64-NEXT: ret
%b = mul i64 %a, 4352
ret i64 %b
More information about the llvm-commits
mailing list