[Target][RISCV] Add HwMode support to subregister index size/offset. (#86368)
This is needed to provide proper size and offset for the GPRPair subreg indices on RISC-V. The size of a GPR already uses HwMode. Previously we said the subreg indices have unknown size and offset, but this stops DwarfExpression::addMachineReg from being able to find the registers that make up the pair. I believe this fixes https://github.com/llvm/llvm-project/issues/85864 but need to verify.
This commit is contained in:
parent
aeb8628c21
commit
baf66ec061
@ -83,10 +83,27 @@ class RegInfoByHwMode<list<HwMode> Ms = [], list<RegInfo> Ts = []>
|
|||||||
list<RegInfo> Objects = Ts;
|
list<RegInfo> Objects = Ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SubRegRange<int size, int offset = 0> {
|
||||||
|
int Size = size; // Sub register size in bits.
|
||||||
|
int Offset = offset; // Offset of the first bit of the sub-reg index.
|
||||||
|
}
|
||||||
|
|
||||||
|
class SubRegRangeByHwMode<list<HwMode> Ms = [], list<SubRegRange> Ts = []>
|
||||||
|
: HwModeSelect<Ms> {
|
||||||
|
// The length of this list must be the same as the length of Ms.
|
||||||
|
list<SubRegRange> Objects = Ts;
|
||||||
|
}
|
||||||
|
|
||||||
// SubRegIndex - Use instances of SubRegIndex to identify subregisters.
|
// SubRegIndex - Use instances of SubRegIndex to identify subregisters.
|
||||||
class SubRegIndex<int size, int offset = 0> {
|
class SubRegIndex<int size, int offset = 0> {
|
||||||
string Namespace = "";
|
string Namespace = "";
|
||||||
|
|
||||||
|
// The size/offset information, parameterized by a HW mode.
|
||||||
|
// If the HwModes provided for SubRegRanges does not include the DefaultMode,
|
||||||
|
// the/ Size and Offset fields below will be used for the default. Otherwise,
|
||||||
|
// the Size and Offset fields are ignored.
|
||||||
|
SubRegRangeByHwMode SubRegRanges;
|
||||||
|
|
||||||
// Size - Size (in bits) of the sub-registers represented by this index.
|
// Size - Size (in bits) of the sub-registers represented by this index.
|
||||||
int Size = size;
|
int Size = size;
|
||||||
|
|
||||||
|
@ -595,13 +595,13 @@ bool TargetRegisterInfo::getCoveringSubRegIndexes(
|
|||||||
unsigned TargetRegisterInfo::getSubRegIdxSize(unsigned Idx) const {
|
unsigned TargetRegisterInfo::getSubRegIdxSize(unsigned Idx) const {
|
||||||
assert(Idx && Idx < getNumSubRegIndices() &&
|
assert(Idx && Idx < getNumSubRegIndices() &&
|
||||||
"This is not a subregister index");
|
"This is not a subregister index");
|
||||||
return SubRegIdxRanges[Idx].Size;
|
return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned TargetRegisterInfo::getSubRegIdxOffset(unsigned Idx) const {
|
unsigned TargetRegisterInfo::getSubRegIdxOffset(unsigned Idx) const {
|
||||||
assert(Idx && Idx < getNumSubRegIndices() &&
|
assert(Idx && Idx < getNumSubRegIndices() &&
|
||||||
"This is not a subregister index");
|
"This is not a subregister index");
|
||||||
return SubRegIdxRanges[Idx].Offset;
|
return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Register
|
Register
|
||||||
|
@ -64,9 +64,14 @@ def sub_vrm1_6 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_0>;
|
|||||||
def sub_vrm1_7 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_1>;
|
def sub_vrm1_7 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_1>;
|
||||||
|
|
||||||
// GPR sizes change with HwMode.
|
// GPR sizes change with HwMode.
|
||||||
// FIXME: Support HwMode in SubRegIndex?
|
def sub_gpr_even : SubRegIndex<32> {
|
||||||
def sub_gpr_even : SubRegIndex<-1>;
|
let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64],
|
||||||
def sub_gpr_odd : SubRegIndex<-1, -1>;
|
[SubRegRange<32>, SubRegRange<64>]>;
|
||||||
|
}
|
||||||
|
def sub_gpr_odd : SubRegIndex<32, 32> {
|
||||||
|
let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64],
|
||||||
|
[SubRegRange<32, 32>, SubRegRange<64, 64>]>;
|
||||||
|
}
|
||||||
} // Namespace = "RISCV"
|
} // Namespace = "RISCV"
|
||||||
|
|
||||||
// Integer registers
|
// Integer registers
|
||||||
|
@ -90,16 +90,19 @@ def TestTarget : Target;
|
|||||||
// CHECK-LABEL: RegisterClass DRegs:
|
// CHECK-LABEL: RegisterClass DRegs:
|
||||||
|
|
||||||
// CHECK-LABEL: SubRegIndex ssub1:
|
// CHECK-LABEL: SubRegIndex ssub1:
|
||||||
// CHECK: Offset, Size: 16, 16
|
// CHECK: Offset: { Default:16 }
|
||||||
|
// CHECK: Size: { Default:16 }
|
||||||
// CHECK-LABEL: SubRegIndex sub0:
|
// CHECK-LABEL: SubRegIndex sub0:
|
||||||
// CHECK-LABEL: SubRegIndex sub1:
|
// CHECK-LABEL: SubRegIndex sub1:
|
||||||
// CHECK-LABEL: SubRegIndex sub2:
|
// CHECK-LABEL: SubRegIndex sub2:
|
||||||
// Check inferred indexes:
|
// Check inferred indexes:
|
||||||
// CHECK-LABEL: SubRegIndex ssub1_ssub2:
|
// CHECK-LABEL: SubRegIndex ssub1_ssub2:
|
||||||
// CHECK: Offset, Size: 16, 65535
|
// CHECK: Offset: { Default:16 }
|
||||||
|
// CHECK: Size: { Default:65535 }
|
||||||
// CHECK-LABEL: SubRegIndex ssub3_ssub4:
|
// CHECK-LABEL: SubRegIndex ssub3_ssub4:
|
||||||
// CHECK-LABEL: SubRegIndex ssub0_ssub1_ssub2_ssub3:
|
// CHECK-LABEL: SubRegIndex ssub0_ssub1_ssub2_ssub3:
|
||||||
// CHECK: Offset, Size: 65535, 65535
|
// CHECK: Offset: { Default:65535 }
|
||||||
|
// CHECK: Size: { Default:65535 }
|
||||||
// CHECK-LABEL: SubRegIndex ssub1_ssub2_ssub3_ssub4:
|
// CHECK-LABEL: SubRegIndex ssub1_ssub2_ssub3_ssub4:
|
||||||
|
|
||||||
// Check that all subregs are generated on some examples
|
// Check that all subregs are generated on some examples
|
||||||
|
75
llvm/test/TableGen/HwModeSubRegs.td
Normal file
75
llvm/test/TableGen/HwModeSubRegs.td
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s
|
||||||
|
include "llvm/Target/Target.td"
|
||||||
|
|
||||||
|
def HasFeat : Predicate<"Subtarget->hasFeat()">;
|
||||||
|
|
||||||
|
def TestMode : HwMode<"+feat1", [HasFeat]>;
|
||||||
|
|
||||||
|
class MyReg<string n>
|
||||||
|
: Register<n> {
|
||||||
|
let Namespace = "Test";
|
||||||
|
}
|
||||||
|
class MyClass<int size, list<ValueType> types, dag registers>
|
||||||
|
: RegisterClass<"Test", types, size, registers> {
|
||||||
|
let Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
def X0 : MyReg<"x0">;
|
||||||
|
def X1 : MyReg<"x1">;
|
||||||
|
def X2 : MyReg<"x2">;
|
||||||
|
def X3 : MyReg<"x3">;
|
||||||
|
def X4 : MyReg<"x4">;
|
||||||
|
def X5 : MyReg<"x5">;
|
||||||
|
def X6 : MyReg<"x6">;
|
||||||
|
def X7 : MyReg<"x7">;
|
||||||
|
def X8 : MyReg<"x8">;
|
||||||
|
def X9 : MyReg<"x9">;
|
||||||
|
def X10 : MyReg<"x10">;
|
||||||
|
def X11 : MyReg<"x11">;
|
||||||
|
def X12 : MyReg<"x12">;
|
||||||
|
def X13 : MyReg<"x13">;
|
||||||
|
def X14 : MyReg<"x14">;
|
||||||
|
def X15 : MyReg<"x15">;
|
||||||
|
|
||||||
|
def ModeVT : ValueTypeByHwMode<[DefaultMode, TestMode],
|
||||||
|
[i32, i64]>;
|
||||||
|
let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
|
||||||
|
[RegInfo<32,32,32>, RegInfo<64,64,64>]> in
|
||||||
|
def XRegs : MyClass<32, [ModeVT], (sequence "X%u", 0, 15)>;
|
||||||
|
|
||||||
|
def sub_even : SubRegIndex<32> {
|
||||||
|
let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
|
||||||
|
[SubRegRange<32>, SubRegRange<64>]>;
|
||||||
|
}
|
||||||
|
def sub_odd : SubRegIndex<32, 32> {
|
||||||
|
let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
|
||||||
|
[SubRegRange<32, 32>, SubRegRange<64, 64>]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
def XPairs : RegisterTuples<[sub_even, sub_odd],
|
||||||
|
[(decimate (rotl XRegs, 0), 2),
|
||||||
|
(decimate (rotl XRegs, 1), 2)]>;
|
||||||
|
|
||||||
|
let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
|
||||||
|
[RegInfo<64,64,32>, RegInfo<128,128,64>]> in
|
||||||
|
def XPairsClass : MyClass<64, [untyped], (add XPairs)>;
|
||||||
|
|
||||||
|
def TestTarget : Target;
|
||||||
|
|
||||||
|
// CHECK-LABEL: RegisterClass XRegs:
|
||||||
|
// CHECK: SpillSize: { Default:32 TestMode:64 }
|
||||||
|
// CHECK: SpillAlignment: { Default:32 TestMode:64 }
|
||||||
|
// CHECK: Regs: X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
|
||||||
|
|
||||||
|
// CHECK-LABEL: RegisterClass XPairsClass:
|
||||||
|
// CHECK: SpillSize: { Default:64 TestMode:128 }
|
||||||
|
// CHECK: SpillAlignment: { Default:32 TestMode:64 }
|
||||||
|
// CHECK: CoveredBySubRegs: 1
|
||||||
|
// CHECK: Regs: X0_X1 X2_X3 X4_X5 X6_X7 X8_X9 X10_X11 X12_X13 X14_X15
|
||||||
|
|
||||||
|
// CHECK-LABEL: SubRegIndex sub_even:
|
||||||
|
// CHECK: Offset: { Default:0 TestMode:0 }
|
||||||
|
// CHECK: Size: { Default:32 TestMode:64 }
|
||||||
|
// CHECK-LABEL: SubRegIndex sub_odd:
|
||||||
|
// CHECK: Offset: { Default:32 TestMode:64 }
|
||||||
|
// CHECK: Size: { Default:32 TestMode:64 }
|
@ -47,19 +47,24 @@ using namespace llvm;
|
|||||||
// CodeGenSubRegIndex
|
// CodeGenSubRegIndex
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
|
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum,
|
||||||
|
const CodeGenHwModes &CGH)
|
||||||
: TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {
|
: TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {
|
||||||
Name = std::string(R->getName());
|
Name = std::string(R->getName());
|
||||||
if (R->getValue("Namespace"))
|
if (R->getValue("Namespace"))
|
||||||
Namespace = std::string(R->getValueAsString("Namespace"));
|
Namespace = std::string(R->getValueAsString("Namespace"));
|
||||||
Size = R->getValueAsInt("Size");
|
|
||||||
Offset = R->getValueAsInt("Offset");
|
if (const RecordVal *RV = R->getValue("SubRegRanges"))
|
||||||
|
if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue()))
|
||||||
|
Range = SubRegRangeByHwMode(DI->getDef(), CGH);
|
||||||
|
if (!Range.hasDefault())
|
||||||
|
Range.insertSubRegRangeForMode(DefaultMode, SubRegRange(R));
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
|
CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
|
||||||
unsigned Enum)
|
unsigned Enum)
|
||||||
: TheDef(nullptr), Name(std::string(N)), Namespace(std::string(Nspace)),
|
: TheDef(nullptr), Name(std::string(N)), Namespace(std::string(Nspace)),
|
||||||
Size(-1), Offset(-1), EnumValue(Enum), AllSuperRegsCovered(true),
|
Range(SubRegRange(-1, -1)), EnumValue(Enum), AllSuperRegsCovered(true),
|
||||||
Artificial(true) {}
|
Artificial(true) {}
|
||||||
|
|
||||||
std::string CodeGenSubRegIndex::getQualifiedName() const {
|
std::string CodeGenSubRegIndex::getQualifiedName() const {
|
||||||
@ -81,7 +86,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
|
|||||||
"ComposedOf must have exactly two entries");
|
"ComposedOf must have exactly two entries");
|
||||||
CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
|
CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
|
||||||
CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
|
CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
|
||||||
CodeGenSubRegIndex *X = A->addComposite(B, this);
|
CodeGenSubRegIndex *X = A->addComposite(B, this, RegBank.getHwModes());
|
||||||
if (X)
|
if (X)
|
||||||
PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
|
PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
|
||||||
}
|
}
|
||||||
@ -518,7 +523,8 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
|
|||||||
|
|
||||||
// Each part of Cand is a sub-register of this. Make the full Cand also
|
// Each part of Cand is a sub-register of this. Make the full Cand also
|
||||||
// a sub-register with a concatenated sub-register index.
|
// a sub-register with a concatenated sub-register index.
|
||||||
CodeGenSubRegIndex *Concat = RegBank.getConcatSubRegIndex(Parts);
|
CodeGenSubRegIndex *Concat =
|
||||||
|
RegBank.getConcatSubRegIndex(Parts, RegBank.getHwModes());
|
||||||
std::pair<CodeGenSubRegIndex *, CodeGenRegister *> NewSubReg =
|
std::pair<CodeGenSubRegIndex *, CodeGenRegister *> NewSubReg =
|
||||||
std::pair(Concat, Cand);
|
std::pair(Concat, Cand);
|
||||||
|
|
||||||
@ -542,7 +548,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
|
|||||||
PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
|
PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
|
||||||
SubReg.second->getName() +
|
SubReg.second->getName() +
|
||||||
" in " + getName());
|
" in " + getName());
|
||||||
NewIdx->addComposite(SubReg.first, SubIdx);
|
NewIdx->addComposite(SubReg.first, SubIdx, RegBank.getHwModes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1315,7 +1321,7 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
|
|||||||
CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
|
CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
|
||||||
if (Idx)
|
if (Idx)
|
||||||
return Idx;
|
return Idx;
|
||||||
SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1);
|
SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1, getHwModes());
|
||||||
Idx = &SubRegIndices.back();
|
Idx = &SubRegIndices.back();
|
||||||
return Idx;
|
return Idx;
|
||||||
}
|
}
|
||||||
@ -1379,12 +1385,13 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
|
|||||||
// None exists, synthesize one.
|
// None exists, synthesize one.
|
||||||
std::string Name = A->getName() + "_then_" + B->getName();
|
std::string Name = A->getName() + "_then_" + B->getName();
|
||||||
Comp = createSubRegIndex(Name, A->getNamespace());
|
Comp = createSubRegIndex(Name, A->getNamespace());
|
||||||
A->addComposite(B, Comp);
|
A->addComposite(B, Comp, getHwModes());
|
||||||
return Comp;
|
return Comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
|
CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
|
||||||
const SmallVector<CodeGenSubRegIndex *, 8> &Parts) {
|
const SmallVector<CodeGenSubRegIndex *, 8> &Parts,
|
||||||
|
const CodeGenHwModes &CGH) {
|
||||||
assert(Parts.size() > 1 && "Need two parts to concatenate");
|
assert(Parts.size() > 1 && "Need two parts to concatenate");
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for (CodeGenSubRegIndex *Idx : Parts) {
|
for (CodeGenSubRegIndex *Idx : Parts) {
|
||||||
@ -1399,28 +1406,47 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
|
|||||||
|
|
||||||
// None exists, synthesize one.
|
// None exists, synthesize one.
|
||||||
std::string Name = Parts.front()->getName();
|
std::string Name = Parts.front()->getName();
|
||||||
// Determine whether all parts are contiguous.
|
|
||||||
bool IsContinuous = true;
|
|
||||||
unsigned Size = Parts.front()->Size;
|
|
||||||
unsigned LastOffset = Parts.front()->Offset;
|
|
||||||
unsigned LastSize = Parts.front()->Size;
|
|
||||||
const unsigned UnknownSize = (uint16_t)-1;
|
const unsigned UnknownSize = (uint16_t)-1;
|
||||||
|
|
||||||
for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
|
for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
|
||||||
Name += '_';
|
Name += '_';
|
||||||
Name += Parts[i]->getName();
|
Name += Parts[i]->getName();
|
||||||
if (Size == UnknownSize || Parts[i]->Size == UnknownSize)
|
|
||||||
Size = UnknownSize;
|
|
||||||
else
|
|
||||||
Size += Parts[i]->Size;
|
|
||||||
if (LastSize == UnknownSize || Parts[i]->Offset != (LastOffset + LastSize))
|
|
||||||
IsContinuous = false;
|
|
||||||
LastOffset = Parts[i]->Offset;
|
|
||||||
LastSize = Parts[i]->Size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
|
Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
|
||||||
Idx->Size = Size;
|
|
||||||
Idx->Offset = IsContinuous ? Parts.front()->Offset : -1;
|
|
||||||
Idx->ConcatenationOf.assign(Parts.begin(), Parts.end());
|
Idx->ConcatenationOf.assign(Parts.begin(), Parts.end());
|
||||||
|
|
||||||
|
unsigned NumModes = CGH.getNumModeIds();
|
||||||
|
for (unsigned M = 0; M < NumModes; ++M) {
|
||||||
|
const CodeGenSubRegIndex *Part = Parts.front();
|
||||||
|
|
||||||
|
// Determine whether all parts are contiguous.
|
||||||
|
bool IsContinuous = true;
|
||||||
|
const SubRegRange &FirstPartRange = Part->Range.get(M);
|
||||||
|
unsigned Size = FirstPartRange.Size;
|
||||||
|
unsigned LastOffset = FirstPartRange.Offset;
|
||||||
|
unsigned LastSize = FirstPartRange.Size;
|
||||||
|
|
||||||
|
for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
|
||||||
|
Part = Parts[i];
|
||||||
|
Name += '_';
|
||||||
|
Name += Part->getName();
|
||||||
|
|
||||||
|
const SubRegRange &PartRange = Part->Range.get(M);
|
||||||
|
if (Size == UnknownSize || PartRange.Size == UnknownSize)
|
||||||
|
Size = UnknownSize;
|
||||||
|
else
|
||||||
|
Size += PartRange.Size;
|
||||||
|
if (LastSize == UnknownSize ||
|
||||||
|
PartRange.Offset != (LastOffset + LastSize))
|
||||||
|
IsContinuous = false;
|
||||||
|
LastOffset = PartRange.Offset;
|
||||||
|
LastSize = PartRange.Size;
|
||||||
|
}
|
||||||
|
unsigned Offset = IsContinuous ? FirstPartRange.Offset : -1;
|
||||||
|
Idx->Range.get(M) = SubRegRange(Size, Offset);
|
||||||
|
}
|
||||||
|
|
||||||
return Idx;
|
return Idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1504,7 +1530,8 @@ void CodeGenRegBank::computeComposites() {
|
|||||||
assert(Idx3 && "Sub-register doesn't have an index");
|
assert(Idx3 && "Sub-register doesn't have an index");
|
||||||
|
|
||||||
// Conflicting composition? Emit a warning but allow it.
|
// Conflicting composition? Emit a warning but allow it.
|
||||||
if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3)) {
|
if (CodeGenSubRegIndex *Prev =
|
||||||
|
Idx1->addComposite(Idx2, Idx3, getHwModes())) {
|
||||||
// If the composition was not user-defined, always emit a warning.
|
// If the composition was not user-defined, always emit a warning.
|
||||||
if (!UserDefined.count({Idx1, Idx2}) ||
|
if (!UserDefined.count({Idx1, Idx2}) ||
|
||||||
agree(compose(Idx1, Idx2), SubRegAction.at(Idx3)))
|
agree(compose(Idx1, Idx2), SubRegAction.at(Idx3)))
|
||||||
|
@ -68,8 +68,7 @@ class CodeGenSubRegIndex {
|
|||||||
std::string Namespace;
|
std::string Namespace;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint16_t Size;
|
SubRegRangeByHwMode Range;
|
||||||
uint16_t Offset;
|
|
||||||
const unsigned EnumValue;
|
const unsigned EnumValue;
|
||||||
mutable LaneBitmask LaneMask;
|
mutable LaneBitmask LaneMask;
|
||||||
mutable SmallVector<MaskRolPair, 1> CompositionLaneMaskTransform;
|
mutable SmallVector<MaskRolPair, 1> CompositionLaneMaskTransform;
|
||||||
@ -86,7 +85,7 @@ public:
|
|||||||
// indexes are not used to create new register classes.
|
// indexes are not used to create new register classes.
|
||||||
bool Artificial;
|
bool Artificial;
|
||||||
|
|
||||||
CodeGenSubRegIndex(Record *R, unsigned Enum);
|
CodeGenSubRegIndex(Record *R, unsigned Enum, const CodeGenHwModes &CGH);
|
||||||
CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
|
CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
|
||||||
CodeGenSubRegIndex(CodeGenSubRegIndex &) = delete;
|
CodeGenSubRegIndex(CodeGenSubRegIndex &) = delete;
|
||||||
|
|
||||||
@ -108,19 +107,42 @@ public:
|
|||||||
|
|
||||||
// Add a composite subreg index: this+A = B.
|
// Add a composite subreg index: this+A = B.
|
||||||
// Return a conflicting composite, or NULL
|
// Return a conflicting composite, or NULL
|
||||||
CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A,
|
CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B,
|
||||||
CodeGenSubRegIndex *B) {
|
const CodeGenHwModes &CGH) {
|
||||||
assert(A && B);
|
assert(A && B);
|
||||||
std::pair<CompMap::iterator, bool> Ins = Composed.insert(std::pair(A, B));
|
std::pair<CompMap::iterator, bool> Ins = Composed.insert(std::pair(A, B));
|
||||||
|
|
||||||
// Synthetic subreg indices that aren't contiguous (for instance ARM
|
// Synthetic subreg indices that aren't contiguous (for instance ARM
|
||||||
// register tuples) don't have a bit range, so it's OK to let
|
// register tuples) don't have a bit range, so it's OK to let
|
||||||
// B->Offset == -1. For the other cases, accumulate the offset and set
|
// B->Offset == -1. For the other cases, accumulate the offset and set
|
||||||
// the size here. Only do so if there is no offset yet though.
|
// the size here. Only do so if there is no offset yet though.
|
||||||
if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) &&
|
unsigned NumModes = CGH.getNumModeIds();
|
||||||
(B->Offset == (uint16_t)-1)) {
|
// Skip default mode.
|
||||||
B->Offset = Offset + A->Offset;
|
for (unsigned M = 0; M < NumModes; ++M) {
|
||||||
B->Size = A->Size;
|
// Handle DefaultMode last.
|
||||||
|
if (M == DefaultMode)
|
||||||
|
continue;
|
||||||
|
SubRegRange &Range = this->Range.get(M);
|
||||||
|
SubRegRange &ARange = A->Range.get(M);
|
||||||
|
SubRegRange &BRange = B->Range.get(M);
|
||||||
|
|
||||||
|
if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 &&
|
||||||
|
BRange.Offset == (uint16_t)-1) {
|
||||||
|
BRange.Offset = Range.Offset + ARange.Offset;
|
||||||
|
BRange.Size = ARange.Size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now handle default.
|
||||||
|
SubRegRange &Range = this->Range.get(DefaultMode);
|
||||||
|
SubRegRange &ARange = A->Range.get(DefaultMode);
|
||||||
|
SubRegRange &BRange = B->Range.get(DefaultMode);
|
||||||
|
if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 &&
|
||||||
|
BRange.Offset == (uint16_t)-1) {
|
||||||
|
BRange.Offset = Range.Offset + ARange.Offset;
|
||||||
|
BRange.Size = ARange.Size;
|
||||||
|
}
|
||||||
|
|
||||||
return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second;
|
return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +703,8 @@ public:
|
|||||||
// Find or create a sub-register index representing the concatenation of
|
// Find or create a sub-register index representing the concatenation of
|
||||||
// non-overlapping sibling indices.
|
// non-overlapping sibling indices.
|
||||||
CodeGenSubRegIndex *
|
CodeGenSubRegIndex *
|
||||||
getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &);
|
getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &,
|
||||||
|
const CodeGenHwModes &CGH);
|
||||||
|
|
||||||
const std::deque<CodeGenRegister> &getRegisters() const { return Registers; }
|
const std::deque<CodeGenRegister> &getRegisters() const { return Registers; }
|
||||||
|
|
||||||
|
@ -183,6 +183,20 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const {
|
|||||||
OS << '}';
|
OS << '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SubRegRange::SubRegRange(Record *R) {
|
||||||
|
Size = R->getValueAsInt("Size");
|
||||||
|
Offset = R->getValueAsInt("Offset");
|
||||||
|
}
|
||||||
|
|
||||||
|
SubRegRangeByHwMode::SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH) {
|
||||||
|
const HwModeSelect &MS = CGH.getHwModeSelect(R);
|
||||||
|
for (const HwModeSelect::PairType &P : MS.Items) {
|
||||||
|
auto I = Map.insert({P.first, SubRegRange(P.second)});
|
||||||
|
assert(I.second && "Duplicate entry?");
|
||||||
|
(void)I;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R,
|
EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R,
|
||||||
const CodeGenHwModes &CGH) {
|
const CodeGenHwModes &CGH) {
|
||||||
const HwModeSelect &MS = CGH.getHwModeSelect(R);
|
const HwModeSelect &MS = CGH.getHwModeSelect(R);
|
||||||
|
@ -176,6 +176,8 @@ struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
|
|||||||
|
|
||||||
ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH);
|
ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH);
|
||||||
|
|
||||||
|
raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
|
||||||
|
|
||||||
struct RegSizeInfo {
|
struct RegSizeInfo {
|
||||||
unsigned RegSize;
|
unsigned RegSize;
|
||||||
unsigned SpillSize;
|
unsigned SpillSize;
|
||||||
@ -213,10 +215,27 @@ struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
|
|
||||||
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
|
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
|
||||||
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
|
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
|
||||||
|
|
||||||
|
struct SubRegRange {
|
||||||
|
uint16_t Size;
|
||||||
|
uint16_t Offset;
|
||||||
|
|
||||||
|
SubRegRange(Record *R);
|
||||||
|
SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubRegRangeByHwMode : public InfoByHwMode<SubRegRange> {
|
||||||
|
SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH);
|
||||||
|
SubRegRangeByHwMode(SubRegRange Range) { Map.insert({DefaultMode, Range}); }
|
||||||
|
SubRegRangeByHwMode() = default;
|
||||||
|
|
||||||
|
void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) {
|
||||||
|
Map.insert(std::pair(Mode, Info));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct EncodingInfoByHwMode : public InfoByHwMode<Record *> {
|
struct EncodingInfoByHwMode : public InfoByHwMode<Record *> {
|
||||||
EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
|
EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
|
||||||
EncodingInfoByHwMode() = default;
|
EncodingInfoByHwMode() = default;
|
||||||
|
@ -1245,10 +1245,13 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
|||||||
// Emit the table of sub-register index sizes.
|
// Emit the table of sub-register index sizes.
|
||||||
OS << "static const TargetRegisterInfo::SubRegCoveredBits "
|
OS << "static const TargetRegisterInfo::SubRegCoveredBits "
|
||||||
"SubRegIdxRangeTable[] = {\n";
|
"SubRegIdxRangeTable[] = {\n";
|
||||||
OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n";
|
for (unsigned M = 0; M < NumModes; ++M) {
|
||||||
for (const auto &Idx : SubRegIndices) {
|
OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n";
|
||||||
OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// "
|
for (const auto &Idx : SubRegIndices) {
|
||||||
<< Idx.getName() << "\n";
|
const SubRegRange &Range = Idx.Range.get(M);
|
||||||
|
OS << " { " << Range.Offset << ", " << Range.Size << " },\t// "
|
||||||
|
<< Idx.getName() << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
OS << "};\n\n";
|
OS << "};\n\n";
|
||||||
|
|
||||||
@ -1864,7 +1867,13 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
|
|||||||
OS << "SubRegIndex " << SRI.getName() << ":\n";
|
OS << "SubRegIndex " << SRI.getName() << ":\n";
|
||||||
OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n';
|
OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n';
|
||||||
OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n';
|
OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n';
|
||||||
OS << "\tOffset, Size: " << SRI.Offset << ", " << SRI.Size << '\n';
|
OS << "\tOffset: {";
|
||||||
|
for (unsigned M = 0; M != NumModes; ++M)
|
||||||
|
OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Offset;
|
||||||
|
OS << " }\n\tSize: {";
|
||||||
|
for (unsigned M = 0; M != NumModes; ++M)
|
||||||
|
OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Size;
|
||||||
|
OS << " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const CodeGenRegister &R : RegBank.getRegisters()) {
|
for (const CodeGenRegister &R : RegBank.getRegisters()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user