diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f7b303a9f3c..74dac1cb911 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-07-13 Richard Guenther + + PR tree-optimization/53907 + * tree-ssa-forwprop.c (associate_pointerplus): New function. + (ssa_forward_propagate_and_combine): Call it. + 2012-07-13 Richard Guenther PR tree-optimization/53922 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c6286636b14..9e6e3b4b5f1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-07-13 Richard Guenther + + PR tree-optimization/53907 + * gcc.target/i386/pr53907.c: New testcase. + 2012-07-13 Richard Guenther 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 index 00000000000..8de8f0de985 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr53907.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -msse2" } */ + +#include + +__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" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 3c01623130c..60d53770417 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -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)