Skip to content

Commit 72da5bf

Browse files
author
Martien de Jong
committed
[AIE][CodeGenFormat] Compute ConflictBits using all given formats
Separate SlotBits from ConflictBits
1 parent 8b335be commit 72da5bf

File tree

8 files changed

+222
-16
lines changed

8 files changed

+222
-16
lines changed

llvm/include/llvm/Target/CodeGenFormat.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ class InstSlot<string slotname, int Size, bit isDefault=false> : Operand<OtherV
4545
// Namespace.
4646
bit isDefaultSlot = isDefault;
4747

48+
// Mark a slot as artificial. This will exclude it from any resource
49+
// estimations.
50+
bit Artificial = false;
51+
4852
let DecoderMethod = "decode" # SlotName # "Slot";
4953
}
5054

llvm/lib/Target/AIE/AIE2PSlotInclude.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ let Namespace = "AIE2P" in
2121
// 64 bit one.
2222
def nop_slot : InstSlot<"Nop", 1> {
2323
let FieldToFind = "nop";
24+
let Artificial = true;
2425
}
2526
}

llvm/lib/Target/AIE/AIE2Slots.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ let Namespace = "AIE2" in
5959
// 64 bit one.
6060
def nop_slot : InstSlot<"Nop", 1> {
6161
let FieldToFind = "nop";
62+
let Artificial = true;
6263
}
6364
}
6465

llvm/lib/Target/AIE/MCTargetDesc/AIEMCFormats.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
7-
// (c) Copyright 2023-2024 Advanced Micro Devices, Inc. or its affiliates
7+
// (c) Copyright 2023-2025 Advanced Micro Devices, Inc. or its affiliates
88
//
99
//===----------------------------------------------------------------------===//
1010
// Utility classes to interface the generated Formats from CodeGenFormat with
@@ -93,18 +93,23 @@ class MCSlotInfo {
9393
const char *SlotName;
9494
/// Size of the slot (in bits)
9595
const unsigned Size;
96-
/// Bitset representing the occupancy of the slot
96+
/// Bitset representing the occupancy of the slots
9797
const SlotBits SlotOccupancy;
98-
/// Opcode of the NOP inst. attached to the slot
98+
/// The closure of SlotOccupancy with the computed exclusions,
99+
/// e.g. XM implies X and M
100+
const SlotBits ConflictBits;
101+
/// Opcode of the NOP instruction attached to the slot
99102
const unsigned NopOpc;
100103

101104
public:
102105
constexpr MCSlotInfo(const char *SlotName, unsigned Size, SlotBits Bits,
103-
unsigned NopOpc)
104-
: SlotName(SlotName), Size(Size), SlotOccupancy(Bits), NopOpc(NopOpc) {}
106+
SlotBits ConflictBits, unsigned NopOpc)
107+
: SlotName(SlotName), Size(Size), SlotOccupancy(Bits),
108+
ConflictBits(ConflictBits), NopOpc(NopOpc) {}
105109

