42 #define DEBUG_TYPE "early-ifcvt" 48 cl::desc(
"Maximum number of instructions per speculated block."));
54 STATISTIC(NumDiamondsSeen,
"Number of diamonds");
55 STATISTIC(NumDiamondsConv,
"Number of diamonds converted");
56 STATISTIC(NumTrianglesSeen,
"Number of triangles");
57 STATISTIC(NumTrianglesConv,
"Number of triangles converted");
101 bool isTriangle()
const {
return TBB == Tail || FBB == Tail; }
114 int CondCycles, TCycles, FCycles;
117 : PHI(phi), TReg(0), FReg(0), CondCycles(0), TCycles(0), FCycles(0) {}
145 bool findInsertionPoint();
148 void replacePHIInstrs();
151 void rewritePHIOperands();
159 LiveRegUnits.
clear();
161 ClobberedRegUnits.
clear();
198 if (
I->isDebugInstr())
222 bool DontMoveAcrossStore =
true;
223 if (!
I->isSafeToMove(
nullptr, DontMoveAcrossStore)) {
230 if (MO.isRegMask()) {
236 unsigned Reg = MO.getReg();
241 ClobberedRegUnits.
set(*Units);
246 if (!DefMI || DefMI->
getParent() != Head)
248 if (InsertAfter.
insert(DefMI).second)
252 LLVM_DEBUG(
dbgs() <<
"Can't insert instructions below terminator.\n");
271 bool SSAIfConv::findInsertionPoint() {
274 LiveRegUnits.
clear();
282 if (InsertAfter.
count(&*I)) {
292 unsigned Reg = MO.getReg();
298 LiveRegUnits.
erase(*Units);
304 while (!Reads.
empty())
307 if (ClobberedRegUnits.
test(*Units))
308 LiveRegUnits.
insert(*Units);
311 if (I != FirstTerm && I->isTerminator())
316 if (!LiveRegUnits.
empty()) {
318 dbgs() <<
"Would clobber";
320 i = LiveRegUnits.
begin(), e = LiveRegUnits.
end(); i != e; ++i)
322 dbgs() <<
" live before " << *
I;
343 TBB = FBB = Tail =
nullptr;
397 LLVM_DEBUG(
dbgs() <<
"AnalyzeBranch didn't find conditional branch.\n");
404 LLVM_DEBUG(
dbgs() <<
"AnalyzeBranch found an unconditional branch.\n");
410 FBB = TBB == Succ0 ? Succ1 : Succ0;
417 I !=
E && I->isPHI(); ++
I) {
419 PHIInfo &PI = PHIs.
back();
421 for (
unsigned i = 1; i != PI.PHI->getNumOperands(); i += 2) {
422 if (PI.PHI->getOperand(i+1).getMBB() == TPred)
423 PI.TReg = PI.PHI->getOperand(i).getReg();
424 if (PI.PHI->getOperand(i+1).getMBB() == FPred)
425 PI.FReg = PI.PHI->getOperand(i).getReg();
432 PI.CondCycles, PI.TCycles, PI.FCycles)) {
440 ClobberedRegUnits.
reset();
441 if (TBB != Tail && !canSpeculateInstrs(TBB))
443 if (FBB != Tail && !canSpeculateInstrs(FBB))
448 if (!findInsertionPoint())
461 void SSAIfConv::replacePHIInstrs() {
464 assert(FirstTerm != Head->
end() &&
"No terminators");
465 DebugLoc HeadDL = FirstTerm->getDebugLoc();
468 for (
unsigned i = 0, e = PHIs.
size(); i != e; ++i) {
469 PHIInfo &PI = PHIs[i];
471 unsigned DstReg = PI.PHI->getOperand(0).getReg();
472 TII->
insertSelect(*Head, FirstTerm, HeadDL, DstReg, Cond, PI.TReg, PI.FReg);
474 PI.PHI->eraseFromParent();
482 void SSAIfConv::rewritePHIOperands() {
484 assert(FirstTerm != Head->
end() &&
"No terminators");
485 DebugLoc HeadDL = FirstTerm->getDebugLoc();
488 for (
unsigned i = 0, e = PHIs.
size(); i != e; ++i) {
489 PHIInfo &PI = PHIs[i];
493 if (PI.TReg == PI.FReg) {
498 unsigned PHIDst = PI.PHI->getOperand(0).getReg();
501 DstReg, Cond, PI.TReg, PI.FReg);
506 for (
unsigned i = PI.PHI->getNumOperands(); i != 1; i -= 2) {
508 if (MBB == getTPred()) {
509 PI.PHI->getOperand(i-1).setMBB(Head);
510 PI.PHI->getOperand(i-2).setReg(DstReg);
511 }
else if (MBB == getFPred()) {
512 PI.PHI->RemoveOperand(i-1);
513 PI.PHI->RemoveOperand(i-2);
526 assert(Head && Tail && TBB && FBB &&
"Call canConvertIf first.");
541 bool ExtraPreds = Tail->
pred_size() != 2;
543 rewritePHIOperands();
585 TII->
insertBranch(*Head, Tail,
nullptr, EmptyCond, HeadDL);
613 StringRef getPassName()
const override {
return "Early If-Conversion"; }
619 void invalidateTraces();
620 bool shouldConvertIf();
628 "Early If Converter",
false,
false)
635 void EarlyIfConverter::getAnalysisUsage(
AnalysisUsage &AU)
const {
652 for (
unsigned i = 0, e = Removed.
size(); i != e; ++i) {
654 assert(Node != HeadNode &&
"Cannot erase the head node");
657 DomTree->changeImmediateDominator(Node->
getChildren().back(), HeadNode);
659 DomTree->eraseNode(Removed[i]);
669 for (
unsigned i = 0, e = Removed.
size(); i != e; ++i)
670 Loops->removeBlock(Removed[i]);
674 void EarlyIfConverter::invalidateTraces() {
675 Traces->verifyAnalysis();
676 Traces->invalidate(IfConv.Head);
677 Traces->invalidate(IfConv.Tail);
678 Traces->invalidate(IfConv.TBB);
679 Traces->invalidate(IfConv.FBB);
680 Traces->verifyAnalysis();
685 if (Delta < 0 && Cyc + Delta > Cyc)
693 bool EarlyIfConverter::shouldConvertIf() {
708 unsigned CritLimit = SchedModel.MispredictPenalty/2;
714 if (IfConv.TBB != IfConv.Tail)
718 <<
", minimal critical path " << MinCrit <<
'\n');
719 if (ResLength > MinCrit + CritLimit) {
728 unsigned BranchDepth =
735 for (
unsigned i = 0, e = IfConv.PHIs.size(); i != e; ++i) {
736 SSAIfConv::PHIInfo &PI = IfConv.PHIs[i];
742 unsigned CondDepth =
adjCycles(BranchDepth, PI.CondCycles);
743 if (CondDepth > MaxDepth) {
744 unsigned Extra = CondDepth -
MaxDepth;
746 if (Extra > CritLimit) {
754 if (TDepth > MaxDepth) {
757 if (Extra > CritLimit) {
765 if (FDepth > MaxDepth) {
768 if (Extra > CritLimit) {
780 bool Changed =
false;
781 while (IfConv.canConvertIf(MBB) && shouldConvertIf()) {
785 IfConv.convertIf(RemovedBlocks);
787 updateDomTree(RemovedBlocks);
788 updateLoops(RemovedBlocks);
794 LLVM_DEBUG(
dbgs() <<
"********** EARLY IF-CONVERSION **********\n" 795 <<
"********** Function: " << MF.
getName() <<
'\n');
808 DomTree = &getAnalysis<MachineDominatorTree>();
809 Loops = getAnalysisIfAvailable<MachineLoopInfo>();
810 Traces = &getAnalysis<MachineTraceMetrics>();
813 bool Changed =
false;
814 IfConv.runOnMachineFunction(MF);
821 if (tryConvertIf(DomNode->getBlock()))
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
static cl::opt< bool > Stress("stress-early-ifcvt", cl::Hidden, cl::desc("Turn all knobs to 11"))
virtual bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, unsigned TrueReg, unsigned FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const
Return true if it is possible to insert a select instruction that chooses between TrueReg and FalseRe...
virtual void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DstReg, ArrayRef< MachineOperand > Cond, unsigned TrueReg, unsigned FalseReg) const
Insert a select instruction into MBB before I that will copy TrueReg to DstReg when Cond is true...
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
This class represents lattice values for constants.
std::pair< iterator, bool > insert(const ValueT &Val)
insert - Attempts to insert a new element.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
unsigned Depth
Earliest issue cycle as determined by data dependencies and instruction latencies from the beginning ...
void push_back(const T &Elt)
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool test(unsigned Idx) const
virtual unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const
Insert branch code into the end of the specified MachineBasicBlock.
char & EarlyIfConverterID
EarlyIfConverter - This pass performs if-conversion on SSA form by inserting cmov instructions...
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
A trace ensemble is a collection of traces selected using the same strategy, for example 'minimum res...
static unsigned InstrCount
virtual unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const
Remove the branching code at the end of the specific MBB.
unsigned getNumRegUnits() const
Return the number of (native) register units in the target.
virtual bool enableEarlyIfConversion() const
Enable the use of the early if conversion pass.
#define INITIALIZE_PASS_DEPENDENCY(depName)
void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
void clear()
clear - Removes all bits from the bitvector. Does not change capacity.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
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.
Printable printRegUnit(unsigned Unit, const TargetRegisterInfo *TRI)
Create Printable object to print register units on a raw_ostream.
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Select the trace through a block that has the fewest instructions.
INITIALIZE_PASS_BEGIN(EarlyIfConverter, DEBUG_TYPE, "Early If Converter", false, false) INITIALIZE_PASS_END(EarlyIfConverter
Base class for the actual dominator tree node.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
const std::vector< DomTreeNodeBase * > & getChildren() const
virtual const TargetInstrInfo * getInstrInfo() const
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
iterator erase(iterator I)
erase - Erases an existing element identified by a valid iterator.
TargetInstrInfo - Interface to description of machine instruction set.
bool empty() const
empty - Returns true if the set is empty.
initializer< Ty > init(const Ty &Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
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.
size_t size() const
size - Get the array size.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
unsigned getCriticalPath() const
Return the length of the (data dependency) critical path through the trace.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
InstrCycles getInstrCycles(const MachineInstr &MI) const
Return the depth and height of MI.
Represent the analysis usage information of a pass.
iterator_range< po_iterator< T > > post_order(const T &G)
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
bool livein_empty() const
void setUniverse(unsigned U)
setUniverse - Set the universe size which determines the largest key the set can hold.
succ_iterator succ_begin()
virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A trace represents a plausible sequence of executed basic blocks that passes through the current basi...
const_iterator end() const
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
static unsigned adjCycles(unsigned Cyc, int Delta)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
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...
size_t getNumChildren() const
MachineInstrBuilder MachineInstrBuilder & DefMI
const_iterator begin() const
LLVM_NODISCARD T pop_back_val()
unsigned pred_size() const
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static cl::opt< unsigned > BlockInstrLimit("early-ifcvt-limit", cl::init(30), cl::Hidden, cl::desc("Maximum number of instructions per speculated block."))
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
unsigned succ_size() const
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
TargetSubtargetInfo - Generic base class for all target subtargets.
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
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.
LLVM_NODISCARD bool empty() const
A set of register units used to track register liveness.
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
void clear()
clear - Clears the set.
unsigned getPHIDepth(const MachineInstr &PHI) const
Return the Depth of a PHI instruction in a trace center block successor.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getResourceLength(ArrayRef< const MachineBasicBlock *> Extrablocks=None, ArrayRef< const MCSchedClassDesc *> ExtraInstrs=None, ArrayRef< const MCSchedClassDesc *> RemoveInstrs=None) const
Return the resource length of the trace.
StringRef - Represent a constant reference to a string, i.e.
unsigned getInstrSlack(const MachineInstr &MI) const
Return the slack of MI.
Machine model for scheduling, bundling, and heuristics.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...