===================================================================
@@ -2634,7 +2634,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_arr
locus * where)
{
int n;
- tree index;
+ tree index, offset, *indexp;
tree tmp;
tree stride;
gfc_se indexse;
@@ -2669,9 +2669,16 @@ gfc_conv_array_ref (gfc_se * se, gfc_arr
return;
}
- index = gfc_index_zero_node;
+ offset = gfc_conv_array_offset (se->expr);
+ if (TREE_CODE (offset) != INTEGER_CST)
+ index = offset;
+ else
+ index = gfc_index_zero_node;
- /* Calculate the offsets from all the dimensions. */
+ indexp = &index;
+
+ /* Calculate the offsets from all the dimensions. Make sure to associate
+ the final offset so that we form a chain of loop invariant summands. */
for (n = 0; n < ar->dimen; n++)
{
/* Calculate the index for this dimension. */
@@ -2740,15 +2747,43 @@ gfc_conv_array_ref (gfc_se * se, gfc_arr
tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
indexse.expr, stride);
- /* And add it to the total. */
- index = fold_build2_loc (input_location, PLUS_EXPR,
- gfc_array_index_type, index, tmp);
+ /* And add it to the total. Avoid folding as that re-associates
+ in a non-optimal way. We want to have constant offsets as
+ the outermost addition and the rest of the additions in order
+ of the loop depth. */
+ if (!integer_zerop (index))
+ {
+ if (TREE_CODE (tmp) == INTEGER_CST)
+ {
+ bool reset = indexp == &index;
+ index = fold_build2_loc (input_location, PLUS_EXPR,
+ gfc_array_index_type, index, tmp);
+ if (reset)
+ {
+ if (TREE_CODE (index) == PLUS_EXPR)
+ indexp = &TREE_OPERAND (index, 0);
+ else
+ indexp = &index;
+ }
+ }
+ else
+ {
+ *indexp
+ = build2_loc (input_location, PLUS_EXPR,
+ gfc_array_index_type, *indexp, tmp);
+ indexp = &TREE_OPERAND (*indexp, 0);
+ }
+ }
+ else
+ {
+ index = tmp;
+ indexp = &index;
+ }
}
- tmp = gfc_conv_array_offset (se->expr);
- if (!integer_zerop (tmp))
+ if (TREE_CODE (offset) == INTEGER_CST)
index = fold_build2_loc (input_location, PLUS_EXPR,
- gfc_array_index_type, index, tmp);
+ gfc_array_index_type, index, offset);
/* Access the calculated element. */
tmp = gfc_conv_array_data (se->expr);
===================================================================
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-require-effective-target vect_double }
+ subroutine shell(nx,ny,nz,q,dq)
+ implicit none
+ integer i,j,k,l,nx,ny,nz
+ real*8 q(5,nx,ny),dq(5,nx,ny)
+ do j=1,ny
+ do i=1,nx
+ do l=1,5
+ q(l,i,j)=q(l,i,j)+dq(l,i,j)
+ enddo
+ enddo
+ enddo
+ return
+ end
+! { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail vect_no_align } } }