Hi,

Curretly CSE may modify CFG and leave invalid dominance info.  This patch
improves track of CFG changes by CSE passes and frees dominance info if
required.  This allows to remove corresponding workaround from STV pass.

Does it look OK?

Bootstrapped and regtested on x86-64-unknown-linux-gnu.

Thanks,
Ilya
--
gcc/

2016-05-10  Ilya Enkovich  <ilya.enkov...@intel.com>

        PR middle-end/70807
        * cfgrtl.h (delete_insn_and_edges): Now return bool.
        * cfgrtl.c (delete_insn_and_edges): Likewise.
        * config/i386/i386.c (convert_scalars_to_vector): Remove
        redundant code.
        * cse.c (cse_insn): Compute cse_cfg_altered.
        (delete_trivially_dead_insns): Likewise.
        (cse_cc_succs): Likewise.
        (rest_of_handle_cse): Free dominance info if required.
        (rest_of_handle_cse2): Likewise.
        (rest_of_handle_cse_after_global_opts): Likewise.

gcc/testsuite/

2016-05-10  Ilya Enkovich  <ilya.enkov...@intel.com>

        PR middle-end/70807
        * gcc.dg/pr70807.c: New test.


diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 62b0596..3d8ed60 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -215,9 +215,10 @@ delete_insn (rtx uncast_insn)
     }
 }
 
-/* Like delete_insn but also purge dead edges from BB.  */
+/* Like delete_insn but also purge dead edges from BB.
+   Return true if any edges are eliminated.  */
 
-void
+bool
 delete_insn_and_edges (rtx_insn *insn)
 {
   bool purge = false;
@@ -228,7 +229,8 @@ delete_insn_and_edges (rtx_insn *insn)
     purge = true;
   delete_insn (insn);
   if (purge)
-    purge_dead_edges (BLOCK_FOR_INSN (insn));
+    return purge_dead_edges (BLOCK_FOR_INSN (insn));
+  return false;
 }
 
 /* Unlink a chain of insns between START and FINISH, leaving notes
diff --git a/gcc/cfgrtl.h b/gcc/cfgrtl.h
index 0d88024..d81928a 100644
--- a/gcc/cfgrtl.h
+++ b/gcc/cfgrtl.h
@@ -21,7 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_CFGRTL_H
 
 extern void delete_insn (rtx);
-extern void delete_insn_and_edges (rtx_insn *);
+extern bool delete_insn_and_edges (rtx_insn *);
 extern void delete_insn_chain (rtx, rtx, bool);
 extern basic_block create_basic_block_structure (rtx_insn *, rtx_insn *,
                                                 rtx_note *, basic_block);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 05476f3..7c023b7 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3911,13 +3911,6 @@ convert_scalars_to_vector ()
   bitmap_obstack_release (NULL);
   df_process_deferred_rescans ();
 
-  /* FIXME: Since the CSE pass may change dominance info, which isn't
-     expected by the fwprop pass, call free_dominance_info to
-     invalidate dominance info.  Otherwise, the fwprop pass may crash
-     when dominance info is changed.  */
-  if (TARGET_64BIT)
-    free_dominance_info (CDI_DOMINATORS);
-
   /* Conversion means we may have 128bit register spills/fills
      which require aligned stack.  */
   if (converted_insns)
diff --git a/gcc/cse.c b/gcc/cse.c
index 7456e84..04e1a85 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -5505,7 +5505,7 @@ cse_insn (rtx_insn *insn)
       else if (n_sets == 1 && dest == pc_rtx && src == pc_rtx)
        {
          /* One less use of the label this insn used to jump to.  */
-         delete_insn_and_edges (insn);
+         cse_cfg_altered |= delete_insn_and_edges (insn);
          cse_jumps_altered = true;
          /* No more processing for this set.  */
          sets[i].rtl = 0;
@@ -5516,7 +5516,7 @@ cse_insn (rtx_insn *insn)
        {
          if (cfun->can_throw_non_call_exceptions && can_throw_internal (insn))
            cse_cfg_altered = true;
-         delete_insn_and_edges (insn);
+         cse_cfg_altered |= delete_insn_and_edges (insn);
          /* No more processing for this set.  */
          sets[i].rtl = 0;
        }
@@ -5551,7 +5551,7 @@ cse_insn (rtx_insn *insn)
                  REG_NOTES (new_rtx) = note;
                }
 
-             delete_insn_and_edges (insn);
+             cse_cfg_altered |= delete_insn_and_edges (insn);
              insn = new_rtx;
            }
          else
@@ -7131,7 +7131,7 @@ delete_trivially_dead_insns (rtx_insn *insns, int nreg)
              count_reg_usage (insn, counts, NULL_RTX, -1);
              ndead++;
            }
-         delete_insn_and_edges (insn);
+         cse_cfg_altered |= delete_insn_and_edges (insn);
        }
     }
 
@@ -7427,7 +7427,7 @@ cse_cc_succs (basic_block bb, basic_block orig_bb, rtx 
cc_reg, rtx cc_src,
                                    newreg);
        }
 
-      delete_insn_and_edges (insns[i]);
+      cse_cfg_altered |= delete_insn_and_edges (insns[i]);
     }
 
   return mode;
@@ -7568,6 +7568,9 @@ rest_of_handle_cse (void)
   else if (tem == 1 || optimize > 1)
     cleanup_cfg (0);
 
+  if (cse_cfg_altered && dom_info_available_p (CDI_DOMINATORS))
+    free_dominance_info (CDI_DOMINATORS);
+
   return 0;
 }
 
@@ -7637,6 +7640,9 @@ rest_of_handle_cse2 (void)
   else if (tem == 1)
     cleanup_cfg (0);
 
+  if (cse_cfg_altered && dom_info_available_p (CDI_DOMINATORS))
+    free_dominance_info (CDI_DOMINATORS);
+
   cse_not_expected = 1;
   return 0;
 }
@@ -7695,7 +7701,7 @@ rest_of_handle_cse_after_global_opts (void)
 
   rebuild_jump_labels (get_insns ());
   tem = cse_main (get_insns (), max_reg_num ());
-  purge_all_dead_edges ();
+  cse_cfg_altered |= purge_all_dead_edges ();
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
   cse_not_expected = !flag_rerun_cse_after_loop;
@@ -7711,6 +7717,9 @@ rest_of_handle_cse_after_global_opts (void)
   else if (tem == 1)
     cleanup_cfg (0);
 
+  if (cse_cfg_altered && dom_info_available_p (CDI_DOMINATORS))
+    free_dominance_info (CDI_DOMINATORS);
+
   flag_cse_follow_jumps = save_cfj;
   return 0;
 }
diff --git a/gcc/testsuite/gcc.dg/pr70807.c b/gcc/testsuite/gcc.dg/pr70807.c
new file mode 100644
index 0000000..9ef2a4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr70807.c
@@ -0,0 +1,18 @@
+/* PR middle-end/70807 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef int INT;
+int a, b, c, d, e, f;
+void fn1() {
+  INT g;
+  if (d && a)
+    ;
+  else if (e && b)
+    ;
+  else if (!a && !b && c)
+    ;
+  else if (b && d || a && e)
+    a = 0;
+  f = g || d;
+}

Reply via email to