30#define DEBUG_TYPE "ppc-branch-coalescing"
32STATISTIC(NumBlocksCoalesced,
"Number of blocks coalesced");
33STATISTIC(NumPHINotMoved,
"Number of PHI Nodes that cannot be merged");
34STATISTIC(NumBlocksNotCoalesced,
"Number of blocks not coalesced");
136 struct CoalescingCandidateInfo {
144 CoalescingCandidateInfo();
148 MachineDominatorTree *MDT;
149 MachinePostDominatorTree *MPDT;
150 const TargetInstrInfo *TII;
151 MachineRegisterInfo *MRI;
154 bool canCoalesceBranch(CoalescingCandidateInfo &Cand);
157 bool validateCandidates(CoalescingCandidateInfo &SourceRegion,
158 CoalescingCandidateInfo &TargetRegion)
const;
163 PPCBranchCoalescing() : MachineFunctionPass(ID) {}
165 void getAnalysisUsage(AnalysisUsage &AU)
const override {
167 AU.
addRequired<MachinePostDominatorTreeWrapperPass>();
171 StringRef getPassName()
const override {
return "Branch Coalescing"; }
173 bool mergeCandidates(CoalescingCandidateInfo &SourceRegion,
174 CoalescingCandidateInfo &TargetRegion);
175 bool canMoveToBeginning(
const MachineInstr &
MI,
176 const MachineBasicBlock &
MBB)
const;
177 bool canMoveToEnd(
const MachineInstr &
MI,
178 const MachineBasicBlock &
MBB)
const;
179 bool canMerge(CoalescingCandidateInfo &SourceRegion,
180 CoalescingCandidateInfo &TargetRegion)
const;
181 void moveAndUpdatePHIs(MachineBasicBlock *SourceRegionMBB,
182 MachineBasicBlock *TargetRegionMBB);
183 bool runOnMachineFunction(MachineFunction &MF)
override;
187char PPCBranchCoalescing::ID = 0;
191 return new PPCBranchCoalescing();
195 "Branch Coalescing",
false,
false)
201PPCBranchCoalescing::CoalescingCandidateInfo::CoalescingCandidateInfo()
202 : BranchBlock(
nullptr), BranchTargetBlock(
nullptr),
203 FallThroughBlock(
nullptr), MustMoveDown(
false), MustMoveUp(
false) {}
205void PPCBranchCoalescing::CoalescingCandidateInfo::clear() {
206 BranchBlock =
nullptr;
207 BranchTargetBlock =
nullptr;
208 FallThroughBlock =
nullptr;
210 MustMoveDown =
false;
214void PPCBranchCoalescing::initialize(MachineFunction &MF) {
215 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
216 MPDT = &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
231bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) {
233 << Cand.BranchBlock->getNumber() <<
" can be coalesced:");
234 MachineBasicBlock *FalseMBB =
nullptr;
242 for (
auto &
I : Cand.BranchBlock->terminators()) {
260 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
261 LLVM_DEBUG(
dbgs() <<
"Terminator contains implicit operands - skip : "
267 if (Cand.BranchBlock->isEHPad() || Cand.BranchBlock->hasEHPadSuccessor()) {
272 if (Cand.BranchBlock->mayHaveInlineAsmBr()) {
279 if (!Cand.BranchTargetBlock || FalseMBB ||
280 !Cand.BranchBlock->isSuccessor(Cand.BranchTargetBlock)) {
286 if (Cand.BranchBlock->succ_size() != 2) {
292 assert(Cand.BranchBlock->canFallThrough() &&
293 "Expecting the block to fall through!");
298 MachineBasicBlock *Succ =
299 (*Cand.BranchBlock->succ_begin() == Cand.BranchTargetBlock)
300 ? *Cand.BranchBlock->succ_rbegin()
301 : *Cand.BranchBlock->succ_begin();
303 assert(Succ &&
"Expecting a valid fall-through block\n");
305 if (!Succ->
empty()) {
306 LLVM_DEBUG(
dbgs() <<
"Fall-through block contains code -- skip\n");
313 <<
"Successor of fall through block is not branch taken block\n");
317 Cand.FallThroughBlock = Succ;
329bool PPCBranchCoalescing::identicalOperands(
332 if (OpList1.
size() != OpList2.
size()) {
337 for (
unsigned i = 0; i < OpList1.
size(); ++i) {
338 const MachineOperand &Op1 = OpList1[i];
339 const MachineOperand &Op2 = OpList2[i];
342 <<
"Op2: " << Op2 <<
"\n");
350 LLVM_DEBUG(
dbgs() <<
"The operands are not provably identical.\n");
362 MachineInstr *Op1Def =
MRI->getVRegDef(Op1.
getReg());
363 MachineInstr *Op2Def =
MRI->getVRegDef(Op2.
getReg());
364 if (
TII->produceSameValue(*Op1Def, *Op2Def,
MRI)) {
366 <<
" produce the same value!\n");
372 LLVM_DEBUG(
dbgs() <<
"The operands are not provably identical.\n");
389void PPCBranchCoalescing::moveAndUpdatePHIs(MachineBasicBlock *SourceMBB,
390 MachineBasicBlock *TargetMBB) {
396 LLVM_DEBUG(
dbgs() <<
"SourceMBB contains no PHI instructions.\n");
402 MachineInstr &PHIInst = *Iter;
403 for (
unsigned i = 2, e = PHIInst.
getNumOperands() + 1; i != e; i += 2) {
405 if (MO.
getMBB() == SourceMBB)
422bool PPCBranchCoalescing::canMoveToBeginning(
const MachineInstr &
MI,
423 const MachineBasicBlock &TargetMBB
429 for (
auto &Def :
MI.defs()) {
430 for (
auto &Use :
MRI->use_instructions(
Def.getReg())) {
431 if (
Use.isPHI() &&
Use.getParent() == &TargetMBB) {
453bool PPCBranchCoalescing::canMoveToEnd(
const MachineInstr &
MI,
454 const MachineBasicBlock &TargetMBB
460 for (
auto &Use :
MI.uses()) {
461 if (
Use.isReg() &&
Use.getReg().isVirtual()) {
462 MachineInstr *DefInst =
MRI->getVRegDef(
Use.getReg());
468 dbgs() <<
" *** def is in another block -- safe to move!\n");
486bool PPCBranchCoalescing::validateCandidates(
487 CoalescingCandidateInfo &SourceRegion,
488 CoalescingCandidateInfo &TargetRegion)
const {
490 if (TargetRegion.BranchTargetBlock != SourceRegion.BranchBlock)
491 llvm_unreachable(
"Expecting SourceRegion to immediately follow TargetRegion");
492 else if (!MDT->
dominates(TargetRegion.BranchBlock, SourceRegion.BranchBlock))
494 else if (!MPDT->
dominates(SourceRegion.BranchBlock, TargetRegion.BranchBlock))
496 else if (!TargetRegion.FallThroughBlock->empty() ||
497 !SourceRegion.FallThroughBlock->empty())
529bool PPCBranchCoalescing::canMerge(CoalescingCandidateInfo &SourceRegion,
530 CoalescingCandidateInfo &TargetRegion)
const {
531 if (!validateCandidates(SourceRegion, TargetRegion))
537 I = SourceRegion.BranchBlock->instr_begin(),
538 E = SourceRegion.BranchBlock->getFirstNonPHI();
540 for (
auto &Def :
I->defs())
541 for (
auto &Use :
MRI->use_instructions(
Def.getReg())) {
542 if (
Use.isPHI() &&
Use.getParent() == SourceRegion.BranchTargetBlock) {
545 <<
" defines register used in another "
546 "PHI within branch target block -- can't merge\n");
550 if (
Use.getParent() == SourceRegion.BranchBlock) {
552 <<
" defines register used in this "
553 "block -- all must move down\n");
554 SourceRegion.MustMoveDown =
true;
562 I = SourceRegion.BranchBlock->getFirstNonPHI(),
563 E = SourceRegion.BranchBlock->end();
565 if (!canMoveToBeginning(*
I, *SourceRegion.BranchTargetBlock)) {
567 <<
" cannot move down - must move up!\n");
568 SourceRegion.MustMoveUp =
true;
570 if (!canMoveToEnd(*
I, *TargetRegion.BranchBlock)) {
572 <<
" cannot move up - must move down!\n");
573 SourceRegion.MustMoveDown =
true;
577 return (SourceRegion.MustMoveUp && SourceRegion.MustMoveDown) ?
false :
true;
636bool PPCBranchCoalescing::mergeCandidates(CoalescingCandidateInfo &SourceRegion,
637 CoalescingCandidateInfo &TargetRegion) {
639 if (SourceRegion.MustMoveUp && SourceRegion.MustMoveDown) {
644 if (!validateCandidates(SourceRegion, TargetRegion))
649 moveAndUpdatePHIs(SourceRegion.BranchBlock, SourceRegion.BranchTargetBlock);
654 SourceRegion.BranchBlock->getFirstNonPHI();
656 SourceRegion.BranchBlock->getFirstTerminator();
658 MachineBasicBlock *
Source = SourceRegion.MustMoveDown
659 ? SourceRegion.BranchTargetBlock
660 : TargetRegion.BranchBlock;
663 SourceRegion.MustMoveDown
664 ? SourceRegion.BranchTargetBlock->getFirstNonPHI()
665 : TargetRegion.BranchBlock->getFirstTerminator();
667 Source->splice(Target, SourceRegion.BranchBlock, firstInstr, lastInstr);
674 SourceRegion.BranchBlock->removeSuccessor(SourceRegion.FallThroughBlock);
675 TargetRegion.BranchBlock->transferSuccessorsAndUpdatePHIs(
676 SourceRegion.BranchBlock);
680 TargetRegion.BranchBlock->ReplaceUsesOfBlockWith(
681 SourceRegion.BranchBlock, SourceRegion.BranchTargetBlock);
684 SourceRegion.BranchBlock->terminators().begin();
685 while (
I != SourceRegion.BranchBlock->terminators().end()) {
686 MachineInstr &CurrInst = *
I;
694 assert(TargetRegion.FallThroughBlock->empty() &&
695 "FallThroughBlocks should be empty!");
699 TargetRegion.FallThroughBlock->transferSuccessorsAndUpdatePHIs(
700 SourceRegion.FallThroughBlock);
701 TargetRegion.FallThroughBlock->removeSuccessor(SourceRegion.BranchBlock);
702 TargetRegion.FallThroughBlock->normalizeSuccProbs();
705 assert(SourceRegion.BranchBlock->empty() &&
706 "Expecting branch block to be empty!");
707 SourceRegion.BranchBlock->eraseFromParent();
709 assert(SourceRegion.FallThroughBlock->empty() &&
710 "Expecting fall-through block to be empty!\n");
711 SourceRegion.FallThroughBlock->eraseFromParent();
713 NumBlocksCoalesced++;
717bool PPCBranchCoalescing::runOnMachineFunction(MachineFunction &MF) {
722 bool didSomething =
false;
729 CoalescingCandidateInfo Cand1, Cand2;
733 for (MachineBasicBlock &
MBB : MF) {
734 bool MergedCandidates =
false;
736 MergedCandidates =
false;
740 Cand1.BranchBlock = &
MBB;
743 if (!canCoalesceBranch(Cand1))
746 Cand2.BranchBlock = Cand1.BranchTargetBlock;
747 if (!canCoalesceBranch(Cand2))
753 "Branch-taken block should post-dominate first candidate");
755 if (!identicalOperands(Cand1.Cond, Cand2.Cond)) {
757 <<
" and " << Cand2.BranchBlock->getNumber()
758 <<
" have different branches\n");
761 if (!canMerge(Cand2, Cand1)) {
763 << Cand1.BranchBlock->getNumber() <<
" and "
764 << Cand2.BranchBlock->getNumber() <<
"\n");
765 NumBlocksNotCoalesced++;
768 LLVM_DEBUG(
dbgs() <<
"Merging blocks " << Cand1.BranchBlock->getNumber()
769 <<
" and " << Cand1.BranchTargetBlock->getNumber()
771 MergedCandidates = mergeCandidates(Cand2, Cand1);
772 if (MergedCandidates)
777 }
while (MergedCandidates);
783 MF.verify(
nullptr,
"Error in code produced by branch coalescing");
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis false
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
AnalysisUsage & addRequired()
size_t size() const
size - Get the array size.
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
FunctionPass class - This class is used to implement most global optimizations.
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....
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
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 '...
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
bool dominates(const MachineInstr *A, const MachineInstr *B) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void dump() const
dump - Print the current MachineFunction to cerr, useful for debugger use.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
void setMBB(MachineBasicBlock *MBB)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
virtual const TargetInstrInfo * getInstrInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
NodeAddr< DefNode * > Def
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createPPCBranchCoalescingPass()
createPPCBranchCoalescingPass - returns an instance of the Branch Coalescing Pass
ArrayRef(const T &OneElt) -> ArrayRef< T >