LLVM  8.0.1
InstrBuilder.cpp
Go to the documentation of this file.
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"
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 
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;
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);
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);
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 
497 InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
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 
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 
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())
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])
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
Expected< std::unique_ptr< Instruction > > createInstruction(const MCInst &MCI)
unsigned getNumImplicitUses() const
Return the number of implicit uses this instruction has.
Definition: MCInstrDesc.h:527
A sequence of cycles.
Definition: Instruction.h:264
unsigned getNumImplicitDefs() const
Return the number of implicit defs this instruct has.
Definition: MCInstrDesc.h:549
This class represents lattice values for constants.
Definition: AllocatorList.h:24
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition: Format.h:186
SmallVector< uint64_t, 4 > Buffers
Definition: Instruction.h:331
Subclass of Error for the sole purpose of identifying the success path in the type system...
Definition: Error.h:325
bool isImplicitRead() const
Definition: Instruction.h:79
A register read descriptor.
Definition: Instruction.h:65
const MCPhysReg * getImplicitUses() const
Return a list of registers that are potentially read by any instance of this machine instruction...
Definition: MCInstrDesc.h:524
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:164
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by other flags.
Definition: MCInstrDesc.h:419
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Definition: MCSchedule.h:339
bool isReg() const
Definition: MCInst.h:58
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition: WithColor.cpp:63
block Block Frequency true
unsigned getProcessorID() const
Definition: MCSchedule.h:317
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
Definition: MCSchedule.h:346
Error takeError()
Take ownership of the stored error.
Definition: Error.h:553
bool mayLoad() const
Return true if this instruction could possibly read memory.
Definition: MCInstrDesc.h:399
bool isReturn() const
Return true if the instruction is a return.
Definition: MCInstrDesc.h:246
void setBit(unsigned BitPosition)
Set a given bit to 1.
Definition: APInt.h:1403
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:211
Tracks register operand latency in cycles.
Definition: Instruction.h:205
SmallVector< ReadDescriptor, 4 > Reads
Definition: Instruction.h:324
static raw_ostream & note()
Convenience method for printing "note: " to stderr.
Definition: WithColor.cpp:65
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
This file implements a class to represent arbitrary precision integral constant values and operations...
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:65
virtual bool isOptimizableRegisterMove(const MCInst &MI, unsigned CPUID) const
Returns true if MI is a candidate for move elimination.
void setIndependentFromDef()
Definition: Instruction.h:247
Helper used by class InstrDesc to describe how hardware resources are used.
Definition: Instruction.h:311
uint16_t NumWriteProcResEntries
Definition: MCSchedule.h:121
const MCWriteLatencyEntry * getWriteLatencyEntry(const MCSchedClassDesc *SC, unsigned DefIdx) const
A register write descriptor.
Definition: Instruction.h:37
void computeProcResourceMasks(const MCSchedModel &SM, MutableArrayRef< uint64_t > Masks)
Populates vector Masks with processor resource masks.
Definition: Support.cpp:24
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
const char * getName(unsigned RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register...
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Definition: MCInstrDesc.h:577
const MCPhysReg * getImplicitDefs() const
Return a list of registers that are potentially written by any instance of this machine instruction...
Definition: MCInstrDesc.h:546
virtual bool clearsSuperRegisters(const MCRegisterInfo &MRI, const MCInst &Inst, APInt &Writes) const
Returns true if at least one of the register writes performed by.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
unsigned countPopulation() const
Count the number of bits set.
Definition: APInt.h:1658
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
Definition: MCInstrDesc.h:239
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition: MCSchedule.h:64
bool isVariadic() const
Return true if this instruction can have a variable number of operands.
Definition: MCInstrDesc.h:235
static Error verifyOperands(const MCInstrDesc &MCDesc, const MCInst &MCI)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Summarize the scheduling resources required for an instruction of a particular scheduling class...
Definition: MCSchedule.h:110
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
virtual bool isDependencyBreaking(const MCInst &MI, APInt &Mask, unsigned CPUID) const
Returns true if MI is a dependency breaking instruction for the subtarget associated with CPUID ...
unsigned getNumOperands() const
Definition: MCInst.h:184
SmallVector< std::pair< uint64_t, ResourceUsage >, 4 > Resources
Definition: Instruction.h:328
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition: MCInstrInfo.h:51
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1116
static const unsigned short InvalidNumMicroOps
Definition: MCSchedule.h:111
bool hasInstrSchedModel() const
Does this machine model include instruction-level scheduling.
Definition: MCSchedule.h:320
unsigned countPopulation(T Value)
Count the number of set bits in a value.
Definition: MathExtras.h:520
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition: MCSchedule.h:78
bool isImplicitWrite() const
Definition: Instruction.h:61
Define a kind of processor resource that will be modeled by the scheduler.
Definition: MCSchedule.h:32
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:182
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Definition: MCInstrDesc.h:226
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
Class for arbitrary precision integers.
Definition: APInt.h:70
bool isVariant() const
Definition: MCSchedule.h:130
bool mayStore() const
Return true if this instruction could possibly modify memory.
Definition: MCInstrDesc.h:405
virtual bool isZeroIdiom(const MCInst &MI, APInt &Mask, unsigned CPUID) const
Returns true if MI is a dependency breaking zero-idiom for the given subtarget.
An instruction descriptor.
Definition: Instruction.h:322
static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc, const MCSchedClassDesc &SCDesc, const MCSubtargetInfo &STI)
static int computeInstrLatency(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Returns the latency value for the scheduling class.
Definition: MCSchedule.cpp:41
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:56
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
#define I(x, y, z)
Definition: MD5.cpp:58
bool isCall() const
Return true if the instruction is a call.
Definition: MCInstrDesc.h:258
Generic base class for all target subtargets.
virtual unsigned resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI, unsigned CPUID) const
Resolve a variant scheduling class for the given MCInst and CPU.
const MCWriteProcResEntry * getWriteProcResBegin(const MCSchedClassDesc *SC) const
Return an iterator at the first process resource consumed by the given scheduling class...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A builder class for instructions that are statically analyzed by llvm-mca.
uint64_t PowerOf2Floor(uint64_t A)
Returns the power of two which is less than or equal to the given value.
Definition: MathExtras.h:652
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:81
uint16_t NumWriteLatencyEntries
Definition: MCSchedule.h:123
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
unsigned getOpcode() const
Definition: MCInst.h:174
#define LLVM_DEBUG(X)
Definition: Debug.h:123
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
static void initializeUsedResources(InstrDesc &ID, const MCSchedClassDesc &SCDesc, const MCSubtargetInfo &STI, ArrayRef< uint64_t > ProcResourceMasks)
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:244
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget&#39;s CPU.
unsigned getNumProcResourceKinds() const
Definition: MCSchedule.h:335
SmallVector< WriteDescriptor, 4 > Writes
Definition: Instruction.h:323
void resize(size_type N)
Definition: SmallVector.h:351