[Mlir-commits] [mlir] [MLIR][NVVM]Import llvm intrinsics for nvvm.barrier (PR #202862)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Jun 9 23:06:36 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-llvm

Author: xys-syx

<details>
<summary>Changes</summary>

This PR adds LLVM IR import support for the `bar.sync` intrinsic family, lifting the four variants into `nvvm.barrier` with the appropriate `aligned` attribute and optional thread-count operand.

`LLVM_IntrOpBase` and its auto-generated import is one to one, but four `bar.sync` variants are many-to-one, where they all lift into `nvvm.barrier`, differing only in `aligned` and the optional `numberOfThreads` operand.

An alternative implementation would extend mlir-tblgen with many-to-one intrinsic-to-op mapping support so the conversion could live in `NVVMOps.td`. But the change is bigger than manually import `bar.sync` intrinsic family.

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


2 Files Affected:

- (modified) mlir/lib/Target/LLVMIR/Dialect/NVVM/LLVMIRToNVVMTranslation.cpp (+59-7) 
- (modified) mlir/test/Target/LLVMIR/Import/nvvmir.ll (+41-1) 


``````````diff
diff --git a/mlir/lib/Target/LLVMIR/Dialect/NVVM/LLVMIRToNVVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/NVVM/LLVMIRToNVVMTranslation.cpp
index 55e73e839afcb..f15965e01761a 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/NVVM/LLVMIRToNVVMTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/NVVM/LLVMIRToNVVMTranslation.cpp
@@ -18,21 +18,68 @@
 using namespace mlir;
 using namespace mlir::NVVM;
 
-/// Returns true if the LLVM IR intrinsic is convertible to an MLIR NVVM dialect
-/// intrinsic. Returns false otherwise.
+/// LLVM intrinsic IDs of the four `bar.sync` variants imported into
+/// `nvvm.barrier`.
+static constexpr llvm::Intrinsic::ID kBarrierSyncIntrinsics[] = {
+    llvm::Intrinsic::nvvm_barrier_cta_sync_all,
+    llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_all,
+    llvm::Intrinsic::nvvm_barrier_cta_sync_count,
+    llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count,
+};
+
+/// Returns true if `id` is one of the `bar.sync` intrinsic IDs imported into
+/// `nvvm.barrier`.
+static bool isBarrierSyncIntrinsic(llvm::Intrinsic::ID id) {
+  return llvm::is_contained(kBarrierSyncIntrinsics, id);
+}
+
+/// Imports one of the four `bar.sync` LLVM intrinsic variants into a single
+/// `nvvm.barrier` op, deriving the `aligned` attribute and the optional
+/// `numberOfThreads` operand from the specific intrinsic ID.
+static LogicalResult
+convertBarrierSyncIntrinsic(OpBuilder &odsBuilder, llvm::CallInst *inst,
+                            LLVM::ModuleImport &moduleImport,
+                            ArrayRef<llvm::Value *> llvmOperands,
+                            ArrayRef<llvm::OperandBundleUse> llvmOpBundles) {
+  llvm::Intrinsic::ID id = inst->getIntrinsicID();
+  bool aligned = (id == llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_all ||
+                  id == llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count);
+  bool hasCount = (id == llvm::Intrinsic::nvvm_barrier_cta_sync_count ||
+                   id == llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count);
+
+  SmallVector<Value> mlirOperands;
+  SmallVector<NamedAttribute> mlirAttrs;
+  if (failed(moduleImport.convertIntrinsicArguments(
+          llvmOperands, llvmOpBundles, /*requiresOpBundles=*/false, {}, {},
+          mlirOperands, mlirAttrs)))
+    return failure();
+
+  auto op = NVVM::BarrierOp::create(
+      odsBuilder, moduleImport.translateLoc(inst->getDebugLoc()),
+      mlirOperands.front(), hasCount ? mlirOperands.back() : Value{},
+      odsBuilder.getBoolAttr(aligned));
+  moduleImport.mapNoResultOp(inst, op);
+  return success();
+}
+
+/// Returns true if the LLVM intrinsic `id` has a corresponding MLIR NVVM op.
 static bool isConvertibleIntrinsic(llvm::Intrinsic::ID id) {
   static const DenseSet<unsigned> convertibleIntrinsics = {
 #include "mlir/Dialect/LLVMIR/NVVMConvertibleLLVMIRIntrinsics.inc"
   };
-  return convertibleIntrinsics.contains(id);
+  return convertibleIntrinsics.contains(id) || isBarrierSyncIntrinsic(id);
 }
 
-/// Returns the list of LLVM IR intrinsic identifiers that are convertible to
-/// MLIR NVVM dialect intrinsics.
+/// Returns the LLVM intrinsic IDs that have a corresponding MLIR NVVM op.
 static ArrayRef<unsigned> getSupportedIntrinsicsImpl() {
-  static const SmallVector<unsigned> convertibleIntrinsics = {
+  static const SmallVector<unsigned> convertibleIntrinsics = []() {
+    SmallVector<unsigned> ids = {
 #include "mlir/Dialect/LLVMIR/NVVMConvertibleLLVMIRIntrinsics.inc"
-  };
+    };
+    ids.append(std::begin(kBarrierSyncIntrinsics),
+               std::end(kBarrierSyncIntrinsics));
+    return ids;
+  }();
   return convertibleIntrinsics;
 }
 
@@ -54,6 +101,11 @@ static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
     for (unsigned i = 0; i < inst->getNumOperandBundles(); ++i)
       llvmOpBundles.push_back(inst->getOperandBundleAt(i));
 
+    // Route `bar.sync` intrinsics to `nvvm.barrier`.
+    if (isBarrierSyncIntrinsic(intrinsicID))
+      return convertBarrierSyncIntrinsic(odsBuilder, inst, moduleImport,
+                                         llvmOperands, llvmOpBundles);
+
 #include "mlir/Dialect/LLVMIR/NVVMFromLLVMIRConversions.inc"
   }
 
