1 //===- RISCVCompressInstEmitter.cpp - Generator for RISCV Compression -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 // RISCVCompressInstEmitter implements a tablegen-driven CompressPat based 8 // RISCV Instruction Compression mechanism. 9 // 10 //===--------------------------------------------------------------===// 11 // 12 // RISCVCompressInstEmitter implements a tablegen-driven CompressPat Instruction 13 // Compression mechanism for generating RISCV compressed instructions 14 // (C ISA Extension) from the expanded instruction form. 15 16 // This tablegen backend processes CompressPat declarations in a 17 // td file and generates all the required checks to validate the pattern 18 // declarations; validate the input and output operands to generate the correct 19 // compressed instructions. The checks include validating different types of 20 // operands; register operands, immediate operands, fixed register and fixed 21 // immediate inputs. 22 // 23 // Example: 24 // class CompressPat<dag input, dag output> { 25 // dag Input = input; 26 // dag Output = output; 27 // list<Predicate> Predicates = []; 28 // } 29 // 30 // let Predicates = [HasStdExtC] in { 31 // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2), 32 // (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; 33 // } 34 // 35 // The result is an auto-generated header file 36 // 'RISCVGenCompressInstEmitter.inc' which exports two functions for 37 // compressing/uncompressing MCInst instructions, plus 38 // some helper functions: 39 // 40 // bool compressInst(MCInst& OutInst, const MCInst &MI, 41 // const MCSubtargetInfo &STI, 42 // MCContext &Context); 43 // 44 // bool uncompressInst(MCInst& OutInst, const MCInst &MI, 45 // const MCRegisterInfo &MRI, 46 // const MCSubtargetInfo &STI); 47 // 48 // The clients that include this auto-generated header file and 49 // invoke these functions can compress an instruction before emitting 50 // it in the target-specific ASM or ELF streamer or can uncompress 51 // an instruction before printing it when the expanded instruction 52 // format aliases is favored. 53 54 //===----------------------------------------------------------------------===// 55 56 #include "CodeGenInstruction.h" 57 #include "CodeGenTarget.h" 58 #include "llvm/ADT/IndexedMap.h" 59 #include "llvm/ADT/SmallVector.h" 60 #include "llvm/ADT/StringExtras.h" 61 #include "llvm/ADT/StringMap.h" 62 #include "llvm/Support/Debug.h" 63 #include "llvm/Support/ErrorHandling.h" 64 #include "llvm/TableGen/Error.h" 65 #include "llvm/TableGen/Record.h" 66 #include "llvm/TableGen/TableGenBackend.h" 67 #include <set> 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(Inst.TheDef->getLoc(), 257 "Input operands for Inst '" + Inst.TheDef->getName() + 258 "' and input Dag operand count mismatch"); 259 // The Dag can't have more arguments than the Instruction. 260 if (Dag->getNumArgs() > Inst.Operands.size()) 261 PrintFatalError(Inst.TheDef->getLoc(), 262 "Inst '" + Inst.TheDef->getName() + 263 "' and Dag operand count mismatch"); 264 265 // The Instruction might have tied operands so the Dag might have 266 // a fewer operand count. 267 unsigned RealCount = Inst.Operands.size(); 268 for (unsigned i = 0; i < Inst.Operands.size(); i++) 269 if (Inst.Operands[i].getTiedRegister() != -1) 270 --RealCount; 271 272 if (Dag->getNumArgs() != RealCount) 273 PrintFatalError(Inst.TheDef->getLoc(), 274 "Inst '" + Inst.TheDef->getName() + 275 "' and Dag operand count mismatch"); 276 return true; 277 } 278 279 static bool validateArgsTypes(Init *Arg1, Init *Arg2) { 280 DefInit *Type1 = dyn_cast<DefInit>(Arg1); 281 DefInit *Type2 = dyn_cast<DefInit>(Arg2); 282 assert(Type1 && ("Arg1 type not found\n")); 283 assert(Type2 && ("Arg2 type not found\n")); 284 return Type1->getDef() == Type2->getDef(); 285 } 286 287 // Creates a mapping between the operand name in the Dag (e.g. $rs1) and 288 // its index in the list of Dag operands and checks that operands with the same 289 // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the 290 // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied) 291 // same Dag we use the last occurrence for indexing. 292 void RISCVCompressInstEmitter::createDagOperandMapping( 293 Record *Rec, StringMap<unsigned> &SourceOperands, 294 StringMap<unsigned> &DestOperands, DagInit *SourceDag, DagInit *DestDag, 295 IndexedMap<OpData> &SourceOperandMap) { 296 for (unsigned i = 0; i < DestDag->getNumArgs(); ++i) { 297 // Skip fixed immediates and registers, they were handled in 298 // addDagOperandMapping. 299 if ("" == DestDag->getArgNameStr(i)) 300 continue; 301 DestOperands[DestDag->getArgNameStr(i)] = i; 302 } 303 304 for (unsigned i = 0; i < SourceDag->getNumArgs(); ++i) { 305 // Skip fixed immediates and registers, they were handled in 306 // addDagOperandMapping. 307 if ("" == SourceDag->getArgNameStr(i)) 308 continue; 309 310 StringMap<unsigned>::iterator it = 311 SourceOperands.find(SourceDag->getArgNameStr(i)); 312 if (it != SourceOperands.end()) { 313 // Operand sharing the same name in the Dag should be mapped as tied. 314 SourceOperandMap[i].TiedOpIdx = it->getValue(); 315 if (!validateArgsTypes(SourceDag->getArg(it->getValue()), 316 SourceDag->getArg(i))) 317 PrintFatalError(Rec->getLoc(), 318 "Input Operand '" + SourceDag->getArgNameStr(i) + 319 "' has a mismatched tied operand!\n"); 320 } 321 it = DestOperands.find(SourceDag->getArgNameStr(i)); 322 if (it == DestOperands.end()) 323 PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(i) + 324 " defined in Input Dag but not used in" 325 " Output Dag!\n"); 326 // Input Dag operand types must match output Dag operand type. 327 if (!validateArgsTypes(DestDag->getArg(it->getValue()), 328 SourceDag->getArg(i))) 329 PrintFatalError(Rec->getLoc(), "Type mismatch between Input and " 330 "Output Dag operand '" + 331 SourceDag->getArgNameStr(i) + "'!"); 332 SourceOperands[SourceDag->getArgNameStr(i)] = i; 333 } 334 } 335 336 /// Map operand names in the Dag to their index in both corresponding input and 337 /// output instructions. Validate that operands defined in the input are 338 /// used in the output pattern while populating the maps. 339 void RISCVCompressInstEmitter::createInstOperandMapping( 340 Record *Rec, DagInit *SourceDag, DagInit *DestDag, 341 IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap, 342 StringMap<unsigned> &SourceOperands, CodeGenInstruction &DestInst) { 343 // TiedCount keeps track of the number of operands skipped in Inst 344 // operands list to get to the corresponding Dag operand. 345 unsigned TiedCount = 0; 346 LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n"); 347 for (unsigned i = 0, e = DestInst.Operands.size(); i != e; ++i) { 348 int TiedInstOpIdx = DestInst.Operands[i].getTiedRegister(); 349 if (TiedInstOpIdx != -1) { 350 ++TiedCount; 351 DestOperandMap[i].Data = DestOperandMap[TiedInstOpIdx].Data; 352 DestOperandMap[i].Kind = DestOperandMap[TiedInstOpIdx].Kind; 353 if (DestOperandMap[i].Kind == OpData::Operand) 354 // No need to fill the SourceOperandMap here since it was mapped to 355 // destination operand 'TiedInstOpIdx' in a previous iteration. 356 LLVM_DEBUG(dbgs() << " " << DestOperandMap[i].Data.Operand 357 << " ====> " << i 358 << " Dest operand tied with operand '" 359 << TiedInstOpIdx << "'\n"); 360 continue; 361 } 362 // Skip fixed immediates and registers, they were handled in 363 // addDagOperandMapping. 364 if (DestOperandMap[i].Kind != OpData::Operand) 365 continue; 366 367 unsigned DagArgIdx = i - TiedCount; 368 StringMap<unsigned>::iterator SourceOp = 369 SourceOperands.find(DestDag->getArgNameStr(DagArgIdx)); 370 if (SourceOp == SourceOperands.end()) 371 PrintFatalError(Rec->getLoc(), 372 "Output Dag operand '" + 373 DestDag->getArgNameStr(DagArgIdx) + 374 "' has no matching input Dag operand."); 375 376 assert(DestDag->getArgNameStr(DagArgIdx) == 377 SourceDag->getArgNameStr(SourceOp->getValue()) && 378 "Incorrect operand mapping detected!\n"); 379 DestOperandMap[i].Data.Operand = SourceOp->getValue(); 380 SourceOperandMap[SourceOp->getValue()].Data.Operand = i; 381 LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ====> " << i 382 << "\n"); 383 } 384 } 385 386 /// Validates the CompressPattern and create operand mapping. 387 /// These are the checks to validate a CompressPat pattern declarations. 388 /// Error out with message under these conditions: 389 /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a 390 /// compressed instruction. 391 /// - Operands in Dag Input must be all used in Dag Output. 392 /// Register Operand type in Dag Input Type must be contained in the 393 /// corresponding Source Instruction type. 394 /// - Register Operand type in Dag Input must be the same as in Dag Ouput. 395 /// - Register Operand type in Dag Output must be the same as the 396 /// corresponding Destination Inst type. 397 /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput. 398 /// - Immediate Operand type in Dag Ouput must be the same as the corresponding 399 /// Destination Instruction type. 400 /// - Fixed register must be contained in the corresponding Source Instruction 401 /// type. 402 /// - Fixed register must be contained in the corresponding Destination 403 /// Instruction type. Warning message printed under these conditions: 404 /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time 405 /// and generate warning. 406 /// - Immediate operand type in Dag Input differs from the corresponding Source 407 /// Instruction type and generate a warning. 408 void RISCVCompressInstEmitter::evaluateCompressPat(Record *Rec) { 409 // Validate input Dag operands. 410 DagInit *SourceDag = Rec->getValueAsDag("Input"); 411 assert(SourceDag && "Missing 'Input' in compress pattern!"); 412 LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n"); 413 414 // Checking we are transforming from compressed to uncompressed instructions. 415 Record *Operator = SourceDag->getOperatorAsDef(Rec->getLoc()); 416 if (!Operator->isSubClassOf("RVInst")) 417 PrintFatalError(Rec->getLoc(), "Input instruction '" + Operator->getName() + 418 "' is not a 32 bit wide instruction!"); 419 CodeGenInstruction SourceInst(Operator); 420 verifyDagOpCount(SourceInst, SourceDag, true); 421 422 // Validate output Dag operands. 423 DagInit *DestDag = Rec->getValueAsDag("Output"); 424 assert(DestDag && "Missing 'Output' in compress pattern!"); 425 LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n"); 426 427 Record *DestOperator = DestDag->getOperatorAsDef(Rec->getLoc()); 428 if (!DestOperator->isSubClassOf("RVInst16")) 429 PrintFatalError(Rec->getLoc(), "Output instruction '" + 430 DestOperator->getName() + 431 "' is not a 16 bit wide instruction!"); 432 CodeGenInstruction DestInst(DestOperator); 433 verifyDagOpCount(DestInst, DestDag, false); 434 435 // Fill the mapping from the source to destination instructions. 436 437 IndexedMap<OpData> SourceOperandMap; 438 SourceOperandMap.grow(SourceInst.Operands.size()); 439 // Create a mapping between source Dag operands and source Inst operands. 440 addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap, 441 /*IsSourceInst*/ true); 442 443 IndexedMap<OpData> DestOperandMap; 444 DestOperandMap.grow(DestInst.Operands.size()); 445 // Create a mapping between destination Dag operands and destination Inst 446 // operands. 447 addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap, 448 /*IsSourceInst*/ false); 449 450 StringMap<unsigned> SourceOperands; 451 StringMap<unsigned> DestOperands; 452 createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag, 453 SourceOperandMap); 454 // Create operand mapping between the source and destination instructions. 455 createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap, 456 DestOperandMap, SourceOperands, DestInst); 457 458 // Get the target features for the CompressPat. 459 std::vector<Record *> PatReqFeatures; 460 std::vector<Record *> RF = Rec->getValueAsListOfDefs("Predicates"); 461 copy_if(RF, std::back_inserter(PatReqFeatures), [](Record *R) { 462 return R->getValueAsBit("AssemblerMatcherPredicate"); 463 }); 464 465 CompressPatterns.push_back(CompressPat(SourceInst, DestInst, PatReqFeatures, 466 SourceOperandMap, DestOperandMap)); 467 } 468 469 static void getReqFeatures(std::set<StringRef> &FeaturesSet, 470 const std::vector<Record *> &ReqFeatures) { 471 for (auto &R : ReqFeatures) { 472 StringRef AsmCondString = R->getValueAsString("AssemblerCondString"); 473 474 // AsmCondString has syntax [!]F(,[!]F)* 475 SmallVector<StringRef, 4> Ops; 476 SplitString(AsmCondString, Ops, ","); 477 assert(!Ops.empty() && "AssemblerCondString cannot be empty"); 478 for (auto &Op : Ops) { 479 assert(!Op.empty() && "Empty operator"); 480 FeaturesSet.insert(Op); 481 } 482 } 483 } 484 485 unsigned getMCOpPredicate(DenseMap<const Record *, unsigned> &MCOpPredicateMap, 486 std::vector<const Record *> &MCOpPredicates, 487 Record *Rec) { 488 unsigned Entry = MCOpPredicateMap[Rec]; 489 if (Entry) 490 return Entry; 491 492 if (!Rec->isValueUnset("MCOperandPredicate")) { 493 MCOpPredicates.push_back(Rec); 494 Entry = MCOpPredicates.size(); 495 MCOpPredicateMap[Rec] = Entry; 496 return Entry; 497 } 498 499 PrintFatalError(Rec->getLoc(), 500 "No MCOperandPredicate on this operand at all: " + 501 Rec->getName().str() + "'"); 502 return 0; 503 } 504 505 static std::string mergeCondAndCode(raw_string_ostream &CondStream, 506 raw_string_ostream &CodeStream) { 507 std::string S; 508 raw_string_ostream CombinedStream(S); 509 CombinedStream.indent(4) 510 << "if (" 511 << CondStream.str().substr( 512 6, CondStream.str().length() - 513 10) // remove first indentation and last '&&'. 514 << ") {\n"; 515 CombinedStream << CodeStream.str(); 516 CombinedStream.indent(4) << " return true;\n"; 517 CombinedStream.indent(4) << "} // if\n"; 518 return CombinedStream.str(); 519 } 520 521 void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, 522 bool Compress) { 523 Record *AsmWriter = Target.getAsmWriter(); 524 if (!AsmWriter->getValueAsInt("PassSubtarget")) 525 PrintFatalError(AsmWriter->getLoc(), 526 "'PassSubtarget' is false. SubTargetInfo object is needed " 527 "for target features.\n"); 528 529 std::string Namespace = Target.getName(); 530 531 // Sort entries in CompressPatterns to handle instructions that can have more 532 // than one candidate for compression\uncompression, e.g ADD can be 533 // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the 534 // source and destination are flipped and the sort key needs to change 535 // accordingly. 536 llvm::stable_sort(CompressPatterns, 537 [Compress](const CompressPat &LHS, const CompressPat &RHS) { 538 if (Compress) 539 return (LHS.Source.TheDef->getName().str() < 540 RHS.Source.TheDef->getName().str()); 541 else 542 return (LHS.Dest.TheDef->getName().str() < 543 RHS.Dest.TheDef->getName().str()); 544 }); 545 546 // A list of MCOperandPredicates for all operands in use, and the reverse map. 547 std::vector<const Record *> MCOpPredicates; 548 DenseMap<const Record *, unsigned> MCOpPredicateMap; 549 550 std::string F; 551 std::string FH; 552 raw_string_ostream Func(F); 553 raw_string_ostream FuncH(FH); 554 bool NeedMRI = false; 555 556 if (Compress) 557 o << "\n#ifdef GEN_COMPRESS_INSTR\n" 558 << "#undef GEN_COMPRESS_INSTR\n\n"; 559 else 560 o << "\n#ifdef GEN_UNCOMPRESS_INSTR\n" 561 << "#undef GEN_UNCOMPRESS_INSTR\n\n"; 562 563 if (Compress) { 564 FuncH << "static bool compressInst(MCInst& OutInst,\n"; 565 FuncH.indent(25) << "const MCInst &MI,\n"; 566 FuncH.indent(25) << "const MCSubtargetInfo &STI,\n"; 567 FuncH.indent(25) << "MCContext &Context) {\n"; 568 } else { 569 FuncH << "static bool uncompressInst(MCInst& OutInst,\n"; 570 FuncH.indent(27) << "const MCInst &MI,\n"; 571 FuncH.indent(27) << "const MCRegisterInfo &MRI,\n"; 572 FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n"; 573 } 574 575 if (CompressPatterns.empty()) { 576 o << FuncH.str(); 577 o.indent(2) << "return false;\n}\n"; 578 if (Compress) 579 o << "\n#endif //GEN_COMPRESS_INSTR\n"; 580 else 581 o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 582 return; 583 } 584 585 std::string CaseString(""); 586 raw_string_ostream CaseStream(CaseString); 587 std::string PrevOp(""); 588 std::string CurOp(""); 589 CaseStream << " switch (MI.getOpcode()) {\n"; 590 CaseStream << " default: return false;\n"; 591 592 for (auto &CompressPat : CompressPatterns) { 593 std::string CondString; 594 std::string CodeString; 595 raw_string_ostream CondStream(CondString); 596 raw_string_ostream CodeStream(CodeString); 597 CodeGenInstruction &Source = 598 Compress ? CompressPat.Source : CompressPat.Dest; 599 CodeGenInstruction &Dest = Compress ? CompressPat.Dest : CompressPat.Source; 600 IndexedMap<OpData> SourceOperandMap = 601 Compress ? CompressPat.SourceOperandMap : CompressPat.DestOperandMap; 602 IndexedMap<OpData> &DestOperandMap = 603 Compress ? CompressPat.DestOperandMap : CompressPat.SourceOperandMap; 604 605 CurOp = Source.TheDef->getName().str(); 606 // Check current and previous opcode to decide to continue or end a case. 607 if (CurOp != PrevOp) { 608 if (PrevOp != "") 609 CaseStream.indent(6) << "break;\n } // case " + PrevOp + "\n"; 610 CaseStream.indent(4) << "case " + Namespace + "::" + CurOp + ": {\n"; 611 } 612 613 std::set<StringRef> FeaturesSet; 614 // Add CompressPat required features. 615 getReqFeatures(FeaturesSet, CompressPat.PatReqFeatures); 616 617 // Add Dest instruction required features. 618 std::vector<Record *> ReqFeatures; 619 std::vector<Record *> RF = Dest.TheDef->getValueAsListOfDefs("Predicates"); 620 copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) { 621 return R->getValueAsBit("AssemblerMatcherPredicate"); 622 }); 623 getReqFeatures(FeaturesSet, ReqFeatures); 624 625 // Emit checks for all required features. 626 for (auto &Op : FeaturesSet) { 627 if (Op[0] == '!') 628 CondStream.indent(6) << ("!STI.getFeatureBits()[" + Namespace + 629 "::" + Op.substr(1) + "]") 630 .str() + 631 " &&\n"; 632 else 633 CondStream.indent(6) 634 << ("STI.getFeatureBits()[" + Namespace + "::" + Op + "]").str() + 635 " &&\n"; 636 } 637 638 // Start Source Inst operands validation. 639 unsigned OpNo = 0; 640 for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) { 641 if (SourceOperandMap[OpNo].TiedOpIdx != -1) { 642 if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass")) 643 CondStream.indent(6) 644 << "(MI.getOperand(" 645 << std::to_string(OpNo) + ").getReg() == MI.getOperand(" 646 << std::to_string(SourceOperandMap[OpNo].TiedOpIdx) 647 << ").getReg()) &&\n"; 648 else 649 PrintFatalError("Unexpected tied operand types!\n"); 650 } 651 // Check for fixed immediates\registers in the source instruction. 652 switch (SourceOperandMap[OpNo].Kind) { 653 case OpData::Operand: 654 // We don't need to do anything for source instruction operand checks. 655 break; 656 case OpData::Imm: 657 CondStream.indent(6) 658 << "(MI.getOperand(" + std::to_string(OpNo) + ").isImm()) &&\n" + 659 " (MI.getOperand(" + std::to_string(OpNo) + 660 ").getImm() == " + 661 std::to_string(SourceOperandMap[OpNo].Data.Imm) + ") &&\n"; 662 break; 663 case OpData::Reg: { 664 Record *Reg = SourceOperandMap[OpNo].Data.Reg; 665 CondStream.indent(6) << "(MI.getOperand(" + std::to_string(OpNo) + 666 ").getReg() == " + Namespace + 667 "::" + Reg->getName().str() + ") &&\n"; 668 break; 669 } 670 } 671 } 672 CodeStream.indent(6) << "// " + Dest.AsmString + "\n"; 673 CodeStream.indent(6) << "OutInst.setOpcode(" + Namespace + 674 "::" + Dest.TheDef->getName().str() + ");\n"; 675 OpNo = 0; 676 for (const auto &DestOperand : Dest.Operands) { 677 CodeStream.indent(6) << "// Operand: " + DestOperand.Name + "\n"; 678 switch (DestOperandMap[OpNo].Kind) { 679 case OpData::Operand: { 680 unsigned OpIdx = DestOperandMap[OpNo].Data.Operand; 681 // Check that the operand in the Source instruction fits 682 // the type for the Dest instruction. 683 if (DestOperand.Rec->isSubClassOf("RegisterClass")) { 684 NeedMRI = true; 685 // This is a register operand. Check the register class. 686 // Don't check register class if this is a tied operand, it was done 687 // for the operand its tied to. 688 if (DestOperand.getTiedRegister() == -1) 689 CondStream.indent(6) 690 << "(MRI.getRegClass(" + Namespace + 691 "::" + DestOperand.Rec->getName().str() + 692 "RegClassID).contains(" + "MI.getOperand(" + 693 std::to_string(OpIdx) + ").getReg())) &&\n"; 694 695 CodeStream.indent(6) << "OutInst.addOperand(MI.getOperand(" + 696 std::to_string(OpIdx) + "));\n"; 697 } else { 698 // Handling immediate operands. 699 unsigned Entry = getMCOpPredicate(MCOpPredicateMap, MCOpPredicates, 700 DestOperand.Rec); 701 CondStream.indent(6) << Namespace + "ValidateMCOperand(" + 702 "MI.getOperand(" + std::to_string(OpIdx) + 703 "), STI, " + std::to_string(Entry) + 704 ") &&\n"; 705 CodeStream.indent(6) << "OutInst.addOperand(MI.getOperand(" + 706 std::to_string(OpIdx) + "));\n"; 707 } 708 break; 709 } 710 case OpData::Imm: { 711 unsigned Entry = 712 getMCOpPredicate(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec); 713 CondStream.indent(6) 714 << Namespace + "ValidateMCOperand(" + "MCOperand::createImm(" + 715 std::to_string(DestOperandMap[OpNo].Data.Imm) + "), STI, " + 716 std::to_string(Entry) + ") &&\n"; 717 CodeStream.indent(6) 718 << "OutInst.addOperand(MCOperand::createImm(" + 719 std::to_string(DestOperandMap[OpNo].Data.Imm) + "));\n"; 720 } break; 721 case OpData::Reg: { 722 // Fixed register has been validated at pattern validation time. 723 Record *Reg = DestOperandMap[OpNo].Data.Reg; 724 CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createReg(" + 725 Namespace + "::" + Reg->getName().str() + 726 "));\n"; 727 } break; 728 } 729 ++OpNo; 730 } 731 CaseStream << mergeCondAndCode(CondStream, CodeStream); 732 PrevOp = CurOp; 733 } 734 Func << CaseStream.str() << "\n"; 735 // Close brace for the last case. 736 Func.indent(4) << "} // case " + CurOp + "\n"; 737 Func.indent(2) << "} // switch\n"; 738 Func.indent(2) << "return false;\n}\n"; 739 740 if (!MCOpPredicates.empty()) { 741 o << "static bool " << Namespace 742 << "ValidateMCOperand(const MCOperand &MCOp,\n" 743 << " const MCSubtargetInfo &STI,\n" 744 << " unsigned PredicateIndex) {\n" 745 << " switch (PredicateIndex) {\n" 746 << " default:\n" 747 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" 748 << " break;\n"; 749 750 for (unsigned i = 0; i < MCOpPredicates.size(); ++i) { 751 Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate"); 752 if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) 753 o << " case " << i + 1 << ": {\n" 754 << " // " << MCOpPredicates[i]->getName().str() << SI->getValue() 755 << "\n" 756 << " }\n"; 757 else 758 llvm_unreachable("Unexpected MCOperandPredicate field!"); 759 } 760 o << " }\n" 761 << "}\n\n"; 762 } 763 764 o << FuncH.str(); 765 if (NeedMRI && Compress) 766 o.indent(2) << "const MCRegisterInfo &MRI = *Context.getRegisterInfo();\n"; 767 o << Func.str(); 768 769 if (Compress) 770 o << "\n#endif //GEN_COMPRESS_INSTR\n"; 771 else 772 o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 773 } 774 775 void RISCVCompressInstEmitter::run(raw_ostream &o) { 776 Record *CompressClass = Records.getClass("CompressPat"); 777 assert(CompressClass && "Compress class definition missing!"); 778 std::vector<Record *> Insts; 779 for (const auto &D : Records.getDefs()) { 780 if (D.second->isSubClassOf(CompressClass)) 781 Insts.push_back(D.second.get()); 782 } 783 784 // Process the CompressPat definitions, validating them as we do so. 785 for (unsigned i = 0, e = Insts.size(); i != e; ++i) 786 evaluateCompressPat(Insts[i]); 787 788 // Emit file header. 789 emitSourceFileHeader("Compress instruction Source Fragment", o); 790 // Generate compressInst() function. 791 emitCompressInstEmitter(o, true); 792 // Generate uncompressInst() function. 793 emitCompressInstEmitter(o, false); 794 } 795 796 namespace llvm { 797 798 void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS) { 799 RISCVCompressInstEmitter(RK).run(OS); 800 } 801 802 } // namespace llvm 803