aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/DecoderEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/DecoderEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/DecoderEmitter.cpp25
1 files changed, 21 insertions, 4 deletions
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 95e7408..8747d02 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 @@ public:
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)