Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2487,6 +2487,12 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
device-type-aware getter methods. When modifying these operands, the
corresponding `device_type` attributes must be updated to maintain
consistency between operands and their target device types.

The `unstructured` attribute indicates that the loops inside the OpenACC
construct contain early exits and cannot be lowered to structured MLIR
operations. When this flag is set, the acc.loop should have no induction
variables and the loop must be implemented via explicit control flow
inside its body.
}];

let arguments = (ins
Expand Down Expand Up @@ -2520,7 +2526,8 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
OptionalAttr<SymbolRefArrayAttr>:$firstprivatizationRecipes,
Variadic<AnyType>:$reductionOperands,
OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
OptionalAttr<OpenACC_CombinedConstructsAttr>:$combined
OptionalAttr<OpenACC_CombinedConstructsAttr>:$combined,
UnitAttr:$unstructured
);

let results = (outs Variadic<AnyType>:$results);
Expand Down
8 changes: 6 additions & 2 deletions mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3065,8 +3065,12 @@ 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.
if (isContainerLike()) {
if (getUnstructured()) {
if (!isContainerLike())
return emitError(
"unstructured acc.loop must not have induction variables");
} else if (isContainerLike()) {
// When it is container-like - it is expected to hold a loop-like operation.
// Obtain the maximum collapse count - we use this to check that there
// are enough loops contained.
uint64_t collapseCount = getCollapseValue().value_or(1);
Expand Down
9 changes: 9 additions & 0 deletions mlir/test/Dialect/OpenACC/invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,15 @@ func.func @fct1(%0 : !llvm.ptr) -> () {

// -----

%i1 = arith.constant 1 : i32
%i2 = arith.constant 10 : i32
// expected-error@+1 {{unstructured acc.loop must not have induction variables}}
acc.loop control(%iv : i32) = (%i1 : i32) to (%i2 : i32) step (%i1 : i32) {
acc.yield
} attributes {independent = [#acc.device_type<none>], unstructured}

// -----

// expected-error@+1 {{expect at least one of num, dim or static values}}
acc.loop gang({}) {
"test.openacc_dummy_op"() : () -> ()
Expand Down
14 changes: 14 additions & 0 deletions mlir/test/Dialect/OpenACC/ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,20 @@ func.func @acc_loop_container() {

// -----

func.func @acc_unstructured_loop() {
acc.loop {
acc.yield
} attributes {independent = [#acc.device_type<none>], unstructured}
return
}

// CHECK-LABEL: func.func @acc_unstructured_loop
// CHECK: acc.loop
// CHECK: acc.yield
// CHECK: } attributes {independent = [#acc.device_type<none>], unstructured}

// -----

// Test private recipe with data bounds for array slicing
acc.private.recipe @privatization_memref_slice : memref<10x10xf32> init {
^bb0(%arg0: memref<10x10xf32>, %bounds0: !acc.data_bounds_ty, %bounds1: !acc.data_bounds_ty):
Expand Down