[Mlir-commits] [mlir] [MLIR][NVVM] Add explicit aligned attribute to nvvm.barrier and nvvm.barrier.reduction (PR #200745)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Jun 1 00:49:11 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 according to the third PR commitments in #<!-- -->192203 

This PR adds an explicit aligned boolean attribute to `nvvm.barrier`, defaulting to true to preserve the existing semantic default, and extends the op's LLVM IR lowering to pick between the `.aligned` and non-`.aligned` spellings of the `@<!-- -->llvm.nvvm.barrier.cta.*` intrinsic family.

Notes on using `BoolAttr` instead of UnitAttr: `nvvm.barrier`'s existing lowering always emits an aligned intrinsic variant. Making aligned a BoolAttr with default true captures that as the op's default, and the `custom<Aligned>` described below only emits the keyword when non-default.

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


4 Files Affected:

- (modified) mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td (+11-5) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp (+34-18) 
- (modified) mlir/test/Dialect/LLVMIR/nvvm.mlir (+6) 
- (modified) mlir/test/Target/LLVMIR/nvvm/barrier.mlir (+22) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
index 01abc7e70f57c..84ca4dcc3ddb1 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
@@ -1131,13 +1131,15 @@ def NVVM_BarrierOp : NVVM_VoidIntrinsicOp<"barrier",
     within a CTA (Cooperative Thread Array). It causes executing threads to wait for 
     all non-exited threads participating in the barrier to arrive.
 
-    The operation takes the following optional operands:
+    The operation takes the following optional operands and attributes:
 
     - `barrierId`: Specifies a logical barrier resource with value 0 through 15. 
       Each CTA instance has sixteen barriers numbered 0..15. Defaults to 0 if not specified.
     - `numberOfThreads`: Specifies the number of threads participating in the barrier. 
       When specified, the value must be a multiple of the warp size. If not specified, 
       all threads in the CTA participate in the barrier.
+    - `aligned`: Selects between the `.aligned` and non-`.aligned` forms of the
+      underlying `@llvm.nvvm.barrier.cta.*` intrinsic family. Defaults to true.
 
     Reduction variants of the barrier instruction are modeled by the
     `nvvm.barrier.reduction` op.
@@ -1159,7 +1161,8 @@ def NVVM_BarrierOp : NVVM_VoidIntrinsicOp<"barrier",
 
   let arguments = (ins
       Optional<I32>:$barrierId,
-      Optional<I32>:$numberOfThreads);
+      Optional<I32>:$numberOfThreads,
+      DefaultValuedAttr<BoolAttr, "true">:$aligned);
 
   let assemblyFormat =
       "(`id` `=` $barrierId^)? (`number_of_threads` `=` $numberOfThreads^)? "
@@ -1184,10 +1187,12 @@ def NVVM_BarrierReductionOp :
       per-thread predicates.
     - `reductionPredicate`: The per-thread i32 predicate. It is compared against
       zero to form the i1 value fed into the reduction.
+    - `aligned`: Selects between the `.aligned` and non-`.aligned` forms of the
+      underlying `@llvm.nvvm.barrier.cta.red.*` intrinsic family. Defaults to
+      true.
 
     The result is the i32 reduction value computed across all threads
-    participating in the barrier. This op always lowers to the aligned form of
-    the `@llvm.nvvm.barrier.cta.red.*` intrinsic family.
+    participating in the barrier.
 
     [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-bar)
   }];
@@ -1195,7 +1200,8 @@ def NVVM_BarrierReductionOp :
   let arguments = (ins
       Optional<I32>:$barrierId,
       BarrierReductionAttr:$reductionOp,
-      I32:$reductionPredicate);
+      I32:$reductionPredicate,
+      DefaultValuedAttr<BoolAttr, "true">:$aligned);
   let results = (outs I32:$res);
 
   let assemblyFormat =
diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
index 00c997ec7a031..3f4ec39698320 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
@@ -3453,38 +3453,54 @@ void SubFOp::getCanonicalizationPatterns(RewritePatternSet &patterns,
 // getIntrinsicID/getIntrinsicIDAndArgs methods
 //===----------------------------------------------------------------------===//
 
+/// Maps the (aligned, hasCount) pair to the `@llvm.nvvm.barrier.cta.sync.*`
+/// intrinsic ID.
+static llvm::Intrinsic::ID getBarrierSyncIntrinsic(bool aligned, bool hasCount) {
+  if (hasCount)
+    return aligned ? llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count
+                   : llvm::Intrinsic::nvvm_barrier_cta_sync_count;
+  return aligned ? llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_all
+                 : llvm::Intrinsic::nvvm_barrier_cta_sync_all;
+}
+
+/// Maps the (aligned, kind) pair to the `@llvm.nvvm.barrier.cta.red.*`
+/// intrinsic ID.
+static llvm::Intrinsic::ID
+getBarrierReductionIntrinsic(bool aligned, NVVM::BarrierReduction kind) {
+  switch (kind) {
+  case NVVM::BarrierReduction::AND:
+    return aligned ? llvm::Intrinsic::nvvm_barrier_cta_red_and_aligned_all
+                   : llvm::Intrinsic::nvvm_barrier_cta_red_and_all;
+  case NVVM::BarrierReduction::OR:
+    return aligned ? llvm::Intrinsic::nvvm_barrier_cta_red_or_aligned_all
+                   : llvm::Intrinsic::nvvm_barrier_cta_red_or_all;
+  case NVVM::BarrierReduction::POPC:
+    return aligned ? llvm::Intrinsic::nvvm_barrier_cta_red_popc_aligned_all
+                   : llvm::Intrinsic::nvvm_barrier_cta_red_popc_all;
+  }
+  llvm_unreachable("unknown BarrierReduction kind");
+}
+
 mlir::NVVM::IDArgPair NVVM::BarrierOp::getIntrinsicIDAndArgs(
     Operation &op, LLVM::ModuleTranslation &mt, llvm::IRBuilderBase &builder) {
   auto thisOp = cast<NVVM::BarrierOp>(op);
   llvm::Value *barrierId = thisOp.getBarrierId()
                                ? mt.lookupValue(thisOp.getBarrierId())
                                : builder.getInt32(0);
-  llvm::Intrinsic::ID id;
+  bool hasCount = static_cast<bool>(thisOp.getNumberOfThreads());
+  llvm::Intrinsic::ID id =
+      getBarrierSyncIntrinsic(thisOp.getAligned(), hasCount);
   llvm::SmallVector<llvm::Value *> args = {barrierId};
-  if (thisOp.getNumberOfThreads()) {
-    id = llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count;
+  if (hasCount)
     args.push_back(mt.lookupValue(thisOp.getNumberOfThreads()));
-  } else {
-    id = llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_all;
-  }
   return {id, std::move(args)};
 }
 
 mlir::NVVM::IDArgPair NVVM::BarrierReductionOp::getIntrinsicIDAndArgs(
     Operation &op, LLVM::ModuleTranslation &mt, llvm::IRBuilderBase &builder) {
   auto thisOp = cast<NVVM::BarrierReductionOp>(op);
-  llvm::Intrinsic::ID id;
-  switch (thisOp.getReductionOp()) {
-  case NVVM::BarrierReduction::AND:
-    id = llvm::Intrinsic::nvvm_barrier_cta_red_and_aligned_all;
-    break;
-  case NVVM::BarrierReduction::OR:
-    id = llvm::Intrinsic::nvvm_barrier_cta_red_or_aligned_all;
-    break;
-  case NVVM::BarrierReduction::POPC:
-    id = llvm::Intrinsic::nvvm_barrier_cta_red_popc_aligned_all;
-    break;
-  }
+  llvm::Intrinsic::ID id =
+      getBarrierReductionIntrinsic(thisOp.getAligned(), thisOp.getReductionOp());
   llvm::Value *barrierId = thisOp.getBarrierId()
                                ? mt.lookupValue(thisOp.getBarrierId())
                                : builder.getInt32(0);
diff --git a/mlir/test/Dialect/LLVMIR/nvvm.mlir b/mlir/test/Dialect/LLVMIR/nvvm.mlir
index 6ba251fe804ad..72935ffd7b7ce 100644
--- a/mlir/test/Dialect/LLVMIR/nvvm.mlir
+++ b/mlir/test/Dialect/LLVMIR/nvvm.mlir
@@ -49,6 +49,10 @@ llvm.func @llvm_nvvm_barrier(%barId : i32, %numberOfThreads : i32) {
   nvvm.barrier id = %barId number_of_threads = %numberOfThreads
   // CHECK: nvvm.barrier number_of_threads = %[[numberOfThreads]]
   nvvm.barrier number_of_threads = %numberOfThreads
+  // CHECK: nvvm.barrier {aligned = false}
+  nvvm.barrier {aligned = false}
+  // CHECK: nvvm.barrier id = %[[barId]] number_of_threads = %[[numberOfThreads]] {aligned = false}
+  nvvm.barrier id = %barId number_of_threads = %numberOfThreads {aligned = false}
   llvm.return
 }
 
@@ -63,6 +67,8 @@ llvm.func @llvm_nvvm_barrier_reduction(%barId : i32, %pred : i32) {
   %2 = nvvm.barrier.reduction #nvvm.reduction<popc> %pred -> i32
   // CHECK: nvvm.barrier.reduction #nvvm.reduction<and> %[[pred]] id = %[[barId]] -> i32
   %3 = nvvm.barrier.reduction #nvvm.reduction<and> %pred id = %barId -> i32
+  // CHECK: nvvm.barrier.reduction #nvvm.reduction<and> %[[pred]] -> i32 {aligned = false}
+  %4 = nvvm.barrier.reduction #nvvm.reduction<and> %pred -> i32 {aligned = false}
   llvm.return
 }
 
diff --git a/mlir/test/Target/LLVMIR/nvvm/barrier.mlir b/mlir/test/Target/LLVMIR/nvvm/barrier.mlir
index ecfee955904bd..17c086d7737d8 100644
--- a/mlir/test/Target/LLVMIR/nvvm/barrier.mlir
+++ b/mlir/test/Target/LLVMIR/nvvm/barrier.mlir
@@ -33,5 +33,27 @@ llvm.func @llvm_nvvm_barrier(%barID : i32, %numberOfThreads : i32, %redOperand :
   // CHECK: %{{.*}} = nvvm.barrier.reduction #nvvm.reduction<and> %{{.*}} id = %{{.*}} -> i32
   %3 = nvvm.barrier.reduction #nvvm.reduction<and> %redOperand id = %barID -> i32
 
+  // Non-aligned sync variants.
+  // LLVM: call void @llvm.nvvm.barrier.cta.sync.all(i32 0)
+  // CHECK: nvvm.barrier {aligned = false}
+  nvvm.barrier {aligned = false}
+  // LLVM: call void @llvm.nvvm.barrier.cta.sync.count(i32 %[[barId]], i32 %[[numThreads]])
+  // CHECK: nvvm.barrier id = %{{.*}} number_of_threads = %{{.*}} {aligned = false}
+  nvvm.barrier id = %barID number_of_threads = %numberOfThreads {aligned = false}
+
+  // Non-aligned reduction variants.
+  // LLVM: %[[redOperandCmp5:.*]] = icmp ne i32 %[[redOperand]], 0
+  // LLVM: %{{.*}} = call i1 @llvm.nvvm.barrier.cta.red.and.all(i32 0, i1 %[[redOperandCmp5]])
+  // CHECK: %{{.*}} = nvvm.barrier.reduction #nvvm.reduction<and> %{{.*}} -> i32 {aligned = false}
+  %4 = nvvm.barrier.reduction #nvvm.reduction<and> %redOperand -> i32 {aligned = false}
+  // LLVM: %[[redOperandCmp6:.*]] = icmp ne i32 %[[redOperand]], 0
+  // LLVM: %{{.*}} = call i1 @llvm.nvvm.barrier.cta.red.or.all(i32 0, i1 %[[redOperandCmp6]])
+  // CHECK: %{{.*}} = nvvm.barrier.reduction #nvvm.reduction<or> %{{.*}} -> i32 {aligned = false}
+  %5 = nvvm.barrier.reduction #nvvm.reduction<or> %redOperand -> i32 {aligned = false}
+  // LLVM: %[[redOperandCmp7:.*]] = icmp ne i32 %[[redOperand]], 0
+  // LLVM: %{{.*}} = call i32 @llvm.nvvm.barrier.cta.red.popc.all(i32 0, i1 %[[redOperandCmp7]])
+  // CHECK: %{{.*}} = nvvm.barrier.reduction #nvvm.reduction<popc> %{{.*}} -> i32 {aligned = false}
+  %6 = nvvm.barrier.reduction #nvvm.reduction<popc> %redOperand -> i32 {aligned = false}
+
   llvm.return
 }

``````````

</details>


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


More information about the Mlir-commits mailing list