Skip to content

Commit 80b08d1

Browse files
authored
[TableGen] Add support for per-write cycle tunables (#125870)
This patch adds support for describing per-write resource cycle counts for ReadAdvance records via a new optional field called `tunables`. This makes it possible to declare ReadAdvance records such as: def : ReadAdvance<Read_C, 1, [Write_A, Write_B], [2]>; The above will effectively declare two entries in the ReadAdvance table for Read_C, one for Write_A with a cycle count of 1+2, and one for Write_B with a cycle count of 1+0 (omitted values are assumed 0). The field `tunables` provides a list of deltas relative to the base `cycle` count of the ReadAdvance. Since the field is optional and defaults to a list of 0's, this change doesn't affect current targets.
1 parent a177be5 commit 80b08d1

File tree

3 files changed

+69
-11
lines changed

3 files changed

+69
-11
lines changed

llvm/include/llvm/Target/TargetSchedule.td

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,13 @@ class SchedWriteRes<list<ProcResourceKind> resources> : SchedWrite,
321321
// Define values common to ReadAdvance and SchedReadAdvance.
322322
//
323323
// SchedModel ties these resources to a processor.
324-
class ProcReadAdvance<int cycles, list<SchedWrite> writes = []> {
324+
class ProcReadAdvance<int cycles, list<SchedWrite> writes = [],
325+
list<int> tunables = []> {
326+
assert !le(!size(tunables), !size(writes)),
327+
"cannot have more `tunables' than `writes'";
325328
int Cycles = cycles;
326329
list<SchedWrite> ValidWrites = writes;
330+
list<int> CycleTunables = tunables;
327331
// Allow a processor to mark some scheduling classes as unsupported
328332
// for stronger verification.
329333
bit Unsupported = false;
@@ -340,15 +344,17 @@ class ProcReadAdvance<int cycles, list<SchedWrite> writes = []> {
340344
// indicate operands that are always read this number of Cycles later
341345
// than a normal register read, allowing the read's parent instruction
342346
// to issue earlier relative to the writer.
343-
class ReadAdvance<SchedRead read, int cycles, list<SchedWrite> writes = []>
344-
: ProcReadAdvance<cycles, writes> {
347+
class ReadAdvance<SchedRead read, int cycles, list<SchedWrite> writes = [],
348+
list<int> tunables = []>
349+
: ProcReadAdvance<cycles, writes, tunables> {
345350
SchedRead ReadType = read;
346351
}
347352

348353
// Directly associate a new SchedRead type with a delay and optional
349354
// pipeline bypass. For use with InstRW or ItinRW.
350-
class SchedReadAdvance<int cycles, list<SchedWrite> writes = []> : SchedRead,
351-
ProcReadAdvance<cycles, writes>;
355+
class SchedReadAdvance<int cycles, list<SchedWrite> writes = [],
356+
list<int> tunables = []>
357+
: SchedRead, ProcReadAdvance<cycles, writes, tunables>;
352358

353359
// Define SchedRead defaults. Reads seldom need special treatment.
354360
def ReadDefault : SchedRead;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s 2>&1 | FileCheck %s
2+
// RUN: not llvm-tblgen -gen-subtarget -I %p/../../include -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
3+
4+
// Make sure that ReadAdvance entries with multiple writes are correctly
5+
// handled.
6+
7+
include "llvm/Target/Target.td"
8+
9+
def MyTarget : Target;
10+
11+
let OutOperandList = (outs), InOperandList = (ins) in {
12+
def Inst_A : Instruction;
13+
def Inst_B : Instruction;
14+
def Inst_C : Instruction;
15+
}
16+
17+
let CompleteModel = 0 in {
18+
def SchedModel_A: SchedMachineModel;
19+
}
20+
21+
def Read_D : SchedRead;
22+
def Read_E : SchedRead;
23+
24+
// CHECK: extern const llvm::MCReadAdvanceEntry MyTargetReadAdvanceTable[] = {
25+
// CHECK-NEXT: {0, 0, 0}, // Invalid
26+
// CHECK-NEXT: {0, 1, 1}, // #1
27+
// CHECK-NEXT: {0, 2, 3}, // #2
28+
// CHECK-NEXT: {0, 3, 2} // #3
29+
// CHECK-NEXT: }; // MyTargetReadAdvanceTable
30+
31+
let SchedModel = SchedModel_A in {
32+
def Write_A : SchedWriteRes<[]>;
33+
def Write_B : SchedWriteRes<[]>;
34+
def Write_C : SchedWriteRes<[]>;
35+
36+
def : InstRW<[Write_A], (instrs Inst_A)>;
37+
def : InstRW<[Write_B], (instrs Inst_B)>;
38+
def : InstRW<[Write_C, Read_D], (instrs Inst_C)>;
39+
40+
def : ReadAdvance<Read_D, 2, [Write_A, Write_B, Write_C], [-1, 1]>;
41+
42+
#ifdef ERROR1
43+
// ERROR1: error: assertion failed: cannot have more `tunables' than `writes'
44+
def : ReadAdvance<Read_E, 2, [Write_A, Write_B, Write_C], [1, 2, 3, 4]>;
45+
#endif
46+
}
47+
48+
def ProcessorA: ProcessorModel<"ProcessorA", SchedModel_A, []>;

llvm/utils/TableGen/SubtargetEmitter.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,23 +1308,27 @@ void SubtargetEmitter::genSchedClassTables(const CodeGenProcModel &ProcModel,
13081308
}
13091309
ConstRecVec ValidWrites =
13101310
ReadAdvance->getValueAsListOfDefs("ValidWrites");
1311-
IdxVec WriteIDs;
1311+
std::vector<int64_t> CycleTunables =
1312+
ReadAdvance->getValueAsListOfInts("CycleTunables");
1313+
std::vector<std::pair<unsigned, int>> WriteIDs;
1314+
assert(CycleTunables.size() <= ValidWrites.size() && "Bad ReadAdvance");
1315+
CycleTunables.resize(ValidWrites.size(), 0);
13121316
if (ValidWrites.empty())
1313-
WriteIDs.push_back(0);
1317+
WriteIDs.emplace_back(0, 0);
13141318
else {
1315-
for (const Record *VW : ValidWrites) {
1319+
for (const auto [VW, CT] : zip_equal(ValidWrites, CycleTunables)) {
13161320
unsigned WriteID = SchedModels.getSchedRWIdx(VW, /*IsRead=*/false);
13171321
assert(WriteID != 0 &&
13181322
"Expected a valid SchedRW in the list of ValidWrites");
1319-
WriteIDs.push_back(WriteID);
1323+
WriteIDs.emplace_back(WriteID, CT);
13201324
}
13211325
}
13221326
llvm::sort(WriteIDs);
1323-
for (unsigned W : WriteIDs) {
1327+
for (const auto &[W, T] : WriteIDs) {
13241328
MCReadAdvanceEntry RAEntry;
13251329
RAEntry.UseIdx = UseIdx;
13261330
RAEntry.WriteResourceID = W;
1327-
RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
1331+
RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles") + T;
13281332
ReadAdvanceEntries.push_back(RAEntry);
13291333
}
13301334
}

0 commit comments

Comments
 (0)