Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===--------------------- Instruction.h ------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
///
10
/// This file defines abstractions used by the Pipeline to model register reads,
11
/// register writes and instructions.
12
///
13
//===----------------------------------------------------------------------===//
14
 
15
#ifndef LLVM_MCA_INSTRUCTION_H
16
#define LLVM_MCA_INSTRUCTION_H
17
 
18
#include "llvm/ADT/ArrayRef.h"
19
#include "llvm/ADT/STLExtras.h"
20
#include "llvm/ADT/SmallVector.h"
21
#include "llvm/MC/MCRegister.h" // definition of MCPhysReg.
22
#include "llvm/Support/MathExtras.h"
23
 
24
#ifndef NDEBUG
25
#include "llvm/Support/raw_ostream.h"
26
#endif
27
 
28
#include <memory>
29
 
30
namespace llvm {
31
 
32
namespace mca {
33
 
34
constexpr int UNKNOWN_CYCLES = -512;
35
 
36
/// A representation of an mca::Instruction operand
37
/// for use in mca::CustomBehaviour.
38
class MCAOperand {
39
  // This class is mostly copied from MCOperand within
40
  // MCInst.h except that we don't keep track of
41
  // expressions or sub-instructions.
42
  enum MCAOperandType : unsigned char {
43
    kInvalid,   ///< Uninitialized, Relocatable immediate, or Sub-instruction.
44
    kRegister,  ///< Register operand.
45
    kImmediate, ///< Immediate operand.
46
    kSFPImmediate, ///< Single-floating-point immediate operand.
47
    kDFPImmediate, ///< Double-Floating-point immediate operand.
48
  };
49
  MCAOperandType Kind;
50
 
51
  union {
52
    unsigned RegVal;
53
    int64_t ImmVal;
54
    uint32_t SFPImmVal;
55
    uint64_t FPImmVal;
56
  };
57
 
58
  // We only store specific operands for specific instructions
59
  // so an instruction's operand 3 may be stored within the list
60
  // of MCAOperand as element 0. This Index attribute keeps track
61
  // of the original index (3 for this example).
62
  unsigned Index;
63
 
64
public:
65
  MCAOperand() : Kind(kInvalid), FPImmVal(), Index() {}
66
 
67
  bool isValid() const { return Kind != kInvalid; }
68
  bool isReg() const { return Kind == kRegister; }
69
  bool isImm() const { return Kind == kImmediate; }
70
  bool isSFPImm() const { return Kind == kSFPImmediate; }
71
  bool isDFPImm() const { return Kind == kDFPImmediate; }
72
 
73
  /// Returns the register number.
74
  unsigned getReg() const {
75
    assert(isReg() && "This is not a register operand!");
76
    return RegVal;
77
  }
78
 
79
  int64_t getImm() const {
80
    assert(isImm() && "This is not an immediate");
81
    return ImmVal;
82
  }
83
 
84
  uint32_t getSFPImm() const {
85
    assert(isSFPImm() && "This is not an SFP immediate");
86
    return SFPImmVal;
87
  }
88
 
89
  uint64_t getDFPImm() const {
90
    assert(isDFPImm() && "This is not an FP immediate");
91
    return FPImmVal;
92
  }
93
 
94
  void setIndex(const unsigned Idx) { Index = Idx; }
95
 
96
  unsigned getIndex() const { return Index; }
97
 
98
  static MCAOperand createReg(unsigned Reg) {
99
    MCAOperand Op;
100
    Op.Kind = kRegister;
101
    Op.RegVal = Reg;
102
    return Op;
103
  }
104
 
105
  static MCAOperand createImm(int64_t Val) {
106
    MCAOperand Op;
107
    Op.Kind = kImmediate;
108
    Op.ImmVal = Val;
109
    return Op;
110
  }
111
 
112
  static MCAOperand createSFPImm(uint32_t Val) {
113
    MCAOperand Op;
114
    Op.Kind = kSFPImmediate;
115
    Op.SFPImmVal = Val;
116
    return Op;
117
  }
118
 
119
  static MCAOperand createDFPImm(uint64_t Val) {
120
    MCAOperand Op;
121
    Op.Kind = kDFPImmediate;
122
    Op.FPImmVal = Val;
123
    return Op;
124
  }
125
 
126
  static MCAOperand createInvalid() {
127
    MCAOperand Op;
128
    Op.Kind = kInvalid;
129
    Op.FPImmVal = 0;
130
    return Op;
131
  }
132
};
133
 
134
/// A register write descriptor.
135
struct WriteDescriptor {
136
  // Operand index. The index is negative for implicit writes only.
137
  // For implicit writes, the actual operand index is computed performing
138
  // a bitwise not of the OpIndex.
139
  int OpIndex;
140
  // Write latency. Number of cycles before write-back stage.
141
  unsigned Latency;
142
  // This field is set to a value different than zero only if this
143
  // is an implicit definition.
144
  MCPhysReg RegisterID;
145
  // Instruction itineraries would set this field to the SchedClass ID.
146
  // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
147
  // element associated to this write.
148
  // When computing read latencies, this value is matched against the
149
  // "ReadAdvance" information. The hardware backend may implement
150
  // dedicated forwarding paths to quickly propagate write results to dependent
151
  // instructions waiting in the reservation station (effectively bypassing the
152
  // write-back stage).
153
  unsigned SClassOrWriteResourceID;
154
  // True only if this is a write obtained from an optional definition.
155
  // Optional definitions are allowed to reference regID zero (i.e. "no
156
  // register").
157
  bool IsOptionalDef;
158
 
159
  bool isImplicitWrite() const { return OpIndex < 0; };
160
};
161
 
162
/// A register read descriptor.
163
struct ReadDescriptor {
164
  // A MCOperand index. This is used by the Dispatch logic to identify register
165
  // reads. Implicit reads have negative indices. The actual operand index of an
166
  // implicit read is the bitwise not of field OpIndex.
167
  int OpIndex;
168
  // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
169
  // uses always come first in the sequence of uses.
170
  unsigned UseIndex;
171
  // This field is only set if this is an implicit read.
172
  MCPhysReg RegisterID;
173
  // Scheduling Class Index. It is used to query the scheduling model for the
174
  // MCSchedClassDesc object.
175
  unsigned SchedClassID;
176
 
177
  bool isImplicitRead() const { return OpIndex < 0; };
178
};
179
 
180
class ReadState;
181
 
182
/// A critical data dependency descriptor.
183
///
184
/// Field RegID is set to the invalid register for memory dependencies.
185
struct CriticalDependency {
186
  unsigned IID;
187
  MCPhysReg RegID;
188
  unsigned Cycles;
189
};
190
 
191
/// Tracks uses of a register definition (e.g. register write).
192
///
193
/// Each implicit/explicit register write is associated with an instance of
194
/// this class. A WriteState object tracks the dependent users of a
195
/// register write. It also tracks how many cycles are left before the write
196
/// back stage.
197
class WriteState {
198
  const WriteDescriptor *WD;
199
  // On instruction issue, this field is set equal to the write latency.
200
  // Before instruction issue, this field defaults to -512, a special
201
  // value that represents an "unknown" number of cycles.
202
  int CyclesLeft;
203
 
204
  // Actual register defined by this write. This field is only used
205
  // to speedup queries on the register file.
206
  // For implicit writes, this field always matches the value of
207
  // field RegisterID from WD.
208
  MCPhysReg RegisterID;
209
 
210
  // Physical register file that serves register RegisterID.
211
  unsigned PRFID;
212
 
213
  // True if this write implicitly clears the upper portion of RegisterID's
214
  // super-registers.
215
  bool ClearsSuperRegs;
216
 
217
  // True if this write is from a dependency breaking zero-idiom instruction.
218
  bool WritesZero;
219
 
220
  // True if this write has been eliminated at register renaming stage.
221
  // Example: a register move doesn't consume scheduler/pipleline resources if
222
  // it is eliminated at register renaming stage. It still consumes
223
  // decode bandwidth, and ROB entries.
224
  bool IsEliminated;
225
 
226
  // This field is set if this is a partial register write, and it has a false
227
  // dependency on any previous write of the same register (or a portion of it).
228
  // DependentWrite must be able to complete before this write completes, so
229
  // that we don't break the WAW, and the two writes can be merged together.
230
  const WriteState *DependentWrite;
231
 
232
  // A partial write that is in a false dependency with this write.
233
  WriteState *PartialWrite;
234
  unsigned DependentWriteCyclesLeft;
235
 
236
  // Critical register dependency for this write.
237
  CriticalDependency CRD;
238
 
239
  // A list of dependent reads. Users is a set of dependent
240
  // reads. A dependent read is added to the set only if CyclesLeft
241
  // is "unknown". As soon as CyclesLeft is 'known', each user in the set
242
  // gets notified with the actual CyclesLeft.
243
 
244
  // The 'second' element of a pair is a "ReadAdvance" number of cycles.
245
  SmallVector<std::pair<ReadState *, int>, 4> Users;
246
 
247
public:
248
  WriteState(const WriteDescriptor &Desc, MCPhysReg RegID,
249
             bool clearsSuperRegs = false, bool writesZero = false)
250
      : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0),
251
        ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
252
        IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr),
253
        DependentWriteCyclesLeft(0), CRD() {}
254
 
255
  WriteState(const WriteState &Other) = default;
256
  WriteState &operator=(const WriteState &Other) = default;
257
 
258
  int getCyclesLeft() const { return CyclesLeft; }
259
  unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; }
