[Mlir-commits] [mlir] [MLIR][LLVMIR] Import unregistered intrinsics via llvm.intrinsic_call (PR #128626)

Bruno Cardoso Lopes llvmlistbot at llvm.org
Tue Feb 25 15:13:06 PST 2025


https://github.com/bcardosolopes updated https://github.com/llvm/llvm-project/pull/128626

>From 3896bb916e925427f997906591cb813bdde202f8 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 20 Feb 2025 16:24:56 -0800
Subject: [PATCH 1/5] [MLIR][LLVMIR] Import unregistered intrinsics via
 llvm.intrinsic_call

Currently, the llvm importer can only cover intrinsics that have a first class
representation in an MLIR dialect (arm-neon, etc). This PR introduces a
fallback mechanism that allow "unregistered" intrinsics to be imported by using
the generic `llvm.intrinsic_call` operation. This is useful in several ways:

1. Allows round-trip the LLVM dialect output lowered from other dialects
(example: ClangIR)
2. Enables MLIR-linking tools to operate on imported LLVM IR without requiring
adding new operations to dozen of different targets (cc @xlauko @smeenai).

Implemented:
- Cover intrinsics across all current supported LLVM targets and generic ones.
- Use existing LLVM tablegen files to populate intrinsic matching.
- Matches with lower priority against dialect supported intrinsic conversion.

Open question: how to add the proper include path for tablegen to find
Intrinsics.td?
---
 .../mlir/Dialect/LLVMIR/CMakeLists.txt        |  26 ++++
 .../mlir/Target/LLVMIR/LLVMImportInterface.h  |  24 +++-
 mlir/lib/Dialect/LLVMIR/CMakeLists.txt        |   3 +
 .../LLVMIR/LLVMIRToLLVMTranslation.cpp        | 125 ++++++++++++++++++
 .../Target/LLVMIR/Import/import-failure.ll    |  12 --
 .../LLVMIR/Import/intrinsic-unregistered.ll   |  68 ++++++++++
 .../tools/mlir-tblgen/LLVMIRConversionGen.cpp |  57 ++++++++
 7 files changed, 302 insertions(+), 13 deletions(-)
 create mode 100644 mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll

diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index 759de745440c2..cefd1bbe4b027 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -81,3 +81,29 @@ mlir_tablegen(VCIXConversions.inc -gen-llvmir-conversions)
 mlir_tablegen(VCIXOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=vcix)
 mlir_tablegen(VCIXOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=vcix)
 add_public_tablegen_target(MLIRVCIXConversionsIncGen)
+
+# FIXME: Should emit extra file with intrinsics_gen if MLIR is enabled? Or maybe find
+# a better way to get the path for Intrinsics.td?
+set(LLVM_TARGET_DEFINITIONS ../../../../../llvm/include/llvm/IR/Intrinsics.td)
+
+mlir_tablegen(LLVMUnregisteredLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics)
+mlir_tablegen(LLVMUnregisteredAArch64LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=aarch64)
+mlir_tablegen(LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=amdgcn)
+mlir_tablegen(LLVMUnregisteredARMLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=arm)
+mlir_tablegen(LLVMUnregisteredBPFLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=bpf)
+mlir_tablegen(LLVMUnregisteredDirectXLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=dx)
+mlir_tablegen(LLVMUnregisteredHexagonLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=hexagon)
+mlir_tablegen(LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=loongarch)
+mlir_tablegen(LLVMUnregisteredMipsLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=mips)
+mlir_tablegen(LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=nvvm)
+mlir_tablegen(LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=ppc)
+mlir_tablegen(LLVMUnregisteredR600LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=r600)
+mlir_tablegen(LLVMUnregisteredRISCVLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=riscv)
+mlir_tablegen(LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=spv)
+mlir_tablegen(LLVMUnregisteredS390LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=s390)
+mlir_tablegen(LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=wasm)
+mlir_tablegen(LLVMUnregisteredX86LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=x86)
+mlir_tablegen(LLVMUnregisteredXCoreLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=xcore)
+mlir_tablegen(LLVMUnregisteredVELLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=ve)
+
+add_public_tablegen_target(MLIRLLVMIntrinsicUnregisteredIncGen)
\ No newline at end of file
diff --git a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
index cc5a77ed35d2b..d122021e8586d 100644
--- a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
+++ b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
@@ -74,6 +74,10 @@ class LLVMImportDialectInterface
   /// returns the list of supported intrinsic identifiers.
   virtual ArrayRef<unsigned> getSupportedIntrinsics() const { return {}; }
 
+  /// Returns the list of LLVM IR intrinsic identifiers that are unsupported
+  /// but dialects might have a generic way to represent them.
+  virtual ArrayRef<unsigned> getUnregisteredIntrinsics() const { return {}; }
+
   /// Hook for derived dialect interfaces to publish the supported instructions.
   /// As every LLVM IR instruction has a unique integer identifier, the function
   /// returns the list of supported instruction identifiers. These identifiers
@@ -139,6 +143,9 @@ class LLVMImportInterface
       // Add a mapping for all supported intrinsic identifiers.
       for (unsigned id : iface.getSupportedIntrinsics())
         intrinsicToDialect[id] = iface.getDialect();
+      // Add a mapping for all unregistered intrinsic identifiers.
+      for (unsigned id : iface.getUnregisteredIntrinsics())
+        unregisteredIntrinscToDialect[id] = iface.getDialect();
       // Add a mapping for all supported instruction identifiers.
       for (unsigned id : iface.getSupportedInstructions())
         instructionToDialect[id] = &iface;
@@ -155,7 +162,19 @@ class LLVMImportInterface
   LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
                                  LLVM::ModuleImport &moduleImport) const {
     // Lookup the dialect interface for the given intrinsic.
-    Dialect *dialect = intrinsicToDialect.lookup(inst->getIntrinsicID());
+    llvm::Intrinsic::ID intrinId = inst->getIntrinsicID();
+    if (intrinId == llvm::Intrinsic::not_intrinsic)
+      return failure();
+
+    // First lookup intrinsic across different dialects for known
+    // supported converstions, examples include arm-neon, nvm-sve, etc
+    Dialect *dialect = intrinsicToDialect.lookup(intrinId);
+
+    // No specialized (supported) intrinsics, attempt to generate a generic
+    // version via llvm.call_intrinsic (if available).
+    if (!dialect)
+      dialect = unregisteredIntrinscToDialect.lookup(intrinId);
+
     if (!dialect)
       return failure();
 
@@ -227,6 +246,9 @@ class LLVMImportInterface
   DenseMap<unsigned, Dialect *> intrinsicToDialect;
   DenseMap<unsigned, const LLVMImportDialectInterface *> instructionToDialect;
   DenseMap<unsigned, SmallVector<Dialect *, 1>> metadataToDialect;
+
+  /// Unregistered generic and target independent intrinsics.
+  DenseMap<unsigned, Dialect *> unregisteredIntrinscToDialect;
 };
 
 } // namespace mlir
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index c9a3b97294562..030aed9cdb06a 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -17,6 +17,9 @@ add_mlir_dialect_library(MLIRLLVMDialect
   MLIRLLVMTypesIncGen
   MLIRLLVMIntrinsicOpsIncGen
   MLIRLLVMInterfacesIncGen
+  MLIRLLVMConversionsIncGen
+  MLIRLLVMIntrinsicConversionsIncGen
+  MLIRLLVMIntrinsicUnregisteredIncGen
   MLIROpenMPOpsIncGen
   intrinsics_gen
 
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
index 4fd043c7c93e6..88ea2ff58434d 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
@@ -24,6 +24,24 @@
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IntrinsicsAArch64.h"
+#include "llvm/IR/IntrinsicsAMDGPU.h"
+#include "llvm/IR/IntrinsicsARM.h"
+#include "llvm/IR/IntrinsicsBPF.h"
+#include "llvm/IR/IntrinsicsDirectX.h"
+#include "llvm/IR/IntrinsicsHexagon.h"
+#include "llvm/IR/IntrinsicsLoongArch.h"
+#include "llvm/IR/IntrinsicsMips.h"
+#include "llvm/IR/IntrinsicsNVPTX.h"
+#include "llvm/IR/IntrinsicsPowerPC.h"
+#include "llvm/IR/IntrinsicsR600.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
+#include "llvm/IR/IntrinsicsS390.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/IR/IntrinsicsVE.h"
+#include "llvm/IR/IntrinsicsWebAssembly.h"
+#include "llvm/IR/IntrinsicsX86.h"
+#include "llvm/IR/IntrinsicsXCore.h"
 #include "llvm/Support/ModRef.h"
 
 using namespace mlir;
@@ -56,6 +74,105 @@ static ArrayRef<unsigned> getSupportedIntrinsicsImpl() {
   return convertibleIntrinsics;
 }
 
+/// Returns true if the LLVM IR intrinsic is convertible to llvm.intrinsic_call
+/// Returns false otherwise.
+static bool isConvertibleUnregisteredIntrinsic(llvm::Intrinsic::ID id) {
+  static const DenseSet<unsigned> convertibleTargetIntrinsics = {
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAArch64LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredARMLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredBPFLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredDirectXLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredHexagonLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredMipsLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredR600LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredRISCVLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredS390LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredVELLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredX86LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredXCoreLLVMIRIntrinsics.inc"
+  };
+  return convertibleTargetIntrinsics.contains(id);
+}
+
+/// Returns the list of LLVM IR intrinsic identifiers that are not registered
+/// by any dialect but can be convertible to llvm.intrinsic_call operation.
+static ArrayRef<unsigned> getUnregisteredIntrinsicsImpl() {
+  static const SmallVector<unsigned> convertibleTargetIntrinsics = {
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAArch64LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredARMLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredBPFLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredDirectXLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredHexagonLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredMipsLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredR600LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredRISCVLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredS390LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredVELLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredX86LLVMIRIntrinsics.inc"
+#include "mlir/Dialect/LLVMIR/LLVMUnregisteredXCoreLLVMIRIntrinsics.inc"
+  };
+  return convertibleTargetIntrinsics;
+}
+
+/// Converts the LLVM intrinsic to a generic LLVM intrinsic call using
+/// llvm.intrinsic_call. Returns failure otherwise.
+static LogicalResult
+convertUnregisteredIntrinsicImpl(OpBuilder &odsBuilder, llvm::CallInst *inst,
+                                 LLVM::ModuleImport &moduleImport) {
+  llvm::Intrinsic::ID intrinsicID = inst->getIntrinsicID();
+  StringRef intrinName = inst->getCalledFunction()->getName();
+
+  // Sanity check the intrinsic ID.
+  assert(isConvertibleUnregisteredIntrinsic(intrinsicID));
+  SmallVector<llvm::Value *> args(inst->args());
+  ArrayRef<llvm::Value *> llvmOperands(args);
+
+  SmallVector<llvm::OperandBundleUse> llvmOpBundles;
+  llvmOpBundles.reserve(inst->getNumOperandBundles());
+  for (unsigned i = 0; i < inst->getNumOperandBundles(); ++i)
+    llvmOpBundles.push_back(inst->getOperandBundleAt(i));
+
+  SmallVector<Value> mlirOperands;
+  SmallVector<NamedAttribute> mlirAttrs;
+  if (failed(moduleImport.convertIntrinsicArguments(
+          llvmOperands, llvmOpBundles, false, {}, {}, mlirOperands, mlirAttrs)))
+    return failure();
+
+  mlir::Type results = moduleImport.convertType(inst->getType());
+  auto op = odsBuilder.create<::mlir::LLVM::CallIntrinsicOp>(
+      moduleImport.translateLoc(inst->getDebugLoc()), results,
+      StringAttr::get(odsBuilder.getContext(), intrinName),
+      ValueRange{mlirOperands}, FastmathFlagsAttr{});
+
+  moduleImport.setFastmathFlagsAttr(inst, op);
+
+  // Update importer tracking of results.
+  unsigned numRes = op.getNumResults();
+  if (numRes == 1)
+    moduleImport.mapValue(inst) = op.getResult(0);
+  else if (numRes == 0)
+    moduleImport.mapNoResultOp(inst);
+  else
+    return op.emitError(
+        "expected at most one result from target intrinsic call");
+
+  return success();
+}
+
 /// Converts the LLVM intrinsic to an MLIR LLVM dialect operation if a
 /// conversion exits. Returns failure otherwise.
 static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
@@ -75,6 +192,8 @@ static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
       llvmOpBundles.push_back(inst->getOperandBundleAt(i));
 
 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicFromLLVMIRConversions.inc"
+  } else if (isConvertibleUnregisteredIntrinsic(intrinsicID)) {
+    return convertUnregisteredIntrinsicImpl(odsBuilder, inst, moduleImport);
   }
 
   return failure();
