Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  313.