260
  MCPhysReg getRegisterID() const { return RegisterID; }
261
  void setRegisterID(const MCPhysReg RegID) { RegisterID = RegID; }
262
  unsigned getRegisterFileID() const { return PRFID; }
263
  unsigned getLatency() const { return WD->Latency; }
264
  unsigned getDependentWriteCyclesLeft() const {
265
    return DependentWriteCyclesLeft;
266
  }
267
  const WriteState *getDependentWrite() const { return DependentWrite; }
268
  const CriticalDependency &getCriticalRegDep() const { return CRD; }
269
 
270
  // This method adds Use to the set of data dependent reads. IID is the
271
  // instruction identifier associated with this write. ReadAdvance is the
272
  // number of cycles to subtract from the latency of this data dependency.
273
  // Use is in a RAW dependency with this write.
274
  void addUser(unsigned IID, ReadState *Use, int ReadAdvance);
275
 
276
  // Use is a younger register write that is in a false dependency with this
277
  // write. IID is the instruction identifier associated with this write.
278
  void addUser(unsigned IID, WriteState *Use);
279
 
280
  unsigned getNumUsers() const {
281
    unsigned NumUsers = Users.size();
282
    if (PartialWrite)
283
      ++NumUsers;
284
    return NumUsers;
285
  }
