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