Skip to content

Commit cdc79e3

Browse files
authored
[TableGen][DecoderEmitter] Optimize single-case OPC_ExtractField (llvm#155414)
OPC_ExtractField followed by a single OPC_FilterValue is equivalent to OPC_CheckField. Optimize this relatively common case.
1 parent fbd2f47 commit cdc79e3

File tree

5 files changed

+53
-65
lines changed

5 files changed

+53
-65
lines changed

llvm/test/TableGen/trydecode-emission.td

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@ def InstB : TestInstruction {
3434
let hasCompleteDecoder = 0;
3535
}
3636

37-
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
38-
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
39-
// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
40-
// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 17
41-
// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
37+
// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
38+
// CHECK-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 16
39+
// CHECK-NEXT: /* 10 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 16
40+
// CHECK-NEXT: /* 16 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
4241
// CHECK-NEXT: };
4342

4443
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
@@ -47,11 +46,10 @@ def InstB : TestInstruction {
4746
// CHECK-NEXT: NumToSkip |= (*Ptr++) << 8;
4847
// CHECK-NEXT: return NumToSkip;
4948

50-
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
51-
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
52-
// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
53-
// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 19
54-
// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
49+
// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
50+
// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 18
51+
// CHECK-LARGE-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
52+
// CHECK-LARGE-NEXT: /* 18 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
5553
// CHECK-LARGE-NEXT: };
5654

5755
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }

llvm/test/TableGen/trydecode-emission2.td

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,27 +31,23 @@ def InstB : TestInstruction {
3131
let hasCompleteDecoder = 0;
3232
}
3333

34-
// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
35-
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
36-
// CHECK-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
37-
// CHECK-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0
38-
// CHECK-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 22
39-
// CHECK-NEXT: /* 16 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 22
40-
// CHECK-NEXT: /* 22 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
41-
// CHECK-NEXT: /* 26 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
34+
// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 2, 1, 0,
35+
// CHECK-NEXT: /* 4 */ MCD::OPC_CheckFieldOrFail, 5, 3, 0,
36+
// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 20
37+
// CHECK-NEXT: /* 14 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 20
38+
// CHECK-NEXT: /* 20 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
39+
// CHECK-NEXT: /* 24 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
4240
// CHECK-NEXT: };
4341

4442
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
4543
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
4644

47-
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
48-
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
49-
// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
50-
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0,
51-
// CHECK-LARGE-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 24
52-
// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 24
53-
// CHECK-LARGE-NEXT: /* 24 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
54-
// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
45+
// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 2, 1, 0,
46+
// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_CheckFieldOrFail, 5, 3, 0,
47+
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 22
48+
// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 22
49+
// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
50+
// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
5551
// CHECK-LARGE-NEXT: };
5652

5753
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }

llvm/test/TableGen/trydecode-emission3.td

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,18 @@ def InstB : TestInstruction {
3535
let AsmString = "InstB";
3636
}
3737

38-
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
39-
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
40-
// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
41-
// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 17
42-
// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
38+
// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
39+
// CHECK-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 16
40+
// CHECK-NEXT: /* 10 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 16
41+
// CHECK-NEXT: /* 16 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
4342
// CHECK-NEXT: };
4443

4544
// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
4645

47-
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
48-
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
49-
// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
50-
// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 19
51-
// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
46+
// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 4, 4, 0,
47+
// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 18
48+
// CHECK-LARGE-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
49+
// CHECK-LARGE-NEXT: /* 18 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
5250
// CHECK-LARGE-NEXT: };
5351

5452
// CHECK-LARGE: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }

llvm/test/TableGen/trydecode-emission4.td

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,19 @@ def InstB : TestInstruction {
3333
let hasCompleteDecoder = 0;
3434
}
3535

