Skip to content

Commit 45f6c50

Browse files
authored
[TableGen][DecoderEmitter] Decode operands with "all zeros" encoding (#158163)
Follow-up to #156358. The original change didn't take into account operands with "all zeros" encoding, now fixed.
1 parent 93a1470 commit 45f6c50

File tree

3 files changed

+88
-71
lines changed

3 files changed

+88
-71
lines changed

llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s
2+
3+
include "llvm/Target/Target.td"
4+
5+
def R0 : Register<"r0">;
6+
def RC : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
7+
8+
def MyInstrInfo : InstrInfo;
9+
10+
def MyTarget : Target {
11+
let InstructionSet = MyInstrInfo;
12+
}
13+
14+
// CHECK-LABEL: case 0:
15+
// CHECK-NEXT: if (!Check(S, DecodeRCRegisterClass(MI, Decoder)))
16+
// CHECK-NEXT: return MCDisassembler::Fail;
17+
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 2, 4);
18+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
19+
// CHECK-NEXT: tmp = 0x0;
20+
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 0, 2), 0, 2);
21+
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 6, 2), 2, 2);
22+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
23+
// CHECK-NEXT: tmp = 0x0;
24+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
25+
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 13, 2) << 1;
26+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
27+
// CHECK-NEXT: tmp = 0x0;
28+
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 17, 1), 1, 1);
29+
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 19, 1), 3, 1);
30+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
31+
// CHECK-NEXT: tmp = 0x5;
32+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
33+
// CHECK-NEXT: tmp = 0x2;
34+
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 26, 2), 2, 2);
35+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
36+
// CHECK-NEXT: tmp = 0xa;
37+
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 28, 1), 0, 1);
38+
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 30, 1), 2, 1);
39+
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
40+
// CHECK-NEXT: return S;
41+
42+
def I : Instruction {
43+
let OutOperandList = (outs RC:$op0);
44+
let InOperandList = (ins i32imm:$op1, i32imm:$op2, i32imm:$op3, i32imm:$op4,
45+
i32imm:$op5, i32imm:$op6, i32imm:$op7, i32imm:$op8);
46+
let Size = 4;
47+
bits<32> Inst;
48+
bits<0> op0; // no init, no variable parts
49+
bits<4> op1; // no init, 1 variable part
50+
bits<4> op2; // no init, 2 variable parts
51+
bits<4> op3 = 0b0000; // zero init, no variable parts
52+
bits<4> op4 = {0, ?, ?, 0}; // zero init, 1 variable part
53+
bits<4> op5 = {?, 0, ?, 0}; // zero init, 2 variable parts
54+
bits<4> op6 = 0b0101; // non-zero init, no variable parts
55+
bits<4> op7 = {?, ?, 1, 0}; // non-zero init, 1 variable part
56+
bits<4> op8 = {1, ?, 1, ?}; // non-zero init, 2 variable parts
57+
let Inst{5...2} = op1;
58+
let Inst{1...0} = op2{1...0};
59+
let Inst{7...6} = op2{3...2};
60+
let Inst{11...8} = op3;
61+
let Inst{15...12} = op4;
62+
let Inst{19...16} = op5;
63+
let Inst{23...20} = op6;
64+
let Inst{27...24} = op7;
65+
let Inst{31...28} = op8;
66+
}

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "llvm/Support/CommandLine.h"
3434
#include "llvm/Support/Debug.h"
3535
#include "llvm/Support/ErrorHandling.h"
36+
#include "llvm/Support/Format.h"
3637
#include "llvm/Support/FormatVariadic.h"
3738
#include "llvm/Support/FormattedStream.h"
3839
#include "llvm/Support/KnownBits.h"
@@ -169,8 +170,6 @@ struct OperandInfo {
169170
Fields.emplace_back(Base, Width, Offset);
170171
}
171172

172-
unsigned numFields() const { return Fields.size(); }
173-
174173
ArrayRef<EncodingField> fields() const { return Fields; }
175174
};
176175

@@ -1104,31 +1103,29 @@ void DecoderTableBuilder::emitBinaryParser(raw_ostream &OS, indent Indent,
11041103
return;
11051104
}
11061105

1107-
if (OpInfo.Fields.empty() && OpInfo.InitValue && IgnoreFullyDefinedOperands)
1108-
return;
1109-
1110-
// We need to construct the encoding of the operand from pieces if it is not
1111-
// encoded sequentially or has a non-zero constant part in the encoding.
1112-
bool UseInsertBits = OpInfo.numFields() > 1 || OpInfo.InitValue.value_or(0);
1113-
1114-
if (UseInsertBits) {
1115-
OS << Indent << "tmp = 0x";
1116-
OS.write_hex(OpInfo.InitValue.value_or(0));
1117-
OS << ";\n";
1118-
}
1119-
1120-
for (const auto &[Base, Width, Offset] : OpInfo.fields()) {
1121-
OS << Indent;
1122-
if (UseInsertBits)
1123-
OS << "insertBits(tmp, ";
1124-
else
1125-
OS << "tmp = ";
1126-
OS << "fieldFromInstruction(insn, " << Base << ", " << Width << ')';
1127-
if (UseInsertBits)
1128-
OS << ", " << Offset << ", " << Width << ')';
1129-
else if (Offset != 0)
1106+
if (OpInfo.fields().empty()) {
1107+
// Only a constant part. The old behavior is to not decode this operand.
1108+
if (IgnoreFullyDefinedOperands)
1109+
return;
1110+
// Initialize `tmp` with the constant part.
1111+
OS << Indent << "tmp = " << format_hex(*OpInfo.InitValue, 0) << ";\n";
1112+
} else if (OpInfo.fields().size() == 1 && !OpInfo.InitValue.value_or(0)) {
1113+
// One variable part and no/zero constant part. Initialize `tmp` with the
1114+
// variable part.
1115+
auto [Base, Width, Offset] = OpInfo.fields().front();
1116+
OS << Indent << "tmp = fieldFromInstruction(insn, " << Base << ", " << Width
1117+
<< ')';
1118+
if (Offset)
11301119
OS << " << " << Offset;
11311120
OS << ";\n";
1121+
} else {
1122+
// General case. Initialize `tmp` with the constant part, if any, and
1123+
// insert the variable parts into it.
1124+
OS << Indent << "tmp = " << format_hex(OpInfo.InitValue.value_or(0), 0)
1125+
<< ";\n";
1126+
for (auto [Base, Width, Offset] : OpInfo.fields())
1127+
OS << Indent << "insertBits(tmp, fieldFromInstruction(insn, " << Base
1128+
<< ", " << Width << "), " << Offset << ", " << Width << ");\n";
11321129
}
11331130

11341131
StringRef Decoder = OpInfo.Decoder;

0 commit comments

Comments
 (0)