286
 
287
  bool clearsSuperRegisters() const { return ClearsSuperRegs; }
288
  bool isWriteZero() const { return WritesZero; }
289
  bool isEliminated() const { return IsEliminated; }
290
 
291
  bool isReady() const {
292
    if (DependentWrite)
293
      return false;
294
    unsigned CyclesLeft = getDependentWriteCyclesLeft();
295
    return !CyclesLeft || CyclesLeft < getLatency();
296
  }
297
 
298
  bool isExecuted() const {
299
    return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
300
  }
301
 
302
  void setDependentWrite(const WriteState *Other) { DependentWrite = Other; }
303
  void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
304
  void setWriteZero() { WritesZero = true; }
305
  void setEliminated() {
306
    assert(Users.empty() && "Write is in an inconsistent state.");
307
    CyclesLeft = 0;
308
    IsEliminated = true;
309
  }
310
 
311
  void setPRF(unsigned PRF) { PRFID = PRF; }
312
 
313
  // On every cycle, update CyclesLeft and notify dependent users.
314
  void cycleEvent();
315
  void onInstructionIssued(unsigned IID);
316
 
317
#ifndef NDEBUG
318
  void dump() const;
319
#endif
320
};
321
 
322
/// Tracks register operand latency in cycles.
323
///
324
/// A read may be dependent on more than one write. This occurs when some
325
/// writes only partially update the register associated to this read.
326
class ReadState {
327
  const ReadDescriptor *RD;
328
  // Physical register identified associated to this read.
329
  MCPhysReg RegisterID;
330
  // Physical register file that serves register RegisterID.
331
  unsigned PRFID;
332
  // Number of writes that contribute to the definition of RegisterID.
333
  // In the absence of partial register updates, the number of DependentWrites
334
  // cannot be more than one.
335
  unsigned DependentWrites;
336
  // Number of cycles left before RegisterID can be read. This value depends on
337
  // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES.
338
  // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of
339
  // every dependent write is known.
340
  int CyclesLeft;
341
  // This field is updated on every writeStartEvent(). When the number of
342
  // dependent writes (i.e. field DependentWrite) is zero, this value is
343
  // propagated to field CyclesLeft.
344
  unsigned TotalCycles;
345
  // Longest register dependency.
346
  CriticalDependency CRD;
347
  // This field is set to true only if there are no dependent writes, and
348
  // there are no `CyclesLeft' to wait.
349
  bool IsReady;
350
  // True if this is a read from a known zero register.
351
  bool IsZero;
352
  // True if this register read is from a dependency-breaking instruction.
353
  bool IndependentFromDef;
354
 
355
public:
356
  ReadState(const ReadDescriptor &Desc, MCPhysReg RegID)
357
      : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0),
