62 #define DEBUG_TYPE "hexagon-eif"
107 cl::desc(
"Size limit in Hexagon early if-conversion"));
115 return OS <<
"<none>";
116 return OS <<
'#' << P.MB->getNumber();
120 FlowPattern() =
default;
123 : SplitB(B), TrueB(TB), FalseB(FB), JoinB(JB), PredR(PR) {}
136 const FlowPattern &FP;
143 OS <<
"{ SplitB:" << PrintMB(P.FP.SplitB)
144 <<
", PredR:" <<
PrintReg(P.FP.PredR, &P.TRI)
145 <<
", TrueB:" << PrintMB(P.FP.TrueB) <<
", FalseB:"
146 << PrintMB(P.FP.FalseB)
147 <<
", JoinB:" << PrintMB(P.FP.JoinB) <<
" }";
156 HII(nullptr), TRI(nullptr), MFN(nullptr),
MRI(nullptr), MDT(nullptr),
162 return "Hexagon early if conversion";
188 bool isValid(
const FlowPattern &FP)
const;
191 bool isProfitable(
const FlowPattern &FP)
const;
195 unsigned getCondStoreOpcode(
unsigned Opc,
bool IfTrue)
const;
200 unsigned PredR,
bool IfTrue);
203 void convert(
const FlowPattern &FP);
209 void simplifyFlowGraph(
const FlowPattern &FP);
217 BlockSetType Deleted;
226 "Hexagon early if conversion",
false,
false)
229 if (B->succ_size() != 1)
247 unsigned Opc = T1I->getOpcode();
248 if (Opc != Hexagon::J2_jumpt && Opc != Hexagon::J2_jumpf)
250 unsigned PredR = T1I->getOperand(0).getReg();
259 assert(T2I == B->
end() || T2I->getOpcode() == Hexagon::J2_jump);
261 : T2I->getOperand(0).getMBB();
268 if (MLI->getLoopFor(T1B) != L || MLI->getLoopFor(T2B) !=
L)
273 if (Opc == Hexagon::J2_jumpt)
278 if (!MDT->properlyDominates(B, TB) || !MDT->properlyDominates(B, FB))
285 unsigned TNP = TB->
pred_size(), FNP = FB->pred_size();
286 unsigned TNS = TB->succ_size(), FNS = FB->succ_size();
292 bool TOk = (TNP == 1) && (TNS == 1);
293 bool FOk = (FNP == 1) && (FNS == 1);
323 if ((TB && isPreheader(TB)) || (FB && isPreheader(FB))) {
324 DEBUG(
dbgs() <<
"One of blocks " << PrintMB(TB) <<
", " << PrintMB(FB)
325 <<
" is a loop preheader. Skipping.\n");
329 FP = FlowPattern(B, PredR, TB, FB, JB);
330 DEBUG(
dbgs() <<
"Detected " << PrintFP(FP, *TRI) <<
"\n");
365 for (
auto &
MI : *B) {
366 if (
MI.isDebugValue())
368 if (
MI.isConditionalBranch())
370 unsigned Opc =
MI.getOpcode();
371 bool IsJMP = (Opc == Hexagon::J2_jump);
372 if (!isPredicableStore(&
MI) && !IsJMP && !isSafeToSpeculate(&
MI))
381 if (!MO.isReg() || !MO.isDef())
383 unsigned R = MO.getReg();
386 if (
MRI->getRegClass(R) != &Hexagon::PredRegsRegClass)
388 for (
auto U =
MRI->use_begin(R); U !=
MRI->use_end(); ++U)
389 if (U->getParent()->isPHI())
396 bool HexagonEarlyIfConversion::usesUndefVReg(
const MachineInstr *
MI)
const {
398 if (!MO.isReg() || !MO.isUse())
400 unsigned R = MO.getReg();
405 assert(DefI &&
"Expecting a reaching def in MRI");
413 if (hasEHLabel(FP.SplitB))
415 if (FP.TrueB && !isValidCandidate(FP.TrueB))
417 if (FP.FalseB && !isValidCandidate(FP.FalseB))
434 if (usesUndefVReg(&MI))
438 if (RC == &Hexagon::PredRegsRegClass)
452 for (I = B->
begin(); I !=
E; ++
I) {
463 if (!HII->isPredicable(*Def1) || !HII->isPredicable(*Def3))
469 unsigned HexagonEarlyIfConversion::countPredicateDefs(
471 unsigned PredDefs = 0;
472 for (
auto &MI : *B) {
474 if (!MO.isReg() || !MO.isDef())
476 unsigned R = MO.getReg();
479 if (
MRI->getRegClass(R) == &Hexagon::PredRegsRegClass)
486 bool HexagonEarlyIfConversion::isProfitable(
const FlowPattern &FP)
const {
487 if (FP.TrueB && FP.FalseB) {
492 if (MBPI->getEdgeProbability(FP.SplitB, FP.TrueB) > Prob)
494 if (MBPI->getEdgeProbability(FP.SplitB, FP.FalseB) > Prob)
513 unsigned TS = 0,
FS = 0, Spare = 0;
515 TS = std::distance(FP.TrueB->begin(), FP.TrueB->getFirstTerminator());
520 FS = std::distance(FP.FalseB->begin(), FP.FalseB->getFirstTerminator());
524 unsigned TotalIn = TS+
FS;
525 DEBUG(
dbgs() <<
"Total number of instructions to be predicated/speculated: "
526 << TotalIn <<
", spare room: " << Spare <<
"\n");
527 if (TotalIn >= SizeLimit+Spare)
536 unsigned TotalPh = 0;
537 unsigned PredDefs = countPredicateDefs(FP.SplitB);
539 TotalPh = computePhiCost(FP.JoinB);
540 PredDefs += countPredicateDefs(FP.JoinB);
542 if (FP.TrueB && FP.TrueB->succ_size() > 0) {
544 TotalPh += computePhiCost(SB);
545 PredDefs += countPredicateDefs(SB);
547 if (FP.FalseB && FP.FalseB->succ_size() > 0) {
549 TotalPh += computePhiCost(SB);
550 PredDefs += countPredicateDefs(SB);
553 DEBUG(
dbgs() <<
"Total number of extra muxes from converted phis: "
555 if (TotalIn+TotalPh >= SizeLimit+Spare)
558 DEBUG(
dbgs() <<
"Total number of predicate registers: " << PredDefs <<
"\n");
567 bool Changed =
false;
580 DTNodeVectType Cn(GTN::child_begin(N), GTN::child_end(N));
581 for (DTNodeVectType::iterator I = Cn.begin(), E = Cn.end(); I !=
E; ++
I) {
583 if (!Deleted.count(SB))
584 Changed |= visitBlock(SB, L);
589 if (MLI->getLoopFor(B) !=
L)
593 if (!matchFlowPattern(B, L, FP))
597 DEBUG(
dbgs() <<
"Conversion is not valid\n");
600 if (!isProfitable(FP)) {
601 DEBUG(
dbgs() <<
"Conversion is not profitable\n");
606 simplifyFlowGraph(FP);
610 bool HexagonEarlyIfConversion::visitLoop(
MachineLoop *L) {
612 DEBUG((L ?
dbgs() <<
"Visiting loop H:" << PrintMB(HB)
613 :
dbgs() <<
"Visiting function") <<
"\n");
614 bool Changed =
false;
617 Changed |= visitLoop(*I);
621 Changed |= visitBlock(L ? HB : EntryB, L);
625 bool HexagonEarlyIfConversion::isPredicableStore(
const MachineInstr *MI)
632 case Hexagon::S2_storerb_io:
633 case Hexagon::S2_storerbnew_io:
634 case Hexagon::S2_storerh_io:
635 case Hexagon::S2_storerhnew_io:
636 case Hexagon::S2_storeri_io:
637 case Hexagon::S2_storerinew_io:
638 case Hexagon::S2_storerd_io:
639 case Hexagon::S4_storeirb_io:
640 case Hexagon::S4_storeirh_io:
641 case Hexagon::S4_storeiri_io:
646 return MI->
mayStore() && HII->isPredicable(const_cast<MachineInstr&>(*MI));
649 bool HexagonEarlyIfConversion::isSafeToSpeculate(
const MachineInstr *MI)
661 unsigned HexagonEarlyIfConversion::getCondStoreOpcode(
unsigned Opc,
663 return HII->getCondOpcode(Opc, !IfTrue);
668 unsigned PredR,
bool IfTrue) {
670 if (At != ToB->
end())
671 DL = At->getDebugLoc();
672 else if (!ToB->
empty())
677 if (isPredicableStore(MI)) {
678 unsigned COpc = getCondStoreOpcode(Opc, IfTrue);
682 if (HII->isPostIncrement(*MI)) {
699 if (Opc == Hexagon::J2_jump) {
701 const MCInstrDesc &
D = HII->get(IfTrue ? Hexagon::J2_jumpt
702 : Hexagon::J2_jumpf);
721 unsigned PredR,
bool IfTrue) {
722 DEBUG(
dbgs() <<
"Predicating block " << PrintMB(FromB) <<
"\n");
726 for (I = FromB->
begin(); I !=
End; I = NextI) {
728 NextI = std::next(I);
729 if (isSafeToSpeculate(&*I))
730 ToB->
splice(At, FromB, I);
732 predicateInstr(ToB, At, &*I, PredR, IfTrue);
737 const FlowPattern &FP) {
741 for (
auto I = WhereB->
begin(); I != NonPHI; ++
I) {
744 unsigned TR = 0, TSR = 0, FR = 0, FSR = 0, SR = 0, SSR = 0;
747 if (BO.getMBB() == FP.SplitB)
749 else if (BO.getMBB() == FP.TrueB)
751 else if (BO.getMBB() == FP.FalseB)
764 using namespace Hexagon;
769 if (RC == &IntRegsRegClass)
771 else if (RC == &DoubleRegsRegClass)
773 else if (RC == &VectorRegsRegClass)
775 else if (RC == &VecDblRegsRegClass)
777 else if (RC == &VectorRegs128BRegClass)
778 Opc = PS_vselect_128B;
779 else if (RC == &VecDblRegs128BRegClass)
780 Opc = PS_wselect_128B;
787 if (MuxAt != FP.SplitB->end())
788 DL = MuxAt->getDebugLoc();
789 unsigned MuxR =
MRI->createVirtualRegister(RC);
790 BuildMI(*FP.SplitB, MuxAt, DL, D, MuxR)
800 void HexagonEarlyIfConversion::convert(
const FlowPattern &FP) {
803 assert(OldTI != FP.SplitB->end());
807 TSB = *FP.TrueB->succ_begin();
808 predicateBlockNB(FP.SplitB, OldTI, FP.TrueB, FP.PredR,
true);
811 FSB = *FP.FalseB->succ_begin();
813 predicateBlockNB(FP.SplitB, At, FP.FalseB, FP.PredR,
false);
820 FP.SplitB->erase(OldTI, FP.SplitB->end());
821 while (FP.SplitB->succ_size() > 0) {
837 if (T != FP.TrueB && T != FP.FalseB) {
841 FP.SplitB->removeSuccessor(FP.SplitB->succ_begin());
849 assert(!SSB || SSB == FP.JoinB);
850 BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jump))
852 FP.SplitB->addSuccessor(FP.JoinB);
854 bool HasBranch =
false;
856 BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jumpt))
859 FP.SplitB->addSuccessor(TSB);
863 const MCInstrDesc &D = HasBranch ? HII->get(Hexagon::J2_jump)
864 : HII->get(Hexagon::J2_jumpf);
869 FP.SplitB->addSuccessor(FSB);
876 BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jump))
878 FP.SplitB->addSuccessor(SSB);
885 updatePhiNodes(FP.JoinB, FP);
888 updatePhiNodes(TSB, FP);
890 updatePhiNodes(FSB, FP);
896 DEBUG(
dbgs() <<
"Removing block " << PrintMB(B) <<
"\n");
905 DTNodeVectType Cn(GTN::child_begin(N), GTN::child_end(N));
906 for (DTNodeVectType::iterator I = Cn.begin(), E = Cn.end(); I !=
E; ++
I) {
908 MDT->changeImmediateDominator(SB, IDB);
916 (*I)->removeSuccessor(B,
true);
924 DEBUG(
dbgs() <<
"Removing phi nodes from block " << PrintMB(B) <<
"\n");
926 for (I = B->
begin(); I != NonPHI; I = NextI) {
927 NextI = std::next(I);
931 unsigned UseR = UO.
getReg(), UseSR = UO.getSubReg();
933 unsigned NewR = UseR;
940 NewR =
MRI->createVirtualRegister(RC);
941 NonPHI =
BuildMI(*B, NonPHI, DL, HII->
get(TargetOpcode::COPY), NewR)
942 .addReg(UseR, 0, UseSR);
944 MRI->replaceRegWith(DefR, NewR);
954 for (P = SB->
begin(); P !=
N; ++
P) {
957 if (MO.isMBB() && MO.getMBB() == OldB)
965 DEBUG(
dbgs() <<
"Merging blocks " << PrintMB(PredB) <<
" and "
966 << PrintMB(SuccB) <<
"\n");
967 bool TermOk = hasUncondBranch(SuccB);
968 eliminatePhis(SuccB);
969 HII->removeBranch(*PredB);
976 replacePhiEdges(SuccB, PredB);
982 void HexagonEarlyIfConversion::simplifyFlowGraph(
const FlowPattern &FP) {
984 removeBlock(FP.TrueB);
986 removeBlock(FP.FalseB);
988 FP.SplitB->updateTerminator();
989 if (FP.SplitB->succ_size() != 1)
1001 if (!hasEHLabel(SB) || hasUncondBranch(SB))
1002 mergeBlocks(FP.SplitB, SB);
1005 bool HexagonEarlyIfConversion::runOnMachineFunction(
MachineFunction &MF) {
1010 HII =
ST.getInstrInfo();
1011 TRI =
ST.getRegisterInfo();
1014 MDT = &getAnalysis<MachineDominatorTree>();
1015 MLI = &getAnalysis<MachineLoopInfo>();
1016 MBPI = EnableHexagonBP ? &getAnalysis<MachineBranchProbabilityInfo>() :
1020 bool Changed =
false;
1023 Changed |= visitLoop(*I);
1024 Changed |= visitLoop(
nullptr);
1033 return new HexagonEarlyIfConversion();
unsigned succ_size() const
bool isEHPad() const
Returns true if the block is a landing pad.
mop_iterator operands_end()
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
MachineBasicBlock * getMBB() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Implements a dense probed hash-table based set.
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
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.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
A global registry used in conjunction with static constructors to make pluggable components (like tar...
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
iterator_range< mop_iterator > operands()
BlockT * getHeader() const
DomTreeNodeBase< NodeT > * getIDom() const
AnalysisUsage & addRequired()
A description of a memory reference used in the backend.
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...
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false)
#define HEXAGON_PACKET_SIZE
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
std::vector< MachineBasicBlock * >::iterator succ_iterator
unsigned getNumOperands() const
Access to explicit operands of the instruction.
void RemoveOperand(unsigned i)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
Base class for the actual dominator tree node.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubRegIdx=0)
Prints virtual and physical registers with or without a TRI instance.
void normalizeSuccProbs()
Normalize probabilities of all successors so that the sum of them becomes one.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
bool isImplicitDef() const
mmo_iterator memoperands_end() const
INITIALIZE_PASS(HexagonEarlyIfConversion,"hexagon-eif","Hexagon early if conversion", false, false) bool HexagonEarlyIfConversion MachineBasicBlock * SB
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)
const MachineInstrBuilder & setMemRefs(MachineInstr::mmo_iterator b, MachineInstr::mmo_iterator e) const
FunctionPass * createHexagonEarlyIfConversion()
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
#define LLVM_ATTRIBUTE_UNUSED
static const unsigned End
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.
self_iterator getIterator()
succ_iterator succ_begin()
unsigned getSubReg() 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.
void initializeHexagonEarlyIfConversionPass(PassRegistry &Registry)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Iterator for intrusive lists based on ilist_node.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
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...
void updateTerminator()
Update the terminator instructions in block to account for changes to the layout. ...
INITIALIZE_PASS(HexagonGenMux,"hexagon-mux","Hexagon generate mux instructions", false, false) void HexagonGenMux I isValid()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Representation of each machine instruction.
bool hasAddressTaken() const
Test whether this block is potentially the target of an indirect branch.
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0)
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
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
mop_iterator operands_begin()
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
std::vector< LoopT * >::const_iterator iterator
LoopInfoBase< MachineBasicBlock, MachineLoop >::iterator iterator
The iterator interface to the top-level loops in the current function.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
unsigned pred_size() const
bool isBarrier(QueryType Type=AnyInBundle) const
Returns true if the specified instruction stops control flow from executing the instruction immediate...
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.