|  | //===-- lib/CodeGen/MachineInstrBundle.cpp --------------------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/CodeGen/MachineInstrBundle.h" | 
|  | #include "llvm/ADT/SmallSet.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | #include "llvm/CodeGen/Passes.h" | 
|  | #include "llvm/CodeGen/TargetInstrInfo.h" | 
|  | #include "llvm/CodeGen/TargetRegisterInfo.h" | 
|  | #include "llvm/CodeGen/TargetSubtargetInfo.h" | 
|  | #include "llvm/Target/TargetMachine.h" | 
|  | #include <utility> | 
|  | using namespace llvm; | 
|  |  | 
|  | namespace { | 
|  | class UnpackMachineBundles : public MachineFunctionPass { | 
|  | public: | 
|  | static char ID; // Pass identification | 
|  | UnpackMachineBundles( | 
|  | std::function<bool(const MachineFunction &)> Ftor = nullptr) | 
|  | : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) { | 
|  | initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry()); | 
|  | } | 
|  |  | 
|  | bool runOnMachineFunction(MachineFunction &MF) override; | 
|  |  | 
|  | private: | 
|  | std::function<bool(const MachineFunction &)> PredicateFtor; | 
|  | }; | 
|  | } // end anonymous namespace | 
|  |  | 
|  | char UnpackMachineBundles::ID = 0; | 
|  | char &llvm::UnpackMachineBundlesID = UnpackMachineBundles::ID; | 
|  | INITIALIZE_PASS(UnpackMachineBundles, "unpack-mi-bundles", | 
|  | "Unpack machine instruction bundles", false, false) | 
|  |  | 
|  | bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) { | 
|  | if (PredicateFtor && !PredicateFtor(MF)) | 
|  | return false; | 
|  |  | 
|  | bool Changed = false; | 
|  | for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { | 
|  | MachineBasicBlock *MBB = &*I; | 
|  |  | 
|  | for (MachineBasicBlock::instr_iterator MII = MBB->instr_begin(), | 
|  | MIE = MBB->instr_end(); MII != MIE; ) { | 
|  | MachineInstr *MI = &*MII; | 
|  |  | 
|  | // Remove BUNDLE instruction and the InsideBundle flags from bundled | 
|  | // instructions. | 
|  | if (MI->isBundle()) { | 
|  | while (++MII != MIE && MII->isBundledWithPred()) { | 
|  | MII->unbundleFromPred(); | 
|  | for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { | 
|  | MachineOperand &MO = MII->getOperand(i); | 
|  | if (MO.isReg() && MO.isInternalRead()) | 
|  | MO.setIsInternalRead(false); | 
|  | } | 
|  | } | 
|  | MI->eraseFromParent(); | 
|  |  | 
|  | Changed = true; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | ++MII; | 
|  | } | 
|  | } | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | FunctionPass * | 
|  | llvm::createUnpackMachineBundles( | 
|  | std::function<bool(const MachineFunction &)> Ftor) { | 
|  | return new UnpackMachineBundles(std::move(Ftor)); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  | class FinalizeMachineBundles : public MachineFunctionPass { | 
|  | public: | 
|  | static char ID; // Pass identification | 
|  | FinalizeMachineBundles() : MachineFunctionPass(ID) { | 
|  | initializeFinalizeMachineBundlesPass(*PassRegistry::getPassRegistry()); | 
|  | } | 
|  |  | 
|  | bool runOnMachineFunction(MachineFunction &MF) override; | 
|  | }; | 
|  | } // end anonymous namespace | 
|  |  | 
|  | char FinalizeMachineBundles::ID = 0; | 
|  | char &llvm::FinalizeMachineBundlesID = FinalizeMachineBundles::ID; | 
|  | INITIALIZE_PASS(FinalizeMachineBundles, "finalize-mi-bundles", | 
|  | "Finalize machine instruction bundles", false, false) | 
|  |  | 
|  | bool FinalizeMachineBundles::runOnMachineFunction(MachineFunction &MF) { | 
|  | return llvm::finalizeBundles(MF); | 
|  | } | 
|  |  | 
|  |  | 
|  | /// finalizeBundle - Finalize a machine instruction bundle which includes | 
|  | /// a sequence of instructions starting from FirstMI to LastMI (exclusive). | 
|  | /// This routine adds a BUNDLE instruction to represent the bundle, it adds | 
|  | /// IsInternalRead markers to MachineOperands which are defined inside the | 
|  | /// bundle, and it copies externally visible defs and uses to the BUNDLE | 
|  | /// instruction. | 
|  | void llvm::finalizeBundle(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::instr_iterator FirstMI, | 
|  | MachineBasicBlock::instr_iterator LastMI) { | 
|  | assert(FirstMI != LastMI && "Empty bundle?"); | 
|  | MIBundleBuilder Bundle(MBB, FirstMI, LastMI); | 
|  |  | 
|  | MachineFunction &MF = *MBB.getParent(); | 
|  | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); | 
|  | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); | 
|  |  | 
|  | MachineInstrBuilder MIB = | 
|  | BuildMI(MF, FirstMI->getDebugLoc(), TII->get(TargetOpcode::BUNDLE)); | 
|  | Bundle.prepend(MIB); | 
|  |  | 
|  | SmallVector<unsigned, 32> LocalDefs; | 
|  | SmallSet<unsigned, 32> LocalDefSet; | 
|  | SmallSet<unsigned, 8> DeadDefSet; | 
|  | SmallSet<unsigned, 16> KilledDefSet; | 
|  | SmallVector<unsigned, 8> ExternUses; | 
|  | SmallSet<unsigned, 8> ExternUseSet; | 
|  | SmallSet<unsigned, 8> KilledUseSet; | 
|  | SmallSet<unsigned, 8> UndefUseSet; | 
|  | SmallVector<MachineOperand*, 4> Defs; | 
|  | for (; FirstMI != LastMI; ++FirstMI) { | 
|  | for (unsigned i = 0, e = FirstMI->getNumOperands(); i != e; ++i) { | 
|  | MachineOperand &MO = FirstMI->getOperand(i); | 
|  | if (!MO.isReg()) | 
|  | continue; | 
|  | if (MO.isDef()) { | 
|  | Defs.push_back(&MO); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | unsigned Reg = MO.getReg(); | 
|  | if (!Reg) | 
|  | continue; | 
|  | assert(TargetRegisterInfo::isPhysicalRegister(Reg)); | 
|  | if (LocalDefSet.count(Reg)) { | 
|  | MO.setIsInternalRead(); | 
|  | if (MO.isKill()) | 
|  | // Internal def is now killed. | 
|  | KilledDefSet.insert(Reg); | 
|  | } else { | 
|  | if (ExternUseSet.insert(Reg).second) { | 
|  | ExternUses.push_back(Reg); | 
|  | if (MO.isUndef()) | 
|  | UndefUseSet.insert(Reg); | 
|  | } | 
|  | if (MO.isKill()) | 
|  | // External def is now killed. | 
|  | KilledUseSet.insert(Reg); | 
|  | } | 
|  | } | 
|  |  | 
|  | for (unsigned i = 0, e = Defs.size(); i != e; ++i) { | 
|  | MachineOperand &MO = *Defs[i]; | 
|  | unsigned Reg = MO.getReg(); | 
|  | if (!Reg) | 
|  | continue; | 
|  |  | 
|  | if (LocalDefSet.insert(Reg).second) { | 
|  | LocalDefs.push_back(Reg); | 
|  | if (MO.isDead()) { | 
|  | DeadDefSet.insert(Reg); | 
|  | } | 
|  | } else { | 
|  | // Re-defined inside the bundle, it's no longer killed. | 
|  | KilledDefSet.erase(Reg); | 
|  | if (!MO.isDead()) | 
|  | // Previously defined but dead. | 
|  | DeadDefSet.erase(Reg); | 
|  | } | 
|  |  | 
|  | if (!MO.isDead()) { | 
|  | for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) { | 
|  | unsigned SubReg = *SubRegs; | 
|  | if (LocalDefSet.insert(SubReg).second) | 
|  | LocalDefs.push_back(SubReg); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | Defs.clear(); | 
|  | } | 
|  |  | 
|  | SmallSet<unsigned, 32> Added; | 
|  | for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) { | 
|  | unsigned Reg = LocalDefs[i]; | 
|  | if (Added.insert(Reg).second) { | 
|  | // If it's not live beyond end of the bundle, mark it dead. | 
|  | bool isDead = DeadDefSet.count(Reg) || KilledDefSet.count(Reg); | 
|  | MIB.addReg(Reg, getDefRegState(true) | getDeadRegState(isDead) | | 
|  | getImplRegState(true)); | 
|  | } | 
|  | } | 
|  |  | 
|  | for (unsigned i = 0, e = ExternUses.size(); i != e; ++i) { | 
|  | unsigned Reg = ExternUses[i]; | 
|  | bool isKill = KilledUseSet.count(Reg); | 
|  | bool isUndef = UndefUseSet.count(Reg); | 
|  | MIB.addReg(Reg, getKillRegState(isKill) | getUndefRegState(isUndef) | | 
|  | getImplRegState(true)); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// finalizeBundle - Same functionality as the previous finalizeBundle except | 
|  | /// the last instruction in the bundle is not provided as an input. This is | 
|  | /// used in cases where bundles are pre-determined by marking instructions | 
|  | /// with 'InsideBundle' marker. It returns the MBB instruction iterator that | 
|  | /// points to the end of the bundle. | 
|  | MachineBasicBlock::instr_iterator | 
|  | llvm::finalizeBundle(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::instr_iterator FirstMI) { | 
|  | MachineBasicBlock::instr_iterator E = MBB.instr_end(); | 
|  | MachineBasicBlock::instr_iterator LastMI = std::next(FirstMI); | 
|  | while (LastMI != E && LastMI->isInsideBundle()) | 
|  | ++LastMI; | 
|  | finalizeBundle(MBB, FirstMI, LastMI); | 
|  | return LastMI; | 
|  | } | 
|  |  | 
|  | /// finalizeBundles - Finalize instruction bundles in the specified | 
|  | /// MachineFunction. Return true if any bundles are finalized. | 
|  | bool llvm::finalizeBundles(MachineFunction &MF) { | 
|  | bool Changed = false; | 
|  | for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { | 
|  | MachineBasicBlock &MBB = *I; | 
|  | MachineBasicBlock::instr_iterator MII = MBB.instr_begin(); | 
|  | MachineBasicBlock::instr_iterator MIE = MBB.instr_end(); | 
|  | if (MII == MIE) | 
|  | continue; | 
|  | assert(!MII->isInsideBundle() && | 
|  | "First instr cannot be inside bundle before finalization!"); | 
|  |  | 
|  | for (++MII; MII != MIE; ) { | 
|  | if (!MII->isInsideBundle()) | 
|  | ++MII; | 
|  | else { | 
|  | MII = finalizeBundle(MBB, std::prev(MII)); | 
|  | Changed = true; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // MachineOperand iterator | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | MachineOperandIteratorBase::VirtRegInfo | 
|  | MachineOperandIteratorBase::analyzeVirtReg(unsigned Reg, | 
|  | SmallVectorImpl<std::pair<MachineInstr*, unsigned> > *Ops) { | 
|  | VirtRegInfo RI = { false, false, false }; | 
|  | for(; isValid(); ++*this) { | 
|  | MachineOperand &MO = deref(); | 
|  | if (!MO.isReg() || MO.getReg() != Reg) | 
|  | continue; | 
|  |  | 
|  | // Remember each (MI, OpNo) that refers to Reg. | 
|  | if (Ops) | 
|  | Ops->push_back(std::make_pair(MO.getParent(), getOperandNo())); | 
|  |  | 
|  | // Both defs and uses can read virtual registers. | 
|  | if (MO.readsReg()) { | 
|  | RI.Reads = true; | 
|  | if (MO.isDef()) | 
|  | RI.Tied = true; | 
|  | } | 
|  |  | 
|  | // Only defs can write. | 
|  | if (MO.isDef()) | 
|  | RI.Writes = true; | 
|  | else if (!RI.Tied && MO.getParent()->isRegTiedToDefOperand(getOperandNo())) | 
|  | RI.Tied = true; | 
|  | } | 
|  | return RI; | 
|  | } | 
|  |  | 
|  | MachineOperandIteratorBase::PhysRegInfo | 
|  | MachineOperandIteratorBase::analyzePhysReg(unsigned Reg, | 
|  | const TargetRegisterInfo *TRI) { | 
|  | bool AllDefsDead = true; | 
|  | PhysRegInfo PRI = {false, false, false, false, false, false, false, false}; | 
|  |  | 
|  | assert(TargetRegisterInfo::isPhysicalRegister(Reg) && | 
|  | "analyzePhysReg not given a physical register!"); | 
|  | for (; isValid(); ++*this) { | 
|  | MachineOperand &MO = deref(); | 
|  |  | 
|  | if (MO.isRegMask() && MO.clobbersPhysReg(Reg)) { | 
|  | PRI.Clobbered = true; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (!MO.isReg()) | 
|  | continue; | 
|  |  | 
|  | unsigned MOReg = MO.getReg(); | 
|  | if (!MOReg || !TargetRegisterInfo::isPhysicalRegister(MOReg)) | 
|  | continue; | 
|  |  | 
|  | if (!TRI->regsOverlap(MOReg, Reg)) | 
|  | continue; | 
|  |  | 
|  | bool Covered = TRI->isSuperRegisterEq(Reg, MOReg); | 
|  | if (MO.readsReg()) { | 
|  | PRI.Read = true; | 
|  | if (Covered) { | 
|  | PRI.FullyRead = true; | 
|  | if (MO.isKill()) | 
|  | PRI.Killed = true; | 
|  | } | 
|  | } else if (MO.isDef()) { | 
|  | PRI.Defined = true; | 
|  | if (Covered) | 
|  | PRI.FullyDefined = true; | 
|  | if (!MO.isDead()) | 
|  | AllDefsDead = false; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (AllDefsDead) { | 
|  | if (PRI.FullyDefined || PRI.Clobbered) | 
|  | PRI.DeadDef = true; | 
|  | else if (PRI.Defined) | 
|  | PRI.PartialDeadDef = true; | 
|  | } | 
|  |  | 
|  | return PRI; | 
|  | } |