[flang-commits] [flang] [flang][OpenMP]Add parsing and semantics support for ATOMIC COMPARE (PR #117032)

Mats Petersson via flang-commits flang-commits at lists.llvm.org
Thu Nov 28 04:02:23 PST 2024


https://github.com/Leporacanthicus updated https://github.com/llvm/llvm-project/pull/117032

>From 6fa660017ff80dc5ba467239c53c43ed561e99d4 Mon Sep 17 00:00:00 2001
From: Mats Petersson <mats.petersson at arm.com>
Date: Wed, 20 Nov 2024 18:09:23 +0000
Subject: [PATCH 1/3] [flang][OpenMP]Add parsing and semantics support for
 ATOMIC COMPARE

This adds a minimalistic implementation of parsing and semantics
for the ATOMIC COMPARE feature from OpenMP 5.1.

There is no lowering, just a TODO for that part. Some of the
Semantics is also just a comment explaining that more is needed.
---
 flang/include/flang/Parser/dump-parse-tree.h  |  1 +
 flang/include/flang/Parser/parse-tree.h       | 13 +++-
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  4 +
 flang/lib/Parser/openmp-parsers.cpp           |  7 ++
 flang/lib/Parser/unparse.cpp                  | 10 +++
 flang/lib/Semantics/check-omp-structure.cpp   | 28 +++++++
 flang/lib/Semantics/check-omp-structure.h     |  1 +
 flang/test/Parser/OpenMP/atomic-compare.f90   | 16 ++++
 flang/test/Parser/OpenMP/atomic-unparse.f90   | 39 ++++++++++
 .../test/Semantics/OpenMP/atomic-compare.f90  | 76 +++++++++++++++++++
 flang/test/Semantics/OpenMP/atomic.f90        |  2 +
 11 files changed, 195 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Parser/OpenMP/atomic-compare.f90
 create mode 100644 flang/test/Semantics/OpenMP/atomic-compare.f90

diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 63fddc424182b2..a31dd82e266b7e 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -484,6 +484,7 @@ class ParseTreeDumper {
   NODE(parser, OmpAtomicCapture)
   NODE(OmpAtomicCapture, Stmt1)
   NODE(OmpAtomicCapture, Stmt2)
+  NODE(parser, OmpAtomicCompare)
   NODE(parser, OmpAtomicRead)
   NODE(parser, OmpAtomicUpdate)
   NODE(parser, OmpAtomicWrite)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 22b7f9acd1af52..a8a23d1a16938b 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4126,6 +4126,15 @@ struct OmpAtomicCapture {
       t;
 };
 
+// ATOMCI COMPARE (OpenMP 5.1, Spec: 15.8.4)
+struct OmpAtomicCompare {
+  TUPLE_CLASS_BOILERPLATE(OmpAtomicCompare);
+  CharBlock source;
+  std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
+      Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
+      t;
+};
+
 // ATOMIC
 struct OmpAtomic {
   TUPLE_CLASS_BOILERPLATE(OmpAtomic);
@@ -4138,11 +4147,11 @@ struct OmpAtomic {
 // 2.17.7 atomic ->
 //        ATOMIC [atomic-clause-list] atomic-construct [atomic-clause-list] |
 //        ATOMIC [atomic-clause-list]
-//        atomic-construct -> READ | WRITE | UPDATE | CAPTURE
+//        atomic-construct -> READ | WRITE | UPDATE | CAPTURE | COMPARE
 struct OpenMPAtomicConstruct {
   UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
   std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
-      OmpAtomic>
+      OmpAtomicCompare, OmpAtomic>
       u;
 };
 
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index a2779213a1a15a..80a17e97ee67f3 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2896,6 +2896,10 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
                                           parser::OmpAtomicClauseList>(
                 converter, atomicCapture, loc);
           },
+          [&](const parser::OmpAtomicCompare &atomicCompare) {
+            mlir::Location loc = converter.genLocation(atomicCompare.source);
+            TODO(loc, "OpenMP atomic compare");
+          },
       },
       atomicConstruct.u);
 }
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 630acf9a6b256c..6d19d13f181e11 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -912,6 +912,12 @@ TYPE_PARSER("ATOMIC" >>
         Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
         statement(assignmentStmt), Parser<OmpEndAtomic>{} / endOmpLine)))
 