358
        CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true),
359
        IsZero(false), IndependentFromDef(false) {}
360
 
361
  const ReadDescriptor &getDescriptor() const { return *RD; }
362
  unsigned getSchedClass() const { return RD->SchedClassID; }
363
  MCPhysReg getRegisterID() const { return RegisterID; }
364
  unsigned getRegisterFileID() const { return PRFID; }
365
  const CriticalDependency &getCriticalRegDep() const { return CRD; }
366
 
367
  bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
368
  bool isReady() const { return IsReady; }
369
  bool isImplicitRead() const { return RD->isImplicitRead(); }
370
 
371
  bool isIndependentFromDef() const { return IndependentFromDef; }
372
  void setIndependentFromDef() { IndependentFromDef = true; }
373
 
374
  void cycleEvent();
375
  void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
376
  void setDependentWrites(unsigned Writes) {
377
    DependentWrites = Writes;
378
    IsReady = !Writes;
379
  }
380
 
381
  bool isReadZero() const { return IsZero; }
382
  void setReadZero() { IsZero = true; }
383
  void setPRF(unsigned ID) { PRFID = ID; }
384
};
385
 
386
/// A sequence of cycles.
387
///
388
/// This class can be used as a building block to construct ranges of cycles.
389
class CycleSegment {
390
  unsigned Begin; // Inclusive.
391
  unsigned End;   // Exclusive.
392
  bool Reserved;  // Resources associated to this segment must be reserved.
393
 
394
public:
395
  CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
396
      : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
397
 
398
  bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; }
399
  bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; }
400
  bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; }
401
  bool overlaps(const CycleSegment &CS) const {
402
    return !startsAfter(CS) && !endsBefore(CS);
403
  }
404
  bool isExecuting() const { return Begin == 0 && End != 0; }
405
  bool isExecuted() const { return End == 0; }
406
  bool operator<(const CycleSegment &Other) const {
407
    return Begin < Other.Begin;
408
  }
409
  CycleSegment &operator--() {
410
    if (Begin)
411
      Begin--;
412
    if (End)
413
      End--;
414
    return *this;
415
  }
416
 
417
  bool isValid() const { return Begin <= End; }
418
  unsigned size() const { return End - Begin; };
419
  void subtract(unsigned Cycles) {
420
    assert(End >= Cycles);
421
    End -= Cycles;
422
  }
423
 
424
  unsigned begin() const { return Begin; }
425
  unsigned end() const { return End; }
426
  void setEnd(unsigned NewEnd) { End = NewEnd; }
427
  bool isReserved() const { return Reserved; }
428
  void setReserved() { Reserved = true; }
429
};
430
 
431
/// Helper used by class InstrDesc to describe how hardware resources
432
/// are used.
433
///
434
/// This class describes how many resource units of a specific resource kind
435
/// (and how many cycles) are "used" by an instruction.
436
struct ResourceUsage {
437
  CycleSegment CS;
438
  unsigned NumUnits;
439
  ResourceUsage(CycleSegment Cycles, unsigned Units = 1)
440
      : CS(Cycles), NumUnits(Units) {}
441
  unsigned size() const { return CS.size(); }
442
  bool isReserved() const { return CS.isReserved(); }
443
  void setReserved() { CS.setReserved(); }
444
};
445
 