@@ -422,6 +541,12 @@ class LLVMDialectLLVMIRImportInterface : public LLVMImportDialectInterface {
     return getSupportedIntrinsicsImpl();
   }
 
+  /// Returns the list of LLVM IR intrinsic identifiers that are unsupported
+  /// by existing dialects by are convertible to generic llvm.call_intrinsic.
+  ArrayRef<unsigned> getUnregisteredIntrinsics() const final {
+    return getUnregisteredIntrinsicsImpl();
+  }
+
   /// Returns the list of LLVM IR metadata kinds that are convertible to MLIR
   /// LLVM dialect attributes.
   ArrayRef<unsigned>
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index d929a59284762..fc4ccddb756d5 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -38,18 +38,6 @@ bb1:
 
 ; // -----
 
-declare void @llvm.gcroot(ptr %arg1, ptr %arg2)
-
-; CHECK:      <unknown>
-; CHECK-SAME: error: unhandled intrinsic: call void @llvm.gcroot(ptr %arg1, ptr null)
-define void @unhandled_intrinsic() gc "example" {
-  %arg1 = alloca ptr
-  call void @llvm.gcroot(ptr %arg1, ptr null)
-  ret void
-}
-
-; // -----
-
 ; Check that debug intrinsics with an unsupported argument are dropped.
 
 declare void @llvm.dbg.value(metadata, metadata, metadata)
diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
new file mode 100644
index 0000000000000..0f30ce438dbaa
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
@@ -0,0 +1,68 @@
+; RUN: mlir-translate -import-llvm %s -split-input-file | FileCheck %s
+
+declare i64 @llvm.aarch64.ldxr.p0(ptr)
+
+define dso_local void @t0(ptr %a) {
+  %x = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i8) %a)
+  ret void
+}
+
+; CHECK-LABEL: llvm.func @llvm.aarch64.ldxr.p0(!llvm.ptr)
+; CHECK-LABEL: llvm.func @t0
+; CHECK:   llvm.call_intrinsic "llvm.aarch64.ldxr.p0"({{.*}}) : (!llvm.ptr) -> i64
+; CHECK:   llvm.return
+; CHECK: }
+
+; -----
+
+declare <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8>, <8 x i8>)
+
+define dso_local <8 x i8> @t1(<8 x i8> %lhs, <8 x i8> %rhs) {
+  %r = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> %lhs, <8 x i8> %rhs)
+  ret <8 x i8> %r
+}
+
+; CHECK: llvm.func @t1(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>) -> vector<8xi8> {{.*}} {
+; CHECK:   %[[R:.*]] = llvm.call_intrinsic "llvm.aarch64.neon.uabd.v8i8"(%[[A0]], %[[A1]]) : (vector<8xi8>, vector<8xi8>) -> vector<8xi8>
+; CHECK:   llvm.return %[[R]] : vector<8xi8>
+; CHECK: }
+
+; -----
+
+declare void @llvm.aarch64.neon.st2.v8i8.p0(<8 x i8>, <8 x i8>, ptr)
+
+define dso_local void @t2(<8 x i8> %lhs, <8 x i8> %rhs, ptr %a) {
+  call void @llvm.aarch64.neon.st2.v8i8.p0(<8 x i8> %lhs, <8 x i8> %rhs, ptr %a)
+  ret void
+}
+
+; CHECK: llvm.func @t2(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>, %[[A2:.*]]: !llvm.ptr) {{.*}} {
+; CHECK:   llvm.call_intrinsic "llvm.aarch64.neon.st2.v8i8.p0"(%[[A0]], %[[A1]], %[[A2]]) : (vector<8xi8>, vector<8xi8>, !llvm.ptr) -> !llvm.void
+; CHECK:   llvm.return
+; CHECK: }
+
+; -----
+
+declare void @llvm.gcroot(ptr %arg1, ptr %arg2)
+define void @gctest() gc "example" {
+  %arg1 = alloca ptr
+  call void @llvm.gcroot(ptr %arg1, ptr null)
+  ret void
+}
+
+; CHECK-LABEL: @gctest
+; CHECK: llvm.call_intrinsic "llvm.gcroot"({{.*}}, {{.*}}) : (!llvm.ptr, !llvm.ptr) -> !llvm.void
+
+; -----
+
+; Test we get the supported version, not the unregistered one.
+
+declare i32 @llvm.lround.i32.f32(float)
+
+; CHECK-LABEL: llvm.func @lround_test
+define void @lround_test(float %0, double %1) {
+  ; CHECK-NOT: llvm.call_intrinsic "llvm.lround
+  ; CHECK: llvm.intr.lround(%{{.*}}) : (f32) -> i32
+  %3 = call i32 @llvm.lround.i32.f32(float %0)
+  ret void
+}
\ No newline at end of file
diff --git a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
index 9e19f479d673a..c78872fa2de39 100644
--- a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
+++ b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/Error.h"
@@ -564,6 +565,46 @@ static bool emitConvertibleIntrinsics(const RecordKeeper &records,
   return false;
 }
 
