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();
154 bool canCoalesceBranch(CoalescingCandidateInfo &Cand);
157 bool validateCandidates(CoalescingCandidateInfo &SourceRegion,
158 CoalescingCandidateInfo &TargetRegion)
const;
173 bool mergeCandidates(CoalescingCandidateInfo &SourceRegion,
174 CoalescingCandidateInfo &TargetRegion);
179 bool canMerge(CoalescingCandidateInfo &SourceRegion,
180 CoalescingCandidateInfo &TargetRegion)
const;
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;
215 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
216 MPDT = &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
231bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) {
233 << Cand.BranchBlock->getNumber() <<
" can be coalesced:");
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!");
299 (*Cand.BranchBlock->succ_begin() == Cand.BranchTargetBlock)
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) {
342 <<
"Op2: " << Op2 <<
"\n");
350 LLVM_DEBUG(
dbgs() <<
"The operands are not provably identical.\n");
364 if (
TII->produceSameValue(*Op1Def, *Op2Def,
MRI)) {
366 <<
" produce the same value!\n");
372 LLVM_DEBUG(
dbgs() <<
"The operands are not provably identical.\n");
396 LLVM_DEBUG(
dbgs() <<
"SourceMBB contains no PHI instructions.\n");
403 for (
unsigned i = 2, e = PHIInst.
getNumOperands() + 1; i != e; i += 2) {
405 if (MO.
getMBB() == SourceMBB)
422bool PPCBranchCoalescing::canMoveToBeginning(
const MachineInstr &
MI,
429 for (
auto &Def :
MI.defs()) {
430 for (
auto &
Use :
MRI->use_instructions(
Def.getReg())) {
431 if (
Use.isPHI() &&
Use.getParent() == &TargetMBB) {
460 for (
auto &
Use :
MI.uses()) {
461 if (
Use.isReg() &&
Use.getReg().isVirtual()) {
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();
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()) {
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++;
722 bool didSomething =
false;
729 CoalescingCandidateInfo Cand1, Cand2;
734 bool MergedCandidates =
false;
736 MergedCandidates =
false;
740 Cand1.BranchBlock = &
MBB;
743 if (!canCoalesceBranch(Cand1))
746 Cand2.BranchBlock = Cand1.BranchTargetBlock;
747 if (!canCoalesceBranch(Cand2))
752 assert(MPDT->dominates(Cand2.BranchTargetBlock, Cand1.BranchBlock) &&
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!")
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.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
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.
succ_reverse_iterator succ_rbegin()
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 '...
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
Representation of each machine instruction.
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
MachineOperand class - Representation of each machine instruction operand.
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 ...
MachinePostDominatorTree - an analysis pass wrapper for DominatorTree used to compute the post-domina...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
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.
StringRef - Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetInstrInfo * getInstrInfo() const
Target - Wrapper for Target specific information.
A Use represents the edge between a Value definition and its users.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
NodeAddr< DefNode * > Def
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