Skip to content

[openacc][openmp] Add dialect representation for acc atomic operations #65493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_subdirectory(MemRef)
add_subdirectory(MLProgram)
add_subdirectory(NVGPU)
add_subdirectory(OpenACC)
add_subdirectory(OpenACCMPCommon)
add_subdirectory(OpenMP)
add_subdirectory(PDL)
add_subdirectory(PDLInterp)
Expand Down
2 changes: 2 additions & 0 deletions mlir/include/mlir/Dialect/OpenACC/OpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/SymbolTable.h"

#include "mlir/Bytecode/BytecodeOpInterface.h"
#include "mlir/Dialect/OpenACC/OpenACCOpsDialect.h.inc"
#include "mlir/Dialect/OpenACC/OpenACCOpsEnums.h.inc"
#include "mlir/Dialect/OpenACC/OpenACCTypeInterfaces.h.inc"
#include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"

Expand Down
155 changes: 152 additions & 3 deletions mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ include "mlir/IR/SymbolInterfaces.td"
include "mlir/Dialect/OpenACC/OpenACCBase.td"
include "mlir/Dialect/OpenACC/OpenACCOpsTypes.td"
include "mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td"
include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td"

// AccCommon requires definition of OpenACC_Dialect.
include "mlir/Dialect/OpenACC/AccCommon.td"
Expand Down Expand Up @@ -1191,13 +1192,14 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",

// Yield operation for the acc.loop and acc.parallel operations.
def OpenACC_YieldOp : OpenACC_Op<"yield", [ReturnLike, Terminator,
ParentOneOf<["FirstprivateRecipeOp, LoopOp, ParallelOp, PrivateRecipeOp, ReductionRecipeOp, SerialOp"]>]> {
ParentOneOf<["FirstprivateRecipeOp, LoopOp, ParallelOp, PrivateRecipeOp,"
"ReductionRecipeOp, SerialOp, AtomicUpdateOp"]>]> {
let summary = "Acc yield and termination operation";

let description = [{
`acc.yield` is a special terminator operation for block inside regions in
acc ops (parallel and loop). It returns values to the immediately enclosing
acc op.
various acc ops (including parallel, loop, atomic.update). It returns values
to the immediately enclosing acc op.
}];

let arguments = (ins Variadic<AnyType>:$operands);
Expand All @@ -1207,6 +1209,153 @@ def OpenACC_YieldOp : OpenACC_Op<"yield", [ReturnLike, Terminator,
let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?";
}

//===----------------------------------------------------------------------===//
// 2.12 atomic construct
//===----------------------------------------------------------------------===//

def AtomicReadOp : OpenACC_Op<"atomic.read", [AllTypesMatch<["x", "v"]>,
AtomicReadOpInterface]> {

let summary = "performs an atomic read";

let description = [{
This operation performs an atomic read.

The operand `x` is the address from where the value is atomically read.
The operand `v` is the address where the value is stored after reading.
}];

let arguments = (ins OpenACC_PointerLikeType:$x,
OpenACC_PointerLikeType:$v,
TypeAttr:$element_type);
let assemblyFormat = [{
$v `=` $x
`:` type($x) `,` $element_type attr-dict
}];
let hasVerifier = 1;
}

def AtomicWriteOp : OpenACC_Op<"atomic.write",[AtomicWriteOpInterface]> {

let summary = "performs an atomic write";

let description = [{
This operation performs an atomic write.

The operand `x` is the address to where the `expr` is atomically
written w.r.t. multiple threads. The evaluation of `expr` need not be
atomic w.r.t. the write to address. In general, the type(x) must
dereference to type(expr).
}];

let arguments = (ins OpenACC_PointerLikeType:$x,
AnyType:$expr);
let assemblyFormat = [{
$x `=` $expr
`:` type($x) `,` type($expr)
attr-dict
}];
let hasVerifier = 1;
}

def AtomicUpdateOp : OpenACC_Op<"atomic.update",
[SingleBlockImplicitTerminator<"YieldOp">,
RecursiveMemoryEffects,
AtomicUpdateOpInterface]> {

let summary = "performs an atomic update";

let description = [{
This operation performs an atomic update.

The operand `x` is exactly the same as the operand `x` in the OpenACC
Standard (OpenACC 3.3, section 2.12). It is the address of the variable
that is being updated. `x` is atomically read/written.

The region describes how to update the value of `x`. It takes the value at
`x` as an input and must yield the updated value. Only the update to `x` is
atomic. Generally the region must have only one instruction, but can
potentially have more than one instructions too. The update is sematically
similar to a compare-exchange loop based atomic update.

The syntax of atomic update operation is different from atomic read and
atomic write operations. This is because only the host dialect knows how to
appropriately update a value. For example, while generating LLVM IR, if
there are no special `atomicrmw` instructions for the operation-type
combination in atomic update, a compare-exchange loop is generated, where
the core update operation is directly translated like regular operations by
the host dialect. The front-end must handle semantic checks for allowed
operations.
}];

let arguments = (ins Arg<OpenACC_PointerLikeType,
"Address of variable to be updated",
[MemRead, MemWrite]>:$x);
let regions = (region SizedRegion<1>:$region);
let assemblyFormat = [{
$x `:` type($x) $region attr-dict
}];
let hasVerifier = 1;
let hasRegionVerifier = 1;
let hasCanonicalizeMethod = 1;
let extraClassDeclaration = [{
Operation* getFirstOp() {
return &getRegion().front().getOperations().front();
}
}];
}

def AtomicCaptureOp : OpenACC_Op<"atomic.capture",
[SingleBlockImplicitTerminator<"TerminatorOp">,
RecursiveMemoryEffects, AtomicCaptureOpInterface]> {
let summary = "performs an atomic capture";
let description = [{
This operation performs an atomic capture.

The region has the following allowed forms:

```
acc.atomic.capture {
acc.atomic.update ...
acc.atomic.read ...
acc.terminator
}

acc.atomic.capture {
acc.atomic.read ...
acc.atomic.update ...
acc.terminator
}

acc.atomic.capture {
acc.atomic.read ...
acc.atomic.write ...
acc.terminator
}
```

}];

let regions = (region SizedRegion<1>:$region);
let assemblyFormat = [{
$region attr-dict
}];
let hasRegionVerifier = 1;
let extraClassDeclaration = [{
/// Returns the `atomic.read` operation inside the region, if any.
/// Otherwise, it returns nullptr.
AtomicReadOp getAtomicReadOp();

/// Returns the `atomic.write` operation inside the region, if any.
/// Otherwise, it returns nullptr.
AtomicWriteOp getAtomicWriteOp();

/// Returns the `atomic.update` operation inside the region, if any.
/// Otherwise, it returns nullptr.
AtomicUpdateOp getAtomicUpdateOp();
}];
}

//===----------------------------------------------------------------------===//
// 2.13 Declare Directive
//===----------------------------------------------------------------------===//
Expand Down
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/OpenACCMPCommon/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(Interfaces)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===- DirectiveAtomicInterfaces.h - directive atomic ops interfaces ------===//
//
// Part of the LLVM 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the operation interface for atomic operations used
// in OpenACC and OpenMP.
//
//===----------------------------------------------------------------------===//

#ifndef OPENACC_MP_COMMON_INTERFACES_ATOMICINTERFACES_H_
#define OPENACC_MP_COMMON_INTERFACES_ATOMICINTERFACES_H_

#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"

#include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h.inc"

#endif // OPENACC_MP_COMMON_INTERFACES_ATOMICINTERFACES_H_
Loading