From: Jakub Jelinek Date: Sun, 13 Dec 2020 18:25:33 +0000 (+0100) Subject: widening_mul: Fix a > ~b to .ADD_OVERFLOW optimization [PR98256] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=49ec63666e086853401021e686f0aa4d285ce9dc;p=gcc.git widening_mul: Fix a > ~b to .ADD_OVERFLOW optimization [PR98256] Unfortunately, my latest tree-ssa-math-opts.c patch broke the following testcase. The problem is that the code is adding .ADD_OVERFLOW or .SUB_OVERFLOW before or after the stmt on which the function has been called, which is normally a addition or subtraction that has all the operands. But in the a > ~b optimization that stmt is the ~b stmt and the other comparison operand might be defined only after that ~b stmt, so we can't insert the .ADD_OVERFLOW next to ~b that we want to delete, but need to insert it before the a > temp comparison that uses it; and in that case when removing the BIT_NOT_EXPR stmt we need to ensure the caller doesn't do gsi_next because gsi_remove already points the iterator to the next stmt. 2020-12-13 Jakub Jelinek PR tree-optimization/98256 * tree-ssa-math-opts.c (match_uaddsub_overflow): For BIT_NOT_EXPR, only handle a single use, and insert .ADD_OVERFLOW before the comparison rather than after the BIT_NOT_EXPR. Return true iff it is BIT_NOT_EXPR and it has been removed. (math_opts_dom_walker::after_dom_children) : If match_uaddsub_overflow returned true, continue instead of break. * gcc.c-torture/compile/pr98256.c: New test. --- diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98256.c b/gcc/testsuite/gcc.c-torture/compile/pr98256.c new file mode 100644 index 00000000000..44839c7b42a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr98256.c @@ -0,0 +1,9 @@ +/* PR tree-optimization/98256 */ + +unsigned a, b; + +int +foo (void) +{ + return !!(~a / b); +} diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index b8cdce94bff..c74b763d99a 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -3598,6 +3598,7 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt, gimple *use_stmt; gimple *add_stmt = NULL; bool add_first = false; + gimple *cond_stmt = NULL; gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR @@ -3628,8 +3629,9 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt, return false; if (rhs2 == NULL) rhs2 = other; - else if (rhs2 != other) + else return false; + cond_stmt = use_stmt; } ovf_use_seen = true; } @@ -3818,6 +3820,9 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt, } } + if (code == BIT_NOT_EXPR) + *gsi = gsi_for_stmt (cond_stmt); + tree ctype = build_complex_type (type); gcall *g = gimple_build_call_internal (code != MINUS_EXPR ? IFN_ADD_OVERFLOW : IFN_SUB_OVERFLOW, @@ -3843,7 +3848,10 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt, tree ovf = make_ssa_name (type); g2 = gimple_build_assign (ovf, IMAGPART_EXPR, build1 (IMAGPART_EXPR, type, ctmp)); - gsi_insert_after (gsi, g2, GSI_NEW_STMT); + if (code != BIT_NOT_EXPR) + gsi_insert_after (gsi, g2, GSI_NEW_STMT); + else + gsi_insert_before (gsi, g2, GSI_SAME_STMT); FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) { @@ -3908,11 +3916,12 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt, } else if (code == BIT_NOT_EXPR) { - gimple_stmt_iterator gsi2 = gsi_for_stmt (stmt); - gsi_remove (&gsi2, true); + *gsi = gsi_for_stmt (stmt); + gsi_remove (gsi, true); release_ssa_name (lhs); + return true; } - return true; + return false; } /* Return true if target has support for divmod. */ @@ -4238,7 +4247,8 @@ math_opts_dom_walker::after_dom_children (basic_block bb) break; case BIT_NOT_EXPR: - match_uaddsub_overflow (&gsi, stmt, code); + if (match_uaddsub_overflow (&gsi, stmt, code)) + continue; break; case TRUNC_MOD_EXPR: