1 //===- RISCVCompressInstEmitter.cpp - Generator for RISCV Compression -===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 // RISCVCompressInstEmitter implements a tablegen-driven CompressPat based 9 // RISCV Instruction Compression mechanism. 10 // 11 //===--------------------------------------------------------------===// 12 // 13 // RISCVCompressInstEmitter implements a tablegen-driven CompressPat Instruction 14 // Compression mechanism for generating RISCV compressed instructions 15 // (C ISA Extension) from the expanded instruction form. 16 17 // This tablegen backend processes CompressPat declarations in a 18 // td file and generates all the required checks to validate the pattern 19 // declarations; validate the input and output operands to generate the correct 20 // compressed instructions. The checks include validating different types of 21 // operands; register operands, immediate operands, fixed register and fixed 22 // immediate inputs. 23 // 24 // Example: 25 // class CompressPat<dag input, dag output> { 26 // dag Input = input; 27 // dag Output = output; 28 // list<Predicate> Predicates = []; 29 // } 30 // 31 // let Predicates = [HasStdExtC] in { 32 // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2), 33 // (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; 34 // } 35 // 36 // The result is an auto-generated header file 37 // 'RISCVGenCompressInstEmitter.inc' which exports two functions for 38 // compressing/uncompressing MCInst instructions, plus 39 // some helper functions: 40 // 41 // bool compressInst(MCInst& OutInst, const MCInst &MI, 42 // const MCSubtargetInfo &STI, 43 // MCContext &Context); 44 // 45 // bool uncompressInst(MCInst& OutInst, const MCInst &MI, 46 // const MCRegisterInfo &MRI, 47 // const MCSubtargetInfo &STI); 48 // 49 // The clients that include this auto-generated header file and 50 // invoke these functions can compress an instruction before emitting 51 // it in the target-specific ASM or ELF streamer or can uncompress 52 // an instruction before printing it when the expanded instruction 53 // format aliases is favored. 54 55 //===----------------------------------------------------------------------===// 56 57 #include "CodeGenInstruction.h" 58 #include "CodeGenTarget.h" 59 #include "llvm/ADT/IndexedMap.h" 60 #include "llvm/ADT/SmallVector.h" 61 #include "llvm/ADT/StringExtras.h" 62 #include "llvm/ADT/StringMap.h" 63 #include "llvm/Support/Debug.h" 64 #include "llvm/Support/ErrorHandling.h" 65 #include "llvm/TableGen/Error.h" 66 #include "llvm/TableGen/Record.h" 67 #include "llvm/TableGen/TableGenBackend.h" 68 #include <vector> 69 using namespace llvm; 70 71 #define DEBUG_TYPE "compress-inst-emitter" 72 73 namespace { 74 class RISCVCompressInstEmitter { 75 struct OpData { 76 enum MapKind { Operand, Imm, Reg }; 77 MapKind Kind; 78 union { 79 unsigned Operand; // Operand number mapped to. 80 uint64_t Imm; // Integer immediate value. 81 Record *Reg; // Physical register. 82 } Data; 83 int TiedOpIdx = -1; // Tied operand index within the instruction. 84 }; 85 struct CompressPat { 86 CodeGenInstruction Source; // The source instruction definition. 87 CodeGenInstruction Dest; // The destination instruction to transform to. 88 std::vector<Record *> 89 PatReqFeatures; // Required target features to enable pattern. 90 IndexedMap<OpData> 91 SourceOperandMap; // Maps operands in the Source Instruction to 92 // the corresponding Dest instruction operand. 93 IndexedMap<OpData> 94 DestOperandMap; // Maps operands in the Dest Instruction 95 // to the corresponding Source instruction operand. 96 CompressPat(CodeGenInstruction &S, CodeGenInstruction &D, 97 std::vector<Record *> RF, IndexedMap<OpData> &SourceMap, 98 IndexedMap<OpData> &DestMap) 99 : Source(S), Dest(D), PatReqFeatures(RF), SourceOperandMap(SourceMap), 100 DestOperandMap(DestMap) {} 101 }; 102 103 RecordKeeper &Records; 104 CodeGenTarget Target; 105 SmallVector<CompressPat, 4> CompressPatterns; 106 107 void addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Inst, 108 IndexedMap<OpData> &OperandMap, bool IsSourceInst); 109 void evaluateCompressPat(Record *Compress); 110 void emitCompressInstEmitter(raw_ostream &o, bool Compress); 111 bool validateTypes(Record *SubType, Record *Type, bool IsSourceInst); 112 bool validateRegister(Record *Reg, Record *RegClass); 113 void createDagOperandMapping(Record *Rec, StringMap<unsigned> &SourceOperands, 114 StringMap<unsigned> &DestOperands, 115 DagInit *SourceDag, DagInit *DestDag, 116 IndexedMap<OpData> &SourceOperandMap); 117 118 void createInstOperandMapping(Record *Rec, DagInit *SourceDag, 119 DagInit *DestDag, 120 IndexedMap<OpData> &SourceOperandMap, 121 IndexedMap<OpData> &DestOperandMap, 122 StringMap<unsigned> &SourceOperands, 123 CodeGenInstruction &DestInst); 124 125 public: 126 RISCVCompressInstEmitter(RecordKeeper &R) : Records(R), Target(R) {} 127 128 void run(raw_ostream &o); 129 }; 130 } // End anonymous namespace. 131 132 bool RISCVCompressInstEmitter::validateRegister(Record *Reg, Record *RegClass) { 133 assert(Reg->isSubClassOf("Register") && "Reg record should be a Register\n"); 134 assert(RegClass->isSubClassOf("RegisterClass") && "RegClass record should be" 135 " a RegisterClass\n"); 136 CodeGenRegisterClass RC = Target.getRegisterClass(RegClass); 137 const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower()); 138 assert((R != nullptr) && 139 ("Register" + Reg->getName().str() + " not defined!!\n").c_str()); 140 return RC.contains(R); 141 } 142 143 bool RISCVCompressInstEmitter::validateTypes(Record *DagOpType, 144 Record *InstOpType, 145 bool IsSourceInst) { 146 if (DagOpType == InstOpType) 147 return true; 148 // Only source instruction operands are allowed to not match Input Dag 149 // operands. 150 if (!IsSourceInst) 151 return false; 152 153 if (DagOpType->isSubClassOf("RegisterClass") && 154 InstOpType->isSubClassOf("RegisterClass")) { 155 CodeGenRegisterClass RC = Target.getRegisterClass(InstOpType); 156 CodeGenRegisterClass SubRC = Target.getRegisterClass(DagOpType); 157 return RC.hasSubClass(&SubRC); 158 } 159 160 // At this point either or both types are not registers, reject the pattern. 161 if (DagOpType->isSubClassOf("RegisterClass") || 162 InstOpType->isSubClassOf("RegisterClass")) 163 return false; 164 165 // Let further validation happen when compress()/uncompress() functions are 166 // invoked. 167 LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output") 168 << " Dag Operand Type: '" << DagOpType->getName() 169 << "' and " 170 << "Instruction Operand Type: '" << InstOpType->getName() 171 << "' can't be checked at pattern validation time!\n"); 172 return true; 173 } 174 175 /// The patterns in the Dag contain different types of operands: 176 /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate 177 /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function 178 /// maps Dag operands to its corresponding instruction operands. For register 179 /// operands and fixed registers it expects the Dag operand type to be contained 180 /// in the instantiated instruction operand type. For immediate operands and 181 /// immediates no validation checks are enforced at pattern validation time. 182 void RISCVCompressInstEmitter::addDagOperandMapping( 183 Record *Rec, DagInit *Dag, CodeGenInstruction &Inst, 184 IndexedMap<OpData> &OperandMap, bool IsSourceInst) { 185 // TiedCount keeps track of the number of operands skipped in Inst 186 // operands list to get to the corresponding Dag operand. This is 187 // necessary because the number of operands in Inst might be greater 188 // than number of operands in the Dag due to how tied operands 189 // are represented. 190 unsigned TiedCount = 0; 191 for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { 192 int TiedOpIdx = Inst.Operands[i].getTiedRegister(); 193 if (-1 != TiedOpIdx) { 194 // Set the entry in OperandMap for the tied operand we're skipping. 195 OperandMap[i].Kind = OperandMap[TiedOpIdx].Kind; 196 OperandMap[i].Data = OperandMap[TiedOpIdx].Data; 197 TiedCount++; 198 continue; 199 } 200 if (DefInit *DI = dyn_cast<DefInit>(Dag->getArg(i - TiedCount))) { 201 if (DI->getDef()->isSubClassOf("Register")) { 202 // Check if the fixed register belongs to the Register class. 203 if (!validateRegister(DI->getDef(), Inst.Operands[i].Rec)) 204 PrintFatalError(Rec->getLoc(), 205 "Error in Dag '" + Dag->getAsString() + 206 "'Register: '" + DI->getDef()->getName() + 207 "' is not in register class '" + 208 Inst.Operands[i].Rec->getName() + "'"); 209 OperandMap[i].Kind = OpData::Reg; 210 OperandMap[i].Data.Reg = DI->getDef(); 211 continue; 212 } 213 // Validate that Dag operand type matches the type defined in the 214 // corresponding instruction. Operands in the input Dag pattern are 215 // allowed to be a subclass of the type specified in corresponding 216 // instruction operand instead of being an exact match. 217 if (!validateTypes(DI->getDef(), Inst.Operands[i].Rec, IsSourceInst)) 218 PrintFatalError(Rec->getLoc(), 219 "Error in Dag '" + Dag->getAsString() + "'. Operand '" + 220 Dag->getArgNameStr(i - TiedCount) + "' has type '" + 221 DI->getDef()->getName() + 222 "' which does not match the type '" + 223 Inst.Operands[i].Rec->getName() + 224 "' in the corresponding instruction operand!"); 225 226 OperandMap[i].Kind = OpData::Operand; 227 } else if (IntInit *II = dyn_cast<IntInit>(Dag->getArg(i - TiedCount))) { 228 // Validate that corresponding instruction operand expects an immediate. 229 if (Inst.Operands[i].Rec->isSubClassOf("RegisterClass")) 230 PrintFatalError( 231 Rec->getLoc(), 232 ("Error in Dag '" + Dag->getAsString() + "' Found immediate: '" + 233 II->getAsString() + 234 "' but corresponding instruction operand expected a register!")); 235 // No pattern validation check possible for values of fixed immediate. 236 OperandMap[i].Kind = OpData::Imm; 237 OperandMap[i].Data.Imm = II->getValue(); 238 LLVM_DEBUG( 239 dbgs() << " Found immediate '" << II->getValue() << "' at " 240 << (IsSourceInst ? "input " : "output ") 241 << "Dag. No validation time check possible for values of " 242 "fixed immediate.\n"); 243 } else 244 llvm_unreachable("Unhandled CompressPat argument type!"); 245 } 246 } 247 248 // Verify the Dag operand count is enough to build an instruction. 249 static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag, 250 bool IsSource) { 251 if (Dag->getNumArgs() == Inst.Operands.size()) 252 return true; 253 // Source instructions are non compressed instructions and don't have tied 254 // operands. 255 if (IsSource) 256 PrintFatalError("Input operands for Inst '" + Inst.TheDef->getName() + 257 "' and input Dag operand count mismatch"); 258 // The Dag can't have more arguments than the Instruction. 259 if (Dag->getNumArgs() > Inst.Operands.size()) 260 PrintFatalError("Inst '" + Inst.TheDef->getName() + 261 "' and Dag operand count mismatch"); 262 263 // The Instruction might have tied operands so the Dag might have 264 // a fewer operand count. 265 unsigned RealCount = Inst.Operands.size(); 266 for (unsigned i = 0; i < Inst.Operands.size(); i++) 267 if (Inst.Operands[i].getTiedRegister() != -1) 268 --RealCount; 269 270 if (Dag->getNumArgs() != RealCount) 271 PrintFatalError("Inst '" + Inst.TheDef->getName() + 272 "' and Dag operand count mismatch"); 273 return true; 274 } 275 276 static bool validateArgsTypes(Init *Arg1, Init *Arg2) { 277 DefInit *Type1 = dyn_cast<DefInit>(Arg1); 278 DefInit *Type2 = dyn_cast<DefInit>(Arg2); 279 assert(Type1 && ("Arg1 type not found\n")); 280 assert(Type2 && ("Arg2 type not found\n")); 281 return Type1->getDef() == Type2->getDef(); 282 } 283 284 // Creates a mapping between the operand name in the Dag (e.g. $rs1) and 285 // its index in the list of Dag operands and checks that operands with the same 286 // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the 287 // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied) 288 // same Dag we use the last occurrence for indexing. 289 void RISCVCompressInstEmitter::createDagOperandMapping( 290 Record *Rec, StringMap<unsigned> &SourceOperands, 291 StringMap<unsigned> &DestOperands, DagInit *SourceDag, DagInit *DestDag, 292 IndexedMap<OpData> &SourceOperandMap) { 293 for (unsigned i = 0; i < DestDag->getNumArgs(); ++i) { 294 // Skip fixed immediates and registers, they were handled in 295 // addDagOperandMapping. 296 if ("" == DestDag->getArgNameStr(i)) 297 continue; 298 DestOperands[DestDag->getArgNameStr(i)] = i; 299 } 300 301 for (unsigned i = 0; i < SourceDag->getNumArgs(); ++i) { 302 // Skip fixed immediates and registers, they were handled in 303 // addDagOperandMapping. 304 if ("" == SourceDag->getArgNameStr(i)) 305 continue; 306 307 StringMap<unsigned>::iterator it = 308 SourceOperands.find(SourceDag->getArgNameStr(i)); 309 if (it != SourceOperands.end()) { 310 // Operand sharing the same name in the Dag should be mapped as tied. 311 SourceOperandMap[i].TiedOpIdx = it->getValue(); 312 if (!validateArgsTypes(SourceDag->getArg(it->getValue()), 313 SourceDag->getArg(i))) 314 PrintFatalError(Rec->getLoc(), 315 "Input Operand '" + SourceDag->getArgNameStr(i) + 316 "' has a mismatched tied operand!\n"); 317 } 318 it = DestOperands.find(SourceDag->getArgNameStr(i)); 319 if (it == DestOperands.end()) 320 PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(i) + 321 " defined in Input Dag but not used in" 322 " Output Dag!\n"); 323 // Input Dag operand types must match output Dag operand type. 324 if (!validateArgsTypes(DestDag->getArg(it->getValue()), 325 SourceDag->getArg(i))) 326 PrintFatalError(Rec->getLoc(), "Type mismatch between Input and " 327 "Output Dag operand '" + 328 SourceDag->getArgNameStr(i) + "'!"); 329 SourceOperands[SourceDag->getArgNameStr(i)] = i; 330 } 331 } 332 333 /// Map operand names in the Dag to their index in both corresponding input and 334 /// output instructions. Validate that operands defined in the input are 335 /// used in the output pattern while populating the maps. 336 void RISCVCompressInstEmitter::createInstOperandMapping( 337 Record *Rec, DagInit *SourceDag, DagInit *DestDag, 338 IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap, 339 StringMap<unsigned> &SourceOperands, CodeGenInstruction &DestInst) { 340 // TiedCount keeps track of the number of operands skipped in Inst 341 // operands list to get to the corresponding Dag operand. 342 unsigned TiedCount = 0; 343 LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n"); 344 for (unsigned i = 0, e = DestInst.Operands.size(); i != e; ++i) { 345 int TiedInstOpIdx = DestInst.Operands[i].getTiedRegister(); 346 if (TiedInstOpIdx != -1) { 347 ++TiedCount; 348 DestOperandMap[i].Data = DestOperandMap[TiedInstOpIdx].Data; 349 DestOperandMap[i].Kind = DestOperandMap[TiedInstOpIdx].Kind; 350 if (DestOperandMap[i].Kind == OpData::Operand) 351 // No need to fill the SourceOperandMap here since it was mapped to 352 // destination operand 'TiedInstOpIdx' in a previous iteration. 353 LLVM_DEBUG(dbgs() << " " << DestOperandMap[i].Data.Operand 354 << " ====> " << i 355 << " Dest operand tied with operand '" 356 << TiedInstOpIdx << "'\n"); 357 continue; 358 } 359 // Skip fixed immediates and registers, they were handled in 360 // addDagOperandMapping. 361 if (DestOperandMap[i].Kind != OpData::Operand) 362 continue; 363 364 unsigned DagArgIdx = i - TiedCount; 365 StringMap<unsigned>::iterator SourceOp = 366 SourceOperands.find(DestDag->getArgNameStr(DagArgIdx)); 367 if (SourceOp == SourceOperands.end()) 368 PrintFatalError(Rec->getLoc(), 369 "Output Dag operand '" + 370 DestDag->getArgNameStr(DagArgIdx) + 371 "' has no matching input Dag operand."); 372 373 assert(DestDag->getArgNameStr(DagArgIdx) == 374 SourceDag->getArgNameStr(SourceOp->getValue()) && 375 "Incorrect operand mapping detected!\n"); 376 DestOperandMap[i].Data.Operand = SourceOp->getValue(); 377 SourceOperandMap[SourceOp->getValue()].Data.Operand = i; 378 LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ====> " << i 379 << "\n"); 380 } 381 } 382 383 /// Validates the CompressPattern and create operand mapping. 384 /// These are the checks to validate a CompressPat pattern declarations. 385 /// Error out with message under these conditions: 386 /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a 387 /// compressed instruction. 388 /// - Operands in Dag Input must be all used in Dag Output. 389 /// Register Operand type in Dag Input Type must be contained in the 390 /// corresponding Source Instruction type. 391 /// - Register Operand type in Dag Input must be the same as in Dag Ouput. 392 /// - Register Operand type in Dag Output must be the same as the 393 /// corresponding Destination Inst type. 394 /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput. 395 /// - Immediate Operand type in Dag Ouput must be the same as the corresponding 396 /// Destination Instruction type. 397 /// - Fixed register must be contained in the corresponding Source Instruction 398 /// type. 399 /// - Fixed register must be contained in the corresponding Destination 400 /// Instruction type. Warning message printed under these conditions: 401 /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time 402 /// and generate warning. 403 /// - Immediate operand type in Dag Input differs from the corresponding Source 404 /// Instruction type and generate a warning. 405 void RISCVCompressInstEmitter::evaluateCompressPat(Record *Rec) { 406 // Validate input Dag operands. 407 DagInit *SourceDag = Rec->getValueAsDag("Input"); 408 assert(SourceDag && "Missing 'Input' in compress pattern!"); 409 LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n"); 410 411 DefInit *OpDef = dyn_cast<DefInit>(SourceDag->getOperator()); 412 if (!OpDef) 413 PrintFatalError(Rec->getLoc(), 414 Rec->getName() + " has unexpected operator type!"); 415 // Checking we are transforming from compressed to uncompressed instructions. 416 Record *Operator = OpDef->getDef(); 417 if (!Operator->isSubClassOf("RVInst")) 418 PrintFatalError(Rec->getLoc(), "Input instruction '" + Operator->getName() + 419 "' is not a 32 bit wide instruction!"); 420 CodeGenInstruction SourceInst(Operator); 421 verifyDagOpCount(SourceInst, SourceDag, true); 422 423 // Validate output Dag operands. 424 DagInit *DestDag = Rec->getValueAsDag("Output"); 425 assert(DestDag && "Missing 'Output' in compress pattern!"); 426 LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n"); 427 428 DefInit *DestOpDef = dyn_cast<DefInit>(DestDag->getOperator()); 429 if (!DestOpDef) 430 PrintFatalError(Rec->getLoc(), 431 Rec->getName() + " has unexpected operator type!"); 432 433 Record *DestOperator = DestOpDef->getDef(); 434 if (!DestOperator->isSubClassOf("RVInst16")) 435 PrintFatalError(Rec->getLoc(), "Output instruction '" + 436 DestOperator->getName() + 437 "' is not a 16 bit wide instruction!"); 438 CodeGenInstruction DestInst(DestOperator); 439 verifyDagOpCount(DestInst, DestDag, false); 440 441 // Fill the mapping from the source to destination instructions. 442 443 IndexedMap<OpData> SourceOperandMap; 444 SourceOperandMap.grow(SourceInst.Operands.size()); 445 // Create a mapping between source Dag operands and source Inst operands. 446 addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap, 447 /*IsSourceInst*/ true); 448 449 IndexedMap<OpData> DestOperandMap; 450 DestOperandMap.grow(DestInst.Operands.size()); 451 // Create a mapping between destination Dag operands and destination Inst 452 // operands. 453 addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap, 454 /*IsSourceInst*/ false); 455 456 StringMap<unsigned> SourceOperands; 457 StringMap<unsigned> DestOperands; 458 createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag, 459 SourceOperandMap); 460 // Create operand mapping between the source and destination instructions. 461 createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap, 462 DestOperandMap, SourceOperands, DestInst); 463 464 // Get the target features for the CompressPat. 465 std::vector<Record *> PatReqFeatures; 466 std::vector<Record *> RF = Rec->getValueAsListOfDefs("Predicates"); 467 copy_if(RF, std::back_inserter(PatReqFeatures), [](Record *R) { 468 return R->getValueAsBit("AssemblerMatcherPredicate"); 469 }); 470 471 CompressPatterns.push_back(CompressPat(SourceInst, DestInst, PatReqFeatures, 472 SourceOperandMap, DestOperandMap)); 473 } 474 475 static void getReqFeatures(std::map<StringRef, int> &FeaturesMap, 476 const std::vector<Record *> &ReqFeatures) { 477 for (auto &R : ReqFeatures) { 478 StringRef AsmCondString = R->getValueAsString("AssemblerCondString"); 479 480 // AsmCondString has syntax [!]F(,[!]F)* 481 SmallVector<StringRef, 4> Ops; 482 SplitString(AsmCondString, Ops, ","); 483 assert(!Ops.empty() && "AssemblerCondString cannot be empty"); 484 485 for (auto &Op : Ops) { 486 assert(!Op.empty() && "Empty operator"); 487 if (FeaturesMap.find(Op) == FeaturesMap.end()) 488 FeaturesMap[Op] = FeaturesMap.size(); 489 } 490 } 491 } 492 493 unsigned getMCOpPredicate(DenseMap<const Record *, unsigned> &MCOpPredicateMap, 494 std::vector<const Record *> &MCOpPredicates, 495 Record *Rec) { 496 unsigned Entry = MCOpPredicateMap[Rec]; 497 if (Entry) 498 return Entry; 499 500 if (!Rec->isValueUnset("MCOperandPredicate")) { 501 MCOpPredicates.push_back(Rec); 502 Entry = MCOpPredicates.size(); 503 MCOpPredicateMap[Rec] = Entry; 504 return Entry; 505 } 506 507 PrintFatalError(Rec->getLoc(), 508 "No MCOperandPredicate on this operand at all: " + 509 Rec->getName().str() + "'"); 510 return 0; 511 } 512 513 static std::string mergeCondAndCode(raw_string_ostream &CondStream, 514 raw_string_ostream &CodeStream) { 515 std::string S; 516 raw_string_ostream CombinedStream(S); 517 CombinedStream.indent(4) 518 << "if (" 519 << CondStream.str().substr( 520 6, CondStream.str().length() - 521 10) // remove first indentation and last '&&'. 522 << ") {\n"; 523 CombinedStream << CodeStream.str(); 524 CombinedStream.indent(4) << " return true;\n"; 525 CombinedStream.indent(4) << "} // if\n"; 526 return CombinedStream.str(); 527 } 528 529 void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, 530 bool Compress) { 531 Record *AsmWriter = Target.getAsmWriter(); 532 if (!AsmWriter->getValueAsInt("PassSubtarget")) 533 PrintFatalError("'PassSubtarget' is false. SubTargetInfo object is needed " 534 "for target features.\n"); 535 536 std::string Namespace = Target.getName(); 537 538 // Sort entries in CompressPatterns to handle instructions that can have more 539 // than one candidate for compression\uncompression, e.g ADD can be 540 // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the 541 // source and destination are flipped and the sort key needs to change 542 // accordingly. 543 std::stable_sort(CompressPatterns.begin(), CompressPatterns.end(), 544 [Compress](const CompressPat &LHS, const CompressPat &RHS) { 545 if (Compress) 546 return (LHS.Source.TheDef->getName().str() < 547 RHS.Source.TheDef->getName().str()); 548 else 549 return (LHS.Dest.TheDef->getName().str() < 550 RHS.Dest.TheDef->getName().str()); 551 }); 552 553 // A list of MCOperandPredicates for all operands in use, and the reverse map. 554 std::vector<const Record *> MCOpPredicates; 555 DenseMap<const Record *, unsigned> MCOpPredicateMap; 556 557 std::string F; 558 std::string FH; 559 raw_string_ostream Func(F); 560 raw_string_ostream FuncH(FH); 561 bool NeedMRI = false; 562 563 if (Compress) 564 o << "\n#ifdef GEN_COMPRESS_INSTR\n" 565 << "#undef GEN_COMPRESS_INSTR\n\n"; 566 else 567 o << "\n#ifdef GEN_UNCOMPRESS_INSTR\n" 568 << "#undef GEN_UNCOMPRESS_INSTR\n\n"; 569 570 if (Compress) { 571 FuncH << "static bool compressInst(MCInst& OutInst,\n"; 572 FuncH.indent(25) << "const MCInst &MI,\n"; 573 FuncH.indent(25) << "const MCSubtargetInfo &STI,\n"; 574 FuncH.indent(25) << "MCContext &Context) {\n"; 575 } else { 576 FuncH << "static bool uncompressInst(MCInst& OutInst,\n"; 577 FuncH.indent(27) << "const MCInst &MI,\n"; 578 FuncH.indent(27) << "const MCRegisterInfo &MRI,\n"; 579 FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n"; 580 } 581 582 if (CompressPatterns.empty()) { 583 o << FuncH.str(); 584 o.indent(2) << "return false;\n}\n"; 585 if (Compress) 586 o << "\n#endif //GEN_COMPRESS_INSTR\n"; 587 else 588 o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 589 return; 590 } 591 592 std::string CaseString(""); 593 raw_string_ostream CaseStream(CaseString); 594 std::string PrevOp(""); 595 std::string CurOp(""); 596 CaseStream << " switch (MI.getOpcode()) {\n"; 597 CaseStream << " default: return false;\n"; 598 599 for (auto &CompressPat : CompressPatterns) { 600 std::string CondString; 601 std::string CodeString; 602 raw_string_ostream CondStream(CondString); 603 raw_string_ostream CodeStream(CodeString); 604 CodeGenInstruction &Source = 605 Compress ? CompressPat.Source : CompressPat.Dest; 606 CodeGenInstruction &Dest = Compress ? CompressPat.Dest : CompressPat.Source; 607 IndexedMap<OpData> SourceOperandMap = 608 Compress ? CompressPat.SourceOperandMap : CompressPat.DestOperandMap; 609 IndexedMap<OpData> &DestOperandMap = 610 Compress ? CompressPat.DestOperandMap : CompressPat.SourceOperandMap; 611 612 CurOp = Source.TheDef->getName().str(); 613 // Check current and previous opcode to decide to continue or end a case. 614 if (CurOp != PrevOp) { 615 if (PrevOp != "") 616 CaseStream.indent(6) << "break;\n } // case " + PrevOp + "\n"; 617 CaseStream.indent(4) << "case " + Namespace + "::" + CurOp + ": {\n"; 618 } 619 620 std::map<StringRef, int> FeaturesMap; 621 // Add CompressPat required features. 622 getReqFeatures(FeaturesMap, CompressPat.PatReqFeatures); 623 624 // Add Dest instruction required features. 625 std::vector<Record *> ReqFeatures; 626 std::vector<Record *> RF = Dest.TheDef->getValueAsListOfDefs("Predicates"); 627 copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) { 628 return R->getValueAsBit("AssemblerMatcherPredicate"); 629 }); 630 getReqFeatures(FeaturesMap, ReqFeatures); 631 632 // Emit checks for all required features. 633 for (auto &F : FeaturesMap) { 634 StringRef Op = F.first; 635 if (Op[0] == '!') 636 CondStream.indent(6) << ("!STI.getFeatureBits()[" + Namespace + 637 "::" + Op.substr(1) + "]") 638 .str() + 639 " &&\n"; 640 else 641 CondStream.indent(6) 642 << ("STI.getFeatureBits()[" + Namespace + "::" + Op + "]").str() + 643 " &&\n"; 644 } 645 646 // Start Source Inst operands validation. 647 unsigned OpNo = 0; 648 for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) { 649 if (SourceOperandMap[OpNo].TiedOpIdx != -1) { 650 if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass")) 651 CondStream.indent(6) 652 << "(MI.getOperand(" 653 << std::to_string(OpNo) + ").getReg() == MI.getOperand(" 654 << std::to_string(SourceOperandMap[OpNo].TiedOpIdx) 655 << ").getReg()) &&\n"; 656 else 657 PrintFatalError("Unexpected tied operand types!\n"); 658 } 659 // Check for fixed immediates\registers in the source instruction. 660 switch (SourceOperandMap[OpNo].Kind) { 661 case OpData::Operand: 662 // We don't need to do anything for source instruction operand checks. 663 break; 664 case OpData::Imm: 665 CondStream.indent(6) 666 << "(MI.getOperand(" + std::to_string(OpNo) + ").isImm()) &&\n" + 667 " (MI.getOperand(" + std::to_string(OpNo) + 668 ").getImm() == " + 669 std::to_string(SourceOperandMap[OpNo].Data.Imm) + ") &&\n"; 670 break; 671 case OpData::Reg: { 672 Record *Reg = SourceOperandMap[OpNo].Data.Reg; 673 CondStream.indent(6) << "(MI.getOperand(" + std::to_string(OpNo) + 674 ").getReg() == " + Namespace + 675 "::" + Reg->getName().str() + ") &&\n"; 676 break; 677 } 678 } 679 } 680 CodeStream.indent(6) << "// " + Dest.AsmString + "\n"; 681 CodeStream.indent(6) << "OutInst.setOpcode(" + Namespace + 682 "::" + Dest.TheDef->getName().str() + ");\n"; 683 OpNo = 0; 684 for (const auto &DestOperand : Dest.Operands) { 685 CodeStream.indent(6) << "// Operand: " + DestOperand.Name + "\n"; 686 switch (DestOperandMap[OpNo].Kind) { 687 case OpData::Operand: { 688 unsigned OpIdx = DestOperandMap[OpNo].Data.Operand; 689 // Check that the operand in the Source instruction fits 690 // the type for the Dest instruction. 691 if (DestOperand.Rec->isSubClassOf("RegisterClass")) { 692 NeedMRI = true; 693 // This is a register operand. Check the register class. 694 // Don't check register class if this is a tied operand, it was done 695 // for the operand its tied to. 696 if (DestOperand.getTiedRegister() == -1) 697 CondStream.indent(6) 698 << "(MRI.getRegClass(" + Namespace + 699 "::" + DestOperand.Rec->getName().str() + 700 "RegClassID).contains(" + "MI.getOperand(" + 701 std::to_string(OpIdx) + ").getReg())) &&\n"; 702 703 CodeStream.indent(6) << "OutInst.addOperand(MI.getOperand(" + 704 std::to_string(OpIdx) + "));\n"; 705 } else { 706 // Handling immediate operands. 707 unsigned Entry = getMCOpPredicate(MCOpPredicateMap, MCOpPredicates, 708 DestOperand.Rec); 709 CondStream.indent(6) << Namespace + "ValidateMCOperand(" + 710 "MI.getOperand(" + std::to_string(OpIdx) + 711 "), STI, " + std::to_string(Entry) + 712 ") &&\n"; 713 CodeStream.indent(6) << "OutInst.addOperand(MI.getOperand(" + 714 std::to_string(OpIdx) + "));\n"; 715 } 716 break; 717 } 718 case OpData::Imm: { 719 unsigned Entry = 720 getMCOpPredicate(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec); 721 CondStream.indent(6) 722 << Namespace + "ValidateMCOperand(" + "MCOperand::createImm(" + 723 std::to_string(DestOperandMap[OpNo].Data.Imm) + "), STI, " + 724 std::to_string(Entry) + ") &&\n"; 725 CodeStream.indent(6) 726 << "OutInst.addOperand(MCOperand::createImm(" + 727 std::to_string(DestOperandMap[OpNo].Data.Imm) + "));\n"; 728 } break; 729 case OpData::Reg: { 730 // Fixed register has been validated at pattern validation time. 731 Record *Reg = DestOperandMap[OpNo].Data.Reg; 732 CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createReg(" + 733 Namespace + "::" + Reg->getName().str() + 734 "));\n"; 735 } break; 736 } 737 ++OpNo; 738 } 739 CaseStream << mergeCondAndCode(CondStream, CodeStream); 740 PrevOp = CurOp; 741 } 742 Func << CaseStream.str() << "\n"; 743 // Close brace for the last case. 744 Func.indent(4) << "} // case " + CurOp + "\n"; 745 Func.indent(2) << "} // switch\n"; 746 Func.indent(2) << "return false;\n}\n"; 747 748 if (!MCOpPredicates.empty()) { 749 o << "static bool " << Namespace 750 << "ValidateMCOperand(const MCOperand &MCOp,\n" 751 << " const MCSubtargetInfo &STI,\n" 752 << " unsigned PredicateIndex) {\n" 753 << " switch (PredicateIndex) {\n" 754 << " default:\n" 755 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" 756 << " break;\n"; 757 758 for (unsigned i = 0; i < MCOpPredicates.size(); ++i) { 759 Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate"); 760 if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) 761 o << " case " << i + 1 << ": {\n" 762 << " // " << MCOpPredicates[i]->getName().str() << SI->getValue() 763 << "\n" 764 << " }\n"; 765 else 766 llvm_unreachable("Unexpected MCOperandPredicate field!"); 767 } 768 o << " }\n" 769 << "}\n\n"; 770 } 771 772 o << FuncH.str(); 773 if (NeedMRI && Compress) 774 o.indent(2) << "const MCRegisterInfo &MRI = *Context.getRegisterInfo();\n"; 775 o << Func.str(); 776 777 if (Compress) 778 o << "\n#endif //GEN_COMPRESS_INSTR\n"; 779 else 780 o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 781 } 782 783 void RISCVCompressInstEmitter::run(raw_ostream &o) { 784 Record *CompressClass = Records.getClass("CompressPat"); 785 assert(CompressClass && "Compress class definition missing!"); 786 std::vector<Record *> Insts; 787 for (const auto &D : Records.getDefs()) { 788 if (D.second->isSubClassOf(CompressClass)) 789 Insts.push_back(D.second.get()); 790 } 791 792 // Process the CompressPat definitions, validating them as we do so. 793 for (unsigned i = 0, e = Insts.size(); i != e; ++i) 794 evaluateCompressPat(Insts[i]); 795 796 // Emit file header. 797 emitSourceFileHeader("Compress instruction Source Fragment", o); 798 // Generate compressInst() function. 799 emitCompressInstEmitter(o, true); 800 // Generate uncompressInst() function. 801 emitCompressInstEmitter(o, false); 802 } 803 804 namespace llvm { 805 806 void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS) { 807 RISCVCompressInstEmitter(RK).run(OS); 808 } 809 810 } // namespace llvm 811