31 #define DEBUG_TYPE "ppc-branch-coalescing" 33 STATISTIC(NumBlocksCoalesced,
"Number of blocks coalesced");
34 STATISTIC(NumPHINotMoved,
"Number of PHI Nodes that cannot be merged");
35 STATISTIC(NumBlocksNotCoalesced,
"Number of blocks not coalesced");
141 struct CoalescingCandidateInfo {
149 CoalescingCandidateInfo();
159 bool canCoalesceBranch(CoalescingCandidateInfo &Cand);
162 bool validateCandidates(CoalescingCandidateInfo &SourceRegion,
163 CoalescingCandidateInfo &TargetRegion)
const;
178 StringRef getPassName()
const override {
return "Branch Coalescing"; }
180 bool mergeCandidates(CoalescingCandidateInfo &SourceRegion,
181 CoalescingCandidateInfo &TargetRegion);
186 bool canMerge(CoalescingCandidateInfo &SourceRegion,
187 CoalescingCandidateInfo &TargetRegion)
const;
198 return new PPCBranchCoalescing();
202 "Branch Coalescing",
false,
false)
208 PPCBranchCoalescing::CoalescingCandidateInfo::CoalescingCandidateInfo()
209 : BranchBlock(
nullptr), BranchTargetBlock(
nullptr),
210 FallThroughBlock(
nullptr), MustMoveDown(false), MustMoveUp(false) {}
213 BranchBlock =
nullptr;
214 BranchTargetBlock =
nullptr;
215 FallThroughBlock =
nullptr;
217 MustMoveDown =
false;
222 MDT = &getAnalysis<MachineDominatorTree>();
223 MPDT = &getAnalysis<MachinePostDominatorTree>();
238 bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) {
240 << Cand.BranchBlock->getNumber() <<
" can be coalesced:");
249 for (
auto &
I : Cand.BranchBlock->terminators()) {
267 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
268 LLVM_DEBUG(
dbgs() <<
"Terminator contains implicit operands - skip : " 274 if (Cand.BranchBlock->isEHPad() || Cand.BranchBlock->hasEHPadSuccessor()) {
281 if (!Cand.BranchTargetBlock || FalseMBB ||
282 !Cand.BranchBlock->isSuccessor(Cand.BranchTargetBlock)) {
288 if (Cand.BranchBlock->succ_size() != 2) {
294 assert(Cand.BranchBlock->canFallThrough() &&
295 "Expecting the block to fall through!");
301 (*Cand.BranchBlock->succ_begin() == Cand.BranchTargetBlock)
302 ? *Cand.BranchBlock->succ_rbegin()
303 : *Cand.BranchBlock->succ_begin();
305 assert(Succ &&
"Expecting a valid fall-through block\n");
307 if (!Succ->empty()) {
308 LLVM_DEBUG(
dbgs() <<
"Fall-through block contains code -- skip\n");
312 if (!Succ->isSuccessor(Cand.BranchTargetBlock)) {
315 <<
"Successor of fall through block is not branch taken block\n");
319 Cand.FallThroughBlock = Succ;
331 bool PPCBranchCoalescing::identicalOperands(
334 if (OpList1.
size() != OpList2.
size()) {
339 for (
unsigned i = 0; i < OpList1.
size(); ++i) {
344 <<
"Op2: " << Op2 <<
"\n");
352 LLVM_DEBUG(
dbgs() <<
"The operands are not provably identical.\n");
367 if (
TII->produceSameValue(*Op1Def, *Op2Def,
MRI)) {
369 <<
" produce the same value!\n");
375 LLVM_DEBUG(
dbgs() <<
"The operands are not provably identical.\n");
399 LLVM_DEBUG(
dbgs() <<
"SourceMBB contains no PHI instructions.\n");
406 for (
unsigned i = 2, e = PHIInst.
getNumOperands() + 1; i != e; i += 2) {
408 if (MO.
getMBB() == SourceMBB)
425 bool PPCBranchCoalescing::canMoveToBeginning(
const MachineInstr &
MI,
429 LLVM_DEBUG(
dbgs() <<
"Checking if " << MI <<
" can move to beginning of " 433 for (
auto &
Use :
MRI->use_instructions(
Def.getReg())) {
434 if (
Use.isPHI() &&
Use.getParent() == &TargetMBB) {
456 bool PPCBranchCoalescing::canMoveToEnd(
const MachineInstr &MI,
460 LLVM_DEBUG(
dbgs() <<
"Checking if " << MI <<
" can move to end of " 471 dbgs() <<
" *** def is in another block -- safe to move!\n");
489 bool PPCBranchCoalescing::validateCandidates(
490 CoalescingCandidateInfo &SourceRegion,
491 CoalescingCandidateInfo &TargetRegion)
const {
493 if (TargetRegion.BranchTargetBlock != SourceRegion.BranchBlock)
494 llvm_unreachable(
"Expecting SourceRegion to immediately follow TargetRegion");
495 else if (!MDT->dominates(TargetRegion.BranchBlock, SourceRegion.BranchBlock))
497 else if (!MPDT->dominates(SourceRegion.BranchBlock, TargetRegion.BranchBlock))
499 else if (!TargetRegion.FallThroughBlock->empty() ||
500 !SourceRegion.FallThroughBlock->empty())
532 bool PPCBranchCoalescing::canMerge(CoalescingCandidateInfo &SourceRegion,
533 CoalescingCandidateInfo &TargetRegion)
const {
534 if (!validateCandidates(SourceRegion, TargetRegion))
540 I = SourceRegion.BranchBlock->instr_begin(),
541 E = SourceRegion.BranchBlock->getFirstNonPHI();
543 for (
auto &
Def :
I->defs())
544 for (
auto &
Use :
MRI->use_instructions(
Def.getReg())) {
545 if (
Use.isPHI() &&
Use.getParent() == SourceRegion.BranchTargetBlock) {
548 <<
" defines register used in another " 549 "PHI within branch target block -- can't merge\n");
553 if (
Use.getParent() == SourceRegion.BranchBlock) {
555 <<
" defines register used in this " 556 "block -- all must move down\n");
557 SourceRegion.MustMoveDown =
true;
565 I = SourceRegion.BranchBlock->getFirstNonPHI(),
566 E = SourceRegion.BranchBlock->end();
568 if (!canMoveToBeginning(*
I, *SourceRegion.BranchTargetBlock)) {
570 <<
" cannot move down - must move up!\n");
571 SourceRegion.MustMoveUp =
true;
573 if (!canMoveToEnd(*
I, *TargetRegion.BranchBlock)) {
575 <<
" cannot move up - must move down!\n");
576 SourceRegion.MustMoveDown =
true;
580 return (SourceRegion.MustMoveUp && SourceRegion.MustMoveDown) ?
false :
true;
639 bool PPCBranchCoalescing::mergeCandidates(CoalescingCandidateInfo &SourceRegion,
640 CoalescingCandidateInfo &TargetRegion) {
642 if (SourceRegion.MustMoveUp && SourceRegion.MustMoveDown) {
647 if (!validateCandidates(SourceRegion, TargetRegion))
652 moveAndUpdatePHIs(SourceRegion.BranchBlock, SourceRegion.BranchTargetBlock);
657 SourceRegion.BranchBlock->getFirstNonPHI();
659 SourceRegion.BranchBlock->getFirstTerminator();
662 ? SourceRegion.BranchTargetBlock
663 : TargetRegion.BranchBlock;
666 SourceRegion.MustMoveDown
667 ? SourceRegion.BranchTargetBlock->getFirstNonPHI()
668 : TargetRegion.BranchBlock->getFirstTerminator();
670 Source->
splice(Target, SourceRegion.BranchBlock, firstInstr, lastInstr);
677 SourceRegion.BranchBlock->removeSuccessor(SourceRegion.FallThroughBlock);
678 TargetRegion.BranchBlock->transferSuccessorsAndUpdatePHIs(
679 SourceRegion.BranchBlock);
683 TargetRegion.BranchBlock->ReplaceUsesOfBlockWith(
684 SourceRegion.BranchBlock, SourceRegion.BranchTargetBlock);
687 SourceRegion.BranchBlock->terminators().begin();
688 while (I != SourceRegion.BranchBlock->terminators().end()) {
697 assert(TargetRegion.FallThroughBlock->empty() &&
698 "FallThroughBlocks should be empty!");
702 TargetRegion.FallThroughBlock->transferSuccessorsAndUpdatePHIs(
703 SourceRegion.FallThroughBlock);
704 TargetRegion.FallThroughBlock->removeSuccessor(SourceRegion.BranchBlock);
707 assert(SourceRegion.BranchBlock->empty() &&
708 "Expecting branch block to be empty!");
709 SourceRegion.BranchBlock->eraseFromParent();
711 assert(SourceRegion.FallThroughBlock->empty() &&
712 "Expecting fall-through block to be empty!\n");
713 SourceRegion.FallThroughBlock->eraseFromParent();
715 NumBlocksCoalesced++;
724 bool didSomething =
false;
731 CoalescingCandidateInfo Cand1, Cand2;
736 bool MergedCandidates =
false;
738 MergedCandidates =
false;
742 Cand1.BranchBlock = &MBB;
745 if (!canCoalesceBranch(Cand1))
748 Cand2.BranchBlock = Cand1.BranchTargetBlock;
749 if (!canCoalesceBranch(Cand2))
755 assert(MPDT->dominates(Cand2.BranchTargetBlock, Cand1.BranchBlock) &&
756 "Branch-taken block should post-dominate first candidate");
758 if (!identicalOperands(Cand1.Cond, Cand2.Cond)) {
760 <<
" and " << Cand2.BranchBlock->getNumber()
761 <<
" have different branches\n");
764 if (!canMerge(Cand2, Cand1)) {
766 << Cand1.BranchBlock->getNumber() <<
" and " 767 << Cand2.BranchBlock->getNumber() <<
"\n");
768 NumBlocksNotCoalesced++;
771 LLVM_DEBUG(
dbgs() <<
"Merging blocks " << Cand1.BranchBlock->getNumber()
772 <<
" and " << Cand1.BranchTargetBlock->getNumber()
774 MergedCandidates = mergeCandidates(Cand2, Cand1);
775 if (MergedCandidates)
780 }
while (MergedCandidates);
786 MF.verify(
nullptr,
"Error in code produced by branch coalescing");
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
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.
STATISTIC(NumFunctions, "Total number of functions")
void dump() const
dump - Print the current MachineFunction to cerr, useful for debugger use.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e...
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
A Use represents the edge between a Value definition and its users.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
void initializePPCBranchCoalescingPass(PassRegistry &)
FunctionPass * createPPCBranchCoalescingPass()
createPPCBranchCoalescingPass - returns an instance of the Branch Coalescing Pass ...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
virtual const TargetInstrInfo * getInstrInfo() const
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
TargetInstrInfo - Interface to description of machine instruction set.
bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
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")
void setMBB(MachineBasicBlock *MBB)
Represent the analysis usage information of a pass.
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
FunctionPass class - This class is used to implement most global optimizations.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
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...
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.
Target - Wrapper for Target specific information.
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringRef > StandardNames)
Initialize the set of available library functions based on the specified target triple.
static void clear(coro::Shape &Shape)
const MachineBasicBlock * getParent() const
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.
INITIALIZE_PASS_BEGIN(PPCBranchCoalescing, DEBUG_TYPE, "Branch Coalescing", false, false) INITIALIZE_PASS_END(PPCBranchCoalescing
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.
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
const MachineOperand & getOperand(unsigned i) const
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...