Hi.
Strlen pass does following transformation:
Optimizing: _7 = *ju_5(D);
into: _7 = 0;
which leads to need of removal of EH for the gimple statement. That's done via
maybe_clean_or_replace_eh_stmt
and then we need to call gimple_purge_dead_eh_edges. Last question I have is
whether it's also needed to
return TODO_cleanup_cfg or not?
Patch as is can bootstrap on ppc64le-redhat-linux and survives regression tests.
Martin
gcc/ChangeLog:
2018-01-03 Martin Liska <[email protected]>
PR tree-optimization/83593
* tree-ssa-strlen.c (strlen_check_and_optimize_stmt): Clean-up
EH gimple statements.
(strlen_dom_walker::before_dom_children): Call
gimple_purge_dead_eh_edges.
gcc/testsuite/ChangeLog:
2018-01-03 Martin Liska <[email protected]>
PR tree-optimization/83593
* gcc.dg/pr83593.c: New test.
---
gcc/testsuite/gcc.dg/pr83593.c | 15 +++++++++++++++
gcc/tree-ssa-strlen.c | 28 +++++++++++++++++++++++++---
2 files changed, 40 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/pr83593.c
diff --git a/gcc/testsuite/gcc.dg/pr83593.c b/gcc/testsuite/gcc.dg/pr83593.c
new file mode 100644
index 00000000000..eddecc0606a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr83593.c
@@ -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;
+ }
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index be6ab9f1e1b..293aeceacce 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -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,25 @@ 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);
+ *cleanup_eh = maybe_clean_or_replace_eh_stmt (stmt,
+ stmt);
update_stmt (gsi_stmt (*gsi));
+
+ 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)
{
@@ -3399,11 +3416,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);
+
bb->aux = stridx_to_strinfo;
if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
(*stridx_to_strinfo)[0] = (strinfo *) bb;