[llvm] [RISCV][llvm] Support frame index in zilsd optimizer (PR #174073)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 31 00:51:01 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Brandon Wu (4vtomat)
<details>
<summary>Changes</summary>
Current zilsd optimizer only support base op that is in a register,
however many use cases are essentially stack load/store.
---
Full diff: https://github.com/llvm/llvm-project/pull/174073.diff
4 Files Affected:
- (modified) llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp (+48-19)
- (modified) llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp (+39-18)
- (modified) llvm/test/CodeGen/RISCV/zilsd-ldst-opt-postra.mir (+99)
- (modified) llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir (+95)
``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp b/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp
index ff5894e1a657d..c4b83adef5ee3 100644
--- a/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp
@@ -576,7 +576,12 @@ void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &MBB,
const MachineOperand &BaseOp = MI->getOperand(2);
Register FirstReg = FirstOp.getReg();
Register SecondReg = SecondOp.getReg();
- Register BaseReg = BaseOp.getReg();
+ unsigned BaseReg;
+ bool BaseIsReg = BaseOp.isReg();
+ if (BaseIsReg)
+ BaseReg = BaseOp.getReg().id();
+ else
+ BaseReg = BaseOp.getIndex();
// Handle both immediate and symbolic operands for offset
const MachineOperand &OffsetOp = MI->getOperand(3);
@@ -601,26 +606,37 @@ void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &MBB,
// we can just switch the order to resolve that:
// X13 = LW X10, 4
// X10 = LW killed X10, 0
- if (FirstReg == BaseReg) {
+ if (BaseIsReg && FirstReg == BaseReg) {
MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
.addReg(SecondReg,
- RegState::Define | getDeadRegState(SecondOp.isDead()))
- .addReg(BaseReg);
+ RegState::Define | getDeadRegState(SecondOp.isDead()));
MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
.addReg(FirstReg,
- RegState::Define | getDeadRegState(FirstOp.isDead()))
- .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
+ RegState::Define | getDeadRegState(FirstOp.isDead()));
+
+ if (BaseIsReg) {
+ MIB2 = MIB2.addReg(BaseReg);
+ MIB1 = MIB1.addReg(BaseReg, getKillRegState(BaseOp.isKill()));
+ } else {
+ MIB2 = MIB2.addFrameIndex(BaseReg);
+ MIB1 = MIB1.addFrameIndex(BaseReg);
+ }
} else {
MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
.addReg(FirstReg,
- RegState::Define | getDeadRegState(FirstOp.isDead()))
- .addReg(BaseReg);
-
+ RegState::Define | getDeadRegState(FirstOp.isDead()));
MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
.addReg(SecondReg,
- RegState::Define | getDeadRegState(SecondOp.isDead()))
- .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
+ RegState::Define | getDeadRegState(SecondOp.isDead()));
+
+ if (BaseIsReg) {
+ MIB1 = MIB1.addReg(BaseReg);
+ MIB2 = MIB2.addReg(BaseReg, getKillRegState(BaseOp.isKill()));
+ } else {
+ MIB1 = MIB1.addFrameIndex(BaseReg);
+ MIB2 = MIB2.addFrameIndex(BaseReg);
+ }
}
++NumLD2LW;
@@ -630,12 +646,18 @@ void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &MBB,
FirstReg != SecondReg &&
"First register and second register is impossible to be same register");
MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
- .addReg(FirstReg, getKillRegState(FirstOp.isKill()))
- .addReg(BaseReg);
+ .addReg(FirstReg, getKillRegState(FirstOp.isKill()));
MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
- .addReg(SecondReg, getKillRegState(SecondOp.isKill()))
- .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
+ .addReg(SecondReg, getKillRegState(SecondOp.isKill()));
+
+ if (BaseIsReg) {
+ MIB1 = MIB1.addReg(BaseReg);
+ MIB2 = MIB2.addReg(BaseReg, getKillRegState(BaseOp.isKill()));
+ } else {
+ MIB1 = MIB1.addFrameIndex(BaseReg);
+ MIB2 = MIB2.addFrameIndex(BaseReg);
+ }
++NumSD2SW;
LLVM_DEBUG(dbgs() << "Split SD back to two SW instructions\n");
@@ -689,7 +711,12 @@ bool RISCVLoadStoreOpt::fixInvalidRegPairOp(MachineBasicBlock &MBB,
// Registers are valid, convert to real LD/SD instruction
const MachineOperand &BaseOp = MI->getOperand(2);
- Register BaseReg = BaseOp.getReg();
+ unsigned BaseReg;
+ bool BaseIsReg = BaseOp.isReg();
+ if (BaseIsReg)
+ BaseReg = BaseOp.getReg().id();
+ else
+ BaseReg = BaseOp.getIndex();
DebugLoc DL = MI->getDebugLoc();
// Handle both immediate and symbolic operands for offset
const MachineOperand &OffsetOp = MI->getOperand(3);
@@ -711,9 +738,11 @@ bool RISCVLoadStoreOpt::fixInvalidRegPairOp(MachineBasicBlock &MBB,
MIB.addReg(RegPair, getKillRegState(FirstOp.isKill() && SecondOp.isKill()));
}
- MIB.addReg(BaseReg, getKillRegState(BaseOp.isKill()))
- .add(OffsetOp)
- .cloneMemRefs(*MI);
+ if (BaseIsReg)
+ MIB = MIB.addReg(BaseReg, getKillRegState(BaseOp.isKill()));
+ else
+ MIB = MIB.addFrameIndex(BaseReg);
+ MIB.add(OffsetOp).cloneMemRefs(*MI);
LLVM_DEBUG(dbgs() << "Converted pseudo to real instruction: " << *MIB
<< "\n");
diff --git a/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp b/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp
index 3b47903c351bf..2de73e6267dd0 100644
--- a/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp
+++ b/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp
@@ -87,7 +87,8 @@ class RISCVPreAllocZilsdOpt : public MachineFunctionPass {
Global = 1,
CPI = 2,
BlockAddr = 3,
- Unknown = 4,
+ FrameIdx = 4,
+ Unknown = 5,
};
using MemOffset = std::pair<MemoryOffsetKind, int>;
using BaseRegInfo = std::pair<unsigned, MemoryOffsetKind>;
@@ -160,12 +161,16 @@ RISCVPreAllocZilsdOpt::getMemoryOpOffset(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case RISCV::LW:
case RISCV::SW: {
- // For LW/SW, the offset is in operand 2
+ // For LW/SW, the base is in operand 1 and offset is in operand 2
+ const MachineOperand &BaseOp = MI.getOperand(1);
const MachineOperand &OffsetOp = MI.getOperand(2);
// Handle immediate offset
- if (OffsetOp.isImm())
+ if (OffsetOp.isImm()) {
+ if (BaseOp.isFI())
+ return std::make_pair(MemoryOffsetKind::FrameIdx, OffsetOp.getImm());
return std::make_pair(MemoryOffsetKind::Imm, OffsetOp.getImm());
+ }
// Handle symbolic operands with MO_LO flag (from MergeBaseOffset)
if (OffsetOp.getTargetFlags() & RISCVII::MO_LO) {
@@ -229,7 +234,7 @@ bool RISCVPreAllocZilsdOpt::isSafeToMove(MachineInstr *MI, MachineInstr *Target,
++Start;
Register DefReg = MI->getOperand(0).getReg();
- Register BaseReg = MI->getOperand(1).getReg();
+ const MachineOperand &BaseOp = MI->getOperand(1);
unsigned ScanCount = 0;
for (auto It = Start; It != End; ++It, ++ScanCount) {
@@ -247,8 +252,8 @@ bool RISCVPreAllocZilsdOpt::isSafeToMove(MachineInstr *MI, MachineInstr *Target,
}
// Check if the base register is modified
- if (It->modifiesRegister(BaseReg, TRI)) {
- LLVM_DEBUG(dbgs() << "Base register " << BaseReg
+ if (BaseOp.isReg() && It->modifiesRegister(BaseOp.getReg(), TRI)) {
+ LLVM_DEBUG(dbgs() << "Base register " << BaseOp.getReg()
<< " modified by: " << *It);
return false;
}
@@ -297,8 +302,16 @@ bool RISCVPreAllocZilsdOpt::rescheduleOps(
Register FirstReg = MI0->getOperand(0).getReg();
Register SecondReg = MI1->getOperand(0).getReg();
- Register BaseReg = MI0->getOperand(1).getReg();
+ const MachineOperand &BaseOp = MI0->getOperand(1);
const MachineOperand &OffsetOp = MI0->getOperand(2);
+ assert((BaseOp.isReg() || BaseOp.isFI()) &&
+ "Base register should be register or frame index");
+ unsigned BaseReg;
+ bool BaseIsReg = BaseOp.isReg();
+ if (BaseIsReg)
+ BaseReg = BaseOp.getReg().id();
+ else
+ BaseReg = BaseOp.getIndex();
// At this point, MI0 and MI1 are:
// 1. both either LW or SW.
@@ -347,21 +360,23 @@ bool RISCVPreAllocZilsdOpt::rescheduleOps(
if (IsLoad) {
MIB = BuildMI(*MBB, InsertPos, DL, TII->get(RISCV::PseudoLD_RV32_OPT))
.addReg(FirstReg, RegState::Define)
- .addReg(SecondReg, RegState::Define)
- .addReg(BaseReg)
- .add(OffsetOp);
+ .addReg(SecondReg, RegState::Define);
++NumLDFormed;
LLVM_DEBUG(dbgs() << "Formed LD: " << *MIB << "\n");
} else {
MIB = BuildMI(*MBB, InsertPos, DL, TII->get(RISCV::PseudoSD_RV32_OPT))
.addReg(FirstReg)
- .addReg(SecondReg)
- .addReg(BaseReg)
- .add(OffsetOp);
+ .addReg(SecondReg);
++NumSDFormed;
LLVM_DEBUG(dbgs() << "Formed SD: " << *MIB << "\n");
}
+ if (BaseIsReg)
+ MIB = MIB.addReg(BaseReg);
+ else
+ MIB = MIB.addFrameIndex(BaseReg);
+ MIB = MIB.add(OffsetOp);
+
// Copy memory operands
MIB.cloneMergedMemRefs({MI0, MI1});
@@ -394,7 +409,7 @@ bool RISCVPreAllocZilsdOpt::isMemoryOp(const MachineInstr &MI) {
if (Opcode != RISCV::LW && Opcode != RISCV::SW)
return false;
- if (!MI.getOperand(1).isReg())
+ if (!MI.getOperand(1).isReg() && !MI.getOperand(1).isFI())
return false;
// When no memory operands are present, conservatively assume unaligned,
@@ -413,7 +428,7 @@ bool RISCVPreAllocZilsdOpt::isMemoryOp(const MachineInstr &MI) {
return false;
// Likewise don't mess with references to undefined addresses.
- if (MI.getOperand(1).isUndef())
+ if (MI.getOperand(1).isReg() && MI.getOperand(1).isUndef())
return false;
return true;
@@ -462,16 +477,22 @@ bool RISCVPreAllocZilsdOpt::rescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
continue;
bool IsLd = (MI.getOpcode() == RISCV::LW);
- Register Base = MI.getOperand(1).getReg();
+ const MachineOperand &BaseOp = MI.getOperand(1);
+ unsigned BaseReg;
+ bool BaseIsReg = BaseOp.isReg();
+ if (BaseIsReg)
+ BaseReg = BaseOp.getReg().id();
+ else
+ BaseReg = BaseOp.getIndex();
bool StopHere = false;
// Lambda to find or add base register entries
auto FindBases = [&](Base2InstMap &Base2Ops, BaseVec &Bases) {
- auto [BI, Inserted] = Base2Ops.try_emplace({Base.id(), Offset.first});
+ auto [BI, Inserted] = Base2Ops.try_emplace({BaseReg, Offset.first});
if (Inserted) {
// First time seeing this base register
BI->second.push_back(&MI);
- Bases.push_back({Base.id(), Offset.first});
+ Bases.push_back({BaseReg, Offset.first});
return;
}
// Check if we've seen this exact base+offset before
diff --git a/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-postra.mir b/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-postra.mir
index c27cb25366f27..ec7ecf5a534ef 100644
--- a/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-postra.mir
+++ b/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-postra.mir
@@ -10,6 +10,10 @@
ret i32 %5
}
+ define void @expand_pseudold_frame_index_valid(ptr %0) {
+ ret void
+ }
+
define void @expand_pseudosd_valid(ptr %0, i32 %1, i32 %2) {
store i32 %1, ptr %0, align 4
%4 = getelementptr inbounds i32, ptr %0, i32 1
@@ -17,6 +21,10 @@
ret void
}
+ define void @expand_pseudosd_frame_index_valid(ptr %0, i32 %1, i32 %2) {
+ ret void
+ }
+
define i32 @expand_pseudold_invalid_pair(ptr %0) {
%2 = load i32, ptr %0, align 4
%3 = getelementptr inbounds i32, ptr %0, i32 1
@@ -25,6 +33,10 @@
ret i32 %5
}
+ define void @expand_pseudold_frame_index_invalid_pair(ptr %0) {
+ ret void
+ }
+
define void @expand_pseudosd_invalid_pair(ptr %0, i32 %1, i32 %2) {
store i32 %1, ptr %0, align 4
%4 = getelementptr inbounds i32, ptr %0, i32 1
@@ -32,6 +44,10 @@
ret void
}
+ define void @expand_pseudosd_frame_index_invalid_pair(ptr %0, i32 %1, i32 %2) {
+ ret void
+ }
+
define void @store_zero_combine_valid(ptr %0) {
store i32 0, ptr %0, align 8
%2 = getelementptr inbounds i32, ptr %0, i32 1
@@ -75,6 +91,27 @@ body: |
$x10 = ADD killed $x12, killed $x13
PseudoRET implicit $x10
+...
+---
+# Valid consecutive even/odd register pair - should expand to LD_RV32
+name: expand_pseudold_frame_index_valid
+tracksRegLiveness: false
+stack:
+ - { id: 0, offset: 0, size: 8, alignment: 4 }
+body: |
+ bb.0:
+ liveins: $x10
+
+ ; CHECK-LABEL: name: expand_pseudold_frame_index_valid
+ ; CHECK: liveins: $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $x12_x13 = LD_RV32 %stack.0, 0
+ ; CHECK-NEXT: $x10 = ADD killed $x12, killed $x13
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ $x12, $x13 = PseudoLD_RV32_OPT %stack.0, 0
+ $x10 = ADD killed $x12, killed $x13
+ PseudoRET implicit $x10
+
...
---
# Valid consecutive even/odd register pair - should expand to SD_RV32
@@ -93,6 +130,26 @@ body: |
PseudoSD_RV32_OPT killed $x12, killed $x13, killed $x10, 0
PseudoRET
+...
+---
+# Valid consecutive even/odd register pair - should expand to SD_RV32
+name: expand_pseudosd_frame_index_valid
+tracksRegLiveness: false
+stack:
+ - { id: 0, offset: 0, size: 8, alignment: 4 }
+body: |
+ bb.0:
+ liveins: $x12, $x13
+
+ ; PseudoSD_RV32_OPT with consecutive even/odd registers (x12, x13)
+ ; CHECK-LABEL: name: expand_pseudosd_frame_index_valid
+ ; CHECK: liveins: $x12, $x13
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: SD_RV32 killed $x12_x13, %stack.0, 0
+ ; CHECK-NEXT: PseudoRET
+ PseudoSD_RV32_OPT killed $x12, killed $x13, %stack.0, 0
+ PseudoRET
+
...
---
# Invalid register pair (not consecutive) - should decompose back to LW
@@ -115,6 +172,26 @@ body: |
$x10 = ADD killed $x11, killed $x13
PseudoRET implicit $x10
+...
+---
+# Invalid register pair (not consecutive) - should decompose back to LW
+name: expand_pseudold_frame_index_invalid_pair
+tracksRegLiveness: false
+stack:
+ - { id: 0, offset: 0, size: 8, alignment: 4 }
+body: |
+ bb.0:
+ ; PseudoLD_RV32_OPT with non-consecutive registers (x11, x13)
+ ; Should decompose back to two LW instructions
+ ; CHECK-LABEL: name: expand_pseudold_frame_index_invalid_pair
+ ; CHECK: $x11 = LW %stack.0, 0
+ ; CHECK-NEXT: $x13 = LW %stack.0, 4
+ ; CHECK-NEXT: $x10 = ADD killed $x11, killed $x13
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ $x11, $x13 = PseudoLD_RV32_OPT %stack.0, 0
+ $x10 = ADD killed $x11, killed $x13
+ PseudoRET implicit $x10
+
...
---
# Invalid register pair (not even/odd) - should decompose back to SW
@@ -135,6 +212,28 @@ body: |
PseudoSD_RV32_OPT killed $x11, killed $x14, killed $x10, 0
PseudoRET
+...
+---
+# Invalid register pair (not even/odd) - should decompose back to SW
+name: expand_pseudosd_frame_index_invalid_pair
+tracksRegLiveness: false
+stack:
+ - { id: 0, offset: 0, size: 8, alignment: 4 }
+body: |
+ bb.0:
+ liveins: $x11, $x14
+
+ ; PseudoSD_RV32_OPT with non-consecutive registers (x11, x14)
+ ; Should decompose back to two SW instructions
+ ; CHECK-LABEL: name: expand_pseudosd_frame_index_invalid_pair
+ ; CHECK: liveins: $x11, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: SW killed $x11, %stack.0, 0
+ ; CHECK-NEXT: SW killed $x14, %stack.0, 4
+ ; CHECK-NEXT: PseudoRET
+ PseudoSD_RV32_OPT killed $x11, killed $x14, %stack.0, 0
+ PseudoRET
+
...
---
# Test store zero combinations - zeros don't need consecutive pairs
diff --git a/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir b/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
index dab394d4bc8c4..dcb9c44f8030b 100644
--- a/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
+++ b/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
@@ -238,6 +238,19 @@
define i32 @symbolic_operands_interleave() {
ret i32 0
}
+
+ declare void @external(ptr)
+ define i32 @frame_index() {
+ %arr = alloca [2 x i32], align 4
+ %arrayidx1 = getelementptr inbounds nuw i8, ptr %arr, i32 4
+ ret i32 0
+ }
+
+ define i32 @frame_index_operands_interleave() {
+ %arr = alloca [2 x i32], align 4
+ %arrayidx1 = getelementptr inbounds nuw i8, ptr %arr, i32 4
+ ret i32 0
+ }
---
# Basic case: two consecutive 32-bit loads that can be combined into LD
name: basic_load_combine
@@ -1240,3 +1253,85 @@ body: |
PseudoRET
...
+---
+name: frame_index
+alignment: 4
+tracksRegLiveness: true
+stack:
+ - { id: 0, offset: 0, size: 8, alignment: 4 }
+liveins:
+ - { reg: '$x10', virtual-reg: '%0' }
+ - { reg: '$x11', virtual-reg: '%1' }
+body: |
+ bb.0:
+ liveins: $x10, $x11
+
+ ; CHECK-LABEL: name: frame_index
+ ; CHECK: liveins: $x10, $x11
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: SW [[COPY]], %stack.0, 0 :: (store (s32) into %ir.arr)
+ ; CHECK-NEXT: SW [[COPY1]], %stack.0, 4 :: (store (s32) into %ir.arrayidx1)
+ ; CHECK-NEXT: PseudoRET
+ ;
+ ; CHECK-4BYTE-LABEL: name: frame_index
+ ; CHECK-4BYTE: liveins: $x10, $x11
+ ; CHECK-4BYTE-NEXT: {{ $}}
+ ; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-4BYTE-NEXT: PseudoSD_RV32_OPT [[COPY]], [[COPY1]], %stack.0, 0 :: (store (s32) into %ir.arr), (store (s32) into %ir.arrayidx1)
+ ; CHECK-4BYTE-NEXT: PseudoRET
+ %0:gpr = COPY $x10
+ %1:gpr = COPY $x11
+ SW %0:gpr, %stack.0, 0 :: (store (s32) into %ir.arr)
+ SW %1:gpr, %stack.0, 4 :: (store (s32) into %ir.arrayidx1)
+ PseudoRET
+...
+---
+name: frame_index_operands_interleave
+alignment: 4
+tracksRegLiveness: true
+stack:
+ - { id: 0, offset: 0, size: 8, alignment: 4 }
+liveins:
+ - { reg: '$x10', virtual-reg: '%0' }
+ - { reg: '$x11', virtual-reg: '%1' }
+body: |
+ bb.0:
+ liveins: $x10, $x11
+
+ ; CHECK-LABEL: name: frame_index_operands_interleave
+ ; CHECK: liveins: $x10, $x11
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW %stack.0, 0 :: (load (s32) from %ir.arr)
+ ; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
+ ; CHECK-NEXT: [[LW2:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
+ ; CHECK-NEXT: [[LW3:%[0-9]+]]:gpr = LW %stack.0, 4 :: (load (s32) from %ir.arrayidx1)
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW2]]
+ ; CHECK-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[LW1]], [[LW3]]
+ ; CHECK-NEXT: PseudoRET
+ ;
+ ; CHECK-4BYTE-LABEL: name: frame_index_operands_interleave
+ ; CHECK-4BYTE: liveins: $x10, $x11
+ ; CHECK-4BYTE-NEXT: {{ $}}
+ ; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT %stack.0, 0 :: (load (s32) from %ir.arr), (load (s32) from %ir.arrayidx1)
+ ; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT2:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT3:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
+ ; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT2]]
+ ; CHECK-4BYTE-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT3]], [[PseudoLD_RV32_OPT1]]
+ ; CHECK-4BYTE-NEXT: PseudoRET
+ %0:gpr = COPY $x10
+ %1:gpr = COPY $x11
+ %2:gpr = LW %stack.0, 0 :: (load (s32) from %ir.arr)
+ %3:gpr = LW %0, 4 :: (load (s32))
+ %4:gpr = LW %0, 0 :: (load (s32))
+ %5:gpr = LW %stack.0, 4 :: (load (s32) from %ir.arrayidx1)
+ %6:gpr = ADD %2, %4
+ %7:gpr = ADD %3, %5
+ PseudoRET
+
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/174073
More information about the llvm-commits
mailing list