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