From eb69458d5a5eb082e6a22a73dcfbe666f287ae43 Mon Sep 17 00:00:00 2001 From: s-watanabe314 Date: Fri, 8 Nov 2024 10:44:55 +0900 Subject: [PATCH 1/2] [flang] Add FIR attributes and apply them to dummy arguments To determine if a function's dummy argument is nocapture, add the asynchronous attribute to the FIR attribute. The volatile attribute will also be used to determine nocapture assignment, but this will remain a TODO until other processing using volatile is implemented. --- flang/include/flang/Optimizer/Dialect/FIROpsSupport.h | 10 ++++++++++ flang/lib/Lower/CallInterface.cpp | 6 +++++- flang/test/Lower/HLFIR/select-rank.f90 | 2 +- flang/test/Lower/attributes.f90 | 8 ++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h index fb7b1d16f62f3..f7f0a3067b318 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h +++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h @@ -75,6 +75,16 @@ constexpr llvm::StringRef getOptionalAttrName() { return "fir.optional"; } /// Attribute to mark Fortran entities with the TARGET attribute. static constexpr llvm::StringRef getTargetAttrName() { return "fir.target"; } +/// Attribute to mark Fortran entities with the ASYNCHRONOUS attribute. +static constexpr llvm::StringRef getAsynchronousAttrName() { + return "fir.asynchronous"; +} + +/// Attribute to mark Fortran entities with the VOLATILE attribute. +static constexpr llvm::StringRef getVolatileAttrName() { + return "fir.volatile"; +} + /// Attribute to mark that a function argument is a character dummy procedure. /// Character dummy procedure have special ABI constraints. static constexpr llvm::StringRef getCharacterProcedureDummyAttrName() { diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 7fc6b14f9c660..1f07be4a5d3e3 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -1116,8 +1116,12 @@ class Fortran::lower::CallInterfaceImpl { addMLIRAttr(fir::getContiguousAttrName()); if (obj.attrs.test(Attrs::Value)) isValueAttr = true; // TODO: do we want an mlir::Attribute as well? - if (obj.attrs.test(Attrs::Volatile)) + if (obj.attrs.test(Attrs::Volatile)) { TODO(loc, "VOLATILE in procedure interface"); + addMLIRAttr(fir::getVolatileAttrName()); + } + if (obj.attrs.test(Attrs::Asynchronous)) + addMLIRAttr(fir::getAsynchronousAttrName()); if (obj.attrs.test(Attrs::Target)) addMLIRAttr(fir::getTargetAttrName()); if (obj.cudaDataAttr) diff --git a/flang/test/Lower/HLFIR/select-rank.f90 b/flang/test/Lower/HLFIR/select-rank.f90 index 7135c248ea44d..175c6688e89f3 100644 --- a/flang/test/Lower/HLFIR/select-rank.f90 +++ b/flang/test/Lower/HLFIR/select-rank.f90 @@ -416,7 +416,7 @@ subroutine test_branching(x) ! CHECK: } ! CHECK-LABEL: func.func @_QPtest_rank_star_attributes( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x", fir.optional, fir.target}) { +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.asynchronous, fir.bindc_name = "x", fir.optional, fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_rank_star_attributesEx"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i8 diff --git a/flang/test/Lower/attributes.f90 b/flang/test/Lower/attributes.f90 index 16e42ab282dae..413024d0a4499 100644 --- a/flang/test/Lower/attributes.f90 +++ b/flang/test/Lower/attributes.f90 @@ -27,3 +27,11 @@ subroutine foo2(x, i) subroutine foo3(x) real, optional, contiguous :: x(:) end subroutine + +! CHECK-LABEL: func @_QPfoo4 +! CHECK-SAME: %arg0: !fir.ref {fir.bindc_name = "x", fir.target} +! CHECK-SAME: %arg1: !fir.ref {fir.asynchronous, fir.bindc_name = "y"} +subroutine foo4(x, y) + real, target :: x + real, asynchronous :: y +end subroutine From 2e8dadf226a21e755b72b97f3eebc80050afe773 Mon Sep 17 00:00:00 2001 From: s-watanabe314 Date: Tue, 12 Nov 2024 10:23:21 +0900 Subject: [PATCH 2/2] fixup! [flang] Add FIR attributes and apply them to dummy arguments --- flang/lib/Lower/CallInterface.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 1f07be4a5d3e3..e20b90b2ff1bc 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -1107,11 +1107,6 @@ class Fortran::lower::CallInterfaceImpl { }; if (obj.attrs.test(Attrs::Optional)) addMLIRAttr(fir::getOptionalAttrName()); - // Skipping obj.attrs.test(Attrs::Asynchronous), this does not impact the - // way the argument is passed given flang implement asynch IO synchronously. - // TODO: it would be safer to treat them as volatile because since Fortran - // 2018 asynchronous can also be used for C defined asynchronous user - // processes (see 18.10.4 Asynchronous communication). if (obj.attrs.test(Attrs::Contiguous)) addMLIRAttr(fir::getContiguousAttrName()); if (obj.attrs.test(Attrs::Value)) @@ -1120,6 +1115,12 @@ class Fortran::lower::CallInterfaceImpl { TODO(loc, "VOLATILE in procedure interface"); addMLIRAttr(fir::getVolatileAttrName()); } + // obj.attrs.test(Attrs::Asynchronous) does not impact the way the argument + // is passed given flang implement asynch IO synchronously. However, it's + // added to determine whether the argument is captured. + // TODO: it would be safer to treat them as volatile because since Fortran + // 2018 asynchronous can also be used for C defined asynchronous user + // processes (see 18.10.4 Asynchronous communication). if (obj.attrs.test(Attrs::Asynchronous)) addMLIRAttr(fir::getAsynchronousAttrName()); if (obj.attrs.test(Attrs::Target))