36-
// CHECK: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
37-
// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
38-
// CHECK-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 19
39-
// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 19
40-
// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
36+
// CHECK: /* 0 */ MCD::OPC_CheckFieldOrFail, 250, 3, 4, 0,
37+
// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 18
38+
// CHECK-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
39+
// CHECK-NEXT: /* 18 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
4140
// CHECK-NEXT: };
4241

4342
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
4443

4544

46-
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
47-
// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
48-
// CHECK-LARGE-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 21
49-
// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 21
50-
// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
45+
// CHECK-LARGE: /* 0 */ MCD::OPC_CheckFieldOrFail, 250, 3, 4, 0,
46+
// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 20
47+
// CHECK-LARGE-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 20
48+
// CHECK-LARGE-NEXT: /* 20 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
5149
// CHECK-LARGE-NEXT: };
5250

5351
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
54-

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,6 @@ struct Filter {
425425
Filter(ArrayRef<InstructionEncoding> Encodings,
426426
ArrayRef<unsigned> EncodingIDs, unsigned StartBit, unsigned NumBits);
427427

428-
bool hasSingleFilteredID() const {
429-
return FilteredIDs.size() == 1 && FilteredIDs.begin()->second.size() == 1;
430-
}
431-
432-
unsigned getSingletonEncodingID() const {
433-
assert(hasSingleFilteredID());
434-
return FilteredIDs.begin()->second.front();
435-
}
436-
437428
// Returns the number of fanout produced by the filter. More fanout implies
438429
// the filter distinguishes more categories of instructions.
439430
unsigned usefulness() const;
@@ -679,14 +670,6 @@ void FilterChooser::applyFilter(const Filter &F) {
679670
FilterBits, *this);
680671
}
681672

682-
// No need to recurse for a singleton filtered instruction.
683-
// See also Filter::emit*().
684-
if (F.hasSingleFilteredID()) {
685-
SingletonEncodingID = F.getSingletonEncodingID();
686-
assert(VariableFC && "Shouldn't have created a filter for one encoding!");
687-
return;
688-
}
689-
690673
// Otherwise, create sub choosers.
691674
for (const auto &[FilterVal, InferiorEncodingIDs] : F.FilteredIDs) {
692675
// Create a new filter by inserting the field bits into the parent filter.
@@ -1646,6 +1629,8 @@ void FilterChooser::dump() const {
16461629
}
16471630

16481631
void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
1632+
DecoderTable &Table = TableInfo.Table;
1633+
16491634
// If there are other encodings that could match if those with all bits
16501635
// known don't, enter a scope so that they have a chance.
16511636
if (FC.VariableFC)
@@ -1657,9 +1642,23 @@ void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
16571642
// fully defined, but we still need to check if the remaining (unfiltered)
16581643
// bits are valid for this encoding. We also need to check predicates etc.
16591644
emitSingletonTableEntry(FC);
1645+
} else if (FC.FilterChooserMap.size() == 1) {
1646+
// If there is only one possible field value, emit a combined OPC_CheckField
1647+
// instead of OPC_ExtractField + OPC_FilterValue.
1648+
const auto &[FilterVal, Delegate] = *FC.FilterChooserMap.begin();
1649+
Table.insertOpcode(!TableInfo.isOutermostScope()
1650+
? MCD::OPC_CheckField
1651+
: MCD::OPC_CheckFieldOrFail);
1652+
Table.insertULEB128(FC.StartBit);
1653+
Table.insertUInt8(FC.NumBits);
1654+
Table.insertULEB128(FilterVal);
1655+
if (!TableInfo.isOutermostScope())
1656+
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
1657+
1658+
// Emit table entries for the only case.
1659+
emitTableEntries(*Delegate);
16601660
} else {
16611661
// The general case: emit a switch over the field value.
1662-
DecoderTable &Table = TableInfo.Table;
16631662
Table.insertOpcode(MCD::OPC_ExtractField);
16641663
Table.insertULEB128(FC.StartBit);
16651664
Table.insertUInt8(FC.NumBits);

0 commit comments

Comments
 (0)