+static void emitOneUnregisteredIntrinsic(const Record &record, raw_ostream &os,
+                                         StringRef targetName) {
+  StringRef targetPrefix = record.getValueAsString("TargetPrefix");
+
+  // Not interested in target specific intrinsics in the generic namespace.
+  if (targetName.empty() && !targetPrefix.empty())
+    return;
+
+  // Skip unknown targets.
+  if (!targetName.empty() && targetPrefix != targetName)
+    return;
+
+  StringRef defName = record.getName();
+  ArrayRef<SMLoc> defLoc = record.getLoc();
+
+  // Sanity check the input.
+  if (!defName.starts_with("int_"))
+    PrintFatalError(defLoc,
+                    "Intrinsic '" + defName + "' does not start with 'int_'!");
+
+  StringRef enumName = defName.substr(4);
+
+  os << "llvm::Intrinsic::";
+  if (!targetName.empty())
+    os << StringRef(targetName).upper() << "Intrinsics::";
+  os << enumName << ",\n";
+}
+
+// Emit the list of LLVM IR intrinsics enums, both target and generic. Those
+// are used for LLVMImporter's convenience when looking at intrinsics while
+// being up-to-date with new additions to LLVM.
+static bool emitUnregisteredIntrinsics(const RecordKeeper &records,
+                                       raw_ostream &os, StringRef targetName) {
+
+  for (const Record *def : records.getAllDerivedDefinitions("Intrinsic"))
+    emitOneUnregisteredIntrinsic(*def, os, targetName);
+
+  return false;
+}
+
 static mlir::GenRegistration
     genLLVMIRConversions("gen-llvmir-conversions",
                          "Generate LLVM IR conversions", emitBuilders);
