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 ] = (*(int4[0:] *) atmp.0.data)[NON_LVALUE_EXPR ]; 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 " 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 * 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 --