On November 21, 2014 8:04:39 PM CET, Jakub Jelinek <ja...@redhat.com> wrote:
>Hi!
>
>As discussed on IRC and in the PR, these internal calls are quite
>unique for VRP in that they return _Complex integer result,
>which VRP doesn't track, but then extract using
>REALPART_EXPR/IMAGPART_EXPR
>the two results from that _Complex int and to generate good code
>it is desirable to get proper ranges of those two results.
>The problem is that right now this works only on the first VRP
>iteration,
>the REALPART_EXPR/IMAGPART_EXPR statements are handled if their operand
>is set by {ADD,SUB,MUL}_OVERFLOW.  If we iterate because a VR of one
>of the internal call arguments changes, nothing in the propagator marks
>the REALPART_EXPR/IMAGPART_EXPR statements for reconsideration.
>
>The following patch handles this, by making the internal calls
>interesting
>to the propagator and returning the right SSA_PROP_* for it (depending
>on
>whether any of the value ranges of the REALPART_EXPR/IMAGPART_EXPR
>immediate
>uses would change or not).
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

>2014-11-21  Jakub Jelinek  <ja...@redhat.com>
>
>       PR tree-optimization/64006
>       * tree-vrp.c (stmt_interesting_for_vrp): Return true
>       for {ADD,SUB,MUL}_OVERFLOW internal calls.
>       (vrp_visit_assignment_or_call): For {ADD,SUB,MUL}_OVERFLOW
>       internal calls, check if any REALPART_EXPR/IMAGPART_EXPR
>       immediate uses would change their value ranges and return
>       SSA_PROP_INTERESTING if so, or SSA_PROP_NOT_INTERESTING
>       if there are some REALPART_EXPR/IMAGPART_EXPR immediate uses
>       interesting for vrp.
>
>       * gcc.c-torture/execute/pr64006.c: New test.
>
>--- gcc/tree-vrp.c.jj  2014-11-21 10:17:05.000000000 +0100
>+++ gcc/tree-vrp.c     2014-11-21 13:12:09.895013334 +0100
>@@ -6949,6 +6949,20 @@ stmt_interesting_for_vrp (gimple stmt)
>         && (is_gimple_call (stmt)
>             || !gimple_vuse (stmt)))
>       return true;
>+      else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
>+      switch (gimple_call_internal_fn (stmt))
>+        {
>+        case IFN_ADD_OVERFLOW:
>+        case IFN_SUB_OVERFLOW:
>+        case IFN_MUL_OVERFLOW:
>+          /* These internal calls return _Complex integer type,
>+             but are interesting to VRP nevertheless.  */
>+          if (lhs && TREE_CODE (lhs) == SSA_NAME)
>+            return true;
>+          break;
>+        default:
>+          break;
>+        }
>     }
>   else if (gimple_code (stmt) == GIMPLE_COND
>          || gimple_code (stmt) == GIMPLE_SWITCH)
>@@ -7101,6 +7115,74 @@ vrp_visit_assignment_or_call (gimple stm
> 
>       return SSA_PROP_NOT_INTERESTING;
>     }
>+  else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
>+    switch (gimple_call_internal_fn (stmt))
>+      {
>+      case IFN_ADD_OVERFLOW:
>+      case IFN_SUB_OVERFLOW:
>+      case IFN_MUL_OVERFLOW:
>+      /* These internal calls return _Complex integer type,
>+         which VRP does not track, but the immediate uses
>+         thereof might be interesting.  */
>+      if (lhs && TREE_CODE (lhs) == SSA_NAME)
>+        {
>+          imm_use_iterator iter;
>+          use_operand_p use_p;
>+          enum ssa_prop_result res = SSA_PROP_VARYING;
>+
>+          set_value_range_to_varying (get_value_range (lhs));
>+
>+          FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
>+            {
>+              gimple use_stmt = USE_STMT (use_p);
>+              if (!is_gimple_assign (use_stmt))
>+                continue;
>+              enum tree_code rhs_code = gimple_assign_rhs_code (use_stmt);
>+              if (rhs_code != REALPART_EXPR && rhs_code != IMAGPART_EXPR)
>+                continue;
>+              tree rhs1 = gimple_assign_rhs1 (use_stmt);
>+              tree use_lhs = gimple_assign_lhs (use_stmt);
>+              if (TREE_CODE (rhs1) != rhs_code
>+                  || TREE_OPERAND (rhs1, 0) != lhs
>+                  || TREE_CODE (use_lhs) != SSA_NAME
>+                  || !stmt_interesting_for_vrp (use_stmt)
>+                  || (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs))
>+                      || !TYPE_MIN_VALUE (TREE_TYPE (use_lhs))
>+                      || !TYPE_MAX_VALUE (TREE_TYPE (use_lhs))))
>+                continue;
>+
>+              /* If there is a change in the value range for any of the
>+                 REALPART_EXPR/IMAGPART_EXPR immediate uses, return
>+                 SSA_PROP_INTERESTING.  If there are any REALPART_EXPR
>+                 or IMAGPART_EXPR immediate uses, but none of them have
>+                 a change in their value ranges, return
>+                 SSA_PROP_NOT_INTERESTING.  If there are no
>+                 {REAL,IMAG}PART_EXPR uses at all,
>+                 return SSA_PROP_VARYING.  */
>+              value_range_t new_vr = VR_INITIALIZER;
>+              extract_range_basic (&new_vr, use_stmt);
>+              value_range_t *old_vr = get_value_range (use_lhs);
>+              if (old_vr->type != new_vr.type
>+                  || !vrp_operand_equal_p (old_vr->min, new_vr.min)
>+                  || !vrp_operand_equal_p (old_vr->max, new_vr.max)
>+                  || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv))
>+                res = SSA_PROP_INTERESTING;
>+              else
>+                res = SSA_PROP_NOT_INTERESTING;
>+              BITMAP_FREE (new_vr.equiv);
>+              if (res == SSA_PROP_INTERESTING)
>+                {
>+                  *output_p = lhs;
>+                  return res;
>+                }
>+            }
>+
>+          return res;
>+        }
>+      break;
>+      default:
>+      break;
>+      }
> 
>   /* Every other statement produces no useful ranges.  */
>   FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
>--- gcc/testsuite/gcc.c-torture/execute/pr64006.c.jj   2014-11-21
>13:22:08.185160990 +0100
>+++ gcc/testsuite/gcc.c-torture/execute/pr64006.c      2014-11-21
>13:29:28.259119733 +0100
>@@ -0,0 +1,26 @@
>+/* PR tree-optimization/64006 */
>+
>+int v;
>+
>+long __attribute__ ((noinline, noclone))
>+test (long *x, int y)
>+{
>+  int i;
>+  long s = 1;
>+  for (i = 0; i < y; i++)
>+    if (__builtin_mul_overflow (s, x[i], &s))
>+      v++;
>+  return s;
>+}
>+
>+int
>+main ()
>+{
>+  long d[7] = { 975, 975, 975, 975, 975, 975, 975 };
>+  long r = test (d, 7);
>+  if (sizeof (long) * __CHAR_BIT__ == 64 && v != 1)
>+    __builtin_abort ();
>+  else if (sizeof (long) * __CHAR_BIT__ == 32 && v != 4)
>+    __builtin_abort ();
>+  return 0;
>+}
>
>       Jakub


Reply via email to