@@ -590,3 +631,19 @@ static mlir::GenRegistration genConvertibleLLVMIRIntrinsics(
     "gen-convertible-llvmir-intrinsics",
     "Generate list of convertible LLVM IR intrinsics",
     emitConvertibleIntrinsics);
+
+static llvm::cl::OptionCategory
+    genUnregIntrinsicCat("Options for -gen-unregistered-llvmir-intrinsics");
+static llvm::cl::opt<std::string> unregIntrinsicPrefix(
+    "intrinsic-prefix",
+    cl::desc("Specify target to generate intrinsic information"),
+    cl::value_desc("target prefix"), cl::cat(genUnregIntrinsicCat));
+
+static mlir::GenRegistration genUnregisteredLLVMIRIntrinsics(
+    "gen-unregistered-llvmir-intrinsics",
+    "Generate enum list of target specific or generic intrinsics according to "
+    "enums defined in LLVM by other tablegen backends",
+    [](const RecordKeeper &records, raw_ostream &os) {
+      return emitUnregisteredIntrinsics(records, os,
+                                        unregIntrinsicPrefix.getValue());
+    });
\ No newline at end of file

>From 17bad5a1a9449a71ab5ec271b4640146c423a9dc Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 25 Feb 2025 11:31:59 -0800
Subject: [PATCH 2/5] Fix newlines

---
 mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll | 2 +-
 mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
index 0f30ce438dbaa..ac7772f488f20 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
@@ -65,4 +65,4 @@ define void @lround_test(float %0, double %1) {
   ; CHECK: llvm.intr.lround(%{{.*}}) : (f32) -> i32
   %3 = call i32 @llvm.lround.i32.f32(float %0)
   ret void
-}
\ No newline at end of file
+}
diff --git a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
index c78872fa2de39..23e7949ea13f3 100644
--- a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
+++ b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
@@ -646,4 +646,4 @@ static mlir::GenRegistration genUnregisteredLLVMIRIntrinsics(
     [](const RecordKeeper &records, raw_ostream &os) {
       return emitUnregisteredIntrinsics(records, os,
                                         unregIntrinsicPrefix.getValue());
-    });
\ No newline at end of file
+    });

>From 69239c9f88274de7d5dc93235e59b6671111582b Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 25 Feb 2025 12:08:41 -0800
Subject: [PATCH 3/5] Simplify and remove tablegen fine grained tracking

---
 .../mlir/Dialect/LLVMIR/CMakeLists.txt        | 26 ------
 .../mlir/Target/LLVMIR/LLVMImportInterface.h  | 19 +++--
 mlir/lib/Dialect/LLVMIR/CMakeLists.txt        |  3 -
 .../LLVMIR/LLVMIRToLLVMTranslation.cpp        | 83 +------------------
 .../tools/mlir-tblgen/LLVMIRConversionGen.cpp | 57 -------------
 5 files changed, 14 insertions(+), 174 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index cefd1bbe4b027..759de745440c2 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -81,29 +81,3 @@ mlir_tablegen(VCIXConversions.inc -gen-llvmir-conversions)
 mlir_tablegen(VCIXOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=vcix)
 mlir_tablegen(VCIXOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=vcix)
 add_public_tablegen_target(MLIRVCIXConversionsIncGen)
