34#define DEBUG_TYPE "riscv-load-store-opt"
35#define RISCV_LOAD_STORE_OPT_NAME "RISC-V Load / Store Optimizer"
50 MachineFunctionProperties getRequiredProperties()
const override {
51 return MachineFunctionProperties().setNoVRegs();
54 void getAnalysisUsage(AnalysisUsage &AU)
const override {
80 MachineRegisterInfo *MRI;
81 const RISCVInstrInfo *TII;
82 const RISCVRegisterInfo *TRI;
83 LiveRegUnits ModifiedRegUnits, UsedRegUnits;
87char RISCVLoadStoreOpt::ID = 0;
92 if (skipFunction(Fn.getFunction()))
95 if (!Subtarget.useLoadStorePairs())
98 bool MadeChange =
false;
99 TII = Subtarget.getInstrInfo();
100 TRI = Subtarget.getRegisterInfo();
101 MRI = &Fn.getRegInfo();
102 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
103 ModifiedRegUnits.init(*
TRI);
104 UsedRegUnits.init(*
TRI);
111 if (
TII->isPairableLdStInstOpc(
MBBI->getOpcode()) &&
112 tryToPairLdStInst(
MBBI))
127 if (
MI.hasOrderedMemoryRef())
130 if (!
TII->isLdStSafeToPair(
MI,
TRI))
138 MBBI = mergePairedInsns(
MBBI, Paired, MergeForward);
150bool RISCVLoadStoreOpt::tryConvertToLdStPair(
153 Align RequiredAlignment;
154 switch (
First->getOpcode()) {
158 PairOpc = RISCV::MIPS_SWP;
159 RequiredAlignment =
Align(8);
162 PairOpc = RISCV::MIPS_LWP;
163 RequiredAlignment =
Align(8);
166 PairOpc = RISCV::MIPS_SDP;
167 RequiredAlignment =
Align(16);
170 PairOpc = RISCV::MIPS_LDP;
171 RequiredAlignment =
Align(16);
175 MachineFunction *MF =
First->getMF();
176 const MachineMemOperand *MMO = *
First->memoperands_begin();
179 if (MMOAlign < RequiredAlignment)
186 MachineInstrBuilder MIB =
BuildMI(
187 *MF,
First->getDebugLoc() ?
First->getDebugLoc() : Second->getDebugLoc(),
190 .
add(Second->getOperand(0))
197 First->removeFromParent();
198 Second->removeFromParent();
221 bool &MergeForward) {
224 MachineInstr &FirstMI = *
I;
233 MergeForward =
false;
237 ModifiedRegUnits.
clear();
238 UsedRegUnits.
clear();
241 SmallVector<MachineInstr *, 4> MemInsns;
249 if (!
MI.isTransient())
254 Register MIBaseReg =
MI.getOperand(1).getReg();
255 int64_t MIOffset =
MI.getOperand(2).getImm();
257 if (BaseReg == MIBaseReg) {
258 if ((
Offset != MIOffset + OffsetStride) &&
259 (
Offset + OffsetStride != MIOffset)) {
269 TRI->isSuperOrSubRegisterEq(
Reg,
MI.getOperand(0).getReg())) {
277 if (!ModifiedRegUnits.
available(BaseReg))
284 if (ModifiedRegUnits.
available(
MI.getOperand(0).getReg()) &&
286 !UsedRegUnits.
available(
MI.getOperand(0).getReg())) &&
289 MergeForward =
false;
321 if (!ModifiedRegUnits.
available(BaseReg))
325 if (
MI.mayLoadOrStore())
348 int Offset =
I->getOperand(2).getImm();
349 int PairedOffset = Paired->getOperand(2).getImm();
350 bool InsertAfter = (
Offset < PairedOffset) ^ MergeForward;
353 Paired->getOperand(1).setIsKill(
false);
356 if (
I->getOperand(0).isUse()) {
360 MachineOperand &PairedRegOp = Paired->getOperand(0);
361 if (PairedRegOp.
isKill()) {
362 for (
auto It = std::next(
I); It != Paired; ++It) {
363 if (It->readsRegister(PairedRegOp.
getReg(),
TRI)) {
373 for (MachineInstr &
MI :
make_range(std::next(
I), std::next(Paired)))
378 MachineInstr *ToInsert = DeletionPoint->removeFromParent();
379 MachineBasicBlock &
MBB = *InsertionPoint->getParent();
384 Second = InsertionPoint;
387 First = InsertionPoint;
390 if (tryConvertToLdStPair(
First, Second)) {
400 return new RISCVLoadStoreOpt();
unsigned const MachineRegisterInfo * MRI
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
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)
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
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)
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.
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 & add(const MachineOperand &MO) 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.
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.
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.
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.