Skip to content

Commit 5dc432e

Browse files
committed
[TableGen] Add CompressedTupleNameStride to compress tuple names.
Currently, the name of a synthetic register generated by `RegisterTuples` is the concatenation of all names in the tuple. This becomes unwieldy for targets with very long tuples. For example, a 16-tuple might look like this by default: R0_R1_R2_R3_R4_R5_R6_R7_R8_R9_R10_R11_R12_R13_R14_R15 This patch adds the `CompressedTupleNameStride` option to give the user the ability to compact the names. By setting this option to one (say), the name above becomes: R0_TO_R15_BY_1 Some targets have much longer tuples than that. AMDGPU currently has up to 31-wide tuples. The downstream NVGPU target currently has 128-wide tuples-- resulting in excessively long synthetic names.
1 parent cb5362a commit 5dc432e

File tree

4 files changed

+126
-8
lines changed

4 files changed

+126
-8
lines changed

llvm/include/llvm/Target/Target.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,20 @@ class RegisterTuples<list<SubRegIndex> Indices, list<dag> Regs,
459459
// PositionOrder - Indicate tablegen to place the newly added register at a later
460460
// position to avoid iterations on them on unsupported target.
461461
int PositionOrder = 0;
462+
463+
// Request a compact synthetic name. By default, the name is the concatenation
464+
// of all names in the tuple. This becomes unwieldy for targets with very long
465+
// tuples. For example, a 16-tuple might look like this by default:
466+
//
467+
// R0_R1_R2_R3_R4_R5_R6_R7_R8_R9_R10_R11_R12_R13_R14_R15
468+
//
469+
// By setting this option to one, the name becomes:
470+
//
471+
// R0_TO_R15_BY_1
472+
//
473+
// Similarly for any positive stride. The default setting of zero keeps the
474+
// default naming.
475+
int CompressedTupleNameStride = 0;
462476
}
463477

464478
// RegisterCategory - This class is a list of RegisterClasses that belong to a

