Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 43 additions & 7 deletions llvm/test/TableGen/FixedLenDecoderEmitter/conflict.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 7 additions & 9 deletions llvm/test/TableGen/FixedLenDecoderEmitter/var-len-conflict-2.td
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@ class I : Instruction {

// Check pretty printing of decoding conflicts.

// CHECK: {{^}}Decoding Conflict:
// CHECK-NEXT: {{^}} ........
// CHECK-NEXT: {{^}} ..............11
// CHECK-NEXT: {{^}} .......0......11
// CHECK-NEXT: {{^}} _______0______11 I16_0
// CHECK-NEXT: {{^}} _______0______11 I16_1
// CHECK-NEXT: {{^}} _______0_______0______11 I24_0
// CHECK: Decoding Conflict:
// CHECK-NEXT: ................
// CHECK-NEXT: ..............11
// CHECK-NEXT: .......0......11
// CHECK-NEXT: _______0______11 I16_0
// CHECK-NEXT: _______0______11 I16_1
// CHECK-NEXT: _______0_______0______11 I24_0

def I8_0 : I { dag Inst = (descend (operand "$op", 6), 0b00); }
def I8_1 : I { dag Inst = (descend (operand "$op", 6), 0b01); }
def I16_0 : I { dag Inst = (descend (operand "$op2", 7), 0b0,
(operand "$op", 6), 0b11); }
def I16_1 : I { dag Inst = (descend (operand "$op2", 7), 0b0,
Expand Down
25 changes: 21 additions & 4 deletions llvm/utils/TableGen/DecoderEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -559,6 +562,9 @@ class FilterChooser {
return Encodings[EncodingIDs.back()].getBitWidth();
}

/// Returns true if any decoding conflicts were encountered.
bool getHasConflict() const { return HasConflict; }

private:
/// Applies the given filter to the set of encodings this FilterChooser
/// works with, creating inferior FilterChoosers as necessary.
Expand Down Expand Up @@ -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.
Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.getHasConflict();
// 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
Expand All @@ -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)
Expand Down
Loading