[Mlir-commits] [mlir] 166713f - [mlir][OpenMP] Change omp.atomic.update to have generic updates
Shraiysh Vaishay
llvmlistbot at llvm.org
Tue Feb 15 04:28:33 PST 2022
Author: Shraiysh Vaishay
Date: 2022-02-15T17:58:13+05:30
New Revision: 166713f987b343e65baf25532b3ff48be154c390
URL: https://github.com/llvm/llvm-project/commit/166713f987b343e65baf25532b3ff48be154c390
DIFF: https://github.com/llvm/llvm-project/commit/166713f987b343e65baf25532b3ff48be154c390.diff
LOG: [mlir][OpenMP] Change omp.atomic.update to have generic updates
This patch changes the syntax of omp.atomic.update to allow the other
dialects to modify the variable with appropriate operations in the
region.
Reviewed By: ftynse
Differential Revision: https://reviews.llvm.org/D119522
Added:
Modified:
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
mlir/test/Dialect/OpenMP/invalid.mlir
mlir/test/Dialect/OpenMP/ops.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 39a6f2f728787..ddeb698fb2a25 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -338,14 +338,12 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
def YieldOp : OpenMP_Op<"yield",
[NoSideEffect, ReturnLike, Terminator,
- ParentOneOf<["WsLoopOp", "ReductionDeclareOp"]>]> {
+ ParentOneOf<["WsLoopOp", "ReductionDeclareOp", "AtomicUpdateOp"]>]> {
let summary = "loop yield and termination operation";
let description = [{
"omp.yield" yields SSA values from the OpenMP dialect op region and
terminates the region. The semantics of how the values are yielded is
defined by the parent operation.
- If "omp.yield" has any operands, the operands must match the parent
- operation's results.
}];
let arguments = (ins Variadic<AnyType>:$results);
@@ -663,39 +661,35 @@ def AtomicBinOpKindAttr : I64EnumAttr<
let symbolToStringFnName = "AtomicBinOpKindToString";
}
-def AtomicUpdateOp : OpenMP_Op<"atomic.update"> {
+def AtomicUpdateOp : OpenMP_Op<"atomic.update",
+ [SingleBlockImplicitTerminator<"YieldOp">]> {
let summary = "performs an atomic update";
let description = [{
This operation performs an atomic update.
- The operands `x` and `expr` are exactly the same as the operands `x` and
- `expr` in the OpenMP Standard. The operand `x` is the address of the
- variable that is being updated. `x` is atomically read/written. The
- evaluation of `expr` need not be atomic w.r.t the read or write of the
- location designated by `x`. In general, type(x) must dereference to
- type(expr).
-
- The attribute `isXBinopExpr` is
- - true when the expression is of the form `x binop expr` on RHS
- - false when the expression is of the form `expr binop x` on RHS
-
- The attribute `binop` is the binary operation being performed atomically.
+ The operand `x` is exactly the same as the operand `x` in the OpenMP
+ Standard (OpenMP 5.0, section 2.17.7). It is the address of the variable
+ that is being updated. `x` is atomically read/written.
`hint` is the value of hint (as used in the hint clause). It is a compile
time constant. As the name suggests, this is just a hint for optimization.
`memory_order` indicates the memory ordering behavior of the construct. It
can be one of `seq_cst`, `acq_rel`, `release`, `acquire` or `relaxed`.
+
+ 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.
}];
let arguments = (ins OpenMP_PointerLikeType:$x,
- AnyType:$expr,
- UnitAttr:$isXBinopExpr,
- AtomicBinOpKindAttr:$binop,
DefaultValuedAttr<I64Attr, "0">:$hint,
OptionalAttr<MemoryOrderKindAttr>:$memory_order);
+ let regions = (region SizedRegion<1>:$region);
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
@@ -769,6 +763,9 @@ def ReductionDeclareOp : OpenMP_Op<"reduction.declare", [Symbol]> {
Note that the MLIR type system does not allow for type-polymorphic
reductions. Separate reduction declarations should be created for
diff erent
element and accumulator types.
+
+ For initializer and reduction regions, the operand to `omp.yield` must
+ match the parent operation's results.
}];
let arguments = (ins SymbolNameAttr:$sym_name,
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 3fb60f3d95dfc..4675eaf047c07 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -1528,63 +1528,30 @@ LogicalResult AtomicWriteOp::verify() {
/// Parser for AtomicUpdateOp
///
-/// operation ::= `omp.atomic.update` atomic-clause-list region
+/// operation ::= `omp.atomic.update` atomic-clause-list ssa-id-and-type region
ParseResult AtomicUpdateOp::parse(OpAsmParser &parser, OperationState &result) {
SmallVector<ClauseType> clauses = {memoryOrderClause, hintClause};
SmallVector<int> segments;
- OpAsmParser::OperandType x, y, z;
+ OpAsmParser::OperandType x, expr;
Type xType, exprType;
- StringRef binOp;
-
- // x = y `op` z : xtype, exprtype
- if (parser.parseOperand(x) || parser.parseEqual() || parser.parseOperand(y) ||
- parser.parseKeyword(&binOp) || parser.parseOperand(z) ||
- parseClauses(parser, result, clauses, segments) || parser.parseColon() ||
- parser.parseType(xType) || parser.parseComma() ||
- parser.parseType(exprType) ||
- parser.resolveOperand(x, xType, result.operands)) {
- return failure();
- }
- auto binOpEnum = AtomicBinOpKindToEnum(binOp.upper());
- if (!binOpEnum)
- return parser.emitError(parser.getNameLoc())
- << "invalid atomic bin op in atomic update\n";
- auto attr =
- parser.getBuilder().getI64IntegerAttr((int64_t)binOpEnum.getValue());
- result.addAttribute("binop", attr);
-
- OpAsmParser::OperandType expr;
- if (x.name == y.name && x.number == y.number) {
- expr = z;
- result.addAttribute("isXBinopExpr", parser.getBuilder().getUnitAttr());
- } else if (x.name == z.name && x.number == z.number) {
- expr = y;
- } else {
- return parser.emitError(parser.getNameLoc())
- << "atomic update variable " << x.name
- << " not found in the RHS of the assignment statement in an"
- " atomic.update operation";
- }
- return parser.resolveOperand(expr, exprType, result.operands);
+ if (parseClauses(parser, result, clauses, segments) ||
+ parser.parseOperand(x) || parser.parseColon() ||
+ parser.parseType(xType) ||
+ parser.resolveOperand(x, xType, result.operands) ||
+ parser.parseRegion(*result.addRegion()))
+ return failure();
+ return success();
}
void AtomicUpdateOp::print(OpAsmPrinter &p) {
- p << " " << x() << " = ";
- Value y, z;
- if (isXBinopExpr()) {
- y = x();
- z = expr();
- } else {
- y = expr();
- z = x();
- }
- p << y << " " << AtomicBinOpKindToString(binop()).lower() << " " << z << " ";
+ p << " ";
if (auto mo = memory_order())
p << "memory_order(" << stringifyClauseMemoryOrderKind(*mo) << ") ";
if (hintAttr())
printSynchronizationHint(p, *this, hintAttr());
- p << ": " << x().getType() << ", " << expr().getType();
+ p << x() << " : " << x().getType();
+ p.printRegion(region());
}
/// Verifier for AtomicUpdateOp
@@ -1596,6 +1563,22 @@ LogicalResult AtomicUpdateOp::verify() {
"memory-order must not be acq_rel or acquire for atomic updates");
}
}
+
+ if (region().getNumArguments() != 1)
+ return emitError("the region must accept exactly one argument");
+
+ if (x().getType().cast<PointerLikeType>().getElementType() !=
+ region().getArgument(0).getType()) {
+ return emitError("the type of the operand must be a pointer type whose "
+ "element type is the same as that of the region argument");
+ }
+
+ YieldOp yieldOp = *region().getOps<YieldOp>().begin();
+
+ if (yieldOp.results().size() != 1)
+ return emitError("only updated value must be returned");
+ if (yieldOp.results().front().getType() != region().getArgument(0).getType())
+ return emitError("input and yielded value must have the same type");
return success();
}
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index d0f66c3218cbc..e2dbd0f7e7268 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -609,17 +609,26 @@ func @omp_atomic_write6(%addr : memref<i32>, %val : i32) {
// -----
-func @omp_atomic_update1(%x: memref<i32>, %expr: i32, %foo: memref<i32>) {
- // expected-error @below {{atomic update variable %x not found in the RHS of the assignment statement in an atomic.update operation}}
- omp.atomic.update %x = %foo add %expr : memref<i32>, i32
+func @omp_atomic_update1(%x: memref<i32>, %expr: f32) {
+ // expected-error @below {{the type of the operand must be a pointer type whose element type is the same as that of the region argument}}
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: f32):
+ %newval = llvm.fadd %xval, %expr : f32
+ omp.yield (%newval : f32)
+ }
return
}
// -----
func @omp_atomic_update2(%x: memref<i32>, %expr: i32) {
- // expected-error @below {{invalid atomic bin op in atomic update}}
- omp.atomic.update %x = %x invalid %expr : memref<i32>, i32
+ // expected-error @+2 {{op expects regions to end with 'omp.yield', found 'omp.terminator'}}
+ // expected-note @below {{in custom textual format, the absence of terminator implies 'omp.yield'}}
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.terminator
+ }
return
}
@@ -627,7 +636,11 @@ func @omp_atomic_update2(%x: memref<i32>, %expr: i32) {
func @omp_atomic_update3(%x: memref<i32>, %expr: i32) {
// expected-error @below {{memory-order must not be acq_rel or acquire for atomic updates}}
- omp.atomic.update %x = %x add %expr memory_order(acq_rel) : memref<i32>, i32
+ omp.atomic.update memory_order(acq_rel) %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
return
}
@@ -635,7 +648,11 @@ func @omp_atomic_update3(%x: memref<i32>, %expr: i32) {
func @omp_atomic_update4(%x: memref<i32>, %expr: i32) {
// expected-error @below {{memory-order must not be acq_rel or acquire for atomic updates}}
- omp.atomic.update %x = %x add %expr memory_order(acquire) : memref<i32>, i32
+ omp.atomic.update memory_order(acquire) %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
return
}
@@ -644,7 +661,47 @@ func @omp_atomic_update4(%x: memref<i32>, %expr: i32) {
// expected-note @below {{prior use here}}
func @omp_atomic_update5(%x: memref<i32>, %expr: i32) {
// expected-error @below {{use of value '%x' expects
diff erent type than prior uses: 'i32' vs 'memref<i32>'}}
- omp.atomic.update %x = %x add %expr : i32, memref<i32>
+ omp.atomic.update %x : i32 {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
+ return
+}
+
+// -----
+
+func @omp_atomic_update6(%x: memref<i32>, %expr: i32) {
+ // expected-error @below {{only updated value must be returned}}
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval, %expr : i32, i32)
+ }
+ return
+}
+
+// -----
+
+func @omp_atomic_update7(%x: memref<i32>, %expr: i32, %y: f32) {
+ // expected-error @below {{input and yielded value must have the same type}}
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%y: f32)
+ }
+ return
+}
+
+// -----
+
+func @omp_atomic_update8(%x: memref<i32>, %expr: i32) {
+ // expected-error @below {{the region must accept exactly one argument}}
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32, %tmp: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
return
}
@@ -676,8 +733,16 @@ func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
omp.atomic.capture {
// expected-error @below {{invalid sequence of operations in the capture region}}
- omp.atomic.update %x = %x add %expr : memref<i32>, i32
- omp.atomic.update %x = %x sub %expr : memref<i32>, i32
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
omp.terminator
}
return
@@ -701,7 +766,11 @@ func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
omp.atomic.capture {
// expected-error @below {{invalid sequence of operations in the capture region}}
omp.atomic.write %x = %expr : memref<i32>, i32
- omp.atomic.update %x = %x add %expr : memref<i32>, i32
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
omp.terminator
}
return
@@ -712,7 +781,11 @@ func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
omp.atomic.capture {
// expected-error @below {{invalid sequence of operations in the capture region}}
- omp.atomic.update %x = %x add %expr : memref<i32>, i32
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
omp.atomic.write %x = %expr : memref<i32>, i32
omp.terminator
}
@@ -736,7 +809,11 @@ func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %expr: i32) {
omp.atomic.capture {
// expected-error @below {{updated variable in omp.atomic.update must be captured in second operation}}
- omp.atomic.update %x = %x add %expr : memref<i32>, i32
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
omp.atomic.read %v = %y : memref<i32>
omp.terminator
}
@@ -748,7 +825,11 @@ func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %exp
omp.atomic.capture {
// expected-error @below {{captured variable in omp.atomic.read must be updated in second operation}}
omp.atomic.read %v = %y : memref<i32>
- omp.atomic.update %x = %x add %expr : memref<i32>, i32
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield (%newval : i32)
+ }
omp.terminator
}
}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index e8afc66f4e2e8..5732712a2c056 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -541,61 +541,55 @@ func @omp_atomic_write(%addr : memref<i32>, %val : i32) {
// CHECK-LABEL: omp_atomic_update
// CHECK-SAME: (%[[X:.*]]: memref<i32>, %[[EXPR:.*]]: i32, %[[XBOOL:.*]]: memref<i1>, %[[EXPRBOOL:.*]]: i1)
func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>, %exprBool : i1) {
- // CHECK: omp.atomic.update %[[X]] = %[[X]] add %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x add %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[X]] sub %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x sub %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[X]] mul %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x mul %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[X]] div %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x div %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[XBOOL]] and %[[EXPRBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %xBool and %exprBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[XBOOL]] or %[[EXPRBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %xBool or %exprBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[XBOOL]] xor %[[EXPRBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %xBool xor %exprBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[X]] = %[[X]] shiftr %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x shiftr %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[X]] shiftl %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x shiftl %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[X]] max %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x max %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[X]] min %[[EXPR]] : memref<i32>, i32
- omp.atomic.update %x = %x min %expr : memref<i32>, i32
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[XBOOL]] eqv %[[EXPRBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %xBool eqv %exprBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[XBOOL]] neqv %[[EXPRBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %xBool neqv %exprBool : memref<i1>, i1
-
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] add %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr add %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] sub %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr sub %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] mul %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr mul %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] div %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr div %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[EXPRBOOL]] and %[[XBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %exprBool and %xBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[EXPRBOOL]] or %[[XBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %exprBool or %xBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[EXPRBOOL]] xor %[[XBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %exprBool xor %xBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] shiftr %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr shiftr %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] shiftl %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr shiftl %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] max %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr max %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] min %[[X]] : memref<i32>, i32
- omp.atomic.update %x = %expr min %x : memref<i32>, i32
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[EXPRBOOL]] eqv %[[XBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %exprBool eqv %xBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[XBOOL]] = %[[EXPRBOOL]] neqv %[[XBOOL]] : memref<i1>, i1
- omp.atomic.update %xBool = %exprBool neqv %xBool : memref<i1>, i1
- // CHECK: omp.atomic.update %[[X]] = %[[EXPR]] add %[[X]] memory_order(seq_cst) hint(speculative) : memref<i32>, i32
- omp.atomic.update %x = %expr add %x hint(speculative) memory_order(seq_cst) : memref<i32>, i32
+ // CHECK: omp.atomic.update %[[X]] : memref<i32>
+ // CHECK-NEXT: (%[[XVAL:.*]]: i32):
+ // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
+ // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield(%newval : i32)
+ }
+ // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
+ // CHECK-NEXT: (%[[XVAL:.*]]: i1):
+ // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.and %[[XVAL]], %[[EXPRBOOL]] : i1
+ // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i1)
+ omp.atomic.update %xBool : memref<i1> {
+ ^bb0(%xval: i1):
+ %newval = llvm.and %xval, %exprBool : i1
+ omp.yield(%newval : i1)
+ }
+ // CHECK: omp.atomic.update %[[X]] : memref<i32>
+ // CHECK-NEXT: (%[[XVAL:.*]]: i32):
+ // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.shl %[[XVAL]], %[[EXPR]] : i32
+ // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
+ // CHECK-NEXT: }
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.shl %xval, %expr : i32
+ omp.yield(%newval : i32)
+ }
+ // CHECK: omp.atomic.update %[[X]] : memref<i32>
+ // CHECK-NEXT: (%[[XVAL:.*]]: i32):
+ // CHECK-NEXT: %[[NEWVAL:.*]] = "llvm.intr.smax"(%[[XVAL]], %[[EXPR]]) : (i32, i32) -> i32
+ // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
+ // CHECK-NEXT: }
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
+ omp.yield(%newval : i32)
+ }
+
+ // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
+ // CHECK-NEXT: (%[[XVAL:.*]]: i1):
+ // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.icmp "eq" %[[XVAL]], %[[EXPRBOOL]] : i1
+ // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i1)
+ // }
+ omp.atomic.update %xBool : memref<i1> {
+ ^bb0(%xval: i1):
+ %newval = llvm.icmp "eq" %xval, %exprBool : i1
+ omp.yield(%newval : i1)
+ }
return
}
@@ -603,23 +597,39 @@ func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>, %exp
// CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>, %[[expr:.*]]: i32)
func @omp_atomic_capture(%v: memref<i32>, %x: memref<i32>, %expr: i32) {
// CHECK: omp.atomic.capture{
- // CHECK-NEXT: omp.atomic.update %[[x]] = %[[expr]] add %[[x]] : memref<i32>, i32
+ // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
+ // CHECK-NEXT: (%[[xval:.*]]: i32):
+ // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
+ // CHECK-NEXT: omp.yield(%[[newval]] : i32)
+ // CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: omp.terminator
// CHECK-NEXT: }
omp.atomic.capture{
- omp.atomic.update %x = %expr add %x : memref<i32>, i32
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield(%newval : i32)
+ }
omp.atomic.read %v = %x : memref<i32>
omp.terminator
}
// CHECK: omp.atomic.capture{
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
- // CHECK-NEXT: omp.atomic.update %[[x]] = %[[expr]] add %[[x]] : memref<i32>, i32
+ // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
+ // CHECK-NEXT: (%[[xval:.*]]: i32):
+ // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
+ // CHECK-NEXT: omp.yield(%[[newval]] : i32)
+ // CHECK-NEXT: }
// CHECK-NEXT: omp.terminator
// CHECK-NEXT: }
omp.atomic.capture{
omp.atomic.read %v = %x : memref<i32>
- omp.atomic.update %x = %expr add %x : memref<i32>, i32
+ omp.atomic.update %x : memref<i32> {
+ ^bb0(%xval: i32):
+ %newval = llvm.add %xval, %expr : i32
+ omp.yield(%newval : i32)
+ }
omp.terminator
}
// CHECK: omp.atomic.capture{
More information about the Mlir-commits
mailing list