-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[TableGen][DecoderEmitter] Calculate encoding bits once #154026
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TableGen][DecoderEmitter] Calculate encoding bits once #154026
Conversation
|
@llvm/pr-subscribers-tablegen Author: Sergei Barannikov (s-barannikov) Changes
Full diff: https://github.com/llvm/llvm-project/pull/154026.diff 1 Files Affected:
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 11d06d1613e89..64149a3841573 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -209,6 +209,7 @@ struct EncodingAndInst {
const Record *EncodingDef;
const CodeGenInstruction *Inst;
StringRef HwModeName;
+ std::vector<struct BitValue> EncodingBits;
EncodingAndInst(const Record *EncodingDef, const CodeGenInstruction *Inst,
StringRef HwModeName = "")
@@ -348,6 +349,26 @@ static const BitsInit &getBitsField(const Record &Def, StringRef FieldName) {
// Representation of the instruction to work on.
typedef std::vector<BitValue> insn_t;
+// Populates the insn given the uid.
+static insn_t getEncodingBits(const Record *EncodingDef, unsigned BitWidth) {
+ const BitsInit &Bits = getBitsField(*EncodingDef, "Inst");
+ insn_t Insn(std::max(BitWidth, Bits.getNumBits()), BitValue::BIT_UNSET);
+ // We may have a SoftFail bitmask, which specifies a mask where an encoding
+ // may differ from the value in "Inst" and yet still be valid, but the
+ // disassembler should return SoftFail instead of Success.
+ //
+ // This is used for marking UNPREDICTABLE instructions in the ARM world.
+ const RecordVal *RV = EncodingDef->getValue("SoftFail");
+ const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
+ for (unsigned i = 0; i < Bits.getNumBits(); ++i) {
+ if (SFBits && BitValue(*SFBits, i) == BitValue::BIT_TRUE)
+ Insn[i] = BitValue::BIT_UNSET;
+ else
+ Insn[i] = BitValue(Bits, i);
+ }
+ return Insn;
+}
+
/// Extracts a NumBits long field from Insn, starting from StartBit.
/// Returns the value of the field if all bits are well-known,
/// otherwise std::nullopt.
@@ -554,28 +575,11 @@ class FilterChooser {
unsigned getBitWidth() const { return BitWidth; }
-protected:
- // Populates the insn given the uid.
- insn_t insnWithID(unsigned Opcode) const {
- const Record *EncodingDef = AllInstructions[Opcode].EncodingDef;
- const BitsInit &Bits = getBitsField(*EncodingDef, "Inst");
- insn_t Insn(std::max(BitWidth, Bits.getNumBits()), BitValue::BIT_UNSET);
- // We may have a SoftFail bitmask, which specifies a mask where an encoding
- // may differ from the value in "Inst" and yet still be valid, but the
- // disassembler should return SoftFail instead of Success.
- //
- // This is used for marking UNPREDICTABLE instructions in the ARM world.
- const RecordVal *RV = EncodingDef->getValue("SoftFail");
- const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
- for (unsigned i = 0; i < Bits.getNumBits(); ++i) {
- if (SFBits && BitValue(*SFBits, i) == BitValue::BIT_TRUE)
- Insn[i] = BitValue::BIT_UNSET;
- else
- Insn[i] = BitValue(Bits, i);
- }
- return Insn;
+ ArrayRef<BitValue> getEncodingBits(unsigned EncodingID) const {
+ return AllInstructions[EncodingID].EncodingBits;
}
+protected:
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
void dumpFilterArray(raw_ostream &OS, ArrayRef<BitValue> Filter) const;
@@ -669,7 +673,7 @@ Filter::Filter(const FilterChooser &owner, unsigned startBit, unsigned numBits)
for (const auto &OpcPair : Owner.Opcodes) {
// Populates the insn given the uid.
- insn_t Insn = Owner.insnWithID(OpcPair.EncodingID);
+ ArrayRef<BitValue> Insn = Owner.getEncodingBits(OpcPair.EncodingID);
// Scans the segment for possibly well-specified encoding bits.
std::optional<uint64_t> Field = fieldFromInsn(Insn, StartBit, NumBits);
@@ -1420,7 +1424,7 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
// Emits table entries to decode the singleton.
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
EncodingIDAndOpcode Opc) const {
- insn_t Insn = insnWithID(Opc.EncodingID);
+ ArrayRef<BitValue> Insn = getEncodingBits(Opc.EncodingID);
// Look for islands of undecoded bits of the singleton.
std::vector<Island> Islands = getIslands(Insn);
@@ -1524,7 +1528,7 @@ bool FilterChooser::filterProcessor(ArrayRef<bitAttr_t> BitAttrs,
assert(Opcodes.size() == 3);
for (const auto &Opcode : Opcodes) {
- insn_t Insn = insnWithID(Opcode.EncodingID);
+ ArrayRef<BitValue> Insn = getEncodingBits(Opcode.EncodingID);
// Look for islands of undecoded bits of any instruction.
std::vector<Island> Islands = getIslands(Insn);
@@ -1713,7 +1717,7 @@ void FilterChooser::doFilter() {
BitAttrs[BitIndex] = ATTR_FILTERED;
for (const EncodingIDAndOpcode &OpcPair : Opcodes) {
- insn_t EncodingBits = insnWithID(OpcPair.EncodingID);
+ ArrayRef<BitValue> EncodingBits = getEncodingBits(OpcPair.EncodingID);
for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
switch (BitAttrs[BitIndex]) {
@@ -2579,10 +2583,17 @@ namespace {
unsigned OpcodeMask = 0;
for (const auto &[NSAndByteSize, EncodingIDs] : OpcMap) {
const std::string &DecoderNamespace = NSAndByteSize.first;
- const unsigned BitWidth = 8 * NSAndByteSize.second;
+ unsigned BitWidth = IsVarLenInst ? MaxInstLen : 8 * NSAndByteSize.second;
+
+ // Populate encoding bits in this group of encodings.
+ for (EncodingIDAndOpcode OpcPair : EncodingIDs) {
+ EncodingAndInst &Enc = NumberedEncodings[OpcPair.EncodingID];
+ assert(Enc.EncodingBits.empty() && "Already populated?");
+ Enc.EncodingBits = getEncodingBits(Enc.EncodingDef, BitWidth);
+ }
+
// Emit the decoder for this namespace+width combination.
- FilterChooser FC(NumberedEncodings, EncodingIDs, Operands,
- IsVarLenInst ? MaxInstLen : BitWidth, this);
+ FilterChooser FC(NumberedEncodings, EncodingIDs, Operands, BitWidth, this);
// The decode table is cleared for each top level decoder function. The
// predicates and decoders themselves, however, are shared across all
|
8ce1ca3 to
988a3dd
Compare
This comment was marked as outdated.
This comment was marked as outdated.
6b0124d to
1111145
Compare
a8bce78 to
13b97a3
Compare
`insnWithID` is called multiple times for the same encoding ID. Call it once and store the result in `NumberedEncodings`. Also, give the method a more meaningful name.
13b97a3 to
983d8be
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Parse the
InstandSoftFieldfields once and store them inInstructionEncodingso that we don't parse them every timegetMandatoryEncodingBits()is called.