1f22ef01cSRoman Divacky //===---------------------- ProcessImplicitDefs.cpp -----------------------===//
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 
107ae0e2c9SDimitry Andric #include "llvm/ADT/SetVector.h"
11f22ef01cSRoman Divacky #include "llvm/Analysis/AliasAnalysis.h"
127ae0e2c9SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
13f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineInstr.h"
14f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineRegisterInfo.h"
15f22ef01cSRoman Divacky #include "llvm/CodeGen/Passes.h"
16f22ef01cSRoman Divacky #include "llvm/Support/Debug.h"
177ae0e2c9SDimitry Andric #include "llvm/Support/raw_ostream.h"
18f22ef01cSRoman Divacky #include "llvm/Target/TargetInstrInfo.h"
19f22ef01cSRoman Divacky 
20f22ef01cSRoman Divacky using namespace llvm;
21f22ef01cSRoman Divacky 
2291bc56edSDimitry Andric #define DEBUG_TYPE "processimplicitdefs"
2391bc56edSDimitry Andric 
247ae0e2c9SDimitry Andric namespace {
257ae0e2c9SDimitry Andric /// Process IMPLICIT_DEF instructions and make sure there is one implicit_def
267ae0e2c9SDimitry Andric /// for each use. Add isUndef marker to implicit_def defs and their uses.
277ae0e2c9SDimitry Andric class ProcessImplicitDefs : public MachineFunctionPass {
287ae0e2c9SDimitry Andric   const TargetInstrInfo *TII;
297ae0e2c9SDimitry Andric   const TargetRegisterInfo *TRI;
307ae0e2c9SDimitry Andric   MachineRegisterInfo *MRI;
317ae0e2c9SDimitry Andric 
327ae0e2c9SDimitry Andric   SmallSetVector<MachineInstr*, 16> WorkList;
337ae0e2c9SDimitry Andric 
347ae0e2c9SDimitry Andric   void processImplicitDef(MachineInstr *MI);
357ae0e2c9SDimitry Andric   bool canTurnIntoImplicitDef(MachineInstr *MI);
367ae0e2c9SDimitry Andric 
377ae0e2c9SDimitry Andric public:
387ae0e2c9SDimitry Andric   static char ID;
397ae0e2c9SDimitry Andric 
407ae0e2c9SDimitry Andric   ProcessImplicitDefs() : MachineFunctionPass(ID) {
417ae0e2c9SDimitry Andric     initializeProcessImplicitDefsPass(*PassRegistry::getPassRegistry());
427ae0e2c9SDimitry Andric   }
437ae0e2c9SDimitry Andric 
4491bc56edSDimitry Andric   void getAnalysisUsage(AnalysisUsage &au) const override;
457ae0e2c9SDimitry Andric 
4691bc56edSDimitry Andric   bool runOnMachineFunction(MachineFunction &fn) override;
477ae0e2c9SDimitry Andric };
487ae0e2c9SDimitry Andric } // end anonymous namespace
497ae0e2c9SDimitry Andric 
50f22ef01cSRoman Divacky char ProcessImplicitDefs::ID = 0;
51dff0c46cSDimitry Andric char &llvm::ProcessImplicitDefsID = ProcessImplicitDefs::ID;
52dff0c46cSDimitry Andric 
532754fe60SDimitry Andric INITIALIZE_PASS_BEGIN(ProcessImplicitDefs, "processimpdefs",
542754fe60SDimitry Andric                 "Process Implicit Definitions", false, false)
552754fe60SDimitry Andric INITIALIZE_PASS_END(ProcessImplicitDefs, "processimpdefs",
562754fe60SDimitry Andric                 "Process Implicit Definitions", false, false)
57f22ef01cSRoman Divacky 
58f22ef01cSRoman Divacky void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const {
59f22ef01cSRoman Divacky   AU.setPreservesCFG();
60f22ef01cSRoman Divacky   AU.addPreserved<AliasAnalysis>();
61f22ef01cSRoman Divacky   MachineFunctionPass::getAnalysisUsage(AU);
62f22ef01cSRoman Divacky }
63f22ef01cSRoman Divacky 
647ae0e2c9SDimitry Andric bool ProcessImplicitDefs::canTurnIntoImplicitDef(MachineInstr *MI) {
657ae0e2c9SDimitry Andric   if (!MI->isCopyLike() &&
667ae0e2c9SDimitry Andric       !MI->isInsertSubreg() &&
677ae0e2c9SDimitry Andric       !MI->isRegSequence() &&
687ae0e2c9SDimitry Andric       !MI->isPHI())
69ffd1746dSEd Schouten     return false;
707ae0e2c9SDimitry Andric   for (MIOperands MO(MI); MO.isValid(); ++MO)
717ae0e2c9SDimitry Andric     if (MO->isReg() && MO->isUse() && MO->readsReg())
727ae0e2c9SDimitry Andric       return false;
73f22ef01cSRoman Divacky   return true;
74f22ef01cSRoman Divacky }
75f22ef01cSRoman Divacky 
767ae0e2c9SDimitry Andric void ProcessImplicitDefs::processImplicitDef(MachineInstr *MI) {
777ae0e2c9SDimitry Andric   DEBUG(dbgs() << "Processing " << *MI);
787ae0e2c9SDimitry Andric   unsigned Reg = MI->getOperand(0).getReg();
797ae0e2c9SDimitry Andric 
807ae0e2c9SDimitry Andric   if (TargetRegisterInfo::isVirtualRegister(Reg)) {
81f785676fSDimitry Andric     // For virtual registers, mark all uses as <undef>, and convert users to
827ae0e2c9SDimitry Andric     // implicit-def when possible.
8391bc56edSDimitry Andric     for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
847ae0e2c9SDimitry Andric       MO.setIsUndef();
857ae0e2c9SDimitry Andric       MachineInstr *UserMI = MO.getParent();
867ae0e2c9SDimitry Andric       if (!canTurnIntoImplicitDef(UserMI))
877ae0e2c9SDimitry Andric         continue;
887ae0e2c9SDimitry Andric       DEBUG(dbgs() << "Converting to IMPLICIT_DEF: " << *UserMI);
897ae0e2c9SDimitry Andric       UserMI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF));
907ae0e2c9SDimitry Andric       WorkList.insert(UserMI);
917ae0e2c9SDimitry Andric     }
927ae0e2c9SDimitry Andric     MI->eraseFromParent();
937ae0e2c9SDimitry Andric     return;
947ae0e2c9SDimitry Andric   }
957ae0e2c9SDimitry Andric 
967ae0e2c9SDimitry Andric   // This is a physreg implicit-def.
977ae0e2c9SDimitry Andric   // Look for the first instruction to use or define an alias.
987ae0e2c9SDimitry Andric   MachineBasicBlock::instr_iterator UserMI = MI;
997ae0e2c9SDimitry Andric   MachineBasicBlock::instr_iterator UserE = MI->getParent()->instr_end();
1007ae0e2c9SDimitry Andric   bool Found = false;
1017ae0e2c9SDimitry Andric   for (++UserMI; UserMI != UserE; ++UserMI) {
1027ae0e2c9SDimitry Andric     for (MIOperands MO(UserMI); MO.isValid(); ++MO) {
1037ae0e2c9SDimitry Andric       if (!MO->isReg())
1047ae0e2c9SDimitry Andric         continue;
1057ae0e2c9SDimitry Andric       unsigned UserReg = MO->getReg();
1067ae0e2c9SDimitry Andric       if (!TargetRegisterInfo::isPhysicalRegister(UserReg) ||
1077ae0e2c9SDimitry Andric           !TRI->regsOverlap(Reg, UserReg))
1087ae0e2c9SDimitry Andric         continue;
1097ae0e2c9SDimitry Andric       // UserMI uses or redefines Reg. Set <undef> flags on all uses.
1107ae0e2c9SDimitry Andric       Found = true;
1117ae0e2c9SDimitry Andric       if (MO->isUse())
1127ae0e2c9SDimitry Andric         MO->setIsUndef();
1137ae0e2c9SDimitry Andric     }
1147ae0e2c9SDimitry Andric     if (Found)
1157ae0e2c9SDimitry Andric       break;
1167ae0e2c9SDimitry Andric   }
1177ae0e2c9SDimitry Andric 
1187ae0e2c9SDimitry Andric   // If we found the using MI, we can erase the IMPLICIT_DEF.
1197ae0e2c9SDimitry Andric   if (Found) {
1207ae0e2c9SDimitry Andric     DEBUG(dbgs() << "Physreg user: " << *UserMI);
1217ae0e2c9SDimitry Andric     MI->eraseFromParent();
1227ae0e2c9SDimitry Andric     return;
1237ae0e2c9SDimitry Andric   }
1247ae0e2c9SDimitry Andric 
1257ae0e2c9SDimitry Andric   // Using instr wasn't found, it could be in another block.
1267ae0e2c9SDimitry Andric   // Leave the physreg IMPLICIT_DEF, but trim any extra operands.
1277ae0e2c9SDimitry Andric   for (unsigned i = MI->getNumOperands() - 1; i; --i)
1287ae0e2c9SDimitry Andric     MI->RemoveOperand(i);
1297ae0e2c9SDimitry Andric   DEBUG(dbgs() << "Keeping physreg: " << *MI);
1307ae0e2c9SDimitry Andric }
1317ae0e2c9SDimitry Andric 
1327ae0e2c9SDimitry Andric /// processImplicitDefs - Process IMPLICIT_DEF instructions and turn them into
1337ae0e2c9SDimitry Andric /// <undef> operands.
1347ae0e2c9SDimitry Andric bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &MF) {
135f22ef01cSRoman Divacky 
136f22ef01cSRoman Divacky   DEBUG(dbgs() << "********** PROCESS IMPLICIT DEFS **********\n"
1373861d79fSDimitry Andric                << "********** Function: " << MF.getName() << '\n');
138f22ef01cSRoman Divacky 
139f22ef01cSRoman Divacky   bool Changed = false;
140f22ef01cSRoman Divacky 
1417ae0e2c9SDimitry Andric   TII = MF.getTarget().getInstrInfo();
1427ae0e2c9SDimitry Andric   TRI = MF.getTarget().getRegisterInfo();
1437ae0e2c9SDimitry Andric   MRI = &MF.getRegInfo();
1447ae0e2c9SDimitry Andric   assert(MRI->isSSA() && "ProcessImplicitDefs only works on SSA form.");
1457ae0e2c9SDimitry Andric   assert(WorkList.empty() && "Inconsistent worklist state");
146f22ef01cSRoman Divacky 
1477ae0e2c9SDimitry Andric   for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end();
1487ae0e2c9SDimitry Andric        MFI != MFE; ++MFI) {
1497ae0e2c9SDimitry Andric     // Scan the basic block for implicit defs.
1507ae0e2c9SDimitry Andric     for (MachineBasicBlock::instr_iterator MBBI = MFI->instr_begin(),
1517ae0e2c9SDimitry Andric          MBBE = MFI->instr_end(); MBBI != MBBE; ++MBBI)
1527ae0e2c9SDimitry Andric       if (MBBI->isImplicitDef())
1537ae0e2c9SDimitry Andric         WorkList.insert(MBBI);
154f22ef01cSRoman Divacky 
1557ae0e2c9SDimitry Andric     if (WorkList.empty())
156f22ef01cSRoman Divacky       continue;
157f22ef01cSRoman Divacky 
1587ae0e2c9SDimitry Andric     DEBUG(dbgs() << "BB#" << MFI->getNumber() << " has " << WorkList.size()
1597ae0e2c9SDimitry Andric                  << " implicit defs.\n");
160f22ef01cSRoman Divacky     Changed = true;
1616122f3e6SDimitry Andric 
1627ae0e2c9SDimitry Andric     // Drain the WorkList to recursively process any new implicit defs.
1637ae0e2c9SDimitry Andric     do processImplicitDef(WorkList.pop_back_val());
1647ae0e2c9SDimitry Andric     while (!WorkList.empty());
165f22ef01cSRoman Divacky   }
166f22ef01cSRoman Divacky   return Changed;
167f22ef01cSRoman Divacky }
168