Subject: transformation method about function

From: Du_Zhi_hui <[email-masked]>
Date: Fri, 21 Mar 1997 15:31:19 +0800 (EAT)

Prof. Li:
  We have discussed the method of how to transform function 
reference and function definition,please consider if it is 
reasonable and feasible.

Du Zhihui    
THE TRANSFORMATION OF FUNCTION REFERENCE AND DEFINITION
                                DU ZHIHUI 1997.3.20
1 THE GENERAL IDEA OF TRANSFORMING FUNCTION
  1.1 HOW TO TRANSFORM ARGUMENTS
  if the argument is scalar then no any change
  if the argument is array then replacing it with the array's 
  first element and the array's dad(just as the current SUBROUTINE's method)
  1.2 HOW TO TRANSFORM THE FORM OF FUNCTION
  if the function return value is scalar then no any change of the form of the function
  if the function return value is array then changing the FUNCTION to SUBROUITNE,
  let return variable as argument of the SUBROUTINE.
  1.3 HOW TO TRANSFORM THE FUNCTION BODY 
  almost same as SUBROUTINE does.
  1.4 THE PHRASE OF THIS TRANSFORMATION
  after transforming array to forall.
2 TRANSFORMATION METHOD WHEN FUNCTION RETRUN VALUE IS SCALAR
   2.1 at the point of function reference
              expr(...F(arg1,...,argn)...)
       2.1.1  if all arguments are scalar then no change for function reference
       2.1.2  if argi is array or array section then change it to
              expr(...F(arg1,...,argi(0),argi_DAD,...,argn)...)
   2.2 at the point of function definition
       2.2.1  if all dummys are scalar then no change for function_stmt
              but if the function_stmt has RESULT keyword,we must replace
              RESULT variable with function name in the function body and 
              delete RESULT part from function_stmt.
       2.2.2  if dummyi is array ,then add dummyi's DAD to
              function_stmt,change the function body just as subroutine does.
			  if the function_stmt has RESULT keyword,we must replace
              RESULT variable with function name in the function body and 
              delete RESULT part from function_stmt.
3 TRANSFORMATION METHOD WHEN FUNCTION RETURN VALUE IS ARRAY
   3.1 at the point of function reference
              A=F(arg1,...,argn)
              change function reference to subroutine call
       3.1.1  if all arguments are scalar then change it to 
              call F(A(0),A_DAD,arg1,...,argn) 
       3.1.2  if argi is array then change it to
              call F(A(0),A_DAD,arg1,...,argi(0),argi_DAD,...,argn) 
   3.2 at the point of function definition
       3.2.1  if all dummys are scalar then change function_stmt 
              FUNCTION F(dummy1,...,dummyn) to 
              SUBROUTINE F(result_array,result_array_DAD,dummy1,...,dummyn)
              in function body,replace assignment to F with assignment to 
              result_array.if the function_stmt has RESULT keyword,we must 
			  replace RESULT variable with result_array in the function body and 
              delete RESULT part from function_stmt.
       3.2.2  if dummyi is array or array section then change function_stmt
              FUNCTION F(dummy1,...,dummyn) to 
              SUBROUTINE F(result_array,result_array_DAD,dummy1,...,
                             dummyi,dummyi_DAD,...,dummyn)
              in function body,replace assignment to F with assignment to 
              result_array.if the function_stmt has RESULT keyword,we must replace
              RESULT variable with result_array in the function body and 
              delete RESULT part from function_stmt.
4 Examples:
   4.1   real rel
         ...
         rel=f1(1.1,2.0)
         ...
         FUNCTION f1(var1,var2)
         real var1,var2
         have any changes
   4.2   real rel,a(910)
         ...
         rel=f2(a)
         ...
         FUNCTION f2(var1)
         real var1(:)
         should be changed to
         ...
         sum=f2(a(0),a_DAD)
         ...
         FUNCTION f2(var1,var1_DAD)
         real var1(0:*)
		 integer var1_DAD
   4.3   real rel(100)
         ...
         rel=f3(3.14)
         ...
         FUNCTION f3(var1)
         real var1
         should be changed to 
         ...
         call f3(rel(0),rel_DAD,3.14)
         ...
         SOUBROUTINE f3(result_array,result_array_DAD,var1)
         replace assignment to f3 with assignment to result_array
         when function f3 is defined like
         FUNCTION f3(var1) RESULT(result_var)
         the function_stmt also changed to               
         SOUBROUTINE f3(result_array,result_array_DAD,var1)
         but the assignment to result_var should be replaced by assignment
         to result_array in function body.
   4.4   real rel(100),a(100),b(100)
         ...
         rel=f4(a,b)
         ...
         FUNCTION f4(dum1,dum2)
         should be changed to 
         call f4(rel(0),rel_DAD,a,a_DAD,b,b_DAD)
         ...
         SUBROUTINE f4(result_array,result_array_DAD,dum1,dum1_DAD,dum2,dum2_DAD)
         replace assignment to f4 with assignment to result_array
         when function f4 is defined like
         FUNCTION f4(dum1,dum2) RESULT(result_var)
         the function_stmt also changed to               
         SOUBROUTINE f3(result_array,result_array_DAD,dum1,dum1_DAD,dum2,dum2_DAD)
         but the assignment to result_var should be replaced by assignment
         to result_array in function body.

---

From: Du_Zhi_hui <[email-masked]>
Date: Sun, 23 Mar 1997 09:42:28 +0800 (EAT)

> As I suggested in the transformation map, they may be transformed
> into a DO loop (in case of array value). For instance,
> 
>      ... X(100), Y(100), Z(100)
> !HPF$  ... X, Y, Z
>      ...
>      X = MIN(Y,Z) 
> 
> may be turned into:
> 
>      CALL pcrc_loopbounds(dad_X,...,l,u,s) 
>      DO i = l, u, s
>        X(i) = pcrc_min(Y,dad_Y,Z,dad_Z,i,)
>      END DO
Yes ,this is one method of changing to Do loop,it is let function 
reference embeding in Do loop,another is our method,change fuction to 
subroutine,it is embeding Do loop in function.
    If we embeding function reference in Do loop, it has efficient 
problem,especialy when the function body has communication(for example, 
pcrc_min),in this case,we have to do at least (u-l+1)/s times 
communication of each function referencd,but if we change the function to 
subroutine,it  only need once communication,maybe more,but it must be less 
than (u-l+1)/s.
    another reason we change function to subroutine is that when function 
return value is array, the function body must contain array operation,we 
can use transBD(link b and d in transformation map) to change this 
statement to FORALL statement directly,and other current transformation 
methods  need least changes  ; if we change a function which return an 
array to a function  which return a scalar, we have to change more in the 
function body,maybe this is more difficult to impliment.

> and for one argument case, such as
>      X = SIN(Y)
> we may treat it as for X = Y.

now in transBD we transform X = Y into FORALL statement
    FORALL (...) X()=Y()
but for X =SIN(Y) ,only when we now the function is elemental function, 
we can change it to 
    FORALL (...) X() = SIN(Y(..))
in fact,transBD does not transform this kind of assignment
    ARRAY=FUNCTION_REF()
just leave it there,and all array value function in expression are 
transformed into this kind  of assignment, just let function 
transformation passing change it to node program.

> Of course, it's possible to define a pcrc subroutine
> 
>      pcrc_sub_min(X,dad_X,Y,dad_Y,R,dad_R)
> 
> so that the above is turned to
> 
>      CALL pcrc_sub_min(...)
> 
this is our method of transforming array value function reference.

> diret]ctly. But we have no need to modify a FUNCTION statement to a
> SUBROUTINE statement in any case.

Why we need not change FUNCTION statement to SUBROUTINE statement ? I 
think this modification can let the transformation of function body easy 
and keep the original meaning of array value function.Could you give me 
the reasons why this kind of modification is not O.K ?

