blob: 55da0a295aaca522c2e29d55566f3d843da8180f [file] [log] [blame]
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +00001//===--------- PPCPreEmitPeephole.cpp - Late peephole optimizations -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// A pre-emit peephole for catching opportunities introduced by late passes such
11// as MachineBlockPlacement.
12//
13//===----------------------------------------------------------------------===//
14
15#include "PPC.h"
16#include "PPCInstrInfo.h"
17#include "PPCSubtarget.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/Statistic.h"
20#include "llvm/CodeGen/LivePhysRegs.h"
Hiroshi Inoue20982f02018-09-26 12:32:45 +000021#include "llvm/CodeGen/MachineBasicBlock.h"
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +000022#include "llvm/CodeGen/MachineFunctionPass.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/Support/CommandLine.h"
26#include "llvm/ADT/Statistic.h"
27#include "llvm/Support/Debug.h"
28
29using namespace llvm;
30
31#define DEBUG_TYPE "ppc-pre-emit-peephole"
32
33STATISTIC(NumRRConvertedInPreEmit,
34 "Number of r+r instructions converted to r+i in pre-emit peephole");
35STATISTIC(NumRemovedInPreEmit,
36 "Number of instructions deleted in pre-emit peephole");
37
38static cl::opt<bool>
Nemanja Ivanovic4e1f5e02017-12-29 12:22:27 +000039RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true),
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +000040 cl::desc("Run pre-emit peephole optimizations."));
41
42namespace {
43 class PPCPreEmitPeephole : public MachineFunctionPass {
44 public:
45 static char ID;
46 PPCPreEmitPeephole() : MachineFunctionPass(ID) {
47 initializePPCPreEmitPeepholePass(*PassRegistry::getPassRegistry());
48 }
49
50 void getAnalysisUsage(AnalysisUsage &AU) const override {
51 MachineFunctionPass::getAnalysisUsage(AU);
52 }
53
54 MachineFunctionProperties getRequiredProperties() const override {
55 return MachineFunctionProperties().set(
56 MachineFunctionProperties::Property::NoVRegs);
57 }
58
59 bool runOnMachineFunction(MachineFunction &MF) override {
Matthias Braunf1caa282017-12-15 22:22:58 +000060 if (skipFunction(MF.getFunction()) || !RunPreEmitPeephole)
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +000061 return false;
62 bool Changed = false;
63 const PPCInstrInfo *TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo();
Hiroshi Inoue20982f02018-09-26 12:32:45 +000064 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +000065 SmallVector<MachineInstr *, 4> InstrsToErase;
66 for (MachineBasicBlock &MBB : MF) {
67 for (MachineInstr &MI : MBB) {
68 MachineInstr *DefMIToErase = nullptr;
69 if (TII->convertToImmediateForm(MI, &DefMIToErase)) {
70 Changed = true;
71 NumRRConvertedInPreEmit++;
Nicola Zaghend34e60c2018-05-14 12:53:11 +000072 LLVM_DEBUG(dbgs() << "Converted instruction to imm form: ");
73 LLVM_DEBUG(MI.dump());
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +000074 if (DefMIToErase) {
75 InstrsToErase.push_back(DefMIToErase);
76 }
77 }
78 }
Hiroshi Inoue20982f02018-09-26 12:32:45 +000079
80 // Eliminate conditional branch based on a constant CR bit by
81 // CRSET or CRUNSET. We eliminate the conditional branch or
82 // convert it into an unconditional branch. Also, if the CR bit
83 // is not used by other instructions, we eliminate CRSET as well.
84 auto I = MBB.getFirstInstrTerminator();
85 if (I == MBB.instr_end())
86 continue;
87 MachineInstr *Br = &*I;
88 if (Br->getOpcode() != PPC::BC && Br->getOpcode() != PPC::BCn)
89 continue;
90 MachineInstr *CRSetMI = nullptr;
91 unsigned CRBit = Br->getOperand(0).getReg();
92 unsigned CRReg = getCRFromCRBit(CRBit);
93 bool SeenUse = false;
94 MachineBasicBlock::reverse_iterator It = Br, Er = MBB.rend();
95 for (It++; It != Er; It++) {
96 if (It->modifiesRegister(CRBit, TRI)) {
97 if ((It->getOpcode() == PPC::CRUNSET ||
98 It->getOpcode() == PPC::CRSET) &&
99 It->getOperand(0).getReg() == CRBit)
100 CRSetMI = &*It;
101 break;
102 }
103 if (It->readsRegister(CRBit, TRI))
104 SeenUse = true;
105 }
106 if (!CRSetMI) continue;
107
108 unsigned CRSetOp = CRSetMI->getOpcode();
109 if ((Br->getOpcode() == PPC::BCn && CRSetOp == PPC::CRSET) ||
110 (Br->getOpcode() == PPC::BC && CRSetOp == PPC::CRUNSET)) {
111 // Remove this branch since it cannot be taken.
112 InstrsToErase.push_back(Br);
113 MBB.removeSuccessor(Br->getOperand(1).getMBB());
114 }
115 else {
116 // This conditional branch is always taken. So, remove all branches
117 // and insert an unconditional branch to the destination of this.
118 MachineBasicBlock::iterator It = Br, Er = MBB.end();
119 for (; It != Er && !SeenUse; It++) {
120 if (It->isDebugInstr()) continue;
121 assert(It->isTerminator() && "Non-terminator after a terminator");
122 InstrsToErase.push_back(&*It);
123 }
124 if (!MBB.isLayoutSuccessor(Br->getOperand(1).getMBB())) {
125 ArrayRef<MachineOperand> NoCond;
126 TII->insertBranch(MBB, Br->getOperand(1).getMBB(), nullptr,
127 NoCond, Br->getDebugLoc());
128 }
129 for (auto &Succ : MBB.successors())
130 if (Succ != Br->getOperand(1).getMBB()) {
131 MBB.removeSuccessor(Succ);
132 break;
133 }
134 }
135
136 // If the CRBit is not used by another instruction, we can eliminate
137 // CRSET/CRUNSET instruction.
138 if (!SeenUse) {
139 // We need to check use of the CRBit in successors.
140 for (auto &SuccMBB : MBB.successors())
141 if (SuccMBB->isLiveIn(CRBit) || SuccMBB->isLiveIn(CRReg)) {
142 SeenUse = true;
143 break;
144 }
145 if (!SeenUse)
146 InstrsToErase.push_back(CRSetMI);
147 }
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +0000148 }
149 for (MachineInstr *MI : InstrsToErase) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000150 LLVM_DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: ");
151 LLVM_DEBUG(MI->dump());
Nemanja Ivanovic6995e5d2017-12-15 07:27:53 +0000152 MI->eraseFromParent();
153 NumRemovedInPreEmit++;
154 }
155 return Changed;
156 }
157 };
158}
159
160INITIALIZE_PASS(PPCPreEmitPeephole, DEBUG_TYPE, "PowerPC Pre-Emit Peephole",
161 false, false)
162char PPCPreEmitPeephole::ID = 0;
163
164FunctionPass *llvm::createPPCPreEmitPeepholePass() {
165 return new PPCPreEmitPeephole();
166}