diff options
Diffstat (limited to 'llvm/utils/TableGen/FixedLenDecoderEmitter.cpp')
-rw-r--r-- | llvm/utils/TableGen/FixedLenDecoderEmitter.cpp | 109 |
1 files changed, 60 insertions, 49 deletions
diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 01b39df055ad..c5dd1e626696 100644 --- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -973,7 +973,13 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders, << "Address, const void *Decoder, bool &DecodeComplete) {\n"; Indentation += 2; OS.indent(Indentation) << "DecodeComplete = true;\n"; - OS.indent(Indentation) << "InsnType tmp;\n"; + // TODO: When InsnType is large, using uint64_t limits all fields to 64 bits + // It would be better for emitBinaryParser to use a 64-bit tmp whenever + // possible but fall back to an InsnType-sized tmp for truly large fields. + OS.indent(Indentation) << "using TmpType = " + "std::conditional_t<std::is_integral<InsnType>::" + "value, InsnType, uint64_t>;\n"; + OS.indent(Indentation) << "TmpType tmp;\n"; OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; unsigned Index = 0; @@ -1107,18 +1113,24 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, bool &OpHasCompleteDecoder) const { const std::string &Decoder = OpInfo.Decoder; - if (OpInfo.numFields() != 1 || OpInfo.InitValue != 0) { + bool UseInsertBits = OpInfo.numFields() != 1 || OpInfo.InitValue != 0; + + if (UseInsertBits) { o.indent(Indentation) << "tmp = 0x"; o.write_hex(OpInfo.InitValue); o << ";\n"; } for (const EncodingField &EF : OpInfo) { - o.indent(Indentation) << "tmp "; - if (OpInfo.numFields() != 1 || OpInfo.InitValue != 0) o << '|'; - o << "= fieldFromInstruction" - << "(insn, " << EF.Base << ", " << EF.Width << ')'; - if (OpInfo.numFields() != 1 || EF.Offset != 0) + o.indent(Indentation); + if (UseInsertBits) + o << "insertBits(tmp, "; + else + o << "tmp = "; + o << "fieldFromInstruction(insn, " << EF.Base << ", " << EF.Width << ')'; + if (UseInsertBits) + o << ", " << EF.Offset << ", " << EF.Width << ')'; + else if (EF.Offset != 0) o << " << " << EF.Offset; o << ";\n"; } @@ -1210,14 +1222,9 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, if (IsOr) o << "("; - bool First = true; + ListSeparator LS(IsOr ? " || " : " && "); for (auto *Arg : D->getArgs()) { - if (!First) { - if (IsOr) - o << " || "; - else - o << " && "; - } + o << LS; if (auto *NotArg = dyn_cast<DagInit>(Arg)) { if (NotArg->getOperator()->getAsString() != "not" || NotArg->getNumArgs() != 1) @@ -1230,8 +1237,6 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, PrintFatalError(Pred->getLoc(), "Invalid AssemblerCondDag!"); o << "Bits[" << Emitter->PredicateNamespace << "::" << Arg->getAsString() << "]"; - - First = false; } if (IsOr) @@ -1250,7 +1255,7 @@ bool FilterChooser::doesOpcodeNeedPredicate(unsigned Opc) const { if (!Pred->getValue("AssemblerMatcherPredicate")) continue; - if (dyn_cast<DagInit>(Pred->getValue("AssemblerCondDag")->getValue())) + if (isa<DagInit>(Pred->getValue("AssemblerCondDag")->getValue())) return true; } return false; @@ -1501,13 +1506,13 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { if (AllowMixed && !Greedy) { assert(numInstructions == 3); - for (unsigned i = 0; i < Opcodes.size(); ++i) { + for (auto Opcode : Opcodes) { std::vector<unsigned> StartBits; std::vector<unsigned> EndBits; std::vector<uint64_t> FieldVals; insn_t Insn; - insnWithID(Insn, Opcodes[i].EncodingID); + insnWithID(Insn, Opcode.EncodingID); // Look for islands of undecoded bits of any instruction. if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) { @@ -1769,13 +1774,13 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const { dumpStack(errs(), "\t\t"); - for (unsigned i = 0; i < Opcodes.size(); ++i) { + for (auto Opcode : Opcodes) { errs() << '\t'; - emitNameWithID(errs(), Opcodes[i].EncodingID); + emitNameWithID(errs(), Opcode.EncodingID); errs() << " "; dumpBits( errs(), - getBitsField(*AllInstructions[Opcodes[i].EncodingID].EncodingDef, "Inst")); + getBitsField(*AllInstructions[Opcode.EncodingID].EncodingDef, "Inst")); errs() << '\n'; } } @@ -2149,27 +2154,22 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) { OS << "// Helper functions for extracting fields from encoded instructions.\n" << "// InsnType must either be integral or an APInt-like object that " "must:\n" - << "// * Have a static const max_size_in_bits equal to the number of bits " - "in the\n" - << "// encoding.\n" << "// * be default-constructible and copy-constructible\n" << "// * be constructible from a uint64_t\n" << "// * be constructible from an APInt (this can be private)\n" - << "// * Support getBitsSet(loBit, hiBit)\n" - << "// * be convertible to uint64_t\n" - << "// * Support the ~, &, ==, !=, and |= operators with other objects of " + << "// * Support insertBits(bits, startBit, numBits)\n" + << "// * Support extractBitsAsZExtValue(numBits, startBit)\n" + << "// * be convertible to bool\n" + << "// * Support the ~, &, ==, and != operators with other objects of " "the same type\n" - << "// * Support shift (<<, >>) with signed and unsigned integers on the " - "RHS\n" << "// * Support put (<<) to raw_ostream&\n" << "template <typename InsnType>\n" << "#if defined(_MSC_VER) && !defined(__clang__)\n" << "__declspec(noinline)\n" << "#endif\n" - << "static InsnType fieldFromInstruction(InsnType insn, unsigned " - "startBit,\n" - << " unsigned numBits, " - "std::true_type) {\n" + << "static std::enable_if_t<std::is_integral<InsnType>::value, InsnType>\n" + << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n" + << " unsigned numBits) {\n" << " assert(startBit + numBits <= 64 && \"Cannot support >64-bit " "extractions!\");\n" << " assert(startBit + numBits <= (sizeof(InsnType) * 8) &&\n" @@ -2183,22 +2183,32 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) { << "}\n" << "\n" << "template <typename InsnType>\n" - << "static InsnType fieldFromInstruction(InsnType insn, unsigned " - "startBit,\n" - << " unsigned numBits, " - "std::false_type) {\n" - << " assert(startBit + numBits <= InsnType::max_size_in_bits && " - "\"Instruction field out of bounds!\");\n" - << " InsnType fieldMask = InsnType::getBitsSet(0, numBits);\n" - << " return (insn >> startBit) & fieldMask;\n" + << "static std::enable_if_t<!std::is_integral<InsnType>::value, " + "uint64_t>\n" + << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n" + << " unsigned numBits) {\n" + << " return insn.extractBitsAsZExtValue(numBits, startBit);\n" + << "}\n\n"; +} + +// emitInsertBits - Emit the templated helper function insertBits(). +static void emitInsertBits(formatted_raw_ostream &OS) { + OS << "// Helper function for inserting bits extracted from an encoded " + "instruction into\n" + << "// a field.\n" + << "template <typename InsnType>\n" + << "static std::enable_if_t<std::is_integral<InsnType>::value>\n" + << "insertBits(InsnType &field, InsnType bits, unsigned startBit, " + "unsigned numBits) {\n" + << " assert(startBit + numBits <= sizeof field * 8);\n" + << " field |= (InsnType)bits << startBit;\n" << "}\n" << "\n" << "template <typename InsnType>\n" - << "static InsnType fieldFromInstruction(InsnType insn, unsigned " - "startBit,\n" - << " unsigned numBits) {\n" - << " return fieldFromInstruction(insn, startBit, numBits, " - "std::is_integral<InsnType>());\n" + << "static std::enable_if_t<!std::is_integral<InsnType>::value>\n" + << "insertBits(InsnType &field, uint64_t bits, unsigned startBit, " + "unsigned numBits) {\n" + << " field.insertBits(bits, startBit, numBits);\n" << "}\n\n"; } @@ -2401,6 +2411,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { OS << "namespace llvm {\n\n"; emitFieldFromInstruction(OS); + emitInsertBits(OS); Target.reverseBitsForLittleEndianEncoding(); @@ -2418,7 +2429,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { const CodeGenHwModes &HWM = Target.getHwModes(); EncodingInfoByHwMode EBM(DI->getDef(), HWM); - for (auto &KV : EBM.Map) + for (auto &KV : EBM) HwModeNames.insert(HWM.getMode(KV.first).Name); } } @@ -2436,7 +2447,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { const CodeGenHwModes &HWM = Target.getHwModes(); EncodingInfoByHwMode EBM(DI->getDef(), HWM); - for (auto &KV : EBM.Map) { + for (auto &KV : EBM) { NumberedEncodings.emplace_back(KV.second, NumberedInstruction, HWM.getMode(KV.first).Name); HwModeNames.insert(HWM.getMode(KV.first).Name); |