91 #define DEBUG_TYPE "hexagon-eif" 105 cl::desc(
"Size limit in Hexagon early if-conversion"));
118 return OS <<
"<none>";
119 return OS <<
'#' << P.MB->getNumber();
123 FlowPattern() =
default;
126 : SplitB(B), TrueB(TB), FalseB(FB), JoinB(JB), PredR(PR) {}
139 const FlowPattern &
FP;
146 OS <<
"{ SplitB:" << PrintMB(P.FP.SplitB)
147 <<
", PredR:" <<
printReg(P.FP.PredR, &P.TRI)
148 <<
", TrueB:" << PrintMB(P.FP.TrueB)
149 <<
", FalseB:" << PrintMB(P.FP.FalseB)
150 <<
", JoinB:" << PrintMB(P.FP.JoinB) <<
" }";
161 return "Hexagon early if conversion";
187 bool isValid(
const FlowPattern &FP)
const;
190 const FlowPattern &FP)
const;
191 bool isProfitable(
const FlowPattern &FP)
const;
194 bool isPredicate(
unsigned R)
const;
196 unsigned getCondStoreOpcode(
unsigned Opc,
bool IfTrue)
const;
201 unsigned PredR,
bool IfTrue);
205 unsigned TSR,
unsigned FR,
unsigned FSR);
207 void convert(
const FlowPattern &FP);
212 void simplifyFlowGraph(
const FlowPattern &FP);
229 "Hexagon early if conversion",
false,
false)
232 if (B->succ_size() != 1)
236 return L && SB == L->
getHeader() && MDT->dominates(B, SB);
251 unsigned Opc = T1I->getOpcode();
252 if (Opc != Hexagon::J2_jumpt && Opc != Hexagon::J2_jumpf)
254 unsigned PredR = T1I->getOperand(0).getReg();
263 assert(T2I == B->
end() || T2I->getOpcode() == Hexagon::J2_jump);
265 : T2I->getOperand(0).getMBB();
274 if (Opc == Hexagon::J2_jumpt)
279 if (!MDT->properlyDominates(B, TB) || !MDT->properlyDominates(B, FB))
286 unsigned TNP = TB->
pred_size(), FNP = FB->pred_size();
287 unsigned TNS = TB->
succ_size(), FNS = FB->succ_size();
294 bool TOk = (TNP == 1 && TNS == 1 && MLI->getLoopFor(TB) == L);
295 bool FOk = (FNP == 1 && FNS == 1 && MLI->getLoopFor(FB) == L);
299 if (SkipExitBranches && MLI->getLoopFor(TB) != MLI->getLoopFor(FB))
328 if ((TB && isPreheader(TB)) || (FB && isPreheader(FB))) {
329 LLVM_DEBUG(
dbgs() <<
"One of blocks " << PrintMB(TB) <<
", " << PrintMB(FB)
330 <<
" is a loop preheader. Skipping.\n");
334 FP = FlowPattern(B, PredR, TB, FB, JB);
370 for (
auto &
MI : *B) {
371 if (
MI.isDebugInstr())
373 if (
MI.isConditionalBranch())
375 unsigned Opc =
MI.getOpcode();
376 bool IsJMP = (Opc == Hexagon::J2_jump);
377 if (!isPredicableStore(&
MI) && !IsJMP && !isSafeToSpeculate(&
MI))
386 if (!MO.isReg() || !MO.isDef())
388 unsigned R = MO.getReg();
393 for (
auto U =
MRI->use_begin(R); U !=
MRI->use_end(); ++U)
394 if (U->getParent()->isPHI())
401 bool HexagonEarlyIfConversion::usesUndefVReg(
const MachineInstr *
MI)
const {
403 if (!MO.isReg() || !MO.isUse())
405 unsigned R = MO.getReg();
410 assert(DefI &&
"Expecting a reaching def in MRI");
417 bool HexagonEarlyIfConversion::isValid(
const FlowPattern &FP)
const {
418 if (hasEHLabel(FP.SplitB))
420 if (FP.TrueB && !isValidCandidate(FP.TrueB))
422 if (FP.FalseB && !isValidCandidate(FP.FalseB))
439 if (usesUndefVReg(&MI))
442 if (isPredicate(DefR))
450 const FlowPattern &FP)
const {
465 if (BB == FP.SplitB || BB == FP.TrueB || BB == FP.FalseB)
482 if (!HII->isPredicable(*Def1) || !HII->isPredicable(*Def3))
488 unsigned HexagonEarlyIfConversion::countPredicateDefs(
490 unsigned PredDefs = 0;
491 for (
auto &MI : *B) {
493 if (!MO.isReg() || !MO.isDef())
495 unsigned R = MO.getReg();
505 bool HexagonEarlyIfConversion::isProfitable(
const FlowPattern &FP)
const {
508 if (MBPI && FP.TrueB && !FP.FalseB &&
509 (MBPI->getEdgeProbability(FP.SplitB, FP.TrueB) < JumpProb ||
510 MBPI->getEdgeProbability(FP.SplitB, FP.TrueB) > Prob))
513 if (MBPI && !FP.TrueB && FP.FalseB &&
514 (MBPI->getEdgeProbability(FP.SplitB, FP.FalseB) < JumpProb ||
515 MBPI->getEdgeProbability(FP.SplitB, FP.FalseB) > Prob))
518 if (FP.TrueB && FP.FalseB) {
521 if (MBPI->getEdgeProbability(FP.SplitB, FP.TrueB) > Prob)
523 if (MBPI->getEdgeProbability(FP.SplitB, FP.FalseB) > Prob)
554 unsigned TotalIn = TotalCount(FP.TrueB, Spare) + TotalCount(FP.FalseB, Spare);
556 dbgs() <<
"Total number of instructions to be predicated/speculated: " 557 << TotalIn <<
", spare room: " << Spare <<
"\n");
558 if (TotalIn >= SizeLimit+Spare)
567 unsigned TotalPh = 0;
568 unsigned PredDefs = countPredicateDefs(FP.SplitB);
570 TotalPh = computePhiCost(FP.JoinB, FP);
571 PredDefs += countPredicateDefs(FP.JoinB);
573 if (FP.TrueB && FP.TrueB->succ_size() > 0) {
575 TotalPh += computePhiCost(SB, FP);
576 PredDefs += countPredicateDefs(SB);
578 if (FP.FalseB && FP.FalseB->succ_size() > 0) {
580 TotalPh += computePhiCost(SB, FP);
581 PredDefs += countPredicateDefs(SB);
584 LLVM_DEBUG(
dbgs() <<
"Total number of extra muxes from converted phis: " 586 if (TotalIn+TotalPh >= SizeLimit+Spare)
589 LLVM_DEBUG(
dbgs() <<
"Total number of predicate registers: " << PredDefs
599 bool Changed =
false;
614 DTNodeVectType Cn(GTN::child_begin(N), GTN::child_end(N));
615 for (DTNodeVectType::iterator
I = Cn.begin(),
E = Cn.end();
I !=
E; ++
I) {
618 Changed |= visitBlock(SB, L);
623 if (MLI->getLoopFor(B) != L)
627 if (!matchFlowPattern(B, L, FP))
634 if (!isProfitable(FP)) {
640 simplifyFlowGraph(FP);
644 bool HexagonEarlyIfConversion::visitLoop(
MachineLoop *L) {
647 :
dbgs() <<
"Visiting function")
649 bool Changed =
false;
652 Changed |= visitLoop(*
I);
656 Changed |= visitBlock(L ? HB : EntryB, L);
660 bool HexagonEarlyIfConversion::isPredicableStore(
const MachineInstr *MI)
667 case Hexagon::S2_storerb_io:
668 case Hexagon::S2_storerbnew_io:
669 case Hexagon::S2_storerh_io:
670 case Hexagon::S2_storerhnew_io:
671 case Hexagon::S2_storeri_io:
672 case Hexagon::S2_storerinew_io:
673 case Hexagon::S2_storerd_io:
674 case Hexagon::S4_storeirb_io:
675 case Hexagon::S4_storeirh_io:
676 case Hexagon::S4_storeiri_io:
681 return MI->
mayStore() && HII->isPredicable(const_cast<MachineInstr&>(*MI));
684 bool HexagonEarlyIfConversion::isSafeToSpeculate(
const MachineInstr *MI)
698 bool HexagonEarlyIfConversion::isPredicate(
unsigned R)
const {
700 return RC == &Hexagon::PredRegsRegClass ||
701 RC == &Hexagon::HvxQRRegClass;
704 unsigned HexagonEarlyIfConversion::getCondStoreOpcode(
unsigned Opc,
706 return HII->getCondOpcode(Opc, !IfTrue);
711 unsigned PredR,
bool IfTrue) {
713 if (At != ToB->
end())
714 DL = At->getDebugLoc();
715 else if (!ToB->
empty())
720 if (isPredicableStore(MI)) {
721 unsigned COpc = getCondStoreOpcode(Opc, IfTrue);
725 if (HII->isPostIncrement(*MI)) {
740 if (Opc == Hexagon::J2_jump) {
742 const MCInstrDesc &
D = HII->get(IfTrue ? Hexagon::J2_jumpt
743 : Hexagon::J2_jumpf);
762 unsigned PredR,
bool IfTrue) {
763 LLVM_DEBUG(
dbgs() <<
"Predicating block " << PrintMB(FromB) <<
"\n");
767 for (I = FromB->
begin(); I != End; I = NextI) {
769 NextI = std::next(I);
770 if (isSafeToSpeculate(&*I))
771 ToB->
splice(At, FromB, I);
773 predicateInstr(ToB, At, &*I, PredR, IfTrue);
779 unsigned PredR,
unsigned TR,
unsigned TSR,
unsigned FR,
unsigned FSR) {
781 switch (DRC->
getID()) {
782 case Hexagon::IntRegsRegClassID:
783 case Hexagon::IntRegsLow8RegClassID:
784 Opc = Hexagon::C2_mux;
786 case Hexagon::DoubleRegsRegClassID:
787 case Hexagon::GeneralDoubleLow8RegsRegClassID:
788 Opc = Hexagon::PS_pselect;
790 case Hexagon::HvxVRRegClassID:
791 Opc = Hexagon::PS_vselect;
793 case Hexagon::HvxWRRegClassID:
794 Opc = Hexagon::PS_wselect;
802 unsigned MuxR =
MRI->createVirtualRegister(DRC);
811 const FlowPattern &FP) {
815 for (
auto I = WhereB->
begin();
I != NonPHI; ++
I) {
818 unsigned TR = 0, TSR = 0, FR = 0, FSR = 0, SR = 0, SSR = 0;
821 if (BO.getMBB() == FP.SplitB)
823 else if (BO.getMBB() == FP.TrueB)
825 else if (BO.getMBB() == FP.FalseB)
838 unsigned MuxR = 0, MuxSR = 0;
843 MuxR = buildMux(FP.SplitB, FP.SplitB->getFirstTerminator(), RC,
844 FP.PredR, TR, TSR, FR, FSR);
854 false,
false, MuxSR));
859 void HexagonEarlyIfConversion::convert(
const FlowPattern &FP) {
862 assert(OldTI != FP.SplitB->end());
866 TSB = *FP.TrueB->succ_begin();
867 predicateBlockNB(FP.SplitB, OldTI, FP.TrueB, FP.PredR,
true);
870 FSB = *FP.FalseB->succ_begin();
872 predicateBlockNB(FP.SplitB, At, FP.FalseB, FP.PredR,
false);
879 FP.SplitB->erase(OldTI, FP.SplitB->end());
880 while (FP.SplitB->succ_size() > 0) {
896 if (T != FP.TrueB && T != FP.FalseB) {
900 FP.SplitB->removeSuccessor(FP.SplitB->succ_begin());
908 assert(!SSB || SSB == FP.JoinB);
909 BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jump))
911 FP.SplitB->addSuccessor(FP.JoinB);
913 bool HasBranch =
false;
915 BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jumpt))
918 FP.SplitB->addSuccessor(TSB);
922 const MCInstrDesc &
D = HasBranch ? HII->get(Hexagon::J2_jump)
923 : HII->get(Hexagon::J2_jumpf);
928 FP.SplitB->addSuccessor(FSB);
935 BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jump))
937 FP.SplitB->addSuccessor(SSB);
966 DTNodeVectType Cn(GTN::child_begin(N), GTN::child_end(N));
967 for (DTNodeVectType::iterator
I = Cn.begin(),
E = Cn.end();
I !=
E; ++
I) {
969 MDT->changeImmediateDominator(SB, IDB);
977 (*I)->removeSuccessor(B,
true);
985 LLVM_DEBUG(
dbgs() <<
"Removing phi nodes from block " << PrintMB(B) <<
"\n");
987 for (I = B->
begin(); I != NonPHI; I = NextI) {
988 NextI = std::next(I);
992 unsigned UseR = UO.
getReg(), UseSR = UO.getSubReg();
994 unsigned NewR = UseR;
1001 NewR =
MRI->createVirtualRegister(RC);
1002 NonPHI =
BuildMI(*B, NonPHI, DL, HII->
get(TargetOpcode::COPY), NewR)
1003 .addReg(UseR, 0, UseSR);
1005 MRI->replaceRegWith(DefR, NewR);
1012 LLVM_DEBUG(
dbgs() <<
"Merging blocks " << PrintMB(PredB) <<
" and " 1013 << PrintMB(SuccB) <<
"\n");
1014 bool TermOk = hasUncondBranch(SuccB);
1015 eliminatePhis(SuccB);
1016 HII->removeBranch(*PredB);
1025 void HexagonEarlyIfConversion::simplifyFlowGraph(
const FlowPattern &FP) {
1027 removeBlock(FP.TrueB);
1029 removeBlock(FP.FalseB);
1031 FP.SplitB->updateTerminator();
1032 if (FP.SplitB->succ_size() != 1)
1044 if (!hasEHLabel(SB) || hasUncondBranch(SB))
1045 mergeBlocks(FP.SplitB, SB);
1048 bool HexagonEarlyIfConversion::runOnMachineFunction(
MachineFunction &MF) {
1053 HII =
ST.getInstrInfo();
1054 TRI =
ST.getRegisterInfo();
1057 MDT = &getAnalysis<MachineDominatorTree>();
1058 MLI = &getAnalysis<MachineLoopInfo>();
1059 MBPI = EnableHexagonBP ? &getAnalysis<MachineBranchProbabilityInfo>() :
1063 bool Changed =
false;
1066 Changed |= visitLoop(*
I);
1067 Changed |= visitLoop(
nullptr);
1076 return new HexagonEarlyIfConversion();
const MachineInstrBuilder & add(const MachineOperand &MO) const
mop_iterator operands_end()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
bool isCall(QueryType Type=AnyInBundle) const
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
Implements a dense probed hash-table based set.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
static void updatePhiNodes(BasicBlock *DestBB, BasicBlock *OldPred, BasicBlock *NewPred, PHINode *LandingPadReplacement)
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.
unsigned getReg() const
getReg - Returns the register number.
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...
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
unsigned getSubReg() const
auto count_if(R &&Range, UnaryPredicate P) -> typename std::iterator_traits< decltype(adl_begin(Range))>::difference_type
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
unsigned const TargetRegisterInfo * TRI
static cl::opt< bool > SkipExitBranches("eif-no-loop-exit", cl::init(false), cl::Hidden, cl::desc("Do not convert branches that may exit the loop"))
bool isMetaInstruction() const
Return true if this instruction doesn't produce any output in the form of executable instructions...
iterator_range< mop_iterator > operands()
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, bool isRenamable=false)
SI optimize exec mask operations pre RA
AnalysisUsage & addRequired()
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...
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
unsigned getNumOperands() const
Retuns the total number of operands.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getID() const
Return the register class ID number.
BlockT * getHeader() const
std::vector< MachineLoop *>::const_iterator iterator
Base class for the actual dominator tree node.
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
initializer< Ty > init(const Ty &Val)
FunctionPass * createHexagonEarlyIfConversion()
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.
DomTreeNodeBase * getIDom() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< bool > EnableHexagonBP("enable-hexagon-br-prob", cl::Hidden, cl::init(true), cl::desc("Enable branch probability info"))
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
self_iterator getIterator()
succ_iterator succ_begin()
bool hasAddressTaken() const
Test whether this block is potentially the target of an indirect branch.
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.
void initializeHexagonEarlyIfConversionPass(PassRegistry &Registry)
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 addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
MachineOperand class - Representation of each machine instruction operand.
void updateTerminator()
Update the terminator instructions in block to account for changes to the layout. ...
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
unsigned pred_size() const
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.
DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
unsigned succ_size() const
static cl::opt< unsigned > SizeLimit("eif-limit", cl::init(6), cl::Hidden, cl::desc("Size limit in Hexagon early if-conversion"))
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
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 isEHPad() const
Returns true if the block is a landing pad.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
LoopInfoBase< MachineBasicBlock, MachineLoop >::iterator iterator
The iterator interface to the top-level loops in the current function.
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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.
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define HEXAGON_PACKET_SIZE
mop_iterator operands_begin()
This class implements an extremely fast bulk output stream that can only output to a stream...
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
bool isBarrier(QueryType Type=AnyInBundle) const
Returns true if the specified instruction stops control flow from executing the instruction immediate...
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
INITIALIZE_PASS(HexagonEarlyIfConversion, "hexagon-early-if", "Hexagon early if conversion", false, false) bool HexagonEarlyIfConversion
#define LLVM_ATTRIBUTE_UNUSED
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
const MachineOperand & getOperand(unsigned i) const
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...