Skip to content

Commit 8d5a48b

Browse files
committed
[TableGen][DecoderEmitter] Report all decoding conflicts
Do not exit when the first decoding conflict is encountered. Instead record the conflict and continue to report any additional decoding conflicts and exit fatally after all instructions have been processed.
1 parent ebd6841 commit 8d5a48b

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-21
lines changed

llvm/test/TableGen/FixedLenDecoderEmitter/conflict.td

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,63 @@ def MyTarget : Target { let InstructionSet = MyTargetISA; }
99
def R0 : Register<"r0"> { let Namespace = "MyTarget"; }
1010
def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
1111

12+
def X0 : Register<"x0"> { let Namespace = "MyTarget"; }
13+
def GPR64 : RegisterClass<"MyTarget", [i64], 64, (add X0)>;
14+
1215
class I<dag OOps, dag IOps, list<dag> Pat>
1316
: Instruction {
1417
let Namespace = "MyTarget";
1518
let OutOperandList = OOps;
1619
let InOperandList = IOps;
1720
let Pattern = Pat;
21+
let Size = 4;
1822
bits<32> Inst;
1923
bits<32> SoftFail;
2024
}
2125

26+
// Assume there is a 2 bit encoding for the dst and src register.
2227
def A : I<(outs GPR32:$dst), (ins GPR32:$src1), []> {
23-
let Size = 4;
24-
let Inst{31...0} = 0;
28+
bits<2> dst;
29+
bits<2> src1;
30+
let Inst{31...4} = 0;
31+
let Inst{1...0} = dst;
32+
let Inst{3...2} = src1;
2533
}
34+
2635
def B : I<(outs GPR32:$dst), (ins GPR32:$src1), []> {
27-
let Size = 4;
28-
let Inst{31...0} = 0;
36+
bits<2> dst;
37+
bits<2> src1;
38+
let Inst{31...4} = 0;
39+
let Inst{1...0} = dst;
40+
let Inst{3...2} = src1;
41+
}
42+
43+
def C : I<(outs GPR64:$dst), (ins GPR64:$src1), []> {
44+
bits<2> dst;
45+
bits<2> src1;
46+
let Inst{31...4} = 1;
47+
let Inst{1...0} = dst;
48+
let Inst{3...2} = src1;
2949
}
3050

51+
def D : I<(outs GPR64:$dst), (ins GPR64:$src1), []> {
52+
bits<2> dst;
53+
bits<2> src1;
54+
let Inst{31...4} = 1;
55+
let Inst{1...0} = dst;
56+
let Inst{3...2} = src1;
57+
}
58+
59+
// CHECK: Decoding Conflict:
60+
// CHECK: ................................
61+
// CHECK: 0000000000000000000000000000....
62+
// CHECK: 0000000000000000000000000000____ A
63+
// CHECK: 0000000000000000000000000000____ B
64+
3165
// CHECK: Decoding Conflict:
3266
// CHECK: ................................
33-
// CHECK: 00000000000000000000000000000000
34-
// CHECK: 00000000000000000000000000000000 A
35-
// CHECK: 00000000000000000000000000000000 B
67+
// CHECK: 0000000000000000000000000001....
68+
// CHECK: 0000000000000000000000000001____ C
69+
// CHECK: 0000000000000000000000000001____ D
70+
71+
// CHECK: Decoding conflict encountered

