X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FMachineRegisterInfo.cpp;h=ffc1f200e212d2468110a7e2d21357d98df66f4c;hb=c08fe15c4f290d18d468f53546a790b7d218a74d;hp=094cf84dd3a847f1450cdfbe69a5276bea160528;hpb=bf63022492e54c8abe7c8d8c8448661342294f46;p=oota-llvm.git diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp index 094cf84dd3a..ffc1f200e21 100644 --- a/lib/CodeGen/MachineRegisterInfo.cpp +++ b/lib/CodeGen/MachineRegisterInfo.cpp @@ -13,31 +13,26 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/IR/Function.h" #include "llvm/Support/raw_os_ostream.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; // Pin the vtable to this file. void MachineRegisterInfo::Delegate::anchor() {} -MachineRegisterInfo::MachineRegisterInfo(const TargetMachine &TM) - : TM(TM), TheDelegate(0), IsSSA(true), TracksLiveness(true) { +MachineRegisterInfo::MachineRegisterInfo(const MachineFunction *MF) + : MF(MF), TheDelegate(nullptr), IsSSA(true), TracksLiveness(true), + TracksSubRegLiveness(false) { VRegInfo.reserve(256); RegAllocHints.reserve(256); - UsedRegUnits.resize(getTargetRegisterInfo()->getNumRegUnits()); UsedPhysRegMask.resize(getTargetRegisterInfo()->getNumRegs()); // Create the physreg use/def lists. - PhysRegUseDefLists = - new MachineOperand*[getTargetRegisterInfo()->getNumRegs()]; - memset(PhysRegUseDefLists, 0, - sizeof(MachineOperand*)*getTargetRegisterInfo()->getNumRegs()); -} - -MachineRegisterInfo::~MachineRegisterInfo() { - delete [] PhysRegUseDefLists; + PhysRegUseDefLists.resize(getTargetRegisterInfo()->getNumRegs(), nullptr); } /// setRegClass - Set the register class of the specified virtual register. @@ -60,28 +55,28 @@ MachineRegisterInfo::constrainRegClass(unsigned Reg, if (!NewRC || NewRC == OldRC) return NewRC; if (NewRC->getNumRegs() < MinNumRegs) - return 0; + return nullptr; setRegClass(Reg, NewRC); return NewRC; } bool -MachineRegisterInfo::recomputeRegClass(unsigned Reg, const TargetMachine &TM) { - const TargetInstrInfo *TII = TM.getInstrInfo(); +MachineRegisterInfo::recomputeRegClass(unsigned Reg) { + const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); const TargetRegisterClass *OldRC = getRegClass(Reg); const TargetRegisterClass *NewRC = - getTargetRegisterInfo()->getLargestLegalSuperClass(OldRC); + getTargetRegisterInfo()->getLargestLegalSuperClass(OldRC, *MF); // Stop early if there is no room to grow. if (NewRC == OldRC) return false; // Accumulate constraints from all uses. - for (reg_nodbg_iterator I = reg_nodbg_begin(Reg), E = reg_nodbg_end(); I != E; - ++I) { + for (MachineOperand &MO : reg_nodbg_operands(Reg)) { // Apply the effect of the given operand to NewRC. - MachineInstr *MI = I->getParent(); - NewRC = MI->getRegClassConstraintEffect(I.getOperandNo(), NewRC, TII, + MachineInstr *MI = MO.getParent(); + unsigned OpNo = &MO - &MI->getOperand(0); + NewRC = MI->getRegClassConstraintEffect(OpNo, NewRC, TII, getTargetRegisterInfo()); if (!NewRC || NewRC == OldRC) return false; @@ -121,19 +116,22 @@ void MachineRegisterInfo::clearVirtRegs() { } #endif VRegInfo.clear(); + for (auto &I : LiveIns) + I.second = 0; } void MachineRegisterInfo::verifyUseList(unsigned Reg) const { #ifndef NDEBUG bool Valid = true; - for (reg_iterator I = reg_begin(Reg), E = reg_end(); I != E; ++I) { - MachineOperand *MO = &*I; + for (MachineOperand &M : reg_operands(Reg)) { + MachineOperand *MO = &M; MachineInstr *MI = MO->getParent(); if (!MI) { errs() << PrintReg(Reg, getTargetRegisterInfo()) << " use list MachineOperand " << MO << " has no parent instruction.\n"; Valid = false; + continue; } MachineOperand *MO0 = &MI->getOperand(0); unsigned NumOps = MI->getNumOperands(); @@ -182,7 +180,7 @@ void MachineRegisterInfo::addRegOperandToUseList(MachineOperand *MO) { // Head is NULL for an empty list. if (!Head) { MO->Contents.Reg.Prev = MO; - MO->Contents.Reg.Next = 0; + MO->Contents.Reg.Next = nullptr; HeadRef = MO; return; } @@ -203,7 +201,7 @@ void MachineRegisterInfo::addRegOperandToUseList(MachineOperand *MO) { HeadRef = MO; } else { // Insert use at the end. - MO->Contents.Reg.Next = 0; + MO->Contents.Reg.Next = nullptr; Last->Contents.Reg.Next = MO; } } @@ -227,8 +225,8 @@ void MachineRegisterInfo::removeRegOperandFromUseList(MachineOperand *MO) { (Next ? Next : Head)->Contents.Reg.Prev = Prev; - MO->Contents.Reg.Prev = 0; - MO->Contents.Reg.Next = 0; + MO->Contents.Reg.Prev = nullptr; + MO->Contents.Reg.Next = nullptr; } /// Move NumOps operands from Src to Dst, updating use-def lists as needed. @@ -283,18 +281,25 @@ void MachineRegisterInfo::moveOperands(MachineOperand *Dst, /// replaceRegWith - Replace all instances of FromReg with ToReg in the /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), /// except that it also changes any definitions of the register as well. +/// If ToReg is a physical register we apply the sub register to obtain the +/// final/proper physical register. void MachineRegisterInfo::replaceRegWith(unsigned FromReg, unsigned ToReg) { assert(FromReg != ToReg && "Cannot replace a reg with itself"); + const TargetRegisterInfo *TRI = getTargetRegisterInfo(); + // TODO: This could be more efficient by bulk changing the operands. for (reg_iterator I = reg_begin(FromReg), E = reg_end(); I != E; ) { MachineOperand &O = *I; ++I; - O.setReg(ToReg); + if (TargetRegisterInfo::isPhysicalRegister(ToReg)) { + O.substPhysReg(ToReg, *TRI); + } else { + O.setReg(ToReg); + } } } - /// getVRegDef - Return the machine instr that defines the specified virtual /// register or null if none is found. This assumes that the code is in SSA /// form, so there should only be one definition. @@ -303,17 +308,17 @@ MachineInstr *MachineRegisterInfo::getVRegDef(unsigned Reg) const { def_instr_iterator I = def_instr_begin(Reg); assert((I.atEnd() || std::next(I) == def_instr_end()) && "getVRegDef assumes a single definition or no definition"); - return !I.atEnd() ? &*I : 0; + return !I.atEnd() ? &*I : nullptr; } /// getUniqueVRegDef - Return the unique machine instr that defines the /// specified virtual register or null if none is found. If there are /// multiple definitions or no definition, return null. MachineInstr *MachineRegisterInfo::getUniqueVRegDef(unsigned Reg) const { - if (def_empty(Reg)) return 0; + if (def_empty(Reg)) return nullptr; def_instr_iterator I = def_instr_begin(Reg); if (std::next(I) != def_instr_end()) - return 0; + return nullptr; return &*I; } @@ -329,8 +334,8 @@ bool MachineRegisterInfo::hasOneNonDBGUse(unsigned RegNo) const { /// optimization passes which extend register lifetimes and need only /// preserve conservative kill flag information. void MachineRegisterInfo::clearKillFlags(unsigned Reg) const { - for (use_iterator UI = use_begin(Reg), UE = use_end(); UI != UE; ++UI) - UI->setIsKill(false); + for (MachineOperand &MO : use_operands(Reg)) + MO.setIsKill(false); } bool MachineRegisterInfo::isLiveIn(unsigned Reg) const { @@ -390,10 +395,17 @@ MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB, } } +LaneBitmask MachineRegisterInfo::getMaxLaneMaskForVReg(unsigned Reg) const { + // Lane masks are only defined for vregs. + assert(TargetRegisterInfo::isVirtualRegister(Reg)); + const TargetRegisterClass &TRC = *getRegClass(Reg); + return TRC.getLaneMask(); +} + #ifndef NDEBUG void MachineRegisterInfo::dumpUses(unsigned Reg) const { - for (use_iterator I = use_begin(Reg), E = use_end(); I != E; ++I) - I->getParent()->dump(); + for (MachineInstr &I : use_instructions(Reg)) + I.dump(); } #endif @@ -430,3 +442,61 @@ void MachineRegisterInfo::markUsesInDebugValueAsUndef(unsigned Reg) const { UseMI->getOperand(0).setReg(0U); } } + +static const Function *getCalledFunction(const MachineInstr &MI) { + for (const MachineOperand &MO : MI.operands()) { + if (!MO.isGlobal()) + continue; + const Function *Func = dyn_cast(MO.getGlobal()); + if (Func != nullptr) + return Func; + } + return nullptr; +} + +static bool isNoReturnDef(const MachineOperand &MO) { + // Anything which is not a noreturn function is a real def. + const MachineInstr &MI = *MO.getParent(); + if (!MI.isCall()) + return false; + const MachineBasicBlock &MBB = *MI.getParent(); + if (!MBB.succ_empty()) + return false; + const MachineFunction &MF = *MBB.getParent(); + // We need to keep correct unwind information even if the function will + // not return, since the runtime may need it. + if (MF.getFunction()->hasFnAttribute(Attribute::UWTable)) + return false; + const Function *Called = getCalledFunction(MI); + if (Called == nullptr || !Called->hasFnAttribute(Attribute::NoReturn) + || !Called->hasFnAttribute(Attribute::NoUnwind)) + return false; + + return true; +} + +bool MachineRegisterInfo::isPhysRegModified(unsigned PhysReg) const { + if (UsedPhysRegMask.test(PhysReg)) + return true; + const TargetRegisterInfo *TRI = getTargetRegisterInfo(); + for (MCRegAliasIterator AI(PhysReg, TRI, true); AI.isValid(); ++AI) { + for (const MachineOperand &MO : make_range(def_begin(*AI), def_end())) { + if (isNoReturnDef(MO)) + continue; + return true; + } + } + return false; +} + +bool MachineRegisterInfo::isPhysRegUsed(unsigned PhysReg) const { + if (UsedPhysRegMask.test(PhysReg)) + return true; + const TargetRegisterInfo *TRI = getTargetRegisterInfo(); + for (MCRegAliasIterator AliasReg(PhysReg, TRI, true); AliasReg.isValid(); + ++AliasReg) { + if (!reg_nodbg_empty(*AliasReg)) + return true; + } + return false; +}