Skip to content

Commit e07716d

Browse files
authored
[TableGen][DecoderEmitter] Report all decoding conflicts (llvm#157847)
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 f756224 commit e07716d

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
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/utils/TableGen/DecoderEmitter.cpp

Lines changed: 21 additions & 4 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;
@@ -559,6 +562,9 @@ class FilterChooser {
559562
return Encodings[EncodingIDs.back()].getBitWidth();
560563
}
561564

565+
/// Returns true if any decoding conflicts were encountered.
566+
bool hasConflict() const { return HasConflict; }
567+
562568
private:
563569
/// Applies the given filter to the set of encodings this FilterChooser
564570
/// works with, creating inferior FilterChoosers as necessary.
@@ -684,6 +690,7 @@ void FilterChooser::applyFilter(const Filter &F) {
684690
// group of instructions whose segment values are variable.
685691
VariableFC = std::make_unique<FilterChooser>(Encodings, F.VariableIDs,
686692
FilterBits, *this);
693+
HasConflict |= VariableFC->HasConflict;
687694
}
688695

689696
// Otherwise, create sub choosers.
@@ -695,9 +702,11 @@ void FilterChooser::applyFilter(const Filter &F) {
695702

696703
// Delegates to an inferior filter chooser for further processing on this
697704
// category of instructions.
698-
FilterChooserMap.try_emplace(FilterVal, std::make_unique<FilterChooser>(
699-
Encodings, InferiorEncodingIDs,
700-
InferiorFilterBits, *this));
705+
auto [It, _] = FilterChooserMap.try_emplace(
706+
FilterVal,
707+
std::make_unique<FilterChooser>(Encodings, InferiorEncodingIDs,
708+
InferiorFilterBits, *this));
709+
HasConflict |= It->second->HasConflict;
701710
}
702711
}
703712

@@ -1592,7 +1601,7 @@ void FilterChooser::doFilter() {
15921601
// Print out useful conflict information for postmortem analysis.
15931602
errs() << "Decoding Conflict:\n";
15941603
dump();
1595-
PrintFatalError("Decoding conflict encountered");
1604+
HasConflict = true;
15961605
}
15971606

15981607
void FilterChooser::dump() const {
@@ -2570,12 +2579,17 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
25702579
DecoderTableBuilder TableBuilder(Target, Encodings, TableInfo);
25712580
unsigned OpcodeMask = 0;
25722581

2582+
bool HasConflict = false;
25732583
for (const auto &[BitWidth, BWMap] : EncMap) {
25742584
for (const auto &[Key, EncodingIDs] : BWMap) {
25752585
auto [DecoderNamespace, HwModeID] = Key;
25762586

25772587
// Emit the decoder for this (namespace, hwmode, width) combination.
25782588
FilterChooser FC(Encodings, EncodingIDs);
2589+
HasConflict |= FC.hasConflict();
2590+
// Skip emitting table entries if a conflict has been detected.
2591+
if (HasConflict)
2592+
continue;
25792593

25802594
// The decode table is cleared for each top level decoder function. The
25812595
// predicates and decoders themselves, however, are shared across
@@ -2600,6 +2614,9 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
26002614
}
26012615
}
26022616

2617+
if (HasConflict)
2618+
PrintFatalError("Decoding conflict encountered");
2619+
26032620
// Emit the decoder function for the last bucket. This will also emit the
26042621
// single decoder function if SpecializeDecodersPerBitwidth = false.
26052622
if (!SpecializeDecodersPerBitwidth)

0 commit comments

Comments
 (0)