On February 1, 2019 12:00:26 AM GMT+01:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>As mentioned in the PR, with the introduction of ABSU_EXPR where we
>were
>previously using ABS_EXPR we've regressed various cases where VRP used
>to be
>able to determine ranges for ABS_EXPR, but as ABSU_EXPR is unknown, we
>always defer to VARYING.  ABSU_EXPR is actually much easier to handle
>than
>ABS_EXPR.  Bootstrapped/regtested on x86_64-linux and i686-linux, ok
>for
>trunk?

OK. 

Richard. 

>2019-01-31  Jakub Jelinek  <ja...@redhat.com>
>
>       PR tree-optimization/89143
>       * wide-int-range.h (wide_int_range_absu): Declare.
>       * wide-int-range.cc (wide_int_range_absu): New function.
>       * tree-vrp.c (extract_range_from_unary_expr): Handle ABSU_EXPR.
>
>       * gcc.dg/tree-ssa/vrp121.c: New test.
>
>--- gcc/wide-int-range.h.jj    2019-01-01 12:37:19.272940249 +0100
>+++ gcc/wide-int-range.h       2019-01-31 21:09:24.045463875 +0100
>@@ -107,6 +107,10 @@ extern bool wide_int_range_abs (wide_int
>                               const wide_int &vr0_min,
>                               const wide_int &vr0_max,
>                               bool overflow_undefined);
>+extern void wide_int_range_absu (wide_int &min, wide_int &max,
>+                               unsigned prec,
>+                               const wide_int &vr0_min,
>+                               const wide_int &vr0_max);
> extern bool wide_int_range_convert (wide_int &min, wide_int &max,
>                                   signop inner_sign,
>                                   unsigned inner_prec,
>--- gcc/wide-int-range.cc.jj   2019-01-01 12:37:15.627000071 +0100
>+++ gcc/wide-int-range.cc      2019-01-31 21:23:09.122900358 +0100
>@@ -735,6 +735,37 @@ wide_int_range_abs (wide_int &min, wide_
>   return true;
> }
> 
>+/* Calculate ABSU_EXPR on a range and store the result in [MIN, MAX]. 
>*/
>+
>+void
>+wide_int_range_absu (wide_int &min, wide_int &max,
>+                   unsigned prec, const wide_int &vr0_min,
>+                   const wide_int &vr0_max)
>+{
>+  /* Pass through VR0 the easy cases.  */
>+  if (wi::ges_p (vr0_min, 0))
>+    {
>+      min = vr0_min;
>+      max = vr0_max;
>+      return;
>+    }
>+
>+  min = wi::abs (vr0_min);
>+  max = wi::abs (vr0_max);
>+
>+  /* If the range contains zero then we know that the minimum value in
>the
>+     range will be zero.  */
>+  if (wi::ges_p (vr0_max, 0))
>+    {
>+      if (wi::gtu_p (min, max))
>+      max = min;
>+      min = wi::zero (prec);
>+    }
>+  else
>+    /* Otherwise, swap MIN and MAX.  */
>+    std::swap (min, max);
>+}
>+
> /* Convert range in [VR0_MIN, VR0_MAX] with INNER_SIGN and INNER_PREC,
>    to a range in [MIN, MAX] with OUTER_SIGN and OUTER_PREC.
> 
>--- gcc/tree-vrp.c.jj  2019-01-01 12:37:15.886995805 +0100
>+++ gcc/tree-vrp.c     2019-01-31 21:26:42.326334608 +0100
>@@ -2196,6 +2196,16 @@ extract_range_from_unary_expr (value_ran
>       vr->set_varying ();
>       return;
>     }
>+  else if (code == ABSU_EXPR)
>+    {
>+      wide_int wmin, wmax;
>+      wide_int vr0_min, vr0_max;
>+      extract_range_into_wide_ints (&vr0, SIGNED, prec, vr0_min,
>vr0_max);
>+      wide_int_range_absu (wmin, wmax, prec, vr0_min, vr0_max);
>+      vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
>+             wide_int_to_tree (type, wmax));
>+      return;
>+    }
> 
>   /* For unhandled operations fall back to varying.  */
>   vr->set_varying ();
>--- gcc/testsuite/gcc.dg/tree-ssa/vrp121.c.jj  2019-01-31
>22:05:49.575733486 +0100
>+++ gcc/testsuite/gcc.dg/tree-ssa/vrp121.c     2019-01-31
>22:05:15.813288163 +0100
>@@ -0,0 +1,67 @@
>+/* PR tree-optimization/89143 */
>+/* { dg-do compile } */
>+/* { dg-options "-O2 -fdump-tree-optimized" } */
>+/* { dg-final { scan-tree-dump-not "link_error \\\(" "optimized" } }
>*/
>+
>+void link_error (void);
>+
>+void
>+f1 (signed char i)
>+{
>+  if (__builtin_abs (i) < 0 || __builtin_abs (i) > __SCHAR_MAX__ + 1)
>+    link_error ();
>+}
>+
>+void
>+f2 (signed char i)
>+{
>+  if (i < 0 || i > 15)
>+    __builtin_unreachable ();
>+  if (__builtin_abs (i) < 0 || __builtin_abs (i) > 15)
>+    link_error ();
>+}
>+
>+void
>+f3 (signed char i)
>+{
>+  if (i < 19 || i > 25)
>+    __builtin_unreachable ();
>+  if (__builtin_abs (i) < 19 || __builtin_abs (i) > 25)
>+    link_error ();
>+}
>+
>+void
>+f4 (signed char i)
>+{
>+  if (i > -60)
>+    __builtin_unreachable ();
>+  if (__builtin_abs (i) < 60 || __builtin_abs (i) > __SCHAR_MAX__ + 1)
>+    link_error ();
>+}
>+
>+void
>+f5 (signed char i)
>+{
>+  if (i < -__SCHAR_MAX__ || i > -30)
>+    __builtin_unreachable ();
>+  if (__builtin_abs (i) < 30 || __builtin_abs (i) > __SCHAR_MAX__)
>+    link_error ();
>+}
>+
>+void
>+f6 (signed char i)
>+{
>+  if (i < -__SCHAR_MAX__ || i > 30)
>+    __builtin_unreachable ();
>+  if (__builtin_abs (i) < 0 || __builtin_abs (i) > __SCHAR_MAX__)
>+    link_error ();
>+}
>+
>+void
>+f7 (signed char i)
>+{
>+  if (i < -31 || i > 30)
>+    __builtin_unreachable ();
>+  if (__builtin_abs (i) < 0 || __builtin_abs (i) > 31)
>+    link_error ();
>+}
>
>       Jakub

Reply via email to