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