Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e038b70
CodeGen: Add RegisterClass by HwMode
arsenm Aug 24, 2025
b4275a6
Review comments
arsenm Sep 15, 2025
77f9e0a
Move getInitValueAsRegClass into CodeGenTarget
arsenm Sep 15, 2025
dcb4387
Use CodeGenTarget::getInitValueAsRegClass in CodeGenInstAlias
arsenm Sep 15, 2025
149b9fd
getInitValueAsRegClass(Like)
arsenm Sep 15, 2025
0987bce
Fix crash in CodeGenInstAlias
arsenm Sep 15, 2025
44b63fe
Avoid unnecessary declaration
arsenm Sep 15, 2025
943b1f2
Move where emitRegClassByHwModeDecoders is called
arsenm Sep 15, 2025
7c391b6
Fix comment
arsenm Sep 15, 2025
b9bd629
Check RegisterClassLike
arsenm Sep 15, 2025
768d114
Use check literal
arsenm Sep 15, 2025
4e0978f
Structured binding
arsenm Sep 15, 2025
586c48f
Re-use RegInfo HwMode kind
arsenm Sep 15, 2025
f780b46
CodeGenRegBank to RegClassByHwMode
arsenm Sep 15, 2025
e862ef3
comment typos
arsenm Sep 16, 2025
2fee8f8
Address comment
arsenm Sep 16, 2025
706d391
Stop multiple inheritance from Operand<iPTR> in test
arsenm Sep 16, 2025
efbcd71
Use find_if
arsenm Sep 16, 2025
9bbaca3
Move RegClassByHwModeUses definition to header
arsenm Sep 17, 2025
4edfaaa
Another InfoByHwMode structure binding
arsenm Sep 18, 2025
abff318
Apply suggestions from code review
arsenm Sep 19, 2025
4722d06
Update llvm/include/llvm/CodeGen/TargetInstrInfo.h
arsenm Sep 19, 2025
8c4a25b
emplace_front returns reference
arsenm Sep 19, 2025
8bfcdcc
variable for Target.getAllRegClassByHwMode
arsenm Sep 19, 2025
53a024c
assert message
arsenm Sep 19, 2025
080dcc6
whitespace is hard on GitHub
arsenm Sep 19, 2025
d479071
whitespace
arsenm Sep 19, 2025
a9006f3
GitHub whitespace is impossible
arsenm Sep 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions llvm/include/llvm/CodeGen/TargetInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,16 @@ struct ExtAddrMode {
///
class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
protected:
/// Subtarget specific sub-array of MCInstrInfo's RegClassByHwModeTables
/// (i.e. the table for the active HwMode). This should be indexed by
/// MCOperandInfo's RegClass field for LookupRegClassByHwMode operands.
const int16_t *const RegClassByHwMode;

TargetInstrInfo(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u,
unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u)
: CallFrameSetupOpcode(CFSetupOpcode),
unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u,
const int16_t *const RegClassByHwModeTable = nullptr)
: RegClassByHwMode(RegClassByHwModeTable),
CallFrameSetupOpcode(CFSetupOpcode),
CallFrameDestroyOpcode(CFDestroyOpcode), CatchRetOpcode(CatchRetOpcode),
ReturnOpcode(ReturnOpcode) {}

Expand All @@ -133,6 +140,18 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
Opc <= TargetOpcode::GENERIC_ATOMICRMW_OP_END;
}

/// \returns the subtarget appropriate RegClassID for \p OpInfo
///
/// Note this shadows a version of getOpRegClassID in MCInstrInfo which takes
/// an additional argument for the subtarget's HwMode, since TargetInstrInfo
/// is owned by a subtarget in CodeGen but MCInstrInfo is a TargetMachine
/// constant.
int16_t getOpRegClassID(const MCOperandInfo &OpInfo) const {
if (OpInfo.isLookupRegClassByHwMode())
return RegClassByHwMode[OpInfo.RegClass];
return OpInfo.RegClass;
}

