On Wed, Apr 14, 2021 at 4:27 PM Richard Biener <rguent...@suse.de> wrote: > > 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. > > Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1.
g:52a5515ed6619739eb122f05ce26057dd8b06fb6 > 2021-04-14 Richard Biener <rguent...@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. > --- > gcc/config/rs6000/rs6000-call.c | 2 +- > gcc/gimple-fold.c | 219 ++++++++++++++++++++++- > gcc/gimple-fold.h | 1 + > gcc/gimple-ssa-sprintf.c | 3 +- > gcc/tree-cfg.c | 2 +- > gcc/tree-ssa-ccp.c | 15 +- > gcc/tree-ssa-dce.c | 3 +- > gcc/tree-ssa-propagate.c | 300 +------------------------------- > gcc/tree-ssa-propagate.h | 3 - > gcc/tree-ssa-strlen.c | 9 +- > gcc/tsan.c | 2 +- > 11 files changed, 226 insertions(+), 333 deletions(-) > > diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c > index f5676255387..6f6dc47f0ae 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 9e6683dbac9..a118ef4bbc3 100644 > --- a/gcc/gimple-fold.c > +++ b/gcc/gimple-fold.c > @@ -338,6 +338,123 @@ maybe_fold_reference (tree expr, bool is_lhs) > 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 > @@ -551,6 +668,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 > @@ -573,17 +756,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); > @@ -602,8 +809,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); > } > > @@ -4972,8 +5177,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; > } > > @@ -5569,8 +5773,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 f495dac9e71..2401646c484 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 fed4fe76279..fc744669e4b 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 4f63aa69ba8..a393e47882a 100644 > --- a/gcc/tree-cfg.c > +++ b/gcc/tree-cfg.c > @@ -7539,7 +7539,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 3bfd4a6265c..bf31f035153 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 c027230acdc..096cfc8721d 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 17dd1efd81d..b3dcd43c00d 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 60e2f68baa8..5257fbb0cf8 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 cccd4a06771..c7b5e2c6e6b 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 7db157e21e5..a1868b661e6 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" > -- > 2.26.2