-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[flang] Fixed regression in copy-in/copy-out #161259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 25 commits
632ed7b
97cbeed
9189ede
f572da2
91f9e67
f52136b
d60edf8
1e69803
94f69ed
42382e0
5eff815
68bab54
413718c
329445c
ad080f1
8792ba4
8fd9427
4371a28
23393fe
1c202be
3423413
80b2ccb
2cef85a
d93b7e2
2abf0cb
57d67d7
e85c4e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1478,13 +1478,12 @@ class CopyInOutExplicitInterface { | |
| const characteristics::DummyDataObject &dummyObj) | ||
| : fc_{fc}, actual_{actual}, dummyObj_{dummyObj} {} | ||
|
|
||
| // Returns true, if actual and dummy have different contiguity requirements | ||
| bool HaveContiguityDifferences() const { | ||
| // Check actual contiguity, unless dummy doesn't care | ||
| // Returns true if dummy arg needs to be contiguous | ||
| bool DummyNeedsContiguity() const { | ||
| if (dummyObj_.ignoreTKR.test(common::IgnoreTKR::Contiguous)) { | ||
| return false; | ||
| } | ||
| bool dummyTreatAsArray{dummyObj_.ignoreTKR.test(common::IgnoreTKR::Rank)}; | ||
| bool actualTreatAsContiguous{ | ||
| dummyObj_.ignoreTKR.test(common::IgnoreTKR::Contiguous) || | ||
| IsSimplyContiguous(actual_, fc_)}; | ||
| bool dummyIsExplicitShape{dummyObj_.type.IsExplicitShape()}; | ||
| bool dummyIsAssumedSize{dummyObj_.type.attrs().test( | ||
| characteristics::TypeAndShape::Attr::AssumedSize)}; | ||
|
|
@@ -1501,32 +1500,17 @@ class CopyInOutExplicitInterface { | |
| (dummyTreatAsArray && !dummyIsPolymorphic) || dummyIsVoidStar || | ||
| dummyObj_.attrs.test( | ||
| characteristics::DummyDataObject::Attr::Contiguous)}; | ||
| return !actualTreatAsContiguous && dummyNeedsContiguity; | ||
| return dummyNeedsContiguity; | ||
| } | ||
|
|
||
| // Returns true, if actual and dummy have polymorphic differences | ||
| bool HavePolymorphicDifferences() const { | ||
| bool dummyIsAssumedRank{dummyObj_.type.attrs().test( | ||
| characteristics::TypeAndShape::Attr::AssumedRank)}; | ||
| bool actualIsAssumedRank{semantics::IsAssumedRank(actual_)}; | ||
| bool dummyIsAssumedShape{dummyObj_.type.attrs().test( | ||
| characteristics::TypeAndShape::Attr::AssumedShape)}; | ||
| bool actualIsAssumedShape{semantics::IsAssumedShape(actual_)}; | ||
| if ((actualIsAssumedRank && dummyIsAssumedRank) || | ||
| (actualIsAssumedShape && dummyIsAssumedShape)) { | ||
| // Assumed-rank and assumed-shape arrays are represented by descriptors, | ||
| // so don't need to do polymorphic check. | ||
| } else if (!dummyObj_.ignoreTKR.test(common::IgnoreTKR::Type)) { | ||
| // flang supports limited cases of passing polymorphic to non-polimorphic. | ||
| // These cases require temporary of non-polymorphic type. (For example, | ||
| // the actual argument could be polymorphic array of child type, | ||
| // while the dummy argument could be non-polymorphic array of parent | ||
| // type.) | ||
| if (dummyObj_.ignoreTKR.test(common::IgnoreTKR::Type)) { | ||
| return false; | ||
| } | ||
| if (auto actualType{ | ||
| characteristics::TypeAndShape::Characterize(actual_, fc_)}) { | ||
| bool actualIsPolymorphic{actualType->type().IsPolymorphic()}; | ||
| bool dummyIsPolymorphic{dummyObj_.type.type().IsPolymorphic()}; | ||
| auto actualType{ | ||
| characteristics::TypeAndShape::Characterize(actual_, fc_)}; | ||
| bool actualIsPolymorphic{ | ||
| actualType && actualType->type().IsPolymorphic()}; | ||
| if (actualIsPolymorphic && !dummyIsPolymorphic) { | ||
| return true; | ||
| } | ||
|
|
@@ -1575,28 +1559,33 @@ class CopyInOutExplicitInterface { | |
| // procedures with explicit interface, it's expected that "dummy" is not null. | ||
| // For procedures with implicit interface dummy may be null. | ||
| // | ||
| // Returns std::optional<bool> indicating whether the copy is known to be | ||
| // needed (true) or not needed (false); returns std::nullopt if the necessity | ||
| // of the copy is undetermined. | ||
| // | ||
| // Note that these copy-in and copy-out checks are done from the caller's | ||
| // perspective, meaning that for copy-in the caller need to do the copy | ||
| // before calling the callee. Similarly, for copy-out the caller is expected | ||
| // to do the copy after the callee returns. | ||
| bool MayNeedCopy(const ActualArgument *actual, | ||
| std::optional<bool> ActualArgNeedsCopy(const ActualArgument *actual, | ||
| const characteristics::DummyArgument *dummy, FoldingContext &fc, | ||
| bool forCopyOut) { | ||
| constexpr auto unknown = std::nullopt; | ||
| if (!actual) { | ||
| return false; | ||
| return unknown; | ||
| } | ||
| if (actual->isAlternateReturn()) { | ||
| return false; | ||
| return unknown; | ||
| } | ||
| const auto *dummyObj{dummy | ||
| ? std::get_if<characteristics::DummyDataObject>(&dummy->u) | ||
| : nullptr}; | ||
| const bool forCopyIn = !forCopyOut; | ||
|
||
| if (!evaluate::IsVariable(*actual)) { | ||
| // Actual argument expressions that aren’t variables are copy-in, but | ||
| // not copy-out. | ||
| // Expressions are copy-in, but not copy-out. | ||
| return forCopyIn; | ||
| } | ||
| auto maybeContigActual{IsContiguous(*actual, fc)}; | ||
| if (dummyObj) { // Explict interface | ||
| CopyInOutExplicitInterface check{fc, *actual, *dummyObj}; | ||
| if (forCopyOut && check.HasIntentIn()) { | ||
|
|
@@ -1619,28 +1608,25 @@ bool MayNeedCopy(const ActualArgument *actual, | |
| if (!check.HaveArrayOrAssumedRankArgs()) { | ||
| return false; | ||
| } | ||
| if (check.HaveContiguityDifferences()) { | ||
| return true; | ||
| } | ||
| if (check.HavePolymorphicDifferences()) { | ||
| return true; | ||
| if (maybeContigActual) { | ||
|
||
| // We know whether actual arg is contiguous or not | ||
| bool isContiguousActual{maybeContigActual.value()}; | ||
| bool actualArgNeedsCopy{ | ||
| (!isContiguousActual || check.HavePolymorphicDifferences()) && | ||
| check.DummyNeedsContiguity()}; | ||
| return actualArgNeedsCopy; | ||
| } else { | ||
| // We don't know whether actual arg is contiguous or not | ||
| return check.DummyNeedsContiguity(); | ||
| } | ||
| } else { // Implicit interface | ||
| if (ExtractCoarrayRef(*actual)) { | ||
| // Coindexed actual args may need copy-in and copy-out with implicit | ||
| // interface | ||
| return true; | ||
| } | ||
| if (!IsSimplyContiguous(*actual, fc)) { | ||
| // Copy-in: actual arguments that are variables are copy-in when | ||
| // non-contiguous. | ||
| // Copy-out: vector subscripts could refer to duplicate elements, can't | ||
| // copy out. | ||
| return !(forCopyOut && HasVectorSubscript(*actual)); | ||
| if (maybeContigActual) { | ||
| // If known contiguous, don't copy in/out. | ||
| // If known non-contiguous, copy in/out. | ||
| return !(maybeContigActual.value()); | ||
|
||
| } | ||
| } | ||
| // For everything else, no copy-in or copy-out | ||
| return false; | ||
| return unknown; | ||
| } | ||
|
|
||
| } // namespace Fortran::evaluate | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe this would increase readability if it were visible to clients, but it doesn't improve anything in the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It helped me to think about the implementation. I can remove it now.