10b57cec5SDimitry Andric //===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // CodeGenMapTable provides functionality for the TableGen to create 90b57cec5SDimitry Andric // relation mapping between instructions. Relation models are defined using 100b57cec5SDimitry Andric // InstrMapping as a base class. This file implements the functionality which 110b57cec5SDimitry Andric // parses these definitions and generates relation maps using the information 120b57cec5SDimitry Andric // specified there. These maps are emitted as tables in the XXXGenInstrInfo.inc 130b57cec5SDimitry Andric // file along with the functions to query them. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric // A relationship model to relate non-predicate instructions with their 160b57cec5SDimitry Andric // predicated true/false forms can be defined as follows: 170b57cec5SDimitry Andric // 180b57cec5SDimitry Andric // def getPredOpcode : InstrMapping { 190b57cec5SDimitry Andric // let FilterClass = "PredRel"; 200b57cec5SDimitry Andric // let RowFields = ["BaseOpcode"]; 210b57cec5SDimitry Andric // let ColFields = ["PredSense"]; 220b57cec5SDimitry Andric // let KeyCol = ["none"]; 230b57cec5SDimitry Andric // let ValueCols = [["true"], ["false"]]; } 240b57cec5SDimitry Andric // 250b57cec5SDimitry Andric // CodeGenMapTable parses this map and generates a table in XXXGenInstrInfo.inc 260b57cec5SDimitry Andric // file that contains the instructions modeling this relationship. This table 270b57cec5SDimitry Andric // is defined in the function 280b57cec5SDimitry Andric // "int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)" 290b57cec5SDimitry Andric // that can be used to retrieve the predicated form of the instruction by 300b57cec5SDimitry Andric // passing its opcode value and the predicate sense (true/false) of the desired 310b57cec5SDimitry Andric // instruction as arguments. 320b57cec5SDimitry Andric // 330b57cec5SDimitry Andric // Short description of the algorithm: 340b57cec5SDimitry Andric // 350b57cec5SDimitry Andric // 1) Iterate through all the records that derive from "InstrMapping" class. 360b57cec5SDimitry Andric // 2) For each record, filter out instructions based on the FilterClass value. 370b57cec5SDimitry Andric // 3) Iterate through this set of instructions and insert them into 380b57cec5SDimitry Andric // RowInstrMap map based on their RowFields values. RowInstrMap is keyed by the 390b57cec5SDimitry Andric // vector of RowFields values and contains vectors of Records (instructions) as 400b57cec5SDimitry Andric // values. RowFields is a list of fields that are required to have the same 410b57cec5SDimitry Andric // values for all the instructions appearing in the same row of the relation 420b57cec5SDimitry Andric // table. All the instructions in a given row of the relation table have some 430b57cec5SDimitry Andric // sort of relationship with the key instruction defined by the corresponding 440b57cec5SDimitry Andric // relationship model. 450b57cec5SDimitry Andric // 460b57cec5SDimitry Andric // Ex: RowInstrMap(RowVal1, RowVal2, ...) -> [Instr1, Instr2, Instr3, ... ] 470b57cec5SDimitry Andric // Here Instr1, Instr2, Instr3 have same values (RowVal1, RowVal2) for 480b57cec5SDimitry Andric // RowFields. These groups of instructions are later matched against ValueCols 490b57cec5SDimitry Andric // to determine the column they belong to, if any. 500b57cec5SDimitry Andric // 510b57cec5SDimitry Andric // While building the RowInstrMap map, collect all the key instructions in 520b57cec5SDimitry Andric // KeyInstrVec. These are the instructions having the same values as KeyCol 530b57cec5SDimitry Andric // for all the fields listed in ColFields. 540b57cec5SDimitry Andric // 550b57cec5SDimitry Andric // For Example: 560b57cec5SDimitry Andric // 570b57cec5SDimitry Andric // Relate non-predicate instructions with their predicated true/false forms. 580b57cec5SDimitry Andric // 590b57cec5SDimitry Andric // def getPredOpcode : InstrMapping { 600b57cec5SDimitry Andric // let FilterClass = "PredRel"; 610b57cec5SDimitry Andric // let RowFields = ["BaseOpcode"]; 620b57cec5SDimitry Andric // let ColFields = ["PredSense"]; 630b57cec5SDimitry Andric // let KeyCol = ["none"]; 640b57cec5SDimitry Andric // let ValueCols = [["true"], ["false"]]; } 650b57cec5SDimitry Andric // 660b57cec5SDimitry Andric // Here, only instructions that have "none" as PredSense will be selected as key 670b57cec5SDimitry Andric // instructions. 680b57cec5SDimitry Andric // 690b57cec5SDimitry Andric // 4) For each key instruction, get the group of instructions that share the 700b57cec5SDimitry Andric // same key-value as the key instruction from RowInstrMap. Iterate over the list 710b57cec5SDimitry Andric // of columns in ValueCols (it is defined as a list<list<string> >. Therefore, 720b57cec5SDimitry Andric // it can specify multi-column relationships). For each column, find the 730b57cec5SDimitry Andric // instruction from the group that matches all the values for the column. 740b57cec5SDimitry Andric // Multiple matches are not allowed. 750b57cec5SDimitry Andric // 760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 770b57cec5SDimitry Andric 78*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h" 79*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 800b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 8106c3fb27SDimitry Andric #include "llvm/TableGen/Record.h" 820b57cec5SDimitry Andric using namespace llvm; 830b57cec5SDimitry Andric typedef std::map<std::string, std::vector<Record *>> InstrRelMapTy; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric typedef std::map<std::vector<Init *>, std::vector<Record *>> RowInstrMapTy; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric namespace { 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 900b57cec5SDimitry Andric // This class is used to represent InstrMapping class defined in Target.td file. 910b57cec5SDimitry Andric class InstrMap { 920b57cec5SDimitry Andric private: 930b57cec5SDimitry Andric std::string Name; 940b57cec5SDimitry Andric std::string FilterClass; 950b57cec5SDimitry Andric ListInit *RowFields; 960b57cec5SDimitry Andric ListInit *ColFields; 970b57cec5SDimitry Andric ListInit *KeyCol; 980b57cec5SDimitry Andric std::vector<ListInit *> ValueCols; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric public: 1010b57cec5SDimitry Andric InstrMap(Record *MapRec) { 1025ffd83dbSDimitry Andric Name = std::string(MapRec->getName()); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric // FilterClass - It's used to reduce the search space only to the 1050b57cec5SDimitry Andric // instructions that define the kind of relationship modeled by 1060b57cec5SDimitry Andric // this InstrMapping object/record. 1070b57cec5SDimitry Andric const RecordVal *Filter = MapRec->getValue("FilterClass"); 1080b57cec5SDimitry Andric FilterClass = Filter->getValue()->getAsUnquotedString(); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric // List of fields/attributes that need to be same across all the 1110b57cec5SDimitry Andric // instructions in a row of the relation table. 1120b57cec5SDimitry Andric RowFields = MapRec->getValueAsListInit("RowFields"); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // List of fields/attributes that are constant across all the instruction 1150b57cec5SDimitry Andric // in a column of the relation table. Ex: ColFields = 'predSense' 1160b57cec5SDimitry Andric ColFields = MapRec->getValueAsListInit("ColFields"); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // Values for the fields/attributes listed in 'ColFields'. 1190b57cec5SDimitry Andric // Ex: KeyCol = 'noPred' -- key instruction is non-predicated 1200b57cec5SDimitry Andric KeyCol = MapRec->getValueAsListInit("KeyCol"); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // List of values for the fields/attributes listed in 'ColFields', one for 1230b57cec5SDimitry Andric // each column in the relation table. 1240b57cec5SDimitry Andric // 1250b57cec5SDimitry Andric // Ex: ValueCols = [['true'],['false']] -- it results two columns in the 1260b57cec5SDimitry Andric // table. First column requires all the instructions to have predSense 1270b57cec5SDimitry Andric // set to 'true' and second column requires it to be 'false'. 1280b57cec5SDimitry Andric ListInit *ColValList = MapRec->getValueAsListInit("ValueCols"); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // Each instruction map must specify at least one column for it to be valid. 1310b57cec5SDimitry Andric if (ColValList->empty()) 1320b57cec5SDimitry Andric PrintFatalError(MapRec->getLoc(), "InstrMapping record `" + 133*0fca6ea1SDimitry Andric MapRec->getName() + "' has empty " + 134*0fca6ea1SDimitry Andric "`ValueCols' field!"); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric for (Init *I : ColValList->getValues()) { 1378bcb0991SDimitry Andric auto *ColI = cast<ListInit>(I); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric // Make sure that all the sub-lists in 'ValueCols' have same number of 1400b57cec5SDimitry Andric // elements as the fields in 'ColFields'. 1410b57cec5SDimitry Andric if (ColI->size() != ColFields->size()) 142*0fca6ea1SDimitry Andric PrintFatalError(MapRec->getLoc(), 143*0fca6ea1SDimitry Andric "Record `" + MapRec->getName() + 1440b57cec5SDimitry Andric "', field `ValueCols' entries don't match with " + 1450b57cec5SDimitry Andric " the entries in 'ColFields'!"); 1460b57cec5SDimitry Andric ValueCols.push_back(ColI); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 150e8d8bef9SDimitry Andric const std::string &getName() const { return Name; } 1510b57cec5SDimitry Andric 152e8d8bef9SDimitry Andric const std::string &getFilterClass() const { return FilterClass; } 1530b57cec5SDimitry Andric 154e8d8bef9SDimitry Andric ListInit *getRowFields() const { return RowFields; } 1550b57cec5SDimitry Andric 156e8d8bef9SDimitry Andric ListInit *getColFields() const { return ColFields; } 1570b57cec5SDimitry Andric 158e8d8bef9SDimitry Andric ListInit *getKeyCol() const { return KeyCol; } 1590b57cec5SDimitry Andric 160*0fca6ea1SDimitry Andric const std::vector<ListInit *> &getValueCols() const { return ValueCols; } 1610b57cec5SDimitry Andric }; 1628bcb0991SDimitry Andric } // end anonymous namespace 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1650b57cec5SDimitry Andric // class MapTableEmitter : It builds the instruction relation maps using 1660b57cec5SDimitry Andric // the information provided in InstrMapping records. It outputs these 1670b57cec5SDimitry Andric // relationship maps as tables into XXXGenInstrInfo.inc file along with the 1680b57cec5SDimitry Andric // functions to query them. 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric namespace { 1710b57cec5SDimitry Andric class MapTableEmitter { 1720b57cec5SDimitry Andric private: 1730b57cec5SDimitry Andric // std::string TargetName; 1740b57cec5SDimitry Andric const CodeGenTarget &Target; 1750b57cec5SDimitry Andric // InstrMapDesc - InstrMapping record to be processed. 1760b57cec5SDimitry Andric InstrMap InstrMapDesc; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric // InstrDefs - list of instructions filtered using FilterClass defined 1790b57cec5SDimitry Andric // in InstrMapDesc. 1800b57cec5SDimitry Andric std::vector<Record *> InstrDefs; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric // RowInstrMap - maps RowFields values to the instructions. It's keyed by the 1830b57cec5SDimitry Andric // values of the row fields and contains vector of records as values. 1840b57cec5SDimitry Andric RowInstrMapTy RowInstrMap; 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // KeyInstrVec - list of key instructions. 1870b57cec5SDimitry Andric std::vector<Record *> KeyInstrVec; 1880b57cec5SDimitry Andric DenseMap<Record *, std::vector<Record *>> MapTable; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric public: 191*0fca6ea1SDimitry Andric MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec) 192*0fca6ea1SDimitry Andric : Target(Target), InstrMapDesc(IMRec) { 193e8d8bef9SDimitry Andric const std::string &FilterClass = InstrMapDesc.getFilterClass(); 1940b57cec5SDimitry Andric InstrDefs = Records.getAllDerivedDefinitions(FilterClass); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric void buildRowInstrMap(); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // Returns true if an instruction is a key instruction, i.e., its ColFields 2000b57cec5SDimitry Andric // have same values as KeyCol. 2010b57cec5SDimitry Andric bool isKeyColInstr(Record *CurInstr); 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric // Find column instruction corresponding to a key instruction based on the 2040b57cec5SDimitry Andric // constraints for that column. 2050b57cec5SDimitry Andric Record *getInstrForColumn(Record *KeyInstr, ListInit *CurValueCol); 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric // Find column instructions for each key instruction based 2080b57cec5SDimitry Andric // on ValueCols and store them into MapTable. 2090b57cec5SDimitry Andric void buildMapTable(); 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric void emitBinSearch(raw_ostream &OS, unsigned TableSize); 2120b57cec5SDimitry Andric void emitTablesWithFunc(raw_ostream &OS); 2130b57cec5SDimitry Andric unsigned emitBinSearchTable(raw_ostream &OS); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric // Lookup functions to query binary search tables. 2160b57cec5SDimitry Andric void emitMapFuncBody(raw_ostream &OS, unsigned TableSize); 2170b57cec5SDimitry Andric }; 2188bcb0991SDimitry Andric } // end anonymous namespace 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2210b57cec5SDimitry Andric // Process all the instructions that model this relation (alreday present in 2220b57cec5SDimitry Andric // InstrDefs) and insert them into RowInstrMap which is keyed by the values of 2230b57cec5SDimitry Andric // the fields listed as RowFields. It stores vectors of records as values. 2240b57cec5SDimitry Andric // All the related instructions have the same values for the RowFields thus are 2250b57cec5SDimitry Andric // part of the same key-value pair. 2260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void MapTableEmitter::buildRowInstrMap() { 2290b57cec5SDimitry Andric for (Record *CurInstr : InstrDefs) { 2300b57cec5SDimitry Andric std::vector<Init *> KeyValue; 2310b57cec5SDimitry Andric ListInit *RowFields = InstrMapDesc.getRowFields(); 2320b57cec5SDimitry Andric for (Init *RowField : RowFields->getValues()) { 2330b57cec5SDimitry Andric RecordVal *RecVal = CurInstr->getValue(RowField); 2340b57cec5SDimitry Andric if (RecVal == nullptr) 235*0fca6ea1SDimitry Andric PrintFatalError(CurInstr->getLoc(), 236*0fca6ea1SDimitry Andric "No value " + RowField->getAsString() + " found in \"" + 237*0fca6ea1SDimitry Andric CurInstr->getName() + 238*0fca6ea1SDimitry Andric "\" instruction description."); 2390b57cec5SDimitry Andric Init *CurInstrVal = RecVal->getValue(); 2400b57cec5SDimitry Andric KeyValue.push_back(CurInstrVal); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Collect key instructions into KeyInstrVec. Later, these instructions are 2440b57cec5SDimitry Andric // processed to assign column position to the instructions sharing 2450b57cec5SDimitry Andric // their KeyValue in RowInstrMap. 2460b57cec5SDimitry Andric if (isKeyColInstr(CurInstr)) 2470b57cec5SDimitry Andric KeyInstrVec.push_back(CurInstr); 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric RowInstrMap[KeyValue].push_back(CurInstr); 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2540b57cec5SDimitry Andric // Return true if an instruction is a KeyCol instruction. 2550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric bool MapTableEmitter::isKeyColInstr(Record *CurInstr) { 2580b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 2590b57cec5SDimitry Andric ListInit *KeyCol = InstrMapDesc.getKeyCol(); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric // Check if the instruction is a KeyCol instruction. 2620b57cec5SDimitry Andric bool MatchFound = true; 263*0fca6ea1SDimitry Andric for (unsigned j = 0, endCF = ColFields->size(); (j < endCF) && MatchFound; 264*0fca6ea1SDimitry Andric j++) { 2650b57cec5SDimitry Andric RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j)); 2660b57cec5SDimitry Andric std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString(); 2670b57cec5SDimitry Andric std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString(); 2680b57cec5SDimitry Andric MatchFound = (CurInstrVal == KeyColValue); 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric return MatchFound; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2740b57cec5SDimitry Andric // Build a map to link key instructions with the column instructions arranged 2750b57cec5SDimitry Andric // according to their column positions. 2760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric void MapTableEmitter::buildMapTable() { 2790b57cec5SDimitry Andric // Find column instructions for a given key based on the ColField 2800b57cec5SDimitry Andric // constraints. 2810b57cec5SDimitry Andric const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols(); 2820b57cec5SDimitry Andric unsigned NumOfCols = ValueCols.size(); 2830b57cec5SDimitry Andric for (Record *CurKeyInstr : KeyInstrVec) { 2840b57cec5SDimitry Andric std::vector<Record *> ColInstrVec(NumOfCols); 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric // Find the column instruction based on the constraints for the column. 2870b57cec5SDimitry Andric for (unsigned ColIdx = 0; ColIdx < NumOfCols; ColIdx++) { 2880b57cec5SDimitry Andric ListInit *CurValueCol = ValueCols[ColIdx]; 2890b57cec5SDimitry Andric Record *ColInstr = getInstrForColumn(CurKeyInstr, CurValueCol); 2900b57cec5SDimitry Andric ColInstrVec[ColIdx] = ColInstr; 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric MapTable[CurKeyInstr] = ColInstrVec; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2970b57cec5SDimitry Andric // Find column instruction based on the constraints for that column. 2980b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr, 3010b57cec5SDimitry Andric ListInit *CurValueCol) { 3020b57cec5SDimitry Andric ListInit *RowFields = InstrMapDesc.getRowFields(); 3030b57cec5SDimitry Andric std::vector<Init *> KeyValue; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // Construct KeyValue using KeyInstr's values for RowFields. 3060b57cec5SDimitry Andric for (Init *RowField : RowFields->getValues()) { 3070b57cec5SDimitry Andric Init *KeyInstrVal = KeyInstr->getValue(RowField)->getValue(); 3080b57cec5SDimitry Andric KeyValue.push_back(KeyInstrVal); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric // Get all the instructions that share the same KeyValue as the KeyInstr 3120b57cec5SDimitry Andric // in RowInstrMap. We search through these instructions to find a match 3130b57cec5SDimitry Andric // for the current column, i.e., the instruction which has the same values 3140b57cec5SDimitry Andric // as CurValueCol for all the fields in ColFields. 3150b57cec5SDimitry Andric const std::vector<Record *> &RelatedInstrVec = RowInstrMap[KeyValue]; 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 3180b57cec5SDimitry Andric Record *MatchInstr = nullptr; 3190b57cec5SDimitry Andric 320fe6060f1SDimitry Andric for (llvm::Record *CurInstr : RelatedInstrVec) { 3210b57cec5SDimitry Andric bool MatchFound = true; 322*0fca6ea1SDimitry Andric for (unsigned j = 0, endCF = ColFields->size(); (j < endCF) && MatchFound; 323*0fca6ea1SDimitry Andric j++) { 3240b57cec5SDimitry Andric Init *ColFieldJ = ColFields->getElement(j); 3250b57cec5SDimitry Andric Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue(); 3260b57cec5SDimitry Andric std::string CurInstrVal = CurInstrInit->getAsUnquotedString(); 3270b57cec5SDimitry Andric Init *ColFieldJVallue = CurValueCol->getElement(j); 3280b57cec5SDimitry Andric MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString()); 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric if (MatchFound) { 3320b57cec5SDimitry Andric if (MatchInstr) { 3330b57cec5SDimitry Andric // Already had a match 3340b57cec5SDimitry Andric // Error if multiple matches are found for a column. 3350b57cec5SDimitry Andric std::string KeyValueStr; 3360b57cec5SDimitry Andric for (Init *Value : KeyValue) { 3370b57cec5SDimitry Andric if (!KeyValueStr.empty()) 3380b57cec5SDimitry Andric KeyValueStr += ", "; 3390b57cec5SDimitry Andric KeyValueStr += Value->getAsString(); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric PrintFatalError("Multiple matches found for `" + KeyInstr->getName() + 343fe6060f1SDimitry Andric "', for the relation `" + InstrMapDesc.getName() + 344fe6060f1SDimitry Andric "', row fields [" + KeyValueStr + "], column `" + 345fe6060f1SDimitry Andric CurValueCol->getAsString() + "'"); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric MatchInstr = CurInstr; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric return MatchInstr; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3540b57cec5SDimitry Andric // Emit one table per relation. Only instructions with a valid relation of a 3550b57cec5SDimitry Andric // given type are included in the table sorted by their enum values (opcodes). 3560b57cec5SDimitry Andric // Binary search is used for locating instructions in the table. 3570b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric ArrayRef<const CodeGenInstruction *> NumberedInstructions = 3620b57cec5SDimitry Andric Target.getInstructionsByEnumValue(); 3630b57cec5SDimitry Andric StringRef Namespace = Target.getInstNamespace(); 3640b57cec5SDimitry Andric const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols(); 3650b57cec5SDimitry Andric unsigned NumCol = ValueCols.size(); 3660b57cec5SDimitry Andric unsigned TotalNumInstr = NumberedInstructions.size(); 3670b57cec5SDimitry Andric unsigned TableSize = 0; 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric OS << "static const uint16_t " << InstrMapDesc.getName(); 3700b57cec5SDimitry Andric // Number of columns in the table are NumCol+1 because key instructions are 3710b57cec5SDimitry Andric // emitted as first column. 3720b57cec5SDimitry Andric OS << "Table[][" << NumCol + 1 << "] = {\n"; 3730b57cec5SDimitry Andric for (unsigned i = 0; i < TotalNumInstr; i++) { 3740b57cec5SDimitry Andric Record *CurInstr = NumberedInstructions[i]->TheDef; 3750b57cec5SDimitry Andric std::vector<Record *> ColInstrs = MapTable[CurInstr]; 376e8d8bef9SDimitry Andric std::string OutStr; 3770b57cec5SDimitry Andric unsigned RelExists = 0; 3780b57cec5SDimitry Andric if (!ColInstrs.empty()) { 3790b57cec5SDimitry Andric for (unsigned j = 0; j < NumCol; j++) { 3800b57cec5SDimitry Andric if (ColInstrs[j] != nullptr) { 3810b57cec5SDimitry Andric RelExists = 1; 3820b57cec5SDimitry Andric OutStr += ", "; 3830b57cec5SDimitry Andric OutStr += Namespace; 3840b57cec5SDimitry Andric OutStr += "::"; 3850b57cec5SDimitry Andric OutStr += ColInstrs[j]->getName(); 386*0fca6ea1SDimitry Andric } else { 387*0fca6ea1SDimitry Andric OutStr += ", (uint16_t)-1U"; 388*0fca6ea1SDimitry Andric } 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric if (RelExists) { 3920b57cec5SDimitry Andric OS << " { " << Namespace << "::" << CurInstr->getName(); 3930b57cec5SDimitry Andric OS << OutStr << " },\n"; 3940b57cec5SDimitry Andric TableSize++; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric if (!TableSize) { 399*0fca6ea1SDimitry Andric OS << " { " << Namespace << "::" 400*0fca6ea1SDimitry Andric << "INSTRUCTION_LIST_END, "; 401*0fca6ea1SDimitry Andric OS << Namespace << "::" 402*0fca6ea1SDimitry Andric << "INSTRUCTION_LIST_END }"; 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric OS << "}; // End of " << InstrMapDesc.getName() << "Table\n\n"; 4050b57cec5SDimitry Andric return TableSize; 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4090b57cec5SDimitry Andric // Emit binary search algorithm as part of the functions used to query 4100b57cec5SDimitry Andric // relation tables. 4110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric void MapTableEmitter::emitBinSearch(raw_ostream &OS, unsigned TableSize) { 4140b57cec5SDimitry Andric OS << " unsigned mid;\n"; 4150b57cec5SDimitry Andric OS << " unsigned start = 0;\n"; 4160b57cec5SDimitry Andric OS << " unsigned end = " << TableSize << ";\n"; 4170b57cec5SDimitry Andric OS << " while (start < end) {\n"; 4180b57cec5SDimitry Andric OS << " mid = start + (end - start) / 2;\n"; 4190b57cec5SDimitry Andric OS << " if (Opcode == " << InstrMapDesc.getName() << "Table[mid][0]) {\n"; 4200b57cec5SDimitry Andric OS << " break;\n"; 4210b57cec5SDimitry Andric OS << " }\n"; 4220b57cec5SDimitry Andric OS << " if (Opcode < " << InstrMapDesc.getName() << "Table[mid][0])\n"; 4230b57cec5SDimitry Andric OS << " end = mid;\n"; 4240b57cec5SDimitry Andric OS << " else\n"; 4250b57cec5SDimitry Andric OS << " start = mid + 1;\n"; 4260b57cec5SDimitry Andric OS << " }\n"; 4270b57cec5SDimitry Andric OS << " if (start == end)\n"; 4280b57cec5SDimitry Andric OS << " return -1; // Instruction doesn't exist in this table.\n\n"; 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4320b57cec5SDimitry Andric // Emit functions to query relation tables. 4330b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4340b57cec5SDimitry Andric 435*0fca6ea1SDimitry Andric void MapTableEmitter::emitMapFuncBody(raw_ostream &OS, unsigned TableSize) { 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 4380b57cec5SDimitry Andric const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols(); 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric // Emit binary search algorithm to locate instructions in the 4410b57cec5SDimitry Andric // relation table. If found, return opcode value from the appropriate column 4420b57cec5SDimitry Andric // of the table. 4430b57cec5SDimitry Andric emitBinSearch(OS, TableSize); 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric if (ValueCols.size() > 1) { 4460b57cec5SDimitry Andric for (unsigned i = 0, e = ValueCols.size(); i < e; i++) { 4470b57cec5SDimitry Andric ListInit *ColumnI = ValueCols[i]; 448349cc55cSDimitry Andric OS << " if ("; 4490b57cec5SDimitry Andric for (unsigned j = 0, ColSize = ColumnI->size(); j < ColSize; ++j) { 4500b57cec5SDimitry Andric std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); 451349cc55cSDimitry Andric OS << "in" << ColName; 4520b57cec5SDimitry Andric OS << " == "; 4530b57cec5SDimitry Andric OS << ColName << "_" << ColumnI->getElement(j)->getAsUnquotedString(); 454349cc55cSDimitry Andric if (j < ColumnI->size() - 1) 455349cc55cSDimitry Andric OS << " && "; 4560b57cec5SDimitry Andric } 457349cc55cSDimitry Andric OS << ")\n"; 4580b57cec5SDimitry Andric OS << " return " << InstrMapDesc.getName(); 4590b57cec5SDimitry Andric OS << "Table[mid][" << i + 1 << "];\n"; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric OS << " return -1;"; 462*0fca6ea1SDimitry Andric } else 4630b57cec5SDimitry Andric OS << " return " << InstrMapDesc.getName() << "Table[mid][1];\n"; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric OS << "}\n\n"; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4690b57cec5SDimitry Andric // Emit relation tables and the functions to query them. 4700b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) { 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric // Emit function name and the input parameters : mostly opcode value of the 4750b57cec5SDimitry Andric // current instruction. However, if a table has multiple columns (more than 2 4760b57cec5SDimitry Andric // since first column is used for the key instructions), then we also need 4770b57cec5SDimitry Andric // to pass another input to indicate the column to be selected. 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 4800b57cec5SDimitry Andric const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols(); 4810b57cec5SDimitry Andric OS << "// " << InstrMapDesc.getName() << "\nLLVM_READONLY\n"; 4820b57cec5SDimitry Andric OS << "int " << InstrMapDesc.getName() << "(uint16_t Opcode"; 4830b57cec5SDimitry Andric if (ValueCols.size() > 1) { 4840b57cec5SDimitry Andric for (Init *CF : ColFields->getValues()) { 4850b57cec5SDimitry Andric std::string ColName = CF->getAsUnquotedString(); 486349cc55cSDimitry Andric OS << ", enum " << ColName << " in" << ColName; 4870b57cec5SDimitry Andric } 488349cc55cSDimitry Andric } 489349cc55cSDimitry Andric OS << ") {\n"; 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric // Emit map table. 4920b57cec5SDimitry Andric unsigned TableSize = emitBinSearchTable(OS); 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric // Emit rest of the function body. 4950b57cec5SDimitry Andric emitMapFuncBody(OS, TableSize); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4990b57cec5SDimitry Andric // Emit enums for the column fields across all the instruction maps. 5000b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric std::vector<Record *> InstrMapVec; 5050b57cec5SDimitry Andric InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); 5060b57cec5SDimitry Andric std::map<std::string, std::vector<Init *>> ColFieldValueMap; 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric // Iterate over all InstrMapping records and create a map between column 5090b57cec5SDimitry Andric // fields and their possible values across all records. 5100b57cec5SDimitry Andric for (Record *CurMap : InstrMapVec) { 5110b57cec5SDimitry Andric ListInit *ColFields; 5120b57cec5SDimitry Andric ColFields = CurMap->getValueAsListInit("ColFields"); 5130b57cec5SDimitry Andric ListInit *List = CurMap->getValueAsListInit("ValueCols"); 5140b57cec5SDimitry Andric std::vector<ListInit *> ValueCols; 5150b57cec5SDimitry Andric unsigned ListSize = List->size(); 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric for (unsigned j = 0; j < ListSize; j++) { 5188bcb0991SDimitry Andric auto *ListJ = cast<ListInit>(List->getElement(j)); 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric if (ListJ->size() != ColFields->size()) 521*0fca6ea1SDimitry Andric PrintFatalError("Record `" + CurMap->getName() + 522*0fca6ea1SDimitry Andric "', field " 523*0fca6ea1SDimitry Andric "`ValueCols' entries don't match with the entries in " 524*0fca6ea1SDimitry Andric "'ColFields' !"); 5250b57cec5SDimitry Andric ValueCols.push_back(ListJ); 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric for (unsigned j = 0, endCF = ColFields->size(); j < endCF; j++) { 5290b57cec5SDimitry Andric for (unsigned k = 0; k < ListSize; k++) { 5300b57cec5SDimitry Andric std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); 5310b57cec5SDimitry Andric ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j)); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric for (auto &Entry : ColFieldValueMap) { 5370b57cec5SDimitry Andric std::vector<Init *> FieldValues = Entry.second; 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric // Delete duplicate entries from ColFieldValueMap 5400b57cec5SDimitry Andric for (unsigned i = 0; i < FieldValues.size() - 1; i++) { 5410b57cec5SDimitry Andric Init *CurVal = FieldValues[i]; 5420b57cec5SDimitry Andric for (unsigned j = i + 1; j < FieldValues.size(); j++) { 5430b57cec5SDimitry Andric if (CurVal == FieldValues[j]) { 5440b57cec5SDimitry Andric FieldValues.erase(FieldValues.begin() + j); 5450b57cec5SDimitry Andric --j; 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric // Emit enumerated values for the column fields. 5510b57cec5SDimitry Andric OS << "enum " << Entry.first << " {\n"; 5520b57cec5SDimitry Andric for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) { 5530b57cec5SDimitry Andric OS << "\t" << Entry.first << "_" << FieldValues[i]->getAsUnquotedString(); 5540b57cec5SDimitry Andric if (i != endFV - 1) 5550b57cec5SDimitry Andric OS << ",\n"; 5560b57cec5SDimitry Andric else 5570b57cec5SDimitry Andric OS << "\n};\n\n"; 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric namespace llvm { 5630b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5640b57cec5SDimitry Andric // Parse 'InstrMapping' records and use the information to form relationship 5650b57cec5SDimitry Andric // between instructions. These relations are emitted as a tables along with the 5660b57cec5SDimitry Andric // functions to query them. 5670b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5680b57cec5SDimitry Andric void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) { 5690b57cec5SDimitry Andric CodeGenTarget Target(Records); 5700b57cec5SDimitry Andric StringRef NameSpace = Target.getInstNamespace(); 5710b57cec5SDimitry Andric std::vector<Record *> InstrMapVec; 5720b57cec5SDimitry Andric InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric if (InstrMapVec.empty()) 5750b57cec5SDimitry Andric return; 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric OS << "#ifdef GET_INSTRMAP_INFO\n"; 5780b57cec5SDimitry Andric OS << "#undef GET_INSTRMAP_INFO\n"; 5790b57cec5SDimitry Andric OS << "namespace llvm {\n\n"; 5800b57cec5SDimitry Andric OS << "namespace " << NameSpace << " {\n\n"; 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric // Emit coulumn field names and their values as enums. 5830b57cec5SDimitry Andric emitEnums(OS, Records); 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric // Iterate over all instruction mapping records and construct relationship 5860b57cec5SDimitry Andric // maps based on the information specified there. 5870b57cec5SDimitry Andric // 5880b57cec5SDimitry Andric for (Record *CurMap : InstrMapVec) { 5890b57cec5SDimitry Andric MapTableEmitter IMap(Target, Records, CurMap); 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric // Build RowInstrMap to group instructions based on their values for 5920b57cec5SDimitry Andric // RowFields. In the process, also collect key instructions into 5930b57cec5SDimitry Andric // KeyInstrVec. 5940b57cec5SDimitry Andric IMap.buildRowInstrMap(); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric // Build MapTable to map key instructions with the corresponding column 5970b57cec5SDimitry Andric // instructions. 5980b57cec5SDimitry Andric IMap.buildMapTable(); 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric // Emit map tables and the functions to query them. 6010b57cec5SDimitry Andric IMap.emitTablesWithFunc(OS); 6020b57cec5SDimitry Andric } 6038bcb0991SDimitry Andric OS << "} // end namespace " << NameSpace << "\n"; 6048bcb0991SDimitry Andric OS << "} // end namespace llvm\n"; 6050b57cec5SDimitry Andric OS << "#endif // GET_INSTRMAP_INFO\n\n"; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 608*0fca6ea1SDimitry Andric } // namespace llvm 609