Skip to content

Commit baf66ec

Browse files
authored
[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 llvm/llvm-project#85864 but need to verify.
1 parent aeb8628 commit baf66ec

File tree

10 files changed

+242
-50
lines changed

10 files changed

+242
-50
lines changed

llvm/include/llvm/Target/Target.td

+17
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,27 @@ class RegInfoByHwMode<list<HwMode> Ms = [], list<RegInfo> Ts = []>
8383
list<RegInfo> Objects = Ts;
8484
}
8585

86+
class SubRegRange<int size, int offset = 0> {
87+
int Size = size; // Sub register size in bits.
88+
int Offset = offset; // Offset of the first bit of the sub-reg index.
89+
}
90+
91+
class SubRegRangeByHwMode<list<HwMode> Ms = [], list<SubRegRange> Ts = []>
92+
: HwModeSelect<Ms> {
93+
// The length of this list must be the same as the length of Ms.
94+
list<SubRegRange> Objects = Ts;
95+
}
96+
8697
// SubRegIndex - Use instances of SubRegIndex to identify subregisters.
8798
class SubRegIndex<int size, int offset = 0> {
8899
string Namespace = "";
89100

101+
// The size/offset information, parameterized by a HW mode.
102+
// If the HwModes provided for SubRegRanges does not include the DefaultMode,
103+
// the/ Size and Offset fields below will be used for the default. Otherwise,
104+
// the Size and Offset fields are ignored.
105+
SubRegRangeByHwMode SubRegRanges;
106+
90107
// Size - Size (in bits) of the sub-registers represented by this index.
91108
int Size = size;
92109

llvm/lib/CodeGen/TargetRegisterInfo.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -595,13 +595,13 @@ bool TargetRegisterInfo::getCoveringSubRegIndexes(
595595
unsigned TargetRegisterInfo::getSubRegIdxSize(unsigned Idx) const {
596596
assert(Idx && Idx < getNumSubRegIndices() &&
597597
"This is not a subregister index");
598-
return SubRegIdxRanges[Idx].Size;
598+
return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Size;
599599
}
600600

601601
unsigned TargetRegisterInfo::getSubRegIdxOffset(unsigned Idx) const {
602602
assert(Idx && Idx < getNumSubRegIndices() &&
603603
"This is not a subregister index");
604-
return SubRegIdxRanges[Idx].Offset;
604+
return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Offset;
605605
}
606606

607607
Register

llvm/lib/Target/RISCV/RISCVRegisterInfo.td

+8-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,14 @@ def sub_vrm1_6 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_0>;
6464
def sub_vrm1_7 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_1>;
6565

6666
// GPR sizes change with HwMode.
67-
// FIXME: Support HwMode in SubRegIndex?
68-
def sub_gpr_even : SubRegIndex<-1>;
69-
def sub_gpr_odd : SubRegIndex<-1, -1>;
67+
def sub_gpr_even : SubRegIndex<32> {
68+
let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64],
69+
[SubRegRange<32>, SubRegRange<64>]>;
70+
}
71+
def sub_gpr_odd : SubRegIndex<32, 32> {
72+
let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64],
73+
[SubRegRange<32, 32>, SubRegRange<64, 64>]>;
74+
}
7075
} // Namespace = "RISCV"
7176

7277
// Integer registers

llvm/test/TableGen/ConcatenatedSubregs.td

+6-3
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,19 @@ def TestTarget : Target;
9090
// CHECK-LABEL: RegisterClass DRegs:
9191

9292
// CHECK-LABEL: SubRegIndex ssub1:
93-
// CHECK: Offset, Size: 16, 16
93+
// CHECK: Offset: { Default:16 }
94+
// CHECK: Size: { Default:16 }
9495
// CHECK-LABEL: SubRegIndex sub0:
9596
// CHECK-LABEL: SubRegIndex sub1:
9697
// CHECK-LABEL: SubRegIndex sub2:
9798
// Check inferred indexes:
9899
// CHECK-LABEL: SubRegIndex ssub1_ssub2:
99-
// CHECK: Offset, Size: 16, 65535
100+
// CHECK: Offset: { Default:16 }
101+
// CHECK: Size: { Default:65535 }
100102
// CHECK-LABEL: SubRegIndex ssub3_ssub4:
101103
// CHECK-LABEL: SubRegIndex ssub0_ssub1_ssub2_ssub3:
102-
// CHECK: Offset, Size: 65535, 65535
104+
// CHECK: Offset: { Default:65535 }
105+
// CHECK: Size: { Default:65535 }
103106
// CHECK-LABEL: SubRegIndex ssub1_ssub2_ssub3_ssub4:
104107

105108
// Check that all subregs are generated on some examples