106110
const char *getName() const { return SlotName; }
107111
SlotBits getSlotSet() const { return SlotOccupancy; }
112+
SlotBits getConflictSet() const { return ConflictBits; }
108113
unsigned getNOPOpcode() const { return NopOpc; }
109114
unsigned getSize() const { return Size; }
110115
};
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//
2+
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
// Copyright 2025 Advanced Micro Devices, Inc. or its affiliates
7+
//
8+
9+
// RUN: llvm-tblgen --gen-instr-format -I %p -I %p/../ -I %p/../../../../include %s 2>&1 | FileCheck %s
10+
11+
// This is a minimal check for the computations of the conflict bits.
12+
// We have the slots A. X, M and XM, which interfere like the
13+
// corresponding slots on typical AIE architectures.
14+
// We compute conflicts from the totality of formats, and we should find
15+
// conflicts
16+
// X -> {X, XM},
17+
// M -> {M, XM},
18+
// XM -> {X, M, XM}
19+
// A -> {A}
20+
// and nothing more.
21+
22+
// CHECK-LABEL: "X",
23+
// CHECK-NEXT: 8,
24+
// CHECK-NEXT: 1,
25+
// CHECK-NEXT: 5,
26+
// CHECK-LABEL: "A",
27+
// CHECK-NEXT: 10,
28+
// CHECK-NEXT: 2,
29+
// CHECK-NEXT: 2,
30+
// CHECK-LABEL: "XM",
31+
// CHECK-NEXT: 18,
32+
// CHECK-NEXT: 4,
33+
// CHECK-NEXT: 13,
34+
// CHECK-LABEL: "M",
35+
// CHECK-NEXT: 10,
36+
// CHECK-NEXT: 8,
37+
// CHECK-NEXT: 12,
38+
// CHECK-LABEL: "nop",
39+
// CHECK-NEXT: 14,
40+
// CHECK-NEXT: 16,
41+
// CHECK-NEXT: 31,
42+
43+
include "llvm/Target/Target.td"
44+
include "llvm/Target/CodeGenFormat.td"
45+
46+
let Namespace = "TEST" in {
47+
def nop_slot : InstSlot<"nop", 14> { let Artificial = true; }
48+
def lda_slot : InstSlot<"A", 10>;
49+
def alu_slot : InstSlot<"X", 8>;
50+
def mov_slot : InstSlot<"M", 10>;
51+
def lng_slot : InstSlot<"XM", 18>;
52+
}
53+
54+
55+
def TESTInstrInfo : InstrInfo;
56+
57+
def TEST : Target {
58+
let InstructionSet = TESTInstrInfo;
59+
}
60+
61+
def TESTCodeGenFormat : CodeGenFormat {
62+
let FormatClassEmitted = "";
63+
}
64+
65+
let Namespace = "TEST" in
66+
def default_slot : InstSlot<"default", 0, true>;
67+
68+
class TESTInst<dag outs, dag ins, string opc, string arg, list<dag> pattern>
69+
: Instruction, InstFormat
70+
{
71+
let Namespace = "TEST";
72+
73+
dag OutOperandList = outs;
74+
dag InOperandList = ins;
75+
let AsmString = opc # "\t" # arg;
76+
let Pattern = pattern;
77+
78+
let Slot = default_slot;
79+
}
80+
81+
class TESTSubInst<dag outs, dag ins>
82+
: TESTInst<outs, ins, "", "", []>
83+
{
84+
let isComposite = false;
85+
}
86+
87+
class TESTFormat<dag outs, dag ins> : TESTInst<outs, ins, "", "", []> {
88+
let isComposite = true;
89+
}
90+
91+
92+
class TEST_I32<dag outs, dag ins> : TESTFormat<outs, ins> {
93+
field bits<32> Inst;
94+
field bits<32> instr32;
95+
let Inst = {instr32};
96+
}
97+
98+
def I32_A_XM : TEST_I32<(outs), (ins lda_slot:$lda, lng_slot:$lng)> {
99+
bits<10> lda;
100+
bits<18> lng;
101+
let instr32 = {lda, lng, 0b1001};
102+
}
103+
104+
def I32_A_X : TEST_I32<(outs), (ins lda_slot:$lda, alu_slot:$alu)> {
105+
bits<10> lda;
106+
bits<8> alu;
107+
let instr32 = {lda, alu, 0b0000000000, 0b1001};
108+
}
109+
110+
def I32_X_M : TEST_I32<(outs), (ins alu_slot:$alu, mov_slot:$mov)> {
111+
bits<8> alu;
112+
bits<10> mov;
113+
let instr32 = {0b0000000000, alu, mov, 0b0110};
114+
}
115+
116+
def I32_A_X_M : TEST_I32<(outs),
117+
(ins lda_slot:$lda, alu_slot:$alu, mov_slot:$mov)> {
118+
bits<10> lda;
119+
bits<8> alu;
120+
bits<10> mov;
121+
let instr32 = {lda, alu, mov, 0b1110};
122+
}
123+

llvm/unittests/Target/AIE/BundleTest.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
7-
// (c) Copyright 2023-2024 Advanced Micro Devices, Inc. or its affiliates
7+
// (c) Copyright 2023-2025 Advanced Micro Devices, Inc. or its affiliates
88
//
99
//===----------------------------------------------------------------------===//
1010

