patch for FORALL resolution
Canqun Yang <canqun-/[email protected]> Mon, 12 May 2003 22:34:26 +0800 (CST)
| Newsgroups | gmane.comp.compilers.g95 |
|---|---|
| Message-ID | <[email protected]> |
--0-1490740966-1052750066=:23256
Content-Type: text/plain; charset=gb2312
Content-Transfer-Encoding: 8bit
Content-Id:
Content-Disposition: inline
Hi, Paul, Steven
This patch enhanced the resolution for FORALL.
Would you please check it?
I hope the patch can be applied, because it took
Lifang Zeng much time on it, and to maintain the patch
is really a burden.
Canqun Yang.
_________________________________________________________
Do You Yahoo!?
Ïà¼û²»ÈçÁÄÌì!²»³öÃÅÒ»ÑùÃæ¶ÔÃæ£¡ÍøÂçÉãÏñÍ·¶Ô¶ÔÅÉËÍÖÐ~¸Ï¿ìÓÃÄãµÄÑÅ»¢µçÓÊÕʺŲÎÓë°É¡¡
http://cn.rd.yahoo.com/mail_cn/tag/?http://cn.messenger.yahoo.com/
--0-1490740966-1052750066=:23256
Content-Type: text/plain; name="forall_resolve_patch.txt"
Content-Description: forall_resolve_patch.txt
Content-Disposition: inline; filename="forall_resolve_patch.txt"
*** resolve.c 2003-05-12 19:56:00.000000000 +0800
--- resolve.c 2003-05-12 21:54:29.000000000 +0800
***************
*** 22,28 ****
#include "config.h"
#include "g95.h"
#include "arith.h" /* For g95_compare_expr(). */
!
#include <string.h>
/* Stack to push the current if we descend into a block during
--- 22,28 ----
#include "config.h"
#include "g95.h"
#include "arith.h" /* For g95_compare_expr(). */
! #include <assert.h>
#include <string.h>
/* Stack to push the current if we descend into a block during
***************
*** 2955,2961 ****
/* Check shape consistent for WHERE assignment target. */
if (e && resolve_where_shape (cnext->expr, e) == FAILURE)
g95_error ("WHERE assignment target at %L has "
! "inconsistent shape", &cnext->expr->where);
break;
/* WHERE or WHERE construct is part of a where-body-construct */
--- 2955,2961 ----
/* Check shape consistent for WHERE assignment target. */
if (e && resolve_where_shape (cnext->expr, e) == FAILURE)
g95_error ("WHERE assignment target at %L has "
! "inconsistent shape", &cnext->expr->where);
break;
/* WHERE or WHERE construct is part of a where-body-construct */
***************
*** 2976,2981 ****
--- 2976,3316 ----
}
+ /* Check whether the forall index appear in the expression or not. */
+
+ static try
+ g95_find_forall_index (g95_expr *expr, g95_symbol *symbol)
+ {
+ g95_array_ref ar;
+ g95_actual_arglist *args;
+ int i;
+
+ switch (expr->expr_type)
+ {
+ case EXPR_VARIABLE:
+ assert (expr->symtree->n.sym);
+
+ /* A scalar assignment */
+ if (!expr->ref)
+ {
+ if (expr->symtree->n.sym == symbol)
+ return 1;
+ }
+ else
+ {
+ g95_ref *tmp;
+
+ /* the expr is array ref, substring or struct component. */
+ tmp = expr->ref;
+ while (tmp != NULL)
+ {
+ switch (tmp->type)
+ {
+ case REF_ARRAY:
+ /* Check if the symbol appears in the array subscript. */
+ ar = tmp->u.ar;
+ for (i = 0; i < G95_MAX_DIMENSIONS; i++)
+ {
+ if (ar.start[i])
+ {
+ if (g95_find_forall_index (ar.start[i], symbol))
+ return 1;
+ }
+ }
+ for (i = 0; i < G95_MAX_DIMENSIONS; i++)
+ {
+ if (ar.end[i])
+ {
+ if (g95_find_forall_index (ar.end[i], symbol))
+ return 1;
+ }
+ }
+ for (i = 0; i < G95_MAX_DIMENSIONS; i++)
+ {
+ if (ar.stride[i])
+ {
+ if (g95_find_forall_index (ar.stride[i], symbol))
+ return 1;
+ }
+ }
+ break;
+
+ case REF_SUBSTRING:
+ if (expr->symtree->n.sym == symbol)
+ return 1;
+
+ /* Check if the symbol appears in the substring section. */
+ if (g95_find_forall_index (expr->ref->u.ss.start, symbol))
+ return 1;
+ if (g95_find_forall_index (expr->ref->u.ss.end, symbol))
+ return 1;
+ break;
+
+ /* If the ref is REF_COMPONENT,just Jumping over it and
+ going to the next. */
+ case REF_COMPONENT:
+ break;
+
+ default:
+ g95_error("expresion reference type error at %L",
+ &expr->where);
+ }
+ tmp = tmp->next;
+ }
+ }
+ break;
+
+ /* If the expression is a function call, then check if the symbol
+ appears in the actual arglist of the function. */
+ case EXPR_FUNCTION:
+ for (args = expr->value.function.actual; args; args = args->next)
+ {
+ if (g95_find_forall_index(args->expr,symbol))
+ return 1;
+ }
+ break;
+
+ /* It seems not to happen? */
+ case EXPR_SUBSTRING:
+ if (expr->ref)
+ {
+ assert(expr->ref->type == REF_SUBSTRING);
+ if (g95_find_forall_index (expr->ref->u.ss.start, symbol))
+ return 1;
+ if (g95_find_forall_index (expr->ref->u.ss.end, symbol))
+ return 1;
+ }
+ break;
+
+ /* It seems not to happen? */
+ case EXPR_STRUCTURE:
+ case EXPR_ARRAY:
+ g95_error ("Not supported statement while finding forall index in "
+ "expression");
+ break;
+
+ default:
+ break;
+ }
+
+ /* Find the forall index in the first operand. */
+ if(expr->op1)
+ {
+ if (g95_find_forall_index (expr->op1, symbol))
+ return 1;
+ }
+
+ /* Find the forall index in the second operand. */
+ if(expr->op2)
+ {
+ if (g95_find_forall_index (expr->op2, symbol))
+ return 1;
+ }
+
+ return 0;
+ }
+
+
+ /* Resolve assignment in forall construct */
+
+ static void
+ g95_resolve_assign_in_forall (g95_code *code, int nvar, g95_expr **var_expr)
+ {
+ int n;
+
+ /* Nvar is the number of FORALL index variables.
+ Var_expr records the FORALL index variables. */
+ for (n = 0; n < nvar; n++)
+ {
+ g95_symbol *forall_index;
+
+ forall_index = var_expr[n]->symtree->n.sym;
+
+ /* Check whether the lhs of the assignment is one of the FORALL
+ index variable. */
+ if ((code->expr->expr_type == EXPR_VARIABLE)
+ && (code->expr->symtree->n.sym == forall_index))
+ g95_error ("Assignment to a FORALL index variable "
+ "at %L", &code->expr->where);
+ else
+ {
+ /* If one of the FORALL index variables doesn't appear in the
+ lhs of the assignment, then there will be a many-to-one
+ assignment. */
+ if ( ! g95_find_forall_index (code->expr, forall_index))
+ g95_error ("The FORALL with index '%s' cause more "
+ "than one assignment to this object at %L",
+ var_expr[n]->symtree->name, &code->expr->where);
+ }
+ }
+ }
+
+
+ /* Resolve where statement in forall construct */
+
+ static void
+ g95_resolve_where_code_in_forall (g95_code *code, int nvar, g95_expr **var_expr){
+ g95_code *cblock;
+ g95_code *cnext;
+
+ cblock = code->block;
+ while (cblock)
+ {
+ /* the assignment statement of a WHERE statement, or the first
+ statement in where-body-construct of a WHERE construct */
+ cnext = cblock->next;
+ while (cnext)
+ {
+ switch (cnext->op)
+ {
+ /* WHERE assignment statement */
+ case EXEC_ASSIGN:
+ g95_resolve_assign_in_forall (cnext, nvar, var_expr);
+ break;
+
+ /* WHERE or WHERE construct is part of a where-body-construct */
+ case EXEC_WHERE:
+ g95_resolve_where_code_in_forall (cnext, nvar, var_expr);
+ break;
+
+ default:
+ g95_error ("Unsupported statement inside WHERE at %L",
+ &cnext->loc);
+ break;
+ }
+ /* the next statement within the same where-body-construct */
+ cnext = cnext->next;
+ }
+ /* the next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt */
+ cblock = cblock->block;
+ }
+ }
+
+
+ /* Traverse the FORALL body to check whether the following errors exist:
+ 1. For assignment, check if a many-to-one assignment happens.
+ 2. For where statement, check the where body to see if there is any
+ many-to-one assignment. */
+
+ static void
+ g95_resolve_forall_body (g95_code *code, int nvar, g95_expr **var_expr)
+ {
+ g95_code *c;
+
+ c = code->block->next;
+
+ while (c)
+ {
+ switch (c->op)
+ {
+ case EXEC_ASSIGN:
+ case EXEC_POINTER_ASSIGN:
+ g95_resolve_assign_in_forall (c, nvar, var_expr);
+ break;
+
+ /* Because the resolve_blocks() will handle the nested FORALL,
+ there is no need to handle it here. */
+ case EXEC_FORALL:
+ break;
+
+ case EXEC_WHERE:
+ g95_resolve_where_code_in_forall(c, nvar, var_expr);
+ break;
+
+ default:
+ break;
+ }
+
+ /* The next statement in the FORALL body. */
+ c = c->next;
+ }
+ }
+
+
+ /* Given a forall construct, first resolve the forall iterator, then call
+ g95_resolve_forall_body to resolve the forall body. */
+
+ static void resolve_blocks (g95_code *, g95_namespace *);
+ static void
+ g95_resolve_forall (g95_code *code, g95_namespace *ns, int forall_save)
+ {
+ static g95_expr **var_expr;
+ static int total_var = 0;
+ static int nvar = 0;
+ g95_forall_iterator *fa;
+ g95_symbol *forall_index;
+ g95_code *next;
+ int i;
+
+ /* Resolve FORALL construct */
+ if (forall_save == 0)
+ {
+ /* Count the total number of FORALL index in the nested FORALL
+ construct in order to allocate the VAR_EXPR with proper size. */
+ next = code;
+ while ((next != NULL) && (next->op == EXEC_FORALL))
+ {
+ for (fa = next->ext.forall_iterator; fa; fa = fa->next)
+ total_var ++;
+ next = next->block->next;
+ }
+
+ /* allocate VAR_EXPR with NUMBER_OF_FORALL_INDEX elements. */
+ var_expr = (g95_expr **) g95_getmem (total_var * sizeof (g95_expr *));
+ }
+
+ /* The information about forall iterator, including forall index start,end
+ and stride. The FORALL index can not appear in start, end or stride. */
+ for (fa = code->ext.forall_iterator; fa; fa = fa->next)
+ {
+ /* Check if any outer FORALL index name is the same as the current
+ one */
+ for (i = 0; i < nvar; i++)
+ {
+ if (fa->var->symtree->n.sym == var_expr[i]->symtree->n.sym)
+ {
+ g95_error ("An outer FORALL construct already has an index "
+ "with this name %L", &fa->var->where);
+ }
+ }
+
+ /* Record the current FORALL index. */
+ var_expr[nvar] = g95_copy_expr (fa->var);
+
+ forall_index = fa->var->symtree->n.sym;
+
+ /* Check if the FORALL index appears in start,end or stride. */
+ if (g95_find_forall_index (fa->start, forall_index))
+ g95_error ("A FORALL index must not appear in a limit or stride "
+ "expression in the same FORALL at %L", &fa->start->where);
+
+ if (g95_find_forall_index (fa->end, forall_index))
+ g95_error ("A FORALL index must not appear in a limit or stride "
+ "expression in the same FORALL at %L", &fa->end->where);
+
+ if (g95_find_forall_index (fa->stride, forall_index))
+ g95_error ("A FORALL index must not appear in a limit or stride "
+ "expression in the same FORALL at %L", &fa->stride->where);
+ nvar++;
+ }
+
+ /* Resolve the forall body. */
+ g95_resolve_forall_body (code, nvar, var_expr);
+
+ resolve_blocks (code->block, ns);
+
+ /* Clear the global var NVAR and VAR_EXPR after resolving a nested
+ FORALL construct. It must be here after resolve_blocks(), because
+ resolve_blocks() will handle the inner FORALL and modify NVAR and
+ VAR_EXPR. */
+ for (i = 0; i < total_var; i++)
+ g95_free_expr (var_expr[i]);
+
+ total_var = 0;
+ nvar = 0;
+ }
+
+
/* Resolve lists of blocks found in IF, SELECT CASE, WHERE, FORALL and DO code
nodes. */
***************
*** 3050,3058 ****
{
forall_save = forall_flag;
forall_flag = 1;
! }
!
! resolve_blocks (code->block, ns);
if (code->op == EXEC_FORALL)
forall_flag = forall_save;
--- 3385,3394 ----
{
forall_save = forall_flag;
forall_flag = 1;
! g95_resolve_forall (code, ns, forall_save);
! }
! else
! resolve_blocks (code->block, ns);
if (code->op == EXEC_FORALL)
forall_flag = forall_save;
*** ChangeLog 2003-05-12 21:58:28.000000000 +0800
--- ChangeLog 2003-05-12 21:53:57.000000000 +0800
***************
*** 1,3 ****
--- 1,11 ----
+ 2003-05-12 Lifang Zeng <[email protected]>
+ *resolve.c (g95_resolve_forall): Resolve FORALL construct.
+ (g95_resolve_where_code_in_forall): New function
+ (g95_resolve_assign_in_forall): New function
+ (g95_resolve_forall_body): New function
+ (g95_find_forall_index): New function
+ (resolve_code): Modified
+
2003-05-11 Paul Brook <[email protected]>
* arith.c (g95_integer_index_kind): New variable.
--0-1490740966-1052750066=:23256
Content-Type: text/plain; name="forall_resolve.txt"
Content-Description: forall_resolve.txt
Content-Disposition: inline; filename="forall_resolve.txt"
! Test FORALL resolution
program forall_resolve
integer a(4)
forall (i=1:4)
a = i
end forall
end
subroutine forall_resolve_2
integer a(4,6), n1, n2
do i=1,4
a(i,1) = -1
a(i,2) = 0
a(i,3) = 1
a(i,4) = 2
a(i,5) = -2
a(i,6) = -1
enddo
n1 = 4
n2 = 6
forall (i=1:n1, a(1,i).GT.0)
forall (j=i:n2, a(i,j).GT.0)
forall (j=i:n2)
a(i,:) = i+j
end forall
end forall
end forall
end
subroutine forall_resolve_3
integer a(10,10),k,j,b(10)
type people
integer a(10,10)
character*10 name
end type
type (people) me(10)
forall (i=1:i)
forall (j=i:10)
me(i)%a(i,b(i)) = 2
me(j)%name = "zlf"
i = 1
j = 1
where (a.GT.0)
me(i)%name = "xmq"
elsewhere
me(j)%name = "xxx"
end where
end forall
end forall
end
subroutine forall_resolve_3
integer a(10,10),i,j
forall (i=1:10)
forall (j=i:10)
a(:,j) = i+j
end forall
end forall
end
subroutine forall_resolve_5
integer, parameter :: N = 10 ! say...
integer, parameter :: M = 2*N
integer :: i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14
real, dimension(M,M,M,M,M,M,M) :: A, B
forall (i1=1:N2, i2=1:N, i3=1:N, i4=1:N, i5=1:N, i6=1:N, i7=1:N,&
i8=1:N2, i9=1:N, i10=1:N, i11=1:N, i12=1:N, i13=1:N, i14=1:N)&
a(i1,i2,i3,i4,i5,i6,i7) = b(i8,i9,i10,i11,i12,i13,i14)
forall (i1=1:N2, i2=1:N, i3=1:N, i4=1:N, i5=1:N, i6=1:N, i7=1:N,&
i8=1:N2, i9=1:N, i10=1:N, i11=1:N, i12=1:N, i13=1:N, i14=1:N)&
a(i1+i2,i3+i4,i5+i6,i7+i8,i9,i11+i12,i13) = 2
end
--0-1490740966-1052750066=:23256--
-------------------------------------------------------
Enterprise Linux Forum Conference & Expo, June 4-6, 2003, Santa Clara
The only event dedicated to issues related to Linux enterprise solutions
www.enterpriselinuxforum.com