13861d79fSDimitry Andric //===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===// 23861d79fSDimitry Andric // 33861d79fSDimitry Andric // The LLVM Compiler Infrastructure 43861d79fSDimitry Andric // 53861d79fSDimitry Andric // This file is distributed under the University of Illinois Open Source 63861d79fSDimitry Andric // License. See LICENSE.TXT for details. 73861d79fSDimitry Andric // 83861d79fSDimitry Andric //===----------------------------------------------------------------------===// 93861d79fSDimitry Andric // CodeGenMapTable provides functionality for the TabelGen to create 103861d79fSDimitry Andric // relation mapping between instructions. Relation models are defined using 113861d79fSDimitry Andric // InstrMapping as a base class. This file implements the functionality which 123861d79fSDimitry Andric // parses these definitions and generates relation maps using the information 133861d79fSDimitry Andric // specified there. These maps are emitted as tables in the XXXGenInstrInfo.inc 143861d79fSDimitry Andric // file along with the functions to query them. 153861d79fSDimitry Andric // 163861d79fSDimitry Andric // A relationship model to relate non-predicate instructions with their 173861d79fSDimitry Andric // predicated true/false forms can be defined as follows: 183861d79fSDimitry Andric // 193861d79fSDimitry Andric // def getPredOpcode : InstrMapping { 203861d79fSDimitry Andric // let FilterClass = "PredRel"; 213861d79fSDimitry Andric // let RowFields = ["BaseOpcode"]; 223861d79fSDimitry Andric // let ColFields = ["PredSense"]; 233861d79fSDimitry Andric // let KeyCol = ["none"]; 243861d79fSDimitry Andric // let ValueCols = [["true"], ["false"]]; } 253861d79fSDimitry Andric // 263861d79fSDimitry Andric // CodeGenMapTable parses this map and generates a table in XXXGenInstrInfo.inc 273861d79fSDimitry Andric // file that contains the instructions modeling this relationship. This table 283861d79fSDimitry Andric // is defined in the function 293861d79fSDimitry Andric // "int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)" 303861d79fSDimitry Andric // that can be used to retrieve the predicated form of the instruction by 313861d79fSDimitry Andric // passing its opcode value and the predicate sense (true/false) of the desired 323861d79fSDimitry Andric // instruction as arguments. 333861d79fSDimitry Andric // 343861d79fSDimitry Andric // Short description of the algorithm: 353861d79fSDimitry Andric // 363861d79fSDimitry Andric // 1) Iterate through all the records that derive from "InstrMapping" class. 373861d79fSDimitry Andric // 2) For each record, filter out instructions based on the FilterClass value. 383861d79fSDimitry Andric // 3) Iterate through this set of instructions and insert them into 393861d79fSDimitry Andric // RowInstrMap map based on their RowFields values. RowInstrMap is keyed by the 403861d79fSDimitry Andric // vector of RowFields values and contains vectors of Records (instructions) as 413861d79fSDimitry Andric // values. RowFields is a list of fields that are required to have the same 423861d79fSDimitry Andric // values for all the instructions appearing in the same row of the relation 433861d79fSDimitry Andric // table. All the instructions in a given row of the relation table have some 443861d79fSDimitry Andric // sort of relationship with the key instruction defined by the corresponding 453861d79fSDimitry Andric // relationship model. 463861d79fSDimitry Andric // 473861d79fSDimitry Andric // Ex: RowInstrMap(RowVal1, RowVal2, ...) -> [Instr1, Instr2, Instr3, ... ] 483861d79fSDimitry Andric // Here Instr1, Instr2, Instr3 have same values (RowVal1, RowVal2) for 493861d79fSDimitry Andric // RowFields. These groups of instructions are later matched against ValueCols 503861d79fSDimitry Andric // to determine the column they belong to, if any. 513861d79fSDimitry Andric // 523861d79fSDimitry Andric // While building the RowInstrMap map, collect all the key instructions in 533861d79fSDimitry Andric // KeyInstrVec. These are the instructions having the same values as KeyCol 543861d79fSDimitry Andric // for all the fields listed in ColFields. 553861d79fSDimitry Andric // 563861d79fSDimitry Andric // For Example: 573861d79fSDimitry Andric // 583861d79fSDimitry Andric // Relate non-predicate instructions with their predicated true/false forms. 593861d79fSDimitry Andric // 603861d79fSDimitry Andric // def getPredOpcode : InstrMapping { 613861d79fSDimitry Andric // let FilterClass = "PredRel"; 623861d79fSDimitry Andric // let RowFields = ["BaseOpcode"]; 633861d79fSDimitry Andric // let ColFields = ["PredSense"]; 643861d79fSDimitry Andric // let KeyCol = ["none"]; 653861d79fSDimitry Andric // let ValueCols = [["true"], ["false"]]; } 663861d79fSDimitry Andric // 673861d79fSDimitry Andric // Here, only instructions that have "none" as PredSense will be selected as key 683861d79fSDimitry Andric // instructions. 693861d79fSDimitry Andric // 703861d79fSDimitry Andric // 4) For each key instruction, get the group of instructions that share the 713861d79fSDimitry Andric // same key-value as the key instruction from RowInstrMap. Iterate over the list 723861d79fSDimitry Andric // of columns in ValueCols (it is defined as a list<list<string> >. Therefore, 733861d79fSDimitry Andric // it can specify multi-column relationships). For each column, find the 743861d79fSDimitry Andric // instruction from the group that matches all the values for the column. 753861d79fSDimitry Andric // Multiple matches are not allowed. 763861d79fSDimitry Andric // 773861d79fSDimitry Andric //===----------------------------------------------------------------------===// 783861d79fSDimitry Andric 793861d79fSDimitry Andric #include "CodeGenTarget.h" 803861d79fSDimitry Andric #include "llvm/Support/Format.h" 813861d79fSDimitry Andric #include "llvm/TableGen/Error.h" 823861d79fSDimitry Andric using namespace llvm; 833861d79fSDimitry Andric typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy; 843861d79fSDimitry Andric 853861d79fSDimitry Andric typedef std::map<std::vector<Init*>, std::vector<Record*> > RowInstrMapTy; 863861d79fSDimitry Andric 873861d79fSDimitry Andric namespace { 883861d79fSDimitry Andric 893861d79fSDimitry Andric //===----------------------------------------------------------------------===// 903861d79fSDimitry Andric // This class is used to represent InstrMapping class defined in Target.td file. 913861d79fSDimitry Andric class InstrMap { 923861d79fSDimitry Andric private: 933861d79fSDimitry Andric std::string Name; 943861d79fSDimitry Andric std::string FilterClass; 953861d79fSDimitry Andric ListInit *RowFields; 963861d79fSDimitry Andric ListInit *ColFields; 973861d79fSDimitry Andric ListInit *KeyCol; 983861d79fSDimitry Andric std::vector<ListInit*> ValueCols; 993861d79fSDimitry Andric 1003861d79fSDimitry Andric public: 1013861d79fSDimitry Andric InstrMap(Record* MapRec) { 1023861d79fSDimitry Andric Name = MapRec->getName(); 1033861d79fSDimitry Andric 1043861d79fSDimitry Andric // FilterClass - It's used to reduce the search space only to the 1053861d79fSDimitry Andric // instructions that define the kind of relationship modeled by 1063861d79fSDimitry Andric // this InstrMapping object/record. 1073861d79fSDimitry Andric const RecordVal *Filter = MapRec->getValue("FilterClass"); 1083861d79fSDimitry Andric FilterClass = Filter->getValue()->getAsUnquotedString(); 1093861d79fSDimitry Andric 1103861d79fSDimitry Andric // List of fields/attributes that need to be same across all the 1113861d79fSDimitry Andric // instructions in a row of the relation table. 1123861d79fSDimitry Andric RowFields = MapRec->getValueAsListInit("RowFields"); 1133861d79fSDimitry Andric 1143861d79fSDimitry Andric // List of fields/attributes that are constant across all the instruction 1153861d79fSDimitry Andric // in a column of the relation table. Ex: ColFields = 'predSense' 1163861d79fSDimitry Andric ColFields = MapRec->getValueAsListInit("ColFields"); 1173861d79fSDimitry Andric 1183861d79fSDimitry Andric // Values for the fields/attributes listed in 'ColFields'. 11991bc56edSDimitry Andric // Ex: KeyCol = 'noPred' -- key instruction is non-predicated 1203861d79fSDimitry Andric KeyCol = MapRec->getValueAsListInit("KeyCol"); 1213861d79fSDimitry Andric 1223861d79fSDimitry Andric // List of values for the fields/attributes listed in 'ColFields', one for 1233861d79fSDimitry Andric // each column in the relation table. 1243861d79fSDimitry Andric // 1253861d79fSDimitry Andric // Ex: ValueCols = [['true'],['false']] -- it results two columns in the 1263861d79fSDimitry Andric // table. First column requires all the instructions to have predSense 1273861d79fSDimitry Andric // set to 'true' and second column requires it to be 'false'. 1283861d79fSDimitry Andric ListInit *ColValList = MapRec->getValueAsListInit("ValueCols"); 1293861d79fSDimitry Andric 1303861d79fSDimitry Andric // Each instruction map must specify at least one column for it to be valid. 1313861d79fSDimitry Andric if (ColValList->getSize() == 0) 1323861d79fSDimitry Andric PrintFatalError(MapRec->getLoc(), "InstrMapping record `" + 1333861d79fSDimitry Andric MapRec->getName() + "' has empty " + "`ValueCols' field!"); 1343861d79fSDimitry Andric 1353861d79fSDimitry Andric for (unsigned i = 0, e = ColValList->getSize(); i < e; i++) { 1363861d79fSDimitry Andric ListInit *ColI = dyn_cast<ListInit>(ColValList->getElement(i)); 1373861d79fSDimitry Andric 1383861d79fSDimitry Andric // Make sure that all the sub-lists in 'ValueCols' have same number of 1393861d79fSDimitry Andric // elements as the fields in 'ColFields'. 1403861d79fSDimitry Andric if (ColI->getSize() != ColFields->getSize()) 1413861d79fSDimitry Andric PrintFatalError(MapRec->getLoc(), "Record `" + MapRec->getName() + 1423861d79fSDimitry Andric "', field `ValueCols' entries don't match with " + 1433861d79fSDimitry Andric " the entries in 'ColFields'!"); 1443861d79fSDimitry Andric ValueCols.push_back(ColI); 1453861d79fSDimitry Andric } 1463861d79fSDimitry Andric } 1473861d79fSDimitry Andric 1483861d79fSDimitry Andric std::string getName() const { 1493861d79fSDimitry Andric return Name; 1503861d79fSDimitry Andric } 1513861d79fSDimitry Andric 1523861d79fSDimitry Andric std::string getFilterClass() { 1533861d79fSDimitry Andric return FilterClass; 1543861d79fSDimitry Andric } 1553861d79fSDimitry Andric 1563861d79fSDimitry Andric ListInit *getRowFields() const { 1573861d79fSDimitry Andric return RowFields; 1583861d79fSDimitry Andric } 1593861d79fSDimitry Andric 1603861d79fSDimitry Andric ListInit *getColFields() const { 1613861d79fSDimitry Andric return ColFields; 1623861d79fSDimitry Andric } 1633861d79fSDimitry Andric 1643861d79fSDimitry Andric ListInit *getKeyCol() const { 1653861d79fSDimitry Andric return KeyCol; 1663861d79fSDimitry Andric } 1673861d79fSDimitry Andric 1683861d79fSDimitry Andric const std::vector<ListInit*> &getValueCols() const { 1693861d79fSDimitry Andric return ValueCols; 1703861d79fSDimitry Andric } 1713861d79fSDimitry Andric }; 1723861d79fSDimitry Andric } // End anonymous namespace. 1733861d79fSDimitry Andric 1743861d79fSDimitry Andric 1753861d79fSDimitry Andric //===----------------------------------------------------------------------===// 1763861d79fSDimitry Andric // class MapTableEmitter : It builds the instruction relation maps using 1773861d79fSDimitry Andric // the information provided in InstrMapping records. It outputs these 1783861d79fSDimitry Andric // relationship maps as tables into XXXGenInstrInfo.inc file along with the 1793861d79fSDimitry Andric // functions to query them. 1803861d79fSDimitry Andric 1813861d79fSDimitry Andric namespace { 1823861d79fSDimitry Andric class MapTableEmitter { 1833861d79fSDimitry Andric private: 1843861d79fSDimitry Andric // std::string TargetName; 1853861d79fSDimitry Andric const CodeGenTarget &Target; 1863861d79fSDimitry Andric // InstrMapDesc - InstrMapping record to be processed. 1873861d79fSDimitry Andric InstrMap InstrMapDesc; 1883861d79fSDimitry Andric 1893861d79fSDimitry Andric // InstrDefs - list of instructions filtered using FilterClass defined 1903861d79fSDimitry Andric // in InstrMapDesc. 1913861d79fSDimitry Andric std::vector<Record*> InstrDefs; 1923861d79fSDimitry Andric 1933861d79fSDimitry Andric // RowInstrMap - maps RowFields values to the instructions. It's keyed by the 1943861d79fSDimitry Andric // values of the row fields and contains vector of records as values. 1953861d79fSDimitry Andric RowInstrMapTy RowInstrMap; 1963861d79fSDimitry Andric 1973861d79fSDimitry Andric // KeyInstrVec - list of key instructions. 1983861d79fSDimitry Andric std::vector<Record*> KeyInstrVec; 1993861d79fSDimitry Andric DenseMap<Record*, std::vector<Record*> > MapTable; 2003861d79fSDimitry Andric 2013861d79fSDimitry Andric public: 2023861d79fSDimitry Andric MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec): 2033861d79fSDimitry Andric Target(Target), InstrMapDesc(IMRec) { 2043861d79fSDimitry Andric const std::string FilterClass = InstrMapDesc.getFilterClass(); 2053861d79fSDimitry Andric InstrDefs = Records.getAllDerivedDefinitions(FilterClass); 2063861d79fSDimitry Andric } 2073861d79fSDimitry Andric 2083861d79fSDimitry Andric void buildRowInstrMap(); 2093861d79fSDimitry Andric 2103861d79fSDimitry Andric // Returns true if an instruction is a key instruction, i.e., its ColFields 2113861d79fSDimitry Andric // have same values as KeyCol. 2123861d79fSDimitry Andric bool isKeyColInstr(Record* CurInstr); 2133861d79fSDimitry Andric 2143861d79fSDimitry Andric // Find column instruction corresponding to a key instruction based on the 2153861d79fSDimitry Andric // constraints for that column. 2163861d79fSDimitry Andric Record *getInstrForColumn(Record *KeyInstr, ListInit *CurValueCol); 2173861d79fSDimitry Andric 2183861d79fSDimitry Andric // Find column instructions for each key instruction based 2193861d79fSDimitry Andric // on ValueCols and store them into MapTable. 2203861d79fSDimitry Andric void buildMapTable(); 2213861d79fSDimitry Andric 2223861d79fSDimitry Andric void emitBinSearch(raw_ostream &OS, unsigned TableSize); 2233861d79fSDimitry Andric void emitTablesWithFunc(raw_ostream &OS); 2243861d79fSDimitry Andric unsigned emitBinSearchTable(raw_ostream &OS); 2253861d79fSDimitry Andric 2263861d79fSDimitry Andric // Lookup functions to query binary search tables. 2273861d79fSDimitry Andric void emitMapFuncBody(raw_ostream &OS, unsigned TableSize); 2283861d79fSDimitry Andric 2293861d79fSDimitry Andric }; 2303861d79fSDimitry Andric } // End anonymous namespace. 2313861d79fSDimitry Andric 2323861d79fSDimitry Andric 2333861d79fSDimitry Andric //===----------------------------------------------------------------------===// 2343861d79fSDimitry Andric // Process all the instructions that model this relation (alreday present in 2353861d79fSDimitry Andric // InstrDefs) and insert them into RowInstrMap which is keyed by the values of 2363861d79fSDimitry Andric // the fields listed as RowFields. It stores vectors of records as values. 2373861d79fSDimitry Andric // All the related instructions have the same values for the RowFields thus are 2383861d79fSDimitry Andric // part of the same key-value pair. 2393861d79fSDimitry Andric //===----------------------------------------------------------------------===// 2403861d79fSDimitry Andric 2413861d79fSDimitry Andric void MapTableEmitter::buildRowInstrMap() { 2423861d79fSDimitry Andric for (unsigned i = 0, e = InstrDefs.size(); i < e; i++) { 2433861d79fSDimitry Andric Record *CurInstr = InstrDefs[i]; 2443861d79fSDimitry Andric std::vector<Init*> KeyValue; 2453861d79fSDimitry Andric ListInit *RowFields = InstrMapDesc.getRowFields(); 2463861d79fSDimitry Andric for (unsigned j = 0, endRF = RowFields->getSize(); j < endRF; j++) { 2473861d79fSDimitry Andric Init *RowFieldsJ = RowFields->getElement(j); 2483861d79fSDimitry Andric Init *CurInstrVal = CurInstr->getValue(RowFieldsJ)->getValue(); 2493861d79fSDimitry Andric KeyValue.push_back(CurInstrVal); 2503861d79fSDimitry Andric } 2513861d79fSDimitry Andric 2523861d79fSDimitry Andric // Collect key instructions into KeyInstrVec. Later, these instructions are 2533861d79fSDimitry Andric // processed to assign column position to the instructions sharing 2543861d79fSDimitry Andric // their KeyValue in RowInstrMap. 2553861d79fSDimitry Andric if (isKeyColInstr(CurInstr)) 2563861d79fSDimitry Andric KeyInstrVec.push_back(CurInstr); 2573861d79fSDimitry Andric 2583861d79fSDimitry Andric RowInstrMap[KeyValue].push_back(CurInstr); 2593861d79fSDimitry Andric } 2603861d79fSDimitry Andric } 2613861d79fSDimitry Andric 2623861d79fSDimitry Andric //===----------------------------------------------------------------------===// 2633861d79fSDimitry Andric // Return true if an instruction is a KeyCol instruction. 2643861d79fSDimitry Andric //===----------------------------------------------------------------------===// 2653861d79fSDimitry Andric 2663861d79fSDimitry Andric bool MapTableEmitter::isKeyColInstr(Record* CurInstr) { 2673861d79fSDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 2683861d79fSDimitry Andric ListInit *KeyCol = InstrMapDesc.getKeyCol(); 2693861d79fSDimitry Andric 2703861d79fSDimitry Andric // Check if the instruction is a KeyCol instruction. 2713861d79fSDimitry Andric bool MatchFound = true; 2723861d79fSDimitry Andric for (unsigned j = 0, endCF = ColFields->getSize(); 2733861d79fSDimitry Andric (j < endCF) && MatchFound; j++) { 2743861d79fSDimitry Andric RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j)); 2753861d79fSDimitry Andric std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString(); 2763861d79fSDimitry Andric std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString(); 2773861d79fSDimitry Andric MatchFound = (CurInstrVal == KeyColValue); 2783861d79fSDimitry Andric } 2793861d79fSDimitry Andric return MatchFound; 2803861d79fSDimitry Andric } 2813861d79fSDimitry Andric 2823861d79fSDimitry Andric //===----------------------------------------------------------------------===// 2833861d79fSDimitry Andric // Build a map to link key instructions with the column instructions arranged 2843861d79fSDimitry Andric // according to their column positions. 2853861d79fSDimitry Andric //===----------------------------------------------------------------------===// 2863861d79fSDimitry Andric 2873861d79fSDimitry Andric void MapTableEmitter::buildMapTable() { 2883861d79fSDimitry Andric // Find column instructions for a given key based on the ColField 2893861d79fSDimitry Andric // constraints. 2903861d79fSDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 2913861d79fSDimitry Andric unsigned NumOfCols = ValueCols.size(); 2923861d79fSDimitry Andric for (unsigned j = 0, endKI = KeyInstrVec.size(); j < endKI; j++) { 2933861d79fSDimitry Andric Record *CurKeyInstr = KeyInstrVec[j]; 2943861d79fSDimitry Andric std::vector<Record*> ColInstrVec(NumOfCols); 2953861d79fSDimitry Andric 2963861d79fSDimitry Andric // Find the column instruction based on the constraints for the column. 2973861d79fSDimitry Andric for (unsigned ColIdx = 0; ColIdx < NumOfCols; ColIdx++) { 2983861d79fSDimitry Andric ListInit *CurValueCol = ValueCols[ColIdx]; 2993861d79fSDimitry Andric Record *ColInstr = getInstrForColumn(CurKeyInstr, CurValueCol); 3003861d79fSDimitry Andric ColInstrVec[ColIdx] = ColInstr; 3013861d79fSDimitry Andric } 3023861d79fSDimitry Andric MapTable[CurKeyInstr] = ColInstrVec; 3033861d79fSDimitry Andric } 3043861d79fSDimitry Andric } 3053861d79fSDimitry Andric 3063861d79fSDimitry Andric //===----------------------------------------------------------------------===// 3073861d79fSDimitry Andric // Find column instruction based on the constraints for that column. 3083861d79fSDimitry Andric //===----------------------------------------------------------------------===// 3093861d79fSDimitry Andric 3103861d79fSDimitry Andric Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr, 3113861d79fSDimitry Andric ListInit *CurValueCol) { 3123861d79fSDimitry Andric ListInit *RowFields = InstrMapDesc.getRowFields(); 3133861d79fSDimitry Andric std::vector<Init*> KeyValue; 3143861d79fSDimitry Andric 3153861d79fSDimitry Andric // Construct KeyValue using KeyInstr's values for RowFields. 3163861d79fSDimitry Andric for (unsigned j = 0, endRF = RowFields->getSize(); j < endRF; j++) { 3173861d79fSDimitry Andric Init *RowFieldsJ = RowFields->getElement(j); 3183861d79fSDimitry Andric Init *KeyInstrVal = KeyInstr->getValue(RowFieldsJ)->getValue(); 3193861d79fSDimitry Andric KeyValue.push_back(KeyInstrVal); 3203861d79fSDimitry Andric } 3213861d79fSDimitry Andric 3223861d79fSDimitry Andric // Get all the instructions that share the same KeyValue as the KeyInstr 3233861d79fSDimitry Andric // in RowInstrMap. We search through these instructions to find a match 3243861d79fSDimitry Andric // for the current column, i.e., the instruction which has the same values 3253861d79fSDimitry Andric // as CurValueCol for all the fields in ColFields. 3263861d79fSDimitry Andric const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue]; 3273861d79fSDimitry Andric 3283861d79fSDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 32991bc56edSDimitry Andric Record *MatchInstr = nullptr; 3303861d79fSDimitry Andric 3313861d79fSDimitry Andric for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) { 3323861d79fSDimitry Andric bool MatchFound = true; 3333861d79fSDimitry Andric Record *CurInstr = RelatedInstrVec[i]; 3343861d79fSDimitry Andric for (unsigned j = 0, endCF = ColFields->getSize(); 3353861d79fSDimitry Andric (j < endCF) && MatchFound; j++) { 3363861d79fSDimitry Andric Init *ColFieldJ = ColFields->getElement(j); 3373861d79fSDimitry Andric Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue(); 3383861d79fSDimitry Andric std::string CurInstrVal = CurInstrInit->getAsUnquotedString(); 3393861d79fSDimitry Andric Init *ColFieldJVallue = CurValueCol->getElement(j); 3403861d79fSDimitry Andric MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString()); 3413861d79fSDimitry Andric } 3423861d79fSDimitry Andric 3433861d79fSDimitry Andric if (MatchFound) { 3443861d79fSDimitry Andric if (MatchInstr) // Already had a match 3453861d79fSDimitry Andric // Error if multiple matches are found for a column. 3463861d79fSDimitry Andric PrintFatalError("Multiple matches found for `" + KeyInstr->getName() + 3473861d79fSDimitry Andric "', for the relation `" + InstrMapDesc.getName()); 3483861d79fSDimitry Andric MatchInstr = CurInstr; 3493861d79fSDimitry Andric } 3503861d79fSDimitry Andric } 3513861d79fSDimitry Andric return MatchInstr; 3523861d79fSDimitry Andric } 3533861d79fSDimitry Andric 3543861d79fSDimitry Andric //===----------------------------------------------------------------------===// 3553861d79fSDimitry Andric // Emit one table per relation. Only instructions with a valid relation of a 3563861d79fSDimitry Andric // given type are included in the table sorted by their enum values (opcodes). 3573861d79fSDimitry Andric // Binary search is used for locating instructions in the table. 3583861d79fSDimitry Andric //===----------------------------------------------------------------------===// 3593861d79fSDimitry Andric 3603861d79fSDimitry Andric unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { 3613861d79fSDimitry Andric 3623861d79fSDimitry Andric const std::vector<const CodeGenInstruction*> &NumberedInstructions = 3633861d79fSDimitry Andric Target.getInstructionsByEnumValue(); 3643861d79fSDimitry Andric std::string TargetName = Target.getName(); 3653861d79fSDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 3663861d79fSDimitry Andric unsigned NumCol = ValueCols.size(); 3673861d79fSDimitry Andric unsigned TotalNumInstr = NumberedInstructions.size(); 3683861d79fSDimitry Andric unsigned TableSize = 0; 3693861d79fSDimitry Andric 3703861d79fSDimitry Andric OS << "static const uint16_t "<<InstrMapDesc.getName(); 3713861d79fSDimitry Andric // Number of columns in the table are NumCol+1 because key instructions are 3723861d79fSDimitry Andric // emitted as first column. 3733861d79fSDimitry Andric OS << "Table[]["<< NumCol+1 << "] = {\n"; 3743861d79fSDimitry Andric for (unsigned i = 0; i < TotalNumInstr; i++) { 3753861d79fSDimitry Andric Record *CurInstr = NumberedInstructions[i]->TheDef; 3763861d79fSDimitry Andric std::vector<Record*> ColInstrs = MapTable[CurInstr]; 3773861d79fSDimitry Andric std::string OutStr(""); 3783861d79fSDimitry Andric unsigned RelExists = 0; 3793861d79fSDimitry Andric if (ColInstrs.size()) { 3803861d79fSDimitry Andric for (unsigned j = 0; j < NumCol; j++) { 38191bc56edSDimitry Andric if (ColInstrs[j] != nullptr) { 3823861d79fSDimitry Andric RelExists = 1; 3833861d79fSDimitry Andric OutStr += ", "; 3843861d79fSDimitry Andric OutStr += TargetName; 3853861d79fSDimitry Andric OutStr += "::"; 3863861d79fSDimitry Andric OutStr += ColInstrs[j]->getName(); 38791bc56edSDimitry Andric } else { OutStr += ", (uint16_t)-1U";} 3883861d79fSDimitry Andric } 3893861d79fSDimitry Andric 3903861d79fSDimitry Andric if (RelExists) { 3913861d79fSDimitry Andric OS << " { " << TargetName << "::" << CurInstr->getName(); 3923861d79fSDimitry Andric OS << OutStr <<" },\n"; 3933861d79fSDimitry Andric TableSize++; 3943861d79fSDimitry Andric } 3953861d79fSDimitry Andric } 3963861d79fSDimitry Andric } 3973861d79fSDimitry Andric if (!TableSize) { 3983861d79fSDimitry Andric OS << " { " << TargetName << "::" << "INSTRUCTION_LIST_END, "; 3993861d79fSDimitry Andric OS << TargetName << "::" << "INSTRUCTION_LIST_END }"; 4003861d79fSDimitry Andric } 4013861d79fSDimitry Andric OS << "}; // End of " << InstrMapDesc.getName() << "Table\n\n"; 4023861d79fSDimitry Andric return TableSize; 4033861d79fSDimitry Andric } 4043861d79fSDimitry Andric 4053861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4063861d79fSDimitry Andric // Emit binary search algorithm as part of the functions used to query 4073861d79fSDimitry Andric // relation tables. 4083861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4093861d79fSDimitry Andric 4103861d79fSDimitry Andric void MapTableEmitter::emitBinSearch(raw_ostream &OS, unsigned TableSize) { 4113861d79fSDimitry Andric OS << " unsigned mid;\n"; 4123861d79fSDimitry Andric OS << " unsigned start = 0;\n"; 4133861d79fSDimitry Andric OS << " unsigned end = " << TableSize << ";\n"; 4143861d79fSDimitry Andric OS << " while (start < end) {\n"; 4153861d79fSDimitry Andric OS << " mid = start + (end - start)/2;\n"; 4163861d79fSDimitry Andric OS << " if (Opcode == " << InstrMapDesc.getName() << "Table[mid][0]) {\n"; 4173861d79fSDimitry Andric OS << " break;\n"; 4183861d79fSDimitry Andric OS << " }\n"; 4193861d79fSDimitry Andric OS << " if (Opcode < " << InstrMapDesc.getName() << "Table[mid][0])\n"; 4203861d79fSDimitry Andric OS << " end = mid;\n"; 4213861d79fSDimitry Andric OS << " else\n"; 4223861d79fSDimitry Andric OS << " start = mid + 1;\n"; 4233861d79fSDimitry Andric OS << " }\n"; 4243861d79fSDimitry Andric OS << " if (start == end)\n"; 4253861d79fSDimitry Andric OS << " return -1; // Instruction doesn't exist in this table.\n\n"; 4263861d79fSDimitry Andric } 4273861d79fSDimitry Andric 4283861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4293861d79fSDimitry Andric // Emit functions to query relation tables. 4303861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4313861d79fSDimitry Andric 4323861d79fSDimitry Andric void MapTableEmitter::emitMapFuncBody(raw_ostream &OS, 4333861d79fSDimitry Andric unsigned TableSize) { 4343861d79fSDimitry Andric 4353861d79fSDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 4363861d79fSDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 4373861d79fSDimitry Andric 4383861d79fSDimitry Andric // Emit binary search algorithm to locate instructions in the 4393861d79fSDimitry Andric // relation table. If found, return opcode value from the appropriate column 4403861d79fSDimitry Andric // of the table. 4413861d79fSDimitry Andric emitBinSearch(OS, TableSize); 4423861d79fSDimitry Andric 4433861d79fSDimitry Andric if (ValueCols.size() > 1) { 4443861d79fSDimitry Andric for (unsigned i = 0, e = ValueCols.size(); i < e; i++) { 4453861d79fSDimitry Andric ListInit *ColumnI = ValueCols[i]; 4463861d79fSDimitry Andric for (unsigned j = 0, ColSize = ColumnI->getSize(); j < ColSize; j++) { 4473861d79fSDimitry Andric std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); 4483861d79fSDimitry Andric OS << " if (in" << ColName; 4493861d79fSDimitry Andric OS << " == "; 4503861d79fSDimitry Andric OS << ColName << "_" << ColumnI->getElement(j)->getAsUnquotedString(); 4513861d79fSDimitry Andric if (j < ColumnI->getSize() - 1) OS << " && "; 4523861d79fSDimitry Andric else OS << ")\n"; 4533861d79fSDimitry Andric } 4543861d79fSDimitry Andric OS << " return " << InstrMapDesc.getName(); 4553861d79fSDimitry Andric OS << "Table[mid]["<<i+1<<"];\n"; 4563861d79fSDimitry Andric } 4573861d79fSDimitry Andric OS << " return -1;"; 4583861d79fSDimitry Andric } 4593861d79fSDimitry Andric else 4603861d79fSDimitry Andric OS << " return " << InstrMapDesc.getName() << "Table[mid][1];\n"; 4613861d79fSDimitry Andric 4623861d79fSDimitry Andric OS <<"}\n\n"; 4633861d79fSDimitry Andric } 4643861d79fSDimitry Andric 4653861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4663861d79fSDimitry Andric // Emit relation tables and the functions to query them. 4673861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4683861d79fSDimitry Andric 4693861d79fSDimitry Andric void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) { 4703861d79fSDimitry Andric 4713861d79fSDimitry Andric // Emit function name and the input parameters : mostly opcode value of the 4723861d79fSDimitry Andric // current instruction. However, if a table has multiple columns (more than 2 4733861d79fSDimitry Andric // since first column is used for the key instructions), then we also need 4743861d79fSDimitry Andric // to pass another input to indicate the column to be selected. 4753861d79fSDimitry Andric 4763861d79fSDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 4773861d79fSDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 4783861d79fSDimitry Andric OS << "// "<< InstrMapDesc.getName() << "\n"; 4793861d79fSDimitry Andric OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode"; 4803861d79fSDimitry Andric if (ValueCols.size() > 1) { 4813861d79fSDimitry Andric for (unsigned i = 0, e = ColFields->getSize(); i < e; i++) { 4823861d79fSDimitry Andric std::string ColName = ColFields->getElement(i)->getAsUnquotedString(); 4833861d79fSDimitry Andric OS << ", enum " << ColName << " in" << ColName << ") {\n"; 4843861d79fSDimitry Andric } 4853861d79fSDimitry Andric } else { OS << ") {\n"; } 4863861d79fSDimitry Andric 4873861d79fSDimitry Andric // Emit map table. 4883861d79fSDimitry Andric unsigned TableSize = emitBinSearchTable(OS); 4893861d79fSDimitry Andric 4903861d79fSDimitry Andric // Emit rest of the function body. 4913861d79fSDimitry Andric emitMapFuncBody(OS, TableSize); 4923861d79fSDimitry Andric } 4933861d79fSDimitry Andric 4943861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4953861d79fSDimitry Andric // Emit enums for the column fields across all the instruction maps. 4963861d79fSDimitry Andric //===----------------------------------------------------------------------===// 4973861d79fSDimitry Andric 4983861d79fSDimitry Andric static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { 4993861d79fSDimitry Andric 5003861d79fSDimitry Andric std::vector<Record*> InstrMapVec; 5013861d79fSDimitry Andric InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); 5023861d79fSDimitry Andric std::map<std::string, std::vector<Init*> > ColFieldValueMap; 5033861d79fSDimitry Andric 5043861d79fSDimitry Andric // Iterate over all InstrMapping records and create a map between column 5053861d79fSDimitry Andric // fields and their possible values across all records. 5063861d79fSDimitry Andric for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) { 5073861d79fSDimitry Andric Record *CurMap = InstrMapVec[i]; 5083861d79fSDimitry Andric ListInit *ColFields; 5093861d79fSDimitry Andric ColFields = CurMap->getValueAsListInit("ColFields"); 5103861d79fSDimitry Andric ListInit *List = CurMap->getValueAsListInit("ValueCols"); 5113861d79fSDimitry Andric std::vector<ListInit*> ValueCols; 5123861d79fSDimitry Andric unsigned ListSize = List->getSize(); 5133861d79fSDimitry Andric 5143861d79fSDimitry Andric for (unsigned j = 0; j < ListSize; j++) { 5153861d79fSDimitry Andric ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j)); 5163861d79fSDimitry Andric 5173861d79fSDimitry Andric if (ListJ->getSize() != ColFields->getSize()) 5183861d79fSDimitry Andric PrintFatalError("Record `" + CurMap->getName() + "', field " 5193861d79fSDimitry Andric "`ValueCols' entries don't match with the entries in 'ColFields' !"); 5203861d79fSDimitry Andric ValueCols.push_back(ListJ); 5213861d79fSDimitry Andric } 5223861d79fSDimitry Andric 5233861d79fSDimitry Andric for (unsigned j = 0, endCF = ColFields->getSize(); j < endCF; j++) { 5243861d79fSDimitry Andric for (unsigned k = 0; k < ListSize; k++){ 5253861d79fSDimitry Andric std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); 5263861d79fSDimitry Andric ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j)); 5273861d79fSDimitry Andric } 5283861d79fSDimitry Andric } 5293861d79fSDimitry Andric } 5303861d79fSDimitry Andric 5313861d79fSDimitry Andric for (std::map<std::string, std::vector<Init*> >::iterator 5323861d79fSDimitry Andric II = ColFieldValueMap.begin(), IE = ColFieldValueMap.end(); 5333861d79fSDimitry Andric II != IE; II++) { 5343861d79fSDimitry Andric std::vector<Init*> FieldValues = (*II).second; 5353861d79fSDimitry Andric 5363861d79fSDimitry Andric // Delete duplicate entries from ColFieldValueMap 537139f7f9bSDimitry Andric for (unsigned i = 0; i < FieldValues.size() - 1; i++) { 5383861d79fSDimitry Andric Init *CurVal = FieldValues[i]; 539139f7f9bSDimitry Andric for (unsigned j = i+1; j < FieldValues.size(); j++) { 5403861d79fSDimitry Andric if (CurVal == FieldValues[j]) { 5413861d79fSDimitry Andric FieldValues.erase(FieldValues.begin()+j); 5423861d79fSDimitry Andric } 5433861d79fSDimitry Andric } 5443861d79fSDimitry Andric } 5453861d79fSDimitry Andric 5463861d79fSDimitry Andric // Emit enumerated values for the column fields. 5473861d79fSDimitry Andric OS << "enum " << (*II).first << " {\n"; 548139f7f9bSDimitry Andric for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) { 5493861d79fSDimitry Andric OS << "\t" << (*II).first << "_" << FieldValues[i]->getAsUnquotedString(); 550139f7f9bSDimitry Andric if (i != endFV - 1) 5513861d79fSDimitry Andric OS << ",\n"; 5523861d79fSDimitry Andric else 5533861d79fSDimitry Andric OS << "\n};\n\n"; 5543861d79fSDimitry Andric } 5553861d79fSDimitry Andric } 5563861d79fSDimitry Andric } 5573861d79fSDimitry Andric 5583861d79fSDimitry Andric namespace llvm { 5593861d79fSDimitry Andric //===----------------------------------------------------------------------===// 5603861d79fSDimitry Andric // Parse 'InstrMapping' records and use the information to form relationship 5613861d79fSDimitry Andric // between instructions. These relations are emitted as a tables along with the 5623861d79fSDimitry Andric // functions to query them. 5633861d79fSDimitry Andric //===----------------------------------------------------------------------===// 5643861d79fSDimitry Andric void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) { 5653861d79fSDimitry Andric CodeGenTarget Target(Records); 5663861d79fSDimitry Andric std::string TargetName = Target.getName(); 5673861d79fSDimitry Andric std::vector<Record*> InstrMapVec; 5683861d79fSDimitry Andric InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); 5693861d79fSDimitry Andric 5703861d79fSDimitry Andric if (!InstrMapVec.size()) 5713861d79fSDimitry Andric return; 5723861d79fSDimitry Andric 5733861d79fSDimitry Andric OS << "#ifdef GET_INSTRMAP_INFO\n"; 5743861d79fSDimitry Andric OS << "#undef GET_INSTRMAP_INFO\n"; 5753861d79fSDimitry Andric OS << "namespace llvm {\n\n"; 5763861d79fSDimitry Andric OS << "namespace " << TargetName << " {\n\n"; 5773861d79fSDimitry Andric 5783861d79fSDimitry Andric // Emit coulumn field names and their values as enums. 5793861d79fSDimitry Andric emitEnums(OS, Records); 5803861d79fSDimitry Andric 5813861d79fSDimitry Andric // Iterate over all instruction mapping records and construct relationship 5823861d79fSDimitry Andric // maps based on the information specified there. 5833861d79fSDimitry Andric // 5843861d79fSDimitry Andric for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) { 5853861d79fSDimitry Andric MapTableEmitter IMap(Target, Records, InstrMapVec[i]); 5863861d79fSDimitry Andric 5873861d79fSDimitry Andric // Build RowInstrMap to group instructions based on their values for 5883861d79fSDimitry Andric // RowFields. In the process, also collect key instructions into 5893861d79fSDimitry Andric // KeyInstrVec. 5903861d79fSDimitry Andric IMap.buildRowInstrMap(); 5913861d79fSDimitry Andric 5923861d79fSDimitry Andric // Build MapTable to map key instructions with the corresponding column 5933861d79fSDimitry Andric // instructions. 5943861d79fSDimitry Andric IMap.buildMapTable(); 5953861d79fSDimitry Andric 5963861d79fSDimitry Andric // Emit map tables and the functions to query them. 5973861d79fSDimitry Andric IMap.emitTablesWithFunc(OS); 5983861d79fSDimitry Andric } 5993861d79fSDimitry Andric OS << "} // End " << TargetName << " namespace\n"; 6003861d79fSDimitry Andric OS << "} // End llvm namespace\n"; 6013861d79fSDimitry Andric OS << "#endif // GET_INSTRMAP_INFO\n\n"; 6023861d79fSDimitry Andric } 6033861d79fSDimitry Andric 6043861d79fSDimitry Andric } // End llvm namespace 605