@@ -42,10 +42,10 @@ const VLIWFormat FormatData[] = {
4242
{0, nullptr, {}, 0, 0}};
4343
const PacketFormats MyFormats{FormatData};
4444

45-
constexpr MCSlotInfo SlotInfos[4] = {{"ALU", 1, 0b0001, 0},
46-
{"MV", 1, 0b0010, 0},
47-
{"ST", 1, 0b0100, 0},
48-
{"LNG", 1, 0b1000, 0}};
45+
constexpr MCSlotInfo SlotInfos[4] = {{"ALU", 1, 0b0001, 0b0001, 0},
46+
{"MV", 1, 0b0010, 0b0010, 0},
47+
{"ST", 1, 0b0100, 0b0100, 0},
48+
{"LNG", 1, 0b1000, 0b1000, 0}};
4949

5050
// Stay clear of standard opcodes
5151
static const int FirstOpcode = 1000;

llvm/utils/TableGen/CodeGenFormat.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ void CodeGenFormat::run(raw_ostream &o) {
109109

110110
assert(Slots.size() != 0 && "no Slot detected");
111111

112+
computeSlotSets(Slots, InstFormats);
113+
112114
o << "#ifdef GET_FORMATS_SLOTKINDS\n"
113115
"#undef GET_FORMATS_SLOTKINDS\n\n";
114116
Slots.emitTargetSlotKindEnum(o);
@@ -207,7 +209,6 @@ void CodeGenFormat::run(raw_ostream &o) {
207209

208210
for (TGInstrLayout &Inst : InstFormats)
209211
if (Inst.isPacketFormat()) {
210-
Inst.computeSlotSet();
211212
Packets.push_back(&Inst);
212213
}
213214

@@ -244,6 +245,47 @@ void CodeGenFormat::run(raw_ostream &o) {
244245
}
245246
}
246247

248+
void CodeGenFormat::computeSlotSets(TGTargetSlots &Slots,
249+
std::vector<TGInstrLayout> &InstFormats) {
250+
251+
// The slots accommodated by each format.
252+
for (TGInstrLayout &Format : InstFormats) {
253+
if (Format.isPacketFormat()) {
254+
Format.computeSlotSet();
255+
}
256+
}
257+
258+
// The universe of all slots
259+
uint64_t AllSlots = 0;
260+
for (const auto &[_, Slot] : Slots) {
261+
if (Slot.isDefaultSlot() || Slot.isArtificial()) {
262+
continue;
263+
}
264+
AllSlots |= Slot.getSlotBits();
265+
}
266+
267+
// Compute the conflict bits of all slots.
268+
for (unsigned S = 0; S < Slots.size(); S++) {
269+
// Effectively we check whether a slot cannot be combined with another
270+
// slot in any format in which the first is accommodated. We start out
271+
// with all slots excluded, and eliminate the exclusion when a format is
272+
// encountered that allows both ThisSlot and the exclusion.
273+
auto &Slot = Slots.getSlot(S).second;
274+
const uint64_t ThisSlot = Slot.getSlotBits();
275+
uint64_t Excluded = AllSlots;
276+
for (TGInstrLayout &Format : InstFormats) {
277+
if (!Format.isPacketFormat()) {
278+
continue;
279+
}
280+
uint64_t SlotSet = Format.getSlotSet();
281+
if (SlotSet & ThisSlot) {
282+
Excluded &= ~SlotSet & AllSlots;
283+
}
284+
}
285+
Slot.setConflictBits(ThisSlot | Excluded);
286+
}
287+
}
288+
247289
// Retrieve the number of consecutive bits (from BitPos) that are part of the
248290
// same "variable" (described by "VarName")
249291
// NOTE0: if the bit at BitPos isn't a variable bit, then we simply return 0
@@ -1093,7 +1135,8 @@ void TGTargetSlots::emitSlotsInfoInstantiation(
10931135
<< " " << TS.getSlotSize()
10941136
<< ",\n"
10951137
// Right now, we're using the slot num as SlotSet
1096-
<< " " << (uint64_t(1) << TS.getNumSlot()) << ",\n"
1138+
<< " " << TS.getSlotBits() << ",\n"
1139+
<< " " << TS.getConflictBits() << ",\n"
10971140
<< " " << NOPName << "\n"
10981141
<< "},\n";
10991142
}

llvm/utils/TableGen/CodeGenFormat.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,11 @@ class CodeGenFormat {
129129
void run(raw_ostream &o);
130130

131131
static unsigned getVariableBits(const std::string &VarName,
132-
const BitsInit *BI, unsigned posBit);
132+
const BitsInit *BI, unsigned BitPos);
133133
static unsigned getFixedBits(std::string &OutChunck, const BitsInit *BI,
134-
unsigned posBit);
134+
unsigned BitPos);
135+
static void computeSlotSets(TGTargetSlots &Slots,
136+
std::vector<TGInstrLayout> &InstFormats);
135137
};
136138