446
/// An instruction descriptor
447
struct InstrDesc {
448
  SmallVector<WriteDescriptor, 2> Writes; // Implicit writes are at the end.
449
  SmallVector<ReadDescriptor, 4> Reads;   // Implicit reads are at the end.
450
 
451
  // For every resource used by an instruction of this kind, this vector
452
  // reports the number of "consumed cycles".
453
  SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Resources;
454
 
455
  // A bitmask of used hardware buffers.
456
  uint64_t UsedBuffers;
457
 
458
  // A bitmask of used processor resource units.
459
  uint64_t UsedProcResUnits;
460
 
461
  // A bitmask of used processor resource groups.
462
  uint64_t UsedProcResGroups;
463
 
464
  unsigned MaxLatency;
465
  // Number of MicroOps for this instruction.
466
  unsigned NumMicroOps;
467
  // SchedClassID used to construct this InstrDesc.
468
  // This information is currently used by views to do fast queries on the
469
  // subtarget when computing the reciprocal throughput.
470
  unsigned SchedClassID;
471
 
472
  // True if all buffered resources are in-order, and there is at least one
473
  // buffer which is a dispatch hazard (BufferSize = 0).
474
  unsigned MustIssueImmediately : 1;
475
 
476
  // True if the corresponding mca::Instruction can be recycled. Currently only
477
  // instructions that are neither variadic nor have any variant can be
478
  // recycled.
479
  unsigned IsRecyclable : 1;
480
 
481
  // True if some of the consumed group resources are partially overlapping.
482
  unsigned HasPartiallyOverlappingGroups : 1;
483
 
484
  // A zero latency instruction doesn't consume any scheduler resources.
485
  bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
486
 
487
  InstrDesc() = default;
488
  InstrDesc(const InstrDesc &Other) = delete;
489
  InstrDesc &operator=(const InstrDesc &Other) = delete;
490
};
491
 
492
/// Base class for instructions consumed by the simulation pipeline.
493
///
494
/// This class tracks data dependencies as well as generic properties
495
/// of the instruction.
496
class InstructionBase {
497
  const InstrDesc &Desc;
498
 
499
  // This field is set for instructions that are candidates for move
500
  // elimination. For more information about move elimination, see the
501
  // definition of RegisterMappingTracker in RegisterFile.h
502
  bool IsOptimizableMove;
503
 
504
  // Output dependencies.
505
  // One entry per each implicit and explicit register definition.
506
  SmallVector<WriteState, 2> Defs;
507
 
508
  // Input dependencies.
509
  // One entry per each implicit and explicit register use.
510
  SmallVector<ReadState, 4> Uses;
511
 
512
  // List of operands which can be used by mca::CustomBehaviour
513
  std::vector<MCAOperand> Operands;
514
 
515
  // Instruction opcode which can be used by mca::CustomBehaviour
516
  unsigned Opcode;
517
 
518
  // Flags used by the LSUnit.
519
  bool IsALoadBarrier : 1;
520
  bool IsAStoreBarrier : 1;
521
  // Flags copied from the InstrDesc and potentially modified by
522
  // CustomBehaviour or (more likely) InstrPostProcess.
523
  bool MayLoad : 1;
524
  bool MayStore : 1;
525
  bool HasSideEffects : 1;
526
  bool BeginGroup : 1;
527
  bool EndGroup : 1;
528
  bool RetireOOO : 1;
529
 
530
public:
531
  InstructionBase(const InstrDesc &D, const unsigned Opcode)
532
      : Desc(D), IsOptimizableMove(false), Operands(0), Opcode(Opcode),
533
        IsALoadBarrier(false), IsAStoreBarrier(false) {}
534
 
535
  SmallVectorImpl<WriteState> &getDefs() { return Defs; }
536
  ArrayRef<WriteState> getDefs() const { return Defs; }
537
  SmallVectorImpl<ReadState> &getUses() { return Uses; }
538
  ArrayRef<ReadState> getUses() const { return Uses; }
539
  const InstrDesc &getDesc() const { return Desc; }
540
 
541
  unsigned getLatency() const { return Desc.MaxLatency; }
542
  unsigned getNumMicroOps() const { return Desc.NumMicroOps; }
543
  unsigned getOpcode() const { return Opcode; }
544
  bool isALoadBarrier() const { return IsALoadBarrier; }
545
  bool isAStoreBarrier() const { return IsAStoreBarrier; }
546
  void setLoadBarrier(bool IsBarrier) { IsALoadBarrier = IsBarrier; }
547
  void setStoreBarrier(bool IsBarrier) { IsAStoreBarrier = IsBarrier; }
548
 
549
  /// Return the MCAOperand which corresponds to index Idx within the original
550
  /// MCInst.
551
  const MCAOperand *getOperand(const unsigned Idx) const {
552
    auto It = llvm::find_if(Operands, [&Idx](const MCAOperand &Op) {
553
      return Op.getIndex() == Idx;
554
    });
555
    if (It == Operands.end())
556
      return nullptr;
557
    return &(*It);
558
  }
559
  unsigned getNumOperands() const { return Operands.size(); }
560
  void addOperand(const MCAOperand Op) { Operands.push_back(Op); }
561
 
562
  bool hasDependentUsers() const {
563
    return any_of(Defs,
564
                  [](const WriteState &Def) { return Def.getNumUsers() > 0; });
565
  }
566
 
567
  unsigned getNumUsers() const {
568
    unsigned NumUsers = 0;
569
    for (const WriteState &Def : Defs)
570
      NumUsers += Def.getNumUsers();
571
    return NumUsers;
572
  }
573
 
574
  // Returns true if this instruction is a candidate for move elimination.
575
  bool isOptimizableMove() const { return IsOptimizableMove; }
576
  void setOptimizableMove() { IsOptimizableMove = true; }
577
  void clearOptimizableMove() { IsOptimizableMove = false; }
578
  bool isMemOp() const { return MayLoad || MayStore; }
579
 
580
  // Getters and setters for general instruction flags.
581
  void setMayLoad(bool newVal) { MayLoad = newVal; }
582
  void setMayStore(bool newVal) { MayStore = newVal; }
583
  void setHasSideEffects(bool newVal) { HasSideEffects = newVal; }
584
  void setBeginGroup(bool newVal) { BeginGroup = newVal; }
585
  void setEndGroup(bool newVal) { EndGroup = newVal; }
586
  void setRetireOOO(bool newVal) { RetireOOO = newVal; }
587
 
588
  bool getMayLoad() const { return MayLoad; }
589
  bool getMayStore() const { return MayStore; }
590
  bool getHasSideEffects() const { return HasSideEffects; }
591
  bool getBeginGroup() const { return BeginGroup; }
592
  bool getEndGroup() const { return EndGroup; }
593
  bool getRetireOOO() const { return RetireOOO; }
594
};
595
 
