This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[FORTRAN PATCH] Improved scalarization of constant array constructors


This patch improves the way that gfortran expands constant array
constructors to GIMPLE.  It's probably best explained via a simple
example; consider the following code:

program v
  integer :: x(4)
  x(:) = (/ 3, 1, 4, 1 /)
end program

Currently, this is expanded by the gfortran front-end as:

MAIN__ ()
{
  int4 x[4];

  _gfortran_set_std (70, 127, 0);
  {
    int4 A.1[4];
    struct array1_int4 atmp.0;

    atmp.0.dtype = 265;
    atmp.0.dim[0].stride = 1;
    atmp.0.dim[0].lbound = 0;
    atmp.0.dim[0].ubound = 3;
    atmp.0.data = (void *) &A.1;
    atmp.0.offset = 0;
    {
      static int4 data.3[4] = {3, 1, 4, 1};

      __builtin_memcpy (&(*(int4[0:] *) atmp.0.data)[0], &data.3, 16);
    }
    {
      int8 S.4;

      S.4 = 0;
      while (1)
        {
          if (S.4 > 3) goto L.1;
          x[NON_LVALUE_EXPR <S.4>] = (*(int4[0:] *)
atmp.0.data)[NON_LVALUE_EXPR <S.4>];
          S.4 = S.4 + 1;
        }
      L.1:;
    }
  }
}

Notice that we create a temporary array A, that requires an array
descriptor, that we then populate via a memcpy call, and then use this in
the scalarization of the assignment.  Hence we require three arrays; "A",
"data" and "x", and two copies.

With the patch below, we now generate the much simpler:

MAIN__ ()
{
  int4 x[4];

  _gfortran_set_std (70, 127, 0);
  {
    static int4 A.0[4] = {3, 1, 4, 1};

    {
      int8 S.1;

      S.1 = 1;
      while (1)
        {
          if (S.1 > 4) goto L.1;
          x[S.1 + -1] = A.0[S.1 + -1];
          S.1 = S.1 + 1;
        }
      L.1:;
    }
  }
}

where the array A, is initialized as a "static const", and then used
directly during the scalarization.  This requires only two arrays and
a single copy.  When the array constructor is large, this can result
in significant time and space savings, for the common case.

The optimization is that when the array constructor consists entirely of
constant elements, that specify it's entire size, it's possible to
pre-initialize "A" if we use gfortran's notion of a non-descriptor array
type.

Some additional comments.

[1] The code is structured so that follow-up patches can re-use this code
to lower EXPR_ARRAY expressions outside of the scalarizer, for example
allowing us to use __builtin_memcpy to move "A" into "x" above.

[2] The patch also contains a small, but unrelated clean-up, to
gfc_trans_constructor, that tidies up the scope/use of the variable
CONST_STRING.  Investigation discovered that we set const_string even
when the assignment was dead, and reorganizing things slightly makes the
role of this variable slightly clearer.

[3] This patch also contains another NON_LVALUE_EXPR tweak, which explains
the elimination/simplificiation of the "NON_LVALUE_EXPR <S.4>"
subexpressions in the example code above.

[4] This change actually allows us to do slightly better on the testcase
gfortran.dg/vect/vect-5.f90.  Previously, we expected to find two
unaligned array accesses, though now, because we scalarize references as
"A" rather than via "atmp.0.data", the vectorizer can tell that they are
suitably aligned, and hence we only find one unaligned array access.


The following patch has been tested against mainline with a full "make
bootstrap", including gfortran, and regression tested with a top-level
"make -k check" with no new failures.

Ok for mainline?

2007-01-07  Roger Sayle  <roger@eyesopen.com>

        * trans-array.c (constant_array_constructor_p): New function to
        determine whether an array constructor consists only of constant
        elements, and if so return its size.
        (gfc_build_constant_array_constructor): Construct a statically
        initialized gfortran array for a given EXPR_ARRAY.
        (gfc_trans_constant_array_constructor): Efficiently scalarize
        a constant array constructor.
        (gfc_trans_array_constructor):  Tidy up use of CONST_STRING.
        Special case scalarization of constant array constructors, all of
        whose elements are specified, using constant_array_constructor_p
        and gfc_trans_constant_array_constructor.
        (gfc_conv_scalarized_array_ref): Check whetger info->offset is zero
        before adding it to index, to avoid creating a NON_LVALUE_EXPR.

        * gfortran.dg/array_constructor_14.f90: New test case.
        * gfortran.dg/vect/vect-5.f90: Update test for improved alignment.

Roger
--

Attachment: patchf.txt
Description: Text document

Attachment: array_constructor_14.f90
Description: Text document

Attachment: testf.txt
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]