Skip to content

Commit 9a211fe

Browse files
[TableGen] Fix concatenation of subreg and artificial subregs (#114391)
When CoveredBySubRegs is true and a sub-register consists of two parts; a regular subreg and an artificial subreg, then TableGen should consider only concatenating the non-artificial subregs. For example, S0_S1 is a concatenated subreg from D0_D1, but S0_S1_HI should not be considered.
1 parent 8b19d29 commit 9a211fe

File tree

2 files changed

+229
-4
lines changed

2 files changed

+229
-4
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK
2+
include "llvm/Target/Target.td"
3+
4+
// This file tests that when using `isArtificial` for subregisters in
5+
// combination with `CoveredBySubRegs`, that TableGen infers the
6+
// correct register classes, subregisters and lane masks, especially
7+
// when the registers (that consist partially from artificial subregs)
8+
// are used in tuples.
9+
//
10+
// The register hierarchy that this test implements is:
11+
//
12+
// ssub_hi ssub
13+
// \ /
14+
// dsub
15+
// dsub_hi /
16+
// \ /
17+
// qsub
18+
//
19+
// Where the _hi parts are artificial and where subregs ssub, dsub and qsub
20+
// are all addressable as real registers.
21+
//
22+
// These are then used in {S0, S1, S2}, {D0, D1, D2} and {Q0, Q1, Q2},
23+
// from which tuples are created.
24+
25+
class MyReg<string n, list<Register> subregs = []>
26+
: Register<n> {
27+
let Namespace = "Test";
28+
let SubRegs = subregs;
29+
}
30+
31+
class MyClass<int size, list<ValueType> types, dag registers>
32+
: RegisterClass<"Test", types, size, registers> {
33+
let Size = size;
34+
}
35+
36+
def ssub : SubRegIndex< 32, 0>;
37+
def ssub_hi : SubRegIndex< 32, 32>;
38+
def dsub : SubRegIndex< 64, 0>;
39+
def dsub_hi : SubRegIndex< 64, 64>;
40+
def qsub : SubRegIndex<128, 0>;
41+
42+
def S0 : MyReg<"s0">;
43+
def S1 : MyReg<"s1">;
44+
def S2 : MyReg<"s2">;
45+
46+
let isArtificial = 1 in {
47+
def S0_HI : MyReg<"s0_hi">;
48+
def S1_HI : MyReg<"s1_hi">;
49+
def S2_HI : MyReg<"s2_hi">;
50+
51+
def D0_HI : MyReg<"D0_hi">;
52+
def D1_HI : MyReg<"D1_hi">;
53+
def D2_HI : MyReg<"D2_hi">;
54+
}
55+
56+
let SubRegIndices = [ssub, ssub_hi], CoveredBySubRegs = 1 in {
57+
def D0 : MyReg<"d0", [S0, S0_HI]>;
58+
def D1 : MyReg<"d1", [S1, S1_HI]>;
59+
def D2 : MyReg<"d2", [S2, S2_HI]>;
60+
}
61+
62+
let SubRegIndices = [dsub, dsub_hi], CoveredBySubRegs = 1 in {
63+
def Q0 : MyReg<"q0", [D0, D0_HI]>;
64+
def Q1 : MyReg<"q1", [D1, D1_HI]>;
65+
def Q2 : MyReg<"q2", [D2, D2_HI]>;
66+
}
67+
68+
def SRegs : MyClass<32, [i32], (sequence "S%u", 0, 2)>;
69+
def DRegs : MyClass<64, [i64], (sequence "D%u", 0, 2)>;
70+
def QRegs : MyClass<128, [i128], (sequence "Q%u", 0, 2)>;
71+
72+
def dsub0 : SubRegIndex<64>;
73+
def dsub1 : SubRegIndex<64>;
74+
def dsub2 : SubRegIndex<64>;
75+
76+
def ssub0 : SubRegIndex<32>;
77+
def ssub1 : ComposedSubRegIndex<dsub1, ssub>;
78+
def ssub2 : ComposedSubRegIndex<dsub2, ssub>;
79+
80+
def STuples2 : RegisterTuples<[ssub0, ssub1],
81+
[(shl SRegs, 0), (shl SRegs, 1)]>;
82+
def STuplesRC2 : MyClass<64, [untyped], (add STuples2)>;
83+
84+
def DTuples2 : RegisterTuples<[dsub0, dsub1],
85+
[(shl DRegs, 0), (shl DRegs, 1)]>;
86+
def DTuplesRC2 : MyClass<128, [untyped], (add DTuples2)>;
87+
88+
def STuples3 : RegisterTuples<[ssub0, ssub1, ssub2],
89+
[(shl SRegs, 0), (shl SRegs, 1), (shl SRegs, 2)]>;
90+
def STuplesRC3 : MyClass<96, [untyped], (add STuples3)>;
91+
92+
def DTuples3 : RegisterTuples<[dsub0, dsub1, dsub2],
93+
[(shl DRegs, 0), (shl DRegs, 1), (shl DRegs, 2)]>;
94+
def DTuplesRC3 : MyClass<192, [untyped], (add DTuples3)>;
95+
96+
def TestTarget : Target;
97+
98+
// CHECK: RegisterClass SRegs:
99+
// CHECK: LaneMask: 0000000000000001
100+
// CHECK: HasDisjunctSubRegs: 0
101+
// CHECK: CoveredBySubRegs: 0
102+
// CHECK: Regs: S0 S1 S2
103+
// CHECK: SubClasses: SRegs
104+
// CHECK: SuperClasses:
105+
//
106+
// CHECK: RegisterClass DRegs:
107+
// CHECK: LaneMask: 0000000000000004
108+
// CHECK: HasDisjunctSubRegs: 1
109+
// CHECK: CoveredBySubRegs: 1
110+
// CHECK: Regs: D0 D1 D2
111+
// CHECK: SubClasses: DRegs
112+
// CHECK: SuperClasses:
113+
//
114+
// CHECK: RegisterClass QRegs:
115+
// CHECK: LaneMask: 0000000000000044
116+
// CHECK: HasDisjunctSubRegs: 1
117+
// CHECK: CoveredBySubRegs: 1
118+
// CHECK: Regs: Q0 Q1 Q2
119+
// CHECK: SubClasses: QRegs
120+
// CHECK: SuperClasses:
121+
//
122+
// CHECK: SubRegIndex dsub:
123+
// CHECK-NEXT: LaneMask: 0000000000000044
124+
// CHECK: SubRegIndex dsub0:
125+
// CHECK-NEXT: LaneMask: 0000000000000044
126+
// CHECK: SubRegIndex dsub1:
127+
// CHECK-NEXT: LaneMask: 0000000000000090
128+
// CHECK: SubRegIndex dsub2:
129+
// CHECK-NEXT: LaneMask: 0000000000000120
130+
// CHECK: SubRegIndex dsub_hi:
131+
// CHECK-NEXT: LaneMask: 0000000000000001
132+
// CHECK: SubRegIndex ssub:
133+
// CHECK-NEXT: LaneMask: 0000000000000004
134+
// CHECK: SubRegIndex ssub0:
135+
// CHECK-NEXT: LaneMask: 0000000000000008
136+
// CHECK: SubRegIndex ssub1:
137+
// CHECK-NEXT: LaneMask: 0000000000000010
138+
// CHECK: SubRegIndex ssub2:
139+
// CHECK-NEXT: LaneMask: 0000000000000020
140+
// CHECK: SubRegIndex ssub_hi:
141+
// CHECK-NEXT: LaneMask: 0000000000000040
142+
// CHECK: SubRegIndex dsub1_then_ssub_hi:
143+
// CHECK-NEXT: LaneMask: 0000000000000080
144+
// CHECK: SubRegIndex dsub2_then_ssub_hi:
145+
// CHECK-NEXT: LaneMask: 0000000000000100
146+
// CHECK: SubRegIndex ssub_ssub1:
147+
// CHECK-NEXT: LaneMask: 0000000000000014
148+
// CHECK: SubRegIndex dsub0_dsub1:
149+
// CHECK-NEXT: LaneMask: 00000000000000D4
150+
// CHECK: SubRegIndex dsub1_dsub2:
151+
// CHECK-NEXT: LaneMask: 00000000000001B0
152+
// CHECK: SubRegIndex ssub_ssub1_ssub2:
153+
// CHECK-NEXT: LaneMask: 0000000000000034
154+
// CHECK: SubRegIndex ssub1_ssub2:
155+
// CHECK-NEXT: LaneMask: 0000000000000030
156+
// CHECK: SubRegIndex ssub0_ssub1:
157+
// CHECK-NEXT: LaneMask: 0000000000000018
158+
159+
// CHECK: Register D0:
160+
// CHECK: CoveredBySubregs: 1
161+
// CHECK: HasDisjunctSubRegs: 1
162+
// CHECK: SubReg ssub = S0
163+
// CHECK: SubReg ssub_hi = S0_HI
164+
//
165+
// CHECK: Register Q0:
166+
// CHECK: CoveredBySubregs: 1
167+
// CHECK: HasDisjunctSubRegs: 1
168+
// CHECK: SubReg dsub = D0
169+
// CHECK: SubReg dsub_hi = D0_HI
170+
// CHECK: SubReg ssub = S0
171+
// CHECK: SubReg ssub_hi = S0_HI
172+
//
173+
// CHECK: Register S0:
174+
// CHECK: CoveredBySubregs: 0
175+
// CHECK: HasDisjunctSubRegs: 0
176+
//
177+
// CHECK: Register D0_D1:
178+
// CHECK: CoveredBySubregs: 1
179+
// CHECK: HasDisjunctSubRegs: 1
180+
// CHECK: SubReg dsub0 = D0
181+
// CHECK: SubReg dsub1 = D1
182+
// CHECK: SubReg ssub = S0
183+
// CHECK: SubReg ssub1 = S1
184+
// CHECK: SubReg ssub_hi = S0_HI
185+
// CHECK: SubReg dsub1_then_ssub_hi = S1_HI
186+
// CHECK: SubReg ssub_ssub1 = S0_S1
187+
//
188+
// CHECK: Register D0_D1_D2:
189+
// CHECK: CoveredBySubregs: 1
190+
// CHECK: HasDisjunctSubRegs: 1
191+
// CHECK: SubReg dsub0 = D0
192+
// CHECK: SubReg dsub1 = D1
193+
// CHECK: SubReg dsub2 = D2
194+
// CHECK: SubReg ssub = S0
195+
// CHECK: SubReg ssub1 = S1
196+
// CHECK: SubReg ssub2 = S2
197+
// CHECK: SubReg ssub_hi = S0_HI
198+
// CHECK: SubReg dsub1_then_ssub_hi = S1_HI
199+
// CHECK: SubReg dsub2_then_ssub_hi = S2_HI
200+
// CHECK: SubReg ssub_ssub1 = S0_S1
201+
// CHECK: SubReg dsub0_dsub1 = D0_D1
202+
// CHECK: SubReg dsub1_dsub2 = D1_D2
203+
// CHECK: SubReg ssub_ssub1_ssub2 = S0_S1_S2
204+
// CHECK: SubReg ssub1_ssub2 = S1_S2
205+
//
206+
// CHECK: Register S0_S1:
207+
// CHECK: CoveredBySubregs: 1
208+
// CHECK: HasDisjunctSubRegs: 1
209+
// CHECK: SubReg ssub0 = S0
210+
// CHECK: SubReg ssub1 = S1
211+
//
212+
// CHECK: Register S0_S1_S2:
213+
// CHECK: CoveredBySubregs: 1
214+
// CHECK: HasDisjunctSubRegs: 1
215+
// CHECK: SubReg ssub0 = S0
216+
// CHECK: SubReg ssub1 = S1
217+
// CHECK: SubReg ssub2 = S2
218+
// CHECK: SubReg ssub1_ssub2 = S1_S2
219+
// CHECK: SubReg ssub0_ssub1 = S0_S1

llvm/utils/TableGen/Common/CodeGenRegisters.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -399,18 +399,24 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
399399
// user already specified.
400400
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
401401
CodeGenRegister *SR = ExplicitSubRegs[i];
402-
if (!SR->CoveredBySubRegs || SR->ExplicitSubRegs.size() <= 1 ||
403-
SR->Artificial)
402+
if (!SR->CoveredBySubRegs || SR->Artificial)
404403
continue;
405404

406405
// SR is composed of multiple sub-regs. Find their names in this register.
406+
bool AnyArtificial = false;
407407
SmallVector<CodeGenSubRegIndex *, 8> Parts;
408408
for (unsigned j = 0, e = SR->ExplicitSubRegs.size(); j != e; ++j) {
409409
CodeGenSubRegIndex &I = *SR->ExplicitSubRegIndices[j];
410-
if (!I.Artificial)
411-
Parts.push_back(getSubRegIndex(SR->ExplicitSubRegs[j]));
410+
if (I.Artificial) {
411+
AnyArtificial = true;
412+
break;
413+
}
414+
Parts.push_back(getSubRegIndex(SR->ExplicitSubRegs[j]));
412415
}
413416

417+
if (AnyArtificial)
418+
continue;
419+
414420
// Offer this as an existing spelling for the concatenation of Parts.
415421
CodeGenSubRegIndex &Idx = *ExplicitSubRegIndices[i];
416422
Idx.setConcatenationOf(Parts);

0 commit comments

Comments
 (0)