xref: /aosp_15_r20/external/llvm/lib/CodeGen/OptimizePHIs.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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