1 //===--------------------- InstrBuilder.cpp ---------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// 11 /// This file implements the InstrBuilder interface. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/MCA/InstrBuilder.h" 16 #include "llvm/ADT/APInt.h" 17 #include "llvm/ADT/DenseMap.h" 18 #include "llvm/MC/MCInst.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/WithColor.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 #define DEBUG_TYPE "llvm-mca" 24 25 namespace llvm { 26 namespace mca { 27 28 InstrBuilder::InstrBuilder(const llvm::MCSubtargetInfo &sti, 29 const llvm::MCInstrInfo &mcii, 30 const llvm::MCRegisterInfo &mri, 31 const llvm::MCInstrAnalysis *mcia) 32 : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), FirstCallInst(true), 33 FirstReturnInst(true) { 34 computeProcResourceMasks(STI.getSchedModel(), ProcResourceMasks); 35 } 36 37 static void initializeUsedResources(InstrDesc &ID, 38 const MCSchedClassDesc &SCDesc, 39 const MCSubtargetInfo &STI, 40 ArrayRef<uint64_t> ProcResourceMasks) { 41 const MCSchedModel &SM = STI.getSchedModel(); 42 43 // Populate resources consumed. 44 using ResourcePlusCycles = std::pair<uint64_t, ResourceUsage>; 45 std::vector<ResourcePlusCycles> Worklist; 46 47 // Track cycles contributed by resources that are in a "Super" relationship. 48 // This is required if we want to correctly match the behavior of method 49 // SubtargetEmitter::ExpandProcResource() in Tablegen. When computing the set 50 // of "consumed" processor resources and resource cycles, the logic in 51 // ExpandProcResource() doesn't update the number of resource cycles 52 // contributed by a "Super" resource to a group. 53 // We need to take this into account when we find that a processor resource is 54 // part of a group, and it is also used as the "Super" of other resources. 55 // This map stores the number of cycles contributed by sub-resources that are 56 // part of a "Super" resource. The key value is the "Super" resource mask ID. 57 DenseMap<uint64_t, unsigned> SuperResources; 58 59 unsigned NumProcResources = SM.getNumProcResourceKinds(); 60 APInt Buffers(NumProcResources, 0); 61 62 bool AllInOrderResources = true; 63 bool AnyDispatchHazards = false; 64 for (unsigned I = 0, E = SCDesc.NumWriteProcResEntries; I < E; ++I) { 65 const MCWriteProcResEntry *PRE = STI.getWriteProcResBegin(&SCDesc) + I; 66 const MCProcResourceDesc &PR = *SM.getProcResource(PRE->ProcResourceIdx); 67 uint64_t Mask = ProcResourceMasks[PRE->ProcResourceIdx]; 68 if (PR.BufferSize < 0) { 69 AllInOrderResources = false; 70 } else { 71 Buffers.setBit(PRE->ProcResourceIdx); 72 AnyDispatchHazards |= (PR.BufferSize == 0); 73 AllInOrderResources &= (PR.BufferSize <= 1); 74 } 75 76 CycleSegment RCy(0, PRE->Cycles, false); 77 Worklist.emplace_back(ResourcePlusCycles(Mask, ResourceUsage(RCy))); 78 if (PR.SuperIdx) { 79 uint64_t Super = ProcResourceMasks[PR.SuperIdx]; 80 SuperResources[Super] += PRE->Cycles; 81 } 82 } 83 84 ID.MustIssueImmediately = AllInOrderResources && AnyDispatchHazards; 85 86 // Sort elements by mask popcount, so that we prioritize resource units over 87 // resource groups, and smaller groups over larger groups. 88 sort(Worklist, [](const ResourcePlusCycles &A, const ResourcePlusCycles &B) { 89 unsigned popcntA = countPopulation(A.first); 90 unsigned popcntB = countPopulation(B.first); 91 if (popcntA < popcntB) 92 return true; 93 if (popcntA > popcntB) 94 return false; 95 return A.first < B.first; 96 }); 97 98 uint64_t UsedResourceUnits = 0; 99 100 // Remove cycles contributed by smaller resources. 101 for (unsigned I = 0, E = Worklist.size(); I < E; ++I) { 102 ResourcePlusCycles &A = Worklist[I]; 103 if (!A.second.size()) { 104 A.second.NumUnits = 0; 105 A.second.setReserved(); 106 ID.Resources.emplace_back(A); 107 continue; 108 } 109 110 ID.Resources.emplace_back(A); 111 uint64_t NormalizedMask = A.first; 112 if (countPopulation(A.first) == 1) { 113 UsedResourceUnits |= A.first; 114 } else { 115 // Remove the leading 1 from the resource group mask. 116 NormalizedMask ^= PowerOf2Floor(NormalizedMask); 117 } 118 119 for (unsigned J = I + 1; J < E; ++J) { 120 ResourcePlusCycles &B = Worklist[J]; 121 if ((NormalizedMask & B.first) == NormalizedMask) { 122 B.second.CS.subtract(A.second.size() - SuperResources[A.first]); 123 if (countPopulation(B.first) > 1) 124 B.second.NumUnits++; 125 } 126 } 127 } 128 129 // A SchedWrite may specify a number of cycles in which a resource group 130 // is reserved. For example (on target x86; cpu Haswell): 131 // 132 // SchedWriteRes<[HWPort0, HWPort1, HWPort01]> { 133 // let ResourceCycles = [2, 2, 3]; 134 // } 135 // 136 // This means: 137 // Resource units HWPort0 and HWPort1 are both used for 2cy. 138 // Resource group HWPort01 is the union of HWPort0 and HWPort1. 139 // Since this write touches both HWPort0 and HWPort1 for 2cy, HWPort01 140 // will not be usable for 2 entire cycles from instruction issue. 141 // 142 // On top of those 2cy, SchedWriteRes explicitly specifies an extra latency 143 // of 3 cycles for HWPort01. This tool assumes that the 3cy latency is an 144 // extra delay on top of the 2 cycles latency. 145 // During those extra cycles, HWPort01 is not usable by other instructions. 146 for (ResourcePlusCycles &RPC : ID.Resources) { 147 if (countPopulation(RPC.first) > 1 && !RPC.second.isReserved()) { 148 // Remove the leading 1 from the resource group mask. 149 uint64_t Mask = RPC.first ^ PowerOf2Floor(RPC.first); 150 if ((Mask & UsedResourceUnits) == Mask) 151 RPC.second.setReserved(); 152 } 153 } 154 155 // Identify extra buffers that are consumed through super resources. 156 for (const std::pair<uint64_t, unsigned> &SR : SuperResources) { 157 for (unsigned I = 1, E = NumProcResources; I < E; ++I) { 158 const MCProcResourceDesc &PR = *SM.getProcResource(I); 159 if (PR.BufferSize == -1) 160 continue; 161 162 uint64_t Mask = ProcResourceMasks[I]; 163 if (Mask != SR.first && ((Mask & SR.first) == SR.first)) 164 Buffers.setBit(I); 165 } 166 } 167 168 // Now set the buffers. 169 if (unsigned NumBuffers = Buffers.countPopulation()) { 170 ID.Buffers.resize(NumBuffers); 171 for (unsigned I = 0, E = NumProcResources; I < E && NumBuffers; ++I) { 172 if (Buffers[I]) { 173 --NumBuffers; 174 ID.Buffers[NumBuffers] = ProcResourceMasks[I]; 175 } 176 } 177 } 178 179 LLVM_DEBUG({ 180 for (const std::pair<uint64_t, ResourceUsage> &R : ID.Resources) 181 dbgs() << "\t\tMask=" << R.first << ", cy=" << R.second.size() << '\n'; 182 for (const uint64_t R : ID.Buffers) 183 dbgs() << "\t\tBuffer Mask=" << R << '\n'; 184 }); 185 } 186 187 static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc, 188 const MCSchedClassDesc &SCDesc, 189 const MCSubtargetInfo &STI) { 190 if (MCDesc.isCall()) { 191 // We cannot estimate how long this call will take. 192 // Artificially set an arbitrarily high latency (100cy). 193 ID.MaxLatency = 100U; 194 return; 195 } 196 197 int Latency = MCSchedModel::computeInstrLatency(STI, SCDesc); 198 // If latency is unknown, then conservatively assume a MaxLatency of 100cy. 199 ID.MaxLatency = Latency < 0 ? 100U : static_cast<unsigned>(Latency); 200 } 201 202 static Error verifyOperands(const MCInstrDesc &MCDesc, const MCInst &MCI) { 203 // Count register definitions, and skip non register operands in the process. 204 unsigned I, E; 205 unsigned NumExplicitDefs = MCDesc.getNumDefs(); 206 for (I = 0, E = MCI.getNumOperands(); NumExplicitDefs && I < E; ++I) { 207 const MCOperand &Op = MCI.getOperand(I); 208 if (Op.isReg()) 209 --NumExplicitDefs; 210 } 211 212 if (NumExplicitDefs) { 213 return make_error<InstructionError<MCInst>>( 214 "Expected more register operand definitions.", MCI); 215 } 216 217 if (MCDesc.hasOptionalDef()) { 218 // Always assume that the optional definition is the last operand. 219 const MCOperand &Op = MCI.getOperand(MCDesc.getNumOperands() - 1); 220 if (I == MCI.getNumOperands() || !Op.isReg()) { 221 std::string Message = 222 "expected a register operand for an optional definition. Instruction " 223 "has not been correctly analyzed."; 224 return make_error<InstructionError<MCInst>>(Message, MCI); 225 } 226 } 227 228 return ErrorSuccess(); 229 } 230 231 void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI, 232 unsigned SchedClassID) { 233 const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode()); 234 const MCSchedModel &SM = STI.getSchedModel(); 235 const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); 236 237 // Assumptions made by this algorithm: 238 // 1. The number of explicit and implicit register definitions in a MCInst 239 // matches the number of explicit and implicit definitions according to 240 // the opcode descriptor (MCInstrDesc). 241 // 2. Uses start at index #(MCDesc.getNumDefs()). 242 // 3. There can only be a single optional register definition, an it is 243 // always the last operand of the sequence (excluding extra operands 244 // contributed by variadic opcodes). 245 // 246 // These assumptions work quite well for most out-of-order in-tree targets 247 // like x86. This is mainly because the vast majority of instructions is 248 // expanded to MCInst using a straightforward lowering logic that preserves 249 // the ordering of the operands. 250 // 251 // About assumption 1. 252 // The algorithm allows non-register operands between register operand 253 // definitions. This helps to handle some special ARM instructions with 254 // implicit operand increment (-mtriple=armv7): 255 // 256 // vld1.32 {d18, d19}, [r1]! @ <MCInst #1463 VLD1q32wb_fixed 257 // @ <MCOperand Reg:59> 258 // @ <MCOperand Imm:0> (!!) 259 // @ <MCOperand Reg:67> 260 // @ <MCOperand Imm:0> 261 // @ <MCOperand Imm:14> 262 // @ <MCOperand Reg:0>> 263 // 264 // MCDesc reports: 265 // 6 explicit operands. 266 // 1 optional definition 267 // 2 explicit definitions (!!) 268 // 269 // The presence of an 'Imm' operand between the two register definitions 270 // breaks the assumption that "register definitions are always at the 271 // beginning of the operand sequence". 272 // 273 // To workaround this issue, this algorithm ignores (i.e. skips) any 274 // non-register operands between register definitions. The optional 275 // definition is still at index #(NumOperands-1). 276 // 277 // According to assumption 2. register reads start at #(NumExplicitDefs-1). 278 // That means, register R1 from the example is both read and written. 279 unsigned NumExplicitDefs = MCDesc.getNumDefs(); 280 unsigned NumImplicitDefs = MCDesc.getNumImplicitDefs(); 281 unsigned NumWriteLatencyEntries = SCDesc.NumWriteLatencyEntries; 282 unsigned TotalDefs = NumExplicitDefs + NumImplicitDefs; 283 if (MCDesc.hasOptionalDef()) 284 TotalDefs++; 285 286 unsigned NumVariadicOps = MCI.getNumOperands() - MCDesc.getNumOperands(); 287 ID.Writes.resize(TotalDefs + NumVariadicOps); 288 // Iterate over the operands list, and skip non-register operands. 289 // The first NumExplictDefs register operands are expected to be register 290 // definitions. 291 unsigned CurrentDef = 0; 292 unsigned i = 0; 293 for (; i < MCI.getNumOperands() && CurrentDef < NumExplicitDefs; ++i) { 294 const MCOperand &Op = MCI.getOperand(i); 295 if (!Op.isReg()) 296 continue; 297 298 WriteDescriptor &Write = ID.Writes[CurrentDef]; 299 Write.OpIndex = i; 300 if (CurrentDef < NumWriteLatencyEntries) { 301 const MCWriteLatencyEntry &WLE = 302 *STI.getWriteLatencyEntry(&SCDesc, CurrentDef); 303 // Conservatively default to MaxLatency. 304 Write.Latency = 305 WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles); 306 Write.SClassOrWriteResourceID = WLE.WriteResourceID; 307 } else { 308 // Assign a default latency for this write. 309 Write.Latency = ID.MaxLatency; 310 Write.SClassOrWriteResourceID = 0; 311 } 312 Write.IsOptionalDef = false; 313 LLVM_DEBUG({ 314 dbgs() << "\t\t[Def] OpIdx=" << Write.OpIndex 315 << ", Latency=" << Write.Latency 316 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n'; 317 }); 318 CurrentDef++; 319 } 320 321 assert(CurrentDef == NumExplicitDefs && 322 "Expected more register operand definitions."); 323 for (CurrentDef = 0; CurrentDef < NumImplicitDefs; ++CurrentDef) { 324 unsigned Index = NumExplicitDefs + CurrentDef; 325 WriteDescriptor &Write = ID.Writes[Index]; 326 Write.OpIndex = ~CurrentDef; 327 Write.RegisterID = MCDesc.getImplicitDefs()[CurrentDef]; 328 if (Index < NumWriteLatencyEntries) { 329 const MCWriteLatencyEntry &WLE = 330 *STI.getWriteLatencyEntry(&SCDesc, Index); 331 // Conservatively default to MaxLatency. 332 Write.Latency = 333 WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles); 334 Write.SClassOrWriteResourceID = WLE.WriteResourceID; 335 } else { 336 // Assign a default latency for this write. 337 Write.Latency = ID.MaxLatency; 338 Write.SClassOrWriteResourceID = 0; 339 } 340 341 Write.IsOptionalDef = false; 342 assert(Write.RegisterID != 0 && "Expected a valid phys register!"); 343 LLVM_DEBUG({ 344 dbgs() << "\t\t[Def][I] OpIdx=" << ~Write.OpIndex 345 << ", PhysReg=" << MRI.getName(Write.RegisterID) 346 << ", Latency=" << Write.Latency 347 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n'; 348 }); 349 } 350 351 if (MCDesc.hasOptionalDef()) { 352 WriteDescriptor &Write = ID.Writes[NumExplicitDefs + NumImplicitDefs]; 353 Write.OpIndex = MCDesc.getNumOperands() - 1; 354 // Assign a default latency for this write. 355 Write.Latency = ID.MaxLatency; 356 Write.SClassOrWriteResourceID = 0; 357 Write.IsOptionalDef = true; 358 LLVM_DEBUG({ 359 dbgs() << "\t\t[Def][O] OpIdx=" << Write.OpIndex 360 << ", Latency=" << Write.Latency 361 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n'; 362 }); 363 } 364 365 if (!NumVariadicOps) 366 return; 367 368 // FIXME: if an instruction opcode is flagged 'mayStore', and it has no 369 // "unmodeledSideEffects', then this logic optimistically assumes that any 370 // extra register operands in the variadic sequence is not a register 371 // definition. 372 // 373 // Otherwise, we conservatively assume that any register operand from the 374 // variadic sequence is both a register read and a register write. 375 bool AssumeUsesOnly = MCDesc.mayStore() && !MCDesc.mayLoad() && 376 !MCDesc.hasUnmodeledSideEffects(); 377 CurrentDef = NumExplicitDefs + NumImplicitDefs + MCDesc.hasOptionalDef(); 378 for (unsigned I = 0, OpIndex = MCDesc.getNumOperands(); 379 I < NumVariadicOps && !AssumeUsesOnly; ++I, ++OpIndex) { 380 const MCOperand &Op = MCI.getOperand(OpIndex); 381 if (!Op.isReg()) 382 continue; 383 384 WriteDescriptor &Write = ID.Writes[CurrentDef]; 385 Write.OpIndex = OpIndex; 386 // Assign a default latency for this write. 387 Write.Latency = ID.MaxLatency; 388 Write.SClassOrWriteResourceID = 0; 389 Write.IsOptionalDef = false; 390 ++CurrentDef; 391 LLVM_DEBUG({ 392 dbgs() << "\t\t[Def][V] OpIdx=" << Write.OpIndex 393 << ", Latency=" << Write.Latency 394 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n'; 395 }); 396 } 397 398 ID.Writes.resize(CurrentDef); 399 } 400 401 void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI, 402 unsigned SchedClassID) { 403 const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode()); 404 unsigned NumExplicitUses = MCDesc.getNumOperands() - MCDesc.getNumDefs(); 405 unsigned NumImplicitUses = MCDesc.getNumImplicitUses(); 406 // Remove the optional definition. 407 if (MCDesc.hasOptionalDef()) 408 --NumExplicitUses; 409 unsigned NumVariadicOps = MCI.getNumOperands() - MCDesc.getNumOperands(); 410 unsigned TotalUses = NumExplicitUses + NumImplicitUses + NumVariadicOps; 411 ID.Reads.resize(TotalUses); 412 unsigned CurrentUse = 0; 413 for (unsigned I = 0, OpIndex = MCDesc.getNumDefs(); I < NumExplicitUses; 414 ++I, ++OpIndex) { 415 const MCOperand &Op = MCI.getOperand(OpIndex); 416 if (!Op.isReg()) 417 continue; 418 419 ReadDescriptor &Read = ID.Reads[CurrentUse]; 420 Read.OpIndex = OpIndex; 421 Read.UseIndex = I; 422 Read.SchedClassID = SchedClassID; 423 ++CurrentUse; 424 LLVM_DEBUG(dbgs() << "\t\t[Use] OpIdx=" << Read.OpIndex 425 << ", UseIndex=" << Read.UseIndex << '\n'); 426 } 427 428 // For the purpose of ReadAdvance, implicit uses come directly after explicit 429 // uses. The "UseIndex" must be updated according to that implicit layout. 430 for (unsigned I = 0; I < NumImplicitUses; ++I) { 431 ReadDescriptor &Read = ID.Reads[CurrentUse + I]; 432 Read.OpIndex = ~I; 433 Read.UseIndex = NumExplicitUses + I; 434 Read.RegisterID = MCDesc.getImplicitUses()[I]; 435 Read.SchedClassID = SchedClassID; 436 LLVM_DEBUG(dbgs() << "\t\t[Use][I] OpIdx=" << ~Read.OpIndex 437 << ", UseIndex=" << Read.UseIndex << ", RegisterID=" 438 << MRI.getName(Read.RegisterID) << '\n'); 439 } 440 441 CurrentUse += NumImplicitUses; 442 443 // FIXME: If an instruction opcode is marked as 'mayLoad', and it has no 444 // "unmodeledSideEffects", then this logic optimistically assumes that any 445 // extra register operands in the variadic sequence are not register 446 // definition. 447 448 bool AssumeDefsOnly = !MCDesc.mayStore() && MCDesc.mayLoad() && 449 !MCDesc.hasUnmodeledSideEffects(); 450 for (unsigned I = 0, OpIndex = MCDesc.getNumOperands(); 451 I < NumVariadicOps && !AssumeDefsOnly; ++I, ++OpIndex) { 452 const MCOperand &Op = MCI.getOperand(OpIndex); 453 if (!Op.isReg()) 454 continue; 455 456 ReadDescriptor &Read = ID.Reads[CurrentUse]; 457 Read.OpIndex = OpIndex; 458 Read.UseIndex = NumExplicitUses + NumImplicitUses + I; 459 Read.SchedClassID = SchedClassID; 460 ++CurrentUse; 461 LLVM_DEBUG(dbgs() << "\t\t[Use][V] OpIdx=" << Read.OpIndex 462 << ", UseIndex=" << Read.UseIndex << '\n'); 463 } 464 465 ID.Reads.resize(CurrentUse); 466 } 467 468 Error InstrBuilder::verifyInstrDesc(const InstrDesc &ID, 469 const MCInst &MCI) const { 470 if (ID.NumMicroOps != 0) 471 return ErrorSuccess(); 472 473 bool UsesMemory = ID.MayLoad || ID.MayStore; 474 bool UsesBuffers = !ID.Buffers.empty(); 475 bool UsesResources = !ID.Resources.empty(); 476 if (!UsesMemory && !UsesBuffers && !UsesResources) 477 return ErrorSuccess(); 478 479 StringRef Message; 480 if (UsesMemory) { 481 Message = "found an inconsistent instruction that decodes " 482 "into zero opcodes and that consumes load/store " 483 "unit resources."; 484 } else { 485 Message = "found an inconsistent instruction that decodes " 486 "to zero opcodes and that consumes scheduler " 487 "resources."; 488 } 489 490 return make_error<InstructionError<MCInst>>(Message, MCI); 491 } 492 493 Expected<const InstrDesc &> 494 InstrBuilder::createInstrDescImpl(const MCInst &MCI) { 495 assert(STI.getSchedModel().hasInstrSchedModel() && 496 "Itineraries are not yet supported!"); 497 498 // Obtain the instruction descriptor from the opcode. 499 unsigned short Opcode = MCI.getOpcode(); 500 const MCInstrDesc &MCDesc = MCII.get(Opcode); 501 const MCSchedModel &SM = STI.getSchedModel(); 502 503 // Then obtain the scheduling class information from the instruction. 504 unsigned SchedClassID = MCDesc.getSchedClass(); 505 bool IsVariant = SM.getSchedClassDesc(SchedClassID)->isVariant(); 506 507 // Try to solve variant scheduling classes. 508 if (IsVariant) { 509 unsigned CPUID = SM.getProcessorID(); 510 while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant()) 511 SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &MCI, CPUID); 512 513 if (!SchedClassID) { 514 return make_error<InstructionError<MCInst>>( 515 "unable to resolve scheduling class for write variant.", MCI); 516 } 517 } 518 519 // Check if this instruction is supported. Otherwise, report an error. 520 const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); 521 if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) { 522 return make_error<InstructionError<MCInst>>( 523 "found an unsupported instruction in the input assembly sequence.", 524 MCI); 525 } 526 527 // Create a new empty descriptor. 528 std::unique_ptr<InstrDesc> ID = llvm::make_unique<InstrDesc>(); 529 ID->NumMicroOps = SCDesc.NumMicroOps; 530 531 if (MCDesc.isCall() && FirstCallInst) { 532 // We don't correctly model calls. 533 WithColor::warning() << "found a call in the input assembly sequence.\n"; 534 WithColor::note() << "call instructions are not correctly modeled. " 535 << "Assume a latency of 100cy.\n"; 536 FirstCallInst = false; 537 } 538 539 if (MCDesc.isReturn() && FirstReturnInst) { 540 WithColor::warning() << "found a return instruction in the input" 541 << " assembly sequence.\n"; 542 WithColor::note() << "program counter updates are ignored.\n"; 543 FirstReturnInst = false; 544 } 545 546 ID->MayLoad = MCDesc.mayLoad(); 547 ID->MayStore = MCDesc.mayStore(); 548 ID->HasSideEffects = MCDesc.hasUnmodeledSideEffects(); 549 ID->BeginGroup = SCDesc.BeginGroup; 550 ID->EndGroup = SCDesc.EndGroup; 551 552 initializeUsedResources(*ID, SCDesc, STI, ProcResourceMasks); 553 computeMaxLatency(*ID, MCDesc, SCDesc, STI); 554 555 if (Error Err = verifyOperands(MCDesc, MCI)) 556 return std::move(Err); 557 558 populateWrites(*ID, MCI, SchedClassID); 559 populateReads(*ID, MCI, SchedClassID); 560 561 #ifndef NDEBUG 562 ID->Name = MCII.getName(Opcode); 563 #endif 564 LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n'); 565 LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n'); 566 567 // Sanity check on the instruction descriptor. 568 if (Error Err = verifyInstrDesc(*ID, MCI)) 569 return std::move(Err); 570 571 // Now add the new descriptor. 572 SchedClassID = MCDesc.getSchedClass(); 573 bool IsVariadic = MCDesc.isVariadic(); 574 if (!IsVariadic && !IsVariant) { 575 Descriptors[MCI.getOpcode()] = std::move(ID); 576 return *Descriptors[MCI.getOpcode()]; 577 } 578 579 VariantDescriptors[&MCI] = std::move(ID); 580 return *VariantDescriptors[&MCI]; 581 } 582 583 Expected<const InstrDesc &> 584 InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) { 585 if (Descriptors.find_as(MCI.getOpcode()) != Descriptors.end()) 586 return *Descriptors[MCI.getOpcode()]; 587 588 if (VariantDescriptors.find(&MCI) != VariantDescriptors.end()) 589 return *VariantDescriptors[&MCI]; 590 591 return createInstrDescImpl(MCI); 592 } 593 594 Expected<std::unique_ptr<Instruction>> 595 InstrBuilder::createInstruction(const MCInst &MCI) { 596 Expected<const InstrDesc &> DescOrErr = getOrCreateInstrDesc(MCI); 597 if (!DescOrErr) 598 return DescOrErr.takeError(); 599 const InstrDesc &D = *DescOrErr; 600 std::unique_ptr<Instruction> NewIS = llvm::make_unique<Instruction>(D); 601 602 // Check if this is a dependency breaking instruction. 603 APInt Mask; 604 605 bool IsZeroIdiom = false; 606 bool IsDepBreaking = false; 607 if (MCIA) { 608 unsigned ProcID = STI.getSchedModel().getProcessorID(); 609 IsZeroIdiom = MCIA->isZeroIdiom(MCI, Mask, ProcID); 610 IsDepBreaking = 611 IsZeroIdiom || MCIA->isDependencyBreaking(MCI, Mask, ProcID); 612 if (MCIA->isOptimizableRegisterMove(MCI, ProcID)) 613 NewIS->setOptimizableMove(); 614 } 615 616 // Initialize Reads first. 617 for (const ReadDescriptor &RD : D.Reads) { 618 int RegID = -1; 619 if (!RD.isImplicitRead()) { 620 // explicit read. 621 const MCOperand &Op = MCI.getOperand(RD.OpIndex); 622 // Skip non-register operands. 623 if (!Op.isReg()) 624 continue; 625 RegID = Op.getReg(); 626 } else { 627 // Implicit read. 628 RegID = RD.RegisterID; 629 } 630 631 // Skip invalid register operands. 632 if (!RegID) 633 continue; 634 635 // Okay, this is a register operand. Create a ReadState for it. 636 assert(RegID > 0 && "Invalid register ID found!"); 637 NewIS->getUses().emplace_back(RD, RegID); 638 ReadState &RS = NewIS->getUses().back(); 639 640 if (IsDepBreaking) { 641 // A mask of all zeroes means: explicit input operands are not 642 // independent. 643 if (Mask.isNullValue()) { 644 if (!RD.isImplicitRead()) 645 RS.setIndependentFromDef(); 646 } else { 647 // Check if this register operand is independent according to `Mask`. 648 // Note that Mask may not have enough bits to describe all explicit and 649 // implicit input operands. If this register operand doesn't have a 650 // corresponding bit in Mask, then conservatively assume that it is 651 // dependent. 652 if (Mask.getBitWidth() > RD.UseIndex) { 653 // Okay. This map describe register use `RD.UseIndex`. 654 if (Mask[RD.UseIndex]) 655 RS.setIndependentFromDef(); 656 } 657 } 658 } 659 } 660 661 // Early exit if there are no writes. 662 if (D.Writes.empty()) 663 return std::move(NewIS); 664 665 // Track register writes that implicitly clear the upper portion of the 666 // underlying super-registers using an APInt. 667 APInt WriteMask(D.Writes.size(), 0); 668 669 // Now query the MCInstrAnalysis object to obtain information about which 670 // register writes implicitly clear the upper portion of a super-register. 671 if (MCIA) 672 MCIA->clearsSuperRegisters(MRI, MCI, WriteMask); 673 674 // Initialize writes. 675 unsigned WriteIndex = 0; 676 for (const WriteDescriptor &WD : D.Writes) { 677 unsigned RegID = WD.isImplicitWrite() ? WD.RegisterID 678 : MCI.getOperand(WD.OpIndex).getReg(); 679 // Check if this is a optional definition that references NoReg. 680 if (WD.IsOptionalDef && !RegID) { 681 ++WriteIndex; 682 continue; 683 } 684 685 assert(RegID && "Expected a valid register ID!"); 686 NewIS->getDefs().emplace_back(WD, RegID, 687 /* ClearsSuperRegs */ WriteMask[WriteIndex], 688 /* WritesZero */ IsZeroIdiom); 689 ++WriteIndex; 690 } 691 692 return std::move(NewIS); 693 } 694 } // namespace mca 695 } // namespace llvm 696