1234285Sdim//===-- lib/CodeGen/MachineInstrBundle.cpp --------------------------------===// 2234285Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6234285Sdim// 7234285Sdim//===----------------------------------------------------------------------===// 8234285Sdim 9234285Sdim#include "llvm/CodeGen/MachineInstrBundle.h" 10249423Sdim#include "llvm/ADT/SmallSet.h" 11249423Sdim#include "llvm/ADT/SmallVector.h" 12249423Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 13234285Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 14234285Sdim#include "llvm/CodeGen/Passes.h" 15327952Sdim#include "llvm/CodeGen/TargetInstrInfo.h" 16327952Sdim#include "llvm/CodeGen/TargetRegisterInfo.h" 17327952Sdim#include "llvm/CodeGen/TargetSubtargetInfo.h" 18360784Sdim#include "llvm/InitializePasses.h" 19234285Sdim#include "llvm/Target/TargetMachine.h" 20309124Sdim#include <utility> 21234285Sdimusing namespace llvm; 22234285Sdim 23234285Sdimnamespace { 24234285Sdim class UnpackMachineBundles : public MachineFunctionPass { 25234285Sdim public: 26234285Sdim static char ID; // Pass identification 27314564Sdim UnpackMachineBundles( 28314564Sdim std::function<bool(const MachineFunction &)> Ftor = nullptr) 29309124Sdim : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) { 30234285Sdim initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry()); 31234285Sdim } 32234285Sdim 33276479Sdim bool runOnMachineFunction(MachineFunction &MF) override; 34288943Sdim 35288943Sdim private: 36314564Sdim std::function<bool(const MachineFunction &)> PredicateFtor; 37234285Sdim }; 38234285Sdim} // end anonymous namespace 39234285Sdim 40234285Sdimchar UnpackMachineBundles::ID = 0; 41234285Sdimchar &llvm::UnpackMachineBundlesID = UnpackMachineBundles::ID; 42234285SdimINITIALIZE_PASS(UnpackMachineBundles, "unpack-mi-bundles", 43234285Sdim "Unpack machine instruction bundles", false, false) 44234285Sdim 45234285Sdimbool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) { 46314564Sdim if (PredicateFtor && !PredicateFtor(MF)) 47288943Sdim return false; 48288943Sdim 49234285Sdim bool Changed = false; 50234285Sdim for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { 51234285Sdim MachineBasicBlock *MBB = &*I; 52234285Sdim 53234285Sdim for (MachineBasicBlock::instr_iterator MII = MBB->instr_begin(), 54234285Sdim MIE = MBB->instr_end(); MII != MIE; ) { 55234285Sdim MachineInstr *MI = &*MII; 56234285Sdim 57234285Sdim // Remove BUNDLE instruction and the InsideBundle flags from bundled 58234285Sdim // instructions. 59234285Sdim if (MI->isBundle()) { 60249423Sdim while (++MII != MIE && MII->isBundledWithPred()) { 61249423Sdim MII->unbundleFromPred(); 62234285Sdim for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { 63234285Sdim MachineOperand &MO = MII->getOperand(i); 64234285Sdim if (MO.isReg() && MO.isInternalRead()) 65234285Sdim MO.setIsInternalRead(false); 66234285Sdim } 67234285Sdim } 68234285Sdim MI->eraseFromParent(); 69234285Sdim 70234285Sdim Changed = true; 71234285Sdim continue; 72234285Sdim } 73234285Sdim 74234285Sdim ++MII; 75234285Sdim } 76234285Sdim } 77234285Sdim 78234285Sdim return Changed; 79234285Sdim} 80234285Sdim 81288943SdimFunctionPass * 82314564Sdimllvm::createUnpackMachineBundles( 83314564Sdim std::function<bool(const MachineFunction &)> Ftor) { 84309124Sdim return new UnpackMachineBundles(std::move(Ftor)); 85288943Sdim} 86234285Sdim 87234285Sdimnamespace { 88234285Sdim class FinalizeMachineBundles : public MachineFunctionPass { 89234285Sdim public: 90234285Sdim static char ID; // Pass identification 91234285Sdim FinalizeMachineBundles() : MachineFunctionPass(ID) { 92234285Sdim initializeFinalizeMachineBundlesPass(*PassRegistry::getPassRegistry()); 93234285Sdim } 94234285Sdim 95276479Sdim bool runOnMachineFunction(MachineFunction &MF) override; 96234285Sdim }; 97234285Sdim} // end anonymous namespace 98234285Sdim 99234285Sdimchar FinalizeMachineBundles::ID = 0; 100234285Sdimchar &llvm::FinalizeMachineBundlesID = FinalizeMachineBundles::ID; 101234285SdimINITIALIZE_PASS(FinalizeMachineBundles, "finalize-mi-bundles", 102234285Sdim "Finalize machine instruction bundles", false, false) 103234285Sdim 104234285Sdimbool FinalizeMachineBundles::runOnMachineFunction(MachineFunction &MF) { 105234285Sdim return llvm::finalizeBundles(MF); 106234285Sdim} 107234285Sdim 108344779Sdim/// Return the first found DebugLoc that has a DILocation, given a range of 109344779Sdim/// instructions. The search range is from FirstMI to LastMI (exclusive). If no 110344779Sdim/// DILocation is found, then an empty location is returned. 111344779Sdimstatic DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, 112344779Sdim MachineBasicBlock::instr_iterator LastMI) { 113344779Sdim for (auto MII = FirstMI; MII != LastMI; ++MII) 114344779Sdim if (MII->getDebugLoc().get()) 115344779Sdim return MII->getDebugLoc(); 116344779Sdim return DebugLoc(); 117344779Sdim} 118234285Sdim 119234285Sdim/// finalizeBundle - Finalize a machine instruction bundle which includes 120234285Sdim/// a sequence of instructions starting from FirstMI to LastMI (exclusive). 121234285Sdim/// This routine adds a BUNDLE instruction to represent the bundle, it adds 122234285Sdim/// IsInternalRead markers to MachineOperands which are defined inside the 123234285Sdim/// bundle, and it copies externally visible defs and uses to the BUNDLE 124234285Sdim/// instruction. 125234285Sdimvoid llvm::finalizeBundle(MachineBasicBlock &MBB, 126234285Sdim MachineBasicBlock::instr_iterator FirstMI, 127234285Sdim MachineBasicBlock::instr_iterator LastMI) { 128234285Sdim assert(FirstMI != LastMI && "Empty bundle?"); 129249423Sdim MIBundleBuilder Bundle(MBB, FirstMI, LastMI); 130234285Sdim 131280031Sdim MachineFunction &MF = *MBB.getParent(); 132280031Sdim const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 133280031Sdim const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 134234285Sdim 135280031Sdim MachineInstrBuilder MIB = 136344779Sdim BuildMI(MF, getDebugLoc(FirstMI, LastMI), TII->get(TargetOpcode::BUNDLE)); 137249423Sdim Bundle.prepend(MIB); 138234285Sdim 139243830Sdim SmallVector<unsigned, 32> LocalDefs; 140243830Sdim SmallSet<unsigned, 32> LocalDefSet; 141234285Sdim SmallSet<unsigned, 8> DeadDefSet; 142243830Sdim SmallSet<unsigned, 16> KilledDefSet; 143234285Sdim SmallVector<unsigned, 8> ExternUses; 144234285Sdim SmallSet<unsigned, 8> ExternUseSet; 145234285Sdim SmallSet<unsigned, 8> KilledUseSet; 146234285Sdim SmallSet<unsigned, 8> UndefUseSet; 147234285Sdim SmallVector<MachineOperand*, 4> Defs; 148344779Sdim for (auto MII = FirstMI; MII != LastMI; ++MII) { 149344779Sdim for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { 150344779Sdim MachineOperand &MO = MII->getOperand(i); 151234285Sdim if (!MO.isReg()) 152234285Sdim continue; 153234285Sdim if (MO.isDef()) { 154234285Sdim Defs.push_back(&MO); 155234285Sdim continue; 156234285Sdim } 157234285Sdim 158360784Sdim Register Reg = MO.getReg(); 159234285Sdim if (!Reg) 160234285Sdim continue; 161360784Sdim 162234285Sdim if (LocalDefSet.count(Reg)) { 163234285Sdim MO.setIsInternalRead(); 164234285Sdim if (MO.isKill()) 165234285Sdim // Internal def is now killed. 166234285Sdim KilledDefSet.insert(Reg); 167234285Sdim } else { 168280031Sdim if (ExternUseSet.insert(Reg).second) { 169234285Sdim ExternUses.push_back(Reg); 170234285Sdim if (MO.isUndef()) 171234285Sdim UndefUseSet.insert(Reg); 172234285Sdim } 173234285Sdim if (MO.isKill()) 174234285Sdim // External def is now killed. 175234285Sdim KilledUseSet.insert(Reg); 176234285Sdim } 177234285Sdim } 178234285Sdim 179234285Sdim for (unsigned i = 0, e = Defs.size(); i != e; ++i) { 180234285Sdim MachineOperand &MO = *Defs[i]; 181360784Sdim Register Reg = MO.getReg(); 182234285Sdim if (!Reg) 183234285Sdim continue; 184234285Sdim 185280031Sdim if (LocalDefSet.insert(Reg).second) { 186234285Sdim LocalDefs.push_back(Reg); 187234285Sdim if (MO.isDead()) { 188234285Sdim DeadDefSet.insert(Reg); 189234285Sdim } 190234285Sdim } else { 191234285Sdim // Re-defined inside the bundle, it's no longer killed. 192234285Sdim KilledDefSet.erase(Reg); 193234285Sdim if (!MO.isDead()) 194234285Sdim // Previously defined but dead. 195234285Sdim DeadDefSet.erase(Reg); 196234285Sdim } 197234285Sdim 198360784Sdim if (!MO.isDead() && Register::isPhysicalRegister(Reg)) { 199239462Sdim for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) { 200239462Sdim unsigned SubReg = *SubRegs; 201280031Sdim if (LocalDefSet.insert(SubReg).second) 202234285Sdim LocalDefs.push_back(SubReg); 203234285Sdim } 204234285Sdim } 205234285Sdim } 206234285Sdim 207234285Sdim Defs.clear(); 208234285Sdim } 209234285Sdim 210243830Sdim SmallSet<unsigned, 32> Added; 211234285Sdim for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) { 212234285Sdim unsigned Reg = LocalDefs[i]; 213280031Sdim if (Added.insert(Reg).second) { 214234285Sdim // If it's not live beyond end of the bundle, mark it dead. 215234285Sdim bool isDead = DeadDefSet.count(Reg) || KilledDefSet.count(Reg); 216234285Sdim MIB.addReg(Reg, getDefRegState(true) | getDeadRegState(isDead) | 217234285Sdim getImplRegState(true)); 218234285Sdim } 219234285Sdim } 220234285Sdim 221234285Sdim for (unsigned i = 0, e = ExternUses.size(); i != e; ++i) { 222234285Sdim unsigned Reg = ExternUses[i]; 223234285Sdim bool isKill = KilledUseSet.count(Reg); 224234285Sdim bool isUndef = UndefUseSet.count(Reg); 225234285Sdim MIB.addReg(Reg, getKillRegState(isKill) | getUndefRegState(isUndef) | 226234285Sdim getImplRegState(true)); 227234285Sdim } 228344779Sdim 229344779Sdim // Set FrameSetup/FrameDestroy for the bundle. If any of the instructions got 230344779Sdim // the property, then also set it on the bundle. 231344779Sdim for (auto MII = FirstMI; MII != LastMI; ++MII) { 232344779Sdim if (MII->getFlag(MachineInstr::FrameSetup)) 233344779Sdim MIB.setMIFlag(MachineInstr::FrameSetup); 234344779Sdim if (MII->getFlag(MachineInstr::FrameDestroy)) 235344779Sdim MIB.setMIFlag(MachineInstr::FrameDestroy); 236344779Sdim } 237234285Sdim} 238234285Sdim 239234285Sdim/// finalizeBundle - Same functionality as the previous finalizeBundle except 240234285Sdim/// the last instruction in the bundle is not provided as an input. This is 241234285Sdim/// used in cases where bundles are pre-determined by marking instructions 242234285Sdim/// with 'InsideBundle' marker. It returns the MBB instruction iterator that 243234285Sdim/// points to the end of the bundle. 244234285SdimMachineBasicBlock::instr_iterator 245234285Sdimllvm::finalizeBundle(MachineBasicBlock &MBB, 246234285Sdim MachineBasicBlock::instr_iterator FirstMI) { 247234285Sdim MachineBasicBlock::instr_iterator E = MBB.instr_end(); 248276479Sdim MachineBasicBlock::instr_iterator LastMI = std::next(FirstMI); 249234285Sdim while (LastMI != E && LastMI->isInsideBundle()) 250234285Sdim ++LastMI; 251234285Sdim finalizeBundle(MBB, FirstMI, LastMI); 252234285Sdim return LastMI; 253234285Sdim} 254234285Sdim 255234285Sdim/// finalizeBundles - Finalize instruction bundles in the specified 256234285Sdim/// MachineFunction. Return true if any bundles are finalized. 257234285Sdimbool llvm::finalizeBundles(MachineFunction &MF) { 258234285Sdim bool Changed = false; 259234285Sdim for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { 260234285Sdim MachineBasicBlock &MBB = *I; 261234285Sdim MachineBasicBlock::instr_iterator MII = MBB.instr_begin(); 262249423Sdim MachineBasicBlock::instr_iterator MIE = MBB.instr_end(); 263249423Sdim if (MII == MIE) 264249423Sdim continue; 265234285Sdim assert(!MII->isInsideBundle() && 266234285Sdim "First instr cannot be inside bundle before finalization!"); 267234285Sdim 268234285Sdim for (++MII; MII != MIE; ) { 269234285Sdim if (!MII->isInsideBundle()) 270234285Sdim ++MII; 271234285Sdim else { 272276479Sdim MII = finalizeBundle(MBB, std::prev(MII)); 273234285Sdim Changed = true; 274234285Sdim } 275234285Sdim } 276234285Sdim } 277234285Sdim 278234285Sdim return Changed; 279234285Sdim} 280234285Sdim 281360784SdimVirtRegInfo llvm::AnalyzeVirtRegInBundle( 282360784Sdim MachineInstr &MI, unsigned Reg, 283360784Sdim SmallVectorImpl<std::pair<MachineInstr *, unsigned>> *Ops) { 284360784Sdim VirtRegInfo RI = {false, false, false}; 285360784Sdim for (MIBundleOperands O(MI); O.isValid(); ++O) { 286360784Sdim MachineOperand &MO = *O; 287234285Sdim if (!MO.isReg() || MO.getReg() != Reg) 288234285Sdim continue; 289234285Sdim 290234285Sdim // Remember each (MI, OpNo) that refers to Reg. 291234285Sdim if (Ops) 292360784Sdim Ops->push_back(std::make_pair(MO.getParent(), O.getOperandNo())); 293234285Sdim 294234285Sdim // Both defs and uses can read virtual registers. 295234285Sdim if (MO.readsReg()) { 296234285Sdim RI.Reads = true; 297234285Sdim if (MO.isDef()) 298234285Sdim RI.Tied = true; 299234285Sdim } 300234285Sdim 301234285Sdim // Only defs can write. 302234285Sdim if (MO.isDef()) 303234285Sdim RI.Writes = true; 304360784Sdim else if (!RI.Tied && 305360784Sdim MO.getParent()->isRegTiedToDefOperand(O.getOperandNo())) 306234285Sdim RI.Tied = true; 307234285Sdim } 308234285Sdim return RI; 309234285Sdim} 310243830Sdim 311360784SdimPhysRegInfo llvm::AnalyzePhysRegInBundle(const MachineInstr &MI, unsigned Reg, 312360784Sdim const TargetRegisterInfo *TRI) { 313243830Sdim bool AllDefsDead = true; 314309124Sdim PhysRegInfo PRI = {false, false, false, false, false, false, false, false}; 315243830Sdim 316360784Sdim assert(Register::isPhysicalRegister(Reg) && 317243830Sdim "analyzePhysReg not given a physical register!"); 318360784Sdim for (ConstMIBundleOperands O(MI); O.isValid(); ++O) { 319360784Sdim const MachineOperand &MO = *O; 320243830Sdim 321296417Sdim if (MO.isRegMask() && MO.clobbersPhysReg(Reg)) { 322296417Sdim PRI.Clobbered = true; 323296417Sdim continue; 324296417Sdim } 325243830Sdim 326243830Sdim if (!MO.isReg()) 327243830Sdim continue; 328243830Sdim 329360784Sdim Register MOReg = MO.getReg(); 330360784Sdim if (!MOReg || !Register::isPhysicalRegister(MOReg)) 331243830Sdim continue; 332243830Sdim 333296417Sdim if (!TRI->regsOverlap(MOReg, Reg)) 334243830Sdim continue; 335243830Sdim 336296417Sdim bool Covered = TRI->isSuperRegisterEq(Reg, MOReg); 337296417Sdim if (MO.readsReg()) { 338296417Sdim PRI.Read = true; 339296417Sdim if (Covered) { 340296417Sdim PRI.FullyRead = true; 341296417Sdim if (MO.isKill()) 342296417Sdim PRI.Killed = true; 343296417Sdim } 344296417Sdim } else if (MO.isDef()) { 345296417Sdim PRI.Defined = true; 346296417Sdim if (Covered) 347296417Sdim PRI.FullyDefined = true; 348243830Sdim if (!MO.isDead()) 349243830Sdim AllDefsDead = false; 350243830Sdim } 351243830Sdim } 352243830Sdim 353309124Sdim if (AllDefsDead) { 354309124Sdim if (PRI.FullyDefined || PRI.Clobbered) 355309124Sdim PRI.DeadDef = true; 356309124Sdim else if (PRI.Defined) 357309124Sdim PRI.PartialDeadDef = true; 358309124Sdim } 359243830Sdim 360243830Sdim return PRI; 361243830Sdim} 362