12cab237bSDimitry Andric //===- OptimizePHIs.cpp - Optimize machine instruction PHIs ---------------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This pass optimizes machine instruction PHIs to take advantage of
11f22ef01cSRoman Divacky // opportunities created during DAG legalization.
12f22ef01cSRoman Divacky //
13f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
14f22ef01cSRoman Divacky 
15139f7f9bSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
16139f7f9bSDimitry Andric #include "llvm/ADT/Statistic.h"
172cab237bSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
182cab237bSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
19f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineFunctionPass.h"
20f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineInstr.h"
212cab237bSDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
22f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineRegisterInfo.h"
232cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
242cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
252cab237bSDimitry Andric #include "llvm/Pass.h"
262cab237bSDimitry Andric #include <cassert>
272cab237bSDimitry Andric 
28f22ef01cSRoman Divacky using namespace llvm;
29f22ef01cSRoman Divacky 
30302affcbSDimitry Andric #define DEBUG_TYPE "opt-phis"
3191bc56edSDimitry Andric 
32f22ef01cSRoman Divacky STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
33f22ef01cSRoman Divacky STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles");
34f22ef01cSRoman Divacky 
35f22ef01cSRoman Divacky namespace {
362cab237bSDimitry Andric 
37f22ef01cSRoman Divacky   class OptimizePHIs : public MachineFunctionPass {
38f22ef01cSRoman Divacky     MachineRegisterInfo *MRI;
39f22ef01cSRoman Divacky     const TargetInstrInfo *TII;
40f22ef01cSRoman Divacky 
41f22ef01cSRoman Divacky   public:
42f22ef01cSRoman Divacky     static char ID; // Pass identification
432cab237bSDimitry Andric 
OptimizePHIs()442754fe60SDimitry Andric     OptimizePHIs() : MachineFunctionPass(ID) {
452754fe60SDimitry Andric       initializeOptimizePHIsPass(*PassRegistry::getPassRegistry());
462754fe60SDimitry Andric     }
47f22ef01cSRoman Divacky 
484ba319b5SDimitry Andric     bool runOnMachineFunction(MachineFunction &Fn) override;
49f22ef01cSRoman Divacky 
getAnalysisUsage(AnalysisUsage & AU) const5091bc56edSDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
51f22ef01cSRoman Divacky       AU.setPreservesCFG();
52f22ef01cSRoman Divacky       MachineFunctionPass::getAnalysisUsage(AU);
53f22ef01cSRoman Divacky     }
54f22ef01cSRoman Divacky 
55f22ef01cSRoman Divacky   private:
562cab237bSDimitry Andric     using InstrSet = SmallPtrSet<MachineInstr *, 16>;
572cab237bSDimitry Andric     using InstrSetIterator = SmallPtrSetIterator<MachineInstr *>;
58f22ef01cSRoman Divacky 
59f22ef01cSRoman Divacky     bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg,
60f22ef01cSRoman Divacky                                InstrSet &PHIsInCycle);
61f22ef01cSRoman Divacky     bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle);
62f22ef01cSRoman Divacky     bool OptimizeBB(MachineBasicBlock &MBB);
63f22ef01cSRoman Divacky   };
642cab237bSDimitry Andric 
652cab237bSDimitry Andric } // end anonymous namespace
66f22ef01cSRoman Divacky 
67f22ef01cSRoman Divacky char OptimizePHIs::ID = 0;
682cab237bSDimitry Andric 
69dff0c46cSDimitry Andric char &llvm::OptimizePHIsID = OptimizePHIs::ID;
702cab237bSDimitry Andric 
71302affcbSDimitry Andric INITIALIZE_PASS(OptimizePHIs, DEBUG_TYPE,
722754fe60SDimitry Andric                 "Optimize machine instruction PHIs", false, false)
73f22ef01cSRoman Divacky 
runOnMachineFunction(MachineFunction & Fn)74f22ef01cSRoman Divacky bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
752cab237bSDimitry Andric   if (skipFunction(Fn.getFunction()))
7691bc56edSDimitry Andric     return false;
7791bc56edSDimitry Andric 
78f22ef01cSRoman Divacky   MRI = &Fn.getRegInfo();
7939d628a0SDimitry Andric   TII = Fn.getSubtarget().getInstrInfo();
80f22ef01cSRoman Divacky 
81f22ef01cSRoman Divacky   // Find dead PHI cycles and PHI cycles that can be replaced by a single
82f22ef01cSRoman Divacky   // value.  InstCombine does these optimizations, but DAG legalization may
83f22ef01cSRoman Divacky   // introduce new opportunities, e.g., when i64 values are split up for
84f22ef01cSRoman Divacky   // 32-bit targets.
85f22ef01cSRoman Divacky   bool Changed = false;
86f22ef01cSRoman Divacky   for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
87f22ef01cSRoman Divacky     Changed |= OptimizeBB(*I);
88f22ef01cSRoman Divacky 
89f22ef01cSRoman Divacky   return Changed;
90f22ef01cSRoman Divacky }
91f22ef01cSRoman Divacky 
92f22ef01cSRoman Divacky /// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands
93f22ef01cSRoman Divacky /// are copies of SingleValReg, possibly via copies through other PHIs. If
94f22ef01cSRoman Divacky /// SingleValReg is zero on entry, it is set to the register with the single
95f22ef01cSRoman Divacky /// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that
96*b5893f02SDimitry Andric /// have been scanned. PHIs may be grouped by cycle, several cycles or chains.
IsSingleValuePHICycle(MachineInstr * MI,unsigned & SingleValReg,InstrSet & PHIsInCycle)97f22ef01cSRoman Divacky bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI,
98f22ef01cSRoman Divacky                                          unsigned &SingleValReg,
99f22ef01cSRoman Divacky                                          InstrSet &PHIsInCycle) {
100f22ef01cSRoman Divacky   assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction");
101f22ef01cSRoman Divacky   unsigned DstReg = MI->getOperand(0).getReg();
102f22ef01cSRoman Divacky 
103f22ef01cSRoman Divacky   // See if we already saw this register.
10439d628a0SDimitry Andric   if (!PHIsInCycle.insert(MI).second)
105f22ef01cSRoman Divacky     return true;
106f22ef01cSRoman Divacky 
107f22ef01cSRoman Divacky   // Don't scan crazily complex things.
108f22ef01cSRoman Divacky   if (PHIsInCycle.size() == 16)
109f22ef01cSRoman Divacky     return false;
110f22ef01cSRoman Divacky 
111f22ef01cSRoman Divacky   // Scan the PHI operands.
112f22ef01cSRoman Divacky   for (unsigned i = 1; i != MI->getNumOperands(); i += 2) {
113f22ef01cSRoman Divacky     unsigned SrcReg = MI->getOperand(i).getReg();
114f22ef01cSRoman Divacky     if (SrcReg == DstReg)
115f22ef01cSRoman Divacky       continue;
116f22ef01cSRoman Divacky     MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
117f22ef01cSRoman Divacky 
118f22ef01cSRoman Divacky     // Skip over register-to-register moves.
119e580952dSDimitry Andric     if (SrcMI && SrcMI->isCopy() &&
120ffd1746dSEd Schouten         !SrcMI->getOperand(0).getSubReg() &&
121ffd1746dSEd Schouten         !SrcMI->getOperand(1).getSubReg() &&
122*b5893f02SDimitry Andric         TargetRegisterInfo::isVirtualRegister(SrcMI->getOperand(1).getReg())) {
123*b5893f02SDimitry Andric       SrcReg = SrcMI->getOperand(1).getReg();
124*b5893f02SDimitry Andric       SrcMI = MRI->getVRegDef(SrcReg);
125*b5893f02SDimitry Andric     }
126f22ef01cSRoman Divacky     if (!SrcMI)
127f22ef01cSRoman Divacky       return false;
128f22ef01cSRoman Divacky 
129f22ef01cSRoman Divacky     if (SrcMI->isPHI()) {
130f22ef01cSRoman Divacky       if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle))
131f22ef01cSRoman Divacky         return false;
132f22ef01cSRoman Divacky     } else {
133f22ef01cSRoman Divacky       // Fail if there is more than one non-phi/non-move register.
134*b5893f02SDimitry Andric       if (SingleValReg != 0 && SingleValReg != SrcReg)
135f22ef01cSRoman Divacky         return false;
136f22ef01cSRoman Divacky       SingleValReg = SrcReg;
137f22ef01cSRoman Divacky     }
138f22ef01cSRoman Divacky   }
139f22ef01cSRoman Divacky   return true;
140f22ef01cSRoman Divacky }
141f22ef01cSRoman Divacky 
142f22ef01cSRoman Divacky /// IsDeadPHICycle - Check if the register defined by a PHI is only used by
143f22ef01cSRoman Divacky /// other PHIs in a cycle.
IsDeadPHICycle(MachineInstr * MI,InstrSet & PHIsInCycle)144f22ef01cSRoman Divacky bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) {
145f22ef01cSRoman Divacky   assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction");
146f22ef01cSRoman Divacky   unsigned DstReg = MI->getOperand(0).getReg();
147f22ef01cSRoman Divacky   assert(TargetRegisterInfo::isVirtualRegister(DstReg) &&
148f22ef01cSRoman Divacky          "PHI destination is not a virtual register");
149f22ef01cSRoman Divacky 
150f22ef01cSRoman Divacky   // See if we already saw this register.
15139d628a0SDimitry Andric   if (!PHIsInCycle.insert(MI).second)
152f22ef01cSRoman Divacky     return true;
153f22ef01cSRoman Divacky 
154f22ef01cSRoman Divacky   // Don't scan crazily complex things.
155f22ef01cSRoman Divacky   if (PHIsInCycle.size() == 16)
156f22ef01cSRoman Divacky     return false;
157f22ef01cSRoman Divacky 
1582cab237bSDimitry Andric   for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DstReg)) {
15991bc56edSDimitry Andric     if (!UseMI.isPHI() || !IsDeadPHICycle(&UseMI, PHIsInCycle))
160f22ef01cSRoman Divacky       return false;
161f22ef01cSRoman Divacky   }
162f22ef01cSRoman Divacky 
163f22ef01cSRoman Divacky   return true;
164f22ef01cSRoman Divacky }
165f22ef01cSRoman Divacky 
166f22ef01cSRoman Divacky /// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by
167f22ef01cSRoman Divacky /// a single value.
OptimizeBB(MachineBasicBlock & MBB)168f22ef01cSRoman Divacky bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) {
169f22ef01cSRoman Divacky   bool Changed = false;
170f22ef01cSRoman Divacky   for (MachineBasicBlock::iterator
171f22ef01cSRoman Divacky          MII = MBB.begin(), E = MBB.end(); MII != E; ) {
172f22ef01cSRoman Divacky     MachineInstr *MI = &*MII++;
173f22ef01cSRoman Divacky     if (!MI->isPHI())
174f22ef01cSRoman Divacky       break;
175f22ef01cSRoman Divacky 
176f22ef01cSRoman Divacky     // Check for single-value PHI cycles.
177f22ef01cSRoman Divacky     unsigned SingleValReg = 0;
178f22ef01cSRoman Divacky     InstrSet PHIsInCycle;
179f22ef01cSRoman Divacky     if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) &&
180f22ef01cSRoman Divacky         SingleValReg != 0) {
181dff0c46cSDimitry Andric       unsigned OldReg = MI->getOperand(0).getReg();
182dff0c46cSDimitry Andric       if (!MRI->constrainRegClass(SingleValReg, MRI->getRegClass(OldReg)))
183dff0c46cSDimitry Andric         continue;
184dff0c46cSDimitry Andric 
185*b5893f02SDimitry Andric       // for the case SingleValReg taken from copy instr
186*b5893f02SDimitry Andric       MRI->clearKillFlags(SingleValReg);
187*b5893f02SDimitry Andric 
188dff0c46cSDimitry Andric       MRI->replaceRegWith(OldReg, SingleValReg);
189f22ef01cSRoman Divacky       MI->eraseFromParent();
190f22ef01cSRoman Divacky       ++NumPHICycles;
191f22ef01cSRoman Divacky       Changed = true;
192f22ef01cSRoman Divacky       continue;
193f22ef01cSRoman Divacky     }
194f22ef01cSRoman Divacky 
195f22ef01cSRoman Divacky     // Check for dead PHI cycles.
196f22ef01cSRoman Divacky     PHIsInCycle.clear();
197f22ef01cSRoman Divacky     if (IsDeadPHICycle(MI, PHIsInCycle)) {
198f22ef01cSRoman Divacky       for (InstrSetIterator PI = PHIsInCycle.begin(), PE = PHIsInCycle.end();
199f22ef01cSRoman Divacky            PI != PE; ++PI) {
200f22ef01cSRoman Divacky         MachineInstr *PhiMI = *PI;
201d88c1a5aSDimitry Andric         if (MII == PhiMI)
202f22ef01cSRoman Divacky           ++MII;
203f22ef01cSRoman Divacky         PhiMI->eraseFromParent();
204f22ef01cSRoman Divacky       }
205f22ef01cSRoman Divacky       ++NumDeadPHICycles;
206f22ef01cSRoman Divacky       Changed = true;
207f22ef01cSRoman Divacky     }
208f22ef01cSRoman Divacky   }
209f22ef01cSRoman Divacky   return Changed;
210f22ef01cSRoman Divacky }
211