Bug 35339 - Improve translation of implied do loop in transfer
Summary: Improve translation of implied do loop in transfer
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks: 25829
  Show dependency treegraph
 
Reported: 2008-02-24 01:41 UTC by Jerry DeLisle
Modified: 2013-08-31 18:27 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-03-13 05:19:18


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jerry DeLisle 2008-02-24 01:41:05 UTC
Currently we create a looping structure which is executed to traverse an array and transfer it one element at a time.  This works, but is not too efficient.  We could improve this by converting the implied do loops into the appropriate array descriptor and call transfer_array.

The two cases are:

real, dimension(10) :: a
write(10,'(10f8.3)') a
write(10,'(10f8.3)') (a(i), i=1,10)

Gives:

    _gfortran_st_write (&dt_parm.3);
    {
      struct array1_real(kind=4) parm.4;

      parm.4.dtype = 281;
      parm.4.dim[0].lbound = 1;
      parm.4.dim[0].ubound = 10;
      parm.4.dim[0].stride = 1;
      parm.4.data = (void *) &a[0];
      parm.4.offset = -1;
      _gfortran_transfer_array (&dt_parm.3, &parm.4, 4, 0);
    }
    _gfortran_st_write_done (&dt_parm.3);

and

    _gfortran_st_write (&dt_parm.3);
    i = 1;
    if (i <= 10)
      {
        while (1)
          {
            {
              logical(kind=4) D.958;

              _gfortran_transfer_real (&dt_parm.3, &a[(integer(kind=8)) i + -1], 4);
              L.2:;
              D.958 = i == 10;
              i = i + 1;
              if (D.958) goto L.3;
            }
          }
      }
    L.3:;
    _gfortran_st_write_done (&dt_parm.3);

The former is needed to simplify asynchronous I/O where we need to be able to convey to the I/O thread the task to be done and not the actual code to do the looping.

Putting it another way, if the implied loop has 10000 count.  We need to pass that count to the I/O routines, so they can take it and run with it.
Comment 1 Francois-Xavier Coudert 2008-02-25 10:00:53 UTC
(In reply to comment #0)
> real, dimension(10) :: a
> write(10,'(10f8.3)') a
> write(10,'(10f8.3)') (a(i), i=1,10)

The problem is, this isn't possible in the most generic case:

  write(10,'(10f8.3)') (a(i**-2*i+13), i=1,10)
Comment 2 Jerry DeLisle 2008-03-01 16:22:56 UTC
OK, I see your point.  Would it be possible to create a hidden iterator function that could be called internally by the I/O library to return the index into the array?

In the meantime, I am thinking through a different approach for aio that avoids the issue here.

Comment 3 Paul Thomas 2008-03-02 07:59:58 UTC
> In the meantime, I am thinking through a different approach for aio that avoids
> the issue here.
> 

Yes it would - use gfc_conv_expr_descriptor to convert the expression and pass the resulting array descriptor.  For the cases that you are concerned with, this would be a temporary.  However, gfortran_transfer array would be used and the io itself taken out of the loop. Obviously, this would only work for a WRITE operation and gfc_conv_subref_array_arg would have to be used for a READ - as in the existing code in gfc_trans_transfer.

In fact, I believe that the exsting code in gfc_trans_transfer would be able to handle iterator expressions, were they passed to it.  However, the frontend does this scalarization; see io.c(match_io_element):2396 onwards. This builds up a DO loop and a call to EXEC_TRANSFER for each element.  Where there is only one element, you will get what you want by turning the iterator expression into an EXPR_ARRAY and writing the gfc_code to pass that to EXEC_TRANSFER.  I think that it should be a very straightforward job.

Best of luck!

Paul




Comment 4 Jerry DeLisle 2008-03-13 05:19:18 UTC
I have a method figured out for async I/O that will handle things as they are now, However, it would greatly improve the situation if we fix this implied do loop business.
Comment 5 Thomas Koenig 2013-08-31 18:27:22 UTC
Depending how much ground we want to cover, this
can be tricky.

Off my head, I can think of the following examples:

(a(i), i=1,10) --> a(1:10)
(a(i), i=1,10,2) --> a(1:10:2)
(a(2*i), i=1,10) --> a(2:20:2)
((a(i,j), i=1,10), j=1,2) --> a(1:10,1:20)
((a(i,j), j=1,2), i=1,10) --> no equivalent
((a(i,j), j=1,2) --> a(i,1:2)
(a(i,2*i), i=1,10) --> no equivalent
(a(i**2), i=1,10) --> no equivalent