Skip to content

Commit

Permalink
[LoongArch] Make use of addu16i.d for adds with suitable immediates
Browse files Browse the repository at this point in the history
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
  • Loading branch information
xen0n authored and SixWeining committed Feb 15, 2023
1 parent dcf9c60 commit 2b8cb7d
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 66 deletions.
40 changes: 40 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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">;
Expand Down Expand Up @@ -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>;
Expand Down
110 changes: 44 additions & 66 deletions llvm/test/CodeGen/LoongArch/ir-instruction/add.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 2b8cb7d

Please sign in to comment.