10b57cec5SDimitry Andric //===- OptimizePHIs.cpp - Optimize machine instruction PHIs ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass optimizes machine instruction PHIs to take advantage of
100b57cec5SDimitry Andric // opportunities created during DAG legalization.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
150b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
24480093f4SDimitry Andric #include "llvm/InitializePasses.h"
250b57cec5SDimitry Andric #include "llvm/Pass.h"
260b57cec5SDimitry Andric #include <cassert>
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric #define DEBUG_TYPE "opt-phis"
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
330b57cec5SDimitry Andric STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles");
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric namespace {
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric class OptimizePHIs : public MachineFunctionPass {
380b57cec5SDimitry Andric MachineRegisterInfo *MRI;
390b57cec5SDimitry Andric const TargetInstrInfo *TII;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric public:
420b57cec5SDimitry Andric static char ID; // Pass identification
430b57cec5SDimitry Andric
OptimizePHIs()440b57cec5SDimitry Andric OptimizePHIs() : MachineFunctionPass(ID) {
450b57cec5SDimitry Andric initializeOptimizePHIsPass(*PassRegistry::getPassRegistry());
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override;
490b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const500b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
510b57cec5SDimitry Andric AU.setPreservesCFG();
520b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric private:
560b57cec5SDimitry Andric using InstrSet = SmallPtrSet<MachineInstr *, 16>;
570b57cec5SDimitry Andric using InstrSetIterator = SmallPtrSetIterator<MachineInstr *>;
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg,
600b57cec5SDimitry Andric InstrSet &PHIsInCycle);
610b57cec5SDimitry Andric bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle);
620b57cec5SDimitry Andric bool OptimizeBB(MachineBasicBlock &MBB);
630b57cec5SDimitry Andric };
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric } // end anonymous namespace
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric char OptimizePHIs::ID = 0;
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric char &llvm::OptimizePHIsID = OptimizePHIs::ID;
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric INITIALIZE_PASS(OptimizePHIs, DEBUG_TYPE,
720b57cec5SDimitry Andric "Optimize machine instruction PHIs", false, false)
730b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & Fn)740b57cec5SDimitry Andric bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
750b57cec5SDimitry Andric if (skipFunction(Fn.getFunction()))
760b57cec5SDimitry Andric return false;
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric MRI = &Fn.getRegInfo();
790b57cec5SDimitry Andric TII = Fn.getSubtarget().getInstrInfo();
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric // Find dead PHI cycles and PHI cycles that can be replaced by a single
820b57cec5SDimitry Andric // value. InstCombine does these optimizations, but DAG legalization may
830b57cec5SDimitry Andric // introduce new opportunities, e.g., when i64 values are split up for
840b57cec5SDimitry Andric // 32-bit targets.
850b57cec5SDimitry Andric bool Changed = false;
86*5f7ddb14SDimitry Andric for (MachineBasicBlock &MBB : Fn)
87*5f7ddb14SDimitry Andric Changed |= OptimizeBB(MBB);
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric return Changed;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric /// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands
930b57cec5SDimitry Andric /// are copies of SingleValReg, possibly via copies through other PHIs. If
940b57cec5SDimitry Andric /// SingleValReg is zero on entry, it is set to the register with the single
950b57cec5SDimitry Andric /// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that
960b57cec5SDimitry Andric /// have been scanned. PHIs may be grouped by cycle, several cycles or chains.
IsSingleValuePHICycle(MachineInstr * MI,unsigned & SingleValReg,InstrSet & PHIsInCycle)970b57cec5SDimitry Andric bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI,
980b57cec5SDimitry Andric unsigned &SingleValReg,
990b57cec5SDimitry Andric InstrSet &PHIsInCycle) {
1000b57cec5SDimitry Andric assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction");
1018bcb0991SDimitry Andric Register DstReg = MI->getOperand(0).getReg();
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric // See if we already saw this register.
1040b57cec5SDimitry Andric if (!PHIsInCycle.insert(MI).second)
1050b57cec5SDimitry Andric return true;
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric // Don't scan crazily complex things.
1080b57cec5SDimitry Andric if (PHIsInCycle.size() == 16)
1090b57cec5SDimitry Andric return false;
1100b57cec5SDimitry Andric
1110b57cec5SDimitry Andric // Scan the PHI operands.
1120b57cec5SDimitry Andric for (unsigned i = 1; i != MI->getNumOperands(); i += 2) {
1138bcb0991SDimitry Andric Register SrcReg = MI->getOperand(i).getReg();
1140b57cec5SDimitry Andric if (SrcReg == DstReg)
1150b57cec5SDimitry Andric continue;
1160b57cec5SDimitry Andric MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric // Skip over register-to-register moves.
1198bcb0991SDimitry Andric if (SrcMI && SrcMI->isCopy() && !SrcMI->getOperand(0).getSubReg() &&
1200b57cec5SDimitry Andric !SrcMI->getOperand(1).getSubReg() &&
1218bcb0991SDimitry Andric Register::isVirtualRegister(SrcMI->getOperand(1).getReg())) {
1220b57cec5SDimitry Andric SrcReg = SrcMI->getOperand(1).getReg();
1230b57cec5SDimitry Andric SrcMI = MRI->getVRegDef(SrcReg);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric if (!SrcMI)
1260b57cec5SDimitry Andric return false;
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric if (SrcMI->isPHI()) {
1290b57cec5SDimitry Andric if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle))
1300b57cec5SDimitry Andric return false;
1310b57cec5SDimitry Andric } else {
1320b57cec5SDimitry Andric // Fail if there is more than one non-phi/non-move register.
1330b57cec5SDimitry Andric if (SingleValReg != 0 && SingleValReg != SrcReg)
1340b57cec5SDimitry Andric return false;
1350b57cec5SDimitry Andric SingleValReg = SrcReg;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric return true;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric /// IsDeadPHICycle - Check if the register defined by a PHI is only used by
1420b57cec5SDimitry Andric /// other PHIs in a cycle.
IsDeadPHICycle(MachineInstr * MI,InstrSet & PHIsInCycle)1430b57cec5SDimitry Andric bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) {
1440b57cec5SDimitry Andric assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction");
1458bcb0991SDimitry Andric Register DstReg = MI->getOperand(0).getReg();
1468bcb0991SDimitry Andric assert(Register::isVirtualRegister(DstReg) &&
1470b57cec5SDimitry Andric "PHI destination is not a virtual register");
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric // See if we already saw this register.
1500b57cec5SDimitry Andric if (!PHIsInCycle.insert(MI).second)
1510b57cec5SDimitry Andric return true;
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric // Don't scan crazily complex things.
1540b57cec5SDimitry Andric if (PHIsInCycle.size() == 16)
1550b57cec5SDimitry Andric return false;
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DstReg)) {
1580b57cec5SDimitry Andric if (!UseMI.isPHI() || !IsDeadPHICycle(&UseMI, PHIsInCycle))
1590b57cec5SDimitry Andric return false;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric return true;
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric /// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by
1660b57cec5SDimitry Andric /// a single value.
OptimizeBB(MachineBasicBlock & MBB)1670b57cec5SDimitry Andric bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) {
1680b57cec5SDimitry Andric bool Changed = false;
1690b57cec5SDimitry Andric for (MachineBasicBlock::iterator
1700b57cec5SDimitry Andric MII = MBB.begin(), E = MBB.end(); MII != E; ) {
1710b57cec5SDimitry Andric MachineInstr *MI = &*MII++;
1720b57cec5SDimitry Andric if (!MI->isPHI())
1730b57cec5SDimitry Andric break;
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric // Check for single-value PHI cycles.
1760b57cec5SDimitry Andric unsigned SingleValReg = 0;
1770b57cec5SDimitry Andric InstrSet PHIsInCycle;
1780b57cec5SDimitry Andric if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) &&
1790b57cec5SDimitry Andric SingleValReg != 0) {
1808bcb0991SDimitry Andric Register OldReg = MI->getOperand(0).getReg();
1810b57cec5SDimitry Andric if (!MRI->constrainRegClass(SingleValReg, MRI->getRegClass(OldReg)))
1820b57cec5SDimitry Andric continue;
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric MRI->replaceRegWith(OldReg, SingleValReg);
1850b57cec5SDimitry Andric MI->eraseFromParent();
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric // The kill flags on OldReg and SingleValReg may no longer be correct.
1880b57cec5SDimitry Andric MRI->clearKillFlags(SingleValReg);
1890b57cec5SDimitry Andric
1900b57cec5SDimitry Andric ++NumPHICycles;
1910b57cec5SDimitry Andric Changed = true;
1920b57cec5SDimitry Andric continue;
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andric // Check for dead PHI cycles.
1960b57cec5SDimitry Andric PHIsInCycle.clear();
1970b57cec5SDimitry Andric if (IsDeadPHICycle(MI, PHIsInCycle)) {
198*5f7ddb14SDimitry Andric for (MachineInstr *PhiMI : PHIsInCycle) {
1990b57cec5SDimitry Andric if (MII == PhiMI)
2000b57cec5SDimitry Andric ++MII;
2010b57cec5SDimitry Andric PhiMI->eraseFromParent();
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric ++NumDeadPHICycles;
2040b57cec5SDimitry Andric Changed = true;
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric return Changed;
2080b57cec5SDimitry Andric }
209