widening_mul: Fix up ICE caused by my signed multiplication overflow pattern recognit...
authorJakub Jelinek <jakub@redhat.com>
Tue, 12 Jan 2021 10:04:46 +0000 (11:04 +0100)
committerJakub Jelinek <jakub@redhat.com>
Tue, 12 Jan 2021 10:04:46 +0000 (11:04 +0100)
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.

gcc/testsuite/gcc.c-torture/compile/pr98629.c [new file with mode: 0644]
gcc/tree-ssa-math-opts.c

diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98629.c b/gcc/testsuite/gcc.c-torture/compile/pr98629.c
new file mode 100644 (file)
index 0000000..3c7f08c
--- /dev/null
@@ -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);
+}
index 91b3d1baa34ef8ec5151c9113fcf0a7a7e78d577..5175ab524dc90fd20e94f05bbb2422da1e397a0b 100644 (file)
@@ -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: