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