Skip to content

Commit f7fff18

Browse files
authored
[mlir][OpenACC] add unstructured attributes for acc.loop with early exits (#164990)
"!$acc loop" directive may be placed above loops with early exits. Currently flang lowers loop with early exits to explicit control flow (this may be revisited when MLIR allows early exits in structured region). The acc loop directive cannot simply be ignored in such case in lowering because it may hold data clauses that should be applied when reaching that point. This patch adds an "unstructured" attribute to acc.loop to support that case. An acc.loop with such attributes may hold data operands but must have no controls. It is expected that the loop logic is implemented in its body in a way that the acc dialect may not understand. Such acc.loop is just a container and the loop with early exit will be executed sequentially.
1 parent c77b614 commit f7fff18

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,12 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
25572557
device-type-aware getter methods. When modifying these operands, the
25582558
corresponding `device_type` attributes must be updated to maintain
25592559
consistency between operands and their target device types.
2560+
2561+
The `unstructured` attribute indicates that the loops inside the OpenACC
2562+
construct contain early exits and cannot be lowered to structured MLIR
2563+
operations. When this flag is set, the acc.loop should have no induction
2564+
variables and the loop must be implemented via explicit control flow
2565+
inside its body.
25602566
}];
25612567

25622568
let arguments = (ins
@@ -2590,7 +2596,8 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
25902596
OptionalAttr<SymbolRefArrayAttr>:$firstprivatizationRecipes,
25912597
Variadic<AnyType>:$reductionOperands,
25922598
OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
2593-
OptionalAttr<OpenACC_CombinedConstructsAttr>:$combined
2599+
OptionalAttr<OpenACC_CombinedConstructsAttr>:$combined,
2600+
UnitAttr:$unstructured
25942601
);
25952602

25962603
let results = (outs Variadic<AnyType>:$results);

mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3068,8 +3068,12 @@ LogicalResult acc::LoopOp::verify() {
30683068
if (getRegion().empty())
30693069
return emitError("expected non-empty body.");
30703070

3071-
// When it is container-like - it is expected to hold a loop-like operation.
3072-
if (isContainerLike()) {
3071+
if (getUnstructured()) {
3072+
if (!isContainerLike())
3073+
return emitError(
3074+
"unstructured acc.loop must not have induction variables");
3075+
} else if (isContainerLike()) {
3076+
// When it is container-like - it is expected to hold a loop-like operation.
30733077
// Obtain the maximum collapse count - we use this to check that there
30743078
// are enough loops contained.
30753079
uint64_t collapseCount = getCollapseValue().value_or(1);

mlir/test/Dialect/OpenACC/invalid.mlir

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,15 @@ func.func @fct1(%0 : !llvm.ptr) -> () {
492492

493493
// -----
494494

495+
%i1 = arith.constant 1 : i32
496+
%i2 = arith.constant 10 : i32
497+
// expected-error@+1 {{unstructured acc.loop must not have induction variables}}
498+
acc.loop control(%iv : i32) = (%i1 : i32) to (%i2 : i32) step (%i1 : i32) {
499+
acc.yield
500+
} attributes {independent = [#acc.device_type<none>], unstructured}
501+
502+
// -----
503+
495504
// expected-error@+1 {{expect at least one of num, dim or static values}}
496505
acc.loop gang({}) {
497506
"test.openacc_dummy_op"() : () -> ()

mlir/test/Dialect/OpenACC/ops.mlir

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,6 +2143,20 @@ func.func @acc_loop_container() {
21432143

21442144
// -----
21452145

2146+
func.func @acc_unstructured_loop() {
2147+
acc.loop {
2148+
acc.yield
2149+
} attributes {independent = [#acc.device_type<none>], unstructured}
2150+
return
2151+
}
2152+
2153+
// CHECK-LABEL: func.func @acc_unstructured_loop
2154+
// CHECK: acc.loop
2155+
// CHECK: acc.yield
2156+
// CHECK: } attributes {independent = [#acc.device_type<none>], unstructured}
2157+
2158+
// -----
2159+
21462160
// Test private recipe with data bounds for array slicing
21472161
acc.private.recipe @privatization_memref_slice : memref<10x10xf32> init {
21482162
^bb0(%arg0: memref<10x10xf32>, %bounds0: !acc.data_bounds_ty, %bounds1: !acc.data_bounds_ty):

0 commit comments

Comments
 (0)