+TYPE_PARSER("ATOMIC" >>
+    sourced(construct<OmpAtomicCompare>(
+        Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("COMPARE"_tok),
+        Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
+        maybe(Parser<OmpEndAtomic>{} / endOmpLine))))
+
 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
 TYPE_PARSER("ATOMIC" >>
     sourced(construct<OmpAtomicUpdate>(
@@ -934,6 +940,7 @@ TYPE_PARSER("ATOMIC" >>
 // Atomic Construct
 TYPE_PARSER(construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) ||
     construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) ||
+    construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCompare>{}) ||
     construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) ||
     construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) ||
     construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{}))
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 4d6aaceb69c185..c1ffb44385f04c 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2520,6 +2520,16 @@ class UnparseVisitor {
     Word("!$OMP END ATOMIC\n");
     EndOpenMP();
   }
+  void Unparse(const OmpAtomicCompare &x) {
+    BeginOpenMP();
+    Word("!$OMP ATOMIC");
+    Walk(std::get<0>(x.t));
+    Word(" COMPARE");
+    Walk(std::get<2>(x.t));
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Statement<AssignmentStmt>>(x.t));
+  }
   void Unparse(const OmpAtomicRead &x) {
     BeginOpenMP();
     Word("!$OMP ATOMIC");
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 9cac652216fcf2..90e8e99043ff5d 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2408,6 +2408,24 @@ void OmpStructureChecker::CheckAtomicUpdateStmt(
   ErrIfAllocatableVariable(var);
 }
 
+void OmpStructureChecker::CheckAtomicCompareConstruct(
+    const parser::OmpAtomicCompare &atomicCompareConstruct) {
+
+  CheckAtomicWriteStmt(std::get<parser::Statement<parser::AssignmentStmt>>(
+      atomicCompareConstruct.t)
+                           .statement);
+
+  unsigned version{context_.langOptions().OpenMPVersion};
+  if (version < 51) {
+    context_.Say(atomicCompareConstruct.source,
+        "%s construct not allowed in %s, %s"_err_en_US,
+        atomicCompareConstruct.source, ThisVersion(version), TryVersion(51));
+  }
+
+  // TODO: More work needed here. Some of the Update restrictions need to
+  // be added, but Update isn't the same either.
+}
+
 // TODO: Allow cond-update-stmt once compare clause is supported.
 void OmpStructureChecker::CheckAtomicCaptureConstruct(
     const parser::OmpAtomicCapture &atomicCaptureConstruct) {
@@ -2553,6 +2571,16 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
                 &std::get<0>(atomicCapture.t), &std::get<2>(atomicCapture.t));
             CheckAtomicCaptureConstruct(atomicCapture);
           },
+          [&](const parser::OmpAtomicCompare &atomicCompare) {
+            const auto &dir{std::get<parser::Verbatim>(atomicCompare.t)};
+            PushContextAndClauseSets(
+                dir.source, llvm::omp::Directive::OMPD_atomic);
+            CheckAtomicMemoryOrderClause(
+                &std::get<0>(atomicCompare.t), &std::get<2>(atomicCompare.t));
+            CheckHintClause<const parser::OmpAtomicClauseList>(
+                &std::get<0>(atomicCompare.t), &std::get<2>(atomicCompare.t));
+            CheckAtomicCompareConstruct(atomicCompare);
+          },
       },
       x.u);
 }
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index df21ebac0f6d76..6b4fb51c2d99cc 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -213,6 +213,7 @@ class OmpStructureChecker
   void CheckAtomicCaptureStmt(const parser::AssignmentStmt &);
   void CheckAtomicWriteStmt(const parser::AssignmentStmt &);
   void CheckAtomicCaptureConstruct(const parser::OmpAtomicCapture &);
+  void CheckAtomicCompareConstruct(const parser::OmpAtomicCompare &);
   void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct &);
   void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
   void CheckSIMDNest(const parser::OpenMPConstruct &x);
