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"
162cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
172cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
18f22ef01cSRoman Divacky #include "llvm/Support/Debug.h"
197ae0e2c9SDimitry Andric #include "llvm/Support/raw_ostream.h"
20f22ef01cSRoman Divacky 
21f22ef01cSRoman Divacky using namespace llvm;
22f22ef01cSRoman Divacky 
23302affcbSDimitry Andric #define DEBUG_TYPE "processimpdefs"
2491bc56edSDimitry Andric 
257ae0e2c9SDimitry Andric namespace {
267ae0e2c9SDimitry Andric /// Process IMPLICIT_DEF instructions and make sure there is one implicit_def
277ae0e2c9SDimitry Andric /// for each use. Add isUndef marker to implicit_def defs and their uses.
287ae0e2c9SDimitry Andric class ProcessImplicitDefs : public MachineFunctionPass {
297ae0e2c9SDimitry Andric   const TargetInstrInfo *TII;
307ae0e2c9SDimitry Andric   const TargetRegisterInfo *TRI;
317ae0e2c9SDimitry Andric   MachineRegisterInfo *MRI;
327ae0e2c9SDimitry Andric 
337ae0e2c9SDimitry Andric   SmallSetVector<MachineInstr*, 16> WorkList;
347ae0e2c9SDimitry Andric 
357ae0e2c9SDimitry Andric   void processImplicitDef(MachineInstr *MI);
367ae0e2c9SDimitry Andric   bool canTurnIntoImplicitDef(MachineInstr *MI);
377ae0e2c9SDimitry Andric 
387ae0e2c9SDimitry Andric public:
397ae0e2c9SDimitry Andric   static char ID;
407ae0e2c9SDimitry Andric 
ProcessImplicitDefs()417ae0e2c9SDimitry Andric   ProcessImplicitDefs() : MachineFunctionPass(ID) {
427ae0e2c9SDimitry Andric     initializeProcessImplicitDefsPass(*PassRegistry::getPassRegistry());
437ae0e2c9SDimitry Andric   }
447ae0e2c9SDimitry Andric 
4591bc56edSDimitry Andric   void getAnalysisUsage(AnalysisUsage &au) const override;
467ae0e2c9SDimitry Andric 
47*4ba319b5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
487ae0e2c9SDimitry Andric };
497ae0e2c9SDimitry Andric } // end anonymous namespace
507ae0e2c9SDimitry Andric 
51f22ef01cSRoman Divacky char ProcessImplicitDefs::ID = 0;
52dff0c46cSDimitry Andric char &llvm::ProcessImplicitDefsID = ProcessImplicitDefs::ID;
53dff0c46cSDimitry Andric 
54302affcbSDimitry Andric INITIALIZE_PASS(ProcessImplicitDefs, DEBUG_TYPE,
552754fe60SDimitry Andric                 "Process Implicit Definitions", false, false)
56f22ef01cSRoman Divacky 
getAnalysisUsage(AnalysisUsage & AU) const57f22ef01cSRoman Divacky void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const {
58f22ef01cSRoman Divacky   AU.setPreservesCFG();
597d523365SDimitry Andric   AU.addPreserved<AAResultsWrapperPass>();
60f22ef01cSRoman Divacky   MachineFunctionPass::getAnalysisUsage(AU);
61f22ef01cSRoman Divacky }
62f22ef01cSRoman Divacky 
canTurnIntoImplicitDef(MachineInstr * MI)637ae0e2c9SDimitry Andric bool ProcessImplicitDefs::canTurnIntoImplicitDef(MachineInstr *MI) {
647ae0e2c9SDimitry Andric   if (!MI->isCopyLike() &&
657ae0e2c9SDimitry Andric       !MI->isInsertSubreg() &&
667ae0e2c9SDimitry Andric       !MI->isRegSequence() &&
677ae0e2c9SDimitry Andric       !MI->isPHI())
68ffd1746dSEd Schouten     return false;
6997bc6c73SDimitry Andric   for (const MachineOperand &MO : MI->operands())
7097bc6c73SDimitry Andric     if (MO.isReg() && MO.isUse() && MO.readsReg())
717ae0e2c9SDimitry Andric       return false;
72f22ef01cSRoman Divacky   return true;
73f22ef01cSRoman Divacky }
74f22ef01cSRoman Divacky 
processImplicitDef(MachineInstr * MI)757ae0e2c9SDimitry Andric void ProcessImplicitDefs::processImplicitDef(MachineInstr *MI) {
76*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Processing " << *MI);
777ae0e2c9SDimitry Andric   unsigned Reg = MI->getOperand(0).getReg();
787ae0e2c9SDimitry Andric 
797ae0e2c9SDimitry Andric   if (TargetRegisterInfo::isVirtualRegister(Reg)) {
80f785676fSDimitry Andric     // For virtual registers, mark all uses as <undef>, and convert users to
817ae0e2c9SDimitry Andric     // implicit-def when possible.
8291bc56edSDimitry Andric     for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
837ae0e2c9SDimitry Andric       MO.setIsUndef();
847ae0e2c9SDimitry Andric       MachineInstr *UserMI = MO.getParent();
857ae0e2c9SDimitry Andric       if (!canTurnIntoImplicitDef(UserMI))
867ae0e2c9SDimitry Andric         continue;
87*4ba319b5SDimitry Andric       LLVM_DEBUG(dbgs() << "Converting to IMPLICIT_DEF: " << *UserMI);
887ae0e2c9SDimitry Andric       UserMI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF));
897ae0e2c9SDimitry Andric       WorkList.insert(UserMI);
907ae0e2c9SDimitry Andric     }
917ae0e2c9SDimitry Andric     MI->eraseFromParent();
927ae0e2c9SDimitry Andric     return;
937ae0e2c9SDimitry Andric   }
947ae0e2c9SDimitry Andric 
957ae0e2c9SDimitry Andric   // This is a physreg implicit-def.
967ae0e2c9SDimitry Andric   // Look for the first instruction to use or define an alias.
977d523365SDimitry Andric   MachineBasicBlock::instr_iterator UserMI = MI->getIterator();
987ae0e2c9SDimitry Andric   MachineBasicBlock::instr_iterator UserE = MI->getParent()->instr_end();
997ae0e2c9SDimitry Andric   bool Found = false;
1007ae0e2c9SDimitry Andric   for (++UserMI; UserMI != UserE; ++UserMI) {
10197bc6c73SDimitry Andric     for (MachineOperand &MO : UserMI->operands()) {
10297bc6c73SDimitry Andric       if (!MO.isReg())
1037ae0e2c9SDimitry Andric         continue;
10497bc6c73SDimitry Andric       unsigned UserReg = MO.getReg();
1057ae0e2c9SDimitry Andric       if (!TargetRegisterInfo::isPhysicalRegister(UserReg) ||
1067ae0e2c9SDimitry Andric           !TRI->regsOverlap(Reg, UserReg))
1077ae0e2c9SDimitry Andric         continue;
1087ae0e2c9SDimitry Andric       // UserMI uses or redefines Reg. Set <undef> flags on all uses.
1097ae0e2c9SDimitry Andric       Found = true;
11097bc6c73SDimitry Andric       if (MO.isUse())
11197bc6c73SDimitry Andric         MO.setIsUndef();
1127ae0e2c9SDimitry Andric     }
1137ae0e2c9SDimitry Andric     if (Found)
1147ae0e2c9SDimitry Andric       break;
1157ae0e2c9SDimitry Andric   }
1167ae0e2c9SDimitry Andric 
1177ae0e2c9SDimitry Andric   // If we found the using MI, we can erase the IMPLICIT_DEF.
1187ae0e2c9SDimitry Andric   if (Found) {
119*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Physreg user: " << *UserMI);
1207ae0e2c9SDimitry Andric     MI->eraseFromParent();
1217ae0e2c9SDimitry Andric     return;
1227ae0e2c9SDimitry Andric   }
1237ae0e2c9SDimitry Andric 
1247ae0e2c9SDimitry Andric   // Using instr wasn't found, it could be in another block.
1257ae0e2c9SDimitry Andric   // Leave the physreg IMPLICIT_DEF, but trim any extra operands.
1267ae0e2c9SDimitry Andric   for (unsigned i = MI->getNumOperands() - 1; i; --i)
1277ae0e2c9SDimitry Andric     MI->RemoveOperand(i);
128*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Keeping physreg: " << *MI);
1297ae0e2c9SDimitry Andric }
1307ae0e2c9SDimitry Andric 
1317ae0e2c9SDimitry Andric /// processImplicitDefs - Process IMPLICIT_DEF instructions and turn them into
1327ae0e2c9SDimitry Andric /// <undef> operands.
runOnMachineFunction(MachineFunction & MF)1337ae0e2c9SDimitry Andric bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &MF) {
134f22ef01cSRoman Divacky 
135*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "********** PROCESS IMPLICIT DEFS **********\n"
1363861d79fSDimitry Andric                     << "********** Function: " << MF.getName() << '\n');
137f22ef01cSRoman Divacky 
138f22ef01cSRoman Divacky   bool Changed = false;
139f22ef01cSRoman Divacky 
14039d628a0SDimitry Andric   TII = MF.getSubtarget().getInstrInfo();
14139d628a0SDimitry Andric   TRI = MF.getSubtarget().getRegisterInfo();
1427ae0e2c9SDimitry Andric   MRI = &MF.getRegInfo();
1437ae0e2c9SDimitry Andric   assert(MRI->isSSA() && "ProcessImplicitDefs only works on SSA form.");
1447ae0e2c9SDimitry Andric   assert(WorkList.empty() && "Inconsistent worklist state");
145f22ef01cSRoman Divacky 
1467ae0e2c9SDimitry Andric   for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end();
1477ae0e2c9SDimitry Andric        MFI != MFE; ++MFI) {
1487ae0e2c9SDimitry Andric     // Scan the basic block for implicit defs.
1497ae0e2c9SDimitry Andric     for (MachineBasicBlock::instr_iterator MBBI = MFI->instr_begin(),
1507ae0e2c9SDimitry Andric          MBBE = MFI->instr_end(); MBBI != MBBE; ++MBBI)
1517ae0e2c9SDimitry Andric       if (MBBI->isImplicitDef())
1527d523365SDimitry Andric         WorkList.insert(&*MBBI);
153f22ef01cSRoman Divacky 
1547ae0e2c9SDimitry Andric     if (WorkList.empty())
155f22ef01cSRoman Divacky       continue;
156f22ef01cSRoman Divacky 
157*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << printMBBReference(*MFI) << " has " << WorkList.size()
1587ae0e2c9SDimitry Andric                       << " implicit defs.\n");
159f22ef01cSRoman Divacky     Changed = true;
1606122f3e6SDimitry Andric 
1617ae0e2c9SDimitry Andric     // Drain the WorkList to recursively process any new implicit defs.
1627ae0e2c9SDimitry Andric     do processImplicitDef(WorkList.pop_back_val());
1637ae0e2c9SDimitry Andric     while (!WorkList.empty());
164f22ef01cSRoman Divacky   }
165f22ef01cSRoman Divacky   return Changed;
166f22ef01cSRoman Divacky }
167