This is an archive of the discontinued LLVM Phabricator instance.

[flang] Limit shape inquiries rewrite to associate construct entity
ClosedPublic

Authored by jeanPerier on Sep 14 2022, 6:26 AM.

Details

Summary

The previous code was rewriting all shape inquires on associate
construct entities to inquires on the associated expression or variable.

This is is incorrect because at the point of inquiry, some statement
between the association and the inquiry may have modified the expression
operands or variable in a way that changes its shapes or bounds.

For instance, in the example below, expression rewrites was previously
replacing size(x, 1) by size(p, 1) which is invalid if p is a
pointer.

associate(x => p + 1)
 call call_that_may_modify_p_shape()
 print *, size(x, 1)
end associate

This change restricts rewrites of shape inquiries on associate construct entity
to use the associated expression shape and bounds if and only if the
shape/bounds are compile time constant. Otherwise, this may be invalid.

Diff Detail

Event Timeline

jeanPerier created this revision.Sep 14 2022, 6:26 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 14 2022, 6:26 AM
Herald added a subscriber: jdoerfert. · View Herald Transcript
jeanPerier requested review of this revision.Sep 14 2022, 6:26 AM
PeteSteinfeld requested changes to this revision.Sep 14 2022, 8:07 AM

The criterion you're using to figure out whether to rewrite the expression seems wrong to me. Rather than checking if the bounds are constant, I think that we should be checking to see if the right hand side of the ASSOCIATE clause is a variable. Here's a program that I believe will give the wrong result if we implement this change:

program test_associate
  real, dimension(:), allocatable :: ra

  allocate (ra(10))
  print *, 'size(ra): ', size(ra)
  associate (x => ra)
    print *, 'size(x): ', size(x)
    deallocate(ra)
    allocate(ra(20))
    print *, 'size(x): ', size(x)
  end associate
end program test_associate
I believe that, for a conforming compiler, the final `print` statement should print `size(x):  20`.  But with the changes you propose, we print `size(x):  10`.

Interestingly, the only compiler I can find that agrees with me is NAG.  Every other compiler I've tried prints `size(x):  10`.
This revision now requires changes to proceed.Sep 14 2022, 8:07 AM

Here's a program that I believe will give the wrong result if we implement this change:
I believe that, for a conforming compiler, the final print statement should print size(x): 20. But with the changes you propose, we print size(x): 10.
Interestingly, the only compiler I can find that agrees with me is NAG. Every other compiler I've tried prints size(x): 10.

I disagree here, I think the program you wrote is non-conforming since deallocate(ra) destroyed x storage (violates 9.7.3.2 point 1). If you do this test with a pointer (without deallocating the pointer, just setting a new target to the pointer), I believe this is conforming, and the expected result is 10 (this times, both NAG and all other compilers agree with this change).

That is because when the selector is an allocatable or pointer, the selector is associated with the current data object/target (and not the pointer/allocatable itself). See:

11.1.3.3 point 1: The associating entity does not have the ALLOCATABLE or POINTER attributes;

And:

19.5.1.6 point 2:
In an ASSOCIATE or SELECT TYPE construct, the following rules apply.
• If a selector is allocatable, it shall be allocated; the associate name is associated with the data object and does not have the ALLOCATABLE attribute.
• If a selector has the POINTER attribute, it shall be associated; the associate name is associated with the target of the pointer and does not have the POINTER attribute.

And:

9.7.3.2 point 1: An allocatable variable shall not be deallocated if it or any subobject of it is argument associated with a dummy argument or construct associated with an associate name.

The criterion you're using to figure out whether to rewrite the expression seems wrong to me. Rather than checking if the bounds are constant, I think that we should be checking to see if the right hand side of the ASSOCIATE clause is a variable.

I disagree here, based on the arguments above, both ASSOCIATE(X => P) and ASSOCIATE(X => P+1) with p a pointer or allocatable should not lead SIZE(X) to be resolved to SIZE(P) as it used to be. So the fact that the selector is a variable or an expression does not matter, and the shape and bounds of the associate name are "frozen" at the time of the association.

PeteSteinfeld accepted this revision.Sep 14 2022, 11:01 AM

Thanks, Jean.

I can't come up with a conforming example that breaks your implementation.

This revision is now accepted and ready to land.Sep 14 2022, 11:01 AM

Revert bad unrelated bad change in an if condition.