[Mlir-commits] [flang] [mlir] [Flang] [OpenMP] atomic compare (PR #184761)
Krzysztof Parzyszek
llvmlistbot at llvm.org
Sun Mar 15 08:11:23 PDT 2026
================
@@ -521,8 +542,121 @@ void Fortran::lower::omp::lowerAtomic(
memOrder = makeValidForAction(memOrder, action0, action1, version);
if (auto *cond = get(analysis.cond)) {
- (void)cond;
- TODO(loc, "OpenMP ATOMIC COMPARE");
+ // atomic compare: if (x == e) x = d
+ // e : expecteVal
+ // d : desiredVal
+
+ // Check for compound clauses (fail, capture, weak) that are not yet
+ // supported with atomic compare.
+ if (llvm::any_of(clauses, [](const omp::Clause &clause) {
+ return clause.id == llvm::omp::Clause::OMPC_fail ||
+ clause.id == llvm::omp::Clause::OMPC_capture ||
+ clause.id == llvm::omp::Clause::OMPC_weak;
+ })) {
+ TODO(loc, "Compound clauses of OpenMP ATOMIC COMPARE");
+ }
+
+ Fortran::common::RelationalOperator relOpr =
+ Fortran::common::RelationalOperator::EQ;
+ std::optional<semantics::SomeExpr> expectedExprStorage;
+
+ if (const auto *rel = Fortran::evaluate::UnwrapExpr<
+ Fortran::evaluate::Relational<Fortran::evaluate::SomeType>>(
+ *cond)) {
+ std::visit(
+ [&](const auto &relImpl) {
+ relOpr = relImpl.opr;
+ using Operand = typename std::decay_t<decltype(relImpl)>::Operand;
+ auto leftExpr = Fortran::evaluate::AsGenericExpr(
+ Fortran::evaluate::Expr<Operand>{relImpl.left()});
+ auto rightExpr = Fortran::evaluate::AsGenericExpr(
+ Fortran::evaluate::Expr<Operand>{relImpl.right()});
+ if (Fortran::evaluate::IsSameOrConvertOf(rightExpr, atom)) {
+ // e.g. e == x (atom is on the right)
+ // left operand is expected value (e)
+ // reverse the operator so that the comparison becomes
+ // x <reversed-op> e.
+ expectedExprStorage = std::move(leftExpr);
+ relOpr = reverseRelOp(relOpr);
+ } else {
+ // Form: x == e (atom is on the left, or default)
+ expectedExprStorage = std::move(rightExpr);
+ }
+ },
+ rel->u);
+ }
+ if (!expectedExprStorage) {
+ mlir::emitError(loc, "internal error: atomic compare condition is not a "
+ "recognized relational expression");
+ return;
+ }
+
+ mlir::UnitAttr weakAttr = nullptr;
+ mlir::Operation *atomicOp = mlir::omp::AtomicCompareOp::create(
+ builder, loc, atomAddr, weakAttr, hint,
+ makeMemOrderAttr(converter, memOrder));
+ mlir::Type elemTypeOfX = fir::unwrapRefType(atomAddr.getType());
+ mlir::Block *block = builder.createBlock(&atomicOp->getRegion(0));
+ mlir::Value blockArg = block->addArgument(elemTypeOfX, loc);
+ builder.setInsertionPointToEnd(block);
+
+ mlir::Value expectedVal = fir::getBase(
+ converter.genExprValue(*expectedExprStorage, stmtCtx, &loc));
+ if (expectedVal.getType() != elemTypeOfX) {
+ expectedVal = builder.createConvert(loc, elemTypeOfX, expectedVal);
+ }
----------------
kparzysz wrote:
I think this should be done before the atomic op.
https://github.com/llvm/llvm-project/pull/184761
More information about the Mlir-commits
mailing list