-
Notifications
You must be signed in to change notification settings - Fork 12.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PowerPC] MachineSSA pass to reduce the number of CR-logical operations
The initial implementation of an MI SSA pass to reduce cr-logical operations. Currently, the only operations handled by the pass are binary operations where both CR-inputs come from the same block and the single use is a conditional branch (also in the same block). Committing this off by default to allow for a period of field testing. Will enable it by default in a follow-up patch soon. Differential Revision: https://reviews.llvm.org/D30431 llvm-svn: 320584
- Loading branch information
Showing
8 changed files
with
952 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| //==-- PPCMachineBasicBlockUtils.h - Functions for common MBB operations ---==// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file defines utility functions for commonly used operations on | ||
| // MachineBasicBlock's. | ||
| // NOTE: Include this file after defining DEBUG_TYPE so that the debug messages | ||
| // can be emitted for the pass that is using this. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIB_TARGET_PPC_MACHINE_BASIC_BLOCK_UTILS_H | ||
| #define LLVM_LIB_TARGET_PPC_MACHINE_BASIC_BLOCK_UTILS_H | ||
|
|
||
| #include "PPCInstrInfo.h" | ||
| #include "llvm/CodeGen/MachineInstrBuilder.h" | ||
| #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" | ||
| #include "llvm/CodeGen/MachineRegisterInfo.h" | ||
|
|
||
| #ifndef DEBUG_TYPE | ||
| #define DEBUG_TYPE "ppc-generic-mbb-utilities" | ||
| #endif | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| /// Given a basic block \p Successor that potentially contains PHIs, this | ||
| /// function will look for any incoming values in the PHIs that are supposed to | ||
| /// be coming from \p OrigMBB but whose definition is actually in \p NewMBB. | ||
| /// Any such PHIs will be updated to reflect reality. | ||
| static void updatePHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB, | ||
| MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI) { | ||
| for (auto &MI : Successor->instrs()) { | ||
| if (!MI.isPHI()) | ||
| continue; | ||
| // This is a really ugly-looking loop, but it was pillaged directly from | ||
| // MachineBasicBlock::transferSuccessorsAndUpdatePHIs(). | ||
| for (unsigned i = 2, e = MI.getNumOperands()+1; i != e; i += 2) { | ||
| MachineOperand &MO = MI.getOperand(i); | ||
| if (MO.getMBB() == OrigMBB) { | ||
| // Check if the instruction is actualy defined in NewMBB. | ||
| if (MI.getOperand(i-1).isReg()) { | ||
| MachineInstr *DefMI = MRI->getVRegDef(MI.getOperand(i-1).getReg()); | ||
| if (DefMI->getParent() == NewMBB || !OrigMBB->isSuccessor(Successor)) { | ||
| MO.setMBB(NewMBB); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Given a basic block \p Successor that potentially contains PHIs, this | ||
| /// function will look for PHIs that have an incoming value from \p OrigMBB | ||
| /// and will add the same incoming value from \p NewMBB. | ||
| /// NOTE: This should only be used if \p NewMBB is an immediate dominator of | ||
| /// \p OrigMBB. | ||
| static void addIncomingValuesToPHIs(MachineBasicBlock *Successor, | ||
| MachineBasicBlock *OrigMBB, | ||
| MachineBasicBlock *NewMBB, | ||
| MachineRegisterInfo *MRI) { | ||
| assert(OrigMBB->isSuccessor(NewMBB) && "NewMBB must be a sucessor of OrigMBB"); | ||
| for (auto &MI : Successor->instrs()) { | ||
| if (!MI.isPHI()) | ||
| continue; | ||
| // This is a really ugly-looking loop, but it was pillaged directly from | ||
| // MachineBasicBlock::transferSuccessorsAndUpdatePHIs(). | ||
| for (unsigned i = 2, e = MI.getNumOperands()+1; i != e; i += 2) { | ||
| MachineOperand &MO = MI.getOperand(i); | ||
| if (MO.getMBB() == OrigMBB) { | ||
| MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI); | ||
| MIB.addReg(MI.getOperand(i-1).getReg()).addMBB(NewMBB); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| struct BlockSplitInfo { | ||
| MachineInstr *OrigBranch; | ||
| MachineInstr *SplitBefore; | ||
| MachineInstr *SplitCond; | ||
| bool InvertNewBranch; | ||
| bool InvertOrigBranch; | ||
| bool BranchToFallThrough; | ||
| const MachineBranchProbabilityInfo *MBPI; | ||
| MachineInstr *MIToDelete; | ||
| MachineInstr *NewCond; | ||
| bool allInstrsInSameMBB() { | ||
| if (!OrigBranch || !SplitBefore || !SplitCond) | ||
| return false; | ||
| MachineBasicBlock *MBB = OrigBranch->getParent(); | ||
| if (SplitBefore->getParent() != MBB || | ||
| SplitCond->getParent() != MBB) | ||
| return false; | ||
| if (MIToDelete && MIToDelete->getParent() != MBB) | ||
| return false; | ||
| if (NewCond && NewCond->getParent() != MBB) | ||
| return false; | ||
| return true; | ||
| } | ||
| }; | ||
|
|
||
| /// Splits a MachineBasicBlock to branch before \p SplitBefore. The original | ||
| /// branch is \p OrigBranch. The target of the new branch can either be the same | ||
| /// as the target of the original branch or the fallthrough successor of the | ||
| /// original block as determined by \p BranchToFallThrough. The branch | ||
| /// conditions will be inverted according to \p InvertNewBranch and | ||
| /// \p InvertOrigBranch. If an instruction that previously fed the branch is to | ||
| /// be deleted, it is provided in \p MIToDelete and \p NewCond will be used as | ||
| /// the branch condition. The branch probabilities will be set if the | ||
| /// MachineBranchProbabilityInfo isn't null. | ||
| static bool splitMBB(BlockSplitInfo &BSI) { | ||
| assert(BSI.allInstrsInSameMBB() && | ||
| "All instructions must be in the same block."); | ||
|
|
||
| MachineBasicBlock *ThisMBB = BSI.OrigBranch->getParent(); | ||
| MachineFunction *MF = ThisMBB->getParent(); | ||
| MachineRegisterInfo *MRI = &MF->getRegInfo(); | ||
| assert(MRI->isSSA() && "Can only do this while the function is in SSA form."); | ||
| if (ThisMBB->succ_size() != 2) { | ||
| DEBUG(dbgs() << "Don't know how to handle blocks that don't have exactly" | ||
| << " two succesors.\n"); | ||
| return false; | ||
| } | ||
|
|
||
| const PPCInstrInfo *TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo(); | ||
| unsigned OrigBROpcode = BSI.OrigBranch->getOpcode(); | ||
| unsigned InvertedOpcode = | ||
| OrigBROpcode == PPC::BC ? PPC::BCn : | ||
| OrigBROpcode == PPC::BCn ? PPC::BC : | ||
| OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR; | ||
| unsigned NewBROpcode = BSI.InvertNewBranch ? InvertedOpcode : OrigBROpcode; | ||
| MachineBasicBlock *OrigTarget = BSI.OrigBranch->getOperand(1).getMBB(); | ||
| MachineBasicBlock *OrigFallThrough = | ||
| OrigTarget == *ThisMBB->succ_begin() ? *ThisMBB->succ_rbegin() : | ||
| *ThisMBB->succ_begin(); | ||
| MachineBasicBlock *NewBRTarget = | ||
| BSI.BranchToFallThrough ? OrigFallThrough : OrigTarget; | ||
| BranchProbability ProbToNewTarget = | ||
| !BSI.MBPI ? BranchProbability::getUnknown() : | ||
| BSI.MBPI->getEdgeProbability(ThisMBB, NewBRTarget); | ||
|
|
||
| // Create a new basic block. | ||
| MachineBasicBlock::iterator InsertPoint = BSI.SplitBefore; | ||
| const BasicBlock *LLVM_BB = ThisMBB->getBasicBlock(); | ||
| MachineFunction::iterator It = ThisMBB->getIterator(); | ||
| MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(LLVM_BB); | ||
| MF->insert(++It, NewMBB); | ||
|
|
||
| // Move everything after SplitBefore into the new block. | ||
| NewMBB->splice(NewMBB->end(), ThisMBB, InsertPoint, ThisMBB->end()); | ||
| NewMBB->transferSuccessors(ThisMBB); | ||
|
|
||
| // Add the two successors to ThisMBB. The probabilities come from the | ||
| // existing blocks if available. | ||
| ThisMBB->addSuccessor(NewBRTarget, ProbToNewTarget); | ||
| ThisMBB->addSuccessor(NewMBB, ProbToNewTarget.getCompl()); | ||
|
|
||
| // Add the branches to ThisMBB. | ||
| BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(), | ||
| TII->get(NewBROpcode)).addReg(BSI.SplitCond->getOperand(0).getReg()) | ||
| .addMBB(NewBRTarget); | ||
| BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(), | ||
| TII->get(PPC::B)).addMBB(NewMBB); | ||
| if (BSI.MIToDelete) | ||
| BSI.MIToDelete->eraseFromParent(); | ||
|
|
||
| // Change the condition on the original branch and invert it if requested. | ||
| auto FirstTerminator = NewMBB->getFirstTerminator(); | ||
| if (BSI.NewCond) { | ||
| assert(FirstTerminator->getOperand(0).isReg() && | ||
| "Can't update condition of unconditional branch."); | ||
| FirstTerminator->getOperand(0).setReg(BSI.NewCond->getOperand(0).getReg()); | ||
| } | ||
| if (BSI.InvertOrigBranch) | ||
| FirstTerminator->setDesc(TII->get(InvertedOpcode)); | ||
|
|
||
| // If any of the PHIs in the successors of NewMBB reference values that | ||
| // now come from NewMBB, they need to be updated. | ||
| for (auto *Succ : NewMBB->successors()) { | ||
| updatePHIs(Succ, ThisMBB, NewMBB, MRI); | ||
| } | ||
| addIncomingValuesToPHIs(NewBRTarget, ThisMBB, NewMBB, MRI); | ||
|
|
||
| DEBUG(dbgs() << "After splitting, ThisMBB:\n"; ThisMBB->dump()); | ||
| DEBUG(dbgs() << "NewMBB:\n"; NewMBB->dump()); | ||
| DEBUG(dbgs() << "New branch-to block:\n"; NewBRTarget->dump()); | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| #endif |
Oops, something went wrong.