diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3abb393d22a..281540f416f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2012-09-10 Marc Glisse + + * tree-ssa-forwprop.c (simplify_bitfield_ref): New function. + (ssa_forward_propagate_and_combine): Call it. + 2012-09-10 Steve Ellcey * config.gcc: Add mips*-mti-linux* target diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b8f4c39350d..dc3577401e8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-09-10 Marc Glisse + + * gcc.dg/tree-ssa/forwprop-21.c: New testcase. + 2012-09-10 Aldy Hernandez * gcc.dg/tm/reg-promotion.c: Modify dump message check. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-21.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-21.c new file mode 100644 index 00000000000..4859fa8c305 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-21.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ +typedef int v4si __attribute__ ((vector_size (4 * sizeof(int)))); + +int +test (v4si *x, v4si *y) +{ + v4si m = { 2, 3, 6, 5 }; + v4si z = __builtin_shuffle (*x, *y, m); + return z[2]; +} +/* { dg-final { scan-tree-dump-not "VEC_PERM_EXPR" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 72217ecbdd5..5692e21f19d 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -2574,6 +2574,78 @@ combine_conversions (gimple_stmt_iterator *gsi) return 0; } +/* Combine an element access with a shuffle. Returns true if there were + any changes made, else it returns false. */ + +static bool +simplify_bitfield_ref (gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + gimple def_stmt; + tree op, op0, op1, op2; + tree elem_type; + unsigned idx, n, size; + enum tree_code code; + + op = gimple_assign_rhs1 (stmt); + gcc_checking_assert (TREE_CODE (op) == BIT_FIELD_REF); + + op0 = TREE_OPERAND (op, 0); + if (TREE_CODE (op0) != SSA_NAME + || TREE_CODE (TREE_TYPE (op0)) != VECTOR_TYPE) + return false; + + elem_type = TREE_TYPE (TREE_TYPE (op0)); + if (TREE_TYPE (op) != elem_type) + return false; + + size = TREE_INT_CST_LOW (TYPE_SIZE (elem_type)); + op1 = TREE_OPERAND (op, 1); + n = TREE_INT_CST_LOW (op1) / size; + if (n != 1) + return false; + + def_stmt = SSA_NAME_DEF_STMT (op0); + if (!def_stmt || !is_gimple_assign (def_stmt) + || !can_propagate_from (def_stmt)) + return false; + + op2 = TREE_OPERAND (op, 2); + idx = TREE_INT_CST_LOW (op2) / size; + + code = gimple_assign_rhs_code (def_stmt); + + if (code == VEC_PERM_EXPR) + { + tree p, m, index, tem; + unsigned nelts; + m = gimple_assign_rhs3 (def_stmt); + if (TREE_CODE (m) != VECTOR_CST) + return false; + nelts = VECTOR_CST_NELTS (m); + idx = TREE_INT_CST_LOW (VECTOR_CST_ELT (m, idx)); + idx %= 2 * nelts; + if (idx < nelts) + { + p = gimple_assign_rhs1 (def_stmt); + } + else + { + p = gimple_assign_rhs2 (def_stmt); + idx -= nelts; + } + index = build_int_cst (TREE_TYPE (TREE_TYPE (m)), idx * size); + tem = build3 (BIT_FIELD_REF, TREE_TYPE (op), + unshare_expr (p), op1, index); + gimple_assign_set_rhs1 (stmt, tem); + fold_stmt (gsi); + update_stmt (gsi_stmt (*gsi)); + return true; + } + + return false; +} + /* Determine whether applying the 2 permutations (mask1 then mask2) gives back one of the input. */ @@ -2891,6 +2963,8 @@ ssa_forward_propagate_and_combine (void) cfg_changed = true; changed = did_something != 0; } + else if (code == BIT_FIELD_REF) + changed = simplify_bitfield_ref (&gsi); break; }