17a7e6055SDimitry Andric //===- lib/Codegen/MachineRegisterInfo.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 //
10f22ef01cSRoman Divacky // Implementation of the MachineRegisterInfo class.
11f22ef01cSRoman Divacky //
12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
13f22ef01cSRoman Divacky
14db17bf38SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
157a7e6055SDimitry Andric #include "llvm/ADT/iterator_range.h"
167a7e6055SDimitry Andric #include "llvm/CodeGen/LowLevelType.h"
177a7e6055SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
187a7e6055SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
197a7e6055SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
20f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineInstrBuilder.h"
217a7e6055SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
222cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
232cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
242cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
254ba319b5SDimitry Andric #include "llvm/Config/llvm-config.h"
267a7e6055SDimitry Andric #include "llvm/IR/Attributes.h"
277a7e6055SDimitry Andric #include "llvm/IR/DebugLoc.h"
28875ed548SDimitry Andric #include "llvm/IR/Function.h"
297a7e6055SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
307a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
317a7e6055SDimitry Andric #include "llvm/Support/CommandLine.h"
327a7e6055SDimitry Andric #include "llvm/Support/Compiler.h"
337a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
347a7e6055SDimitry Andric #include "llvm/Support/raw_ostream.h"
357a7e6055SDimitry Andric #include <cassert>
36284c1978SDimitry Andric
37f22ef01cSRoman Divacky using namespace llvm;
38f22ef01cSRoman Divacky
39d88c1a5aSDimitry Andric static cl::opt<bool> EnableSubRegLiveness("enable-subreg-liveness", cl::Hidden,
40d88c1a5aSDimitry Andric cl::init(true), cl::desc("Enable subregister liveness tracking."));
41d88c1a5aSDimitry Andric
42f785676fSDimitry Andric // Pin the vtable to this file.
anchor()43f785676fSDimitry Andric void MachineRegisterInfo::Delegate::anchor() {}
44f785676fSDimitry Andric
MachineRegisterInfo(MachineFunction * MF)453ca95b02SDimitry Andric MachineRegisterInfo::MachineRegisterInfo(MachineFunction *MF)
467a7e6055SDimitry Andric : MF(MF), TracksSubRegLiveness(MF->getSubtarget().enableSubRegLiveness() &&
477a7e6055SDimitry Andric EnableSubRegLiveness),
487a7e6055SDimitry Andric IsUpdatedCSRsInitialized(false) {
497d523365SDimitry Andric unsigned NumRegs = getTargetRegisterInfo()->getNumRegs();
50f22ef01cSRoman Divacky VRegInfo.reserve(256);
51f22ef01cSRoman Divacky RegAllocHints.reserve(256);
527d523365SDimitry Andric UsedPhysRegMask.resize(NumRegs);
537d523365SDimitry Andric PhysRegUseDefLists.reset(new MachineOperand*[NumRegs]());
54f22ef01cSRoman Divacky }
55f22ef01cSRoman Divacky
56f22ef01cSRoman Divacky /// setRegClass - Set the register class of the specified virtual register.
57f22ef01cSRoman Divacky ///
58f22ef01cSRoman Divacky void
setRegClass(unsigned Reg,const TargetRegisterClass * RC)59f22ef01cSRoman Divacky MachineRegisterInfo::setRegClass(unsigned Reg, const TargetRegisterClass *RC) {
60139f7f9bSDimitry Andric assert(RC && RC->isAllocatable() && "Invalid RC for virtual register");
61f22ef01cSRoman Divacky VRegInfo[Reg].first = RC;
622754fe60SDimitry Andric }
632754fe60SDimitry Andric
setRegBank(unsigned Reg,const RegisterBank & RegBank)643ca95b02SDimitry Andric void MachineRegisterInfo::setRegBank(unsigned Reg,
653ca95b02SDimitry Andric const RegisterBank &RegBank) {
663ca95b02SDimitry Andric VRegInfo[Reg].first = &RegBank;
673ca95b02SDimitry Andric }
683ca95b02SDimitry Andric
694ba319b5SDimitry Andric static const TargetRegisterClass *
constrainRegClass(MachineRegisterInfo & MRI,unsigned Reg,const TargetRegisterClass * OldRC,const TargetRegisterClass * RC,unsigned MinNumRegs)704ba319b5SDimitry Andric constrainRegClass(MachineRegisterInfo &MRI, unsigned Reg,
714ba319b5SDimitry Andric const TargetRegisterClass *OldRC,
724ba319b5SDimitry Andric const TargetRegisterClass *RC, unsigned MinNumRegs) {
732754fe60SDimitry Andric if (OldRC == RC)
742754fe60SDimitry Andric return RC;
75f785676fSDimitry Andric const TargetRegisterClass *NewRC =
764ba319b5SDimitry Andric MRI.getTargetRegisterInfo()->getCommonSubClass(OldRC, RC);
776122f3e6SDimitry Andric if (!NewRC || NewRC == OldRC)
786122f3e6SDimitry Andric return NewRC;
796122f3e6SDimitry Andric if (NewRC->getNumRegs() < MinNumRegs)
8091bc56edSDimitry Andric return nullptr;
814ba319b5SDimitry Andric MRI.setRegClass(Reg, NewRC);
822754fe60SDimitry Andric return NewRC;
83f22ef01cSRoman Divacky }
84f22ef01cSRoman Divacky
854ba319b5SDimitry Andric const TargetRegisterClass *
constrainRegClass(unsigned Reg,const TargetRegisterClass * RC,unsigned MinNumRegs)864ba319b5SDimitry Andric MachineRegisterInfo::constrainRegClass(unsigned Reg,
874ba319b5SDimitry Andric const TargetRegisterClass *RC,
884ba319b5SDimitry Andric unsigned MinNumRegs) {
894ba319b5SDimitry Andric return ::constrainRegClass(*this, Reg, getRegClass(Reg), RC, MinNumRegs);
904ba319b5SDimitry Andric }
914ba319b5SDimitry Andric
924ba319b5SDimitry Andric bool
constrainRegAttrs(unsigned Reg,unsigned ConstrainingReg,unsigned MinNumRegs)934ba319b5SDimitry Andric MachineRegisterInfo::constrainRegAttrs(unsigned Reg,
944ba319b5SDimitry Andric unsigned ConstrainingReg,
954ba319b5SDimitry Andric unsigned MinNumRegs) {
96*b5893f02SDimitry Andric const LLT RegTy = getType(Reg);
97*b5893f02SDimitry Andric const LLT ConstrainingRegTy = getType(ConstrainingReg);
98*b5893f02SDimitry Andric if (RegTy.isValid() && ConstrainingRegTy.isValid() &&
99*b5893f02SDimitry Andric RegTy != ConstrainingRegTy)
1004ba319b5SDimitry Andric return false;
101*b5893f02SDimitry Andric const auto ConstrainingRegCB = getRegClassOrRegBank(ConstrainingReg);
102*b5893f02SDimitry Andric if (!ConstrainingRegCB.isNull()) {
103*b5893f02SDimitry Andric const auto RegCB = getRegClassOrRegBank(Reg);
104*b5893f02SDimitry Andric if (RegCB.isNull())
105*b5893f02SDimitry Andric setRegClassOrRegBank(Reg, ConstrainingRegCB);
106*b5893f02SDimitry Andric else if (RegCB.is<const TargetRegisterClass *>() !=
107*b5893f02SDimitry Andric ConstrainingRegCB.is<const TargetRegisterClass *>())
1084ba319b5SDimitry Andric return false;
109*b5893f02SDimitry Andric else if (RegCB.is<const TargetRegisterClass *>()) {
110*b5893f02SDimitry Andric if (!::constrainRegClass(
111*b5893f02SDimitry Andric *this, Reg, RegCB.get<const TargetRegisterClass *>(),
112*b5893f02SDimitry Andric ConstrainingRegCB.get<const TargetRegisterClass *>(), MinNumRegs))
113*b5893f02SDimitry Andric return false;
114*b5893f02SDimitry Andric } else if (RegCB != ConstrainingRegCB)
115*b5893f02SDimitry Andric return false;
116*b5893f02SDimitry Andric }
117*b5893f02SDimitry Andric if (ConstrainingRegTy.isValid())
118*b5893f02SDimitry Andric setType(Reg, ConstrainingRegTy);
1194ba319b5SDimitry Andric return true;
1204ba319b5SDimitry Andric }
1214ba319b5SDimitry Andric
1226122f3e6SDimitry Andric bool
recomputeRegClass(unsigned Reg)123ff0cc061SDimitry Andric MachineRegisterInfo::recomputeRegClass(unsigned Reg) {
124ff0cc061SDimitry Andric const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
1256122f3e6SDimitry Andric const TargetRegisterClass *OldRC = getRegClass(Reg);
126f785676fSDimitry Andric const TargetRegisterClass *NewRC =
127ff0cc061SDimitry Andric getTargetRegisterInfo()->getLargestLegalSuperClass(OldRC, *MF);
1286122f3e6SDimitry Andric
1296122f3e6SDimitry Andric // Stop early if there is no room to grow.
1306122f3e6SDimitry Andric if (NewRC == OldRC)
1316122f3e6SDimitry Andric return false;
1326122f3e6SDimitry Andric
1336122f3e6SDimitry Andric // Accumulate constraints from all uses.
13491bc56edSDimitry Andric for (MachineOperand &MO : reg_nodbg_operands(Reg)) {
13591bc56edSDimitry Andric // Apply the effect of the given operand to NewRC.
13691bc56edSDimitry Andric MachineInstr *MI = MO.getParent();
13791bc56edSDimitry Andric unsigned OpNo = &MO - &MI->getOperand(0);
13891bc56edSDimitry Andric NewRC = MI->getRegClassConstraintEffect(OpNo, NewRC, TII,
139f785676fSDimitry Andric getTargetRegisterInfo());
1406122f3e6SDimitry Andric if (!NewRC || NewRC == OldRC)
1416122f3e6SDimitry Andric return false;
1426122f3e6SDimitry Andric }
1436122f3e6SDimitry Andric setRegClass(Reg, NewRC);
1446122f3e6SDimitry Andric return true;
1456122f3e6SDimitry Andric }
1466122f3e6SDimitry Andric
createIncompleteVirtualRegister(StringRef Name)1474ba319b5SDimitry Andric unsigned MachineRegisterInfo::createIncompleteVirtualRegister(StringRef Name) {
148d88c1a5aSDimitry Andric unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs());
149d88c1a5aSDimitry Andric VRegInfo.grow(Reg);
150d88c1a5aSDimitry Andric RegAllocHints.grow(Reg);
1514ba319b5SDimitry Andric insertVRegByName(Name, Reg);
152d88c1a5aSDimitry Andric return Reg;
153d88c1a5aSDimitry Andric }
154d88c1a5aSDimitry Andric
155f22ef01cSRoman Divacky /// createVirtualRegister - Create and return a new virtual register in the
156f22ef01cSRoman Divacky /// function with the specified register class.
157f22ef01cSRoman Divacky ///
158f22ef01cSRoman Divacky unsigned
createVirtualRegister(const TargetRegisterClass * RegClass,StringRef Name)1594ba319b5SDimitry Andric MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass,
1604ba319b5SDimitry Andric StringRef Name) {
161f22ef01cSRoman Divacky assert(RegClass && "Cannot create register without RegClass!");
162bd5abe19SDimitry Andric assert(RegClass->isAllocatable() &&
163bd5abe19SDimitry Andric "Virtual register RegClass must be allocatable.");
164f22ef01cSRoman Divacky
1652754fe60SDimitry Andric // New virtual register number.
1664ba319b5SDimitry Andric unsigned Reg = createIncompleteVirtualRegister(Name);
1672754fe60SDimitry Andric VRegInfo[Reg].first = RegClass;
168f785676fSDimitry Andric if (TheDelegate)
169f785676fSDimitry Andric TheDelegate->MRI_NoteNewVirtualRegister(Reg);
1702754fe60SDimitry Andric return Reg;
171f22ef01cSRoman Divacky }
172f22ef01cSRoman Divacky
cloneVirtualRegister(unsigned VReg,StringRef Name)173*b5893f02SDimitry Andric unsigned MachineRegisterInfo::cloneVirtualRegister(unsigned VReg,
174*b5893f02SDimitry Andric StringRef Name) {
175*b5893f02SDimitry Andric unsigned Reg = createIncompleteVirtualRegister(Name);
176*b5893f02SDimitry Andric VRegInfo[Reg].first = VRegInfo[VReg].first;
177*b5893f02SDimitry Andric setType(Reg, getType(VReg));
178*b5893f02SDimitry Andric if (TheDelegate)
179*b5893f02SDimitry Andric TheDelegate->MRI_NoteNewVirtualRegister(Reg);
180*b5893f02SDimitry Andric return Reg;
181*b5893f02SDimitry Andric }
182*b5893f02SDimitry Andric
setType(unsigned VReg,LLT Ty)183d88c1a5aSDimitry Andric void MachineRegisterInfo::setType(unsigned VReg, LLT Ty) {
1844ba319b5SDimitry Andric VRegToType.grow(VReg);
1854ba319b5SDimitry Andric VRegToType[VReg] = Ty;
1863ca95b02SDimitry Andric }
1873ca95b02SDimitry Andric
1883ca95b02SDimitry Andric unsigned
createGenericVirtualRegister(LLT Ty,StringRef Name)1894ba319b5SDimitry Andric MachineRegisterInfo::createGenericVirtualRegister(LLT Ty, StringRef Name) {
1903ca95b02SDimitry Andric // New virtual register number.
1914ba319b5SDimitry Andric unsigned Reg = createIncompleteVirtualRegister(Name);
1923ca95b02SDimitry Andric // FIXME: Should we use a dummy register class?
193d88c1a5aSDimitry Andric VRegInfo[Reg].first = static_cast<RegisterBank *>(nullptr);
1944ba319b5SDimitry Andric setType(Reg, Ty);
1953ca95b02SDimitry Andric if (TheDelegate)
1963ca95b02SDimitry Andric TheDelegate->MRI_NoteNewVirtualRegister(Reg);
1973ca95b02SDimitry Andric return Reg;
1983ca95b02SDimitry Andric }
1993ca95b02SDimitry Andric
clearVirtRegTypes()2004ba319b5SDimitry Andric void MachineRegisterInfo::clearVirtRegTypes() { VRegToType.clear(); }
201d88c1a5aSDimitry Andric
202dff0c46cSDimitry Andric /// clearVirtRegs - Remove all virtual registers (after physreg assignment).
clearVirtRegs()203dff0c46cSDimitry Andric void MachineRegisterInfo::clearVirtRegs() {
204dff0c46cSDimitry Andric #ifndef NDEBUG
205284c1978SDimitry Andric for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i) {
206284c1978SDimitry Andric unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
207284c1978SDimitry Andric if (!VRegInfo[Reg].second)
208284c1978SDimitry Andric continue;
209284c1978SDimitry Andric verifyUseList(Reg);
210284c1978SDimitry Andric llvm_unreachable("Remaining virtual register operands");
211284c1978SDimitry Andric }
212dff0c46cSDimitry Andric #endif
213dff0c46cSDimitry Andric VRegInfo.clear();
2147d523365SDimitry Andric for (auto &I : LiveIns)
2157d523365SDimitry Andric I.second = 0;
216dff0c46cSDimitry Andric }
217dff0c46cSDimitry Andric
verifyUseList(unsigned Reg) const218284c1978SDimitry Andric void MachineRegisterInfo::verifyUseList(unsigned Reg) const {
219284c1978SDimitry Andric #ifndef NDEBUG
220284c1978SDimitry Andric bool Valid = true;
22191bc56edSDimitry Andric for (MachineOperand &M : reg_operands(Reg)) {
22291bc56edSDimitry Andric MachineOperand *MO = &M;
223284c1978SDimitry Andric MachineInstr *MI = MO->getParent();
224284c1978SDimitry Andric if (!MI) {
2252cab237bSDimitry Andric errs() << printReg(Reg, getTargetRegisterInfo())
226f785676fSDimitry Andric << " use list MachineOperand " << MO
227284c1978SDimitry Andric << " has no parent instruction.\n";
228284c1978SDimitry Andric Valid = false;
22939d628a0SDimitry Andric continue;
230284c1978SDimitry Andric }
231284c1978SDimitry Andric MachineOperand *MO0 = &MI->getOperand(0);
232284c1978SDimitry Andric unsigned NumOps = MI->getNumOperands();
233284c1978SDimitry Andric if (!(MO >= MO0 && MO < MO0+NumOps)) {
2342cab237bSDimitry Andric errs() << printReg(Reg, getTargetRegisterInfo())
235f785676fSDimitry Andric << " use list MachineOperand " << MO
236284c1978SDimitry Andric << " doesn't belong to parent MI: " << *MI;
237284c1978SDimitry Andric Valid = false;
238284c1978SDimitry Andric }
239284c1978SDimitry Andric if (!MO->isReg()) {
2402cab237bSDimitry Andric errs() << printReg(Reg, getTargetRegisterInfo())
241f785676fSDimitry Andric << " MachineOperand " << MO << ": " << *MO
242284c1978SDimitry Andric << " is not a register\n";
243284c1978SDimitry Andric Valid = false;
244284c1978SDimitry Andric }
245284c1978SDimitry Andric if (MO->getReg() != Reg) {
2462cab237bSDimitry Andric errs() << printReg(Reg, getTargetRegisterInfo())
247f785676fSDimitry Andric << " use-list MachineOperand " << MO << ": "
248284c1978SDimitry Andric << *MO << " is the wrong register\n";
249284c1978SDimitry Andric Valid = false;
250284c1978SDimitry Andric }
251284c1978SDimitry Andric }
252284c1978SDimitry Andric assert(Valid && "Invalid use list");
253284c1978SDimitry Andric #endif
254284c1978SDimitry Andric }
255284c1978SDimitry Andric
verifyUseLists() const256284c1978SDimitry Andric void MachineRegisterInfo::verifyUseLists() const {
257284c1978SDimitry Andric #ifndef NDEBUG
258284c1978SDimitry Andric for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i)
259284c1978SDimitry Andric verifyUseList(TargetRegisterInfo::index2VirtReg(i));
260f785676fSDimitry Andric for (unsigned i = 1, e = getTargetRegisterInfo()->getNumRegs(); i != e; ++i)
261284c1978SDimitry Andric verifyUseList(i);
262284c1978SDimitry Andric #endif
263284c1978SDimitry Andric }
264284c1978SDimitry Andric
2657ae0e2c9SDimitry Andric /// Add MO to the linked list of operands for its register.
addRegOperandToUseList(MachineOperand * MO)2667ae0e2c9SDimitry Andric void MachineRegisterInfo::addRegOperandToUseList(MachineOperand *MO) {
2677ae0e2c9SDimitry Andric assert(!MO->isOnRegUseList() && "Already on list");
2687ae0e2c9SDimitry Andric MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
2697ae0e2c9SDimitry Andric MachineOperand *const Head = HeadRef;
2707ae0e2c9SDimitry Andric
2717ae0e2c9SDimitry Andric // Head points to the first list element.
2727ae0e2c9SDimitry Andric // Next is NULL on the last list element.
2737ae0e2c9SDimitry Andric // Prev pointers are circular, so Head->Prev == Last.
2747ae0e2c9SDimitry Andric
2757ae0e2c9SDimitry Andric // Head is NULL for an empty list.
2767ae0e2c9SDimitry Andric if (!Head) {
2777ae0e2c9SDimitry Andric MO->Contents.Reg.Prev = MO;
27891bc56edSDimitry Andric MO->Contents.Reg.Next = nullptr;
2797ae0e2c9SDimitry Andric HeadRef = MO;
2807ae0e2c9SDimitry Andric return;
281f22ef01cSRoman Divacky }
2827ae0e2c9SDimitry Andric assert(MO->getReg() == Head->getReg() && "Different regs on the same list!");
2837ae0e2c9SDimitry Andric
2847ae0e2c9SDimitry Andric // Insert MO between Last and Head in the circular Prev chain.
2857ae0e2c9SDimitry Andric MachineOperand *Last = Head->Contents.Reg.Prev;
2867ae0e2c9SDimitry Andric assert(Last && "Inconsistent use list");
2877ae0e2c9SDimitry Andric assert(MO->getReg() == Last->getReg() && "Different regs on the same list!");
2887ae0e2c9SDimitry Andric Head->Contents.Reg.Prev = MO;
2897ae0e2c9SDimitry Andric MO->Contents.Reg.Prev = Last;
2907ae0e2c9SDimitry Andric
2917ae0e2c9SDimitry Andric // Def operands always precede uses. This allows def_iterator to stop early.
2927ae0e2c9SDimitry Andric // Insert def operands at the front, and use operands at the back.
2937ae0e2c9SDimitry Andric if (MO->isDef()) {
2947ae0e2c9SDimitry Andric // Insert def at the front.
2957ae0e2c9SDimitry Andric MO->Contents.Reg.Next = Head;
2967ae0e2c9SDimitry Andric HeadRef = MO;
2977ae0e2c9SDimitry Andric } else {
2987ae0e2c9SDimitry Andric // Insert use at the end.
29991bc56edSDimitry Andric MO->Contents.Reg.Next = nullptr;
3007ae0e2c9SDimitry Andric Last->Contents.Reg.Next = MO;
3017ae0e2c9SDimitry Andric }
3027ae0e2c9SDimitry Andric }
3037ae0e2c9SDimitry Andric
3047ae0e2c9SDimitry Andric /// Remove MO from its use-def list.
removeRegOperandFromUseList(MachineOperand * MO)3057ae0e2c9SDimitry Andric void MachineRegisterInfo::removeRegOperandFromUseList(MachineOperand *MO) {
3067ae0e2c9SDimitry Andric assert(MO->isOnRegUseList() && "Operand not on use list");
3077ae0e2c9SDimitry Andric MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
3087ae0e2c9SDimitry Andric MachineOperand *const Head = HeadRef;
3097ae0e2c9SDimitry Andric assert(Head && "List already empty");
3107ae0e2c9SDimitry Andric
3117ae0e2c9SDimitry Andric // Unlink this from the doubly linked list of operands.
3127ae0e2c9SDimitry Andric MachineOperand *Next = MO->Contents.Reg.Next;
3137ae0e2c9SDimitry Andric MachineOperand *Prev = MO->Contents.Reg.Prev;
3147ae0e2c9SDimitry Andric
3157ae0e2c9SDimitry Andric // Prev links are circular, next link is NULL instead of looping back to Head.
3167ae0e2c9SDimitry Andric if (MO == Head)
3177ae0e2c9SDimitry Andric HeadRef = Next;
3187ae0e2c9SDimitry Andric else
3197ae0e2c9SDimitry Andric Prev->Contents.Reg.Next = Next;
3207ae0e2c9SDimitry Andric
3217ae0e2c9SDimitry Andric (Next ? Next : Head)->Contents.Reg.Prev = Prev;
3227ae0e2c9SDimitry Andric
32391bc56edSDimitry Andric MO->Contents.Reg.Prev = nullptr;
32491bc56edSDimitry Andric MO->Contents.Reg.Next = nullptr;
325f22ef01cSRoman Divacky }
326f22ef01cSRoman Divacky
327139f7f9bSDimitry Andric /// Move NumOps operands from Src to Dst, updating use-def lists as needed.
328139f7f9bSDimitry Andric ///
329139f7f9bSDimitry Andric /// The Dst range is assumed to be uninitialized memory. (Or it may contain
330139f7f9bSDimitry Andric /// operands that won't be destroyed, which is OK because the MO destructor is
331139f7f9bSDimitry Andric /// trivial anyway).
332139f7f9bSDimitry Andric ///
333139f7f9bSDimitry Andric /// The Src and Dst ranges may overlap.
moveOperands(MachineOperand * Dst,MachineOperand * Src,unsigned NumOps)334139f7f9bSDimitry Andric void MachineRegisterInfo::moveOperands(MachineOperand *Dst,
335139f7f9bSDimitry Andric MachineOperand *Src,
336139f7f9bSDimitry Andric unsigned NumOps) {
337139f7f9bSDimitry Andric assert(Src != Dst && NumOps && "Noop moveOperands");
338139f7f9bSDimitry Andric
339139f7f9bSDimitry Andric // Copy backwards if Dst is within the Src range.
340139f7f9bSDimitry Andric int Stride = 1;
341139f7f9bSDimitry Andric if (Dst >= Src && Dst < Src + NumOps) {
342139f7f9bSDimitry Andric Stride = -1;
343139f7f9bSDimitry Andric Dst += NumOps - 1;
344139f7f9bSDimitry Andric Src += NumOps - 1;
345139f7f9bSDimitry Andric }
346139f7f9bSDimitry Andric
347139f7f9bSDimitry Andric // Copy one operand at a time.
348139f7f9bSDimitry Andric do {
349139f7f9bSDimitry Andric new (Dst) MachineOperand(*Src);
350139f7f9bSDimitry Andric
351139f7f9bSDimitry Andric // Dst takes Src's place in the use-def chain.
352139f7f9bSDimitry Andric if (Src->isReg()) {
353139f7f9bSDimitry Andric MachineOperand *&Head = getRegUseDefListHead(Src->getReg());
354139f7f9bSDimitry Andric MachineOperand *Prev = Src->Contents.Reg.Prev;
355139f7f9bSDimitry Andric MachineOperand *Next = Src->Contents.Reg.Next;
356139f7f9bSDimitry Andric assert(Head && "List empty, but operand is chained");
357139f7f9bSDimitry Andric assert(Prev && "Operand was not on use-def list");
358139f7f9bSDimitry Andric
359139f7f9bSDimitry Andric // Prev links are circular, next link is NULL instead of looping back to
360139f7f9bSDimitry Andric // Head.
361139f7f9bSDimitry Andric if (Src == Head)
362139f7f9bSDimitry Andric Head = Dst;
363139f7f9bSDimitry Andric else
364139f7f9bSDimitry Andric Prev->Contents.Reg.Next = Dst;
365139f7f9bSDimitry Andric
366139f7f9bSDimitry Andric // Update Prev pointer. This also works when Src was pointing to itself
367139f7f9bSDimitry Andric // in a 1-element list. In that case Head == Dst.
368139f7f9bSDimitry Andric (Next ? Next : Head)->Contents.Reg.Prev = Dst;
369139f7f9bSDimitry Andric }
370139f7f9bSDimitry Andric
371139f7f9bSDimitry Andric Dst += Stride;
372139f7f9bSDimitry Andric Src += Stride;
373139f7f9bSDimitry Andric } while (--NumOps);
374139f7f9bSDimitry Andric }
375139f7f9bSDimitry Andric
376f22ef01cSRoman Divacky /// replaceRegWith - Replace all instances of FromReg with ToReg in the
377f22ef01cSRoman Divacky /// machine function. This is like llvm-level X->replaceAllUsesWith(Y),
378f22ef01cSRoman Divacky /// except that it also changes any definitions of the register as well.
37939d628a0SDimitry Andric /// If ToReg is a physical register we apply the sub register to obtain the
38039d628a0SDimitry Andric /// final/proper physical register.
replaceRegWith(unsigned FromReg,unsigned ToReg)381f22ef01cSRoman Divacky void MachineRegisterInfo::replaceRegWith(unsigned FromReg, unsigned ToReg) {
382f22ef01cSRoman Divacky assert(FromReg != ToReg && "Cannot replace a reg with itself");
383f22ef01cSRoman Divacky
38439d628a0SDimitry Andric const TargetRegisterInfo *TRI = getTargetRegisterInfo();
38539d628a0SDimitry Andric
386f22ef01cSRoman Divacky // TODO: This could be more efficient by bulk changing the operands.
387f22ef01cSRoman Divacky for (reg_iterator I = reg_begin(FromReg), E = reg_end(); I != E; ) {
38891bc56edSDimitry Andric MachineOperand &O = *I;
389f22ef01cSRoman Divacky ++I;
39039d628a0SDimitry Andric if (TargetRegisterInfo::isPhysicalRegister(ToReg)) {
39139d628a0SDimitry Andric O.substPhysReg(ToReg, *TRI);
39239d628a0SDimitry Andric } else {
393f22ef01cSRoman Divacky O.setReg(ToReg);
394f22ef01cSRoman Divacky }
395f22ef01cSRoman Divacky }
39639d628a0SDimitry Andric }
397f22ef01cSRoman Divacky
398f22ef01cSRoman Divacky /// getVRegDef - Return the machine instr that defines the specified virtual
399f22ef01cSRoman Divacky /// register or null if none is found. This assumes that the code is in SSA
400f22ef01cSRoman Divacky /// form, so there should only be one definition.
getVRegDef(unsigned Reg) const401f22ef01cSRoman Divacky MachineInstr *MachineRegisterInfo::getVRegDef(unsigned Reg) const {
402f22ef01cSRoman Divacky // Since we are in SSA form, we can use the first definition.
40391bc56edSDimitry Andric def_instr_iterator I = def_instr_begin(Reg);
40491bc56edSDimitry Andric assert((I.atEnd() || std::next(I) == def_instr_end()) &&
4057ae0e2c9SDimitry Andric "getVRegDef assumes a single definition or no definition");
40691bc56edSDimitry Andric return !I.atEnd() ? &*I : nullptr;
407f22ef01cSRoman Divacky }
408f22ef01cSRoman Divacky
4097ae0e2c9SDimitry Andric /// getUniqueVRegDef - Return the unique machine instr that defines the
4107ae0e2c9SDimitry Andric /// specified virtual register or null if none is found. If there are
4117ae0e2c9SDimitry Andric /// multiple definitions or no definition, return null.
getUniqueVRegDef(unsigned Reg) const4127ae0e2c9SDimitry Andric MachineInstr *MachineRegisterInfo::getUniqueVRegDef(unsigned Reg) const {
41391bc56edSDimitry Andric if (def_empty(Reg)) return nullptr;
41491bc56edSDimitry Andric def_instr_iterator I = def_instr_begin(Reg);
41591bc56edSDimitry Andric if (std::next(I) != def_instr_end())
41691bc56edSDimitry Andric return nullptr;
4177ae0e2c9SDimitry Andric return &*I;
418f22ef01cSRoman Divacky }
419f22ef01cSRoman Divacky
hasOneNonDBGUse(unsigned RegNo) const420f22ef01cSRoman Divacky bool MachineRegisterInfo::hasOneNonDBGUse(unsigned RegNo) const {
421f22ef01cSRoman Divacky use_nodbg_iterator UI = use_nodbg_begin(RegNo);
422f22ef01cSRoman Divacky if (UI == use_nodbg_end())
423f22ef01cSRoman Divacky return false;
424f22ef01cSRoman Divacky return ++UI == use_nodbg_end();
425f22ef01cSRoman Divacky }
426f22ef01cSRoman Divacky
427f22ef01cSRoman Divacky /// clearKillFlags - Iterate over all the uses of the given register and
428f22ef01cSRoman Divacky /// clear the kill flag from the MachineOperand. This function is used by
429f22ef01cSRoman Divacky /// optimization passes which extend register lifetimes and need only
430f22ef01cSRoman Divacky /// preserve conservative kill flag information.
clearKillFlags(unsigned Reg) const431f22ef01cSRoman Divacky void MachineRegisterInfo::clearKillFlags(unsigned Reg) const {
43291bc56edSDimitry Andric for (MachineOperand &MO : use_operands(Reg))
43391bc56edSDimitry Andric MO.setIsKill(false);
434f22ef01cSRoman Divacky }
435f22ef01cSRoman Divacky
isLiveIn(unsigned Reg) const436f22ef01cSRoman Divacky bool MachineRegisterInfo::isLiveIn(unsigned Reg) const {
437f22ef01cSRoman Divacky for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
438f22ef01cSRoman Divacky if (I->first == Reg || I->second == Reg)
439f22ef01cSRoman Divacky return true;
440f22ef01cSRoman Divacky return false;
441f22ef01cSRoman Divacky }
442f22ef01cSRoman Divacky
443f22ef01cSRoman Divacky /// getLiveInPhysReg - If VReg is a live-in virtual register, return the
444f22ef01cSRoman Divacky /// corresponding live-in physical register.
getLiveInPhysReg(unsigned VReg) const445f22ef01cSRoman Divacky unsigned MachineRegisterInfo::getLiveInPhysReg(unsigned VReg) const {
446f22ef01cSRoman Divacky for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
447f22ef01cSRoman Divacky if (I->second == VReg)
448f22ef01cSRoman Divacky return I->first;
449f22ef01cSRoman Divacky return 0;
450f22ef01cSRoman Divacky }
451f22ef01cSRoman Divacky
452f22ef01cSRoman Divacky /// getLiveInVirtReg - If PReg is a live-in physical register, return the
453f22ef01cSRoman Divacky /// corresponding live-in physical register.
getLiveInVirtReg(unsigned PReg) const454f22ef01cSRoman Divacky unsigned MachineRegisterInfo::getLiveInVirtReg(unsigned PReg) const {
455f22ef01cSRoman Divacky for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
456f22ef01cSRoman Divacky if (I->first == PReg)
457f22ef01cSRoman Divacky return I->second;
458f22ef01cSRoman Divacky return 0;
459f22ef01cSRoman Divacky }
460f22ef01cSRoman Divacky
461f22ef01cSRoman Divacky /// EmitLiveInCopies - Emit copies to initialize livein virtual registers
462f22ef01cSRoman Divacky /// into the given entry block.
463f22ef01cSRoman Divacky void
EmitLiveInCopies(MachineBasicBlock * EntryMBB,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII)464f22ef01cSRoman Divacky MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB,
465f22ef01cSRoman Divacky const TargetRegisterInfo &TRI,
466f22ef01cSRoman Divacky const TargetInstrInfo &TII) {
467ffd1746dSEd Schouten // Emit the copies into the top of the block.
468ffd1746dSEd Schouten for (unsigned i = 0, e = LiveIns.size(); i != e; ++i)
469ffd1746dSEd Schouten if (LiveIns[i].second) {
4702cab237bSDimitry Andric if (use_nodbg_empty(LiveIns[i].second)) {
4712cab237bSDimitry Andric // The livein has no non-dbg uses. Drop it.
472ffd1746dSEd Schouten //
473ffd1746dSEd Schouten // It would be preferable to have isel avoid creating live-in
474ffd1746dSEd Schouten // records for unused arguments in the first place, but it's
475ffd1746dSEd Schouten // complicated by the debug info code for arguments.
476ffd1746dSEd Schouten LiveIns.erase(LiveIns.begin() + i);
477ffd1746dSEd Schouten --i; --e;
478ffd1746dSEd Schouten } else {
479ffd1746dSEd Schouten // Emit a copy.
480dd6029ffSDimitry Andric BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(),
481ffd1746dSEd Schouten TII.get(TargetOpcode::COPY), LiveIns[i].second)
482ffd1746dSEd Schouten .addReg(LiveIns[i].first);
483ffd1746dSEd Schouten
484ffd1746dSEd Schouten // Add the register to the entry block live-in set.
485ffd1746dSEd Schouten EntryMBB->addLiveIn(LiveIns[i].first);
486f22ef01cSRoman Divacky }
487f22ef01cSRoman Divacky } else {
488ffd1746dSEd Schouten // Add the register to the entry block live-in set.
489ffd1746dSEd Schouten EntryMBB->addLiveIn(LiveIns[i].first);
490f22ef01cSRoman Divacky }
491f22ef01cSRoman Divacky }
492f22ef01cSRoman Divacky
getMaxLaneMaskForVReg(unsigned Reg) const4937d523365SDimitry Andric LaneBitmask MachineRegisterInfo::getMaxLaneMaskForVReg(unsigned Reg) const {
49439d628a0SDimitry Andric // Lane masks are only defined for vregs.
49539d628a0SDimitry Andric assert(TargetRegisterInfo::isVirtualRegister(Reg));
49639d628a0SDimitry Andric const TargetRegisterClass &TRC = *getRegClass(Reg);
49739d628a0SDimitry Andric return TRC.getLaneMask();
49839d628a0SDimitry Andric }
49939d628a0SDimitry Andric
5007a7e6055SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dumpUses(unsigned Reg) const5017a7e6055SDimitry Andric LLVM_DUMP_METHOD void MachineRegisterInfo::dumpUses(unsigned Reg) const {
50291bc56edSDimitry Andric for (MachineInstr &I : use_instructions(Reg))
50391bc56edSDimitry Andric I.dump();
504f22ef01cSRoman Divacky }
505f22ef01cSRoman Divacky #endif
506dff0c46cSDimitry Andric
freezeReservedRegs(const MachineFunction & MF)507dff0c46cSDimitry Andric void MachineRegisterInfo::freezeReservedRegs(const MachineFunction &MF) {
508f785676fSDimitry Andric ReservedRegs = getTargetRegisterInfo()->getReservedRegs(MF);
509f785676fSDimitry Andric assert(ReservedRegs.size() == getTargetRegisterInfo()->getNumRegs() &&
5103861d79fSDimitry Andric "Invalid ReservedRegs vector from target");
511dff0c46cSDimitry Andric }
512dff0c46cSDimitry Andric
isConstantPhysReg(unsigned PhysReg) const513d88c1a5aSDimitry Andric bool MachineRegisterInfo::isConstantPhysReg(unsigned PhysReg) const {
514dff0c46cSDimitry Andric assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));
515dff0c46cSDimitry Andric
516d88c1a5aSDimitry Andric const TargetRegisterInfo *TRI = getTargetRegisterInfo();
517d88c1a5aSDimitry Andric if (TRI->isConstantPhysReg(PhysReg))
518d88c1a5aSDimitry Andric return true;
519d88c1a5aSDimitry Andric
5203861d79fSDimitry Andric // Check if any overlapping register is modified, or allocatable so it may be
5213861d79fSDimitry Andric // used later.
522d88c1a5aSDimitry Andric for (MCRegAliasIterator AI(PhysReg, TRI, true);
523f785676fSDimitry Andric AI.isValid(); ++AI)
5243861d79fSDimitry Andric if (!def_empty(*AI) || isAllocatable(*AI))
525dff0c46cSDimitry Andric return false;
526dff0c46cSDimitry Andric return true;
527dff0c46cSDimitry Andric }
52891bc56edSDimitry Andric
5292cab237bSDimitry Andric bool
isCallerPreservedOrConstPhysReg(unsigned PhysReg) const5302cab237bSDimitry Andric MachineRegisterInfo::isCallerPreservedOrConstPhysReg(unsigned PhysReg) const {
5312cab237bSDimitry Andric const TargetRegisterInfo *TRI = getTargetRegisterInfo();
5322cab237bSDimitry Andric return isConstantPhysReg(PhysReg) ||
5332cab237bSDimitry Andric TRI->isCallerPreservedPhysReg(PhysReg, *MF);
5342cab237bSDimitry Andric }
5352cab237bSDimitry Andric
53691bc56edSDimitry Andric /// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the
53791bc56edSDimitry Andric /// specified register as undefined which causes the DBG_VALUE to be
53891bc56edSDimitry Andric /// deleted during LiveDebugVariables analysis.
markUsesInDebugValueAsUndef(unsigned Reg) const53991bc56edSDimitry Andric void MachineRegisterInfo::markUsesInDebugValueAsUndef(unsigned Reg) const {
54091bc56edSDimitry Andric // Mark any DBG_VALUE that uses Reg as undef (but don't delete it.)
54191bc56edSDimitry Andric MachineRegisterInfo::use_instr_iterator nextI;
54291bc56edSDimitry Andric for (use_instr_iterator I = use_instr_begin(Reg), E = use_instr_end();
54391bc56edSDimitry Andric I != E; I = nextI) {
54491bc56edSDimitry Andric nextI = std::next(I); // I is invalidated by the setReg
54591bc56edSDimitry Andric MachineInstr *UseMI = &*I;
54691bc56edSDimitry Andric if (UseMI->isDebugValue())
54791bc56edSDimitry Andric UseMI->getOperand(0).setReg(0U);
54891bc56edSDimitry Andric }
54991bc56edSDimitry Andric }
550875ed548SDimitry Andric
getCalledFunction(const MachineInstr & MI)551875ed548SDimitry Andric static const Function *getCalledFunction(const MachineInstr &MI) {
552875ed548SDimitry Andric for (const MachineOperand &MO : MI.operands()) {
553875ed548SDimitry Andric if (!MO.isGlobal())
554875ed548SDimitry Andric continue;
555875ed548SDimitry Andric const Function *Func = dyn_cast<Function>(MO.getGlobal());
556875ed548SDimitry Andric if (Func != nullptr)
557875ed548SDimitry Andric return Func;
558875ed548SDimitry Andric }
559875ed548SDimitry Andric return nullptr;
560875ed548SDimitry Andric }
561875ed548SDimitry Andric
isNoReturnDef(const MachineOperand & MO)562875ed548SDimitry Andric static bool isNoReturnDef(const MachineOperand &MO) {
563875ed548SDimitry Andric // Anything which is not a noreturn function is a real def.
564875ed548SDimitry Andric const MachineInstr &MI = *MO.getParent();
565875ed548SDimitry Andric if (!MI.isCall())
566875ed548SDimitry Andric return false;
567875ed548SDimitry Andric const MachineBasicBlock &MBB = *MI.getParent();
568875ed548SDimitry Andric if (!MBB.succ_empty())
569875ed548SDimitry Andric return false;
570875ed548SDimitry Andric const MachineFunction &MF = *MBB.getParent();
571875ed548SDimitry Andric // We need to keep correct unwind information even if the function will
572875ed548SDimitry Andric // not return, since the runtime may need it.
5732cab237bSDimitry Andric if (MF.getFunction().hasFnAttribute(Attribute::UWTable))
574875ed548SDimitry Andric return false;
575875ed548SDimitry Andric const Function *Called = getCalledFunction(MI);
5767d523365SDimitry Andric return !(Called == nullptr || !Called->hasFnAttribute(Attribute::NoReturn) ||
5777d523365SDimitry Andric !Called->hasFnAttribute(Attribute::NoUnwind));
578875ed548SDimitry Andric }
579875ed548SDimitry Andric
isPhysRegModified(unsigned PhysReg,bool SkipNoReturnDef) const5803ca95b02SDimitry Andric bool MachineRegisterInfo::isPhysRegModified(unsigned PhysReg,
5813ca95b02SDimitry Andric bool SkipNoReturnDef) const {
582875ed548SDimitry Andric if (UsedPhysRegMask.test(PhysReg))
583875ed548SDimitry Andric return true;
584875ed548SDimitry Andric const TargetRegisterInfo *TRI = getTargetRegisterInfo();
585875ed548SDimitry Andric for (MCRegAliasIterator AI(PhysReg, TRI, true); AI.isValid(); ++AI) {
586875ed548SDimitry Andric for (const MachineOperand &MO : make_range(def_begin(*AI), def_end())) {
5873ca95b02SDimitry Andric if (!SkipNoReturnDef && isNoReturnDef(MO))
588875ed548SDimitry Andric continue;
589875ed548SDimitry Andric return true;
590875ed548SDimitry Andric }
591875ed548SDimitry Andric }
592875ed548SDimitry Andric return false;
593875ed548SDimitry Andric }
5947d523365SDimitry Andric
isPhysRegUsed(unsigned PhysReg) const5957d523365SDimitry Andric bool MachineRegisterInfo::isPhysRegUsed(unsigned PhysReg) const {
5967d523365SDimitry Andric if (UsedPhysRegMask.test(PhysReg))
5977d523365SDimitry Andric return true;
5987d523365SDimitry Andric const TargetRegisterInfo *TRI = getTargetRegisterInfo();
5997d523365SDimitry Andric for (MCRegAliasIterator AliasReg(PhysReg, TRI, true); AliasReg.isValid();
6007d523365SDimitry Andric ++AliasReg) {
6017d523365SDimitry Andric if (!reg_nodbg_empty(*AliasReg))
6027d523365SDimitry Andric return true;
6037d523365SDimitry Andric }
6047d523365SDimitry Andric return false;
6057d523365SDimitry Andric }
6067a7e6055SDimitry Andric
disableCalleeSavedRegister(unsigned Reg)6077a7e6055SDimitry Andric void MachineRegisterInfo::disableCalleeSavedRegister(unsigned Reg) {
6087a7e6055SDimitry Andric
6097a7e6055SDimitry Andric const TargetRegisterInfo *TRI = getTargetRegisterInfo();
6107a7e6055SDimitry Andric assert(Reg && (Reg < TRI->getNumRegs()) &&
6117a7e6055SDimitry Andric "Trying to disable an invalid register");
6127a7e6055SDimitry Andric
6137a7e6055SDimitry Andric if (!IsUpdatedCSRsInitialized) {
6147a7e6055SDimitry Andric const MCPhysReg *CSR = TRI->getCalleeSavedRegs(MF);
6157a7e6055SDimitry Andric for (const MCPhysReg *I = CSR; *I; ++I)
6167a7e6055SDimitry Andric UpdatedCSRs.push_back(*I);
6177a7e6055SDimitry Andric
6187a7e6055SDimitry Andric // Zero value represents the end of the register list
6197a7e6055SDimitry Andric // (no more registers should be pushed).
6207a7e6055SDimitry Andric UpdatedCSRs.push_back(0);
6217a7e6055SDimitry Andric
6227a7e6055SDimitry Andric IsUpdatedCSRsInitialized = true;
6237a7e6055SDimitry Andric }
6247a7e6055SDimitry Andric
6257a7e6055SDimitry Andric // Remove the register (and its aliases from the list).
6267a7e6055SDimitry Andric for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
6277a7e6055SDimitry Andric UpdatedCSRs.erase(std::remove(UpdatedCSRs.begin(), UpdatedCSRs.end(), *AI),
6287a7e6055SDimitry Andric UpdatedCSRs.end());
6297a7e6055SDimitry Andric }
6307a7e6055SDimitry Andric
getCalleeSavedRegs() const6317a7e6055SDimitry Andric const MCPhysReg *MachineRegisterInfo::getCalleeSavedRegs() const {
6327a7e6055SDimitry Andric if (IsUpdatedCSRsInitialized)
6337a7e6055SDimitry Andric return UpdatedCSRs.data();
6347a7e6055SDimitry Andric
6357a7e6055SDimitry Andric return getTargetRegisterInfo()->getCalleeSavedRegs(MF);
6367a7e6055SDimitry Andric }
6377a7e6055SDimitry Andric
setCalleeSavedRegs(ArrayRef<MCPhysReg> CSRs)6387a7e6055SDimitry Andric void MachineRegisterInfo::setCalleeSavedRegs(ArrayRef<MCPhysReg> CSRs) {
6397a7e6055SDimitry Andric if (IsUpdatedCSRsInitialized)
6407a7e6055SDimitry Andric UpdatedCSRs.clear();
6417a7e6055SDimitry Andric
6427a7e6055SDimitry Andric for (MCPhysReg Reg : CSRs)
6437a7e6055SDimitry Andric UpdatedCSRs.push_back(Reg);
6447a7e6055SDimitry Andric
6457a7e6055SDimitry Andric // Zero value represents the end of the register list
6467a7e6055SDimitry Andric // (no more registers should be pushed).
6477a7e6055SDimitry Andric UpdatedCSRs.push_back(0);
6487a7e6055SDimitry Andric IsUpdatedCSRsInitialized = true;
6497a7e6055SDimitry Andric }
650d4419f6fSDimitry Andric
isReservedRegUnit(unsigned Unit) const651d4419f6fSDimitry Andric bool MachineRegisterInfo::isReservedRegUnit(unsigned Unit) const {
652d4419f6fSDimitry Andric const TargetRegisterInfo *TRI = getTargetRegisterInfo();
653d4419f6fSDimitry Andric for (MCRegUnitRootIterator Root(Unit, TRI); Root.isValid(); ++Root) {
654d4419f6fSDimitry Andric bool IsRootReserved = true;
655d4419f6fSDimitry Andric for (MCSuperRegIterator Super(*Root, TRI, /*IncludeSelf=*/true);
656d4419f6fSDimitry Andric Super.isValid(); ++Super) {
657d4419f6fSDimitry Andric unsigned Reg = *Super;
658d4419f6fSDimitry Andric if (!isReserved(Reg)) {
659d4419f6fSDimitry Andric IsRootReserved = false;
660d4419f6fSDimitry Andric break;
661d4419f6fSDimitry Andric }
662d4419f6fSDimitry Andric }
663d4419f6fSDimitry Andric if (IsRootReserved)
664d4419f6fSDimitry Andric return true;
665d4419f6fSDimitry Andric }
666d4419f6fSDimitry Andric return false;
667d4419f6fSDimitry Andric }
668