Patchwork PATCH: PR tree-optimization/45764: [4.6 Regression] wrong code -O2 vs -O3 (problem in vectorizer???)]

login
register
mail settings
Submitter H.J. Lu
Date Oct. 3, 2010, 11:07 a.m.
Message ID <20101003110727.GA20227@intel.com>
Download mbox | patch
Permalink /patch/66596/
State New
Headers show

Comments

H.J. Lu - Oct. 3, 2010, 11:07 a.m.
Resend. Last one may be lost.


H.J.
----- Forwarded message from "H.J. Lu" <hongjiu.lu@intel.com> -----

Date: Sat, 2 Oct 2010 22:17:10 -0700
From: "H.J. Lu" <hongjiu.lu@intel.com>
To: gcc-patches@gcc.gnu.org
Subject: PATCH: PR tree-optimization/45764: [4.6 Regression] wrong code -O2 vs
	-O3 (problem in vectorizer???)
User-Agent: Mutt/1.5.20 (2009-12-10)

Hi,

Revision 164367:

http://gcc.gnu.org/ml/gcc-cvs/2010-09/msg00661.html

tried to fix a missed optimization bug. But it breaks the vectorizer
for 2 weeks.  I am checking this patch to revert it.


H.J.
----
gcc/

2010-10-01  H.J. Lu  <hongjiu.lu@intel.com>

	PR tree-optimization/45720
	PR tree-optimization/45764
	* tree-vect-data-refs.c (vect_analyze_data_ref_access):
	Don't accept backwards consecutive accesses.
	(vect_create_data_ref_ptr): Disallow negative steps.

    	* tree-vect-stmts.c (vectorizable_store): Allow negative steps.
	(perm_mask_for_reverse): Removed.
	(reverse_vec_elements): Likewise.
	(vectorizable_load): Don't hanle negative steps.
    
gcc/testsuite/

2010-10-01  H.J. Lu  <hongjiu.lu@intel.com>

	PR tree-optimization/45720
	PR tree-optimization/45764
	* g++.dg/torture/pr45764.C: New.

	* gcc.dg/vect/pr43432.c: Xfail.
	* gcc.dg/vect/vect-114.c: Likewise.
	* gcc.dg/vect/vect-15.c: Likewise.


----- End forwarded message -----
Richard Guenther - Oct. 3, 2010, 3:42 p.m.
On Sun, Oct 3, 2010 at 1:07 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> Resend. Last one may be lost.

HJ, you can't simply revert patches this way.  Please re-install.

Thanks,
Richard.

