summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc/tree-ssa-forwprop.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index e8a92ed6c16..a12c8e0c6ff 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2996,6 +2996,69 @@ combine_conversions (gimple_stmt_iterator *gsi)
return 0;
}
+/* Combine VIEW_CONVERT_EXPRs with their defining statement. */
+
+static bool
+simplify_vce (gimple_stmt_iterator *gsi)
+{
+ gimple stmt = gsi_stmt (*gsi);
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+
+ /* Drop useless VIEW_CONVERT_EXPRs. */
+ tree op = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+ if (useless_type_conversion_p (type, TREE_TYPE (op)))
+ {
+ gimple_assign_set_rhs1 (stmt, op);
+ update_stmt (stmt);
+ return true;
+ }
+
+ if (TREE_CODE (op) != SSA_NAME)
+ return false;
+
+ gimple def_stmt = SSA_NAME_DEF_STMT (op);
+ if (!is_gimple_assign (def_stmt))
+ return false;
+
+ tree def_op = gimple_assign_rhs1 (def_stmt);
+ switch (gimple_assign_rhs_code (def_stmt))
+ {
+ CASE_CONVERT:
+ /* Strip integral conversions that do not change the precision. */
+ if ((INTEGRAL_TYPE_P (TREE_TYPE (op))
+ || POINTER_TYPE_P (TREE_TYPE (op)))
+ && (INTEGRAL_TYPE_P (TREE_TYPE (def_op))
+ || POINTER_TYPE_P (TREE_TYPE (def_op)))
+ && (TYPE_PRECISION (TREE_TYPE (op))
+ == TYPE_PRECISION (TREE_TYPE (def_op))))
+ {
+ TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) = def_op;
+ update_stmt (stmt);
+ return true;
+ }
+ break;
+
+ case VIEW_CONVERT_EXPR:
+ /* Series of VIEW_CONVERT_EXPRs on register operands can
+ be contracted. */
+ if (TREE_CODE (TREE_OPERAND (def_op, 0)) == SSA_NAME)
+ {
+ if (useless_type_conversion_p (type,
+ TREE_TYPE (TREE_OPERAND (def_op, 0))))
+ gimple_assign_set_rhs1 (stmt, TREE_OPERAND (def_op, 0));
+ else
+ TREE_OPERAND (gimple_assign_rhs1 (stmt), 0)
+ = TREE_OPERAND (def_op, 0);
+ update_stmt (stmt);
+ return true;
+ }
+
+ default:;
+ }
+
+ return false;
+}
+
/* Combine an element access with a shuffle. Returns true if there were
any changes made, else it returns false. */
@@ -3493,6 +3556,8 @@ ssa_forward_propagate_and_combine (void)
changed = did_something != 0;
}
+ else if (code == VIEW_CONVERT_EXPR)
+ changed = simplify_vce (&gsi);
else if (code == VEC_PERM_EXPR)
{
int did_something = simplify_permutation (&gsi);