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" 1939d628a0SDimitry Andric #include "llvm/Target/TargetSubtargetInfo.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 417ae0e2c9SDimitry Andric ProcessImplicitDefs() : MachineFunctionPass(ID) { 427ae0e2c9SDimitry Andric initializeProcessImplicitDefsPass(*PassRegistry::getPassRegistry()); 437ae0e2c9SDimitry Andric } 447ae0e2c9SDimitry Andric 4591bc56edSDimitry Andric void getAnalysisUsage(AnalysisUsage &au) const override; 467ae0e2c9SDimitry Andric 4791bc56edSDimitry Andric bool runOnMachineFunction(MachineFunction &fn) 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 57f22ef01cSRoman 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 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 757ae0e2c9SDimitry Andric void ProcessImplicitDefs::processImplicitDef(MachineInstr *MI) { 767ae0e2c9SDimitry Andric 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; 877ae0e2c9SDimitry Andric 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) { 1197ae0e2c9SDimitry Andric 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); 1287ae0e2c9SDimitry Andric DEBUG(dbgs() << "Keeping physreg: " << *MI); 1297ae0e2c9SDimitry Andric } 1307ae0e2c9SDimitry Andric 1317ae0e2c9SDimitry Andric /// processImplicitDefs - Process IMPLICIT_DEF instructions and turn them into 1327ae0e2c9SDimitry Andric /// <undef> operands. 1337ae0e2c9SDimitry Andric bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &MF) { 134f22ef01cSRoman Divacky 135f22ef01cSRoman Divacky 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 1577ae0e2c9SDimitry Andric DEBUG(dbgs() << "BB#" << MFI->getNumber() << " 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