aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-forwprop.cc')
-rw-r--r--gcc/tree-ssa-forwprop.cc100
1 files changed, 97 insertions, 3 deletions
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 4c048a9..27197bb 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -205,7 +205,6 @@ struct _vec_perm_simplify_seq
typedef struct _vec_perm_simplify_seq *vec_perm_simplify_seq;
static bool forward_propagate_addr_expr (tree, tree, bool);
-static void optimize_vector_load (gimple_stmt_iterator *);
/* Set to true if we delete dead edges during the optimization. */
static bool cfg_changed;
@@ -1226,7 +1225,8 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
gimple *defstmt;
unsigned limit = param_sccvn_max_alias_queries_per_access;
do {
- if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME)
+ /* If the vuse is the default definition, then there is no stores beforhand. */
+ if (SSA_NAME_IS_DEFAULT_DEF (vuse))
return false;
defstmt = SSA_NAME_DEF_STMT (vuse);
if (is_a <gphi*>(defstmt))
@@ -1323,6 +1323,7 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
tree ctor = build_constructor (TREE_TYPE (dest), NULL);
gimple_assign_set_rhs_from_tree (gsip, ctor);
update_stmt (stmt);
+ statistics_counter_event (cfun, "copy zeroing propagation of aggregate", 1);
}
else /* If stmt is memcpy, transform it into memset. */
{
@@ -1332,6 +1333,7 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
gimple_call_set_fntype (call, TREE_TYPE (fndecl));
gimple_call_set_arg (call, 1, val);
update_stmt (stmt);
+ statistics_counter_event (cfun, "memcpy to memset changed", 1);
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1341,6 +1343,88 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
}
return true;
}
+/* Optimizes
+ a = c;
+ b = a;
+ into
+ a = c;
+ b = c;
+ GSIP is the second statement and SRC is the common
+ between the statements.
+*/
+static bool
+optimize_agr_copyprop (gimple_stmt_iterator *gsip)
+{
+ gimple *stmt = gsi_stmt (*gsip);
+ if (gimple_has_volatile_ops (stmt))
+ return false;
+
+ tree dest = gimple_assign_lhs (stmt);
+ tree src = gimple_assign_rhs1 (stmt);
+ /* If the statement is `src = src;` then ignore it. */
+ if (operand_equal_p (dest, src, 0))
+ return false;
+
+ tree vuse = gimple_vuse (stmt);
+ /* If the vuse is the default definition, then there is no store beforehand. */
+ if (SSA_NAME_IS_DEFAULT_DEF (vuse))
+ return false;
+ gimple *defstmt = SSA_NAME_DEF_STMT (vuse);
+ if (!gimple_assign_load_p (defstmt)
+ || !gimple_store_p (defstmt))
+ return false;
+ if (gimple_has_volatile_ops (defstmt))
+ return false;
+
+ tree dest2 = gimple_assign_lhs (defstmt);
+ tree src2 = gimple_assign_rhs1 (defstmt);
+
+ /* If the original store is `src2 = src2;` skip over it. */
+ if (operand_equal_p (src2, dest2, 0))
+ return false;
+ if (!operand_equal_p (src, dest2, 0))
+ return false;
+
+
+ /* For 2 memory refences and using a temporary to do the copy,
+ don't remove the temporary as the 2 memory references might overlap.
+ Note t does not need to be decl as it could be field.
+ See PR 22237 for full details.
+ E.g.
+ t = *a;
+ *b = t;
+ Cannot be convert into
+ t = *a;
+ *b = *a;
+ Though the following is allowed to be done:
+ t = *a;
+ *a = t;
+ And convert it into:
+ t = *a;
+ *a = *a;
+ */
+ if (!operand_equal_p (src2, dest, 0)
+ && !DECL_P (dest) && !DECL_P (src2))
+ return false;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Simplified\n ");
+ print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+ fprintf (dump_file, "after previous\n ");
+ print_gimple_stmt (dump_file, defstmt, 0, dump_flags);
+ }
+ gimple_assign_set_rhs_from_tree (gsip, unshare_expr (src2));
+ update_stmt (stmt);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "into\n ");
+ print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+ }
+ statistics_counter_event (cfun, "copy prop for aggregate", 1);
+ return true;
+}
/* *GSI_P is a GIMPLE_CALL to a builtin function.
Optimize
@@ -3384,6 +3468,7 @@ optimize_vector_load (gimple_stmt_iterator *gsi)
gimple *stmt = gsi_stmt (*gsi);
tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
+ tree vuse = gimple_vuse (stmt);
/* Gather BIT_FIELD_REFs to rewrite, looking through
VEC_UNPACK_{LO,HI}_EXPR. */
@@ -3492,6 +3577,7 @@ optimize_vector_load (gimple_stmt_iterator *gsi)
gimple *new_stmt = gimple_build_assign (tem, new_rhs);
location_t loc = gimple_location (use_stmt);
gimple_set_location (new_stmt, loc);
+ gimple_set_vuse (new_stmt, vuse);
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
/* Perform scalar promotion. */
new_stmt = gimple_build_assign (gimple_assign_lhs (use_stmt),
@@ -3511,6 +3597,7 @@ optimize_vector_load (gimple_stmt_iterator *gsi)
new_rhs);
location_t loc = gimple_location (use_stmt);
gimple_set_location (new_stmt, loc);
+ gimple_set_vuse (new_stmt, vuse);
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
}
gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
@@ -4164,7 +4251,7 @@ const pass_data pass_data_forwprop =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_update_ssa, /* todo_flags_finish */
+ 0, /* todo_flags_finish */
};
class pass_forwprop : public gimple_opt_pass
@@ -4401,6 +4488,7 @@ pass_forwprop::execute (function *fun)
component-wise loads. */
use_operand_p use_p;
imm_use_iterator iter;
+ tree vuse = gimple_vuse (stmt);
bool rewrite = true;
FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
{
@@ -4440,6 +4528,7 @@ pass_forwprop::execute (function *fun)
location_t loc = gimple_location (use_stmt);
gimple_set_location (new_stmt, loc);
+ gimple_set_vuse (new_stmt, vuse);
gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
unlink_stmt_vdef (use_stmt);
gsi_remove (&gsi2, true);
@@ -4717,6 +4806,11 @@ pass_forwprop::execute (function *fun)
changed = true;
break;
}
+ if (optimize_agr_copyprop (&gsi))
+ {
+ changed = true;
+ break;
+ }
}
if (TREE_CODE_CLASS (code) == tcc_comparison)