[Mlir-commits] [mlir] [OpenACC] add isEffectivelySerial() to acc.parallel and acc.kernels (PR #209192)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Jul 13 07:20:40 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-openacc

Author: Scott Manley (rscottmanley)

<details>
<summary>Changes</summary>

Mirror the isEffectivelySerial() function in acc.compute_region to acc.parallel and acc.kernel so this check is unified anywhere it needs to be used, namely before ACCComputeLowering. Should be NFC

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


3 Files Affected:

- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td (+6) 
- (modified) mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp (+35) 
- (modified) mlir/lib/Dialect/OpenACC/Transforms/ACCComputeLowering.cpp (+3-38) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 30298767c0f3e..db2f0e0605db5 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -1842,6 +1842,9 @@ def OpenACC_ParallelOp
     /// clause for the given device_type.
     bool hasAnyGangWorkerVector(mlir::acc::DeviceType deviceType);
 
+    /// Check whether num_gangs, num_workers, and vector_length are all 1.
+    bool isEffectivelySerial();
+
     /// Return true if the op has the wait attribute for the
     /// mlir::acc::DeviceType::None device_type.
     bool hasWaitOnly();
@@ -2173,6 +2176,9 @@ def OpenACC_KernelsOp
     /// clause for the given device_type.
     bool hasAnyGangWorkerVector(mlir::acc::DeviceType deviceType);
 
+    /// Check whether num_gangs, num_workers, and vector_length are all 1.
+    bool isEffectivelySerial();
+
     /// Return true if the op has the wait attribute for the
     /// mlir::acc::DeviceType::None device_type.
     bool hasWaitOnly();
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp
index 7de59058ead0d..3b168b7631db8 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp
@@ -14,6 +14,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "mlir/Dialect/Arith/IR/Arith.h"
 #include "mlir/Dialect/GPU/IR/GPUDialect.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/Dialect/Utils/StaticValueUtils.h"
@@ -571,6 +572,40 @@ ComputeRegionOp::wireHoistedValueThroughIns(Value value) {
   return arg;
 }
 
+/// Strip index_cast operations from a value before checking for a constant.
+static Value stripIndexCasts(Value val) {
+  while (auto castOp = val.getDefiningOp<arith::IndexCastOp>())
+    val = castOp.getIn();
+  return val;
+}
+
+template <typename ComputeOpT>
+static bool isGangWorkerVectorAllOne(ComputeOpT op) {
+  auto numGangs = op.getNumGangsValues();
+  if (numGangs.empty())
+    return false;
+  for (Value gangSize : numGangs) {
+    if (!isConstantIntValue(stripIndexCasts(gangSize), 1))
+      return false;
+  }
+  Value numWorkers = op.getNumWorkersValue();
+  if (!numWorkers)
+    return false;
+  Value vectorLength = op.getVectorLengthValue();
+  if (!vectorLength)
+    return false;
+  return isConstantIntValue(stripIndexCasts(numWorkers), 1) &&
+         isConstantIntValue(stripIndexCasts(vectorLength), 1);
+}
+
+bool ParallelOp::isEffectivelySerial() {
+  return isGangWorkerVectorAllOne(*this);
+}
+
+bool KernelsOp::isEffectivelySerial() {
+  return isGangWorkerVectorAllOne(*this);
+}
+
 bool ComputeRegionOp::isEffectivelySerial() {
   auto *ctx = getContext();
 
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCComputeLowering.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCComputeLowering.cpp
index b3d54d2e05697..a275a794c9fd5 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCComputeLowering.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCComputeLowering.cpp
@@ -78,41 +78,6 @@ namespace {
 // Helper functions
 //===----------------------------------------------------------------------===//
 
-/// Strip index_cast operations from a value before checking for a constant.
-static Value stripIndexCasts(Value val) {
-  while (auto castOp = val.getDefiningOp<arith::IndexCastOp>())
-    val = castOp.getIn();
-  return val;
-}
-
-template <typename ComputeOpT>
-static bool isGangWorkerVectorAllOne(ComputeOpT op) {
-  auto numGangs = op.getNumGangsValues();
-  if (numGangs.empty())
-    return false;
-  for (Value gangSize : numGangs) {
-    if (!isConstantIntValue(stripIndexCasts(gangSize), 1))
-      return false;
-  }
-  Value numWorkers = op.getNumWorkersValue();
-  if (!numWorkers)
-    return false;
-  Value vectorLength = op.getVectorLengthValue();
-  if (!vectorLength)
-    return false;
-  return isConstantIntValue(stripIndexCasts(numWorkers), 1) &&
-         isConstantIntValue(stripIndexCasts(vectorLength), 1);
-}
-
-/// A compute construct is "effectively serial" when it specifies
-/// num_gangs(1), num_workers(1), and vector_length(1). This is because
-/// these are the only parallelism dimensions expressible from OpenACC spec
-/// point-of-view and is consistent with how `serial` semantics are defined.
-template <typename ComputeOpT>
-static bool isEffectivelySerial(ComputeOpT op) {
-  return isGangWorkerVectorAllOne(op);
-}
-
 static bool isOpInComputeRegion(Operation *op) {
   Region *region = op->getBlock()->getParent();
   return getEnclosingComputeOp(*region) != nullptr;
@@ -120,9 +85,9 @@ static bool isOpInComputeRegion(Operation *op) {
 
 static bool isOpInSerialRegion(Operation *op) {
   if (auto parallelOp = op->getParentOfType<ParallelOp>())
-    return isEffectivelySerial(parallelOp);
+    return parallelOp.isEffectivelySerial();
   if (auto kernelsOp = op->getParentOfType<KernelsOp>())
-    return isEffectivelySerial(kernelsOp);
+    return kernelsOp.isEffectivelySerial();
   if (op->getParentOfType<SerialOp>())
     return true;
   if (auto computeRegion = op->getParentOfType<ComputeRegionOp>())
@@ -230,7 +195,7 @@ assignKnownLaunchArgs(ComputeConstructT computeOp, DeviceType deviceType,
     return {ParWidthOp::create(rewriter, loc, Value(), policy.seqDim(ctx))};
   } else if constexpr (llvm::is_one_of<ComputeConstructT, ParallelOp,
                                        KernelsOp>::value) {
-    if (isEffectivelySerial(computeOp))
+    if (computeOp.isEffectivelySerial())
       return {ParWidthOp::create(rewriter, loc, Value(), policy.seqDim(ctx))};
 
     deviceType = getParDimsDeviceType(computeOp, deviceType);

``````````

</details>


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


More information about the Mlir-commits mailing list