User account creation filtered due to spam.

Bug 35339

Summary: Improve translation of implied do loop in transfer
Product: gcc Reporter: Jerry DeLisle <jvdelisle>
Component: fortranAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: gcc-bugs, tkoenig
Priority: P3 Keywords: missed-optimization
Version: 4.4.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2008-03-13 05:19:18
Bug Depends on:    
Bug Blocks: 25829    

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)


    _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; = (void *) &a[0];
      parm.4.offset = -1;
      _gfortran_transfer_array (&dt_parm.3, &parm.4, 4, 0);
    _gfortran_st_write_done (&dt_parm.3);


    _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);
              D.958 = i == 10;
              i = i + 1;
              if (D.958) goto 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!


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