[llvm] [CodeGen] Merge TargetRegClass into MCRegClass (PR #207168)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 2 05:45:52 PDT 2026
https://github.com/aengelke updated https://github.com/llvm/llvm-project/pull/207168
>From b42a6544129104a833e21439b3cbb86b5cb7e0b9 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Thu, 2 Jul 2026 12:41:38 +0000
Subject: [PATCH 1/2] [spr] initial version
Created using spr 1.3.8-wip
---
llvm/include/llvm/CodeGen/FastISel.h | 3 +-
.../include/llvm/CodeGen/GlobalISel/CSEInfo.h | 3 +-
.../CodeGen/GlobalISel/MachineIRBuilder.h | 3 +-
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | 3 +-
llvm/include/llvm/CodeGen/LiveStacks.h | 3 +-
.../include/llvm/CodeGen/MIRParser/MIParser.h | 3 +-
llvm/include/llvm/CodeGen/MachineBasicBlock.h | 3 +-
llvm/include/llvm/CodeGen/MachineFunction.h | 3 +-
llvm/include/llvm/CodeGen/MachineInstr.h | 3 +-
llvm/include/llvm/CodeGen/MachineSSAUpdater.h | 3 +-
llvm/include/llvm/CodeGen/RegAllocCommon.h | 3 +-
llvm/include/llvm/CodeGen/RegisterBank.h | 3 +-
llvm/include/llvm/CodeGen/RegisterBankInfo.h | 3 +-
.../include/llvm/CodeGen/RegisterScavenging.h | 3 +-
llvm/include/llvm/CodeGen/ScheduleDAG.h | 3 +-
llvm/include/llvm/CodeGen/TargetInstrInfo.h | 3 +-
llvm/include/llvm/CodeGen/TargetLowering.h | 3 +-
.../include/llvm/CodeGen/TargetRegisterInfo.h | 161 +----------
.../llvm/CodeGen/TargetSubtargetInfo.h | 3 +-
llvm/include/llvm/MC/MCRegisterInfo.h | 112 +++++++-
llvm/lib/CodeGen/AggressiveAntiDepBreaker.h | 3 +-
llvm/lib/CodeGen/CriticalAntiDepBreaker.h | 3 +-
llvm/lib/CodeGen/RegisterCoalescer.h | 3 +-
.../AArch64/AArch64ExpandPseudoInsts.cpp | 9 +-
llvm/lib/Target/AArch64/AArch64RegisterInfo.h | 3 +-
.../Target/AMDGPU/AMDGPUArgumentUsageInfo.h | 3 +-
.../Target/AMDGPU/AMDGPUInstructionSelector.h | 3 +-
.../Target/AMDGPU/GCNPreRAOptimizations.cpp | 2 +-
llvm/lib/Target/AMDGPU/SIInstrInfo.h | 3 +-
.../lib/Target/AMDGPU/SIMachineFunctionInfo.h | 3 +-
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 12 +-
llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 5 -
llvm/lib/Target/Hexagon/BitTracker.h | 3 +-
llvm/lib/Target/Hexagon/HexagonBitTracker.cpp | 8 +-
.../lib/Target/Hexagon/HexagonFrameLowering.h | 3 +-
.../Target/Hexagon/HexagonVLIWPacketizer.h | 3 +-
llvm/lib/Target/Mips/MipsISelLowering.h | 3 +-
llvm/lib/Target/Mips/MipsInstrInfo.h | 3 +-
llvm/lib/Target/Mips/MipsRegisterInfo.h | 3 +-
llvm/lib/Target/Mips/MipsSEISelLowering.h | 3 +-
.../WebAssembly/WebAssemblyRegisterInfo.h | 3 +-
.../Target/WebAssembly/WebAssemblyUtilities.h | 3 +-
llvm/lib/Target/Xtensa/XtensaRegisterInfo.h | 3 +-
llvm/test/TableGen/RegisterClassCopyCost.td | 6 +-
.../RegisterInfoEmitter-inherit-properties.td | 19 +-
.../TableGen/RegisterInfoEmitter-tsflags.td | 8 +-
llvm/unittests/CodeGen/MachineInstrTest.cpp | 6 +-
llvm/utils/TableGen/RegisterInfoEmitter.cpp | 272 ++++++++++--------
48 files changed, 361 insertions(+), 367 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/FastISel.h b/llvm/include/llvm/CodeGen/FastISel.h
index 454ed4126213f..02d2059d54785 100644
--- a/llvm/include/llvm/CodeGen/FastISel.h
+++ b/llvm/include/llvm/CodeGen/FastISel.h
@@ -54,7 +54,8 @@ class MCSymbol;
class TargetInstrInfo;
class TargetLibraryInfo;
class TargetMachine;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class Type;
class User;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h
index 39c7ad2cf34ca..f54cbafc0dc37 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h
@@ -165,7 +165,8 @@ class LLVM_ABI GISelCSEInfo : public GISelChangeObserver {
void changedInstr(MachineInstr &MI) override;
};
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class RegisterBank;
// Simple builder class to easily profile properties about MIs.
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 511bc17161e03..ee533d2a8d8b8 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -34,7 +34,8 @@ class ConstantInt;
class DataLayout;
class GISelCSEInfo;
class GlobalValue;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class MachineFunction;
class MachineInstr;
class TargetInstrInfo;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
index bd97f7f4812f8..93fc33a61eb06 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -49,7 +49,8 @@ class TargetInstrInfo;
class TargetLowering;
class TargetPassConfig;
class TargetRegisterInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class ConstantFP;
class APFloat;
diff --git a/llvm/include/llvm/CodeGen/LiveStacks.h b/llvm/include/llvm/CodeGen/LiveStacks.h
index f2ecdca257bb1..2e5455bc671a8 100644
--- a/llvm/include/llvm/CodeGen/LiveStacks.h
+++ b/llvm/include/llvm/CodeGen/LiveStacks.h
@@ -30,7 +30,8 @@ class AnalysisUsage;
class MachineFunction;
class Module;
class raw_ostream;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class LiveStacks {
diff --git a/llvm/include/llvm/CodeGen/MIRParser/MIParser.h b/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
index d0604bbf59c5c..622862279cfdd 100644
--- a/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
+++ b/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
@@ -34,7 +34,8 @@ struct SlotMapping;
class SMDiagnostic;
class SourceMgr;
class StringRef;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetSubtargetInfo;
struct VRegInfo {
diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index 0aa2bc1bf6cbb..47430a100b3cc 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -47,7 +47,8 @@ class StringRef;
class raw_ostream;
class LiveIntervals;
class LiveVariables;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
// This structure uniquely identifies a basic block section.
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index b3c814e1c3590..70b82bcd96b11 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -70,7 +70,8 @@ class PseudoSourceValueManager;
class raw_ostream;
class SlotIndexes;
class StringRef;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetSubtargetInfo;
struct WinEHFuncInfo;
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index f1f70f019a1b6..2efd3d4d6f095 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -58,7 +58,8 @@ template <typename T> class SmallVectorImpl;
class SmallBitVector;
class StringRef;
class TargetInstrInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/CodeGen/MachineSSAUpdater.h b/llvm/include/llvm/CodeGen/MachineSSAUpdater.h
index ee576cb872ee3..64980b8022829 100644
--- a/llvm/include/llvm/CodeGen/MachineSSAUpdater.h
+++ b/llvm/include/llvm/CodeGen/MachineSSAUpdater.h
@@ -24,7 +24,8 @@ class MachineInstr;
class MachineOperand;
class MachineRegisterInfo;
class TargetInstrInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
template<typename T> class SmallVectorImpl;
template<typename T> class SSAUpdaterTraits;
diff --git a/llvm/include/llvm/CodeGen/RegAllocCommon.h b/llvm/include/llvm/CodeGen/RegAllocCommon.h
index 6c5cb295f5290..7ecf8bebd3fb2 100644
--- a/llvm/include/llvm/CodeGen/RegAllocCommon.h
+++ b/llvm/include/llvm/CodeGen/RegAllocCommon.h
@@ -14,7 +14,8 @@
namespace llvm {
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class MachineRegisterInfo;
diff --git a/llvm/include/llvm/CodeGen/RegisterBank.h b/llvm/include/llvm/CodeGen/RegisterBank.h
index 97f9c35a388f2..52b229c697acd 100644
--- a/llvm/include/llvm/CodeGen/RegisterBank.h
+++ b/llvm/include/llvm/CodeGen/RegisterBank.h
@@ -20,7 +20,8 @@ namespace llvm {
// Forward declarations.
class RegisterBankInfo;
class raw_ostream;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
/// This class implements the register bank concept.
diff --git a/llvm/include/llvm/CodeGen/RegisterBankInfo.h b/llvm/include/llvm/CodeGen/RegisterBankInfo.h
index 75153a4f840d2..825e06f429079 100644
--- a/llvm/include/llvm/CodeGen/RegisterBankInfo.h
+++ b/llvm/include/llvm/CodeGen/RegisterBankInfo.h
@@ -33,7 +33,8 @@ class MachineIRBuilder;
class MachineRegisterInfo;
class raw_ostream;
class TargetInstrInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
/// Holds all the information related to register banks.
diff --git a/llvm/include/llvm/CodeGen/RegisterScavenging.h b/llvm/include/llvm/CodeGen/RegisterScavenging.h
index 9b2c92adb0a6f..3d8e9f5bdc122 100644
--- a/llvm/include/llvm/CodeGen/RegisterScavenging.h
+++ b/llvm/include/llvm/CodeGen/RegisterScavenging.h
@@ -28,7 +28,8 @@ namespace llvm {
class MachineInstr;
class TargetInstrInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class RegScavenger {
diff --git a/llvm/include/llvm/CodeGen/ScheduleDAG.h b/llvm/include/llvm/CodeGen/ScheduleDAG.h
index 902d6b83faadf..4638632815971 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAG.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAG.h
@@ -43,7 +43,8 @@ class SDNode;
class SUnit;
class ScheduleDAG;
class TargetInstrInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
/// Scheduling dependency. This represents one direction of an edge in the
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 03f3bf26d0608..8f381c5efe2e2 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -63,7 +63,8 @@ class SelectionDAG;
class SMSchedule;
class SwingSchedulerDAG;
class RegScavenger;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class TargetSchedModel;
class TargetSubtargetInfo;
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 09f522742da4e..75b1ca2d2745f 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -93,7 +93,8 @@ class Module;
class ProfileSummaryInfo;
class TargetLibraryInfo;
class TargetMachine;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class TargetTransformInfo;
class Value;
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 183848b36e800..736aa8a5cf35a 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -43,162 +43,9 @@ class RegScavenger;
class VirtRegMap;
class LiveIntervals;
class LiveInterval;
-class TargetRegisterClass {
-public:
- using iterator = const MCPhysReg *;
- using const_iterator = const MCPhysReg *;
-
- // Instance variables filled by tablegen, do not use!
- const MCRegisterClass *MC;
- const uint32_t *SubClassMask;
- const uint16_t *SuperRegIndices;
- const LaneBitmask LaneMask;
- /// Classes with a higher priority value are assigned first by register
- /// allocators using a greedy heuristic. The value is in the range [0,31].
- const uint8_t AllocationPriority;
-
- // Change allocation priority heuristic used by greedy.
- const bool GlobalPriority;
-
- /// Configurable target specific flags.
- const uint8_t TSFlags;
- const uint8_t SpillStackID;
- /// Whether the class supports two (or more) disjunct subregister indices.
- const bool HasDisjunctSubRegs;
- /// Whether a combination of subregisters can cover every register in the
- /// class. See also the CoveredBySubRegs description in Target.td.
- const bool CoveredBySubRegs;
- const unsigned *SuperClasses;
- const uint16_t SuperClassesSize;
-
- /// Return the register class ID number.
- unsigned getID() const { return MC->getID(); }
-
- /// begin/end - Return all of the registers in this class.
- ///
- iterator begin() const { return MC->begin(); }
- iterator end() const { return MC->end(); }
-
- /// Return the number of registers in this class.
- unsigned getNumRegs() const { return MC->getNumRegs(); }
-
- ArrayRef<MCPhysReg> getRegisters() const {
- return ArrayRef(begin(), getNumRegs());
- }
-
- /// Return the specified register in the class.
- MCRegister getRegister(unsigned i) const {
- return MC->getRegister(i);
- }
-
- /// Return true if the specified register is included in this register class.
- /// This does not include virtual registers.
- bool contains(Register Reg) const {
- /// FIXME: Historically this function has returned false when given vregs
- /// but it should probably only receive physical registers
- if (!Reg.isPhysical())
- return false;
- return MC->contains(Reg.asMCReg());
- }
-
- /// Return true if both registers are in this class.
- bool contains(Register Reg1, Register Reg2) const {
- /// FIXME: Historically this function has returned false when given a vregs
- /// but it should probably only receive physical registers
- if (!Reg1.isPhysical() || !Reg2.isPhysical())
- return false;
- return MC->contains(Reg1.asMCReg(), Reg2.asMCReg());
- }
-
- /// Return the cost of copying a value between two registers in this class. If
- /// this is the maximum value, the register may be impossible to copy.
- uint8_t getCopyCost() const { return MC->getCopyCost(); }
-
- /// \return true if register class is very expensive to copy e.g. status flag
- /// register classes.
- bool expensiveOrImpossibleToCopy() const {
- return MC->getCopyCost() == std::numeric_limits<uint8_t>::max();
- }
-
- /// Return true if this register class may be used to create virtual
- /// registers.
- bool isAllocatable() const { return MC->isAllocatable(); }
-
- /// Return true if this register class has a defined BaseClassOrder.
- bool isBaseClass() const { return MC->isBaseClass(); }
-
- /// Return true if the specified TargetRegisterClass
- /// is a proper sub-class of this TargetRegisterClass.
- bool hasSubClass(const TargetRegisterClass *RC) const {
- return RC != this && hasSubClassEq(RC);
- }
- /// Returns true if RC is a sub-class of or equal to this class.
- bool hasSubClassEq(const TargetRegisterClass *RC) const {
- unsigned ID = RC->getID();
- return (SubClassMask[ID / 32] >> (ID % 32)) & 1;
- }
-
- /// Return true if the specified TargetRegisterClass is a
- /// proper super-class of this TargetRegisterClass.
- bool hasSuperClass(const TargetRegisterClass *RC) const {
- return RC->hasSubClass(this);
- }
-
- /// Returns true if RC is a super-class of or equal to this class.
- bool hasSuperClassEq(const TargetRegisterClass *RC) const {
- return RC->hasSubClassEq(this);
- }
-
- /// Returns a bit vector of subclasses, including this one.
- /// The vector is indexed by class IDs.
- ///
- /// To use it, consider the returned array as a chunk of memory that
- /// contains an array of bits of size NumRegClasses. Each 32-bit chunk
- /// contains a bitset of the ID of the subclasses in big-endian style.
-
- /// I.e., the representation of the memory from left to right at the
- /// bit level looks like:
- /// [31 30 ... 1 0] [ 63 62 ... 33 32] ...
- /// [ XXX NumRegClasses NumRegClasses - 1 ... ]
- /// Where the number represents the class ID and XXX bits that
- /// should be ignored.
- ///
- /// See the implementation of hasSubClassEq for an example of how it
- /// can be used.
- const uint32_t *getSubClassMask() const {
- return SubClassMask;
- }
-
- /// Returns a 0-terminated list of sub-register indices that project some
- /// super-register class into this register class. The list has an entry for
- /// each Idx such that:
- ///
- /// There exists SuperRC where:
- /// For all Reg in SuperRC:
- /// this->contains(Reg:Idx)
- const uint16_t *getSuperRegIndices() const {
- return SuperRegIndices;
- }
-
- /// Returns a list of super-classes. The
- /// classes are ordered by ID which is also a topological ordering from large
- /// to small classes. The list does NOT include the current class.
- ArrayRef<unsigned> superclasses() const {
- return ArrayRef(SuperClasses, SuperClassesSize);
- }
-
- /// Return true if this TargetRegisterClass is a subset
- /// class of at least one other TargetRegisterClass.
- bool isASubClass() const { return SuperClasses != nullptr; }
-
- /// Returns the combination of all lane masks of register in this class.
- /// The lane masks of the registers are the combination of all lane masks
- /// of their subregisters. Returns 1 if there are no subregisters.
- LaneBitmask getLaneMask() const {
- return LaneMask;
- }
-};
+// TODO: Remove.
+using TargetRegisterClass = MCRegisterClass;
/// Extra information, not in MCRegisterDesc, about registers.
/// These are used by codegen, not by MC.
@@ -651,7 +498,7 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
/// index \p SubIdx is \p Reg.
MCRegister getMatchingSuperReg(MCRegister Reg, unsigned SubIdx,
const TargetRegisterClass *RC) const {
- return MCRegisterInfo::getMatchingSuperReg(Reg, SubIdx, RC->MC);
+ return MCRegisterInfo::getMatchingSuperReg(Reg, SubIdx, RC);
}
/// Return a subclass of the register class \p A so that each register in it
@@ -886,7 +733,7 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
/// Returns the name of the register class.
const char *getRegClassName(const TargetRegisterClass *Class) const {
- return MCRegisterInfo::getRegClassName(Class->MC);
+ return MCRegisterInfo::getRegClassName(Class);
}
/// Find the largest common subclass of A and B.
diff --git a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
index fb0589e2c446e..8b8f64f49b595 100644
--- a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
@@ -52,7 +52,8 @@ class SUnit;
class TargetFrameLowering;
class TargetInstrInfo;
class TargetLowering;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class TargetSchedModel;
class Triple;
diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h
index 499dd6d6afda9..dac8f84119dc3 100644
--- a/llvm/include/llvm/MC/MCRegisterInfo.h
+++ b/llvm/include/llvm/MC/MCRegisterInfo.h
@@ -39,6 +39,9 @@ class MCRegisterClass {
using iterator = const MCPhysReg*;
using const_iterator = const MCPhysReg*;
+ MCRegisterClass(const MCRegisterClass &) = delete;
+
+ // TODO: reorder fields to reduce memory usage.
const uint32_t RegsOff; ///< Relative offset to MCPhysReg array.
const uint32_t RegSetOff; ///< Relative offset to uint8_t array.
const uint32_t NameIdx;
@@ -50,6 +53,27 @@ class MCRegisterClass {
const bool Allocatable;
const bool BaseClass;
+ const uint32_t SubClassMaskOff; ///< Relative offset to uin32t_t array.
+ const uint32_t SuperRegIndicesOff; ///< Relative offset to MCPhysReg array.
+ const LaneBitmask LaneMask;
+ /// Classes with a higher priority value are assigned first by register
+ /// allocators using a greedy heuristic. The value is in the range [0,31].
+ const uint8_t AllocationPriority;
+
+ // Change allocation priority heuristic used by greedy.
+ const bool GlobalPriority;
+
+ /// Configurable target specific flags.
+ const uint8_t TSFlags;
+ const uint8_t SpillStackID;
+ /// Whether the class supports two (or more) disjunct subregister indices.
+ const bool HasDisjunctSubRegs;
+ /// Whether a combination of subregisters can cover every register in the
+ /// class. See also the CoveredBySubRegs description in Target.td.
+ const bool CoveredBySubRegs;
+ const uint32_t SuperClassesOff; ///< Relative offset to unsigned array.
+ const uint16_t SuperClassesSize;
+
/// getID() - Return the register class ID number.
///
unsigned getID() const { return ID; }
@@ -73,6 +97,10 @@ class MCRegisterClass {
return begin()[i];
}
+ ArrayRef<MCPhysReg> getRegisters() const {
+ return ArrayRef(begin(), RegsSize);
+ }
+
/// contains - Return true if the specified register is included in this
/// register class. This does not include virtual registers.
bool contains(MCRegister Reg) const {
@@ -101,19 +129,101 @@ class MCRegisterClass {
/// to copy e.g. status flag register classes.
uint8_t getCopyCost() const { return CopyCost; }
+ /// \return true if register class is very expensive to copy e.g. status flag
+ /// register classes.
+ bool expensiveOrImpossibleToCopy() const {
+ return CopyCost == std::numeric_limits<uint8_t>::max();
+ }
+
/// isAllocatable - Return true if this register class may be used to create
/// virtual registers.
bool isAllocatable() const { return Allocatable; }
/// Return true if this register class has a defined BaseClassOrder.
bool isBaseClass() const { return BaseClass; }
+
+ /// Return true if the specified TargetRegisterClass
+ /// is a proper sub-class of this TargetRegisterClass.
+ bool hasSubClass(const MCRegisterClass *RC) const {
+ return RC != this && hasSubClassEq(RC);
+ }
+
+ /// Returns true if RC is a sub-class of or equal to this class.
+ bool hasSubClassEq(const MCRegisterClass *RC) const {
+ unsigned ID = RC->getID();
+ return (getSubClassMask()[ID / 32] >> (ID % 32)) & 1;
+ }
+
+ /// Return true if the specified MCRegisterClass is a
+ /// proper super-class of this MCRegisterClass.
+ bool hasSuperClass(const MCRegisterClass *RC) const {
+ return RC->hasSubClass(this);
+ }
+
+ /// Returns true if RC is a super-class of or equal to this class.
+ bool hasSuperClassEq(const MCRegisterClass *RC) const {
+ return RC->hasSubClassEq(this);
+ }
+
+ /// Returns a bit vector of subclasses, including this one.
+ /// The vector is indexed by class IDs.
+ ///
+ /// To use it, consider the returned array as a chunk of memory that
+ /// contains an array of bits of size NumRegClasses. Each 32-bit chunk
+ /// contains a bitset of the ID of the subclasses in big-endian style.
+
+ /// I.e., the representation of the memory from left to right at the
+ /// bit level looks like:
+ /// [31 30 ... 1 0] [ 63 62 ... 33 32] ...
+ /// [ XXX NumRegClasses NumRegClasses - 1 ... ]
+ /// Where the number represents the class ID and XXX bits that
+ /// should be ignored.
+ ///
+ /// See the implementation of hasSubClassEq for an example of how it
+ /// can be used.
+ const uint32_t *getSubClassMask() const {
+ return reinterpret_cast<const uint32_t *>(
+ reinterpret_cast<const char *>(this) + SubClassMaskOff);
+ }
+
+ /// Returns a 0-terminated list of sub-register indices that project some
+ /// super-register class into this register class. The list has an entry for
+ /// each Idx such that:
+ ///
+ /// There exists SuperRC where:
+ /// For all Reg in SuperRC:
+ /// this->contains(Reg:Idx)
+ const uint16_t *getSuperRegIndices() const {
+ return reinterpret_cast<const uint16_t *>(
+ reinterpret_cast<const char *>(this) + SuperRegIndicesOff);
+ }
+
+ /// Returns a list of super-classes. The
+ /// classes are ordered by ID which is also a topological ordering from large
+ /// to small classes. The list does NOT include the current class.
+ ArrayRef<unsigned> superclasses() const {
+ const unsigned *SuperClasses = reinterpret_cast<const unsigned *>(
+ reinterpret_cast<const char *>(this) + SuperClassesOff);
+ return ArrayRef(SuperClasses, SuperClassesSize);
+ }
+
+ /// Returns the combination of all lane masks of register in this class.
+ /// The lane masks of the registers are the combination of all lane masks
+ /// of their subregisters. Returns 1 if there are no subregisters.
+ LaneBitmask getLaneMask() const { return LaneMask; }
};
-template <unsigned RegClassCount, unsigned RegCount, unsigned BitSetSize>
+template <unsigned RegClassCount, unsigned RegCount, unsigned BitSetSize,
+ unsigned SubClassMaskSize, unsigned SuperRegIdxSeqSize,
+ unsigned SuperClassSize>
struct MCRegisterClassStorage {
MCRegisterClass Classes[RegClassCount];
MCPhysReg Regs[RegCount];
uint8_t BitSets[BitSetSize];
+ uint32_t SubClassMasks[SubClassMaskSize];
+ uint16_t SuperRegIdxSeqs[SuperRegIdxSeqSize];
+ // Avoid zero-sized arrays.
+ unsigned SuperClasses[SuperClassSize > 0 ? SuperClassSize : 1];
};
/// MCRegisterDesc - This record contains information about a particular
diff --git a/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h b/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h
index 8726cdef2bfc4..4f474ebb6b89e 100644
--- a/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h
+++ b/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h
@@ -33,7 +33,8 @@ class MachineOperand;
class MachineRegisterInfo;
class RegisterClassInfo;
class TargetInstrInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
/// Contains all the state necessary for anti-dep breaking.
diff --git a/llvm/lib/CodeGen/CriticalAntiDepBreaker.h b/llvm/lib/CodeGen/CriticalAntiDepBreaker.h
index a96e2ed8cf1a3..81deb80610938 100644
--- a/llvm/lib/CodeGen/CriticalAntiDepBreaker.h
+++ b/llvm/lib/CodeGen/CriticalAntiDepBreaker.h
@@ -30,7 +30,8 @@ class MachineOperand;
class MachineRegisterInfo;
class RegisterClassInfo;
class TargetInstrInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class LLVM_LIBRARY_VISIBILITY CriticalAntiDepBreaker : public AntiDepBreaker {
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.h b/llvm/lib/CodeGen/RegisterCoalescer.h
index ec1940805ea2e..c4aa6276c61b7 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.h
+++ b/llvm/lib/CodeGen/RegisterCoalescer.h
@@ -20,7 +20,8 @@
namespace llvm {
class MachineInstr;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
/// A helper class for register coalescers. When deciding if
diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
index 5fa93da1544fc..944bbeac7bb9b 100644
--- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
@@ -56,8 +56,8 @@ class AArch64ExpandPseudoImpl {
MachineBasicBlock::iterator &NextMBBI);
bool expandMultiVecPseudo(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
- TargetRegisterClass ContiguousClass,
- TargetRegisterClass StridedClass,
+ const TargetRegisterClass &ContiguousClass,
+ const TargetRegisterClass &StridedClass,
unsigned ContiguousOpc, unsigned StridedOpc);
bool expandFormTuplePseudo(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
@@ -1257,8 +1257,9 @@ AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &MBB,
bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- TargetRegisterClass ContiguousClass, TargetRegisterClass StridedClass,
- unsigned ContiguousOp, unsigned StridedOpc) {
+ const TargetRegisterClass &ContiguousClass,
+ const TargetRegisterClass &StridedClass, unsigned ContiguousOp,
+ unsigned StridedOpc) {
MachineInstr &MI = *MBBI;
Register Tuple = MI.getOperand(0).getReg();
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
index ac58d8d6b1cc7..b31104aac6551 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
@@ -20,7 +20,8 @@ namespace llvm {
class MachineFunction;
class RegScavenger;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class Triple;
class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUArgumentUsageInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUArgumentUsageInfo.h
index cbb3c6ce127a4..7f1589f778016 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUArgumentUsageInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUArgumentUsageInfo.h
@@ -17,7 +17,8 @@ namespace llvm {
class LLT;
class raw_ostream;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
struct ArgDescriptor {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
index 1b6722f357080..19028ef58a166 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
@@ -43,7 +43,8 @@ class MachineRegisterInfo;
class RegisterBank;
class SIInstrInfo;
class SIRegisterInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class AMDGPUInstructionSelector final : public InstructionSelector {
private:
diff --git a/llvm/lib/Target/AMDGPU/GCNPreRAOptimizations.cpp b/llvm/lib/Target/AMDGPU/GCNPreRAOptimizations.cpp
index 825634d7af65b..50514e819f412 100644
--- a/llvm/lib/Target/AMDGPU/GCNPreRAOptimizations.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNPreRAOptimizations.cpp
@@ -312,7 +312,7 @@ bool GCNPreRAOptimizationsImpl::run(MachineFunction &MF) {
if (!LIS->hasInterval(Reg))
continue;
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
- if ((RC->MC->getSizeInBits() != 64 || !TRI->isSGPRClass(RC)) &&
+ if ((RC->getSizeInBits() != 64 || !TRI->isSGPRClass(RC)) &&
(ST.hasGFX90AInsts() || !TRI->isAGPRClass(RC)))
continue;
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
index 1d67c8664ff44..a1aa56741bb4f 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -34,7 +34,8 @@ class MachineDominatorTree;
class MachineRegisterInfo;
class RegScavenger;
class SIMachineFunctionInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class ScheduleHazardRecognizer;
constexpr unsigned DefaultMemoryClusterDWordsLimit = 8;
diff --git a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h
index 1f43505650222..7374e996837a5 100644
--- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h
@@ -33,7 +33,8 @@ class MachineFrameInfo;
class MachineFunction;
class SIMachineFunctionInfo;
class SIRegisterInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class AMDGPUPseudoSourceValue : public PseudoSourceValue {
public:
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 9700720f0373a..903599cff67c0 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -3578,10 +3578,6 @@ unsigned SIRegisterInfo::getHWRegIndex(MCRegister Reg) const {
return getEncodingValue(Reg) & AMDGPU::HWEncoding::REG_IDX_MASK;
}
-unsigned AMDGPU::getRegBitWidth(const TargetRegisterClass &RC) {
- return getRegBitWidth(RC.getID());
-}
-
static const TargetRegisterClass *
getAnyVGPRClassForBitWidth(unsigned BitWidth) {
if (BitWidth == 64)
@@ -4257,10 +4253,10 @@ MachineInstr *SIRegisterInfo::findReachingDef(Register Reg, unsigned SubReg,
MCPhysReg SIRegisterInfo::get32BitRegister(MCPhysReg Reg) const {
assert(getRegSizeInBits(*getPhysRegBaseClass(Reg)) <= 32);
- for (const TargetRegisterClass &RC : { AMDGPU::VGPR_32RegClass,
- AMDGPU::SReg_32RegClass,
- AMDGPU::AGPR_32RegClass } ) {
- if (MCPhysReg Super = getMatchingSuperReg(Reg, AMDGPU::lo16, &RC))
+ for (const TargetRegisterClass *RC :
+ {&AMDGPU::VGPR_32RegClass, &AMDGPU::SReg_32RegClass,
+ &AMDGPU::AGPR_32RegClass}) {
+ if (MCPhysReg Super = getMatchingSuperReg(Reg, AMDGPU::lo16, RC))
return Super;
}
if (MCPhysReg Super = getMatchingSuperReg(Reg, AMDGPU::hi16,
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index 5e08e47ad4d83..e464c9334ffea 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -508,11 +508,6 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
}
};
-namespace AMDGPU {
-/// Get the size in bits of a register from the register class \p RC.
-unsigned getRegBitWidth(const TargetRegisterClass &RC);
-} // namespace AMDGPU
-
} // End namespace llvm
#endif
diff --git a/llvm/lib/Target/Hexagon/BitTracker.h b/llvm/lib/Target/Hexagon/BitTracker.h
index 67ae29b21085d..509d5d4d7ddf0 100644
--- a/llvm/lib/Target/Hexagon/BitTracker.h
+++ b/llvm/lib/Target/Hexagon/BitTracker.h
@@ -26,7 +26,8 @@ class MachineRegisterInfo;
class MachineBasicBlock;
class MachineFunction;
class raw_ostream;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
struct BitTracker {
diff --git a/llvm/lib/Target/Hexagon/HexagonBitTracker.cpp b/llvm/lib/Target/Hexagon/HexagonBitTracker.cpp
index 6f15011668e6c..360880a7afb19 100644
--- a/llvm/lib/Target/Hexagon/HexagonBitTracker.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonBitTracker.cpp
@@ -105,10 +105,10 @@ uint16_t HexagonEvaluator::getPhysRegBitWidth(MCRegister Reg) const {
using namespace Hexagon;
const auto &HST = MF.getSubtarget<HexagonSubtarget>();
if (HST.useHVXOps()) {
- for (auto &RC : {HvxVRRegClass, HvxWRRegClass, HvxQRRegClass,
- HvxVQRRegClass})
- if (RC.contains(Reg))
- return TRI.getRegSizeInBits(RC);
+ for (auto *RC :
+ {&HvxVRRegClass, &HvxWRRegClass, &HvxQRRegClass, &HvxVQRRegClass})
+ if (RC->contains(Reg))
+ return TRI.getRegSizeInBits(*RC);
}
// Default treatment for other physical registers.
if (const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg))
diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.h b/llvm/lib/Target/Hexagon/HexagonFrameLowering.h
index 2e876ab034cbe..0b93795f2b912 100644
--- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.h
@@ -26,7 +26,8 @@ class HexagonRegisterInfo;
class MachineFunction;
class MachineInstr;
class MachineRegisterInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class HexagonFrameLowering : public TargetFrameLowering {
public:
diff --git a/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.h b/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.h
index 8eced652b2e32..33edcce995e1d 100644
--- a/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.h
+++ b/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.h
@@ -22,7 +22,8 @@ class MachineBranchProbabilityInfo;
class MachineFunction;
class MachineInstr;
class MachineLoopInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class HexagonPacketizerList : public VLIWPacketizerList {
// Vector of instructions assigned to the packet that has just been created.
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 806fb59f5ff3e..93d90f23b362e 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -49,7 +49,8 @@ class MipsFunctionInfo;
class MipsSubtarget;
class MipsTargetMachine;
class TargetLibraryInfo;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
//===--------------------------------------------------------------------===//
// TargetLowering Implementation
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.h b/llvm/lib/Target/Mips/MipsInstrInfo.h
index 29dfa0c41ad1d..a1d0496ff0c05 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.h
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.h
@@ -35,7 +35,8 @@ namespace llvm {
class MachineInstr;
class MachineOperand;
class MipsSubtarget;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class TargetRegisterInfo;
class MipsInstrInfo : public MipsGenInstrInfo {
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.h b/llvm/lib/Target/Mips/MipsRegisterInfo.h
index e2e81af4a8af1..9e6ef66163bd9 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.h
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.h
@@ -22,7 +22,8 @@
namespace llvm {
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class MipsRegisterInfo : public MipsGenRegisterInfo {
private:
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.h b/llvm/lib/Target/Mips/MipsSEISelLowering.h
index d75acbc9698f5..56b26b39f634d 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.h
@@ -24,7 +24,8 @@ class MachineInstr;
class MipsSubtarget;
class MipsTargetMachine;
class SelectionDAG;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class MipsSETargetLowering : public MipsTargetLowering {
public:
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
index 5b4293b9ec590..ffff5d1d96397 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
@@ -22,7 +22,8 @@ namespace llvm {
class MachineFunction;
class RegScavenger;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class Triple;
class WebAssemblyRegisterInfo final : public WebAssemblyGenRegisterInfo {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h
index 0827791d93657..14ef9d142f36e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h
@@ -25,7 +25,8 @@ class MachineInstr;
class MachineOperand;
class MCContext;
class MCSymbolWasm;
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class WebAssemblyFunctionInfo;
class WebAssemblySubtarget;
class MachineSDNode;
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
index ede0eeb90b42d..7c2af4d978f6c 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
@@ -20,7 +20,8 @@
#include "XtensaGenRegisterInfo.inc"
namespace llvm {
-class TargetRegisterClass;
+class MCRegisterClass;
+using TargetRegisterClass = MCRegisterClass;
class XtensaInstrInfo;
class XtensaSubtarget;
diff --git a/llvm/test/TableGen/RegisterClassCopyCost.td b/llvm/test/TableGen/RegisterClassCopyCost.td
index bf785d4b1ae91..42cd29b00f325 100644
--- a/llvm/test/TableGen/RegisterClassCopyCost.td
+++ b/llvm/test/TableGen/RegisterClassCopyCost.td
@@ -8,10 +8,8 @@
include "llvm/Target/Target.td"
// CHECK: extern const MCRegisterClassStorage<{{[0-9, ]+}}> MyTargetMCRegisterClassStorage = {
-// CHECK-NEXT: {
-// CHECK-NEXT: { {{[^,]+}}, {{[^,]+}}, 0, 32, 2, {{[0-9]+}}, MyTarget::GPR32RegClassID, 1, true, false },
-// CHECK-NEXT: { {{[^,]+}}, {{[^,]+}}, 6, 32, 1, {{[0-9]+}}, MyTarget::SPECIAL_CLASSRegClassID, 255, true, false },
-// CHECK-NEXT: },
+// CHECK: 1, /* CopyCost */
+// CHECK: 255, /* CopyCost */
def MyTargetISA : InstrInfo;
def MyTarget : Target { let InstructionSet = MyTargetISA; }
diff --git a/llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td b/llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td
index 9ca3478662ce9..1707ded61c99c 100644
--- a/llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td
+++ b/llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td
@@ -68,20 +68,11 @@ def ABRC3 : MyClass<32, [untyped], (add ARC3, BRC3)> {
def TestTarget : Target;
-// CHECK: static unsigned const ARC3_with_sub0_sub1Superclasses[] = {
-// CHECK-NEXT: Test::ABRC3RegClassID,
-// CHECK-NEXT: Test::ARC3RegClassID,
-// CHECK-NEXT: Test::ABRC3_with_sub0_sub1RegClassID,
-// CHECK-NEXT: };
-
-// CHECK: static unsigned const ARC3_with_sub1_sub2Superclasses[] = {
-// CHECK-NEXT: Test::ABRC3RegClassID,
-// CHECK-NEXT: Test::ARC3RegClassID,
-// CHECK-NEXT: Test::ABRC3_with_sub1_sub2RegClassID,
-// CHECK-NEXT: };
-
-// CHECK: extern const TargetRegisterClass ARC3_with_sub0_sub1RegClass = {
+// CHECK: ARC3_with_sub0_sub1RegClassID
// CHECK: 0x01, /* TSFlags */
-// CHECK: extern const TargetRegisterClass ARC3_with_sub1_sub2RegClass = {
+// CHECK: ARC3_with_sub1_sub2RegClassID
// CHECK: 0x01, /* TSFlags */
+
+// CHECK: ARC3_with_sub0_sub1 */ Test::ABRC3RegClassID, Test::ARC3RegClassID, Test::ABRC3_with_sub0_sub1RegClassID
+// CHECK: ARC3_with_sub1_sub2 */ Test::ABRC3RegClassID, Test::ARC3RegClassID, Test::ABRC3_with_sub1_sub2RegClassID
diff --git a/llvm/test/TableGen/RegisterInfoEmitter-tsflags.td b/llvm/test/TableGen/RegisterInfoEmitter-tsflags.td
index 55db3ddb1f27e..affdc0648fca9 100644
--- a/llvm/test/TableGen/RegisterInfoEmitter-tsflags.td
+++ b/llvm/test/TableGen/RegisterInfoEmitter-tsflags.td
@@ -38,11 +38,11 @@ def SDRegs : MyClass<32, [i32], (add D, S)>{
def MyTarget : Target;
-// CHECK: extern const TargetRegisterClass SDRegsRegClass = {
+// CHECK: SDRegsRegClassID
// CHECK: 0x07, /* TSFlags */
-// CHECK: extern const TargetRegisterClass DRegsRegClass = {
+// CHECK: DRegsRegClassID
// CHECK: 0x06, /* TSFlags */
-// CHECK: extern const TargetRegisterClass MyRegsRegClass = {
+// CHECK: MyRegsRegClassID
// CHECK: 0x00, /* TSFlags */
-// CHECK: extern const TargetRegisterClass SRegsRegClass = {
+// CHECK: SRegsRegClassID
// CHECK: 0x01, /* TSFlags */
diff --git a/llvm/unittests/CodeGen/MachineInstrTest.cpp b/llvm/unittests/CodeGen/MachineInstrTest.cpp
index 47e260104775f..9fd7b1980929c 100644
--- a/llvm/unittests/CodeGen/MachineInstrTest.cpp
+++ b/llvm/unittests/CodeGen/MachineInstrTest.cpp
@@ -591,9 +591,9 @@ TEST(MachineInstrTest, SpliceOperands) {
EXPECT_EQ(MI->getOperand(8).getImm(), MachineOperand::CreateImm(4).getImm());
// test tied operands
- MCRegisterClass MRC{
- 0, 0, 0, 0, 0, 0, 0, 0, /*Allocatable=*/true, /*BaseClass=*/true};
- TargetRegisterClass RC{&MRC, 0, 0, {}, 0, 0, 0, 0, 0, 0, 0, 0};
+ MCRegisterClass RC{
+ 0, 0, 0, 0, 0, 0, 0, 0, /*Allocatable=*/true, /*BaseClass=*/true,
+ 0, 0, {}, 0, 0, 0, 0, 0, 0, 0, 0};
// MachineRegisterInfo will be very upset if these registers aren't
// allocatable.
assert(RC.isAllocatable() && "unusable TargetRegisterClass");
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 9eaee06143c64..0789e537e56bb 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -1073,15 +1073,45 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
OS << "};\n\n";
}
+ // Emit register class bit mask tables. The first bit mask emitted for a
+ // register class, RC, is the set of sub-classes, including RC itself.
+ //
+ // If RC has super-registers, also create a list of subreg indices and bit
+ // masks, (Idx, Mask). The bit mask has a bit for every superreg regclass,
+ // SuperRC, that satisfies:
+ //
+ // For all SuperReg in SuperRC: SuperReg:Idx in RC
+ //
+ // The 0-terminated list of subreg indices starts at:
+ //
+ // RC->getSuperRegIndices() = SuperRegIdxSeqs + ...
+ //
+ // The corresponding bitmasks follow the sub-class mask in memory. Each
+ // mask has RCMaskWords uint32_t entries.
+ //
+ // Every bit mask present in the list has at least one bit set.
+
const auto &RegisterClasses = RegBank.getRegClasses();
OS << "// Register classes...\n";
SequenceToOffsetTable<std::string> RegClassStrings;
- SmallVector<unsigned> BitSetSizes;
- BitSetSizes.reserve(RegisterClasses.size());
- unsigned TotalRegCount = 0;
- unsigned TotalBitSetSize = 0;
+ // Start indices for per-reg-class info in the respective arrays.
+ struct StartIndex {
+ unsigned RegIdx;
+ unsigned BitSetIdx;
+ unsigned SubClassMaskIdx;
+ unsigned SuperClassIdx;
+ };
+ SmallVector<StartIndex> StartIndices;
+ StartIndices.reserve(RegisterClasses.size() + 1);
+ StartIndices.push_back(StartIndex{0, 0, 0, 0});
+
+ // For compressing the sub-reg index lists.
+ using IdxList = std::vector<const CodeGenSubRegIndex *>;
+ SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
+ SequenceToOffsetTable<IdxList, deref<std::less<>>> SuperRegIdxSeqs;
+ BitVector MaskBV(RegisterClasses.size());
for (const auto &RC : RegisterClasses) {
ArrayRef<const Record *> Order = RC.getOrder();
RegClassStrings.add(RC.getName());
@@ -1089,77 +1119,155 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
unsigned MaxRegVal = 0;
for (const Record *Reg : Order)
MaxRegVal = std::max(MaxRegVal, RegBank.getReg(Reg)->EnumValue);
- // Round to next byte size.
- BitSetSizes.push_back(Order.empty() ? 0 : (MaxRegVal / 8) + 1);
- TotalRegCount += Order.size();
- TotalBitSetSize += BitSetSizes.back();
+
+ unsigned SubClassMaskSize = (RC.getSubClasses().size() + 31) / 32;
+ IdxList &SRIList = SuperRegIdxLists[RC.EnumValue];
+ for (auto &Idx : SubRegIndices) {
+ MaskBV.reset();
+ RC.getSuperRegClasses(&Idx, MaskBV);
+ if (MaskBV.none())
+ continue;
+ SRIList.push_back(&Idx);
+ SubClassMaskSize += (MaskBV.size() + 31) / 32;
+ }
+ SuperRegIdxSeqs.add(SRIList);
+
+ const auto &Last = StartIndices.back();
+ StartIndices.push_back(StartIndex{
+ Last.RegIdx + unsigned(Order.size()),
+ // Round to next byte size.
+ Last.BitSetIdx + (Order.empty() ? 0 : (MaxRegVal / 8) + 1),
+ Last.SubClassMaskIdx + SubClassMaskSize,
+ Last.SuperClassIdx + unsigned(RC.getSuperClasses().size()),
+ });
}
RegClassStrings.layout();
RegClassStrings.emitStringLiteralDef(
OS, Twine("extern const char ") + TargetName + "RegClassStrings[]");
+ SuperRegIdxSeqs.layout();
+
+ const auto &Totals = StartIndices.back();
raw_string_ostream(MCRegisterClassStorageType)
<< "MCRegisterClassStorage<" << RegisterClasses.size() << ", "
- << TotalRegCount << ", " << TotalBitSetSize << ">";
+ << Totals.RegIdx << ", " << Totals.BitSetIdx << ", "
+ << Totals.SubClassMaskIdx << ", " << SuperRegIdxSeqs.size() << ", "
+ << Totals.SuperClassIdx << ">";
+ OS << "using " << TargetName
+ << "RegisterClassStorage = " << MCRegisterClassStorageType << ";\n";
OS << "extern const " << MCRegisterClassStorageType << " " << TargetName
<< "MCRegisterClassStorage = {\n"
<< " {\n";
- unsigned RegCount = 0; // Number of entries in registers array.
- unsigned BitSetSize = 0; // Number of entries in bitset array.
- for (const auto &[Idx, RC] : enumerate(RegisterClasses)) {
- ArrayRef<const Record *> Order = RC.getOrder();
+ for (const auto &It : enumerate(RegisterClasses)) {
+ const auto &RC = It.value();
+ const auto &RCIndices = StartIndices[It.index()];
uint32_t RegSize = 0;
if (RC.RSI.isSimple())
RegSize = RC.RSI.getSimple().RegSize;
- OS << " { " << (RegisterClasses.size() - Idx)
- << " * sizeof(MCRegisterClass)"
- << " + sizeof(MCPhysReg) * " << RegCount << ", "
- << (RegisterClasses.size() - Idx) << " * sizeof(MCRegisterClass)"
- << " + sizeof(MCPhysReg) * " << TotalRegCount << " + " << BitSetSize
- << ", " << RegClassStrings.get(RC.getName()) << ", " << RegSize << ", "
- << RC.getOrder().size() << ", " << BitSetSizes[Idx] << ", "
- << RC.getQualifiedIdName() << ", " << static_cast<unsigned>(RC.CopyCost)
- << ", " << (RC.Allocatable ? "true" : "false") << ", "
- << (RC.getBaseClassOrder() ? "true" : "false") << " },\n";
- RegCount += Order.size();
- BitSetSize += BitSetSizes[Idx];
+ // Helper to generate offsetof macro for relative offset in storage.
+ auto GetOff = [&](std::string_view Member,
+ unsigned DataIdx) -> std::string {
+ return ("offsetof(" + Twine(TargetName) + "RegisterClassStorage, " +
+ Member + "[" + Twine(DataIdx) + "]) - " + Twine(It.index()) +
+ " * sizeof(MCRegisterClass)")
+ .str();
+ };
+
+ unsigned BitSetSize =
+ StartIndices[It.index() + 1].BitSetIdx - RCIndices.BitSetIdx;
+ OS << " {\n " << GetOff("Regs", RCIndices.RegIdx) << ",\n "
+ << GetOff("BitSets", RCIndices.BitSetIdx) << ",\n "
+ << RegClassStrings.get(RC.getName()) << ",\n " << RegSize
+ << ",\n " << RC.getOrder().size() << ",\n " << BitSetSize
+ << ",\n " << RC.getQualifiedIdName() << ",\n "
+ << static_cast<unsigned>(RC.CopyCost) << ", /* CopyCost */\n "
+ << (RC.Allocatable ? "true" : "false") << ", /* Allocatable */\n "
+ << (RC.getBaseClassOrder() ? "true" : "false") << ",\n "
+ << GetOff("SubClassMasks", RCIndices.SubClassMaskIdx) << ",\n "
+ << GetOff("SuperRegIdxSeqs",
+ SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]))
+ << ",\n ";
+ printMask(OS, RC.LaneMask);
+ OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n "
+ << (RC.GlobalPriority ? "true" : "false") << ",\n "
+ << format("0x%02x", RC.TSFlags) << ", /* TSFlags */\n "
+ << (unsigned)RC.SpillStackID << ", /* SpillStackID */\n "
+ << (RC.HasDisjunctSubRegs ? "true" : "false")
+ << ", /* HasDisjunctSubRegs */\n "
+ << (RC.CoveredBySubRegs ? "true" : "false")
+ << ", /* CoveredBySubRegs */\n "
+ << GetOff("SuperClasses", RCIndices.SuperClassIdx) << ",\n "
+ << RC.getSuperClasses().size() << "\n },\n";
}
OS << " },\n {\n";
// Emit registers.
// TODO: these sequences often have overlaps which could be deduplicated.
- RegCount = 0;
- for (const auto &RC : RegisterClasses) {
+ for (const auto &[Idx, RC] : enumerate(RegisterClasses)) {
ArrayRef<const Record *> Order = RC.getOrder();
if (Order.empty())
continue;
- OS << " /* " << RegCount << " */ ";
+ OS << " /* " << StartIndices[Idx].RegIdx << " */ ";
for (const Record *Reg : Order)
OS << getQualifiedName(Reg) << ", ";
OS << "\n";
- RegCount += Order.size();
}
OS << " },\n {\n";
// Emit register bit sets.
- BitSetSize = 0;
for (const auto &[Idx, RC] : enumerate(RegisterClasses)) {
ArrayRef<const Record *> Order = RC.getOrder();
if (!Order.empty()) {
- OS << " /* " << BitSetSize << " */ ";
+ OS << " /* " << StartIndices[Idx].BitSetIdx << " */ ";
BitVectorEmitter BVE;
for (const Record *Reg : Order)
BVE.add(RegBank.getReg(Reg)->EnumValue);
BVE.print(OS);
OS << "\n";
- BitSetSize += BitSetSizes[Idx];
}
}
+ OS << " },\n {\n";
+
+ // Emit subclass masks.
+ for (const auto &[Idx, RC] : enumerate(RegisterClasses)) {
+ OS << " // " << StartIndices[Idx].SubClassMaskIdx << " " << RC.getName()
+ << "\n ";
+ printBitVectorAsHex(OS, RC.getSubClasses(), 32);
+
+ // Emit super-reg class masks for any relevant SubRegIndices that can
+ // project into RC.
+ for (auto &Idx : SubRegIndices) {
+ MaskBV.reset();
+ RC.getSuperRegClasses(&Idx, MaskBV);
+ if (MaskBV.none())
+ continue;
+ OS << "\n ";
+ printBitVectorAsHex(OS, MaskBV, 32);
+ OS << "// " << Idx.getName();
+ }
+ OS << "\n";
+ }
+ OS << " },\n {\n";
+
+ // Emit SubRegIdxSeqs.
+ SuperRegIdxSeqs.emit(OS, printSubRegIndex);
+ OS << " },\n {\n";
+
+ // Emit super-class lists.
+ for (const auto &[Idx, RC] : enumerate(RegisterClasses)) {
+ ArrayRef<CodeGenRegisterClass *> Supers = RC.getSuperClasses();
+ OS << " /* " << StartIndices[Idx].SuperClassIdx << " " << RC.getName()
+ << " */ ";
+ for (const auto *Super : Supers)
+ OS << Super->getQualifiedIdName() << ", ";
+ OS << "\n";
+ }
+
OS << " }\n};\n\n";
OS << "const MCRegisterClass &get" << Target.getName()
<< "MCRegisterClass(unsigned RC) {\n"
@@ -1250,6 +1358,9 @@ void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, raw_ostream &MainOS,
OS << "class " << TargetName << "FrameLowering;\n\n";
+ OS << "extern const " << MCRegisterClassStorageType << " " << TargetName
+ << "MCRegisterClassStorage;\n\n";
+
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
<< " explicit " << ClassName
<< "(unsigned RA, unsigned D = 0, unsigned E = 0,\n"
@@ -1319,8 +1430,9 @@ void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, raw_ostream &MainOS,
for (const auto &RC : RegisterClasses) {
// Output the extern for the instance.
- OS << " extern const TargetRegisterClass " << RC.getName()
- << "RegClass;\n";
+ OS << "static constexpr const TargetRegisterClass &" << RC.getName()
+ << "RegClass = " << TargetName << "MCRegisterClassStorage.Classes["
+ << RC.EnumValue << "];\n";
}
}
}
@@ -1446,71 +1558,6 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, raw_ostream &MainOS,
}
OS << "};\n";
- // Emit register class bit mask tables. The first bit mask emitted for a
- // register class, RC, is the set of sub-classes, including RC itself.
- //
- // If RC has super-registers, also create a list of subreg indices and bit
- // masks, (Idx, Mask). The bit mask has a bit for every superreg regclass,
- // SuperRC, that satisfies:
- //
- // For all SuperReg in SuperRC: SuperReg:Idx in RC
- //
- // The 0-terminated list of subreg indices starts at:
- //
- // RC->getSuperRegIndices() = SuperRegIdxSeqs + ...
- //
- // The corresponding bitmasks follow the sub-class mask in memory. Each
- // mask has RCMaskWords uint32_t entries.
- //
- // Every bit mask present in the list has at least one bit set.
-
- // Compress the sub-reg index lists.
- using IdxList = std::vector<const CodeGenSubRegIndex *>;
- SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
- SequenceToOffsetTable<IdxList, deref<std::less<>>> SuperRegIdxSeqs;
- BitVector MaskBV(RegisterClasses.size());
-
- for (const auto &RC : RegisterClasses) {
- OS << "static const uint32_t " << RC.getName()
- << "SubClassMask[] = {\n ";
- printBitVectorAsHex(OS, RC.getSubClasses(), 32);
-
- // Emit super-reg class masks for any relevant SubRegIndices that can
- // project into RC.
- IdxList &SRIList = SuperRegIdxLists[RC.EnumValue];
- for (auto &Idx : SubRegIndices) {
- MaskBV.reset();
- RC.getSuperRegClasses(&Idx, MaskBV);
- if (MaskBV.none())
- continue;
- SRIList.push_back(&Idx);
- OS << "\n ";
- printBitVectorAsHex(OS, MaskBV, 32);
- OS << "// " << Idx.getName();
- }
- SuperRegIdxSeqs.add(SRIList);
- OS << "\n};\n\n";
- }
-
- OS << "static const uint16_t SuperRegIdxSeqs[] = {\n";
- SuperRegIdxSeqs.layout();
- SuperRegIdxSeqs.emit(OS, printSubRegIndex);
- OS << "};\n\n";
-
- // Emit super-class lists.
- for (const auto &RC : RegisterClasses) {
- ArrayRef<CodeGenRegisterClass *> Supers = RC.getSuperClasses();
-
- // Skip classes without supers.
- if (Supers.empty())
- continue;
-
- OS << "static unsigned const " << RC.getName() << "Superclasses[] = {\n";
- for (const auto *Super : Supers)
- OS << " " << Super->getQualifiedIdName() << ",\n";
- OS << "};\n\n";
- }
-
// Emit methods.
for (const auto &RC : RegisterClasses) {
if (!RC.AltOrderSelect.empty()) {
@@ -1541,33 +1588,6 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, raw_ostream &MainOS,
<< RC.getNumOrders() << ");\n return Order[Select];\n}\n";
}
}
-
- // Now emit the actual value-initialized register class instances.
- NamespaceEmitter RegClassNS(OS, RegisterClasses.front().Namespace);
- OS << "// Register class instances.\n";
-
- for (const auto &RC : RegisterClasses) {
- OS << " extern const TargetRegisterClass " << RC.getName()
- << "RegClass = {\n " << "&" << Target.getName()
- << "MCRegisterClassStorage.Classes[" << RC.getName() << "RegClassID],"
- << "\n " << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + "
- << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n ";
- printMask(OS, RC.LaneMask);
- OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n "
- << (RC.GlobalPriority ? "true" : "false") << ",\n "
- << format("0x%02x", RC.TSFlags) << ", /* TSFlags */\n "
- << (unsigned)RC.SpillStackID << ", /* SpillStackID */\n "
- << (RC.HasDisjunctSubRegs ? "true" : "false")
- << ", /* HasDisjunctSubRegs */\n "
- << (RC.CoveredBySubRegs ? "true" : "false")
- << ", /* CoveredBySubRegs */\n ";
- if (RC.getSuperClasses().empty())
- OS << "nullptr, ";
- else
- OS << RC.getName() << "Superclasses, ";
- OS << RC.getSuperClasses().size() << "\n";
- OS << " };\n\n";
- }
}
OS << "static const TargetRegisterClass *const " << TargetName
>From 358e816346cd1ab3184c6f0dd0d543e23fce0ab4 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Thu, 2 Jul 2026 12:45:14 +0000
Subject: [PATCH 2/2] remove copy constructor (added for testing, valid in
C++17, but breaks C++20...)
Created using spr 1.3.8-wip
---
llvm/include/llvm/MC/MCRegisterInfo.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h
index dac8f84119dc3..88f93dfcdf91c 100644
--- a/llvm/include/llvm/MC/MCRegisterInfo.h
+++ b/llvm/include/llvm/MC/MCRegisterInfo.h
@@ -39,8 +39,6 @@ class MCRegisterClass {
using iterator = const MCPhysReg*;
using const_iterator = const MCPhysReg*;
- MCRegisterClass(const MCRegisterClass &) = delete;
-
// TODO: reorder fields to reduce memory usage.
const uint32_t RegsOff; ///< Relative offset to MCPhysReg array.
const uint32_t RegSetOff; ///< Relative offset to uint8_t array.
More information about the llvm-commits
mailing list