diff --git a/flang/test/Parser/OpenMP/atomic-compare.f90 b/flang/test/Parser/OpenMP/atomic-compare.f90
new file mode 100644
index 00000000000000..5cd02698ff4823
--- /dev/null
+++ b/flang/test/Parser/OpenMP/atomic-compare.f90
@@ -0,0 +1,16 @@
+! RUN: not %flang_fc1  -fopenmp-version=51 -fopenmp %s 2>&1 | FileCheck %s
+! OpenMP version for documentation purposes only - it isn't used until Sema.
+! This is testing for Parser errors that bail out before Sema. 
+program main
+   implicit none
+   integer :: i, j = 10
+   logical :: r
+
+  !CHECK: error: expected OpenMP construct
+  !$omp atomic compare write
+  r =  i .eq. j + 1
+
+  !CHECK: error: expected end of line
+  !$omp atomic compare num_threads(4)
+  r = i .eq. j
+end program main
diff --git a/flang/test/Parser/OpenMP/atomic-unparse.f90 b/flang/test/Parser/OpenMP/atomic-unparse.f90
index f9d8ec5d5c6813..a7b4d673bc3c6d 100644
--- a/flang/test/Parser/OpenMP/atomic-unparse.f90
+++ b/flang/test/Parser/OpenMP/atomic-unparse.f90
@@ -3,6 +3,7 @@
 program main
    implicit none
    integer :: i, j = 10
+   logical :: k
 !READ
 !$omp atomic read
    i = j
@@ -121,6 +122,30 @@ program main
    i = j
 !$omp end atomic
 
+!COMPARE
+!$omp atomic compare
+   r = i .eq. j
+!$omp atomic seq_cst compare
+   r = i .eq. j
+!$omp atomic compare seq_cst
+   r = i .eq. j
+!$omp atomic release compare
+   r = i .eq. j
+!$omp atomic compare release
+   r = i .eq. j
+!$omp atomic acq_rel compare
+   r = i .eq. j
+!$omp atomic compare acq_rel
+   r = i .eq. j
+!$omp atomic acquire compare
+   r = i .eq. j
+!$omp atomic compare acquire
+   r = i .eq. j
+!$omp atomic relaxed compare
+   r = i .eq. j
+!$omp atomic compare relaxed
+   r = i .eq. j
+
 !ATOMIC
 !$omp atomic
    i = j
@@ -205,6 +230,20 @@ end program main
 !CHECK: !$OMP ATOMIC CAPTURE RELAXED
 !CHECK: !$OMP END ATOMIC
 
+!COMPARE
+
+!CHECK: !$OMP ATOMIC COMPARE
+!CHECK: !$OMP ATOMIC SEQ_CST COMPARE
+!CHECK: !$OMP ATOMIC COMPARE SEQ_CST
+!CHECK: !$OMP ATOMIC RELEASE COMPARE
+!CHECK: !$OMP ATOMIC COMPARE RELEASE
+!CHECK: !$OMP ATOMIC ACQ_REL COMPARE
+!CHECK: !$OMP ATOMIC COMPARE ACQ_REL
+!CHECK: !$OMP ATOMIC ACQUIRE COMPARE
+!CHECK: !$OMP ATOMIC COMPARE ACQUIRE
+!CHECK: !$OMP ATOMIC RELAXED COMPARE
+!CHECK: !$OMP ATOMIC COMPARE RELAXED
+
 !ATOMIC
 !CHECK: !$OMP ATOMIC
 !CHECK: !$OMP ATOMIC SEQ_CST
diff --git a/flang/test/Semantics/OpenMP/atomic-compare.f90 b/flang/test/Semantics/OpenMP/atomic-compare.f90
new file mode 100644
index 00000000000000..624624a8ecc4a3
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/atomic-compare.f90
@@ -0,0 +1,76 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51
+  use omp_lib
+  implicit none
+  ! Check atomic compare. This combines elements from multiple other "atomic*.f90", as
+  ! to avoid having several files with just a few lines in them. atomic compare needs
+  ! higher openmp version than the others, so need a separate file.
+  
+
+  real a, b
+  logical r
+  a = 1.0
+  b = 2.0
+  !$omp parallel num_threads(4)
+  ! First a few things that should compile without error.
+  !$omp atomic seq_cst, compare
+  r = b .ne. a
+
+  !$omp atomic seq_cst compare
+  r = a .ge. b
+  !$omp end atomic
+
+  !$omp atomic compare acquire hint(OMP_LOCK_HINT_CONTENDED)
+  r = a .lt. b
+
+  !$omp atomic release hint(OMP_LOCK_HINT_UNCONTENDED) compare
+  r = a .gt. b
+
+  !$omp atomic compare seq_cst
+  r = b .ne. a
+
+  !$omp atomic hint(1) acq_rel compare
+  r = b .eq. a
+  !$omp end atomic
+
+  ! Check for error conidtions:
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
+  !$omp atomic seq_cst seq_cst compare
+  r = a .le. b
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
+  !$omp atomic compare seq_cst seq_cst
+  r = b .gt. a
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
+  !$omp atomic seq_cst compare seq_cst
+  r = b .ge. b
+
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
+  !$omp atomic acquire acquire compare
+  r = a .le. b
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
+  !$omp atomic compare acquire acquire
+  r = b .gt. a
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
+  !$omp atomic acquire compare acquire
+  r = b .ge. b
+
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one RELAXED clause can appear on the COMPARE directive
+  !$omp atomic relaxed relaxed compare
+  r = a .le. b
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one RELAXED clause can appear on the COMPARE directive
+  !$omp atomic compare relaxed relaxed
+  r = b .gt. a
+  !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
+  !ERROR: At most one RELAXED clause can appear on the COMPARE directive
+  !$omp atomic relaxed compare relaxed
+  r = b .ge. b
+
+  !$omp end parallel
+end
diff --git a/flang/test/Semantics/OpenMP/atomic.f90 b/flang/test/Semantics/OpenMP/atomic.f90
index 44f06b7460bf10..0e100871ea9b48 100644
--- a/flang/test/Semantics/OpenMP/atomic.f90
+++ b/flang/test/Semantics/OpenMP/atomic.f90
@@ -35,6 +35,7 @@
   a = a + 1
   !ERROR: expected 'UPDATE'
   !ERROR: expected 'WRITE'
