Re: Automatically transform or expand do loop in a subroutine



On Jan 31, 2:10 pm, Thomas Koenig <tkoe...@xxxxxxxxxxxxx> wrote:
On 2008-01-31, yaqi <yaqiw...@xxxxxxxxx> wrote:

***, are you sure compilers can handle this case?

I modified your program by making the function internal (which
makes inlining much easier), then feeding ito to gfortran.
Here's the modified program (I had to add the I/O statements
to avoid optimizing the whole program away :-)

program main
integer :: e, c
read (*,*) c
e = ad(c, 10)
print *,e
stop
contains
integer function ad(c,d)
implicit none
integer :: c
integer :: d
integer :: i
do i=1,d
c = c + i
end do
ad = c
return
end function ad
end program main

Here's what "gfortran -O3 -fdump-tree-optimized" made of it:

main ()
{
integer(kind=4) c_lsm.57;
integer(kind=4) c_lsm.56;
struct __st_parameter_dt dt_parm.2;
struct __st_parameter_dt dt_parm.1;
static integer(kind=4) options.0[7] = {68, 127, 0, 0, 0, 1, 0};
integer(kind=4) e;
integer(kind=4) c;

<bb 2>:
_gfortran_set_options (7, &options.0);
dt_parm.1.common.filename = &"foo.f90"[1]{lb: 1 sz: 1};
dt_parm.1.common.line = 3;
dt_parm.1.common.flags = 128;
dt_parm.1.common.unit = 5;
_gfortran_st_read (&dt_parm.1);
_gfortran_transfer_integer (&dt_parm.1, &c, 4);
_gfortran_st_read_done (&dt_parm.1);
c_lsm.56 = c;
c_lsm.57 = c_lsm.56 + 55;
c = c_lsm.57;
e = c_lsm.57;
dt_parm.2.common.filename = &"foo.f90"[1]{lb: 1 sz: 1};
dt_parm.2.common.line = 5;
dt_parm.2.common.flags = 128;
dt_parm.2.common.unit = 6;
_gfortran_st_write (&dt_parm.2);
_gfortran_transfer_integer (&dt_parm.2, &e, 4);
_gfortran_st_write_done (&dt_parm.2);
_gfortran_stop_numeric (-1);

}

The loop is optimized into an addition, which isn't bad. This
doesn't work for non-constant d, though.

I tried following modified program:
-----------------------------------------
program main
implicit none
integer :: e, c, ad, i
real :: t1, t2
integer, parameter :: mloop = 100000000

c = 0
call cpu_time(t1)
do i = 1, mloop
e = ad(c,10)
end do
call cpu_time(t2)
print *, 'Time cost with function call:', t2-t1
print *, e

c = 0
call cpu_time(t1)
do i = 1, mloop
c = c + 55
e = c
end do
call cpu_time(t2)
print *, 'Time cost with function call:', t2-t1
print *, e

stop
end program

integer function ad(c,d)
implicit none
integer :: c
integer :: d
integer :: i
do i=1,d
c = c + i
end do
ad = c
return
end function ad

--------------------------------

And compiled with 'gfortran -O5 -fdump-tree-optimized'. The generated
pseudo-code is:
--------------------------------
;; Function ad (ad_)

Analyzing Edge Insertions.
ad (c, d)
{
<unnamed type> D.1138;
<unnamed type> D.1139;
int4 D.1140;
int4 c__lsm.34;
int4 pretmp.33;
logical4 D.1067;
int4 D.1064;
int4 __result_ad;
int4 i;
int4 D.1073;
int4 D.1072;
int4 D.1071;

<bb 0>:
D.1064 = *d;
if (D.1064 > 0) goto <L12>; else goto <L4>;

<L12>:;
c__lsm.34 = *c;
i = 1;

<L10>:;
c__lsm.34 = i + c__lsm.34;
i = i + 1;
if (i == (int4) ((<unnamed type>) D.1064 + 1)) goto <L16>; else goto
<L10>;

<L16>:;
*c = c__lsm.34;

<L4>:;
return *c;

}



;; Function MAIN__ (MAIN__)

Analyzing Edge Insertions.
MAIN__ ()
{
real4 t2.80;
real4 t1.79;
real4 temp.78;
int4 c_lsm.77;
<unnamed type> ivtmp.69;
int4 c_lsm.68;
int4 e_lsm.67;
int4 pretmp.66;
int4 pretmp.65;
int4 C.1039 = 10;
struct __st_parameter_dt dt_parm.3;
real4 D.1049;
struct __st_parameter_dt dt_parm.2;
logical4 D.1047;
struct __st_parameter_dt dt_parm.1;
real4 D.1043;
struct __st_parameter_dt dt_parm.0;
logical4 D.1041;
real4 t1;
real4 t2;
int4 e;
int4 i;
int4 c;
int4 D.1058;
int4 c.6;
real4 D.1055;
real4 t1.5;
real4 t2.4;
int4 D.1052;

<bb 0>:
_gfortran_set_std (70, 127, 0);
c = 0;
_gfortran_cpu_time_4 (&t1);
i = 1;

<L0>:;
D.1052 = ad (&c, &C.1039);
e = D.1052;
i = i + 1;
if (i == 100000001) goto <L4>; else goto <L0>;

<L4>:;
_gfortran_cpu_time_4 (&t2);
dt_parm.0.common.filename = "a.f90";
dt_parm.0.common.line = 13;
dt_parm.0.common.unit = 6;
dt_parm.0.common.flags = 128;
_gfortran_st_write (&dt_parm.0);
_gfortran_transfer_character (&dt_parm.0, "Time cost with function
call:", 29\
);
D.1043 = t2 - t1;
_gfortran_transfer_real (&dt_parm.0, &D.1043, 4);
_gfortran_st_write_done (&dt_parm.0);
dt_parm.1.common.filename = "a.f90";
dt_parm.1.common.line = 14;
dt_parm.1.common.unit = 6;
dt_parm.1.common.flags = 128;
_gfortran_st_write (&dt_parm.1);
_gfortran_transfer_integer (&dt_parm.1, &e, 4);
_gfortran_st_write_done (&dt_parm.1);
c = 0;
_gfortran_cpu_time_4 (&t1);
c_lsm.68 = c;
e = c_lsm.68 + 047d35700;
c = c_lsm.68 + 047d35700;
_gfortran_cpu_time_4 (&t2);
dt_parm.2.common.filename = "a.f90";
dt_parm.2.common.line = 23;
dt_parm.2.common.unit = 6;
dt_parm.2.common.flags = 128;
_gfortran_st_write (&dt_parm.2);
_gfortran_transfer_character (&dt_parm.2, "Time cost with function
call:", 29\
);
D.1049 = t2 - t1;
_gfortran_transfer_real (&dt_parm.2, &D.1049, 4);
_gfortran_st_write_done (&dt_parm.2);
dt_parm.3.common.filename = "a.f90";
dt_parm.3.common.line = 24;
dt_parm.3.common.unit = 6;
dt_parm.3.common.flags = 128;
_gfortran_st_write (&dt_parm.3);
_gfortran_transfer_integer (&dt_parm.3, &e, 4);
_gfortran_st_write_done (&dt_parm.3);
_gfortran_stop_numeric (-1);

}
---------------------------------

gfortran does not incline the function call. What happened?

Yaqi
.