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
//===--------------------- RegisterFile.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 a register mapping file class.  This class is responsible
11
/// for managing hardware register files and the tracking of data dependencies
12
/// between registers.
13
///
14
//===----------------------------------------------------------------------===//
15
 
16
#ifndef LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H
17
#define LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H
18
 
19
#include "llvm/ADT/APInt.h"
20
#include "llvm/ADT/SmallVector.h"
21
#include "llvm/MC/MCRegisterInfo.h"
22
#include "llvm/MC/MCSchedule.h"
23
#include "llvm/MC/MCSubtargetInfo.h"
24
#include "llvm/MCA/HardwareUnits/HardwareUnit.h"
25
 
26
namespace llvm {
27
namespace mca {
28
 
29
class ReadState;
30
class WriteState;
31
class Instruction;
32
 
33
/// A reference to a register write.
34
///
35
/// This class is mainly used by the register file to describe register
36
/// mappings. It correlates a register write to the source index of the
37
/// defining instruction.
38
class WriteRef {
39
  unsigned IID;
40
  unsigned WriteBackCycle;
41
  unsigned WriteResID;
42
  MCPhysReg RegisterID;
43
  WriteState *Write;
44
 
45
  static const unsigned INVALID_IID;
46
 
47
public:
48
  WriteRef()
49
      : IID(INVALID_IID), WriteBackCycle(), WriteResID(), RegisterID(),
50
        Write() {}
51
  WriteRef(unsigned SourceIndex, WriteState *WS);
52
 
53
  unsigned getSourceIndex() const { return IID; }
54
  unsigned getWriteBackCycle() const;
55
 
56
  const WriteState *getWriteState() const { return Write; }
57
  WriteState *getWriteState() { return Write; }
58
  unsigned getWriteResourceID() const;
59
  MCPhysReg getRegisterID() const;
60
 
61
  void commit();
62
  void notifyExecuted(unsigned Cycle);
63
 
64
  bool hasKnownWriteBackCycle() const;
65
  bool isWriteZero() const;
66
  bool isValid() const { return getSourceIndex() != INVALID_IID; }
67
 
68
  /// Returns true if this register write has been executed, and the new
69
  /// register value is therefore available to users.
70
  bool isAvailable() const { return hasKnownWriteBackCycle(); }
71
 
72
  bool operator==(const WriteRef &Other) const {
73
    return Write && Other.Write && Write == Other.Write;
74
  }
75
 
76
#ifndef NDEBUG
77
  void dump() const;
78
#endif
79
};
80
 
81
/// Manages hardware register files, and tracks register definitions for
82
/// register renaming purposes.
83
class RegisterFile : public HardwareUnit {
84
  const MCRegisterInfo &MRI;
85
 
86
  // class RegisterMappingTracker is a  physical register file (PRF) descriptor.
87
  // There is one RegisterMappingTracker for every PRF definition in the
88
  // scheduling model.
89
  //
90
  // An instance of RegisterMappingTracker tracks the number of physical
91
  // registers available for renaming. It also tracks  the number of register
92
  // moves eliminated per cycle.
93
  struct RegisterMappingTracker {
94
    // The total number of physical registers that are available in this
95
    // register file for register renaming purpouses.  A value of zero for this
96
    // field means: this register file has an unbounded number of physical
97
    // registers.
98
    const unsigned NumPhysRegs;
99
    // Number of physical registers that are currently in use.
100
    unsigned NumUsedPhysRegs;
101
 
102
    // Maximum number of register moves that can be eliminated by this PRF every
103
    // cycle. A value of zero means that there is no limit in the number of
104
    // moves which can be eliminated every cycle.
105
    const unsigned MaxMoveEliminatedPerCycle;
106
 
107
    // Number of register moves eliminated during this cycle.
108
    //
109
    // This value is increased by one every time a register move is eliminated.
110
    // Every new cycle, this value is reset to zero.
111
    // A move can be eliminated only if MaxMoveEliminatedPerCycle is zero, or if
112
    // NumMoveEliminated is less than MaxMoveEliminatedPerCycle.
113
    unsigned NumMoveEliminated;
114
 
115
    // If set, move elimination is restricted to zero-register moves only.
116
    bool AllowZeroMoveEliminationOnly;
117
 
118
    RegisterMappingTracker(unsigned NumPhysRegisters,
119
                           unsigned MaxMoveEliminated = 0U,
120
                           bool AllowZeroMoveElimOnly = false)
121
        : NumPhysRegs(NumPhysRegisters), NumUsedPhysRegs(0),
122
          MaxMoveEliminatedPerCycle(MaxMoveEliminated), NumMoveEliminated(0U),
123
          AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly) {}
124
  };
125
 
126
  // A vector of register file descriptors.  This set always contains at least
127
  // one entry. Entry at index #0 is reserved.  That entry describes a register
128
  // file with an unbounded number of physical registers that "sees" all the
129
  // hardware registers declared by the target (i.e. all the register
130
  // definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is
131
  // the target name).
132
  //
133
  // Users can limit the number of physical registers that are available in
134
  // register file #0 specifying command line flag `-register-file-size=<uint>`.
135
  SmallVector<RegisterMappingTracker, 4> RegisterFiles;
136
 
137
  // This type is used to propagate information about the owner of a register,
138
  // and the cost of allocating it in the PRF. Register cost is defined as the
139
  // number of physical registers consumed by the PRF to allocate a user
140
  // register.
141
  //
142
  // For example: on X86 BtVer2, a YMM register consumes 2 128-bit physical
143
  // registers. So, the cost of allocating a YMM register in BtVer2 is 2.
144
  using IndexPlusCostPairTy = std::pair<unsigned, unsigned>;
145
 
146
  // Struct RegisterRenamingInfo is used to map logical registers to register
147
  // files.
148
  //
149
  // There is a RegisterRenamingInfo object for every logical register defined
150
  // by the target. RegisteRenamingInfo objects are stored into vector
151
  // `RegisterMappings`, and MCPhysReg IDs can be used to reference
152
  // elements in that vector.
153
  //
154
  // Each RegisterRenamingInfo is owned by a PRF, and field `IndexPlusCost`
155
  // specifies both the owning PRF, as well as the number of physical registers
156
  // consumed at register renaming stage.
157
  //
158
  // Field `AllowMoveElimination` is set for registers that are used as
159
  // destination by optimizable register moves.
160
  //
161
  // Field `AliasRegID` is set by writes from register moves that have been
162
  // eliminated at register renaming stage. A move eliminated at register
163
  // renaming stage is effectively bypassed, and its write aliases the source
164
  // register definition.
165
  struct RegisterRenamingInfo {
166
    IndexPlusCostPairTy IndexPlusCost;
167
    MCPhysReg RenameAs;
168
    MCPhysReg AliasRegID;
169
    bool AllowMoveElimination;
170
    RegisterRenamingInfo()
171
        : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U), AliasRegID(0U),
172
          AllowMoveElimination(false) {}
173
  };
174
 
175
  // RegisterMapping objects are mainly used to track physical register
176
  // definitions and resolve data dependencies.
177
  //
178
  // Every register declared by the Target is associated with an instance of
179
  // RegisterMapping. RegisterMapping objects keep track of writes to a logical
180
  // register.  That information is used by class RegisterFile to resolve data
181
  // dependencies, and correctly set latencies for register uses.
182
  //
183
  // This implementation does not allow overlapping register files. The only
184
  // register file that is allowed to overlap with other register files is
185
  // register file #0. If we exclude register #0, every register is "owned" by
186
  // at most one register file.
187
  using RegisterMapping = std::pair<WriteRef, RegisterRenamingInfo>;
188
 
189
  // There is one entry per each register defined by the target.
190
  std::vector<RegisterMapping> RegisterMappings;
191
 
192
  // Used to track zero registers. There is one bit for each register defined by
193
  // the target. Bits are set for registers that are known to be zero.
194
  APInt ZeroRegisters;
195
 
196
  unsigned CurrentCycle;
197
 
198
  // This method creates a new register file descriptor.
199
  // The new register file owns all of the registers declared by register
200
  // classes in the 'RegisterClasses' set.
201
  //
202
  // Processor models allow the definition of RegisterFile(s) via tablegen. For
203
  // example, this is a tablegen definition for a x86 register file for
204
  // XMM[0-15] and YMM[0-15], that allows up to 60 renames (each rename costs 1
205
  // physical register).
206
  //
207
  //    def FPRegisterFile : RegisterFile<60, [VR128RegClass, VR256RegClass]>
208
  //
209
  // Here FPRegisterFile contains all the registers defined by register class
210
  // VR128RegClass and VR256RegClass. FPRegisterFile implements 60
211
  // registers which can be used for register renaming purpose.
212
  void addRegisterFile(const MCRegisterFileDesc &RF,
213
                       ArrayRef<MCRegisterCostEntry> Entries);
214
 
215
  // Consumes physical registers in each register file specified by the
216
  // `IndexPlusCostPairTy`. This method is called from `addRegisterMapping()`.
217
  void allocatePhysRegs(const RegisterRenamingInfo &Entry,
218
                        MutableArrayRef<unsigned> UsedPhysRegs);
219
 
220
  // Releases previously allocated physical registers from the register file(s).
221
  // This method is called from `invalidateRegisterMapping()`.
222
  void freePhysRegs(const RegisterRenamingInfo &Entry,
223
                    MutableArrayRef<unsigned> FreedPhysRegs);
224
 
225
  // Create an instance of RegisterMappingTracker for every register file
226
  // specified by the processor model.
227
  // If no register file is specified, then this method creates a default
228
  // register file with an unbounded number of physical registers.
229
  void initialize(const MCSchedModel &SM, unsigned NumRegs);
230
 
231
public:
232
  RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
233
               unsigned NumRegs = 0);
