-
Notifications
You must be signed in to change notification settings - Fork 15k
[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
base: main
Are you sure you want to change the base?
Changes from all commits
632ed7b
97cbeed
9189ede
f572da2
91f9e67
f52136b
d60edf8
1e69803
94f69ed
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 |
|---|---|---|
|
|
@@ -1493,32 +1493,21 @@ class CopyInOutExplicitInterface { | |
| return !actualTreatAsContiguous && 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.) | ||
| bool dummyIsPolymorphic{dummyObj_.type.type().IsPolymorphic()}; | ||
| auto actualType{ | ||
| characteristics::TypeAndShape::Characterize(actual_, fc_)}; | ||
| bool actualIsPolymorphic{ | ||
| actualType && actualType->type().IsPolymorphic()}; | ||
| if (actualIsPolymorphic && !dummyIsPolymorphic) { | ||
| return true; | ||
| } | ||
| // 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; | ||
| } | ||
| auto actualType{characteristics::TypeAndShape::Characterize(actual_, fc_)}; | ||
| if (actualType && actualType->type().IsPolymorphic() && | ||
| !actualType->type().IsAssumedType() && | ||
| !dummyObj_.IsPassedByDescriptor(/*isBindC*/ false)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not get why passing by descriptor matters here. It is possible to have assumed shape arrays with the CONTIGUOUS attribute in which case a contiguous copy is still needed even if they are passed by descriptors. To me, there is a lot of complexity in trying to get an accurate answer at compile time, while outside of the IGNORE_TKR case, it is just fine to generate too much copy-in/copy-out instructions since there is a runtime contiguity check and the copy is not done when not needed. Outside of the IGNORE_TKR case, we could just always generate them for explicit shape dummy arguments and assumed-shape with CONTIGUOUS attribute and get valid code even in the cases where making a copy is invalid. I understand the idea of trying to detect as much as possible situations where you know an actual copy-in/copy-out will happen and to warn/error for cases with VOLATILE and al, but I think using the same logic in lowering comes at a risk of false negative where a copy-in/copy-out could be missed and it is unclear to me how good is our test coverage here, especially with polymorphic arguments (missing copy-in/copy-out code can easily go undetected if the actual happens to be contiguous). The problem I see with sharing the logic between lowering and semantics is that you now need to get both side of the answer prefect. Too much To avoid having to come code that accurately deals with every situation, I would suggest using a ternary logic. std::optional, where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 to the use of I would like us to try to have a single implementation here for both semantics and lowering, if one can be found; it would be hard to have two implementations and be assured that they were identical. It should be possible to write more tests that can verify that code that is warning-free at compilation time doesn't use copy-in at run-time (use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's why contiguity check is done first. Once contiguity is out of the picture, checking for descriptor differences between actual and dummy args seems to work nicely here. |
||
| // Not passing a descriptor, so will need to make a copy of the data | ||
| // with a proper type. | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
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.
An actual argument that is
class(parent)would require a temporary for atype(parent)dummy; type extension isn't necessary.An actual argument that has a monomorphic type that is an extension of a
type(t)dummy will require a temporary unless it actually has no additional components or TBP overrides relative tot.