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 <mli...@suse.cz> 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 <mli...@suse.cz> 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;