>
> H.J.
> ----- Forwarded message from "H.J. Lu" <hongjiu.lu@intel.com> -----
>
> Date: Sat, 2 Oct 2010 22:17:10 -0700
> From: "H.J. Lu" <hongjiu.lu@intel.com>
> To: gcc-patches@gcc.gnu.org
> Subject: PATCH: PR tree-optimization/45764: [4.6 Regression] wrong code -O2 vs
>        -O3 (problem in vectorizer???)
> User-Agent: Mutt/1.5.20 (2009-12-10)
>
> Hi,
>
> Revision 164367:
>
> http://gcc.gnu.org/ml/gcc-cvs/2010-09/msg00661.html
>
> tried to fix a missed optimization bug. But it breaks the vectorizer
> for 2 weeks.  I am checking this patch to revert it.
>
>
> H.J.
> ----
> gcc/
>
> 2010-10-01  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR tree-optimization/45720
>        PR tree-optimization/45764
>        * tree-vect-data-refs.c (vect_analyze_data_ref_access):
>        Don't accept backwards consecutive accesses.
>        (vect_create_data_ref_ptr): Disallow negative steps.
>
>        * tree-vect-stmts.c (vectorizable_store): Allow negative steps.
>        (perm_mask_for_reverse): Removed.
>        (reverse_vec_elements): Likewise.
>        (vectorizable_load): Don't hanle negative steps.
>
> gcc/testsuite/
>
> 2010-10-01  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR tree-optimization/45720
>        PR tree-optimization/45764
>        * g++.dg/torture/pr45764.C: New.
>
>        * gcc.dg/vect/pr43432.c: Xfail.
>        * gcc.dg/vect/vect-114.c: Likewise.
>        * gcc.dg/vect/vect-15.c: Likewise.
>
> diff --git a/gcc/testsuite/gcc.dg/vect/pr43432.c b/gcc/testsuite/gcc.dg/vect/pr43432.c
> index 18c0dba..a979a5c 100644
> --- a/gcc/testsuite/gcc.dg/vect/pr43432.c
> +++ b/gcc/testsuite/gcc.dg/vect/pr43432.c
> @@ -10,5 +10,5 @@ int len){
>         dst[i] = src0[i] * src1[-i];
>  }
>
> -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm } } } } */
> +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_perm } } } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-114.c b/gcc/testsuite/gcc.dg/vect/vect-114.c
> index f9132ac..4964a83 100644
> --- a/gcc/testsuite/gcc.dg/vect/vect-114.c
> +++ b/gcc/testsuite/gcc.dg/vect/vect-114.c
> @@ -35,6 +35,6 @@ int main (void)
>  }
>
>  /* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! vect_perm } } } } */
> -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
> +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_perm } } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
>
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-15.c b/gcc/testsuite/gcc.dg/vect/vect-15.c
> index 87853c1..d4621d3 100644
> --- a/gcc/testsuite/gcc.dg/vect/vect-15.c
> +++ b/gcc/testsuite/gcc.dg/vect/vect-15.c
> @@ -35,5 +35,5 @@ int main (void)
>   return main1 ();
>  }
>
> -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
> +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_perm } } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
> diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
> index 7182513..0d1e338 100644
> --- a/gcc/tree-vect-data-refs.c
> +++ b/gcc/tree-vect-data-refs.c
> @@ -2287,9 +2287,7 @@ vect_analyze_data_ref_access (struct data_reference *dr)
>     }
>
>   /* Consecutive?  */
> -  if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type))
> -      || (dr_step < 0
> -         && !compare_tree_int (TYPE_SIZE_UNIT (scalar_type), -dr_step)))
> +  if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type)))
>     {
>       /* Mark that it is not interleaving.  */
>       DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)) = NULL;
> @@ -2972,7 +2970,6 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
>   tree vptr;
>   gimple_stmt_iterator incr_gsi;
>   bool insert_after;
> -  bool negative;
>   tree indx_before_incr, indx_after_incr;
>   gimple incr;
>   tree step;
> @@ -3005,7 +3002,6 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
>     *inv_p = true;
>   else
>     *inv_p = false;
> -  negative = tree_int_cst_compare (step, size_zero_node) < 0;
>
>   /* Create an expression for the first address accessed by this load
>      in LOOP.  */
> @@ -3164,8 +3160,6 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
>         LOOP is zero. In this case the step here is also zero.  */
>       if (*inv_p)
>        step = size_zero_node;
> -      else if (negative)
> -       step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step);
>
>       standard_iv_increment_position (loop, &incr_gsi, &insert_after);
>
> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
> index b120dc6..a758410 100644
> --- a/gcc/tree-vect-stmts.c
> +++ b/gcc/tree-vect-stmts.c
> @@ -3145,13 +3145,6 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
>   if (!STMT_VINFO_DATA_REF (stmt_info))
>     return false;
>
> -  if (tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0)
> -    {
> -      if (vect_print_dump_info (REPORT_DETAILS))
> -        fprintf (vect_dump, "negative step for store.");
> -      return false;
> -    }
> -
>   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
>     {
>       strided_store = true;
> @@ -3432,68 +3425,6 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
>   return true;
>  }
>
> -/* Given a vector type VECTYPE returns a builtin DECL to be used
> -   for vector permutation and stores a mask into *MASK that implements
> -   reversal of the vector elements.  If that is impossible to do
> -   returns NULL (and *MASK is unchanged).  */
> -
> -static tree
> -perm_mask_for_reverse (tree vectype, tree *mask)
> -{
> -  tree builtin_decl;
> -  tree mask_element_type, mask_type;
> -  tree mask_vec = NULL;
> -  int i;
> -  int nunits;
> -  if (!targetm.vectorize.builtin_vec_perm)
> -    return NULL;
> -
> -  builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
> -                                                     &mask_element_type);
> -  if (!builtin_decl || !mask_element_type)
> -    return NULL;
> -
> -  mask_type = get_vectype_for_scalar_type (mask_element_type);
> -  nunits = TYPE_VECTOR_SUBPARTS (vectype);
> -  if (TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
> -    return NULL;
> -
> -  for (i = 0; i < nunits; i++)
> -    mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec);
> -  mask_vec = build_vector (mask_type, mask_vec);
> -
> -  if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec))
> -    return NULL;
> -  if (mask)
> -    *mask = mask_vec;
> -  return builtin_decl;
> -}
> -
> -/* Given a vector variable X, that was generated for the scalar LHS of
> -   STMT, generate instructions to reverse the vector elements of X,
> -   insert them a *GSI and return the permuted vector variable.  */
> -
> -static tree
> -reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi)
> -{
> -  tree vectype = TREE_TYPE (x);
> -  tree mask_vec, builtin_decl;
> -  tree perm_dest, data_ref;
> -  gimple perm_stmt;
> -
> -  builtin_decl = perm_mask_for_reverse (vectype, &mask_vec);
> -
> -  perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype);
> -
> -  /* Generate the permute statement.  */
> -  perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec);
> -  data_ref = make_ssa_name (perm_dest, perm_stmt);
> -  gimple_call_set_lhs (perm_stmt, data_ref);
> -  vect_finish_stmt_generation (stmt, perm_stmt, gsi);
> -
> -  return data_ref;
> -}
> -
>  /* vectorizable_load.
>
>    Check if STMT reads a non scalar data-ref (array/pointer/structure) that
> @@ -3536,7 +3467,6 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
>   gimple first_stmt;
>   tree scalar_type;
>   bool inv_p;
> -  bool negative;
>   bool compute_in_loop = false;
>   struct loop *at_loop;
>   int vec_num;
> @@ -3599,14 +3529,6 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
>   if (!STMT_VINFO_DATA_REF (stmt_info))
>     return false;
>
> -  negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
> -  if (negative && ncopies > 1)
> -    {
> -      if (vect_print_dump_info (REPORT_DETAILS))
> -        fprintf (vect_dump, "multiple types with negative step.");
> -      return false;
> -    }
> -
>   scalar_type = TREE_TYPE (DR_REF (dr));
>   mode = TYPE_MODE (vectype);
>
> @@ -3641,25 +3563,6 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
>        return false;
>     }
>
> -  if (negative)
> -    {
> -      gcc_assert (!strided_load);
> -      alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
> -      if (alignment_support_scheme != dr_aligned
> -         && alignment_support_scheme != dr_unaligned_supported)
> -       {
> -         if (vect_print_dump_info (REPORT_DETAILS))
> -           fprintf (vect_dump, "negative step but alignment required.");
> -         return false;
> -       }
> -      if (!perm_mask_for_reverse (vectype, NULL))
> -       {
> -         if (vect_print_dump_info (REPORT_DETAILS))
> -           fprintf (vect_dump, "negative step and reversing not supported.");
> -         return false;
> -       }
> -    }
> -
>   if (!vec_stmt) /* transformation not required.  */
>     {
>       STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
> @@ -3834,9 +3737,6 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
>   else
>     at_loop = loop;
>
> -  if (negative)
> -    offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1);
> -
>   prev_stmt_info = NULL;
>   for (j = 0; j < ncopies; j++)
>     {
> @@ -4025,12 +3925,6 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
>                gcc_unreachable (); /* FORNOW. */
>            }
>
> -         if (negative)
> -           {
> -             new_temp = reverse_vec_elements (new_temp, stmt, gsi);
> -             new_stmt = SSA_NAME_DEF_STMT (new_temp);
> -           }
> -
>          /* Collect vector loads and later create their permutation in
>             vect_transform_strided_load ().  */
>           if (strided_load || slp_perm)
> --- /dev/null   2010-09-09 09:16:30.485584932 -0700
> +++ gcc/gcc/testsuite/g++.dg/torture/pr45764.C  2010-10-02 21:00:46.041119115 -0700
> @@ -0,0 +1,25 @@
> +// { dg-do run }
> +
> +int result[64][16];
> +
> +int main()
> +{
> +        double dbuf[1000] = {0.0};
> +        int ibuf[900];
> +
> +        double d1 = 0.0;
> +        double d2 = 0.0;
> +        for (int i = 0; i < 900; ++i) {
> +                ibuf[i] = int(d2 - d1);
> +                d1 += dbuf[i];
> +                d2 += dbuf[i + 64];
> +        }
> +
> +        for (int i = 0; i < 64; ++i) {
> +                for (int j = 0; j < 8; ++j) {
> +                        result[i][     j] = ibuf[64 - i + 64 * j];
> +                        result[i][15 - j] = ibuf[     i + 64 * j];
> +                }
> +        }
> +       return 0;
> +}
>
> ----- End forwarded message -----
>

Patch

diff --git a/gcc/testsuite/gcc.dg/vect/pr43432.c b/gcc/testsuite/gcc.dg/vect/pr43432.c
index 18c0dba..a979a5c 100644
--- a/gcc/testsuite/gcc.dg/vect/pr43432.c
+++ b/gcc/testsuite/gcc.dg/vect/pr43432.c
@@ -10,5 +10,5 @@  int len){
         dst[i] = src0[i] * src1[-i];
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_perm } } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-114.c b/gcc/testsuite/gcc.dg/vect/vect-114.c
index f9132ac..4964a83 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-114.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-114.c
@@ -35,6 +35,6 @@  int main (void)
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! vect_perm } } } } */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_perm } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-15.c b/gcc/testsuite/gcc.dg/vect/vect-15.c
index 87853c1..d4621d3 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-15.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-15.c
@@ -35,5 +35,5 @@  int main (void)
   return main1 ();
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_perm } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 7182513..0d1e338 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2287,9 +2287,7 @@  vect_analyze_data_ref_access (struct data_reference *dr)
     }
 
   /* Consecutive?  */
-  if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type))
-      || (dr_step < 0
-	  && !compare_tree_int (TYPE_SIZE_UNIT (scalar_type), -dr_step)))
+  if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type)))
     {
       /* Mark that it is not interleaving.  */
       DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)) = NULL;
@@ -2972,7 +2970,6 @@  vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
   tree vptr;
   gimple_stmt_iterator incr_gsi;
   bool insert_after;
-  bool negative;
   tree indx_before_incr, indx_after_incr;
   gimple incr;
   tree step;
@@ -3005,7 +3002,6 @@  vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
     *inv_p = true;
   else
     *inv_p = false;
-  negative = tree_int_cst_compare (step, size_zero_node) < 0;
 
   /* Create an expression for the first address accessed by this load
      in LOOP.  */
@@ -3164,8 +3160,6 @@  vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
 	 LOOP is zero. In this case the step here is also zero.  */
       if (*inv_p)
 	step = size_zero_node;
-      else if (negative)
-	step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step);
 
       standard_iv_increment_position (loop, &incr_gsi, &insert_after);
 
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index b120dc6..a758410 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -3145,13 +3145,6 @@  vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   if (!STMT_VINFO_DATA_REF (stmt_info))
     return false;
 
-  if (tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0)
-    {
-      if (vect_print_dump_info (REPORT_DETAILS))
-        fprintf (vect_dump, "negative step for store.");
-      return false;
-    }
-
   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
     {
       strided_store = true;
@@ -3432,68 +3425,6 @@  vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   return true;
 }
 
-/* Given a vector type VECTYPE returns a builtin DECL to be used
-   for vector permutation and stores a mask into *MASK that implements
-   reversal of the vector elements.  If that is impossible to do
-   returns NULL (and *MASK is unchanged).  */
-
-static tree
-perm_mask_for_reverse (tree vectype, tree *mask)
-{
-  tree builtin_decl;
-  tree mask_element_type, mask_type;
-  tree mask_vec = NULL;
-  int i;
-  int nunits;
-  if (!targetm.vectorize.builtin_vec_perm)
-    return NULL;
-
-  builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
-                                                     &mask_element_type);
-  if (!builtin_decl || !mask_element_type)
-    return NULL;
-
-  mask_type = get_vectype_for_scalar_type (mask_element_type);
-  nunits = TYPE_VECTOR_SUBPARTS (vectype);
-  if (TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
-    return NULL;
-
-  for (i = 0; i < nunits; i++)
-    mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec);
-  mask_vec = build_vector (mask_type, mask_vec);
-
-  if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec))
-    return NULL;
-  if (mask)
-    *mask = mask_vec;
-  return builtin_decl;
-}
-
-/* Given a vector variable X, that was generated for the scalar LHS of
-   STMT, generate instructions to reverse the vector elements of X,
-   insert them a *GSI and return the permuted vector variable.  */
-
-static tree
-reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi)
-{
-  tree vectype = TREE_TYPE (x);
-  tree mask_vec, builtin_decl;
-  tree perm_dest, data_ref;
-  gimple perm_stmt;
-
-  builtin_decl = perm_mask_for_reverse (vectype, &mask_vec);
-
-  perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype);
-
-  /* Generate the permute statement.  */
-  perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec);
-  data_ref = make_ssa_name (perm_dest, perm_stmt);
-  gimple_call_set_lhs (perm_stmt, data_ref);
-  vect_finish_stmt_generation (stmt, perm_stmt, gsi);
-
-  return data_ref;
-}
-
 /* vectorizable_load.
 
    Check if STMT reads a non scalar data-ref (array/pointer/structure) that
@@ -3536,7 +3467,6 @@  vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   gimple first_stmt;
   tree scalar_type;
   bool inv_p;
-  bool negative;
   bool compute_in_loop = false;
   struct loop *at_loop;
   int vec_num;
@@ -3599,14 +3529,6 @@  vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   if (!STMT_VINFO_DATA_REF (stmt_info))
     return false;
 
-  negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
-  if (negative && ncopies > 1)
-    {
-      if (vect_print_dump_info (REPORT_DETAILS))
-        fprintf (vect_dump, "multiple types with negative step.");
-      return false;
-    }
-
   scalar_type = TREE_TYPE (DR_REF (dr));
   mode = TYPE_MODE (vectype);
 
@@ -3641,25 +3563,6 @@  vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	return false;
     }
 
-  if (negative)
-    {
-      gcc_assert (!strided_load);
-      alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
-      if (alignment_support_scheme != dr_aligned
-	  && alignment_support_scheme != dr_unaligned_supported)
-	{
-	  if (vect_print_dump_info (REPORT_DETAILS))
-	    fprintf (vect_dump, "negative step but alignment required.");
-	  return false;
-	}
-      if (!perm_mask_for_reverse (vectype, NULL))
-	{
-	  if (vect_print_dump_info (REPORT_DETAILS))
-	    fprintf (vect_dump, "negative step and reversing not supported.");
-	  return false;
-	}
-    }
-
   if (!vec_stmt) /* transformation not required.  */
     {
       STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
@@ -3834,9 +3737,6 @@  vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   else
     at_loop = loop;
 
-  if (negative)
-    offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1);
-
   prev_stmt_info = NULL;
   for (j = 0; j < ncopies; j++)
     {
@@ -4025,12 +3925,6 @@  vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 		gcc_unreachable (); /* FORNOW. */
 	    }
 
