[Mlir-commits] [mlir] [mlir][acc] Improve acc.loop support as a container (PR #137886)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Apr 29 15:19:59 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Razvan Lupusoru (razvanlupusoru)
<details>
<summary>Changes</summary>
Dialects which have their own loop representation not representable
with numeric bounds + steps cannot be represented cleanly with
acc.loop. In such a case, we permit the dialects representation with
acc.loop merely encompasing its loop representation. This limitation
became obvious when looking at range / random iterator C++ loops.
The API of acc.loop was updated to test for this differentiation.
Additionally, the verifier was updated to check for consistent bounds
and whether inner-loops are contained when it works as a container.
---
Full diff: https://github.com/llvm/llvm-project/pull/137886.diff
2 Files Affected:
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td (+6-1)
- (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+33-22)
``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 41cec89fdf598..3ad8e4f9ccbeb 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -2127,6 +2127,11 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
/// Used to retrieve the block inside the op's region.
Block &getBody() { return getLoopRegions().front()->front(); }
+ /// Used to determine if this operation is merely a container for a loop
+ /// operation instead of being loop-like itself.
+ bool isLoopLike() { return !getLowerbound().empty(); }
+ bool isContainerLike() { return !isLoopLike(); }
+
/// Return true if the op has the auto attribute for the
/// mlir::acc::DeviceType::None device_type.
bool hasAuto();
@@ -2197,7 +2202,7 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
let hasCustomAssemblyFormat = 1;
let assemblyFormat = [{
- custom<CombinedConstructsLoop>($combined)
+ ( `combined` `(` custom<CombinedConstructsLoop>($combined)^ `)` )?
oilist(
`gang` `` custom<GangClause>($gangOperands, type($gangOperands),
$gangOperandsArgType, $gangOperandsDeviceType,
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index c4cc560e42f6a..a7b01abe34e03 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -1686,25 +1686,19 @@ static void printDeviceTypeOperandsWithKeywordOnly(
static ParseResult
parseCombinedConstructsLoop(mlir::OpAsmParser &parser,
mlir::acc::CombinedConstructsTypeAttr &attr) {
- if (succeeded(parser.parseOptionalKeyword("combined"))) {
- if (parser.parseLParen())
- return failure();
- if (succeeded(parser.parseOptionalKeyword("kernels"))) {
- attr = mlir::acc::CombinedConstructsTypeAttr::get(
- parser.getContext(), mlir::acc::CombinedConstructsType::KernelsLoop);
- } else if (succeeded(parser.parseOptionalKeyword("parallel"))) {
- attr = mlir::acc::CombinedConstructsTypeAttr::get(
- parser.getContext(), mlir::acc::CombinedConstructsType::ParallelLoop);
- } else if (succeeded(parser.parseOptionalKeyword("serial"))) {
- attr = mlir::acc::CombinedConstructsTypeAttr::get(
- parser.getContext(), mlir::acc::CombinedConstructsType::SerialLoop);
- } else {
- parser.emitError(parser.getCurrentLocation(),
- "expected compute construct name");
- return failure();
- }
- if (parser.parseRParen())
- return failure();
+ if (succeeded(parser.parseOptionalKeyword("kernels"))) {
+ attr = mlir::acc::CombinedConstructsTypeAttr::get(
+ parser.getContext(), mlir::acc::CombinedConstructsType::KernelsLoop);
+ } else if (succeeded(parser.parseOptionalKeyword("parallel"))) {
+ attr = mlir::acc::CombinedConstructsTypeAttr::get(
+ parser.getContext(), mlir::acc::CombinedConstructsType::ParallelLoop);
+ } else if (succeeded(parser.parseOptionalKeyword("serial"))) {
+ attr = mlir::acc::CombinedConstructsTypeAttr::get(
+ parser.getContext(), mlir::acc::CombinedConstructsType::SerialLoop);
+ } else {
+ parser.emitError(parser.getCurrentLocation(),
+ "expected compute construct name");
+ return failure();
}
return success();
}
@@ -1715,13 +1709,13 @@ printCombinedConstructsLoop(mlir::OpAsmPrinter &p, mlir::Operation *op,
if (attr) {
switch (attr.getValue()) {
case mlir::acc::CombinedConstructsType::KernelsLoop:
- p << "combined(kernels)";
+ p << "kernels";
break;
case mlir::acc::CombinedConstructsType::ParallelLoop:
- p << "combined(parallel)";
+ p << "parallel";
break;
case mlir::acc::CombinedConstructsType::SerialLoop:
- p << "combined(serial)";
+ p << "serial";
break;
};
}
@@ -2304,6 +2298,14 @@ LogicalResult checkDeviceTypes(mlir::ArrayAttr deviceTypes) {
}
LogicalResult acc::LoopOp::verify() {
+ if (getUpperbound().size() != getStep().size())
+ return emitError() << "number of upperbounds expected to be the same as "
+ "number of steps";
+
+ if (getUpperbound().size() != getLowerbound().size())
+ return emitError() << "number of upperbounds expected to be the same as "
+ "number of lowerbounds";
+
if (!getUpperbound().empty() && getInclusiveUpperbound() &&
(getUpperbound().size() != getInclusiveUpperbound()->size()))
return emitError() << "inclusiveUpperbound size is expected to be the same"
@@ -2421,6 +2423,15 @@ LogicalResult acc::LoopOp::verify() {
if (getRegion().empty())
return emitError("expected non-empty body.");
+ // When it is container-like - it is expected to hold a loop-like operation.
+ // TODO: Get the collapse attribute into account.
+ if (isContainerLike()) {
+ // TODO: Ensure there is a single loop-like operation at any one level.
+ auto loopLikeOps = getRegion().getOps<LoopLikeOpInterface>();
+ if (loopLikeOps.empty())
+ return emitError("expected to hold a loop-like operation.");
+ }
+
return success();
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/137886
More information about the Mlir-commits
mailing list