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