234
 
235
  // Collects writes that are in a RAW dependency with RS.
236
  void collectWrites(const MCSubtargetInfo &STI, const ReadState &RS,
237
                     SmallVectorImpl<WriteRef> &Writes,
238
                     SmallVectorImpl<WriteRef> &CommittedWrites) const;
239
  struct RAWHazard {
240
    MCPhysReg RegisterID;
241
    int CyclesLeft;
242
 
243
    RAWHazard() : RegisterID(), CyclesLeft() {}
244
    bool isValid() const { return RegisterID; }
245
    bool hasUnknownCycles() const { return CyclesLeft < 0; }
246
  };
247
 
248
  RAWHazard checkRAWHazards(const MCSubtargetInfo &STI,
249
                            const ReadState &RS) const;
250
 
251
  // This method updates the register mappings inserting a new register
252
  // definition. This method is also responsible for updating the number of
253
  // allocated physical registers in each register file modified by the write.
254
  // No physical regiser is allocated if this write is from a zero-idiom.
255
  void addRegisterWrite(WriteRef Write, MutableArrayRef<unsigned> UsedPhysRegs);
256
 
257
  // Collect writes that are in a data dependency with RS, and update RS
258
  // internal state.
259
  void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const;
260
 
261
  // Removes write \param WS from the register mappings.
