Clean-up EH after strlen transformation (PR tree-optimization/83593).
authorMartin Liska <mliska@suse.cz>
Wed, 3 Jan 2018 14:53:39 +0000 (15:53 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Wed, 3 Jan 2018 14:53:39 +0000 (14:53 +0000)
2018-01-03  Martin Liska  <mliska@suse.cz>

PR tree-optimization/83593
* tree-ssa-strlen.c: Include tree-cfg.h.
(strlen_check_and_optimize_stmt): Add new argument cleanup_eh.
(strlen_dom_walker): Add new member variable m_cleanup_cfg.
(strlen_dom_walker::strlen_dom_walker): Initialize m_cleanup_cfg
to false.
(strlen_dom_walker::before_dom_children): Call
gimple_purge_dead_eh_edges. Dump tranformation with details
dump flags.
(strlen_dom_walker::before_dom_children): Update call by adding
new argument cleanup_eh.
(pass_strlen::execute): Return TODO_cleanup_cfg if needed.
2018-01-03  Martin Liska  <mliska@suse.cz>

PR tree-optimization/83593
* gcc.dg/pr83593.c: New test.

From-SVN: r256178

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr83593.c [new file with mode: 0644]
gcc/tree-ssa-strlen.c

index ad327b955d376e960f8e2ceb9bf2df57fbcc45af..95b5ed2468da9f42a4b9ec930a5865f4b63fc95e 100644 (file)
@@ -1,3 +1,18 @@
+2018-01-03  Martin Liska  <mliska@suse.cz>
+
+       PR tree-optimization/83593
+       * tree-ssa-strlen.c: Include tree-cfg.h.
+       (strlen_check_and_optimize_stmt): Add new argument cleanup_eh.
+       (strlen_dom_walker): Add new member variable m_cleanup_cfg.
+       (strlen_dom_walker::strlen_dom_walker): Initialize m_cleanup_cfg
+       to false.
+       (strlen_dom_walker::before_dom_children): Call
+       gimple_purge_dead_eh_edges. Dump tranformation with details
+       dump flags.
+       (strlen_dom_walker::before_dom_children): Update call by adding
+       new argument cleanup_eh.
+       (pass_strlen::execute): Return TODO_cleanup_cfg if needed.
+
 2018-01-03  Martin Liska  <mliska@suse.cz>
 
        PR ipa/83549
index 969ce39efef36240ee1222322302469342a3dcb9..f389dea6971ae233663241a18c7baee987f1096f 100644 (file)
@@ -1,3 +1,8 @@
+2018-01-03  Martin Liska  <mliska@suse.cz>
+
+       PR tree-optimization/83593
+       * gcc.dg/pr83593.c: New test.
+
 2018-01-03  Martin Liska  <mliska@suse.cz>
 
        PR ipa/83549
diff --git a/gcc/testsuite/gcc.dg/pr83593.c b/gcc/testsuite/gcc.dg/pr83593.c
new file mode 100644 (file)
index 0000000..eddecc0
--- /dev/null
@@ -0,0 +1,15 @@
+/* PR tree-optimization/83593 */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fnon-call-exceptions -fno-tree-pre -fexceptions -fno-code-hoisting -fno-tree-fre" } */
+
+void
+hr (int *ed, signed char *ju)
+{
+  int kc;
+    {
+      int xj;
+      int *q2 = (*ed == 0) ? &xj : &kc;
+
+      *ju = 0;
+      kc = *ju;
+    }
+}
index c8b86b69dbe2bd65261fa7713042e160ce181d84..8f7020c14b3fb4723a1ae45528fe4dc48b024f46 100644 (file)
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimplify-me.h"
 #include "expr.h"
+#include "tree-cfg.h"
 #include "tree-dfa.h"
 #include "domwalk.h"
 #include "tree-ssa-alias.h"
@@ -3051,10 +3052,12 @@ fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
 }
 
 /* Attempt to check for validity of the performed access a single statement
-   at *GSI using string length knowledge, and to optimize it.  */
+   at *GSI using string length knowledge, and to optimize it.
+   If the given basic block needs clean-up of EH, CLEANUP_EH is set to
+   true.  */
 
 static bool
-strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi)
+strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh)
 {
   gimple *stmt = gsi_stmt (*gsi);
 
@@ -3201,11 +3204,27 @@ strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi)
                    if (w1 == w2
                        && si->full_string_p)
                      {
+                       if (dump_file && (dump_flags & TDF_DETAILS) != 0)
+                         {
+                           fprintf (dump_file, "Optimizing: ");
+                           print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+                         }
+
                        /* Reading the final '\0' character.  */
                        tree zero = build_int_cst (TREE_TYPE (lhs), 0);
                        gimple_set_vuse (stmt, NULL_TREE);
                        gimple_assign_set_rhs_from_tree (gsi, zero);
-                       update_stmt (gsi_stmt (*gsi));
+                       *cleanup_eh
+                         |= maybe_clean_or_replace_eh_stmt (stmt,
+                                                            gsi_stmt (*gsi));
+                       stmt = gsi_stmt (*gsi);
+                       update_stmt (stmt);
+
+                       if (dump_file && (dump_flags & TDF_DETAILS) != 0)
+                         {
+                           fprintf (dump_file, "into: ");
+                           print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+                         }
                      }
                    else if (w1 > w2)
                      {
@@ -3318,10 +3337,16 @@ do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
 class strlen_dom_walker : public dom_walker
 {
 public:
-  strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
+  strlen_dom_walker (cdi_direction direction)
+    : dom_walker (direction), m_cleanup_cfg (false)
+  {}
 
   virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
+
+  /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
+     execute function.  */
+  bool m_cleanup_cfg;
 };
 
 /* Callback for walk_dominator_tree.  Attempt to optimize various
@@ -3399,11 +3424,16 @@ strlen_dom_walker::before_dom_children (basic_block bb)
        }
     }
 
+  bool cleanup_eh = false;
+
   /* Attempt to optimize individual statements.  */
   for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
-    if (strlen_check_and_optimize_stmt (&gsi))
+    if (strlen_check_and_optimize_stmt (&gsi, &cleanup_eh))
       gsi_next (&gsi);
 
+  if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
+      m_cleanup_cfg = true;
+
   bb->aux = stridx_to_strinfo;
   if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
     (*stridx_to_strinfo)[0] = (strinfo *) bb;
@@ -3477,7 +3507,8 @@ pass_strlen::execute (function *fun)
 
   /* String length optimization is implemented as a walk of the dominator
      tree and a forward walk of statements within each block.  */
-  strlen_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
+  strlen_dom_walker walker (CDI_DOMINATORS);
+  walker.walk (fun->cfg->x_entry_block_ptr);
 
   ssa_ver_to_stridx.release ();
   strinfo_pool.release ();
@@ -3498,7 +3529,7 @@ pass_strlen::execute (function *fun)
       strlen_to_stridx = NULL;
     }
 
-  return 0;
+  return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
 }
 
 } // anon namespace