[PATCH] Middle-end arrays, forward-ported to trunk (again)

Richard Guenther rguenther@suse.de
Tue Jun 21 15:33:00 GMT 2011


On Tue, 21 Jun 2011, Richard Guenther wrote:

> 
> This forward-ports the middle-end array patch.  Patch status is the
> same as with the last forward-port from 2009 - the scalarizer cannot
> deal with control flow and it cannot insert temporaries when
> required (so it operates in a mode that requires the frontend to
> insert those that are necessary).
> 
> Expected FAILs of the C/C++ frontend-hack testcases are
> 
> FAIL: g++.dg/tree-ssa/mea-1.C (test for excess errors)
> FAIL: gcc.dg/mea-1.c (test for excess errors)
> 
> the gimplifier isn't able to properly translate the C/C++ builtin hack
> 
> FAIL: g++.dg/tree-ssa/mea-10.C (internal compiler error)
> FAIL: g++.dg/tree-ssa/mea-10.C (test for excess errors)
> FAIL: gcc.dg/mea-15.c (internal compiler error)
> FAIL: gcc.dg/mea-15.c (test for excess errors)
> 
> aforementioned case of not handling control flow (both testcases
> simulating U(:) = WHERE (U(:) < 0, 0) which would be handled
> if the scalarizer sees an if-converted COND_EXPR).
> 
> Not further tested (I'll try bootstrapping now).  I didn't touch
> the ChangeLog.
> 
> Disclaimer: During the London Gathering we discussed how to eventually
> move forward with respect to Fortran using middle-end arrays.  This is
> step1, forward-port the existing patch.
> 
> Hints on where I could lower simple fortran array expressions from
> the frontend are appreciated.  Simple first example:
> 
>   subroutine copy (dst, src, ni, nj)
>     integer, intent(in) :: ni, nj
>     double precision, intent(out) :: dst(ni, nj)
>     double precision, intent(in)  :: src(ni, nj)
>     dst = src
>   end subroutine copy
> 
> If I have a first Fortran bit working I will probably disentangle
> the C/C++ frontend hacks and put the rest on a branch.

The following is a patch^Whack that should handle almost all
array exprs.  Well, tried on the following testcase:

subroutine foo (dst, bar, ni, nj)
  integer, intent(in) :: ni, nj
  double precision, intent(in) :: bar(ni, nj)
  double precision, intent(out) :: dst(ni, nj)

  dst(2:ni-1,2:nj-1) = 5. + bar(2:ni-1,2:nj-1)
end subroutine foo

I failed to see where the scalarizer inserts the temporary vars it
creates into the scope blocks (thus the gimplify.c hunk ...).  Any
help here is welcome.

The patch also currently runs into type verification issues that
are bugs in the scalarizer (I'll fix that), thus the tree-cfg.c hunk.
And the scalarizer has the issue that it doesn't run at -O0, so we
can't expand there (probably the Fortran scalarizer should be
used at -O0?).  I guess I'll fix it by running it unconditionally
(in the past SSA info wasn't available at -O0 but it relies on that).

For some reason (I guess because of the type mismatches) we
miscompile the loop at -O2 (disabling VRP helps).

Anyway, just as an update, if you want to desperately experiment ;)

Richard.

Index: trunk/gcc/fortran/trans-array.c
===================================================================
*** trunk.orig/gcc/fortran/trans-array.c	2011-06-14 12:41:32.000000000 +0200
--- trunk/gcc/fortran/trans-array.c	2011-06-21 16:52:41.000000000 +0200
*************** gfc_conv_scalarized_array_ref (gfc_se *
*** 2570,2575 ****
--- 2570,2622 ----
    int n;
  
    info = &se->ss->data.info;
+ 
+     {
+       tree vv = build_vl_exp (VLA_VIEW_EXPR, 2 + 2 * info->dimen);
+       tree vi = build_vl_exp (VLA_IDX_EXPR, 2 + info->dimen);
+       tree offset = build_int_cst (gfc_array_index_type, 0);
+       tree elt_type = double_type_node; /* FIXME */
+       tree type = elt_type;
+       for (n = 0; n < info->dimen; ++n)
+ 	{
+ 	  TREE_OPERAND (vv, 2 + 2 * n)  /* extent */
+ 	    = build2 (MINUS_EXPR, TREE_TYPE (info->end[n]),
+ 		      info->end[n], info->start[n]);
+ 	  TREE_OPERAND (vv, 3 + 2 * n)  /* stride */
+ 	    = info->stride[n];
+ 	  /* Accumulate start offset.  */
+ 	  offset = fold_build2_loc (input_location,
+ 				    PLUS_EXPR, TREE_TYPE (offset),
+ 				    offset,
+ 				    fold_build2_loc (input_location,
+ 						     MULT_EXPR, TREE_TYPE (offset),
+ 						     info->start[n],
+ 						     info->stride[n]));
+ 	  type = build_array_type (type, build_index_type
+ 				           (TREE_OPERAND (vv, 2 + 2 * n)));
+ 	}
+       /* Start address.  */
+       TREE_OPERAND (vv, 1)
+ 	= build2 (MEM_REF, type,
+ 		  fold_build2_loc (input_location,
+ 				   POINTER_PLUS_EXPR,
+ 				   TREE_TYPE (info->descriptor),
+ 				   info->descriptor,
+ 				   fold_convert (sizetype, offset)),
+ 		  build_int_cst (build_pointer_type (elt_type), 0));
+       /* Type.  */
+       TREE_TYPE (vv) = type;
+       TREE_OPERAND (vi, 1) = vv;
+       for (n = 0; n < info->dimen; ++n)
+ 	{
+ 	  TREE_OPERAND (vi, 2 + n) /* Index placeholder.  */
+ 	    = se->loop->loopvar[n];
+ 	}
+       TREE_TYPE (vi) = elt_type;
+       se->expr = vi;
+       return;
+     }
+ 
    if (ar)
      n = se->loop->order[0];
    else
Index: trunk/gcc/fortran/trans-expr.c
===================================================================
*** trunk.orig/gcc/fortran/trans-expr.c	2011-06-14 12:41:32.000000000 +0200
--- trunk/gcc/fortran/trans-expr.c	2011-06-21 16:44:28.000000000 +0200
*************** gfc_trans_assignment_1 (gfc_expr * expr1
*** 6126,6131 ****
--- 6126,6142 ----
    else
      gfc_conv_expr (&lse, expr1);
  
+   /* ???  Fixup array LHS.  */
+   if (TREE_CODE (lse.expr) == VLA_IDX_EXPR)
+     {
+       tree vi = lse.expr;
+       lse.expr = TREE_OPERAND (vi, 1);
+       TREE_OPERAND (vi, 1) = rse.expr;
+       TREE_SET_CODE (vi, VLA_RIDX_EXPR);
+       TREE_TYPE (vi) = TREE_TYPE (lse.expr);
+       rse.expr = vi;
+     }
+ 
    /* Assignments of scalar derived types with allocatable components
       to arrays must be done with a deep copy and the rhs temporary
       must have its components deallocated afterwards.  */
*************** gfc_trans_assignment_1 (gfc_expr * expr1
*** 6153,6158 ****
--- 6164,6173 ----
  	&& expr1->ts.deferred)
      gfc_add_block_to_block (&block, &rse.pre);
  
+   /* ???  */
+   if (TREE_CODE (lse.expr) == VLA_VIEW_EXPR)
+     gfc_add_block_to_block (&body, &loop.pre);
+ 
    tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
  				 l_is_temp || init_flag,
  				 expr_is_variable (expr2) || scalar_to_array
*************** gfc_trans_assignment_1 (gfc_expr * expr1
*** 6170,6175 ****
--- 6185,6196 ----
        /* Use the scalar assignment as is.  */
        gfc_add_block_to_block (&block, &body);
      }
+   /* ???  Skip regular scalarization.  */
+   else if (TREE_CODE (lse.expr) == VLA_VIEW_EXPR)
+     {
+       gfc_cleanup_loop (&loop);
+       return gfc_finish_block (&body);
+     }
    else
      {
        gcc_assert (lse.ss == gfc_ss_terminator
Index: trunk/gcc/gimplify.c
===================================================================
*** trunk.orig/gcc/gimplify.c	2011-06-21 15:06:43.000000000 +0200
--- trunk/gcc/gimplify.c	2011-06-21 16:44:21.000000000 +0200
*************** gimplify_var_or_parm_decl (tree *expr_p)
*** 1873,1880 ****
--- 1873,1882 ----
        && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
        && decl_function_context (decl) == current_function_decl)
      {
+ #if 0
        gcc_assert (seen_error ());
        return GS_ERROR;
+ #endif
      }
  
    /* When within an OpenMP context, notice uses of variables.  */
Index: trunk/gcc/tree-cfg.c
===================================================================
*** trunk.orig/gcc/tree-cfg.c	2011-06-21 14:15:49.000000000 +0200
--- trunk/gcc/tree-cfg.c	2011-06-21 17:03:02.000000000 +0200
*************** verify_gimple_in_cfg (struct function *f
*** 4341,4346 ****
--- 4341,4348 ----
    bool err = false;
    struct pointer_set_t *visited, *visited_stmts;
  
+   return;
+ 
    timevar_push (TV_TREE_STMT_VERIFY);
    visited = pointer_set_create ();
    visited_stmts = pointer_set_create ();



More information about the Gcc-patches mailing list