46#define DEBUG_TYPE "riscv-pre-alloc-zilsd-opt"
48STATISTIC(NumLDFormed,
"Number of LD instructions formed");
49STATISTIC(NumSDFormed,
"Number of SD instructions formed");
64 StringRef getPassName()
const override {
65 return "RISC-V pre-allocation Zilsd load/store optimization";
68 MachineFunctionProperties getRequiredProperties()
const override {
69 return MachineFunctionProperties().setIsSSA();
72 void getAnalysisUsage(AnalysisUsage &AU)
const override {
79class RISCVPreAllocZilsdOptImpl {
80 enum class MemoryOffsetKind {
88 using MemOffset = std::pair<MemoryOffsetKind, int>;
89 using BaseRegInfo = std::pair<unsigned, MemoryOffsetKind>;
92 bool rescheduleLoadStoreInstrs(MachineBasicBlock *
MBB);
93 bool canFormLdSdPair(MachineInstr *MI0, MachineInstr *MI1);
94 bool rescheduleOps(MachineBasicBlock *
MBB,
95 SmallVectorImpl<MachineInstr *> &MIs, BaseRegInfo
Base,
97 DenseMap<MachineInstr *, unsigned> &MI2LocMap);
98 bool isSafeToMove(MachineInstr *
MI, MachineInstr *Target,
bool MoveForward);
101 const RISCVSubtarget *STI;
102 const RISCVInstrInfo *TII;
103 const RISCVRegisterInfo *TRI;
104 MachineRegisterInfo *MRI;
115char RISCVPreAllocZilsdOptLegacy::ID = 0;
118 "RISC-V pre-allocation Zilsd optimization",
false,
false)
127bool RISCVPreAllocZilsdOptImpl::runOnMachineFunction(
130 if (!STI->getCLOpts().zilsd_opt)
134 if (STI->is64Bit() || !STI->hasStdExtZilsd())
137 TII = STI->getInstrInfo();
138 TRI = STI->getRegisterInfo();
139 MRI = &MF.getRegInfo();
144 RequiredAlign = STI->getZilsdAlign();
146 for (
auto &
MBB : MF) {
153RISCVPreAllocZilsdOptImpl::MemOffset
154RISCVPreAllocZilsdOptImpl::getMemoryOpOffset(
const MachineInstr &
MI) {
155 switch (
MI.getOpcode()) {
159 const MachineOperand &BaseOp =
MI.getOperand(1);
160 const MachineOperand &
OffsetOp =
MI.getOperand(2);
165 return std::make_pair(MemoryOffsetKind::FrameIdx,
OffsetOp.getImm());
166 return std::make_pair(MemoryOffsetKind::Imm,
OffsetOp.getImm());
172 return std::make_pair(MemoryOffsetKind::Global,
OffsetOp.getOffset());
174 return std::make_pair(MemoryOffsetKind::CPI,
OffsetOp.getOffset());
176 return std::make_pair(MemoryOffsetKind::BlockAddr,
186 return std::make_pair(MemoryOffsetKind::Unknown, 0);
189bool RISCVPreAllocZilsdOptImpl::canFormLdSdPair(MachineInstr *MI0,
199 if (Offset1 - Offset0 != 4)
203 const MachineMemOperand *MMO = *MI0->memoperands_begin();
204 if (MMO->
getAlign() < RequiredAlign)
209 if (MI0->getOperand(0).getReg() == MI1->getOperand(0).getReg())
215bool RISCVPreAllocZilsdOptImpl::isSafeToMove(MachineInstr *
MI,
216 MachineInstr *Target,
230 const MachineOperand &BaseOp =
MI->getOperand(1);
232 unsigned ScanCount = 0;
233 for (
auto It = Start; It !=
End; ++It, ++ScanCount) {
235 if (It->isCall() || It->isTerminator()) {
236 LLVM_DEBUG(
dbgs() <<
"Cannot move across call/terminator: " << *It);
241 if (It->hasUnmodeledSideEffects()) {
242 LLVM_DEBUG(
dbgs() <<
"Cannot move across instruction with side effects: "
248 if (BaseOp.
isReg() && It->modifiesRegister(BaseOp.
getReg(),
TRI)) {
250 <<
" modified by: " << *It);
256 (It->readsRegister(DefReg,
TRI) || It->modifiesRegister(DefReg,
TRI))) {
258 <<
" used by: " << *It);
263 if (
MI->mayStore() && It->modifiesRegister(DefReg,
TRI)) {
265 <<
" modified by: " << *It);
270 if (It->mayLoadOrStore() && It->mayAlias(AA, *
MI,
false)) {
279bool RISCVPreAllocZilsdOptImpl::rescheduleOps(
280 MachineBasicBlock *
MBB, SmallVectorImpl<MachineInstr *> &MIs,
281 BaseRegInfo
Base,
bool IsLoad,
282 DenseMap<MachineInstr *, unsigned> &MI2LocMap) {
286 return getMemoryOpOffset(*A).second < getMemoryOpOffset(*B).second;
292 for (
size_t i = 0; i + 1 < MIs.
size(); i++) {
293 MachineInstr *MI0 = MIs[i];
294 MachineInstr *MI1 = MIs[i + 1];
298 const MachineOperand &BaseOp = MI0->
getOperand(1);
301 "Base register should be register or frame index");
309 if (!canFormLdSdPair(MI0, MI1))
314 bool MI1IsLater = MI2LocMap[MI1] > MI2LocMap[MI0];
318 MachineInstr *MoveInstr, *TargetInstr;
321 MoveInstr = MI1IsLater ? MI1 : MI0;
322 TargetInstr = MI1IsLater ? MI0 : MI1;
325 MoveInstr = MI1IsLater ? MI0 : MI1;
326 TargetInstr = MI1IsLater ? MI1 : MI0;
329 unsigned Distance = MI1IsLater ? MI2LocMap[MI1] - MI2LocMap[MI0]
330 : MI2LocMap[MI0] - MI2LocMap[MI1];
332 Distance > STI->
getCLOpts().zilsd_max_reschedule_distance)
340 if (MoveInstr != TargetInstr)
344 MachineInstrBuilder MIB;
394bool RISCVPreAllocZilsdOptImpl::isMemoryOp(
const MachineInstr &
MI) {
395 unsigned Opcode =
MI.getOpcode();
396 if (Opcode != RISCV::LW && Opcode != RISCV::SW)
399 if (!
MI.getOperand(1).isReg() && !
MI.getOperand(1).isFI())
404 if (!
MI.hasOneMemOperand())
407 const MachineMemOperand *MMO = *
MI.memoperands_begin();
414 if (
MI.getOperand(0).isReg() &&
MI.getOperand(0).isUndef())
418 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).isUndef())
424bool RISCVPreAllocZilsdOptImpl::rescheduleLoadStoreInstrs(
425 MachineBasicBlock *
MBB) {
435 DenseMap<MachineInstr *, unsigned> MI2LocMap;
438 using Base2InstMap = DenseMap<BaseRegInfo, SmallVector<MachineInstr *, 4>>;
440 Base2InstMap Base2LdsMap;
441 Base2InstMap Base2StsMap;
452 if (
MI.isCall() ||
MI.isTerminator()) {
459 if (!
MI.isDebugInstr())
460 MI2LocMap[&
MI] = ++Loc;
467 bool IsLd = (
MI.getOpcode() == RISCV::LW);
468 const MachineOperand &BaseOp =
MI.getOperand(1);
474 bool StopHere =
false;
477 auto FindBases = [&](Base2InstMap &Base2Ops, BaseVec &Bases) {
481 BI->second.push_back(&
MI);
486 if (
any_of(BI->second, [&](
const MachineInstr *PrevMI) {
487 return Offset == getMemoryOpOffset(*PrevMI);
492 BI->second.push_back(&
MI);
497 FindBases(Base2LdsMap, LdBases);
499 FindBases(Base2StsMap, StBases);
510 for (
auto Base : LdBases) {
511 SmallVectorImpl<MachineInstr *> &Lds = Base2LdsMap[
Base];
512 if (Lds.
size() > 1) {
518 for (
auto Base : StBases) {
519 SmallVectorImpl<MachineInstr *> &Sts = Base2StsMap[
Base];
520 if (Sts.
size() > 1) {
534 return new RISCVPreAllocZilsdOptLegacy();
537bool RISCVPreAllocZilsdOptLegacy::runOnMachineFunction(
MachineFunction &MF) {
540 RISCVPreAllocZilsdOptImpl Impl;
541 return Impl.runOnMachineFunction(MF, [&]() {
542 return &getAnalysis<AAResultsWrapperPass>().getAAResults();
549 RISCVPreAllocZilsdOptImpl Impl;
550 bool Changed = Impl.runOnMachineFunction(MF, [&]() {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isMemoryOp(const MachineInstr &MI)
Returns true if instruction is a memory operation that this pass is capable of operating on.
static int getMemoryOpOffset(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
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_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
MachineRegisterInfo & MRI
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use, const MachineInstr *Insert, const WebAssemblyFunctionInfo &MFI, const MachineRegisterInfo &MRI, bool Optimize)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr * > OtherMIs) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const RISCVOptions & getCLOpts() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr unsigned id() const
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
Pass manager infrastructure for declaring and invalidating analyses.
Abstract Attribute helper functions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Unknown
Not known to have no common set bits.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Global
Append to llvm.global_dtors.
@ End
Run the machine verifier once, at the end of the pipeline.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
FunctionPass * createRISCVPreAllocZilsdOptLegacyPass()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.