[llvm] 2b8cb7d - [LoongArch] Make use of addu16i.d for adds with suitable immediates
Weining Lu via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 14 17:16:46 PST 2023
Author: WANG Xuerui
Date: 2023-02-15T09:16:14+08:00
New Revision: 2b8cb7d87fcb7c93ea4e60bed6185f05308c98f1
URL: https://github.com/llvm/llvm-project/commit/2b8cb7d87fcb7c93ea4e60bed6185f05308c98f1
DIFF: https://github.com/llvm/llvm-project/commit/2b8cb7d87fcb7c93ea4e60bed6185f05308c98f1.diff
LOG: [LoongArch] Make use of addu16i.d for adds with suitable immediates
Ideally `addu16i.d` could be paired with `{ld,st}ptr` for faster memory
accesses with 32-bit-aligned offsets (it was designed for this purpose),
but it would require more work and the original use case (GP-relative
accesses) does not exist any more with the current LoongArch psABI.
It could still be used for accelerating additions of certain constants
though, which is what this patch intends to do.
Reviewed By: SixWeining, gonglingqin
Differential Revision: https://reviews.llvm.org/D143710
Added:
Modified:
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 0e968e040ce23..0606c65f9d3b1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -328,6 +328,17 @@ def simm26_symbol : Operand<GRLenVT> {
let DecoderMethod = "decodeSImmOperand<26, 2>";
}
+// A 32-bit signed immediate with the lowest 16 bits zeroed, suitable for
+// direct use with `addu16i.d`.
+def simm16_lsl16 : Operand<GRLenVT>,
+ ImmLeaf<GRLenVT, [{return isShiftedInt<16, 16>(Imm);}]>;
+
+// A 32-bit signed immediate expressible with a pair of `addu16i.d + addi` for
+// use in additions.
+def simm32_hi16_lo12: Operand<GRLenVT>, ImmLeaf<GRLenVT, [{
+ return isShiftedInt<16, 16>(Imm - SignExtend64<12>(Imm));
+}]>;
+
def BareSymbol : AsmOperandClass {
let Name = "BareSymbol";
let RenderMethod = "addImmOperands";
@@ -363,6 +374,26 @@ def ImmSubFrom32 : SDNodeXForm<imm, [{
N->getValueType(0));
}]>;
+// Return the lowest 12 bits of the signed immediate.
+def LO12: SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant(SignExtend64<12>(N->getSExtValue()),
+ SDLoc(N), N->getValueType(0));
+}]>;
+
+// Return the higher 16 bits of the signed immediate.
+def HI16 : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant(N->getSExtValue() >> 16, SDLoc(N),
+ N->getValueType(0));
+}]>;
+
+// Return the higher 16 bits of the signed immediate, adjusted for use within an
+// `addu16i.d + addi` pair.
+def HI16ForAddu16idAddiPair: SDNodeXForm<imm, [{
+ auto Imm = N->getSExtValue();
+ return CurDAG->getTargetConstant((Imm - SignExtend64<12>(Imm)) >> 16,
+ SDLoc(N), N->getValueType(0));
+}]>;
+
def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
def AddrConstant : ComplexPattern<iPTR, 2, "SelectAddrConstant">;
def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">;
@@ -851,6 +882,15 @@ def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))),
def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)),
(loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))),
(MULW_D_WU GPR:$rj, GPR:$rk)>;
+
+def : Pat<(add GPR:$rj, simm16_lsl16:$imm),
+ (ADDU16I_D GPR:$rj, (HI16 $imm))>;
+def : Pat<(add GPR:$rj, simm32_hi16_lo12:$imm),
+ (ADDI_D (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)),
+ (LO12 $imm))>;
+def : Pat<(sext_inreg (add GPR:$rj, simm32_hi16_lo12:$imm), i32),
+ (ADDI_W (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)),
+ (LO12 $imm))>;
} // Predicates = [IsLA64]
def : PatGprGpr<and, AND>;
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
index 2bf6c319f8e4e..3763cc2307de0 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
@@ -183,7 +183,7 @@ define i64 @add_i64_3(i64 %x) {
ret i64 %add
}
-;; TODO: emit `addu16i.d` for these cases.
+;; Check that `addu16i.d` is emitted for these cases.
define i32 @add_i32_0x12340000(i32 %x) {
; LA32-LABEL: add_i32_0x12340000:
@@ -194,8 +194,7 @@ define i32 @add_i32_0x12340000(i32 %x) {
;
; LA64-LABEL: add_i32_0x12340000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 74560
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 4660
; LA64-NEXT: ret
%add = add i32 %x, 305397760
ret i32 %add
@@ -210,8 +209,8 @@ define signext i32 @add_i32_0x12340000_sext(i32 %x) {
;
; LA64-LABEL: add_i32_0x12340000_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 74560
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 4660
+; LA64-NEXT: addi.w $a0, $a0, 0
; LA64-NEXT: ret
%add = add i32 %x, 305397760
ret i32 %add
@@ -229,8 +228,7 @@ define i64 @add_i64_0x12340000(i64 %x) {
;
; LA64-LABEL: add_i64_0x12340000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 74560
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 4660
; LA64-NEXT: ret
%add = add i64 %x, 305397760
ret i64 %add
@@ -245,8 +243,7 @@ define i32 @add_i32_0x7fff0000(i32 %x) {
;
; LA64-LABEL: add_i32_0x7fff0000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524272
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
; LA64-NEXT: ret
%add = add i32 %x, 2147418112
ret i32 %add
@@ -261,8 +258,8 @@ define signext i32 @add_i32_0x7fff0000_sext(i32 %x) {
;
; LA64-LABEL: add_i32_0x7fff0000_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524272
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
+; LA64-NEXT: addi.w $a0, $a0, 0
; LA64-NEXT: ret
%add = add i32 %x, 2147418112
ret i32 %add
@@ -280,8 +277,7 @@ define i64 @add_i64_0x7fff0000(i64 %x) {
;
; LA64-LABEL: add_i64_0x7fff0000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524272
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
; LA64-NEXT: ret
%add = add i64 %x, 2147418112
ret i64 %add
@@ -296,8 +292,7 @@ define i32 @add_i32_minus_0x80000000(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x80000000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -524288
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -32768
; LA64-NEXT: ret
%add = add i32 %x, -2147483648
ret i32 %add
@@ -312,8 +307,8 @@ define signext i32 @add_i32_minus_0x80000000_sext(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x80000000_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -524288
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -32768
+; LA64-NEXT: addi.w $a0, $a0, 0
; LA64-NEXT: ret
%add = add i32 %x, -2147483648
ret i32 %add
@@ -332,8 +327,7 @@ define i64 @add_i64_minus_0x80000000(i64 %x) {
;
; LA64-LABEL: add_i64_minus_0x80000000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -524288
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -32768
; LA64-NEXT: ret
%add = add i64 %x, -2147483648
ret i64 %add
@@ -348,8 +342,7 @@ define i32 @add_i32_minus_0x10000(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x10000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -16
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -1
; LA64-NEXT: ret
%add = add i32 %x, -65536
ret i32 %add
@@ -364,8 +357,8 @@ define signext i32 @add_i32_minus_0x10000_sext(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x10000_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -16
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -1
+; LA64-NEXT: addi.w $a0, $a0, 0
; LA64-NEXT: ret
%add = add i32 %x, -65536
ret i32 %add
@@ -384,14 +377,13 @@ define i64 @add_i64_minus_0x10000(i64 %x) {
;
; LA64-LABEL: add_i64_minus_0x10000:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -16
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -1
; LA64-NEXT: ret
%add = add i64 %x, -65536
ret i64 %add
}
-;; TODO: use `addu16i.d + addi` for these cases.
+;; Check that `addu16i.d + addi` is emitted for these cases.
define i32 @add_i32_0x7fff07ff(i32 %x) {
; LA32-LABEL: add_i32_0x7fff07ff:
@@ -403,9 +395,8 @@ define i32 @add_i32_0x7fff07ff(i32 %x) {
;
; LA64-LABEL: add_i32_0x7fff07ff:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524272
-; LA64-NEXT: ori $a1, $a1, 2047
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
+; LA64-NEXT: addi.d $a0, $a0, 2047
; LA64-NEXT: ret
%add = add i32 %x, 2147420159
ret i32 %add
@@ -421,9 +412,8 @@ define signext i32 @add_i32_0x7fff07ff_sext(i32 %x) {
;
; LA64-LABEL: add_i32_0x7fff07ff_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524272
-; LA64-NEXT: ori $a1, $a1, 2047
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
+; LA64-NEXT: addi.w $a0, $a0, 2047
; LA64-NEXT: ret
%add = add i32 %x, 2147420159
ret i32 %add
@@ -442,9 +432,8 @@ define i64 @add_i64_0x7fff07ff(i64 %x) {
;
; LA64-LABEL: add_i64_0x7fff07ff:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524272
-; LA64-NEXT: ori $a1, $a1, 2047
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
+; LA64-NEXT: addi.d $a0, $a0, 2047
; LA64-NEXT: ret
%add = add i64 %x, 2147420159
ret i64 %add
@@ -460,9 +449,8 @@ define i32 @add_i32_0x7ffef800(i32 %x) {
;
; LA64-LABEL: add_i32_0x7ffef800:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524271
-; LA64-NEXT: ori $a1, $a1, 2048
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
+; LA64-NEXT: addi.d $a0, $a0, -2048
; LA64-NEXT: ret
%add = add i32 %x, 2147416064
ret i32 %add
@@ -478,9 +466,8 @@ define signext i32 @add_i32_0x7ffef800_sext(i32 %x) {
;
; LA64-LABEL: add_i32_0x7ffef800_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524271
-; LA64-NEXT: ori $a1, $a1, 2048
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
+; LA64-NEXT: addi.w $a0, $a0, -2048
; LA64-NEXT: ret
%add = add i32 %x, 2147416064
ret i32 %add
@@ -499,9 +486,8 @@ define i64 @add_i64_0x7ffef800(i64 %x) {
;
; LA64-LABEL: add_i64_0x7ffef800:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524271
-; LA64-NEXT: ori $a1, $a1, 2048
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, 32767
+; LA64-NEXT: addi.d $a0, $a0, -2048
; LA64-NEXT: ret
%add = add i64 %x, 2147416064
ret i64 %add
@@ -521,10 +507,8 @@ define i64 @add_i64_minus_0x80000800(i64 %x) {
;
; LA64-LABEL: add_i64_minus_0x80000800:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 524287
-; LA64-NEXT: ori $a1, $a1, 2048
-; LA64-NEXT: lu32i.d $a1, -1
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -32768
+; LA64-NEXT: addi.d $a0, $a0, -2048
; LA64-NEXT: ret
%add = add i64 %x, -2147485696
ret i64 %add
@@ -540,9 +524,8 @@ define i32 @add_i32_minus_0x23450679(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x23450679:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -144465
-; LA64-NEXT: ori $a1, $a1, 2439
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -9029
+; LA64-NEXT: addi.d $a0, $a0, -1657
; LA64-NEXT: ret
%add = add i32 %x, -591726201
ret i32 %add
@@ -558,9 +541,8 @@ define signext i32 @add_i32_minus_0x23450679_sext(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x23450679_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -144465
-; LA64-NEXT: ori $a1, $a1, 2439
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -9029
+; LA64-NEXT: addi.w $a0, $a0, -1657
; LA64-NEXT: ret
%add = add i32 %x, -591726201
ret i32 %add
@@ -580,9 +562,8 @@ define i64 @add_i64_minus_0x23450679(i64 %x) {
;
; LA64-LABEL: add_i64_minus_0x23450679:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -144465
-; LA64-NEXT: ori $a1, $a1, 2439
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -9029
+; LA64-NEXT: addi.d $a0, $a0, -1657
; LA64-NEXT: ret
%add = add i64 %x, -591726201
ret i64 %add
@@ -598,9 +579,8 @@ define i32 @add_i32_minus_0x2345fedd(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x2345fedd:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -144480
-; LA64-NEXT: ori $a1, $a1, 291
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -9030
+; LA64-NEXT: addi.d $a0, $a0, 291
; LA64-NEXT: ret
%add = add i32 %x, -591789789
ret i32 %add
@@ -616,9 +596,8 @@ define signext i32 @add_i32_minus_0x2345fedd_sext(i32 %x) {
;
; LA64-LABEL: add_i32_minus_0x2345fedd_sext:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -144480
-; LA64-NEXT: ori $a1, $a1, 291
-; LA64-NEXT: add.w $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -9030
+; LA64-NEXT: addi.w $a0, $a0, 291
; LA64-NEXT: ret
%add = add i32 %x, -591789789
ret i32 %add
@@ -638,9 +617,8 @@ define i64 @add_i64_minus_0x2345fedd(i64 %x) {
;
; LA64-LABEL: add_i64_minus_0x2345fedd:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, -144480
-; LA64-NEXT: ori $a1, $a1, 291
-; LA64-NEXT: add.d $a0, $a0, $a1
+; LA64-NEXT: addu16i.d $a0, $a0, -9030
+; LA64-NEXT: addi.d $a0, $a0, 291
; LA64-NEXT: ret
%add = add i64 %x, -591789789
ret i64 %add
More information about the llvm-commits
mailing list