diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-01-12 11:04:46 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-01-12 11:04:46 +0100 |
commit | 24ea113f75cfad38894dc1ad16b23c0538ef17d4 (patch) | |
tree | 1340c30d7161c93e6435fbccf4198251a6e76efb /gcc | |
parent | 13d47c37a2c043f3e5981e73e4c82158a39f41e8 (diff) | |
download | gcc-24ea113f75cfad38894dc1ad16b23c0538ef17d4.zip gcc-24ea113f75cfad38894dc1ad16b23c0538ef17d4.tar.gz gcc-24ea113f75cfad38894dc1ad16b23c0538ef17d4.tar.bz2 |
widening_mul: Fix up ICE caused by my signed multiplication overflow pattern recognition changes [PR98629]
As the testcase shows, my latest changes caused ICE on that testcase.
The problem is that arith_overflow_check_p now can change the use_stmt
argument (has a reference), so that if it succeeds (returns non-zero),
it points it to the GIMPLE_COND or EQ/NE or COND_EXPR assignment from the
TRUNC_DIV_EXPR assignment.
The problem was that it would change use_stmt also if it returned 0 in some
cases, such as multiple imm uses of the division, and in one of the callers
if arith_overflow_check_p returns 0 it looks at use_stmt again and performs
other checks, which of course assumes that use_stmt is the one passed
to arith_overflow_check_p and not e.g. NULL instead or some other unrelated
stmt.
The following patch fixes that by only changing use_stmt when we are about
to return non-zero (for the MULT_EXPR case, which is the only one with the
need to use different use_stmt).
2021-01-12 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/98629
* tree-ssa-math-opts.c (arith_overflow_check_p): Don't update use_stmt
unless returning non-zero.
* gcc.c-torture/compile/pr98629.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr98629.c | 11 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 35 |
2 files changed, 32 insertions, 14 deletions
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98629.c b/gcc/testsuite/gcc.c-torture/compile/pr98629.c new file mode 100644 index 0000000..3c7f08c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr98629.c @@ -0,0 +1,11 @@ +/* PR tree-optimization/98629 */ + +unsigned int a; +int b, c; + +void +foo (void) +{ + unsigned int *e = &a; + (a /= a |= b) - (0 <= (*e += *e)) * (c *= *e); +} diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 91b3d1b..5175ab5 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -3667,6 +3667,7 @@ arith_overflow_check_p (gimple *stmt, gimple *cast_stmt, gimple *&use_stmt, tree rhs1 = gimple_assign_rhs1 (stmt); tree rhs2 = gimple_assign_rhs2 (stmt); tree multop = NULL_TREE, divlhs = NULL_TREE; + gimple *cur_use_stmt = use_stmt; if (code == MULT_EXPR) { @@ -3697,26 +3698,26 @@ arith_overflow_check_p (gimple *stmt, gimple *cast_stmt, gimple *&use_stmt, if (!divlhs) return 0; use_operand_p use; - if (!single_imm_use (divlhs, &use, &use_stmt)) + if (!single_imm_use (divlhs, &use, &cur_use_stmt)) return 0; } - if (gimple_code (use_stmt) == GIMPLE_COND) + if (gimple_code (cur_use_stmt) == GIMPLE_COND) { - ccode = gimple_cond_code (use_stmt); - crhs1 = gimple_cond_lhs (use_stmt); - crhs2 = gimple_cond_rhs (use_stmt); + ccode = gimple_cond_code (cur_use_stmt); + crhs1 = gimple_cond_lhs (cur_use_stmt); + crhs2 = gimple_cond_rhs (cur_use_stmt); } - else if (is_gimple_assign (use_stmt)) + else if (is_gimple_assign (cur_use_stmt)) { - if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS) + if (gimple_assign_rhs_class (cur_use_stmt) == GIMPLE_BINARY_RHS) { - ccode = gimple_assign_rhs_code (use_stmt); - crhs1 = gimple_assign_rhs1 (use_stmt); - crhs2 = gimple_assign_rhs2 (use_stmt); + ccode = gimple_assign_rhs_code (cur_use_stmt); + crhs1 = gimple_assign_rhs1 (cur_use_stmt); + crhs2 = gimple_assign_rhs2 (cur_use_stmt); } - else if (gimple_assign_rhs_code (use_stmt) == COND_EXPR) + else if (gimple_assign_rhs_code (cur_use_stmt) == COND_EXPR) { - tree cond = gimple_assign_rhs1 (use_stmt); + tree cond = gimple_assign_rhs1 (cur_use_stmt); if (COMPARISON_CLASS_P (cond)) { ccode = TREE_CODE (cond); @@ -3792,11 +3793,17 @@ arith_overflow_check_p (gimple *stmt, gimple *cast_stmt, gimple *&use_stmt, { if ((crhs1 == divlhs && arith_cast_equal_p (crhs2, multop)) || (crhs2 == divlhs && arith_cast_equal_p (crhs1, multop))) - return ccode == NE_EXPR ? 1 : -1; + { + use_stmt = cur_use_stmt; + return ccode == NE_EXPR ? 1 : -1; + } } else if ((crhs1 == divlhs && operand_equal_p (crhs2, multop, 0)) || (crhs2 == divlhs && crhs1 == multop)) - return ccode == NE_EXPR ? 1 : -1; + { + use_stmt = cur_use_stmt; + return ccode == NE_EXPR ? 1 : -1; + } } break; default: |