+  !ERROR: expected 'COMPARE'
   !ERROR: expected 'CAPTURE'
   !ERROR: expected 'READ'
   !$omp atomic num_threads(4)
@@ -49,6 +50,7 @@
 
   !ERROR: expected 'UPDATE'
   !ERROR: expected 'WRITE'
+  !ERROR: expected 'COMPARE'
   !ERROR: expected 'CAPTURE'
   !ERROR: expected 'READ'
   !$omp atomic num_threads write

>From 549e2e01dfdea843cdf6b650e08ac4f4bc3f3b06 Mon Sep 17 00:00:00 2001
From: Mats Petersson <mats.petersson at arm.com>
Date: Wed, 27 Nov 2024 19:47:11 +0000
Subject: [PATCH 2/3] Update based on review comments, consisting of:

* Accept only if statements, rather than an assignment statement.
* Modify tests to match the if-statment required.
* Add test to check for the TODO in lowering.
---
 flang/include/flang/Parser/dump-parse-tree.h  |  1 +
 flang/include/flang/Parser/parse-tree.h       |  9 +++-
 flang/lib/Parser/openmp-parsers.cpp           |  8 +++-
 flang/lib/Parser/unparse.cpp                  |  2 +-
 flang/lib/Semantics/check-omp-structure.cpp   |  5 +--
 .../test/Lower/OpenMP/Todo/atomic-compare.f90 | 11 +++++
 flang/test/Parser/OpenMP/atomic-unparse.f90   | 43 +++++++++++++------
 .../test/Semantics/OpenMP/atomic-compare.f90  | 36 ++++++++--------
 8 files changed, 79 insertions(+), 36 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/Todo/atomic-compare.f90

diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index a31dd82e266b7e..150a07d1142f60 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -485,6 +485,7 @@ class ParseTreeDumper {
   NODE(OmpAtomicCapture, Stmt1)
   NODE(OmpAtomicCapture, Stmt2)
   NODE(parser, OmpAtomicCompare)
+  NODE(parser, OmpAtomicCompareIfStmt)
   NODE(parser, OmpAtomicRead)
   NODE(parser, OmpAtomicUpdate)
   NODE(parser, OmpAtomicWrite)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index a8a23d1a16938b..b8ae734596128c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4126,12 +4126,17 @@ struct OmpAtomicCapture {
       t;
 };
 
-// ATOMCI COMPARE (OpenMP 5.1, Spec: 15.8.4)
+struct OmpAtomicCompareIfStmt {
+  UNION_CLASS_BOILERPLATE(OmpAtomicCompareIfStmt);
+  std::variant<common::Indirection<IfStmt>, common::Indirection<IfConstruct>> u;
+};
+
+// ATOMIC COMPARE (OpenMP 5.1, OPenMP 5.2 spec: 15.8.4)
 struct OmpAtomicCompare {
   TUPLE_CLASS_BOILERPLATE(OmpAtomicCompare);
   CharBlock source;
   std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
-      Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
+      OmpAtomicCompareIfStmt, std::optional<OmpEndAtomic>>
       t;
 };
 
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 6d19d13f181e11..1e01c2a5634de2 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -10,6 +10,7 @@
 // See OpenMP-4.5-grammar.txt for documentation.
 
 #include "basic-parsers.h"
+#include "debug-parser.h"
 #include "expr-parsers.h"
 #include "misc-parsers.h"
 #include "stmt-parser.h"
@@ -912,10 +913,15 @@ TYPE_PARSER("ATOMIC" >>
         Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
         statement(assignmentStmt), Parser<OmpEndAtomic>{} / endOmpLine)))
 
