This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran 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: Question WRT gfortran.dg/allocatable_function_1.f90


On Sat, Nov 25, 2006 at 06:25:13PM +0200, erik.edelmann@iki.fi wrote:
> On Sat, Nov 25, 2006 at 01:50:01AM +0100, Tobias Schl?ter wrote:
> > I'm trying to get the testsuite to work with -fbounds-check, and I ran
> > into a problem with gfortran.dg/allocatable_function_1.f90.  It
> > produces 9 calls to gfortran_internal_free without bounds checking,
> > which is what the testcase expects.  OTOH with bounds checking enabled
> > it produces 10 calls, and the 10th call looks fairly unsensible.
> > 
> > Can either of you two look into this?  I presume that the different
> > block structure confuses the bookkeeping in some way.
> 
> I can take a look at it during the weekend.

I haven't solved the mystery yet, but found some interesting things. Here's
a reduced testcase:

--------------------------
program alloc_fun

    implicit none
    integer :: a(3)

! 2 _gfortran_internal_free's
    a(1:size (bar (3))) = 2*bar(size(a)) + 2 + a(size (bar (3)))

contains

    function bar (n) result(b)
        integer, intent(in) :: n
        integer, target, allocatable :: b(:)

        allocate (b(n))
        b = 5
    end function bar

end program alloc_fun
--------------------------

According to the comment, gfortran should generate 2 calls to
_gfortran_internal_free for the line 

        a(1:size (bar (3))) = 2*bar(size(a)) + 2 + a(size (bar (3)))

and thats what gfortran does without -fbounds-check.  With -fbounds-check, 3
calls are generated, and that perfectly fine because there are three
calls to bar(), each with it's own temporary result variable.

The interesting question here is, why only 2 without -fbounds-check? It
turns out that, without -fbounds-check, bar() is called only twice for that
line of code; the result of the first call is used both for the LHS and the
first term in the RHS, and the result of second call is used in the last
term in the RHS.

As a small experiment, I tried this little testprogram:
---------------------------
program alloc_fun

    implicit none
    integer :: a(3)

! 2 _gfortran_internal_free's
    a(1:size (bar (3))) = 2*beer(size(a)-2) + 2 + a(size (bar (3)))

contains

    function bar (n) result(b)
        integer, intent(in) :: n
        integer, target, allocatable :: b(:)

        allocate (b(n))
        b = 5
    end function bar

    function beer (n) result(b)
        integer, intent(in) :: n
        integer, target, allocatable :: b(:)

        allocate (b(n+2))
        b = 5
    end function beer

end program alloc_fun
------------------------------

This produces one call to bar() and one to beer() (sorry about the name --
I just couldn't resist :-).  It turns out that the result from beer() is
used in the LHS, which happens to work here. The question is of course if
it works just because of luck, or because of gfortran being smart.

Wild guess: without -fbounds-check, gfortran calculates only the shape of
the RHS and assumes that the shape of LHS is the same, but is using a more
literal interpretation when -fbounds-check is used.

In the 'no -fbounds-check'-case we will have a problem if bar() has side
effects, SAVEd variables etc.  In that case, calling bar() too few times
may give wrong results.


        Erik


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