Skip to content

Commit 9c5003c

Browse files
authored
[RISCV] Implement RISCVInstrInfo::getMemOperandsWithOffsetWidth (#73681)
This hook is called by the default implementation of getMemOperandWithOffset and by the load/store clustering code in the MachineScheduler though this isn't enabled by default and is not yet enabled for RISC-V. Only return true for queries on scalar loads/stores for now (this is a conservative starting point, and vector load/store can be handled in a follow-on patch).
1 parent 1886b1a commit 9c5003c

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,11 +2193,51 @@ MachineInstr *RISCVInstrInfo::emitLdStWithAddr(MachineInstr &MemI,
21932193
.setMIFlags(MemI.getFlags());
21942194
}
21952195

2196+
bool RISCVInstrInfo::getMemOperandsWithOffsetWidth(
2197+
const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps,
2198+
int64_t &Offset, bool &OffsetIsScalable, unsigned &Width,
2199+
const TargetRegisterInfo *TRI) const {
2200+
if (!LdSt.mayLoadOrStore())
2201+
return false;
2202+
2203+
// Conservatively, only handle scalar loads/stores for now.
2204+
switch (LdSt.getOpcode()) {
2205+
case RISCV::LB:
2206+
case RISCV::LBU:
2207+
case RISCV::SB:
2208+
case RISCV::LH:
2209+
case RISCV::LHU:
2210+
case RISCV::FLH:
2211+
case RISCV::SH:
2212+
case RISCV::FSH:
2213+
case RISCV::LW:
2214+
case RISCV::LWU:
2215+
case RISCV::FLW:
2216+
case RISCV::SW:
2217+
case RISCV::FSW:
2218+
case RISCV::LD:
2219+
case RISCV::FLD:
2220+
case RISCV::SD:
2221+
case RISCV::FSD:
2222+
break;
2223+
default:
2224+
return false;
2225+
}
2226+
const MachineOperand *BaseOp;
2227+
OffsetIsScalable = false;
2228+
if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, Width, TRI))
2229+
return false;
2230+
BaseOps.push_back(BaseOp);
2231+
return true;
2232+
}
2233+
21962234
// Set BaseReg (the base register operand), Offset (the byte offset being
21972235
// accessed) and the access Width of the passed instruction that reads/writes
21982236
// memory. Returns false if the instruction does not read/write memory or the
21992237
// BaseReg/Offset/Width can't be determined. Is not guaranteed to always
22002238
// recognise base operands and offsets in all cases.
2239+
// TODO: Add an IsScalable bool ref argument (like the equivalent AArch64
2240+
// function) and set it as appropriate.
22012241
bool RISCVInstrInfo::getMemOperandWithOffsetWidth(
22022242
const MachineInstr &LdSt, const MachineOperand *&BaseReg, int64_t &Offset,
22032243
unsigned &Width, const TargetRegisterInfo *TRI) const {

llvm/lib/Target/RISCV/RISCVInstrInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
152152
MachineInstr *emitLdStWithAddr(MachineInstr &MemI,
153153
const ExtAddrMode &AM) const override;
154154

155+
bool getMemOperandsWithOffsetWidth(
156+
const MachineInstr &MI, SmallVectorImpl<const MachineOperand *> &BaseOps,
157+
int64_t &Offset, bool &OffsetIsScalable, unsigned &Width,
158+
const TargetRegisterInfo *TRI) const override;
159+
155160
bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
156161
const MachineOperand *&BaseOp,
157162
int64_t &Offset, unsigned &Width,

llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,69 @@ TEST_P(RISCVInstrInfoTest, IsAddImmediate) {
9292
}
9393
}
9494

95+
TEST_P(RISCVInstrInfoTest, GetMemOperandsWithOffsetWidth) {
96+
const RISCVInstrInfo *TII = ST->getInstrInfo();
97+
const TargetRegisterInfo *TRI = ST->getRegisterInfo();
98+
DebugLoc DL;
99+
100+
SmallVector<const MachineOperand *> BaseOps;
101+
unsigned Width;
102+
int64_t Offset;
103+
bool OffsetIsScalable;
104+
105+
auto MMO = MF->getMachineMemOperand(MachinePointerInfo(),
106+
MachineMemOperand::MOLoad, 1, Align(1));
107+
MachineInstr *MI = BuildMI(*MF, DL, TII->get(RISCV::LB), RISCV::X1)
108+
.addReg(RISCV::X2)
109+
.addImm(-128)
110+
.addMemOperand(MMO)
111+
.getInstr();
112+
bool Res = TII->getMemOperandsWithOffsetWidth(*MI, BaseOps, Offset,
113+
OffsetIsScalable, Width, TRI);
114+
ASSERT_TRUE(Res);
115+
ASSERT_EQ(BaseOps.size(), 1u);
116+
ASSERT_TRUE(BaseOps.front()->isReg());
117+
EXPECT_EQ(BaseOps.front()->getReg(), RISCV::X2);
118+
EXPECT_EQ(Offset, -128);
119+
EXPECT_FALSE(OffsetIsScalable);
120+
EXPECT_EQ(Width, 1u);
121+
122+
BaseOps.clear();
123+
MMO = MF->getMachineMemOperand(MachinePointerInfo(),
124+
MachineMemOperand::MOStore, 4, Align(4));
125+
MI = BuildMI(*MF, DL, TII->get(RISCV::FSW))
126+
.addReg(RISCV::F3_F)
127+
.addReg(RISCV::X3)
128+
.addImm(36)
129+
.addMemOperand(MMO);
130+
Res = TII->getMemOperandsWithOffsetWidth(*MI, BaseOps, Offset,
131+
OffsetIsScalable, Width, TRI);
132+
ASSERT_TRUE(Res);
133+
ASSERT_EQ(BaseOps.size(), 1u);
134+
ASSERT_TRUE(BaseOps.front()->isReg());
135+
EXPECT_EQ(BaseOps.front()->getReg(), RISCV::X3);
136+
EXPECT_EQ(Offset, 36);
137+
EXPECT_FALSE(OffsetIsScalable);
138+
EXPECT_EQ(Width, 4u);
139+
140+
BaseOps.clear();
141+
MMO = MF->getMachineMemOperand(MachinePointerInfo(),
142+
MachineMemOperand::MOStore, 16, Align(16));
143+
MI = BuildMI(*MF, DL, TII->get(RISCV::PseudoVLE32_V_M1), RISCV::V8)
144+
.addReg(RISCV::X3)
145+
.addMemOperand(MMO);
146+
Res = TII->getMemOperandsWithOffsetWidth(*MI, BaseOps, Offset,
147+
OffsetIsScalable, Width, TRI);
148+
ASSERT_FALSE(Res); // Vector loads/stored are not handled for now.
149+
150+
BaseOps.clear();
151+
MI = BuildMI(*MF, DL, TII->get(RISCV::ADDI), RISCV::X4)
152+
.addReg(RISCV::X5)
153+
.addImm(16);
154+
Res = TII->getMemOperandsWithOffsetWidth(*MI, BaseOps, Offset,
155+
OffsetIsScalable, Width, TRI);
156+
}
157+
95158
} // namespace
96159

97160
INSTANTIATE_TEST_SUITE_P(RV32And64, RISCVInstrInfoTest,

0 commit comments

Comments
 (0)