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;
+ }

Reply via email to