This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch, fortran] Load scalar intent-in variables at the beginning of procedures


Hi Richard,

On 11/21/19 1:16 PM, Richard Biener wrote:
OK, so I found it, it's handled via SSA_NAME_POINTS_TO_READONLY_MEMORY which is initialized during the rewrite into SSA form from the information given by the "fn spec" attribute […] so when the frontend sets "fn spec" from the intent it should already work.

Which I can confirm for the following made-up example:

real function foo(n)
  implicit none (type)
  integer, intent(in) :: n
  integer :: i
  foo = 0.5
  if (n /= 0) return
  call bar()
  do i = 1, n
    foo = foo + sin(foo)
  end do
end

The optimized dump shows the following, i.e. GCC nicely optimizes both the loop and the 'sin' call away:

foo (integer(kind=4) & restrict n)
{
  integer(kind=4) _1;
  <bb 2> [local count: 241635843]:
  _1 = *n_9(D);
  if (_1 != 0)
    goto <bb 4>; [51.12%]
  else
    goto <bb 3>; [48.88%]

  <bb 3> [local count: 118111600]:
  bar ();

  <bb 4> [local count: 241635844]:
  return 5.0e-1;
}

I think this optimization permits some crucial optimizations.
I have not fully followed the later versions of the patch whether
they exploit some additional language semantics to permit optimizations
even without intent(in), but the initial discussion started with intent(in).

But the examples I saw above didn't use INTENT(IN) for the scalar parameters.

I concur that a well-written program should make use of intent(in) where sensible.

There are cases, which could be optimized likewise – but based on the case that the pointer address cannot escape instead of just assuming that the argument cannot change. – The question is how to convey this to the middle end.

I wonder whether there is a 'fn attr' which can tell that the first argument of 'print_i' does not cause the address of 'i' escape. If so, one could mark all procedure arguments such – unless they have the pointer, target or asynchronous attribute or are coarrays. [Probably needs some fine tuning.]

In this example, variable values do change, but only in a controlled way ('print_i' could change it, 'bar' cannot). The semantic is also mainly a property of the (local) variable (or dummy argument) declaration and not of the functions which are called – although, if 'i' has no target attribute, print_i's argument cannot have neither – hence, one could generated a function interface

real function foo(i, y)
  implicit none (type)
  integer :: i
  real :: y
  foo = 0.0
  call print_i(i)
  i = 5
  call bar()  ! < this prevents optimizing the sin(y) away
  if (i == 5) return
  foo = sin(y)
end

Fortran semantics implies that 'i' can only change after the 'i = 5' if: 'i' has the TARGET (or POINTER) attribute. Or it is possible if 'i' has the ASYNCHRONOUS or VOLATILE attribute – or it is a coarray (where a remote image can modify the local value).

For asynchronous, it would be something like "call read_i(i); call wait()" which is structurally the same as above.

TARGET: "An object without the TARGET attribute shall not have a pointer associated with it." VOLATILE: "may be referenced, defined, or become undefined, by means20not specified by the program" ASYNCHRONOUS: "An entity with the ASYNCHRONOUS attribute is a variable, and may be subject to asynchronous input/output or asynchronous communication."

Tobias


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]