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