https://gcc.gnu.org/g:39b59f1c6b339a131480a9e01ec6d9841279ee4d
commit 39b59f1c6b339a131480a9e01ec6d9841279ee4d Author: Michael Matz <[email protected]> Date: Mon Feb 19 00:50:04 2018 +0100 no-update-stmt: start hacking This survives the check-gcc testsuite. update_stmt() only checks for valid operands update_stmt_for_real() is the former update_stmt the operand setters call update_stmt_for_real. Various places that directly pointer-modify operands need to call update_stmt_for_real as well. Diff: --- gcc/gimple-fold.c | 7 ++++ gcc/gimple-ssa-isolate-paths.c | 2 +- gcc/gimple-ssa-store-merging.c | 2 +- gcc/gimple-ssa-strength-reduction.c | 4 +- gcc/gimple-ssa.h | 4 +- gcc/gimple.c | 4 ++ gcc/gimple.h | 83 ++++++++++++++++++++++++++----------- gcc/gimplify-me.c | 5 ++- gcc/ipa-split.c | 2 +- gcc/omp-simd-clone.c | 4 +- gcc/print-tree.c | 4 +- gcc/tree-cfg.c | 6 +-- gcc/tree-chkp-opt.c | 3 +- gcc/tree-inline.c | 2 +- gcc/tree-into-ssa.c | 2 +- gcc/tree-parloops.c | 4 +- gcc/tree-profile.c | 6 ++- gcc/tree-sra.c | 10 ++++- gcc/tree-ssa-dom.c | 1 + gcc/tree-ssa-dse.c | 3 +- gcc/tree-ssa-forwprop.c | 12 ++++-- gcc/tree-ssa-loop-im.c | 6 ++- gcc/tree-ssa-loop-ivopts.c | 9 ++-- gcc/tree-ssa-operands.c | 37 ++++++++++++++++- gcc/tree-ssa-phionlycprop.c | 10 ++++- gcc/tree-ssa-sccvn.c | 11 ++++- gcc/tree-ssa-scopedtables.c | 2 +- gcc/tree-ssa-tail-merge.c | 9 +++- gcc/tree-ssa.c | 8 +++- gcc/tree-vect-patterns.c | 6 ++- gcc/tree-vect-stmts.c | 4 ++ gcc/value-prof.c | 9 ++-- 32 files changed, 215 insertions(+), 66 deletions(-) diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index bd8c44a6a607..5091ac003b99 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2882,6 +2882,9 @@ gimple_fold_builtin_snprintf_chk (gimple_stmt_iterator *gsi, for (unsigned i = 3; i < gimple_call_num_args (stmt) - 2; ++i) gimple_call_set_arg (stmt, i, gimple_call_arg (stmt, i + 2)); gimple_set_num_ops (stmt, gimple_num_ops (stmt) - 2); + /* XXX gimple_set_num_ops removes arguments which requires updating + the operand cache. Make that implicit. */ + update_stmt_for_real (stmt); fold_stmt (gsi); return true; } @@ -2978,6 +2981,9 @@ gimple_fold_builtin_sprintf_chk (gimple_stmt_iterator *gsi, for (unsigned i = 2; i < gimple_call_num_args (stmt) - 2; ++i) gimple_call_set_arg (stmt, i, gimple_call_arg (stmt, i + 2)); gimple_set_num_ops (stmt, gimple_num_ops (stmt) - 2); + /* XXX gimple_set_num_ops removes arguments which requires updating + the operand cache. Make that implicit. */ + update_stmt_for_real (stmt); fold_stmt (gsi); return true; } @@ -3944,6 +3950,7 @@ fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *gsi) } gimple_call_set_nothrow (as_a <gcall *> (g), gimple_call_nothrow_p (as_a <gcall *> (stmt))); + stmt->bb = NULL; // XXX disable operand updating (makes expected addressable again) gimple_call_set_lhs (stmt, NULL_TREE); gsi_replace (gsi, g, true); if (oldlhs) diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c index 131705d18279..ffea8b262797 100644 --- a/gcc/gimple-ssa-isolate-paths.c +++ b/gcc/gimple-ssa-isolate-paths.c @@ -56,7 +56,7 @@ check_loadstore (gimple *stmt, tree op, tree, void *data) { TREE_THIS_VOLATILE (op) = 1; TREE_SIDE_EFFECTS (op) = 1; - update_stmt (stmt); + gimple_set_has_volatile_ops (stmt, true); return true; } return false; diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 2e1a6ef0e551..33c235fa5160 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -1014,8 +1014,8 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl, } else if (cur_stmt) { - gimple_assign_set_rhs_with_ops (&gsi, MEM_REF, val_expr); gimple_set_vuse (cur_stmt, n->vuse); + gimple_assign_set_rhs_with_ops (&gsi, MEM_REF, val_expr); update_stmt (cur_stmt); } else diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index 1c00f094db80..ba418fdbafac 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -1992,7 +1992,9 @@ replace_ref (tree *expr, slsr_cand_t c) /*before=*/true, GSI_SAME_STMT); copy_ref_info (mem_ref, *expr); *expr = mem_ref; - update_stmt (c->cand_stmt); + /* XXX change gimple operands via proper wrappers not via + pointer store, so no update_stmt would be needed. */ + update_stmt_for_real (c->cand_stmt); } /* Replace CAND_REF candidate C, each sibling of candidate C, and each diff --git a/gcc/gimple-ssa.h b/gcc/gimple-ssa.h index a82857e95292..e4328c50474d 100644 --- a/gcc/gimple-ssa.h +++ b/gcc/gimple-ssa.h @@ -167,7 +167,7 @@ gimple_vdef_op (gimple *g) /* Mark statement S as modified, and update it. */ static inline void -update_stmt (gimple *s) +update_stmt_for_real (gimple *s) { if (gimple_has_ops (s)) { @@ -176,6 +176,8 @@ update_stmt (gimple *s) } } +void update_stmt (gimple *); + /* Update statement S if it has been optimized. */ static inline void diff --git a/gcc/gimple.c b/gcc/gimple.c index 9dc4911a36e0..11fa0a8af866 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1594,6 +1594,8 @@ void gimple_set_bb (gimple *stmt, basic_block bb) { stmt->bb = bb; + if (flag_try_patch && bb) + update_stmt_for_real (stmt); if (gimple_code (stmt) != GIMPLE_LABEL) return; @@ -1744,6 +1746,8 @@ gimple_copy (gimple *stmt) /* Shallow copy all the fields from STMT. */ memcpy (copy, stmt, gimple_size (code)); gimple_init_singleton (copy); + copy->bb = NULL; + //gimple_set_bb (copy, NULL); // XXX deactivate operand updating in _set_op /* If STMT has sub-statements, deep-copy them as well. */ if (gimple_has_substatements (stmt)) diff --git a/gcc/gimple.h b/gcc/gimple.h index 265e3e24398c..cf5bb844ab79 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -2402,6 +2402,16 @@ gimple_op_ptr (gimple *gs, unsigned i) return NULL; } +#include "gimple-ssa.h" +static inline void +gimple_set_op_update (gimple *gs, unsigned i, tree val) +{ + tree *pop = gimple_op_ptr (gs, i); + *pop = val; + if (flag_try_patch && gs->bb) + update_stmt_for_real (gs); +} + /* Set operand I of statement GS to OP. */ static inline void @@ -2413,7 +2423,8 @@ gimple_set_op (gimple *gs, unsigned i, tree op) is_gimple_operand, but that would be wrong. Different tuples accept slightly different sets of tree operands. Each caller should perform its own validation. */ - gimple_ops (gs)[i] = op; + //gimple_ops (gs)[i] = op; + gimple_set_op_update (gs, i, op); } /* Return true if GS is a GIMPLE_ASSIGN. */ @@ -2470,7 +2481,8 @@ gimple_assign_lhs_ptr (gimple *gs) static inline void gimple_assign_set_lhs (gassign *gs, tree lhs) { - gs->op[0] = lhs; + //gs->op[0] = lhs; + gimple_set_op_update (gs, 0, lhs); if (lhs && TREE_CODE (lhs) == SSA_NAME) SSA_NAME_DEF_STMT (lhs) = gs; @@ -2521,7 +2533,8 @@ gimple_assign_rhs1_ptr (gimple *gs) static inline void gimple_assign_set_rhs1 (gassign *gs, tree rhs) { - gs->op[1] = rhs; + //gs->op[1] = rhs; + gimple_set_op_update (gs, 1, rhs); } static inline void @@ -2576,7 +2589,8 @@ static inline void gimple_assign_set_rhs2 (gassign *gs, tree rhs) { gcc_gimple_checking_assert (gimple_num_ops (gs) >= 3); - gs->op[2] = rhs; + //gs->op[2] = rhs; + gimple_set_op_update (gs, 2, rhs); } static inline void @@ -2623,7 +2637,8 @@ static inline void gimple_assign_set_rhs3 (gassign *gs, tree rhs) { gcc_gimple_checking_assert (gimple_num_ops (gs) >= 4); - gs->op[3] = rhs; + //gs->op[3] = rhs; + gimple_set_op_update (gs, 3, rhs); } static inline void @@ -2827,7 +2842,8 @@ gimple_call_lhs_ptr (gimple *gs) static inline void gimple_call_set_lhs (gcall *gs, tree lhs) { - gs->op[0] = lhs; + //gs->op[0] = lhs; + gimple_set_op_update (gs, 0, lhs); if (lhs && TREE_CODE (lhs) == SSA_NAME) SSA_NAME_DEF_STMT (lhs) = gs; } @@ -3056,7 +3072,8 @@ static inline void gimple_call_set_fn (gcall *gs, tree fn) { gcc_gimple_checking_assert (!gimple_call_internal_p (gs)); - gs->op[1] = fn; + //gs->op[1] = fn; + gimple_set_op_update (gs, 1, fn); } @@ -3066,8 +3083,9 @@ static inline void gimple_call_set_fndecl (gcall *gs, tree decl) { gcc_gimple_checking_assert (!gimple_call_internal_p (gs)); - gs->op[1] = build1_loc (gimple_location (gs), ADDR_EXPR, - build_pointer_type (TREE_TYPE (decl)), decl); + gimple_call_set_fn (gs, + build1_loc (gimple_location (gs), ADDR_EXPR, + build_pointer_type (TREE_TYPE (decl)), decl)); } static inline void @@ -3151,7 +3169,8 @@ gimple_call_chain_ptr (gcall *call_stmt) static inline void gimple_call_set_chain (gcall *call_stmt, tree chain) { - call_stmt->op[2] = chain; + //call_stmt->op[2] = chain; + gimple_set_op_update (call_stmt, 2, chain); } @@ -3212,7 +3231,8 @@ static inline void gimple_call_set_arg (gcall *gs, unsigned index, tree arg) { gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 3); - gs->op[index + 3] = arg; + //gs->op[index + 3] = arg; + gimple_set_op_update (gs, index + 3, arg); } static inline void @@ -3509,7 +3529,8 @@ gimple_cond_lhs_ptr (gcond *gs) static inline void gimple_cond_set_lhs (gcond *gs, tree lhs) { - gs->op[0] = lhs; + //gs->op[0] = lhs; + gimple_set_op_update (gs, 0, lhs); } @@ -3544,7 +3565,8 @@ gimple_cond_rhs_ptr (gcond *gs) static inline void gimple_cond_set_rhs (gcond *gs, tree rhs) { - gs->op[1] = rhs; + //gs->op[1] = rhs; + gimple_set_op_update (gs, 1, rhs); } @@ -3564,7 +3586,8 @@ gimple_cond_true_label (const gcond *gs) static inline void gimple_cond_set_true_label (gcond *gs, tree label) { - gs->op[2] = label; + //gs->op[2] = label; + gimple_set_op_update (gs, 2, label); } @@ -3574,7 +3597,8 @@ gimple_cond_set_true_label (gcond *gs, tree label) static inline void gimple_cond_set_false_label (gcond *gs, tree label) { - gs->op[3] = label; + //gs->op[3] = label; + gimple_set_op_update (gs, 3, label); } @@ -3685,7 +3709,8 @@ gimple_label_label (const glabel *gs) static inline void gimple_label_set_label (glabel *gs, tree label) { - gs->op[0] = label; + //gs->op[0] = label; + gimple_set_op_update (gs, 0, label); } @@ -3704,7 +3729,8 @@ gimple_goto_dest (const gimple *gs) static inline void gimple_goto_set_dest (ggoto *gs, tree dest) { - gs->op[0] = dest; + //gs->op[0] = dest; + gimple_set_op_update (gs, 0, dest); } @@ -3852,7 +3878,8 @@ gimple_asm_set_input_op (gasm *asm_stmt, unsigned index, tree in_op) { gcc_gimple_checking_assert (index < asm_stmt->ni && TREE_CODE (in_op) == TREE_LIST); - asm_stmt->op[index + asm_stmt->no] = in_op; + //asm_stmt->op[index + asm_stmt->no] = in_op; + gimple_set_op_update (asm_stmt, index + asm_stmt->no, in_op); } @@ -3872,7 +3899,8 @@ gimple_asm_set_output_op (gasm *asm_stmt, unsigned index, tree out_op) { gcc_gimple_checking_assert (index < asm_stmt->no && TREE_CODE (out_op) == TREE_LIST); - asm_stmt->op[index] = out_op; + //asm_stmt->op[index] = out_op; + gimple_set_op_update (asm_stmt, index, out_op); } @@ -3893,7 +3921,9 @@ gimple_asm_set_clobber_op (gasm *asm_stmt, unsigned index, tree clobber_op) { gcc_gimple_checking_assert (index < asm_stmt->nc && TREE_CODE (clobber_op) == TREE_LIST); - asm_stmt->op[index + asm_stmt->ni + asm_stmt->no] = clobber_op; + //asm_stmt->op[index + asm_stmt->ni + asm_stmt->no] = clobber_op; + gimple_set_op_update (asm_stmt, index + asm_stmt->ni + asm_stmt->no, + clobber_op); } /* Return label operand INDEX of GIMPLE_ASM ASM_STMT. */ @@ -3912,7 +3942,9 @@ gimple_asm_set_label_op (gasm *asm_stmt, unsigned index, tree label_op) { gcc_gimple_checking_assert (index < asm_stmt->nl && TREE_CODE (label_op) == TREE_LIST); - asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc] = label_op; + //asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc] = label_op; + gimple_set_op_update (asm_stmt, index + asm_stmt->ni + asm_stmt->nc, + label_op); } /* Return the string representing the assembly instruction in @@ -4551,7 +4583,8 @@ static inline void gimple_switch_set_index (gswitch *gs, tree index) { gcc_gimple_checking_assert (SSA_VAR_P (index) || CONSTANT_CLASS_P (index)); - gs->op[0] = index; + //gs->op[0] = index; + gimple_set_op_update (gs, 0, index); } @@ -4573,7 +4606,8 @@ gimple_switch_set_label (gswitch *gs, unsigned index, tree label) gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 1 && (label == NULL_TREE || TREE_CODE (label) == CASE_LABEL_EXPR)); - gs->op[index + 1] = label; + //gs->op[index + 1] = label; + gimple_set_op_update (gs, index + 1, label); } /* Return the default label for a switch statement. */ @@ -6219,7 +6253,8 @@ gimple_return_retval (const greturn *gs) static inline void gimple_return_set_retval (greturn *gs, tree retval) { - gs->op[0] = retval; + //gs->op[0] = retval; + gimple_set_op_update (gs, 0, retval); } diff --git a/gcc/gimplify-me.c b/gcc/gimplify-me.c index 137a5662ccf5..eca7681ff0d2 100644 --- a/gcc/gimplify-me.c +++ b/gcc/gimplify-me.c @@ -316,7 +316,10 @@ gimple_regimplify_operands (gimple *stmt, gimple_stmt_iterator *gsi_p) pop_gimplify_context (NULL); - update_stmt (stmt); + /* XXX some of the above transforms directly change gimple ops + instead of going through setters. Once rewritten, update_stmt + isn't necessary. */ + update_stmt_for_real (stmt); } diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index b03ae02924aa..3d18f071e347 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -1359,7 +1359,7 @@ split_function (basic_block return_bb, struct split_point *split_point, if (gimple_vuse (stmt)) { gimple_set_vuse (stmt, NULL_TREE); - update_stmt (stmt); + update_stmt_for_real (stmt); // XXX find better way to set vuse } if (gimple_vdef (stmt)) break; diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c index b15adf0bada4..92a5fd8bc330 100644 --- a/gcc/omp-simd-clone.c +++ b/gcc/omp-simd-clone.c @@ -1012,7 +1012,9 @@ ipa_simd_modify_function_body (struct cgraph_node *node, if (info.modified) { - update_stmt (stmt); + /* XXX direct operand changes via walk_gimple_op make + this necessary: */ + update_stmt_for_real (stmt); if (maybe_clean_eh_stmt (stmt)) gimple_purge_dead_eh_edges (gimple_bb (stmt)); } diff --git a/gcc/print-tree.c b/gcc/print-tree.c index caf5f2601475..41c5bfcb8379 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -369,6 +369,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent, if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node)) fputs (" suppress-debug", file); + if (code == FUNCTION_DECL && DECL_PURE_P (node)) + fputs (" pure", file); if (code == FUNCTION_DECL && DECL_FUNCTION_SPECIFIC_TARGET (node)) fputs (" function-specific-target", file); @@ -383,7 +385,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent, fputs (" built-in", file); if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node)) fputs (" static-chain", file); - if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node)) + if (code == FUNCTION_DECL && decl_is_tm_clone (node)) fputs (" tm-clone", file); if (code == FIELD_DECL && DECL_PACKED (node)) diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 2ada965edd61..fca7a2f7287b 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -7033,7 +7033,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, the current function. */ free_stmt_operands (cfun, stmt); push_cfun (dest_cfun); - update_stmt (stmt); + update_stmt_for_real (stmt); pop_cfun (); } @@ -9367,10 +9367,10 @@ execute_fixup_cfg (void) if (gimple_purge_dead_abnormal_call_edges (bb)) todo |= TODO_cleanup_cfg; - if (gimple_in_ssa_p (cfun)) + if (gimple_in_ssa_p (cfun) && gimple_vuse (stmt)) { todo |= TODO_update_ssa | TODO_cleanup_cfg; - update_stmt (stmt); + update_stmt_for_real (stmt); } } diff --git a/gcc/tree-chkp-opt.c b/gcc/tree-chkp-opt.c index 5a005a6a7b63..df90016de5dc 100644 --- a/gcc/tree-chkp-opt.c +++ b/gcc/tree-chkp-opt.c @@ -1238,7 +1238,8 @@ chkp_reduce_bounds_lifetime (void) gimple_set_vdef (stmt, NULL_TREE); gimple_set_vuse (stmt, NULL_TREE); - update_stmt (stmt); + /* XXX only needed to reset vops. */ + update_stmt_for_real (stmt); } } else diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 5a0a2525c0ca..1696ba9d3598 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2919,7 +2919,7 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id) processing_debug_stmt = 0; - update_stmt (stmt); + update_stmt_for_real (stmt); } /* Process deferred debug stmts. In order to give values better odds diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c index f4af33c1303a..195443f2d82c 100644 --- a/gcc/tree-into-ssa.c +++ b/gcc/tree-into-ssa.c @@ -646,7 +646,7 @@ mark_def_sites (basic_block bb, gimple *stmt, bitmap kills) /* Since this is the first time that we rewrite the program into SSA form, force an operand scan on every statement. */ - update_stmt (stmt); + update_stmt_for_real (stmt); gcc_checking_assert (blocks_to_update == NULL); set_register_defs (stmt, false); diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index 3a788ccf1b74..a3276e7d40ee 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -739,8 +739,10 @@ eliminate_local_variables_stmt (edge entry, gimple_stmt_iterator *gsi, walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info); } + /* XXX If we weren't changing the gimple ops via direct pointer + access we wouldn't need to do this: */ if (dta.changed) - update_stmt (stmt); + update_stmt_for_real (stmt); } /* Eliminates the references to local variables from the single entry diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index f96bd4b97048..9f3b8aff5667 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -715,7 +715,9 @@ tree_profiling (void) node->set_pure_flag (false, false); } - /* Update call statements and rebuild the cgraph. */ + /* As callees const/pure status might have changed we now may need + vdefs or vuses on call statements, so update all of them + a nd rebuild the cgraph. */ FOR_EACH_DEFINED_FUNCTION (node) { basic_block bb; @@ -738,7 +740,7 @@ tree_profiling (void) { gimple *stmt = gsi_stmt (gsi); if (is_gimple_call (stmt)) - update_stmt (stmt); + update_stmt_for_real (stmt); } } diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index b513676152fc..3be6d2ca09a6 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -3848,7 +3848,10 @@ sra_modify_function_body (void) if (modified) { - update_stmt (stmt); + /* XXX Use proper gimple operand setter to update + operands instead of in-place modifications, so no + update_stmt is necessary. */ + update_stmt_for_real (stmt); if (maybe_clean_eh_stmt (stmt) && gimple_purge_dead_eh_edges (gimple_bb (stmt))) cfg_changed = true; @@ -5113,7 +5116,10 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) if (modified) { - update_stmt (stmt); + /* XXX Use proper gimple operand setter to update + operands instead of in-place modifications, so no + update_stmt is necessary. */ + update_stmt_for_real (stmt); if (maybe_clean_eh_stmt (stmt) && gimple_purge_dead_eh_edges (gimple_bb (stmt))) cfg_changed = true; diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index a6f176c5def0..329aed6da0d6 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -1687,6 +1687,7 @@ record_equivalences_from_stmt (gimple *stmt, int may_optimize_p, } else new_stmt = gimple_build_assign (rhs, lhs); + /* XXX jeez, the above might construct statements like '3 = *p_42' */ gimple_set_vuse (new_stmt, gimple_vdef (stmt)); diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 9220fea7f2ec..bcaed1675cd8 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -388,7 +388,8 @@ increment_start_addr (gimple *stmt, tree *where, int increment) gimple_stmt_iterator gsi = gsi_for_stmt (stmt); gsi_insert_before (&gsi, newop, GSI_SAME_STMT); *where = tem; - update_stmt (gsi_stmt (gsi)); + /* XXX don't use direct operand change via pointer. */ + update_stmt_for_real (gsi_stmt (gsi)); return; } diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 58ec6b47a5bb..31286868c34f 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -779,6 +779,10 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, TREE_OPERAND (lhs, 1) = wide_int_to_tree (TREE_TYPE (TREE_OPERAND (lhs, 1)), off); tidy_after_forward_propagate_addr (use_stmt); + /* XXX fix the horrible in-place changes of tree operands, instead use + SET_USE and friends, so no update_stmt is necessary. + E.g. &TREE_OPERAND(lhs,0) will be some ssa use operand on use_stmt. */ + update_stmt_for_real (use_stmt); /* Continue propagating into the RHS if this was not the only use. */ if (single_use_p) return true; @@ -825,6 +829,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, TREE_SIDE_EFFECTS (new_lhs) = TREE_SIDE_EFFECTS (lhs); *def_rhs_basep = saved; tidy_after_forward_propagate_addr (use_stmt); + update_stmt_for_real (use_stmt); /* Continue propagating into the RHS if this was not the only use. */ if (single_use_p) @@ -871,6 +876,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, = wide_int_to_tree (TREE_TYPE (TREE_OPERAND (rhs, 1)), off); fold_stmt_inplace (use_stmt_gsi); tidy_after_forward_propagate_addr (use_stmt); + update_stmt_for_real (use_stmt); return res; } /* If the RHS is a plain dereference and the value type is the same as @@ -912,6 +918,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, *def_rhs_basep = saved; fold_stmt_inplace (use_stmt_gsi); tidy_after_forward_propagate_addr (use_stmt); + update_stmt_for_real (use_stmt); return res; } } @@ -1939,9 +1946,8 @@ simplify_permutation (gimple_stmt_iterator *gsi) return 0; orig = (ident == 1) ? gimple_assign_rhs1 (def_stmt) : gimple_assign_rhs2 (def_stmt); - gimple_assign_set_rhs1 (stmt, unshare_expr (orig)); - gimple_assign_set_rhs_code (stmt, TREE_CODE (orig)); - gimple_set_num_ops (stmt, 2); + gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (orig), + unshare_expr (orig)); update_stmt (stmt); return remove_prop_source_from_use (op0) ? 2 : 1; } diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 030aac0b6163..4dddd3056bc5 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -1666,8 +1666,12 @@ struct rewrite_mem_ref_loc bool rewrite_mem_ref_loc::operator () (mem_ref_loc *loc) { + /* XXX should use proper gimple operand setters so that + update_stmt isn't needed. (At this point we replace a real + memref (in top-level operand) with a tmp VAR_DECL which is + going to become an SSA name) */ *loc->ref = tmp_var; - update_stmt (loc->stmt); + update_stmt_for_real (loc->stmt); return false; } diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index b3135717f22c..4cd8298226f4 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -7217,7 +7217,7 @@ rewrite_groups (struct ivopts_data *data) for (j = 0; j < group->vuses.length (); j++) { rewrite_use_nonlinear_expr (data, group->vuses[j], cand); - update_stmt (group->vuses[j]->stmt); + update_stmt_for_real (group->vuses[j]->stmt); } } else if (address_p (group->type)) @@ -7225,7 +7225,7 @@ rewrite_groups (struct ivopts_data *data) for (j = 0; j < group->vuses.length (); j++) { rewrite_use_address (data, group->vuses[j], cand); - update_stmt (group->vuses[j]->stmt); + update_stmt_for_real (group->vuses[j]->stmt); } } else @@ -7235,7 +7235,7 @@ rewrite_groups (struct ivopts_data *data) for (j = 0; j < group->vuses.length (); j++) { rewrite_use_compare (data, group->vuses[j], cand); - update_stmt (group->vuses[j]->stmt); + update_stmt_for_real (group->vuses[j]->stmt); } } } @@ -7365,7 +7365,8 @@ remove_unused_ivs (struct ivopts_data *data) FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) SET_USE (use_p, comp); - update_stmt (stmt); + /* XXX blaeh, debug statement operands are complicated. */ + update_stmt_for_real (stmt); } } } diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 41dcb56001dd..0c23dba4ce14 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -835,6 +835,9 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) case BIT_INSERT_EXPR: case COMPOUND_EXPR: + //abort(); // happens in debug insns + /* FALLTHRU */ + case OBJ_TYPE_REF: case ASSERT_EXPR: do_binary: @@ -851,6 +854,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) case WIDEN_MULT_MINUS_EXPR: case FMA_EXPR: { + abort(); // hmm, but might exist hidden down in debug stmts? yes! get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags); get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), flags); @@ -865,12 +869,15 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) return; default: + if (codeclass == tcc_constant || codeclass == tcc_type) + return; + /*fprintf(stderr, "XXX"); + debug_tree (expr); + fputs ("\n", stderr);*/ if (codeclass == tcc_unary) goto do_unary; if (codeclass == tcc_binary || codeclass == tcc_comparison) goto do_binary; - if (codeclass == tcc_constant || codeclass == tcc_type) - return; } /* If we get here, something has gone wrong. */ @@ -1084,6 +1091,32 @@ update_stmt_operands (struct function *fn, gimple *stmt) timevar_pop (TV_TREE_OPS); } +void +update_stmt (gimple *s) +{ + if (gimple_has_ops (s) && ssa_operands_active (cfun)) + { + if (!flag_try_patch) + update_stmt_for_real (s); + else + { + /* Cleanup stale per-statement operands. Those happen + when non-SSA-names are placed into operands via SET_USE. */ + gimple_statement_with_ops *ops_stmt = + dyn_cast <gimple_statement_with_ops *> (s); + use_optype_p *ptr = &ops_stmt->use_ops; + while (*ptr) + { + if (!USE_OP_PTR(*ptr)->prev && !SSA_VAR_P (USE_OP (*ptr))) + *ptr = (*ptr)->next; + else + ptr = &((*ptr)->next); + } + if (verify_ssa_operands (cfun, s)) + print_gimple_stmt (stderr, s, 0, TDF_VOPS); + } + } +} /* Swap operands EXP0 and EXP1 in statement STMT. No attempt is done to test the validity of the swap operation. */ diff --git a/gcc/tree-ssa-phionlycprop.c b/gcc/tree-ssa-phionlycprop.c index 632df271fb7c..0cd501aa3cbe 100644 --- a/gcc/tree-ssa-phionlycprop.c +++ b/gcc/tree-ssa-phionlycprop.c @@ -158,6 +158,8 @@ propagate_rhs_into_lhs (gimple *stmt, tree lhs, tree rhs, continue; } + int old_call_flags + = is_gimple_call (use_stmt) ? gimple_call_flags (use_stmt) : 0; /* Dump details. */ if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -208,7 +210,13 @@ propagate_rhs_into_lhs (gimple *stmt, tree lhs, tree rhs, /* Sometimes propagation can expose new operands to the renamer. */ - update_stmt (use_stmt); + /* XXX the updating fixes the vops in case an indirect call + became direct and known const/pure. */ + if (is_gimple_call (use_stmt) + && old_call_flags != gimple_call_flags (use_stmt)) + update_stmt_for_real (use_stmt); + else + update_stmt (use_stmt); /* Dump details. */ if (dump_file && (dump_flags & TDF_DETAILS)) diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 1463c1d41165..4da4d105e80d 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -5417,6 +5417,7 @@ eliminate_dom_walker::before_dom_children (basic_block b) tree sprime = NULL_TREE; gimple *stmt = gsi_stmt (gsi); tree lhs = gimple_get_lhs (stmt); + int old_call_flags = is_gimple_call (stmt) ? gimple_call_flags (stmt) : 0; if (lhs && TREE_CODE (lhs) == SSA_NAME && !gimple_has_volatile_ops (stmt) /* See PR43491. Do not replace a global register variable when @@ -5761,7 +5762,7 @@ eliminate_dom_walker::before_dom_children (basic_block b) /* Visit indirect calls and turn them into direct calls if possible using the devirtualization machinery. Do this before - checking for required EH/abnormal/noreturn cleanup as devird + checking for required EH/abnormal/noreturn cleanup as devirt may expose more of those. */ if (gcall *call_stmt = dyn_cast <gcall *> (stmt)) { @@ -5851,7 +5852,13 @@ eliminate_dom_walker::before_dom_children (basic_block b) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " Removed AB side-effects.\n"); } - update_stmt (stmt); + /* XXX the updating fixes the vops in case an indirect call + became direct and known const/pure. */ + if (is_gimple_call (stmt) + && old_call_flags != gimple_call_flags (stmt)) + update_stmt_for_real (stmt); + else + update_stmt (stmt); if (vdef != gimple_vdef (stmt)) VN_INFO (vdef)->valnum = vuse; } diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c index 2a40fdae0a27..827787cb72f9 100644 --- a/gcc/tree-ssa-scopedtables.c +++ b/gcc/tree-ssa-scopedtables.c @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "options.h" #include "function.h" #include "basic-block.h" #include "tree.h" @@ -33,7 +34,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-eh.h" #include "internal-fn.h" #include "tree-dfa.h" -#include "options.h" #include "params.h" static bool hashable_expr_equal_p (const struct hashable_expr *, diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index f482ce197cd8..ddba1de98061 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -702,7 +702,14 @@ find_same_succ_bb (basic_block bb, same_succ **same_p) edge_iterator ei; edge e; - if (bb == NULL) + /* Ignore blocks without successors here. Merging them potentially + merges syntactic scopes and destroys sharing of local variables because + the clobbers stopping the scope aren't reachable. + If the blocks do have successors the clobbers will be reachable and + the problem doesn't happen. + + Those blocks can still be merged later by RTL cross jumping. */ + if (bb == NULL || !EDGE_COUNT (bb->succs)) return; bitmap_set_bit (same->bbs, bb->index); FOR_EACH_EDGE (e, ei, bb->succs) diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index d197f99bdd23..13b9a0e5c298 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -479,7 +479,9 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) else gimple_debug_bind_reset_value (stmt); - update_stmt (stmt); + /* XXX nested debug expressions are hard for SSA operands. + Forcibly update the whole statement. */ + update_stmt_for_real (stmt); } } @@ -2021,7 +2023,9 @@ execute_update_addresses_taken (void) if (gimple_references_memory_p (stmt) || is_gimple_debug (stmt)) - update_stmt (stmt); + /* XXX maybe find better way of removing vops for statements + which now no longer refer to memory due to non-address-taken */ + update_stmt_for_real (stmt); gsi_next (&gsi); } diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 5c2578f04659..ac7e883e4d43 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -4417,7 +4417,8 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt, pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo); set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info); } - gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt)); + //gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt)); + pattern_stmt->bb = gimple_bb (orig_stmt); // XXX STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt; STMT_VINFO_DEF_TYPE (pattern_stmt_info) @@ -4440,7 +4441,8 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt, def_stmt_info = new_stmt_vec_info (def_stmt, vinfo); set_vinfo_for_stmt (def_stmt, def_stmt_info); } - gimple_set_bb (def_stmt, gimple_bb (orig_stmt)); + //gimple_set_bb (def_stmt, gimple_bb (orig_stmt)); + def_stmt->bb = gimple_bb (orig_stmt); // XXX STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt; STMT_VINFO_DEF_TYPE (def_stmt_info) = vect_internal_def; if (STMT_VINFO_VECTYPE (def_stmt_info) == NULL_TREE) diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 1e8ccbce2af0..49716c09af2c 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -9758,7 +9758,10 @@ free_stmt_vec_info (gimple *stmt) { gimple_seq seq = STMT_VINFO_PATTERN_DEF_SEQ (patt_info); gimple *patt_stmt = STMT_VINFO_STMT (patt_info); + /* XXX This resets BB, but patt_stmt still is linked + in the imm-use lists of all operands */ gimple_set_bb (patt_stmt, NULL); + delink_stmt_imm_use (patt_stmt); tree lhs = gimple_get_lhs (patt_stmt); if (lhs && TREE_CODE (lhs) == SSA_NAME) release_ssa_name (lhs); @@ -9769,6 +9772,7 @@ free_stmt_vec_info (gimple *stmt) { gimple *seq_stmt = gsi_stmt (si); gimple_set_bb (seq_stmt, NULL); + delink_stmt_imm_use (seq_stmt); lhs = gimple_get_lhs (seq_stmt); if (lhs && TREE_CODE (lhs) == SSA_NAME) release_ssa_name (lhs); diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 16cdbd64f46d..d6ac350e4ca1 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -1336,7 +1336,8 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call, } gimple_set_vdef (icall_stmt, NULL_TREE); gimple_set_vuse (icall_stmt, NULL_TREE); - update_stmt (icall_stmt); + /* XXX only needed to reset vops. */ + update_stmt_for_real (icall_stmt); dcall_stmt = as_a <gcall *> (gimple_copy (icall_stmt)); gimple_call_set_fndecl (dcall_stmt, direct_call->decl); dflags = flags_from_decl_or_type (direct_call->decl); @@ -1422,7 +1423,8 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call, } gimple_set_vdef (iretbnd_stmt, NULL_TREE); gimple_set_vuse (iretbnd_stmt, NULL_TREE); - update_stmt (iretbnd_stmt); + /* XXX only needed to reset vops. */ + update_stmt_for_real (iretbnd_stmt); result = gimple_call_lhs (iretbnd_stmt); phi = create_phi_node (result, join_bb); @@ -1655,7 +1657,8 @@ gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, profile_probabi } gimple_set_vdef (vcall_stmt, NULL); gimple_set_vuse (vcall_stmt, NULL); - update_stmt (vcall_stmt); + /* XXX only needed to reset vops. */ + update_stmt_for_real (vcall_stmt); icall_stmt = as_a <gcall *> (gimple_copy (vcall_stmt)); gimple_call_set_arg (icall_stmt, size_arg, fold_convert (optype, icall_size));
