]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/53907 (gcc uses unaligned load when aligned load was requested)
authorRichard Guenther <rguenther@suse.de>
Fri, 13 Jul 2012 13:01:06 +0000 (13:01 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 13 Jul 2012 13:01:06 +0000 (13:01 +0000)
2012-07-13  Richard Guenther  <rguenther@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.

From-SVN: r189462

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr53907.c [new file with mode: 0644]
gcc/tree-ssa-forwprop.c

index f7b303a9f3c3154eae9438d9321abe49932e6396..74dac1cb911e7e213bdc265fc5bc5dcec4ecd522 100644 (file)
@@ -1,3 +1,9 @@
+2012-07-13  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53907
+       * tree-ssa-forwprop.c (associate_pointerplus): New function.
+       (ssa_forward_propagate_and_combine): Call it.
+
 2012-07-13  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/53922
index c6286636b148018ac2ceb3abbdebabdc020e953a..9e6e3b4b5f1b7a1a645b71a872776fa9457859cc 100644 (file)
@@ -1,3 +1,8 @@
+2012-07-13  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53907
+       * gcc.target/i386/pr53907.c: New testcase.
+
 2012-07-13  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/53922
diff --git a/gcc/testsuite/gcc.target/i386/pr53907.c b/gcc/testsuite/gcc.target/i386/pr53907.c
new file mode 100644 (file)
index 0000000..8de8f0d
--- /dev/null
@@ -0,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" } } */
index 3c01623130ca067e739d8f6bc822c36e291ab039..60d537704172aa2af28c67bd1f866236aad4522f 100644 (file)
@@ -2474,6 +2474,59 @@ out:
   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.  */
@@ -2815,6 +2868,8 @@ ssa_forward_propagate_and_combine (void)
                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)