This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug fortran/31009] Use memcpy when assigning whole arrays
- From: "burnus at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 1 Mar 2007 16:33:14 -0000
- Subject: [Bug fortran/31009] Use memcpy when assigning whole arrays
- References: <bug-31009-13648@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Comment #1 from burnus at gcc dot gnu dot org 2007-03-01 16:33 -------
> I'd like to suggest to do the same for derived type components.
The point is not components or not, the point is: Known size at compile time or
not. (A different thing are arrays of derived types.)
The same tree without memcopy is produced for e.g.
SUBROUTINE summed_amplitude_init_copy(this, other)
COMPLEX, DIMENSION(:,:), INTENT(out) :: this
COMPLEX, DIMENSION(:,:), INTENT(in) :: other
this = other
END SUBROUTINE
And if one replaces (:,:) by e.g. (5,5), __builtin_memcpy is used.
As the bounds are not constant, __builtin_memcpy cannot be used for (:,:) and
__memcpy has to be used.
The complication is that the memory might be not contiguous, example:
real :: r(5,5)
interface
subroutine foo(a)
real :: a(:,:)
end subroutine foo
end interface
call foo(r(1:3,1:3))
call foo(r(1:5:2,1:5:3))
end
(If no interface for "foo" is given, gfortran creates via
_gfortran_internal_pack a temporary array which is then contiguous.)
Thus you want to generate (schematically):
if(contiguous)
__memcopy
else
for(i = ...) {this[i] = that[i]}
For small arrays and for noncontiguous arrays, the contiguous check even slows
down the assignment, whereas I would expect a gain for big, contiguous arrays.
An implementation of the contiguous test can be found in
libgfortran/*/in_pack*, which is quite complicated and not necessarily fast for
small, noncontiguous arrays.
Maybe implementing it for one dimensional arrays is worthwhile as one has only
two simple extra if statments if the array is non contiguos.
if (stride * (ubound-lbound) <= 0)
return;
if(stride == 1)
memcpy(this[lbound],that[lbound], ubound-lbound);
else
for(i = lbound; i <= ubound; i++) that[i] = this[i]
For two-dimensional arrays, it is already more complicated, but it might still
be worthwhile.
--
burnus at gcc dot gnu dot org changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |burnus at gcc dot gnu dot
| |org
Summary|derived type components: use|Use memcpy when assigning
|memcpy when assigning arrays|whole arrays
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31009