[llvm] e07716d - [TableGen][DecoderEmitter] Report all decoding conflicts (#157847)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 10 09:06:48 PDT 2025
Author: Rahul Joshi
Date: 2025-09-10T09:06:44-07:00
New Revision: e07716de0f85dd121f85cfdf1b413cb764beda2e
URL: https://github.com/llvm/llvm-project/commit/e07716de0f85dd121f85cfdf1b413cb764beda2e
DIFF: https://github.com/llvm/llvm-project/commit/e07716de0f85dd121f85cfdf1b413cb764beda2e.diff
LOG: [TableGen][DecoderEmitter] Report all decoding conflicts (#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.
Added:
Modified:
llvm/test/TableGen/FixedLenDecoderEmitter/conflict.td
llvm/utils/TableGen/DecoderEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/test/TableGen/FixedLenDecoderEmitter/conflict.td b/llvm/test/TableGen/FixedLenDecoderEmitter/conflict.td
index 853a68d22d1d9..e3666ebbf942a 100644
--- a/llvm/test/TableGen/FixedLenDecoderEmitter/conflict.td
+++ b/llvm/test/TableGen/FixedLenDecoderEmitter/conflict.td
@@ -9,27 +9,63 @@ def MyTarget : Target { let InstructionSet = MyTargetISA; }
def R0 : Register<"r0"> { let Namespace = "MyTarget"; }
def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
+def X0 : Register<"x0"> { let Namespace = "MyTarget"; }
+def GPR64 : RegisterClass<"MyTarget", [i64], 64, (add X0)>;
+
class I<dag OOps, dag IOps, list<dag> Pat>
: Instruction {
let Namespace = "MyTarget";
let OutOperandList = OOps;
let InOperandList = IOps;
let Pattern = Pat;
+ let Size = 4;
bits<32> Inst;
bits<32> SoftFail;
}
+// Assume there is a 2 bit encoding for the dst and src register.
def A : I<(outs GPR32:$dst), (ins GPR32:$src1), []> {
- let Size = 4;
- let Inst{31...0} = 0;
+ bits<2> dst;
+ bits<2> src1;
+ let Inst{31...4} = 0;
+ let Inst{1...0} = dst;
+ let Inst{3...2} = src1;
}
+
def B : I<(outs GPR32:$dst), (ins GPR32:$src1), []> {
- let Size = 4;
- let Inst{31...0} = 0;
+ bits<2> dst;
+ bits<2> src1;
+ let Inst{31...4} = 0;
+ let Inst{1...0} = dst;
+ let Inst{3...2} = src1;
+}
+
+def C : I<(outs GPR64:$dst), (ins GPR64:$src1), []> {
+ bits<2> dst;
+ bits<2> src1;
+ let Inst{31...4} = 1;
+ let Inst{1...0} = dst;
+ let Inst{3...2} = src1;
}
+def D : I<(outs GPR64:$dst), (ins GPR64:$src1), []> {
+ bits<2> dst;
+ bits<2> src1;
+ let Inst{31...4} = 1;
+ let Inst{1...0} = dst;
+ let Inst{3...2} = src1;
+}
+
+// CHECK: Decoding Conflict:
+// CHECK: ................................
+// CHECK: 0000000000000000000000000000....
+// CHECK: 0000000000000000000000000000____ A
+// CHECK: 0000000000000000000000000000____ B
+
// CHECK: Decoding Conflict:
// CHECK: ................................
-// CHECK: 00000000000000000000000000000000
-// CHECK: 00000000000000000000000000000000 A
-// CHECK: 00000000000000000000000000000000 B
+// CHECK: 0000000000000000000000000001....
+// CHECK: 0000000000000000000000000001____ C
+// CHECK: 0000000000000000000000000001____ D
+
+// CHECK: Decoding conflict encountered
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 95e7408ea88c7..8747d02ac892b 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -517,6 +517,9 @@ class FilterChooser {
/// The "field value" here refers to the encoding bits in the filtered range.
std::map<uint64_t, std::unique_ptr<const FilterChooser>> FilterChooserMap;
+ /// Set to true if decoding conflict was encountered.
+ bool HasConflict = false;
+
struct Island {
unsigned StartBit;
unsigned NumBits;
@@ -559,6 +562,9 @@ class FilterChooser {
return Encodings[EncodingIDs.back()].getBitWidth();
}
+ /// Returns true if any decoding conflicts were encountered.
+ bool hasConflict() const { return HasConflict; }
+
private:
/// Applies the given filter to the set of encodings this FilterChooser
/// works with, creating inferior FilterChoosers as necessary.
@@ -684,6 +690,7 @@ void FilterChooser::applyFilter(const Filter &F) {
// group of instructions whose segment values are variable.
VariableFC = std::make_unique<FilterChooser>(Encodings, F.VariableIDs,
FilterBits, *this);
+ HasConflict |= VariableFC->HasConflict;
}
// Otherwise, create sub choosers.
@@ -695,9 +702,11 @@ void FilterChooser::applyFilter(const Filter &F) {
// Delegates to an inferior filter chooser for further processing on this
// category of instructions.
- FilterChooserMap.try_emplace(FilterVal, std::make_unique<FilterChooser>(
- Encodings, InferiorEncodingIDs,
- InferiorFilterBits, *this));
+ auto [It, _] = FilterChooserMap.try_emplace(
+ FilterVal,
+ std::make_unique<FilterChooser>(Encodings, InferiorEncodingIDs,
+ InferiorFilterBits, *this));
+ HasConflict |= It->second->HasConflict;
}
}
@@ -1592,7 +1601,7 @@ void FilterChooser::doFilter() {
// Print out useful conflict information for postmortem analysis.
errs() << "Decoding Conflict:\n";
dump();
- PrintFatalError("Decoding conflict encountered");
+ HasConflict = true;
}
void FilterChooser::dump() const {
@@ -2570,12 +2579,17 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
DecoderTableBuilder TableBuilder(Target, Encodings, TableInfo);
unsigned OpcodeMask = 0;
+ bool HasConflict = false;
for (const auto &[BitWidth, BWMap] : EncMap) {
for (const auto &[Key, EncodingIDs] : BWMap) {
auto [DecoderNamespace, HwModeID] = Key;
// Emit the decoder for this (namespace, hwmode, width) combination.
FilterChooser FC(Encodings, EncodingIDs);
+ HasConflict |= FC.hasConflict();
+ // Skip emitting table entries if a conflict has been detected.
+ if (HasConflict)
+ continue;
// The decode table is cleared for each top level decoder function. The
// predicates and decoders themselves, however, are shared across
@@ -2600,6 +2614,9 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
}
}
+ if (HasConflict)
+ PrintFatalError("Decoding conflict encountered");
+
// Emit the decoder function for the last bucket. This will also emit the
// single decoder function if SpecializeDecodersPerBitwidth = false.
if (!SpecializeDecodersPerBitwidth)
More information about the llvm-commits
mailing list