If one writes p - ((intptr_t)p % align) to align a pointer we neither
produce optimal code for the aligning nor can we track the alignment
for the resulting pointer from within CCP.  The following makes
sure we transform the above to p & ~align instead.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2012-07-13  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/53907
        * tree-ssa-forwprop.c (associate_pointerplus): New function.
        (ssa_forward_propagate_and_combine): Call it.

        * gcc.target/i386/pr53907.c: New testcase.

Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c     (revision 189458)
--- gcc/tree-ssa-forwprop.c     (working copy)
***************
*** 2474,2479 ****
--- 2465,2523 ----
    return false;
  }
  
+ /* Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI.  Returns
+    true if anything changed, false otherwise.  */
+ 
+ static bool
+ associate_pointerplus (gimple_stmt_iterator *gsi)
+ {
+   gimple stmt = gsi_stmt (*gsi);
+   gimple def_stmt;
+   tree ptr, rhs, algn;
+ 
+   /* Pattern match
+        tem = (sizetype) ptr;
+        tem = tem & algn;
+        tem = -tem;
+        ... = ptr p+ tem;
+      and produce the simpler and easier to analyze with respect to alignment
+        ... = ptr & ~algn;  */
+   ptr = gimple_assign_rhs1 (stmt);
+   rhs = gimple_assign_rhs2 (stmt);
+   if (TREE_CODE (rhs) != SSA_NAME)
+     return false;
+   def_stmt = SSA_NAME_DEF_STMT (rhs);
+   if (!is_gimple_assign (def_stmt)
+       || gimple_assign_rhs_code (def_stmt) != NEGATE_EXPR)
+     return false;
+   rhs = gimple_assign_rhs1 (def_stmt);
+   if (TREE_CODE (rhs) != SSA_NAME)
+     return false;
+   def_stmt = SSA_NAME_DEF_STMT (rhs);
+   if (!is_gimple_assign (def_stmt)
+       || gimple_assign_rhs_code (def_stmt) != BIT_AND_EXPR)
+     return false;
+   rhs = gimple_assign_rhs1 (def_stmt);
+   algn = gimple_assign_rhs2 (def_stmt);
+   if (TREE_CODE (rhs) != SSA_NAME
+       || TREE_CODE (algn) != INTEGER_CST)
+     return false;
+   def_stmt = SSA_NAME_DEF_STMT (rhs);
+   if (!is_gimple_assign (def_stmt)
+       || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
+     return false;
+   if (gimple_assign_rhs1 (def_stmt) != ptr)
+     return false;
+ 
+   algn = double_int_to_tree (TREE_TYPE (ptr),
+                            double_int_not (tree_to_double_int (algn)));
+   gimple_assign_set_rhs_with_ops (gsi, BIT_AND_EXPR, ptr, algn);
+   fold_stmt_inplace (gsi);
+   update_stmt (stmt);
+ 
+   return true;
+ }
+ 
  /* Combine two conversions in a row for the second conversion at *GSI.
     Returns 1 if there were any changes made, 2 if cfg-cleanup needs to
     run.  Else it returns 0.  */
*************** ssa_forward_propagate_and_combine (void)
*** 2815,2820 ****
--- 2850,2857 ----
                else if (code == PLUS_EXPR
                         || code == MINUS_EXPR)
                  changed = associate_plusminus (&gsi);
+               else if (code == POINTER_PLUS_EXPR)
+                 changed = associate_pointerplus (&gsi);
                else if (CONVERT_EXPR_CODE_P (code)
                         || code == FLOAT_EXPR
                         || code == FIX_TRUNC_EXPR)
Index: gcc/testsuite/gcc.target/i386/pr53907.c
===================================================================
*** gcc/testsuite/gcc.target/i386/pr53907.c     (revision 0)
--- gcc/testsuite/gcc.target/i386/pr53907.c     (working copy)
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -msse2" } */
+ 
+ #include <emmintrin.h>
+ 
+ __m128i x(char *s)
+ {
+   __m128i sz,z,mvec;
+   s-=((unsigned long) s)%16;
+   sz=_mm_load_si128((__m128i *)s);
+   return sz;
+ }
+ 
+ /* { dg-final { scan-assembler "movdqa" } } */

Reply via email to