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