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. 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