[llvm] 892e456 - Support a list of CostPerUse values

Christudasan Devadasan via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 28 20:46:24 PST 2021


Author: Christudasan Devadasan
Date: 2021-01-29T10:14:52+05:30
New Revision: 892e4567e1357ee10ef67ee6dfbe45aeded9d2dc

URL: https://github.com/llvm/llvm-project/commit/892e4567e1357ee10ef67ee6dfbe45aeded9d2dc
DIFF: https://github.com/llvm/llvm-project/commit/892e4567e1357ee10ef67ee6dfbe45aeded9d2dc.diff

LOG: Support a list of CostPerUse values

This patch allows targets to define multiple cost
values for each register so that the cost model
can be more flexible and better used during the
register allocation as per the target requirements.

For AMDGPU the VGPR allocation will be more efficient
if the register cost can be associated dynamically
based on the calling convention.

Reviewed By: qcolombet

Differential Revision: https://reviews.llvm.org/D86836

Added: 
    llvm/test/TableGen/RegisterInfoEmitter-regcost-list.td
    llvm/test/TableGen/RegisterInfoEmitter-regcost-tuple.td
    llvm/test/TableGen/RegisterInfoEmitter-regcost.td

Modified: 
    llvm/include/llvm/CodeGen/RegisterClassInfo.h
    llvm/include/llvm/CodeGen/TargetRegisterInfo.h
    llvm/include/llvm/Target/Target.td
    llvm/lib/CodeGen/RegAllocGreedy.cpp
    llvm/lib/CodeGen/RegisterClassInfo.cpp
    llvm/lib/Target/ARC/ARCRegisterInfo.td
    llvm/lib/Target/ARM/ARMRegisterInfo.td
    llvm/lib/Target/RISCV/RISCVRegisterInfo.td
    llvm/lib/Target/X86/X86RegisterInfo.td
    llvm/utils/TableGen/CodeGenRegisters.cpp
    llvm/utils/TableGen/CodeGenRegisters.h
    llvm/utils/TableGen/RegisterInfoEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/RegisterClassInfo.h b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
index 25b310c47621..00b853561859 100644
--- a/llvm/include/llvm/CodeGen/RegisterClassInfo.h
+++ b/llvm/include/llvm/CodeGen/RegisterClassInfo.h
@@ -66,6 +66,9 @@ class RegisterClassInfo {
 
   std::unique_ptr<unsigned[]> PSetLimits;
 
+  // The register cost values.
+  ArrayRef<uint8_t> RegCosts;
+
   // Compute all information about RC.
   void compute(const TargetRegisterClass *RC) const;
 
@@ -117,16 +120,14 @@ class RegisterClassInfo {
   }
 
   /// Get the minimum register cost in RC's allocation order.
-  /// This is the smallest value returned by TRI->getCostPerUse(Reg) for all
+  /// This is the smallest value in RegCosts[Reg] for all
   /// the registers in getOrder(RC).
-  unsigned getMinCost(const TargetRegisterClass *RC) {
-    return get(RC).MinCost;
-  }
+  uint8_t getMinCost(const TargetRegisterClass *RC) { return get(RC).MinCost; }
 
   /// Get the position of the last cost change in getOrder(RC).
   ///
   /// All registers in getOrder(RC).slice(getLastCostChange(RC)) will have the
-  /// same cost according to TRI->getCostPerUse().
+  /// same cost according to RegCosts[Reg].
   unsigned getLastCostChange(const TargetRegisterClass *RC) {
     return get(RC).LastCostChange;
   }

diff  --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 8790e2f09eb6..0e9f89a22f64 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -209,8 +209,10 @@ class TargetRegisterClass {
 /// Extra information, not in MCRegisterDesc, about registers.
 /// These are used by codegen, not by MC.
 struct TargetRegisterInfoDesc {
-  unsigned CostPerUse;          // Extra cost of instructions using register.
-  bool inAllocatableClass;      // Register belongs to an allocatable regclass.
+  const uint8_t *CostPerUse; // Extra cost of instructions using register.
+  unsigned NumCosts; // Number of cost values associated with each register.
+  const bool
+      *InAllocatableClass; // Register belongs to an allocatable regclass.
 };
 
 /// Each TargetRegisterClass has a per register weight, and weight
@@ -329,15 +331,19 @@ class TargetRegisterInfo : public MCRegisterInfo {
   BitVector getAllocatableSet(const MachineFunction &MF,
                               const TargetRegisterClass *RC = nullptr) const;
 
-  /// Return the additional cost of using this register instead
-  /// of other registers in its class.
-  unsigned getCostPerUse(MCRegister RegNo) const {
-    return InfoDesc[RegNo].CostPerUse;
+  /// Get a list of cost values for all registers that correspond to the index
+  /// returned by RegisterCostTableIndex.
+  ArrayRef<uint8_t> getRegisterCosts(const MachineFunction &MF) const {
+    unsigned Idx = getRegisterCostTableIndex(MF);
+    unsigned NumRegs = getNumRegs();
+    assert(Idx < InfoDesc->NumCosts && "CostPerUse index out of bounds");
+
+    return makeArrayRef(&InfoDesc->CostPerUse[Idx * NumRegs], NumRegs);
   }
 
   /// Return true if the register is in the allocation of any register class.
   bool isInAllocatableClass(MCRegister RegNo) const {
-    return InfoDesc[RegNo].inAllocatableClass;
+    return InfoDesc->InAllocatableClass[RegNo];
   }
 
   /// Return the human-readable symbolic target-specific
@@ -648,6 +654,13 @@ class TargetRegisterInfo : public MCRegisterInfo {
     llvm_unreachable("Target has no sub-registers");
   }
 
+  /// Return the register cost table index. This implementation is sufficient
+  /// for most architectures and can be overriden by targets in case there are
+  /// multiple cost values associated with each register.
+  virtual unsigned getRegisterCostTableIndex(const MachineFunction &MF) const {
+    return 0;
+  }
+
 public:
   /// Find a common super-register class if it exists.
   ///

diff  --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 1c97d70a477f..332de74d4cc3 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -168,8 +168,15 @@ class Register<string n, list<string> altNames = []> {
   // minimize the number of instructions using a register with a CostPerUse.
   // This is used by the ARC target, by the ARM Thumb and x86-64 targets, where
   // some registers require larger instruction encodings, by the RISC-V target,
-  // where some registers preclude using some C instructions.
-  int CostPerUse = 0;
+  // where some registers preclude using some C instructions. By making it a
+  // list, targets can have multiple cost models associated with each register
+  // and can choose one specific cost model per Machine Function by overriding
+  // TargetRegisterInfo::getRegisterCostTableIndex. Every target register will
+  // finally have an equal number of cost values which is the max of costPerUse
+  // values specified. Any mismatch in the cost values for a register will be
+  // filled with zeros. Restricted the cost type to uint8_t in the
+  // generated table. It will considerably reduce the table size.
+  list<int> CostPerUse = [0];
 
   // CoveredBySubRegs - When this bit is set, the value of this register is
   // completely determined by the value of its sub-registers.  For example, the

diff  --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index 166414e4ffa1..7d671e635baa 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -406,6 +406,10 @@ class RAGreedy : public MachineFunctionPass,
   /// Set of broken hints that may be reconciled later because of eviction.
   SmallSetVector<LiveInterval *, 8> SetOfBrokenHints;
 
+  /// The register cost values. This list will be recreated for each Machine
+  /// Function
+  ArrayRef<uint8_t> RegCosts;
+
 public:
   RAGreedy();
 
@@ -482,9 +486,9 @@ class RAGreedy : public MachineFunctionPass,
   Register tryAssign(LiveInterval&, AllocationOrder&,
                      SmallVectorImpl<Register>&,
                      const SmallVirtRegSet&);
-  unsigned tryEvict(LiveInterval&, AllocationOrder&,
-                    SmallVectorImpl<Register>&, unsigned,
-                    const SmallVirtRegSet&);
+  unsigned tryEvict(LiveInterval &, AllocationOrder &,
+                    SmallVectorImpl<Register> &, uint8_t,
+                    const SmallVirtRegSet &);
   MCRegister tryRegionSplit(LiveInterval &, AllocationOrder &,
                             SmallVectorImpl<Register> &);
   /// Calculate cost of region splitting.
@@ -501,7 +505,7 @@ class RAGreedy : public MachineFunctionPass,
   /// time.
   MCRegister tryAssignCSRFirstTime(LiveInterval &VirtReg,
                                    AllocationOrder &Order, MCRegister PhysReg,
-                                   unsigned &CostPerUseLimit,
+                                   uint8_t &CostPerUseLimit,
                                    SmallVectorImpl<Register> &NewVRegs);
   void initializeCSRCost();
   unsigned tryBlockSplit(LiveInterval&, AllocationOrder&,
@@ -797,7 +801,7 @@ Register RAGreedy::tryAssign(LiveInterval &VirtReg,
     }
 
   // Try to evict interference from a cheaper alternative.
-  unsigned Cost = TRI->getCostPerUse(PhysReg);
+  uint8_t Cost = RegCosts[PhysReg];
 
   // Most registers have 0 additional cost.
   if (!Cost)
@@ -1109,10 +1113,9 @@ bool RAGreedy::isUnusedCalleeSavedReg(MCRegister PhysReg) const {
 /// @param  VirtReg Currently unassigned virtual register.
 /// @param  Order   Physregs to try.
 /// @return         Physreg to assign VirtReg, or 0.
-unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
-                            AllocationOrder &Order,
+unsigned RAGreedy::tryEvict(LiveInterval &VirtReg, AllocationOrder &Order,
                             SmallVectorImpl<Register> &NewVRegs,
-                            unsigned CostPerUseLimit,
+                            uint8_t CostPerUseLimit,
                             const SmallVirtRegSet &FixedRegisters) {
   NamedRegionTimer T("evict", "Evict", TimerGroupName, TimerGroupDescription,
                      TimePassesIsEnabled);
@@ -1125,13 +1128,13 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
 
   // When we are just looking for a reduced cost per use, don't break any
   // hints, and only evict smaller spill weights.
-  if (CostPerUseLimit < ~0u) {
+  if (CostPerUseLimit < uint8_t(~0u)) {
     BestCost.BrokenHints = 0;
     BestCost.MaxWeight = VirtReg.weight();
 
     // Check of any registers in RC are below CostPerUseLimit.
     const TargetRegisterClass *RC = MRI->getRegClass(VirtReg.reg());
-    unsigned MinCost = RegClassInfo.getMinCost(RC);
+    uint8_t MinCost = RegClassInfo.getMinCost(RC);
     if (MinCost >= CostPerUseLimit) {
       LLVM_DEBUG(dbgs() << TRI->getRegClassName(RC) << " minimum cost = "
                         << MinCost << ", no cheaper registers to be found.\n");
@@ -1140,7 +1143,7 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
 
     // It is normal for register classes to have a long tail of registers with
     // the same cost. We don't need to look at them if they're too expensive.
-    if (TRI->getCostPerUse(Order.getOrder().back()) >= CostPerUseLimit) {
+    if (RegCosts[Order.getOrder().back()] >= CostPerUseLimit) {
       OrderLimit = RegClassInfo.getLastCostChange(RC);
       LLVM_DEBUG(dbgs() << "Only trying the first " << OrderLimit
                         << " regs.\n");
@@ -1151,7 +1154,7 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
        ++I) {
     MCRegister PhysReg = *I;
     assert(PhysReg);
-    if (TRI->getCostPerUse(PhysReg) >= CostPerUseLimit)
+    if (RegCosts[PhysReg] >= CostPerUseLimit)
       continue;
     // The first use of a callee-saved register in a function has cost 1.
     // Don't start using a CSR when the CostPerUseLimit is low.
@@ -2793,7 +2796,7 @@ MCRegister RAGreedy::selectOrSplit(LiveInterval &VirtReg,
 /// to use the CSR; otherwise return 0.
 MCRegister
 RAGreedy::tryAssignCSRFirstTime(LiveInterval &VirtReg, AllocationOrder &Order,
-                                MCRegister PhysReg, unsigned &CostPerUseLimit,
+                                MCRegister PhysReg, uint8_t &CostPerUseLimit,
                                 SmallVectorImpl<Register> &NewVRegs) {
   if (getStage(VirtReg) == RS_Spill && VirtReg.isSpillable()) {
     // We choose spill over using the CSR for the first time if the spill cost
@@ -3024,7 +3027,7 @@ MCRegister RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
                                        SmallVectorImpl<Register> &NewVRegs,
                                        SmallVirtRegSet &FixedRegisters,
                                        unsigned Depth) {
-  unsigned CostPerUseLimit = ~0u;
+  uint8_t CostPerUseLimit = uint8_t(~0u);
   // First try assigning a free register.
   auto Order =
       AllocationOrder::create(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
@@ -3241,6 +3244,8 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
 
   initializeCSRCost();
 
+  RegCosts = TRI->getRegisterCosts(*MF);
+
   VRAI = std::make_unique<VirtRegAuxInfo>(*MF, *LIS, *VRM, *Loops, *MBFI);
 
   VRAI->calculateSpillWeightsAndHints();

diff  --git a/llvm/lib/CodeGen/RegisterClassInfo.cpp b/llvm/lib/CodeGen/RegisterClassInfo.cpp
index 0488db3d09cb..797899fb5b86 100644
--- a/llvm/lib/CodeGen/RegisterClassInfo.cpp
+++ b/llvm/lib/CodeGen/RegisterClassInfo.cpp
@@ -68,6 +68,8 @@ void RegisterClassInfo::runOnMachineFunction(const MachineFunction &mf) {
   }
   CalleeSavedRegs = CSR;
 
+  RegCosts = TRI->getRegisterCosts(*MF);
+
   // Different reserved registers?
   const BitVector &RR = MF->getRegInfo().getReservedRegs();
   if (Reserved.size() != RR.size() || RR != Reserved) {
@@ -100,8 +102,8 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
 
   unsigned N = 0;
   SmallVector<MCPhysReg, 16> CSRAlias;
-  unsigned MinCost = 0xff;
-  unsigned LastCost = ~0u;
+  uint8_t MinCost = uint8_t(~0u);
+  uint8_t LastCost = uint8_t(~0u);
   unsigned LastCostChange = 0;
 
   // FIXME: Once targets reserve registers instead of removing them from the
@@ -112,7 +114,7 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
     // Remove reserved registers from the allocation order.
     if (Reserved.test(PhysReg))
       continue;
-    unsigned Cost = TRI->getCostPerUse(PhysReg);
+    uint8_t Cost = RegCosts[PhysReg];
     MinCost = std::min(MinCost, Cost);
 
     if (CalleeSavedAliases[PhysReg] &&
@@ -132,7 +134,7 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
   // CSR aliases go after the volatile registers, preserve the target's order.
   for (unsigned i = 0, e = CSRAlias.size(); i != e; ++i) {
     unsigned PhysReg = CSRAlias[i];
-    unsigned Cost = TRI->getCostPerUse(PhysReg);
+    uint8_t Cost = RegCosts[PhysReg];
     if (Cost != LastCost)
       LastCostChange = N;
     RCI.Order[N++] = PhysReg;
@@ -149,7 +151,7 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
     if (Super != RC && getNumAllocatableRegs(Super) > RCI.NumRegs)
       RCI.ProperSubClass = true;
 
-  RCI.MinCost = uint8_t(MinCost);
+  RCI.MinCost = MinCost;
   RCI.LastCostChange = LastCostChange;
 
   LLVM_DEBUG({

diff  --git a/llvm/lib/Target/ARC/ARCRegisterInfo.td b/llvm/lib/Target/ARC/ARCRegisterInfo.td
index 82fdccc51466..5f2bc7974dde 100644
--- a/llvm/lib/Target/ARC/ARCRegisterInfo.td
+++ b/llvm/lib/Target/ARC/ARCRegisterInfo.td
@@ -29,7 +29,7 @@ def R0 : Core< 0, "%r0">, DwarfRegNum<[0]>;
 def R1 : Core< 1, "%r1">, DwarfRegNum<[1]>;
 def R2 : Core< 2, "%r2">, DwarfRegNum<[2]>;
 def R3 : Core< 3, "%r3">, DwarfRegNum<[3]>;
-let CostPerUse=1 in {
+let CostPerUse=[1] in {
 def R4 : Core< 4, "%r4">, DwarfRegNum<[4]>;
 def R5 : Core< 5, "%r5">, DwarfRegNum<[5]>;
 def R6 : Core< 6, "%r6">, DwarfRegNum<[6]>;
@@ -44,7 +44,7 @@ def R13 : Core<13, "%r13">, DwarfRegNum<[13]>;
 def R14 : Core<14, "%r14">, DwarfRegNum<[14]>;
 def R15 : Core<15, "%r15">, DwarfRegNum<[15]>;
 
-let CostPerUse=1 in {
+let CostPerUse=[1] in {
 def R16 : Core<16, "%r16">, DwarfRegNum<[16]>;
 def R17 : Core<17, "%r17">, DwarfRegNum<[17]>;
 def R18 : Core<18, "%r18">, DwarfRegNum<[18]>;

diff  --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
index fe3243315d68..b37988232127 100644
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -83,7 +83,7 @@ def R5  : ARMReg< 5, "r5">,  DwarfRegNum<[5]>;
 def R6  : ARMReg< 6, "r6">,  DwarfRegNum<[6]>;
 def R7  : ARMReg< 7, "r7">,  DwarfRegNum<[7]>;
 // These require 32-bit instructions.
-let CostPerUse = 1 in {
+let CostPerUse = [1] in {
 def R8  : ARMReg< 8, "r8">,  DwarfRegNum<[8]>;
 def R9  : ARMReg< 9, "r9">,  DwarfRegNum<[9]>;
 def R10 : ARMReg<10, "r10">, DwarfRegNum<[10]>;

diff  --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index e1a11fd9389f..522722024435 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -78,7 +78,7 @@ def sub_vrm4_1 : SubRegIndex<256, -1>;
 
 let RegAltNameIndices = [ABIRegAltName] in {
   def X0  : RISCVReg<0, "x0", ["zero"]>, DwarfRegNum<[0]>;
-  let CostPerUse = 1 in {
+  let CostPerUse = [1] in {
   def X1  : RISCVReg<1, "x1", ["ra"]>, DwarfRegNum<[1]>;
   def X2  : RISCVReg<2, "x2", ["sp"]>, DwarfRegNum<[2]>;
   def X3  : RISCVReg<3, "x3", ["gp"]>, DwarfRegNum<[3]>;
@@ -95,7 +95,7 @@ let RegAltNameIndices = [ABIRegAltName] in {
   def X13 : RISCVReg<13,"x13", ["a3"]>, DwarfRegNum<[13]>;
   def X14 : RISCVReg<14,"x14", ["a4"]>, DwarfRegNum<[14]>;
   def X15 : RISCVReg<15,"x15", ["a5"]>, DwarfRegNum<[15]>;
-  let CostPerUse = 1 in {
+  let CostPerUse = [1] in {
   def X16 : RISCVReg<16,"x16", ["a6"]>, DwarfRegNum<[16]>;
   def X17 : RISCVReg<17,"x17", ["a7"]>, DwarfRegNum<[17]>;
   def X18 : RISCVReg<18,"x18", ["s2"]>, DwarfRegNum<[18]>;

diff  --git a/llvm/lib/Target/X86/X86RegisterInfo.td b/llvm/lib/Target/X86/X86RegisterInfo.td
index 75cbd4e1cff1..47810b98e03b 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.td
+++ b/llvm/lib/Target/X86/X86RegisterInfo.td
@@ -61,7 +61,7 @@ def CH : X86Reg<"ch", 5>;
 def BH : X86Reg<"bh", 7>;
 
 // X86-64 only, requires REX.
-let CostPerUse = 1 in {
+let CostPerUse = [1] in {
 def SIL  : X86Reg<"sil",   6>;
 def DIL  : X86Reg<"dil",   7>;
 def BPL  : X86Reg<"bpl",   5>;
@@ -126,7 +126,7 @@ def SP : X86Reg<"sp", 4, [SPL,SPH]>;
 def IP : X86Reg<"ip", 0>;
 
 // X86-64 only, requires REX.
-let SubRegIndices = [sub_8bit, sub_8bit_hi_phony], CostPerUse = 1,
+let SubRegIndices = [sub_8bit, sub_8bit_hi_phony], CostPerUse = [1],
     CoveredBySubRegs = 1 in {
 def R8W  : X86Reg<"r8w",   8, [R8B,R8BH]>;
 def R9W  : X86Reg<"r9w",   9, [R9B,R9BH]>;
@@ -152,7 +152,7 @@ def EIP : X86Reg<"eip", 0, [IP, HIP]>, DwarfRegNum<[-2, 8, 8]>;
 }
 
 // X86-64 only, requires REX
-let SubRegIndices = [sub_16bit, sub_16bit_hi], CostPerUse = 1,
+let SubRegIndices = [sub_16bit, sub_16bit_hi], CostPerUse = [1],
     CoveredBySubRegs = 1 in {
 def R8D  : X86Reg<"r8d",   8, [R8W,R8WH]>;
 def R9D  : X86Reg<"r9d",   9, [R9W,R9WH]>;
@@ -176,7 +176,7 @@ def RBP : X86Reg<"rbp", 5, [EBP]>, DwarfRegNum<[6, -2, -2]>;
 def RSP : X86Reg<"rsp", 4, [ESP]>, DwarfRegNum<[7, -2, -2]>;
 
 // These also require REX.
-let CostPerUse = 1 in {
+let CostPerUse = [1] in {
 def R8  : X86Reg<"r8",   8, [R8D]>,  DwarfRegNum<[ 8, -2, -2]>;
 def R9  : X86Reg<"r9",   9, [R9D]>,  DwarfRegNum<[ 9, -2, -2]>;
 def R10 : X86Reg<"r10", 10, [R10D]>, DwarfRegNum<[10, -2, -2]>;
@@ -219,7 +219,7 @@ def XMM6: X86Reg<"xmm6", 6>, DwarfRegNum<[23, 27, 27]>;
 def XMM7: X86Reg<"xmm7", 7>, DwarfRegNum<[24, 28, 28]>;
 
 // X86-64 only
-let CostPerUse = 1 in {
+let CostPerUse = [1] in {
 def XMM8:  X86Reg<"xmm8",   8>, DwarfRegNum<[25, -2, -2]>;
 def XMM9:  X86Reg<"xmm9",   9>, DwarfRegNum<[26, -2, -2]>;
 def XMM10: X86Reg<"xmm10", 10>, DwarfRegNum<[27, -2, -2]>;

diff  --git a/llvm/test/TableGen/RegisterInfoEmitter-regcost-list.td b/llvm/test/TableGen/RegisterInfoEmitter-regcost-list.td
new file mode 100644
index 000000000000..ead51fb44cad
--- /dev/null
+++ b/llvm/test/TableGen/RegisterInfoEmitter-regcost-list.td
@@ -0,0 +1,34 @@
+// RUN: llvm-tblgen -gen-register-info -I %p/../../include -I %p/Common %s | FileCheck %s
+
+// Checks two CostPerUse values for the registers.
+include "llvm/Target/Target.td"
+
+let Namespace = "MyTarget" in {
+  foreach Index = 0-3 in {
+    // Adding two cost values per register.
+    let CostPerUse = [1, Index] in {
+      def S#Index : Register <"s"#Index>;
+    }
+  }
+
+  // CostPerUse by default to 0.
+  def D0 : Register<"d0">;
+  def D1 : Register<"d1">;
+
+} // Namespace = "MyTarget"
+
+def SRegs : RegisterClass<"MyTarget", [i32], 32, (sequence "S%u", 0, 3)>;
+def DRegs : RegisterClass<"MyTarget", [i32], 32, (sequence "D%u", 0, 1)>;
+
+def MyTarget : Target;
+
+// CHECK:  static const uint8_t CostPerUseTable[] = {
+// CHECK-NEXT:  0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 2, 3, };
+
+// CHECK:  static const bool InAllocatableClassTable[] = {
+// CHECK-NEXT:  false, true, true, true, true, true, true, };
+
+// CHECK:  static const TargetRegisterInfoDesc MyTargetRegInfoDesc = { // Extra Descriptors
+// CHECK-NEXT:  CostPerUseTable, 2, InAllocatableClassTable};
+
+// CHECK:  TargetRegisterInfo(&MyTargetRegInfoDesc, RegisterClasses, RegisterClasses+2,

diff  --git a/llvm/test/TableGen/RegisterInfoEmitter-regcost-tuple.td b/llvm/test/TableGen/RegisterInfoEmitter-regcost-tuple.td
new file mode 100644
index 000000000000..e2a49c11c36e
--- /dev/null
+++ b/llvm/test/TableGen/RegisterInfoEmitter-regcost-tuple.td
@@ -0,0 +1,71 @@
+// RUN: llvm-tblgen -gen-register-info -I %p/../../include -I %p/Common %s | FileCheck %s
+
+// Checks the cost values for the register tuple.
+include "llvm/Target/Target.td"
+
+class MyClass<int size, list<ValueType> types, dag registers>
+  : RegisterClass<"MyTarget", types, size, registers> {
+  let Size = size;
+}
+
+class Indexes<int N> {
+  list<int> all = [0,  1,  2,  3];
+  list<int> slice =
+    !foldl([]<int>, all, acc, cur,
+           !listconcat(acc, !if(!lt(cur, N), [cur], [])));
+}
+
+foreach Index = 0-3 in {
+  def sub#Index : SubRegIndex<32, !shl(Index, 5)>;
+}
+
+foreach Size = {2,4} in {
+  foreach Index = Indexes<!add(5, !mul(Size, -1))>.slice in {
+    def !foldl("", Indexes<Size>.slice, acc, cur,
+               !strconcat(acc#!if(!eq(acc,""),"","_"), "sub"#!add(cur, Index))) :
+      SubRegIndex<!mul(Size, 32), !shl(Index, 5)> {
+      let CoveringSubRegIndices =
+        !foldl([]<SubRegIndex>, Indexes<Size>.slice, acc, cur,
+               !listconcat(acc, [!cast<SubRegIndex>(sub#!add(cur, Index))]));
+    }
+  }
+}
+
+let Namespace = "MyTarget" in {
+  foreach Index = 0-15 in {
+    // Adding two cost values per register.
+    let CostPerUse = [Index, !shl(Index, 1)] in {
+      def S#Index : Register <"s"#Index>;
+    }
+  }
+} // Namespace = "MyTarget"
+
+def GPR32 : MyClass<32,  [i32], (sequence "S%u", 0, 15)>;
+
+def GPR64 : RegisterTuples<[sub0, sub1],
+                           [(decimate (shl GPR32, 0), 1),
+                            (decimate (shl GPR32, 1), 1)
+                           ]>;
+
+def GPR128 : RegisterTuples<[sub0, sub1, sub2, sub3],
+                            [
+                             (decimate (shl GPR32, 0), 1),
+                             (decimate (shl GPR32, 1), 1),
+                             (decimate (shl GPR32, 2), 1),
+                             (decimate (shl GPR32, 3), 1)
+                            ]>;
+
+
+def GPR_64 : MyClass<64, [v2i32], (add GPR64)>;
+def GPR_128 : MyClass<128, [v4i32], (add GPR128)>;
+
+
+def MyTarget : Target;
+
+// CHECK: static const uint8_t CostPerUseTable[] = {
+// CHECK-NEXT:  0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, };
+
+// CHECK:  static const TargetRegisterInfoDesc MyTargetRegInfoDesc = { // Extra Descriptors
+// CHECK-NEXT:  CostPerUseTable, 2, InAllocatableClassTable};
+
+// CHECK:  TargetRegisterInfo(&MyTargetRegInfoDesc, RegisterClasses, RegisterClasses+3,

diff  --git a/llvm/test/TableGen/RegisterInfoEmitter-regcost.td b/llvm/test/TableGen/RegisterInfoEmitter-regcost.td
new file mode 100644
index 000000000000..e039bc686fd8
--- /dev/null
+++ b/llvm/test/TableGen/RegisterInfoEmitter-regcost.td
@@ -0,0 +1,36 @@
+// RUN: llvm-tblgen -gen-register-info -I %p/../../include -I %p/Common %s | FileCheck %s
+
+// Checks the CostPerUse value for the registers.
+include "llvm/Target/Target.td"
+
+let Namespace = "MyTarget" in {
+
+  foreach Index = 0-3 in {
+    // Adds register cost value 1.
+    let CostPerUse = [1] in {
+      def S#Index : Register <"s"#Index>;
+    }
+  }
+
+  // CostPerUse by default to 0.
+  def D0 : Register<"d0">;
+  def D1 : Register<"d1">;
+
+} // Namespace = "MyTarget"
+
+
+def SRegs : RegisterClass<"MyTarget", [i32], 32, (sequence "S%u", 0, 3)>;
+def DRegs : RegisterClass<"MyTarget", [i32], 32, (sequence "D%u", 0, 1)>;
+
+def MyTarget : Target;
+
+// CHECK:  static const uint8_t CostPerUseTable[] = {
+// CHECK-NEXT:  0, 0, 0, 1, 1, 1, 1, };
+
+// CHECK:  static const bool InAllocatableClassTable[] = {
+// CHECK-NEXT:  false, true, true, true, true, true, true, };
+
+// CHECK:  static const TargetRegisterInfoDesc MyTargetRegInfoDesc = { // Extra Descriptors
+// CHECK-NEXT:  CostPerUseTable, 1, InAllocatableClassTable};
+
+// CHECK:  TargetRegisterInfo(&MyTargetRegInfoDesc, RegisterClasses, RegisterClasses+2,

diff  --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp
index f9a7ba6bba80..d0c9db4eaef6 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -154,14 +154,11 @@ void CodeGenSubRegIndex::computeConcatTransitiveClosure() {
 //===----------------------------------------------------------------------===//
 
 CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
-  : TheDef(R),
-    EnumValue(Enum),
-    CostPerUse(R->getValueAsInt("CostPerUse")),
-    CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
-    HasDisjunctSubRegs(false),
-    SubRegsComplete(false),
-    SuperRegsComplete(false),
-    TopoSig(~0u) {
+    : TheDef(R), EnumValue(Enum),
+      CostPerUse(R->getValueAsListOfInts("CostPerUse")),
+      CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
+      HasDisjunctSubRegs(false), SubRegsComplete(false),
+      SuperRegsComplete(false), TopoSig(~0u) {
   Artificial = R->getValueAsBit("isArtificial");
 }
 
@@ -646,16 +643,18 @@ struct TupleExpander : SetTheory::Expander {
       std::string Name;
       Record *Proto = Lists[0][n];
       std::vector<Init*> Tuple;
-      unsigned CostPerUse = 0;
       for (unsigned i = 0; i != Dim; ++i) {
         Record *Reg = Lists[i][n];
         if (i) Name += '_';
         Name += Reg->getName();
         Tuple.push_back(DefInit::get(Reg));
-        CostPerUse = std::max(CostPerUse,
-                              unsigned(Reg->getValueAsInt("CostPerUse")));
       }
 
+      // Take the cost list of the first register in the tuple.
+      ListInit *CostList = Proto->getValueAsListInit("CostPerUse");
+      SmallVector<Init *, 2> CostPerUse;
+      CostPerUse.insert(CostPerUse.end(), CostList->begin(), CostList->end());
+
       StringInit *AsmName = StringInit::get("");
       if (!RegNames.empty()) {
         if (RegNames.size() <= n)
@@ -697,7 +696,7 @@ struct TupleExpander : SetTheory::Expander {
 
         // CostPerUse is aggregated from all Tuple members.
         if (Field == "CostPerUse")
-          RV.setValue(IntInit::get(CostPerUse));
+          RV.setValue(ListInit::get(CostPerUse, CostList->getElementType()));
 
         // Composite registers are always covered by sub-registers.
         if (Field == "CoveredBySubRegs")

diff  --git a/llvm/utils/TableGen/CodeGenRegisters.h b/llvm/utils/TableGen/CodeGenRegisters.h
index 5228e6518fe5..f1712d663dd0 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.h
+++ b/llvm/utils/TableGen/CodeGenRegisters.h
@@ -151,7 +151,7 @@ namespace llvm {
   struct CodeGenRegister {
     Record *TheDef;
     unsigned EnumValue;
-    unsigned CostPerUse;
+    std::vector<int64_t> CostPerUse;
     bool CoveredBySubRegs;
     bool HasDisjunctSubRegs;
     bool Artificial;

diff  --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index dce7594dec2f..ad60295f0afc 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -1441,19 +1441,52 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
 
   // Emit extra information about registers.
   const std::string &TargetName = std::string(Target.getName());
-  OS << "\nstatic const TargetRegisterInfoDesc "
-     << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n";
-  OS << "  { 0, false },\n";
-
   const auto &Regs = RegBank.getRegisters();
+  unsigned NumRegCosts = 1;
+  for (const auto &Reg : Regs)
+    NumRegCosts = std::max((size_t)NumRegCosts, Reg.CostPerUse.size());
+
+  std::vector<unsigned> AllRegCostPerUse;
+  llvm::BitVector InAllocClass(Regs.size() + 1, false);
+  AllRegCostPerUse.insert(AllRegCostPerUse.end(), NumRegCosts, 0);
+
+  // Populate the vector RegCosts with the CostPerUse list of the registers
+  // in the order they are read. Have at most NumRegCosts entries for
+  // each register. Fill with zero for values which are not explicitly given.
   for (const auto &Reg : Regs) {
-    OS << "  { ";
-    OS << Reg.CostPerUse << ", "
-       << ( AllocatableRegs.count(Reg.TheDef) != 0 ? "true" : "false" )
-       << " },\n";
+    auto Costs = Reg.CostPerUse;
+    AllRegCostPerUse.insert(AllRegCostPerUse.end(), Costs.begin(), Costs.end());
+    if (NumRegCosts > Costs.size())
+      AllRegCostPerUse.insert(AllRegCostPerUse.end(),
+                              NumRegCosts - Costs.size(), 0);
+
+    if (AllocatableRegs.count(Reg.TheDef))
+      InAllocClass.set(Reg.EnumValue);
+  }
+
+  // Emit the cost values as a 1D-array after grouping them by their indices,
+  // i.e. the costs for all registers corresponds to index 0, 1, 2, etc.
+  // Size of the emitted array should be NumRegCosts * (Regs.size() + 1).
+  OS << "\nstatic const uint8_t "
+     << "CostPerUseTable[] = { \n";
+  for (unsigned int I = 0; I < NumRegCosts; ++I) {
+    for (unsigned J = I, E = AllRegCostPerUse.size(); J < E; J += NumRegCosts)
+      OS << AllRegCostPerUse[J] << ", ";
   }
-  OS << "};\n";      // End of register descriptors...
+  OS << "};\n\n";
 
+  OS << "\nstatic const bool "
+     << "InAllocatableClassTable[] = { \n";
+  for (unsigned I = 0, E = InAllocClass.size(); I < E; ++I) {
+    OS << (InAllocClass[I] ? "true" : "false") << ", ";
+  }
+  OS << "};\n\n";
+
+  OS << "\nstatic const TargetRegisterInfoDesc " << TargetName
+     << "RegInfoDesc = { // Extra Descriptors\n";
+  OS << "CostPerUseTable, " << NumRegCosts << ", "
+     << "InAllocatableClassTable";
+  OS << "};\n\n"; // End of register descriptors...
 
   std::string ClassName = Target.getName().str() + "GenRegisterInfo";
 
@@ -1513,10 +1546,11 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
 
   EmitRegMappingTables(OS, Regs, true);
 
-  OS << ClassName << "::\n" << ClassName
+  OS << ClassName << "::\n"
+     << ClassName
      << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour,\n"
         "      unsigned PC, unsigned HwMode)\n"
-     << "  : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
+     << "  : TargetRegisterInfo(&" << TargetName << "RegInfoDesc"
      << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() << ",\n"
      << "             SubRegIndexNameTable, SubRegIndexLaneMaskTable,\n"
      << "             ";
@@ -1679,7 +1713,10 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
 
   for (const CodeGenRegister &R : RegBank.getRegisters()) {
     OS << "Register " << R.getName() << ":\n";
-    OS << "\tCostPerUse: " << R.CostPerUse << '\n';
+    OS << "\tCostPerUse: ";
+    for (const auto &Cost : R.CostPerUse)
+      OS << Cost << " ";
+    OS << '\n';
     OS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n';
     OS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n';
     for (std::pair<CodeGenSubRegIndex*,CodeGenRegister*> P : R.getSubRegs()) {


        


More information about the llvm-commits mailing list