summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorHiroshi Inoue <inouehrs@jp.ibm.com>2018-09-26 12:32:45 +0000
committerHiroshi Inoue <inouehrs@jp.ibm.com>2018-09-26 12:32:45 +0000
commit20982f09956d2630a7d889293a9f4a26c6d2c43e (patch)
tree6fb200edabb49fe08589ae9081b9fc2703d6953e /llvm/lib
parent20b5abe23b33b924a9f1a7ad62f3a9d9e118ebf5 (diff)
downloadbcm5719-llvm-20982f09956d2630a7d889293a9f4a26c6d2c43e.tar.gz
bcm5719-llvm-20982f09956d2630a7d889293a9f4a26c6d2c43e.zip
[PowerPC] optimize conditional branch on CRSET/CRUNSET
This patch adds a check to optimize conditional branch (BC and BCn) based on a constant set by CRSET or CRUNSET. Other optimizers, such as block placement, may generate such code and hence I do this at the very end of the optimization in pre-emit peephole pass. A conditional branch based on a constant is eliminated or converted into unconditional branch. Also CRSET/CRUNSET is eliminated if the condition code register is not used by instruction other than the branch to be optimized. Differential Revision: https://reviews.llvm.org/D52345 llvm-svn: 343100
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp b/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
index 1892d1e3dc2..55da0a295aa 100644
--- a/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LivePhysRegs.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -60,6 +61,7 @@ namespace {
return false;
bool Changed = false;
const PPCInstrInfo *TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo();
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
SmallVector<MachineInstr *, 4> InstrsToErase;
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
@@ -74,6 +76,75 @@ namespace {
}
}
}
+
+ // Eliminate conditional branch based on a constant CR bit by
+ // CRSET or CRUNSET. We eliminate the conditional branch or
+ // convert it into an unconditional branch. Also, if the CR bit
+ // is not used by other instructions, we eliminate CRSET as well.
+ auto I = MBB.getFirstInstrTerminator();
+ if (I == MBB.instr_end())
+ continue;
+ MachineInstr *Br = &*I;
+ if (Br->getOpcode() != PPC::BC && Br->getOpcode() != PPC::BCn)
+ continue;
+ MachineInstr *CRSetMI = nullptr;
+ unsigned CRBit = Br->getOperand(0).getReg();
+ unsigned CRReg = getCRFromCRBit(CRBit);
+ bool SeenUse = false;
+ MachineBasicBlock::reverse_iterator It = Br, Er = MBB.rend();
+ for (It++; It != Er; It++) {
+ if (It->modifiesRegister(CRBit, TRI)) {
+ if ((It->getOpcode() == PPC::CRUNSET ||
+ It->getOpcode() == PPC::CRSET) &&
+ It->getOperand(0).getReg() == CRBit)
+ CRSetMI = &*It;
+ break;
+ }
+ if (It->readsRegister(CRBit, TRI))
+ SeenUse = true;
+ }
+ if (!CRSetMI) continue;
+
+ unsigned CRSetOp = CRSetMI->getOpcode();
+ if ((Br->getOpcode() == PPC::BCn && CRSetOp == PPC::CRSET) ||
+ (Br->getOpcode() == PPC::BC && CRSetOp == PPC::CRUNSET)) {
+ // Remove this branch since it cannot be taken.
+ InstrsToErase.push_back(Br);
+ MBB.removeSuccessor(Br->getOperand(1).getMBB());
+ }
+ else {
+ // This conditional branch is always taken. So, remove all branches
+ // and insert an unconditional branch to the destination of this.
+ MachineBasicBlock::iterator It = Br, Er = MBB.end();
+ for (; It != Er && !SeenUse; It++) {
+ if (It->isDebugInstr()) continue;
+ assert(It->isTerminator() && "Non-terminator after a terminator");
+ InstrsToErase.push_back(&*It);
+ }
+ if (!MBB.isLayoutSuccessor(Br->getOperand(1).getMBB())) {
+ ArrayRef<MachineOperand> NoCond;
+ TII->insertBranch(MBB, Br->getOperand(1).getMBB(), nullptr,
+ NoCond, Br->getDebugLoc());
+ }
+ for (auto &Succ : MBB.successors())
+ if (Succ != Br->getOperand(1).getMBB()) {
+ MBB.removeSuccessor(Succ);
+ break;
+ }
+ }
+
+ // If the CRBit is not used by another instruction, we can eliminate
+ // CRSET/CRUNSET instruction.
+ if (!SeenUse) {
+ // We need to check use of the CRBit in successors.
+ for (auto &SuccMBB : MBB.successors())
+ if (SuccMBB->isLiveIn(CRBit) || SuccMBB->isLiveIn(CRReg)) {
+ SeenUse = true;
+ break;
+ }
+ if (!SeenUse)
+ InstrsToErase.push_back(CRSetMI);
+ }
}
for (MachineInstr *MI : InstrsToErase) {
LLVM_DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: ");
OpenPOWER on IntegriCloud