https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/158274
Replace the target uses of PointerLikeRegClass with RegClassByHwMode >From cbdfe4d18061f72bb5b3ba5577f9a8bd40fb210c Mon Sep 17 00:00:00 2001 From: Matt Arsenault <matthew.arsena...@amd.com> Date: Tue, 9 Sep 2025 11:15:47 +0900 Subject: [PATCH] X86: Switch to RegClassByHwMode Replace the target uses of PointerLikeRegClass with RegClassByHwMode --- .../X86/MCTargetDesc/X86MCTargetDesc.cpp | 3 ++ llvm/lib/Target/X86/X86.td | 2 ++ llvm/lib/Target/X86/X86InstrInfo.td | 8 ++--- llvm/lib/Target/X86/X86InstrOperands.td | 30 +++++++++++----- llvm/lib/Target/X86/X86InstrPredicates.td | 14 ++++++++ llvm/lib/Target/X86/X86RegisterInfo.cpp | 35 +++++-------------- llvm/lib/Target/X86/X86Subtarget.h | 4 +-- llvm/utils/TableGen/X86FoldTablesEmitter.cpp | 4 +-- 8 files changed, 57 insertions(+), 43 deletions(-) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp index bb1e716c33ed5..1d5ef8b0996dc 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -55,6 +55,9 @@ std::string X86_MC::ParseX86Triple(const Triple &TT) { else FS = "-64bit-mode,-32bit-mode,+16bit-mode"; + if (TT.isX32()) + FS += ",+x32"; + return FS; } diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td index 7c9e821c02fda..3af8b3e060a16 100644 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -25,6 +25,8 @@ def Is32Bit : SubtargetFeature<"32bit-mode", "Is32Bit", "true", "32-bit mode (80386)">; def Is16Bit : SubtargetFeature<"16bit-mode", "Is16Bit", "true", "16-bit mode (i8086)">; +def IsX32 : SubtargetFeature<"x32", "IsX32", "true", + "64-bit with ILP32 programming model (e.g. x32 ABI)">; //===----------------------------------------------------------------------===// // X86 Subtarget ISA features diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 7f6c5614847e3..0c4abc2c400f6 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -18,14 +18,14 @@ include "X86InstrFragments.td" include "X86InstrFragmentsSIMD.td" //===----------------------------------------------------------------------===// -// X86 Operand Definitions. +// X86 Predicate Definitions. // -include "X86InstrOperands.td" +include "X86InstrPredicates.td" //===----------------------------------------------------------------------===// -// X86 Predicate Definitions. +// X86 Operand Definitions. // -include "X86InstrPredicates.td" +include "X86InstrOperands.td" //===----------------------------------------------------------------------===// // X86 Instruction Format Definitions. diff --git a/llvm/lib/Target/X86/X86InstrOperands.td b/llvm/lib/Target/X86/X86InstrOperands.td index 80843f6bb80e6..5207ecad127a2 100644 --- a/llvm/lib/Target/X86/X86InstrOperands.td +++ b/llvm/lib/Target/X86/X86InstrOperands.td @@ -6,9 +6,15 @@ // //===----------------------------------------------------------------------===// +def x86_ptr_rc : RegClassByHwMode< + [X86_32, X86_64, X86_64_X32], + [GR32, GR64, LOW32_ADDR_ACCESS]>; + // A version of ptr_rc which excludes SP, ESP, and RSP. This is used for // the index operand of an address, to conform to x86 encoding restrictions. -def ptr_rc_nosp : PointerLikeRegClass<1>; +def ptr_rc_nosp : RegClassByHwMode< + [X86_32, X86_64, X86_64_X32], + [GR32_NOSP, GR64_NOSP, GR32_NOSP]>; // *mem - Operand definitions for the funky X86 addressing mode operands. // @@ -53,7 +59,7 @@ class X86MemOperand<string printMethod, AsmOperandClass parserMatchClass = X86MemAsmOperand, int size = 0> : Operand<iPTR> { let PrintMethod = printMethod; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); + let MIOperandInfo = (ops x86_ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); let ParserMatchClass = parserMatchClass; let OperandType = "OPERAND_MEMORY"; int Size = size; @@ -63,7 +69,7 @@ class X86MemOperand<string printMethod, class X86VMemOperand<RegisterClass RC, string printMethod, AsmOperandClass parserMatchClass, int size = 0> : X86MemOperand<printMethod, parserMatchClass, size> { - let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); + let MIOperandInfo = (ops x86_ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); } def anymem : X86MemOperand<"printMemReference">; @@ -113,8 +119,14 @@ def sdmem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand>; // A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead // of a plain GPR, so that it doesn't potentially require a REX prefix. -def ptr_rc_norex : PointerLikeRegClass<2>; -def ptr_rc_norex_nosp : PointerLikeRegClass<3>; +def ptr_rc_norex : RegClassByHwMode< + [X86_32, X86_64, X86_64_X32], + [GR32_NOREX, GR64_NOREX, GR32_NOREX]>; + +def ptr_rc_norex_nosp : RegClassByHwMode< + [X86_32, X86_64, X86_64_X32], + [GR32_NOREX_NOSP, GR64_NOREX_NOSP, GR32_NOREX_NOSP]>; + def i8mem_NOREX : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8> { let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, @@ -123,7 +135,9 @@ def i8mem_NOREX : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8> { // GPRs available for tailcall. // It represents GR32_TC, GR64_TC or GR64_TCW64. -def ptr_rc_tailcall : PointerLikeRegClass<4>; +def ptr_rc_tailcall : RegClassByHwMode< + [X86_32, X86_64, X86_64_X32], + [GR32_TC, GR64_TC, GR64_TC]>; // Special i32mem for addresses of load folding tail calls. These are not // allowed to use callee-saved registers since they must be scheduled @@ -270,12 +284,12 @@ let RenderMethod = "addMemOffsOperands" in { class X86SrcIdxOperand<string printMethod, AsmOperandClass parserMatchClass> : X86MemOperand<printMethod, parserMatchClass> { - let MIOperandInfo = (ops ptr_rc, SEGMENT_REG); + let MIOperandInfo = (ops x86_ptr_rc, SEGMENT_REG); } class X86DstIdxOperand<string printMethod, AsmOperandClass parserMatchClass> : X86MemOperand<printMethod, parserMatchClass> { - let MIOperandInfo = (ops ptr_rc); + let MIOperandInfo = (ops x86_ptr_rc); } def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>; diff --git a/llvm/lib/Target/X86/X86InstrPredicates.td b/llvm/lib/Target/X86/X86InstrPredicates.td index 8339c2081842d..c20bb05018b4d 100644 --- a/llvm/lib/Target/X86/X86InstrPredicates.td +++ b/llvm/lib/Target/X86/X86InstrPredicates.td @@ -195,6 +195,12 @@ def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, AssemblerPredicate<(all_of (not Is64Bit)), "Not 64-bit mode">; def In64BitMode : Predicate<"Subtarget->is64Bit()">, AssemblerPredicate<(all_of Is64Bit), "64-bit mode">; + +def IsX32Mode : Predicate<"Subtarget->getTargetTriple().isX32()">, + AssemblerPredicate<(all_of IsX32), "x32 ABI">; +def NotX32Mode : Predicate<"!Subtarget->getTargetTriple().isX32()">, + AssemblerPredicate<(all_of (not IsX32)), "not x32 ABI">; + def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">; def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">; def In16BitMode : Predicate<"Subtarget->is16Bit()">, @@ -250,3 +256,11 @@ def HasMFence : Predicate<"Subtarget->hasMFence()">; def HasFastDPWSSD: Predicate<"Subtarget->hasFastDPWSSD()">; def UseIndirectThunkCalls : Predicate<"Subtarget->useIndirectThunkCalls()">; def NotUseIndirectThunkCalls : Predicate<"!Subtarget->useIndirectThunkCalls()">; + +//===----------------------------------------------------------------------===// +// HwModes +//===----------------------------------------------------------------------===// + +defvar X86_32 = DefaultMode; +def X86_64 : HwMode<[In64BitMode, NotX32Mode]>; +def X86_64_X32 : HwMode<[IsX32Mode]>; diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index c47bb3e67e625..efccf5c72596e 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -194,33 +194,14 @@ X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC, const TargetRegisterClass * X86RegisterInfo::getPointerRegClass(unsigned Kind) const { - switch (Kind) { - default: llvm_unreachable("Unexpected Kind in getPointerRegClass!"); - case 0: // Normal GPRs. - if (IsTarget64BitLP64) - return &X86::GR64RegClass; - // If the target is 64bit but we have been told to use 32bit addresses, - // we can still use 64-bit register as long as we know the high bits - // are zeros. - // Reflect that in the returned register class. - return Is64Bit ? &X86::LOW32_ADDR_ACCESSRegClass : &X86::GR32RegClass; - case 1: // Normal GPRs except the stack pointer (for encoding reasons). - if (IsTarget64BitLP64) - return &X86::GR64_NOSPRegClass; - // NOSP does not contain RIP, so no special case here. - return &X86::GR32_NOSPRegClass; - case 2: // NOREX GPRs. - if (IsTarget64BitLP64) - return &X86::GR64_NOREXRegClass; - return &X86::GR32_NOREXRegClass; - case 3: // NOREX GPRs except the stack pointer (for encoding reasons). - if (IsTarget64BitLP64) - return &X86::GR64_NOREX_NOSPRegClass; - // NOSP does not contain RIP, so no special case here. - return &X86::GR32_NOREX_NOSPRegClass; - case 4: // Available for tailcall (not callee-saved GPRs). - return Is64Bit ? &X86::GR64_TCRegClass : &X86::GR32_TCRegClass; - } + assert(Kind == 0 && "this should only be used for default cases"); + if (IsTarget64BitLP64) + return &X86::GR64RegClass; + // If the target is 64bit but we have been told to use 32bit addresses, + // we can still use 64-bit register as long as we know the high bits + // are zeros. + // Reflect that in the returned register class. + return Is64Bit ? &X86::LOW32_ADDR_ACCESSRegClass : &X86::GR32RegClass; } const TargetRegisterClass * diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h index fa3f3b59741df..a8802c4bf164d 100644 --- a/llvm/lib/Target/X86/X86Subtarget.h +++ b/llvm/lib/Target/X86/X86Subtarget.h @@ -170,10 +170,10 @@ class X86Subtarget final : public X86GenSubtargetInfo { #include "X86GenSubtargetInfo.inc" /// Is this x86_64 with the ILP32 programming model (x32 ABI)? - bool isTarget64BitILP32() const { return Is64Bit && (TargetTriple.isX32()); } + bool isTarget64BitILP32() const { return Is64Bit && IsX32; } /// Is this x86_64 with the LP64 programming model (standard AMD64, no x32)? - bool isTarget64BitLP64() const { return Is64Bit && (!TargetTriple.isX32()); } + bool isTarget64BitLP64() const { return Is64Bit && !IsX32; } PICStyles::Style getPICStyle() const { return PICStyle; } void setPICStyle(PICStyles::Style Style) { PICStyle = Style; } diff --git a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp index b1f7b9a6b4ad9..1e1e4ab650030 100644 --- a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp +++ b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp @@ -553,10 +553,10 @@ void X86FoldTablesEmitter::updateTables(const CodeGenInstruction *RegInst, for (unsigned I = RegOutSize, E = RegInst->Operands.size(); I < E; I++) { const Record *RegOpRec = RegInst->Operands[I].Rec; const Record *MemOpRec = MemInst->Operands[I].Rec; - // PointerLikeRegClass: For instructions like TAILJMPr, TAILJMPr64, + // RegClassByHwMode: For instructions like TAILJMPr, TAILJMPr64, // TAILJMPr64_REX if ((isRegisterOperand(RegOpRec) || - RegOpRec->isSubClassOf("PointerLikeRegClass")) && + (RegOpRec->isSubClassOf("RegClassByHwMode"))) && isMemoryOperand(MemOpRec)) { switch (I) { case 0: _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits