aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-08-04 12:22:42 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-08-04 12:22:42 +0000
commit428f80e65119aca0c7c03d5382d684dfdeaa7ac7 (patch)
tree1e961cfbf89e2f48a7457ac4fcac919d87391ec7 /gcc
parent9515740f004bf41a1a084285943cf73eb7316ef8 (diff)
downloadgcc-428f80e65119aca0c7c03d5382d684dfdeaa7ac7.zip
gcc-428f80e65119aca0c7c03d5382d684dfdeaa7ac7.tar.gz
gcc-428f80e65119aca0c7c03d5382d684dfdeaa7ac7.tar.bz2
re PR tree-optimization/49957 (Fails to SLP in 410.bwaves)
2011-08-04 Richard Guenther <rguenther@suse.de> PR fortran/49957 * trans-array.c (add_to_offset): New function. (gfc_conv_array_ref): Build the array index expression in optimally associated order. (gfc_walk_variable_expr): Adjust for the backward walk. * gfortran.dg/vect/O3-pr49957.f: New testcase. From-SVN: r177368
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fortran/ChangeLog8
-rw-r--r--gcc/fortran/trans-array.c40
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/vect/O3-pr49957.f16
4 files changed, 57 insertions, 12 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 912c011ba..d794d14a 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,11 @@
+2011-08-04 Richard Guenther <rguenther@suse.de>
+
+ PR fortran/49957
+ * trans-array.c (add_to_offset): New function.
+ (gfc_conv_array_ref): Build the array index expression in optimally
+ associated order.
+ (gfc_walk_variable_expr): Adjust for the backward walk.
+
2011-08-02 Daniel Kraft <d@domob.eu>
PR fortran/49885
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 85acf0c..3a75658 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2622,6 +2622,22 @@ gfc_conv_tmp_array_ref (gfc_se * se)
gfc_advance_se_ss_chain (se);
}
+/* Add T to the offset pair *OFFSET, *CST_OFFSET. */
+
+static void
+add_to_offset (tree *cst_offset, tree *offset, tree t)
+{
+ if (TREE_CODE (t) == INTEGER_CST)
+ *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
+ else
+ {
+ if (!integer_zerop (*offset))
+ *offset = fold_build2_loc (input_location, PLUS_EXPR,
+ gfc_array_index_type, *offset, t);
+ else
+ *offset = t;
+ }
+}
/* Build an array reference. se->expr already holds the array descriptor.
This should be either a variable, indirect variable reference or component
@@ -2634,7 +2650,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
locus * where)
{
int n;
- tree index;
+ tree offset, cst_offset;
tree tmp;
tree stride;
gfc_se indexse;
@@ -2669,10 +2685,12 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
return;
}
- index = gfc_index_zero_node;
+ cst_offset = offset = gfc_index_zero_node;
+ add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
- /* Calculate the offsets from all the dimensions. */
- for (n = 0; n < ar->dimen; n++)
+ /* 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 = ar->dimen - 1; n >= 0; n--)
{
/* Calculate the index for this dimension. */
gfc_init_se (&indexse, se);
@@ -2741,19 +2759,17 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
indexse.expr, stride);
/* And add it to the total. */
- index = fold_build2_loc (input_location, PLUS_EXPR,
- gfc_array_index_type, index, tmp);
+ add_to_offset (&cst_offset, &offset, tmp);
}
- tmp = gfc_conv_array_offset (se->expr);
- if (!integer_zerop (tmp))
- index = fold_build2_loc (input_location, PLUS_EXPR,
- gfc_array_index_type, index, tmp);
+ if (!integer_zerop (cst_offset))
+ offset = fold_build2_loc (input_location, PLUS_EXPR,
+ gfc_array_index_type, offset, cst_offset);
/* Access the calculated element. */
tmp = gfc_conv_array_data (se->expr);
tmp = build_fold_indirect_ref (tmp);
- se->expr = gfc_build_array_ref (tmp, index, sym->backend_decl);
+ se->expr = gfc_build_array_ref (tmp, offset, sym->backend_decl);
}
@@ -7575,7 +7591,7 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
switch (ar->type)
{
case AR_ELEMENT:
- for (n = 0; n < ar->dimen + ar->codimen; n++)
+ for (n = ar->dimen + ar->codimen - 1; n >= 0; n--)
{
newss = gfc_get_ss ();
newss->type = GFC_SS_SCALAR;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d1d4569..9145186 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-08-04 Richard Guenther <rguenther@suse.de>
+
+ PR fortran/49957
+ * gfortran.dg/vect/O3-pr49957.f: New testcase.
+
2011-08-04 Ian Bolton <ian.bolton@arm.com>
* gcc.target/arm/vfp-1.c: no large negative offsets on Thumb2.
diff --git a/gcc/testsuite/gfortran.dg/vect/O3-pr49957.f b/gcc/testsuite/gfortran.dg/vect/O3-pr49957.f
new file mode 100644
index 0000000..a973567
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/O3-pr49957.f
@@ -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 } } }