[llvm] c62b014 - [RISCV] Merge addi into load/store as there is a ADD between them
Hsiangkai Wang via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 28 21:36:34 PDT 2022
Author: Hsiangkai Wang
Date: 2022-04-29T04:33:05Z
New Revision: c62b014db97953bee25d17b46730f05eea6a3430
URL: https://github.com/llvm/llvm-project/commit/c62b014db97953bee25d17b46730f05eea6a3430
DIFF: https://github.com/llvm/llvm-project/commit/c62b014db97953bee25d17b46730f05eea6a3430.diff
LOG: [RISCV] Merge addi into load/store as there is a ADD between them
This patch adds peephole optimizations for the following patterns:
(load (add base, (addi src, off1)), off2)
-> (load (add base, src), off1+off2)
(store val, (add base, (addi src, off1)), off2)
-> (store val, (add base, src), off1+off2)
Differential Revision: https://reviews.llvm.org/D124231
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
llvm/test/CodeGen/RISCV/large-stack.ll
llvm/test/CodeGen/RISCV/mem.ll
llvm/test/CodeGen/RISCV/mem64.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 221e7c68e44a..87c3d6d3a19e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -2053,6 +2053,10 @@ bool RISCVDAGToDAGISel::selectRVVSimm5(SDValue N, unsigned Width,
// Merge an ADDI into the offset of a load/store instruction where possible.
// (load (addi base, off1), off2) -> (load base, off1+off2)
// (store val, (addi base, off1), off2) -> (store val, base, off1+off2)
+// (load (add base, (addi src, off1)), off2)
+// -> (load (add base, src), off1+off2)
+// (store val, (add base, (addi src, off1)), off2)
+// -> (store val, (add base, src), off1+off2)
// This is possible when off1+off2 fits a 12-bit immediate.
bool RISCVDAGToDAGISel::doPeepholeLoadStoreADDI(SDNode *N) {
int OffsetOpIdx;
@@ -2092,8 +2096,34 @@ bool RISCVDAGToDAGISel::doPeepholeLoadStoreADDI(SDNode *N) {
SDValue Base = N->getOperand(BaseOpIdx);
+ if (!Base.isMachineOpcode())
+ return false;
+
+ // There is a ADD between ADDI and load/store.
+ SDValue Add;
+ int AddBaseIdx;
+ if (Base.getMachineOpcode() == RISCV::ADD) {
+ if (!Base.hasOneUse())
+ return false;
+ Add = Base;
+ SDValue Op0 = Base.getOperand(0);
+ SDValue Op1 = Base.getOperand(1);
+ if (Op0.isMachineOpcode() && Op0.getMachineOpcode() == RISCV::ADDI &&
+ isa<ConstantSDNode>(Op0.getOperand(1)) &&
+ cast<ConstantSDNode>(Op0.getOperand(1))->getSExtValue() != 0) {
+ AddBaseIdx = 1;
+ Base = Op0;
+ } else if (Op1.isMachineOpcode() && Op1.getMachineOpcode() == RISCV::ADDI &&
+ isa<ConstantSDNode>(Op1.getOperand(1)) &&
+ cast<ConstantSDNode>(Op1.getOperand(1))->getSExtValue() != 0) {
+ AddBaseIdx = 0;
+ Base = Op1;
+ } else
+ return false;
+ }
+
// If the base is an ADDI, we can merge it in to the load/store.
- if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI)
+ if (Base.getMachineOpcode() != RISCV::ADDI)
return false;
SDValue ImmOperand = Base.getOperand(1);
@@ -2140,13 +2170,27 @@ bool RISCVDAGToDAGISel::doPeepholeLoadStoreADDI(SDNode *N) {
LLVM_DEBUG(N->dump(CurDAG));
LLVM_DEBUG(dbgs() << "\n");
+ if (Add)
+ Add = SDValue(CurDAG->UpdateNodeOperands(Add.getNode(),
+ Add.getOperand(AddBaseIdx),
+ Base.getOperand(0)),
+ 0);
+
// Modify the offset operand of the load/store.
- if (BaseOpIdx == 0) // Load
- CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand,
- N->getOperand(2));
- else // Store
- CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0),
- ImmOperand, N->getOperand(3));
+ if (BaseOpIdx == 0) { // Load
+ if (Add)
+ N = CurDAG->UpdateNodeOperands(N, Add, ImmOperand, N->getOperand(2));
+ else
+ N = CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand,
+ N->getOperand(2));
+ } else { // Store
+ if (Add)
+ N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), Add, ImmOperand,
+ N->getOperand(3));
+ else
+ N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0),
+ ImmOperand, N->getOperand(3));
+ }
return true;
}
diff --git a/llvm/test/CodeGen/RISCV/large-stack.ll b/llvm/test/CodeGen/RISCV/large-stack.ll
index ff265d9598c8..c684d50f40f1 100644
--- a/llvm/test/CodeGen/RISCV/large-stack.ll
+++ b/llvm/test/CodeGen/RISCV/large-stack.ll
@@ -59,13 +59,12 @@ define void @test_emergency_spill_slot(i32 %a) {
; RV32I-FPELIM-NEXT: sub sp, sp, a1
; RV32I-FPELIM-NEXT: .cfi_def_cfa_offset 400016
; RV32I-FPELIM-NEXT: lui a1, 78
-; RV32I-FPELIM-NEXT: addi a1, a1, 512
; RV32I-FPELIM-NEXT: addi a2, sp, 8
; RV32I-FPELIM-NEXT: add a1, a2, a1
; RV32I-FPELIM-NEXT: #APP
; RV32I-FPELIM-NEXT: nop
; RV32I-FPELIM-NEXT: #NO_APP
-; RV32I-FPELIM-NEXT: sw a0, 0(a1)
+; RV32I-FPELIM-NEXT: sw a0, 512(a1)
; RV32I-FPELIM-NEXT: #APP
; RV32I-FPELIM-NEXT: nop
; RV32I-FPELIM-NEXT: #NO_APP
@@ -95,7 +94,6 @@ define void @test_emergency_spill_slot(i32 %a) {
; RV32I-WITHFP-NEXT: addi a1, a1, 688
; RV32I-WITHFP-NEXT: sub sp, sp, a1
; RV32I-WITHFP-NEXT: lui a1, 78
-; RV32I-WITHFP-NEXT: addi a1, a1, 512
; RV32I-WITHFP-NEXT: lui a2, 1048478
; RV32I-WITHFP-NEXT: addi a2, a2, 1388
; RV32I-WITHFP-NEXT: add a2, s0, a2
@@ -103,7 +101,7 @@ define void @test_emergency_spill_slot(i32 %a) {
; RV32I-WITHFP-NEXT: #APP
; RV32I-WITHFP-NEXT: nop
; RV32I-WITHFP-NEXT: #NO_APP
-; RV32I-WITHFP-NEXT: sw a0, 0(a1)
+; RV32I-WITHFP-NEXT: sw a0, 512(a1)
; RV32I-WITHFP-NEXT: #APP
; RV32I-WITHFP-NEXT: nop
; RV32I-WITHFP-NEXT: #NO_APP
diff --git a/llvm/test/CodeGen/RISCV/mem.ll b/llvm/test/CodeGen/RISCV/mem.ll
index 083909c72529..180074386ba8 100644
--- a/llvm/test/CodeGen/RISCV/mem.ll
+++ b/llvm/test/CodeGen/RISCV/mem.ll
@@ -198,3 +198,42 @@ define dso_local i32 @lw_sw_constant(i32 %a) nounwind {
store i32 %a, i32* %1
ret i32 %2
}
+
+define i32 @lw_far_local(i32* %a) {
+; RV32I-LABEL: lw_far_local:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a1, 4
+; RV32I-NEXT: add a0, a0, a1
+; RV32I-NEXT: lw a0, -4(a0)
+; RV32I-NEXT: ret
+ %1 = getelementptr inbounds i32, i32* %a, i64 4095
+ %2 = load volatile i32, i32* %1
+ ret i32 %2
+}
+
+define void @st_far_local(i32* %a, i32 %b) {
+; RV32I-LABEL: st_far_local:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a2, 4
+; RV32I-NEXT: add a0, a0, a2
+; RV32I-NEXT: sw a1, -4(a0)
+; RV32I-NEXT: ret
+ %1 = getelementptr inbounds i32, i32* %a, i64 4095
+ store i32 %b, i32* %1
+ ret void
+}
+
+define i32 @lw_sw_far_local(i32* %a, i32 %b) {
+; RV32I-LABEL: lw_sw_far_local:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lui a2, 4
+; RV32I-NEXT: addi a2, a2, -4
+; RV32I-NEXT: add a2, a0, a2
+; RV32I-NEXT: lw a0, 0(a2)
+; RV32I-NEXT: sw a1, 0(a2)
+; RV32I-NEXT: ret
+ %1 = getelementptr inbounds i32, i32* %a, i64 4095
+ %2 = load volatile i32, i32* %1
+ store i32 %b, i32* %1
+ ret i32 %2
+}
diff --git a/llvm/test/CodeGen/RISCV/mem64.ll b/llvm/test/CodeGen/RISCV/mem64.ll
index 4fcc6643bf7c..74f52ff12e65 100644
--- a/llvm/test/CodeGen/RISCV/mem64.ll
+++ b/llvm/test/CodeGen/RISCV/mem64.ll
@@ -228,3 +228,44 @@ define dso_local i64 @ld_sd_global(i64 %a) nounwind {
store i64 %a, i64* %2
ret i64 %1
}
+
+define i64 @lw_far_local(i64* %a) {
+; RV64I-LABEL: lw_far_local:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a1, 8
+; RV64I-NEXT: addiw a1, a1, -8
+; RV64I-NEXT: add a0, a0, a1
+; RV64I-NEXT: ld a0, 0(a0)
+; RV64I-NEXT: ret
+ %1 = getelementptr inbounds i64, i64* %a, i64 4095
+ %2 = load volatile i64, i64* %1
+ ret i64 %2
+}
+
+define void @st_far_local(i64* %a, i64 %b) {
+; RV64I-LABEL: st_far_local:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a2, 8
+; RV64I-NEXT: addiw a2, a2, -8
+; RV64I-NEXT: add a0, a0, a2
+; RV64I-NEXT: sd a1, 0(a0)
+; RV64I-NEXT: ret
+ %1 = getelementptr inbounds i64, i64* %a, i64 4095
+ store i64 %b, i64* %1
+ ret void
+}
+
+define i64 @lw_sw_far_local(i64* %a, i64 %b) {
+; RV64I-LABEL: lw_sw_far_local:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a2, 8
+; RV64I-NEXT: addiw a2, a2, -8
+; RV64I-NEXT: add a2, a0, a2
+; RV64I-NEXT: ld a0, 0(a2)
+; RV64I-NEXT: sd a1, 0(a2)
+; RV64I-NEXT: ret
+ %1 = getelementptr inbounds i64, i64* %a, i64 4095
+ %2 = load volatile i64, i64* %1
+ store i64 %b, i64* %1
+ ret i64 %2
+}
More information about the llvm-commits
mailing list