35 #define DEBUG_TYPE "delay-slot-filler"
37 STATISTIC(FilledSlots,
"Number of delay slots filled");
38 STATISTIC(UsefulSlots,
"Number of delay slots filled with instructions that"
42 "disable-mips-delay-filler",
44 cl::desc(
"Fill all delay slots with NOPs."),
48 "disable-mips-df-forward-search",
50 cl::desc(
"Disallow MIPS delay filler to search forward."),
54 "disable-mips-df-succbb-search",
56 cl::desc(
"Disallow MIPS delay filler to search successor basic blocks."),
60 "disable-mips-df-backward-search",
62 cl::desc(
"Disallow MIPS delay filler to search backward."),
78 cl::desc(
"MIPS Specific: Compact branch policy."),
114 bool isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const;
121 class InspectMemInstr {
123 InspectMemInstr(
bool ForbidMemInstr_)
125 SeenStore(
false), ForbidMemInstr(ForbidMemInstr_) {}
130 virtual ~InspectMemInstr() {}
134 bool OrigSeenLoad, OrigSeenStore, SeenLoad, SeenStore;
145 class NoMemInstr :
public InspectMemInstr {
147 NoMemInstr() : InspectMemInstr(
true) {}
153 class LoadFromStackOrConst :
public InspectMemInstr {
155 LoadFromStackOrConst() : InspectMemInstr(
false) {}
162 class MemDefsUses :
public InspectMemInstr {
186 bool SeenNoObjLoad, SeenNoObjStore;
194 StringRef getPassName()
const override {
return "Mips Delay Slot Filler"; }
197 bool Changed =
false;
200 Changed |= runOnMachineBasicBlock(*FI);
230 bool delayHasHazard(
const MachineInstr &Candidate, RegDefsUses &RegDU,
231 InspectMemInstr &IM)
const;
235 template<
typename IterTy>
237 RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot,
238 IterTy &Filler)
const;
259 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
265 RegDefsUses &RegDU,
bool &HasMultipleSuccs,
266 BB2BrMap &BrMap)
const;
268 bool terminateSearch(
const MachineInstr &Candidate)
const;
285 for (BB2BrMap::const_iterator
I = BrMap.begin();
I != BrMap.end(); ++
I) {
297 for (
unsigned I = 0,
E = Filler->getNumOperands();
I !=
E; ++
I) {
307 "Shouldn't move an instruction with unallocatable registers across "
308 "basic block boundaries.");
317 : TRI(TRI), Defs(TRI.getNumRegs(),
false), Uses(TRI.getNumRegs(),
false) {}
332 Defs.reset(Mips::AT);
336 void RegDefsUses::setCallerSaved(
const MachineInstr &MI) {
344 Defs.set(Mips::RA_64);
348 BitVector CallerSavedRegs(TRI.getNumRegs(),
true);
350 CallerSavedRegs.
reset(Mips::ZERO);
351 CallerSavedRegs.
reset(Mips::ZERO_64);
356 CallerSavedRegs.
reset(*AI);
358 Defs |= CallerSavedRegs;
362 BitVector AllocSet = TRI.getAllocatableSet(MF);
368 AllocSet.
set(Mips::ZERO);
369 AllocSet.
set(Mips::ZERO_64);
371 Defs |= AllocSet.
flip();
379 for (
const auto &LI : (*SI)->liveins())
380 Uses.
set(LI.PhysReg);
383 bool RegDefsUses::update(
const MachineInstr &MI,
unsigned Begin,
unsigned End) {
384 BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs());
385 bool HasHazard =
false;
387 for (
unsigned I = Begin;
I !=
End; ++
I) {
391 HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.
getReg(), MO.
isDef());
401 unsigned Reg,
bool IsDef)
const {
405 return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg));
410 return isRegInSet(Defs, Reg);
413 bool RegDefsUses::isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const {
416 if (RegSet.
test(*AI))
421 bool InspectMemInstr::hasHazard(
const MachineInstr &MI) {
428 OrigSeenLoad = SeenLoad;
429 OrigSeenStore = SeenStore;
436 ForbidMemInstr =
true;
440 return hasHazard_(MI);
443 bool LoadFromStackOrConst::hasHazard_(
const MachineInstr &MI) {
452 if (isa<FixedStackPseudoSourceValue>(PSV))
454 return !PSV->isConstant(
nullptr) && !PSV->isStack();
461 : InspectMemInstr(
false), MFI(MFI_), DL(DL), SeenNoObjLoad(
false),
462 SeenNoObjStore(
false) {}
465 bool HasHazard =
false;
471 I != Objs.
end(); ++
I)
472 HasHazard |= updateDefsUses(*
I, MI.
mayStore());
478 HasHazard = MI.
mayStore() && (OrigSeenLoad || OrigSeenStore);
479 HasHazard |= MI.
mayLoad() || OrigSeenStore;
489 return !Defs.insert(V).second || Uses.count(V) || SeenNoObjStore ||
493 return Defs.count(V) || SeenNoObjStore;
506 if (!PSV->isAliased(MFI))
535 Branch = TII->genInstrWithNewOpc(NewOpcode, Branch);
537 std::next(Branch)->eraseFromParent();
549 return Mips::BGEZALS_MM;
551 return Mips::BLTZALS_MM;
553 return Mips::JALS_MM;
555 return Mips::JALRS_MM;
556 case Mips::JALR16_MM:
557 return Mips::JALRS16_MM;
558 case Mips::TAILCALL_MM:
560 case Mips::TAILCALLREG:
561 return Mips::JR16_MM;
570 bool Changed =
false;
594 if (searchBackward(MBB, *
I)) {
596 }
else if (
I->isTerminator()) {
597 if (searchSuccBBs(MBB,
I)) {
600 }
else if (searchForward(MBB,
I)) {
634 if ((InMicroMipsMode ||
637 I = replaceWithCompactBranch(MBB,
I,
I->getDebugLoc());
642 BuildMI(MBB, std::next(
I),
I->getDebugLoc(), TII->get(Mips::NOP));
652 return new Filler(tm);
655 template<
typename IterTy>
657 RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot,
658 IterTy &Filler)
const {
659 for (IterTy
I = Begin;
I !=
End;) {
664 if (CurrI->isDebugValue())
667 if (terminateSearch(*CurrI))
670 assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) &&
671 "Cannot put calls, returns or branches in delay slot.");
673 if (CurrI->isKill()) {
674 CurrI->eraseFromParent();
678 if (delayHasHazard(*CurrI, RegDU, IM))
696 unsigned Opcode = (*Slot).getOpcode();
703 (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
704 Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL))
719 RegDefsUses RegDU(*Fn->getSubtarget().getRegisterInfo());
720 MemDefsUses MemDU(Fn->getDataLayout(), &Fn->getFrameInfo());
726 if (!searchRange(MBB, ++SlotI.
getReverse(), MBB.
rend(), RegDU, MemDU, Slot,
730 MBB.
splice(std::next(SlotI), &MBB, Filler.getReverse());
745 RegDU.setCallerSaved(*Slot);
747 if (!searchRange(MBB, std::next(Slot), MBB.
end(), RegDU, NM, Slot, Filler))
750 MBB.
splice(std::next(Slot), &MBB, Filler);
766 bool HasMultipleSuccs =
false;
768 std::unique_ptr<InspectMemInstr> IM;
774 PE = SuccBB->
pred_end(); PI != PE; ++PI)
775 if (!examinePred(**PI, *SuccBB, RegDU, HasMultipleSuccs, BrMap))
780 RegDU.setUnallocatableRegs(*Fn);
784 if (HasMultipleSuccs) {
785 IM.reset(
new LoadFromStackOrConst());
788 IM.reset(
new MemDefsUses(Fn->getDataLayout(), &MFI));
791 if (!searchRange(MBB, SuccBB->
begin(), SuccBB->
end(), RegDU, *IM, Slot,
797 Filler->eraseFromParent();
807 auto &Prob = getAnalysis<MachineBranchProbabilityInfo>();
811 return Prob.getEdgeProbability(&B, Dst0) <
812 Prob.getEdgeProbability(&B, Dst1);
814 return S->
isEHPad() ?
nullptr : S;
817 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
826 TII->
analyzeBranch(MBB, TrueBB, FalseBB, Cond,
false, BranchInstrs);
828 if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch))
829 return std::make_pair(R,
nullptr);
831 if (R != MipsInstrInfo::BT_CondUncond) {
833 return std::make_pair(MipsInstrInfo::BT_None,
nullptr);
835 assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst)));
837 return std::make_pair(R, BranchInstrs[0]);
840 assert((TrueBB == &Dst) || (FalseBB == &Dst));
844 return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]);
848 return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]);
850 return std::make_pair(MipsInstrInfo::BT_None,
nullptr);
854 RegDefsUses &RegDU,
bool &HasMultipleSuccs,
855 BB2BrMap &BrMap)
const {
856 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
P =
857 getBranch(Pred, Succ);
861 if (P.first == MipsInstrInfo::BT_None)
864 if ((P.first != MipsInstrInfo::BT_Uncond) &&
865 (P.first != MipsInstrInfo::BT_NoBranch)) {
866 HasMultipleSuccs =
true;
867 RegDU.addLiveOut(Pred, Succ);
870 BrMap[&Pred] = P.second;
874 bool Filler::delayHasHazard(
const MachineInstr &Candidate, RegDefsUses &RegDU,
875 InspectMemInstr &IM)
const {
877 "KILL instructions should have been eliminated at this point.");
881 HasHazard |= IM.hasHazard(Candidate);
882 HasHazard |= RegDU.update(Candidate, 0, Candidate.
getNumOperands());
887 bool Filler::terminateSearch(
const MachineInstr &Candidate)
const {
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
Return the number of bytes of code the specified instruction may be.
void push_back(const T &Elt)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
bool isEHPad() const
Returns true if the block is a landing pad.
A parsed version of the target data layout string in and methods for querying it. ...
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
STATISTIC(NumFunctions,"Total number of functions")
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Branch Analysis.
bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx, bool *IsStore=nullptr)
int find_next(unsigned Prev) const
find_next - Returns the index of the next set bit following the "Prev" bit.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const MipsInstrInfo * getInstrInfo() const override
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Optimal is the default and will produce compact branches when delay slots cannot be filled...
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
static bool hasUnoccupiedSlot(const MachineInstr *MI)
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...
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
static cl::opt< bool > DisableDelaySlotFiller("disable-mips-delay-filler", cl::init(false), cl::desc("Fill all delay slots with NOPs."), cl::Hidden)
AnalysisUsage & addRequired()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
Reg
All possible values of the reg field in the ModR/M byte.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
bool baseRegNeedsLoadStoreMask(unsigned Reg)
unsigned getNumOperands() const
Access to explicit operands of the instruction.
bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool isBundledWithSucc() const
Return true if this instruction is part of a bundle, and it is not the last instruction in the bundle...
static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB)
This function adds registers Filler defines to MBB's live-in register list.
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.")))
bool hasDelaySlot(QueryType Type=AnyInBundle) const
Returns true if the specified instruction has a delay slot which must be filled by the code generator...
static cl::opt< bool > DisableBackwardSearch("disable-mips-df-backward-search", cl::init(false), cl::desc("Disallow MIPS delay filler to search backward."), cl::Hidden)
Function Alias Analysis false
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
std::vector< MachineBasicBlock * >::iterator pred_iterator
static cl::opt< bool > DisableForwardSearch("disable-mips-df-forward-search", cl::init(true), cl::desc("Disallow MIPS delay filler to search forward."), cl::Hidden)
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...
static void getUnderlyingObjects(MachineInstr *MI, SmallVectorImpl< Value * > &Objs, const DataLayout &DL)
Return the underlying objects for the memory references of an instruction.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const MachineBasicBlock * getParent() const
bool isImplicitDef() const
ValuesClass values(OptsTy...Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
const MachineOperand & getOperand(unsigned i) const
'always' may in some circumstances may not be absolutely adhered to there may not be a corresponding ...
MCRegAliasIterator enumerates all registers aliasing Reg.
Represent the analysis usage information of a pass.
static const unsigned End
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
FunctionPass class - This class is used to implement most global optimizations.
bool inMicroMipsMode() const
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)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
pred_iterator pred_begin()
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const
Determine the opcode of a non-delay slot form for a branch if one exists.
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
Iterator for intrusive lists based on ilist_node.
bool isTargetNaCl() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
const MipsRegisterInfo * getRegisterInfo() const override
MachineInstr * CloneMachineInstr(const MachineInstr *Orig)
CloneMachineInstr - Create a new MachineInstr which is a copy of the 'Orig' instruction, identical in all ways except the instruction has no parent, prev, or next.
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 test(unsigned Idx) const
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
FunctionPass * createMipsDelaySlotFillerPass(MipsTargetMachine &TM)
createMipsDelaySlotFillerPass - Returns a pass that fills in delay slots in Mips MachineFunctions ...
Special value supplied for machine level alias analysis.
static int getEquivalentCallShort(int Opcode)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
static void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap)
This function inserts clones of Filler into predecessor blocks.
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 isCall(QueryType Type=AnyInBundle) const
The policy 'never' may in some circumstances or for some ISAs not be absolutely adhered to...
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
unsigned getReg() const
getReg - Returns the register number.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< MachineBasicBlock * >::const_iterator const_succ_iterator
LLVM Value Representation.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Primary interface to the complete machine description for the target machine.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
StringRef - Represent a constant reference to a string, i.e.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
Properties which a MachineFunction may have at a given point in time.
Helper class for constructing bundles of MachineInstrs.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.