llvm/test/TableGen/Common/reg-with-subregs-common.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Indexes<int N> {
1919
#ifdef USE_NAMESPACE
2020
let Namespace = "TestNamespace" in {
2121
#endif
22-
foreach Index = 0...31 in {
22+
foreach Index = 0...63 in {
2323
def sub#Index : SubRegIndex<32, !shl(Index, 5)>;
2424
}
2525

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// RUN: llvm-tblgen -gen-register-info -I %p/../../include -I %p/Common %s 2>&1 | FileCheck %s
2+
3+
// Verify that the `CompressedTupleNameStride` option produces the expected
4+
// compact synthesized tuple names rather than the default names.
5+
6+
include "reg-with-subregs-common.td"
7+
8+
class getSubRegs<int Size> {
9+
list<SubRegIndex> Ret =
10+
!foreach(X, !range(Size), !cast<SubRegIndex>("sub"#X));
11+
}
12+
13+
// A 64-wide tuple with no alignment constraints.
14+
let CompressedTupleNameStride = 1 in
15+
def Tuples64X_S1 : RegisterTuples<
16+
getSubRegs<64>.Ret, !foreach(X, !range(64), (decimate (shl GPR32, X), 1))>;
17+
18+
// A 5-wide tuple with 8-alignment.
19+
let CompressedTupleNameStride = 2 in
20+
def Tuples5X_S2 : RegisterTuples<
21+
getSubRegs<5>.Ret, !foreach(X, !range(5), (decimate (shl GPR32, X), 8))>;
22+
23+
24+
def GPR2048 : RegisterClass<"", [v64i32], 2048, (add Tuples64X_S1)>;
25+
def GPR160 : RegisterClass<"", [v5i32], 160, (add Tuples5X_S2)>;
26+
27+
28+
// CHECK: enum : unsigned {
29+
// CHECK-NEXT: NoRegister,
30+
//
31+
// CHECK: R0_R1_R2_R3_R4_R5_R6_R7_R8_R9_R10_R11_R12_R13_R14_R15_R16_R17_R18_R19_R20_R21_R22_R23_R24_R25_R26_R27_R28_R29_R30_R31 = 1255,
32+
// CHECK-NEXT: R1_R2_R3_R4_R5_R6_R7_R8_R9_R10_R11_R12_R13_R14_R15_R16_R17_R18_R19_R20_R21_R22_R23_R24_R25_R26_R27_R28_R29_R30_R31_R32 = 1256,
33+
//
34+
// CHECK: R0_TO_R4_BY_2 = 1480,
35+
// CHECK-NEXT: R8_TO_R12_BY_2 = 1481,
36+
// CHECK-NEXT: R16_TO_R20_BY_2 = 1482,
37+
// CHECK-NEXT: R24_TO_R28_BY_2 = 1483,
38+
// CHECK-NEXT: R32_TO_R36_BY_2 = 1484,
39+
// CHECK-NEXT: R40_TO_R44_BY_2 = 1485,
40+
// CHECK-NEXT: R48_TO_R52_BY_2 = 1486,
41+
//
42+
// CHECK: R0_TO_R63_BY_1 = 1512,
43+
// CHECK-NEXT: R1_TO_R64_BY_1 = 1513,
44+
// CHECK-NEXT: R2_TO_R65_BY_1 = 1514,
45+
// CHECK-NEXT: R3_TO_R66_BY_1 = 1515,
46+
// CHECK-NEXT: R4_TO_R67_BY_1 = 1516,
47+
// CHECK-NEXT: R5_TO_R68_BY_1 = 1517,
48+
// CHECK-NEXT: R6_TO_R69_BY_1 = 1518,
49+
//
50+
// CHECK: NUM_TARGET_REGS
51+
// CHECK-NEXT: };
52+
//
53+
// CHECK: enum {
54+
// CHECK-NEXT: GPR32RegClassID = 0,
55+
// CHECK-NEXT: GPR_64RegClassID = 1,
56+
// CHECK-NEXT: GPR160RegClassID = 2,
57+
// CHECK-NEXT: GPR_1024RegClassID = 3,
58+
// CHECK-NEXT: GPR_1024_with_sub0_sub1_sub2_sub3_sub4RegClassID = 4,
59+
// CHECK-NEXT: GPR_1024_with_sub1_sub2_sub3_sub4_sub5RegClassID = 5,
60+
// CHECK-NEXT: GPR_1024_with_sub2_sub3_sub4_sub5_sub6RegClassID = 6,
61+
// CHECK-NEXT: GPR_1024_with_sub3_sub4_sub5_sub6_sub7RegClassID = 7,
62+
// CHECK-NEXT: GPR_1024_with_sub4_sub5_sub6_sub7_sub8RegClassID = 8,
63+
// CHECK-NEXT: GPR_1024_with_sub5_sub6_sub7_sub8_sub9RegClassID = 9,
64+
// CHECK-NEXT: GPR_1024_with_sub6_sub7_sub8_sub9_sub10RegClassID = 10,
65+
// CHECK-NEXT: GPR_1024_with_sub7_sub8_sub9_sub10_sub11RegClassID = 11,
66+
// CHECK-NEXT: GPR2048RegClassID = 12,
67+
// CHECK-NEXT: GPR2048_with_sub0_sub1_sub2_sub3_sub4RegClassID = 13,
68+
// CHECK-NEXT: GPR2048_with_sub1_sub2_sub3_sub4_sub5RegClassID = 14,
69+
// CHECK-NEXT: GPR2048_with_sub2_sub3_sub4_sub5_sub6RegClassID = 15,
70+
// CHECK-NEXT: GPR2048_with_sub3_sub4_sub5_sub6_sub7RegClassID = 16,
71+
// CHECK-NEXT: GPR2048_with_sub4_sub5_sub6_sub7_sub8RegClassID = 17,
72+
// CHECK-NEXT: GPR2048_with_sub5_sub6_sub7_sub8_sub9RegClassID = 18,
73+
// CHECK-NEXT: GPR2048_with_sub6_sub7_sub8_sub9_sub10RegClassID = 19,
74+
// CHECK-NEXT: GPR2048_with_sub7_sub8_sub9_sub10_sub11RegClassID = 20,
75+
//
76+
// CHECK: extern const char TestTargetRegStrings[] = {
77+
// CHECK: /* {{[0-9]+}} */ "R0_R1_R2_R3_R4_R5_R6_R7_R8_R9_R10_R11_R12_R13_R14_R15_R16_R17_R18_R19_R20_R21_R22_R23_R24_R25_R26_R27_R28_R29_R30_R31\000"
78+
// CHECK: /* {{[0-9]+}} */ "R0_TO_R63_BY_1\000"
79+
// CHECK-NEXT: /* {{[0-9]+}} */ "R110_TO_R173_BY_1\000"
80+
// CHECK-NEXT: /* {{[0-9]+}} */ "R10_TO_R73_BY_1\000"
81+
// CHECK-NEXT: /* {{[0-9]+}} */ "R120_TO_R183_BY_1\000"
82+
// CHECK-NEXT: /* {{[0-9]+}} */ "R20_TO_R83_BY_1\000"
83+
// CHECK-NEXT: /* {{[0-9]+}} */ "R130_TO_R193_BY_1\000"
84+
// CHECK: /* {{[0-9]+}} */ "R0_TO_R4_BY_2\000"
85+
// CHECK-NEXT: /* {{[0-9]+}} */ "R112_TO_R116_BY_2\000"
86+
// CHECK-NEXT: /* {{[0-9]+}} */ "R232_TO_R236_BY_2\000"
87+
// CHECK-NEXT: /* {{[0-9]+}} */ "R32_TO_R36_BY_2\000"
88+
// CHECK-NEXT: /* {{[0-9]+}} */ "R152_TO_R156_BY_2\000"
89+
// CHECK-NEXT: /* {{[0-9]+}} */ "R72_TO_R76_BY_2\000"
90+
//
91+
// CHECK: // GPR160 Register Class...
92+
// CHECK-NEXT: const MCPhysReg GPR160[] = {
93+
// CHECK-NEXT: R0_TO_R4_BY_2, R8_TO_R12_BY_2, R16_TO_R20_BY_2, R24_TO_R28_BY_2, R32_TO_R36_BY_2, R40_TO_R44_BY_2, R48_TO_R52_BY_2, R56_TO_R60_BY_2, R64_TO_R68_BY_2, R72_TO_R76_BY_2, R80_TO_R84_BY_2, R88_TO_R92_BY_2, R96_TO_R100_BY_2, R104_TO_R108_BY_2, R112_TO_R116_BY_2, R120_TO_R124_BY_2, R128_TO_R132_BY_2, R136_TO_R140_BY_2, R144_TO_R148_BY_2, R152_TO_R156_BY_2, R160_TO_R164_BY_2, R168_TO_R172_BY_2, R176_TO_R180_BY_2, R184_TO_R188_BY_2, R192_TO_R196_BY_2, R200_TO_R204_BY_2, R208_TO_R212_BY_2, R216_TO_R220_BY_2, R224_TO_R228_BY_2, R232_TO_R236_BY_2, R240_TO_R244_BY_2, R248_TO_R252_BY_2,

llvm/utils/TableGen/Common/CodeGenRegisters.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/ADT/StringSet.h"
2828
#include "llvm/ADT/Twine.h"
2929
#include "llvm/Support/Debug.h"
30+
#include "llvm/Support/FormatVariadic.h"
3031
#include "llvm/Support/raw_ostream.h"
3132
#include "llvm/TableGen/Error.h"
3233
#include "llvm/TableGen/Record.h"
@@ -577,19 +578,29 @@ struct TupleExpander : SetTheory::Expander {
577578
const RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
578579
std::vector<StringRef> RegNames =
579580
Def->getValueAsListOfStrings("RegAsmNames");
581+
const int NameStride = Def->getValueAsInt("CompressedTupleNameStride");
582+
if (NameStride < 0)
583+
PrintFatalError(Def->getLoc(),
584+
"CompressedTupleNameStride must be non-negative");
580585

581586
// Zip them up.
582587
RecordKeeper &RK = Def->getRecords();
583588
for (unsigned n = 0; n != Length; ++n) {
584-
std::string Name;
585589
const Record *Proto = Lists[0][n];
586590
std::vector<Init *> Tuple;
587-
for (unsigned i = 0; i != Dim; ++i) {
588-
const Record *Reg = Lists[i][n];
589-
if (i)
590-
Name += '_';
591-
Name += Reg->getName();
592-
Tuple.push_back(Reg->getDefInit());
591+
transform(Lists, std::back_inserter(Tuple),
592+
[&](SetTheory::RecSet &RS) { return RS[n]->getDefInit(); });
593+
594+
std::string Name;
595+
if (NameStride == 0) {
596+
// Default name is the catenation of all names delimited by underscores.
597+
Name = formatv("{:$[_]}", map_range(Lists, [&](SetTheory::RecSet &RS) {
598+
return RS[n]->getName();
599+
}));
600+
} else {
601+
// Use a compact vector/strided name if the user requested it.
602+
Name = formatv("{}_TO_{}_BY_{}", Lists[0][n]->getName(),
603+
Lists[Dim - 1][n]->getName(), NameStride);
593604
}
594605

595606
// Take the cost list of the first register in the tuple.

0 commit comments

Comments
 (0)