aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2021-04-14 13:40:58 +0200
committerRichard Biener <rguenther@suse.de>2021-04-26 10:08:46 +0200
commit52a5515ed6619739eb122f05ce26057dd8b06fb6 (patch)
treece23cf5cca7daae1d47e61007eccfdbfe862fe13 /gcc
parent297bfacdb448c0d29b8dfac2818350b90902bc75 (diff)
downloadgcc-52a5515ed6619739eb122f05ce26057dd8b06fb6.zip
gcc-52a5515ed6619739eb122f05ce26057dd8b06fb6.tar.gz
gcc-52a5515ed6619739eb122f05ce26057dd8b06fb6.tar.bz2
Simplify {gimplify_and_,}update_call_from_tree API
This removes update_call_from_tree in favor of gimplify_and_update_call_from_tree, removing some code duplication and simplifying the API use. Some users of update_call_from_tree have been transitioned to replace_call_with_value and the API and its dependences have been moved to gimple-fold.h. This shaves off another user of valid_gimple_rhs_p which is now only used from within gimple-fold.c and thus moved and made private. 2021-04-14 Richard Biener <rguenther@suse.de> * tree-ssa-propagate.h (valid_gimple_rhs_p): Remove. (update_gimple_call): Likewise. (update_call_from_tree): Likewise. * tree-ssa-propagate.c (valid_gimple_rhs_p): Remove. (valid_gimple_call_p): Likewise. (move_ssa_defining_stmt_for_defs): Likewise. (finish_update_gimple_call): Likewise. (update_gimple_call): Likewise. (update_call_from_tree): Likewise. (propagate_tree_value_into_stmt): Use replace_call_with_value. * gimple-fold.h (update_gimple_call): Declare. * gimple-fold.c (valid_gimple_rhs_p): Move here from tree-ssa-propagate.c. (update_gimple_call): Likewise. (valid_gimple_call_p): Likewise. (finish_update_gimple_call): Likewise, and simplify. (gimplify_and_update_call_from_tree): Implement update_call_from_tree functionality, avoid excessive push/pop_gimplify_context. (gimple_fold_builtin): Use only gimplify_and_update_call_from_tree. (gimple_fold_call): Likewise. * gimple-ssa-sprintf.c (try_substitute_return_value): Likewise. * tree-ssa-ccp.c (ccp_folder::fold_stmt): Likewise. (pass_fold_builtins::execute): Likewise. (optimize_stack_restore): Use replace_call_with_value. * tree-cfg.c (fold_loop_internal_call): Likewise. * tree-ssa-dce.c (maybe_optimize_arith_overflow): Use only gimplify_and_update_call_from_tree. * tree-ssa-strlen.c (handle_builtin_strlen): Likewise. (handle_builtin_strchr): Likewise. * tsan.c: Include gimple-fold.h instead of tree-ssa-propagate.h. * config/rs6000/rs6000-call.c (rs6000_gimple_fold_builtin): Use replace_call_with_value.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000-call.c2
-rw-r--r--gcc/gimple-fold.c219
-rw-r--r--gcc/gimple-fold.h1
-rw-r--r--gcc/gimple-ssa-sprintf.c3
-rw-r--r--gcc/tree-cfg.c2
-rw-r--r--gcc/tree-ssa-ccp.c15
-rw-r--r--gcc/tree-ssa-dce.c3
-rw-r--r--gcc/tree-ssa-propagate.c300
-rw-r--r--gcc/tree-ssa-propagate.h3
-rw-r--r--gcc/tree-ssa-strlen.c9
-rw-r--r--gcc/tsan.c2
11 files changed, 226 insertions, 333 deletions
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index f567625..6f6dc47 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -12369,7 +12369,7 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
/* Convert result back to the lhs type. */
res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res);
gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
- update_call_from_tree (gsi, res);
+ replace_call_with_value (gsi, res);
return true;
}
/* Vector loads. */
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 7602018..aa33779 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -335,6 +335,123 @@ maybe_fold_reference (tree expr)
return NULL_TREE;
}
+/* Return true if EXPR is an acceptable right-hand-side for a
+ GIMPLE assignment. We validate the entire tree, not just
+ the root node, thus catching expressions that embed complex
+ operands that are not permitted in GIMPLE. This function
+ is needed because the folding routines in fold-const.c
+ may return such expressions in some cases, e.g., an array
+ access with an embedded index addition. It may make more
+ sense to have folding routines that are sensitive to the
+ constraints on GIMPLE operands, rather than abandoning any
+ any attempt to fold if the usual folding turns out to be too
+ aggressive. */
+
+bool
+valid_gimple_rhs_p (tree expr)
+{
+ enum tree_code code = TREE_CODE (expr);
+
+ switch (TREE_CODE_CLASS (code))
+ {
+ case tcc_declaration:
+ if (!is_gimple_variable (expr))
+ return false;
+ break;
+
+ case tcc_constant:
+ /* All constants are ok. */
+ break;
+
+ case tcc_comparison:
+ /* GENERIC allows comparisons with non-boolean types, reject
+ those for GIMPLE. Let vector-typed comparisons pass - rules
+ for GENERIC and GIMPLE are the same here. */
+ if (!(INTEGRAL_TYPE_P (TREE_TYPE (expr))
+ && (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
+ || TYPE_PRECISION (TREE_TYPE (expr)) == 1))
+ && ! VECTOR_TYPE_P (TREE_TYPE (expr)))
+ return false;
+
+ /* Fallthru. */
+ case tcc_binary:
+ if (!is_gimple_val (TREE_OPERAND (expr, 0))
+ || !is_gimple_val (TREE_OPERAND (expr, 1)))
+ return false;
+ break;
+
+ case tcc_unary:
+ if (!is_gimple_val (TREE_OPERAND (expr, 0)))
+ return false;
+ break;
+
+ case tcc_expression:
+ switch (code)
+ {
+ case ADDR_EXPR:
+ {
+ tree t;
+ if (is_gimple_min_invariant (expr))
+ return true;
+ t = TREE_OPERAND (expr, 0);
+ while (handled_component_p (t))
+ {
+ /* ??? More checks needed, see the GIMPLE verifier. */
+ if ((TREE_CODE (t) == ARRAY_REF
+ || TREE_CODE (t) == ARRAY_RANGE_REF)
+ && !is_gimple_val (TREE_OPERAND (t, 1)))
+ return false;
+ t = TREE_OPERAND (t, 0);
+ }
+ if (!is_gimple_id (t))
+ return false;
+ }
+ break;
+
+ default:
+ if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
+ {
+ if ((code == COND_EXPR
+ ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
+ : !is_gimple_val (TREE_OPERAND (expr, 0)))
+ || !is_gimple_val (TREE_OPERAND (expr, 1))
+ || !is_gimple_val (TREE_OPERAND (expr, 2)))
+ return false;
+ break;
+ }
+ return false;
+ }
+ break;
+
+ case tcc_vl_exp:
+ return false;
+
+ case tcc_exceptional:
+ if (code == CONSTRUCTOR)
+ {
+ unsigned i;
+ tree elt;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, elt)
+ if (!is_gimple_val (elt))
+ return false;
+ return true;
+ }
+ if (code != SSA_NAME)
+ return false;
+ break;
+
+ case tcc_reference:
+ if (code == BIT_FIELD_REF)
+ return is_gimple_val (TREE_OPERAND (expr, 0));
+ return false;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
/* Attempt to fold an assignment statement pointed-to by SI. Returns a
replacement rhs for the statement or NULL_TREE if no simplification
@@ -534,6 +651,72 @@ gsi_replace_with_seq_vops (gimple_stmt_iterator *si_p, gimple_seq stmts)
gsi_replace_with_seq (si_p, stmts, false);
}
+/* Helper function for update_gimple_call and
+ gimplify_and_update_call_from_tree. A GIMPLE_CALL STMT is being replaced
+ with GIMPLE_CALL NEW_STMT. */
+
+static void
+finish_update_gimple_call (gimple_stmt_iterator *si_p, gimple *new_stmt,
+ gimple *stmt)
+{
+ tree lhs = gimple_call_lhs (stmt);
+ gimple_call_set_lhs (new_stmt, lhs);
+ if (lhs && TREE_CODE (lhs) == SSA_NAME)
+ SSA_NAME_DEF_STMT (lhs) = new_stmt;
+ gimple_move_vops (new_stmt, stmt);
+ gimple_set_location (new_stmt, gimple_location (stmt));
+ if (gimple_block (new_stmt) == NULL_TREE)
+ gimple_set_block (new_stmt, gimple_block (stmt));
+ gsi_replace (si_p, new_stmt, false);
+}
+
+/* Update a GIMPLE_CALL statement at iterator *SI_P to call to FN
+ with number of arguments NARGS, where the arguments in GIMPLE form
+ follow NARGS argument. */
+
+bool
+update_gimple_call (gimple_stmt_iterator *si_p, tree fn, int nargs, ...)
+{
+ va_list ap;
+ gcall *new_stmt, *stmt = as_a <gcall *> (gsi_stmt (*si_p));
+
+ gcc_assert (is_gimple_call (stmt));
+ va_start (ap, nargs);
+ new_stmt = gimple_build_call_valist (fn, nargs, ap);
+ finish_update_gimple_call (si_p, new_stmt, stmt);
+ va_end (ap);
+ return true;
+}
+
+/* Return true if EXPR is a CALL_EXPR suitable for representation
+ as a single GIMPLE_CALL statement. If the arguments require
+ further gimplification, return false. */
+
+static bool
+valid_gimple_call_p (tree expr)
+{
+ unsigned i, nargs;
+
+ if (TREE_CODE (expr) != CALL_EXPR)
+ return false;
+
+ nargs = call_expr_nargs (expr);
+ for (i = 0; i < nargs; i++)
+ {
+ tree arg = CALL_EXPR_ARG (expr, i);
+ if (is_gimple_reg_type (TREE_TYPE (arg)))
+ {
+ if (!is_gimple_val (arg))
+ return false;
+ }
+ else
+ if (!is_gimple_lvalue (arg))
+ return false;
+ }
+
+ return true;
+}
+
/* Convert EXPR into a GIMPLE value suitable for substitution on the
RHS of an assignment. Insert the necessary statements before
iterator *SI_P. The statement at *SI_P, which must be a GIMPLE_CALL
@@ -556,17 +739,41 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
gcc_assert (is_gimple_call (stmt));
- push_gimplify_context (gimple_in_ssa_p (cfun));
+ if (valid_gimple_call_p (expr))
+ {
+ /* The call has simplified to another call. */
+ tree fn = CALL_EXPR_FN (expr);
+ unsigned i;
+ unsigned nargs = call_expr_nargs (expr);
+ vec<tree> args = vNULL;
+ gcall *new_stmt;
+
+ if (nargs > 0)
+ {
+ args.create (nargs);
+ args.safe_grow_cleared (nargs, true);
+
+ for (i = 0; i < nargs; i++)
+ args[i] = CALL_EXPR_ARG (expr, i);
+ }
+
+ new_stmt = gimple_build_call_vec (fn, args);
+ finish_update_gimple_call (si_p, new_stmt, stmt);
+ args.release ();
+ return;
+ }
lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
{
+ push_gimplify_context (gimple_in_ssa_p (cfun));
gimplify_and_add (expr, &stmts);
+ pop_gimplify_context (NULL);
+
/* We can end up with folding a memcpy of an empty class assignment
which gets optimized away by C++ gimplification. */
if (gimple_seq_empty_p (stmts))
{
- pop_gimplify_context (NULL);
if (gimple_in_ssa_p (cfun))
{
unlink_stmt_vdef (stmt);
@@ -585,8 +792,6 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
GSI_CONTINUE_LINKING);
}
- pop_gimplify_context (NULL);
-
gsi_replace_with_seq_vops (si_p, stmts);
}
@@ -4955,8 +5160,7 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
STRIP_NOPS (result);
else
result = fold_convert (gimple_call_return_type (stmt), result);
- if (!update_call_from_tree (gsi, result))
- gimplify_and_update_call_from_tree (gsi, result);
+ gimplify_and_update_call_from_tree (gsi, result);
return true;
}
@@ -5552,8 +5756,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
result = build2_loc (gimple_location (stmt), COMPLEX_EXPR,
ctype, result, overflow);
}
- if (!update_call_from_tree (gsi, result))
- gimplify_and_update_call_from_tree (gsi, result);
+ gimplify_and_update_call_from_tree (gsi, result);
changed = true;
}
}
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index f495dac..2401646 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -28,6 +28,7 @@ extern tree get_symbol_constant_value (tree);
struct c_strlen_data;
extern bool get_range_strlen (tree, c_strlen_data *, unsigned eltsize);
extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
+extern bool update_gimple_call (gimple_stmt_iterator *, tree, int, ...);
extern bool fold_stmt (gimple_stmt_iterator *);
extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree));
extern bool fold_stmt_inplace (gimple_stmt_iterator *);
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index fed4fe7..fc74466 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -4149,8 +4149,7 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
/* Replace the call to the bounded function with a zero size
(e.g., snprintf(0, 0, "%i", 123) with the constant result
of the function. */
- if (!update_call_from_tree (gsi, cst))
- gimplify_and_update_call_from_tree (gsi, cst);
+ gimplify_and_update_call_from_tree (gsi, cst);
gimple *callstmt = gsi_stmt (*gsi);
update_stmt (callstmt);
}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index f985867..316aa83 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -7530,7 +7530,7 @@ fold_loop_internal_call (gimple *g, tree value)
gimple *use_stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (g);
- update_call_from_tree (&gsi, value);
+ replace_call_with_value (&gsi, value);
FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
{
FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 3bfd4a6..bf31f03 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2332,12 +2332,10 @@ ccp_folder::fold_stmt (gimple_stmt_iterator *gsi)
&& (flags & ECF_LOOPING_CONST_OR_PURE) == 0)
{
tree new_rhs = unshare_expr (val);
- bool res;
if (!useless_type_conversion_p (TREE_TYPE (lhs),
TREE_TYPE (new_rhs)))
new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
- res = update_call_from_tree (gsi, new_rhs);
- gcc_assert (res);
+ gimplify_and_update_call_from_tree (gsi, new_rhs);
return true;
}
@@ -2355,9 +2353,8 @@ ccp_folder::fold_stmt (gimple_stmt_iterator *gsi)
tree new_rhs = fold_builtin_alloca_with_align (stmt);
if (new_rhs)
{
- bool res = update_call_from_tree (gsi, new_rhs);
+ gimplify_and_update_call_from_tree (gsi, new_rhs);
tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
- gcc_assert (res);
insert_clobbers_for_var (*gsi, var);
return true;
}
@@ -2382,8 +2379,7 @@ ccp_folder::fold_stmt (gimple_stmt_iterator *gsi)
&& ((TREE_INT_CST_LOW (ptrval.value) & (align - 1))
== (TREE_INT_CST_LOW (val.value) & (align - 1))))
{
- bool res = update_call_from_tree (gsi, ptr);
- gcc_assert (res);
+ replace_call_with_value (gsi, ptr);
return true;
}
}
@@ -2710,7 +2706,7 @@ optimize_stack_restore (gimple_stmt_iterator i)
stack_save_gsi = gsi_for_stmt (stack_save);
rhs = build_int_cst (TREE_TYPE (gimple_call_arg (call, 0)), 0);
- update_call_from_tree (&stack_save_gsi, rhs);
+ replace_call_with_value (&stack_save_gsi, rhs);
}
}
}
@@ -3434,8 +3430,7 @@ pass_fold_builtins::execute (function *fun)
continue;
}
- if (!update_call_from_tree (&i, result))
- gimplify_and_update_call_from_tree (&i, result);
+ gimplify_and_update_call_from_tree (&i, result);
}
todoflags |= TODO_update_address_taken;
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index c027230..096cfc8 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1274,8 +1274,7 @@ maybe_optimize_arith_overflow (gimple_stmt_iterator *gsi,
fprintf (dump_file, "\n");
}
- if (!update_call_from_tree (gsi, result))
- gimplify_and_update_call_from_tree (gsi, result);
+ gimplify_and_update_call_from_tree (gsi, result);
}
/* Eliminate unnecessary statements. Any instruction not marked as necessary
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 17dd1ef..b3dcd43 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -439,302 +439,6 @@ ssa_prop_fini (void)
}
-/* Return true if EXPR is an acceptable right-hand-side for a
- GIMPLE assignment. We validate the entire tree, not just
- the root node, thus catching expressions that embed complex
- operands that are not permitted in GIMPLE. This function
- is needed because the folding routines in fold-const.c
- may return such expressions in some cases, e.g., an array
- access with an embedded index addition. It may make more
- sense to have folding routines that are sensitive to the
- constraints on GIMPLE operands, rather than abandoning any
- any attempt to fold if the usual folding turns out to be too
- aggressive. */
-
-bool
-valid_gimple_rhs_p (tree expr)
-{
- enum tree_code code = TREE_CODE (expr);
-
- switch (TREE_CODE_CLASS (code))
- {
- case tcc_declaration:
- if (!is_gimple_variable (expr))
- return false;
- break;
-
- case tcc_constant:
- /* All constants are ok. */
- break;
-
- case tcc_comparison:
- /* GENERIC allows comparisons with non-boolean types, reject
- those for GIMPLE. Let vector-typed comparisons pass - rules
- for GENERIC and GIMPLE are the same here. */
- if (!(INTEGRAL_TYPE_P (TREE_TYPE (expr))
- && (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
- || TYPE_PRECISION (TREE_TYPE (expr)) == 1))
- && ! VECTOR_TYPE_P (TREE_TYPE (expr)))
- return false;
-
- /* Fallthru. */
- case tcc_binary:
- if (!is_gimple_val (TREE_OPERAND (expr, 0))
- || !is_gimple_val (TREE_OPERAND (expr, 1)))
- return false;
- break;
-
- case tcc_unary:
- if (!is_gimple_val (TREE_OPERAND (expr, 0)))
- return false;
- break;
-
- case tcc_expression:
- switch (code)
- {
- case ADDR_EXPR:
- {
- tree t;
- if (is_gimple_min_invariant (expr))
- return true;
- t = TREE_OPERAND (expr, 0);
- while (handled_component_p (t))
- {
- /* ??? More checks needed, see the GIMPLE verifier. */
- if ((TREE_CODE (t) == ARRAY_REF
- || TREE_CODE (t) == ARRAY_RANGE_REF)
- && !is_gimple_val (TREE_OPERAND (t, 1)))
- return false;
- t = TREE_OPERAND (t, 0);
- }
- if (!is_gimple_id (t))
- return false;
- }
- break;
-
- default:
- if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
- {
- if ((code == COND_EXPR
- ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
- : !is_gimple_val (TREE_OPERAND (expr, 0)))
- || !is_gimple_val (TREE_OPERAND (expr, 1))
- || !is_gimple_val (TREE_OPERAND (expr, 2)))
- return false;
- break;
- }
- return false;
- }
- break;
-
- case tcc_vl_exp:
- return false;
-
- case tcc_exceptional:
- if (code == CONSTRUCTOR)
- {
- unsigned i;
- tree elt;
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, elt)
- if (!is_gimple_val (elt))
- return false;
- return true;
- }
- if (code != SSA_NAME)
- return false;
- break;
-
- case tcc_reference:
- if (code == BIT_FIELD_REF)
- return is_gimple_val (TREE_OPERAND (expr, 0));
- return false;
-
- default:
- return false;
- }
-
- return true;
-}
-
-
-/* Return true if EXPR is a CALL_EXPR suitable for representation
- as a single GIMPLE_CALL statement. If the arguments require
- further gimplification, return false. */
-
-static bool
-valid_gimple_call_p (tree expr)
-{
- unsigned i, nargs;
-
- if (TREE_CODE (expr) != CALL_EXPR)
- return false;
-
- nargs = call_expr_nargs (expr);
- for (i = 0; i < nargs; i++)
- {
- tree arg = CALL_EXPR_ARG (expr, i);
- if (is_gimple_reg_type (TREE_TYPE (arg)))
- {
- if (!is_gimple_val (arg))
- return false;
- }
- else
- if (!is_gimple_lvalue (arg))
- return false;
- }
-
- return true;
-}
-
-
-/* Make SSA names defined by OLD_STMT point to NEW_STMT
- as their defining statement. */
-
-void
-move_ssa_defining_stmt_for_defs (gimple *new_stmt, gimple *old_stmt)
-{
- tree var;
- ssa_op_iter iter;
-
- if (gimple_in_ssa_p (cfun))
- {
- /* Make defined SSA_NAMEs point to the new
- statement as their definition. */
- FOR_EACH_SSA_TREE_OPERAND (var, old_stmt, iter, SSA_OP_ALL_DEFS)
- {
- if (TREE_CODE (var) == SSA_NAME)
- SSA_NAME_DEF_STMT (var) = new_stmt;
- }
- }
-}
-
-/* Helper function for update_gimple_call and update_call_from_tree.
- A GIMPLE_CALL STMT is being replaced with GIMPLE_CALL NEW_STMT. */
-
-static void
-finish_update_gimple_call (gimple_stmt_iterator *si_p, gimple *new_stmt,
- gimple *stmt)
-{
- gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
- move_ssa_defining_stmt_for_defs (new_stmt, stmt);
- gimple_move_vops (new_stmt, stmt);
- gimple_set_location (new_stmt, gimple_location (stmt));
- if (gimple_block (new_stmt) == NULL_TREE)
- gimple_set_block (new_stmt, gimple_block (stmt));
- gsi_replace (si_p, new_stmt, false);
-}
-
-/* Update a GIMPLE_CALL statement at iterator *SI_P to call to FN
- with number of arguments NARGS, where the arguments in GIMPLE form
- follow NARGS argument. */
-
-bool
-update_gimple_call (gimple_stmt_iterator *si_p, tree fn, int nargs, ...)
-{
- va_list ap;
- gcall *new_stmt, *stmt = as_a <gcall *> (gsi_stmt (*si_p));
-
- gcc_assert (is_gimple_call (stmt));
- va_start (ap, nargs);
- new_stmt = gimple_build_call_valist (fn, nargs, ap);
- finish_update_gimple_call (si_p, new_stmt, stmt);
- va_end (ap);
- return true;
-}
-
-/* Update a GIMPLE_CALL statement at iterator *SI_P to reflect the
- value of EXPR, which is expected to be the result of folding the
- call. This can only be done if EXPR is a CALL_EXPR with valid
- GIMPLE operands as arguments, or if it is a suitable RHS expression
- for a GIMPLE_ASSIGN. More complex expressions will require
- gimplification, which will introduce additional statements. In this
- event, no update is performed, and the function returns false.
- Note that we cannot mutate a GIMPLE_CALL in-place, so we always
- replace the statement at *SI_P with an entirely new statement.
- The new statement need not be a call, e.g., if the original call
- folded to a constant. */
-
-bool
-update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
-{
- gimple *stmt = gsi_stmt (*si_p);
-
- if (valid_gimple_call_p (expr))
- {
- /* The call has simplified to another call. */
- tree fn = CALL_EXPR_FN (expr);
- unsigned i;
- unsigned nargs = call_expr_nargs (expr);
- vec<tree> args = vNULL;
- gcall *new_stmt;
-
- if (nargs > 0)
- {
- args.create (nargs);
- args.safe_grow_cleared (nargs, true);
-
- for (i = 0; i < nargs; i++)
- args[i] = CALL_EXPR_ARG (expr, i);
- }
-
- new_stmt = gimple_build_call_vec (fn, args);
- finish_update_gimple_call (si_p, new_stmt, stmt);
- args.release ();
-
- return true;
- }
- else if (valid_gimple_rhs_p (expr))
- {
- tree lhs = gimple_call_lhs (stmt);
- gimple *new_stmt;
-
- /* The call has simplified to an expression
- that cannot be represented as a GIMPLE_CALL. */
- if (lhs)
- {
- /* A value is expected.
- Introduce a new GIMPLE_ASSIGN statement. */
- STRIP_USELESS_TYPE_CONVERSION (expr);
- new_stmt = gimple_build_assign (lhs, expr);
- move_ssa_defining_stmt_for_defs (new_stmt, stmt);
- gimple_move_vops (new_stmt, stmt);
- }
- else if (!TREE_SIDE_EFFECTS (expr))
- {
- /* No value is expected, and EXPR has no effect.
- Replace it with an empty statement. */
- new_stmt = gimple_build_nop ();
- if (gimple_in_ssa_p (cfun))
- {
- unlink_stmt_vdef (stmt);
- release_defs (stmt);
- }
- }
- else
- {
- /* No value is expected, but EXPR has an effect,
- e.g., it could be a reference to a volatile
- variable. Create an assignment statement
- with a dummy (unused) lhs variable. */
- STRIP_USELESS_TYPE_CONVERSION (expr);
- if (gimple_in_ssa_p (cfun))
- lhs = make_ssa_name (TREE_TYPE (expr));
- else
- lhs = create_tmp_var (TREE_TYPE (expr));
- new_stmt = gimple_build_assign (lhs, expr);
- gimple_move_vops (new_stmt, stmt);
- move_ssa_defining_stmt_for_defs (new_stmt, stmt);
- }
- gimple_set_location (new_stmt, gimple_location (stmt));
- gsi_replace (si_p, new_stmt, false);
- return true;
- }
- else
- /* The call simplified to an expression that is
- not a valid GIMPLE RHS. */
- return false;
-}
-
/* Entry point to the propagation engine.
The VISIT_STMT virtual function is called for every statement
@@ -1539,10 +1243,8 @@ propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
&& gimple_call_lhs (stmt) != NULL_TREE)
{
tree expr = NULL_TREE;
- bool res;
propagate_tree_value (&expr, val);
- res = update_call_from_tree (gsi, expr);
- gcc_assert (res);
+ replace_call_with_value (gsi, expr);
}
else if (gswitch *swtch_stmt = dyn_cast <gswitch *> (stmt))
propagate_tree_value (gimple_switch_index_ptr (swtch_stmt), val);
diff --git a/gcc/tree-ssa-propagate.h b/gcc/tree-ssa-propagate.h
index 60e2f68..5257fbb 100644
--- a/gcc/tree-ssa-propagate.h
+++ b/gcc/tree-ssa-propagate.h
@@ -63,10 +63,7 @@ enum ssa_prop_result {
};
-extern bool valid_gimple_rhs_p (tree);
extern void move_ssa_defining_stmt_for_defs (gimple *, gimple *);
-extern bool update_gimple_call (gimple_stmt_iterator *, tree, int, ...);
-extern bool update_call_from_tree (gimple_stmt_iterator *, tree);
extern bool stmt_makes_single_store (gimple *);
extern bool may_propagate_copy (tree, tree);
extern bool may_propagate_copy_into_stmt (gimple *, tree);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index cccd4a0..c7b5e2c 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -2158,8 +2158,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
if (bound)
rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
- if (!update_call_from_tree (gsi, rhs))
- gimplify_and_update_call_from_tree (gsi, rhs);
+ gimplify_and_update_call_from_tree (gsi, rhs);
stmt = gsi_stmt (*gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -2258,8 +2257,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
}
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
- if (!update_call_from_tree (gsi, ret))
- gimplify_and_update_call_from_tree (gsi, ret);
+ gimplify_and_update_call_from_tree (gsi, ret);
stmt = gsi_stmt (*gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -2337,8 +2335,7 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
TREE_TYPE (rhs)))
rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
}
- if (!update_call_from_tree (gsi, rhs))
- gimplify_and_update_call_from_tree (gsi, rhs);
+ gimplify_and_update_call_from_tree (gsi, rhs);
stmt = gsi_stmt (*gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
diff --git a/gcc/tsan.c b/gcc/tsan.c
index 7db157e..a1868b6 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify-me.h"
#include "tree-cfg.h"
#include "tree-iterator.h"
-#include "tree-ssa-propagate.h"
+#include "gimple-fold.h"
#include "tree-ssa-loop-ivopts.h"
#include "tree-eh.h"
#include "tsan.h"