mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-13 22:11:47 +08:00
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 <jakub@redhat.com> 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) <case BIT_NOT_EXPR>: If match_uaddsub_overflow returned true, continue instead of break. * gcc.c-torture/compile/pr98256.c: New test.
This commit is contained in:
parent
3cc4e183f1
commit
49ec63666e
9
gcc/testsuite/gcc.c-torture/compile/pr98256.c
Normal file
9
gcc/testsuite/gcc.c-torture/compile/pr98256.c
Normal file
@ -0,0 +1,9 @@
|
||||
/* PR tree-optimization/98256 */
|
||||
|
||||
unsigned a, b;
|
||||
|
||||
int
|
||||
foo (void)
|
||||
{
|
||||
return !!(~a / b);
|
||||
}
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user