forked from OSchip/llvm-project
Add a CoveredBySubRegs property to Register descriptions.
When set, this bit indicates that a register is completely defined by the value of its sub-registers. Use the CoveredBySubRegs property to infer which super-registers are call-preserved given a list of callee-saved registers. For example, the ARM registers D8-D15 are callee-saved. This now automatically implies that Q4-Q7 are call-preserved. Conversely, Win64 callees save XMM6-XMM15, but the corresponding YMM6-YMM15 registers are not call-preserved because they are not fully defined by their sub-registers. llvm-svn: 148363
This commit is contained in:
parent
9619961e1b
commit
f43b599550
|
@ -86,6 +86,12 @@ class Register<string n, list<string> altNames = []> {
|
|||
// This is used by the x86-64 and ARM Thumb targets where some registers
|
||||
// require larger instruction encodings.
|
||||
int CostPerUse = 0;
|
||||
|
||||
// CoveredBySubRegs - When this bit is set, the value of this register is
|
||||
// completely determined by the value of its sub-registers. For example, the
|
||||
// x86 register AX is covered by its sub-registers AL and AH, but EAX is not
|
||||
// covered by its sub-register AX.
|
||||
bit CoveredBySubRegs = 0;
|
||||
}
|
||||
|
||||
// RegisterWithSubRegs - This can be used to define instances of Register which
|
||||
|
|
|
@ -16,6 +16,8 @@ class ARMReg<bits<4> num, string n, list<Register> subregs = []> : Register<n> {
|
|||
field bits<4> Num;
|
||||
let Namespace = "ARM";
|
||||
let SubRegs = subregs;
|
||||
// All bits of ARM registers with sub-registers are covered by sub-registers.
|
||||
let CoveredBySubRegs = 1;
|
||||
}
|
||||
|
||||
class ARMFReg<bits<6> num, string n> : Register<n> {
|
||||
|
|
|
@ -94,7 +94,7 @@ let Namespace = "Hexagon" in {
|
|||
def GP : Ri<31, "r31">, DwarfRegNum<[33]>;
|
||||
|
||||
// Aliases of the R* registers used to hold 64-bit int values (doubles).
|
||||
let SubRegIndices = [subreg_loreg, subreg_hireg] in {
|
||||
let SubRegIndices = [subreg_loreg, subreg_hireg], CoveredBySubRegs = 1 in {
|
||||
def D0 : Rd< 0, "r1:0", [R0, R1]>, DwarfRegNum<[32]>;
|
||||
def D1 : Rd< 2, "r3:2", [R2, R3]>, DwarfRegNum<[34]>;
|
||||
def D2 : Rd< 4, "r5:4", [R4, R5]>, DwarfRegNum<[36]>;
|
||||
|
|
|
@ -50,6 +50,7 @@ class AFPR<bits<5> num, string n, list<Register> subregs>
|
|||
: MipsRegWithSubRegs<n, subregs> {
|
||||
let Num = num;
|
||||
let SubRegIndices = [sub_fpeven, sub_fpodd];
|
||||
let CoveredBySubRegs = 1;
|
||||
}
|
||||
|
||||
class AFPR64<bits<5> num, string n, list<Register> subregs>
|
||||
|
|
|
@ -39,6 +39,7 @@ class Rd<bits<5> num, string n, list<Register> subregs> : SparcReg<n> {
|
|||
let Num = num;
|
||||
let SubRegs = subregs;
|
||||
let SubRegIndices = [sub_even, sub_odd];
|
||||
let CoveredBySubRegs = 1;
|
||||
}
|
||||
|
||||
// Control Registers
|
||||
|
|
|
@ -70,7 +70,7 @@ let Namespace = "X86" in {
|
|||
def BH : Register<"bh">;
|
||||
|
||||
// 16-bit registers
|
||||
let SubRegIndices = [sub_8bit, sub_8bit_hi] in {
|
||||
let SubRegIndices = [sub_8bit, sub_8bit_hi], CoveredBySubRegs = 1 in {
|
||||
def AX : RegisterWithSubRegs<"ax", [AL,AH]>;
|
||||
def DX : RegisterWithSubRegs<"dx", [DL,DH]>;
|
||||
def CX : RegisterWithSubRegs<"cx", [CL,CH]>;
|
||||
|
|
|
@ -29,6 +29,7 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
|
|||
: TheDef(R),
|
||||
EnumValue(Enum),
|
||||
CostPerUse(R->getValueAsInt("CostPerUse")),
|
||||
CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
|
||||
SubRegsComplete(false)
|
||||
{}
|
||||
|
||||
|
@ -215,33 +216,40 @@ struct TupleExpander : SetTheory::Expander {
|
|||
for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) {
|
||||
RecordVal RV = Proto->getValues()[i];
|
||||
|
||||
if (RV.getName() == "NAME")
|
||||
// Skip existing fields, like NAME.
|
||||
if (NewReg->getValue(RV.getNameInit()))
|
||||
continue;
|
||||
|
||||
StringRef Field = RV.getName();
|
||||
|
||||
// Replace the sub-register list with Tuple.
|
||||
if (RV.getName() == "SubRegs")
|
||||
if (Field == "SubRegs")
|
||||
RV.setValue(ListInit::get(Tuple, RegisterRecTy));
|
||||
|
||||
// Provide a blank AsmName. MC hacks are required anyway.
|
||||
if (RV.getName() == "AsmName")
|
||||
if (Field == "AsmName")
|
||||
RV.setValue(BlankName);
|
||||
|
||||
// CostPerUse is aggregated from all Tuple members.
|
||||
if (RV.getName() == "CostPerUse")
|
||||
if (Field == "CostPerUse")
|
||||
RV.setValue(IntInit::get(CostPerUse));
|
||||
|
||||
// Composite registers are always covered by sub-registers.
|
||||
if (Field == "CoveredBySubRegs")
|
||||
RV.setValue(BitInit::get(true));
|
||||
|
||||
// Copy fields from the RegisterTuples def.
|
||||
if (RV.getName() == "SubRegIndices" ||
|
||||
RV.getName() == "CompositeIndices") {
|
||||
NewReg->addValue(*Def->getValue(RV.getName()));
|
||||
if (Field == "SubRegIndices" ||
|
||||
Field == "CompositeIndices") {
|
||||
NewReg->addValue(*Def->getValue(Field));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Some fields get their default uninitialized value.
|
||||
if (RV.getName() == "DwarfNumbers" ||
|
||||
RV.getName() == "DwarfAlias" ||
|
||||
RV.getName() == "Aliases") {
|
||||
if (const RecordVal *DefRV = RegisterCl->getValue(RV.getName()))
|
||||
if (Field == "DwarfNumbers" ||
|
||||
Field == "DwarfAlias" ||
|
||||
Field == "Aliases") {
|
||||
if (const RecordVal *DefRV = RegisterCl->getValue(Field))
|
||||
NewReg->addValue(*DefRV);
|
||||
continue;
|
||||
}
|
||||
|
@ -1006,7 +1014,27 @@ BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) {
|
|||
}
|
||||
|
||||
// Second, find all super-registers that are completely covered by the set.
|
||||
// FIXME: Implement CoveredBySubRegs bit.
|
||||
for (unsigned i = 0; i != Set.size(); ++i) {
|
||||
const CodeGenRegister::SuperRegList &SR = Set[i]->getSuperRegs();
|
||||
for (unsigned j = 0, e = SR.size(); j != e; ++j) {
|
||||
CodeGenRegister *Super = SR[j];
|
||||
if (!Super->CoveredBySubRegs || Set.count(Super))
|
||||
continue;
|
||||
// This new super-register is covered by its sub-registers.
|
||||
bool AllSubsInSet = true;
|
||||
const CodeGenRegister::SubRegMap &SRM = Super->getSubRegs();
|
||||
for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
|
||||
E = SRM.end(); I != E; ++I)
|
||||
if (!Set.count(I->second)) {
|
||||
AllSubsInSet = false;
|
||||
break;
|
||||
}
|
||||
// All sub-registers in Set, add Super as well.
|
||||
// We will visit Super later to recheck its super-registers.
|
||||
if (AllSubsInSet)
|
||||
Set.insert(Super);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to BitVector.
|
||||
BitVector BV(Registers.size() + 1);
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace llvm {
|
|||
Record *TheDef;
|
||||
unsigned EnumValue;
|
||||
unsigned CostPerUse;
|
||||
bool CoveredBySubRegs;
|
||||
|
||||
// Map SubRegIndex -> Register.
|
||||
typedef std::map<Record*, CodeGenRegister*, LessRecord> SubRegMap;
|
||||
|
|
Loading…
Reference in New Issue