137139
/// Main class abstracting a CodeGenInstruction (CGI).
@@ -269,13 +271,28 @@ class TGTargetSlot {
269271
std::string SlotName;
270272
// The namespace of the current instruction
271273
std::string Namespace;
272-
// primarely used when emitting the C++ enumeration constant
274+
// primarily used when emitting the C++ enumeration constant
273275
std::string EnumerationString;
274276
// Name of the field to find in the hierarchy
275277
std::string FieldToFind;
278+
// Artificial slots should not be considered for resource estimates
279+
bool Artificial = false;
276280
// Unique number attributed (in the pool) for the slot.
277281
// It is used to generate a unique "SlotSet".
278282
int NumSlot;
283+
284+
// The Slot bits for this slot. These are the pristine bits that correspond
285+
// to the slots a format accommodates.
286+
uint64_t SlotBits = 0;
287+
288+
// The conflict bits for this slot. These are used to prevent format table
289+
// searches as much as possible. It normally duplicates the SlotBit, since
290+
// that is a trivial conflict.
291+
// However, there may be more bits set. For example, XM conflicts with
292+
// XM, X and M.
293+
// Note that the scoreboard runs on these conflict bits.
294+
uint64_t ConflictBits;
295+
279296
// Size of the Slot, in bits.
280297
// The storage of the size is made using an integer value as the size could
281298
// be negative. In this case, the slot pool (TGTargetSlots) will consider
@@ -296,6 +313,7 @@ class TGTargetSlot {
296313
SlotName(SlotRecord->getValueAsString("SlotName")),
297314
Namespace(SlotRecord->getValueAsString("Namespace")),
298315
FieldToFind(SlotRecord->getValueAsString("FieldToFind")),
316+
Artificial(SlotRecord->getValueAsBit("Artificial")),
299317
// NumSlot is defined as -1 for now.
300318
// When the pool of slots will be finalized, then the final ID will be
301319
// attributed.
@@ -349,12 +367,21 @@ class TGTargetSlot {
349367
const std::string &getLabelToFind() const { return FieldToFind; }
350368

351369
unsigned getSlotSize() const { return static_cast<unsigned>(SlotSize); }
370+
uint64_t getSlotBits() const { return SlotBits; }
371+
uint64_t getConflictBits() const { return ConflictBits; }
352372

353373
const std::string &getEnumerationString() const { return EnumerationString; }
354374
bool isDefaultSlot() const { return IsDefaultSlot; }
375+
bool isArtificial() const { return Artificial; }
376+
void setConflictBits(uint64_t Bits) { ConflictBits = Bits; }
355377

356378
private:
357-
void setNumSlot(int SlotID) { NumSlot = SlotID; }
379+
void setNumSlot(int SlotID) {
380+
NumSlot = SlotID;
381+
const uint64_t Base = 1;
382+
SlotBits = Base << SlotID;
383+
}
384+
358385
void setNopInst(const std::string &NOPName) { NOPInstrName = NOPName; }
359386
};
360387

@@ -393,6 +420,8 @@ class TGTargetSlots {
393420
/// Add the Slot (if legal) in the Slot pool
394421
bool addSlot(const Record *const R);
395422

423+
RecordSlot &getSlot(unsigned N) { return Slots[N]; }
424+
396425
/// This method performs a finalization of the slot pool. This finalization
397426
/// is composed of 2 stages: the attribution of a unique ID for each slot and
398427
/// then the sorting of the internal container based on their ID, in order to

0 commit comments

Comments
 (0)