38#define DEBUG_TYPE "riscv-load-store-opt"
39#define RISCV_LOAD_STORE_OPT_NAME "RISC-V Load / Store Optimizer"
45STATISTIC(NumLD2LW,
"Number of LD instructions split back to LW");
46STATISTIC(NumSD2SW,
"Number of SD instructions split back to SW");
56 MachineFunctionProperties getRequiredProperties()
const override {
57 return MachineFunctionProperties().setNoVRegs();
60 void getAnalysisUsage(AnalysisUsage &AU)
const override {
85 bool fixInvalidRegPairOp(MachineBasicBlock &
MBB,
88 void splitLdSdIntoTwo(MachineBasicBlock &
MBB,
93 MachineRegisterInfo *MRI;
94 const RISCVInstrInfo *TII;
95 const RISCVRegisterInfo *TRI;
96 LiveRegUnits ModifiedRegUnits, UsedRegUnits;
100char RISCVLoadStoreOpt::ID = 0;
105 if (skipFunction(Fn.getFunction()))
109 bool MadeChange =
false;
110 TII = Subtarget.getInstrInfo();
111 TRI = Subtarget.getRegisterInfo();
112 MRI = &Fn.getRegInfo();
113 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
114 ModifiedRegUnits.init(*
TRI);
115 UsedRegUnits.init(*
TRI);
117 if (Subtarget.useMIPSLoadStorePairs()) {
118 for (MachineBasicBlock &MBB : Fn) {
119 LLVM_DEBUG(dbgs() <<
"MBB: " << MBB.getName() <<
"\n");
121 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
123 if (TII->isPairableLdStInstOpc(MBBI->getOpcode()) &&
124 tryToPairLdStInst(MBBI))
132 if (!Subtarget.is64Bit() && Subtarget.hasStdExtZilsd()) {
133 for (auto &MBB : Fn) {
134 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E;) {
135 if (fixInvalidRegPairOp(MBB, MBBI)) {
154 if (
MI.hasOrderedMemoryRef())
157 if (!
TII->isLdStSafeToPair(
MI,
TRI))
165 MBBI = mergePairedInsns(
MBBI, Paired, MergeForward);
177bool RISCVLoadStoreOpt::tryConvertToLdStPair(
180 Align RequiredAlignment;
181 switch (
First->getOpcode()) {
185 PairOpc = RISCV::MIPS_SWP;
186 RequiredAlignment =
Align(8);
189 PairOpc = RISCV::MIPS_LWP;
190 RequiredAlignment =
Align(8);
193 PairOpc = RISCV::MIPS_SDP;
194 RequiredAlignment =
Align(16);
197 PairOpc = RISCV::MIPS_LDP;
198 RequiredAlignment =
Align(16);
202 MachineFunction *MF =
First->getMF();
203 const MachineMemOperand *MMO = *
First->memoperands_begin();
206 if (MMOAlign < RequiredAlignment)
213 MachineInstrBuilder MIB =
BuildMI(
214 *MF,
First->getDebugLoc() ?
First->getDebugLoc() : Second->getDebugLoc(),
217 .
add(Second->getOperand(0))
224 First->removeFromParent();
225 Second->removeFromParent();
248 bool &MergeForward) {
251 MachineInstr &FirstMI = *
I;
260 MergeForward =
false;
264 ModifiedRegUnits.
clear();
265 UsedRegUnits.
clear();
268 SmallVector<MachineInstr *, 4> MemInsns;
276 if (!
MI.isTransient())
281 Register MIBaseReg =
MI.getOperand(1).getReg();
282 int64_t MIOffset =
MI.getOperand(2).getImm();
284 if (BaseReg == MIBaseReg) {
285 if ((
Offset != MIOffset + OffsetStride) &&
286 (
Offset + OffsetStride != MIOffset)) {
296 TRI->isSuperOrSubRegisterEq(
Reg,
MI.getOperand(0).getReg())) {
304 if (!ModifiedRegUnits.
available(BaseReg))
311 if (ModifiedRegUnits.
available(
MI.getOperand(0).getReg()) &&
313 !UsedRegUnits.
available(
MI.getOperand(0).getReg())) &&
316 MergeForward =
false;
348 if (!ModifiedRegUnits.
available(BaseReg))
352 if (
MI.mayLoadOrStore())
375 int Offset =
I->getOperand(2).getImm();
376 int PairedOffset = Paired->getOperand(2).getImm();
377 bool InsertAfter = (
Offset < PairedOffset) ^ MergeForward;
380 Paired->getOperand(1).setIsKill(
false);
383 if (
I->getOperand(0).isUse()) {
387 MachineOperand &PairedRegOp = Paired->getOperand(0);
388 if (PairedRegOp.
isKill()) {
389 for (
auto It = std::next(
I); It != Paired; ++It) {
390 if (It->readsRegister(PairedRegOp.
getReg(),
TRI)) {
400 for (MachineInstr &
MI :
make_range(std::next(
I), std::next(Paired)))
405 MachineInstr *ToInsert = DeletionPoint->removeFromParent();
406 MachineBasicBlock &
MBB = *InsertionPoint->getParent();
411 Second = InsertionPoint;
414 First = InsertionPoint;
417 if (tryConvertToLdStPair(
First, Second)) {
436 if (
First == RISCV::X0)
437 return Second == RISCV::X0;
440 unsigned FirstNum =
TRI->getEncodingValue(
First);
441 unsigned SecondNum =
TRI->getEncodingValue(Second);
444 return (FirstNum % 2 == 0) && (SecondNum == FirstNum + 1);
447void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &
MBB,
450 MachineInstr *
MI = &*
MBBI;
453 const MachineOperand &FirstOp =
MI->getOperand(0);
454 const MachineOperand &SecondOp =
MI->getOperand(1);
455 const MachineOperand &BaseOp =
MI->getOperand(2);
461 const MachineOperand &
OffsetOp =
MI->getOperand(3);
469 unsigned Opc = IsLoad ? RISCV::LW : RISCV::SW;
470 MachineInstrBuilder MIB1, MIB2;
483 if (FirstReg == BaseReg) {
509 FirstReg != SecondReg &&
510 "First register and second register is impossible to be same register");
526 MIB2.
addImm(BaseOffset + 4);
547bool RISCVLoadStoreOpt::fixInvalidRegPairOp(MachineBasicBlock &
MBB,
549 MachineInstr *
MI = &*
MBBI;
550 unsigned Opcode =
MI->getOpcode();
553 if (Opcode != RISCV::PseudoLD_RV32_OPT && Opcode != RISCV::PseudoSD_RV32_OPT)
556 bool IsLoad = Opcode == RISCV::PseudoLD_RV32_OPT;
558 const MachineOperand &FirstOp =
MI->getOperand(0);
559 const MachineOperand &SecondOp =
MI->getOperand(1);
563 if (!isValidZilsdRegPair(FirstReg, SecondReg)) {
565 splitLdSdIntoTwo(
MBB,
MBBI, IsLoad);
570 const MachineOperand &BaseOp =
MI->getOperand(2);
574 const MachineOperand &
OffsetOp =
MI->getOperand(3);
576 unsigned RealOpc = IsLoad ? RISCV::LD_RV32 : RISCV::SD_RV32;
579 unsigned RegPair =
TRI->getMatchingSuperReg(FirstReg, RISCV::sub_gpr_even,
580 &RISCV::GPRPairRegClass);
597 LLVM_DEBUG(
dbgs() <<
"Converted pseudo to real instruction: " << *MIB
608 return new RISCVLoadStoreOpt();
unsigned const MachineRegisterInfo * MRI
static bool mayAlias(MachineInstr &MIa, SmallVectorImpl< MachineInstr * > &MemInsns, AliasAnalysis *AA)
static cl::opt< unsigned > LdStLimit("aarch64-load-store-scan-limit", cl::init(20), cl::Hidden)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define RISCV_LOAD_STORE_OPT_NAME
static cl::opt< unsigned > LdStLimit("riscv-load-store-scan-limit", cl::init(128), cl::Hidden)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
AnalysisUsage & addRequired()
FunctionPass class - This class is used to implement most global optimizations.
static void accumulateUsedDefed(const MachineInstr &MI, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI)
For a machine instruction MI, adds all register units used in UsedRegUnits and defined or clobbered i...
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void clear()
Clears the set.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator insertAfter(iterator I, MachineInstr *MI)
Insert MI into the instruction list after I.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr * > OtherMIs) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI bool mayAlias(BatchAAResults *AA, const MachineInstr &Other, bool UseTBAA) const
Returns true if this instruction's memory access aliases the memory access of Other.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Define
Register definition.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionPass * createRISCVLoadStoreOptPass()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getDeadRegState(bool B)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
unsigned getKillRegState(bool B)
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It, then continue decrementing it while it points to a debug instruction.