llvm/test/TableGen/HwModeSubRegs.td

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s
2+
include "llvm/Target/Target.td"
3+
4+
def HasFeat : Predicate<"Subtarget->hasFeat()">;
5+
6+
def TestMode : HwMode<"+feat1", [HasFeat]>;
7+
8+
class MyReg<string n>
9+
: Register<n> {
10+
let Namespace = "Test";
11+
}
12+
class MyClass<int size, list<ValueType> types, dag registers>
13+
: RegisterClass<"Test", types, size, registers> {
14+
let Size = size;
15+
}
16+
17+
def X0 : MyReg<"x0">;
18+
def X1 : MyReg<"x1">;
19+
def X2 : MyReg<"x2">;
20+
def X3 : MyReg<"x3">;
21+
def X4 : MyReg<"x4">;
22+
def X5 : MyReg<"x5">;
23+
def X6 : MyReg<"x6">;
24+
def X7 : MyReg<"x7">;
25+
def X8 : MyReg<"x8">;
26+
def X9 : MyReg<"x9">;
27+
def X10 : MyReg<"x10">;
28+
def X11 : MyReg<"x11">;
29+
def X12 : MyReg<"x12">;
30+
def X13 : MyReg<"x13">;
31+
def X14 : MyReg<"x14">;
32+
def X15 : MyReg<"x15">;
33+
34+
def ModeVT : ValueTypeByHwMode<[DefaultMode, TestMode],
35+
[i32, i64]>;
36+
let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
37+
[RegInfo<32,32,32>, RegInfo<64,64,64>]> in
38+
def XRegs : MyClass<32, [ModeVT], (sequence "X%u", 0, 15)>;
39+
40+
def sub_even : SubRegIndex<32> {
41+
let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
42+
[SubRegRange<32>, SubRegRange<64>]>;
43+
}
44+
def sub_odd : SubRegIndex<32, 32> {
45+
let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
46+
[SubRegRange<32, 32>, SubRegRange<64, 64>]>;
47+
}
48+
49+
def XPairs : RegisterTuples<[sub_even, sub_odd],
50+
[(decimate (rotl XRegs, 0), 2),
51+
(decimate (rotl XRegs, 1), 2)]>;
52+
53+
let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
54+
[RegInfo<64,64,32>, RegInfo<128,128,64>]> in
55+
def XPairsClass : MyClass<64, [untyped], (add XPairs)>;
56+
57+
def TestTarget : Target;
58+
59+
// CHECK-LABEL: RegisterClass XRegs:
60+
// CHECK: SpillSize: { Default:32 TestMode:64 }
61+
// CHECK: SpillAlignment: { Default:32 TestMode:64 }
62+
// CHECK: Regs: X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
63+
64+
// CHECK-LABEL: RegisterClass XPairsClass:
65+
// CHECK: SpillSize: { Default:64 TestMode:128 }
66+
// CHECK: SpillAlignment: { Default:32 TestMode:64 }
67+
// CHECK: CoveredBySubRegs: 1
68+
// CHECK: Regs: X0_X1 X2_X3 X4_X5 X6_X7 X8_X9 X10_X11 X12_X13 X14_X15
69+
70+
// CHECK-LABEL: SubRegIndex sub_even:
71+
// CHECK: Offset: { Default:0 TestMode:0 }
72+
// CHECK: Size: { Default:32 TestMode:64 }
73+
// CHECK-LABEL: SubRegIndex sub_odd:
74+
// CHECK: Offset: { Default:32 TestMode:64 }
75+
// CHECK: Size: { Default:32 TestMode:64 }

llvm/utils/TableGen/Common/CodeGenRegisters.cpp

+53-26
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,24 @@ using namespace llvm;
4747
// CodeGenSubRegIndex
4848
//===----------------------------------------------------------------------===//
4949

50-
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
50+
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum,
51+
const CodeGenHwModes &CGH)
5152
: TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {
5253
Name = std::string(R->getName());
5354
if (R->getValue("Namespace"))
5455
Namespace = std::string(R->getValueAsString("Namespace"));
55-
Size = R->getValueAsInt("Size");
56-
Offset = R->getValueAsInt("Offset");
56+
57+
if (const RecordVal *RV = R->getValue("SubRegRanges"))
58+
if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue()))
59+
Range = SubRegRangeByHwMode(DI->getDef(), CGH);
60+
if (!Range.hasDefault())
61+
Range.insertSubRegRangeForMode(DefaultMode, SubRegRange(R));
5762
}
5863

5964
CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
6065
unsigned Enum)
6166
: TheDef(nullptr), Name(std::string(N)), Namespace(std::string(Nspace)),
62-
Size(-1), Offset(-1), EnumValue(Enum), AllSuperRegsCovered(true),
67+
Range(SubRegRange(-1, -1)), EnumValue(Enum), AllSuperRegsCovered(true),
6368
Artificial(true) {}
6469

