Skip to content

Commit f3006f8

Browse files
committed
[RISCV] Generate MIPS load/store pair instructions
Introduce RISCVLoadStoreOptimizer MIR Pass that will do the optimization. It bundles loads and stores that operate on consecutive memory locations to take the advantage of hardware load/store bonding or replaces them with ldp/sdp instructions. 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 de968c8 commit f3006f8

File tree

9 files changed

+941
-1
lines changed

9 files changed

+941
-1
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
RISCVISelLowering.cpp
4949
RISCVLandingPadSetup.cpp
5050
RISCVMachineFunctionInfo.cpp
51+
RISCVLoadStoreOptimizer.cpp
5152
RISCVMergeBaseOffset.cpp
5253
RISCVOptWInstrs.cpp
5354
RISCVPostRAExpandPseudoInsts.cpp

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2749,6 +2749,46 @@ MachineInstr *RISCVInstrInfo::emitLdStWithAddr(MachineInstr &MemI,
27492749
.setMIFlags(MemI.getFlags());
27502750
}
27512751

2752+
bool RISCVInstrInfo::isPairableLdStInstOpc(unsigned Opc) {
2753+
switch (Opc) {
2754+
default:
2755+
return false;
2756+
case RISCV::SH:
2757+
case RISCV::LH:
2758+
case RISCV::LHU:
2759+
case RISCV::SW:
2760+
case RISCV::FSW:
2761+
case RISCV::LW:
2762+
case RISCV::FLW:
2763+
case RISCV::SD:
2764+
case RISCV::FSD:
2765+
case RISCV::LD:
2766+
case RISCV::FLD:
2767+
return true;
2768+
}
2769+
}
2770+
2771+
bool RISCVInstrInfo::isLdStSafeToPair(const MachineInstr &LdSt,
2772+
const TargetRegisterInfo *TRI) {
2773+
// If this is a volatile load/store, don't mess with it.
2774+
if (LdSt.hasOrderedMemoryRef() || LdSt.getNumExplicitOperands() != 3)
2775+
return false;
2776+
2777+
if (LdSt.getOperand(1).isFI())
2778+
return true;
2779+
2780+
assert(LdSt.getOperand(1).isReg() && "Expected a reg operand.");
2781+
// Can't cluster if the instruction modifies the base register
2782+
// or it is update form. e.g. ld x5,8(x5)
2783+
if (LdSt.modifiesRegister(LdSt.getOperand(1).getReg(), TRI))
2784+
return false;
2785+
2786+
if (!LdSt.getOperand(2).isImm())
2787+
return false;
2788+
2789+
return true;
2790+
}
2791+
27522792
bool RISCVInstrInfo::getMemOperandsWithOffsetWidth(
27532793
const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps,
27542794
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
@@ -300,6 +300,12 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
300300
std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
301301
analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;
302302

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

0 commit comments

Comments
 (0)