[llvm] cdc79e3 - [TableGen][DecoderEmitter] Optimize single-case OPC_ExtractField (#155414)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 26 09:12:07 PDT 2025
Author: Sergei Barannikov
Date: 2025-08-26T19:12:04+03:00
New Revision: cdc79e32f2689192a13f1be4b78730192c645b26
URL: https://github.com/llvm/llvm-project/commit/cdc79e32f2689192a13f1be4b78730192c645b26
DIFF: https://github.com/llvm/llvm-project/commit/cdc79e32f2689192a13f1be4b78730192c645b26.diff
LOG: [TableGen][DecoderEmitter] Optimize single-case OPC_ExtractField (#155414)
OPC_ExtractField followed by a single OPC_FilterValue is equivalent to
OPC_CheckField. Optimize this relatively common case.
Added:
Modified:
llvm/test/TableGen/trydecode-emission.td
llvm/test/TableGen/trydecode-emission2.td
llvm/test/TableGen/trydecode-emission3.td
llvm/test/TableGen/trydecode-emission4.td
llvm/utils/TableGen/DecoderEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/test/TableGen/trydecode-emission.td b/llvm/test/TableGen/trydecode-emission.td
index 6e47909b8f09a..5d1c18fe65d0e 100644
--- a/llvm/test/TableGen/trydecode-emission.td
+++ b/llvm/test/TableGen/trydecode-emission.td
@@ -34,11 +34,10 @@ def InstB : TestInstruction {
let hasCompleteDecoder = 0;
}
-// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
-// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 17
-// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
+// CHECK-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 16
+// CHECK-NEXT: /* 10 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 16
+// CHECK-NEXT: /* 16 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
// CHECK-NEXT: };
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
@@ -47,11 +46,10 @@ def InstB : TestInstruction {
// CHECK-NEXT: NumToSkip |= (*Ptr++) << 8;
// CHECK-NEXT: return NumToSkip;
-// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
-// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 19
-// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
+// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 18
+// CHECK-LARGE-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
+// CHECK-LARGE-NEXT: /* 18 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
// CHECK-LARGE-NEXT: };
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission2.td b/llvm/test/TableGen/trydecode-emission2.td
index 826b1715514f9..375be9ad13d19 100644
--- a/llvm/test/TableGen/trydecode-emission2.td
+++ b/llvm/test/TableGen/trydecode-emission2.td
@@ -31,27 +31,23 @@ def InstB : TestInstruction {
let hasCompleteDecoder = 0;
}
-// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
-// CHECK-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0
-// CHECK-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 22
-// CHECK-NEXT: /* 16 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 22
-// CHECK-NEXT: /* 22 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
-// CHECK-NEXT: /* 26 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
+// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 2, 1, 0,
+// CHECK-NEXT: /* 4 */ MCD::OPC_CheckFieldOrFail, 5, 3, 0,
+// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 20
+// CHECK-NEXT: /* 14 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 20
+// CHECK-NEXT: /* 20 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
+// CHECK-NEXT: /* 24 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
// CHECK-NEXT: };
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
-// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
-// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
-// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-LARGE-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 24
-// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 24
-// CHECK-LARGE-NEXT: /* 24 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
-// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
+// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 2, 1, 0,
+// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_CheckFieldOrFail, 5, 3, 0,
+// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 22
+// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 22
+// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
+// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
// CHECK-LARGE-NEXT: };
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission3.td b/llvm/test/TableGen/trydecode-emission3.td
index 039a37ba416f6..9696724ce2836 100644
--- a/llvm/test/TableGen/trydecode-emission3.td
+++ b/llvm/test/TableGen/trydecode-emission3.td
@@ -35,20 +35,18 @@ def InstB : TestInstruction {
let AsmString = "InstB";
}
-// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
-// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 17
-// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
+// CHECK-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 16
+// CHECK-NEXT: /* 10 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 16
+// CHECK-NEXT: /* 16 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
// CHECK-NEXT: };
// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
-// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
-// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 19
-// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
+// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 18
+// CHECK-LARGE-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
+// CHECK-LARGE-NEXT: /* 18 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
// CHECK-LARGE-NEXT: };
// CHECK-LARGE: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission4.td b/llvm/test/TableGen/trydecode-emission4.td
index d00d17501f16f..03cb635dbcaad 100644
--- a/llvm/test/TableGen/trydecode-emission4.td
+++ b/llvm/test/TableGen/trydecode-emission4.td
@@ -33,22 +33,19 @@ def InstB : TestInstruction {
let hasCompleteDecoder = 0;
}
-// CHECK: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
-// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 19
-// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 19
-// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 250, 3, 4, 0,
+// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 18
+// CHECK-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
+// CHECK-NEXT: /* 18 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
// CHECK-NEXT: };
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
-// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
-// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
-// CHECK-LARGE-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 21
-// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 21
-// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 250, 3, 4, 0,
+// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 20
+// CHECK-LARGE-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 20
+// CHECK-LARGE-NEXT: /* 20 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
// CHECK-LARGE-NEXT: };
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
-
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 9105d24f66d6d..ecdc48775c9c1 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -425,15 +425,6 @@ struct Filter {
Filter(ArrayRef<InstructionEncoding> Encodings,
ArrayRef<unsigned> EncodingIDs, unsigned StartBit, unsigned NumBits);
- bool hasSingleFilteredID() const {
- return FilteredIDs.size() == 1 && FilteredIDs.begin()->second.size() == 1;
- }
-
- unsigned getSingletonEncodingID() const {
- assert(hasSingleFilteredID());
- return FilteredIDs.begin()->second.front();
- }
-
// Returns the number of fanout produced by the filter. More fanout implies
// the filter distinguishes more categories of instructions.
unsigned usefulness() const;
@@ -679,14 +670,6 @@ void FilterChooser::applyFilter(const Filter &F) {
FilterBits, *this);
}
- // No need to recurse for a singleton filtered instruction.
- // See also Filter::emit*().
- if (F.hasSingleFilteredID()) {
- SingletonEncodingID = F.getSingletonEncodingID();
- assert(VariableFC && "Shouldn't have created a filter for one encoding!");
- return;
- }
-
// Otherwise, create sub choosers.
for (const auto &[FilterVal, InferiorEncodingIDs] : F.FilteredIDs) {
// Create a new filter by inserting the field bits into the parent filter.
@@ -1646,6 +1629,8 @@ void FilterChooser::dump() const {
}
void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
+ DecoderTable &Table = TableInfo.Table;
+
// If there are other encodings that could match if those with all bits
// known don't, enter a scope so that they have a chance.
if (FC.VariableFC)
@@ -1657,9 +1642,23 @@ void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
// fully defined, but we still need to check if the remaining (unfiltered)
// bits are valid for this encoding. We also need to check predicates etc.
emitSingletonTableEntry(FC);
+ } else if (FC.FilterChooserMap.size() == 1) {
+ // If there is only one possible field value, emit a combined OPC_CheckField
+ // instead of OPC_ExtractField + OPC_FilterValue.
+ const auto &[FilterVal, Delegate] = *FC.FilterChooserMap.begin();
+ Table.insertOpcode(!TableInfo.isOutermostScope()
+ ? MCD::OPC_CheckField
+ : MCD::OPC_CheckFieldOrFail);
+ Table.insertULEB128(FC.StartBit);
+ Table.insertUInt8(FC.NumBits);
+ Table.insertULEB128(FilterVal);
+ if (!TableInfo.isOutermostScope())
+ TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
+
+ // Emit table entries for the only case.
+ emitTableEntries(*Delegate);
} else {
// The general case: emit a switch over the field value.
- DecoderTable &Table = TableInfo.Table;
Table.insertOpcode(MCD::OPC_ExtractField);
Table.insertULEB128(FC.StartBit);
Table.insertUInt8(FC.NumBits);
More information about the llvm-commits
mailing list