[flang-commits] [flang] 1eb5cd0 - [flang] Add atomic_cas to the list of intrinsics

Katherine Rasmussen via flang-commits flang-commits at lists.llvm.org
Tue Oct 18 10:25:53 PDT 2022


Author: Katherine Rasmussen
Date: 2022-10-18T11:20:12-06:00
New Revision: 1eb5cd020c8782166c13a4d14b2a911e3d00de3d

URL: https://github.com/llvm/llvm-project/commit/1eb5cd020c8782166c13a4d14b2a911e3d00de3d
DIFF: https://github.com/llvm/llvm-project/commit/1eb5cd020c8782166c13a4d14b2a911e3d00de3d.diff

LOG: [flang] Add atomic_cas to the list of intrinsics

Add the atomic subroutine, atomic_cas, to the list of intrinsic
subroutines and check one of its arguments for a coindexed object.
Create a new function, CheckAtomicKind, that will be used for the
atomic subroutines that have arguments that can be either of type
int and of kind atomic_int_kind or of type logical and of kind
atomic_logical_kind.

Reviewed By: jeanPerier

Differential Revision: https://reviews.llvm.org/D135835

Added: 
    

Modified: 
    flang/lib/Evaluate/intrinsics.cpp
    flang/test/Semantics/atomic03.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 1d52e9b497109..7a5aaba7141c8 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -96,6 +96,7 @@ ENUM_CLASS(KindCode, none, defaultIntegerKind,
     nullPointerType, // for ASSOCIATED(NULL())
     exactKind, // a single explicit exactKindValue
     atomicIntKind, // atomic_int_kind from iso_fortran_env
+    sameAtom, // same type and kind as atom
 )
 
 struct TypePattern {
@@ -184,6 +185,8 @@ static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind};
 static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
 
 static constexpr TypePattern AtomicInt{IntType, KindCode::atomicIntKind};
+static constexpr TypePattern SameAtom{
+    IntType | LogicalType, KindCode::sameAtom};
 
 // The default rank pattern for dummy arguments and function results is
 // "elemental".
@@ -1097,6 +1100,18 @@ static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
 
 static const IntrinsicInterface intrinsicSubroutine[]{
     {"abort", {}, {}, Rank::elemental, IntrinsicClass::impureSubroutine},
+    {"atomic_cas",
+        {{"atom", SameAtom, Rank::atom, Optionality::required,
+             common::Intent::InOut},
+            {"old", SameAtom, Rank::scalar, Optionality::required,
+                common::Intent::Out},
+            {"compare", SameAtom, Rank::scalar, Optionality::required,
+                common::Intent::In},
+            {"new", SameAtom, Rank::scalar, Optionality::required,
+                common::Intent::In},
+            {"stat", AnyInt, Rank::scalar, Optionality::optional,
+                common::Intent::Out}},
+        {}, Rank::elemental, IntrinsicClass::atomicSubroutine},
     {"atomic_fetch_or",
         {{"atom", AtomicInt, Rank::atom, Optionality::required,
              common::Intent::InOut},
@@ -1329,6 +1344,31 @@ static bool CheckMaxMinArgument(std::optional<parser::CharBlock> keyword,
   return true;
 }
 
+static bool CheckAtomicKind(const ActualArgument &arg,
+    const semantics::Scope *builtinsScope,
+    parser::ContextualMessages &messages) {
+  std::string atomicKindStr;
+  std::optional<DynamicType> type{arg.GetType()};
+
+  if (type->category() == TypeCategory::Integer) {
+    atomicKindStr = "atomic_int_kind";
+  } else if (type->category() == TypeCategory::Logical) {
+    atomicKindStr = "atomic_logical_kind";
+  } else {
+    common::die("atomic_int_kind or atomic_logical_kind from iso_fortran_env "
+                "must be used with IntType or LogicalType");
+  }
+
+  bool argOk = type->kind() ==
+      GetBuiltinKind(builtinsScope, ("__builtin_" + atomicKindStr).c_str());
+  if (!argOk) {
+    messages.Say(arg.sourceLocation(),
+        "Actual argument for 'atom=' must have kind=atomic_int_kind or atomic_logical_kind, but is '%s'"_err_en_US,
+        type->AsFortran());
+  }
+  return argOk;
+}
+
 // Intrinsic interface matching against the arguments of a particular
 // procedure reference.
 std::optional<SpecificCall> IntrinsicInterface::Match(
@@ -1570,6 +1610,21 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
     case KindCode::exactKind:
       argOk = type->kind() == d.typePattern.exactKindValue;
       break;
+    case KindCode::sameAtom:
+      if (!sameArg) {
+        sameArg = arg;
+        argOk = CheckAtomicKind(DEREF(arg), builtinsScope, messages);
+      } else {
+        argOk = type->IsTkCompatibleWith(sameArg->GetType().value());
+        if (!argOk) {
+          messages.Say(arg->sourceLocation(),
+              "Actual argument for '%s=' must have same type and kind as 'atom=', but is '%s'"_err_en_US,
+              d.keyword, type->AsFortran());
+        }
+      }
+      if (!argOk)
+        return std::nullopt;
+      break;
     case KindCode::atomicIntKind:
       argOk = type->kind() ==
           GetBuiltinKind(builtinsScope, "__builtin_atomic_int_kind");
@@ -2555,6 +2610,8 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
     }
   } else if (name == "associated") {
     return CheckAssociated(call, context);
+  } else if (name == "atomic_cas") {
+    return CheckForCoindexedObject(context, call.arguments[4], name, "stat");
   } else if (name == "atomic_fetch_or") {
     return CheckForCoindexedObject(context, call.arguments[3], name, "stat");
   } else if (name == "co_broadcast" || name == "co_max" || name == "co_min" ||

diff  --git a/flang/test/Semantics/atomic03.f90 b/flang/test/Semantics/atomic03.f90
index 58cac5b6f8403..f01e11656c03c 100644
--- a/flang/test/Semantics/atomic03.f90
+++ b/flang/test/Semantics/atomic03.f90
@@ -1,5 +1,4 @@
 ! RUN: %python %S/test_errors.py %s %flang_fc1
-! XFAIL: *
 ! This test checks for semantic errors in atomic_cas subroutine calls based on
 ! the interface defined in section 16.9.22 of the Fortran 2018 standard.
 


        


More information about the flang-commits mailing list