-	  if (negative)
-	    {
-	      new_temp = reverse_vec_elements (new_temp, stmt, gsi);
-	      new_stmt = SSA_NAME_DEF_STMT (new_temp);
-	    }
-
 	  /* Collect vector loads and later create their permutation in
 	     vect_transform_strided_load ().  */
           if (strided_load || slp_perm)
--- /dev/null	2010-09-09 09:16:30.485584932 -0700
+++ gcc/gcc/testsuite/g++.dg/torture/pr45764.C	2010-10-02 21:00:46.041119115 -0700
@@ -0,0 +1,25 @@ 
+// { dg-do run }
+
+int result[64][16];
+
+int main()
+{
+        double dbuf[1000] = {0.0};
+        int ibuf[900];
+
+        double d1 = 0.0;
+        double d2 = 0.0;
+        for (int i = 0; i < 900; ++i) {
+                ibuf[i] = int(d2 - d1);
+                d1 += dbuf[i];
+                d2 += dbuf[i + 64];
+        }
+
+        for (int i = 0; i < 64; ++i) {
+                for (int j = 0; j < 8; ++j) {
+                        result[i][     j] = ibuf[64 - i + 64 * j];
+                        result[i][15 - j] = ibuf[     i + 64 * j];
+                }
+        }
+	return 0;
+}