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