596
/// An instruction propagated through the simulated instruction pipeline.
597
///
598
/// This class is used to monitor changes to the internal state of instructions
599
/// that are sent to the various components of the simulated hardware pipeline.
600
class Instruction : public InstructionBase {
601
  enum InstrStage {
602
    IS_INVALID,    // Instruction in an invalid state.
603
    IS_DISPATCHED, // Instruction dispatched but operands are not ready.
604
    IS_PENDING,    // Instruction is not ready, but operand latency is known.
605
    IS_READY,      // Instruction dispatched and operands ready.
606
    IS_EXECUTING,  // Instruction issued.
607
    IS_EXECUTED,   // Instruction executed. Values are written back.
608
    IS_RETIRED     // Instruction retired.
609
  };
610
 
611
  // The current instruction stage.
612
  enum InstrStage Stage;
613
 
614
  // This value defaults to the instruction latency. This instruction is
615
  // considered executed when field CyclesLeft goes to zero.
616
  int CyclesLeft;
617
 
618
  // Retire Unit token ID for this instruction.
619
  unsigned RCUTokenID;
620
 
621
  // LS token ID for this instruction.
622
  // This field is set to the invalid null token if this is not a memory
623
  // operation.
624
  unsigned LSUTokenID;
625
 
626
  // A resource mask which identifies buffered resources consumed by this
627
  // instruction at dispatch stage. In the absence of macro-fusion, this value
628
  // should always match the value of field `UsedBuffers` from the instruction
629
  // descriptor (see field InstrBase::Desc).
630
  uint64_t UsedBuffers;
631
 
632
  // Critical register dependency.
633
  CriticalDependency CriticalRegDep;
634
 
635
  // Critical memory dependency.
636
  CriticalDependency CriticalMemDep;
637
 
638
  // A bitmask of busy processor resource units.
639
  // This field is set to zero only if execution is not delayed during this
640
  // cycle because of unavailable pipeline resources.
641
  uint64_t CriticalResourceMask;
642
 
643
  // True if this instruction has been optimized at register renaming stage.
644
  bool IsEliminated;
645
 
646
public:
647
  Instruction(const InstrDesc &D, const unsigned Opcode)
648
      : InstructionBase(D, Opcode), Stage(IS_INVALID),
649
        CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0), LSUTokenID(0),
