This fixes PR59715 by splitting critical edges again before
code sinking.  The critical edge splitting done before PRE
was designed to survive until sinking originally, but at least
since 4.5 PRE now eventually cleans up the CFG and thus undos
critical edge splitting.  This results in less than optimal
code placement (and lost opportunities) for sinking and it
breaks (at least) the virtual operand updating code which
assumes that critical edges are still split.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2014-01-09  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/59715
        * tree-cfg.h (split_critical_edges): Declare.
        * tree-cfg.c (split_critical_edges): Export.
        * tree-ssa-sink.c (execute_sink_code): Split critical edges.

        * gcc.dg/torture/pr59715.c: New testcase.

Index: gcc/tree-cfg.h
===================================================================
*** gcc/tree-cfg.h      (revision 206421)
--- gcc/tree-cfg.h      (working copy)
*************** extern tree gimplify_build1 (gimple_stmt
*** 93,97 ****
--- 93,98 ----
                             tree, tree);
  extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
  extern unsigned int execute_fixup_cfg (void);
+ extern unsigned int split_critical_edges (void);
  
  #endif /* _TREE_CFG_H  */
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c      (revision 206421)
--- gcc/tree-cfg.c      (working copy)
*************** static void make_goto_expr_edges (basic_
*** 159,165 ****
  static void make_gimple_asm_edges (basic_block);
  static edge gimple_redirect_edge_and_branch (edge, basic_block);
  static edge gimple_try_redirect_by_replacing_jump (edge, basic_block);
- static unsigned int split_critical_edges (void);
  
  /* Various helpers.  */
  static inline bool stmt_starts_bb_p (gimple, gimple);
--- 159,164 ----
*************** struct cfg_hooks gimple_cfg_hooks = {
*** 7929,7935 ****
  
  /* Split all critical edges.  */
  
! static unsigned int
  split_critical_edges (void)
  {
    basic_block bb;
--- 7954,7960 ----
  
  /* Split all critical edges.  */
  
! unsigned int
  split_critical_edges (void)
  {
    basic_block bb;
Index: gcc/tree-ssa-sink.c
===================================================================
*** gcc/tree-ssa-sink.c (revision 206421)
--- gcc/tree-ssa-sink.c (working copy)
*************** static void
*** 567,573 ****
  execute_sink_code (void)
  {
    loop_optimizer_init (LOOPS_NORMAL);
! 
    connect_infinite_loops_to_exit ();
    memset (&sink_stats, 0, sizeof (sink_stats));
    calculate_dominance_info (CDI_DOMINATORS);
--- 567,573 ----
  execute_sink_code (void)
  {
    loop_optimizer_init (LOOPS_NORMAL);
!   split_critical_edges ();
    connect_infinite_loops_to_exit ();
    memset (&sink_stats, 0, sizeof (sink_stats));
    calculate_dominance_info (CDI_DOMINATORS);
Index: gcc/testsuite/gcc.dg/torture/pr59715.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr59715.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr59715.c      (working copy)
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do run } */
+ 
+ extern void abort (void);
+ 
+ int a = 2, b;
+ 
+ int
+ main ()
+ {
+   int c;
+   if (!b)
+     {
+       b = a;
+       c = a == 0 ? 1 : 1 % a;
+       if (c)
+       b = 0;
+     }
+   if (b != 0)
+     abort ();
+   return 0;
+ }

Reply via email to