1*0b57cec5SDimitry Andric //===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // CodeGenMapTable provides functionality for the TabelGen to create 9*0b57cec5SDimitry Andric // relation mapping between instructions. Relation models are defined using 10*0b57cec5SDimitry Andric // InstrMapping as a base class. This file implements the functionality which 11*0b57cec5SDimitry Andric // parses these definitions and generates relation maps using the information 12*0b57cec5SDimitry Andric // specified there. These maps are emitted as tables in the XXXGenInstrInfo.inc 13*0b57cec5SDimitry Andric // file along with the functions to query them. 14*0b57cec5SDimitry Andric // 15*0b57cec5SDimitry Andric // A relationship model to relate non-predicate instructions with their 16*0b57cec5SDimitry Andric // predicated true/false forms can be defined as follows: 17*0b57cec5SDimitry Andric // 18*0b57cec5SDimitry Andric // def getPredOpcode : InstrMapping { 19*0b57cec5SDimitry Andric // let FilterClass = "PredRel"; 20*0b57cec5SDimitry Andric // let RowFields = ["BaseOpcode"]; 21*0b57cec5SDimitry Andric // let ColFields = ["PredSense"]; 22*0b57cec5SDimitry Andric // let KeyCol = ["none"]; 23*0b57cec5SDimitry Andric // let ValueCols = [["true"], ["false"]]; } 24*0b57cec5SDimitry Andric // 25*0b57cec5SDimitry Andric // CodeGenMapTable parses this map and generates a table in XXXGenInstrInfo.inc 26*0b57cec5SDimitry Andric // file that contains the instructions modeling this relationship. This table 27*0b57cec5SDimitry Andric // is defined in the function 28*0b57cec5SDimitry Andric // "int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)" 29*0b57cec5SDimitry Andric // that can be used to retrieve the predicated form of the instruction by 30*0b57cec5SDimitry Andric // passing its opcode value and the predicate sense (true/false) of the desired 31*0b57cec5SDimitry Andric // instruction as arguments. 32*0b57cec5SDimitry Andric // 33*0b57cec5SDimitry Andric // Short description of the algorithm: 34*0b57cec5SDimitry Andric // 35*0b57cec5SDimitry Andric // 1) Iterate through all the records that derive from "InstrMapping" class. 36*0b57cec5SDimitry Andric // 2) For each record, filter out instructions based on the FilterClass value. 37*0b57cec5SDimitry Andric // 3) Iterate through this set of instructions and insert them into 38*0b57cec5SDimitry Andric // RowInstrMap map based on their RowFields values. RowInstrMap is keyed by the 39*0b57cec5SDimitry Andric // vector of RowFields values and contains vectors of Records (instructions) as 40*0b57cec5SDimitry Andric // values. RowFields is a list of fields that are required to have the same 41*0b57cec5SDimitry Andric // values for all the instructions appearing in the same row of the relation 42*0b57cec5SDimitry Andric // table. All the instructions in a given row of the relation table have some 43*0b57cec5SDimitry Andric // sort of relationship with the key instruction defined by the corresponding 44*0b57cec5SDimitry Andric // relationship model. 45*0b57cec5SDimitry Andric // 46*0b57cec5SDimitry Andric // Ex: RowInstrMap(RowVal1, RowVal2, ...) -> [Instr1, Instr2, Instr3, ... ] 47*0b57cec5SDimitry Andric // Here Instr1, Instr2, Instr3 have same values (RowVal1, RowVal2) for 48*0b57cec5SDimitry Andric // RowFields. These groups of instructions are later matched against ValueCols 49*0b57cec5SDimitry Andric // to determine the column they belong to, if any. 50*0b57cec5SDimitry Andric // 51*0b57cec5SDimitry Andric // While building the RowInstrMap map, collect all the key instructions in 52*0b57cec5SDimitry Andric // KeyInstrVec. These are the instructions having the same values as KeyCol 53*0b57cec5SDimitry Andric // for all the fields listed in ColFields. 54*0b57cec5SDimitry Andric // 55*0b57cec5SDimitry Andric // For Example: 56*0b57cec5SDimitry Andric // 57*0b57cec5SDimitry Andric // Relate non-predicate instructions with their predicated true/false forms. 58*0b57cec5SDimitry Andric // 59*0b57cec5SDimitry Andric // def getPredOpcode : InstrMapping { 60*0b57cec5SDimitry Andric // let FilterClass = "PredRel"; 61*0b57cec5SDimitry Andric // let RowFields = ["BaseOpcode"]; 62*0b57cec5SDimitry Andric // let ColFields = ["PredSense"]; 63*0b57cec5SDimitry Andric // let KeyCol = ["none"]; 64*0b57cec5SDimitry Andric // let ValueCols = [["true"], ["false"]]; } 65*0b57cec5SDimitry Andric // 66*0b57cec5SDimitry Andric // Here, only instructions that have "none" as PredSense will be selected as key 67*0b57cec5SDimitry Andric // instructions. 68*0b57cec5SDimitry Andric // 69*0b57cec5SDimitry Andric // 4) For each key instruction, get the group of instructions that share the 70*0b57cec5SDimitry Andric // same key-value as the key instruction from RowInstrMap. Iterate over the list 71*0b57cec5SDimitry Andric // of columns in ValueCols (it is defined as a list<list<string> >. Therefore, 72*0b57cec5SDimitry Andric // it can specify multi-column relationships). For each column, find the 73*0b57cec5SDimitry Andric // instruction from the group that matches all the values for the column. 74*0b57cec5SDimitry Andric // Multiple matches are not allowed. 75*0b57cec5SDimitry Andric // 76*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric #include "CodeGenTarget.h" 79*0b57cec5SDimitry Andric #include "llvm/Support/Format.h" 80*0b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 81*0b57cec5SDimitry Andric using namespace llvm; 82*0b57cec5SDimitry Andric typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy; 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric typedef std::map<std::vector<Init*>, std::vector<Record*> > RowInstrMapTy; 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric namespace { 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 89*0b57cec5SDimitry Andric // This class is used to represent InstrMapping class defined in Target.td file. 90*0b57cec5SDimitry Andric class InstrMap { 91*0b57cec5SDimitry Andric private: 92*0b57cec5SDimitry Andric std::string Name; 93*0b57cec5SDimitry Andric std::string FilterClass; 94*0b57cec5SDimitry Andric ListInit *RowFields; 95*0b57cec5SDimitry Andric ListInit *ColFields; 96*0b57cec5SDimitry Andric ListInit *KeyCol; 97*0b57cec5SDimitry Andric std::vector<ListInit*> ValueCols; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric public: 100*0b57cec5SDimitry Andric InstrMap(Record* MapRec) { 1015ffd83dbSDimitry Andric Name = std::string(MapRec->getName()); 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric // FilterClass - It's used to reduce the search space only to the 104*0b57cec5SDimitry Andric // instructions that define the kind of relationship modeled by 105*0b57cec5SDimitry Andric // this InstrMapping object/record. 106*0b57cec5SDimitry Andric const RecordVal *Filter = MapRec->getValue("FilterClass"); 107*0b57cec5SDimitry Andric FilterClass = Filter->getValue()->getAsUnquotedString(); 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric // List of fields/attributes that need to be same across all the 110*0b57cec5SDimitry Andric // instructions in a row of the relation table. 111*0b57cec5SDimitry Andric RowFields = MapRec->getValueAsListInit("RowFields"); 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric // List of fields/attributes that are constant across all the instruction 114*0b57cec5SDimitry Andric // in a column of the relation table. Ex: ColFields = 'predSense' 115*0b57cec5SDimitry Andric ColFields = MapRec->getValueAsListInit("ColFields"); 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric // Values for the fields/attributes listed in 'ColFields'. 118*0b57cec5SDimitry Andric // Ex: KeyCol = 'noPred' -- key instruction is non-predicated 119*0b57cec5SDimitry Andric KeyCol = MapRec->getValueAsListInit("KeyCol"); 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric // List of values for the fields/attributes listed in 'ColFields', one for 122*0b57cec5SDimitry Andric // each column in the relation table. 123*0b57cec5SDimitry Andric // 124*0b57cec5SDimitry Andric // Ex: ValueCols = [['true'],['false']] -- it results two columns in the 125*0b57cec5SDimitry Andric // table. First column requires all the instructions to have predSense 126*0b57cec5SDimitry Andric // set to 'true' and second column requires it to be 'false'. 127*0b57cec5SDimitry Andric ListInit *ColValList = MapRec->getValueAsListInit("ValueCols"); 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric // Each instruction map must specify at least one column for it to be valid. 130*0b57cec5SDimitry Andric if (ColValList->empty()) 131*0b57cec5SDimitry Andric PrintFatalError(MapRec->getLoc(), "InstrMapping record `" + 132*0b57cec5SDimitry Andric MapRec->getName() + "' has empty " + "`ValueCols' field!"); 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric for (Init *I : ColValList->getValues()) { 1358bcb0991SDimitry Andric auto *ColI = cast<ListInit>(I); 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric // Make sure that all the sub-lists in 'ValueCols' have same number of 138*0b57cec5SDimitry Andric // elements as the fields in 'ColFields'. 139*0b57cec5SDimitry Andric if (ColI->size() != ColFields->size()) 140*0b57cec5SDimitry Andric PrintFatalError(MapRec->getLoc(), "Record `" + MapRec->getName() + 141*0b57cec5SDimitry Andric "', field `ValueCols' entries don't match with " + 142*0b57cec5SDimitry Andric " the entries in 'ColFields'!"); 143*0b57cec5SDimitry Andric ValueCols.push_back(ColI); 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric std::string getName() const { 148*0b57cec5SDimitry Andric return Name; 149*0b57cec5SDimitry Andric } 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric std::string getFilterClass() { 152*0b57cec5SDimitry Andric return FilterClass; 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric ListInit *getRowFields() const { 156*0b57cec5SDimitry Andric return RowFields; 157*0b57cec5SDimitry Andric } 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric ListInit *getColFields() const { 160*0b57cec5SDimitry Andric return ColFields; 161*0b57cec5SDimitry Andric } 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric ListInit *getKeyCol() const { 164*0b57cec5SDimitry Andric return KeyCol; 165*0b57cec5SDimitry Andric } 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric const std::vector<ListInit*> &getValueCols() const { 168*0b57cec5SDimitry Andric return ValueCols; 169*0b57cec5SDimitry Andric } 170*0b57cec5SDimitry Andric }; 1718bcb0991SDimitry Andric } // end anonymous namespace 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 175*0b57cec5SDimitry Andric // class MapTableEmitter : It builds the instruction relation maps using 176*0b57cec5SDimitry Andric // the information provided in InstrMapping records. It outputs these 177*0b57cec5SDimitry Andric // relationship maps as tables into XXXGenInstrInfo.inc file along with the 178*0b57cec5SDimitry Andric // functions to query them. 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric namespace { 181*0b57cec5SDimitry Andric class MapTableEmitter { 182*0b57cec5SDimitry Andric private: 183*0b57cec5SDimitry Andric // std::string TargetName; 184*0b57cec5SDimitry Andric const CodeGenTarget &Target; 185*0b57cec5SDimitry Andric // InstrMapDesc - InstrMapping record to be processed. 186*0b57cec5SDimitry Andric InstrMap InstrMapDesc; 187*0b57cec5SDimitry Andric 188*0b57cec5SDimitry Andric // InstrDefs - list of instructions filtered using FilterClass defined 189*0b57cec5SDimitry Andric // in InstrMapDesc. 190*0b57cec5SDimitry Andric std::vector<Record*> InstrDefs; 191*0b57cec5SDimitry Andric 192*0b57cec5SDimitry Andric // RowInstrMap - maps RowFields values to the instructions. It's keyed by the 193*0b57cec5SDimitry Andric // values of the row fields and contains vector of records as values. 194*0b57cec5SDimitry Andric RowInstrMapTy RowInstrMap; 195*0b57cec5SDimitry Andric 196*0b57cec5SDimitry Andric // KeyInstrVec - list of key instructions. 197*0b57cec5SDimitry Andric std::vector<Record*> KeyInstrVec; 198*0b57cec5SDimitry Andric DenseMap<Record*, std::vector<Record*> > MapTable; 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric public: 201*0b57cec5SDimitry Andric MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec): 202*0b57cec5SDimitry Andric Target(Target), InstrMapDesc(IMRec) { 203*0b57cec5SDimitry Andric const std::string FilterClass = InstrMapDesc.getFilterClass(); 204*0b57cec5SDimitry Andric InstrDefs = Records.getAllDerivedDefinitions(FilterClass); 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric void buildRowInstrMap(); 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric // Returns true if an instruction is a key instruction, i.e., its ColFields 210*0b57cec5SDimitry Andric // have same values as KeyCol. 211*0b57cec5SDimitry Andric bool isKeyColInstr(Record* CurInstr); 212*0b57cec5SDimitry Andric 213*0b57cec5SDimitry Andric // Find column instruction corresponding to a key instruction based on the 214*0b57cec5SDimitry Andric // constraints for that column. 215*0b57cec5SDimitry Andric Record *getInstrForColumn(Record *KeyInstr, ListInit *CurValueCol); 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric // Find column instructions for each key instruction based 218*0b57cec5SDimitry Andric // on ValueCols and store them into MapTable. 219*0b57cec5SDimitry Andric void buildMapTable(); 220*0b57cec5SDimitry Andric 221*0b57cec5SDimitry Andric void emitBinSearch(raw_ostream &OS, unsigned TableSize); 222*0b57cec5SDimitry Andric void emitTablesWithFunc(raw_ostream &OS); 223*0b57cec5SDimitry Andric unsigned emitBinSearchTable(raw_ostream &OS); 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric // Lookup functions to query binary search tables. 226*0b57cec5SDimitry Andric void emitMapFuncBody(raw_ostream &OS, unsigned TableSize); 227*0b57cec5SDimitry Andric 228*0b57cec5SDimitry Andric }; 2298bcb0991SDimitry Andric } // end anonymous namespace 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 233*0b57cec5SDimitry Andric // Process all the instructions that model this relation (alreday present in 234*0b57cec5SDimitry Andric // InstrDefs) and insert them into RowInstrMap which is keyed by the values of 235*0b57cec5SDimitry Andric // the fields listed as RowFields. It stores vectors of records as values. 236*0b57cec5SDimitry Andric // All the related instructions have the same values for the RowFields thus are 237*0b57cec5SDimitry Andric // part of the same key-value pair. 238*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric void MapTableEmitter::buildRowInstrMap() { 241*0b57cec5SDimitry Andric for (Record *CurInstr : InstrDefs) { 242*0b57cec5SDimitry Andric std::vector<Init*> KeyValue; 243*0b57cec5SDimitry Andric ListInit *RowFields = InstrMapDesc.getRowFields(); 244*0b57cec5SDimitry Andric for (Init *RowField : RowFields->getValues()) { 245*0b57cec5SDimitry Andric RecordVal *RecVal = CurInstr->getValue(RowField); 246*0b57cec5SDimitry Andric if (RecVal == nullptr) 247*0b57cec5SDimitry Andric PrintFatalError(CurInstr->getLoc(), "No value " + 248*0b57cec5SDimitry Andric RowField->getAsString() + " found in \"" + 249*0b57cec5SDimitry Andric CurInstr->getName() + "\" instruction description."); 250*0b57cec5SDimitry Andric Init *CurInstrVal = RecVal->getValue(); 251*0b57cec5SDimitry Andric KeyValue.push_back(CurInstrVal); 252*0b57cec5SDimitry Andric } 253*0b57cec5SDimitry Andric 254*0b57cec5SDimitry Andric // Collect key instructions into KeyInstrVec. Later, these instructions are 255*0b57cec5SDimitry Andric // processed to assign column position to the instructions sharing 256*0b57cec5SDimitry Andric // their KeyValue in RowInstrMap. 257*0b57cec5SDimitry Andric if (isKeyColInstr(CurInstr)) 258*0b57cec5SDimitry Andric KeyInstrVec.push_back(CurInstr); 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric RowInstrMap[KeyValue].push_back(CurInstr); 261*0b57cec5SDimitry Andric } 262*0b57cec5SDimitry Andric } 263*0b57cec5SDimitry Andric 264*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 265*0b57cec5SDimitry Andric // Return true if an instruction is a KeyCol instruction. 266*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andric bool MapTableEmitter::isKeyColInstr(Record* CurInstr) { 269*0b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 270*0b57cec5SDimitry Andric ListInit *KeyCol = InstrMapDesc.getKeyCol(); 271*0b57cec5SDimitry Andric 272*0b57cec5SDimitry Andric // Check if the instruction is a KeyCol instruction. 273*0b57cec5SDimitry Andric bool MatchFound = true; 274*0b57cec5SDimitry Andric for (unsigned j = 0, endCF = ColFields->size(); 275*0b57cec5SDimitry Andric (j < endCF) && MatchFound; j++) { 276*0b57cec5SDimitry Andric RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j)); 277*0b57cec5SDimitry Andric std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString(); 278*0b57cec5SDimitry Andric std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString(); 279*0b57cec5SDimitry Andric MatchFound = (CurInstrVal == KeyColValue); 280*0b57cec5SDimitry Andric } 281*0b57cec5SDimitry Andric return MatchFound; 282*0b57cec5SDimitry Andric } 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 285*0b57cec5SDimitry Andric // Build a map to link key instructions with the column instructions arranged 286*0b57cec5SDimitry Andric // according to their column positions. 287*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 288*0b57cec5SDimitry Andric 289*0b57cec5SDimitry Andric void MapTableEmitter::buildMapTable() { 290*0b57cec5SDimitry Andric // Find column instructions for a given key based on the ColField 291*0b57cec5SDimitry Andric // constraints. 292*0b57cec5SDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 293*0b57cec5SDimitry Andric unsigned NumOfCols = ValueCols.size(); 294*0b57cec5SDimitry Andric for (Record *CurKeyInstr : KeyInstrVec) { 295*0b57cec5SDimitry Andric std::vector<Record*> ColInstrVec(NumOfCols); 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric // Find the column instruction based on the constraints for the column. 298*0b57cec5SDimitry Andric for (unsigned ColIdx = 0; ColIdx < NumOfCols; ColIdx++) { 299*0b57cec5SDimitry Andric ListInit *CurValueCol = ValueCols[ColIdx]; 300*0b57cec5SDimitry Andric Record *ColInstr = getInstrForColumn(CurKeyInstr, CurValueCol); 301*0b57cec5SDimitry Andric ColInstrVec[ColIdx] = ColInstr; 302*0b57cec5SDimitry Andric } 303*0b57cec5SDimitry Andric MapTable[CurKeyInstr] = ColInstrVec; 304*0b57cec5SDimitry Andric } 305*0b57cec5SDimitry Andric } 306*0b57cec5SDimitry Andric 307*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 308*0b57cec5SDimitry Andric // Find column instruction based on the constraints for that column. 309*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 310*0b57cec5SDimitry Andric 311*0b57cec5SDimitry Andric Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr, 312*0b57cec5SDimitry Andric ListInit *CurValueCol) { 313*0b57cec5SDimitry Andric ListInit *RowFields = InstrMapDesc.getRowFields(); 314*0b57cec5SDimitry Andric std::vector<Init*> KeyValue; 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andric // Construct KeyValue using KeyInstr's values for RowFields. 317*0b57cec5SDimitry Andric for (Init *RowField : RowFields->getValues()) { 318*0b57cec5SDimitry Andric Init *KeyInstrVal = KeyInstr->getValue(RowField)->getValue(); 319*0b57cec5SDimitry Andric KeyValue.push_back(KeyInstrVal); 320*0b57cec5SDimitry Andric } 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric // Get all the instructions that share the same KeyValue as the KeyInstr 323*0b57cec5SDimitry Andric // in RowInstrMap. We search through these instructions to find a match 324*0b57cec5SDimitry Andric // for the current column, i.e., the instruction which has the same values 325*0b57cec5SDimitry Andric // as CurValueCol for all the fields in ColFields. 326*0b57cec5SDimitry Andric const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue]; 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 329*0b57cec5SDimitry Andric Record *MatchInstr = nullptr; 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) { 332*0b57cec5SDimitry Andric bool MatchFound = true; 333*0b57cec5SDimitry Andric Record *CurInstr = RelatedInstrVec[i]; 334*0b57cec5SDimitry Andric for (unsigned j = 0, endCF = ColFields->size(); 335*0b57cec5SDimitry Andric (j < endCF) && MatchFound; j++) { 336*0b57cec5SDimitry Andric Init *ColFieldJ = ColFields->getElement(j); 337*0b57cec5SDimitry Andric Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue(); 338*0b57cec5SDimitry Andric std::string CurInstrVal = CurInstrInit->getAsUnquotedString(); 339*0b57cec5SDimitry Andric Init *ColFieldJVallue = CurValueCol->getElement(j); 340*0b57cec5SDimitry Andric MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString()); 341*0b57cec5SDimitry Andric } 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric if (MatchFound) { 344*0b57cec5SDimitry Andric if (MatchInstr) { 345*0b57cec5SDimitry Andric // Already had a match 346*0b57cec5SDimitry Andric // Error if multiple matches are found for a column. 347*0b57cec5SDimitry Andric std::string KeyValueStr; 348*0b57cec5SDimitry Andric for (Init *Value : KeyValue) { 349*0b57cec5SDimitry Andric if (!KeyValueStr.empty()) 350*0b57cec5SDimitry Andric KeyValueStr += ", "; 351*0b57cec5SDimitry Andric KeyValueStr += Value->getAsString(); 352*0b57cec5SDimitry Andric } 353*0b57cec5SDimitry Andric 354*0b57cec5SDimitry Andric PrintFatalError("Multiple matches found for `" + KeyInstr->getName() + 355*0b57cec5SDimitry Andric "', for the relation `" + InstrMapDesc.getName() + "', row fields [" + 356*0b57cec5SDimitry Andric KeyValueStr + "], column `" + CurValueCol->getAsString() + "'"); 357*0b57cec5SDimitry Andric } 358*0b57cec5SDimitry Andric MatchInstr = CurInstr; 359*0b57cec5SDimitry Andric } 360*0b57cec5SDimitry Andric } 361*0b57cec5SDimitry Andric return MatchInstr; 362*0b57cec5SDimitry Andric } 363*0b57cec5SDimitry Andric 364*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 365*0b57cec5SDimitry Andric // Emit one table per relation. Only instructions with a valid relation of a 366*0b57cec5SDimitry Andric // given type are included in the table sorted by their enum values (opcodes). 367*0b57cec5SDimitry Andric // Binary search is used for locating instructions in the table. 368*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric ArrayRef<const CodeGenInstruction*> NumberedInstructions = 373*0b57cec5SDimitry Andric Target.getInstructionsByEnumValue(); 374*0b57cec5SDimitry Andric StringRef Namespace = Target.getInstNamespace(); 375*0b57cec5SDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 376*0b57cec5SDimitry Andric unsigned NumCol = ValueCols.size(); 377*0b57cec5SDimitry Andric unsigned TotalNumInstr = NumberedInstructions.size(); 378*0b57cec5SDimitry Andric unsigned TableSize = 0; 379*0b57cec5SDimitry Andric 380*0b57cec5SDimitry Andric OS << "static const uint16_t "<<InstrMapDesc.getName(); 381*0b57cec5SDimitry Andric // Number of columns in the table are NumCol+1 because key instructions are 382*0b57cec5SDimitry Andric // emitted as first column. 383*0b57cec5SDimitry Andric OS << "Table[]["<< NumCol+1 << "] = {\n"; 384*0b57cec5SDimitry Andric for (unsigned i = 0; i < TotalNumInstr; i++) { 385*0b57cec5SDimitry Andric Record *CurInstr = NumberedInstructions[i]->TheDef; 386*0b57cec5SDimitry Andric std::vector<Record*> ColInstrs = MapTable[CurInstr]; 387*0b57cec5SDimitry Andric std::string OutStr(""); 388*0b57cec5SDimitry Andric unsigned RelExists = 0; 389*0b57cec5SDimitry Andric if (!ColInstrs.empty()) { 390*0b57cec5SDimitry Andric for (unsigned j = 0; j < NumCol; j++) { 391*0b57cec5SDimitry Andric if (ColInstrs[j] != nullptr) { 392*0b57cec5SDimitry Andric RelExists = 1; 393*0b57cec5SDimitry Andric OutStr += ", "; 394*0b57cec5SDimitry Andric OutStr += Namespace; 395*0b57cec5SDimitry Andric OutStr += "::"; 396*0b57cec5SDimitry Andric OutStr += ColInstrs[j]->getName(); 397*0b57cec5SDimitry Andric } else { OutStr += ", (uint16_t)-1U";} 398*0b57cec5SDimitry Andric } 399*0b57cec5SDimitry Andric 400*0b57cec5SDimitry Andric if (RelExists) { 401*0b57cec5SDimitry Andric OS << " { " << Namespace << "::" << CurInstr->getName(); 402*0b57cec5SDimitry Andric OS << OutStr <<" },\n"; 403*0b57cec5SDimitry Andric TableSize++; 404*0b57cec5SDimitry Andric } 405*0b57cec5SDimitry Andric } 406*0b57cec5SDimitry Andric } 407*0b57cec5SDimitry Andric if (!TableSize) { 408*0b57cec5SDimitry Andric OS << " { " << Namespace << "::" << "INSTRUCTION_LIST_END, "; 409*0b57cec5SDimitry Andric OS << Namespace << "::" << "INSTRUCTION_LIST_END }"; 410*0b57cec5SDimitry Andric } 411*0b57cec5SDimitry Andric OS << "}; // End of " << InstrMapDesc.getName() << "Table\n\n"; 412*0b57cec5SDimitry Andric return TableSize; 413*0b57cec5SDimitry Andric } 414*0b57cec5SDimitry Andric 415*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 416*0b57cec5SDimitry Andric // Emit binary search algorithm as part of the functions used to query 417*0b57cec5SDimitry Andric // relation tables. 418*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric void MapTableEmitter::emitBinSearch(raw_ostream &OS, unsigned TableSize) { 421*0b57cec5SDimitry Andric OS << " unsigned mid;\n"; 422*0b57cec5SDimitry Andric OS << " unsigned start = 0;\n"; 423*0b57cec5SDimitry Andric OS << " unsigned end = " << TableSize << ";\n"; 424*0b57cec5SDimitry Andric OS << " while (start < end) {\n"; 425*0b57cec5SDimitry Andric OS << " mid = start + (end - start)/2;\n"; 426*0b57cec5SDimitry Andric OS << " if (Opcode == " << InstrMapDesc.getName() << "Table[mid][0]) {\n"; 427*0b57cec5SDimitry Andric OS << " break;\n"; 428*0b57cec5SDimitry Andric OS << " }\n"; 429*0b57cec5SDimitry Andric OS << " if (Opcode < " << InstrMapDesc.getName() << "Table[mid][0])\n"; 430*0b57cec5SDimitry Andric OS << " end = mid;\n"; 431*0b57cec5SDimitry Andric OS << " else\n"; 432*0b57cec5SDimitry Andric OS << " start = mid + 1;\n"; 433*0b57cec5SDimitry Andric OS << " }\n"; 434*0b57cec5SDimitry Andric OS << " if (start == end)\n"; 435*0b57cec5SDimitry Andric OS << " return -1; // Instruction doesn't exist in this table.\n\n"; 436*0b57cec5SDimitry Andric } 437*0b57cec5SDimitry Andric 438*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 439*0b57cec5SDimitry Andric // Emit functions to query relation tables. 440*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 441*0b57cec5SDimitry Andric 442*0b57cec5SDimitry Andric void MapTableEmitter::emitMapFuncBody(raw_ostream &OS, 443*0b57cec5SDimitry Andric unsigned TableSize) { 444*0b57cec5SDimitry Andric 445*0b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 446*0b57cec5SDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 447*0b57cec5SDimitry Andric 448*0b57cec5SDimitry Andric // Emit binary search algorithm to locate instructions in the 449*0b57cec5SDimitry Andric // relation table. If found, return opcode value from the appropriate column 450*0b57cec5SDimitry Andric // of the table. 451*0b57cec5SDimitry Andric emitBinSearch(OS, TableSize); 452*0b57cec5SDimitry Andric 453*0b57cec5SDimitry Andric if (ValueCols.size() > 1) { 454*0b57cec5SDimitry Andric for (unsigned i = 0, e = ValueCols.size(); i < e; i++) { 455*0b57cec5SDimitry Andric ListInit *ColumnI = ValueCols[i]; 456*0b57cec5SDimitry Andric for (unsigned j = 0, ColSize = ColumnI->size(); j < ColSize; ++j) { 457*0b57cec5SDimitry Andric std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); 458*0b57cec5SDimitry Andric OS << " if (in" << ColName; 459*0b57cec5SDimitry Andric OS << " == "; 460*0b57cec5SDimitry Andric OS << ColName << "_" << ColumnI->getElement(j)->getAsUnquotedString(); 461*0b57cec5SDimitry Andric if (j < ColumnI->size() - 1) OS << " && "; 462*0b57cec5SDimitry Andric else OS << ")\n"; 463*0b57cec5SDimitry Andric } 464*0b57cec5SDimitry Andric OS << " return " << InstrMapDesc.getName(); 465*0b57cec5SDimitry Andric OS << "Table[mid]["<<i+1<<"];\n"; 466*0b57cec5SDimitry Andric } 467*0b57cec5SDimitry Andric OS << " return -1;"; 468*0b57cec5SDimitry Andric } 469*0b57cec5SDimitry Andric else 470*0b57cec5SDimitry Andric OS << " return " << InstrMapDesc.getName() << "Table[mid][1];\n"; 471*0b57cec5SDimitry Andric 472*0b57cec5SDimitry Andric OS <<"}\n\n"; 473*0b57cec5SDimitry Andric } 474*0b57cec5SDimitry Andric 475*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 476*0b57cec5SDimitry Andric // Emit relation tables and the functions to query them. 477*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 478*0b57cec5SDimitry Andric 479*0b57cec5SDimitry Andric void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) { 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric // Emit function name and the input parameters : mostly opcode value of the 482*0b57cec5SDimitry Andric // current instruction. However, if a table has multiple columns (more than 2 483*0b57cec5SDimitry Andric // since first column is used for the key instructions), then we also need 484*0b57cec5SDimitry Andric // to pass another input to indicate the column to be selected. 485*0b57cec5SDimitry Andric 486*0b57cec5SDimitry Andric ListInit *ColFields = InstrMapDesc.getColFields(); 487*0b57cec5SDimitry Andric const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); 488*0b57cec5SDimitry Andric OS << "// "<< InstrMapDesc.getName() << "\nLLVM_READONLY\n"; 489*0b57cec5SDimitry Andric OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode"; 490*0b57cec5SDimitry Andric if (ValueCols.size() > 1) { 491*0b57cec5SDimitry Andric for (Init *CF : ColFields->getValues()) { 492*0b57cec5SDimitry Andric std::string ColName = CF->getAsUnquotedString(); 493*0b57cec5SDimitry Andric OS << ", enum " << ColName << " in" << ColName << ") {\n"; 494*0b57cec5SDimitry Andric } 495*0b57cec5SDimitry Andric } else { OS << ") {\n"; } 496*0b57cec5SDimitry Andric 497*0b57cec5SDimitry Andric // Emit map table. 498*0b57cec5SDimitry Andric unsigned TableSize = emitBinSearchTable(OS); 499*0b57cec5SDimitry Andric 500*0b57cec5SDimitry Andric // Emit rest of the function body. 501*0b57cec5SDimitry Andric emitMapFuncBody(OS, TableSize); 502*0b57cec5SDimitry Andric } 503*0b57cec5SDimitry Andric 504*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 505*0b57cec5SDimitry Andric // Emit enums for the column fields across all the instruction maps. 506*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 507*0b57cec5SDimitry Andric 508*0b57cec5SDimitry Andric static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { 509*0b57cec5SDimitry Andric 510*0b57cec5SDimitry Andric std::vector<Record*> InstrMapVec; 511*0b57cec5SDimitry Andric InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); 512*0b57cec5SDimitry Andric std::map<std::string, std::vector<Init*> > ColFieldValueMap; 513*0b57cec5SDimitry Andric 514*0b57cec5SDimitry Andric // Iterate over all InstrMapping records and create a map between column 515*0b57cec5SDimitry Andric // fields and their possible values across all records. 516*0b57cec5SDimitry Andric for (Record *CurMap : InstrMapVec) { 517*0b57cec5SDimitry Andric ListInit *ColFields; 518*0b57cec5SDimitry Andric ColFields = CurMap->getValueAsListInit("ColFields"); 519*0b57cec5SDimitry Andric ListInit *List = CurMap->getValueAsListInit("ValueCols"); 520*0b57cec5SDimitry Andric std::vector<ListInit*> ValueCols; 521*0b57cec5SDimitry Andric unsigned ListSize = List->size(); 522*0b57cec5SDimitry Andric 523*0b57cec5SDimitry Andric for (unsigned j = 0; j < ListSize; j++) { 5248bcb0991SDimitry Andric auto *ListJ = cast<ListInit>(List->getElement(j)); 525*0b57cec5SDimitry Andric 526*0b57cec5SDimitry Andric if (ListJ->size() != ColFields->size()) 527*0b57cec5SDimitry Andric PrintFatalError("Record `" + CurMap->getName() + "', field " 528*0b57cec5SDimitry Andric "`ValueCols' entries don't match with the entries in 'ColFields' !"); 529*0b57cec5SDimitry Andric ValueCols.push_back(ListJ); 530*0b57cec5SDimitry Andric } 531*0b57cec5SDimitry Andric 532*0b57cec5SDimitry Andric for (unsigned j = 0, endCF = ColFields->size(); j < endCF; j++) { 533*0b57cec5SDimitry Andric for (unsigned k = 0; k < ListSize; k++){ 534*0b57cec5SDimitry Andric std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); 535*0b57cec5SDimitry Andric ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j)); 536*0b57cec5SDimitry Andric } 537*0b57cec5SDimitry Andric } 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric 540*0b57cec5SDimitry Andric for (auto &Entry : ColFieldValueMap) { 541*0b57cec5SDimitry Andric std::vector<Init*> FieldValues = Entry.second; 542*0b57cec5SDimitry Andric 543*0b57cec5SDimitry Andric // Delete duplicate entries from ColFieldValueMap 544*0b57cec5SDimitry Andric for (unsigned i = 0; i < FieldValues.size() - 1; i++) { 545*0b57cec5SDimitry Andric Init *CurVal = FieldValues[i]; 546*0b57cec5SDimitry Andric for (unsigned j = i+1; j < FieldValues.size(); j++) { 547*0b57cec5SDimitry Andric if (CurVal == FieldValues[j]) { 548*0b57cec5SDimitry Andric FieldValues.erase(FieldValues.begin()+j); 549*0b57cec5SDimitry Andric --j; 550*0b57cec5SDimitry Andric } 551*0b57cec5SDimitry Andric } 552*0b57cec5SDimitry Andric } 553*0b57cec5SDimitry Andric 554*0b57cec5SDimitry Andric // Emit enumerated values for the column fields. 555*0b57cec5SDimitry Andric OS << "enum " << Entry.first << " {\n"; 556*0b57cec5SDimitry Andric for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) { 557*0b57cec5SDimitry Andric OS << "\t" << Entry.first << "_" << FieldValues[i]->getAsUnquotedString(); 558*0b57cec5SDimitry Andric if (i != endFV - 1) 559*0b57cec5SDimitry Andric OS << ",\n"; 560*0b57cec5SDimitry Andric else 561*0b57cec5SDimitry Andric OS << "\n};\n\n"; 562*0b57cec5SDimitry Andric } 563*0b57cec5SDimitry Andric } 564*0b57cec5SDimitry Andric } 565*0b57cec5SDimitry Andric 566*0b57cec5SDimitry Andric namespace llvm { 567*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 568*0b57cec5SDimitry Andric // Parse 'InstrMapping' records and use the information to form relationship 569*0b57cec5SDimitry Andric // between instructions. These relations are emitted as a tables along with the 570*0b57cec5SDimitry Andric // functions to query them. 571*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 572*0b57cec5SDimitry Andric void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) { 573*0b57cec5SDimitry Andric CodeGenTarget Target(Records); 574*0b57cec5SDimitry Andric StringRef NameSpace = Target.getInstNamespace(); 575*0b57cec5SDimitry Andric std::vector<Record*> InstrMapVec; 576*0b57cec5SDimitry Andric InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); 577*0b57cec5SDimitry Andric 578*0b57cec5SDimitry Andric if (InstrMapVec.empty()) 579*0b57cec5SDimitry Andric return; 580*0b57cec5SDimitry Andric 581*0b57cec5SDimitry Andric OS << "#ifdef GET_INSTRMAP_INFO\n"; 582*0b57cec5SDimitry Andric OS << "#undef GET_INSTRMAP_INFO\n"; 583*0b57cec5SDimitry Andric OS << "namespace llvm {\n\n"; 584*0b57cec5SDimitry Andric OS << "namespace " << NameSpace << " {\n\n"; 585*0b57cec5SDimitry Andric 586*0b57cec5SDimitry Andric // Emit coulumn field names and their values as enums. 587*0b57cec5SDimitry Andric emitEnums(OS, Records); 588*0b57cec5SDimitry Andric 589*0b57cec5SDimitry Andric // Iterate over all instruction mapping records and construct relationship 590*0b57cec5SDimitry Andric // maps based on the information specified there. 591*0b57cec5SDimitry Andric // 592*0b57cec5SDimitry Andric for (Record *CurMap : InstrMapVec) { 593*0b57cec5SDimitry Andric MapTableEmitter IMap(Target, Records, CurMap); 594*0b57cec5SDimitry Andric 595*0b57cec5SDimitry Andric // Build RowInstrMap to group instructions based on their values for 596*0b57cec5SDimitry Andric // RowFields. In the process, also collect key instructions into 597*0b57cec5SDimitry Andric // KeyInstrVec. 598*0b57cec5SDimitry Andric IMap.buildRowInstrMap(); 599*0b57cec5SDimitry Andric 600*0b57cec5SDimitry Andric // Build MapTable to map key instructions with the corresponding column 601*0b57cec5SDimitry Andric // instructions. 602*0b57cec5SDimitry Andric IMap.buildMapTable(); 603*0b57cec5SDimitry Andric 604*0b57cec5SDimitry Andric // Emit map tables and the functions to query them. 605*0b57cec5SDimitry Andric IMap.emitTablesWithFunc(OS); 606*0b57cec5SDimitry Andric } 6078bcb0991SDimitry Andric OS << "} // end namespace " << NameSpace << "\n"; 6088bcb0991SDimitry Andric OS << "} // end namespace llvm\n"; 609*0b57cec5SDimitry Andric OS << "#endif // GET_INSTRMAP_INFO\n\n"; 610*0b57cec5SDimitry Andric } 611*0b57cec5SDimitry Andric 612*0b57cec5SDimitry Andric } // End llvm namespace 613