[llvm] [AMDGPU] Export selected AMDGPUBaseInfo utilities from libLLVM (PR #217016)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 05:50:23 PDT 2026


Martin Paul =?utf-8?q?Lücke?= <martin.luecke at amd.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/217016 at github.com>


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Martin Paul Lücke (martin-luecke)

<details>
<summary>Changes</summary>

ROCm AMDGPU binary-transformation path uses LLVM’s MC information to decode instructions, map hardware registers to LLVM pseudo registers, map between instruction encoding forms, and reconstruct code-object ABI state. The required utilities are available when linking directly against the AMDGPU component libraries, but their symbols are hidden when the same consumer links against the monolithic `libLLVM`.

This exports a narrow set of existing `AMDGPUBaseInfo` utilities needed for these operations. This includes named-operand lookup, opcode-form mappings, register queries, subtarget predicates, and code-object implicit-argument layout helpers. Move the selected opcode-mapping declarations to `AMDGPUBaseInfo.h`, where their generated definitions are instantiated.

Because `getNamedOperandIdx` is generated by TableGen, add an opt-in `InstrInfo` setting that applies `LLVM_ABI` to that lookup. The setting remains disabled by default, so this does not change the exported interfaces of other targets.

For `S_SET_VGPR_MSB`, add a semantic query that maps its four fields to MC operand indices instead of exporting the underlying operand-name tables. Migrate `AMDGPUInstPrinter` to this query so the table interpretation remains centralized in AMDGPUBaseInfo.

---
Full diff: https://github.com/llvm/llvm-project/pull/217016.diff


9 Files Affected:

- (modified) llvm/include/llvm/Target/Target.td (+4) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPU.td (+1) 
- (modified) llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp (+6-11) 
- (modified) llvm/lib/Target/AMDGPU/SIInstrInfo.h (-17) 
- (modified) llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp (+21) 
- (modified) llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h (+55-19) 
- (modified) llvm/test/TableGen/get-named-operand-idx.td (+19-4) 
- (modified) llvm/unittests/Target/AMDGPU/AMDGPUUnitTests.cpp (+49) 
- (modified) llvm/utils/TableGen/InstrInfoEmitter.cpp (+14-6) 


``````````diff
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 7d1e7a28b7b6e..27456052c1cba 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1308,6 +1308,10 @@ class InstrInfo {
   //
   // This option is a temporary migration help. It will go away.
   bit guessInstructionProperties = true;
+
+  // Export the generated getNamedOperandIdx function from shared LLVM
+  // libraries.
+  bit ExportNamedOperandLookup = false;
 }
 
 // Standard Pseudo Instructions.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index 4806e1e9901ef..78afbafb485ba 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -2521,6 +2521,7 @@ def FeatureISAVersion13_Generic: FeatureSet<
 //===----------------------------------------------------------------------===//
 
 def AMDGPUInstrInfo : InstrInfo {
+  let ExportNamedOperandLookup = true;
   let guessInstructionProperties = 1;
 }
 
diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
index 2764ff2d68ce0..ded847bda78cf 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
@@ -364,20 +364,15 @@ static MCRegister getRegFromMIA(MCRegister Reg, unsigned OpNo,
   if (!(Enc & AMDGPU::HWEncoding::IS_VGPR))
     return Reg;
 
-  auto Ops = AMDGPU::getVGPRLoweringOperandTables(Desc);
-  if (!Ops.first)
-    return Reg;
-  unsigned Opc = Desc.getOpcode();
+  const AMDGPU::VGPRMSBOperandIndices OperandIndices =
+      AMDGPU::getVGPRMSBOperandIndices(Desc);
   unsigned I;
-  for (I = 0; I < 4; ++I) {
-    if (Ops.first[I] != AMDGPU::OpName::NUM_OPERAND_NAMES &&
-        (unsigned)AMDGPU::getNamedOperandIdx(Opc, Ops.first[I]) == OpNo)
-      break;
-    if (Ops.second && Ops.second[I] != AMDGPU::OpName::NUM_OPERAND_NAMES &&
-        (unsigned)AMDGPU::getNamedOperandIdx(Opc, Ops.second[I]) == OpNo)
+  for (I = 0; I != OperandIndices.size(); ++I) {
+    auto [XOperandIndex, YOperandIndex] = OperandIndices[I];
+    if (XOperandIndex == OpNo || YOperandIndex == OpNo)
       break;
   }
-  if (I == 4)
+  if (I == OperandIndices.size())
     return Reg;
   unsigned OpMSBs = (VgprMSBs >> (I * 2)) & 3;
   if (!OpMSBs)
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
index 6c7b2d7d2279e..8fabfbaa87285 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -1825,24 +1825,12 @@ bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI,
 
 namespace AMDGPU {
 
-  LLVM_READONLY
-  int32_t getVOPe64(uint32_t Opcode);
-
   LLVM_READONLY
   int32_t getVOPe32(uint32_t Opcode);
 
   LLVM_READONLY
   int32_t getSDWAOp(uint32_t Opcode);
 
-  LLVM_READONLY
-  int32_t getDPPOp32(uint32_t Opcode);
-
-  LLVM_READONLY
-  int32_t getDPPOp64(uint32_t Opcode);
-
-  LLVM_READONLY
-  int32_t getBasicFromSDWAOp(uint32_t Opcode);
-
   LLVM_READONLY
   int32_t getCommuteRev(uint32_t Opcode);
 
@@ -1866,11 +1854,6 @@ namespace AMDGPU {
   LLVM_READONLY
   int32_t getGlobalSaddrOp(uint32_t Opcode);
 
-  /// \returns VADDR form of a FLAT Global instruction given an \p Opcode
-  /// of a SADDR form.
-  LLVM_READONLY
-  int32_t getGlobalVaddrOp(uint32_t Opcode);
-
   LLVM_READONLY
   int32_t getVCMPXNoSDstOp(uint32_t Opcode);
 
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
index b2b1e4237367d..16248eebd2ad2 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
@@ -3658,6 +3658,27 @@ getVGPRLoweringOperandTables(const MCInstrDesc &Desc) {
   return {};
 }
 
+VGPRMSBOperandIndices getVGPRMSBOperandIndices(const MCInstrDesc &Desc) {
+  auto [XOperandNames, YOperandNames] = getVGPRLoweringOperandTables(Desc);
+  auto GetOperandIndex = [&](const AMDGPU::OpName *OperandNames,
+                             unsigned Slot) -> std::optional<unsigned> {
+    if (!OperandNames ||
+        OperandNames[Slot] == AMDGPU::OpName::NUM_OPERAND_NAMES)
+      return std::nullopt;
+    int16_t OperandIndex =
+        getNamedOperandIdx(Desc.getOpcode(), OperandNames[Slot]);
+    if (OperandIndex < 0)
+      return std::nullopt;
+    return static_cast<unsigned>(OperandIndex);
+  };
+
+  VGPRMSBOperandIndices Indices;
+  for (unsigned Slot = 0; Slot != Indices.size(); ++Slot)
+    Indices[Slot] = {GetOperandIndex(XOperandNames, Slot),
+                     GetOperandIndex(YOperandNames, Slot)};
+  return Indices;
+}
+
 bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode) {
   const MCInstrDesc &Desc = MII.get(Opcode);
   if (SIInstrFlags::isSMRD(Desc))
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
index 35194739d692e..8e9d829c24628 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
@@ -18,6 +18,7 @@
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Alignment.h"
+#include "llvm/Support/Compiler.h"
 #include "llvm/TargetParser/AMDGPUTargetParser.h"
 #include <array>
 #include <functional>
@@ -83,20 +84,23 @@ unsigned getAMDHSACodeObjectVersion(unsigned ABIVersion);
 /// \returns The default HSA code object version. This should only be used when
 /// we lack a more accurate CodeObjectVersion value (e.g. from the IR module
 /// flag or a .amdhsa_code_object_version directive)
-unsigned getDefaultAMDHSACodeObjectVersion();
+LLVM_ABI unsigned getDefaultAMDHSACodeObjectVersion();
 
 /// \returns ABIVersion suitable for use in ELF's e_ident[EI_ABIVERSION]. \param
 /// CodeObjectVersion is a value returned by getAMDHSACodeObjectVersion().
 uint8_t getELFABIVersion(const Triple &OS, unsigned CodeObjectVersion);
 
 /// \returns The offset of the multigrid_sync_arg argument from implicitarg_ptr
-unsigned getMultigridSyncArgImplicitArgPosition(unsigned COV);
+LLVM_ABI unsigned getMultigridSyncArgImplicitArgPosition(unsigned COV);
 
 /// \returns The offset of the hostcall pointer argument from implicitarg_ptr
-unsigned getHostcallImplicitArgPosition(unsigned COV);
+LLVM_ABI unsigned getHostcallImplicitArgPosition(unsigned COV);
 
-unsigned getDefaultQueueImplicitArgPosition(unsigned COV);
-unsigned getCompletionActionImplicitArgPosition(unsigned COV);
+/// \returns The offset of the default queue pointer from implicitarg_ptr
+LLVM_ABI unsigned getDefaultQueueImplicitArgPosition(unsigned COV);
+
+/// \returns The offset of the completion action pointer from implicitarg_ptr
+LLVM_ABI unsigned getCompletionActionImplicitArgPosition(unsigned COV);
 
 struct GcnBufferFormatInfo {
   unsigned Format;
@@ -619,8 +623,27 @@ LLVM_READONLY
 const GcnBufferFormatInfo *getGcnBufferFormatInfo(uint8_t Format,
                                                   const MCSubtargetInfo &STI);
 
-LLVM_READONLY
-int32_t getMCOpcode(uint32_t Opcode, unsigned Gen);
+/// \returns The opcode for \p Opcode in the \p Gen SIEncodingFamily. Returns
+/// -1 if \p Opcode is already native and INSTRUCTION_LIST_END if it has no
+/// encoding in that family.
+LLVM_ABI LLVM_READONLY int32_t getMCOpcode(uint32_t Opcode, unsigned Gen);
+
+/// \returns The e64 form of \p Opcode, or -1 if no mapping exists.
+LLVM_ABI LLVM_READONLY int32_t getVOPe64(uint32_t Opcode);
+
+/// \returns The DPP form of an ordinary e32 \p Opcode, or -1 if no mapping
+/// exists.
+LLVM_ABI LLVM_READONLY int32_t getDPPOp32(uint32_t Opcode);
+
+/// \returns The DPP form of a VOP3 \p Opcode, or -1 if no mapping exists.
+LLVM_ABI LLVM_READONLY int32_t getDPPOp64(uint32_t Opcode);
+
+/// \returns The ordinary form of an SDWA \p Opcode, or -1 if no mapping exists.
+LLVM_ABI LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode);
+
+/// \returns VADDR form of a FLAT Global instruction given an \p Opcode
+/// of a SADDR form, or -1 if no mapping exists.
+LLVM_ABI LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode);
 
 LLVM_READONLY
 unsigned getVOPDOpcode(unsigned Opc, bool VOPD3);
@@ -629,8 +652,8 @@ LLVM_READONLY
 int getVOPDFull(unsigned OpX, unsigned OpY, unsigned EncodingFamily,
                 bool VOPD3);
 
-LLVM_READONLY
-bool isVOPD(unsigned Opc);
+/// \returns true if \p Opc is a VOPD instruction.
+LLVM_ABI LLVM_READONLY bool isVOPD(unsigned Opc);
 
 LLVM_READNONE
 bool isMAC(unsigned Opc);
@@ -937,8 +960,10 @@ class InstInfo {
 
 } // namespace VOPD
 
-LLVM_READONLY
-std::pair<unsigned, unsigned> getVOPDComponents(unsigned VOPDOpcode);
+/// \returns the X and Y component opcodes for \p VOPDOpcode, which must
+/// identify a VOPD instruction.
+LLVM_ABI LLVM_READONLY std::pair<unsigned, unsigned>
+getVOPDComponents(unsigned VOPDOpcode);
 
 LLVM_READONLY
 // Get properties of 2 single VOP1/VOP2 instructions
@@ -1542,19 +1567,19 @@ bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST);
 /// Is Reg - scalar register
 bool isSGPR(MCRegister Reg, const MCRegisterInfo *TRI);
 
-/// \returns if \p Reg occupies the high 16-bits of a 32-bit register.
-bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI);
+/// \returns true if \p Reg denotes the high 16 bits of a 32-bit register.
+LLVM_ABI bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI);
 
 /// If \p Reg is a pseudo reg, return the correct hardware register given
 /// \p STI otherwise return \p Reg.
 MCRegister getMCReg(MCRegister Reg, const MCSubtargetInfo &STI);
 
-/// Convert hardware register \p Reg to a pseudo register
-LLVM_READNONE
-MCRegister mc2PseudoReg(MCRegister Reg);
+/// \returns the pseudo-register equivalent of \p Reg, or \p Reg if no mapping
+/// exists.
+LLVM_ABI LLVM_READNONE MCRegister mc2PseudoReg(MCRegister Reg);
 
-LLVM_READNONE
-bool isInlineValue(MCRegister Reg);
+/// \returns true if \p Reg is a named inline value.
+LLVM_ABI LLVM_READNONE bool isInlineValue(MCRegister Reg);
 
 /// Is this an AMDGPU specific source operand? These include registers,
 /// inline constants, literals and mandatory literals (KImm).
@@ -1580,7 +1605,7 @@ bool isSISrcInlinableOperand(const MCInstrDesc &Desc, unsigned OpNo);
 unsigned getRegBitWidth(unsigned RCID);
 
 /// Get the size in bits of a register from the register class \p RC.
-unsigned getRegBitWidth(const MCRegisterClass &RC);
+LLVM_ABI unsigned getRegBitWidth(const MCRegisterClass &RC);
 
 LLVM_READNONE
 inline unsigned getOperandSize(const MCOperandInfo &OpInfo) {
@@ -1797,6 +1822,17 @@ std::optional<unsigned> convertSetRegImmToVgprMSBs(const MCInst &MI,
 std::pair<const AMDGPU::OpName *, const AMDGPU::OpName *>
 getVGPRLoweringOperandTables(const MCInstrDesc &Desc);
 
+/// MC operand indices associated with the four two-bit S_SET_VGPR_MSB fields.
+/// Elements 0 through 3 correspond to src0, src1, src2, and dst. Each pair
+/// contains the X and Y component indices for one field. An index is absent
+/// when the instruction has no corresponding operand.
+using VGPRMSBOperandIndices =
+    std::array<std::pair<std::optional<unsigned>, std::optional<unsigned>>, 4>;
+
+/// \returns the S_SET_VGPR_MSB operand-index mapping for \p Desc.
+LLVM_ABI VGPRMSBOperandIndices
+getVGPRMSBOperandIndices(const MCInstrDesc &Desc);
+
 /// \returns true if a memory instruction supports scale_offset modifier.
 bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode);
 
diff --git a/llvm/test/TableGen/get-named-operand-idx.td b/llvm/test/TableGen/get-named-operand-idx.td
index 5e6a9859f3603..5d2b905e1662f 100644
--- a/llvm/test/TableGen/get-named-operand-idx.td
+++ b/llvm/test/TableGen/get-named-operand-idx.td
@@ -1,10 +1,17 @@
-// RUN: llvm-tblgen -gen-instr-info -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-instr-info -I %p/../../include \
+// RUN:   -D EXPORT_NAMED_OPERAND_LOOKUP %s | FileCheck %s
+// RUN: llvm-tblgen -gen-instr-info -I %p/../../include %s | \
+// RUN:   FileCheck %s --check-prefix=NOEXPORT
 
 // Check that OpName enum and getNamedOperandIdx are as expected.
 
 include "llvm/Target/Target.td"
 
-def archInstrInfo : InstrInfo { }
+def archInstrInfo : InstrInfo {
+#ifdef EXPORT_NAMED_OPERAND_LOOKUP
+  let ExportNamedOperandLookup = true;
+#endif
+}
 
 def arch : Target {
   let InstructionSet = archInstrInfo;
@@ -64,13 +71,17 @@ defm : RemapAllTargetPseudoPointerOperands<RegClass>;
 // CHECK-NEXT:    NUM_OPERAND_NAMES = 5,
 // CHECK-NEXT:  }; // enum class OpName
 // CHECK-EMPTY:
-// CHECK-NEXT:  LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName Name);
+// CHECK-NEXT:  LLVM_ABI LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName Name);
 // CHECK-NEXT:  LLVM_READONLY OpName getOperandIdxName(uint32_t Opcode, int16_t Idx);
 // CHECK-EMPTY:
 // CHECK-NEXT:  } // namespace llvm::MyNamespace
 // CHECK-EMPTY:
 // CHECK-NEXT:  #endif // GET_INSTRINFO_OPERAND_ENUM
 
+// NOEXPORT-LABEL: #ifdef GET_INSTRINFO_OPERAND_ENUM
+// NOEXPORT-NOT: LLVM_ABI LLVM_READONLY int16_t getNamedOperandIdx
+// NOEXPORT: LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName Name);
+
 // CHECK-LABEL: #ifdef GET_INSTRINFO_NAMED_OPS
 // CHECK-NEXT:  #undef GET_INSTRINFO_NAMED_OPS
 // CHECK-EMPTY:
@@ -102,7 +113,7 @@ defm : RemapAllTargetPseudoPointerOperands<RegClass>;
 // CHECK-NEXT:    };
 // CHECK-NEXT:    return InstructionIndex[Opcode];
 // CHECK-NEXT:  }
-// CHECK-NEXT:  LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName Name) {
+// CHECK-NEXT:  LLVM_ABI LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName Name) {
 // CHECK-NEXT:    assert(Name != OpName::NUM_OPERAND_NAMES);
 // CHECK-NEXT:    static constexpr int8_t OperandMap[][5] = {
 // CHECK-NEXT:      {-1, -1, -1, -1, -1, },
@@ -126,3 +137,7 @@ defm : RemapAllTargetPseudoPointerOperands<RegClass>;
 // CHECK-NEXT:  } // namespace llvm::MyNamespace
 // CHECK-EMPTY:
 // CHECK-NEXT:  #endif // GET_INSTRINFO_NAMED_OPS
+
+// NOEXPORT-LABEL: #ifdef GET_INSTRINFO_NAMED_OPS
+// NOEXPORT-NOT: LLVM_ABI LLVM_READONLY int16_t getNamedOperandIdx
+// NOEXPORT: LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName Name) {
diff --git a/llvm/unittests/Target/AMDGPU/AMDGPUUnitTests.cpp b/llvm/unittests/Target/AMDGPU/AMDGPUUnitTests.cpp
index 51fda88e66eca..0b87d3231fd2f 100644
--- a/llvm/unittests/Target/AMDGPU/AMDGPUUnitTests.cpp
+++ b/llvm/unittests/Target/AMDGPU/AMDGPUUnitTests.cpp
@@ -10,6 +10,7 @@
 #include "AMDGPUGenSubtargetInfo.inc"
 #include "AMDGPUTargetMachine.h"
 #include "GCNSubtarget.h"
+#include "Utils/AMDGPUBaseInfo.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/TargetParser/AMDGPUTargetParser.h"
@@ -375,3 +376,51 @@ TEST_F(AMDGPUTestBase, TestGetNamedOperandIdx) {
     }
   }
 }
+
+TEST_F(AMDGPUTestBase, TestGetVGPRMSBOperandIndices) {
+  std::unique_ptr<const GCNTargetMachine> TM =
+      createAMDGPUTargetMachine(Triple("amdgpu9.00-amd-"), "", "");
+  ASSERT_NE(TM, nullptr);
+  const MCInstrInfo *MCII = TM->getMCInstrInfo();
+
+  const MCInstrDesc &Move = MCII->get(AMDGPU::V_MOV_B32_e32);
+  const AMDGPU::VGPRMSBOperandIndices MoveIndices =
+      AMDGPU::getVGPRMSBOperandIndices(Move);
+  EXPECT_EQ(MoveIndices[0].first,
+            static_cast<unsigned>(AMDGPU::getNamedOperandIdx(
+                Move.getOpcode(), AMDGPU::OpName::src0)));
+  EXPECT_FALSE(MoveIndices[0].second);
+  EXPECT_FALSE(MoveIndices[1].first);
+  EXPECT_EQ(MoveIndices[3].first,
+            static_cast<unsigned>(AMDGPU::getNamedOperandIdx(
+                Move.getOpcode(), AMDGPU::OpName::vdst)));
+
+  const MCInstrDesc &FMAMK = MCII->get(AMDGPU::V_FMAMK_F32);
+  const AMDGPU::VGPRMSBOperandIndices FMAMKIndices =
+      AMDGPU::getVGPRMSBOperandIndices(FMAMK);
+  EXPECT_FALSE(FMAMKIndices[1].first);
+  EXPECT_EQ(FMAMKIndices[2].first,
+            static_cast<unsigned>(AMDGPU::getNamedOperandIdx(
+                FMAMK.getOpcode(), AMDGPU::OpName::src1)));
+
+  const MCInstrDesc &VOPD =
+      MCII->get(AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_gfx12);
+  const AMDGPU::VGPRMSBOperandIndices VOPDIndices =
+      AMDGPU::getVGPRMSBOperandIndices(VOPD);
+  EXPECT_EQ(VOPDIndices[0].first,
+            static_cast<unsigned>(AMDGPU::getNamedOperandIdx(
+                VOPD.getOpcode(), AMDGPU::OpName::src0X)));
+  EXPECT_EQ(VOPDIndices[0].second,
+            static_cast<unsigned>(AMDGPU::getNamedOperandIdx(
+                VOPD.getOpcode(), AMDGPU::OpName::src0Y)));
+}
+
+TEST_F(AMDGPUTestBase, TestIsHi16Reg) {
+  std::unique_ptr<const GCNTargetMachine> TM =
+      createAMDGPUTargetMachine(Triple("amdgpu9.00-amd-"), "", "");
+  ASSERT_NE(TM, nullptr);
+  const MCRegisterInfo &MRI = TM->getMCRegisterInfo();
+
+  EXPECT_TRUE(AMDGPU::isHi16Reg(AMDGPU::VGPR0_HI16, MRI));
+  EXPECT_FALSE(AMDGPU::isHi16Reg(AMDGPU::VGPR0_LO16, MRI));
+}
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 272912aa90f63..81a396004af69 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -274,9 +274,12 @@ static void emitGetInstructionIndexForOpLookup(
 static void
 emitGetNamedOperandIdx(raw_ostream &OS,
                        const MapVector<SmallVector<int>, unsigned> &OperandMap,
-                       unsigned MaxOperandNo, unsigned NumOperandNames) {
-  OS << "LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName "
-        "Name) {\n";
+                       unsigned MaxOperandNo, unsigned NumOperandNames,
+                       bool ExportNamedOperandLookup) {
+  if (ExportNamedOperandLookup)
+    OS << "LLVM_ABI ";
+  OS << "LLVM_READONLY int16_t "
+        "getNamedOperandIdx(uint32_t Opcode, OpName Name) {\n";
   OS << "  assert(Name != OpName::NUM_OPERAND_NAMES);\n";
   if (!NumOperandNames) {
     // There are no operands, so no need to emit anything
@@ -399,6 +402,8 @@ void InstrInfoEmitter::emitOperandNameMappings(
 
   const size_t NumOperandNames = OperandNameToID.size();
   const unsigned MaxNumOperands = MaxOperandNo + 1;
+  const bool ExportNamedOperandLookup =
+      Target.getInstructionSet()->getValueAsBit("ExportNamedOperandLookup");
 
   const SmallString<32> Namespace({"llvm::", Target.getInstNamespace()});
   {
@@ -414,8 +419,10 @@ void InstrInfoEmitter::emitOperandNameMappings(
     OS << "  NUM_OPERAND_NAMES = " << NumOperandNames << ",\n";
     OS << "}; // enum class OpName\n\n";
 
-    OS << "LLVM_READONLY int16_t getNamedOperandIdx(uint32_t Opcode, OpName "
-          "Name);\n";
+    if (ExportNamedOperandLookup)
+      OS << "LLVM_ABI ";
+    OS << "LLVM_READONLY int16_t "
+          "getNamedOperandIdx(uint32_t Opcode, OpName Name);\n";
     OS << "LLVM_READONLY OpName getOperandIdxName(uint32_t Opcode, int16_t "
           "Idx);\n";
   }
@@ -425,7 +432,8 @@ void InstrInfoEmitter::emitOperandNameMappings(
     NamespaceEmitter NS(OS, Namespace);
     emitGetInstructionIndexForOpLookup(OS, OperandMap, InstructionIndex);
 
-    emitGetNamedOperandIdx(OS, OperandMap, MaxOperandNo, NumOperandNames);
+    emitGetNamedOperandIdx(OS, OperandMap, MaxOperandNo, NumOperandNames,
+                           ExportNamedOperandLookup);
     emitGetOperandIdxName(OS, OperandNameToID, OperandMap, MaxNumOperands,
                           NumOperandNames);
   }

``````````

</details>


https://github.com/llvm/llvm-project/pull/217016


More information about the llvm-commits mailing list