/// Given a machine instruction descriptor, returns the register
/// class constraint for OpNum, or NULL.
virtual const TargetRegisterClass *
Expand Down
19 changes: 15 additions & 4 deletions llvm/include/llvm/MC/MCInstrDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ enum OperandConstraint {
/// See the accessors for a description of what these are.
enum OperandFlags {
LookupPtrRegClass = 0,
LookupRegClassByHwMode,
Predicate,
OptionalDef,
BranchTarget
Expand Down Expand Up @@ -85,10 +86,13 @@ enum OperandType {
/// indicating the register class for register operands, etc.
class MCOperandInfo {
public:
/// This specifies the register class enumeration of the operand
/// if the operand is a register. If isLookupPtrRegClass is set, then this is
/// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to
/// get a dynamic register class.
/// This specifies the register class enumeration of the operand if the
/// operand is a register. If LookupRegClassByHwMode is set, then this is an
/// index into a table in TargetInstrInfo or MCInstrInfo which contains the
/// real register class ID.
///
/// If isLookupPtrRegClass is set, then this is an index that is passed to
/// TargetRegisterInfo::getPointerRegClass(x) to get a dynamic register class.
int16_t RegClass;

/// These are flags from the MCOI::OperandFlags enum.
Expand All @@ -102,10 +106,17 @@ class MCOperandInfo {

/// Set if this operand is a pointer value and it requires a callback
/// to look up its register class.
// TODO: Deprecated in favor of isLookupRegClassByHwMode
bool isLookupPtrRegClass() const {
return Flags & (1 << MCOI::LookupPtrRegClass);
}

/// Set if this operand is a value that requires the current hwmode to look up
/// its register class.
bool isLookupRegClassByHwMode() const {
return Flags & (1 << MCOI::LookupRegClassByHwMode);
}

/// Set if this is one of the operands that made up of the predicate
/// operand that controls an isPredicable() instruction.
bool isPredicate() const { return Flags & (1 << MCOI::Predicate); }
Expand Down
28 changes: 27 additions & 1 deletion llvm/include/llvm/MC/MCInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,48 @@ class MCInstrInfo {
const ComplexDeprecationPredicate *ComplexDeprecationInfos;
unsigned NumOpcodes; // Number of entries in the desc array

protected:
// Pointer to 2d array [NumHwModes][NumRegClassByHwModes]
const int16_t *RegClassByHwModeTables;
int16_t NumRegClassByHwModes;

public:
/// Initialize MCInstrInfo, called by TableGen auto-generated routines.
/// *DO NOT USE*.
void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND,
const uint8_t *DF,
const ComplexDeprecationPredicate *CDI, unsigned NO) {
const ComplexDeprecationPredicate *CDI, unsigned NO,
const int16_t *RCHWTables = nullptr,
int16_t NumRegClassByHwMode = 0) {
LastDesc = D + NO - 1;
InstrNameIndices = NI;
InstrNameData = ND;
DeprecatedFeatures = DF;
ComplexDeprecationInfos = CDI;
NumOpcodes = NO;
RegClassByHwModeTables = RCHWTables;
NumRegClassByHwModes = NumRegClassByHwMode;
}

unsigned getNumOpcodes() const { return NumOpcodes; }

const int16_t *getRegClassByHwModeTable(unsigned ModeId) const {
assert(RegClassByHwModeTables && NumRegClassByHwModes != 0 &&
"MCInstrInfo not properly initialized");
return &RegClassByHwModeTables[ModeId * NumRegClassByHwModes];
}

/// Return the ID of the register class to use for \p OpInfo, for the active
/// HwMode \p HwModeId. In general TargetInstrInfo's version which is already
/// specialized to the subtarget should be used.
int16_t getOpRegClassID(const MCOperandInfo &OpInfo,
unsigned HwModeId) const {
int16_t RegClass = OpInfo.RegClass;
if (OpInfo.isLookupRegClassByHwMode())
RegClass = getRegClassByHwModeTable(HwModeId)[RegClass];
return RegClass;
}

/// Return the machine instruction descriptor that corresponds to the
/// specified instruction opcode.
const MCInstrDesc &get(unsigned Opcode) const {
Expand Down
8 changes: 4 additions & 4 deletions llvm/include/llvm/MC/MCSubtargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,10 @@ class LLVM_ABI MCSubtargetInfo {
/// this method also supports controlling multiple attributes with a single
/// HwMode ID, just as was done previously.
enum HwModeType {
HwMode_Default, // Return the smallest HwMode ID of current subtarget.
HwMode_ValueType, // Return the HwMode ID that controls the ValueType.
HwMode_RegInfo, // Return the HwMode ID that controls the RegSizeInfo and
// SubRegRange.
HwMode_Default, // Return the smallest HwMode ID of current subtarget.
HwMode_ValueType, // Return the HwMode ID that controls the ValueType.
HwMode_RegInfo, // Return the HwMode ID that controls the RegSizeInfo,
// SubRegRange, and RegisterClass.
HwMode_EncodingInfo // Return the HwMode ID that controls the EncodingInfo.
};

Expand Down
27 changes: 24 additions & 3 deletions llvm/include/llvm/Target/Target.td
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,20 @@ class DAGOperand {
bit hasCompleteDecoder = true;
}

/// Abstract base class common to RegisterClass and
/// RegClassByHwMode. This permits using RegClassByHwMode in
/// RegisterOperand contexts without creating an artificial
/// RegisterClass.
class RegisterClassLike : DAGOperand;

// RegisterClass - Now that all of the registers are defined, and aliases
// between registers are defined, specify which registers belong to which
// register classes. This also defines the default allocation order of
// registers by register allocators.
//
class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
dag regList, RegAltNameIndex idx = NoRegAltName>
: DAGOperand {
: RegisterClassLike {
string Namespace = namespace;

// The register size/alignment information, parameterized by a HW mode.
Expand Down Expand Up @@ -916,15 +922,30 @@ def decoder;
/// derived from this. TableGen treats the register class as having a symbolic
/// type that it doesn't know, and resolves the actual regclass to use by using
/// the TargetRegisterInfo::getPointerRegClass() hook at codegen time.
///
/// This is deprecated in favor of RegClassByHwMode.
class PointerLikeRegClass<int Kind> {
int RegClassKind = Kind;
}

/// RegClassByHwMode - Operands that change the register class based
/// on the subtarget are derived from this. TableGen
/// treats the register class as having a symbolic kind that it
/// doesn't know, and resolves the actual regclass to use by using the
/// a mapping in TargetInstrInfo at codegen time. This can be used to
/// define operands which swap the register class with the pointer
/// type.
class RegClassByHwMode<list<HwMode> Modes,
list<RegisterClass> RegClasses>
: HwModeSelect<Modes, !size(RegClasses)>, RegisterClassLike {
list<RegisterClass> Objects = RegClasses;
}

/// ptr_rc definition - Mark this operand as being a pointer value whose
/// register class is resolved dynamically via a callback to TargetInstrInfo.
/// FIXME: We should probably change this to a class which contain a list of
/// flags. But currently we have but one flag.
// Deprecated, use RegClassByHwMode instead.
def ptr_rc : PointerLikeRegClass<0>;

/// unknown definition - Mark this operand as being of unknown type, causing
Expand Down Expand Up @@ -1024,10 +1045,10 @@ class Operand<ValueType ty> : DAGOperand {
AsmOperandClass ParserMatchClass = ImmAsmOperand;
}

class RegisterOperand<RegisterClass regclass, string pm = "printOperand">
class RegisterOperand<RegisterClassLike regclass, string pm = "printOperand">
: DAGOperand {
// RegClass - The register class of the operand.
RegisterClass RegClass = regclass;
RegisterClassLike RegClass = regclass;
// PrintMethod - The target method to call to print register operands of
// this type. The method normally will just use an alt-name index to look
// up the name to print. Default to the generic printOperand().
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/CodeGen/TargetInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ TargetInstrInfo::getRegClass(const MCInstrDesc &MCID, unsigned OpNum,
if (OpNum >= MCID.getNumOperands())
return nullptr;

short RegClass = MCID.operands()[OpNum].RegClass;
if (MCID.operands()[OpNum].isLookupPtrRegClass())
const MCOperandInfo &OpInfo = MCID.operands()[OpNum];
int16_t RegClass = getOpRegClassID(OpInfo);

// TODO: Remove isLookupPtrRegClass in favor of isLookupRegClassByHwMode
if (OpInfo.isLookupPtrRegClass())
return TRI->getPointerRegClass(RegClass);

// Instructions like INSERT_SUBREG do not have fixed register classes.
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/AMDGPU/BUFInstructions.td
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,16 @@ class getBUFVDataRegisterOperand<int Size, bit isTFE> {
RegisterOperand ret = !if(isTFE, tfeVDataOp, VDataOp);
}

class getBUFVDataRegisterOperandForOp<RegisterOperand Op, bit isTFE> {
defvar Size = !cast<RegisterClass>(Op.RegClass).Size;
RegisterOperand ret = getBUFVDataRegisterOperand<Size, isTFE>.ret;
}

class getMUBUFInsDA<list<RegisterOperand> vdataList,
list<RegisterClass> vaddrList, bit isTFE, bit hasRestrictedSOffset> {
RegisterOperand vdataClass = !if(!empty(vdataList), ?, !head(vdataList));
RegisterClass vaddrClass = !if(!empty(vaddrList), ?, !head(vaddrList));
RegisterOperand vdata_op = getBUFVDataRegisterOperand<vdataClass.RegClass.Size, isTFE>.ret;
RegisterOperand vdata_op = getBUFVDataRegisterOperandForOp<vdataClass, isTFE>.ret;

dag SOffset = !if(hasRestrictedSOffset, (ins SReg_32:$soffset), (ins SCSrc_b32:$soffset));
dag NonVaddrInputs = !con((ins SReg_128_XNULL:$srsrc), SOffset, (ins Offset:$offset, CPol_0:$cpol, i1imm_0:$swz));
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AMDGPU/SIInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def CPolBit {
int SCAL = 11;
}

class VOPDstOperand <RegisterClass rc> : RegisterOperand <rc, "printVOPDst">;
class VOPDstOperand<RegisterClassLike rc> : RegisterOperand<rc, "printVOPDst">;

def VOPDstOperand_t16 : VOPDstOperand <VGPR_16> {
let EncoderMethod = "getMachineOpValueT16";
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -2636,7 +2636,7 @@ class getAlign2RegOp<RegisterOperand RC> {
}

class getEquivalentAGPROperand<RegisterOperand RC> {
defvar Size = RC.RegClass.Size;
defvar Size = !cast<RegisterClass>(RC.RegClass).Size;
RegisterOperand ret =
!cond(!eq(Size, 32) : RegisterOperand<AGPR_32>,
!eq(Size, 64) : RegisterOperand<AReg_64>,
Expand All @@ -2647,7 +2647,7 @@ class getEquivalentAGPROperand<RegisterOperand RC> {
}

class getEquivalentVGPROperand<RegisterOperand RC> {
defvar Size = RC.RegClass.Size;
defvar Size = !cast<RegisterClass>(RC.RegClass).Size;
RegisterOperand ret =
!cond(!eq(Size, 32) : RegisterOperand<VGPR_32>,
!eq(Size, 64) : RegisterOperand<VReg_64>,
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ unsigned AVRAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
RegName << "r" << RegNum;
if (MCRegister Reg = MatchRegisterName(RegName.str())) {
Op.makeReg(Reg);
if (validateOperandClass(Op, Expected) == Match_Success) {
if (validateOperandClass(Op, Expected, *STI) == Match_Success) {
return Match_Success;
}
}
Expand All @@ -780,7 +780,7 @@ unsigned AVRAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,

if (correspondingDREG) {
Op.makeReg(correspondingDREG);
return validateOperandClass(Op, Expected);
return validateOperandClass(Op, Expected, *STI);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,7 @@ bool SystemZAsmParser::parseDirectiveInsn(SMLoc L) {
MatchClassKind Kind = Entry->OperandKinds[I];

// Verify operand.
unsigned Res = validateOperandClass(Operand, Kind);
unsigned Res = validateOperandClass(Operand, Kind, *STI);
if (Res != Match_Success)
return Error(Operand.getStartLoc(), "unexpected operand type");

Expand Down
Loading