1*9880d681SAndroid Build Coastguard Worker //===-- OptimizePHIs.cpp - Optimize machine instruction PHIs --------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This pass optimizes machine instruction PHIs to take advantage of
11*9880d681SAndroid Build Coastguard Worker // opportunities created during DAG legalization.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "phi-opt"
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
29*9880d681SAndroid Build Coastguard Worker STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles");
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker namespace {
32*9880d681SAndroid Build Coastguard Worker class OptimizePHIs : public MachineFunctionPass {
33*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo *MRI;
34*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII;
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker public:
37*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identification
OptimizePHIs()38*9880d681SAndroid Build Coastguard Worker OptimizePHIs() : MachineFunctionPass(ID) {
39*9880d681SAndroid Build Coastguard Worker initializeOptimizePHIsPass(*PassRegistry::getPassRegistry());
40*9880d681SAndroid Build Coastguard Worker }
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &MF) override;
43*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const44*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
45*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG();
46*9880d681SAndroid Build Coastguard Worker MachineFunctionPass::getAnalysisUsage(AU);
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker private:
50*9880d681SAndroid Build Coastguard Worker typedef SmallPtrSet<MachineInstr*, 16> InstrSet;
51*9880d681SAndroid Build Coastguard Worker typedef SmallPtrSetIterator<MachineInstr*> InstrSetIterator;
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg,
54*9880d681SAndroid Build Coastguard Worker InstrSet &PHIsInCycle);
55*9880d681SAndroid Build Coastguard Worker bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle);
56*9880d681SAndroid Build Coastguard Worker bool OptimizeBB(MachineBasicBlock &MBB);
57*9880d681SAndroid Build Coastguard Worker };
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker char OptimizePHIs::ID = 0;
61*9880d681SAndroid Build Coastguard Worker char &llvm::OptimizePHIsID = OptimizePHIs::ID;
62*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(OptimizePHIs, "opt-phis",
63*9880d681SAndroid Build Coastguard Worker "Optimize machine instruction PHIs", false, false)
64*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & Fn)65*9880d681SAndroid Build Coastguard Worker bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
66*9880d681SAndroid Build Coastguard Worker if (skipFunction(*Fn.getFunction()))
67*9880d681SAndroid Build Coastguard Worker return false;
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker MRI = &Fn.getRegInfo();
70*9880d681SAndroid Build Coastguard Worker TII = Fn.getSubtarget().getInstrInfo();
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker // Find dead PHI cycles and PHI cycles that can be replaced by a single
73*9880d681SAndroid Build Coastguard Worker // value. InstCombine does these optimizations, but DAG legalization may
74*9880d681SAndroid Build Coastguard Worker // introduce new opportunities, e.g., when i64 values are split up for
75*9880d681SAndroid Build Coastguard Worker // 32-bit targets.
76*9880d681SAndroid Build Coastguard Worker bool Changed = false;
77*9880d681SAndroid Build Coastguard Worker for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
78*9880d681SAndroid Build Coastguard Worker Changed |= OptimizeBB(*I);
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker return Changed;
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker /// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands
84*9880d681SAndroid Build Coastguard Worker /// are copies of SingleValReg, possibly via copies through other PHIs. If
85*9880d681SAndroid Build Coastguard Worker /// SingleValReg is zero on entry, it is set to the register with the single
86*9880d681SAndroid Build Coastguard Worker /// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that
87*9880d681SAndroid Build Coastguard Worker /// have been scanned.
IsSingleValuePHICycle(MachineInstr * MI,unsigned & SingleValReg,InstrSet & PHIsInCycle)88*9880d681SAndroid Build Coastguard Worker bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI,
89*9880d681SAndroid Build Coastguard Worker unsigned &SingleValReg,
90*9880d681SAndroid Build Coastguard Worker InstrSet &PHIsInCycle) {
91*9880d681SAndroid Build Coastguard Worker assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction");
92*9880d681SAndroid Build Coastguard Worker unsigned DstReg = MI->getOperand(0).getReg();
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker // See if we already saw this register.
95*9880d681SAndroid Build Coastguard Worker if (!PHIsInCycle.insert(MI).second)
96*9880d681SAndroid Build Coastguard Worker return true;
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker // Don't scan crazily complex things.
99*9880d681SAndroid Build Coastguard Worker if (PHIsInCycle.size() == 16)
100*9880d681SAndroid Build Coastguard Worker return false;
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker // Scan the PHI operands.
103*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1; i != MI->getNumOperands(); i += 2) {
104*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = MI->getOperand(i).getReg();
105*9880d681SAndroid Build Coastguard Worker if (SrcReg == DstReg)
106*9880d681SAndroid Build Coastguard Worker continue;
107*9880d681SAndroid Build Coastguard Worker MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker // Skip over register-to-register moves.
110*9880d681SAndroid Build Coastguard Worker if (SrcMI && SrcMI->isCopy() &&
111*9880d681SAndroid Build Coastguard Worker !SrcMI->getOperand(0).getSubReg() &&
112*9880d681SAndroid Build Coastguard Worker !SrcMI->getOperand(1).getSubReg() &&
113*9880d681SAndroid Build Coastguard Worker TargetRegisterInfo::isVirtualRegister(SrcMI->getOperand(1).getReg()))
114*9880d681SAndroid Build Coastguard Worker SrcMI = MRI->getVRegDef(SrcMI->getOperand(1).getReg());
115*9880d681SAndroid Build Coastguard Worker if (!SrcMI)
116*9880d681SAndroid Build Coastguard Worker return false;
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker if (SrcMI->isPHI()) {
119*9880d681SAndroid Build Coastguard Worker if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle))
120*9880d681SAndroid Build Coastguard Worker return false;
121*9880d681SAndroid Build Coastguard Worker } else {
122*9880d681SAndroid Build Coastguard Worker // Fail if there is more than one non-phi/non-move register.
123*9880d681SAndroid Build Coastguard Worker if (SingleValReg != 0)
124*9880d681SAndroid Build Coastguard Worker return false;
125*9880d681SAndroid Build Coastguard Worker SingleValReg = SrcReg;
126*9880d681SAndroid Build Coastguard Worker }
127*9880d681SAndroid Build Coastguard Worker }
128*9880d681SAndroid Build Coastguard Worker return true;
129*9880d681SAndroid Build Coastguard Worker }
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker /// IsDeadPHICycle - Check if the register defined by a PHI is only used by
132*9880d681SAndroid Build Coastguard Worker /// other PHIs in a cycle.
IsDeadPHICycle(MachineInstr * MI,InstrSet & PHIsInCycle)133*9880d681SAndroid Build Coastguard Worker bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) {
134*9880d681SAndroid Build Coastguard Worker assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction");
135*9880d681SAndroid Build Coastguard Worker unsigned DstReg = MI->getOperand(0).getReg();
136*9880d681SAndroid Build Coastguard Worker assert(TargetRegisterInfo::isVirtualRegister(DstReg) &&
137*9880d681SAndroid Build Coastguard Worker "PHI destination is not a virtual register");
138*9880d681SAndroid Build Coastguard Worker
139*9880d681SAndroid Build Coastguard Worker // See if we already saw this register.
140*9880d681SAndroid Build Coastguard Worker if (!PHIsInCycle.insert(MI).second)
141*9880d681SAndroid Build Coastguard Worker return true;
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker // Don't scan crazily complex things.
144*9880d681SAndroid Build Coastguard Worker if (PHIsInCycle.size() == 16)
145*9880d681SAndroid Build Coastguard Worker return false;
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker for (MachineInstr &UseMI : MRI->use_instructions(DstReg)) {
148*9880d681SAndroid Build Coastguard Worker if (!UseMI.isPHI() || !IsDeadPHICycle(&UseMI, PHIsInCycle))
149*9880d681SAndroid Build Coastguard Worker return false;
150*9880d681SAndroid Build Coastguard Worker }
151*9880d681SAndroid Build Coastguard Worker
152*9880d681SAndroid Build Coastguard Worker return true;
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker /// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by
156*9880d681SAndroid Build Coastguard Worker /// a single value.
OptimizeBB(MachineBasicBlock & MBB)157*9880d681SAndroid Build Coastguard Worker bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) {
158*9880d681SAndroid Build Coastguard Worker bool Changed = false;
159*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator
160*9880d681SAndroid Build Coastguard Worker MII = MBB.begin(), E = MBB.end(); MII != E; ) {
161*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = &*MII++;
162*9880d681SAndroid Build Coastguard Worker if (!MI->isPHI())
163*9880d681SAndroid Build Coastguard Worker break;
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker // Check for single-value PHI cycles.
166*9880d681SAndroid Build Coastguard Worker unsigned SingleValReg = 0;
167*9880d681SAndroid Build Coastguard Worker InstrSet PHIsInCycle;
168*9880d681SAndroid Build Coastguard Worker if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) &&
169*9880d681SAndroid Build Coastguard Worker SingleValReg != 0) {
170*9880d681SAndroid Build Coastguard Worker unsigned OldReg = MI->getOperand(0).getReg();
171*9880d681SAndroid Build Coastguard Worker if (!MRI->constrainRegClass(SingleValReg, MRI->getRegClass(OldReg)))
172*9880d681SAndroid Build Coastguard Worker continue;
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker MRI->replaceRegWith(OldReg, SingleValReg);
175*9880d681SAndroid Build Coastguard Worker MI->eraseFromParent();
176*9880d681SAndroid Build Coastguard Worker ++NumPHICycles;
177*9880d681SAndroid Build Coastguard Worker Changed = true;
178*9880d681SAndroid Build Coastguard Worker continue;
179*9880d681SAndroid Build Coastguard Worker }
180*9880d681SAndroid Build Coastguard Worker
181*9880d681SAndroid Build Coastguard Worker // Check for dead PHI cycles.
182*9880d681SAndroid Build Coastguard Worker PHIsInCycle.clear();
183*9880d681SAndroid Build Coastguard Worker if (IsDeadPHICycle(MI, PHIsInCycle)) {
184*9880d681SAndroid Build Coastguard Worker for (InstrSetIterator PI = PHIsInCycle.begin(), PE = PHIsInCycle.end();
185*9880d681SAndroid Build Coastguard Worker PI != PE; ++PI) {
186*9880d681SAndroid Build Coastguard Worker MachineInstr *PhiMI = *PI;
187*9880d681SAndroid Build Coastguard Worker if (&*MII == PhiMI)
188*9880d681SAndroid Build Coastguard Worker ++MII;
189*9880d681SAndroid Build Coastguard Worker PhiMI->eraseFromParent();
190*9880d681SAndroid Build Coastguard Worker }
191*9880d681SAndroid Build Coastguard Worker ++NumDeadPHICycles;
192*9880d681SAndroid Build Coastguard Worker Changed = true;
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker return Changed;
196*9880d681SAndroid Build Coastguard Worker }
197