xref: /llvm-project/llvm/lib/CodeGen/OptimizePHIs.cpp (revision 735ab61ac828bd61398e6847d60e308fdf2b54ec)
1 //===- OptimizePHIs.cpp - Optimize machine instruction PHIs ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass optimizes machine instruction PHIs to take advantage of
10 // opportunities created during DAG legalization.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/CodeGen/OptimizePHIs.h"
15 #include "llvm/ADT/SmallPtrSet.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/CodeGen/MachineFunctionPass.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineOperand.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/CodeGen/TargetSubtargetInfo.h"
23 #include "llvm/InitializePasses.h"
24 #include "llvm/Pass.h"
25 #include <cassert>
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "opt-phis"
30 
31 STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
32 STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles");
33 
34 namespace {
35 
36 class OptimizePHIs {
37   MachineRegisterInfo *MRI = nullptr;
38   const TargetInstrInfo *TII = nullptr;
39 
40 public:
41   bool run(MachineFunction &Fn);
42 
43 private:
44   using InstrSet = SmallPtrSet<MachineInstr *, 16>;
45   using InstrSetIterator = SmallPtrSetIterator<MachineInstr *>;
46 
47   bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg,
48                              InstrSet &PHIsInCycle);
49   bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle);
50   bool OptimizeBB(MachineBasicBlock &MBB);
51 };
52 
53 class OptimizePHIsLegacy : public MachineFunctionPass {
54 public:
55   static char ID;
56   OptimizePHIsLegacy() : MachineFunctionPass(ID) {
57     initializeOptimizePHIsLegacyPass(*PassRegistry::getPassRegistry());
58   }
59 
60   bool runOnMachineFunction(MachineFunction &MF) override {
61     if (skipFunction(MF.getFunction()))
62       return false;
63     OptimizePHIs OP;
64     return OP.run(MF);
65   }
66 
67   void getAnalysisUsage(AnalysisUsage &AU) const override {
68     AU.setPreservesCFG();
69     MachineFunctionPass::getAnalysisUsage(AU);
70   }
71 };
72 } // end anonymous namespace
73 
74 char OptimizePHIsLegacy::ID = 0;
75 
76 char &llvm::OptimizePHIsLegacyID = OptimizePHIsLegacy::ID;
77 
78 INITIALIZE_PASS(OptimizePHIsLegacy, DEBUG_TYPE,
79                 "Optimize machine instruction PHIs", false, false)
80 
81 PreservedAnalyses OptimizePHIsPass::run(MachineFunction &MF,
82                                         MachineFunctionAnalysisManager &MFAM) {
83   OptimizePHIs OP;
84   if (!OP.run(MF))
85     return PreservedAnalyses::all();
86   auto PA = getMachineFunctionPassPreservedAnalyses();
87   PA.preserveSet<CFGAnalyses>();
88   return PA;
89 }
90 
91 bool OptimizePHIs::run(MachineFunction &Fn) {
92   MRI = &Fn.getRegInfo();
93   TII = Fn.getSubtarget().getInstrInfo();
94 
95   // Find dead PHI cycles and PHI cycles that can be replaced by a single
96   // value.  InstCombine does these optimizations, but DAG legalization may
97   // introduce new opportunities, e.g., when i64 values are split up for
98   // 32-bit targets.
99   bool Changed = false;
100   for (MachineBasicBlock &MBB : Fn)
101     Changed |= OptimizeBB(MBB);
102 
103   return Changed;
104 }
105 
106 /// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands
107 /// are copies of SingleValReg, possibly via copies through other PHIs. If
108 /// SingleValReg is zero on entry, it is set to the register with the single
109 /// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that
110 /// have been scanned. PHIs may be grouped by cycle, several cycles or chains.
111 bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI,
112                                          unsigned &SingleValReg,
113                                          InstrSet &PHIsInCycle) {
114   assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction");
115   Register DstReg = MI->getOperand(0).getReg();
116 
117   // See if we already saw this register.
118   if (!PHIsInCycle.insert(MI).second)
119     return true;
120 
121   // Don't scan crazily complex things.
122   if (PHIsInCycle.size() == 16)
123     return false;
124 
125   // Scan the PHI operands.
126   for (unsigned i = 1; i != MI->getNumOperands(); i += 2) {
127     Register SrcReg = MI->getOperand(i).getReg();
128     if (SrcReg == DstReg)
129       continue;
130     MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
131 
132     // Skip over register-to-register moves.
133     if (SrcMI && SrcMI->isCopy() && !SrcMI->getOperand(0).getSubReg() &&
134         !SrcMI->getOperand(1).getSubReg() &&
135         SrcMI->getOperand(1).getReg().isVirtual()) {
136       SrcReg = SrcMI->getOperand(1).getReg();
137       SrcMI = MRI->getVRegDef(SrcReg);
138     }
139     if (!SrcMI)
140       return false;
141 
142     if (SrcMI->isPHI()) {
143       if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle))
144         return false;
145     } else {
146       // Fail if there is more than one non-phi/non-move register.
147       if (SingleValReg != 0 && SingleValReg != SrcReg)
148         return false;
149       SingleValReg = SrcReg;
150     }
151   }
152   return true;
153 }
154 
155 /// IsDeadPHICycle - Check if the register defined by a PHI is only used by
156 /// other PHIs in a cycle.
157 bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) {
158   assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction");
159   Register DstReg = MI->getOperand(0).getReg();
160   assert(DstReg.isVirtual() && "PHI destination is not a virtual register");
161 
162   // See if we already saw this register.
163   if (!PHIsInCycle.insert(MI).second)
164     return true;
165 
166   // Don't scan crazily complex things.
167   if (PHIsInCycle.size() == 16)
168     return false;
169 
170   for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DstReg)) {
171     if (!UseMI.isPHI() || !IsDeadPHICycle(&UseMI, PHIsInCycle))
172       return false;
173   }
174 
175   return true;
176 }
177 
178 /// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by
179 /// a single value.
180 bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) {
181   bool Changed = false;
182   for (MachineBasicBlock::iterator
183          MII = MBB.begin(), E = MBB.end(); MII != E; ) {
184     MachineInstr *MI = &*MII++;
185     if (!MI->isPHI())
186       break;
187 
188     // Check for single-value PHI cycles.
189     unsigned SingleValReg = 0;
190     InstrSet PHIsInCycle;
191     if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) &&
192         SingleValReg != 0) {
193       Register OldReg = MI->getOperand(0).getReg();
194       if (!MRI->constrainRegClass(SingleValReg, MRI->getRegClass(OldReg)))
195         continue;
196 
197       MRI->replaceRegWith(OldReg, SingleValReg);
198       MI->eraseFromParent();
199 
200       // The kill flags on OldReg and SingleValReg may no longer be correct.
201       MRI->clearKillFlags(SingleValReg);
202 
203       ++NumPHICycles;
204       Changed = true;
205       continue;
206     }
207 
208     // Check for dead PHI cycles.
209     PHIsInCycle.clear();
210     if (IsDeadPHICycle(MI, PHIsInCycle)) {
211       for (MachineInstr *PhiMI : PHIsInCycle) {
212         if (MII == PhiMI)
213           ++MII;
214         PhiMI->eraseFromParent();
215       }
216       ++NumDeadPHICycles;
217       Changed = true;
218     }
219   }
220   return Changed;
221 }
222