diff options
Diffstat (limited to 'contrib/llvm/utils')
45 files changed, 3647 insertions, 3209 deletions
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp deleted file mode 100644 index 145b96df98e2..000000000000 --- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp +++ /dev/null @@ -1,1790 +0,0 @@ -//===------------ ARMDecoderEmitter.cpp - Decoder Generator ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is part of the ARM Disassembler. -// It contains the tablegen backend that emits the decoder functions for ARM and -// Thumb. The disassembler core includes the auto-generated file, invokes the -// decoder functions, and builds up the MCInst based on the decoded Opcode. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "arm-decoder-emitter" - -#include "ARMDecoderEmitter.h" -#include "CodeGenTarget.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/TableGen/Record.h" - -#include <vector> -#include <map> -#include <string> - -using namespace llvm; - -///////////////////////////////////////////////////// -// // -// Enums and Utilities for ARM Instruction Format // -// // -///////////////////////////////////////////////////// - -#define ARM_FORMATS \ - ENTRY(ARM_FORMAT_PSEUDO, 0) \ - ENTRY(ARM_FORMAT_MULFRM, 1) \ - ENTRY(ARM_FORMAT_BRFRM, 2) \ - ENTRY(ARM_FORMAT_BRMISCFRM, 3) \ - ENTRY(ARM_FORMAT_DPFRM, 4) \ - ENTRY(ARM_FORMAT_DPSOREGREGFRM, 5) \ - ENTRY(ARM_FORMAT_LDFRM, 6) \ - ENTRY(ARM_FORMAT_STFRM, 7) \ - ENTRY(ARM_FORMAT_LDMISCFRM, 8) \ - ENTRY(ARM_FORMAT_STMISCFRM, 9) \ - ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \ - ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \ - ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \ - ENTRY(ARM_FORMAT_SATFRM, 13) \ - ENTRY(ARM_FORMAT_EXTFRM, 14) \ - ENTRY(ARM_FORMAT_VFPUNARYFRM, 15) \ - ENTRY(ARM_FORMAT_VFPBINARYFRM, 16) \ - ENTRY(ARM_FORMAT_VFPCONV1FRM, 17) \ - ENTRY(ARM_FORMAT_VFPCONV2FRM, 18) \ - ENTRY(ARM_FORMAT_VFPCONV3FRM, 19) \ - ENTRY(ARM_FORMAT_VFPCONV4FRM, 20) \ - ENTRY(ARM_FORMAT_VFPCONV5FRM, 21) \ - ENTRY(ARM_FORMAT_VFPLDSTFRM, 22) \ - ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \ - ENTRY(ARM_FORMAT_VFPMISCFRM, 24) \ - ENTRY(ARM_FORMAT_THUMBFRM, 25) \ - ENTRY(ARM_FORMAT_MISCFRM, 26) \ - ENTRY(ARM_FORMAT_NEONGETLNFRM, 27) \ - ENTRY(ARM_FORMAT_NEONSETLNFRM, 28) \ - ENTRY(ARM_FORMAT_NEONDUPFRM, 29) \ - ENTRY(ARM_FORMAT_NLdSt, 30) \ - ENTRY(ARM_FORMAT_N1RegModImm, 31) \ - ENTRY(ARM_FORMAT_N2Reg, 32) \ - ENTRY(ARM_FORMAT_NVCVT, 33) \ - ENTRY(ARM_FORMAT_NVecDupLn, 34) \ - ENTRY(ARM_FORMAT_N2RegVecShL, 35) \ - ENTRY(ARM_FORMAT_N2RegVecShR, 36) \ - ENTRY(ARM_FORMAT_N3Reg, 37) \ - ENTRY(ARM_FORMAT_N3RegVecSh, 38) \ - ENTRY(ARM_FORMAT_NVecExtract, 39) \ - ENTRY(ARM_FORMAT_NVecMulScalar, 40) \ - ENTRY(ARM_FORMAT_NVTBL, 41) \ - ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42) - -// ARM instruction format specifies the encoding used by the instruction. -#define ENTRY(n, v) n = v, -typedef enum { - ARM_FORMATS - ARM_FORMAT_NA -} ARMFormat; -#undef ENTRY - -// Converts enum to const char*. -static const char *stringForARMFormat(ARMFormat form) { -#define ENTRY(n, v) case n: return #n; - switch(form) { - ARM_FORMATS - case ARM_FORMAT_NA: - default: - return ""; - } -#undef ENTRY -} - -enum { - IndexModeNone = 0, - IndexModePre = 1, - IndexModePost = 2, - IndexModeUpd = 3 -}; - -///////////////////////// -// // -// Utility functions // -// // -///////////////////////// - -/// byteFromBitsInit - Return the byte value from a BitsInit. -/// Called from getByteField(). -static uint8_t byteFromBitsInit(BitsInit &init) { - int width = init.getNumBits(); - - assert(width <= 8 && "Field is too large for uint8_t!"); - - int index; - uint8_t mask = 0x01; - - uint8_t ret = 0; - - for (index = 0; index < width; index++) { - if (static_cast<BitInit*>(init.getBit(index))->getValue()) - ret |= mask; - - mask <<= 1; - } - - return ret; -} - -static uint8_t getByteField(const Record &def, const char *str) { - BitsInit *bits = def.getValueAsBitsInit(str); - return byteFromBitsInit(*bits); -} - -static BitsInit &getBitsField(const Record &def, const char *str) { - BitsInit *bits = def.getValueAsBitsInit(str); - return *bits; -} - -/// sameStringExceptSuffix - Return true if the two strings differ only in RHS's -/// suffix. ("VST4d8", "VST4d8_UPD", "_UPD") as input returns true. -static -bool sameStringExceptSuffix(const StringRef LHS, const StringRef RHS, - const StringRef Suffix) { - - if (RHS.startswith(LHS) && RHS.endswith(Suffix)) - return RHS.size() == LHS.size() + Suffix.size(); - - return false; -} - -/// thumbInstruction - Determine whether we have a Thumb instruction. -/// See also ARMInstrFormats.td. -static bool thumbInstruction(uint8_t Form) { - return Form == ARM_FORMAT_THUMBFRM; -} - -// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system -// for a bit value. -// -// BIT_UNFILTERED is used as the init value for a filter position. It is used -// only for filter processings. -typedef enum { - BIT_TRUE, // '1' - BIT_FALSE, // '0' - BIT_UNSET, // '?' - BIT_UNFILTERED // unfiltered -} bit_value_t; - -static bool ValueSet(bit_value_t V) { - return (V == BIT_TRUE || V == BIT_FALSE); -} -static bool ValueNotSet(bit_value_t V) { - return (V == BIT_UNSET); -} -static int Value(bit_value_t V) { - return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1); -} -static bit_value_t bitFromBits(BitsInit &bits, unsigned index) { - if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index))) - return bit->getValue() ? BIT_TRUE : BIT_FALSE; - - // The bit is uninitialized. - return BIT_UNSET; -} -// Prints the bit value for each position. -static void dumpBits(raw_ostream &o, BitsInit &bits) { - unsigned index; - - for (index = bits.getNumBits(); index > 0; index--) { - switch (bitFromBits(bits, index - 1)) { - case BIT_TRUE: - o << "1"; - break; - case BIT_FALSE: - o << "0"; - break; - case BIT_UNSET: - o << "_"; - break; - default: - assert(0 && "unexpected return value from bitFromBits"); - } - } -} - -// Enums for the available target names. -typedef enum { - TARGET_ARM = 0, - TARGET_THUMB -} TARGET_NAME_t; - -// FIXME: Possibly auto-detected? -#define BIT_WIDTH 32 - -// Forward declaration. -class ARMFilterChooser; - -// Representation of the instruction to work on. -typedef bit_value_t insn_t[BIT_WIDTH]; - -/// Filter - Filter works with FilterChooser to produce the decoding tree for -/// the ISA. -/// -/// It is useful to think of a Filter as governing the switch stmts of the -/// decoding tree in a certain level. Each case stmt delegates to an inferior -/// FilterChooser to decide what further decoding logic to employ, or in another -/// words, what other remaining bits to look at. The FilterChooser eventually -/// chooses a best Filter to do its job. -/// -/// This recursive scheme ends when the number of Opcodes assigned to the -/// FilterChooser becomes 1 or if there is a conflict. A conflict happens when -/// the Filter/FilterChooser combo does not know how to distinguish among the -/// Opcodes assigned. -/// -/// An example of a conflict is -/// -/// Conflict: -/// 111101000.00........00010000.... -/// 111101000.00........0001........ -/// 1111010...00........0001........ -/// 1111010...00.................... -/// 1111010......................... -/// 1111............................ -/// ................................ -/// VST4q8a 111101000_00________00010000____ -/// VST4q8b 111101000_00________00010000____ -/// -/// The Debug output shows the path that the decoding tree follows to reach the -/// the conclusion that there is a conflict. VST4q8a is a vst4 to double-spaced -/// even registers, while VST4q8b is a vst4 to double-spaced odd regsisters. -/// -/// The encoding info in the .td files does not specify this meta information, -/// which could have been used by the decoder to resolve the conflict. The -/// decoder could try to decode the even/odd register numbering and assign to -/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a" -/// version and return the Opcode since the two have the same Asm format string. -class ARMFilter { -protected: - ARMFilterChooser *Owner; // points to the FilterChooser who owns this filter - unsigned StartBit; // the starting bit position - unsigned NumBits; // number of bits to filter - bool Mixed; // a mixed region contains both set and unset bits - - // Map of well-known segment value to the set of uid's with that value. - std::map<uint64_t, std::vector<unsigned> > FilteredInstructions; - - // Set of uid's with non-constant segment values. - std::vector<unsigned> VariableInstructions; - - // Map of well-known segment value to its delegate. - std::map<unsigned, ARMFilterChooser*> FilterChooserMap; - - // Number of instructions which fall under FilteredInstructions category. - unsigned NumFiltered; - - // Keeps track of the last opcode in the filtered bucket. - unsigned LastOpcFiltered; - - // Number of instructions which fall under VariableInstructions category. - unsigned NumVariable; - -public: - unsigned getNumFiltered() { return NumFiltered; } - unsigned getNumVariable() { return NumVariable; } - unsigned getSingletonOpc() { - assert(NumFiltered == 1); - return LastOpcFiltered; - } - // Return the filter chooser for the group of instructions without constant - // segment values. - ARMFilterChooser &getVariableFC() { - assert(NumFiltered == 1); - assert(FilterChooserMap.size() == 1); - return *(FilterChooserMap.find((unsigned)-1)->second); - } - - ARMFilter(const ARMFilter &f); - ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits, - bool mixed); - - ~ARMFilter(); - - // Divides the decoding task into sub tasks and delegates them to the - // inferior FilterChooser's. - // - // A special case arises when there's only one entry in the filtered - // instructions. In order to unambiguously decode the singleton, we need to - // match the remaining undecoded encoding bits against the singleton. - void recurse(); - - // Emit code to decode instructions given a segment or segments of bits. - void emit(raw_ostream &o, unsigned &Indentation); - - // Returns the number of fanout produced by the filter. More fanout implies - // the filter distinguishes more categories of instructions. - unsigned usefulness() const; -}; // End of class Filter - -// These are states of our finite state machines used in FilterChooser's -// filterProcessor() which produces the filter candidates to use. -typedef enum { - ATTR_NONE, - ATTR_FILTERED, - ATTR_ALL_SET, - ATTR_ALL_UNSET, - ATTR_MIXED -} bitAttr_t; - -/// ARMFilterChooser - FilterChooser chooses the best filter among a set of Filters -/// in order to perform the decoding of instructions at the current level. -/// -/// Decoding proceeds from the top down. Based on the well-known encoding bits -/// of instructions available, FilterChooser builds up the possible Filters that -/// can further the task of decoding by distinguishing among the remaining -/// candidate instructions. -/// -/// Once a filter has been chosen, it is called upon to divide the decoding task -/// into sub-tasks and delegates them to its inferior FilterChoosers for further -/// processings. -/// -/// It is useful to think of a Filter as governing the switch stmts of the -/// decoding tree. And each case is delegated to an inferior FilterChooser to -/// decide what further remaining bits to look at. -class ARMFilterChooser { - static TARGET_NAME_t TargetName; - -protected: - friend class ARMFilter; - - // Vector of codegen instructions to choose our filter. - const std::vector<const CodeGenInstruction*> &AllInstructions; - - // Vector of uid's for this filter chooser to work on. - const std::vector<unsigned> Opcodes; - - // Vector of candidate filters. - std::vector<ARMFilter> Filters; - - // Array of bit values passed down from our parent. - // Set to all BIT_UNFILTERED's for Parent == NULL. - bit_value_t FilterBitValues[BIT_WIDTH]; - - // Links to the FilterChooser above us in the decoding tree. - ARMFilterChooser *Parent; - - // Index of the best filter from Filters. - int BestIndex; - -public: - static void setTargetName(TARGET_NAME_t tn) { TargetName = tn; } - - ARMFilterChooser(const ARMFilterChooser &FC) : - AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), - Filters(FC.Filters), Parent(FC.Parent), BestIndex(FC.BestIndex) { - memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues)); - } - - ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts, - const std::vector<unsigned> &IDs) : - AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(NULL), - BestIndex(-1) { - for (unsigned i = 0; i < BIT_WIDTH; ++i) - FilterBitValues[i] = BIT_UNFILTERED; - - doFilter(); - } - - ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts, - const std::vector<unsigned> &IDs, - bit_value_t (&ParentFilterBitValues)[BIT_WIDTH], - ARMFilterChooser &parent) : - AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(&parent), - BestIndex(-1) { - for (unsigned i = 0; i < BIT_WIDTH; ++i) - FilterBitValues[i] = ParentFilterBitValues[i]; - - doFilter(); - } - - // The top level filter chooser has NULL as its parent. - bool isTopLevel() { return Parent == NULL; } - - // This provides an opportunity for target specific code emission. - void emitTopHook(raw_ostream &o); - - // Emit the top level typedef and decodeInstruction() function. - void emitTop(raw_ostream &o, unsigned &Indentation); - - // This provides an opportunity for target specific code emission after - // emitTop(). - void emitBot(raw_ostream &o, unsigned &Indentation); - -protected: - // Populates the insn given the uid. - void insnWithID(insn_t &Insn, unsigned Opcode) const { - if (AllInstructions[Opcode]->isPseudo) - return; - - BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst"); - - for (unsigned i = 0; i < BIT_WIDTH; ++i) - Insn[i] = bitFromBits(Bits, i); - - // Set Inst{21} to 1 (wback) when IndexModeBits == IndexModeUpd. - Record *R = AllInstructions[Opcode]->TheDef; - if (R->getValue("IndexModeBits") && - getByteField(*R, "IndexModeBits") == IndexModeUpd) - Insn[21] = BIT_TRUE; - } - - // Returns the record name. - const std::string &nameWithID(unsigned Opcode) const { - return AllInstructions[Opcode]->TheDef->getName(); - } - - // Populates the field of the insn given the start position and the number of - // consecutive bits to scan for. - // - // Returns false if there exists any uninitialized bit value in the range. - // Returns true, otherwise. - bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit, - unsigned NumBits) const; - - /// dumpFilterArray - dumpFilterArray prints out debugging info for the given - /// filter array as a series of chars. - void dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]); - - /// dumpStack - dumpStack traverses the filter chooser chain and calls - /// dumpFilterArray on each filter chooser up to the top level one. - void dumpStack(raw_ostream &o, const char *prefix); - - ARMFilter &bestFilter() { - assert(BestIndex != -1 && "BestIndex not set"); - return Filters[BestIndex]; - } - - // Called from Filter::recurse() when singleton exists. For debug purpose. - void SingletonExists(unsigned Opc); - - bool PositionFiltered(unsigned i) { - return ValueSet(FilterBitValues[i]); - } - - // Calculates the island(s) needed to decode the instruction. - // This returns a lit of undecoded bits of an instructions, for example, - // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be - // decoded bits in order to verify that the instruction matches the Opcode. - unsigned getIslands(std::vector<unsigned> &StartBits, - std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, - insn_t &Insn); - - // The purpose of this function is for the API client to detect possible - // Load/Store Coprocessor instructions. If the coprocessor number is of - // the instruction is either 10 or 11, the decoder should not report the - // instruction as LDC/LDC2/STC/STC2, but should match against Advanced SIMD or - // VFP instructions. - bool LdStCopEncoding1(unsigned Opc) { - const std::string &Name = nameWithID(Opc); - if (Name == "LDC_OFFSET" || Name == "LDC_OPTION" || - Name == "LDC_POST" || Name == "LDC_PRE" || - Name == "LDCL_OFFSET" || Name == "LDCL_OPTION" || - Name == "LDCL_POST" || Name == "LDCL_PRE" || - Name == "STC_OFFSET" || Name == "STC_OPTION" || - Name == "STC_POST" || Name == "STC_PRE" || - Name == "STCL_OFFSET" || Name == "STCL_OPTION" || - Name == "STCL_POST" || Name == "STCL_PRE") - return true; - else - return false; - } - - // Emits code to decode the singleton. Return true if we have matched all the - // well-known bits. - bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc); - - // Emits code to decode the singleton, and then to decode the rest. - void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - ARMFilter &Best); - - // Assign a single filter and run with it. - void runSingleFilter(ARMFilterChooser &owner, unsigned startBit, - unsigned numBit, bool mixed); - - // reportRegion is a helper function for filterProcessor to mark a region as - // eligible for use as a filter region. - void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex, - bool AllowMixed); - - // FilterProcessor scans the well-known encoding bits of the instructions and - // builds up a list of candidate filters. It chooses the best filter and - // recursively descends down the decoding tree. - bool filterProcessor(bool AllowMixed, bool Greedy = true); - - // Decides on the best configuration of filter(s) to use in order to decode - // the instructions. A conflict of instructions may occur, in which case we - // dump the conflict set to the standard error. - void doFilter(); - - // Emits code to decode our share of instructions. Returns true if the - // emitted code causes a return, which occurs if we know how to decode - // the instruction at this level or the instruction is not decodeable. - bool emit(raw_ostream &o, unsigned &Indentation); -}; - -/////////////////////////// -// // -// Filter Implmenetation // -// // -/////////////////////////// - -ARMFilter::ARMFilter(const ARMFilter &f) : - Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), - FilteredInstructions(f.FilteredInstructions), - VariableInstructions(f.VariableInstructions), - FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), - LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) { -} - -ARMFilter::ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits, - bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits), - Mixed(mixed) { - assert(StartBit + NumBits - 1 < BIT_WIDTH); - - NumFiltered = 0; - LastOpcFiltered = 0; - NumVariable = 0; - - for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) { - insn_t Insn; - - // Populates the insn given the uid. - Owner->insnWithID(Insn, Owner->Opcodes[i]); - - uint64_t Field; - // Scans the segment for possibly well-specified encoding bits. - bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits); - - if (ok) { - // The encoding bits are well-known. Lets add the uid of the - // instruction into the bucket keyed off the constant field value. - LastOpcFiltered = Owner->Opcodes[i]; - FilteredInstructions[Field].push_back(LastOpcFiltered); - ++NumFiltered; - } else { - // Some of the encoding bit(s) are unspecfied. This contributes to - // one additional member of "Variable" instructions. - VariableInstructions.push_back(Owner->Opcodes[i]); - ++NumVariable; - } - } - - assert((FilteredInstructions.size() + VariableInstructions.size() > 0) - && "Filter returns no instruction categories"); -} - -ARMFilter::~ARMFilter() { - std::map<unsigned, ARMFilterChooser*>::iterator filterIterator; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { - delete filterIterator->second; - } -} - -// Divides the decoding task into sub tasks and delegates them to the -// inferior FilterChooser's. -// -// A special case arises when there's only one entry in the filtered -// instructions. In order to unambiguously decode the singleton, we need to -// match the remaining undecoded encoding bits against the singleton. -void ARMFilter::recurse() { - std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator; - - bit_value_t BitValueArray[BIT_WIDTH]; - // Starts by inheriting our parent filter chooser's filter bit values. - memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray)); - - unsigned bitIndex; - - if (VariableInstructions.size()) { - // Conservatively marks each segment position as BIT_UNSET. - for (bitIndex = 0; bitIndex < NumBits; bitIndex++) - BitValueArray[StartBit + bitIndex] = BIT_UNSET; - - // Delegates to an inferior filter chooser for further processing on this - // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>( - (unsigned)-1, - new ARMFilterChooser(Owner->AllInstructions, - VariableInstructions, - BitValueArray, - *Owner) - )); - } - - // No need to recurse for a singleton filtered instruction. - // See also Filter::emit(). - if (getNumFiltered() == 1) { - //Owner->SingletonExists(LastOpcFiltered); - assert(FilterChooserMap.size() == 1); - return; - } - - // Otherwise, create sub choosers. - for (mapIterator = FilteredInstructions.begin(); - mapIterator != FilteredInstructions.end(); - mapIterator++) { - - // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. - for (bitIndex = 0; bitIndex < NumBits; bitIndex++) { - if (mapIterator->first & (1ULL << bitIndex)) - BitValueArray[StartBit + bitIndex] = BIT_TRUE; - else - BitValueArray[StartBit + bitIndex] = BIT_FALSE; - } - - // Delegates to an inferior filter chooser for further processing on this - // category of instructions. - FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>( - mapIterator->first, - new ARMFilterChooser(Owner->AllInstructions, - mapIterator->second, - BitValueArray, - *Owner) - )); - } -} - -// Emit code to decode instructions given a segment or segments of bits. -void ARMFilter::emit(raw_ostream &o, unsigned &Indentation) { - o.indent(Indentation) << "// Check Inst{"; - - if (NumBits > 1) - o << (StartBit + NumBits - 1) << '-'; - - o << StartBit << "} ...\n"; - - o.indent(Indentation) << "switch (fieldFromInstruction(insn, " - << StartBit << ", " << NumBits << ")) {\n"; - - std::map<unsigned, ARMFilterChooser*>::iterator filterIterator; - - bool DefaultCase = false; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { - - // Field value -1 implies a non-empty set of variable instructions. - // See also recurse(). - if (filterIterator->first == (unsigned)-1) { - DefaultCase = true; - - o.indent(Indentation) << "default:\n"; - o.indent(Indentation) << " break; // fallthrough\n"; - - // Closing curly brace for the switch statement. - // This is unconventional because we want the default processing to be - // performed for the fallthrough cases as well, i.e., when the "cases" - // did not prove a decoded instruction. - o.indent(Indentation) << "}\n"; - - } else - o.indent(Indentation) << "case " << filterIterator->first << ":\n"; - - // We arrive at a category of instructions with the same segment value. - // Now delegate to the sub filter chooser for further decodings. - // The case may fallthrough, which happens if the remaining well-known - // encoding bits do not match exactly. - if (!DefaultCase) { ++Indentation; ++Indentation; } - - bool finished = filterIterator->second->emit(o, Indentation); - // For top level default case, there's no need for a break statement. - if (Owner->isTopLevel() && DefaultCase) - break; - if (!finished) - o.indent(Indentation) << "break;\n"; - - if (!DefaultCase) { --Indentation; --Indentation; } - } - - // If there is no default case, we still need to supply a closing brace. - if (!DefaultCase) { - // Closing curly brace for the switch statement. - o.indent(Indentation) << "}\n"; - } -} - -// Returns the number of fanout produced by the filter. More fanout implies -// the filter distinguishes more categories of instructions. -unsigned ARMFilter::usefulness() const { - if (VariableInstructions.size()) - return FilteredInstructions.size(); - else - return FilteredInstructions.size() + 1; -} - -////////////////////////////////// -// // -// Filterchooser Implementation // -// // -////////////////////////////////// - -// Define the symbol here. -TARGET_NAME_t ARMFilterChooser::TargetName; - -// This provides an opportunity for target specific code emission. -void ARMFilterChooser::emitTopHook(raw_ostream &o) { - if (TargetName == TARGET_ARM) { - // Emit code that references the ARMFormat data type. - o << "static const ARMFormat ARMFormats[] = {\n"; - for (unsigned i = 0, e = AllInstructions.size(); i != e; ++i) { - const Record &Def = *(AllInstructions[i]->TheDef); - const std::string &Name = Def.getName(); - if (Def.isSubClassOf("InstARM") || Def.isSubClassOf("InstThumb")) - o.indent(2) << - stringForARMFormat((ARMFormat)getByteField(Def, "Form")); - else - o << " ARM_FORMAT_NA"; - - o << ",\t// Inst #" << i << " = " << Name << '\n'; - } - o << " ARM_FORMAT_NA\t// Unreachable.\n"; - o << "};\n\n"; - } -} - -// Emit the top level typedef and decodeInstruction() function. -void ARMFilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) { - // Run the target specific emit hook. - emitTopHook(o); - - switch (BIT_WIDTH) { - case 8: - o.indent(Indentation) << "typedef uint8_t field_t;\n"; - break; - case 16: - o.indent(Indentation) << "typedef uint16_t field_t;\n"; - break; - case 32: - o.indent(Indentation) << "typedef uint32_t field_t;\n"; - break; - case 64: - o.indent(Indentation) << "typedef uint64_t field_t;\n"; - break; - default: - assert(0 && "Unexpected instruction size!"); - } - - o << '\n'; - - o.indent(Indentation) << "static field_t " << - "fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n"; - - o.indent(Indentation) << "{\n"; - - ++Indentation; ++Indentation; - o.indent(Indentation) << "assert(startBit + numBits <= " << BIT_WIDTH - << " && \"Instruction field out of bounds!\");\n"; - o << '\n'; - o.indent(Indentation) << "field_t fieldMask;\n"; - o << '\n'; - o.indent(Indentation) << "if (numBits == " << BIT_WIDTH << ")\n"; - - ++Indentation; ++Indentation; - o.indent(Indentation) << "fieldMask = (field_t)-1;\n"; - --Indentation; --Indentation; - - o.indent(Indentation) << "else\n"; - - ++Indentation; ++Indentation; - o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n"; - --Indentation; --Indentation; - - o << '\n'; - o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n"; - --Indentation; --Indentation; - - o.indent(Indentation) << "}\n"; - - o << '\n'; - - o.indent(Indentation) <<"static uint16_t decodeInstruction(field_t insn) {\n"; - - ++Indentation; ++Indentation; - // Emits code to decode the instructions. - emit(o, Indentation); - - o << '\n'; - o.indent(Indentation) << "return 0;\n"; - --Indentation; --Indentation; - - o.indent(Indentation) << "}\n"; - - o << '\n'; -} - -// This provides an opportunity for target specific code emission after -// emitTop(). -void ARMFilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) { - if (TargetName != TARGET_THUMB) return; - - // Emit code that decodes the Thumb ISA. - o.indent(Indentation) - << "static uint16_t decodeThumbInstruction(field_t insn) {\n"; - - ++Indentation; ++Indentation; - - // Emits code to decode the instructions. - emit(o, Indentation); - - o << '\n'; - o.indent(Indentation) << "return 0;\n"; - - --Indentation; --Indentation; - - o.indent(Indentation) << "}\n"; -} - -// Populates the field of the insn given the start position and the number of -// consecutive bits to scan for. -// -// Returns false if and on the first uninitialized bit value encountered. -// Returns true, otherwise. -bool ARMFilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, - unsigned StartBit, unsigned NumBits) const { - Field = 0; - - for (unsigned i = 0; i < NumBits; ++i) { - if (Insn[StartBit + i] == BIT_UNSET) - return false; - - if (Insn[StartBit + i] == BIT_TRUE) - Field = Field | (1ULL << i); - } - - return true; -} - -/// dumpFilterArray - dumpFilterArray prints out debugging info for the given -/// filter array as a series of chars. -void ARMFilterChooser::dumpFilterArray(raw_ostream &o, - bit_value_t (&filter)[BIT_WIDTH]) { - unsigned bitIndex; - - for (bitIndex = BIT_WIDTH; bitIndex > 0; bitIndex--) { - switch (filter[bitIndex - 1]) { - case BIT_UNFILTERED: - o << "."; - break; - case BIT_UNSET: - o << "_"; - break; - case BIT_TRUE: - o << "1"; - break; - case BIT_FALSE: - o << "0"; - break; - } - } -} - -/// dumpStack - dumpStack traverses the filter chooser chain and calls -/// dumpFilterArray on each filter chooser up to the top level one. -void ARMFilterChooser::dumpStack(raw_ostream &o, const char *prefix) { - ARMFilterChooser *current = this; - - while (current) { - o << prefix; - dumpFilterArray(o, current->FilterBitValues); - o << '\n'; - current = current->Parent; - } -} - -// Called from Filter::recurse() when singleton exists. For debug purpose. -void ARMFilterChooser::SingletonExists(unsigned Opc) { - insn_t Insn0; - insnWithID(Insn0, Opc); - - errs() << "Singleton exists: " << nameWithID(Opc) - << " with its decoding dominating "; - for (unsigned i = 0; i < Opcodes.size(); ++i) { - if (Opcodes[i] == Opc) continue; - errs() << nameWithID(Opcodes[i]) << ' '; - } - errs() << '\n'; - - dumpStack(errs(), "\t\t"); - for (unsigned i = 0; i < Opcodes.size(); i++) { - const std::string &Name = nameWithID(Opcodes[i]); - - errs() << '\t' << Name << " "; - dumpBits(errs(), - getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); - errs() << '\n'; - } -} - -// Calculates the island(s) needed to decode the instruction. -// This returns a list of undecoded bits of an instructions, for example, -// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be -// decoded bits in order to verify that the instruction matches the Opcode. -unsigned ARMFilterChooser::getIslands(std::vector<unsigned> &StartBits, - std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, - insn_t &Insn) { - unsigned Num, BitNo; - Num = BitNo = 0; - - uint64_t FieldVal = 0; - - // 0: Init - // 1: Water (the bit value does not affect decoding) - // 2: Island (well-known bit value needed for decoding) - int State = 0; - int Val = -1; - - for (unsigned i = 0; i < BIT_WIDTH; ++i) { - Val = Value(Insn[i]); - bool Filtered = PositionFiltered(i); - switch (State) { - default: - assert(0 && "Unreachable code!"); - break; - case 0: - case 1: - if (Filtered || Val == -1) - State = 1; // Still in Water - else { - State = 2; // Into the Island - BitNo = 0; - StartBits.push_back(i); - FieldVal = Val; - } - break; - case 2: - if (Filtered || Val == -1) { - State = 1; // Into the Water - EndBits.push_back(i - 1); - FieldVals.push_back(FieldVal); - ++Num; - } else { - State = 2; // Still in Island - ++BitNo; - FieldVal = FieldVal | Val << BitNo; - } - break; - } - } - // If we are still in Island after the loop, do some housekeeping. - if (State == 2) { - EndBits.push_back(BIT_WIDTH - 1); - FieldVals.push_back(FieldVal); - ++Num; - } - - assert(StartBits.size() == Num && EndBits.size() == Num && - FieldVals.size() == Num); - return Num; -} - -// Emits code to decode the singleton. Return true if we have matched all the -// well-known bits. -bool ARMFilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - unsigned Opc) { - std::vector<unsigned> StartBits; - std::vector<unsigned> EndBits; - std::vector<uint64_t> FieldVals; - insn_t Insn; - insnWithID(Insn, Opc); - - // This provides a good opportunity to check for possible Ld/St Coprocessor - // Opcode and escapes if the coproc # is either 10 or 11. It is a NEON/VFP - // instruction is disguise. - if (TargetName == TARGET_ARM && LdStCopEncoding1(Opc)) { - o.indent(Indentation); - // A8.6.51 & A8.6.188 - // If coproc = 0b101?, i.e, slice(insn, 11, 8) = 10 or 11, escape. - o << "if (fieldFromInstruction(insn, 9, 3) == 5) break; // fallthrough\n"; - } - - // Look for islands of undecoded bits of the singleton. - getIslands(StartBits, EndBits, FieldVals, Insn); - - unsigned Size = StartBits.size(); - unsigned I, NumBits; - - // If we have matched all the well-known bits, just issue a return. - if (Size == 0) { - o.indent(Indentation) << "return " << Opc << "; // " << nameWithID(Opc) - << '\n'; - return true; - } - - // Otherwise, there are more decodings to be done! - - // Emit code to match the island(s) for the singleton. - o.indent(Indentation) << "// Check "; - - for (I = Size; I != 0; --I) { - o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} "; - if (I > 1) - o << "&& "; - else - o << "for singleton decoding...\n"; - } - - o.indent(Indentation) << "if ("; - - for (I = Size; I != 0; --I) { - NumBits = EndBits[I-1] - StartBits[I-1] + 1; - o << "fieldFromInstruction(insn, " << StartBits[I-1] << ", " << NumBits - << ") == " << FieldVals[I-1]; - if (I > 1) - o << " && "; - else - o << ")\n"; - } - - o.indent(Indentation) << " return " << Opc << "; // " << nameWithID(Opc) - << '\n'; - - return false; -} - -// Emits code to decode the singleton, and then to decode the rest. -void ARMFilterChooser::emitSingletonDecoder(raw_ostream &o, - unsigned &Indentation, - ARMFilter &Best) { - - unsigned Opc = Best.getSingletonOpc(); - - emitSingletonDecoder(o, Indentation, Opc); - - // Emit code for the rest. - o.indent(Indentation) << "else\n"; - - Indentation += 2; - Best.getVariableFC().emit(o, Indentation); - Indentation -= 2; -} - -// Assign a single filter and run with it. Top level API client can initialize -// with a single filter to start the filtering process. -void ARMFilterChooser::runSingleFilter(ARMFilterChooser &owner, - unsigned startBit, - unsigned numBit, bool mixed) { - Filters.clear(); - ARMFilter F(*this, startBit, numBit, true); - Filters.push_back(F); - BestIndex = 0; // Sole Filter instance to choose from. - bestFilter().recurse(); -} - -// reportRegion is a helper function for filterProcessor to mark a region as -// eligible for use as a filter region. -void ARMFilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, - unsigned BitIndex, bool AllowMixed) { - if (RA == ATTR_MIXED && AllowMixed) - Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, true)); - else if (RA == ATTR_ALL_SET && !AllowMixed) - Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, false)); -} - -// FilterProcessor scans the well-known encoding bits of the instructions and -// builds up a list of candidate filters. It chooses the best filter and -// recursively descends down the decoding tree. -bool ARMFilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { - Filters.clear(); - BestIndex = -1; - unsigned numInstructions = Opcodes.size(); - - assert(numInstructions && "Filter created with no instructions"); - - // No further filtering is necessary. - if (numInstructions == 1) - return true; - - // Heuristics. See also doFilter()'s "Heuristics" comment when num of - // instructions is 3. - if (AllowMixed && !Greedy) { - assert(numInstructions == 3); - - for (unsigned i = 0; i < Opcodes.size(); ++i) { - std::vector<unsigned> StartBits; - std::vector<unsigned> EndBits; - std::vector<uint64_t> FieldVals; - insn_t Insn; - - insnWithID(Insn, Opcodes[i]); - - // Look for islands of undecoded bits of any instruction. - if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) { - // Found an instruction with island(s). Now just assign a filter. - runSingleFilter(*this, StartBits[0], EndBits[0] - StartBits[0] + 1, - true); - return true; - } - } - } - - unsigned BitIndex, InsnIndex; - - // We maintain BIT_WIDTH copies of the bitAttrs automaton. - // The automaton consumes the corresponding bit from each - // instruction. - // - // Input symbols: 0, 1, and _ (unset). - // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED. - // Initial state: NONE. - // - // (NONE) ------- [01] -> (ALL_SET) - // (NONE) ------- _ ----> (ALL_UNSET) - // (ALL_SET) ---- [01] -> (ALL_SET) - // (ALL_SET) ---- _ ----> (MIXED) - // (ALL_UNSET) -- [01] -> (MIXED) - // (ALL_UNSET) -- _ ----> (ALL_UNSET) - // (MIXED) ------ . ----> (MIXED) - // (FILTERED)---- . ----> (FILTERED) - - bitAttr_t bitAttrs[BIT_WIDTH]; - - // FILTERED bit positions provide no entropy and are not worthy of pursuing. - // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position. - for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) - if (FilterBitValues[BitIndex] == BIT_TRUE || - FilterBitValues[BitIndex] == BIT_FALSE) - bitAttrs[BitIndex] = ATTR_FILTERED; - else - bitAttrs[BitIndex] = ATTR_NONE; - - for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { - insn_t insn; - - insnWithID(insn, Opcodes[InsnIndex]); - - for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) { - switch (bitAttrs[BitIndex]) { - case ATTR_NONE: - if (insn[BitIndex] == BIT_UNSET) - bitAttrs[BitIndex] = ATTR_ALL_UNSET; - else - bitAttrs[BitIndex] = ATTR_ALL_SET; - break; - case ATTR_ALL_SET: - if (insn[BitIndex] == BIT_UNSET) - bitAttrs[BitIndex] = ATTR_MIXED; - break; - case ATTR_ALL_UNSET: - if (insn[BitIndex] != BIT_UNSET) - bitAttrs[BitIndex] = ATTR_MIXED; - break; - case ATTR_MIXED: - case ATTR_FILTERED: - break; - } - } - } - - // The regionAttr automaton consumes the bitAttrs automatons' state, - // lowest-to-highest. - // - // Input symbols: F(iltered), (all_)S(et), (all_)U(nset), M(ixed) - // States: NONE, ALL_SET, MIXED - // Initial state: NONE - // - // (NONE) ----- F --> (NONE) - // (NONE) ----- S --> (ALL_SET) ; and set region start - // (NONE) ----- U --> (NONE) - // (NONE) ----- M --> (MIXED) ; and set region start - // (ALL_SET) -- F --> (NONE) ; and report an ALL_SET region - // (ALL_SET) -- S --> (ALL_SET) - // (ALL_SET) -- U --> (NONE) ; and report an ALL_SET region - // (ALL_SET) -- M --> (MIXED) ; and report an ALL_SET region - // (MIXED) ---- F --> (NONE) ; and report a MIXED region - // (MIXED) ---- S --> (ALL_SET) ; and report a MIXED region - // (MIXED) ---- U --> (NONE) ; and report a MIXED region - // (MIXED) ---- M --> (MIXED) - - bitAttr_t RA = ATTR_NONE; - unsigned StartBit = 0; - - for (BitIndex = 0; BitIndex < BIT_WIDTH; BitIndex++) { - bitAttr_t bitAttr = bitAttrs[BitIndex]; - - assert(bitAttr != ATTR_NONE && "Bit without attributes"); - - switch (RA) { - case ATTR_NONE: - switch (bitAttr) { - case ATTR_FILTERED: - break; - case ATTR_ALL_SET: - StartBit = BitIndex; - RA = ATTR_ALL_SET; - break; - case ATTR_ALL_UNSET: - break; - case ATTR_MIXED: - StartBit = BitIndex; - RA = ATTR_MIXED; - break; - default: - assert(0 && "Unexpected bitAttr!"); - } - break; - case ATTR_ALL_SET: - switch (bitAttr) { - case ATTR_FILTERED: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - RA = ATTR_NONE; - break; - case ATTR_ALL_SET: - break; - case ATTR_ALL_UNSET: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - RA = ATTR_NONE; - break; - case ATTR_MIXED: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - StartBit = BitIndex; - RA = ATTR_MIXED; - break; - default: - assert(0 && "Unexpected bitAttr!"); - } - break; - case ATTR_MIXED: - switch (bitAttr) { - case ATTR_FILTERED: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - StartBit = BitIndex; - RA = ATTR_NONE; - break; - case ATTR_ALL_SET: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - StartBit = BitIndex; - RA = ATTR_ALL_SET; - break; - case ATTR_ALL_UNSET: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - RA = ATTR_NONE; - break; - case ATTR_MIXED: - break; - default: - assert(0 && "Unexpected bitAttr!"); - } - break; - case ATTR_ALL_UNSET: - assert(0 && "regionAttr state machine has no ATTR_UNSET state"); - case ATTR_FILTERED: - assert(0 && "regionAttr state machine has no ATTR_FILTERED state"); - } - } - - // At the end, if we're still in ALL_SET or MIXED states, report a region - switch (RA) { - case ATTR_NONE: - break; - case ATTR_FILTERED: - break; - case ATTR_ALL_SET: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - break; - case ATTR_ALL_UNSET: - break; - case ATTR_MIXED: - reportRegion(RA, StartBit, BitIndex, AllowMixed); - break; - } - - // We have finished with the filter processings. Now it's time to choose - // the best performing filter. - BestIndex = 0; - bool AllUseless = true; - unsigned BestScore = 0; - - for (unsigned i = 0, e = Filters.size(); i != e; ++i) { - unsigned Usefulness = Filters[i].usefulness(); - - if (Usefulness) - AllUseless = false; - - if (Usefulness > BestScore) { - BestIndex = i; - BestScore = Usefulness; - } - } - - if (!AllUseless) - bestFilter().recurse(); - - return !AllUseless; -} // end of FilterChooser::filterProcessor(bool) - -// Decides on the best configuration of filter(s) to use in order to decode -// the instructions. A conflict of instructions may occur, in which case we -// dump the conflict set to the standard error. -void ARMFilterChooser::doFilter() { - unsigned Num = Opcodes.size(); - assert(Num && "FilterChooser created with no instructions"); - - // Heuristics: Use Inst{31-28} as the top level filter for ARM ISA. - if (TargetName == TARGET_ARM && Parent == NULL) { - runSingleFilter(*this, 28, 4, false); - return; - } - - // Try regions of consecutive known bit values first. - if (filterProcessor(false)) - return; - - // Then regions of mixed bits (both known and unitialized bit values allowed). - if (filterProcessor(true)) - return; - - // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where - // no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a - // well-known encoding pattern. In such case, we backtrack and scan for the - // the very first consecutive ATTR_ALL_SET region and assign a filter to it. - if (Num == 3 && filterProcessor(true, false)) - return; - - // If we come to here, the instruction decoding has failed. - // Set the BestIndex to -1 to indicate so. - BestIndex = -1; -} - -// Emits code to decode our share of instructions. Returns true if the -// emitted code causes a return, which occurs if we know how to decode -// the instruction at this level or the instruction is not decodeable. -bool ARMFilterChooser::emit(raw_ostream &o, unsigned &Indentation) { - if (Opcodes.size() == 1) - // There is only one instruction in the set, which is great! - // Call emitSingletonDecoder() to see whether there are any remaining - // encodings bits. - return emitSingletonDecoder(o, Indentation, Opcodes[0]); - - // Choose the best filter to do the decodings! - if (BestIndex != -1) { - ARMFilter &Best = bestFilter(); - if (Best.getNumFiltered() == 1) - emitSingletonDecoder(o, Indentation, Best); - else - bestFilter().emit(o, Indentation); - return false; - } - - // If we reach here, there is a conflict in decoding. Let's resolve the known - // conflicts! - if ((TargetName == TARGET_ARM || TargetName == TARGET_THUMB) && - Opcodes.size() == 2) { - // Resolve the known conflict sets: - // - // 1. source registers are identical => VMOVDneon; otherwise => VORRd - // 2. source registers are identical => VMOVQ; otherwise => VORRq - // 3. LDR, LDRcp => return LDR for now. - // FIXME: How can we distinguish between LDR and LDRcp? Do we need to? - // 4. tLDMIA, tLDMIA_UPD => Rn = Inst{10-8}, reglist = Inst{7-0}, - // wback = registers<Rn> = 0 - // NOTE: (tLDM, tLDM_UPD) resolution must come before Advanced SIMD - // addressing mode resolution!!! - // 5. VLD[234]LN*/VST[234]LN* vs. VLD[234]LN*_UPD/VST[234]LN*_UPD conflicts - // are resolved returning the non-UPD versions of the instructions if the - // Rm field, i.e., Inst{3-0} is 0b1111. This is specified in A7.7.1 - // Advanced SIMD addressing mode. - const std::string &name1 = nameWithID(Opcodes[0]); - const std::string &name2 = nameWithID(Opcodes[1]); - if ((name1 == "VMOVDneon" && name2 == "VORRd") || - (name1 == "VMOVQ" && name2 == "VORRq")) { - // Inserting the opening curly brace for this case block. - --Indentation; --Indentation; - o.indent(Indentation) << "{\n"; - ++Indentation; ++Indentation; - - o.indent(Indentation) - << "field_t N = fieldFromInstruction(insn, 7, 1), " - << "M = fieldFromInstruction(insn, 5, 1);\n"; - o.indent(Indentation) - << "field_t Vn = fieldFromInstruction(insn, 16, 4), " - << "Vm = fieldFromInstruction(insn, 0, 4);\n"; - o.indent(Indentation) - << "return (N == M && Vn == Vm) ? " - << Opcodes[0] << " /* " << name1 << " */ : " - << Opcodes[1] << " /* " << name2 << " */ ;\n"; - - // Inserting the closing curly brace for this case block. - --Indentation; --Indentation; - o.indent(Indentation) << "}\n"; - ++Indentation; ++Indentation; - - return true; - } - if (name1 == "LDR" && name2 == "LDRcp") { - o.indent(Indentation) - << "return " << Opcodes[0] - << "; // Returning LDR for {LDR, LDRcp}\n"; - return true; - } - if (name1 == "tLDMIA" && name2 == "tLDMIA_UPD") { - // Inserting the opening curly brace for this case block. - --Indentation; --Indentation; - o.indent(Indentation) << "{\n"; - ++Indentation; ++Indentation; - - o.indent(Indentation) - << "unsigned Rn = fieldFromInstruction(insn, 8, 3), " - << "list = fieldFromInstruction(insn, 0, 8);\n"; - o.indent(Indentation) - << "return ((list >> Rn) & 1) == 0 ? " - << Opcodes[1] << " /* " << name2 << " */ : " - << Opcodes[0] << " /* " << name1 << " */ ;\n"; - - // Inserting the closing curly brace for this case block. - --Indentation; --Indentation; - o.indent(Indentation) << "}\n"; - ++Indentation; ++Indentation; - - return true; - } - if (sameStringExceptSuffix(name1, name2, "_UPD")) { - o.indent(Indentation) - << "return fieldFromInstruction(insn, 0, 4) == 15 ? " << Opcodes[0] - << " /* " << name1 << " */ : " << Opcodes[1] << "/* " << name2 - << " */ ; // Advanced SIMD addressing mode\n"; - return true; - } - - // Otherwise, it does not belong to the known conflict sets. - } - - // We don't know how to decode these instructions! Return 0 and dump the - // conflict set! - o.indent(Indentation) << "return 0;" << " // Conflict set: "; - for (int i = 0, N = Opcodes.size(); i < N; ++i) { - o << nameWithID(Opcodes[i]); - if (i < (N - 1)) - o << ", "; - else - o << '\n'; - } - - // Print out useful conflict information for postmortem analysis. - errs() << "Decoding Conflict:\n"; - - dumpStack(errs(), "\t\t"); - - for (unsigned i = 0; i < Opcodes.size(); i++) { - const std::string &Name = nameWithID(Opcodes[i]); - - errs() << '\t' << Name << " "; - dumpBits(errs(), - getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); - errs() << '\n'; - } - - return true; -} - - -//////////////////////////////////////////// -// // -// ARMDEBackend // -// (Helper class for ARMDecoderEmitter) // -// // -//////////////////////////////////////////// - -class ARMDecoderEmitter::ARMDEBackend { -public: - ARMDEBackend(ARMDecoderEmitter &frontend, RecordKeeper &Records) : - NumberedInstructions(), - Opcodes(), - Frontend(frontend), - Target(Records), - FC(NULL) - { - if (Target.getName() == "ARM") - TargetName = TARGET_ARM; - else { - errs() << "Target name " << Target.getName() << " not recognized\n"; - assert(0 && "Unknown target"); - } - - // Populate the instructions for our TargetName. - populateInstructions(); - } - - ~ARMDEBackend() { - if (FC) { - delete FC; - FC = NULL; - } - } - - void getInstructionsByEnumValue(std::vector<const CodeGenInstruction*> - &NumberedInstructions) { - // We must emit the PHI opcode first... - std::string Namespace = Target.getInstNamespace(); - assert(!Namespace.empty() && "No instructions defined."); - - NumberedInstructions = Target.getInstructionsByEnumValue(); - } - - bool populateInstruction(const CodeGenInstruction &CGI, TARGET_NAME_t TN); - - void populateInstructions(); - - // Emits disassembler code for instruction decoding. This delegates to the - // FilterChooser instance to do the heavy lifting. - void emit(raw_ostream &o); - -protected: - std::vector<const CodeGenInstruction*> NumberedInstructions; - std::vector<unsigned> Opcodes; - // Special case for the ARM chip, which supports ARM and Thumb ISAs. - // Opcodes2 will be populated with the Thumb opcodes. - std::vector<unsigned> Opcodes2; - ARMDecoderEmitter &Frontend; - CodeGenTarget Target; - ARMFilterChooser *FC; - - TARGET_NAME_t TargetName; -}; - -bool ARMDecoderEmitter:: -ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, - TARGET_NAME_t TN) { - const Record &Def = *CGI.TheDef; - const StringRef Name = Def.getName(); - uint8_t Form = getByteField(Def, "Form"); - - BitsInit &Bits = getBitsField(Def, "Inst"); - - // If all the bit positions are not specified; do not decode this instruction. - // We are bound to fail! For proper disassembly, the well-known encoding bits - // of the instruction must be fully specified. - // - // This also removes pseudo instructions from considerations of disassembly, - // which is a better design and less fragile than the name matchings. - if (Bits.allInComplete()) return false; - - // Ignore "asm parser only" instructions. - if (Def.getValueAsBit("isAsmParserOnly")) - return false; - - if (TN == TARGET_ARM) { - if (Form == ARM_FORMAT_PSEUDO) - return false; - if (thumbInstruction(Form)) - return false; - - // Tail calls are other patterns that generate existing instructions. - if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" || - Name == "TCRETURNri" || Name == "TCRETURNriND" || - Name == "TAILJMPd" || Name == "TAILJMPdt" || - Name == "TAILJMPdND" || Name == "TAILJMPdNDt" || - Name == "TAILJMPr" || Name == "TAILJMPrND" || - Name == "MOVr_TC") - return false; - - // Delegate ADR disassembly to the more generic ADDri/SUBri instructions. - if (Name == "ADR") - return false; - - // - // The following special cases are for conflict resolutions. - // - - // A8-598: VEXT - // Vector Extract extracts elements from the bottom end of the second - // operand vector and the top end of the first, concatenates them and - // places the result in the destination vector. The elements of the - // vectors are treated as being 8-bit bitfields. There is no distinction - // between data types. The size of the operation can be specified in - // assembler as vext.size. If the value is 16, 32, or 64, the syntax is - // a pseudo-instruction for a VEXT instruction specifying the equivalent - // number of bytes. - // - // Variants VEXTd16, VEXTd32, VEXTd8, and VEXTdf are reduced to VEXTd8; - // variants VEXTq16, VEXTq32, VEXTq8, and VEXTqf are reduced to VEXTq8. - if (Name == "VEXTd16" || Name == "VEXTd32" || Name == "VEXTdf" || - Name == "VEXTq16" || Name == "VEXTq32" || Name == "VEXTqf") - return false; - } else if (TN == TARGET_THUMB) { - if (!thumbInstruction(Form)) - return false; - - // A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg. - if (Name == "tBX_RET" || Name == "tBX_RET_vararg") - return false; - - // Ignore tADR, prefer tADDrPCi. - if (Name == "tADR") - return false; - - // Delegate t2ADR disassembly to the more generic t2ADDri12/t2SUBri12 - // instructions. - if (Name == "t2ADR") - return false; - - // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr. - // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s]. - // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s]. - if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" || - Name == "t2SUBrSPs" || Name == "t2ADDrSPs") - return false; - - // FIXME: Use ldr.n to work around a Darwin assembler bug. - // Introduce a workaround with tLDRpciDIS opcode. - if (Name == "tLDRpci") - return false; - - // Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST. - if (Name == "t2LDRDpci") - return false; - - // Resolve conflicts: - // - // t2LDMIA_RET conflict with t2LDM (ditto) - // tMOVCCi conflicts with tMOVi8 - // tMOVCCr conflicts with tMOVgpr2gpr - // tLDRcp conflicts with tLDRspi - // t2MOVCCi16 conflicts with tMOVi16 - if (Name == "t2LDMIA_RET" || - Name == "tMOVCCi" || Name == "tMOVCCr" || - Name == "tLDRcp" || - Name == "t2MOVCCi16") - return false; - } - - DEBUG({ - // Dumps the instruction encoding format. - switch (TargetName) { - case TARGET_ARM: - case TARGET_THUMB: - errs() << Name << " " << stringForARMFormat((ARMFormat)Form); - break; - } - - errs() << " "; - - // Dumps the instruction encoding bits. - dumpBits(errs(), Bits); - - errs() << '\n'; - - // Dumps the list of operand info. - for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { - const CGIOperandList::OperandInfo &Info = CGI.Operands[i]; - const std::string &OperandName = Info.Name; - const Record &OperandDef = *Info.Rec; - - errs() << "\t" << OperandName << " (" << OperandDef.getName() << ")\n"; - } - }); - - return true; -} - -void ARMDecoderEmitter::ARMDEBackend::populateInstructions() { - getInstructionsByEnumValue(NumberedInstructions); - - unsigned numUIDs = NumberedInstructions.size(); - if (TargetName == TARGET_ARM) { - for (unsigned uid = 0; uid < numUIDs; uid++) { - // filter out intrinsics - if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM")) - continue; - - if (populateInstruction(*NumberedInstructions[uid], TargetName)) - Opcodes.push_back(uid); - } - - // Special handling for the ARM chip, which supports two modes of execution. - // This branch handles the Thumb opcodes. - for (unsigned uid = 0; uid < numUIDs; uid++) { - // filter out intrinsics - if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM") - && !NumberedInstructions[uid]->TheDef->isSubClassOf("InstThumb")) - continue; - - if (populateInstruction(*NumberedInstructions[uid], TARGET_THUMB)) - Opcodes2.push_back(uid); - } - - return; - } - - // For other targets. - for (unsigned uid = 0; uid < numUIDs; uid++) { - Record *R = NumberedInstructions[uid]->TheDef; - if (R->getValueAsString("Namespace") == "TargetOpcode") - continue; - - if (populateInstruction(*NumberedInstructions[uid], TargetName)) - Opcodes.push_back(uid); - } -} - -// Emits disassembler code for instruction decoding. This delegates to the -// FilterChooser instance to do the heavy lifting. -void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) { - switch (TargetName) { - case TARGET_ARM: - Frontend.EmitSourceFileHeader("ARM/Thumb Decoders", o); - break; - default: - assert(0 && "Unreachable code!"); - } - - o << "#include \"llvm/Support/DataTypes.h\"\n"; - o << "#include <assert.h>\n"; - o << '\n'; - o << "namespace llvm {\n\n"; - - ARMFilterChooser::setTargetName(TargetName); - - switch (TargetName) { - case TARGET_ARM: { - // Emit common utility and ARM ISA decoder. - FC = new ARMFilterChooser(NumberedInstructions, Opcodes); - // Reset indentation level. - unsigned Indentation = 0; - FC->emitTop(o, Indentation); - delete FC; - - // Emit Thumb ISA decoder as well. - ARMFilterChooser::setTargetName(TARGET_THUMB); - FC = new ARMFilterChooser(NumberedInstructions, Opcodes2); - // Reset indentation level. - Indentation = 0; - FC->emitBot(o, Indentation); - break; - } - default: - assert(0 && "Unreachable code!"); - } - - o << "\n} // End llvm namespace \n"; -} - -///////////////////////// -// Backend interface // -///////////////////////// - -void ARMDecoderEmitter::initBackend() -{ - Backend = new ARMDEBackend(*this, Records); -} - -void ARMDecoderEmitter::run(raw_ostream &o) -{ - Backend->emit(o); -} - -void ARMDecoderEmitter::shutdownBackend() -{ - delete Backend; - Backend = NULL; -} diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h deleted file mode 100644 index 486f899354f4..000000000000 --- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h +++ /dev/null @@ -1,49 +0,0 @@ -//===------------ ARMDecoderEmitter.h - Decoder Generator -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is part of the ARM Disassembler. -// It contains the tablegen backend declaration ARMDecoderEmitter. -// -//===----------------------------------------------------------------------===// - -#ifndef ARMDECODEREMITTER_H -#define ARMDECODEREMITTER_H - -#include "llvm/Support/DataTypes.h" -#include "llvm/TableGen/TableGenBackend.h" - -namespace llvm { - -class ARMDecoderEmitter : public TableGenBackend { - RecordKeeper &Records; -public: - ARMDecoderEmitter(RecordKeeper &R) : Records(R) { - initBackend(); - } - - ~ARMDecoderEmitter() { - shutdownBackend(); - } - - // run - Output the code emitter - void run(raw_ostream &o); - -private: - // Helper class for ARMDecoderEmitter. - class ARMDEBackend; - - ARMDEBackend *Backend; - - void initBackend(); - void shutdownBackend(); -}; - -} // end llvm namespace - -#endif diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 8b86c23d0632..39a3c25d99da 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -99,6 +99,7 @@ #include "AsmMatcherEmitter.h" #include "CodeGenTarget.h" #include "StringMatcher.h" +#include "StringToOffsetTable.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallPtrSet.h" @@ -107,6 +108,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include <map> @@ -251,12 +253,7 @@ public: switch (Kind) { case Invalid: - assert(0 && "Invalid kind!"); - case Token: - // Tokens are comparable by value. - // - // FIXME: Compare by enum value. - return ValueName < RHS.ValueName; + llvm_unreachable("Invalid kind!"); default: // This class precedes the RHS if it is a proper subset of the RHS. @@ -287,7 +284,11 @@ struct MatchableInfo { /// The suboperand index within SrcOpName, or -1 for the entire operand. int SubOpIdx; - explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1) {} + /// Register record if this token is singleton register. + Record *SingletonReg; + + explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1), + SingletonReg(0) {} }; /// ResOperand - This represents a single operand in the result instruction @@ -366,6 +367,9 @@ struct MatchableInfo { } }; + /// AsmVariantID - Target's assembly syntax variant no. + int AsmVariantID; + /// TheDef - This is the definition of the instruction or InstAlias that this /// matchable came from. Record *const TheDef; @@ -406,24 +410,28 @@ struct MatchableInfo { std::string ConversionFnKind; MatchableInfo(const CodeGenInstruction &CGI) - : TheDef(CGI.TheDef), DefRec(&CGI), AsmString(CGI.AsmString) { + : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI), + AsmString(CGI.AsmString) { } MatchableInfo(const CodeGenInstAlias *Alias) - : TheDef(Alias->TheDef), DefRec(Alias), AsmString(Alias->AsmString) { + : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias), + AsmString(Alias->AsmString) { } void Initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters); + SmallPtrSet<Record*, 16> &SingletonRegisters, + int AsmVariantNo, std::string &RegisterPrefix); /// Validate - Return true if this matchable is a valid thing to match against /// and perform a bunch of validity checking. bool Validate(StringRef CommentDelimiter, bool Hack) const; - /// getSingletonRegisterForAsmOperand - If the specified token is a singleton - /// register, return the Record for it, otherwise return null. - Record *getSingletonRegisterForAsmOperand(unsigned i, - const AsmMatcherInfo &Info) const; + /// extractSingletonRegisterForAsmOperand - Extract singleton register, + /// if present, from specified token. + void + extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info, + std::string &RegisterPrefix); /// FindAsmOperand - Find the AsmOperand with the specified name and /// suboperand index. @@ -557,9 +565,6 @@ public: /// Target - The target information. CodeGenTarget &Target; - /// The AsmParser "RegisterPrefix" value. - std::string RegisterPrefix; - /// The classes which are needed for matching. std::vector<ClassInfo*> Classes; @@ -591,7 +596,8 @@ private: /// getOperandClass - Lookup or create the class for the given operand. ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI, - int SubOpIdx = -1); + int SubOpIdx); + ClassInfo *getOperandClass(Record *Rec, int SubOpIdx); /// BuildRegisterClasses - Build the ClassInfo* instances for register /// classes. @@ -645,9 +651,11 @@ void MatchableInfo::dump() { } void MatchableInfo::Initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters) { - // TODO: Eventually support asmparser for Variant != 0. - AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, 0); + SmallPtrSet<Record*, 16> &SingletonRegisters, + int AsmVariantNo, std::string &RegisterPrefix) { + AsmVariantID = AsmVariantNo; + AsmString = + CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo); TokenizeAsmString(Info); @@ -660,7 +668,8 @@ void MatchableInfo::Initialize(const AsmMatcherInfo &Info, // Collect singleton registers, if used. for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - if (Record *Reg = getSingletonRegisterForAsmOperand(i, Info)) + extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix); + if (Record *Reg = AsmOperands[i].SingletonReg) SingletonRegisters.insert(Reg); } } @@ -736,9 +745,12 @@ void MatchableInfo::TokenizeAsmString(const AsmMatcherInfo &Info) { // The first token of the instruction is the mnemonic, which must be a // simple string, not a $foo variable or a singleton register. - assert(!AsmOperands.empty() && "Instruction has no tokens?"); + if (AsmOperands.empty()) + throw TGError(TheDef->getLoc(), + "Instruction '" + TheDef->getName() + "' has no tokens"); Mnemonic = AsmOperands[0].Token; - if (Mnemonic[0] == '$' || getSingletonRegisterForAsmOperand(0, Info)) + // FIXME : Check and raise an error if it is a register. + if (Mnemonic[0] == '$') throw TGError(TheDef->getLoc(), "Invalid instruction mnemonic '" + Mnemonic.str() + "'!"); @@ -801,28 +813,30 @@ bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const { return true; } -/// getSingletonRegisterForAsmOperand - If the specified token is a singleton -/// register, return the register name, otherwise return a null StringRef. -Record *MatchableInfo:: -getSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info) const{ - StringRef Tok = AsmOperands[i].Token; - if (!Tok.startswith(Info.RegisterPrefix)) - return 0; +/// extractSingletonRegisterForAsmOperand - Extract singleton register, +/// if present, from specified token. +void MatchableInfo:: +extractSingletonRegisterForAsmOperand(unsigned OperandNo, + const AsmMatcherInfo &Info, + std::string &RegisterPrefix) { + StringRef Tok = AsmOperands[OperandNo].Token; + if (RegisterPrefix.empty()) { + std::string LoweredTok = Tok.lower(); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok)) + AsmOperands[OperandNo].SingletonReg = Reg->TheDef; + return; + } + + if (!Tok.startswith(RegisterPrefix)) + return; - StringRef RegName = Tok.substr(Info.RegisterPrefix.size()); + StringRef RegName = Tok.substr(RegisterPrefix.size()); if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) - return Reg->TheDef; + AsmOperands[OperandNo].SingletonReg = Reg->TheDef; // If there is no register prefix (i.e. "%" in "%eax"), then this may // be some random non-register token, just ignore it. - if (Info.RegisterPrefix.empty()) - return 0; - - // Otherwise, we have something invalid prefixed with the register prefix, - // such as %foo. - std::string Err = "unable to find register for '" + RegName.str() + - "' (which matches register prefix)"; - throw TGError(TheDef->getLoc(), Err); + return; } static std::string getEnumNameForToken(StringRef Str) { @@ -870,7 +884,11 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI, Record *Rec = OI.Rec; if (SubOpIdx != -1) Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef(); + return getOperandClass(Rec, SubOpIdx); +} +ClassInfo * +AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { if (Rec->isSubClassOf("RegisterOperand")) { // RegisterOperand may have an associated ParserMatchClass. If it does, // use it, else just fall back to the underlying register class. @@ -1102,8 +1120,7 @@ void AsmMatcherInfo::BuildOperandClasses() { AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, CodeGenTarget &target, RecordKeeper &records) - : Records(records), AsmParser(asmParser), Target(target), - RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) { + : Records(records), AsmParser(asmParser), Target(target) { } /// BuildOperandMatchInfo - Build the necessary information to handle user @@ -1158,86 +1175,92 @@ void AsmMatcherInfo::BuildInfo() { assert(FeatureNo < 32 && "Too many subtarget features!"); } - std::string CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter"); - // Parse the instructions; we need to do this first so that we can gather the // singleton register classes. SmallPtrSet<Record*, 16> SingletonRegisters; - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - const CodeGenInstruction &CGI = **I; - - // If the tblgen -match-prefix option is specified (for tblgen hackers), - // filter the set of instructions we consider. - if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) - continue; + unsigned VariantCount = Target.getAsmParserVariantCount(); + for (unsigned VC = 0; VC != VariantCount; ++VC) { + Record *AsmVariant = Target.getAsmParserVariant(VC); + std::string CommentDelimiter = AsmVariant->getValueAsString("CommentDelimiter"); + std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); + int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); + + for (CodeGenTarget::inst_iterator I = Target.inst_begin(), + E = Target.inst_end(); I != E; ++I) { + const CodeGenInstruction &CGI = **I; + + // If the tblgen -match-prefix option is specified (for tblgen hackers), + // filter the set of instructions we consider. + if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) + continue; - // Ignore "codegen only" instructions. - if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) - continue; + // Ignore "codegen only" instructions. + if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) + continue; - // Validate the operand list to ensure we can handle this instruction. - for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { - const CGIOperandList::OperandInfo &OI = CGI.Operands[i]; - - // Validate tied operands. - if (OI.getTiedRegister() != -1) { - // If we have a tied operand that consists of multiple MCOperands, - // reject it. We reject aliases and ignore instructions for now. - if (OI.MINumOperands != 1) { - // FIXME: Should reject these. The ARM backend hits this with $lane - // in a bunch of instructions. It is unclear what the right answer is. - DEBUG({ - errs() << "warning: '" << CGI.TheDef->getName() << "': " - << "ignoring instruction with multi-operand tied operand '" - << OI.Name << "'\n"; - }); - continue; + // Validate the operand list to ensure we can handle this instruction. + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OI = CGI.Operands[i]; + + // Validate tied operands. + if (OI.getTiedRegister() != -1) { + // If we have a tied operand that consists of multiple MCOperands, + // reject it. We reject aliases and ignore instructions for now. + if (OI.MINumOperands != 1) { + // FIXME: Should reject these. The ARM backend hits this with $lane + // in a bunch of instructions. It is unclear what the right answer is. + DEBUG({ + errs() << "warning: '" << CGI.TheDef->getName() << "': " + << "ignoring instruction with multi-operand tied operand '" + << OI.Name << "'\n"; + }); + continue; + } } } - } - OwningPtr<MatchableInfo> II(new MatchableInfo(CGI)); + OwningPtr<MatchableInfo> II(new MatchableInfo(CGI)); - II->Initialize(*this, SingletonRegisters); + II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); - // Ignore instructions which shouldn't be matched and diagnose invalid - // instruction definitions with an error. - if (!II->Validate(CommentDelimiter, true)) - continue; + // Ignore instructions which shouldn't be matched and diagnose invalid + // instruction definitions with an error. + if (!II->Validate(CommentDelimiter, true)) + continue; - // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. - // - // FIXME: This is a total hack. - if (StringRef(II->TheDef->getName()).startswith("Int_") || - StringRef(II->TheDef->getName()).endswith("_Int")) - continue; + // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. + // + // FIXME: This is a total hack. + if (StringRef(II->TheDef->getName()).startswith("Int_") || + StringRef(II->TheDef->getName()).endswith("_Int")) + continue; - Matchables.push_back(II.take()); - } + Matchables.push_back(II.take()); + } - // Parse all of the InstAlias definitions and stick them in the list of - // matchables. - std::vector<Record*> AllInstAliases = - Records.getAllDerivedDefinitions("InstAlias"); - for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { - CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target); - - // If the tblgen -match-prefix option is specified (for tblgen hackers), - // filter the set of instruction aliases we consider, based on the target - // instruction. - if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith( - MatchPrefix)) - continue; + // Parse all of the InstAlias definitions and stick them in the list of + // matchables. + std::vector<Record*> AllInstAliases = + Records.getAllDerivedDefinitions("InstAlias"); + for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { + CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target); + + // If the tblgen -match-prefix option is specified (for tblgen hackers), + // filter the set of instruction aliases we consider, based on the target + // instruction. + if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith( + MatchPrefix)) + continue; - OwningPtr<MatchableInfo> II(new MatchableInfo(Alias)); + OwningPtr<MatchableInfo> II(new MatchableInfo(Alias)); - II->Initialize(*this, SingletonRegisters); + II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); - // Validate the alias definitions. - II->Validate(CommentDelimiter, false); + // Validate the alias definitions. + II->Validate(CommentDelimiter, false); - Matchables.push_back(II.take()); + Matchables.push_back(II.take()); + } } // Build info for the register classes. @@ -1260,7 +1283,7 @@ void AsmMatcherInfo::BuildInfo() { StringRef Token = Op.Token; // Check for singleton registers. - if (Record *RegRecord = II->getSingletonRegisterForAsmOperand(i, *this)) { + if (Record *RegRecord = II->AsmOperands[i].SingletonReg) { Op.Class = RegisterClasses[RegRecord]; assert(Op.Class && Op.Class->Registers.size() == 1 && "Unexpected class for singleton register"); @@ -1297,6 +1320,17 @@ void AsmMatcherInfo::BuildInfo() { II->BuildAliasResultOperands(); } + // Process token alias definitions and set up the associated superclass + // information. + std::vector<Record*> AllTokenAliases = + Records.getAllDerivedDefinitions("TokenAlias"); + for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) { + Record *Rec = AllTokenAliases[i]; + ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); + ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); + FromClass->SuperClasses.push_back(ToClass); + } + // Reorder classes so that classes precede super classes. std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); } @@ -1375,9 +1409,11 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II, CGA.ResultOperands[i].getName() == OperandName) { // It's safe to go with the first one we find, because CodeGenInstAlias // validates that all operands with the same name have the same record. - unsigned ResultIdx = CGA.ResultInstOperandIndex[i].first; Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second; - Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx], + // Use the match class from the Alias definition, not the + // destination instruction, as we may have an immediate that's + // being munged by the match class. + Op.Class = getOperandClass(CGA.ResultOperands[i].getRecord(), Op.SubOpIdx); Op.SrcOpName = OperandName; return; @@ -1453,7 +1489,6 @@ void MatchableInfo::BuildAliasResultOperands() { // Find out what operand from the asmparser that this MCInst operand // comes from. switch (CGA.ResultOperands[AliasOpNo].Kind) { - default: assert(0 && "unexpected InstAlias operand kind"); case CodeGenInstAlias::ResultOperand::K_Record: { StringRef Name = CGA.ResultOperands[AliasOpNo].getName(); int SrcOperand = FindAsmOperand(Name, SubIdx); @@ -1656,7 +1691,7 @@ static void EmitMatchClassEnumeration(CodeGenTarget &Target, /// EmitValidateOperandClass - Emit the function to validate an operand class. static void EmitValidateOperandClass(AsmMatcherInfo &Info, raw_ostream &OS) { - OS << "static bool ValidateOperandClass(MCParsedAsmOperand *GOp, " + OS << "static bool validateOperandClass(MCParsedAsmOperand *GOp, " << "MatchClassKind Kind) {\n"; OS << " " << Info.Target.getName() << "Operand &Operand = *(" << Info.Target.getName() << "Operand*)GOp;\n"; @@ -1667,7 +1702,8 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info, // Check for Token operands first. OS << " if (Operand.isToken())\n"; - OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n"; + OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind);" + << "\n\n"; // Check for register operands, including sub-classes. OS << " if (Operand.isReg()) {\n"; @@ -1681,7 +1717,7 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info, << it->first->getName() << ": OpKind = " << it->second->Name << "; break;\n"; OS << " }\n"; - OS << " return IsSubclass(OpKind, Kind);\n"; + OS << " return isSubclass(OpKind, Kind);\n"; OS << " }\n\n"; // Check the user classes. We don't care what order since we're only @@ -1708,8 +1744,8 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info, static void EmitIsSubclass(CodeGenTarget &Target, std::vector<ClassInfo*> &Infos, raw_ostream &OS) { - OS << "/// IsSubclass - Compute whether \\arg A is a subclass of \\arg B.\n"; - OS << "static bool IsSubclass(MatchClassKind A, MatchClassKind B) {\n"; + OS << "/// isSubclass - Compute whether \\arg A is a subclass of \\arg B.\n"; + OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n"; OS << " if (A == B)\n"; OS << " return true;\n\n"; @@ -1720,32 +1756,30 @@ static void EmitIsSubclass(CodeGenTarget &Target, ie = Infos.end(); it != ie; ++it) { ClassInfo &A = **it; - if (A.Kind != ClassInfo::Token) { - std::vector<StringRef> SuperClasses; - for (std::vector<ClassInfo*>::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &B = **it; - - if (&A != &B && A.isSubsetOf(B)) - SuperClasses.push_back(B.Name); - } + std::vector<StringRef> SuperClasses; + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + ie = Infos.end(); it != ie; ++it) { + ClassInfo &B = **it; - if (SuperClasses.empty()) - continue; + if (&A != &B && A.isSubsetOf(B)) + SuperClasses.push_back(B.Name); + } - OS << "\n case " << A.Name << ":\n"; + if (SuperClasses.empty()) + continue; - if (SuperClasses.size() == 1) { - OS << " return B == " << SuperClasses.back() << ";\n"; - continue; - } + OS << "\n case " << A.Name << ":\n"; - OS << " switch (B) {\n"; - OS << " default: return false;\n"; - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - OS << " case " << SuperClasses[i] << ": return true;\n"; - OS << " }\n"; + if (SuperClasses.size() == 1) { + OS << " return B == " << SuperClasses.back() << ";\n"; + continue; } + + OS << " switch (B) {\n"; + OS << " default: return false;\n"; + for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) + OS << " case " << SuperClasses[i] << ": return true;\n"; + OS << " }\n"; } OS << " }\n"; OS << "}\n\n"; @@ -1767,7 +1801,7 @@ static void EmitMatchTokenString(CodeGenTarget &Target, "return " + CI.Name + ";")); } - OS << "static MatchClassKind MatchTokenString(StringRef Name) {\n"; + OS << "static MatchClassKind matchTokenString(StringRef Name) {\n"; StringMatcher("Name", Matches, OS).Emit(); @@ -1905,7 +1939,7 @@ static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) { Info.getRecords().getAllDerivedDefinitions("MnemonicAlias"); if (Aliases.empty()) return false; - OS << "static void ApplyMnemonicAliases(StringRef &Mnemonic, " + OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " "unsigned Features) {\n"; // Keep track of all the aliases from a mnemonic. Use an std::map so that the @@ -1975,45 +2009,62 @@ static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) { return true; } +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, const AsmMatcherInfo &Info, StringRef ClassName) { // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " const char *Mnemonic;\n"; - OS << " unsigned OperandMask;\n"; - OS << " MatchClassKind Class;\n"; - OS << " unsigned RequiredFeatures;\n"; + OS << " static const char *const MnemonicTable;\n"; + OS << " uint32_t OperandMask;\n"; + OS << " uint32_t Mnemonic;\n"; + OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + << " RequiredFeatures;\n"; + OS << " " << getMinimalTypeForRange(Info.Classes.size()) + << " Class;\n\n"; + OS << " StringRef getMnemonic() const {\n"; + OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; + OS << " MnemonicTable[Mnemonic]);\n"; + OS << " }\n"; OS << " };\n\n"; OS << " // Predicate for searching for an opcode.\n"; OS << " struct LessOpcodeOperand {\n"; OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n"; - OS << " return StringRef(LHS.Mnemonic) < RHS;\n"; + OS << " return LHS.getMnemonic() < RHS;\n"; OS << " }\n"; OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n"; - OS << " return LHS < StringRef(RHS.Mnemonic);\n"; + OS << " return LHS < RHS.getMnemonic();\n"; OS << " }\n"; OS << " bool operator()(const OperandMatchEntry &LHS,"; OS << " const OperandMatchEntry &RHS) {\n"; - OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n"; + OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n"; OS << " }\n"; OS << " };\n"; OS << "} // end anonymous namespace.\n\n"; + StringToOffsetTable StringTable; + OS << "static const OperandMatchEntry OperandMatchTable[" << Info.OperandMatchInfo.size() << "] = {\n"; - OS << " /* Mnemonic, Operand List Mask, Operand Class, Features */\n"; + OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n"; for (std::vector<OperandMatchEntry>::const_iterator it = Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end(); it != ie; ++it) { const OperandMatchEntry &OMI = *it; const MatchableInfo &II = *OMI.MI; - OS << " { \"" << II.Mnemonic << "\"" - << ", " << OMI.OperandMask; + OS << " { " << OMI.OperandMask; OS << " /* "; bool printComma = false; @@ -2026,8 +2077,10 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, } OS << " */"; - OS << ", " << OMI.CI->Name - << ", "; + // Store a pascal-style length byte in the mnemonic. + std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false) + << " /* " << II.Mnemonic << " */, "; // Write the required features mask. if (!II.RequiredFeatures.empty()) { @@ -2037,15 +2090,22 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, } } else OS << "0"; + + OS << ", " << OMI.CI->Name; + OS << " },\n"; } OS << "};\n\n"; + OS << "const char *const OperandMatchEntry::MnemonicTable =\n"; + StringTable.EmitString(OS); + OS << ";\n\n"; + // Emit the operand class switch to call the correct custom parser for // the found operand class. OS << Target.getName() << ClassName << "::OperandMatchResultTy " << Target.getName() << ClassName << "::\n" - << "TryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>" + << "tryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>" << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; @@ -2094,7 +2154,7 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " *ie = MnemonicRange.second; it != ie; ++it) {\n"; OS << " // equal_range guarantees that instruction mnemonic matches.\n"; - OS << " assert(Mnemonic == it->Mnemonic);\n\n"; + OS << " assert(Mnemonic == it->getMnemonic());\n\n"; // Emit check that the required features are available. OS << " // check if the available features match\n"; @@ -2111,7 +2171,7 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit call to the custom parser method OS << " // call custom parse method to handle the operand\n"; OS << " OperandMatchResultTy Result = "; - OS << "TryCustomParseOperand(Operands, it->Class);\n"; + OS << "tryCustomParseOperand(Operands, it->Class);\n"; OS << " if (Result != MatchOperand_NoMatch)\n"; OS << " return Result;\n"; OS << " }\n\n"; @@ -2186,7 +2246,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " bool MnemonicIsValid(StringRef Mnemonic);\n"; OS << " unsigned MatchInstructionImpl(\n"; OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; - OS << " MCInst &Inst, unsigned &ErrorInfo);\n"; + OS << " MCInst &Inst, unsigned &ErrorInfo, unsigned VariantID = 0);\n"; if (Info.OperandMatchInfo.size()) { OS << "\n enum OperandMatchResultTy {\n"; @@ -2198,7 +2258,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; OS << " StringRef Mnemonic);\n"; - OS << " OperandMatchResultTy TryCustomParseOperand(\n"; + OS << " OperandMatchResultTy tryCustomParseOperand(\n"; OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; OS << " unsigned MCK);\n\n"; } @@ -2260,28 +2320,39 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // following the mnemonic. OS << "namespace {\n"; OS << " struct MatchEntry {\n"; - OS << " unsigned Opcode;\n"; - OS << " const char *Mnemonic;\n"; - OS << " ConversionKind ConvertFn;\n"; - OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n"; - OS << " unsigned RequiredFeatures;\n"; + OS << " static const char *const MnemonicTable;\n"; + OS << " uint32_t Mnemonic;\n"; + OS << " uint16_t Opcode;\n"; + OS << " " << getMinimalTypeForRange(Info.Matchables.size()) + << " ConvertFn;\n"; + OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + << " RequiredFeatures;\n"; + OS << " " << getMinimalTypeForRange(Info.Classes.size()) + << " Classes[" << MaxNumOperands << "];\n"; + OS << " uint8_t AsmVariantID;\n\n"; + OS << " StringRef getMnemonic() const {\n"; + OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; + OS << " MnemonicTable[Mnemonic]);\n"; + OS << " }\n"; OS << " };\n\n"; OS << " // Predicate for searching for an opcode.\n"; OS << " struct LessOpcode {\n"; OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n"; - OS << " return StringRef(LHS.Mnemonic) < RHS;\n"; + OS << " return LHS.getMnemonic() < RHS;\n"; OS << " }\n"; OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n"; - OS << " return LHS < StringRef(RHS.Mnemonic);\n"; + OS << " return LHS < RHS.getMnemonic();\n"; OS << " }\n"; OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n"; - OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n"; + OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n"; OS << " }\n"; OS << " };\n"; OS << "} // end anonymous namespace.\n\n"; + StringToOffsetTable StringTable; + OS << "static const MatchEntry MatchTable[" << Info.Matchables.size() << "] = {\n"; @@ -2290,16 +2361,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { it != ie; ++it) { MatchableInfo &II = **it; - OS << " { " << Target.getName() << "::" - << II.getResultInst()->TheDef->getName() << ", \"" << II.Mnemonic << "\"" - << ", " << II.ConversionFnKind << ", { "; - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; - - if (i) OS << ", "; - OS << Op.Class->Name; - } - OS << " }, "; + // Store a pascal-style length byte in the mnemonic. + std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) + << " /* " << II.Mnemonic << " */, " + << Target.getName() << "::" + << II.getResultInst()->TheDef->getName() << ", " + << II.ConversionFnKind << ", "; // Write the required features mask. if (!II.RequiredFeatures.empty()) { @@ -2310,11 +2378,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { } else OS << "0"; + OS << ", { "; + for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { + MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + + if (i) OS << ", "; + OS << Op.Class->Name; + } + OS << " }, " << II.AsmVariantID; OS << "},\n"; } OS << "};\n\n"; + OS << "const char *const MatchEntry::MnemonicTable =\n"; + StringTable.EmitString(OS); + OS << ";\n\n"; + // A method to determine if a mnemonic is in the list. OS << "bool " << Target.getName() << ClassName << "::\n" << "MnemonicIsValid(StringRef Mnemonic) {\n"; @@ -2330,7 +2410,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << Target.getName() << ClassName << "::\n" << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>" << " &Operands,\n"; - OS << " MCInst &Inst, unsigned &ErrorInfo) {\n"; + OS << " MCInst &Inst, unsigned &ErrorInfo,\n"; + OS << " unsigned VariantID) {\n"; // Emit code to get the available features. OS << " // Get the current feature set.\n"; @@ -2342,7 +2423,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (HasMnemonicAliases) { OS << " // Process all MnemonicAliases to remap the mnemonic.\n"; - OS << " ApplyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n"; + OS << " // FIXME : Add an entry in AsmParserVariant to check this.\n"; + OS << " if (!VariantID)\n"; + OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n"; } // Emit code to compute the class list for this operand vector. @@ -2375,16 +2458,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " it != ie; ++it) {\n"; OS << " // equal_range guarantees that instruction mnemonic matches.\n"; - OS << " assert(Mnemonic == it->Mnemonic);\n"; + OS << " assert(Mnemonic == it->getMnemonic());\n"; // Emit check that the subclasses match. + OS << " if (VariantID != it->AsmVariantID) continue;\n"; OS << " bool OperandsValid = true;\n"; OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; OS << " if (i + 1 >= Operands.size()) {\n"; OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n"; OS << " break;\n"; OS << " }\n"; - OS << " if (ValidateOperandClass(Operands[i+1], it->Classes[i]))\n"; + OS << " if (validateOperandClass(Operands[i+1], " + "(MatchClassKind)it->Classes[i]))\n"; OS << " continue;\n"; OS << " // If this operand is broken for all of the instances of this\n"; OS << " // mnemonic, keep track of it so we can report loc info.\n"; diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index 3123e11f774f..e0b0aace33e6 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -16,6 +16,7 @@ #include "AsmWriterInst.h" #include "CodeGenTarget.h" #include "StringToOffsetTable.h" +#include "SequenceToOffsetTable.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" @@ -277,12 +278,27 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i])); // Build an aggregate string, and build a table of offsets into it. - StringToOffsetTable StringTable; + SequenceToOffsetTable<std::string> StringTable; /// OpcodeInfo - This encodes the index of the string to use for the first /// chunk of the output as well as indices used for operand printing. std::vector<unsigned> OpcodeInfo; + // Add all strings to the string table upfront so it can generate an optimized + // representation. + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; + if (AWI != 0 && + AWI->Operands[0].OperandType == AsmWriterOperand::isLiteralTextOperand && + !AWI->Operands[0].Str.empty()) { + std::string Str = AWI->Operands[0].Str; + UnescapeString(Str); + StringTable.add(Str); + } + } + + StringTable.layout(); + unsigned MaxStringIdx = 0; for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; @@ -294,11 +310,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { AsmWriterOperand::isLiteralTextOperand || AWI->Operands[0].Str.empty()) { // Something handled by the asmwriter printer, but with no leading string. - Idx = StringTable.GetOrAddStringOffset(""); + Idx = StringTable.get(""); } else { std::string Str = AWI->Operands[0].Str; UnescapeString(Str); - Idx = StringTable.GetOrAddStringOffset(Str); + Idx = StringTable.get(Str); MaxStringIdx = std::max(MaxStringIdx, Idx); // Nuke the string from the operand list. It is now handled! @@ -373,9 +389,9 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << " };\n\n"; // Emit the string itself. - O << " const char *AsmStrs = \n"; - StringTable.EmitString(O); - O << ";\n\n"; + O << " const char AsmStrs[] = {\n"; + StringTable.emit(O, printChar); + O << " };\n\n"; O << " O << \"\\t\";\n\n"; @@ -461,13 +477,13 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { static void emitRegisterNameString(raw_ostream &O, StringRef AltName, - const std::vector<CodeGenRegister*> &Registers) { - StringToOffsetTable StringTable; - O << " static const unsigned RegAsmOffset" << AltName << "[] = {\n "; + const std::vector<CodeGenRegister*> &Registers) { + SequenceToOffsetTable<std::string> StringTable; + SmallVector<std::string, 4> AsmNames(Registers.size()); for (unsigned i = 0, e = Registers.size(); i != e; ++i) { const CodeGenRegister &Reg = *Registers[i]; + std::string &AsmName = AsmNames[i]; - std::string AsmName; // "NoRegAltName" is special. We don't need to do a lookup for that, // as it's just a reference to the default register name. if (AltName == "" || AltName == "NoRegAltName") { @@ -495,21 +511,22 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, AsmName = AltNames[Idx]; } } + StringTable.add(AsmName); + } - O << StringTable.GetOrAddStringOffset(AsmName); - if (((i + 1) % 14) == 0) - O << ",\n "; - else - O << ", "; + StringTable.layout(); + O << " static const char AsmStrs" << AltName << "[] = {\n"; + StringTable.emit(O, printChar); + O << " };\n\n"; + O << " static const unsigned RegAsmOffset" << AltName << "[] = {"; + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + if ((i % 14) == 0) + O << "\n "; + O << StringTable.get(AsmNames[i]) << ", "; } - O << "0\n" - << " };\n" + O << "\n };\n" << "\n"; - - O << " const char *AsmStrs" << AltName << " =\n"; - StringTable.EmitString(O); - O << ";\n"; } void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { @@ -544,7 +561,7 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { O << " const unsigned *RegAsmOffset;\n" << " const char *AsmStrs;\n" << " switch(AltIdx) {\n" - << " default: assert(0 && \"Invalid register alt name index!\");\n"; + << " default: llvm_unreachable(\"Invalid register alt name index!\");\n"; for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) { StringRef Namespace = AltNameIndices[1]->getValueAsString("Namespace"); StringRef AltName(AltNameIndices[i]->getName()); @@ -563,48 +580,6 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { << "}\n"; } -void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { - CodeGenTarget Target(Records); - Record *AsmWriter = Target.getAsmWriter(); - std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - - const std::vector<const CodeGenInstruction*> &NumberedInstructions = - Target.getInstructionsByEnumValue(); - - StringToOffsetTable StringTable; - O << -"\n\n#ifdef GET_INSTRUCTION_NAME\n" -"#undef GET_INSTRUCTION_NAME\n\n" -"/// getInstructionName: This method is automatically generated by tblgen\n" -"/// from the instruction set description. This returns the enum name of the\n" -"/// specified instruction.\n" - "const char *" << Target.getName() << ClassName - << "::getInstructionName(unsigned Opcode) {\n" - << " assert(Opcode < " << NumberedInstructions.size() - << " && \"Invalid instruction number!\");\n" - << "\n" - << " static const unsigned InstAsmOffset[] = {"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - const CodeGenInstruction &Inst = *NumberedInstructions[i]; - - std::string AsmName = Inst.TheDef->getName(); - if ((i % 14) == 0) - O << "\n "; - - O << StringTable.GetOrAddStringOffset(AsmName) << ", "; - } - O << "0\n" - << " };\n" - << "\n"; - - O << " const char *Strs =\n"; - StringTable.EmitString(O); - O << ";\n"; - - O << " return Strs+InstAsmOffset[Opcode];\n" - << "}\n\n#endif\n"; -} - namespace { // IAPrinter - Holds information about an InstAlias. Two InstAliases match if // they both have the same conditionals. In which case, we cannot print out the @@ -694,70 +669,7 @@ static void EmitGetMapOperandNumber(raw_ostream &O) { O << " I = OpMap.begin(), E = OpMap.end(); I != E; ++I)\n"; O << " if (I->first == Name)\n"; O << " return I->second;\n"; - O << " assert(false && \"Operand not in map!\");\n"; - O << " return 0;\n"; - O << "}\n\n"; -} - -void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) { - CodeGenTarget Target(Records); - - // Enumerate the register classes. - ArrayRef<CodeGenRegisterClass*> RegisterClasses = - Target.getRegBank().getRegClasses(); - - O << "namespace { // Register classes\n"; - O << " enum RegClass {\n"; - - // Emit the register enum value for each RegisterClass. - for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) { - if (I != 0) O << ",\n"; - O << " RC_" << RegisterClasses[I]->getName(); - } - - O << "\n };\n"; - O << "} // end anonymous namespace\n\n"; - - // Emit a function that returns 'true' if a regsiter is part of a particular - // register class. I.e., RAX is part of GR64 on X86. - O << "static bool regIsInRegisterClass" - << "(unsigned RegClass, unsigned Reg) {\n"; - - // Emit the switch that checks if a register belongs to a particular register - // class. - O << " switch (RegClass) {\n"; - O << " default: break;\n"; - - for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) { - const CodeGenRegisterClass &RC = *RegisterClasses[I]; - - // Give the register class a legal C name if it's anonymous. - std::string Name = RC.getName(); - O << " case RC_" << Name << ":\n"; - - // Emit the register list now. - unsigned IE = RC.getOrder().size(); - if (IE == 1) { - O << " if (Reg == " << getQualifiedName(RC.getOrder()[0]) << ")\n"; - O << " return true;\n"; - } else { - O << " switch (Reg) {\n"; - O << " default: break;\n"; - - for (unsigned II = 0; II != IE; ++II) { - Record *Reg = RC.getOrder()[II]; - O << " case " << getQualifiedName(Reg) << ":\n"; - } - - O << " return true;\n"; - O << " }\n"; - } - - O << " break;\n"; - } - - O << " }\n\n"; - O << " return false;\n"; + O << " llvm_unreachable(\"Operand not in map!\");\n"; O << "}\n\n"; } @@ -804,8 +716,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << "\n#ifdef PRINT_ALIAS_INSTR\n"; O << "#undef PRINT_ALIAS_INSTR\n\n"; - EmitRegIsInRegClass(O); - // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); @@ -858,7 +768,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; switch (RO.Kind) { - default: assert(0 && "unexpected InstAlias operand kind"); case CodeGenInstAlias::ResultOperand::K_Record: { const Record *Rec = RO.getRecord(); StringRef ROName = RO.getName(); @@ -872,9 +781,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (!IAP->isOpMapped(ROName)) { IAP->addOperand(ROName, i); - Cond = std::string("regIsInRegisterClass(RC_") + - CGA->ResultOperands[i].getRecord()->getName() + - ", MI->getOperand(" + llvm::utostr(i) + ").getReg())"; + Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + + CGA->ResultOperands[i].getRecord()->getName() + "RegClassID)" + ".contains(MI->getOperand(" + llvm::utostr(i) + ").getReg())"; IAP->addCond(Cond); } else { Cond = std::string("MI->getOperand(") + @@ -900,6 +809,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { IAP->addCond(Cond); break; case CodeGenInstAlias::ResultOperand::K_Reg: + // If this is zero_reg, something's playing tricks we're not + // equipped to handle. + if (!CGA->ResultOperands[i].getRegister()) { + CantHandle = true; + break; + } + Cond = std::string("MI->getOperand(") + llvm::utostr(i) + ").getReg() == " + Target.getName() + "::" + CGA->ResultOperands[i].getRegister()->getName(); @@ -1015,7 +931,6 @@ void AsmWriterEmitter::run(raw_ostream &O) { EmitPrintInstruction(O); EmitGetRegisterName(O); - EmitGetInstructionName(O); EmitPrintAliasInstruction(O); } diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h index 731e31cc746e..9719b202faab 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h @@ -37,8 +37,6 @@ namespace llvm { private: void EmitPrintInstruction(raw_ostream &o); void EmitGetRegisterName(raw_ostream &o); - void EmitGetInstructionName(raw_ostream &o); - void EmitRegIsInRegClass(raw_ostream &O); void EmitPrintAliasInstruction(raw_ostream &O); AsmWriterInst *getAsmWriterInstByID(unsigned ID) const { diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp index fcdaa082fb2a..afbb3a870894 100644 --- a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp +++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp @@ -96,7 +96,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "if (unsigned Reg = State.AllocateReg("; O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n"; } else { - O << IndentStr << "static const unsigned RegList" << ++Counter + O << IndentStr << "static const uint16_t RegList" << ++Counter << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { @@ -127,7 +127,7 @@ void CallingConvEmitter::EmitAction(Record *Action, unsigned RegListNumber = ++Counter; unsigned ShadowRegListNumber = ++Counter; - O << IndentStr << "static const unsigned RegList" << RegListNumber + O << IndentStr << "static const uint16_t RegList" << RegListNumber << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { @@ -136,7 +136,7 @@ void CallingConvEmitter::EmitAction(Record *Action, } O << "\n" << IndentStr << "};\n"; - O << IndentStr << "static const unsigned RegList" + O << IndentStr << "static const uint16_t RegList" << ShadowRegListNumber << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) { diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp index c5a152665b06..3943e8a40f87 100644 --- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -163,19 +163,19 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, --bit; } - unsigned opMask = ~0U >> (32-N); + uint64_t opMask = ~(uint64_t)0 >> (64-N); int opShift = beginVarBit - N + 1; opMask <<= opShift; opShift = beginInstBit - beginVarBit; if (opShift > 0) { - Case += " Value |= (op & " + utostr(opMask) + "U) << " + + Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) << " + itostr(opShift) + ";\n"; } else if (opShift < 0) { - Case += " Value |= (op & " + utostr(opMask) + "U) >> " + + Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) >> " + itostr(-opShift) + ";\n"; } else { - Case += " Value |= op & " + utostr(opMask) + "U;\n"; + Case += " Value |= op & UINT64_C(" + utostr(opMask) + ");\n"; } } } @@ -220,7 +220,7 @@ void CodeEmitterGen::run(raw_ostream &o) { Target.getInstructionsByEnumValue(); // Emit function declaration - o << "unsigned " << Target.getName(); + o << "uint64_t " << Target.getName(); if (MCEmitter) o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" << " SmallVectorImpl<MCFixup> &Fixups) const {\n"; @@ -228,7 +228,7 @@ void CodeEmitterGen::run(raw_ostream &o) { o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; // Emit instruction base values - o << " static const unsigned InstBits[] = {\n"; + o << " static const uint64_t InstBits[] = {\n"; for (std::vector<const CodeGenInstruction*>::const_iterator IN = NumberedInstructions.begin(), EN = NumberedInstructions.end(); @@ -238,21 +238,21 @@ void CodeEmitterGen::run(raw_ostream &o) { if (R->getValueAsString("Namespace") == "TargetOpcode" || R->getValueAsBit("isPseudo")) { - o << " 0U,\n"; + o << " UINT64_C(0),\n"; continue; } BitsInit *BI = R->getValueAsBitsInit("Inst"); // Start by filling in fixed values. - unsigned Value = 0; + uint64_t Value = 0; for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) - Value |= B->getValue() << (e-i-1); + Value |= (uint64_t)B->getValue() << (e-i-1); } - o << " " << Value << "U," << '\t' << "// " << R->getName() << "\n"; + o << " UINT64_C(" << Value << ")," << '\t' << "// " << R->getName() << "\n"; } - o << " 0U\n };\n"; + o << " UINT64_C(0)\n };\n"; // Map to accumulate all the cases. std::map<std::string, std::vector<std::string> > CaseMap; @@ -273,8 +273,8 @@ void CodeEmitterGen::run(raw_ostream &o) { // Emit initial function code o << " const unsigned opcode = MI.getOpcode();\n" - << " unsigned Value = InstBits[opcode];\n" - << " unsigned op = 0;\n" + << " uint64_t Value = InstBits[opcode];\n" + << " uint64_t op = 0;\n" << " (void)op; // suppress warning\n" << " switch (opcode) {\n"; diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index dbf166262bb6..d2ddf232b32a 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -18,8 +18,10 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" -#include <set> +#include "llvm/Support/ErrorHandling.h" #include <algorithm> +#include <cstdio> +#include <set> using namespace llvm; //===----------------------------------------------------------------------===// @@ -629,11 +631,11 @@ TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { } std::string TreePredicateFn::getPredCode() const { - return PatFragRec->getRecord()->getValueAsCode("PredicateCode"); + return PatFragRec->getRecord()->getValueAsString("PredicateCode"); } std::string TreePredicateFn::getImmCode() const { - return PatFragRec->getRecord()->getValueAsCode("ImmediateCode"); + return PatFragRec->getRecord()->getValueAsString("ImmediateCode"); } @@ -748,7 +750,7 @@ std::string PatternToMatch::getPredicateCheck() const { #ifndef NDEBUG Def->dump(); #endif - assert(0 && "Unknown predicate type!"); + llvm_unreachable("Unknown predicate type!"); } if (!PredicateCheck.empty()) PredicateCheck += " && "; @@ -839,7 +841,6 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); switch (ConstraintType) { - default: assert(0 && "Unknown constraint type!"); case SDTCisVT: // Operand must be a particular type. return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP); @@ -913,7 +914,7 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP); } } - return false; + llvm_unreachable("Invalid ConstraintType!"); } //===----------------------------------------------------------------------===// @@ -1609,10 +1610,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP); } else if (OperandNode->getName() == "unknown") { // Nothing to do. - } else { - assert(0 && "Unknown operand type!"); - abort(); - } + } else + llvm_unreachable("Unknown operand type!"); + MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); } @@ -2071,7 +2071,7 @@ void CodeGenDAGPatterns::ParseNodeTransforms() { while (!Xforms.empty()) { Record *XFormNode = Xforms.back(); Record *SDNode = XFormNode->getValueAsDef("Opcode"); - std::string Code = XFormNode->getValueAsCode("XFormFunction"); + std::string Code = XFormNode->getValueAsString("XFormFunction"); SDNodeXForms.insert(std::make_pair(XFormNode, NodeXForm(SDNode, Code))); Xforms.pop_back(); diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h index 936fd0146455..5a2d40aa7c86 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -19,6 +19,7 @@ #include "CodeGenIntrinsics.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" #include <set> #include <algorithm> #include <vector> @@ -723,8 +724,7 @@ public: if (Intrinsics[i].TheDef == R) return Intrinsics[i]; for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i) if (TgtIntrinsics[i].TheDef == R) return TgtIntrinsics[i]; - assert(0 && "Unknown intrinsic!"); - abort(); + llvm_unreachable("Unknown intrinsic!"); } const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const { @@ -732,8 +732,7 @@ public: return Intrinsics[IID-1]; if (IID-Intrinsics.size()-1 < TgtIntrinsics.size()) return TgtIntrinsics[IID-Intrinsics.size()-1]; - assert(0 && "Bad intrinsic ID!"); - abort(); + llvm_unreachable("Bad intrinsic ID!"); } unsigned getIntrinsicID(Record *R) const { @@ -741,8 +740,7 @@ public: if (Intrinsics[i].TheDef == R) return i; for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i) if (TgtIntrinsics[i].TheDef == R) return i + Intrinsics.size(); - assert(0 && "Unknown intrinsic!"); - abort(); + llvm_unreachable("Unknown intrinsic!"); } const DAGDefaultOperand &getDefaultOperand(Record *R) const { diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp index 53d499f39553..fb9ad9371bea 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -245,7 +245,7 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; Ops[DestOp.first].Constraints[DestOp.second] = - CGIOperandList::ConstraintInfo::getTied(FlatOpNo); + CGIOperandList::ConstraintInfo::getTied(FlatOpNo); } static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) { @@ -423,6 +423,18 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return true; } + // For register operands, the source register class can be a subclass + // of the instruction register class, not just an exact match. + if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) { + if (!InstOpRec->isSubClassOf("RegisterClass")) + return false; + if (!T.getRegisterClass(InstOpRec) + .hasSubClass(&T.getRegisterClass(ADI->getDef()))) + return false; + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + return true; + } + // Handle explicit registers. if (ADI && ADI->getDef()->isSubClassOf("Register")) { if (InstOpRec->isSubClassOf("OptionalDefOperand")) { @@ -456,14 +468,19 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, if (ADI && ADI->getDef()->getName() == "zero_reg") { // Check if this is an optional def. - if (!InstOpRec->isSubClassOf("OptionalDefOperand")) - throw TGError(Loc, "reg0 used for result that is not an " - "OptionalDefOperand!"); + // Tied operands where the source is a sub-operand of a complex operand + // need to represent both operands in the alias destination instruction. + // Allow zero_reg for the tied portion. This can and should go away once + // the MC representation of things doesn't use tied operands at all. + //if (!InstOpRec->isSubClassOf("OptionalDefOperand")) + // throw TGError(Loc, "reg0 used for result that is not an " + // "OptionalDefOperand!"); ResOp = ResultOperand(static_cast<Record*>(0)); return true; } + // Literal integers. if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) return false; @@ -475,6 +492,19 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return true; } + // If both are Operands with the same MVT, allow the conversion. It's + // up to the user to make sure the values are appropriate, just like + // for isel Pat's. + if (InstOpRec->isSubClassOf("Operand") && + ADI->getDef()->isSubClassOf("Operand")) { + // FIXME: What other attributes should we check here? Identical + // MIOperandInfo perhaps? + if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type")) + return false; + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + return true; + } + return false; } @@ -511,8 +541,11 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { unsigned AliasOpNo = 0; for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { - // Tied registers don't have an entry in the result dag. - if (ResultInst->Operands[i].getTiedRegister() != -1) + // Tied registers don't have an entry in the result dag unless they're part + // of a complex operand, in which case we include them anyways, as we + // don't have any other way to specify the whole operand. + if (ResultInst->Operands[i].MINumOperands == 1 && + ResultInst->Operands[i].getTiedRegister() != -1) continue; if (AliasOpNo >= Result->getNumArgs()) diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp index 8de461527955..7ce4f878a3e7 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -15,6 +15,7 @@ #include "CodeGenRegisters.h" #include "CodeGenTarget.h" #include "llvm/TableGen/Error.h" +#include "llvm/ADT/IntEqClasses.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -22,6 +23,57 @@ using namespace llvm; //===----------------------------------------------------------------------===// +// CodeGenSubRegIndex +//===----------------------------------------------------------------------===// + +CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) + : TheDef(R), + EnumValue(Enum) +{} + +std::string CodeGenSubRegIndex::getNamespace() const { + if (TheDef->getValue("Namespace")) + return TheDef->getValueAsString("Namespace"); + else + return ""; +} + +const std::string &CodeGenSubRegIndex::getName() const { + return TheDef->getName(); +} + +std::string CodeGenSubRegIndex::getQualifiedName() const { + std::string N = getNamespace(); + if (!N.empty()) + N += "::"; + N += getName(); + return N; +} + +void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { + std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf"); + if (Comps.empty()) + return; + if (Comps.size() != 2) + throw TGError(TheDef->getLoc(), "ComposedOf must have exactly two entries"); + CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); + CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); + CodeGenSubRegIndex *X = A->addComposite(B, this); + if (X) + throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); +} + +void CodeGenSubRegIndex::cleanComposites() { + // Clean out redundant mappings of the form this+X -> X. + for (CompMap::iterator i = Composed.begin(), e = Composed.end(); i != e;) { + CompMap::iterator j = i; + ++i; + if (j->first == j->second) + Composed.erase(j); + } +} + +//===----------------------------------------------------------------------===// // CodeGenRegister //===----------------------------------------------------------------------===// @@ -29,6 +81,7 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum) : TheDef(R), EnumValue(Enum), CostPerUse(R->getValueAsInt("CostPerUse")), + CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")), SubRegsComplete(false) {} @@ -37,12 +90,81 @@ const std::string &CodeGenRegister::getName() const { } namespace { - struct Orphan { - CodeGenRegister *SubReg; - Record *First, *Second; - Orphan(CodeGenRegister *r, Record *a, Record *b) - : SubReg(r), First(a), Second(b) {} - }; +// Iterate over all register units in a set of registers. +class RegUnitIterator { + CodeGenRegister::Set::const_iterator RegI, RegE; + CodeGenRegister::RegUnitList::const_iterator UnitI, UnitE; + +public: + RegUnitIterator(const CodeGenRegister::Set &Regs): + RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() { + + if (RegI != RegE) { + UnitI = (*RegI)->getRegUnits().begin(); + UnitE = (*RegI)->getRegUnits().end(); + advance(); + } + } + + bool isValid() const { return UnitI != UnitE; } + + unsigned operator* () const { assert(isValid()); return *UnitI; }; + + const CodeGenRegister *getReg() const { assert(isValid()); return *RegI; } + + /// Preincrement. Move to the next unit. + void operator++() { + assert(isValid() && "Cannot advance beyond the last operand"); + ++UnitI; + advance(); + } + +protected: + void advance() { + while (UnitI == UnitE) { + if (++RegI == RegE) + break; + UnitI = (*RegI)->getRegUnits().begin(); + UnitE = (*RegI)->getRegUnits().end(); + } + } +}; +} // namespace + +// Merge two RegUnitLists maintaining the order and removing duplicates. +// Overwrites MergedRU in the process. +static void mergeRegUnits(CodeGenRegister::RegUnitList &MergedRU, + const CodeGenRegister::RegUnitList &RRU) { + CodeGenRegister::RegUnitList LRU = MergedRU; + MergedRU.clear(); + std::set_union(LRU.begin(), LRU.end(), RRU.begin(), RRU.end(), + std::back_inserter(MergedRU)); +} + +// Return true of this unit appears in RegUnits. +static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) { + return std::count(RegUnits.begin(), RegUnits.end(), Unit); +} + +// Inherit register units from subregisters. +// Return true if the RegUnits changed. +bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) { + unsigned OldNumUnits = RegUnits.size(); + for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end(); + I != E; ++I) { + // Strangely a register may have itself as a subreg (self-cycle) e.g. XMM. + // Only create a unit if no other subregs have units. + CodeGenRegister *SR = I->second; + if (SR == this) { + // RegUnits are only empty during getSubRegs, prior to computing weight. + if (RegUnits.empty()) + RegUnits.push_back(RegBank.newRegUnit(0)); + continue; + } + // Merge the subregister's units into this register's RegUnits. + mergeRegUnits(RegUnits, SR->RegUnits); + } + return OldNumUnits != RegUnits.size(); } const CodeGenRegister::SubRegMap & @@ -53,23 +175,26 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { SubRegsComplete = true; std::vector<Record*> SubList = TheDef->getValueAsListOfDefs("SubRegs"); - std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); - if (SubList.size() != Indices.size()) + std::vector<Record*> IdxList = TheDef->getValueAsListOfDefs("SubRegIndices"); + if (SubList.size() != IdxList.size()) throw TGError(TheDef->getLoc(), "Register " + getName() + " SubRegIndices doesn't match SubRegs"); // First insert the direct subregs and make sure they are fully indexed. + SmallVector<CodeGenSubRegIndex*, 8> Indices; for (unsigned i = 0, e = SubList.size(); i != e; ++i) { CodeGenRegister *SR = RegBank.getReg(SubList[i]); - if (!SubRegs.insert(std::make_pair(Indices[i], SR)).second) - throw TGError(TheDef->getLoc(), "SubRegIndex " + Indices[i]->getName() + + CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(IdxList[i]); + Indices.push_back(Idx); + if (!SubRegs.insert(std::make_pair(Idx, SR)).second) + throw TGError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() + " appears twice in Register " + getName()); } // Keep track of inherited subregs and how they can be reached. - SmallVector<Orphan, 8> Orphans; + SmallPtrSet<CodeGenRegister*, 8> Orphans; - // Clone inherited subregs and place duplicate entries on Orphans. + // Clone inherited subregs and place duplicate entries in Orphans. // Here the order is important - earlier subregs take precedence. for (unsigned i = 0, e = SubList.size(); i != e; ++i) { CodeGenRegister *SR = RegBank.getReg(SubList[i]); @@ -83,7 +208,7 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; ++SI) { if (!SubRegs.insert(*SI).second) - Orphans.push_back(Orphan(SI->second, Indices[i], SI->first)); + Orphans.insert(SI->second); // Noop sub-register indexes are possible, so avoid duplicates. if (SI->second != SR) @@ -91,6 +216,33 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { } } + // Expand any composed subreg indices. + // If dsub_2 has ComposedOf = [qsub_1, dsub_0], and this register has a + // qsub_1 subreg, add a dsub_2 subreg. Keep growing Indices and process + // expanded subreg indices recursively. + for (unsigned i = 0; i != Indices.size(); ++i) { + CodeGenSubRegIndex *Idx = Indices[i]; + const CodeGenSubRegIndex::CompMap &Comps = Idx->getComposites(); + CodeGenRegister *SR = SubRegs[Idx]; + const SubRegMap &Map = SR->getSubRegs(RegBank); + + // Look at the possible compositions of Idx. + // They may not all be supported by SR. + for (CodeGenSubRegIndex::CompMap::const_iterator I = Comps.begin(), + E = Comps.end(); I != E; ++I) { + SubRegMap::const_iterator SRI = Map.find(I->first); + if (SRI == Map.end()) + continue; // Idx + I->first doesn't exist in SR. + // Add I->second as a name for the subreg SRI->second, assuming it is + // orphaned, and the name isn't already used for something else. + if (SubRegs.count(I->second) || !Orphans.erase(SRI->second)) + continue; + // We found a new name for the orphaned sub-register. + SubRegs.insert(std::make_pair(I->second, SRI->second)); + Indices.push_back(I->second); + } + } + // Process the composites. ListInit *Comps = TheDef->getValueAsListInit("CompositeIndices"); for (unsigned i = 0, e = Comps->size(); i != e; ++i) { @@ -103,6 +255,7 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex")) throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + Pat->getAsString()); + CodeGenSubRegIndex *BaseIdx = RegBank.getSubRegIdx(BaseIdxInit->getDef()); // Resolve list of subreg indices into R2. CodeGenRegister *R2 = this; @@ -112,8 +265,9 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + Pat->getAsString()); + CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(IdxInit->getDef()); const SubRegMap &R2Subs = R2->getSubRegs(RegBank); - SubRegMap::const_iterator ni = R2Subs.find(IdxInit->getDef()); + SubRegMap::const_iterator ni = R2Subs.find(Idx); if (ni == R2Subs.end()) throw TGError(TheDef->getLoc(), "Composite " + Pat->getAsString() + " refers to bad index in " + R2->getName()); @@ -121,35 +275,76 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { } // Insert composite index. Allow overriding inherited indices etc. - SubRegs[BaseIdxInit->getDef()] = R2; + SubRegs[BaseIdx] = R2; // R2 is no longer an orphan. - for (unsigned j = 0, je = Orphans.size(); j != je; ++j) - if (Orphans[j].SubReg == R2) - Orphans[j].SubReg = 0; + Orphans.erase(R2); } // Now Orphans contains the inherited subregisters without a direct index. // Create inferred indexes for all missing entries. - for (unsigned i = 0, e = Orphans.size(); i != e; ++i) { - Orphan &O = Orphans[i]; - if (!O.SubReg) - continue; - SubRegs[RegBank.getCompositeSubRegIndex(O.First, O.Second, true)] = - O.SubReg; + // Work backwards in the Indices vector in order to compose subregs bottom-up. + // Consider this subreg sequence: + // + // qsub_1 -> dsub_0 -> ssub_0 + // + // The qsub_1 -> dsub_0 composition becomes dsub_2, so the ssub_0 register + // can be reached in two different ways: + // + // qsub_1 -> ssub_0 + // dsub_2 -> ssub_0 + // + // We pick the latter composition because another register may have [dsub_0, + // dsub_1, dsub_2] subregs without neccessarily having a qsub_1 subreg. The + // dsub_2 -> ssub_0 composition can be shared. + while (!Indices.empty() && !Orphans.empty()) { + CodeGenSubRegIndex *Idx = Indices.pop_back_val(); + CodeGenRegister *SR = SubRegs[Idx]; + const SubRegMap &Map = SR->getSubRegs(RegBank); + for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; + ++SI) + if (Orphans.erase(SI->second)) + SubRegs[RegBank.getCompositeSubRegIndex(Idx, SI->first)] = SI->second; } + + // Initialize RegUnitList. A register with no subregisters creates its own + // unit. Otherwise, it inherits all its subregister's units. Because + // getSubRegs is called recursively, this processes the register hierarchy in + // postorder. + // + // TODO: We currently assume all register units correspond to a named "leaf" + // register. We should also unify register units for ad-hoc register + // aliases. This can be done by iteratively merging units for aliasing + // registers using a worklist. + assert(RegUnits.empty() && "Should only initialize RegUnits once"); + if (SubRegs.empty()) + RegUnits.push_back(RegBank.newRegUnit(0)); + else + inheritRegUnits(RegBank); return SubRegs; } void -CodeGenRegister::addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const { +CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet, + CodeGenRegBank &RegBank) const { assert(SubRegsComplete && "Must precompute sub-registers"); std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); for (unsigned i = 0, e = Indices.size(); i != e; ++i) { - CodeGenRegister *SR = SubRegs.find(Indices[i])->second; + CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(Indices[i]); + CodeGenRegister *SR = SubRegs.find(Idx)->second; if (OSet.insert(SR)) - SR->addSubRegsPreOrder(OSet); + SR->addSubRegsPreOrder(OSet, RegBank); + } +} + +// Get the sum of this register's unit weights. +unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const { + unsigned Weight = 0; + for (RegUnitList::const_iterator I = RegUnits.begin(), E = RegUnits.end(); + I != E; ++I) { + Weight += RegBank.getRegUnitWeight(*I); } + return Weight; } //===----------------------------------------------------------------------===// @@ -215,30 +410,40 @@ struct TupleExpander : SetTheory::Expander { for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) { RecordVal RV = Proto->getValues()[i]; + // Skip existing fields, like NAME. + if (NewReg->getValue(RV.getNameInit())) + continue; + + StringRef Field = RV.getName(); + // Replace the sub-register list with Tuple. - if (RV.getName() == "SubRegs") + if (Field == "SubRegs") RV.setValue(ListInit::get(Tuple, RegisterRecTy)); // Provide a blank AsmName. MC hacks are required anyway. - if (RV.getName() == "AsmName") + if (Field == "AsmName") RV.setValue(BlankName); // CostPerUse is aggregated from all Tuple members. - if (RV.getName() == "CostPerUse") + if (Field == "CostPerUse") RV.setValue(IntInit::get(CostPerUse)); + // Composite registers are always covered by sub-registers. + if (Field == "CoveredBySubRegs") + RV.setValue(BitInit::get(true)); + // Copy fields from the RegisterTuples def. - if (RV.getName() == "SubRegIndices" || - RV.getName() == "CompositeIndices") { - NewReg->addValue(*Def->getValue(RV.getName())); + if (Field == "SubRegIndices" || + Field == "CompositeIndices") { + NewReg->addValue(*Def->getValue(Field)); continue; } // Some fields get their default uninitialized value. - if (RV.getName() == "DwarfNumbers" || - RV.getName() == "DwarfAlias" || - RV.getName() == "Aliases") { - if (const RecordVal *DefRV = RegisterCl->getValue(RV.getName())) + if (Field == "DwarfNumbers" || + Field == "DwarfAlias" || + Field == "Aliases") { + if (const RecordVal *DefRV = RegisterCl->getValue(Field)) NewReg->addValue(*DefRV); continue; } @@ -330,7 +535,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) SpillAlignment = R->getValueAsInt("Alignment"); CopyCost = R->getValueAsInt("CopyCost"); Allocatable = R->getValueAsBit("isAllocatable"); - AltOrderSelect = R->getValueAsCode("AltOrderSelect"); + AltOrderSelect = R->getValueAsString("AltOrderSelect"); } // Create an inferred register class that was missing from the .td files. @@ -448,7 +653,7 @@ static int TopoOrderRC(const void *PA, const void *PB) { return 1; // Finally order by name as a tie breaker. - return A->getName() < B->getName(); + return StringRef(A->getName()).compare(B->getName()); } std::string CodeGenRegisterClass::getQualifiedName() const { @@ -504,6 +709,30 @@ void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) { RegClasses[rci]->inheritProperties(RegBank); } +void +CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx, + BitVector &Out) const { + DenseMap<CodeGenSubRegIndex*, + SmallPtrSet<CodeGenRegisterClass*, 8> >::const_iterator + FindI = SuperRegClasses.find(SubIdx); + if (FindI == SuperRegClasses.end()) + return; + for (SmallPtrSet<CodeGenRegisterClass*, 8>::const_iterator I = + FindI->second.begin(), E = FindI->second.end(); I != E; ++I) + Out.set((*I)->EnumValue); +} + +// Populate a unique sorted list of units from a register set. +void CodeGenRegisterClass::buildRegUnitSet( + std::vector<unsigned> &RegUnits) const { + std::vector<unsigned> TmpUnits; + for (RegUnitIterator UnitI(Members); UnitI.isValid(); ++UnitI) + TmpUnits.push_back(*UnitI); + std::sort(TmpUnits.begin(), TmpUnits.end()); + std::unique_copy(TmpUnits.begin(), TmpUnits.end(), + std::back_inserter(RegUnits)); +} + //===----------------------------------------------------------------------===// // CodeGenRegBank //===----------------------------------------------------------------------===// @@ -511,13 +740,19 @@ void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) { CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { // Configure register Sets to understand register classes and tuples. Sets.addFieldExpander("RegisterClass", "MemberList"); + Sets.addFieldExpander("CalleeSavedRegs", "SaveList"); Sets.addExpander("RegisterTuples", new TupleExpander()); // Read in the user-defined (named) sub-register indices. // More indices will be synthesized later. - SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex"); - std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord()); - NumNamedIndices = SubRegIndices.size(); + std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex"); + std::sort(SRIs.begin(), SRIs.end(), LessRecord()); + NumNamedIndices = SRIs.size(); + for (unsigned i = 0, e = SRIs.size(); i != e; ++i) + getSubRegIdx(SRIs[i]); + // Build composite maps from ComposedOf fields. + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + SubRegIndices[i]->updateComponents(*this); // Read in the register definitions. std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register"); @@ -538,9 +773,14 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { // Precompute all sub-register maps now all the registers are known. // This will create Composite entries for all inferred sub-register indices. + NumRegUnits = 0; for (unsigned i = 0, e = Registers.size(); i != e; ++i) Registers[i]->getSubRegs(*this); + // Native register units are associated with a leaf register. They've all been + // discovered now. + NumNativeRegUnits = NumRegUnits; + // Read in register class definitions. std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); if (RCs.empty()) @@ -561,6 +801,15 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { CodeGenRegisterClass::computeSubClasses(*this); } +CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { + CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; + if (Idx) + return Idx; + Idx = new CodeGenSubRegIndex(Def, SubRegIndices.size() + 1); + SubRegIndices.push_back(Idx); + return Idx; +} + CodeGenRegister *CodeGenRegBank::getReg(Record *Def) { CodeGenRegister *&Reg = Def2Reg[Def]; if (Reg) @@ -582,6 +831,23 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) { Key2RC.insert(std::make_pair(K, RC)); } +// Create a synthetic sub-class if it is missing. +CodeGenRegisterClass* +CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC, + const CodeGenRegister::Set *Members, + StringRef Name) { + // Synthetic sub-class has the same size and alignment as RC. + CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment); + RCKeyMap::const_iterator FoundI = Key2RC.find(K); + if (FoundI != Key2RC.end()) + return FoundI->second; + + // Sub-class doesn't exist, create a new one. + CodeGenRegisterClass *NewRC = new CodeGenRegisterClass(Name, K); + addToMaps(NewRC); + return NewRC; +} + CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { if (CodeGenRegisterClass *RC = Def2RC[Def]) return RC; @@ -589,34 +855,28 @@ CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { throw TGError(Def->getLoc(), "Not a known RegisterClass!"); } -Record *CodeGenRegBank::getCompositeSubRegIndex(Record *A, Record *B, - bool create) { +CodeGenSubRegIndex* +CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A, + CodeGenSubRegIndex *B) { // Look for an existing entry. - Record *&Comp = Composite[std::make_pair(A, B)]; - if (Comp || !create) + CodeGenSubRegIndex *Comp = A->compose(B); + if (Comp) return Comp; // None exists, synthesize one. std::string Name = A->getName() + "_then_" + B->getName(); - Comp = new Record(Name, SMLoc(), Records); - SubRegIndices.push_back(Comp); + Comp = getSubRegIdx(new Record(Name, SMLoc(), Records)); + A->addComposite(B, Comp); return Comp; } -unsigned CodeGenRegBank::getSubRegIndexNo(Record *idx) { - std::vector<Record*>::const_iterator i = - std::find(SubRegIndices.begin(), SubRegIndices.end(), idx); - assert(i != SubRegIndices.end() && "Not a SubRegIndex"); - return (i - SubRegIndices.begin()) + 1; -} - void CodeGenRegBank::computeComposites() { for (unsigned i = 0, e = Registers.size(); i != e; ++i) { CodeGenRegister *Reg1 = Registers[i]; const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end(); i1 != e1; ++i1) { - Record *Idx1 = i1->first; + CodeGenSubRegIndex *Idx1 = i1->first; CodeGenRegister *Reg2 = i1->second; // Ignore identity compositions. if (Reg1 == Reg2) @@ -625,7 +885,7 @@ void CodeGenRegBank::computeComposites() { // Try composing Idx1 with another SubRegIndex. for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM2.begin(), e2 = SRM2.end(); i2 != e2; ++i2) { - std::pair<Record*, Record*> IdxPair(Idx1, i2->first); + CodeGenSubRegIndex *Idx2 = i2->first; CodeGenRegister *Reg3 = i2->second; // Ignore identity compositions. if (Reg2 == Reg3) @@ -634,16 +894,13 @@ void CodeGenRegBank::computeComposites() { for (CodeGenRegister::SubRegMap::const_iterator i1d = SRM1.begin(), e1d = SRM1.end(); i1d != e1d; ++i1d) { if (i1d->second == Reg3) { - std::pair<CompositeMap::iterator, bool> Ins = - Composite.insert(std::make_pair(IdxPair, i1d->first)); // Conflicting composition? Emit a warning but allow it. - if (!Ins.second && Ins.first->second != i1d->first) { - errs() << "Warning: SubRegIndex " << getQualifiedName(Idx1) - << " and " << getQualifiedName(IdxPair.second) + if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, i1d->first)) + errs() << "Warning: SubRegIndex " << Idx1->getQualifiedName() + << " and " << Idx2->getQualifiedName() << " compose ambiguously as " - << getQualifiedName(Ins.first->second) << " or " - << getQualifiedName(i1d->first) << "\n"; - } + << Prev->getQualifiedName() << " or " + << i1d->first->getQualifiedName() << "\n"; } } } @@ -652,12 +909,388 @@ void CodeGenRegBank::computeComposites() { // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid // compositions, so remove any mappings of that form. - for (CompositeMap::iterator i = Composite.begin(), e = Composite.end(); - i != e;) { - CompositeMap::iterator j = i; - ++i; - if (j->first.second == j->second) - Composite.erase(j); + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + SubRegIndices[i]->cleanComposites(); +} + +namespace { +// UberRegSet is a helper class for computeRegUnitWeights. Each UberRegSet is +// the transitive closure of the union of overlapping register +// classes. Together, the UberRegSets form a partition of the registers. If we +// consider overlapping register classes to be connected, then each UberRegSet +// is a set of connected components. +// +// An UberRegSet will likely be a horizontal slice of register names of +// the same width. Nontrivial subregisters should then be in a separate +// UberRegSet. But this property isn't required for valid computation of +// register unit weights. +// +// A Weight field caches the max per-register unit weight in each UberRegSet. +// +// A set of SingularDeterminants flags single units of some register in this set +// for which the unit weight equals the set weight. These units should not have +// their weight increased. +struct UberRegSet { + CodeGenRegister::Set Regs; + unsigned Weight; + CodeGenRegister::RegUnitList SingularDeterminants; + + UberRegSet(): Weight(0) {} +}; +} // namespace + +// Partition registers into UberRegSets, where each set is the transitive +// closure of the union of overlapping register classes. +// +// UberRegSets[0] is a special non-allocatable set. +static void computeUberSets(std::vector<UberRegSet> &UberSets, + std::vector<UberRegSet*> &RegSets, + CodeGenRegBank &RegBank) { + + const std::vector<CodeGenRegister*> &Registers = RegBank.getRegisters(); + + // The Register EnumValue is one greater than its index into Registers. + assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + "register enum value mismatch"); + + // For simplicitly make the SetID the same as EnumValue. + IntEqClasses UberSetIDs(Registers.size()+1); + std::set<unsigned> AllocatableRegs; + for (unsigned i = 0, e = RegBank.getRegClasses().size(); i != e; ++i) { + + CodeGenRegisterClass *RegClass = RegBank.getRegClasses()[i]; + if (!RegClass->Allocatable) + continue; + + const CodeGenRegister::Set &Regs = RegClass->getMembers(); + if (Regs.empty()) + continue; + + unsigned USetID = UberSetIDs.findLeader((*Regs.begin())->EnumValue); + assert(USetID && "register number 0 is invalid"); + + AllocatableRegs.insert((*Regs.begin())->EnumValue); + for (CodeGenRegister::Set::const_iterator I = llvm::next(Regs.begin()), + E = Regs.end(); I != E; ++I) { + AllocatableRegs.insert((*I)->EnumValue); + UberSetIDs.join(USetID, (*I)->EnumValue); + } + } + // Combine non-allocatable regs. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + unsigned RegNum = Registers[i]->EnumValue; + if (AllocatableRegs.count(RegNum)) + continue; + + UberSetIDs.join(0, RegNum); + } + UberSetIDs.compress(); + + // Make the first UberSet a special unallocatable set. + unsigned ZeroID = UberSetIDs[0]; + + // Insert Registers into the UberSets formed by union-find. + // Do not resize after this. + UberSets.resize(UberSetIDs.getNumClasses()); + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + const CodeGenRegister *Reg = Registers[i]; + unsigned USetID = UberSetIDs[Reg->EnumValue]; + if (!USetID) + USetID = ZeroID; + else if (USetID == ZeroID) + USetID = 0; + + UberRegSet *USet = &UberSets[USetID]; + USet->Regs.insert(Reg); + RegSets[i] = USet; + } +} + +// Recompute each UberSet weight after changing unit weights. +static void computeUberWeights(std::vector<UberRegSet> &UberSets, + CodeGenRegBank &RegBank) { + // Skip the first unallocatable set. + for (std::vector<UberRegSet>::iterator I = llvm::next(UberSets.begin()), + E = UberSets.end(); I != E; ++I) { + + // Initialize all unit weights in this set, and remember the max units/reg. + const CodeGenRegister *Reg = 0; + unsigned MaxWeight = 0, Weight = 0; + for (RegUnitIterator UnitI(I->Regs); UnitI.isValid(); ++UnitI) { + if (Reg != UnitI.getReg()) { + if (Weight > MaxWeight) + MaxWeight = Weight; + Reg = UnitI.getReg(); + Weight = 0; + } + unsigned UWeight = RegBank.getRegUnitWeight(*UnitI); + if (!UWeight) { + UWeight = 1; + RegBank.increaseRegUnitWeight(*UnitI, UWeight); + } + Weight += UWeight; + } + if (Weight > MaxWeight) + MaxWeight = Weight; + + // Update the set weight. + I->Weight = MaxWeight; + + // Find singular determinants. + for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(), + RegE = I->Regs.end(); RegI != RegE; ++RegI) { + if ((*RegI)->getRegUnits().size() == 1 + && (*RegI)->getWeight(RegBank) == I->Weight) + mergeRegUnits(I->SingularDeterminants, (*RegI)->getRegUnits()); + } + } +} + +// normalizeWeight is a computeRegUnitWeights helper that adjusts the weight of +// a register and its subregisters so that they have the same weight as their +// UberSet. Self-recursion processes the subregister tree in postorder so +// subregisters are normalized first. +// +// Side effects: +// - creates new adopted register units +// - causes superregisters to inherit adopted units +// - increases the weight of "singular" units +// - induces recomputation of UberWeights. +static bool normalizeWeight(CodeGenRegister *Reg, + std::vector<UberRegSet> &UberSets, + std::vector<UberRegSet*> &RegSets, + CodeGenRegister::RegUnitList &NormalUnits, + CodeGenRegBank &RegBank) { + bool Changed = false; + const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(), + SRE = SRM.end(); SRI != SRE; ++SRI) { + if (SRI->second == Reg) + continue; // self-cycles happen + + Changed |= + normalizeWeight(SRI->second, UberSets, RegSets, NormalUnits, RegBank); + } + // Postorder register normalization. + + // Inherit register units newly adopted by subregisters. + if (Reg->inheritRegUnits(RegBank)) + computeUberWeights(UberSets, RegBank); + + // Check if this register is too skinny for its UberRegSet. + UberRegSet *UberSet = RegSets[RegBank.getRegIndex(Reg)]; + + unsigned RegWeight = Reg->getWeight(RegBank); + if (UberSet->Weight > RegWeight) { + // A register unit's weight can be adjusted only if it is the singular unit + // for this register, has not been used to normalize a subregister's set, + // and has not already been used to singularly determine this UberRegSet. + unsigned AdjustUnit = Reg->getRegUnits().front(); + if (Reg->getRegUnits().size() != 1 + || hasRegUnit(NormalUnits, AdjustUnit) + || hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) { + // We don't have an adjustable unit, so adopt a new one. + AdjustUnit = RegBank.newRegUnit(UberSet->Weight - RegWeight); + Reg->adoptRegUnit(AdjustUnit); + // Adopting a unit does not immediately require recomputing set weights. + } + else { + // Adjust the existing single unit. + RegBank.increaseRegUnitWeight(AdjustUnit, UberSet->Weight - RegWeight); + // The unit may be shared among sets and registers within this set. + computeUberWeights(UberSets, RegBank); + } + Changed = true; + } + + // Mark these units normalized so superregisters can't change their weights. + mergeRegUnits(NormalUnits, Reg->getRegUnits()); + + return Changed; +} + +// Compute a weight for each register unit created during getSubRegs. +// +// The goal is that two registers in the same class will have the same weight, +// where each register's weight is defined as sum of its units' weights. +void CodeGenRegBank::computeRegUnitWeights() { + assert(RegUnitWeights.empty() && "Only initialize RegUnitWeights once"); + + // Only allocatable units will be initialized to nonzero weight. + RegUnitWeights.resize(NumRegUnits); + + std::vector<UberRegSet> UberSets; + std::vector<UberRegSet*> RegSets(Registers.size()); + computeUberSets(UberSets, RegSets, *this); + // UberSets and RegSets are now immutable. + + computeUberWeights(UberSets, *this); + + // Iterate over each Register, normalizing the unit weights until reaching + // a fix point. + unsigned NumIters = 0; + for (bool Changed = true; Changed; ++NumIters) { + assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights"); + Changed = false; + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister::RegUnitList NormalUnits; + Changed |= + normalizeWeight(Registers[i], UberSets, RegSets, NormalUnits, *this); + } + } +} + +// Find a set in UniqueSets with the same elements as Set. +// Return an iterator into UniqueSets. +static std::vector<RegUnitSet>::const_iterator +findRegUnitSet(const std::vector<RegUnitSet> &UniqueSets, + const RegUnitSet &Set) { + std::vector<RegUnitSet>::const_iterator + I = UniqueSets.begin(), E = UniqueSets.end(); + for(;I != E; ++I) { + if (I->Units == Set.Units) + break; + } + return I; +} + +// Return true if the RUSubSet is a subset of RUSuperSet. +static bool isRegUnitSubSet(const std::vector<unsigned> &RUSubSet, + const std::vector<unsigned> &RUSuperSet) { + return std::includes(RUSuperSet.begin(), RUSuperSet.end(), + RUSubSet.begin(), RUSubSet.end()); +} + +// Iteratively prune unit sets. +void CodeGenRegBank::pruneUnitSets() { + assert(RegClassUnitSets.empty() && "this invalidates RegClassUnitSets"); + + // Form an equivalence class of UnitSets with no significant difference. + std::vector<unsigned> SuperSetIDs; + for (unsigned SubIdx = 0, EndIdx = RegUnitSets.size(); + SubIdx != EndIdx; ++SubIdx) { + const RegUnitSet &SubSet = RegUnitSets[SubIdx]; + unsigned SuperIdx = 0; + for (; SuperIdx != EndIdx; ++SuperIdx) { + if (SuperIdx == SubIdx) + continue; + + const RegUnitSet &SuperSet = RegUnitSets[SuperIdx]; + if (isRegUnitSubSet(SubSet.Units, SuperSet.Units) + && (SubSet.Units.size() + 3 > SuperSet.Units.size())) { + break; + } + } + if (SuperIdx == EndIdx) + SuperSetIDs.push_back(SubIdx); + } + // Populate PrunedUnitSets with each equivalence class's superset. + std::vector<RegUnitSet> PrunedUnitSets(SuperSetIDs.size()); + for (unsigned i = 0, e = SuperSetIDs.size(); i != e; ++i) { + unsigned SuperIdx = SuperSetIDs[i]; + PrunedUnitSets[i].Name = RegUnitSets[SuperIdx].Name; + PrunedUnitSets[i].Units.swap(RegUnitSets[SuperIdx].Units); + } + RegUnitSets.swap(PrunedUnitSets); +} + +// Create a RegUnitSet for each RegClass that contains all units in the class +// including adopted units that are necessary to model register pressure. Then +// iteratively compute RegUnitSets such that the union of any two overlapping +// RegUnitSets is repreresented. +// +// RegisterInfoEmitter will map each RegClass to its RegUnitClass and any +// RegUnitSet that is a superset of that RegUnitClass. +void CodeGenRegBank::computeRegUnitSets() { + + // Compute a unique RegUnitSet for each RegClass. + const ArrayRef<CodeGenRegisterClass*> &RegClasses = getRegClasses(); + unsigned NumRegClasses = RegClasses.size(); + for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { + if (!RegClasses[RCIdx]->Allocatable) + continue; + + // Speculatively grow the RegUnitSets to hold the new set. + RegUnitSets.resize(RegUnitSets.size() + 1); + RegUnitSets.back().Name = RegClasses[RCIdx]->getName(); + + // Compute a sorted list of units in this class. + RegClasses[RCIdx]->buildRegUnitSet(RegUnitSets.back().Units); + + // Find an existing RegUnitSet. + std::vector<RegUnitSet>::const_iterator SetI = + findRegUnitSet(RegUnitSets, RegUnitSets.back()); + if (SetI != llvm::prior(RegUnitSets.end())) + RegUnitSets.pop_back(); + } + + // Iteratively prune unit sets. + pruneUnitSets(); + + // Iterate over all unit sets, including new ones added by this loop. + unsigned NumRegUnitSubSets = RegUnitSets.size(); + for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) { + // In theory, this is combinatorial. In practice, it needs to be bounded + // by a small number of sets for regpressure to be efficient. + // If the assert is hit, we need to implement pruning. + assert(Idx < (2*NumRegUnitSubSets) && "runaway unit set inference"); + + // Compare new sets with all original classes. + for (unsigned SearchIdx = (Idx >= NumRegUnitSubSets) ? 0 : Idx+1; + SearchIdx != EndIdx; ++SearchIdx) { + std::set<unsigned> Intersection; + std::set_intersection(RegUnitSets[Idx].Units.begin(), + RegUnitSets[Idx].Units.end(), + RegUnitSets[SearchIdx].Units.begin(), + RegUnitSets[SearchIdx].Units.end(), + std::inserter(Intersection, Intersection.begin())); + if (Intersection.empty()) + continue; + + // Speculatively grow the RegUnitSets to hold the new set. + RegUnitSets.resize(RegUnitSets.size() + 1); + RegUnitSets.back().Name = + RegUnitSets[Idx].Name + "+" + RegUnitSets[SearchIdx].Name; + + std::set_union(RegUnitSets[Idx].Units.begin(), + RegUnitSets[Idx].Units.end(), + RegUnitSets[SearchIdx].Units.begin(), + RegUnitSets[SearchIdx].Units.end(), + std::inserter(RegUnitSets.back().Units, + RegUnitSets.back().Units.begin())); + + // Find an existing RegUnitSet, or add the union to the unique sets. + std::vector<RegUnitSet>::const_iterator SetI = + findRegUnitSet(RegUnitSets, RegUnitSets.back()); + if (SetI != llvm::prior(RegUnitSets.end())) + RegUnitSets.pop_back(); + } + } + + // Iteratively prune unit sets after inferring supersets. + pruneUnitSets(); + + // For each register class, list the UnitSets that are supersets. + RegClassUnitSets.resize(NumRegClasses); + for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { + if (!RegClasses[RCIdx]->Allocatable) + continue; + + // Recompute the sorted list of units in this class. + std::vector<unsigned> RegUnits; + RegClasses[RCIdx]->buildRegUnitSet(RegUnits); + + // Don't increase pressure for unallocatable regclasses. + if (RegUnits.empty()) + continue; + + // Find all supersets. + for (unsigned USIdx = 0, USEnd = RegUnitSets.size(); + USIdx != USEnd; ++USIdx) { + if (isRegUnitSubSet(RegUnits, RegUnitSets[USIdx].Units)) + RegClassUnitSets[RCIdx].push_back(USIdx); + } + assert(!RegClassUnitSets[RCIdx].empty() && "missing unit set for regclass"); } } @@ -737,62 +1370,187 @@ computeOverlaps(std::map<const CodeGenRegister*, CodeGenRegister::Set> &Map) { void CodeGenRegBank::computeDerivedInfo() { computeComposites(); + + // Compute a weight for each register unit created during getSubRegs. + // This may create adopted register units (with unit # >= NumNativeRegUnits). + computeRegUnitWeights(); + + // Compute a unique set of RegUnitSets. One for each RegClass and inferred + // supersets for the union of overlapping sets. + computeRegUnitSets(); } -// Infer missing register classes. // -// For every register class RC, make sure that the set of registers in RC with -// a given SubIxx sub-register form a register class. -void CodeGenRegBank::computeInferredRegisterClasses() { - // When this function is called, the register classes have not been sorted - // and assigned EnumValues yet. That means getSubClasses(), - // getSuperClasses(), and hasSubClass() functions are defunct. +// Synthesize missing register class intersections. +// +// Make sure that sub-classes of RC exists such that getCommonSubClass(RC, X) +// returns a maximal register class for all X. +// +void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { + for (unsigned rci = 0, rce = RegClasses.size(); rci != rce; ++rci) { + CodeGenRegisterClass *RC1 = RC; + CodeGenRegisterClass *RC2 = RegClasses[rci]; + if (RC1 == RC2) + continue; - // Map SubRegIndex to register set. - typedef std::map<Record*, CodeGenRegister::Set, LessRecord> SubReg2SetMap; + // Compute the set intersection of RC1 and RC2. + const CodeGenRegister::Set &Memb1 = RC1->getMembers(); + const CodeGenRegister::Set &Memb2 = RC2->getMembers(); + CodeGenRegister::Set Intersection; + std::set_intersection(Memb1.begin(), Memb1.end(), + Memb2.begin(), Memb2.end(), + std::inserter(Intersection, Intersection.begin()), + CodeGenRegister::Less()); + + // Skip disjoint class pairs. + if (Intersection.empty()) + continue; - // Visit all register classes, including the ones being added by the loop. - for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { - CodeGenRegisterClass &RC = *RegClasses[rci]; + // If RC1 and RC2 have different spill sizes or alignments, use the + // larger size for sub-classing. If they are equal, prefer RC1. + if (RC2->SpillSize > RC1->SpillSize || + (RC2->SpillSize == RC1->SpillSize && + RC2->SpillAlignment > RC1->SpillAlignment)) + std::swap(RC1, RC2); - // Compute the set of registers supporting each SubRegIndex. - SubReg2SetMap SRSets; - for (CodeGenRegister::Set::const_iterator RI = RC.getMembers().begin(), - RE = RC.getMembers().end(); RI != RE; ++RI) { - const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs(); - for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), - E = SRM.end(); I != E; ++I) - SRSets[I->first].insert(*RI); + getOrCreateSubClass(RC1, &Intersection, + RC1->getName() + "_and_" + RC2->getName()); + } +} + +// +// Synthesize missing sub-classes for getSubClassWithSubReg(). +// +// Make sure that the set of registers in RC with a given SubIdx sub-register +// form a register class. Update RC->SubClassWithSubReg. +// +void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { + // Map SubRegIndex to set of registers in RC supporting that SubRegIndex. + typedef std::map<CodeGenSubRegIndex*, CodeGenRegister::Set, + CodeGenSubRegIndex::Less> SubReg2SetMap; + + // Compute the set of registers supporting each SubRegIndex. + SubReg2SetMap SRSets; + for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), + RE = RC->getMembers().end(); RI != RE; ++RI) { + const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), + E = SRM.end(); I != E; ++I) + SRSets[I->first].insert(*RI); + } + + // Find matching classes for all SRSets entries. Iterate in SubRegIndex + // numerical order to visit synthetic indices last. + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; + SubReg2SetMap::const_iterator I = SRSets.find(SubIdx); + // Unsupported SubRegIndex. Skip it. + if (I == SRSets.end()) + continue; + // In most cases, all RC registers support the SubRegIndex. + if (I->second.size() == RC->getMembers().size()) { + RC->setSubClassWithSubReg(SubIdx, RC); + continue; + } + // This is a real subset. See if we have a matching class. + CodeGenRegisterClass *SubRC = + getOrCreateSubClass(RC, &I->second, + RC->getName() + "_with_" + I->first->getName()); + RC->setSubClassWithSubReg(SubIdx, SubRC); + } +} + +// +// Synthesize missing sub-classes of RC for getMatchingSuperRegClass(). +// +// Create sub-classes of RC such that getMatchingSuperRegClass(RC, SubIdx, X) +// has a maximal result for any SubIdx and any X >= FirstSubRegRC. +// + +void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, + unsigned FirstSubRegRC) { + SmallVector<std::pair<const CodeGenRegister*, + const CodeGenRegister*>, 16> SSPairs; + + // Iterate in SubRegIndex numerical order to visit synthetic indices last. + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; + // Skip indexes that aren't fully supported by RC's registers. This was + // computed by inferSubClassWithSubReg() above which should have been + // called first. + if (RC->getSubClassWithSubReg(SubIdx) != RC) + continue; + + // Build list of (Super, Sub) pairs for this SubIdx. + SSPairs.clear(); + for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), + RE = RC->getMembers().end(); RI != RE; ++RI) { + const CodeGenRegister *Super = *RI; + const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second; + assert(Sub && "Missing sub-register"); + SSPairs.push_back(std::make_pair(Super, Sub)); } - // Find matching classes for all SRSets entries. Iterate in SubRegIndex - // numerical order to visit synthetic indices last. - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - Record *SubIdx = SubRegIndices[sri]; - SubReg2SetMap::const_iterator I = SRSets.find(SubIdx); - // Unsupported SubRegIndex. Skip it. - if (I == SRSets.end()) + // Iterate over sub-register class candidates. Ignore classes created by + // this loop. They will never be useful. + for (unsigned rci = FirstSubRegRC, rce = RegClasses.size(); rci != rce; + ++rci) { + CodeGenRegisterClass *SubRC = RegClasses[rci]; + // Compute the subset of RC that maps into SubRC. + CodeGenRegister::Set SubSet; + for (unsigned i = 0, e = SSPairs.size(); i != e; ++i) + if (SubRC->contains(SSPairs[i].second)) + SubSet.insert(SSPairs[i].first); + if (SubSet.empty()) continue; - // In most cases, all RC registers support the SubRegIndex. - if (I->second.size() == RC.getMembers().size()) { - RC.setSubClassWithSubReg(SubIdx, &RC); + // RC injects completely into SubRC. + if (SubSet.size() == SSPairs.size()) { + SubRC->addSuperRegClass(SubIdx, RC); continue; } + // Only a subset of RC maps into SubRC. Make sure it is represented by a + // class. + getOrCreateSubClass(RC, &SubSet, RC->getName() + + "_with_" + SubIdx->getName() + + "_in_" + SubRC->getName()); + } + } +} - // This is a real subset. See if we have a matching class. - CodeGenRegisterClass::Key K(&I->second, RC.SpillSize, RC.SpillAlignment); - RCKeyMap::const_iterator FoundI = Key2RC.find(K); - if (FoundI != Key2RC.end()) { - RC.setSubClassWithSubReg(SubIdx, FoundI->second); - continue; - } - // Class doesn't exist. - CodeGenRegisterClass *NewRC = - new CodeGenRegisterClass(RC.getName() + "_with_" + - I->first->getName(), K); - addToMaps(NewRC); - RC.setSubClassWithSubReg(SubIdx, NewRC); +// +// Infer missing register classes. +// +void CodeGenRegBank::computeInferredRegisterClasses() { + // When this function is called, the register classes have not been sorted + // and assigned EnumValues yet. That means getSubClasses(), + // getSuperClasses(), and hasSubClass() functions are defunct. + unsigned FirstNewRC = RegClasses.size(); + + // Visit all register classes, including the ones being added by the loop. + for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { + CodeGenRegisterClass *RC = RegClasses[rci]; + + // Synthesize answers for getSubClassWithSubReg(). + inferSubClassWithSubReg(RC); + + // Synthesize answers for getCommonSubClass(). + inferCommonSubClass(RC); + + // Synthesize answers for getMatchingSuperRegClass(). + inferMatchingSuperRegClass(RC); + + // New register classes are created while this loop is running, and we need + // to visit all of them. I particular, inferMatchingSuperRegClass needs + // to match old super-register classes with sub-register classes created + // after inferMatchingSuperRegClass was called. At this point, + // inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC = + // [0..FirstNewRC). We need to cover SubRC = [FirstNewRC..rci]. + if (rci + 1 == FirstNewRC) { + unsigned NextNewRC = RegClasses.size(); + for (unsigned rci2 = 0; rci2 != FirstNewRC; ++rci2) + inferMatchingSuperRegClass(RegClasses[rci2], FirstNewRC); + FirstNewRC = NextNewRC; } } } @@ -843,3 +1601,45 @@ CodeGenRegBank::getRegClassForRegister(Record *R) { } return FoundRC; } + +BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) { + SetVector<const CodeGenRegister*> Set; + + // First add Regs with all sub-registers. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + CodeGenRegister *Reg = getReg(Regs[i]); + if (Set.insert(Reg)) + // Reg is new, add all sub-registers. + // The pre-ordering is not important here. + Reg->addSubRegsPreOrder(Set, *this); + } + + // Second, find all super-registers that are completely covered by the set. + for (unsigned i = 0; i != Set.size(); ++i) { + const CodeGenRegister::SuperRegList &SR = Set[i]->getSuperRegs(); + for (unsigned j = 0, e = SR.size(); j != e; ++j) { + const CodeGenRegister *Super = SR[j]; + if (!Super->CoveredBySubRegs || Set.count(Super)) + continue; + // This new super-register is covered by its sub-registers. + bool AllSubsInSet = true; + const CodeGenRegister::SubRegMap &SRM = Super->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), + E = SRM.end(); I != E; ++I) + if (!Set.count(I->second)) { + AllSubsInSet = false; + break; + } + // All sub-registers in Set, add Super as well. + // We will visit Super later to recheck its super-registers. + if (AllSubsInSet) + Set.insert(Super); + } + } + + // Convert to BitVector. + BitVector BV(Registers.size() + 1); + for (unsigned i = 0, e = Set.size(); i != e; ++i) + BV.set(Set[i]->EnumValue); + return BV; +} diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h index 4fc34b092260..232a6e71de2d 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h @@ -22,6 +22,7 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" +#include "llvm/Support/ErrorHandling.h" #include <cstdlib> #include <map> #include <string> @@ -31,14 +32,69 @@ namespace llvm { class CodeGenRegBank; + /// CodeGenSubRegIndex - Represents a sub-register index. + class CodeGenSubRegIndex { + Record *const TheDef; + const unsigned EnumValue; + + public: + CodeGenSubRegIndex(Record *R, unsigned Enum); + + const std::string &getName() const; + std::string getNamespace() const; + std::string getQualifiedName() const; + + // Order CodeGenSubRegIndex pointers by EnumValue. + struct Less { + bool operator()(const CodeGenSubRegIndex *A, + const CodeGenSubRegIndex *B) const { + assert(A && B); + return A->EnumValue < B->EnumValue; + } + }; + + // Map of composite subreg indices. + typedef std::map<CodeGenSubRegIndex*, CodeGenSubRegIndex*, Less> CompMap; + + // Returns the subreg index that results from composing this with Idx. + // Returns NULL if this and Idx don't compose. + CodeGenSubRegIndex *compose(CodeGenSubRegIndex *Idx) const { + CompMap::const_iterator I = Composed.find(Idx); + return I == Composed.end() ? 0 : I->second; + } + + // Add a composite subreg index: this+A = B. + // Return a conflicting composite, or NULL + CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, + CodeGenSubRegIndex *B) { + std::pair<CompMap::iterator, bool> Ins = + Composed.insert(std::make_pair(A, B)); + return (Ins.second || Ins.first->second == B) ? 0 : Ins.first->second; + } + + // Update the composite maps of components specified in 'ComposedOf'. + void updateComponents(CodeGenRegBank&); + + // Clean out redundant composite mappings. + void cleanComposites(); + + // Return the map of composites. + const CompMap &getComposites() const { return Composed; } + + private: + CompMap Composed; + }; + /// CodeGenRegister - Represents a register definition. struct CodeGenRegister { Record *TheDef; unsigned EnumValue; unsigned CostPerUse; + bool CoveredBySubRegs; // Map SubRegIndex -> Register. - typedef std::map<Record*, CodeGenRegister*, LessRecord> SubRegMap; + typedef std::map<CodeGenSubRegIndex*, CodeGenRegister*, + CodeGenSubRegIndex::Less> SubRegMap; CodeGenRegister(Record *R, unsigned Enum); @@ -54,18 +110,37 @@ namespace llvm { } // Add sub-registers to OSet following a pre-order defined by the .td file. - void addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const; + void addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet, + CodeGenRegBank&) const; // List of super-registers in topological order, small to large. - typedef std::vector<CodeGenRegister*> SuperRegList; + typedef std::vector<const CodeGenRegister*> SuperRegList; - // Get the list of super-registers. - // This is only valid after computeDerivedInfo has visited all registers. + // Get the list of super-registers. This is valid after getSubReg + // visits all registers during RegBank construction. const SuperRegList &getSuperRegs() const { assert(SubRegsComplete && "Must precompute sub-registers"); return SuperRegs; } + // List of register units in ascending order. + typedef SmallVector<unsigned, 16> RegUnitList; + + // Get the list of register units. + // This is only valid after getSubRegs() completes. + const RegUnitList &getRegUnits() const { return RegUnits; } + + // Inherit register units from subregisters. + // Return true if the RegUnits changed. + bool inheritRegUnits(CodeGenRegBank &RegBank); + + // Adopt a register unit for pressure tracking. + // A unit is adopted iff its unit number is >= NumNativeRegUnits. + void adoptRegUnit(unsigned RUID) { RegUnits.push_back(RUID); } + + // Get the sum of this register's register unit weights. + unsigned getWeight(const CodeGenRegBank &RegBank) const; + // Order CodeGenRegister pointers by EnumValue. struct Less { bool operator()(const CodeGenRegister *A, @@ -82,6 +157,7 @@ namespace llvm { bool SubRegsComplete; SubRegMap SubRegs; SuperRegList SuperRegs; + RegUnitList RegUnits; }; @@ -101,8 +177,17 @@ namespace llvm { // super-class. void inheritProperties(CodeGenRegBank&); - // Map SubRegIndex -> sub-class - DenseMap<Record*, CodeGenRegisterClass*> SubClassWithSubReg; + // Map SubRegIndex -> sub-class. This is the largest sub-class where all + // registers have a SubRegIndex sub-register. + DenseMap<CodeGenSubRegIndex*, CodeGenRegisterClass*> SubClassWithSubReg; + + // Map SubRegIndex -> set of super-reg classes. This is all register + // classes SuperRC such that: + // + // R:SubRegIndex in this RC for all R in SuperRC. + // + DenseMap<CodeGenSubRegIndex*, + SmallPtrSet<CodeGenRegisterClass*, 8> > SuperRegClasses; public: unsigned EnumValue; @@ -128,8 +213,7 @@ namespace llvm { MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const { if (VTNum < VTs.size()) return VTs[VTNum]; - assert(0 && "VTNum greater than number of ValueTypes in RegClass!"); - abort(); + llvm_unreachable("VTNum greater than number of ValueTypes in RegClass!"); } // Return true if this this class contains the register. @@ -150,14 +234,26 @@ namespace llvm { // getSubClassWithSubReg - Returns the largest sub-class where all // registers have a SubIdx sub-register. - CodeGenRegisterClass *getSubClassWithSubReg(Record *SubIdx) const { + CodeGenRegisterClass* + getSubClassWithSubReg(CodeGenSubRegIndex *SubIdx) const { return SubClassWithSubReg.lookup(SubIdx); } - void setSubClassWithSubReg(Record *SubIdx, CodeGenRegisterClass *SubRC) { + void setSubClassWithSubReg(CodeGenSubRegIndex *SubIdx, + CodeGenRegisterClass *SubRC) { SubClassWithSubReg[SubIdx] = SubRC; } + // getSuperRegClasses - Returns a bit vector of all register classes + // containing only SubIdx super-registers of this class. + void getSuperRegClasses(CodeGenSubRegIndex *SubIdx, BitVector &Out) const; + + // addSuperRegClass - Add a class containing only SudIdx super-registers. + void addSuperRegClass(CodeGenSubRegIndex *SubIdx, + CodeGenRegisterClass *SuperRC) { + SuperRegClasses[SubIdx].insert(SuperRC); + } + // getSubClasses - Returns a constant BitVector of subclasses indexed by // EnumValue. // The SubClasses vector includs an entry for this class. @@ -183,6 +279,9 @@ namespace llvm { // getOrder(0). const CodeGenRegister::Set &getMembers() const { return Members; } + // Populate a unique sorted list of units from a register set. + void buildRegUnitSet(std::vector<unsigned> &RegUnits) const; + CodeGenRegisterClass(CodeGenRegBank&, Record *R); // A key representing the parts of a register class used for forming @@ -217,16 +316,34 @@ namespace llvm { static void computeSubClasses(CodeGenRegBank&); }; + // Each RegUnitSet is a sorted vector with a name. + struct RegUnitSet { + typedef std::vector<unsigned>::const_iterator iterator; + + std::string Name; + std::vector<unsigned> Units; + }; + // CodeGenRegBank - Represent a target's registers and the relations between // them. class CodeGenRegBank { RecordKeeper &Records; SetTheory Sets; - std::vector<Record*> SubRegIndices; + // SubRegIndices. + std::vector<CodeGenSubRegIndex*> SubRegIndices; + DenseMap<Record*, CodeGenSubRegIndex*> Def2SubRegIdx; unsigned NumNamedIndices; + + // Registers. std::vector<CodeGenRegister*> Registers; DenseMap<Record*, CodeGenRegister*> Def2Reg; + unsigned NumNativeRegUnits; + unsigned NumRegUnits; // # native + adopted register units. + + // Map each register unit to a weight (for register pressure). + // Includes native and adopted register units. + std::vector<unsigned> RegUnitWeights; // Register classes. std::vector<CodeGenRegisterClass*> RegClasses; @@ -234,16 +351,38 @@ namespace llvm { typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap; RCKeyMap Key2RC; + // Remember each unique set of register units. Initially, this contains a + // unique set for each register class. Simliar sets are coalesced with + // pruneUnitSets and new supersets are inferred during computeRegUnitSets. + std::vector<RegUnitSet> RegUnitSets; + + // Map RegisterClass index to the index of the RegUnitSet that contains the + // class's units and any inferred RegUnit supersets. + std::vector<std::vector<unsigned> > RegClassUnitSets; + // Add RC to *2RC maps. void addToMaps(CodeGenRegisterClass*); + // Create a synthetic sub-class if it is missing. + CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC, + const CodeGenRegister::Set *Membs, + StringRef Name); + // Infer missing register classes. void computeInferredRegisterClasses(); + void inferCommonSubClass(CodeGenRegisterClass *RC); + void inferSubClassWithSubReg(CodeGenRegisterClass *RC); + void inferMatchingSuperRegClass(CodeGenRegisterClass *RC, + unsigned FirstSubRegRC = 0); + + // Iteratively prune unit sets. + void pruneUnitSets(); + + // Compute a weight for each register unit created during getSubRegs. + void computeRegUnitWeights(); - // Composite SubRegIndex instances. - // Map (SubRegIndex, SubRegIndex) -> SubRegIndex. - typedef DenseMap<std::pair<Record*, Record*>, Record*> CompositeMap; - CompositeMap Composite; + // Create a RegUnitSet for each RegClass and infer superclasses. + void computeRegUnitSets(); // Populate the Composite map from sub-register relationships. void computeComposites(); @@ -256,20 +395,44 @@ namespace llvm { // Sub-register indices. The first NumNamedIndices are defined by the user // in the .td files. The rest are synthesized such that all sub-registers // have a unique name. - const std::vector<Record*> &getSubRegIndices() { return SubRegIndices; } + ArrayRef<CodeGenSubRegIndex*> getSubRegIndices() { return SubRegIndices; } unsigned getNumNamedIndices() { return NumNamedIndices; } - // Map a SubRegIndex Record to its enum value. - unsigned getSubRegIndexNo(Record *idx); + // Find a SubRegIndex form its Record def. + CodeGenSubRegIndex *getSubRegIdx(Record*); // Find or create a sub-register index representing the A+B composition. - Record *getCompositeSubRegIndex(Record *A, Record *B, bool create = false); + CodeGenSubRegIndex *getCompositeSubRegIndex(CodeGenSubRegIndex *A, + CodeGenSubRegIndex *B); const std::vector<CodeGenRegister*> &getRegisters() { return Registers; } // Find a register from its Record def. CodeGenRegister *getReg(Record*); + // Get a Register's index into the Registers array. + unsigned getRegIndex(const CodeGenRegister *Reg) const { + return Reg->EnumValue - 1; + } + + // Create a new non-native register unit that can be adopted by a register + // to increase its pressure. Note that NumNativeRegUnits is not increased. + unsigned newRegUnit(unsigned Weight) { + if (!RegUnitWeights.empty()) { + assert(Weight && "should only add allocatable units"); + RegUnitWeights.resize(NumRegUnits+1); + RegUnitWeights[NumRegUnits] = Weight; + } + return NumRegUnits++; + } + + // Native units are the singular unit of a leaf register. Register aliasing + // is completely characterized by native units. Adopted units exist to give + // register additional weight but don't affect aliasing. + bool isNativeUnit(unsigned RUID) { + return RUID < NumNativeRegUnits; + } + ArrayRef<CodeGenRegisterClass*> getRegClasses() const { return RegClasses; } @@ -284,6 +447,41 @@ namespace llvm { /// return the superclass. Otherwise return null. const CodeGenRegisterClass* getRegClassForRegister(Record *R); + // Get a register unit's weight. Zero for unallocatable registers. + unsigned getRegUnitWeight(unsigned RUID) const { + return RegUnitWeights[RUID]; + } + + // Get the sum of unit weights. + unsigned getRegUnitSetWeight(const std::vector<unsigned> &Units) const { + unsigned Weight = 0; + for (std::vector<unsigned>::const_iterator + I = Units.begin(), E = Units.end(); I != E; ++I) + Weight += getRegUnitWeight(*I); + return Weight; + } + + // Increase a RegUnitWeight. + void increaseRegUnitWeight(unsigned RUID, unsigned Inc) { + RegUnitWeights[RUID] += Inc; + } + + // Get the number of register pressure dimensions. + unsigned getNumRegPressureSets() const { return RegUnitSets.size(); } + + // Get a set of register unit IDs for a given dimension of pressure. + RegUnitSet getRegPressureSet(unsigned Idx) const { + return RegUnitSets[Idx]; + } + + // Get a list of pressure set IDs for a register class. Liveness of a + // register in this class impacts each pressure set in this list by the + // weight of the register. An exact solution requires all registers in a + // class to have the same class, but it is not strictly guaranteed. + ArrayRef<unsigned> getRCPressureSetIDs(unsigned RCIdx) const { + return RegClassUnitSets[RCIdx]; + } + // Computed derived records such as missing sub-register indices. void computeDerivedInfo(); @@ -295,6 +493,15 @@ namespace llvm { // If R1 is a sub-register of R2, Map[R1] is a subset of Map[R2]. void computeOverlaps(std::map<const CodeGenRegister*, CodeGenRegister::Set> &Map); + + // Compute the set of registers completely covered by the registers in Regs. + // The returned BitVector will have a bit set for each register in Regs, + // all sub-registers, and all super-registers that are covered by the + // registers in Regs. + // + // This is used to compute the mask of call-preserved registers from a list + // of callee-saves. + BitVector computeCoveredRegisters(ArrayRef<Record*> Regs); }; } diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp index 4a7bad7e6d85..cf6793570a26 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -58,6 +58,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::iAny: return "MVT::iAny"; case MVT::fAny: return "MVT::fAny"; case MVT::vAny: return "MVT::vAny"; + case MVT::f16: return "MVT::f16"; case MVT::f32: return "MVT::f32"; case MVT::f64: return "MVT::f64"; case MVT::f80: return "MVT::f80"; @@ -82,6 +83,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v2i64: return "MVT::v2i64"; case MVT::v4i64: return "MVT::v4i64"; case MVT::v8i64: return "MVT::v8i64"; + case MVT::v2f16: return "MVT::v2f16"; case MVT::v2f32: return "MVT::v2f32"; case MVT::v4f32: return "MVT::v4f32"; case MVT::v8f32: return "MVT::v8f32"; @@ -90,8 +92,8 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::Metadata: return "MVT::Metadata"; case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; - case MVT::untyped: return "MVT::untyped"; - default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; + case MVT::Untyped: return "MVT::Untyped"; + default: llvm_unreachable("ILLEGAL VALUE TYPE!"); } } @@ -149,6 +151,26 @@ Record *CodeGenTarget::getAsmParser() const { return LI[AsmParserNum]; } +/// getAsmParserVariant - Return the AssmblyParserVariant definition for +/// this target. +/// +Record *CodeGenTarget::getAsmParserVariant(unsigned i) const { + std::vector<Record*> LI = + TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); + if (i >= LI.size()) + throw "Target does not have an AsmParserVariant #" + utostr(i) + "!"; + return LI[i]; +} + +/// getAsmParserVariantCount - Return the AssmblyParserVariant definition +/// available for this target. +/// +unsigned CodeGenTarget::getAsmParserVariantCount() const { + std::vector<Record*> LI = + TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); + return LI.size(); +} + /// getAsmWriter - Return the AssemblyWriter definition for this target. /// Record *CodeGenTarget::getAsmWriter() const { @@ -267,6 +289,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "DBG_VALUE", "REG_SEQUENCE", "COPY", + "BUNDLE", 0 }; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); @@ -492,7 +515,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); } else - assert(0 && "Unknown property!"); + llvm_unreachable("Unknown property!"); } // Sort the argument attributes for later benefit. diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h index 730216c331b4..85463da59731 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.h +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h @@ -91,6 +91,16 @@ public: /// Record *getAsmParser() const; + /// getAsmParserVariant - Return the AssmblyParserVariant definition for + /// this target. + /// + Record *getAsmParserVariant(unsigned i) const; + + /// getAsmParserVariantCount - Return the AssmblyParserVariant definition + /// available for this target. + /// + unsigned getAsmParserVariantCount() const; + /// getAsmWriter - Return the AssemblyWriter definition for this target. /// Record *getAsmWriter() const; diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp index 1367e8dd6e86..bd77907a9bd9 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp @@ -15,6 +15,8 @@ #include "llvm/ADT/StringExtras.h" using namespace llvm; +void Matcher::anchor() { } + void Matcher::dump() const { print(errs(), 0); } @@ -324,6 +326,10 @@ unsigned EmitNodeMatcherCommon::getHashImpl() const { } +void EmitNodeMatcher::anchor() { } + +void MorphNodeToMatcher::anchor() { } + unsigned MarkGlueResultsMatcher::getHashImpl() const { return HashUnsigneds(GlueResultNodes.begin(), GlueResultNodes.end()); } diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h index dcb8da71086e..99ebf98b1e4b 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcher.h +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h @@ -41,6 +41,7 @@ class Matcher { // The next matcher node that is executed after this one. Null if this is the // last stage of a match. OwningPtr<Matcher> Next; + virtual void anchor(); public: enum KindTy { // Matcher state manipulation. @@ -1011,6 +1012,7 @@ private: /// EmitNodeMatcher - This signals a successful match and generates a node. class EmitNodeMatcher : public EmitNodeMatcherCommon { + virtual void anchor(); unsigned FirstResultSlot; public: EmitNodeMatcher(const std::string &opcodeName, @@ -1033,6 +1035,7 @@ public: }; class MorphNodeToMatcher : public EmitNodeMatcherCommon { + virtual void anchor(); const PatternToMatch &Pattern; public: MorphNodeToMatcher(const std::string &opcodeName, diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 3b65b2a6de0c..bd425a9bc1a9 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -573,8 +573,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, return 2 + NumResultBytes; } } - assert(0 && "Unreachable"); - return 0; + llvm_unreachable("Unreachable"); } /// EmitMatcherList - Emit the bytes for the specified matcher subtree. @@ -601,7 +600,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { if (!PatternPredicates.empty()) { OS << "bool CheckPatternPredicate(unsigned PredNo) const {\n"; OS << " switch (PredNo) {\n"; - OS << " default: assert(0 && \"Invalid predicate in table?\");\n"; + OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i) OS << " case " << i << ": return " << PatternPredicates[i] << ";\n"; OS << " }\n"; @@ -619,7 +618,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { if (!NodePredicates.empty()) { OS << "bool CheckNodePredicate(SDNode *Node, unsigned PredNo) const {\n"; OS << " switch (PredNo) {\n"; - OS << " default: assert(0 && \"Invalid predicate in table?\");\n"; + OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) { // Emit the predicate code corresponding to this pattern. TreePredicateFn PredFn = NodePredicates[i]; @@ -641,7 +640,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { OS << " SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {\n"; OS << " unsigned NextRes = Result.size();\n"; OS << " switch (PatternNo) {\n"; - OS << " default: assert(0 && \"Invalid pattern # in table?\");\n"; + OS << " default: llvm_unreachable(\"Invalid pattern # in table?\");\n"; for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) { const ComplexPattern &P = *ComplexPatterns[i]; unsigned NumOps = P.getNumOperands(); @@ -679,7 +678,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { if (!NodeXForms.empty()) { OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n"; OS << " switch (XFormNo) {\n"; - OS << " default: assert(0 && \"Invalid xform # in table?\");\n"; + OS << " default: llvm_unreachable(\"Invalid xform # in table?\");\n"; // FIXME: The node xform could take SDValue's instead of SDNode*'s. for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) { diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp index 49ad956f8866..2ac7b87e7010 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -217,7 +217,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue()); if (DI == 0) { - errs() << "Unknown leaf kind: " << *DI << "\n"; + errs() << "Unknown leaf kind: " << *N << "\n"; abort(); } diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp new file mode 100644 index 000000000000..4abf54ebae2e --- /dev/null +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp @@ -0,0 +1,512 @@ +//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine-----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class parses the Schedule.td file and produces an API that can be used +// to reason about whether an instruction can be added to a packet on a VLIW +// architecture. The class internally generates a deterministic finite +// automaton (DFA) that models all possible mappings of machine instructions +// to functional units as instructions are added to a packet. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Record.h" +#include "CodeGenTarget.h" +#include "DFAPacketizerEmitter.h" +#include <list> + +using namespace llvm; + +// +// +// State represents the usage of machine resources if the packet contains +// a set of instruction classes. +// +// Specifically, currentState is a set of bit-masks. +// The nth bit in a bit-mask indicates whether the nth resource is being used +// by this state. The set of bit-masks in a state represent the different +// possible outcomes of transitioning to this state. +// For example: consider a two resource architecture: resource L and resource M +// with three instruction classes: L, M, and L_or_M. +// From the initial state (currentState = 0x00), if we add instruction class +// L_or_M we will transition to a state with currentState = [0x01, 0x10]. This +// represents the possible resource states that can result from adding a L_or_M +// instruction +// +// Another way of thinking about this transition is we are mapping a NDFA with +// two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10]. +// +// +namespace { +class State { + public: + static int currentStateNum; + int stateNum; + bool isInitial; + std::set<unsigned> stateInfo; + + State(); + State(const State &S); + + // + // canAddInsnClass - Returns true if an instruction of type InsnClass is a + // valid transition from this state, i.e., can an instruction of type InsnClass + // be added to the packet represented by this state. + // + // PossibleStates is the set of valid resource states that ensue from valid + // transitions. + // + bool canAddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); +}; +} // End anonymous namespace. + + +namespace { +struct Transition { + public: + static int currentTransitionNum; + int transitionNum; + State *from; + unsigned input; + State *to; + + Transition(State *from_, unsigned input_, State *to_); +}; +} // End anonymous namespace. + + +// +// Comparators to keep set of states sorted. +// +namespace { +struct ltState { + bool operator()(const State *s1, const State *s2) const; +}; +} // End anonymous namespace. + + +// +// class DFA: deterministic finite automaton for processor resource tracking. +// +namespace { +class DFA { +public: + DFA(); + + // Set of states. Need to keep this sorted to emit the transition table. + std::set<State*, ltState> states; + + // Map from a state to the list of transitions with that state as source. + std::map<State*, SmallVector<Transition*, 16>, ltState> stateTransitions; + State *currentState; + + // Highest valued Input seen. + unsigned LargestInput; + + // + // Modify the DFA. + // + void initialize(); + void addState(State *); + void addTransition(Transition *); + + // + // getTransition - Return the state when a transition is made from + // State From with Input I. If a transition is not found, return NULL. + // + State *getTransition(State *, unsigned); + + // + // isValidTransition: Predicate that checks if there is a valid transition + // from state From on input InsnClass. + // + bool isValidTransition(State *From, unsigned InsnClass); + + // + // writeTable: Print out a table representing the DFA. + // + void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName); +}; +} // End anonymous namespace. + + +// +// Constructors for State, Transition, and DFA +// +State::State() : + stateNum(currentStateNum++), isInitial(false) {} + + +State::State(const State &S) : + stateNum(currentStateNum++), isInitial(S.isInitial), + stateInfo(S.stateInfo) {} + + +Transition::Transition(State *from_, unsigned input_, State *to_) : + transitionNum(currentTransitionNum++), from(from_), input(input_), + to(to_) {} + + +DFA::DFA() : + LargestInput(0) {} + + +bool ltState::operator()(const State *s1, const State *s2) const { + return (s1->stateNum < s2->stateNum); +} + + +// +// canAddInsnClass - Returns true if an instruction of type InsnClass is a +// valid transition from this state i.e., can an instruction of type InsnClass +// be added to the packet represented by this state. +// +// PossibleStates is the set of valid resource states that ensue from valid +// transitions. +// +bool State::canAddInsnClass(unsigned InsnClass, + std::set<unsigned> &PossibleStates) { + // + // Iterate over all resource states in currentState. + // + bool AddedState = false; + + for (std::set<unsigned>::iterator SI = stateInfo.begin(); + SI != stateInfo.end(); ++SI) { + unsigned thisState = *SI; + + // + // Iterate over all possible resources used in InsnClass. + // For ex: for InsnClass = 0x11, all resources = {0x01, 0x10}. + // + + DenseSet<unsigned> VisitedResourceStates; + for (unsigned int j = 0; j < sizeof(InsnClass) * 8; ++j) { + if ((0x1 << j) & InsnClass) { + // + // For each possible resource used in InsnClass, generate the + // resource state if that resource was used. + // + unsigned ResultingResourceState = thisState | (0x1 << j); + // + // Check if the resulting resource state can be accommodated in this + // packet. + // We compute ResultingResourceState OR thisState. + // If the result of the OR is different than thisState, it implies + // that there is at least one resource that can be used to schedule + // InsnClass in the current packet. + // Insert ResultingResourceState into PossibleStates only if we haven't + // processed ResultingResourceState before. + // + if ((ResultingResourceState != thisState) && + (VisitedResourceStates.count(ResultingResourceState) == 0)) { + VisitedResourceStates.insert(ResultingResourceState); + PossibleStates.insert(ResultingResourceState); + AddedState = true; + } + } + } + } + + return AddedState; +} + + +void DFA::initialize() { + currentState->isInitial = true; +} + + +void DFA::addState(State *S) { + assert(!states.count(S) && "State already exists"); + states.insert(S); +} + + +void DFA::addTransition(Transition *T) { + // Update LargestInput. + if (T->input > LargestInput) + LargestInput = T->input; + + // Add the new transition. + stateTransitions[T->from].push_back(T); +} + + +// +// getTransition - Return the state when a transition is made from +// State From with Input I. If a transition is not found, return NULL. +// +State *DFA::getTransition(State *From, unsigned I) { + // Do we have a transition from state From? + if (!stateTransitions.count(From)) + return NULL; + + // Do we have a transition from state From with Input I? + for (SmallVector<Transition*, 16>::iterator VI = + stateTransitions[From].begin(); + VI != stateTransitions[From].end(); ++VI) + if ((*VI)->input == I) + return (*VI)->to; + + return NULL; +} + + +bool DFA::isValidTransition(State *From, unsigned InsnClass) { + return (getTransition(From, InsnClass) != NULL); +} + + +int State::currentStateNum = 0; +int Transition::currentTransitionNum = 0; + +DFAGen::DFAGen(RecordKeeper &R): + TargetName(CodeGenTarget(R).getName()), + allInsnClasses(), Records(R) {} + + +// +// writeTableAndAPI - Print out a table representing the DFA and the +// associated API to create a DFA packetizer. +// +// Format: +// DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid +// transitions. +// DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable for +// the ith state. +// +// +void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { + std::set<State*, ltState>::iterator SI = states.begin(); + // This table provides a map to the beginning of the transitions for State s + // in DFAStateInputTable. + std::vector<int> StateEntry(states.size()); + + OS << "namespace llvm {\n\n"; + OS << "const int " << TargetName << "DFAStateInputTable[][2] = {\n"; + + // Tracks the total valid transitions encountered so far. It is used + // to construct the StateEntry table. + int ValidTransitions = 0; + for (unsigned i = 0; i < states.size(); ++i, ++SI) { + StateEntry[i] = ValidTransitions; + for (unsigned j = 0; j <= LargestInput; ++j) { + assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); + if (!isValidTransition(*SI, j)) + continue; + + OS << "{" << j << ", " + << getTransition(*SI, j)->stateNum + << "}, "; + ++ValidTransitions; + } + + // If there are no valid transitions from this stage, we need a sentinel + // transition. + if (ValidTransitions == StateEntry[i]) { + OS << "{-1, -1},"; + ++ValidTransitions; + } + + OS << "\n"; + } + OS << "};\n\n"; + OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n"; + + // Multiply i by 2 since each entry in DFAStateInputTable is a set of + // two numbers. + for (unsigned i = 0; i < states.size(); ++i) + OS << StateEntry[i] << ", "; + + OS << "\n};\n"; + OS << "} // namespace\n"; + + + // + // Emit DFA Packetizer tables if the target is a VLIW machine. + // + std::string SubTargetClassName = TargetName + "GenSubtargetInfo"; + OS << "\n" << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n"; + OS << "namespace llvm {\n"; + OS << "DFAPacketizer *" << SubTargetClassName << "::" + << "createDFAPacketizer(const InstrItineraryData *IID) const {\n" + << " return new DFAPacketizer(IID, " << TargetName + << "DFAStateInputTable, " << TargetName << "DFAStateEntryTable);\n}\n\n"; + OS << "} // End llvm namespace \n"; +} + + +// +// collectAllInsnClasses - Populate allInsnClasses which is a set of units +// used in each stage. +// +void DFAGen::collectAllInsnClasses(const std::string &Name, + Record *ItinData, + unsigned &NStages, + raw_ostream &OS) { + // Collect processor itineraries. + std::vector<Record*> ProcItinList = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + + // If just no itinerary then don't bother. + if (ProcItinList.size() < 2) + return; + std::map<std::string, unsigned> NameToBitsMap; + + // Parse functional units for all the itineraries. + for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { + Record *Proc = ProcItinList[i]; + std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); + + // Convert macros to bits for each stage. + for (unsigned i = 0, N = FUs.size(); i < N; ++i) + NameToBitsMap[FUs[i]->getName()] = (unsigned) (1U << i); + } + + const std::vector<Record*> &StageList = + ItinData->getValueAsListOfDefs("Stages"); + + // The number of stages. + NStages = StageList.size(); + + // For each unit. + unsigned UnitBitValue = 0; + + // Compute the bitwise or of each unit used in this stage. + for (unsigned i = 0; i < NStages; ++i) { + const Record *Stage = StageList[i]; + + // Get unit list. + const std::vector<Record*> &UnitList = + Stage->getValueAsListOfDefs("Units"); + + for (unsigned j = 0, M = UnitList.size(); j < M; ++j) { + // Conduct bitwise or. + std::string UnitName = UnitList[j]->getName(); + assert(NameToBitsMap.count(UnitName)); + UnitBitValue |= NameToBitsMap[UnitName]; + } + + if (UnitBitValue != 0) + allInsnClasses.insert(UnitBitValue); + } +} + + +// +// Run the worklist algorithm to generate the DFA. +// +void DFAGen::run(raw_ostream &OS) { + EmitSourceFileHeader("Target DFA Packetizer Tables", OS); + + // Collect processor iteraries. + std::vector<Record*> ProcItinList = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + + // + // Collect the instruction classes. + // + for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { + Record *Proc = ProcItinList[i]; + + // Get processor itinerary name. + const std::string &Name = Proc->getName(); + + // Skip default. + if (Name == "NoItineraries") + continue; + + // Sanity check for at least one instruction itinerary class. + unsigned NItinClasses = + Records.getAllDerivedDefinitions("InstrItinClass").size(); + if (NItinClasses == 0) + return; + + // Get itinerary data list. + std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); + + // Collect instruction classes for all itinerary data. + for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { + Record *ItinData = ItinDataList[j]; + unsigned NStages; + collectAllInsnClasses(Name, ItinData, NStages, OS); + } + } + + + // + // Run a worklist algorithm to generate the DFA. + // + DFA D; + State *Initial = new State; + Initial->isInitial = true; + Initial->stateInfo.insert(0x0); + D.addState(Initial); + SmallVector<State*, 32> WorkList; + std::map<std::set<unsigned>, State*> Visited; + + WorkList.push_back(Initial); + + // + // Worklist algorithm to create a DFA for processor resource tracking. + // C = {set of InsnClasses} + // Begin with initial node in worklist. Initial node does not have + // any consumed resources, + // ResourceState = 0x0 + // Visited = {} + // While worklist != empty + // S = first element of worklist + // For every instruction class C + // if we can accommodate C in S: + // S' = state with resource states = {S Union C} + // Add a new transition: S x C -> S' + // If S' is not in Visited: + // Add S' to worklist + // Add S' to Visited + // + while (!WorkList.empty()) { + State *current = WorkList.pop_back_val(); + for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(), + CE = allInsnClasses.end(); CI != CE; ++CI) { + unsigned InsnClass = *CI; + + std::set<unsigned> NewStateResources; + // + // If we haven't already created a transition for this input + // and the state can accommodate this InsnClass, create a transition. + // + if (!D.getTransition(current, InsnClass) && + current->canAddInsnClass(InsnClass, NewStateResources)) { + State *NewState = NULL; + + // + // If we have seen this state before, then do not create a new state. + // + // + std::map<std::set<unsigned>, State*>::iterator VI; + if ((VI = Visited.find(NewStateResources)) != Visited.end()) + NewState = VI->second; + else { + NewState = new State; + NewState->stateInfo = NewStateResources; + D.addState(NewState); + Visited[NewStateResources] = NewState; + WorkList.push_back(NewState); + } + + Transition *NewTransition = new Transition(current, InsnClass, + NewState); + D.addTransition(NewTransition); + } + } + } + + // Print out the table. + D.writeTableAndAPI(OS, TargetName); +} diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.h b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.h new file mode 100644 index 000000000000..1727150ae926 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.h @@ -0,0 +1,52 @@ +//===- DFAPacketizerEmitter.h - Packetization DFA for a VLIW machine-------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class parses the Schedule.td file and produces an API that can be used +// to reason about whether an instruction can be added to a packet on a VLIW +// architecture. The class internally generates a deterministic finite +// automaton (DFA) that models all possible mappings of machine instructions +// to functional units as instructions are added to a packet. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseSet.h" +#include "llvm/TableGen/TableGenBackend.h" +#include <map> +#include <string> + +namespace llvm { +// +// class DFAGen: class that generates and prints out the DFA for resource +// tracking. +// +class DFAGen : public TableGenBackend { +private: + std::string TargetName; + // + // allInsnClasses is the set of all possible resources consumed by an + // InstrStage. + // + DenseSet<unsigned> allInsnClasses; + RecordKeeper &Records; + +public: + DFAGen(RecordKeeper &R); + + // + // collectAllInsnClasses: Populate allInsnClasses which is a set of units + // used in each stage. + // + void collectAllInsnClasses(const std::string &Name, + Record *ItinData, + unsigned &NStages, + raw_ostream &OS); + + void run(raw_ostream &OS); +}; +} diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp index ff314e9c4f2f..4650197ae718 100644 --- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -11,7 +11,6 @@ #include "CodeGenTarget.h" #include "X86DisassemblerTables.h" #include "X86RecognizableInstr.h" -#include "ARMDecoderEmitter.h" #include "FixedLenDecoderEmitter.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp index abef70e31897..3809a4576a54 100644 --- a/contrib/llvm/utils/TableGen/EDEmitter.cpp +++ b/contrib/llvm/utils/TableGen/EDEmitter.cpp @@ -287,6 +287,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, IMM("i64i8imm"); IMM("i64i32imm"); IMM("SSECC"); + IMM("AVXCC"); // all R, I, R, I, R MEM("i8mem"); @@ -519,6 +520,8 @@ static void X86ExtractSemantics( // ignore (doesn't go anywhere we know about) } else if (name.find("VMCALL") != name.npos) { // ignore (rather different semantics than a regular call) + } else if (name.find("VMMCALL") != name.npos) { + // ignore (rather different semantics than a regular call) } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { CALL("off"); } else { @@ -567,12 +570,23 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, REG("DPR"); REG("DPR_VFP2"); REG("DPR_8"); + REG("DPair"); REG("SPR"); REG("QPR"); REG("QQPR"); REG("QQQQPR"); + REG("VecListOneD"); + REG("VecListDPair"); + REG("VecListDPairSpaced"); + REG("VecListThreeD"); + REG("VecListFourD"); + REG("VecListOneDAllLanes"); + REG("VecListDPairAllLanes"); + REG("VecListDPairSpacedAllLanes"); IMM("i32imm"); + IMM("fbits16"); + IMM("fbits32"); IMM("i32imm_hilo16"); IMM("bf_inv_mask_imm"); IMM("lsb_pos_imm"); @@ -597,6 +611,20 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("imm1_16"); IMM("imm1_32"); IMM("nModImm"); + IMM("nImmSplatI8"); + IMM("nImmSplatI16"); + IMM("nImmSplatI32"); + IMM("nImmSplatI64"); + IMM("nImmVMOVI32"); + IMM("nImmVMOVF32"); + IMM("imm8"); + IMM("imm16"); + IMM("imm32"); + IMM("imm1_7"); + IMM("imm1_15"); + IMM("imm1_31"); + IMM("imm0_1"); + IMM("imm0_3"); IMM("imm0_7"); IMM("imm0_15"); IMM("imm0_255"); @@ -735,7 +763,7 @@ static void ARMPopulateOperands( errs() << "Operand type: " << rec.getName() << '\n'; errs() << "Operand name: " << operandInfo.Name << '\n'; errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; - llvm_unreachable("Unhandled type"); + throw("Unhandled type in EDEmitter"); } } } @@ -956,11 +984,7 @@ void EDEmitter::run(raw_ostream &o) { emitCommonEnums(o, i); - o << "namespace {\n"; - - o << "llvm::EDInstInfo instInfo" << target.getName().c_str() << "[] = "; + o << "static const llvm::EDInstInfo instInfo" << target.getName() << "[] = "; infoArray.emit(o, i); o << ";" << "\n"; - - o << "}\n"; } diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp index 9fdc2e33a546..e8dad77302c3 100644 --- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp @@ -21,7 +21,6 @@ #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/VectorExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -280,7 +279,7 @@ struct OperandsSignature { } else if (Operands[i].isImm()) { OS << "uint64_t imm" << i; } else if (Operands[i].isFP()) { - OS << "ConstantFP *f" << i; + OS << "const ConstantFP *f" << i; } else { llvm_unreachable("Unknown operand kind!"); } diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 02b966a21431..9b676f21a1d3 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -17,6 +17,7 @@ #include "FixedLenDecoderEmitter.h" #include "CodeGenTarget.h" #include "llvm/TableGen/Record.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -48,7 +49,7 @@ static bool ValueNotSet(bit_value_t V) { static int Value(bit_value_t V) { return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1); } -static bit_value_t bitFromBits(BitsInit &bits, unsigned index) { +static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) { if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index))) return bit->getValue() ? BIT_TRUE : BIT_FALSE; @@ -56,7 +57,7 @@ static bit_value_t bitFromBits(BitsInit &bits, unsigned index) { return BIT_UNSET; } // Prints the bit value for each position. -static void dumpBits(raw_ostream &o, BitsInit &bits) { +static void dumpBits(raw_ostream &o, const BitsInit &bits) { unsigned index; for (index = bits.getNumBits(); index > 0; index--) { @@ -71,7 +72,7 @@ static void dumpBits(raw_ostream &o, BitsInit &bits) { o << "_"; break; default: - assert(0 && "unexpected return value from bitFromBits"); + llvm_unreachable("unexpected return value from bitFromBits"); } } } @@ -125,7 +126,7 @@ typedef std::vector<bit_value_t> insn_t; /// version and return the Opcode since the two have the same Asm format string. class Filter { protected: - FilterChooser *Owner; // points to the FilterChooser who owns this filter + const FilterChooser *Owner;// points to the FilterChooser who owns this filter unsigned StartBit; // the starting bit position unsigned NumBits; // number of bits to filter bool Mixed; // a mixed region contains both set and unset bits @@ -137,7 +138,7 @@ protected: std::vector<unsigned> VariableInstructions; // Map of well-known segment value to its delegate. - std::map<unsigned, FilterChooser*> FilterChooserMap; + std::map<unsigned, const FilterChooser*> FilterChooserMap; // Number of instructions which fall under FilteredInstructions category. unsigned NumFiltered; @@ -145,19 +146,15 @@ protected: // Keeps track of the last opcode in the filtered bucket. unsigned LastOpcFiltered; - // Number of instructions which fall under VariableInstructions category. - unsigned NumVariable; - public: - unsigned getNumFiltered() { return NumFiltered; } - unsigned getNumVariable() { return NumVariable; } - unsigned getSingletonOpc() { + unsigned getNumFiltered() const { return NumFiltered; } + unsigned getSingletonOpc() const { assert(NumFiltered == 1); return LastOpcFiltered; } // Return the filter chooser for the group of instructions without constant // segment values. - FilterChooser &getVariableFC() { + const FilterChooser &getVariableFC() const { assert(NumFiltered == 1); assert(FilterChooserMap.size() == 1); return *(FilterChooserMap.find((unsigned)-1)->second); @@ -177,7 +174,7 @@ public: void recurse(); // Emit code to decode instructions given a segment or segments of bits. - void emit(raw_ostream &o, unsigned &Indentation); + void emit(raw_ostream &o, unsigned &Indentation) const; // Returns the number of fanout produced by the filter. More fanout implies // the filter distinguishes more categories of instructions. @@ -217,10 +214,10 @@ protected: const std::vector<const CodeGenInstruction*> &AllInstructions; // Vector of uid's for this filter chooser to work on. - const std::vector<unsigned> Opcodes; + const std::vector<unsigned> &Opcodes; // Lookup table for the operand decoding of instructions. - std::map<unsigned, std::vector<OperandInfo> > &Operands; + const std::map<unsigned, std::vector<OperandInfo> > &Operands; // Vector of candidate filters. std::vector<Filter> Filters; @@ -230,7 +227,7 @@ protected: std::vector<bit_value_t> FilterBitValues; // Links to the FilterChooser above us in the decoding tree. - FilterChooser *Parent; + const FilterChooser *Parent; // Index of the best filter from Filters. int BestIndex; @@ -242,19 +239,19 @@ protected: const FixedLenDecoderEmitter *Emitter; public: - FilterChooser(const FilterChooser &FC) : - AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), + FilterChooser(const FilterChooser &FC) + : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), Operands(FC.Operands), Filters(FC.Filters), FilterBitValues(FC.FilterBitValues), Parent(FC.Parent), - BestIndex(FC.BestIndex), BitWidth(FC.BitWidth), - Emitter(FC.Emitter) { } + BestIndex(FC.BestIndex), BitWidth(FC.BitWidth), + Emitter(FC.Emitter) { } FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, const std::vector<unsigned> &IDs, - std::map<unsigned, std::vector<OperandInfo> > &Ops, + const std::map<unsigned, std::vector<OperandInfo> > &Ops, unsigned BW, - const FixedLenDecoderEmitter *E) : - AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), + const FixedLenDecoderEmitter *E) + : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) { for (unsigned i = 0; i < BitWidth; ++i) FilterBitValues.push_back(BIT_UNFILTERED); @@ -264,10 +261,10 @@ public: FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, const std::vector<unsigned> &IDs, - std::map<unsigned, std::vector<OperandInfo> > &Ops, - std::vector<bit_value_t> &ParentFilterBitValues, - FilterChooser &parent) : - AllInstructions(Insts), Opcodes(IDs), Operands(Ops), + const std::map<unsigned, std::vector<OperandInfo> > &Ops, + const std::vector<bit_value_t> &ParentFilterBitValues, + const FilterChooser &parent) + : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth), Emitter(parent.Emitter) { @@ -275,18 +272,31 @@ public: } // The top level filter chooser has NULL as its parent. - bool isTopLevel() { return Parent == NULL; } + bool isTopLevel() const { return Parent == NULL; } // Emit the top level typedef and decodeInstruction() function. - void emitTop(raw_ostream &o, unsigned Indentation, std::string Namespace); + void emitTop(raw_ostream &o, unsigned Indentation, + const std::string &Namespace) const; protected: // Populates the insn given the uid. void insnWithID(insn_t &Insn, unsigned Opcode) const { BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst"); - for (unsigned i = 0; i < BitWidth; ++i) - Insn.push_back(bitFromBits(Bits, i)); + // 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. + BitsInit *SFBits = + AllInstructions[Opcode]->TheDef->getValueAsBitsInit("SoftFail"); + + for (unsigned i = 0; i < BitWidth; ++i) { + if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE) + Insn.push_back(BIT_UNSET); + else + Insn.push_back(bitFromBits(Bits, i)); + } } // Returns the record name. @@ -300,15 +310,16 @@ protected: // Returns false if there exists any uninitialized bit value in the range. // Returns true, otherwise. bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit, - unsigned NumBits) const; + unsigned NumBits) const; /// dumpFilterArray - dumpFilterArray prints out debugging info for the given /// filter array as a series of chars. - void dumpFilterArray(raw_ostream &o, std::vector<bit_value_t> & filter); + void dumpFilterArray(raw_ostream &o, + const std::vector<bit_value_t> & filter) const; /// dumpStack - dumpStack traverses the filter chooser chain and calls /// dumpFilterArray on each filter chooser up to the top level one. - void dumpStack(raw_ostream &o, const char *prefix); + void dumpStack(raw_ostream &o, const char *prefix) const; Filter &bestFilter() { assert(BestIndex != -1 && "BestIndex not set"); @@ -316,9 +327,9 @@ protected: } // Called from Filter::recurse() when singleton exists. For debug purpose. - void SingletonExists(unsigned Opc); + void SingletonExists(unsigned Opc) const; - bool PositionFiltered(unsigned i) { + bool PositionFiltered(unsigned i) const { return ValueSet(FilterBitValues[i]); } @@ -327,31 +338,37 @@ protected: // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be // decoded bits in order to verify that the instruction matches the Opcode. unsigned getIslands(std::vector<unsigned> &StartBits, - std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, - insn_t &Insn); + std::vector<unsigned> &EndBits, + std::vector<uint64_t> &FieldVals, + const insn_t &Insn) const; // Emits code to check the Predicates member of an instruction are true. // Returns true if predicate matches were emitted, false otherwise. - bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation,unsigned Opc); + bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation, + unsigned Opc) const; + + void emitSoftFailCheck(raw_ostream &o, unsigned Indentation, + unsigned Opc) const; // Emits code to decode the singleton. Return true if we have matched all the // well-known bits. - bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc); + bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + unsigned Opc) const; // Emits code to decode the singleton, and then to decode the rest. - void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best); + void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + const Filter &Best) const; void emitBinaryParser(raw_ostream &o , unsigned &Indentation, - OperandInfo &OpInfo); + const OperandInfo &OpInfo) const; // Assign a single filter and run with it. - void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit, - bool mixed); + void runSingleFilter(unsigned startBit, unsigned numBit, bool mixed); // reportRegion is a helper function for filterProcessor to mark a region as // eligible for use as a filter region. void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex, - bool AllowMixed); + bool AllowMixed); // FilterProcessor scans the well-known encoding bits of the instructions and // builds up a list of candidate filters. It chooses the best filter and @@ -366,31 +383,30 @@ protected: // Emits code to decode our share of instructions. Returns true if the // emitted code causes a return, which occurs if we know how to decode // the instruction at this level or the instruction is not decodeable. - bool emit(raw_ostream &o, unsigned &Indentation); + bool emit(raw_ostream &o, unsigned &Indentation) const; }; /////////////////////////// // // -// Filter Implmenetation // +// Filter Implementation // // // /////////////////////////// -Filter::Filter(const Filter &f) : - Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), - FilteredInstructions(f.FilteredInstructions), - VariableInstructions(f.VariableInstructions), - FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), - LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) { +Filter::Filter(const Filter &f) + : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), + FilteredInstructions(f.FilteredInstructions), + VariableInstructions(f.VariableInstructions), + FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), + LastOpcFiltered(f.LastOpcFiltered) { } Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, - bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits), - Mixed(mixed) { + bool mixed) + : Owner(&owner), StartBit(startBit), NumBits(numBits), Mixed(mixed) { assert(StartBit + NumBits - 1 < Owner->BitWidth); NumFiltered = 0; LastOpcFiltered = 0; - NumVariable = 0; for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) { insn_t Insn; @@ -409,10 +425,9 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, FilteredInstructions[Field].push_back(LastOpcFiltered); ++NumFiltered; } else { - // Some of the encoding bit(s) are unspecfied. This contributes to + // Some of the encoding bit(s) are unspecified. This contributes to // one additional member of "Variable" instructions. VariableInstructions.push_back(Owner->Opcodes[i]); - ++NumVariable; } } @@ -421,7 +436,7 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, } Filter::~Filter() { - std::map<unsigned, FilterChooser*>::iterator filterIterator; + std::map<unsigned, const FilterChooser*>::iterator filterIterator; for (filterIterator = FilterChooserMap.begin(); filterIterator != FilterChooserMap.end(); filterIterator++) { @@ -450,7 +465,7 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( + FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( (unsigned)-1, new FilterChooser(Owner->AllInstructions, VariableInstructions, @@ -483,7 +498,7 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // category of instructions. - FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( + FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( mapIterator->first, new FilterChooser(Owner->AllInstructions, mapIterator->second, @@ -495,7 +510,7 @@ void Filter::recurse() { } // Emit code to decode instructions given a segment or segments of bits. -void Filter::emit(raw_ostream &o, unsigned &Indentation) { +void Filter::emit(raw_ostream &o, unsigned &Indentation) const { o.indent(Indentation) << "// Check Inst{"; if (NumBits > 1) @@ -507,7 +522,7 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) { << "(insn, " << StartBit << ", " << NumBits << ")) {\n"; - std::map<unsigned, FilterChooser*>::iterator filterIterator; + std::map<unsigned, const FilterChooser*>::const_iterator filterIterator; bool DefaultCase = false; for (filterIterator = FilterChooserMap.begin(); @@ -537,12 +552,12 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) { // encoding bits do not match exactly. if (!DefaultCase) { ++Indentation; ++Indentation; } - bool finished = filterIterator->second->emit(o, Indentation); + filterIterator->second->emit(o, Indentation); // For top level default case, there's no need for a break statement. if (Owner->isTopLevel() && DefaultCase) break; - if (!finished) - o.indent(Indentation) << "break;\n"; + + o.indent(Indentation) << "break;\n"; if (!DefaultCase) { --Indentation; --Indentation; } } @@ -571,13 +586,17 @@ unsigned Filter::usefulness() const { // Emit the top level typedef and decodeInstruction() function. void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation, - std::string Namespace) { + const std::string &Namespace) const { o.indent(Indentation) << - "static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" << BitWidth - << "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, " + "static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" + << BitWidth << "(MCInst &MI, uint" << BitWidth + << "_t insn, uint64_t Address, " << "const void *Decoder, const MCSubtargetInfo &STI) {\n"; - o.indent(Indentation) << " unsigned tmp = 0;\n (void)tmp;\n" << Emitter->Locals << "\n"; + o.indent(Indentation) << " unsigned tmp = 0;\n"; + o.indent(Indentation) << " (void)tmp;\n"; + o.indent(Indentation) << Emitter->Locals << "\n"; o.indent(Indentation) << " uint64_t Bits = STI.getFeatureBits();\n"; + o.indent(Indentation) << " (void)Bits;\n"; ++Indentation; ++Indentation; // Emits code to decode the instructions. @@ -598,7 +617,7 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation, // Returns false if and on the first uninitialized bit value encountered. // Returns true, otherwise. bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, - unsigned StartBit, unsigned NumBits) const { + unsigned StartBit, unsigned NumBits) const { Field = 0; for (unsigned i = 0; i < NumBits; ++i) { @@ -615,7 +634,7 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, /// dumpFilterArray - dumpFilterArray prints out debugging info for the given /// filter array as a series of chars. void FilterChooser::dumpFilterArray(raw_ostream &o, - std::vector<bit_value_t> &filter) { + const std::vector<bit_value_t> &filter) const { unsigned bitIndex; for (bitIndex = BitWidth; bitIndex > 0; bitIndex--) { @@ -638,8 +657,8 @@ void FilterChooser::dumpFilterArray(raw_ostream &o, /// dumpStack - dumpStack traverses the filter chooser chain and calls /// dumpFilterArray on each filter chooser up to the top level one. -void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) { - FilterChooser *current = this; +void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) const { + const FilterChooser *current = this; while (current) { o << prefix; @@ -650,7 +669,7 @@ void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) { } // Called from Filter::recurse() when singleton exists. For debug purpose. -void FilterChooser::SingletonExists(unsigned Opc) { +void FilterChooser::SingletonExists(unsigned Opc) const { insn_t Insn0; insnWithID(Insn0, Opc); @@ -663,7 +682,7 @@ void FilterChooser::SingletonExists(unsigned Opc) { errs() << '\n'; dumpStack(errs(), "\t\t"); - for (unsigned i = 0; i < Opcodes.size(); i++) { + for (unsigned i = 0; i < Opcodes.size(); ++i) { const std::string &Name = nameWithID(Opcodes[i]); errs() << '\t' << Name << " "; @@ -678,8 +697,9 @@ void FilterChooser::SingletonExists(unsigned Opc) { // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be // decoded bits in order to verify that the instruction matches the Opcode. unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, - std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, - insn_t &Insn) { + std::vector<unsigned> &EndBits, + std::vector<uint64_t> &FieldVals, + const insn_t &Insn) const { unsigned Num, BitNo; Num = BitNo = 0; @@ -695,9 +715,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, Val = Value(Insn[i]); bool Filtered = PositionFiltered(i); switch (State) { - default: - assert(0 && "Unreachable code!"); - break; + default: llvm_unreachable("Unreachable code!"); case 0: case 1: if (Filtered || Val == -1) @@ -736,17 +754,17 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, } void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, - OperandInfo &OpInfo) { - std::string &Decoder = OpInfo.Decoder; + const OperandInfo &OpInfo) const { + const std::string &Decoder = OpInfo.Decoder; if (OpInfo.numFields() == 1) { - OperandInfo::iterator OI = OpInfo.begin(); + OperandInfo::const_iterator OI = OpInfo.begin(); o.indent(Indentation) << " tmp = fieldFromInstruction" << BitWidth << "(insn, " << OI->Base << ", " << OI->Width << ");\n"; } else { o.indent(Indentation) << " tmp = 0;\n"; - for (OperandInfo::iterator OI = OpInfo.begin(), OE = OpInfo.end(); + for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); OI != OE; ++OI) { o.indent(Indentation) << " tmp |= (fieldFromInstruction" << BitWidth << "(insn, " << OI->Base << ", " << OI->Width @@ -756,14 +774,15 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, if (Decoder != "") o.indent(Indentation) << " " << Emitter->GuardPrefix << Decoder - << "(MI, tmp, Address, Decoder)" << Emitter->GuardPostfix << "\n"; + << "(MI, tmp, Address, Decoder)" + << Emitter->GuardPostfix << "\n"; else o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; } static void emitSinglePredicateMatch(raw_ostream &o, StringRef str, - std::string PredicateNamespace) { + const std::string &PredicateNamespace) { if (str[0] == '!') o << "!(Bits & " << PredicateNamespace << "::" << str.slice(1,str.size()) << ")"; @@ -772,8 +791,9 @@ static void emitSinglePredicateMatch(raw_ostream &o, StringRef str, } bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, - unsigned Opc) { - ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates"); + unsigned Opc) const { + ListInit *Predicates = + AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates"); for (unsigned i = 0; i < Predicates->getSize(); ++i) { Record *Pred = Predicates->getElementAsRecord(i); if (!Pred->getValue("AssemblerMatcherPredicate")) @@ -799,10 +819,70 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, return Predicates->getSize() > 0; } +void FilterChooser::emitSoftFailCheck(raw_ostream &o, unsigned Indentation, + unsigned Opc) const { + BitsInit *SFBits = + AllInstructions[Opc]->TheDef->getValueAsBitsInit("SoftFail"); + if (!SFBits) return; + BitsInit *InstBits = AllInstructions[Opc]->TheDef->getValueAsBitsInit("Inst"); + + APInt PositiveMask(BitWidth, 0ULL); + APInt NegativeMask(BitWidth, 0ULL); + for (unsigned i = 0; i < BitWidth; ++i) { + bit_value_t B = bitFromBits(*SFBits, i); + bit_value_t IB = bitFromBits(*InstBits, i); + + if (B != BIT_TRUE) continue; + + switch (IB) { + case BIT_FALSE: + // The bit is meant to be false, so emit a check to see if it is true. + PositiveMask.setBit(i); + break; + case BIT_TRUE: + // The bit is meant to be true, so emit a check to see if it is false. + NegativeMask.setBit(i); + break; + default: + // The bit is not set; this must be an error! + StringRef Name = AllInstructions[Opc]->TheDef->getName(); + errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in " + << Name + << " is set but Inst{" << i <<"} is unset!\n" + << " - You can only mark a bit as SoftFail if it is fully defined" + << " (1/0 - not '?') in Inst\n"; + o << "#error SoftFail Conflict, " << Name << "::SoftFail{" << i + << "} set but Inst{" << i << "} undefined!\n"; + } + } + + bool NeedPositiveMask = PositiveMask.getBoolValue(); + bool NeedNegativeMask = NegativeMask.getBoolValue(); + + if (!NeedPositiveMask && !NeedNegativeMask) + return; + + std::string PositiveMaskStr = PositiveMask.toString(16, /*signed=*/false); + std::string NegativeMaskStr = NegativeMask.toString(16, /*signed=*/false); + StringRef BitExt = ""; + if (BitWidth > 32) + BitExt = "ULL"; + + o.indent(Indentation) << "if ("; + if (NeedPositiveMask) + o << "insn & 0x" << PositiveMaskStr << BitExt; + if (NeedPositiveMask && NeedNegativeMask) + o << " || "; + if (NeedNegativeMask) + o << "~insn & 0x" << NegativeMaskStr << BitExt; + o << ")\n"; + o.indent(Indentation+2) << "S = MCDisassembler::SoftFail;\n"; +} + // Emits code to decode the singleton. Return true if we have matched all the // well-known bits. bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - unsigned Opc) { + unsigned Opc) const { std::vector<unsigned> StartBits; std::vector<unsigned> EndBits; std::vector<uint64_t> FieldVals; @@ -821,22 +901,26 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, if (!emitPredicateMatch(o, Indentation, Opc)) o << "1"; o << ") {\n"; + emitSoftFailCheck(o, Indentation+2, Opc); o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; - std::vector<OperandInfo>& InsnOperands = Operands[Opc]; - for (std::vector<OperandInfo>::iterator + std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = + Operands.find(Opc); + const std::vector<OperandInfo>& InsnOperands = OpIter->second; + for (std::vector<OperandInfo>::const_iterator I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { // If a custom instruction decoder was specified, use that. if (I->numFields() == 0 && I->Decoder.size()) { o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder - << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n"; + << "(MI, insn, Address, Decoder)" + << Emitter->GuardPostfix << "\n"; break; } emitBinaryParser(o, Indentation, *I); } - o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc) - << '\n'; + o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " + << nameWithID(Opc) << '\n'; o.indent(Indentation) << "}\n"; // Closing predicate block. return true; } @@ -870,21 +954,25 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, else o << ") {\n"; } + emitSoftFailCheck(o, Indentation+2, Opc); o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; - std::vector<OperandInfo>& InsnOperands = Operands[Opc]; - for (std::vector<OperandInfo>::iterator + std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = + Operands.find(Opc); + const std::vector<OperandInfo>& InsnOperands = OpIter->second; + for (std::vector<OperandInfo>::const_iterator I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { // If a custom instruction decoder was specified, use that. if (I->numFields() == 0 && I->Decoder.size()) { o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder - << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n"; + << "(MI, insn, Address, Decoder)" + << Emitter->GuardPostfix << "\n"; break; } emitBinaryParser(o, Indentation, *I); } - o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc) - << '\n'; + o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " + << nameWithID(Opc) << '\n'; o.indent(Indentation) << "}\n"; return false; @@ -892,7 +980,7 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, // Emits code to decode the singleton, and then to decode the rest. void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - Filter &Best) { + const Filter &Best) const { unsigned Opc = Best.getSingletonOpc(); @@ -908,8 +996,8 @@ void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, // Assign a single filter and run with it. Top level API client can initialize // with a single filter to start the filtering process. -void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit, - unsigned numBit, bool mixed) { +void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, + bool mixed) { Filters.clear(); Filter F(*this, startBit, numBit, true); Filters.push_back(F); @@ -920,7 +1008,7 @@ void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit, // reportRegion is a helper function for filterProcessor to mark a region as // eligible for use as a filter region. void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, - unsigned BitIndex, bool AllowMixed) { + unsigned BitIndex, bool AllowMixed) { if (RA == ATTR_MIXED && AllowMixed) Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true)); else if (RA == ATTR_ALL_SET && !AllowMixed) @@ -957,8 +1045,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { // Look for islands of undecoded bits of any instruction. if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) { // Found an instruction with island(s). Now just assign a filter. - runSingleFilter(*this, StartBits[0], EndBits[0] - StartBits[0] + 1, - true); + runSingleFilter(StartBits[0], EndBits[0] - StartBits[0] + 1, true); return true; } } @@ -1066,7 +1153,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { RA = ATTR_MIXED; break; default: - assert(0 && "Unexpected bitAttr!"); + llvm_unreachable("Unexpected bitAttr!"); } break; case ATTR_ALL_SET: @@ -1087,7 +1174,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { RA = ATTR_MIXED; break; default: - assert(0 && "Unexpected bitAttr!"); + llvm_unreachable("Unexpected bitAttr!"); } break; case ATTR_MIXED: @@ -1109,13 +1196,13 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { case ATTR_MIXED: break; default: - assert(0 && "Unexpected bitAttr!"); + llvm_unreachable("Unexpected bitAttr!"); } break; case ATTR_ALL_UNSET: - assert(0 && "regionAttr state machine has no ATTR_UNSET state"); + llvm_unreachable("regionAttr state machine has no ATTR_UNSET state"); case ATTR_FILTERED: - assert(0 && "regionAttr state machine has no ATTR_FILTERED state"); + llvm_unreachable("regionAttr state machine has no ATTR_FILTERED state"); } } @@ -1189,7 +1276,7 @@ void FilterChooser::doFilter() { // Emits code to decode our share of instructions. Returns true if the // emitted code causes a return, which occurs if we know how to decode // the instruction at this level or the instruction is not decodeable. -bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { +bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) const { if (Opcodes.size() == 1) // There is only one instruction in the set, which is great! // Call emitSingletonDecoder() to see whether there are any remaining @@ -1198,11 +1285,11 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { // Choose the best filter to do the decodings! if (BestIndex != -1) { - Filter &Best = bestFilter(); + const Filter &Best = Filters[BestIndex]; if (Best.getNumFiltered() == 1) emitSingletonDecoder(o, Indentation, Best); else - bestFilter().emit(o, Indentation); + Best.emit(o, Indentation); return false; } @@ -1222,7 +1309,7 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { dumpStack(errs(), "\t\t"); - for (unsigned i = 0; i < Opcodes.size(); i++) { + for (unsigned i = 0; i < Opcodes.size(); ++i) { const std::string &Name = nameWithID(Opcodes[i]); errs() << '\t' << Name << " "; @@ -1234,9 +1321,8 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { return true; } -static bool populateInstruction(const CodeGenInstruction &CGI, - unsigned Opc, - std::map<unsigned, std::vector<OperandInfo> >& Operands){ +static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, + std::map<unsigned, std::vector<OperandInfo> > &Operands){ const Record &Def = *CGI.TheDef; // If all the bit positions are not specified; do not decode this instruction. // We are bound to fail! For proper disassembly, the well-known encoding bits @@ -1290,7 +1376,7 @@ static bool populateInstruction(const CodeGenInstruction &CGI, } // For each operand, see if we can figure out where it is encoded. - for (std::vector<std::pair<Init*, std::string> >::iterator + for (std::vector<std::pair<Init*, std::string> >::const_iterator NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) { std::string Decoder = ""; @@ -1435,8 +1521,7 @@ static void emitHelper(llvm::raw_ostream &o, unsigned BitWidth) { } // Emits disassembler code for instruction decoding. -void FixedLenDecoderEmitter::run(raw_ostream &o) -{ +void FixedLenDecoderEmitter::run(raw_ostream &o) { o << "#include \"llvm/MC/MCInst.h\"\n"; o << "#include \"llvm/Support/DataTypes.h\"\n"; o << "#include <assert.h>\n"; @@ -1444,14 +1529,15 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) o << "namespace llvm {\n\n"; // Parameterize the decoders based on namespace and instruction width. - NumberedInstructions = Target.getInstructionsByEnumValue(); + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); std::map<std::pair<std::string, unsigned>, std::vector<unsigned> > OpcMap; std::map<unsigned, std::vector<OperandInfo> > Operands; for (unsigned i = 0; i < NumberedInstructions.size(); ++i) { const CodeGenInstruction *Inst = NumberedInstructions[i]; - Record *Def = Inst->TheDef; + const Record *Def = Inst->TheDef; unsigned Size = Def->getValueAsInt("Size"); if (Def->getValueAsString("Namespace") == "TargetOpcode" || Def->getValueAsBit("isPseudo") || @@ -1470,7 +1556,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) std::set<unsigned> Sizes; for (std::map<std::pair<std::string, unsigned>, - std::vector<unsigned> >::iterator + std::vector<unsigned> >::const_iterator I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) { // If we haven't visited this instruction width before, emit the // helper method to extract fields. diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h index 2df5448aa8d1..195297c966dd 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h @@ -39,12 +39,12 @@ struct OperandInfo { Fields.push_back(EncodingField(Base, Width, Offset)); } - unsigned numFields() { return Fields.size(); } + unsigned numFields() const { return Fields.size(); } - typedef std::vector<EncodingField>::iterator iterator; + typedef std::vector<EncodingField>::const_iterator const_iterator; - iterator begin() { return Fields.begin(); } - iterator end() { return Fields.end(); } + const_iterator begin() const { return Fields.begin(); } + const_iterator end() const { return Fields.end(); } }; class FixedLenDecoderEmitter : public TableGenBackend { @@ -52,12 +52,12 @@ public: FixedLenDecoderEmitter(RecordKeeper &R, std::string PredicateNamespace, std::string GPrefix = "if (", - std::string GPostfix = " == MCDisassembler::Fail) return MCDisassembler::Fail;", + std::string GPostfix = " == MCDisassembler::Fail)" + " return MCDisassembler::Fail;", std::string ROK = "MCDisassembler::Success", std::string RFail = "MCDisassembler::Fail", std::string L = "") : - Records(R), Target(R), - NumberedInstructions(Target.getInstructionsByEnumValue()), + Target(R), PredicateNamespace(PredicateNamespace), GuardPrefix(GPrefix), GuardPostfix(GPostfix), ReturnOK(ROK), ReturnFail(RFail), Locals(L) {} @@ -66,11 +66,7 @@ public: void run(raw_ostream &o); private: - RecordKeeper &Records; CodeGenTarget Target; - std::vector<const CodeGenInstruction*> NumberedInstructions; - std::vector<unsigned> Opcodes; - std::map<unsigned, std::vector<OperandInfo> > Operands; public: std::string PredicateNamespace; std::string GuardPrefix, GuardPostfix; diff --git a/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp b/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp deleted file mode 100644 index 5981afde0e7e..000000000000 --- a/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//===- InstrEnumEmitter.cpp - Generate Instruction Set Enums --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This tablegen backend is responsible for emitting enums for each machine -// instruction. -// -//===----------------------------------------------------------------------===// - -#include "InstrEnumEmitter.h" -#include "CodeGenTarget.h" -#include "llvm/TableGen/Record.h" -#include <cstdio> -using namespace llvm; - -// runEnums - Print out enum values for all of the instructions. -void InstrEnumEmitter::run(raw_ostream &OS) { - EmitSourceFileHeader("Target Instruction Enum Values", OS); - OS << "namespace llvm {\n\n"; - - CodeGenTarget Target(Records); - - // We must emit the PHI opcode first... - std::string Namespace = Target.getInstNamespace(); - - if (Namespace.empty()) { - fprintf(stderr, "No instructions defined!\n"); - exit(1); - } - - const std::vector<const CodeGenInstruction*> &NumberedInstructions = - Target.getInstructionsByEnumValue(); - - OS << "namespace " << Namespace << " {\n"; - OS << " enum {\n"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - OS << " " << NumberedInstructions[i]->TheDef->getName() - << "\t= " << i << ",\n"; - } - OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; - OS << " };\n}\n"; - OS << "} // End llvm namespace \n"; -} diff --git a/contrib/llvm/utils/TableGen/InstrEnumEmitter.h b/contrib/llvm/utils/TableGen/InstrEnumEmitter.h deleted file mode 100644 index c29a30938d34..000000000000 --- a/contrib/llvm/utils/TableGen/InstrEnumEmitter.h +++ /dev/null @@ -1,33 +0,0 @@ -//===- InstrEnumEmitter.h - Generate Instruction Set Enums ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This tablegen backend is responsible for emitting enums for each machine -// instruction. -// -//===----------------------------------------------------------------------===// - -#ifndef INSTRENUM_EMITTER_H -#define INSTRENUM_EMITTER_H - -#include "llvm/TableGen/TableGenBackend.h" - -namespace llvm { - -class InstrEnumEmitter : public TableGenBackend { - RecordKeeper &Records; -public: - InstrEnumEmitter(RecordKeeper &R) : Records(R) {} - - // run - Output the instruction set description, returning true on failure. - void run(raw_ostream &OS); -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp index 8341724a73e4..8b3efd33f4dc 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -14,14 +14,16 @@ #include "InstrInfoEmitter.h" #include "CodeGenTarget.h" +#include "SequenceToOffsetTable.h" #include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include <algorithm> +#include <cstdio> using namespace llvm; static void PrintDefList(const std::vector<Record*> &Uses, unsigned Num, raw_ostream &OS) { - OS << "static const unsigned ImplicitList" << Num << "[] = { "; + OS << "static const uint16_t ImplicitList" << Num << "[] = { "; for (unsigned i = 0, e = Uses.size(); i != e; ++i) OS << getQualifiedName(Uses[i]) << ", "; OS << "0 };\n"; @@ -106,6 +108,11 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand")) Res += "|(1<<MCOI::OptionalDef)"; + // Fill in operand type. + Res += ", MCOI::"; + assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type."); + Res += Inst.Operands[i].OperandType; + // Fill in constraint info. Res += ", "; @@ -121,11 +128,6 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { " << 16) | (1 << MCOI::TIED_TO))"; } - // Fill in operand type. - Res += ", MCOI::"; - assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type."); - Res += Inst.Operands[i].OperandType; - Result.push_back(Res); } } @@ -203,7 +205,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { // Emit all of the MCInstrDesc records in their ENUM ordering. // - OS << "\nMCInstrDesc " << TargetName << "Insts[] = {\n"; + OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n"; const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); @@ -212,10 +214,33 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OperandInfoIDs, OS); OS << "};\n\n"; + // Build an array of instruction names + SequenceToOffsetTable<std::string> InstrNames; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + const CodeGenInstruction *Instr = NumberedInstructions[i]; + InstrNames.add(Instr->TheDef->getName()); + } + + InstrNames.layout(); + OS << "extern const char " << TargetName << "InstrNameData[] = {\n"; + InstrNames.emit(OS, printChar); + OS << "};\n\n"; + + OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {"; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + if (i % 8 == 0) + OS << "\n "; + const CodeGenInstruction *Instr = NumberedInstructions[i]; + OS << InstrNames.get(Instr->TheDef->getName()) << "U, "; + } + + OS << "\n};\n\n"; + // MCInstrInfo initialization routine. OS << "static inline void Init" << TargetName << "MCInstrInfo(MCInstrInfo *II) {\n"; OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " + << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " << NumberedInstructions.size() << ");\n}\n\n"; OS << "} // End llvm namespace \n"; @@ -239,10 +264,13 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "#undef GET_INSTRINFO_CTOR\n"; OS << "namespace llvm {\n"; - OS << "extern MCInstrDesc " << TargetName << "Insts[];\n"; + OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n"; + OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; + OS << "extern const char " << TargetName << "InstrNameData[];\n"; OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" << " : TargetInstrInfoImpl(SO, DO) {\n" << " InitMCInstrInfo(" << TargetName << "Insts, " + << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " << NumberedInstructions.size() << ");\n}\n"; OS << "} // End llvm namespace \n"; @@ -264,8 +292,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << Num << ",\t" << MinOperands << ",\t" << Inst.Operands.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef) << ",\t" - << Inst.TheDef->getValueAsInt("Size") << ",\t\"" - << Inst.TheDef->getName() << "\", 0"; + << Inst.TheDef->getValueAsInt("Size") << ",\t0"; // Emit all of the target indepedent flags... if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)"; @@ -346,7 +373,7 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { // We must emit the PHI opcode first... std::string Namespace = Target.getInstNamespace(); - + if (Namespace.empty()) { fprintf(stderr, "No instructions defined!\n"); exit(1); diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h index 1461e2c5f7cf..f8d3ea51c814 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h @@ -31,19 +31,19 @@ class InstrInfoEmitter : public TableGenBackend { RecordKeeper &Records; CodeGenDAGPatterns CDP; std::map<std::string, unsigned> ItinClassMap; - + public: InstrInfoEmitter(RecordKeeper &R) : Records(R), CDP(R) { } - // run - Output the instruction set description, returning true on failure. + // run - Output the instruction set description. void run(raw_ostream &OS); private: void emitEnums(raw_ostream &OS); - typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; + typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; void emitRecord(const CodeGenInstruction &Inst, unsigned Num, - Record *InstrInfo, + Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EL, const OperandInfoMapTy &OpInfo, raw_ostream &OS); @@ -51,7 +51,7 @@ private: // Itinerary information. void GatherItinClasses(); unsigned getItinClassNumber(const Record *InstRec); - + // Operand information. void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp index 782b89ede2e7..8e1bae8c1f0f 100644 --- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -57,9 +57,6 @@ void IntrinsicEmitter::run(raw_ostream &OS) { // Emit intrinsic alias analysis mod/ref behavior. EmitModRefBehavior(Ints, OS); - // Emit a list of intrinsics with corresponding GCC builtins. - EmitGCCBuiltinList(Ints, OS); - // Emit code to translate GCC builtins into LLVM intrinsics. EmitIntrinsicToGCCBuiltinMap(Ints, OS); @@ -160,17 +157,20 @@ EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, void IntrinsicEmitter:: EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { - OS << "// Intrinsic ID to overload table\n"; + OS << "// Intrinsic ID to overload bitset\n"; OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n"; - OS << " // Note that entry #0 is the invalid intrinsic!\n"; + OS << "static const uint8_t OTable[] = {\n"; + OS << " 0"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - OS << " "; + // Add one to the index so we emit a null bit for the invalid #0 intrinsic. + if ((i+1)%8 == 0) + OS << ",\n 0"; if (Ints[i].isOverloaded) - OS << "true"; - else - OS << "false"; - OS << ",\n"; + OS << " | (1<<" << (i+1)%8 << ')'; } + OS << "\n};\n\n"; + // OTable contains a true bit at the position if the intrinsic is overloaded. + OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n"; OS << "#endif\n\n"; } @@ -181,6 +181,8 @@ static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) { } else if (VT == MVT::Other) { // MVT::OtherVT is used to mean the empty struct type here. OS << "StructType::get(Context)"; + } else if (VT == MVT::f16) { + OS << "Type::getHalfTy(Context)"; } else if (VT == MVT::f32) { OS << "Type::getFloatTy(Context)"; } else if (VT == MVT::f64) { @@ -318,7 +320,7 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, OS << "// Verifier::visitIntrinsicFunctionCall code.\n"; OS << "#ifdef GET_INTRINSIC_VERIFIER\n"; OS << " switch (ID) {\n"; - OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; + OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n"; // This checking can emit a lot of very common code. To reduce the amount of // code that we emit, batch up cases that have identical types. This avoids @@ -414,7 +416,7 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, OS << "// Code for generating Intrinsic function declarations.\n"; OS << "#ifdef GET_INTRINSIC_GENERATOR\n"; OS << " switch (id) {\n"; - OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; + OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n"; // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical // types. @@ -483,8 +485,7 @@ namespace { case CodeGenIntrinsic::ReadWriteMem: return MRK_none; } - assert(0 && "bad mod-ref kind"); - return MRK_none; + llvm_unreachable("bad mod-ref kind"); } struct AttributeComparator { @@ -516,37 +517,50 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { else OS << "AttrListPtr Intrinsic::getAttributes(ID id) {\n"; - // Compute the maximum number of attribute arguments. - std::vector<const CodeGenIntrinsic*> sortedIntrinsics(Ints.size()); + // Compute the maximum number of attribute arguments and the map + typedef std::map<const CodeGenIntrinsic*, unsigned, + AttributeComparator> UniqAttrMapTy; + UniqAttrMapTy UniqAttributes; unsigned maxArgAttrs = 0; + unsigned AttrNum = 0; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { const CodeGenIntrinsic &intrinsic = Ints[i]; - sortedIntrinsics[i] = &intrinsic; maxArgAttrs = std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size())); + unsigned &N = UniqAttributes[&intrinsic]; + if (N) continue; + assert(AttrNum < 256 && "Too many unique attributes for table!"); + N = ++AttrNum; } // Emit an array of AttributeWithIndex. Most intrinsics will have // at least one entry, for the function itself (index ~1), which is // usually nounwind. - OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n"; - OS << " unsigned NumAttrs = 0;\n"; - OS << " switch (id) {\n"; - OS << " default: break;\n"; + OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n"; - AttributeComparator precedes; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + const CodeGenIntrinsic &intrinsic = Ints[i]; - std::stable_sort(sortedIntrinsics.begin(), sortedIntrinsics.end(), precedes); + OS << " " << UniqAttributes[&intrinsic] << ", // " + << intrinsic.Name << "\n"; + } + OS << " };\n\n"; - for (unsigned i = 0, e = sortedIntrinsics.size(); i != e; ++i) { - const CodeGenIntrinsic &intrinsic = *sortedIntrinsics[i]; - OS << " case " << TargetPrefix << "Intrinsic::" - << intrinsic.EnumName << ":\n"; + OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n"; + OS << " unsigned NumAttrs = 0;\n"; + OS << " if (id != 0) {\n"; + OS << " switch(IntrinsicsToAttributesMap[id - "; + if (TargetOnly) + OS << "Intrinsic::num_intrinsics"; + else + OS << "1"; + OS << "]) {\n"; + OS << " default: llvm_unreachable(\"Invalid attribute number\");\n"; + for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(), + E = UniqAttributes.end(); I != E; ++I) { + OS << " case " << I->second << ":\n"; - // Fill out the case if this is the last case for this range of - // intrinsics. - if (i + 1 != e && !precedes(&intrinsic, sortedIntrinsics[i + 1])) - continue; + const CodeGenIntrinsic &intrinsic = *(I->first); // Keep track of the number of attributes we're writing out. unsigned numAttrs = 0; @@ -554,8 +568,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { // The argument attributes are alreadys sorted by argument index. for (unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); ai != ae;) { unsigned argNo = intrinsic.ArgumentAttributes[ai].first; - - OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(" + + OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(" << argNo+1 << ", "; bool moreThanOne = false; @@ -579,7 +593,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { ModRefKind modRef = getModRefKind(intrinsic); if (!intrinsic.canThrow || modRef) { - OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, "; + OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, "; if (!intrinsic.canThrow) { OS << "Attribute::NoUnwind"; if (modRef) OS << '|'; @@ -593,13 +607,14 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { } if (numAttrs) { - OS << " NumAttrs = " << numAttrs << ";\n"; - OS << " break;\n"; + OS << " NumAttrs = " << numAttrs << ";\n"; + OS << " break;\n"; } else { - OS << " return AttrListPtr();\n"; + OS << " return AttrListPtr();\n"; } } + OS << " }\n"; OS << " }\n"; OS << " return AttrListPtr::get(AWI, NumAttrs);\n"; OS << "}\n"; @@ -609,50 +624,36 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { /// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. void IntrinsicEmitter:: EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ - OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"; - OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"; - OS << "switch (iid) {\n"; - OS << "default:\n return UnknownModRefBehavior;\n"; + OS << "// Determine intrinsic alias analysis mod/ref behavior.\n" + << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n" + << "assert(iid <= Intrinsic::" << Ints.back().EnumName << " && " + << "\"Unknown intrinsic.\");\n\n"; + + OS << "static const uint8_t IntrinsicModRefBehavior[] = {\n" + << " /* invalid */ UnknownModRefBehavior,\n"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - if (Ints[i].ModRef == CodeGenIntrinsic::ReadWriteMem) - continue; - OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName - << ":\n"; + OS << " /* " << TargetPrefix << Ints[i].EnumName << " */ "; switch (Ints[i].ModRef) { - default: - assert(false && "Unknown Mod/Ref type!"); case CodeGenIntrinsic::NoMem: - OS << " return DoesNotAccessMemory;\n"; + OS << "DoesNotAccessMemory,\n"; break; case CodeGenIntrinsic::ReadArgMem: - OS << " return OnlyReadsArgumentPointees;\n"; + OS << "OnlyReadsArgumentPointees,\n"; break; case CodeGenIntrinsic::ReadMem: - OS << " return OnlyReadsMemory;\n"; + OS << "OnlyReadsMemory,\n"; break; case CodeGenIntrinsic::ReadWriteArgMem: - OS << " return OnlyAccessesArgumentPointees;\n"; + OS << "OnlyAccessesArgumentPointees,\n"; + break; + case CodeGenIntrinsic::ReadWriteMem: + OS << "UnknownModRefBehavior,\n"; break; } } - OS << "}\n"; - OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; -} - -void IntrinsicEmitter:: -EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ - OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n"; - OS << "#ifdef GET_GCC_BUILTIN_NAME\n"; - OS << " switch (F->getIntrinsicID()) {\n"; - OS << " default: BuiltinName = \"\"; break;\n"; - for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - if (!Ints[i].GCCBuiltinName.empty()) { - OS << " case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \"" - << Ints[i].GCCBuiltinName << "\"; break;\n"; - } - } - OS << " }\n"; - OS << "#endif\n\n"; + OS << "};\n\n" + << "return static_cast<ModRefBehavior>(IntrinsicModRefBehavior[iid]);\n" + << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; } /// EmitTargetBuiltins - All of the builtins in the specified map are for the diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.h b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h index eb6379cc7414..f9bcd5980226 100644 --- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.h +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h @@ -48,8 +48,6 @@ namespace llvm { raw_ostream &OS); void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); - void EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, - raw_ostream &OS); void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); void EmitSuffix(raw_ostream &OS); diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp index c685527a140c..802d112108fa 100644 --- a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp @@ -67,7 +67,7 @@ addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, // Since we added more than one, we also need to adjust the base. BaseIdx += NewOps - 1; } else - assert(0 && "Unhandled pseudo-expansion argument type!"); + llvm_unreachable("Unhandled pseudo-expansion argument type!"); } return OpsAdded; } @@ -100,8 +100,11 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + "' operand count mismatch"); + unsigned NumMIOperands = 0; + for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) + NumMIOperands += Insn.Operands[i].MINumOperands; IndexedMap<OpData> OperandMap; - OperandMap.grow(Insn.Operands.size()); + OperandMap.grow(NumMIOperands); addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0); @@ -176,8 +179,6 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; i != e; ++i) { switch (Expansion.OperandMap[MIOpNo + i].Kind) { - default: - llvm_unreachable("Unknown operand type?!"); case OpData::Operand: o << " lowerOperand(MI->getOperand(" << Source.Operands[Expansion.OperandMap[MIOpNo].Data diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp index b0f4ffc84e08..a2478a7330e8 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -16,6 +16,7 @@ #include "RegisterInfoEmitter.h" #include "CodeGenTarget.h" #include "CodeGenRegisters.h" +#include "SequenceToOffsetTable.h" #include "llvm/TableGen/Record.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringExtras.h" @@ -31,6 +32,9 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &Bank) { const std::vector<CodeGenRegister*> &Registers = Bank.getRegisters(); + // Register enums are stored as uint16_t in the tables. Make sure we'll fit + assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); + std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace"); EmitSourceFileHeader("Target Register Enum Values", OS); @@ -41,7 +45,8 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "namespace llvm {\n\n"; OS << "class MCRegisterClass;\n" - << "extern MCRegisterClass " << Namespace << "MCRegisterClasses[];\n\n"; + << "extern const MCRegisterClass " << Namespace + << "MCRegisterClasses[];\n\n"; if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; @@ -59,6 +64,11 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, ArrayRef<CodeGenRegisterClass*> RegisterClasses = Bank.getRegClasses(); if (!RegisterClasses.empty()) { + + // RegisterClass enums are stored as uint16_t in the tables. + assert(RegisterClasses.size() <= 0xffff && + "Too many register classes to fit in tables"); + OS << "\n// Register classes\n"; if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; @@ -89,16 +99,104 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "}\n"; } + ArrayRef<CodeGenSubRegIndex*> SubRegIndices = Bank.getSubRegIndices(); + if (!SubRegIndices.empty()) { + OS << "\n// Subregister indices\n"; + std::string Namespace = + SubRegIndices[0]->getNamespace(); + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n NoSubRegister,\n"; + for (unsigned i = 0, e = Bank.getNumNamedIndices(); i != e; ++i) + OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; + OS << " NUM_TARGET_NAMED_SUBREGS\n};\n"; + if (!Namespace.empty()) + OS << "}\n"; + } OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_ENUM\n\n"; } -void -RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, - const std::vector<CodeGenRegister*> &Regs, - bool isCtor) { +void RegisterInfoEmitter:: +EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, + const std::string &ClassName) { + unsigned NumRCs = RegBank.getRegClasses().size(); + unsigned NumSets = RegBank.getNumRegPressureSets(); + + OS << "/// Get the weight in units of pressure for this register class.\n" + << "const RegClassWeight &" << ClassName << "::\n" + << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" + << " static const RegClassWeight RCWeightTable[] = {\n"; + for (unsigned i = 0, e = NumRCs; i != e; ++i) { + const CodeGenRegisterClass &RC = *RegBank.getRegClasses()[i]; + const CodeGenRegister::Set &Regs = RC.getMembers(); + if (Regs.empty()) + OS << " {0, 0"; + else { + std::vector<unsigned> RegUnits; + RC.buildRegUnitSet(RegUnits); + OS << " {" << (*Regs.begin())->getWeight(RegBank) + << ", " << RegBank.getRegUnitSetWeight(RegUnits); + } + OS << "}, \t// " << RC.getName() << "\n"; + } + OS << " {0, 0} };\n" + << " return RCWeightTable[RC->getID()];\n" + << "}\n\n"; + + OS << "\n" + << "// Get the number of dimensions of register pressure.\n" + << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" + << " return " << NumSets << ";\n}\n\n"; + + OS << "// Get the register unit pressure limit for this dimension.\n" + << "// This limit must be adjusted dynamically for reserved registers.\n" + << "unsigned " << ClassName << "::\n" + << "getRegPressureSetLimit(unsigned Idx) const {\n" + << " static const unsigned PressureLimitTable[] = {\n"; + for (unsigned i = 0; i < NumSets; ++i ) { + const RegUnitSet &RegUnits = RegBank.getRegPressureSet(i); + OS << " " << RegBank.getRegUnitSetWeight(RegUnits.Units) + << ", \t// " << i << ": " << RegBank.getRegPressureSet(i).Name << "\n"; + } + OS << " 0 };\n" + << " return PressureLimitTable[Idx];\n" + << "}\n\n"; + + OS << "/// Get the dimensions of register pressure " + << "impacted by this register class.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int* " << ClassName << "::\n" + << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n" + << " static const int RCSetsTable[] = {\n "; + std::vector<unsigned> RCSetStarts(NumRCs); + for (unsigned i = 0, StartIdx = 0, e = NumRCs; i != e; ++i) { + RCSetStarts[i] = StartIdx; + ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i); + for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(), + PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { + OS << *PSetI << ", "; + ++StartIdx; + } + OS << "-1, \t// " << RegBank.getRegClasses()[i]->getName() << "\n "; + ++StartIdx; + } + OS << "-1 };\n"; + OS << " static const unsigned RCSetStartTable[] = {\n "; + for (unsigned i = 0, e = NumRCs; i != e; ++i) { + OS << RCSetStarts[i] << ","; + } + OS << "0 };\n" + << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n" + << " return &RCSetsTable[SetListStart];\n" + << "}\n\n"; +} +void +RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, + const std::vector<CodeGenRegister*> &Regs, + bool isCtor) { // Collect all information about dwarf register numbers typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy; DwarfRegNumsMapTy DwarfRegNums; @@ -124,6 +222,121 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) I->second.push_back(-1); + std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + + OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; + + // Emit reverse information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << i << "Dwarf2L[]"; + + if (!isCtor) { + OS << " = {\n"; + + // Store the mapping sorted by the LLVM reg num so lookup can be done + // with a binary search. + std::map<uint64_t, Record*> Dwarf2LMap; + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { + int DwarfRegNo = I->second[i]; + if (DwarfRegNo < 0) + continue; + Dwarf2LMap[DwarfRegNo] = I->first; + } + + for (std::map<uint64_t, Record*>::iterator + I = Dwarf2LMap.begin(), E = Dwarf2LMap.end(); I != E; ++I) + OS << " { " << I->first << "U, " << getQualifiedName(I->second) + << " },\n"; + + OS << "};\n"; + } else { + OS << ";\n"; + } + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; + if (!isCtor) + OS << " = sizeof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + else + OS << ";\n\n"; + } + } + + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + Record *Reg = Regs[i]->TheDef; + const RecordVal *V = Reg->getValue("DwarfAlias"); + if (!V || !V->getValue()) + continue; + + DefInit *DI = dynamic_cast<DefInit*>(V->getValue()); + Record *Alias = DI->getDef(); + DwarfRegNums[Reg] = DwarfRegNums[Alias]; + } + + // Emit information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << i << "L2Dwarf[]"; + if (!isCtor) { + OS << " = {\n"; + // Store the mapping sorted by the Dwarf reg num so lookup can be done + // with a binary search. + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { + int RegNo = I->second[i]; + if (RegNo == -1) // -1 is the default value, don't emit a mapping. + continue; + + OS << " { " << getQualifiedName(I->first) << ", " << RegNo + << "U },\n"; + } + OS << "};\n"; + } else { + OS << ";\n"; + } + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; + if (!isCtor) + OS << " = sizeof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + else + OS << ";\n\n"; + } + } +} + +void +RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, + const std::vector<CodeGenRegister*> &Regs, + bool isCtor) { + // Emit the initializer so the tables from EmitRegMappingTables get wired up + // to the MCRegisterInfo object. + unsigned maxLength = 0; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + Record *Reg = Regs[i]->TheDef; + maxLength = std::max((size_t)maxLength, + Reg->getValueAsListOfInts("DwarfNumbers").size()); + } + + if (!maxLength) + return; + + std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + // Emit reverse information about the dwarf register numbers. for (unsigned j = 0; j < 2; ++j) { OS << " switch ("; @@ -133,43 +346,28 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, OS << "EHFlavour"; OS << ") {\n" << " default:\n" - << " assert(0 && \"Unknown DWARF flavour\");\n" - << " break;\n"; + << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; for (unsigned i = 0, e = maxLength; i != e; ++i) { OS << " case " << i << ":\n"; - for (DwarfRegNumsMapTy::iterator - I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { - int DwarfRegNo = I->second[i]; - if (DwarfRegNo < 0) - continue; - OS << " "; - if (!isCtor) - OS << "RI->"; - OS << "mapDwarfRegToLLVMReg(" << DwarfRegNo << ", " - << getQualifiedName(I->first) << ", "; - if (j == 0) + OS << " "; + if (!isCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "Dwarf2L"; + OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, "; + if (j == 0) OS << "false"; else OS << "true"; - OS << " );\n"; - } + OS << ");\n"; OS << " break;\n"; } OS << " }\n"; } - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; - const RecordVal *V = Reg->getValue("DwarfAlias"); - if (!V || !V->getValue()) - continue; - - DefInit *DI = dynamic_cast<DefInit*>(V->getValue()); - Record *Alias = DI->getDef(); - DwarfRegNums[Reg] = DwarfRegNums[Alias]; - } - // Emit information about the dwarf register numbers. for (unsigned j = 0; j < 2; ++j) { OS << " switch ("; @@ -179,26 +377,23 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, OS << "EHFlavour"; OS << ") {\n" << " default:\n" - << " assert(0 && \"Unknown DWARF flavour\");\n" - << " break;\n"; + << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; for (unsigned i = 0, e = maxLength; i != e; ++i) { OS << " case " << i << ":\n"; - // Sort by name to get a stable order. - for (DwarfRegNumsMapTy::iterator - I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { - int RegNo = I->second[i]; - OS << " "; - if (!isCtor) - OS << "RI->"; - OS << "mapLLVMRegToDwarfReg(" << getQualifiedName(I->first) << ", " - << RegNo << ", "; - if (j == 0) + OS << " "; + if (!isCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "L2Dwarf"; + OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, "; + if (j == 0) OS << "false"; else OS << "true"; - OS << " );\n"; - } + OS << ");\n"; OS << " break;\n"; } OS << " }\n"; @@ -235,6 +430,14 @@ public: } }; +static void printRegister(raw_ostream &OS, const CodeGenRegister *Reg) { + OS << getQualifiedName(Reg->TheDef); +} + +static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) { + OS << getEnumName(VT); +} + // // runMCDesc - Print out MC register descriptions. // @@ -246,87 +449,79 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; + const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); std::map<const CodeGenRegister*, CodeGenRegister::Set> Overlaps; RegBank.computeOverlaps(Overlaps); - OS << "namespace llvm {\n\n"; - - const std::string &TargetName = Target.getName(); - std::string ClassName = TargetName + "GenMCRegisterInfo"; - OS << "struct " << ClassName << " : public MCRegisterInfo {\n" - << " explicit " << ClassName << "(const MCRegisterDesc *D);\n"; - OS << "};\n"; + // The lists of sub-registers, super-registers, and overlaps all go in the + // same array. That allows us to share suffixes. + typedef std::vector<const CodeGenRegister*> RegVec; + SmallVector<RegVec, 4> SubRegLists(Regs.size()); + SmallVector<RegVec, 4> OverlapLists(Regs.size()); + SequenceToOffsetTable<RegVec, CodeGenRegister::Less> RegSeqs; - OS << "\nnamespace {\n"; - - const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); - - // Emit an overlap list for all registers. + // Precompute register lists for the SequenceToOffsetTable. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; - const CodeGenRegister::Set &O = Overlaps[Reg]; - // Move Reg to the front so TRI::getAliasSet can share the list. - OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { " - << getQualifiedName(Reg->TheDef) << ", "; - for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end(); - I != E; ++I) - if (*I != Reg) - OS << getQualifiedName((*I)->TheDef) << ", "; - OS << "0 };\n"; - } - // Emit the empty sub-registers list - OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; - // Loop over all of the registers which have sub-registers, emitting the - // sub-registers list to memory. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - if (Reg.getSubRegs().empty()) - continue; - // getSubRegs() orders by SubRegIndex. We want a topological order. - SetVector<CodeGenRegister*> SR; - Reg.addSubRegsPreOrder(SR); - OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { "; - for (unsigned j = 0, je = SR.size(); j != je; ++j) - OS << getQualifiedName(SR[j]->TheDef) << ", "; - OS << "0 };\n"; + // Compute the ordered sub-register list. + SetVector<const CodeGenRegister*> SR; + Reg->addSubRegsPreOrder(SR, RegBank); + RegVec &SubRegList = SubRegLists[i]; + SubRegList.assign(SR.begin(), SR.end()); + RegSeqs.add(SubRegList); + + // Super-registers are already computed. + const RegVec &SuperRegList = Reg->getSuperRegs(); + RegSeqs.add(SuperRegList); + + // The list of overlaps doesn't need to have any particular order, except + // Reg itself must be the first element. Pick an ordering that has one of + // the other lists as a suffix. + RegVec &OverlapList = OverlapLists[i]; + const RegVec &Suffix = SubRegList.size() > SuperRegList.size() ? + SubRegList : SuperRegList; + CodeGenRegister::Set Omit(Suffix.begin(), Suffix.end()); + + // First element is Reg itself. + OverlapList.push_back(Reg); + Omit.insert(Reg); + + // Any elements not in Suffix. + const CodeGenRegister::Set &OSet = Overlaps[Reg]; + std::set_difference(OSet.begin(), OSet.end(), + Omit.begin(), Omit.end(), + std::back_inserter(OverlapList), + CodeGenRegister::Less()); + + // Finally, Suffix itself. + OverlapList.insert(OverlapList.end(), Suffix.begin(), Suffix.end()); + RegSeqs.add(OverlapList); } - // Emit the empty super-registers list - OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; - // Loop over all of the registers which have super-registers, emitting the - // super-registers list to memory. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs(); - if (SR.empty()) - continue; - OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { "; - for (unsigned j = 0, je = SR.size(); j != je; ++j) - OS << getQualifiedName(SR[j]->TheDef) << ", "; - OS << "0 };\n"; - } - OS << "}\n"; // End of anonymous namespace... + // Compute the final layout of the sequence table. + RegSeqs.layout(); - OS << "\nMCRegisterDesc " << TargetName + OS << "namespace llvm {\n\n"; + + const std::string &TargetName = Target.getName(); + + // Emit the shared table of register lists. + OS << "extern const uint16_t " << TargetName << "RegLists[] = {\n"; + RegSeqs.emit(OS, printRegister); + OS << "};\n\n"; + + OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; + OS << " { \"NOREG\", 0, 0, 0 },\n"; - // Now that register alias and sub-registers sets have been emitted, emit the - // register descriptors now. + // Emit the register descriptors now. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; - OS << " { \""; - OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; - if (!Reg.getSubRegs().empty()) - OS << Reg.getName() << "_SubRegsSet,\t"; - else - OS << "Empty_SubRegsSet,\t"; - if (!Reg.getSuperRegs().empty()) - OS << Reg.getName() << "_SuperRegsSet"; - else - OS << "Empty_SuperRegsSet"; - OS << " },\n"; + const CodeGenRegister *Reg = Regs[i]; + OS << " { \"" << Reg->getName() << "\", " + << RegSeqs.get(OverlapLists[i]) << ", " + << RegSeqs.get(SubRegLists[i]) << ", " + << RegSeqs.get(Reg->getSuperRegs()) << " },\n"; } OS << "};\n\n"; // End of register descriptors... @@ -345,7 +540,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the register list now. OS << " // " << Name << " Register Class...\n" - << " static const unsigned " << Name + << " const uint16_t " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; @@ -354,7 +549,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\n };\n\n"; OS << " // " << Name << " Bit set.\n" - << " static const unsigned char " << Name + << " const uint8_t " << Name << "Bits[] = {\n "; BitVectorEmitter BVE; for (unsigned i = 0, e = Order.size(); i != e; ++i) { @@ -367,37 +562,81 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "}\n\n"; - OS << "MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; + OS << "extern const MCRegisterClass " << TargetName + << "MCRegisterClasses[] = {\n"; for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; - OS << " MCRegisterClass(" << RC.getQualifiedName() + "RegClassID" << ", " - << '\"' << RC.getName() << "\", " + + // Asserts to make sure values will fit in table assuming types from + // MCRegisterInfo.h + assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); + assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); + assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); + + OS << " { " << '\"' << RC.getName() << "\", " + << RC.getName() << ", " << RC.getName() << "Bits, " + << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " + << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << RC.CopyCost << ", " - << RC.Allocatable << ", " - << RC.getName() << ", " << RC.getName() << " + " - << RC.getOrder().size() << ", " - << RC.getName() << "Bits, sizeof(" << RC.getName() << "Bits)" - << "),\n"; + << RC.Allocatable << " },\n"; } OS << "};\n\n"; + // Emit the data table for getSubReg(). + ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); + if (SubRegIndices.size()) { + OS << "const uint16_t " << TargetName << "SubRegTable[][" + << SubRegIndices.size() << "] = {\n"; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); + OS << " /* " << Regs[i]->TheDef->getName() << " */\n"; + if (SRM.empty()) { + OS << " {0},\n"; + continue; + } + OS << " {"; + for (unsigned j = 0, je = SubRegIndices.size(); j != je; ++j) { + // FIXME: We really should keep this to 80 columns... + CodeGenRegister::SubRegMap::const_iterator SubReg = + SRM.find(SubRegIndices[j]); + if (SubReg != SRM.end()) + OS << getQualifiedName(SubReg->second->TheDef); + else + OS << "0"; + if (j != je - 1) + OS << ", "; + } + OS << "}" << (i != e ? "," : "") << "\n"; + } + OS << "};\n\n"; + OS << "const uint16_t *get" << TargetName + << "SubRegTable() {\n return (const uint16_t *)" << TargetName + << "SubRegTable;\n}\n\n"; + } + + EmitRegMappingTables(OS, Regs, false); + // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n"; OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " - << RegisterClasses.size() << ");\n\n"; + << RegisterClasses.size() << ", " << TargetName << "RegLists, "; + if (SubRegIndices.size() != 0) + OS << "(uint16_t*)" << TargetName << "SubRegTable, " + << SubRegIndices.size() << ");\n\n"; + else + OS << "NULL, 0);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; - OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; } @@ -413,8 +652,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, const std::string &TargetName = Target.getName(); std::string ClassName = TargetName + "GenRegisterInfo"; - OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n"; - OS << "#include <string>\n\n"; + OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n\n"; OS << "namespace llvm {\n\n"; @@ -423,28 +661,20 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n" << " virtual bool needsStackRealignment(const MachineFunction &) const\n" << " { return false; }\n" - << " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n" - << " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n" << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n" << " const TargetRegisterClass *" "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n" + << " const TargetRegisterClass *getMatchingSuperRegClass(" + "const TargetRegisterClass*, const TargetRegisterClass*, " + "unsigned) const;\n" + << " const RegClassWeight &getRegClassWeight(" + << "const TargetRegisterClass *RC) const;\n" + << " unsigned getNumRegPressureSets() const;\n" + << " unsigned getRegPressureSetLimit(unsigned Idx) const;\n" + << " const int *getRegClassPressureSets(" + << "const TargetRegisterClass *RC) const;\n" << "};\n\n"; - const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices(); - if (!SubRegIndices.empty()) { - OS << "\n// Subregister indices\n"; - std::string Namespace = SubRegIndices[0]->getValueAsString("Namespace"); - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = RegBank.getNumNamedIndices(); i != e; ++i) - OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; - OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n"; - OS << "};\n"; - if (!Namespace.empty()) - OS << "}\n"; - } - ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); if (!RegisterClasses.empty()) { @@ -455,19 +685,11 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, const CodeGenRegisterClass &RC = *RegisterClasses[i]; const std::string &Name = RC.getName(); - // Output the register class definition. - OS << " struct " << Name << "Class : public TargetRegisterClass {\n" - << " " << Name << "Class();\n"; - if (!RC.AltOrderSelect.empty()) - OS << " ArrayRef<unsigned> " - "getRawAllocationOrder(const MachineFunction&) const;\n"; - OS << " };\n"; - // Output the extern for the instance. - OS << " extern " << Name << "Class\t" << Name << "RegClass;\n"; + OS << " extern const TargetRegisterClass " << Name << "RegClass;\n"; // Output the extern for the pointer to the instance (should remove). - OS << " static TargetRegisterClass * const "<< Name <<"RegisterClass = &" - << Name << "RegClass;\n"; + OS << " static const TargetRegisterClass * const " << Name + << "RegisterClass = &" << Name << "RegClass;\n"; } OS << "} // end of namespace " << TargetName << "\n\n"; } @@ -489,8 +711,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "namespace llvm {\n\n"; // Get access to MCRegisterClass data. - OS << "extern MCRegisterClass " << Target.getName() - << "MCRegisterClasses[];\n"; + OS << "extern const MCRegisterClass " << Target.getName() + << "MCRegisterClasses[];\n"; // Start out by emitting each of the register classes. ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); @@ -507,38 +729,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, AllocatableRegs.insert(Order.begin(), Order.end()); } - OS << "namespace { // Register classes...\n"; - - // Emit the ValueType arrays for each RegisterClass - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; - - // Give the register class a legal C name if it's anonymous. - std::string Name = RC.getName() + "VTs"; - - // Emit the register list now. - OS << " // " << Name - << " Register Class Value Types...\n" - << " static const EVT " << Name - << "[] = {\n "; - for (unsigned i = 0, e = RC.VTs.size(); i != e; ++i) - OS << getEnumName(RC.VTs[i]) << ", "; - OS << "MVT::Other\n };\n\n"; - } - OS << "} // end anonymous namespace\n\n"; + // Build a shared array of value types. + SequenceToOffsetTable<std::vector<MVT::SimpleValueType> > VTSeqs; + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) + VTSeqs.add(RegisterClasses[rc]->VTs); + VTSeqs.layout(); + OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; + VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); + OS << "};\n"; // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { - OS << "namespace " << RegisterClasses[0]->Namespace - << " { // Register class instances\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) - OS << " " << RegisterClasses[i]->getName() << "Class\t" - << RegisterClasses[i]->getName() << "RegClass;\n"; - std::map<unsigned, std::set<unsigned> > SuperRegClassMap; - OS << "\n static const TargetRegisterClass* const " - << "NullRegClasses[] = { NULL };\n\n"; + OS << "\nstatic const TargetRegisterClass *const " + << "NullRegClasses[] = { NULL };\n\n"; unsigned NumSubRegIndices = RegBank.getSubRegIndices().size(); @@ -563,10 +768,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); - OS << " // " << Name + OS << "// " << Name << " Super-register Classes...\n" - << " static const TargetRegisterClass* const " - << Name << "SuperRegClasses[] = {\n "; + << "static const TargetRegisterClass *const " + << Name << "SuperRegClasses[] = {\n "; bool Empty = true; std::map<unsigned, std::set<unsigned> >::iterator I = @@ -583,7 +788,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << (!Empty ? ", " : "") << "NULL"; - OS << "\n };\n\n"; + OS << "\n};\n\n"; } } @@ -594,9 +799,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); - OS << " static const unsigned " << Name << "SubclassMask[] = { "; + OS << "static const uint32_t " << Name << "SubclassMask[] = {\n "; printBitVectorAsHex(OS, RC.getSubClasses(), 32); - OS << "};\n\n"; + OS << "\n};\n\n"; } // Emit NULL terminated super-class lists. @@ -608,54 +813,71 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, if (Supers.empty()) continue; - OS << " static const TargetRegisterClass* const " + OS << "static const TargetRegisterClass *const " << RC.getName() << "Superclasses[] = {\n"; for (unsigned i = 0; i != Supers.size(); ++i) - OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; - OS << " NULL\n };\n\n"; + OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; + OS << " NULL\n};\n\n"; } // Emit methods. for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RegisterClasses[i]; - OS << RC.getName() << "Class::" << RC.getName() - << "Class() : TargetRegisterClass(&" - << Target.getName() << "MCRegisterClasses[" - << RC.getName() + "RegClassID" << "], " - << RC.getName() + "VTs" << ", " - << RC.getName() + "SubclassMask" << ", "; - if (RC.getSuperClasses().empty()) - OS << "NullRegClasses, "; - else - OS << RC.getName() + "Superclasses, "; - OS << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null")) - << "RegClasses" - << ") {}\n"; if (!RC.AltOrderSelect.empty()) { OS << "\nstatic inline unsigned " << RC.getName() << "AltOrderSelect(const MachineFunction &MF) {" - << RC.AltOrderSelect << "}\n\nArrayRef<unsigned> " - << RC.getName() << "Class::" - << "getRawAllocationOrder(const MachineFunction &MF) const {\n"; + << RC.AltOrderSelect << "}\n\n" + << "static ArrayRef<uint16_t> " << RC.getName() + << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { ArrayRef<Record*> Elems = RC.getOrder(oi); - OS << " static const unsigned AltOrder" << oi << "[] = {"; - for (unsigned elem = 0; elem != Elems.size(); ++elem) - OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); - OS << " };\n"; + if (!Elems.empty()) { + OS << " static const uint16_t AltOrder" << oi << "[] = {"; + for (unsigned elem = 0; elem != Elems.size(); ++elem) + OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); + OS << " };\n"; + } } OS << " const MCRegisterClass &MCR = " << Target.getName() - << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];" - << " static const ArrayRef<unsigned> Order[] = {\n" + << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" + << " const ArrayRef<uint16_t> Order[] = {\n" << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) - OS << "),\n makeArrayRef(AltOrder" << oi; + if (RC.getOrder(oi).empty()) + OS << "),\n ArrayRef<uint16_t>("; + else + OS << "),\n makeArrayRef(AltOrder" << oi; OS << ")\n };\n const unsigned Select = " << RC.getName() << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() << ");\n return Order[Select];\n}\n"; } } + // Now emit the actual value-initialized register class instances. + OS << "namespace " << RegisterClasses[0]->Namespace + << " { // Register class instances\n"; + + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = *RegisterClasses[i]; + OS << " extern const TargetRegisterClass " + << RegisterClasses[i]->getName() << "RegClass = {\n " + << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName() + << "RegClassID],\n " + << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " + << RC.getName() << "SubclassMask,\n "; + if (RC.getSuperClasses().empty()) + OS << "NullRegClasses,\n "; + else + OS << RC.getName() << "Superclasses,\n "; + OS << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null")) + << "RegClasses,\n "; + if (RC.AltOrderSelect.empty()) + OS << "0\n"; + else + OS << RC.getName() << "GetRawAllocationOrder\n"; + OS << " };\n\n"; + } + OS << "}\n"; } @@ -669,28 +891,27 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit extra information about registers. const std::string &TargetName = Target.getName(); - OS << "\n static const TargetRegisterInfoDesc " - << TargetName << "RegInfoDesc[] = " - << "{ // Extra Descriptors\n"; - OS << " { 0, 0 },\n"; + OS << "\nstatic const TargetRegisterInfoDesc " + << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n"; + OS << " { 0, 0 },\n"; const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister &Reg = *Regs[i]; - OS << " { "; + OS << " { "; OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; } - OS << " };\n"; // End of register descriptors... + OS << "};\n"; // End of register descriptors... // Calculate the mapping of subregister+index pairs to physical registers. - // This will also create further anonymous indexes. + // This will also create further anonymous indices. unsigned NamedIndices = RegBank.getNumNamedIndices(); // Emit SubRegIndex names, skipping 0 - const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices(); - OS << "\n static const char *const " << TargetName + ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); + OS << "\nstatic const char *const " << TargetName << "SubRegIndexTable[] = { \""; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << SubRegIndices[i]->getName(); @@ -699,7 +920,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "\" };\n\n"; - // Emit names of the anonymus subreg indexes. + // Emit names of the anonymous subreg indices. if (SubRegIndices.size() > NamedIndices) { OS << " enum {"; for (unsigned i = NamedIndices, e = SubRegIndices.size(); i != e; ++i) { @@ -713,48 +934,6 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, std::string ClassName = Target.getName() + "GenRegisterInfo"; - // Emit the subregister + index mapping function based on the information - // calculated above. - OS << "unsigned " << ClassName - << "::getSubReg(unsigned RegNo, unsigned Index) const {\n" - << " switch (RegNo) {\n" - << " default:\n return 0;\n"; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); - if (SRM.empty()) - continue; - OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n"; - OS << " switch (Index) {\n"; - OS << " default: return 0;\n"; - for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(), - ie = SRM.end(); ii != ie; ++ii) - OS << " case " << getQualifiedName(ii->first) - << ": return " << getQualifiedName(ii->second->TheDef) << ";\n"; - OS << " };\n" << " break;\n"; - } - OS << " };\n"; - OS << " return 0;\n"; - OS << "}\n\n"; - - OS << "unsigned " << ClassName - << "::getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const {\n" - << " switch (RegNo) {\n" - << " default:\n return 0;\n"; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); - if (SRM.empty()) - continue; - OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n"; - for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(), - ie = SRM.end(); ii != ie; ++ii) - OS << " if (SubRegNo == " << getQualifiedName(ii->second->TheDef) - << ") return " << getQualifiedName(ii->first) << ";\n"; - OS << " return 0;\n"; - } - OS << " };\n"; - OS << " return 0;\n"; - OS << "}\n\n"; - // Emit composeSubRegIndices OS << "unsigned " << ClassName << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n" @@ -763,15 +942,15 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { bool Open = false; for (unsigned j = 0; j != e; ++j) { - if (Record *Comp = RegBank.getCompositeSubRegIndex(SubRegIndices[i], - SubRegIndices[j])) { + if (CodeGenSubRegIndex *Comp = + SubRegIndices[i]->compose(SubRegIndices[j])) { if (!Open) { - OS << " case " << getQualifiedName(SubRegIndices[i]) + OS << " case " << SubRegIndices[i]->getQualifiedName() << ": switch(IdxB) {\n default: return IdxB;\n"; Open = true; } - OS << " case " << getQualifiedName(SubRegIndices[j]) - << ": return " << getQualifiedName(Comp) << ";\n"; + OS << " case " << SubRegIndices[j]->getQualifiedName() + << ": return " << Comp->getQualifiedName() << ";\n"; } } if (Open) @@ -800,7 +979,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, const CodeGenRegisterClass &RC = *RegisterClasses[rci]; OS << " {\t// " << RC.getName() << "\n"; for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - Record *Idx = SubRegIndices[sri]; + CodeGenSubRegIndex *Idx = SubRegIndices[sri]; if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx)) OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName() << " -> " << SRC->getName() << "\n"; @@ -817,22 +996,106 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "}\n\n"; + // Emit getMatchingSuperRegClass. + OS << "const TargetRegisterClass *" << ClassName + << "::getMatchingSuperRegClass(const TargetRegisterClass *A," + " const TargetRegisterClass *B, unsigned Idx) const {\n"; + if (SubRegIndices.empty()) { + OS << " llvm_unreachable(\"Target has no sub-registers\");\n"; + } else { + // We need to find the largest sub-class of A such that every register has + // an Idx sub-register in B. Map (B, Idx) to a bit-vector of + // super-register classes that map into B. Then compute the largest common + // sub-class with A by taking advantage of the register class ordering, + // like getCommonSubClass(). + + // Bitvector table is NumRCs x NumSubIndexes x BVWords, where BVWords is + // the number of 32-bit words required to represent all register classes. + const unsigned BVWords = (RegisterClasses.size()+31)/32; + BitVector BV(RegisterClasses.size()); + + OS << " static const uint32_t Table[" << RegisterClasses.size() + << "][" << SubRegIndices.size() << "][" << BVWords << "] = {\n"; + for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { + const CodeGenRegisterClass &RC = *RegisterClasses[rci]; + OS << " {\t// " << RC.getName() << "\n"; + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + CodeGenSubRegIndex *Idx = SubRegIndices[sri]; + BV.reset(); + RC.getSuperRegClasses(Idx, BV); + OS << " { "; + printBitVectorAsHex(OS, BV, 32); + OS << "},\t// " << Idx->getName() << '\n'; + } + OS << " },\n"; + } + OS << " };\n assert(A && B && \"Missing regclass\");\n" + << " --Idx;\n" + << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" + << " const uint32_t *TV = Table[B->getID()][Idx];\n" + << " const uint32_t *SC = A->getSubClassMask();\n" + << " for (unsigned i = 0; i != " << BVWords << "; ++i)\n" + << " if (unsigned Common = TV[i] & SC[i])\n" + << " return getRegClass(32*i + CountTrailingZeros_32(Common));\n" + << " return 0;\n"; + } + OS << "}\n\n"; + + EmitRegUnitPressure(OS, RegBank, ClassName); + // Emit the constructor of the class... - OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n"; + OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; + OS << "extern const uint16_t " << TargetName << "RegLists[];\n"; + if (SubRegIndices.size() != 0) + OS << "extern const uint16_t *get" << TargetName + << "SubRegTable();\n"; - OS << ClassName << "::" << ClassName + EmitRegMappingTables(OS, Regs, true); + + OS << ClassName << "::\n" << ClassName << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" - << " " << TargetName << "SubRegIndexTable) {\n" + << " " << TargetName << "SubRegIndexTable) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " - << RegisterClasses.size() << ");\n\n"; + << Regs.size()+1 << ", RA,\n " << TargetName + << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" + << " " << TargetName << "RegLists,\n" + << " "; + if (SubRegIndices.size() != 0) + OS << "get" << TargetName << "SubRegTable(), " + << SubRegIndices.size() << ");\n\n"; + else + OS << "NULL, 0);\n\n"; EmitRegMapping(OS, Regs, true); OS << "}\n\n"; + + // Emit CalleeSavedRegs information. + std::vector<Record*> CSRSets = + Records.getAllDerivedDefinitions("CalleeSavedRegs"); + for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) { + Record *CSRSet = CSRSets[i]; + const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet); + assert(Regs && "Cannot expand CalleeSavedRegs instance"); + + // Emit the *_SaveList list of callee-saved registers. + OS << "static const uint16_t " << CSRSet->getName() + << "_SaveList[] = { "; + for (unsigned r = 0, re = Regs->size(); r != re; ++r) + OS << getQualifiedName((*Regs)[r]) << ", "; + OS << "0 };\n"; + + // Emit the *_RegMask bit mask of call-preserved registers. + OS << "static const uint32_t " << CSRSet->getName() + << "_RegMask[] = { "; + printBitVectorAsHex(OS, RegBank.computeCoveredRegisters(*Regs), 32); + OS << "};\n"; + } + OS << "\n\n"; + OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; } diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h index 0fd4d079ebc0..ee9903cac7b1 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h @@ -50,7 +50,13 @@ public: private: void EmitRegMapping(raw_ostream &o, const std::vector<CodeGenRegister*> &Regs, bool isCtor); + void EmitRegMappingTables(raw_ostream &o, + const std::vector<CodeGenRegister*> &Regs, + bool isCtor); void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target); + + void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, + const std::string &ClassName); }; } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h new file mode 100644 index 000000000000..97c764e61d56 --- /dev/null +++ b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h @@ -0,0 +1,139 @@ +//===-- SequenceToOffsetTable.h - Compress similar sequences ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// SequenceToOffsetTable can be used to emit a number of null-terminated +// sequences as one big array. Use the same memory when a sequence is a suffix +// of another. +// +//===----------------------------------------------------------------------===// + +#ifndef TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H +#define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H + +#include "llvm/Support/raw_ostream.h" +#include <functional> +#include <algorithm> +#include <vector> +#include <cassert> +#include <cctype> + +namespace llvm { + +/// SequenceToOffsetTable - Collect a number of terminated sequences of T. +/// Compute the layout of a table that contains all the sequences, possibly by +/// reusing entries. +/// +/// @param SeqT The sequence container. (vector or string). +/// @param Less A stable comparator for SeqT elements. +template<typename SeqT, typename Less = std::less<typename SeqT::value_type> > +class SequenceToOffsetTable { + typedef typename SeqT::value_type ElemT; + + // Define a comparator for SeqT that sorts a suffix immediately before a + // sequence with that suffix. + struct SeqLess : public std::binary_function<SeqT, SeqT, bool> { + Less L; + bool operator()(const SeqT &A, const SeqT &B) const { + return std::lexicographical_compare(A.rbegin(), A.rend(), + B.rbegin(), B.rend(), L); + } + }; + + // Keep sequences ordered according to SeqLess so suffixes are easy to find. + // Map each sequence to its offset in the table. + typedef std::map<SeqT, unsigned, SeqLess> SeqMap; + + // Sequences added so far, with suffixes removed. + SeqMap Seqs; + + // Entries in the final table, or 0 before layout was called. + unsigned Entries; + + // isSuffix - Returns true if A is a suffix of B. + static bool isSuffix(const SeqT &A, const SeqT &B) { + return A.size() <= B.size() && std::equal(A.rbegin(), A.rend(), B.rbegin()); + } + +public: + SequenceToOffsetTable() : Entries(0) {} + + /// add - Add a sequence to the table. + /// This must be called before layout(). + void add(const SeqT &Seq) { + assert(Entries == 0 && "Cannot call add() after layout()"); + typename SeqMap::iterator I = Seqs.lower_bound(Seq); + + // If SeqMap contains a sequence that has Seq as a suffix, I will be + // pointing to it. + if (I != Seqs.end() && isSuffix(Seq, I->first)) + return; + + I = Seqs.insert(I, std::make_pair(Seq, 0u)); + + // The entry before I may be a suffix of Seq that can now be erased. + if (I != Seqs.begin() && isSuffix((--I)->first, Seq)) + Seqs.erase(I); + } + + /// layout - Computes the final table layout. + void layout() { + assert(Entries == 0 && "Can only call layout() once"); + // Lay out the table in Seqs iteration order. + for (typename SeqMap::iterator I = Seqs.begin(), E = Seqs.end(); I != E; + ++I) { + I->second = Entries; + // Include space for a terminator. + Entries += I->first.size() + 1; + } + } + + /// get - Returns the offset of Seq in the final table. + unsigned get(const SeqT &Seq) const { + assert(Entries && "Call layout() before get()"); + typename SeqMap::const_iterator I = Seqs.lower_bound(Seq); + assert(I != Seqs.end() && isSuffix(Seq, I->first) && + "get() called with sequence that wasn't added first"); + return I->second + (I->first.size() - Seq.size()); + } + + /// emit - Print out the table as the body of an array initializer. + /// Use the Print function to print elements. + void emit(raw_ostream &OS, + void (*Print)(raw_ostream&, ElemT), + const char *Term = "0") const { + assert(Entries && "Call layout() before emit()"); + for (typename SeqMap::const_iterator I = Seqs.begin(), E = Seqs.end(); + I != E; ++I) { + OS << " /* " << I->second << " */ "; + for (typename SeqT::const_iterator SI = I->first.begin(), + SE = I->first.end(); SI != SE; ++SI) { + Print(OS, *SI); + OS << ", "; + } + OS << Term << ",\n"; + } + } +}; + +// Helper function for SequenceToOffsetTable<string>. +static inline void printChar(raw_ostream &OS, char C) { + unsigned char UC(C); + if (isalnum(UC) || ispunct(UC)) { + OS << '\''; + if (C == '\\' || C == '\'') + OS << '\\'; + OS << C << '\''; + } else { + OS << unsigned(UC); + } +} + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/utils/TableGen/SetTheory.cpp b/contrib/llvm/utils/TableGen/SetTheory.cpp index bef73f33effe..0649fd1cfaf9 100644 --- a/contrib/llvm/utils/TableGen/SetTheory.cpp +++ b/contrib/llvm/utils/TableGen/SetTheory.cpp @@ -139,6 +139,24 @@ struct DecimateOp : public SetIntBinOp { } }; +// (interleave S1, S2, ...) Interleave elements of the arguments. +struct InterleaveOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + // Evaluate the arguments individually. + SmallVector<RecSet, 4> Args(Expr->getNumArgs()); + unsigned MaxSize = 0; + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { + ST.evaluate(Expr->getArg(i), Args[i]); + MaxSize = std::max(MaxSize, unsigned(Args[i].size())); + } + // Interleave arguments into Elts. + for (unsigned n = 0; n != MaxSize; ++n) + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) + if (n < Args[i].size()) + Elts.insert(Args[i][n]); + } +}; + // (sequence "Format", From, To) Generate a sequence of records by name. struct SequenceOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { @@ -198,6 +216,10 @@ struct FieldExpander : public SetTheory::Expander { }; } // end anonymous namespace +void SetTheory::Operator::anchor() { } + +void SetTheory::Expander::anchor() { } + SetTheory::SetTheory() { addOperator("add", new AddOp); addOperator("sub", new SubOp); @@ -207,6 +229,7 @@ SetTheory::SetTheory() { addOperator("rotl", new RotOp(false)); addOperator("rotr", new RotOp(true)); addOperator("decimate", new DecimateOp); + addOperator("interleave", new InterleaveOp); addOperator("sequence", new SequenceOp); } diff --git a/contrib/llvm/utils/TableGen/SetTheory.h b/contrib/llvm/utils/TableGen/SetTheory.h index 6e8313be07a3..b394058f4c35 100644 --- a/contrib/llvm/utils/TableGen/SetTheory.h +++ b/contrib/llvm/utils/TableGen/SetTheory.h @@ -65,7 +65,9 @@ public: typedef SmallSetVector<Record*, 16> RecSet; /// Operator - A callback representing a DAG operator. - struct Operator { + class Operator { + virtual void anchor(); + public: virtual ~Operator() {} /// apply - Apply this operator to Expr's arguments and insert the result @@ -76,7 +78,9 @@ public: /// Expander - A callback function that can transform a Record representing a /// set into a fully expanded list of elements. Expanders provide a way for /// users to define named sets that can be used in DAG expressions. - struct Expander { + class Expander { + virtual void anchor(); + public: virtual ~Expander() {} virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; diff --git a/contrib/llvm/utils/TableGen/StringToOffsetTable.h b/contrib/llvm/utils/TableGen/StringToOffsetTable.h index ac9422c5d72d..803f5bd5cf01 100644 --- a/contrib/llvm/utils/TableGen/StringToOffsetTable.h +++ b/contrib/llvm/utils/TableGen/StringToOffsetTable.h @@ -26,16 +26,17 @@ class StringToOffsetTable { std::string AggregateString; public: - unsigned GetOrAddStringOffset(StringRef Str) { - unsigned &Entry = StringOffset[Str]; - if (Entry == 0) { + unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { + StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U); + if (Entry.getValue() == -1U) { // Add the string to the aggregate if this is the first time found. - Entry = AggregateString.size(); + Entry.setValue(AggregateString.size()); AggregateString.append(Str.begin(), Str.end()); - AggregateString += '\0'; + if (appendZero) + AggregateString += '\0'; } - return Entry; + return Entry.getValue(); } void EmitString(raw_ostream &O) { diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp index 103a4032b02a..986c50f87865 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -39,28 +39,41 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, OS << "namespace " << Target << " {\n"; - // Open enumeration - OS << "enum {\n"; + // For bit flag enumerations with more than 32 items, emit constants. + // Emit an enum for everything else. + if (isBits && N > 32) { + // For each record + for (unsigned i = 0; i < N; i++) { + // Next record + Record *Def = DefList[i]; + + // Get and emit name and expression (1 << i) + OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n"; + } + } else { + // Open enumeration + OS << "enum {\n"; - // For each record - for (unsigned i = 0; i < N;) { - // Next record - Record *Def = DefList[i]; + // For each record + for (unsigned i = 0; i < N;) { + // Next record + Record *Def = DefList[i]; - // Get and emit name - OS << " " << Def->getName(); + // Get and emit name + OS << " " << Def->getName(); - // If bit flags then emit expression (1 << i) - if (isBits) OS << " = " << " 1ULL << " << i; + // If bit flags then emit expression (1 << i) + if (isBits) OS << " = " << " 1ULL << " << i; - // Depending on 'if more in the list' emit comma - if (++i < N) OS << ","; + // Depending on 'if more in the list' emit comma + if (++i < N) OS << ","; - OS << "\n"; - } + OS << "\n"; + } - // Close enumeration - OS << "};\n"; + // Close enumeration + OS << "};\n"; + } OS << "}\n"; } @@ -81,7 +94,8 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { // Begin feature table OS << "// Sorted (by key) array of values for CPU features.\n" - << "llvm::SubtargetFeatureKV " << Target << "FeatureKV[] = {\n"; + << "extern const llvm::SubtargetFeatureKV " << Target + << "FeatureKV[] = {\n"; // For each feature unsigned NumFeatures = 0; @@ -140,7 +154,8 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // Begin processor table OS << "// Sorted (by key) array of values for CPU subtype.\n" - << "llvm::SubtargetFeatureKV " << Target << "SubTypeKV[] = {\n"; + << "extern const llvm::SubtargetFeatureKV " << Target + << "SubTypeKV[] = {\n"; // For each processor for (unsigned i = 0, N = ProcessorList.size(); i < N;) { @@ -327,9 +342,9 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name << "\"\n" << "namespace " << Name << "Bypass {\n"; - OS << " unsigned NoBypass = 0;\n"; + OS << " const unsigned NoBypass = 0;\n"; for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) - OS << " unsigned " << BPs[j]->getName() + OS << " const unsigned " << BPs[j]->getName() << " = 1 << " << j << ";\n"; OS << "}\n"; @@ -337,16 +352,17 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, } // Begin stages table - std::string StageTable = "\nllvm::InstrStage " + Target + "Stages[] = {\n"; + std::string StageTable = "\nextern const llvm::InstrStage " + Target + + "Stages[] = {\n"; StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; // Begin operand cycle table - std::string OperandCycleTable = "unsigned " + Target + + std::string OperandCycleTable = "extern const unsigned " + Target + "OperandCycles[] = {\n"; OperandCycleTable += " 0, // No itinerary\n"; // Begin pipeline bypass table - std::string BypassTable = "unsigned " + Target + + std::string BypassTable = "extern const unsigned " + Target + "ForwardingPathes[] = {\n"; BypassTable += " 0, // No itinerary\n"; @@ -488,7 +504,7 @@ EmitProcessorData(raw_ostream &OS, // Begin processor itinerary table OS << "\n"; - OS << "llvm::InstrItinerary " << Name << "[] = {\n"; + OS << "static const llvm::InstrItinerary " << Name << "[] = {\n"; // For each itinerary class std::vector<InstrItinerary> &ItinList = *ProcListIter++; @@ -530,7 +546,7 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { // Begin processor table OS << "\n"; OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" - << "llvm::SubtargetInfoKV " + << "extern const llvm::SubtargetInfoKV " << Target << "ProcItinKV[] = {\n"; // For each processor @@ -708,9 +724,13 @@ void SubtargetEmitter::run(raw_ostream &OS) { std::string ClassName = Target + "GenSubtargetInfo"; OS << "namespace llvm {\n"; + OS << "class DFAPacketizer;\n"; OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " << "StringRef FS);\n" + << "public:\n" + << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" + << " const;\n" << "};\n"; OS << "} // End llvm namespace \n"; @@ -720,13 +740,13 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#undef GET_SUBTARGETINFO_CTOR\n"; OS << "namespace llvm {\n"; - OS << "extern llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; - OS << "extern llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; + OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; + OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; if (HasItineraries) { - OS << "extern llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; - OS << "extern llvm::InstrStage " << Target << "Stages[];\n"; - OS << "extern unsigned " << Target << "OperandCycles[];\n"; - OS << "extern unsigned " << Target << "ForwardingPathes[];\n"; + OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; + OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; + OS << "extern const unsigned " << Target << "OperandCycles[];\n"; + OS << "extern const unsigned " << Target << "ForwardingPathes[];\n"; } OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp index eacfdf6fed39..8c41358e3d85 100644 --- a/contrib/llvm/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/utils/TableGen/TableGen.cpp @@ -16,6 +16,7 @@ #include "CallingConvEmitter.h" #include "CodeEmitterGen.h" #include "DAGISelEmitter.h" +#include "DFAPacketizerEmitter.h" #include "DisassemblerEmitter.h" #include "EDEmitter.h" #include "FastISelEmitter.h" @@ -23,7 +24,6 @@ #include "IntrinsicEmitter.h" #include "PseudoLoweringEmitter.h" #include "RegisterInfoEmitter.h" -#include "ARMDecoderEmitter.h" #include "SubtargetEmitter.h" #include "SetTheory.h" @@ -44,11 +44,11 @@ enum ActionType { GenInstrInfo, GenAsmWriter, GenAsmMatcher, - GenARMDecoder, GenDisassembler, GenPseudoLowering, GenCallingConv, GenDAGISel, + GenDFAPacketizer, GenFastISel, GenSubtarget, GenIntrinsic, @@ -73,8 +73,6 @@ namespace { "Generate calling convention descriptions"), clEnumValN(GenAsmWriter, "gen-asm-writer", "Generate assembly writer"), - clEnumValN(GenARMDecoder, "gen-arm-decoder", - "Generate decoders for ARM/Thumb"), clEnumValN(GenDisassembler, "gen-disassembler", "Generate disassembler"), clEnumValN(GenPseudoLowering, "gen-pseudo-lowering", @@ -83,6 +81,8 @@ namespace { "Generate assembly instruction matcher"), clEnumValN(GenDAGISel, "gen-dag-isel", "Generate a DAG instruction selector"), + clEnumValN(GenDFAPacketizer, "gen-dfa-packetizer", + "Generate DFA Packetizer for VLIW targets"), clEnumValN(GenFastISel, "gen-fast-isel", "Generate a \"fast\" instruction selector"), clEnumValN(GenSubtarget, "gen-subtarget", @@ -101,92 +101,89 @@ namespace { cl::opt<std::string> Class("class", cl::desc("Print Enum list for this class"), - cl::value_desc("class name")); -} - -class LLVMTableGenAction : public TableGenAction { -public: - bool operator()(raw_ostream &OS, RecordKeeper &Records) { - switch (Action) { - case PrintRecords: - OS << Records; // No argument, dump all contents - break; - case GenEmitter: - CodeEmitterGen(Records).run(OS); - break; - case GenRegisterInfo: - RegisterInfoEmitter(Records).run(OS); - break; - case GenInstrInfo: - InstrInfoEmitter(Records).run(OS); - break; - case GenCallingConv: - CallingConvEmitter(Records).run(OS); - break; - case GenAsmWriter: - AsmWriterEmitter(Records).run(OS); - break; - case GenARMDecoder: - ARMDecoderEmitter(Records).run(OS); - break; - case GenAsmMatcher: - AsmMatcherEmitter(Records).run(OS); - break; - case GenDisassembler: - DisassemblerEmitter(Records).run(OS); - break; - case GenPseudoLowering: - PseudoLoweringEmitter(Records).run(OS); - break; - case GenDAGISel: - DAGISelEmitter(Records).run(OS); - break; - case GenFastISel: - FastISelEmitter(Records).run(OS); - break; - case GenSubtarget: - SubtargetEmitter(Records).run(OS); - break; - case GenIntrinsic: - IntrinsicEmitter(Records).run(OS); - break; - case GenTgtIntrinsic: - IntrinsicEmitter(Records, true).run(OS); - break; - case GenEDInfo: - EDEmitter(Records).run(OS); - break; - case PrintEnums: - { - std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) - OS << Recs[i]->getName() << ", "; - OS << "\n"; - break; - } - case PrintSets: - { - SetTheory Sets; - Sets.addFieldExpander("Set", "Elements"); - std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set"); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) { - OS << Recs[i]->getName() << " = ["; - const std::vector<Record*> *Elts = Sets.expand(Recs[i]); - assert(Elts && "Couldn't expand Set instance"); - for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) - OS << ' ' << (*Elts)[ei]->getName(); - OS << " ]\n"; + cl::value_desc("class name")); + + class LLVMTableGenAction : public TableGenAction { + public: + bool operator()(raw_ostream &OS, RecordKeeper &Records) { + switch (Action) { + case PrintRecords: + OS << Records; // No argument, dump all contents + break; + case GenEmitter: + CodeEmitterGen(Records).run(OS); + break; + case GenRegisterInfo: + RegisterInfoEmitter(Records).run(OS); + break; + case GenInstrInfo: + InstrInfoEmitter(Records).run(OS); + break; + case GenCallingConv: + CallingConvEmitter(Records).run(OS); + break; + case GenAsmWriter: + AsmWriterEmitter(Records).run(OS); + break; + case GenAsmMatcher: + AsmMatcherEmitter(Records).run(OS); + break; + case GenDisassembler: + DisassemblerEmitter(Records).run(OS); + break; + case GenPseudoLowering: + PseudoLoweringEmitter(Records).run(OS); + break; + case GenDAGISel: + DAGISelEmitter(Records).run(OS); + break; + case GenDFAPacketizer: + DFAGen(Records).run(OS); + break; + case GenFastISel: + FastISelEmitter(Records).run(OS); + break; + case GenSubtarget: + SubtargetEmitter(Records).run(OS); + break; + case GenIntrinsic: + IntrinsicEmitter(Records).run(OS); + break; + case GenTgtIntrinsic: + IntrinsicEmitter(Records, true).run(OS); + break; + case GenEDInfo: + EDEmitter(Records).run(OS); + break; + case PrintEnums: + { + std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); + for (unsigned i = 0, e = Recs.size(); i != e; ++i) + OS << Recs[i]->getName() << ", "; + OS << "\n"; + break; } - break; - } - default: - assert(1 && "Invalid Action"); - return true; + case PrintSets: + { + SetTheory Sets; + Sets.addFieldExpander("Set", "Elements"); + std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set"); + for (unsigned i = 0, e = Recs.size(); i != e; ++i) { + OS << Recs[i]->getName() << " = ["; + const std::vector<Record*> *Elts = Sets.expand(Recs[i]); + assert(Elts && "Couldn't expand Set instance"); + for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) + OS << ' ' << (*Elts)[ei]->getName(); + OS << " ]\n"; + } + break; + } + } + + return false; } - - return false; - } -}; + }; +} int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp index e8c9a4897321..2875168a1083 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp @@ -41,15 +41,20 @@ static inline bool inheritsFrom(InstructionContext child, case IC: return(inheritsFrom(child, IC_64BIT) || inheritsFrom(child, IC_OPSIZE) || + inheritsFrom(child, IC_ADSIZE) || inheritsFrom(child, IC_XD) || inheritsFrom(child, IC_XS)); case IC_64BIT: return(inheritsFrom(child, IC_64BIT_REXW) || inheritsFrom(child, IC_64BIT_OPSIZE) || + inheritsFrom(child, IC_64BIT_ADSIZE) || inheritsFrom(child, IC_64BIT_XD) || inheritsFrom(child, IC_64BIT_XS)); case IC_OPSIZE: return inheritsFrom(child, IC_64BIT_OPSIZE); + case IC_ADSIZE: + case IC_64BIT_ADSIZE: + return false; case IC_XD: return inheritsFrom(child, IC_64BIT_XD); case IC_XS: @@ -95,11 +100,13 @@ static inline bool inheritsFrom(InstructionContext child, case IC_VEX_L: case IC_VEX_L_XS: case IC_VEX_L_XD: + return false; case IC_VEX_L_OPSIZE: + return inheritsFrom(child, IC_VEX_L_W_OPSIZE); + case IC_VEX_L_W_OPSIZE: return false; default: llvm_unreachable("Unknown instruction class"); - return false; } } @@ -138,8 +145,6 @@ static inline const char* stringForContext(InstructionContext insnContext) { INSTRUCTION_CONTEXTS #undef ENUM_ENTRY } - - return 0; } /// stringForOperandType - Like stringForContext, but for OperandTypes. @@ -194,8 +199,7 @@ void DisassemblerTables::emitOneID(raw_ostream &o, /// @param i - The indentation level for that output stream. static void emitEmptyTable(raw_ostream &o, uint32_t &i) { - o.indent(i * 2) << "static const InstrUID modRMEmptyTable[1] = { 0 };\n"; - o << "\n"; + o.indent(i * 2) << "0x0, /* EmptyTable */\n"; } /// getDecisionType - Determines whether a ModRM decision with 255 entries can @@ -207,28 +211,40 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) { bool satisfiesOneEntry = true; bool satisfiesSplitRM = true; - + bool satisfiesSplitReg = true; + uint16_t index; - + for (index = 0; index < 256; ++index) { if (decision.instructionIDs[index] != decision.instructionIDs[0]) satisfiesOneEntry = false; - + if (((index & 0xc0) == 0xc0) && (decision.instructionIDs[index] != decision.instructionIDs[0xc0])) satisfiesSplitRM = false; - + if (((index & 0xc0) != 0xc0) && (decision.instructionIDs[index] != decision.instructionIDs[0x00])) satisfiesSplitRM = false; + + if (((index & 0xc0) == 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8])) + satisfiesSplitReg = false; + + if (((index & 0xc0) != 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[index&0x38])) + satisfiesSplitReg = false; } - + if (satisfiesOneEntry) return MODRM_ONEENTRY; - + if (satisfiesSplitRM) return MODRM_SPLITRM; - + + if (satisfiesSplitReg) + return MODRM_SPLITREG; + return MODRM_FULL; } @@ -291,71 +307,76 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, ModRMDecision &decision) const { static uint64_t sTableNumber = 0; - uint64_t thisTableNumber = sTableNumber; + static uint64_t sEntryNumber = 1; ModRMDecisionType dt = getDecisionType(decision); uint16_t index; - + if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) { o2.indent(i2) << "{ /* ModRMDecision */" << "\n"; i2++; - + o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; - o2.indent(i2) << "modRMEmptyTable"; - + o2.indent(i2) << 0 << " /* EmptyTable */\n"; + i2--; o2.indent(i2) << "}"; return; } - - o1.indent(i1) << "static const InstrUID modRMTable" << thisTableNumber; - - switch (dt) { - default: - llvm_unreachable("Unknown decision type"); - case MODRM_ONEENTRY: - o1 << "[1]"; - break; - case MODRM_SPLITRM: - o1 << "[2]"; - break; - case MODRM_FULL: - o1 << "[256]"; - break; - } - o1 << " = {" << "\n"; + o1 << "/* Table" << sTableNumber << " */\n"; i1++; - + switch (dt) { default: llvm_unreachable("Unknown decision type"); case MODRM_ONEENTRY: - emitOneID(o1, i1, decision.instructionIDs[0], false); + emitOneID(o1, i1, decision.instructionIDs[0], true); break; case MODRM_SPLITRM: emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00 - emitOneID(o1, i1, decision.instructionIDs[0xc0], false); // mod = 0b11 + emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11 + break; + case MODRM_SPLITREG: + for (index = 0; index < 64; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + for (index = 0xc0; index < 256; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); break; case MODRM_FULL: for (index = 0; index < 256; ++index) - emitOneID(o1, i1, decision.instructionIDs[index], index < 255); + emitOneID(o1, i1, decision.instructionIDs[index], true); break; } - + i1--; - o1.indent(i1) << "};" << "\n"; - o1 << "\n"; - + o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n"; i2++; - + o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; - o2.indent(i2) << "modRMTable" << sTableNumber << "\n"; - + o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n"; + i2--; o2.indent(i2) << "}"; - + + switch (dt) { + default: + llvm_unreachable("Unknown decision type"); + case MODRM_ONEENTRY: + sEntryNumber += 1; + break; + case MODRM_SPLITRM: + sEntryNumber += 2; + break; + case MODRM_SPLITREG: + sEntryNumber += 16; + break; + case MODRM_FULL: + sEntryNumber += 256; + break; + } + ++sTableNumber; } @@ -436,11 +457,11 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) for (index = 0; index < numInstructions; ++index) { o.indent(i * 2) << "{ /* " << index << " */" << "\n"; i++; - - o.indent(i * 2) << - stringForModifierType(InstructionSpecifiers[index].modifierType); + + o.indent(i * 2) << stringForModifierType( + (ModifierType)InstructionSpecifiers[index].modifierType); o << "," << "\n"; - + o.indent(i * 2) << "0x"; o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase); o << "," << "\n"; @@ -450,11 +471,11 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) for (operandIndex = 0; operandIndex < X86_MAX_OPERANDS; ++operandIndex) { o.indent(i * 2) << "{ "; - o << stringForOperandEncoding(InstructionSpecifiers[index] - .operands[operandIndex] - .encoding); + o <<stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index] + .operands[operandIndex] + .encoding); o << ", "; - o << stringForOperandType(InstructionSpecifiers[index] + o << stringForOperandType((OperandType)InstructionSpecifiers[index] .operands[operandIndex] .type); o << " }"; @@ -468,7 +489,7 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) i--; o.indent(i * 2) << "}," << "\n"; - o.indent(i * 2) << "\"" << InstructionSpecifiers[index].name << "\""; + o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */"; o << "\n"; i--; @@ -494,7 +515,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { for (index = 0; index < 256; ++index) { o.indent(i * 2); - if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) + if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) + o << "IC_VEX_L_W_OPSIZE"; + else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) o << "IC_VEX_L_OPSIZE"; else if ((index & ATTR_VEXL) && (index & ATTR_XD)) o << "IC_VEX_L_XD"; @@ -535,6 +558,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { o << "IC_64BIT_XD"; else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE)) o << "IC_64BIT_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE)) + o << "IC_64BIT_ADSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW)) o << "IC_64BIT_REXW"; else if ((index & ATTR_64BIT)) @@ -549,6 +574,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { o << "IC_XD"; else if (index & ATTR_OPSIZE) o << "IC_OPSIZE"; + else if (index & ATTR_ADSIZE) + o << "IC_ADSIZE"; else o << "IC"; @@ -594,11 +621,16 @@ void DisassemblerTables::emit(raw_ostream &o) const { emitContextTable(o, i2); o << "\n"; - + + o << "static const InstrUID modRMTable[] = {\n"; + i1++; emitEmptyTable(o1, i1); + i1--; emitContextDecisions(o1, o2, i1, i2); - + o << o1.str(); + o << " 0x0\n"; + o << "};\n"; o << "\n"; o << o2.str(); o << "\n"; diff --git a/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp b/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp new file mode 100644 index 000000000000..7166fe02d890 --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp @@ -0,0 +1,26 @@ +//===- X86ModRMFilters.cpp - Disassembler ModR/M filterss -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "X86ModRMFilters.h" + +using namespace llvm::X86Disassembler; + +void ModRMFilter::anchor() { } + +void DumbFilter::anchor() { } + +void ModFilter::anchor() { } + +void EscapeFilter::anchor() { } + +void AddRegEscapeFilter::anchor() { } + +void ExtendedFilter::anchor() { } + +void ExactFilter::anchor() { } diff --git a/contrib/llvm/utils/TableGen/X86ModRMFilters.h b/contrib/llvm/utils/TableGen/X86ModRMFilters.h index 199040bad840..19fecbc3a0a5 100644 --- a/contrib/llvm/utils/TableGen/X86ModRMFilters.h +++ b/contrib/llvm/utils/TableGen/X86ModRMFilters.h @@ -27,6 +27,7 @@ namespace X86Disassembler { /// ModRMFilter - Abstract base class for clases that recognize patterns in /// ModR/M bytes. class ModRMFilter { + virtual void anchor(); public: /// Destructor - Override as necessary. virtual ~ModRMFilter() { } @@ -49,6 +50,7 @@ public: /// require a ModR/M byte or instructions where the entire ModR/M byte is used /// for operands. class DumbFilter : public ModRMFilter { + virtual void anchor(); public: bool isDumb() const { return true; @@ -63,7 +65,7 @@ public: /// Some instructions are classified based on whether they are 11 or anything /// else. This filter performs that classification. class ModFilter : public ModRMFilter { -private: + virtual void anchor(); bool R; public: /// Constructor @@ -90,7 +92,7 @@ public: /// possible value. Otherwise, there is one instruction for each value of the /// nnn field [bits 5-3], known elsewhere as the reg field. class EscapeFilter : public ModRMFilter { -private: + virtual void anchor(); bool C0_FF; uint8_t NNN_or_ModRM; public: @@ -121,7 +123,7 @@ public: /// maps to a single instruction. Such instructions require the ModR/M byte /// to fall between 0xc0 and 0xff. class AddRegEscapeFilter : public ModRMFilter { -private: + virtual void anchor(); uint8_t ModRM; public: /// Constructor @@ -142,7 +144,7 @@ public: /// ExtendedFilter - Extended opcodes are classified based on the value of the /// mod field [bits 7-6] and the value of the nnn field [bits 5-3]. class ExtendedFilter : public ModRMFilter { -private: + virtual void anchor(); bool R; uint8_t NNN; public: @@ -169,9 +171,8 @@ public: /// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR) /// requires the ModR/M byte to have a specific value. -class ExactFilter : public ModRMFilter -{ -private: +class ExactFilter : public ModRMFilter { + virtual void anchor(); uint8_t ModRM; public: /// Constructor diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index cae823749245..6a01cce637e4 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -36,7 +36,16 @@ using namespace llvm; MAP(F8, 41) \ MAP(F9, 42) \ MAP(D0, 45) \ - MAP(D1, 46) + MAP(D1, 46) \ + MAP(D4, 47) \ + MAP(D8, 48) \ + MAP(D9, 49) \ + MAP(DA, 50) \ + MAP(DB, 51) \ + MAP(DC, 52) \ + MAP(DD, 53) \ + MAP(DE, 54) \ + MAP(DF, 55) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -68,7 +77,7 @@ namespace X86Local { DC = 7, DD = 8, DE = 9, DF = 10, XD = 11, XS = 12, T8 = 13, P_TA = 14, - A6 = 15, A7 = 16, TF = 17 + A6 = 15, A7 = 16, T8XD = 17, T8XS = 18, TAXD = 19 }; } @@ -119,6 +128,9 @@ namespace X86Local { EXTENSION_TABLE(ba) \ EXTENSION_TABLE(c7) +#define THREE_BYTE_38_EXTENSION_TABLES \ + EXTENSION_TABLE(F3) + using namespace X86Disassembler; /// needsModRMForDecode - Indicates whether a particular instruction requires a @@ -213,10 +225,13 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, SegOvr = byteFromRec(Rec, "SegOvrBits"); HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix"); + HasAdSizePrefix = Rec->getValueAsBit("hasAdSizePrefix"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix"); HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix"); + HasVEX_4VOp3Prefix = Rec->getValueAsBit("hasVEX_4VOp3Prefix"); HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix"); + HasMemOp4Prefix = Rec->getValueAsBit("hasMemOp4Prefix"); IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L"); HasLockPrefix = Rec->getValueAsBit("hasLockPrefix"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); @@ -230,7 +245,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, (Name.find("CRC32") != Name.npos); HasFROperands = hasFROperands(); HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L"); - + // Check for 64-bit inst which does not require REX Is32Bit = false; Is64Bit = false; @@ -254,10 +269,6 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, Rec->getName() == "PUSHFS64" || Rec->getName() == "PUSHGS64" || Rec->getName() == "REX64_PREFIX" || - Rec->getName().find("VMREAD64") != Name.npos || - Rec->getName().find("VMWRITE64") != Name.npos || - Rec->getName().find("INVEPT64") != Name.npos || - Rec->getName().find("INVVPID64") != Name.npos || Rec->getName().find("MOV64") != Name.npos || Rec->getName().find("PUSH64") != Name.npos || Rec->getName().find("POP64") != Name.npos; @@ -284,67 +295,90 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables, InstructionContext RecognizableInstr::insnContext() const { InstructionContext insnContext; - if (HasVEX_4VPrefix || HasVEXPrefix) { - if (HasVEX_LPrefix && HasVEX_WPrefix) - llvm_unreachable("Don't support VEX.L and VEX.W together"); - else if (HasOpSizePrefix && HasVEX_LPrefix) + if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix|| HasVEXPrefix) { + if (HasVEX_LPrefix && HasVEX_WPrefix) { + if (HasOpSizePrefix) + insnContext = IC_VEX_L_W_OPSIZE; + else + llvm_unreachable("Don't support VEX.L and VEX.W together"); + } else if (HasOpSizePrefix && HasVEX_LPrefix) insnContext = IC_VEX_L_OPSIZE; else if (HasOpSizePrefix && HasVEX_WPrefix) insnContext = IC_VEX_W_OPSIZE; else if (HasOpSizePrefix) insnContext = IC_VEX_OPSIZE; - else if (HasVEX_LPrefix && Prefix == X86Local::XS) + else if (HasVEX_LPrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) insnContext = IC_VEX_L_XS; - else if (HasVEX_LPrefix && Prefix == X86Local::XD) + else if (HasVEX_LPrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) insnContext = IC_VEX_L_XD; - else if (HasVEX_WPrefix && Prefix == X86Local::XS) + else if (HasVEX_WPrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) insnContext = IC_VEX_W_XS; - else if (HasVEX_WPrefix && Prefix == X86Local::XD) + else if (HasVEX_WPrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) insnContext = IC_VEX_W_XD; else if (HasVEX_WPrefix) insnContext = IC_VEX_W; else if (HasVEX_LPrefix) insnContext = IC_VEX_L; - else if (Prefix == X86Local::XD) + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) insnContext = IC_VEX_XD; - else if (Prefix == X86Local::XS) + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) insnContext = IC_VEX_XS; else insnContext = IC_VEX; } else if (Is64Bit || HasREX_WPrefix) { if (HasREX_WPrefix && HasOpSizePrefix) insnContext = IC_64BIT_REXW_OPSIZE; - else if (HasOpSizePrefix && - (Prefix == X86Local::XD || Prefix == X86Local::TF)) + else if (HasOpSizePrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) insnContext = IC_64BIT_XD_OPSIZE; - else if (HasOpSizePrefix && Prefix == X86Local::XS) + else if (HasOpSizePrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) insnContext = IC_64BIT_XS_OPSIZE; else if (HasOpSizePrefix) insnContext = IC_64BIT_OPSIZE; - else if (HasREX_WPrefix && Prefix == X86Local::XS) - insnContext = IC_64BIT_REXW_XS; + else if (HasAdSizePrefix) + insnContext = IC_64BIT_ADSIZE; else if (HasREX_WPrefix && - (Prefix == X86Local::XD || Prefix == X86Local::TF)) + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + insnContext = IC_64BIT_REXW_XS; + else if (HasREX_WPrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) insnContext = IC_64BIT_REXW_XD; - else if (Prefix == X86Local::XD || Prefix == X86Local::TF) + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) insnContext = IC_64BIT_XD; - else if (Prefix == X86Local::XS) + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) insnContext = IC_64BIT_XS; else if (HasREX_WPrefix) insnContext = IC_64BIT_REXW; else insnContext = IC_64BIT; } else { - if (HasOpSizePrefix && - (Prefix == X86Local::XD || Prefix == X86Local::TF)) + if (HasOpSizePrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) insnContext = IC_XD_OPSIZE; - else if (HasOpSizePrefix && Prefix == X86Local::XS) + else if (HasOpSizePrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) insnContext = IC_XS_OPSIZE; else if (HasOpSizePrefix) insnContext = IC_OPSIZE; - else if (Prefix == X86Local::XD || Prefix == X86Local::TF) + else if (HasAdSizePrefix) + insnContext = IC_ADSIZE; + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) insnContext = IC_XD; - else if (Prefix == X86Local::XS || Prefix == X86Local::REP) + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS || + Prefix == X86Local::REP) insnContext = IC_XS; else insnContext = IC; @@ -371,19 +405,12 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { return FILTER_STRONG; - // Filter out artificial instructions + // Filter out artificial instructions but leave in the LOCK_PREFIX so it is + // printed as a separate "instruction". - if (Name.find("TAILJMP") != Name.npos || - Name.find("_Int") != Name.npos || - Name.find("_int") != Name.npos || + if (Name.find("_Int") != Name.npos || Name.find("Int_") != Name.npos || Name.find("_NOREX") != Name.npos || - Name.find("_TC") != Name.npos || - Name.find("EH_RETURN") != Name.npos || - Name.find("V_SET") != Name.npos || - Name.find("LOCK_") != Name.npos || - Name.find("WIN") != Name.npos || - Name.find("_AVX") != Name.npos || Name.find("2SDL") != Name.npos) return FILTER_STRONG; @@ -421,12 +448,6 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { Name.find("Xrr") != Name.npos || Name.find("rr64") != Name.npos) return FILTER_WEAK; - - if (Name == "VMASKMOVDQU64" || - Name == "VEXTRACTPSrr64" || - Name == "VMOVQd64rr" || - Name == "VMOVQs64rr") - return FILTER_WEAK; // Special cases. @@ -441,29 +462,15 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { return FILTER_WEAK; if (Name.find("Fs") != Name.npos) return FILTER_WEAK; - if (Name == "MOVLPDrr" || - Name == "MOVLPSrr" || - Name == "PUSHFQ" || - Name == "BSF16rr" || - Name == "BSF16rm" || - Name == "BSR16rr" || - Name == "BSR16rm" || - Name == "MOVSX16rm8" || - Name == "MOVSX16rr8" || - Name == "MOVZX16rm8" || - Name == "MOVZX16rr8" || - Name == "PUSH32i16" || - Name == "PUSH64i16" || + if (Name == "PUSH64i16" || Name == "MOVPQI2QImr" || Name == "VMOVPQI2QImr" || - Name == "MOVSDmr" || - Name == "MOVSDrm" || - Name == "MOVSSmr" || - Name == "MOVSSrm" || Name == "MMX_MOVD64rrv164" || - Name == "CRC32m16" || Name == "MOV64ri64i32" || - Name == "CRC32r16") + Name == "VMASKMOVDQU64" || + Name == "VEXTRACTPSrr64" || + Name == "VMOVQd64rr" || + Name == "VMOVQs64rr") return FILTER_WEAK; if (HasFROperands && Name.find("MOV") != Name.npos && @@ -566,7 +573,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { bool hasFROperands = false; - assert(numOperands < X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough"); + assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough"); for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { if (OperandList[operandIndex].Constraints.size()) { @@ -684,31 +691,40 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4VPrefix) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); else assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && "Unexpected number of operands for MRMSrcRegFrm"); HANDLE_OPERAND(roRegister) - + if (HasVEX_4VPrefix) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) - + + if (HasMemOp4Prefix) + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(rmRegister) - HANDLE_OPTIONAL(immediate) + + if (HasVEX_4VOp3Prefix) + HANDLE_OPERAND(vvvvRegister) + + if (!HasMemOp4Prefix) + HANDLE_OPTIONAL(immediate) + HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 break; case X86Local::MRMSrcMem: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a memory operand (possibly SIB-extended) // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - - if (HasVEX_4VPrefix) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + + if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); else assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && @@ -721,8 +737,17 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) + if (HasMemOp4Prefix) + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(memory) - HANDLE_OPTIONAL(immediate) + + if (HasVEX_4VOp3Prefix) + HANDLE_OPERAND(vvvvRegister) + + if (!HasMemOp4Prefix) + HANDLE_OPTIONAL(immediate) + HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 break; case X86Local::MRM0r: case X86Local::MRM1r: @@ -736,12 +761,12 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // Operand 2 (optional) is an immediate or relocation. if (HasVEX_4VPrefix) assert(numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); + "Unexpected number of operands for MRMnRFrm with VEX_4V"); else assert(numPhysicalOperands <= 2 && "Unexpected number of operands for MRMnRFrm"); if (HasVEX_4VPrefix) - HANDLE_OPERAND(vvvvRegister); + HANDLE_OPERAND(vvvvRegister) HANDLE_OPTIONAL(rmRegister) HANDLE_OPTIONAL(relocation) break; @@ -755,8 +780,14 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { case X86Local::MRM7m: // Operand 1 is a memory operand (possibly SIB-extended) // Operand 2 (optional) is an immediate or relocation. - assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 && - "Unexpected number of operands for MRMnMFrm"); + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMnMFrm"); + else + assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 && + "Unexpected number of operands for MRMnMFrm"); + if (HasVEX_4VPrefix) + HANDLE_OPERAND(vvvvRegister) HANDLE_OPERAND(memory) HANDLE_OPTIONAL(relocation) break; @@ -843,15 +874,50 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { opcodeToSet = Opcode; break; case X86Local::T8: - case X86Local::TF: + case X86Local::T8XD: + case X86Local::T8XS: opcodeType = THREEBYTE_38; - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); + switch (Opcode) { + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + break; +#define EXTENSION_TABLE(n) case 0x##n: + THREE_BYTE_38_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Unhandled two-byte extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) + break; + } // switch (Opcode) opcodeToSet = Opcode; break; case X86Local::P_TA: + case X86Local::TAXD: opcodeType = THREEBYTE_3A; if (needsModRMForDecode(Form)) filter = new ModFilter(isRegFormat(Form)); @@ -1049,6 +1115,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i16imm_pcrel", TYPE_REL16) TYPE("i32imm_pcrel", TYPE_REL32) TYPE("SSECC", TYPE_IMM3) + TYPE("AVXCC", TYPE_IMM5) TYPE("brtarget", TYPE_RELv) TYPE("uncondbrtarget", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) @@ -1090,6 +1157,7 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString ENCODING("i32i8imm", ENCODING_IB) ENCODING("u32u8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) + ENCODING("AVXCC", ENCODING_IB) ENCODING("i16imm", ENCODING_Iv) ENCODING("i16i8imm", ENCODING_IB) ENCODING("i32imm", ENCODING_Iv) diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h index 44415978273f..6c0a234b5eff 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h @@ -50,17 +50,23 @@ private: uint8_t SegOvr; /// The hasOpSizePrefix field from the record bool HasOpSizePrefix; + /// The hasAdSizePrefix field from the record + bool HasAdSizePrefix; /// The hasREX_WPrefix field from the record bool HasREX_WPrefix; /// The hasVEXPrefix field from the record bool HasVEXPrefix; /// The hasVEX_4VPrefix field from the record bool HasVEX_4VPrefix; + /// The hasVEX_4VOp3Prefix field from the record + bool HasVEX_4VOp3Prefix; /// The hasVEX_WPrefix field from the record bool HasVEX_WPrefix; /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set bool HasVEX_LPrefix; - // The ignoreVEX_L field from the record + /// The hasMemOp4Prefix field from the record + bool HasMemOp4Prefix; + /// The ignoreVEX_L field from the record bool IgnoresVEX_L; /// The hasLockPrefix field from the record bool HasLockPrefix; @@ -70,7 +76,7 @@ private: bool Is64Bit; // Whether the instruction has the predicate "In32BitMode" bool Is32Bit; - + /// The instruction name as listed in the tables std::string Name; /// The AT&T AsmString for the instruction |