1044eb2f6SDimitry Andric //===- OptimizePHIs.cpp - Optimize machine instruction PHIs ---------------===//
26fe5c7aaSRoman Divacky //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66fe5c7aaSRoman Divacky //
76fe5c7aaSRoman Divacky //===----------------------------------------------------------------------===//
86fe5c7aaSRoman Divacky //
96fe5c7aaSRoman Divacky // This pass optimizes machine instruction PHIs to take advantage of
106fe5c7aaSRoman Divacky // opportunities created during DAG legalization.
116fe5c7aaSRoman Divacky //
126fe5c7aaSRoman Divacky //===----------------------------------------------------------------------===//
136fe5c7aaSRoman Divacky
144a16efa3SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
154a16efa3SDimitry Andric #include "llvm/ADT/Statistic.h"
16044eb2f6SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
17044eb2f6SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
186fe5c7aaSRoman Divacky #include "llvm/CodeGen/MachineFunctionPass.h"
196fe5c7aaSRoman Divacky #include "llvm/CodeGen/MachineInstr.h"
20044eb2f6SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
216fe5c7aaSRoman Divacky #include "llvm/CodeGen/MachineRegisterInfo.h"
22044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
23706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
24044eb2f6SDimitry Andric #include "llvm/Pass.h"
25044eb2f6SDimitry Andric #include <cassert>
26044eb2f6SDimitry Andric
276fe5c7aaSRoman Divacky using namespace llvm;
286fe5c7aaSRoman Divacky
29ab44ce3dSDimitry Andric #define DEBUG_TYPE "opt-phis"
305ca98fd9SDimitry Andric
316fe5c7aaSRoman Divacky STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
326fe5c7aaSRoman Divacky STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles");
336fe5c7aaSRoman Divacky
346fe5c7aaSRoman Divacky namespace {
35044eb2f6SDimitry Andric
366fe5c7aaSRoman Divacky class OptimizePHIs : public MachineFunctionPass {
377fa27ce4SDimitry Andric MachineRegisterInfo *MRI = nullptr;
387fa27ce4SDimitry Andric const TargetInstrInfo *TII = nullptr;
396fe5c7aaSRoman Divacky
406fe5c7aaSRoman Divacky public:
416fe5c7aaSRoman Divacky static char ID; // Pass identification
42044eb2f6SDimitry Andric
OptimizePHIs()43cf099d11SDimitry Andric OptimizePHIs() : MachineFunctionPass(ID) {
44cf099d11SDimitry Andric initializeOptimizePHIsPass(*PassRegistry::getPassRegistry());
45cf099d11SDimitry Andric }
466fe5c7aaSRoman Divacky
47eb11fae6SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override;
486fe5c7aaSRoman Divacky
getAnalysisUsage(AnalysisUsage & AU) const495ca98fd9SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
506fe5c7aaSRoman Divacky AU.setPreservesCFG();
516fe5c7aaSRoman Divacky MachineFunctionPass::getAnalysisUsage(AU);
526fe5c7aaSRoman Divacky }
536fe5c7aaSRoman Divacky
546fe5c7aaSRoman Divacky private:
55044eb2f6SDimitry Andric using InstrSet = SmallPtrSet<MachineInstr *, 16>;
56044eb2f6SDimitry Andric using InstrSetIterator = SmallPtrSetIterator<MachineInstr *>;
576fe5c7aaSRoman Divacky
586fe5c7aaSRoman Divacky bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg,
596fe5c7aaSRoman Divacky InstrSet &PHIsInCycle);
606fe5c7aaSRoman Divacky bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle);
616fe5c7aaSRoman Divacky bool OptimizeBB(MachineBasicBlock &MBB);
626fe5c7aaSRoman Divacky };
63044eb2f6SDimitry Andric
64044eb2f6SDimitry Andric } // end anonymous namespace
656fe5c7aaSRoman Divacky
666fe5c7aaSRoman Divacky char OptimizePHIs::ID = 0;
67044eb2f6SDimitry Andric
6863faed5bSDimitry Andric char &llvm::OptimizePHIsID = OptimizePHIs::ID;
69044eb2f6SDimitry Andric
70ab44ce3dSDimitry Andric INITIALIZE_PASS(OptimizePHIs, DEBUG_TYPE,
71cf099d11SDimitry Andric "Optimize machine instruction PHIs", false, false)
726fe5c7aaSRoman Divacky
runOnMachineFunction(MachineFunction & Fn)736fe5c7aaSRoman Divacky bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
74044eb2f6SDimitry Andric if (skipFunction(Fn.getFunction()))
755ca98fd9SDimitry Andric return false;
765ca98fd9SDimitry Andric
776fe5c7aaSRoman Divacky MRI = &Fn.getRegInfo();
7867c32a98SDimitry Andric TII = Fn.getSubtarget().getInstrInfo();
796fe5c7aaSRoman Divacky
806fe5c7aaSRoman Divacky // Find dead PHI cycles and PHI cycles that can be replaced by a single
816fe5c7aaSRoman Divacky // value. InstCombine does these optimizations, but DAG legalization may
826fe5c7aaSRoman Divacky // introduce new opportunities, e.g., when i64 values are split up for
836fe5c7aaSRoman Divacky // 32-bit targets.
846fe5c7aaSRoman Divacky bool Changed = false;
85344a3780SDimitry Andric for (MachineBasicBlock &MBB : Fn)
86344a3780SDimitry Andric Changed |= OptimizeBB(MBB);
876fe5c7aaSRoman Divacky
886fe5c7aaSRoman Divacky return Changed;
896fe5c7aaSRoman Divacky }
906fe5c7aaSRoman Divacky
916fe5c7aaSRoman Divacky /// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands
926fe5c7aaSRoman Divacky /// are copies of SingleValReg, possibly via copies through other PHIs. If
936fe5c7aaSRoman Divacky /// SingleValReg is zero on entry, it is set to the register with the single
946fe5c7aaSRoman Divacky /// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that
95d8e91e46SDimitry Andric /// have been scanned. PHIs may be grouped by cycle, several cycles or chains.
IsSingleValuePHICycle(MachineInstr * MI,unsigned & SingleValReg,InstrSet & PHIsInCycle)966fe5c7aaSRoman Divacky bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI,
976fe5c7aaSRoman Divacky unsigned &SingleValReg,
986fe5c7aaSRoman Divacky InstrSet &PHIsInCycle) {
996fe5c7aaSRoman Divacky assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction");
1001d5ae102SDimitry Andric Register DstReg = MI->getOperand(0).getReg();
1016fe5c7aaSRoman Divacky
1026fe5c7aaSRoman Divacky // See if we already saw this register.
10367c32a98SDimitry Andric if (!PHIsInCycle.insert(MI).second)
1046fe5c7aaSRoman Divacky return true;
1056fe5c7aaSRoman Divacky
1066fe5c7aaSRoman Divacky // Don't scan crazily complex things.
1076fe5c7aaSRoman Divacky if (PHIsInCycle.size() == 16)
1086fe5c7aaSRoman Divacky return false;
1096fe5c7aaSRoman Divacky
1106fe5c7aaSRoman Divacky // Scan the PHI operands.
1116fe5c7aaSRoman Divacky for (unsigned i = 1; i != MI->getNumOperands(); i += 2) {
1121d5ae102SDimitry Andric Register SrcReg = MI->getOperand(i).getReg();
1136fe5c7aaSRoman Divacky if (SrcReg == DstReg)
1146fe5c7aaSRoman Divacky continue;
1156fe5c7aaSRoman Divacky MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
1166fe5c7aaSRoman Divacky
1176fe5c7aaSRoman Divacky // Skip over register-to-register moves.
1181d5ae102SDimitry Andric if (SrcMI && SrcMI->isCopy() && !SrcMI->getOperand(0).getSubReg() &&
11966e41e3cSRoman Divacky !SrcMI->getOperand(1).getSubReg() &&
120e3b55780SDimitry Andric SrcMI->getOperand(1).getReg().isVirtual()) {
121d8e91e46SDimitry Andric SrcReg = SrcMI->getOperand(1).getReg();
122d8e91e46SDimitry Andric SrcMI = MRI->getVRegDef(SrcReg);
123d8e91e46SDimitry Andric }
1246fe5c7aaSRoman Divacky if (!SrcMI)
1256fe5c7aaSRoman Divacky return false;
1266fe5c7aaSRoman Divacky
1276fe5c7aaSRoman Divacky if (SrcMI->isPHI()) {
1286fe5c7aaSRoman Divacky if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle))
1296fe5c7aaSRoman Divacky return false;
1306fe5c7aaSRoman Divacky } else {
1316fe5c7aaSRoman Divacky // Fail if there is more than one non-phi/non-move register.
132d8e91e46SDimitry Andric if (SingleValReg != 0 && SingleValReg != SrcReg)
1336fe5c7aaSRoman Divacky return false;
1346fe5c7aaSRoman Divacky SingleValReg = SrcReg;
1356fe5c7aaSRoman Divacky }
1366fe5c7aaSRoman Divacky }
1376fe5c7aaSRoman Divacky return true;
1386fe5c7aaSRoman Divacky }
1396fe5c7aaSRoman Divacky
1406fe5c7aaSRoman Divacky /// IsDeadPHICycle - Check if the register defined by a PHI is only used by
1416fe5c7aaSRoman Divacky /// other PHIs in a cycle.
IsDeadPHICycle(MachineInstr * MI,InstrSet & PHIsInCycle)1426fe5c7aaSRoman Divacky bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) {
1436fe5c7aaSRoman Divacky assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction");
1441d5ae102SDimitry Andric Register DstReg = MI->getOperand(0).getReg();
145e3b55780SDimitry Andric assert(DstReg.isVirtual() && "PHI destination is not a virtual register");
1466fe5c7aaSRoman Divacky
1476fe5c7aaSRoman Divacky // See if we already saw this register.
14867c32a98SDimitry Andric if (!PHIsInCycle.insert(MI).second)
1496fe5c7aaSRoman Divacky return true;
1506fe5c7aaSRoman Divacky
1516fe5c7aaSRoman Divacky // Don't scan crazily complex things.
1526fe5c7aaSRoman Divacky if (PHIsInCycle.size() == 16)
1536fe5c7aaSRoman Divacky return false;
1546fe5c7aaSRoman Divacky
155044eb2f6SDimitry Andric for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DstReg)) {
1565ca98fd9SDimitry Andric if (!UseMI.isPHI() || !IsDeadPHICycle(&UseMI, PHIsInCycle))
1576fe5c7aaSRoman Divacky return false;
1586fe5c7aaSRoman Divacky }
1596fe5c7aaSRoman Divacky
1606fe5c7aaSRoman Divacky return true;
1616fe5c7aaSRoman Divacky }
1626fe5c7aaSRoman Divacky
1636fe5c7aaSRoman Divacky /// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by
1646fe5c7aaSRoman Divacky /// a single value.
OptimizeBB(MachineBasicBlock & MBB)1656fe5c7aaSRoman Divacky bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) {
1666fe5c7aaSRoman Divacky bool Changed = false;
1676fe5c7aaSRoman Divacky for (MachineBasicBlock::iterator
1686fe5c7aaSRoman Divacky MII = MBB.begin(), E = MBB.end(); MII != E; ) {
1696fe5c7aaSRoman Divacky MachineInstr *MI = &*MII++;
1706fe5c7aaSRoman Divacky if (!MI->isPHI())
1716fe5c7aaSRoman Divacky break;
1726fe5c7aaSRoman Divacky
1736fe5c7aaSRoman Divacky // Check for single-value PHI cycles.
1746fe5c7aaSRoman Divacky unsigned SingleValReg = 0;
1756fe5c7aaSRoman Divacky InstrSet PHIsInCycle;
1766fe5c7aaSRoman Divacky if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) &&
1776fe5c7aaSRoman Divacky SingleValReg != 0) {
1781d5ae102SDimitry Andric Register OldReg = MI->getOperand(0).getReg();
17963faed5bSDimitry Andric if (!MRI->constrainRegClass(SingleValReg, MRI->getRegClass(OldReg)))
18063faed5bSDimitry Andric continue;
18163faed5bSDimitry Andric
18263faed5bSDimitry Andric MRI->replaceRegWith(OldReg, SingleValReg);
1836fe5c7aaSRoman Divacky MI->eraseFromParent();
184e6d15924SDimitry Andric
185e6d15924SDimitry Andric // The kill flags on OldReg and SingleValReg may no longer be correct.
186e6d15924SDimitry Andric MRI->clearKillFlags(SingleValReg);
187e6d15924SDimitry Andric
1886fe5c7aaSRoman Divacky ++NumPHICycles;
1896fe5c7aaSRoman Divacky Changed = true;
1906fe5c7aaSRoman Divacky continue;
1916fe5c7aaSRoman Divacky }
1926fe5c7aaSRoman Divacky
1936fe5c7aaSRoman Divacky // Check for dead PHI cycles.
1946fe5c7aaSRoman Divacky PHIsInCycle.clear();
1956fe5c7aaSRoman Divacky if (IsDeadPHICycle(MI, PHIsInCycle)) {
196344a3780SDimitry Andric for (MachineInstr *PhiMI : PHIsInCycle) {
197b915e9e0SDimitry Andric if (MII == PhiMI)
1986fe5c7aaSRoman Divacky ++MII;
1996fe5c7aaSRoman Divacky PhiMI->eraseFromParent();
2006fe5c7aaSRoman Divacky }
2016fe5c7aaSRoman Divacky ++NumDeadPHICycles;
2026fe5c7aaSRoman Divacky Changed = true;
2036fe5c7aaSRoman Divacky }
2046fe5c7aaSRoman Divacky }
2056fe5c7aaSRoman Divacky return Changed;
2066fe5c7aaSRoman Divacky }
207