[llvm] [RISCV] Addi optimization ported to GISel (PR #120463)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 18 10:37:10 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel
Author: Luke Quinn (lquinn2015)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/120463.diff
3 Files Affected:
- (modified) llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp (+24)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+12-2)
- (added) llvm/test/CodeGen/RISCV/GlobalISel/add-imm.ll (+247)
``````````diff
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 985264c591e105..5aa66b3780b86b 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -137,6 +137,11 @@ class RISCVInstructionSelector : public InstructionSelector {
void renderXLenSubTrailingOnes(MachineInstrBuilder &MIB,
const MachineInstr &MI, int OpIdx) const;
+ void renderAddiPairImmLarge(MachineInstrBuilder &MIB, const MachineInstr &MI,
+ int OpIdx) const;
+ void renderAddiPairImmSmall(MachineInstrBuilder &MIB, const MachineInstr &MI,
+ int OpIdx) const;
+
const RISCVSubtarget &STI;
const RISCVInstrInfo &TII;
const RISCVRegisterInfo &TRI;
@@ -871,6 +876,25 @@ void RISCVInstructionSelector::renderXLenSubTrailingOnes(
MIB.addImm(Subtarget->getXLen() - llvm::countr_one(C));
}
+void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
+ const MachineInstr &MI,
+ int OpIdx) const {
+ assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
+ "Expected G_CONSTANT");
+ int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
+ int64_t Adj = Imm < 0 ? -2048 : 2047;
+ MIB.addImm(Imm - Adj);
+}
+
+void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
+ const MachineInstr &MI,
+ int OpIdx) const {
+ assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
+ "Expected G_CONSTANT");
+ int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
+ MIB.addImm(Imm);
+}
+
const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
LLT Ty, const RegisterBank &RB) const {
if (RB.getID() == RISCV::GPRBRegBankID) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 24bf7da4dadc07..ac9805ded9d307 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -454,7 +454,14 @@ def AddiPair : PatLeaf<(imm), [{
// 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);
-}]>;
+}]> {
+ let GISelPredicateCode = [{
+ if (!MRI.hasOneNonDBGUse(MI.getOperand(0).getReg()))
+ return false;
+ int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
+ return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);
+ }];
+}
// Return imm - (imm < 0 ? -2048 : 2047).
def AddiPairImmSmall : SDNodeXForm<imm, [{
@@ -463,6 +470,8 @@ def AddiPairImmSmall : SDNodeXForm<imm, [{
return CurDAG->getSignedTargetConstant(Imm - Adj, SDLoc(N),
N->getValueType(0));
}]>;
+def GIAddiPairImmSmall : GICustomOperandRenderer<"renderAddiPairImmSmall">,
+ GISDNodeXFormEquiv<AddiPairImmSmall>;
// Return -2048 if immediate is negative or 2047 if positive. These are the
// largest simm12 values.
@@ -470,6 +479,8 @@ def AddiPairImmLarge : SDNodeXForm<imm, [{
int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047;
return CurDAG->getSignedTargetConstant(Imm, SDLoc(N), N->getValueType(0));
}]>;
+def GIAddiPairImmLarge : GICustomOperandRenderer<"renderAddiPairImmLarge">,
+ GISDNodeXFormEquiv<AddiPairImmLarge>;
def TrailingZeros : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()),
@@ -537,7 +548,6 @@ def LeadingOnesWMask : PatLeaf<(imm), [{
return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) &&
Imm != UINT64_C(0xffffffff);
}];
-
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/add-imm.ll b/llvm/test/CodeGen/RISCV/GlobalISel/add-imm.ll
new file mode 100644
index 00000000000000..ff56ab193c480c
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/add-imm.ll
@@ -0,0 +1,247 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -global-isel < %s \
+; RUN: | FileCheck %s -check-prefix=RV32I
+; RUN: llc -mtriple=riscv64 -global-isel < %s \
+; RUN: | FileCheck %s -check-prefix=RV64I
+
+; These test how the immediate in an addition is materialized.
+
+define i32 @add_positive_low_bound_reject(i32 %a) nounwind {
+; RV32I-LABEL: add_positive_low_bound_reject:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, 2047
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_positive_low_bound_reject:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: ret
+ %1 = add i32 %a, 2047
+ ret i32 %1
+}
+
+define i32 @add_positive_low_bound_accept(i32 %a) nounwind {
+; RV32I-LABEL: add_positive_low_bound_accept:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, 2047
+; RV32I-NEXT: addi a0, a0, 1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_positive_low_bound_accept:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: addi a0, a0, 1
+; RV64I-NEXT: ret
+ %1 = add i32 %a, 2048
+ ret i32 %1
+}
+
+define i32 @add_positive_high_bound_accept(i32 %a) nounwind {
+; RV32I-LABEL: add_positive_high_bound_accept:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, 2047
+; RV32I-NEXT: addi a0, a0, 2047
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_positive_high_bound_accept:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: ret
+ %1 = add i32 %a, 4094
+ ret i32 %1
+}
+
+define i32 @add_positive_high_bound_reject(i32 %a) nounwind {
+; RV32I-LABEL: add_positive_high_bound_reject:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a1, 1
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: add a0, a0, a1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_positive_high_bound_reject:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a1, 1
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: add a0, a0, a1
+; RV64I-NEXT: ret
+ %1 = add i32 %a, 4095
+ ret i32 %1
+}
+
+define i32 @add_negative_high_bound_reject(i32 %a) nounwind {
+; RV32I-LABEL: add_negative_high_bound_reject:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, -2048
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_negative_high_bound_reject:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, -2048
+; RV64I-NEXT: ret
+ %1 = add i32 %a, -2048
+ ret i32 %1
+}
+
+define i32 @add_negative_high_bound_accept(i32 %a) nounwind {
+; RV32I-LABEL: add_negative_high_bound_accept:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, -2048
+; RV32I-NEXT: addi a0, a0, -1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_negative_high_bound_accept:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, -2048
+; RV64I-NEXT: addi a0, a0, -1
+; RV64I-NEXT: ret
+ %1 = add i32 %a, -2049
+ ret i32 %1
+}
+
+define i32 @add_negative_low_bound_accept(i32 %a) nounwind {
+; RV32I-LABEL: add_negative_low_bound_accept:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, -2048
+; RV32I-NEXT: addi a0, a0, -2048
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_negative_low_bound_accept:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, -2048
+; RV64I-NEXT: addi a0, a0, -2048
+; RV64I-NEXT: ret
+ %1 = add i32 %a, -4096
+ ret i32 %1
+}
+
+define i32 @add_negative_low_bound_reject(i32 %a) nounwind {
+; RV32I-LABEL: add_negative_low_bound_reject:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a1, 1048575
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: add a0, a0, a1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add_negative_low_bound_reject:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a1, 1048575
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: add a0, a0, a1
+; RV64I-NEXT: ret
+ %1 = add i32 %a, -4097
+ ret i32 %1
+}
+
+define i32 @add32_accept(i32 %a) nounwind {
+; RV32I-LABEL: add32_accept:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, 2047
+; RV32I-NEXT: addi a0, a0, 952
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add32_accept:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: addi a0, a0, 952
+; RV64I-NEXT: ret
+ %1 = add i32 %a, 2999
+ ret i32 %1
+}
+
+define signext i32 @add32_sext_accept(i32 signext %a) nounwind {
+; RV32I-LABEL: add32_sext_accept:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a0, a0, 2047
+; RV32I-NEXT: addi a0, a0, 952
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add32_sext_accept:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: addiw a0, a0, 952
+; RV64I-NEXT: ret
+ %1 = add i32 %a, 2999
+ ret i32 %1
+}
+
+ at gv0 = global i32 0, align 4
+define signext i32 @add32_sext_reject_on_rv64(i32 signext %a) nounwind {
+; RV32I-LABEL: add32_sext_reject_on_rv64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a1, %hi(gv0)
+; RV32I-NEXT: addi a0, a0, 2047
+; RV32I-NEXT: addi a0, a0, 953
+; RV32I-NEXT: sw a0, %lo(gv0)(a1)
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add32_sext_reject_on_rv64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a1, %hi(gv0)
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: addiw a0, a0, 953
+; RV64I-NEXT: sw a0, %lo(gv0)(a1)
+; RV64I-NEXT: ret
+ %b = add nsw i32 %a, 3000
+ store i32 %b, ptr @gv0, align 4
+ ret i32 %b
+}
+
+define i64 @add64_accept(i64 %a) nounwind {
+; RV32I-LABEL: add64_accept:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a2, 1
+; RV32I-NEXT: addi a2, a2, -1097
+; RV32I-NEXT: add a0, a0, a2
+; RV32I-NEXT: sltu a2, a0, a2
+; RV32I-NEXT: add a1, a1, a2
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add64_accept:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi a0, a0, 2047
+; RV64I-NEXT: addi a0, a0, 952
+; RV64I-NEXT: ret
+ %1 = add i64 %a, 2999
+ ret i64 %1
+}
+
+ at ga = global i32 0, align 4
+ at gb = global i32 0, align 4
+define void @add32_reject() nounwind {
+; RV32I-LABEL: add32_reject:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a0, %hi(ga)
+; RV32I-NEXT: lui a1, %hi(gb)
+; RV32I-NEXT: lw a2, %lo(ga)(a0)
+; RV32I-NEXT: lw a3, %lo(gb)(a1)
+; RV32I-NEXT: lui a4, 1
+; RV32I-NEXT: addi a4, a4, -1096
+; RV32I-NEXT: add a2, a2, a4
+; RV32I-NEXT: add a3, a3, a4
+; RV32I-NEXT: sw a2, %lo(ga)(a0)
+; RV32I-NEXT: sw a3, %lo(gb)(a1)
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: add32_reject:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a0, %hi(ga)
+; RV64I-NEXT: lui a1, %hi(gb)
+; RV64I-NEXT: lw a2, %lo(ga)(a0)
+; RV64I-NEXT: lw a3, %lo(gb)(a1)
+; RV64I-NEXT: lui a4, 1
+; RV64I-NEXT: addi a4, a4, -1096
+; RV64I-NEXT: add a2, a2, a4
+; RV64I-NEXT: add a3, a3, a4
+; RV64I-NEXT: sw a2, %lo(ga)(a0)
+; RV64I-NEXT: sw a3, %lo(gb)(a1)
+; RV64I-NEXT: ret
+ %1 = load i32, ptr @ga, align 4
+ %2 = load i32, ptr @gb, align 4
+ %3 = add i32 %1, 3000
+ %4 = add i32 %2, 3000
+ store i32 %3, ptr @ga, align 4
+ store i32 %4, ptr @gb, align 4
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/120463
More information about the llvm-commits
mailing list