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."),
93 bool isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const;
100 class InspectMemInstr {
102 InspectMemInstr(
bool ForbidMemInstr_)
104 SeenStore(
false), ForbidMemInstr(ForbidMemInstr_) {}
109 virtual ~InspectMemInstr() {}
113 bool OrigSeenLoad, OrigSeenStore, SeenLoad, SeenStore;
124 class NoMemInstr :
public InspectMemInstr {
126 NoMemInstr() : InspectMemInstr(
true) {}
132 class LoadFromStackOrConst :
public InspectMemInstr {
134 LoadFromStackOrConst() : InspectMemInstr(
false) {}
141 class MemDefsUses :
public InspectMemInstr {
165 bool SeenNoObjLoad, SeenNoObjStore;
173 const char *getPassName()
const override {
174 return "Mips Delay Slot Filler";
178 bool Changed =
false;
181 Changed |= runOnMachineBasicBlock(*FI);
209 bool delayHasHazard(
const MachineInstr &Candidate, RegDefsUses &RegDU,
210 InspectMemInstr &IM)
const;
214 template<
typename IterTy>
216 RegDefsUses &RegDU, InspectMemInstr &IM, Iter
Slot,
217 IterTy &Filler)
const;
238 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
244 RegDefsUses &RegDU,
bool &HasMultipleSuccs,
245 BB2BrMap &BrMap)
const;
247 bool terminateSearch(
const MachineInstr &Candidate)
const;
264 for (BB2BrMap::const_iterator
I = BrMap.begin();
I != BrMap.end(); ++
I) {
276 for (
unsigned I = 0, E = Filler->getNumOperands();
I != E; ++
I) {
286 "Shouldn't move an instruction with unallocatable registers across "
287 "basic block boundaries.");
296 : TRI(TRI), Defs(TRI.getNumRegs(),
false), Uses(TRI.getNumRegs(),
false) {}
311 Defs.reset(Mips::AT);
315 void RegDefsUses::setCallerSaved(
const MachineInstr &MI) {
323 Defs.set(Mips::RA_64);
327 BitVector CallerSavedRegs(TRI.getNumRegs(),
true);
329 CallerSavedRegs.
reset(Mips::ZERO);
330 CallerSavedRegs.
reset(Mips::ZERO_64);
335 CallerSavedRegs.
reset(*AI);
337 Defs |= CallerSavedRegs;
341 BitVector AllocSet = TRI.getAllocatableSet(MF);
347 AllocSet.
set(Mips::ZERO);
348 AllocSet.
set(Mips::ZERO_64);
350 Defs |= AllocSet.
flip();
359 LE = (*SI)->livein_end(); LI !=
LE; ++LI)
363 bool RegDefsUses::update(
const MachineInstr &MI,
unsigned Begin,
unsigned End) {
364 BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs());
365 bool HasHazard =
false;
367 for (
unsigned I = Begin;
I != End; ++
I) {
371 HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.
getReg(), MO.
isDef());
381 unsigned Reg,
bool IsDef)
const {
385 return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg));
390 return isRegInSet(Defs, Reg);
393 bool RegDefsUses::isRegInSet(
const BitVector &RegSet,
unsigned Reg)
const {
396 if (RegSet.
test(*AI))
401 bool InspectMemInstr::hasHazard(
const MachineInstr &MI) {
408 OrigSeenLoad = SeenLoad;
409 OrigSeenStore = SeenStore;
416 ForbidMemInstr =
true;
420 return hasHazard_(MI);
423 bool LoadFromStackOrConst::hasHazard_(
const MachineInstr &MI) {
432 if (isa<FixedStackPseudoSourceValue>(PSV))
434 return !PSV->isConstant(
nullptr) && PSV != PseudoSourceValue::getStack();
441 : InspectMemInstr(
false), MFI(MFI_), DL(DL), SeenNoObjLoad(
false),
442 SeenNoObjStore(
false) {}
445 bool HasHazard =
false;
451 I != Objs.
end(); ++
I)
452 HasHazard |= updateDefsUses(*
I, MI.
mayStore());
458 HasHazard = MI.
mayStore() && (OrigSeenLoad || OrigSeenStore);
459 HasHazard |= MI.
mayLoad() || OrigSeenStore;
469 return !Defs.insert(V).second || Uses.count(V) || SeenNoObjStore ||
473 return Defs.count(V) || SeenNoObjStore;
486 if (!PSV->isAliased(MFI))
515 (((
unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM
521 MIB.
addReg(Branch->getOperand(0).getReg());
522 MIB.
addMBB(Branch->getOperand(2).getMBB());
525 Branch = std::prev(Branch);
537 const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM);
540 MIB.
addReg(Jump->getOperand(0).getReg());
543 Jump = std::prev(Jump);
554 return Mips::BGEZALS_MM;
556 return Mips::BLTZALS_MM;
558 return Mips::JALS_MM;
560 return Mips::JALRS_MM;
561 case Mips::JALR16_MM:
562 return Mips::JALRS16_MM;
571 bool Changed =
false;
587 if (searchBackward(MBB,
I)) {
589 }
else if (
I->isTerminator()) {
590 if (searchSuccBBs(MBB,
I)) {
593 }
else if (searchForward(MBB,
I)) {
615 unsigned Opcode =
I->getOpcode();
616 if (InMicroMipsMode) {
620 if (((
unsigned)
I->getOperand(1).getReg()) == Mips::ZERO) {
621 I = replaceWithCompactBranch(MBB,
I,
I->getDebugLoc());
626 case Mips::PseudoReturn:
627 case Mips::PseudoIndirectBranch:
630 I = replaceWithCompactJump(MBB,
I,
I->getDebugLoc());
637 BuildMI(MBB, std::next(
I),
I->getDebugLoc(), TII->get(Mips::NOP));
647 return new Filler(tm);
650 template<
typename IterTy>
652 RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot,
653 IterTy &Filler)
const {
654 bool IsReverseIter = std::is_convertible<IterTy, ReverseIter>::value;
656 for (IterTy
I = Begin;
I != End;) {
661 if (CurrI->isDebugValue())
664 if (terminateSearch(*CurrI))
667 assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) &&
668 "Cannot put calls, returns or branches in delay slot.");
670 if (CurrI->isKill()) {
671 CurrI->eraseFromParent();
676 if (IsReverseIter &&
I != End)
681 if (delayHasHazard(*CurrI, RegDU, IM))
699 unsigned Opcode = (*Slot).getOpcode();
701 (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
702 Opcode == Mips::PseudoReturn))
722 if (!searchRange(MBB, ReverseIter(Slot), MBB.
rend(), RegDU, MemDU, Slot,
726 MBB.
splice(std::next(Slot), &MBB, std::next(Filler).base());
741 RegDU.setCallerSaved(*Slot);
743 if (!searchRange(MBB, std::next(Slot), MBB.
end(), RegDU, NM, Slot, Filler))
746 MBB.
splice(std::next(Slot), &MBB, Filler);
762 bool HasMultipleSuccs =
false;
764 std::unique_ptr<InspectMemInstr> IM;
769 PE = SuccBB->
pred_end(); PI != PE; ++PI)
770 if (!examinePred(**PI, *SuccBB, RegDU, HasMultipleSuccs, BrMap))
775 RegDU.setUnallocatableRegs(*MBB.
getParent());
779 if (HasMultipleSuccs) {
780 IM.reset(
new LoadFromStackOrConst());
783 IM.reset(
new MemDefsUses(*
TM.getDataLayout(), MFI));
786 if (!searchRange(MBB, SuccBB->
begin(), SuccBB->
end(), RegDU, *IM, Slot,
792 Filler->eraseFromParent();
802 auto &Prob = getAnalysis<MachineBranchProbabilityInfo>();
806 return Prob.getEdgeWeight(&B, Dst0) < Prob.getEdgeWeight(&B, Dst1);
811 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
820 TII->
AnalyzeBranch(MBB, TrueBB, FalseBB, Cond,
false, BranchInstrs);
822 if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch))
823 return std::make_pair(R,
nullptr);
825 if (R != MipsInstrInfo::BT_CondUncond) {
827 return std::make_pair(MipsInstrInfo::BT_None,
nullptr);
829 assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst)));
831 return std::make_pair(R, BranchInstrs[0]);
834 assert((TrueBB == &Dst) || (FalseBB == &Dst));
838 return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]);
842 return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]);
844 return std::make_pair(MipsInstrInfo::BT_None,
nullptr);
848 RegDefsUses &RegDU,
bool &HasMultipleSuccs,
849 BB2BrMap &BrMap)
const {
850 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
P =
851 getBranch(Pred, Succ);
855 if (P.first == MipsInstrInfo::BT_None)
858 if ((P.first != MipsInstrInfo::BT_Uncond) &&
859 (P.first != MipsInstrInfo::BT_NoBranch)) {
860 HasMultipleSuccs =
true;
861 RegDU.addLiveOut(Pred, Succ);
864 BrMap[&Pred] = P.second;
868 bool Filler::delayHasHazard(
const MachineInstr &Candidate, RegDefsUses &RegDU,
869 InspectMemInstr &IM)
const {
870 assert(!Candidate.
isKill() &&
871 "KILL instructions should have been eliminated at this point.");
875 HasHazard |= IM.hasHazard(Candidate);
876 HasHazard |= RegDU.update(Candidate, 0, Candidate.
getNumOperands());
881 bool Filler::terminateSearch(
const MachineInstr &Candidate)
const {
void push_back(const T &Elt)
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
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.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
STATISTIC(NumFunctions,"Total number of functions")
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.
std::vector< unsigned >::const_iterator livein_iterator
Describe properties that are true of each instruction in the target description file.
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...
void addLiveIn(unsigned Reg)
Adds the specified register as a live in.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
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...
Instructions::iterator instr_iterator
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()
bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Branch Analysis.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
static void getUnderlyingObjects(const Value *V, SmallVectorImpl< Value * > &Objects, const DataLayout &DL)
getUnderlyingObjects - This is a wrapper around GetUnderlyingObjects and adds support for basic ptrto...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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)
isIdentifiedObject - 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.
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)
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
getAllocatableSet - Returns a bitset indexed by register number indicating if a register is allocatab...
const MachineBasicBlock * getParent() const
bool isImplicitDef() const
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineOperand & getOperand(unsigned i) const
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.
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
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
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()
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
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
MachineFrameInfo * getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
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 ...
PseudoSourceValue - Special value supplied for machine level alias analysis.
static int getEquivalentCallShort(int Opcode)
Representation of each machine instruction.
bool isLandingPad() const
isLandingPad - Returns true if the block is a landing pad.
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 '...
bool isLiveIn(unsigned Reg) const
isLiveIn - Return true if the specified register is in the live in set.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isCall(QueryType Type=AnyInBundle) const
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.
std::vector< MachineBasicBlock * >::const_iterator const_succ_iterator
std::reverse_iterator< iterator > reverse_iterator
LLVM Value Representation.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
BasicBlockListType::iterator iterator
Primary interface to the complete machine description for the target machine.
unsigned GetInstSizeInBytes(const MachineInstr *MI) const
Return the number of bytes of code the specified instruction may be.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
addReg - Add a new virtual register operand...
Helper class for constructing bundles of MachineInstrs.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.