llvm/test/TableGen/FixedLenDecoderEmitter/var-len-conflict-2.td

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,14 @@ class I : Instruction {
1010

1111
// Check pretty printing of decoding conflicts.
1212

13-
// CHECK: {{^}}Decoding Conflict:
14-
// CHECK-NEXT: {{^}} ........
15-
// CHECK-NEXT: {{^}} ..............11
16-
// CHECK-NEXT: {{^}} .......0......11
17-
// CHECK-NEXT: {{^}} _______0______11 I16_0
18-
// CHECK-NEXT: {{^}} _______0______11 I16_1
19-
// CHECK-NEXT: {{^}} _______0_______0______11 I24_0
13+
// CHECK: Decoding Conflict:
14+
// CHECK-NEXT: ................
15+
// CHECK-NEXT: ..............11
16+
// CHECK-NEXT: .......0......11
17+
// CHECK-NEXT: _______0______11 I16_0
18+
// CHECK-NEXT: _______0______11 I16_1
19+
// CHECK-NEXT: _______0_______0______11 I24_0
2020

21-
def I8_0 : I { dag Inst = (descend (operand "$op", 6), 0b00); }
22-
def I8_1 : I { dag Inst = (descend (operand "$op", 6), 0b01); }
2321
def I16_0 : I { dag Inst = (descend (operand "$op2", 7), 0b0,
2422
(operand "$op", 6), 0b11); }
2523
def I16_1 : I { dag Inst = (descend (operand "$op2", 7), 0b0,

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,9 @@ class FilterChooser {
517517
/// The "field value" here refers to the encoding bits in the filtered range.
518518
std::map<uint64_t, std::unique_ptr<const FilterChooser>> FilterChooserMap;
519519

520+
/// Set to true if decoding conflict was encountered.
521+
bool HasConflict = false;
522+
520523
struct Island {
521524
unsigned StartBit;
522525
unsigned NumBits;
@@ -600,18 +603,22 @@ class DecoderTableBuilder {
600603
ArrayRef<InstructionEncoding> Encodings;
601604
DecoderTableInfo &TableInfo;
602605

606+
bool HasConflict = false;
607+
603608
public:
604609
DecoderTableBuilder(const CodeGenTarget &Target,
605610
ArrayRef<InstructionEncoding> Encodings,
606611
DecoderTableInfo &TableInfo)
607612
: Target(Target), Encodings(Encodings), TableInfo(TableInfo) {}
608613

609-
void buildTable(const FilterChooser &FC, unsigned BitWidth) const {
614+
/// Returns true if a decoding conflict was encountered.
615+
bool buildTable(const FilterChooser &FC, unsigned BitWidth) {
610616
// When specializing decoders per bit width, each decoder table will begin
611617
// with the bitwidth for that table.
612618
if (SpecializeDecodersPerBitwidth)
613619
TableInfo.Table.insertULEB128(BitWidth);
614620
emitTableEntries(FC);
621+
return HasConflict;
615622
}
616623

617624
private:
@@ -637,7 +644,7 @@ class DecoderTableBuilder {
637644

638645
void emitSingletonTableEntry(const FilterChooser &FC) const;
639646

640-
void emitTableEntries(const FilterChooser &FC) const;
647+
void emitTableEntries(const FilterChooser &FC);
641648
};
642649

643650
} // end anonymous namespace
@@ -1592,7 +1599,7 @@ void FilterChooser::doFilter() {
15921599
// Print out useful conflict information for postmortem analysis.
15931600
errs() << "Decoding Conflict:\n";
15941601
dump();
1595-
PrintFatalError("Decoding conflict encountered");
1602+
HasConflict = true;
15961603
}
15971604

15981605
void FilterChooser::dump() const {
@@ -1612,7 +1619,12 @@ void FilterChooser::dump() const {
16121619
}
16131620
}
16141621

1615-
void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
1622+
void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) {
1623+
if (FC.HasConflict) {
1624+
HasConflict = true;
1625+
return;
1626+
}
1627+
16161628
DecoderTable &Table = TableInfo.Table;
16171629

16181630
// If there are other encodings that could match if those with all bits
@@ -2570,6 +2582,7 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
25702582
DecoderTableBuilder TableBuilder(Target, Encodings, TableInfo);
25712583
unsigned OpcodeMask = 0;
25722584

2585+
bool HasConflict = false;
25732586
for (const auto &[BitWidth, BWMap] : EncMap) {
25742587
for (const auto &[Key, EncodingIDs] : BWMap) {
25752588
auto [DecoderNamespace, HwModeID] = Key;
@@ -2585,7 +2598,10 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
25852598
// across all decoder tables.
25862599
// - predicates are shared across all decoder tables.
25872600
TableInfo.Table.clear();
2588-
TableBuilder.buildTable(FC, BitWidth);
2601+
HasConflict |= TableBuilder.buildTable(FC, BitWidth);
2602+
// Skip emitting table entries if a conflict has been detected.
2603+
if (HasConflict)
2604+
continue;
25892605

25902606
// Print the table to the output stream.
25912607
OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,
@@ -2600,6 +2616,9 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
26002616
}
26012617
}
26022618

2619+
if (HasConflict)
2620+
PrintFatalError("Decoding conflict encountered");
2621+
26032622
// Emit the decoder function for the last bucket. This will also emit the
26042623
// single decoder function if SpecializeDecodersPerBitwidth = false.
26052624
if (!SpecializeDecodersPerBitwidth)

0 commit comments

Comments
 (0)