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";
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">;
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>;
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:
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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:
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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
;
; 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