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