650
        UsedBuffers(D.UsedBuffers), CriticalRegDep(), CriticalMemDep(),
651
        CriticalResourceMask(0), IsEliminated(false) {}
652
 
653
  void reset();
654
 
655
  unsigned getRCUTokenID() const { return RCUTokenID; }
656
  unsigned getLSUTokenID() const { return LSUTokenID; }
657
  void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; }
658
 
659
  uint64_t getUsedBuffers() const { return UsedBuffers; }
660
  void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; }
661
  void clearUsedBuffers() { UsedBuffers = 0ULL; }
662
 
663
  int getCyclesLeft() const { return CyclesLeft; }
664
 
665
  // Transition to the dispatch stage, and assign a RCUToken to this
666
  // instruction. The RCUToken is used to track the completion of every
667
  // register write performed by this instruction.
668
  void dispatch(unsigned RCUTokenID);
669
 
670
  // Instruction issued. Transition to the IS_EXECUTING state, and update
671
  // all the register definitions.
672
  void execute(unsigned IID);
673
 
674
  // Force a transition from the IS_DISPATCHED state to the IS_READY or
675
  // IS_PENDING state. State transitions normally occur either at the beginning
676
  // of a new cycle (see method cycleEvent()), or as a result of another issue
677
  // event. This method is called every time the instruction might have changed
678
  // in state. It internally delegates to method updateDispatched() and
679
  // updateWaiting().
680
  void update();
681
  bool updateDispatched();
682
  bool updatePending();
683
 
684
  bool isInvalid() const { return Stage == IS_INVALID; }
685
  bool isDispatched() const { return Stage == IS_DISPATCHED; }
686
  bool isPending() const { return Stage == IS_PENDING; }
687
  bool isReady() const { return Stage == IS_READY; }
688
  bool isExecuting() const { return Stage == IS_EXECUTING; }
689
  bool isExecuted() const { return Stage == IS_EXECUTED; }
690
  bool isRetired() const { return Stage == IS_RETIRED; }
691
  bool isEliminated() const { return IsEliminated; }
692
 
693
  // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
694
  void forceExecuted();
695
  void setEliminated() { IsEliminated = true; }
696
 
697
  void retire() {
698
    assert(isExecuted() && "Instruction is in an invalid state!");
699
    Stage = IS_RETIRED;
700
  }
701
 
702
  const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; }
703
  const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; }
704
  const CriticalDependency &computeCriticalRegDep();
705
  void setCriticalMemDep(const CriticalDependency &MemDep) {
706
    CriticalMemDep = MemDep;
707
  }
708
 
709
  uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
710
  void setCriticalResourceMask(uint64_t ResourceMask) {
711
    CriticalResourceMask = ResourceMask;
712
  }
713
 
714
  void cycleEvent();
715
};
716
 
717
/// An InstRef contains both a SourceMgr index and Instruction pair.  The index
718
/// is used as a unique identifier for the instruction.  MCA will make use of
719
/// this index as a key throughout MCA.
720
class InstRef {
721
  std::pair<unsigned, Instruction *> Data;
722
 
723
public:
724
  InstRef() : Data(std::make_pair(0, nullptr)) {}
725
  InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
726
 
727
  bool operator==(const InstRef &Other) const { return Data == Other.Data; }
728
  bool operator!=(const InstRef &Other) const { return Data != Other.Data; }
729
  bool operator<(const InstRef &Other) const {
730
    return Data.first < Other.Data.first;
731
  }
732
 
733
  unsigned getSourceIndex() const { return Data.first; }
734
  Instruction *getInstruction() { return Data.second; }
735
  const Instruction *getInstruction() const { return Data.second; }
736
 
737
  /// Returns true if this references a valid instruction.
738
  explicit operator bool() const { return Data.second != nullptr; }
739
 
740
  /// Invalidate this reference.
741
  void invalidate() { Data.second = nullptr; }
742
 
743
#ifndef NDEBUG
744
  void print(raw_ostream &OS) const { OS << getSourceIndex(); }
745
#endif
746
};
747
 
748
#ifndef NDEBUG
749
inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) {
750
  IR.print(OS);
751
  return OS;
752
}
753
#endif
754
 
755
} // namespace mca
756
} // namespace llvm
757
 
758
#endif // LLVM_MCA_INSTRUCTION_H