262
  // Physical registers may be released to reflect this update.
263
  // No registers are released if this write is from a zero-idiom.
264
  void removeRegisterWrite(const WriteState &WS,
265
                           MutableArrayRef<unsigned> FreedPhysRegs);
266
 
267
  // Returns true if the PRF at index `PRFIndex` can eliminate a move from RS to
268
  // WS.
269
  bool canEliminateMove(const WriteState &WS, const ReadState &RS,
270
                        unsigned PRFIndex) const;
271
 
272
  // Returns true if this instruction can be fully eliminated at register
273
  // renaming stage. On success, this method updates the internal state of each
274
  // WriteState by setting flag `WS.isEliminated`, and by propagating the zero
275
  // flag for known zero registers. It internally uses `canEliminateMove` to
276
  // determine if a read/write pair can be eliminated. By default, it assumes a
277
  // register swap if there is more than one register definition.
278
  bool tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
279
                              MutableArrayRef<ReadState> Reads);
280
 
281
  // Checks if there are enough physical registers in the register files.
282
  // Returns a "response mask" where each bit represents the response from a
283
  // different register file.  A mask of all zeroes means that all register
284
  // files are available.  Otherwise, the mask can be used to identify which
285
  // register file was busy.  This sematic allows us to classify dispatch
286
  // stalls caused by the lack of register file resources.
287
  //
288
  // Current implementation can simulate up to 32 register files (including the
289
  // special register file at index #0).
290
  unsigned isAvailable(ArrayRef<MCPhysReg> Regs) const;
291
 
292
  // Returns the number of PRFs implemented by this processor.
293
  unsigned getNumRegisterFiles() const { return RegisterFiles.size(); }
294
 
295
  unsigned getElapsedCyclesFromWriteBack(const WriteRef &WR) const;
296
 
297
  void onInstructionExecuted(Instruction *IS);
298
 
299
  // Notify each PRF that a new cycle just started.
300
  void cycleStart();
301
 
302
  void cycleEnd() { ++CurrentCycle; }
303
 
304
#ifndef NDEBUG
305
  void dump() const;
306
#endif
307
};
308
 
309
} // namespace mca
310
} // namespace llvm
311
 
312
#endif // LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H