I am testing the following patch fixing a python miscompile with FDO (requires -ftracer to trigger). A previous fix to SCCVN made resetting of flow-sensitive SSA info from tail-merging ineffective by eventually restoring the original info.
Fixed by splitting that part out of free_scc_vn and calling it before tail-merging. Bootstrap & regtest running on x86_64-unknown-linux-gnu, will apply to trunk and branch if it succeeds. Richard. 2016-04-19 Richard Biener <rguent...@suse.de> PR tree-optimization/70724 * tree-ssa-sccvn.c (scc_vn_restore_ssa_info): Split SSA info restoring out from ... (free_scc_vn): ... here. * tree-ssa-sccvn.h (scc_vn_restore_ssa_info): Declare. * tres-ssa-pre.c (pass_pre::execute): Restore SSA info before tail merging. (pass_fre::execute): Restore SSA info. * gcc.dg/torture/pr70724.c: New testcase. Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 235188) --- gcc/tree-ssa-sccvn.c (working copy) *************** init_scc_vn (void) *** 4300,4325 **** } } void ! free_scc_vn (void) { ! size_t i; ! ! delete constant_to_value_id; ! constant_to_value_id = NULL; ! BITMAP_FREE (constant_value_ids); ! shared_lookup_phiargs.release (); ! shared_lookup_references.release (); ! XDELETEVEC (rpo_numbers); ! ! for (i = 0; i < num_ssa_names; i++) { tree name = ssa_name (i); if (name && has_VN_INFO (name)) { if (VN_INFO (name)->needs_insertion) ! release_ssa_name (name); else if (POINTER_TYPE_P (TREE_TYPE (name)) && VN_INFO (name)->info.ptr_info) SSA_NAME_PTR_INFO (name) = VN_INFO (name)->info.ptr_info; --- 4300,4318 ---- } } + /* Restore SSA info that has been reset on value leaders. */ + void ! scc_vn_restore_ssa_info (void) { ! for (unsigned i = 0; i < num_ssa_names; i++) { tree name = ssa_name (i); if (name && has_VN_INFO (name)) { if (VN_INFO (name)->needs_insertion) ! ; else if (POINTER_TYPE_P (TREE_TYPE (name)) && VN_INFO (name)->info.ptr_info) SSA_NAME_PTR_INFO (name) = VN_INFO (name)->info.ptr_info; *************** free_scc_vn (void) *** 4332,4337 **** --- 4325,4352 ---- } } } + } + + void + free_scc_vn (void) + { + size_t i; + + delete constant_to_value_id; + constant_to_value_id = NULL; + BITMAP_FREE (constant_value_ids); + shared_lookup_phiargs.release (); + shared_lookup_references.release (); + XDELETEVEC (rpo_numbers); + + for (i = 0; i < num_ssa_names; i++) + { + tree name = ssa_name (i); + if (name + && has_VN_INFO (name) + && VN_INFO (name)->needs_insertion) + release_ssa_name (name); + } obstack_free (&vn_ssa_aux_obstack, NULL); vn_ssa_aux_table.release (); Index: gcc/tree-ssa-sccvn.h =================================================================== *** gcc/tree-ssa-sccvn.h (revision 235188) --- gcc/tree-ssa-sccvn.h (working copy) *************** extern vn_ssa_aux_t VN_INFO_GET (tree); *** 204,209 **** --- 204,210 ---- tree vn_get_expr_for (tree); bool run_scc_vn (vn_lookup_kind); void free_scc_vn (void); + void scc_vn_restore_ssa_info (void); tree vn_nary_op_lookup (tree, vn_nary_op_t *); tree vn_nary_op_lookup_stmt (gimple *, vn_nary_op_t *); tree vn_nary_op_lookup_pieces (unsigned int, enum tree_code, Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 235188) --- gcc/tree-ssa-pre.c (working copy) *************** pass_pre::execute (function *fun) *** 4828,4833 **** --- 4828,4836 ---- todo |= fini_eliminate (); loop_optimizer_finalize (); + /* Restore SSA info before tail-merging as that resets it as well. */ + scc_vn_restore_ssa_info (); + /* TODO: tail_merge_optimize may merge all predecessors of a block, in which case we can merge the block with the remaining predecessor of the block. It should either: *************** pass_fre::execute (function *fun) *** 4901,4906 **** --- 4904,4910 ---- todo |= fini_eliminate (); + scc_vn_restore_ssa_info (); free_scc_vn (); statistics_counter_event (fun, "Insertions", pre_stats.insertions); Index: gcc/testsuite/gcc.dg/torture/pr70724.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr70724.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr70724.c (working copy) *************** *** 0 **** --- 1,39 ---- + /* { dg-do run } */ + /* { dg-additional-options "-ftracer" } */ + + extern void abort (void); + + typedef long int _PyTime_t; + typedef enum { _PyTime_ROUND_FLOOR = 0, _PyTime_ROUND_CEILING = 1 } + _PyTime_round_t; + + static _PyTime_t + _PyTime_Divide(const _PyTime_t t, const _PyTime_t k, + const _PyTime_round_t round) + { + if (round == _PyTime_ROUND_CEILING) { + if (t >= 0) + return (t + k - 1) / k; + else + return t / k; + } + else { + if (t >= 0) + return t / k; + else + return (t - (k - 1)) / k; + } + } + + _PyTime_t __attribute__((noinline,noclone)) + _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) + { + return _PyTime_Divide(t, 1000, round); + } + + int main() + { + if (_PyTime_AsMicroseconds (10000, _PyTime_ROUND_FLOOR) != 10) + abort (); + return 0; + }