6570
std::string CodeGenSubRegIndex::getQualifiedName() const {
@@ -81,7 +86,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
8186
"ComposedOf must have exactly two entries");
8287
CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
8388
CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
84-
CodeGenSubRegIndex *X = A->addComposite(B, this);
89+
CodeGenSubRegIndex *X = A->addComposite(B, this, RegBank.getHwModes());
8590
if (X)
8691
PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
8792
}
@@ -518,7 +523,8 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
518523

519524
// Each part of Cand is a sub-register of this. Make the full Cand also
520525
// a sub-register with a concatenated sub-register index.
521-
CodeGenSubRegIndex *Concat = RegBank.getConcatSubRegIndex(Parts);
526+
CodeGenSubRegIndex *Concat =
527+
RegBank.getConcatSubRegIndex(Parts, RegBank.getHwModes());
522528
std::pair<CodeGenSubRegIndex *, CodeGenRegister *> NewSubReg =
523529
std::pair(Concat, Cand);
524530

@@ -542,7 +548,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
542548
PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
543549
SubReg.second->getName() +
544550
" in " + getName());
545-
NewIdx->addComposite(SubReg.first, SubIdx);
551+
NewIdx->addComposite(SubReg.first, SubIdx, RegBank.getHwModes());
546552
}
547553
}
548554
}
@@ -1315,7 +1321,7 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
13151321
CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
13161322
if (Idx)
13171323
return Idx;
1318-
SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1);
1324+
SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1, getHwModes());
13191325
Idx = &SubRegIndices.back();
13201326
return Idx;
13211327
}
@@ -1379,12 +1385,13 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
13791385
// None exists, synthesize one.
13801386
std::string Name = A->getName() + "_then_" + B->getName();
13811387
Comp = createSubRegIndex(Name, A->getNamespace());
1382-
A->addComposite(B, Comp);
1388+
A->addComposite(B, Comp, getHwModes());
13831389
return Comp;
13841390
}
13851391

13861392
CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
1387-
const SmallVector<CodeGenSubRegIndex *, 8> &Parts) {
1393+
const SmallVector<CodeGenSubRegIndex *, 8> &Parts,
1394+
const CodeGenHwModes &CGH) {
13881395
assert(Parts.size() > 1 && "Need two parts to concatenate");
13891396
#ifndef NDEBUG
13901397
for (CodeGenSubRegIndex *Idx : Parts) {
@@ -1399,28 +1406,47 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
13991406

14001407
// None exists, synthesize one.
14011408
std::string Name = Parts.front()->getName();
1402-
// Determine whether all parts are contiguous.
1403-
bool IsContinuous = true;
1404-
unsigned Size = Parts.front()->Size;
1405-
unsigned LastOffset = Parts.front()->Offset;
1406-
unsigned LastSize = Parts.front()->Size;
14071409
const unsigned UnknownSize = (uint16_t)-1;
1410+
14081411
for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
14091412
Name += '_';
14101413
Name += Parts[i]->getName();
1411-
if (Size == UnknownSize || Parts[i]->Size == UnknownSize)
1412-
Size = UnknownSize;
1413-
else
1414-
Size += Parts[i]->Size;
1415-
if (LastSize == UnknownSize || Parts[i]->Offset != (LastOffset + LastSize))
1416-
IsContinuous = false;
1417-
LastOffset = Parts[i]->Offset;
1418-
LastSize = Parts[i]->Size;
14191414
}
1415+
14201416
Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
1421-
Idx->Size = Size;
1422-
Idx->Offset = IsContinuous ? Parts.front()->Offset : -1;
14231417
Idx->ConcatenationOf.assign(Parts.begin(), Parts.end());
1418+
1419+
unsigned NumModes = CGH.getNumModeIds();
1420+
for (unsigned M = 0; M < NumModes; ++M) {
1421+
const CodeGenSubRegIndex *Part = Parts.front();
1422+
1423+
// Determine whether all parts are contiguous.
1424+
bool IsContinuous = true;
1425+
const SubRegRange &FirstPartRange = Part->Range.get(M);
1426+
unsigned Size = FirstPartRange.Size;
1427+
unsigned LastOffset = FirstPartRange.Offset;
1428+
unsigned LastSize = FirstPartRange.Size;
1429+
1430+
for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
1431+
Part = Parts[i];
1432+
Name += '_';
1433+
Name += Part->getName();
1434+
1435+
const SubRegRange &PartRange = Part->Range.get(M);
1436+
if (Size == UnknownSize || PartRange.Size == UnknownSize)
1437+
Size = UnknownSize;
1438+
else
1439+
Size += PartRange.Size;
1440+
if (LastSize == UnknownSize ||
1441+
PartRange.Offset != (LastOffset + LastSize))
1442+
IsContinuous = false;
1443+
LastOffset = PartRange.Offset;
1444+
LastSize = PartRange.Size;
1445+
}
1446+
unsigned Offset = IsContinuous ? FirstPartRange.Offset : -1;
1447+
Idx->Range.get(M) = SubRegRange(Size, Offset);
1448+
}
1449+
14241450
return Idx;
14251451
}
14261452

