[Mlir-commits] [mlir] [nfc][mlir][acc] Move some operations to new file (PR #182054)
Razvan Lupusoru
llvmlistbot at llvm.org
Wed Feb 18 08:14:30 PST 2026
https://github.com/razvanlupusoru created https://github.com/llvm/llvm-project/pull/182054
Create a new file named OpenACCCGOps.cpp to hold implementation of operations, attributes, and types related to OpenACC codegen (though only operations exist at this time). These originate from OpenACCCGOps.td.
These are codegen/intermediate ops used when decomposing and lowering primary acc dialect ops; they do not map directly to OpenACC language constructs. Moving them out of OpenACC.cpp keeps the main dialect file focused and avoids it growing further.
>From 5438f9efeafd919bf140b0bb969e88c8d6f0539a Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Wed, 18 Feb 2026 08:11:15 -0800
Subject: [PATCH] [nfc][mlir][acc] Move some operations to new file
Create a new file named OpenACCCGOps.cpp to hold implementation of
operations, attributes, and types related to OpenACC codegen (though
only operations exist at this time). These originate from
OpenACCCGOps.td.
These are codegen/intermediate ops used when decomposing and lowering
primary acc dialect ops; they do not map directly to OpenACC language
constructs. Moving them out of OpenACC.cpp keeps the main dialect file
focused and avoids it growing further.
---
mlir/lib/Dialect/OpenACC/IR/CMakeLists.txt | 1 +
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 119 -------------
mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp | 186 +++++++++++++++++++++
3 files changed, 187 insertions(+), 119 deletions(-)
create mode 100644 mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp
diff --git a/mlir/lib/Dialect/OpenACC/IR/CMakeLists.txt b/mlir/lib/Dialect/OpenACC/IR/CMakeLists.txt
index 2bd41d99a3661..2ba1778532860 100644
--- a/mlir/lib/Dialect/OpenACC/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/OpenACC/IR/CMakeLists.txt
@@ -1,5 +1,6 @@
add_mlir_dialect_library(MLIROpenACCDialect
OpenACC.cpp
+ OpenACCCG.cpp
ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/OpenACC
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 03fe5d177e327..ce024648b160c 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -465,16 +465,6 @@ ValueRange SerialOp::getSuccessorInputs(RegionSuccessor successor) {
return getSingleRegionSuccessorInputs(getOperation(), successor);
}
-void KernelEnvironmentOp::getSuccessorRegions(
- RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
- getSingleRegionOpSuccessorRegions(getOperation(), getRegion(), point,
- regions);
-}
-
-ValueRange KernelEnvironmentOp::getSuccessorInputs(RegionSuccessor successor) {
- return getSingleRegionSuccessorInputs(getOperation(), successor);
-}
-
void DataOp::getSuccessorRegions(RegionBranchPoint point,
SmallVectorImpl<RegionSuccessor> ®ions) {
getSingleRegionOpSuccessorRegions(getOperation(), getRegion(), point,
@@ -876,20 +866,6 @@ LogicalResult acc::FirstprivateOp::verify() {
return success();
}
-//===----------------------------------------------------------------------===//
-// FirstprivateMapInitialOp
-//===----------------------------------------------------------------------===//
-LogicalResult acc::FirstprivateMapInitialOp::verify() {
- if (getDataClause() != acc::DataClause::acc_firstprivate)
- return emitError("data clause associated with firstprivate operation must "
- "match its intent");
- if (failed(checkVarAndVarType(*this)))
- return failure();
- if (failed(checkNoModifier(*this)))
- return failure();
- return success();
-}
-
//===----------------------------------------------------------------------===//
// ReductionOp
//===----------------------------------------------------------------------===//
@@ -1289,16 +1265,6 @@ void acc::FirstprivateOp::getEffects(
addResultEffect<MemoryEffects::Write>(effects, getAccVar());
}
-// FirstprivateMapInitialOp: var read, accVar result write.
-void acc::FirstprivateMapInitialOp::getEffects(
- SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
- &effects) {
- effects.emplace_back(MemoryEffects::Read::get(),
- acc::CurrentDeviceIdResource::get());
- addOperandEffect<MemoryEffects::Read>(effects, getVarMutable());
- addResultEffect<MemoryEffects::Write>(effects, getAccVar());
-}
-
// ReductionOp: var read, accVar result write.
void acc::ReductionOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
@@ -1573,65 +1539,6 @@ struct RemoveConstantIfConditionWithRegion : public OpRewritePattern<OpTy> {
}
};
-/// Remove empty acc.kernel_environment operations. If the operation has wait
-/// operands, create a acc.wait operation to preserve synchronization.
-struct RemoveEmptyKernelEnvironment
- : public OpRewritePattern<acc::KernelEnvironmentOp> {
- using OpRewritePattern<acc::KernelEnvironmentOp>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(acc::KernelEnvironmentOp op,
- PatternRewriter &rewriter) const override {
- assert(op->getNumRegions() == 1 && "expected op to have one region");
-
- Block &block = op.getRegion().front();
- if (!block.empty())
- return failure();
-
- // Conservatively disable canonicalization of empty acc.kernel_environment
- // operations if the wait operands in the kernel_environment cannot be fully
- // represented by acc.wait operation.
-
- // Disable canonicalization if device type is not the default
- if (auto deviceTypeAttr = op.getWaitOperandsDeviceTypeAttr()) {
- for (auto attr : deviceTypeAttr) {
- if (auto dtAttr = mlir::dyn_cast<acc::DeviceTypeAttr>(attr)) {
- if (dtAttr.getValue() != mlir::acc::DeviceType::None)
- return failure();
- }
- }
- }
-
- // Disable canonicalization if any wait segment has a devnum
- if (auto hasDevnumAttr = op.getHasWaitDevnumAttr()) {
- for (auto attr : hasDevnumAttr) {
- if (auto boolAttr = mlir::dyn_cast<mlir::BoolAttr>(attr)) {
- if (boolAttr.getValue())
- return failure();
- }
- }
- }
-
- // Disable canonicalization if there are multiple wait segments
- if (auto segmentsAttr = op.getWaitOperandsSegmentsAttr()) {
- if (segmentsAttr.size() > 1)
- return failure();
- }
-
- // Remove empty kernel environment.
- // Preserve synchronization by creating acc.wait operation if needed.
- if (!op.getWaitOperands().empty() || op.getWaitOnlyAttr())
- rewriter.replaceOpWithNewOp<acc::WaitOp>(op, op.getWaitOperands(),
- /*asyncOperand=*/Value(),
- /*waitDevnum=*/Value(),
- /*async=*/nullptr,
- /*ifCond=*/Value());
- else
- rewriter.eraseOp(op);
-
- return success();
- }
-};
-
//===----------------------------------------------------------------------===//
// Recipe Region Helpers
//===----------------------------------------------------------------------===//
@@ -3221,15 +3128,6 @@ void acc::HostDataOp::getCanonicalizationPatterns(RewritePatternSet &results,
results.add<RemoveConstantIfConditionWithRegion<HostDataOp>>(context);
}
-//===----------------------------------------------------------------------===//
-// KernelEnvironmentOp
-//===----------------------------------------------------------------------===//
-
-void acc::KernelEnvironmentOp::getCanonicalizationPatterns(
- RewritePatternSet &results, MLIRContext *context) {
- results.add<RemoveEmptyKernelEnvironment>(context);
-}
-
//===----------------------------------------------------------------------===//
// LoopOp
//===----------------------------------------------------------------------===//
@@ -5129,23 +5027,6 @@ LogicalResult acc::WaitOp::verify() {
return success();
}
-//===----------------------------------------------------------------------===//
-// ReductionCombineOp
-//===----------------------------------------------------------------------===//
-void acc::ReductionCombineOp::getEffects(
- llvm::SmallVectorImpl<
- mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
- &effects) {
- effects.emplace_back(mlir::MemoryEffects::Read::get(), &getSrcMemrefMutable(),
- mlir::SideEffects::DefaultResource::get());
- effects.emplace_back(mlir::MemoryEffects::Read::get(),
- &getDestMemrefMutable(),
- mlir::SideEffects::DefaultResource::get());
- effects.emplace_back(mlir::MemoryEffects::Write::get(),
- &getDestMemrefMutable(),
- mlir::SideEffects::DefaultResource::get());
-}
-
#define GET_OP_CLASSES
#include "mlir/Dialect/OpenACC/OpenACCOps.cpp.inc"
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp
new file mode 100644
index 0000000000000..2753750128699
--- /dev/null
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACCCG.cpp
@@ -0,0 +1,186 @@
+//===- OpenACCCG.cpp - OpenACC codegen ops, attributes, and types ---------===//
+//
+// Part of the MLIR Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation for OpenACC codegen operations, attributes, and types.
+// These correspond to the definitions in OpenACCCG*.td tablegen files
+// and are kept in a separate file because they do not represent direct mappings
+// of OpenACC language constructs; they are intermediate representations used
+// when decomposing and lowering primary `acc` dialect operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/IR/Region.h"
+#include "mlir/Interfaces/ControlFlowInterfaces.h"
+#include "mlir/Support/LogicalResult.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace mlir;
+using namespace acc;
+
+namespace {
+
+/// Generic helper for single-region OpenACC ops that execute their body once
+/// and then return to the parent operation with their results (if any).
+static void
+getSingleRegionOpSuccessorRegions(Operation *op, Region ®ion,
+ RegionBranchPoint point,
+ SmallVectorImpl<RegionSuccessor> ®ions) {
+ if (point.isParent()) {
+ regions.push_back(RegionSuccessor(®ion));
+ return;
+ }
+ regions.push_back(RegionSuccessor::parent());
+}
+
+static ValueRange getSingleRegionSuccessorInputs(Operation *op,
+ RegionSuccessor successor) {
+ return successor.isParent() ? ValueRange(op->getResults()) : ValueRange();
+}
+
+/// Remove empty acc.kernel_environment operations. If the operation has wait
+/// operands, create a acc.wait operation to preserve synchronization.
+struct RemoveEmptyKernelEnvironment
+ : public OpRewritePattern<acc::KernelEnvironmentOp> {
+ using OpRewritePattern<acc::KernelEnvironmentOp>::OpRewritePattern;
+
+ LogicalResult matchAndRewrite(acc::KernelEnvironmentOp op,
+ PatternRewriter &rewriter) const override {
+ assert(op->getNumRegions() == 1 && "expected op to have one region");
+
+ Block &block = op.getRegion().front();
+ if (!block.empty())
+ return failure();
+
+ // Conservatively disable canonicalization of empty acc.kernel_environment
+ // operations if the wait operands in the kernel_environment cannot be fully
+ // represented by acc.wait operation.
+
+ // Disable canonicalization if device type is not the default
+ if (auto deviceTypeAttr = op.getWaitOperandsDeviceTypeAttr()) {
+ for (auto attr : deviceTypeAttr) {
+ if (auto dtAttr = mlir::dyn_cast<acc::DeviceTypeAttr>(attr)) {
+ if (dtAttr.getValue() != mlir::acc::DeviceType::None)
+ return failure();
+ }
+ }
+ }
+
+ // Disable canonicalization if any wait segment has a devnum
+ if (auto hasDevnumAttr = op.getHasWaitDevnumAttr()) {
+ for (auto attr : hasDevnumAttr) {
+ if (auto boolAttr = mlir::dyn_cast<mlir::BoolAttr>(attr)) {
+ if (boolAttr.getValue())
+ return failure();
+ }
+ }
+ }
+
+ // Disable canonicalization if there are multiple wait segments
+ if (auto segmentsAttr = op.getWaitOperandsSegmentsAttr()) {
+ if (segmentsAttr.size() > 1)
+ return failure();
+ }
+
+ // Remove empty kernel environment.
+ // Preserve synchronization by creating acc.wait operation if needed.
+ if (!op.getWaitOperands().empty() || op.getWaitOnlyAttr())
+ rewriter.replaceOpWithNewOp<acc::WaitOp>(op, op.getWaitOperands(),
+ /*asyncOperand=*/Value(),
+ /*waitDevnum=*/Value(),
+ /*async=*/nullptr,
+ /*ifCond=*/Value());
+ else
+ rewriter.eraseOp(op);
+
+ return success();
+ }
+};
+
+template <typename EffectTy>
+static void addOperandEffect(
+ SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+ &effects,
+ const MutableOperandRange &operand) {
+ for (unsigned i = 0, e = operand.size(); i < e; ++i)
+ effects.emplace_back(EffectTy::get(), &operand[i]);
+}
+
+template <typename EffectTy>
+static void addResultEffect(
+ SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+ &effects,
+ Value result) {
+ effects.emplace_back(EffectTy::get(), mlir::cast<mlir::OpResult>(result));
+}
+
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// KernelEnvironmentOp
+//===----------------------------------------------------------------------===//
+
+void KernelEnvironmentOp::getSuccessorRegions(
+ RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
+ getSingleRegionOpSuccessorRegions(getOperation(), getRegion(), point,
+ regions);
+}
+
+ValueRange KernelEnvironmentOp::getSuccessorInputs(RegionSuccessor successor) {
+ return getSingleRegionSuccessorInputs(getOperation(), successor);
+}
+
+void KernelEnvironmentOp::getCanonicalizationPatterns(
+ RewritePatternSet &results, MLIRContext *context) {
+ results.add<RemoveEmptyKernelEnvironment>(context);
+}
+
+//===----------------------------------------------------------------------===//
+// FirstprivateMapInitialOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult FirstprivateMapInitialOp::verify() {
+ if (getDataClause() != acc::DataClause::acc_firstprivate)
+ return emitError("data clause associated with firstprivate operation must "
+ "match its intent");
+ if (!getVar())
+ return emitError("must have var operand");
+ if (!mlir::isa<mlir::acc::PointerLikeType>(getVar().getType()) &&
+ !mlir::isa<mlir::acc::MappableType>(getVar().getType()))
+ return emitError("var must be mappable or pointer-like");
+ if (mlir::isa<mlir::acc::PointerLikeType>(getVar().getType()) &&
+ getVarType() == getVar().getType())
+ return emitError("varType must capture the element type of var");
+ if (getModifiers() != acc::DataClauseModifier::none)
+ return emitError("no data clause modifiers are allowed");
+ return success();
+}
+
+void FirstprivateMapInitialOp::getEffects(
+ SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+ &effects) {
+ effects.emplace_back(MemoryEffects::Read::get(),
+ acc::CurrentDeviceIdResource::get());
+ addOperandEffect<MemoryEffects::Read>(effects, getVarMutable());
+ addResultEffect<MemoryEffects::Write>(effects, getAccVar());
+}
+
+//===----------------------------------------------------------------------===//
+// ReductionCombineOp
+//===----------------------------------------------------------------------===//
+
+void ReductionCombineOp::getEffects(
+ SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+ &effects) {
+ effects.emplace_back(MemoryEffects::Read::get(), &getSrcMemrefMutable(),
+ SideEffects::DefaultResource::get());
+ effects.emplace_back(MemoryEffects::Read::get(), &getDestMemrefMutable(),
+ SideEffects::DefaultResource::get());
+ effects.emplace_back(MemoryEffects::Write::get(), &getDestMemrefMutable(),
+ SideEffects::DefaultResource::get());
+}
More information about the Mlir-commits
mailing list