This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
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