[llvm] ec37a35 - [LoongArch] Optimize additions with immediates
Ben Shi via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 30 23:47:37 PDT 2023
Author: Ben Shi
Date: 2023-03-31T14:47:19+08:00
New Revision: ec37a35a8cfa43f94745b47e615fa5ccd3d9ec06
URL: https://github.com/llvm/llvm-project/commit/ec37a35a8cfa43f94745b47e615fa5ccd3d9ec06
DIFF: https://github.com/llvm/llvm-project/commit/ec37a35a8cfa43f94745b47e615fa5ccd3d9ec06.diff
LOG: [LoongArch] Optimize additions with immediates
Reviewed By: SixWeining, xen0n
Differential Revision: https://reviews.llvm.org/D147222
Added:
Modified:
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
llvm/test/CodeGen/LoongArch/ldptr.ll
llvm/test/CodeGen/LoongArch/stptr.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 9ba648dfa0481..343c070e32c64 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -403,6 +403,31 @@ def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa),
return N->getFlags().hasNoSignedZeros();
}]>;
+// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1),
+// in which imm = imm0 + imm1, and both imm0 & imm1 are simm12.
+def AddiPair : PatLeaf<(imm), [{
+ if (!N->hasOneUse())
+ return false;
+ // The immediate operand must be in range [-4096,-2049] or [2048,4094].
+ int64_t Imm = N->getSExtValue();
+ return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);
+}]>;
+
+// Return -2048 if immediate is negative or 2047 if positive.
+def AddiPairImmLarge : SDNodeXForm<imm, [{
+ int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047;
+ return CurDAG->getTargetConstant(Imm, SDLoc(N),
+ N->getValueType(0));
+}]>;
+
+// Return imm - (imm < 0 ? -2048 : 2047).
+def AddiPairImmSmall : SDNodeXForm<imm, [{
+ int64_t Imm = N->getSExtValue();
+ int64_t Adj = Imm < 0 ? -2048 : 2047;
+ return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N),
+ N->getValueType(0));
+}]>;
+
//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
@@ -899,6 +924,21 @@ def : Pat<(sext_inreg (add GPR:$rj, simm32_hi16_lo12:$imm), i32),
(ADDI_W (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)),
(LO12 $imm))>;
+let Predicates = [IsLA32] in {
+def : Pat<(add GPR:$rj, (AddiPair:$im)),
+ (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)),
+ (AddiPairImmSmall AddiPair:$im))>;
+} // Predicates = [IsLA32]
+
+let Predicates = [IsLA64] in {
+def : Pat<(add GPR:$rj, (AddiPair:$im)),
+ (ADDI_D (ADDI_D GPR:$rj, (AddiPairImmLarge AddiPair:$im)),
+ (AddiPairImmSmall AddiPair:$im))>;
+def : Pat<(sext_inreg (add GPR:$rj, (AddiPair:$im)), i32),
+ (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)),
+ (AddiPairImmSmall AddiPair:$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/inline-asm-constraint-m.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
index 129368aee1d31..b6d8893d8ac97 100644
--- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
@@ -5,9 +5,8 @@
define i32 @m_offset_neg_2049(ptr %p) nounwind {
; LA32-LABEL: m_offset_neg_2049:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a1, -1
-; LA32-NEXT: ori $a1, $a1, 2047
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, -2048
+; LA32-NEXT: addi.w $a0, $a0, -1
; LA32-NEXT: #APP
; LA32-NEXT: ld.w $a0, $a0, 0
; LA32-NEXT: #NO_APP
@@ -15,9 +14,8 @@ define i32 @m_offset_neg_2049(ptr %p) nounwind {
;
; LA64-LABEL: m_offset_neg_2049:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -1
-; LA64-NEXT: ori $a1, $a1, 2047
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, -2048
+; LA64-NEXT: addi.d $a0, $a0, -1
; LA64-NEXT: #APP
; LA64-NEXT: ld.w $a0, $a0, 0
; LA64-NEXT: #NO_APP
@@ -124,8 +122,8 @@ define i32 @m_offset_2047(ptr %p) nounwind {
define i32 @m_offset_2048(ptr %p) nounwind {
; LA32-LABEL: m_offset_2048:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a1, $zero, 2048
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a0, $a0, 1
; LA32-NEXT: #APP
; LA32-NEXT: ld.w $a0, $a0, 0
; LA32-NEXT: #NO_APP
@@ -133,8 +131,8 @@ define i32 @m_offset_2048(ptr %p) nounwind {
;
; LA64-LABEL: m_offset_2048:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 2048
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, 2047
+; LA64-NEXT: addi.d $a0, $a0, 1
; LA64-NEXT: #APP
; LA64-NEXT: ld.w $a0, $a0, 0
; LA64-NEXT: #NO_APP
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
index 070a7483bfd29..2c504efca26d1 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
@@ -707,14 +707,14 @@ define signext i32 @add_i32_minus_0x80000800_sext(i32 %x) {
define signext i32 @add_i32_4080(i32 %x) {
; LA32-LABEL: add_i32_4080:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a1, $zero, 4080
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a0, $a0, 2033
; LA32-NEXT: ret
;
; LA64-LABEL: add_i32_4080:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 4080
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addi.w $a0, $a0, 2047
+; LA64-NEXT: addi.w $a0, $a0, 2033
; LA64-NEXT: ret
%add = add i32 %x, 4080
ret i32 %add
@@ -723,16 +723,14 @@ define signext i32 @add_i32_4080(i32 %x) {
define signext i32 @add_i32_minus_4080(i32 %x) {
; LA32-LABEL: add_i32_minus_4080:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a1, -1
-; LA32-NEXT: ori $a1, $a1, 16
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, -2048
+; LA32-NEXT: addi.w $a0, $a0, -2032
; LA32-NEXT: ret
;
; LA64-LABEL: add_i32_minus_4080:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -1
-; LA64-NEXT: ori $a1, $a1, 16
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addi.w $a0, $a0, -2048
+; LA64-NEXT: addi.w $a0, $a0, -2032
; LA64-NEXT: ret
%add = add i32 %x, -4080
ret i32 %add
@@ -741,14 +739,14 @@ define signext i32 @add_i32_minus_4080(i32 %x) {
define signext i32 @add_i32_2048(i32 %x) {
; LA32-LABEL: add_i32_2048:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a1, $zero, 2048
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a0, $a0, 1
; LA32-NEXT: ret
;
; LA64-LABEL: add_i32_2048:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 2048
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addi.w $a0, $a0, 2047
+; LA64-NEXT: addi.w $a0, $a0, 1
; LA64-NEXT: ret
%add = add i32 %x, 2048
ret i32 %add
@@ -757,14 +755,14 @@ define signext i32 @add_i32_2048(i32 %x) {
define signext i32 @add_i32_4094(i32 %x) {
; LA32-LABEL: add_i32_4094:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a1, $zero, 4094
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a0, $a0, 2047
; LA32-NEXT: ret
;
; LA64-LABEL: add_i32_4094:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 4094
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addi.w $a0, $a0, 2047
+; LA64-NEXT: addi.w $a0, $a0, 2047
; LA64-NEXT: ret
%add = add i32 %x, 4094
ret i32 %add
@@ -773,16 +771,14 @@ define signext i32 @add_i32_4094(i32 %x) {
define signext i32 @add_i32_minus_2049(i32 %x) {
; LA32-LABEL: add_i32_minus_2049:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a1, -1
-; LA32-NEXT: ori $a1, $a1, 2047
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, -2048
+; LA32-NEXT: addi.w $a0, $a0, -1
; LA32-NEXT: ret
;
; LA64-LABEL: add_i32_minus_2049:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -1
-; LA64-NEXT: ori $a1, $a1, 2047
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addi.w $a0, $a0, -2048
+; LA64-NEXT: addi.w $a0, $a0, -1
; LA64-NEXT: ret
%add = add i32 %x, -2049
ret i32 %add
@@ -791,14 +787,14 @@ define signext i32 @add_i32_minus_2049(i32 %x) {
define signext i32 @add_i32_minus_4096(i32 %x) {
; LA32-LABEL: add_i32_minus_4096:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a1, -1
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, -2048
+; LA32-NEXT: addi.w $a0, $a0, -2048
; LA32-NEXT: ret
;
; LA64-LABEL: add_i32_minus_4096:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -1
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addi.w $a0, $a0, -2048
+; LA64-NEXT: addi.w $a0, $a0, -2048
; LA64-NEXT: ret
%add = add i32 %x, -4096
ret i32 %add
@@ -807,8 +803,8 @@ define signext i32 @add_i32_minus_4096(i32 %x) {
define i64 @add_i64_4080(i64 %x) {
; LA32-LABEL: add_i64_4080:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a2, $zero, 4080
-; LA32-NEXT: add.w $a2, $a0, $a2
+; LA32-NEXT: addi.w $a2, $a0, 2047
+; LA32-NEXT: addi.w $a2, $a2, 2033
; LA32-NEXT: sltu $a0, $a2, $a0
; LA32-NEXT: add.w $a1, $a1, $a0
; LA32-NEXT: move $a0, $a2
@@ -816,8 +812,8 @@ define i64 @add_i64_4080(i64 %x) {
;
; LA64-LABEL: add_i64_4080:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 4080
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, 2047
+; LA64-NEXT: addi.d $a0, $a0, 2033
; LA64-NEXT: ret
%add = add i64 %x, 4080
ret i64 %add
@@ -826,9 +822,8 @@ define i64 @add_i64_4080(i64 %x) {
define i64 @add_i64_minus_4080(i64 %x) {
; LA32-LABEL: add_i64_minus_4080:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a2, -1
-; LA32-NEXT: ori $a2, $a2, 16
-; LA32-NEXT: add.w $a2, $a0, $a2
+; LA32-NEXT: addi.w $a2, $a0, -2048
+; LA32-NEXT: addi.w $a2, $a2, -2032
; LA32-NEXT: sltu $a0, $a2, $a0
; LA32-NEXT: add.w $a0, $a1, $a0
; LA32-NEXT: addi.w $a1, $a0, -1
@@ -837,9 +832,8 @@ define i64 @add_i64_minus_4080(i64 %x) {
;
; LA64-LABEL: add_i64_minus_4080:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -1
-; LA64-NEXT: ori $a1, $a1, 16
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, -2048
+; LA64-NEXT: addi.d $a0, $a0, -2032
; LA64-NEXT: ret
%add = add i64 %x, -4080
ret i64 %add
@@ -848,8 +842,8 @@ define i64 @add_i64_minus_4080(i64 %x) {
define i64 @add_i64_2048(i64 %x) {
; LA32-LABEL: add_i64_2048:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a2, $zero, 2048
-; LA32-NEXT: add.w $a2, $a0, $a2
+; LA32-NEXT: addi.w $a2, $a0, 2047
+; LA32-NEXT: addi.w $a2, $a2, 1
; LA32-NEXT: sltu $a0, $a2, $a0
; LA32-NEXT: add.w $a1, $a1, $a0
; LA32-NEXT: move $a0, $a2
@@ -857,8 +851,8 @@ define i64 @add_i64_2048(i64 %x) {
;
; LA64-LABEL: add_i64_2048:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 2048
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, 2047
+; LA64-NEXT: addi.d $a0, $a0, 1
; LA64-NEXT: ret
%add = add i64 %x, 2048
ret i64 %add
@@ -867,8 +861,8 @@ define i64 @add_i64_2048(i64 %x) {
define i64 @add_i64_4094(i64 %x) {
; LA32-LABEL: add_i64_4094:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a2, $zero, 4094
-; LA32-NEXT: add.w $a2, $a0, $a2
+; LA32-NEXT: addi.w $a2, $a0, 2047
+; LA32-NEXT: addi.w $a2, $a2, 2047
; LA32-NEXT: sltu $a0, $a2, $a0
; LA32-NEXT: add.w $a1, $a1, $a0
; LA32-NEXT: move $a0, $a2
@@ -876,8 +870,8 @@ define i64 @add_i64_4094(i64 %x) {
;
; LA64-LABEL: add_i64_4094:
; LA64: # %bb.0:
-; LA64-NEXT: ori $a1, $zero, 4094
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, 2047
+; LA64-NEXT: addi.d $a0, $a0, 2047
; LA64-NEXT: ret
%add = add i64 %x, 4094
ret i64 %add
@@ -886,9 +880,8 @@ define i64 @add_i64_4094(i64 %x) {
define i64 @add_i64_minus_2049(i64 %x) {
; LA32-LABEL: add_i64_minus_2049:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a2, -1
-; LA32-NEXT: ori $a2, $a2, 2047
-; LA32-NEXT: add.w $a2, $a0, $a2
+; LA32-NEXT: addi.w $a2, $a0, -2048
+; LA32-NEXT: addi.w $a2, $a2, -1
; LA32-NEXT: sltu $a0, $a2, $a0
; LA32-NEXT: add.w $a0, $a1, $a0
; LA32-NEXT: addi.w $a1, $a0, -1
@@ -897,9 +890,8 @@ define i64 @add_i64_minus_2049(i64 %x) {
;
; LA64-LABEL: add_i64_minus_2049:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -1
-; LA64-NEXT: ori $a1, $a1, 2047
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, -2048
+; LA64-NEXT: addi.d $a0, $a0, -1
; LA64-NEXT: ret
%add = add i64 %x, -2049
ret i64 %add
@@ -908,8 +900,8 @@ define i64 @add_i64_minus_2049(i64 %x) {
define i64 @add_i64_minus_4096(i64 %x) {
; LA32-LABEL: add_i64_minus_4096:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a2, -1
-; LA32-NEXT: add.w $a2, $a0, $a2
+; LA32-NEXT: addi.w $a2, $a0, -2048
+; LA32-NEXT: addi.w $a2, $a2, -2048
; LA32-NEXT: sltu $a0, $a2, $a0
; LA32-NEXT: add.w $a0, $a1, $a0
; LA32-NEXT: addi.w $a1, $a0, -1
@@ -918,8 +910,8 @@ define i64 @add_i64_minus_4096(i64 %x) {
;
; LA64-LABEL: add_i64_minus_4096:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -1
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addi.d $a0, $a0, -2048
+; LA64-NEXT: addi.d $a0, $a0, -2048
; LA64-NEXT: ret
%add = add i64 %x, -4096
ret i64 %add
diff --git a/llvm/test/CodeGen/LoongArch/ldptr.ll b/llvm/test/CodeGen/LoongArch/ldptr.ll
index bab449b3c4607..c7c2374d5fd58 100644
--- a/llvm/test/CodeGen/LoongArch/ldptr.ll
+++ b/llvm/test/CodeGen/LoongArch/ldptr.ll
@@ -23,8 +23,8 @@ entry:
define signext i32 @ldptr_w(ptr %p) nounwind {
; LA32-LABEL: ldptr_w:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: ori $a1, $zero, 2048
-; LA32-NEXT: add.w $a0, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a0, $a0, 1
; LA32-NEXT: ld.w $a0, $a0, 0
; LA32-NEXT: ret
;
@@ -81,8 +81,8 @@ entry:
define i64 @ldptr_d(ptr %p) nounwind {
; LA32-LABEL: ldptr_d:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: ori $a1, $zero, 2048
-; LA32-NEXT: add.w $a1, $a0, $a1
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a1, $a0, 1
; LA32-NEXT: ld.w $a0, $a1, 0
; LA32-NEXT: ld.w $a1, $a1, 4
; LA32-NEXT: ret
diff --git a/llvm/test/CodeGen/LoongArch/stptr.ll b/llvm/test/CodeGen/LoongArch/stptr.ll
index 644a931ca7584..cc198f9c2f8cc 100644
--- a/llvm/test/CodeGen/LoongArch/stptr.ll
+++ b/llvm/test/CodeGen/LoongArch/stptr.ll
@@ -22,8 +22,8 @@ define void @stptr_w_too_small_offset(ptr %p, i32 signext %val) nounwind {
define void @stptr_w(ptr %p, i32 signext %val) nounwind {
; LA32-LABEL: stptr_w:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a2, $zero, 2048
-; LA32-NEXT: add.w $a0, $a0, $a2
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a0, $a0, 1
; LA32-NEXT: st.w $a1, $a0, 0
; LA32-NEXT: ret
;
@@ -76,8 +76,8 @@ define void @stptr_d_too_small_offset(ptr %p, i64 %val) nounwind {
define void @stptr_d(ptr %p, i64 %val) nounwind {
; LA32-LABEL: stptr_d:
; LA32: # %bb.0:
-; LA32-NEXT: ori $a3, $zero, 2048
-; LA32-NEXT: add.w $a0, $a0, $a3
+; LA32-NEXT: addi.w $a0, $a0, 2047
+; LA32-NEXT: addi.w $a0, $a0, 1
; LA32-NEXT: st.w $a2, $a0, 4
; LA32-NEXT: st.w $a1, $a0, 0
; LA32-NEXT: ret
More information about the llvm-commits
mailing list