-
-# FIXME: Should emit extra file with intrinsics_gen if MLIR is enabled? Or maybe find
-# a better way to get the path for Intrinsics.td?
-set(LLVM_TARGET_DEFINITIONS ../../../../../llvm/include/llvm/IR/Intrinsics.td)
-
-mlir_tablegen(LLVMUnregisteredLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics)
-mlir_tablegen(LLVMUnregisteredAArch64LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=aarch64)
-mlir_tablegen(LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=amdgcn)
-mlir_tablegen(LLVMUnregisteredARMLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=arm)
-mlir_tablegen(LLVMUnregisteredBPFLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=bpf)
-mlir_tablegen(LLVMUnregisteredDirectXLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=dx)
-mlir_tablegen(LLVMUnregisteredHexagonLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=hexagon)
-mlir_tablegen(LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=loongarch)
-mlir_tablegen(LLVMUnregisteredMipsLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=mips)
-mlir_tablegen(LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=nvvm)
-mlir_tablegen(LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=ppc)
-mlir_tablegen(LLVMUnregisteredR600LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=r600)
-mlir_tablegen(LLVMUnregisteredRISCVLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=riscv)
-mlir_tablegen(LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=spv)
-mlir_tablegen(LLVMUnregisteredS390LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=s390)
-mlir_tablegen(LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=wasm)
-mlir_tablegen(LLVMUnregisteredX86LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=x86)
-mlir_tablegen(LLVMUnregisteredXCoreLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=xcore)
-mlir_tablegen(LLVMUnregisteredVELLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=ve)
-
-add_public_tablegen_target(MLIRLLVMIntrinsicUnregisteredIncGen)
\ No newline at end of file
diff --git a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
index d122021e8586d..6004fd1519022 100644
--- a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
+++ b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
@@ -74,9 +74,9 @@ class LLVMImportDialectInterface
   /// returns the list of supported intrinsic identifiers.
   virtual ArrayRef<unsigned> getSupportedIntrinsics() const { return {}; }
 
-  /// Returns the list of LLVM IR intrinsic identifiers that are unsupported
-  /// but dialects might have a generic way to represent them.
-  virtual ArrayRef<unsigned> getUnregisteredIntrinsics() const { return {}; }
+  /// Whether dialect have a generic way to represent unsupported intrinsics
+  /// (i.e. as oposed to supported ones aboves).
+  virtual bool getUnregisteredIntrinsics() const { return false; }
 
   /// Hook for derived dialect interfaces to publish the supported instructions.
   /// As every LLVM IR instruction has a unique integer identifier, the function
@@ -143,15 +143,18 @@ class LLVMImportInterface
       // Add a mapping for all supported intrinsic identifiers.
       for (unsigned id : iface.getSupportedIntrinsics())
         intrinsicToDialect[id] = iface.getDialect();
-      // Add a mapping for all unregistered intrinsic identifiers.
-      for (unsigned id : iface.getUnregisteredIntrinsics())
-        unregisteredIntrinscToDialect[id] = iface.getDialect();
       // Add a mapping for all supported instruction identifiers.
       for (unsigned id : iface.getSupportedInstructions())
         instructionToDialect[id] = &iface;
       // Add a mapping for all supported metadata kinds.
       for (unsigned kind : iface.getSupportedMetadata(llvmContext))
         metadataToDialect[kind].push_back(iface.getDialect());
+
+      // There can be only one dialect dealing with unregistered
+      // intrinsics, the last one to support the interface is the
+      // one to be used.
+      if (iface.getUnregisteredIntrinsics())
+        unregisteredIntrinscToDialect = iface.getDialect();
     }
 
     return success();
@@ -173,7 +176,7 @@ class LLVMImportInterface
     // No specialized (supported) intrinsics, attempt to generate a generic
     // version via llvm.call_intrinsic (if available).
     if (!dialect)
-      dialect = unregisteredIntrinscToDialect.lookup(intrinId);
+      dialect = unregisteredIntrinscToDialect;
 
     if (!dialect)
       return failure();
@@ -248,7 +251,7 @@ class LLVMImportInterface
   DenseMap<unsigned, SmallVector<Dialect *, 1>> metadataToDialect;
 
   /// Unregistered generic and target independent intrinsics.
