[flang-commits] [flang] [flang] Create temporaries for array sections passed to IGNORE_TKR dummy args (PR #147419)
Eugene Epshteyn via flang-commits
flang-commits at lists.llvm.org
Wed Jul 9 10:51:43 PDT 2025
https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/147419
>From 2477076ba81ec61e8bbff36fb624e8bb76c27380 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Fri, 4 Jul 2025 16:26:17 -0400
Subject: [PATCH 1/7] [flang] Contiguity check on IGNORE_TKR argument
If argument is marked as IGNORE_TKR, enable contiguity check on it,
unless IGNORE_TKR explicitly specifies to ignore contiguity.
---
flang/lib/Lower/CallInterface.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 72431a9cfacc4..abe43dc9cb2b7 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -1426,6 +1426,13 @@ bool Fortran::lower::CallInterface<T>::PassedEntity::mustBeMadeContiguous()
&characteristics->u);
if (!dummy)
return false;
+ if (dummy->ignoreTKR.test(common::IgnoreTKR::Contiguous))
+ return false;
+
+ // TODO: should this check ignore "device" or "managed"?
+ if (dummy->ignoreTKR.any())
+ return true;
+
const auto &shapeAttrs = dummy->type.attrs();
using ShapeAttrs = Fortran::evaluate::characteristics::TypeAndShape::Attr;
if (shapeAttrs.test(ShapeAttrs::AssumedRank) ||
>From 50dd216ff0487709d52944006e35e6102015cef0 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 7 Jul 2025 10:20:38 -0400
Subject: [PATCH 2/7] [flang] Add -pedantic check for passing non-VOLATILE
array section to VOLATILE dummy arg
Add the check, which partially addresses https://github.com/llvm/llvm-project/issues/137369
Implement HasTriplet().
---
flang/include/flang/Evaluate/tools.h | 3 +++
flang/lib/Evaluate/tools.cpp | 19 +++++++++++++++++++
flang/lib/Semantics/definable.cpp | 3 +++
3 files changed, 25 insertions(+)
diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index cad1b634f8924..0604049fd6a6d 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1123,6 +1123,9 @@ extern template semantics::UnorderedSymbolSet CollectCudaSymbols(
// Predicate: does a variable contain a vector-valued subscript (not a triplet)?
bool HasVectorSubscript(const Expr<SomeType> &);
+// Predicate: does a variable contain a triplet?
+bool HasTriplet(const Expr<SomeType> &);
+
// Predicate: does an expression contain constant?
bool HasConstant(const Expr<SomeType> &);
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index fcacdb93d662b..50a201dfcaced 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1173,6 +1173,25 @@ bool HasVectorSubscript(const Expr<SomeType> &expr) {
return HasVectorSubscriptHelper{}(expr);
}
+// HasTriplet()
+struct HasTripletHelper
+ : public AnyTraverse<HasTripletHelper, bool,
+ /*TraverseAssocEntityDetails=*/false> {
+ using Base = AnyTraverse<HasTripletHelper, bool, false>;
+ HasTripletHelper() : Base{*this} {}
+ using Base::operator();
+ bool operator()(const Subscript &ss) const {
+ return std::holds_alternative<Triplet>(ss.u);
+ }
+ bool operator()(const ProcedureRef &) const {
+ return false; // don't descend into function call arguments
+ }
+};
+
+bool HasTriplet(const Expr<SomeType> &expr) {
+ return HasTripletHelper{}(expr);
+}
+
// HasConstant()
struct HasConstantHelper : public AnyTraverse<HasConstantHelper, bool,
/*TraverseAssocEntityDetails=*/false> {
diff --git a/flang/lib/Semantics/definable.cpp b/flang/lib/Semantics/definable.cpp
index 08cb268b318ae..b2d2330887a53 100644
--- a/flang/lib/Semantics/definable.cpp
+++ b/flang/lib/Semantics/definable.cpp
@@ -371,6 +371,9 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
return parser::Message{at,
"Variable '%s' has a vector subscript"_err_en_US, expr.AsFortran()};
}
+ } else if (evaluate::HasTriplet(expr)) {
+ return parser::Message{at,
+ "Variable '%s' has array section"_err_en_US, expr.AsFortran()};
}
if (FindPureProcedureContaining(scope) &&
evaluate::ExtractCoarrayRef(expr)) {
>From 28cb65fbc9ee572dfffac698f0853e3bf5932871 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 7 Jul 2025 13:29:46 -0400
Subject: [PATCH 3/7] Undid change to definable.cpp
---
flang/lib/Semantics/definable.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/flang/lib/Semantics/definable.cpp b/flang/lib/Semantics/definable.cpp
index b2d2330887a53..08cb268b318ae 100644
--- a/flang/lib/Semantics/definable.cpp
+++ b/flang/lib/Semantics/definable.cpp
@@ -371,9 +371,6 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
return parser::Message{at,
"Variable '%s' has a vector subscript"_err_en_US, expr.AsFortran()};
}
- } else if (evaluate::HasTriplet(expr)) {
- return parser::Message{at,
- "Variable '%s' has array section"_err_en_US, expr.AsFortran()};
}
if (FindPureProcedureContaining(scope) &&
evaluate::ExtractCoarrayRef(expr)) {
>From a176d2d1a6aab8c3cc3c4ceba907462970d86565 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 7 Jul 2025 16:19:47 -0400
Subject: [PATCH 4/7] The current implementation seems to work, but I will
likely move some code around
---
flang/include/flang/Lower/CallInterface.h | 2 +-
flang/lib/Lower/CallInterface.cpp | 5 +++--
flang/lib/Lower/ConvertCall.cpp | 9 ++++++++-
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/flang/include/flang/Lower/CallInterface.h b/flang/include/flang/Lower/CallInterface.h
index 72bc9dd890a94..f2c8db47c60b1 100644
--- a/flang/include/flang/Lower/CallInterface.h
+++ b/flang/include/flang/Lower/CallInterface.h
@@ -170,7 +170,7 @@ class CallInterface {
/// Is the argument INTENT(OUT)
bool isIntentOut() const;
/// Does the argument have the CONTIGUOUS attribute or have explicit shape?
- bool mustBeMadeContiguous() const;
+ bool mustBeMadeContiguous(const bool argHasTriplet = false) const;
/// Does the dummy argument have the VALUE attribute?
bool hasValueAttribute() const;
/// Does the dummy argument have the ALLOCATABLE attribute?
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index abe43dc9cb2b7..2ffdd985e4f72 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -1416,8 +1416,9 @@ bool Fortran::lower::CallInterface<T>::PassedEntity::isIntentOut() const {
return true;
return characteristics->GetIntent() == Fortran::common::Intent::Out;
}
+
template <typename T>
-bool Fortran::lower::CallInterface<T>::PassedEntity::mustBeMadeContiguous()
+bool Fortran::lower::CallInterface<T>::PassedEntity::mustBeMadeContiguous(const bool argHasTriplet)
const {
if (!characteristics)
return true;
@@ -1430,7 +1431,7 @@ bool Fortran::lower::CallInterface<T>::PassedEntity::mustBeMadeContiguous()
return false;
// TODO: should this check ignore "device" or "managed"?
- if (dummy->ignoreTKR.any())
+ if (dummy->ignoreTKR.any() && argHasTriplet)
return true;
const auto &shapeAttrs = dummy->type.attrs();
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 6ed15df0de754..91e54b15fb869 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1255,11 +1255,18 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
passingPolymorphicToNonPolymorphic &&
(actual.isArray() || mlir::isa<fir::BaseBoxType>(dummyType));
+ // Helper function to make it easier to unwrap and use expression
+ auto argHasTriplet = [](const Fortran::evaluate::ActualArgument &arg) -> bool {
+ if (const auto *expr = arg.UnwrapExpr())
+ return HasTriplet(*expr);
+ return false;
+ };
+
// The simple contiguity of the actual is "lost" when passing a polymorphic
// to a non polymorphic entity because the dummy dynamic type matters for
// the contiguity.
const bool mustDoCopyInOut =
- actual.isArray() && arg.mustBeMadeContiguous() &&
+ actual.isArray() && arg.mustBeMadeContiguous(argHasTriplet(*arg.entity)) &&
(passingPolymorphicToNonPolymorphic ||
!isSimplyContiguous(*arg.entity, foldingContext));
>From 96daba4399d66cd16667592cae4e0aff5e332f63 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 7 Jul 2025 18:55:10 -0400
Subject: [PATCH 5/7] clang-format
---
flang/lib/Evaluate/tools.cpp | 9 +++------
flang/lib/Lower/CallInterface.cpp | 4 ++--
flang/lib/Lower/ConvertCall.cpp | 6 ++++--
3 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 50a201dfcaced..1c43e475905d2 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1174,9 +1174,8 @@ bool HasVectorSubscript(const Expr<SomeType> &expr) {
}
// HasTriplet()
-struct HasTripletHelper
- : public AnyTraverse<HasTripletHelper, bool,
- /*TraverseAssocEntityDetails=*/false> {
+struct HasTripletHelper : public AnyTraverse<HasTripletHelper, bool,
+ /*TraverseAssocEntityDetails=*/false> {
using Base = AnyTraverse<HasTripletHelper, bool, false>;
HasTripletHelper() : Base{*this} {}
using Base::operator();
@@ -1188,9 +1187,7 @@ struct HasTripletHelper
}
};
-bool HasTriplet(const Expr<SomeType> &expr) {
- return HasTripletHelper{}(expr);
-}
+bool HasTriplet(const Expr<SomeType> &expr) { return HasTripletHelper{}(expr); }
// HasConstant()
struct HasConstantHelper : public AnyTraverse<HasConstantHelper, bool,
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 2ffdd985e4f72..26bb1acfeea1b 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -1418,8 +1418,8 @@ bool Fortran::lower::CallInterface<T>::PassedEntity::isIntentOut() const {
}
template <typename T>
-bool Fortran::lower::CallInterface<T>::PassedEntity::mustBeMadeContiguous(const bool argHasTriplet)
- const {
+bool Fortran::lower::CallInterface<T>::PassedEntity::mustBeMadeContiguous(
+ const bool argHasTriplet) const {
if (!characteristics)
return true;
const auto *dummy =
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 91e54b15fb869..0da869adc5efa 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1256,7 +1256,8 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
(actual.isArray() || mlir::isa<fir::BaseBoxType>(dummyType));
// Helper function to make it easier to unwrap and use expression
- auto argHasTriplet = [](const Fortran::evaluate::ActualArgument &arg) -> bool {
+ auto argHasTriplet =
+ [](const Fortran::evaluate::ActualArgument &arg) -> bool {
if (const auto *expr = arg.UnwrapExpr())
return HasTriplet(*expr);
return false;
@@ -1266,7 +1267,8 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
// to a non polymorphic entity because the dummy dynamic type matters for
// the contiguity.
const bool mustDoCopyInOut =
- actual.isArray() && arg.mustBeMadeContiguous(argHasTriplet(*arg.entity)) &&
+ actual.isArray() &&
+ arg.mustBeMadeContiguous(argHasTriplet(*arg.entity)) &&
(passingPolymorphicToNonPolymorphic ||
!isSimplyContiguous(*arg.entity, foldingContext));
>From aace0c2a95b6d8af56deb8f20f0aae92d64f3c36 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 7 Jul 2025 19:19:01 -0400
Subject: [PATCH 6/7] Some reformatting and comments
---
flang/lib/Lower/CallInterface.cpp | 2 ++
flang/lib/Lower/ConvertCall.cpp | 8 ++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 26bb1acfeea1b..80f8eb969797a 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -1417,6 +1417,8 @@ bool Fortran::lower::CallInterface<T>::PassedEntity::isIntentOut() const {
return characteristics->GetIntent() == Fortran::common::Intent::Out;
}
+/// Returning "true" from this function is a prerequisite for running
+/// contiguity check on the actual argument.
template <typename T>
bool Fortran::lower::CallInterface<T>::PassedEntity::mustBeMadeContiguous(
const bool argHasTriplet) const {
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 0da869adc5efa..34f35e4fd4fb4 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1256,19 +1256,19 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
(actual.isArray() || mlir::isa<fir::BaseBoxType>(dummyType));
// Helper function to make it easier to unwrap and use expression
- auto argHasTriplet =
- [](const Fortran::evaluate::ActualArgument &arg) -> bool {
+ auto argHasTriplet = [](const Fortran::evaluate::ActualArgument &arg) -> bool {
if (const auto *expr = arg.UnwrapExpr())
return HasTriplet(*expr);
return false;
};
+ const bool actualHasTriplet = argHasTriplet(*arg.entity);
+
// The simple contiguity of the actual is "lost" when passing a polymorphic
// to a non polymorphic entity because the dummy dynamic type matters for
// the contiguity.
const bool mustDoCopyInOut =
- actual.isArray() &&
- arg.mustBeMadeContiguous(argHasTriplet(*arg.entity)) &&
+ actual.isArray() && arg.mustBeMadeContiguous(actualHasTriplet) &&
(passingPolymorphicToNonPolymorphic ||
!isSimplyContiguous(*arg.entity, foldingContext));
>From 5fdfb455a4618a2bfb3b219dd51acab3da791d13 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 7 Jul 2025 19:20:01 -0400
Subject: [PATCH 7/7] clang-format
---
flang/lib/Lower/ConvertCall.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 34f35e4fd4fb4..4d7d142c6b49d 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1256,7 +1256,8 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
(actual.isArray() || mlir::isa<fir::BaseBoxType>(dummyType));
// Helper function to make it easier to unwrap and use expression
- auto argHasTriplet = [](const Fortran::evaluate::ActualArgument &arg) -> bool {
+ auto argHasTriplet =
+ [](const Fortran::evaluate::ActualArgument &arg) -> bool {
if (const auto *expr = arg.UnwrapExpr())
return HasTriplet(*expr);
return false;
More information about the flang-commits
mailing list