54 #define DEBUG_TYPE "mips-delay-slot-filler" 56 STATISTIC(FilledSlots,
"Number of delay slots filled");
57 STATISTIC(UsefulSlots,
"Number of delay slots filled with instructions that" 61 "disable-mips-delay-filler",
63 cl::desc(
"Fill all delay slots with NOPs."),
67 "disable-mips-df-forward-search",
69 cl::desc(
"Disallow MIPS delay filler to search forward."),
73 "disable-mips-df-succbb-search",
75 cl::desc(
"Disallow MIPS delay filler to search successor basic blocks."),
79 "disable-mips-df-backward-search",
81 cl::desc(
"Disallow MIPS delay filler to search backward."),
97 cl::desc(
"MIPS Specific: Compact branch policy."),
128 bool update(
const MachineInstr &
MI,
unsigned Begin,
unsigned End);
135 bool isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const;
142 class InspectMemInstr {
144 InspectMemInstr(
bool ForbidMemInstr_) : ForbidMemInstr(ForbidMemInstr_) {}
145 virtual ~InspectMemInstr() =
default;
152 bool OrigSeenLoad =
false;
153 bool OrigSeenStore =
false;
154 bool SeenLoad =
false;
155 bool SeenStore =
false;
166 class NoMemInstr :
public InspectMemInstr {
168 NoMemInstr() : InspectMemInstr(
true) {}
175 class LoadFromStackOrConst :
public InspectMemInstr {
177 LoadFromStackOrConst() : InspectMemInstr(
false) {}
185 class MemDefsUses :
public InspectMemInstr {
209 bool SeenNoObjLoad =
false;
210 bool SeenNoObjStore =
false;
219 StringRef getPassName()
const override {
return "Mips Delay Slot Filler"; }
223 bool Changed =
false;
226 Changed |= runOnMachineBasicBlock(*FI);
258 bool delayHasHazard(
const MachineInstr &Candidate, RegDefsUses &RegDU,
259 InspectMemInstr &IM)
const;
263 template<
typename IterTy>
265 RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot,
266 IterTy &Filler)
const;
287 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
293 RegDefsUses &RegDU,
bool &HasMultipleSuccs,
294 BB2BrMap &
BrMap)
const;
296 bool terminateSearch(
const MachineInstr &Candidate)
const;
310 "Fill delay slot for MIPS",
false,
false)
313 static
void insertDelayFiller(Iter Filler,
const BB2BrMap &
BrMap) {
316 for (BB2BrMap::const_iterator
I = BrMap.begin();
I != BrMap.end(); ++
I) {
328 for (
unsigned I = 0,
E = Filler->getNumOperands();
I !=
E; ++
I) {
338 "Shouldn't move an instruction with unallocatable registers across " 339 "basic block boundaries.");
363 Defs.reset(Mips::AT);
367 void RegDefsUses::setCallerSaved(
const MachineInstr &MI) {
375 Defs.set(Mips::RA_64);
381 CallerSavedRegs.
reset(Mips::ZERO);
382 CallerSavedRegs.
reset(Mips::ZERO_64);
387 CallerSavedRegs.
reset(*AI);
389 Defs |= CallerSavedRegs;
395 for (
unsigned R : AllocSet.
set_bits())
399 AllocSet.
set(Mips::ZERO);
400 AllocSet.
set(Mips::ZERO_64);
402 Defs |= AllocSet.
flip();
410 for (
const auto &LI : (*SI)->liveins())
411 Uses.
set(LI.PhysReg);
414 bool RegDefsUses::update(
const MachineInstr &MI,
unsigned Begin,
unsigned End) {
416 bool HasHazard =
false;
418 for (
unsigned I = Begin;
I != End; ++
I) {
422 HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.
getReg(), MO.
isDef());
432 unsigned Reg,
bool IsDef)
const {
436 return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg));
441 return isRegInSet(Defs, Reg);
444 bool RegDefsUses::isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const {
447 if (RegSet.
test(*AI))
452 bool InspectMemInstr::hasHazard(
const MachineInstr &MI) {
459 OrigSeenLoad = SeenLoad;
460 OrigSeenStore = SeenStore;
467 ForbidMemInstr =
true;
471 return hasHazard_(MI);
474 bool LoadFromStackOrConst::hasHazard_(
const MachineInstr &MI) {
483 if (isa<FixedStackPseudoSourceValue>(PSV))
485 return !PSV->isConstant(
nullptr) && !PSV->isStack();
492 : InspectMemInstr(
false), MFI(MFI_), DL(DL) {}
495 bool HasHazard =
false;
501 I != Objs.
end(); ++
I)
502 HasHazard |= updateDefsUses(*
I, MI.
mayStore());
508 HasHazard = MI.
mayStore() && (OrigSeenLoad || OrigSeenStore);
509 HasHazard |= MI.
mayLoad() || OrigSeenStore;
519 return !Defs.insert(V).second || Uses.count(V) || SeenNoObjStore ||
523 return Defs.count(V) || SeenNoObjStore;
536 if (!PSV->isAliased(MFI))
566 Branch = TII->genInstrWithNewOpc(NewOpcode, Branch);
568 std::next(Branch)->eraseFromParent();
580 return Mips::BGEZALS_MM;
582 return Mips::BLTZALS_MM;
585 return Mips::JALS_MM;
587 return Mips::JALRS_MM;
588 case Mips::JALR16_MM:
589 return Mips::JALRS16_MM;
590 case Mips::TAILCALL_MM:
592 case Mips::TAILCALLREG:
593 return Mips::JR16_MM;
602 bool Changed =
false;
619 if (searchBackward(MBB, *
I)) {
621 }
else if (
I->isTerminator()) {
622 if (searchSuccBBs(MBB,
I)) {
625 }
else if (searchForward(MBB,
I)) {
661 if ((InMicroMipsMode ||
664 I = replaceWithCompactBranch(MBB,
I,
I->getDebugLoc());
670 BuildMI(MBB, std::next(
I),
I->getDebugLoc(), TII->get(Mips::NOP));
679 template <
typename IterTy>
681 IterTy End, RegDefsUses &RegDU,
682 InspectMemInstr &IM, Iter Slot,
683 IterTy &Filler)
const {
684 for (IterTy
I = Begin;
I != End;) {
689 if (CurrI->isDebugInstr())
692 if (terminateSearch(*CurrI))
695 assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) &&
696 "Cannot put calls, returns or branches in delay slot.");
698 if (CurrI->isKill()) {
699 CurrI->eraseFromParent();
703 if (delayHasHazard(*CurrI, RegDU, IM))
721 unsigned Opcode = (*Slot).getOpcode();
728 (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
729 Opcode == Mips::PseudoIndirectBranch_MM ||
730 Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL))
734 if (InMicroMipsMode && (Opcode == Mips::LWP_MM || Opcode == Mips::SWP_MM ||
735 Opcode == Mips::MOVEP_MM))
751 RegDefsUses RegDU(*Fn->getSubtarget().getRegisterInfo());
752 MemDefsUses MemDU(Fn->getDataLayout(), &Fn->getFrameInfo());
758 if (!searchRange(MBB, ++SlotI.
getReverse(), MBB.
rend(), RegDU, MemDU, Slot,
762 MBB.
splice(std::next(SlotI), &MBB, Filler.getReverse());
778 RegDU.setCallerSaved(*Slot);
780 if (!searchRange(MBB, std::next(Slot), MBB.
end(), RegDU, NM, Slot, Filler))
783 MBB.
splice(std::next(Slot), &MBB, Filler);
800 bool HasMultipleSuccs =
false;
802 std::unique_ptr<InspectMemInstr> IM;
808 PE = SuccBB->
pred_end(); PI != PE; ++PI)
809 if (!examinePred(**PI, *SuccBB, RegDU, HasMultipleSuccs, BrMap))
814 RegDU.setUnallocatableRegs(*Fn);
818 if (HasMultipleSuccs) {
819 IM.reset(
new LoadFromStackOrConst());
822 IM.reset(
new MemDefsUses(Fn->getDataLayout(), &MFI));
825 if (!searchRange(MBB, SuccBB->
begin(), SuccBB->
end(), RegDU, *IM, Slot,
829 insertDelayFiller(Filler, BrMap);
831 Filler->eraseFromParent();
842 auto &Prob = getAnalysis<MachineBranchProbabilityInfo>();
846 return Prob.getEdgeProbability(&B, Dst0) <
847 Prob.getEdgeProbability(&B, Dst1);
849 return S->
isEHPad() ? nullptr : S;
852 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
862 TII->
analyzeBranch(MBB, TrueBB, FalseBB, Cond,
false, BranchInstrs);
865 return std::make_pair(R,
nullptr);
873 return std::make_pair(R, BranchInstrs[0]);
876 assert((TrueBB == &Dst) || (FalseBB == &Dst));
892 bool &HasMultipleSuccs,
893 BB2BrMap &BrMap)
const {
894 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
P =
895 getBranch(Pred, Succ);
904 HasMultipleSuccs =
true;
905 RegDU.addLiveOut(Pred, Succ);
908 BrMap[&Pred] = P.second;
912 bool MipsDelaySlotFiller::delayHasHazard(
const MachineInstr &Candidate,
914 InspectMemInstr &IM)
const {
916 "KILL instructions should have been eliminated at this point.");
920 HasHazard |= IM.hasHazard(Candidate);
921 HasHazard |= RegDU.update(Candidate, 0, Candidate.
getNumOperands());
926 bool MipsDelaySlotFiller::terminateSearch(
const MachineInstr &Candidate)
const {
BitVector getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC=nullptr) const
Returns a bitset indexed by register number indicating if a register is allocatable or not...
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
Return the number of bytes of code the specified instruction may be.
A parsed version of the target data layout string in and methods for querying it. ...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
bool isCall(QueryType Type=AnyInBundle) const
typename SuperClass::const_iterator const_iterator
This class represents lattice values for constants.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Branch Analysis.
static cl::opt< CompactBranchPolicy > MipsCompactBranchPolicy("mips-compact-branches", cl::Optional, cl::init(CB_Optimal), cl::desc("MIPS Specific: Compact branch policy."), cl::values(clEnumValN(CB_Never, "never", "Do not use compact branches if possible."), clEnumValN(CB_Optimal, "optimal", "Use compact branches where appropiate (default)."), clEnumValN(CB_Always, "always", "Always use compact branches if possible.")))
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx, bool *IsStore=nullptr)
void push_back(const T &Elt)
unsigned getReg() const
getReg - Returns the register number.
static void getUnderlyingObjects(MachineInstr *MI, SmallVectorImpl< Value *> &Objs, const DataLayout &DL)
Return the underlying objects for the memory references of an instruction.
bool hasDelaySlot(QueryType Type=AnyInBundle) const
Returns true if the specified instruction has a delay slot which must be filled by the code generator...
const MipsInstrInfo * getInstrInfo() const override
bool test(unsigned Idx) const
Optimal is the default and will produce compact branches when delay slots cannot be filled...
FunctionPass * createMipsDelaySlotFillerPass()
createMipsDelaySlotFillerPass - Returns a pass that fills in delay slots in Mips MachineFunctions ...
static bool hasUnoccupiedSlot(const MachineInstr *MI)
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
block Block Frequency true
static cl::opt< bool > DisableDelaySlotFiller("disable-mips-delay-filler", cl::init(false), cl::desc("Fill all delay slots with NOPs."), cl::Hidden)
SI optimize exec mask operations pre RA
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
bool inMicroMipsMode() const
bool isBundledWithSucc() const
Return true if this instruction is part of a bundle, and it is not the last instruction in the bundle...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
bool baseRegNeedsLoadStoreMask(unsigned Reg)
bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB)
This function adds registers Filler defines to MBB's live-in register list.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
static cl::opt< bool > DisableBackwardSearch("disable-mips-df-backward-search", cl::init(false), cl::desc("Disallow MIPS delay filler to search backward."), cl::Hidden)
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
static cl::opt< bool > DisableForwardSearch("disable-mips-df-forward-search", cl::init(true), cl::desc("Disallow MIPS delay filler to search forward."), cl::Hidden)
virtual const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const =0
Return a null-terminated list of all of the callee-saved registers on this target.
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
bool isTargetNaCl() const
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
unsigned getNumRegs() const
Return the number of registers this target has (useful for sizing arrays holding per register informa...
INITIALIZE_PASS(MipsDelaySlotFiller, DEBUG_TYPE, "Fill delay slot for MIPS", false, false) static void insertDelayFiller(Iter Filler
This function inserts clones of Filler into predecessor blocks.
initializer< Ty > init(const Ty &Val)
MachineInstrBundleIterator< MachineInstr > iterator
void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
'always' may in some circumstances may not be absolutely adhered to there may not be a corresponding ...
unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const
Determine the opcode of a non-delay slot form for a branch if one exists.
MCRegAliasIterator enumerates all registers aliasing Reg.
Represent the analysis usage information of a pass.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
FunctionPass class - This class is used to implement most global optimizations.
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
std::vector< MachineBasicBlock * >::const_iterator const_succ_iterator
std::vector< MachineBasicBlock * >::iterator pred_iterator
succ_iterator succ_begin()
static cl::opt< bool > DisableSuccBBSearch("disable-mips-df-succbb-search", cl::init(true), cl::desc("Disallow MIPS delay filler to search successor basic blocks."), cl::Hidden)
bool isImplicitDef() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
pred_iterator pred_begin()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const MipsRegisterInfo * getRegisterInfo() const override
MachineInstr * CloneMachineInstr(const MachineInstr *Orig)
Create a new MachineInstr which is a copy of Orig, identical in all ways except the instruction has n...
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
Special value supplied for machine level alias analysis.
static int getEquivalentCallShort(int Opcode)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
const MachineBasicBlock * getParent() const
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
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 '...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isEHPad() const
Returns true if the block is a landing pad.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
The policy 'never' may in some circumstances or for some ISAs not be absolutely adhered to...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void GetUnderlyingObjects(Value *V, SmallVectorImpl< Value *> &Objects, const DataLayout &DL, LoopInfo *LI=nullptr, unsigned MaxLookup=6)
This method is similar to GetUnderlyingObject except that it can look through phi and select instruct...
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
iterator_range< const_set_bits_iterator > set_bits() const
LLVM Value Representation.
Primary interface to the complete machine description for the target machine.
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
StringRef - Represent a constant reference to a string, i.e.
void initializeMipsDelaySlotFillerPass(PassRegistry &)
const MachineOperand & getOperand(unsigned i) const
Properties which a MachineFunction may have at a given point in time.
Helper class for constructing bundles of MachineInstrs.
A discriminated union of two pointer types, with the discriminator in the low bit of the pointer...