> 
> Thus, I see the discussion "... if the function return value is
> array ..." is irrelevant.  Rather, making a classification on
> elemental intrinsic functions, deciding on how to support them
> by runtime functions, respectively, may be valuable. Compiler
> transformation strategy will be based on those decisions. 

now two members of our group are analysing the intrinsic functions,I 
agree that making a classification on intrinsic functions ,deciding  
how to support them by runtime functions is valuable, in fact them are 
doing just as you suggest.

---

From: Zheng Gengbin <[email-masked]>
Date: Wed, 7 May 1997 11:04:36 +0800 (EAT)

On Tue, 6 May 1997, Guansong Zhang wrote:

> On Mar 23,  9:42am, Du_Zhi_hui wrote:
> > Subject: Re: transformation method about function
> >
> I'd like to know the conclusion of this discussion, if there is any one.
> 
> Guansong
> 

	Ok, I think it is too late to discuss this problem now , because
I have already implemented this idea :-) .  I put my work in tof77 as a 
separate pass now. In this pass, I change all the function header whose
return type is array to a subroutine header. And change the function call
to subroutine call statement .  

Zheng

---

From: Zheng Gengbin <[email-masked]>
Date: Thu, 8 May 1997 22:03:20 +0800 (EAT)

On Wed, 7 May 1997, Guansong Zhang wrote:

> >-- End of excerpt from Zheng Gengbin
> 
> First, I don't understand how you solve this problem,
> 
> For example, how to deal with the following code
> 	A=cshift(B, 1, 1)
> and
> 	A=C+cshift(B, 1, 1)
> cshift is a intrinsic function. A, B and C are partitioned array.
>

	Our strategy is to convert your second code form to the first by
insert a temporary variable , 
that is
	Temp = cshift(B , 1 , 1)
	A = C + Temp

	This is almost done in trans2 , and trans2 will try to map the Temp
as reasonable as possible , for example trans2 will align Temp with A .

	SO all the function call is unified to one form:

	T = func( A )

	Now , tof77 will perform the function header to subroutine header
conversion , and transform the function call to subroutine call , like :

	CALL func ( A , T)

	Then all are left to trans0 to transform the PROC CALL statement .

> Second, no matter how it is dealed, it should not be in tof77. As we talked
> previously, tof77 should convert f90 to f77. It seems having nothing to do with
> node program generation.
> 

	I thought that because functions in f90 can return results of 
array type while f77 cannot , so I thought if we use f90 compiler , maybe 
we won't need this kind of transformation .

Zheng

---

From: Zheng Gengbin <[email-masked]>
Date: Fri, 9 May 1997 10:54:53 +0800 (EAT)

On Thu, 8 May 1997, Guansong Zhang wrote:

> On May 8, 10:03pm, Zheng Gengbin wrote:
> This is good, execpt you need to pay attention one thing, Temp may need a lot
> of memory, when ever a function call appear, you need to declare a temp array.
> So may be the best way to do it in the future is using allocate to locate temp
> array on heap instead. The trouble is that this is a F90 feather.
>

	Temp is always declared the size as same as the return type of 
the function call. This sure may need a lot of memory . Maybe we can assume
different strategy according to the final compiler we use .

> Here is a problem: when do you want to carry out tof77 transformation?
> 
> To me, the reasonable place seems to be after trans0.
> 
> And the question I asked last time is how trans0 deal with this.
> 

	I think the best place to put the transformation is somewhere before
trans0 , because after the transformation , trans0 need not take special 
care of this , I think .  It will treat the code after transformation just
the same as other normal subroutine calls .

> If trans0 need to take care of the above assignment any way, we can try to make
> the output as procedure calls, instead of function. So maybe there is no need
> for tof77 to do this work.
> 

	So Maybe to put this transformation in trans1 is better if we decide
that both f77 and f90 compiler need this ?

Zheng Gengbin