-  DenseMap<unsigned, Dialect *> unregisteredIntrinscToDialect;
+  Dialect *unregisteredIntrinscToDialect = nullptr;
 };
 
 } // namespace mlir
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index 030aed9cdb06a..c9a3b97294562 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -17,9 +17,6 @@ add_mlir_dialect_library(MLIRLLVMDialect
   MLIRLLVMTypesIncGen
   MLIRLLVMIntrinsicOpsIncGen
   MLIRLLVMInterfacesIncGen
-  MLIRLLVMConversionsIncGen
-  MLIRLLVMIntrinsicConversionsIncGen
-  MLIRLLVMIntrinsicUnregisteredIncGen
   MLIROpenMPOpsIncGen
   intrinsics_gen
 
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
index 88ea2ff58434d..0d5a5f77b5d4a 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
@@ -24,24 +24,6 @@
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/IntrinsicsAArch64.h"
-#include "llvm/IR/IntrinsicsAMDGPU.h"
-#include "llvm/IR/IntrinsicsARM.h"
-#include "llvm/IR/IntrinsicsBPF.h"
-#include "llvm/IR/IntrinsicsDirectX.h"
-#include "llvm/IR/IntrinsicsHexagon.h"
-#include "llvm/IR/IntrinsicsLoongArch.h"
-#include "llvm/IR/IntrinsicsMips.h"
-#include "llvm/IR/IntrinsicsNVPTX.h"
-#include "llvm/IR/IntrinsicsPowerPC.h"
-#include "llvm/IR/IntrinsicsR600.h"
-#include "llvm/IR/IntrinsicsRISCV.h"
-#include "llvm/IR/IntrinsicsS390.h"
-#include "llvm/IR/IntrinsicsSPIRV.h"
-#include "llvm/IR/IntrinsicsVE.h"
-#include "llvm/IR/IntrinsicsWebAssembly.h"
-#include "llvm/IR/IntrinsicsX86.h"
-#include "llvm/IR/IntrinsicsXCore.h"
 #include "llvm/Support/ModRef.h"
 
 using namespace mlir;
@@ -74,70 +56,14 @@ static ArrayRef<unsigned> getSupportedIntrinsicsImpl() {
   return convertibleIntrinsics;
 }
 
-/// Returns true if the LLVM IR intrinsic is convertible to llvm.intrinsic_call
-/// Returns false otherwise.
-static bool isConvertibleUnregisteredIntrinsic(llvm::Intrinsic::ID id) {
-  static const DenseSet<unsigned> convertibleTargetIntrinsics = {
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAArch64LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredARMLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredBPFLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredDirectXLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredHexagonLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredMipsLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredR600LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredRISCVLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredS390LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredVELLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredX86LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredXCoreLLVMIRIntrinsics.inc"
-  };
-  return convertibleTargetIntrinsics.contains(id);
-}
-
-/// Returns the list of LLVM IR intrinsic identifiers that are not registered
-/// by any dialect but can be convertible to llvm.intrinsic_call operation.
-static ArrayRef<unsigned> getUnregisteredIntrinsicsImpl() {
-  static const SmallVector<unsigned> convertibleTargetIntrinsics = {
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAArch64LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredARMLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredBPFLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredDirectXLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredHexagonLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredMipsLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredR600LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredRISCVLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredS390LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredVELLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredX86LLVMIRIntrinsics.inc"
-#include "mlir/Dialect/LLVMIR/LLVMUnregisteredXCoreLLVMIRIntrinsics.inc"
-  };
-  return convertibleTargetIntrinsics;
-}
-
 /// Converts the LLVM intrinsic to a generic LLVM intrinsic call using
 /// llvm.intrinsic_call. Returns failure otherwise.
 static LogicalResult
 convertUnregisteredIntrinsicImpl(OpBuilder &odsBuilder, llvm::CallInst *inst,
                                  LLVM::ModuleImport &moduleImport) {
-  llvm::Intrinsic::ID intrinsicID = inst->getIntrinsicID();
   StringRef intrinName = inst->getCalledFunction()->getName();
 
   // Sanity check the intrinsic ID.
-  assert(isConvertibleUnregisteredIntrinsic(intrinsicID));
   SmallVector<llvm::Value *> args(inst->args());
   ArrayRef<llvm::Value *> llvmOperands(args);
 
@@ -192,7 +118,7 @@ static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
       llvmOpBundles.push_back(inst->getOperandBundleAt(i));
 
 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicFromLLVMIRConversions.inc"
-  } else if (isConvertibleUnregisteredIntrinsic(intrinsicID)) {
+  } else if (intrinsicID != llvm::Intrinsic::not_intrinsic) {
     return convertUnregisteredIntrinsicImpl(odsBuilder, inst, moduleImport);
   }
 
@@ -541,11 +467,8 @@ class LLVMDialectLLVMIRImportInterface : public LLVMImportDialectInterface {
     return getSupportedIntrinsicsImpl();
   }
 
-  /// Returns the list of LLVM IR intrinsic identifiers that are unsupported
-  /// by existing dialects by are convertible to generic llvm.call_intrinsic.
-  ArrayRef<unsigned> getUnregisteredIntrinsics() const final {
-    return getUnregisteredIntrinsicsImpl();
-  }
+  /// Cnvertible to generic llvm.call_intrinsic.
+  bool getUnregisteredIntrinsics() const final { return true; }
 
   /// Returns the list of LLVM IR metadata kinds that are convertible to MLIR
   /// LLVM dialect attributes.
diff --git a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
index 23e7949ea13f3..9e19f479d673a 100644
--- a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
+++ b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
@@ -19,7 +19,6 @@
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Twine.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/Error.h"
@@ -565,46 +564,6 @@ static bool emitConvertibleIntrinsics(const RecordKeeper &records,
   return false;
 }
 
-static void emitOneUnregisteredIntrinsic(const Record &record, raw_ostream &os,
-                                         StringRef targetName) {
-  StringRef targetPrefix = record.getValueAsString("TargetPrefix");
-
-  // Not interested in target specific intrinsics in the generic namespace.
-  if (targetName.empty() && !targetPrefix.empty())
-    return;
-
-  // Skip unknown targets.
-  if (!targetName.empty() && targetPrefix != targetName)
-    return;
-
-  StringRef defName = record.getName();
-  ArrayRef<SMLoc> defLoc = record.getLoc();
-
-  // Sanity check the input.
-  if (!defName.starts_with("int_"))
-    PrintFatalError(defLoc,
-                    "Intrinsic '" + defName + "' does not start with 'int_'!");
-
-  StringRef enumName = defName.substr(4);
-
-  os << "llvm::Intrinsic::";
-  if (!targetName.empty())
-    os << StringRef(targetName).upper() << "Intrinsics::";
-  os << enumName << ",\n";
-}
-
-// Emit the list of LLVM IR intrinsics enums, both target and generic. Those
-// are used for LLVMImporter's convenience when looking at intrinsics while
-// being up-to-date with new additions to LLVM.
-static bool emitUnregisteredIntrinsics(const RecordKeeper &records,
-                                       raw_ostream &os, StringRef targetName) {
-
-  for (const Record *def : records.getAllDerivedDefinitions("Intrinsic"))
-    emitOneUnregisteredIntrinsic(*def, os, targetName);
-
-  return false;
-}
-
 static mlir::GenRegistration
     genLLVMIRConversions("gen-llvmir-conversions",
                          "Generate LLVM IR conversions", emitBuilders);
@@ -631,19 +590,3 @@ static mlir::GenRegistration genConvertibleLLVMIRIntrinsics(
     "gen-convertible-llvmir-intrinsics",
     "Generate list of convertible LLVM IR intrinsics",
     emitConvertibleIntrinsics);
-
-static llvm::cl::OptionCategory
-    genUnregIntrinsicCat("Options for -gen-unregistered-llvmir-intrinsics");
-static llvm::cl::opt<std::string> unregIntrinsicPrefix(
-    "intrinsic-prefix",
-    cl::desc("Specify target to generate intrinsic information"),
-    cl::value_desc("target prefix"), cl::cat(genUnregIntrinsicCat));
-
-static mlir::GenRegistration genUnregisteredLLVMIRIntrinsics(
-    "gen-unregistered-llvmir-intrinsics",
-    "Generate enum list of target specific or generic intrinsics according to "
-    "enums defined in LLVM by other tablegen backends",
-    [](const RecordKeeper &records, raw_ostream &os) {
-      return emitUnregisteredIntrinsics(records, os,
-                                        unregIntrinsicPrefix.getValue());
-    });

>From bf15901e9f29300e6e1829842b8a6458513a2d50 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bcardosolopes at users.noreply.github.com>
Date: Tue, 25 Feb 2025 15:12:15 -0800
Subject: [PATCH 4/5] Update
 mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp

Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
 .../Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
index 0d5a5f77b5d4a..3711846dcd7cc 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
@@ -78,7 +78,7 @@ convertUnregisteredIntrinsicImpl(OpBuilder &odsBuilder, llvm::CallInst *inst,
           llvmOperands, llvmOpBundles, false, {}, {}, mlirOperands, mlirAttrs)))
     return failure();
 
-  mlir::Type results = moduleImport.convertType(inst->getType());
+  Type results = moduleImport.convertType(inst->getType());
   auto op = odsBuilder.create<::mlir::LLVM::CallIntrinsicOp>(
       moduleImport.translateLoc(inst->getDebugLoc()), results,
       StringAttr::get(odsBuilder.getContext(), intrinName),

>From 69721c03fda185b80e0224074a7a549e1eef394d Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bcardosolopes at users.noreply.github.com>
Date: Tue, 25 Feb 2025 15:12:57 -0800
Subject: [PATCH 5/5] Update
 mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h

Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
 mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
index 6004fd1519022..3233cab1499b9 100644
--- a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
+++ b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
@@ -165,6 +165,7 @@ class LLVMImportInterface
   LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
                                  LLVM::ModuleImport &moduleImport) const {
     // Lookup the dialect interface for the given intrinsic.
+    // Verify the intrinsic identifier maps to an actual intrinsic.
     llvm::Intrinsic::ID intrinId = inst->getIntrinsicID();
     if (intrinId == llvm::Intrinsic::not_intrinsic)
       return failure();



More information about the Mlir-commits mailing list