MachineRegisterInfo.h [plain text]
#ifndef LLVM_CODEGEN_MACHINEREGISTERINFO_H
#define LLVM_CODEGEN_MACHINEREGISTERINFO_H
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <vector>
namespace llvm {
class PSetIterator;
class MachineRegisterInfo {
public:
class Delegate {
virtual void anchor();
public:
virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0;
virtual ~Delegate() {}
};
private:
const MachineFunction *MF;
Delegate *TheDelegate;
bool IsSSA;
bool TracksLiveness;
bool TracksSubRegLiveness;
IndexedMap<std::pair<const TargetRegisterClass*, MachineOperand*>,
VirtReg2IndexFunctor> VRegInfo;
IndexedMap<std::pair<unsigned, unsigned>, VirtReg2IndexFunctor> RegAllocHints;
std::vector<MachineOperand *> PhysRegUseDefLists;
MachineOperand *&getRegUseDefListHead(unsigned RegNo) {
if (TargetRegisterInfo::isVirtualRegister(RegNo))
return VRegInfo[RegNo].second;
return PhysRegUseDefLists[RegNo];
}
MachineOperand *getRegUseDefListHead(unsigned RegNo) const {
if (TargetRegisterInfo::isVirtualRegister(RegNo))
return VRegInfo[RegNo].second;
return PhysRegUseDefLists[RegNo];
}
static MachineOperand *getNextOperandForReg(const MachineOperand *MO) {
assert(MO && MO->isReg() && "This is not a register operand!");
return MO->Contents.Reg.Next;
}
BitVector UsedRegUnits;
BitVector UsedPhysRegMask;
BitVector ReservedRegs;
std::vector<std::pair<unsigned, unsigned> > LiveIns;
MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION;
void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION;
public:
explicit MachineRegisterInfo(const MachineFunction *MF);
const TargetRegisterInfo *getTargetRegisterInfo() const {
return MF->getSubtarget().getRegisterInfo();
}
void resetDelegate(Delegate *delegate) {
assert(TheDelegate == delegate &&
"Only the current delegate can perform reset!");
TheDelegate = nullptr;
}
void setDelegate(Delegate *delegate) {
assert(delegate && !TheDelegate &&
"Attempted to set delegate to null, or to change it without "
"first resetting it!");
TheDelegate = delegate;
}
bool isSSA() const { return IsSSA; }
void leaveSSA() { IsSSA = false; }
bool tracksLiveness() const { return TracksLiveness; }
void invalidateLiveness() { TracksLiveness = false; }
bool tracksSubRegLiveness() const { return TracksSubRegLiveness; }
void enableSubRegLiveness(bool Enable = true) {
TracksSubRegLiveness = Enable;
}
void addRegOperandToUseList(MachineOperand *MO);
void removeRegOperandFromUseList(MachineOperand *MO);
void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps);
void verifyUseList(unsigned Reg) const;
void verifyUseLists() const;
template<bool Uses, bool Defs, bool SkipDebug,
bool ByOperand, bool ByInstr, bool ByBundle>
class defusechain_iterator;
template<bool Uses, bool Defs, bool SkipDebug,
bool ByOperand, bool ByInstr, bool ByBundle>
class defusechain_instr_iterator;
template<bool, bool, bool, bool, bool, bool>
friend class defusechain_iterator;
template<bool, bool, bool, bool, bool, bool>
friend class defusechain_instr_iterator;
typedef defusechain_iterator<true,true,false,true,false,false>
reg_iterator;
reg_iterator reg_begin(unsigned RegNo) const {
return reg_iterator(getRegUseDefListHead(RegNo));
}
static reg_iterator reg_end() { return reg_iterator(nullptr); }
inline iterator_range<reg_iterator> reg_operands(unsigned Reg) const {
return iterator_range<reg_iterator>(reg_begin(Reg), reg_end());
}
typedef defusechain_instr_iterator<true,true,false,false,true,false>
reg_instr_iterator;
reg_instr_iterator reg_instr_begin(unsigned RegNo) const {
return reg_instr_iterator(getRegUseDefListHead(RegNo));
}
static reg_instr_iterator reg_instr_end() {
return reg_instr_iterator(nullptr);
}
inline iterator_range<reg_instr_iterator>
reg_instructions(unsigned Reg) const {
return iterator_range<reg_instr_iterator>(reg_instr_begin(Reg),
reg_instr_end());
}
typedef defusechain_instr_iterator<true,true,false,false,false,true>
reg_bundle_iterator;
reg_bundle_iterator reg_bundle_begin(unsigned RegNo) const {
return reg_bundle_iterator(getRegUseDefListHead(RegNo));
}
static reg_bundle_iterator reg_bundle_end() {
return reg_bundle_iterator(nullptr);
}
inline iterator_range<reg_bundle_iterator> reg_bundles(unsigned Reg) const {
return iterator_range<reg_bundle_iterator>(reg_bundle_begin(Reg),
reg_bundle_end());
}
bool reg_empty(unsigned RegNo) const { return reg_begin(RegNo) == reg_end(); }
typedef defusechain_iterator<true,true,true,true,false,false>
reg_nodbg_iterator;
reg_nodbg_iterator reg_nodbg_begin(unsigned RegNo) const {
return reg_nodbg_iterator(getRegUseDefListHead(RegNo));
}
static reg_nodbg_iterator reg_nodbg_end() {
return reg_nodbg_iterator(nullptr);
}
inline iterator_range<reg_nodbg_iterator>
reg_nodbg_operands(unsigned Reg) const {
return iterator_range<reg_nodbg_iterator>(reg_nodbg_begin(Reg),
reg_nodbg_end());
}
typedef defusechain_instr_iterator<true,true,true,false,true,false>
reg_instr_nodbg_iterator;
reg_instr_nodbg_iterator reg_instr_nodbg_begin(unsigned RegNo) const {
return reg_instr_nodbg_iterator(getRegUseDefListHead(RegNo));
}
static reg_instr_nodbg_iterator reg_instr_nodbg_end() {
return reg_instr_nodbg_iterator(nullptr);
}
inline iterator_range<reg_instr_nodbg_iterator>
reg_nodbg_instructions(unsigned Reg) const {
return iterator_range<reg_instr_nodbg_iterator>(reg_instr_nodbg_begin(Reg),
reg_instr_nodbg_end());
}
typedef defusechain_instr_iterator<true,true,true,false,false,true>
reg_bundle_nodbg_iterator;
reg_bundle_nodbg_iterator reg_bundle_nodbg_begin(unsigned RegNo) const {
return reg_bundle_nodbg_iterator(getRegUseDefListHead(RegNo));
}
static reg_bundle_nodbg_iterator reg_bundle_nodbg_end() {
return reg_bundle_nodbg_iterator(nullptr);
}
inline iterator_range<reg_bundle_nodbg_iterator>
reg_nodbg_bundles(unsigned Reg) const {
return iterator_range<reg_bundle_nodbg_iterator>(reg_bundle_nodbg_begin(Reg),
reg_bundle_nodbg_end());
}
bool reg_nodbg_empty(unsigned RegNo) const {
return reg_nodbg_begin(RegNo) == reg_nodbg_end();
}
typedef defusechain_iterator<false,true,false,true,false,false>
def_iterator;
def_iterator def_begin(unsigned RegNo) const {
return def_iterator(getRegUseDefListHead(RegNo));
}
static def_iterator def_end() { return def_iterator(nullptr); }
inline iterator_range<def_iterator> def_operands(unsigned Reg) const {
return iterator_range<def_iterator>(def_begin(Reg), def_end());
}
typedef defusechain_instr_iterator<false,true,false,false,true,false>
def_instr_iterator;
def_instr_iterator def_instr_begin(unsigned RegNo) const {
return def_instr_iterator(getRegUseDefListHead(RegNo));
}
static def_instr_iterator def_instr_end() {
return def_instr_iterator(nullptr);
}
inline iterator_range<def_instr_iterator>
def_instructions(unsigned Reg) const {
return iterator_range<def_instr_iterator>(def_instr_begin(Reg),
def_instr_end());
}
typedef defusechain_instr_iterator<false,true,false,false,false,true>
def_bundle_iterator;
def_bundle_iterator def_bundle_begin(unsigned RegNo) const {
return def_bundle_iterator(getRegUseDefListHead(RegNo));
}
static def_bundle_iterator def_bundle_end() {
return def_bundle_iterator(nullptr);
}
inline iterator_range<def_bundle_iterator> def_bundles(unsigned Reg) const {
return iterator_range<def_bundle_iterator>(def_bundle_begin(Reg),
def_bundle_end());
}
bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); }
bool hasOneDef(unsigned RegNo) const {
def_iterator DI = def_begin(RegNo);
if (DI == def_end())
return false;
return ++DI == def_end();
}
typedef defusechain_iterator<true,false,false,true,false,false>
use_iterator;
use_iterator use_begin(unsigned RegNo) const {
return use_iterator(getRegUseDefListHead(RegNo));
}
static use_iterator use_end() { return use_iterator(nullptr); }
inline iterator_range<use_iterator> use_operands(unsigned Reg) const {
return iterator_range<use_iterator>(use_begin(Reg), use_end());
}
typedef defusechain_instr_iterator<true,false,false,false,true,false>
use_instr_iterator;
use_instr_iterator use_instr_begin(unsigned RegNo) const {
return use_instr_iterator(getRegUseDefListHead(RegNo));
}
static use_instr_iterator use_instr_end() {
return use_instr_iterator(nullptr);
}
inline iterator_range<use_instr_iterator>
use_instructions(unsigned Reg) const {
return iterator_range<use_instr_iterator>(use_instr_begin(Reg),
use_instr_end());
}
typedef defusechain_instr_iterator<true,false,false,false,false,true>
use_bundle_iterator;
use_bundle_iterator use_bundle_begin(unsigned RegNo) const {
return use_bundle_iterator(getRegUseDefListHead(RegNo));
}
static use_bundle_iterator use_bundle_end() {
return use_bundle_iterator(nullptr);
}
inline iterator_range<use_bundle_iterator> use_bundles(unsigned Reg) const {
return iterator_range<use_bundle_iterator>(use_bundle_begin(Reg),
use_bundle_end());
}
bool use_empty(unsigned RegNo) const { return use_begin(RegNo) == use_end(); }
bool hasOneUse(unsigned RegNo) const {
use_iterator UI = use_begin(RegNo);
if (UI == use_end())
return false;
return ++UI == use_end();
}
typedef defusechain_iterator<true,false,true,true,false,false>
use_nodbg_iterator;
use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const {
return use_nodbg_iterator(getRegUseDefListHead(RegNo));
}
static use_nodbg_iterator use_nodbg_end() {
return use_nodbg_iterator(nullptr);
}
inline iterator_range<use_nodbg_iterator>
use_nodbg_operands(unsigned Reg) const {
return iterator_range<use_nodbg_iterator>(use_nodbg_begin(Reg),
use_nodbg_end());
}
typedef defusechain_instr_iterator<true,false,true,false,true,false>
use_instr_nodbg_iterator;
use_instr_nodbg_iterator use_instr_nodbg_begin(unsigned RegNo) const {
return use_instr_nodbg_iterator(getRegUseDefListHead(RegNo));
}
static use_instr_nodbg_iterator use_instr_nodbg_end() {
return use_instr_nodbg_iterator(nullptr);
}
inline iterator_range<use_instr_nodbg_iterator>
use_nodbg_instructions(unsigned Reg) const {
return iterator_range<use_instr_nodbg_iterator>(use_instr_nodbg_begin(Reg),
use_instr_nodbg_end());
}
typedef defusechain_instr_iterator<true,false,true,false,false,true>
use_bundle_nodbg_iterator;
use_bundle_nodbg_iterator use_bundle_nodbg_begin(unsigned RegNo) const {
return use_bundle_nodbg_iterator(getRegUseDefListHead(RegNo));
}
static use_bundle_nodbg_iterator use_bundle_nodbg_end() {
return use_bundle_nodbg_iterator(nullptr);
}
inline iterator_range<use_bundle_nodbg_iterator>
use_nodbg_bundles(unsigned Reg) const {
return iterator_range<use_bundle_nodbg_iterator>(use_bundle_nodbg_begin(Reg),
use_bundle_nodbg_end());
}
bool use_nodbg_empty(unsigned RegNo) const {
return use_nodbg_begin(RegNo) == use_nodbg_end();
}
bool hasOneNonDBGUse(unsigned RegNo) const;
void replaceRegWith(unsigned FromReg, unsigned ToReg);
MachineInstr *getVRegDef(unsigned Reg) const;
MachineInstr *getUniqueVRegDef(unsigned Reg) const;
void clearKillFlags(unsigned Reg) const;
#ifndef NDEBUG
void dumpUses(unsigned RegNo) const;
#endif
bool isConstantPhysReg(unsigned PhysReg, const MachineFunction &MF) const;
PSetIterator getPressureSets(unsigned RegUnit) const;
const TargetRegisterClass *getRegClass(unsigned Reg) const {
return VRegInfo[Reg].first;
}
void setRegClass(unsigned Reg, const TargetRegisterClass *RC);
const TargetRegisterClass *constrainRegClass(unsigned Reg,
const TargetRegisterClass *RC,
unsigned MinNumRegs = 0);
bool recomputeRegClass(unsigned Reg);
unsigned createVirtualRegister(const TargetRegisterClass *RegClass);
unsigned getNumVirtRegs() const { return VRegInfo.size(); }
void clearVirtRegs();
void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) {
RegAllocHints[Reg].first = Type;
RegAllocHints[Reg].second = PrefReg;
}
std::pair<unsigned, unsigned>
getRegAllocationHint(unsigned Reg) const {
return RegAllocHints[Reg];
}
unsigned getSimpleHint(unsigned Reg) const {
std::pair<unsigned, unsigned> Hint = getRegAllocationHint(Reg);
return Hint.first ? 0 : Hint.second;
}
void markUsesInDebugValueAsUndef(unsigned Reg) const;
bool isPhysRegUsed(unsigned Reg) const {
if (UsedPhysRegMask.test(Reg))
return true;
for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo());
Units.isValid(); ++Units)
if (UsedRegUnits.test(*Units))
return true;
return false;
}
void setRegUnitUsed(unsigned RegUnit) {
UsedRegUnits.set(RegUnit);
}
void setPhysRegUsed(unsigned Reg) {
for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo());
Units.isValid(); ++Units)
UsedRegUnits.set(*Units);
}
void addPhysRegsUsedFromRegMask(const uint32_t *RegMask) {
UsedPhysRegMask.setBitsNotInMask(RegMask);
}
void setPhysRegUnused(unsigned Reg) {
UsedPhysRegMask.reset(Reg);
for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo());
Units.isValid(); ++Units)
UsedRegUnits.reset(*Units);
}
void freezeReservedRegs(const MachineFunction&);
bool reservedRegsFrozen() const {
return !ReservedRegs.empty();
}
bool canReserveReg(unsigned PhysReg) const {
return !reservedRegsFrozen() || ReservedRegs.test(PhysReg);
}
const BitVector &getReservedRegs() const {
assert(reservedRegsFrozen() &&
"Reserved registers haven't been frozen yet. "
"Use TRI::getReservedRegs().");
return ReservedRegs;
}
bool isReserved(unsigned PhysReg) const {
return getReservedRegs().test(PhysReg);
}
bool isAllocatable(unsigned PhysReg) const {
return getTargetRegisterInfo()->isInAllocatableClass(PhysReg) &&
!isReserved(PhysReg);
}
void addLiveIn(unsigned Reg, unsigned vreg = 0) {
LiveIns.push_back(std::make_pair(Reg, vreg));
}
typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator
livein_iterator;
livein_iterator livein_begin() const { return LiveIns.begin(); }
livein_iterator livein_end() const { return LiveIns.end(); }
bool livein_empty() const { return LiveIns.empty(); }
bool isLiveIn(unsigned Reg) const;
unsigned getLiveInPhysReg(unsigned VReg) const;
unsigned getLiveInVirtReg(unsigned PReg) const;
void EmitLiveInCopies(MachineBasicBlock *EntryMBB,
const TargetRegisterInfo &TRI,
const TargetInstrInfo &TII);
unsigned getMaxLaneMaskForVReg(unsigned Reg) const;
template<bool ReturnUses, bool ReturnDefs, bool SkipDebug,
bool ByOperand, bool ByInstr, bool ByBundle>
class defusechain_iterator
: public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> {
MachineOperand *Op;
explicit defusechain_iterator(MachineOperand *op) : Op(op) {
if (op) {
if ((!ReturnUses && op->isUse()) ||
(!ReturnDefs && op->isDef()) ||
(SkipDebug && op->isDebug()))
advance();
}
}
friend class MachineRegisterInfo;
void advance() {
assert(Op && "Cannot increment end iterator!");
Op = getNextOperandForReg(Op);
if (!ReturnUses) {
if (Op) {
if (Op->isUse())
Op = nullptr;
else
assert(!Op->isDebug() && "Can't have debug defs");
}
} else {
while (Op && ((!ReturnDefs && Op->isDef()) ||
(SkipDebug && Op->isDebug())))
Op = getNextOperandForReg(Op);
}
}
public:
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::reference reference;
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::pointer pointer;
defusechain_iterator(const defusechain_iterator &I) : Op(I.Op) {}
defusechain_iterator() : Op(nullptr) {}
bool operator==(const defusechain_iterator &x) const {
return Op == x.Op;
}
bool operator!=(const defusechain_iterator &x) const {
return !operator==(x);
}
bool atEnd() const { return Op == nullptr; }
defusechain_iterator &operator++() { assert(Op && "Cannot increment end iterator!");
if (ByOperand)
advance();
else if (ByInstr) {
MachineInstr *P = Op->getParent();
do {
advance();
} while (Op && Op->getParent() == P);
} else if (ByBundle) {
MachineInstr *P = getBundleStart(Op->getParent());
do {
advance();
} while (Op && getBundleStart(Op->getParent()) == P);
}
return *this;
}
defusechain_iterator operator++(int) { defusechain_iterator tmp = *this; ++*this; return tmp;
}
unsigned getOperandNo() const {
assert(Op && "Cannot dereference end iterator!");
return Op - &Op->getParent()->getOperand(0);
}
MachineOperand &operator*() const {
assert(Op && "Cannot dereference end iterator!");
return *Op;
}
MachineOperand *operator->() const {
assert(Op && "Cannot dereference end iterator!");
return Op;
}
};
template<bool ReturnUses, bool ReturnDefs, bool SkipDebug,
bool ByOperand, bool ByInstr, bool ByBundle>
class defusechain_instr_iterator
: public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> {
MachineOperand *Op;
explicit defusechain_instr_iterator(MachineOperand *op) : Op(op) {
if (op) {
if ((!ReturnUses && op->isUse()) ||
(!ReturnDefs && op->isDef()) ||
(SkipDebug && op->isDebug()))
advance();
}
}
friend class MachineRegisterInfo;
void advance() {
assert(Op && "Cannot increment end iterator!");
Op = getNextOperandForReg(Op);
if (!ReturnUses) {
if (Op) {
if (Op->isUse())
Op = nullptr;
else
assert(!Op->isDebug() && "Can't have debug defs");
}
} else {
while (Op && ((!ReturnDefs && Op->isDef()) ||
(SkipDebug && Op->isDebug())))
Op = getNextOperandForReg(Op);
}
}
public:
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::reference reference;
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::pointer pointer;
defusechain_instr_iterator(const defusechain_instr_iterator &I) : Op(I.Op){}
defusechain_instr_iterator() : Op(nullptr) {}
bool operator==(const defusechain_instr_iterator &x) const {
return Op == x.Op;
}
bool operator!=(const defusechain_instr_iterator &x) const {
return !operator==(x);
}
bool atEnd() const { return Op == nullptr; }
defusechain_instr_iterator &operator++() { assert(Op && "Cannot increment end iterator!");
if (ByOperand)
advance();
else if (ByInstr) {
MachineInstr *P = Op->getParent();
do {
advance();
} while (Op && Op->getParent() == P);
} else if (ByBundle) {
MachineInstr *P = getBundleStart(Op->getParent());
do {
advance();
} while (Op && getBundleStart(Op->getParent()) == P);
}
return *this;
}
defusechain_instr_iterator operator++(int) { defusechain_instr_iterator tmp = *this; ++*this; return tmp;
}
MachineInstr &operator*() const {
assert(Op && "Cannot dereference end iterator!");
if (ByBundle) return *(getBundleStart(Op->getParent()));
return *Op->getParent();
}
MachineInstr *operator->() const {
assert(Op && "Cannot dereference end iterator!");
if (ByBundle) return getBundleStart(Op->getParent());
return Op->getParent();
}
};
};
class PSetIterator {
const int *PSet;
unsigned Weight;
public:
PSetIterator(): PSet(nullptr), Weight(0) {}
PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) {
const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();
if (TargetRegisterInfo::isVirtualRegister(RegUnit)) {
const TargetRegisterClass *RC = MRI->getRegClass(RegUnit);
PSet = TRI->getRegClassPressureSets(RC);
Weight = TRI->getRegClassWeight(RC).RegWeight;
}
else {
PSet = TRI->getRegUnitPressureSets(RegUnit);
Weight = TRI->getRegUnitWeight(RegUnit);
}
if (*PSet == -1)
PSet = nullptr;
}
bool isValid() const { return PSet; }
unsigned getWeight() const { return Weight; }
unsigned operator*() const { return *PSet; }
void operator++() {
assert(isValid() && "Invalid PSetIterator.");
++PSet;
if (*PSet == -1)
PSet = nullptr;
}
};
inline PSetIterator MachineRegisterInfo::
getPressureSets(unsigned RegUnit) const {
return PSetIterator(RegUnit, this);
}
}
#endif