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

Paul Richard Thomas paul.richard.thomas@gmail.com
Tue Jun 21 18:47:00 GMT 2011


Dear Richi,

The point of entry for assignments is in trans-expr.c
06038 tree
06039 gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
06040                       bool dealloc)
06041 {

----a bunch of special cases----

06088
06089   /* Fallback to the scalarizer to generate explicit loops.  */
06090   return gfc_trans_assignment_1 (expr1, expr2, init_flag, dealloc);
06091 }

One of the special cases is copying one array to another.  You might
do well to use this function and to create special cases as you go
along.  It's well clear of the scalarizer :-)

BTW the scalarizer does not modify the lhs/rhs expressions (expr1/expr2).

When doing something similar in the past, I gave the lhs a special
name and selected on that so that I did not have to mess around with
the conditions for the special cases.

I hope that this helps.

Cheers

Paul

On Tue, Jun 21, 2011 at 5:08 PM, Richard Guenther <rguenther@suse.de> wrote:
> 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 ();
>



-- 
The knack of flying is learning how to throw yourself at the ground and miss.
       --Hitchhikers Guide to the Galaxy



More information about the Gcc-patches mailing list