@@ -1504,7 +1530,8 @@ void CodeGenRegBank::computeComposites() {
15041530
assert(Idx3 && "Sub-register doesn't have an index");
15051531

15061532
// Conflicting composition? Emit a warning but allow it.
1507-
if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3)) {
1533+
if (CodeGenSubRegIndex *Prev =
1534+
Idx1->addComposite(Idx2, Idx3, getHwModes())) {
15081535
// If the composition was not user-defined, always emit a warning.
15091536
if (!UserDefined.count({Idx1, Idx2}) ||
15101537
agree(compose(Idx1, Idx2), SubRegAction.at(Idx3)))

llvm/utils/TableGen/Common/CodeGenRegisters.h

+33-10
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ class CodeGenSubRegIndex {
6868
std::string Namespace;
6969

7070
public:
71-
uint16_t Size;
72-
uint16_t Offset;
71+
SubRegRangeByHwMode Range;
7372
const unsigned EnumValue;
7473
mutable LaneBitmask LaneMask;
7574
mutable SmallVector<MaskRolPair, 1> CompositionLaneMaskTransform;
@@ -86,7 +85,7 @@ class CodeGenSubRegIndex {
8685
// indexes are not used to create new register classes.
8786
bool Artificial;
8887

89-
CodeGenSubRegIndex(Record *R, unsigned Enum);
88+
CodeGenSubRegIndex(Record *R, unsigned Enum, const CodeGenHwModes &CGH);
9089
CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
9190
CodeGenSubRegIndex(CodeGenSubRegIndex &) = delete;
9291

@@ -108,19 +107,42 @@ class CodeGenSubRegIndex {
108107

109108
// Add a composite subreg index: this+A = B.
110109
// Return a conflicting composite, or NULL
111-
CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A,
112-
CodeGenSubRegIndex *B) {
110+
CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B,
111+
const CodeGenHwModes &CGH) {
113112
assert(A && B);
114113
std::pair<CompMap::iterator, bool> Ins = Composed.insert(std::pair(A, B));
114+
115115
// Synthetic subreg indices that aren't contiguous (for instance ARM
116116
// register tuples) don't have a bit range, so it's OK to let
117117
// B->Offset == -1. For the other cases, accumulate the offset and set
118118
// the size here. Only do so if there is no offset yet though.
119-
if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) &&
120-
(B->Offset == (uint16_t)-1)) {
121-
B->Offset = Offset + A->Offset;
122-
B->Size = A->Size;
119+
unsigned NumModes = CGH.getNumModeIds();
120+
// Skip default mode.
121+
for (unsigned M = 0; M < NumModes; ++M) {
122+
// Handle DefaultMode last.
123+
if (M == DefaultMode)
124+
continue;
125+
SubRegRange &Range = this->Range.get(M);
126+
SubRegRange &ARange = A->Range.get(M);
127+
SubRegRange &BRange = B->Range.get(M);
128+
129+
if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 &&
130+
BRange.Offset == (uint16_t)-1) {
131+
BRange.Offset = Range.Offset + ARange.Offset;
132+
BRange.Size = ARange.Size;
133+
}
134+
}
135+
136+
// Now handle default.
137+
SubRegRange &Range = this->Range.get(DefaultMode);
138+
SubRegRange &ARange = A->Range.get(DefaultMode);
139+
SubRegRange &BRange = B->Range.get(DefaultMode);
140+
if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 &&
141+
BRange.Offset == (uint16_t)-1) {
142+
BRange.Offset = Range.Offset + ARange.Offset;
143+
BRange.Size = ARange.Size;
123144
}
145+
124146
return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second;
125147
}
126148

@@ -681,7 +703,8 @@ class CodeGenRegBank {
681703
// Find or create a sub-register index representing the concatenation of
682704
// non-overlapping sibling indices.
683705
CodeGenSubRegIndex *
684-
getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &);
706+
getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &,
707+
const CodeGenHwModes &CGH);
685708

686709
const std::deque<CodeGenRegister> &getRegisters() const { return Registers; }
687710

0 commit comments

Comments
 (0)