diff --git a/mlir/test/Target/LLVMIR/Import/nvvmir.ll b/mlir/test/Target/LLVMIR/Import/nvvmir.ll
index 1430f9a44eba1..1fe3451cd0dd0 100644
--- a/mlir/test/Target/LLVMIR/Import/nvvmir.ll
+++ b/mlir/test/Target/LLVMIR/Import/nvvmir.ll
@@ -73,11 +73,43 @@ define float @nvvm_rcp(float %0) {
 
 ; CHECK-LABEL: @llvm_nvvm_barrier0()
 define void @llvm_nvvm_barrier0() {
-  ; CHECK: llvm.nvvm.barrier.cta.sync.aligned.all
+  ; CHECK: %[[c0:.*]] = llvm.mlir.constant(0 : i32) : i32
+  ; CHECK: nvvm.barrier id = %[[c0]] {aligned = true}
   call void @llvm.nvvm.barrier0()
   ret void
 }
 
+; CHECK-LABEL: @llvm_nvvm_barrier_sync_all
+define void @llvm_nvvm_barrier_sync_all(i32 %bar) {
+  ; CHECK: nvvm.barrier id = %{{.*}}
+  ; CHECK-NOT: aligned
+  ; CHECK-NOT: number_of_threads
+  call void @llvm.nvvm.barrier.cta.sync.all(i32 %bar)
+  ret void
+}
+
+; CHECK-LABEL: @llvm_nvvm_barrier_sync_aligned_all
+define void @llvm_nvvm_barrier_sync_aligned_all(i32 %bar) {
+  ; CHECK: nvvm.barrier id = %{{.*}} {aligned = true}
+  call void @llvm.nvvm.barrier.cta.sync.aligned.all(i32 %bar)
+  ret void
+}
+
+; CHECK-LABEL: @llvm_nvvm_barrier_sync_count
+define void @llvm_nvvm_barrier_sync_count(i32 %bar, i32 %n) {
+  ; CHECK: nvvm.barrier id = %{{.*}} number_of_threads = %{{.*}}
+  ; CHECK-NOT: aligned
+  call void @llvm.nvvm.barrier.cta.sync.count(i32 %bar, i32 %n)
+  ret void
+}
+
+; CHECK-LABEL: @llvm_nvvm_barrier_sync_aligned_count
+define void @llvm_nvvm_barrier_sync_aligned_count(i32 %bar, i32 %n) {
+  ; CHECK: nvvm.barrier id = %{{.*}} number_of_threads = %{{.*}} {aligned = true}
+  call void @llvm.nvvm.barrier.cta.sync.aligned.count(i32 %bar, i32 %n)
+  ret void
+}
+
 ; CHECK-LABEL: @llvm_nvvm_bar_warp_sync
 define void @llvm_nvvm_bar_warp_sync(i32 %mask) {
   ; CHECK: nvvm.bar.warp.sync %{{.*}} : i32
@@ -276,6 +308,14 @@ declare float @llvm.nvvm.rcp.approx.ftz.f(float)
 
 declare void @llvm.nvvm.barrier0()
 
+declare void @llvm.nvvm.barrier.cta.sync.all(i32)
+
+declare void @llvm.nvvm.barrier.cta.sync.aligned.all(i32)
+
+declare void @llvm.nvvm.barrier.cta.sync.count(i32, i32)
+
+declare void @llvm.nvvm.barrier.cta.sync.aligned.count(i32, i32)
+
 declare void @llvm.nvvm.bar.warp.sync(i32)
 
 declare i32 @llvm.nvvm.shfl.sync.bfly.i32(i32, i32, i32, i32)

``````````

</details>


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


More information about the Mlir-commits mailing list