aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2012-08-21 13:27:00 +0000
committerMarc Glisse <marc.glisse@inria.fr>2012-08-21 13:27:00 +0000
commit1b1e1c18379012b32eef89c16d76bc5f11441ccf (patch)
treeed52f070800b50c7623028376b73988cddec35ad /gcc/tree-ssa-forwprop.c
parent0b60732ea38c8e14b30acb634911f695c32215c1 (diff)
2012-08-21 Marc Glisse <marc.glisse@inria.fr>
gcc/ * fold-const.c (fold_ternary_loc): Detect identity permutations. Canonicalize permutations more. * tree-ssa-forwprop.c (is_combined_permutation_identity): New function. (simplify_permutation): Likewise. (ssa_forward_propagate_and_combine): Call it. gcc/testsuite/ * gcc.dg/tree-ssa/forwprop-19.c: New testcase. * gcc.dg/fold-perm.c: Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@190561 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc/tree-ssa-forwprop.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index bd9b72b9ea5..532b9c5c688 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2577,6 +2577,95 @@ combine_conversions (gimple_stmt_iterator *gsi)
return 0;
}
+/* Determine whether applying the 2 permutations (mask1 then mask2)
+ gives back one of the input. */
+
+static int
+is_combined_permutation_identity (tree mask1, tree mask2)
+{
+ tree mask;
+ unsigned int nelts, i, j;
+ bool maybe_identity1 = true;
+ bool maybe_identity2 = true;
+
+ gcc_checking_assert (TREE_CODE (mask1) == VECTOR_CST
+ && TREE_CODE (mask2) == VECTOR_CST);
+ mask = fold_ternary (VEC_PERM_EXPR, TREE_TYPE (mask1), mask1, mask1, mask2);
+ gcc_assert (TREE_CODE (mask) == VECTOR_CST);
+
+ nelts = VECTOR_CST_NELTS (mask);
+ for (i = 0; i < nelts; i++)
+ {
+ tree val = VECTOR_CST_ELT (mask, i);
+ gcc_assert (TREE_CODE (val) == INTEGER_CST);
+ j = TREE_INT_CST_LOW (val) & (2 * nelts - 1);
+ if (j == i)
+ maybe_identity2 = false;
+ else if (j == i + nelts)
+ maybe_identity1 = false;
+ else
+ return 0;
+ }
+ return maybe_identity1 ? 1 : maybe_identity2 ? 2 : 0;
+}
+
+/* Combine two shuffles in a row. Returns 1 if there were any changes
+ made, 2 if cfg-cleanup needs to run. Else it returns 0. */
+
+static int
+simplify_permutation (gimple_stmt_iterator *gsi)
+{
+ gimple stmt = gsi_stmt (*gsi);
+ gimple def_stmt;
+ tree op0, op1, op2, op3;
+ enum tree_code code = gimple_assign_rhs_code (stmt);
+ enum tree_code code2;
+
+ gcc_checking_assert (code == VEC_PERM_EXPR);
+
+ op0 = gimple_assign_rhs1 (stmt);
+ op1 = gimple_assign_rhs2 (stmt);
+ op2 = gimple_assign_rhs3 (stmt);
+
+ if (TREE_CODE (op0) != SSA_NAME)
+ return 0;
+
+ if (TREE_CODE (op2) != VECTOR_CST)
+ return 0;
+
+ if (op0 != op1)
+ return 0;
+
+ def_stmt = SSA_NAME_DEF_STMT (op0);
+ if (!def_stmt || !is_gimple_assign (def_stmt)
+ || !can_propagate_from (def_stmt))
+ return 0;
+
+ code2 = gimple_assign_rhs_code (def_stmt);
+
+ /* Two consecutive shuffles. */
+ if (code2 == VEC_PERM_EXPR)
+ {
+ tree orig;
+ int ident;
+ op3 = gimple_assign_rhs3 (def_stmt);
+ if (TREE_CODE (op3) != VECTOR_CST)
+ return 0;
+ ident = is_combined_permutation_identity (op3, op2);
+ if (!ident)
+ return 0;
+ orig = (ident == 1) ? gimple_assign_rhs1 (def_stmt)
+ : gimple_assign_rhs2 (def_stmt);
+ gimple_assign_set_rhs1 (stmt, unshare_expr (orig));
+ gimple_assign_set_rhs_code (stmt, TREE_CODE (orig));
+ gimple_set_num_ops (stmt, 2);
+ update_stmt (stmt);
+ return remove_prop_source_from_use (op0) ? 2 : 1;
+ }
+
+ return false;
+}
+
/* Main entry point for the forward propagation and statement combine
optimizer. */
@@ -2739,6 +2828,13 @@ ssa_forward_propagate_and_combine (void)
cfg_changed = true;
changed = did_something != 0;
}
+ else if (code == VEC_PERM_EXPR)
+ {
+ int did_something = simplify_permutation (&gsi);
+ if (did_something == 2)
+ cfg_changed = true;
+ changed = did_something != 0;
+ }
break;
}