+TYPE_PARSER(construct<OmpAtomicCompareIfStmt>(indirect(Parser<IfStmt>{})) ||
+    construct<OmpAtomicCompareIfStmt>(indirect(Parser<IfConstruct>{})))
+
+// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] COMPARE [MEMORY-ORDER-CLAUSE-LIST]
 TYPE_PARSER("ATOMIC" >>
     sourced(construct<OmpAtomicCompare>(
         Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("COMPARE"_tok),
-        Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
+        Parser<OmpAtomicClauseList>{} / endOmpLine,
+        Parser<OmpAtomicCompareIfStmt>{},
         maybe(Parser<OmpEndAtomic>{} / endOmpLine))))
 
 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index c1ffb44385f04c..1e97262d66981d 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2528,7 +2528,7 @@ class UnparseVisitor {
     Walk(std::get<2>(x.t));
     Put("\n");
     EndOpenMP();
-    Walk(std::get<Statement<AssignmentStmt>>(x.t));
+    Walk(std::get<OmpAtomicCompareIfStmt>(x.t));
   }
   void Unparse(const OmpAtomicRead &x) {
     BeginOpenMP();
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 90e8e99043ff5d..0cf9493695607f 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2411,9 +2411,8 @@ void OmpStructureChecker::CheckAtomicUpdateStmt(
 void OmpStructureChecker::CheckAtomicCompareConstruct(
     const parser::OmpAtomicCompare &atomicCompareConstruct) {
 
-  CheckAtomicWriteStmt(std::get<parser::Statement<parser::AssignmentStmt>>(
-      atomicCompareConstruct.t)
-                           .statement);
+  // TODO: Check that the if-stmt is `if (var == expr) var = new`
+  //       [with or without then/end-do]
 
   unsigned version{context_.langOptions().OpenMPVersion};
   if (version < 51) {
diff --git a/flang/test/Lower/OpenMP/Todo/atomic-compare.f90 b/flang/test/Lower/OpenMP/Todo/atomic-compare.f90
new file mode 100644
index 00000000000000..88ec6fe910b9e2
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/atomic-compare.f90
@@ -0,0 +1,11 @@
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: OpenMP atomic compare
+program p
+  integer :: x
+  logical :: r
+  !$omp atomic compare
+  if (x .eq. 0) then
+     x = 2
+  end if
+end program p
diff --git a/flang/test/Parser/OpenMP/atomic-unparse.f90 b/flang/test/Parser/OpenMP/atomic-unparse.f90
index a7b4d673bc3c6d..64fa79fb1d1a2f 100644
--- a/flang/test/Parser/OpenMP/atomic-unparse.f90
+++ b/flang/test/Parser/OpenMP/atomic-unparse.f90
@@ -3,7 +3,7 @@
 program main
    implicit none
    integer :: i, j = 10
-   logical :: k
+   integer :: k
 !READ
 !$omp atomic read
    i = j
@@ -124,27 +124,46 @@ program main
 
 !COMPARE
 !$omp atomic compare
-   r = i .eq. j
+   if (k == i) k = j
 !$omp atomic seq_cst compare
-   r = i .eq. j
+   if (k == j) then
+      k = i
+   end if
 !$omp atomic compare seq_cst
-   r = i .eq. j
+   if (k .eq. j) then
+      k = i
+   end if
 !$omp atomic release compare
-   r = i .eq. j
+   if (i .eq. j) k = i
 !$omp atomic compare release
-   r = i .eq. j
+   if (i .eq. j) then
+      i = k
+   end if
 !$omp atomic acq_rel compare
-   r = i .eq. j
+   if (k .eq. j) then
+      j = i
+   end if
 !$omp atomic compare acq_rel
-   r = i .eq. j
+   if (i .eq. j) then
+      i = k
+   end if
 !$omp atomic acquire compare
-   r = i .eq. j
+   if (i .eq. j + 1) then
+      i = j
+   end if
+   
 !$omp atomic compare acquire
-   r = i .eq. j
+   if (i .eq. j) then
+      i = k
+   end if
 !$omp atomic relaxed compare
-   r = i .eq. j
+   if (i .eq. j) then
+      i = k
+   end if
 !$omp atomic compare relaxed
-   r = i .eq. j
+   if (i .eq. k) then
+      i = j
+   end if
 
 !ATOMIC
 !$omp atomic
diff --git a/flang/test/Semantics/OpenMP/atomic-compare.f90 b/flang/test/Semantics/OpenMP/atomic-compare.f90
index 624624a8ecc4a3..0867950b080536 100644
--- a/flang/test/Semantics/OpenMP/atomic-compare.f90
+++ b/flang/test/Semantics/OpenMP/atomic-compare.f90
@@ -6,71 +6,73 @@
   ! higher openmp version than the others, so need a separate file.
   
 
-  real a, b
-  logical r
+  real a, b, c
   a = 1.0
   b = 2.0
+  c = 3.0
   !$omp parallel num_threads(4)
   ! First a few things that should compile without error.
   !$omp atomic seq_cst, compare
-  r = b .ne. a
+  if (b .eq. a) then
+     b = c
+  end if
 
   !$omp atomic seq_cst compare
-  r = a .ge. b
+  if (a .eq. b) a = c
   !$omp end atomic
 
   !$omp atomic compare acquire hint(OMP_LOCK_HINT_CONTENDED)
-  r = a .lt. b
+  if (b .eq. a) b = c
 
   !$omp atomic release hint(OMP_LOCK_HINT_UNCONTENDED) compare
-  r = a .gt. b
+  if (b .eq. a) b = c
 
   !$omp atomic compare seq_cst
-  r = b .ne. a
+  if (b .eq. c) b = a
 
   !$omp atomic hint(1) acq_rel compare
-  r = b .eq. a
+  if (b .eq. a) b = c
   !$omp end atomic
 
   ! Check for error conidtions:
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
   !$omp atomic seq_cst seq_cst compare
-  r = a .le. b
+  if (b .eq. c) b = a
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
   !$omp atomic compare seq_cst seq_cst
-  r = b .gt. a
+  if (b .eq. c) b = a
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
   !$omp atomic seq_cst compare seq_cst
-  r = b .ge. b
+  if (b .eq. c) b = a
 
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
   !$omp atomic acquire acquire compare
-  r = a .le. b
+  if (b .eq. c) b = a
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
   !$omp atomic compare acquire acquire
-  r = b .gt. a
+  if (b .eq. c) b = a
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
   !$omp atomic acquire compare acquire
-  r = b .ge. b
+  if (b .eq. c) b = a
 
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one RELAXED clause can appear on the COMPARE directive
   !$omp atomic relaxed relaxed compare
-  r = a .le. b
+  if (b .eq. c) b = a
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one RELAXED clause can appear on the COMPARE directive
   !$omp atomic compare relaxed relaxed
-  r = b .gt. a
+  if (b .eq. c) b = a
   !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
   !ERROR: At most one RELAXED clause can appear on the COMPARE directive
   !$omp atomic relaxed compare relaxed
-  r = b .ge. b
+  if (b .eq. c) b = a
 
   !$omp end parallel
 end

>From c55179169cca25968d7e4f4395b152a9a3ffca74 Mon Sep 17 00:00:00 2001
From: Mats Petersson <mats.petersson at arm.com>
Date: Thu, 28 Nov 2024 11:54:08 +0000
Subject: [PATCH 3/3] Use opnemp_flags to get directory location of omp_lib

---
 flang/test/Semantics/OpenMP/atomic-compare.f90 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/test/Semantics/OpenMP/atomic-compare.f90 b/flang/test/Semantics/OpenMP/atomic-compare.f90
index 0867950b080536..29ce60fa6ec1c9 100644
--- a/flang/test/Semantics/OpenMP/atomic-compare.f90
+++ b/flang/test/Semantics/OpenMP/atomic-compare.f90
@@ -1,4 +1,4 @@
-! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp-version=51 %openmp_flags
   use omp_lib
   implicit none
   ! Check atomic compare. This combines elements from multiple other "atomic*.f90", as



More information about the flang-commits mailing list