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