Skip to content

Commit 5048a08

Browse files
authored
[RISCV] Generate MIPS load/store pair instructions (#124717)
Introduce RISCVLoadStoreOptimizer MIR Pass that will do the optimization. The load/store pairing pass identifies adjacent load/store instructions operating on consecutive memory locations and merges them into a single paired instruction. This is part of MIPS extensions for the p8700 CPU. Production of ldp/sdp instructions is OFF by default, since it is beneficial for -Os only in the case of p8700 CPU.
1 parent 749d68b commit 5048a08

File tree

8 files changed

+787
-7
lines changed

8 files changed

+787
-7
lines changed

llvm/lib/Target/RISCV/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ add_llvm_target(RISCVCodeGen
4848
RISCVISelDAGToDAG.cpp
4949
RISCVISelLowering.cpp
5050
RISCVLandingPadSetup.cpp
51+
RISCVLoadStoreOptimizer.cpp
5152
RISCVMachineFunctionInfo.cpp
5253
RISCVMergeBaseOffset.cpp
5354
RISCVOptWInstrs.cpp

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2767,6 +2767,42 @@ MachineInstr *RISCVInstrInfo::emitLdStWithAddr(MachineInstr &MemI,
27672767
.setMIFlags(MemI.getFlags());
27682768
}
27692769

2770+
// TODO: At the moment, MIPS introduced paring of instructions operating with
2771+
// word or double word. This should be extended with more instructions when more
2772+
// vendors support load/store pairing.
2773+
bool RISCVInstrInfo::isPairableLdStInstOpc(unsigned Opc) {
2774+
switch (Opc) {
2775+
default:
2776+
return false;
2777+
case RISCV::SW:
2778+
case RISCV::SD:
2779+
case RISCV::LD:
2780+
case RISCV::LW:
2781+
return true;
2782+
}
2783+
}
2784+
2785+
bool RISCVInstrInfo::isLdStSafeToPair(const MachineInstr &LdSt,
2786+
const TargetRegisterInfo *TRI) {
2787+
// If this is a volatile load/store, don't mess with it.
2788+
if (LdSt.hasOrderedMemoryRef() || LdSt.getNumExplicitOperands() != 3)
2789+
return false;
2790+
2791+
if (LdSt.getOperand(1).isFI())
2792+
return true;
2793+
2794+
assert(LdSt.getOperand(1).isReg() && "Expected a reg operand.");
2795+
// Can't cluster if the instruction modifies the base register
2796+
// or it is update form. e.g. ld x5,8(x5)
2797+
if (LdSt.modifiesRegister(LdSt.getOperand(1).getReg(), TRI))
2798+
return false;
2799+
2800+
if (!LdSt.getOperand(2).isImm())
2801+
return false;
2802+
2803+
return true;
2804+
}
2805+
27702806
bool RISCVInstrInfo::getMemOperandsWithOffsetWidth(
27712807
const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps,
27722808
int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,

llvm/lib/Target/RISCV/RISCVInstrInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,12 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
301301

302302
bool isHighLatencyDef(int Opc) const override;
303303

304+
/// Return true if pairing the given load or store may be paired with another.
305+
static bool isPairableLdStInstOpc(unsigned Opc);
306+
307+
static bool isLdStSafeToPair(const MachineInstr &LdSt,
308+
const TargetRegisterInfo *TRI);
309+
304310
protected:
305311
const RISCVSubtarget &STI;
306312

0 commit comments

Comments
 (0)