On Tue, Sep 25, 2012 at 1:23 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > This patch fixes two spots where signed 1-bit precision isn't handled > properly in VRP. With that type, build_int_cst (TREE_TYPE (min), 1) > will overflow and thus adding it to something or subtracting leads to > ICEs or bad code. In the first spot min is different from max, which > for 1-bit precision implies either all values, or none (but we don't have > empty ranges and fallback to varying for those anyway).
emty ranges are turned into VR_UNDEFINED in intersect_range for example (but not consistently so I see, not in set_and_canonicalize_value_range at least). > In the second case we can optimize if the anti range is singleton, then > the corresponding range is singleton too (the other value). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Ok. Thanks, Richard. > 2012-09-25 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/54676 > * tree-vrp.c (set_and_canonicalize_value_range): Handle > one bit precision properly. > > * gcc.dg/pr54676.c: New test. > > --- gcc/tree-vrp.c.jj 2012-09-17 11:13:12.000000000 +0200 > +++ gcc/tree-vrp.c 2012-09-24 10:06:10.814376659 +0200 > @@ -501,8 +501,19 @@ set_and_canonicalize_value_range (value_ > to adjust them. */ > if (tree_int_cst_lt (max, min)) > { > - tree one = build_int_cst (TREE_TYPE (min), 1); > - tree tmp = int_const_binop (PLUS_EXPR, max, one); > + tree one, tmp; > + > + /* For one bit precision if max < min, then the swapped > + range covers all values, so for VR_RANGE it is varying and > + for VR_ANTI_RANGE empty range, so drop to varying as well. */ > + if (TYPE_PRECISION (TREE_TYPE (min)) == 1) > + { > + set_value_range_to_varying (vr); > + return; > + } > + > + one = build_int_cst (TREE_TYPE (min), 1); > + tmp = int_const_binop (PLUS_EXPR, max, one); > max = int_const_binop (MINUS_EXPR, min, one); > min = tmp; > > @@ -531,6 +542,24 @@ set_and_canonicalize_value_range (value_ > set_value_range_to_varying (vr); > return; > } > + else if (TYPE_PRECISION (TREE_TYPE (min)) == 1 > + && !TYPE_UNSIGNED (TREE_TYPE (min)) > + && (is_min || is_max)) > + { > + /* For signed 1-bit precision, one is not in-range and > + thus adding/subtracting it would result in overflows. */ > + if (operand_equal_p (min, max, 0)) > + { > + min = max = is_min ? vrp_val_max (TREE_TYPE (min)) > + : vrp_val_min (TREE_TYPE (min)); > + t = VR_RANGE; > + } > + else > + { > + set_value_range_to_varying (vr); > + return; > + } > + } > else if (is_min > /* As a special exception preserve non-null ranges. */ > && !(TYPE_UNSIGNED (TREE_TYPE (min)) > --- gcc/testsuite/gcc.dg/pr54676.c.jj 2012-09-24 10:52:48.911691835 +0200 > +++ gcc/testsuite/gcc.dg/pr54676.c 2012-09-24 10:52:30.000000000 +0200 > @@ -0,0 +1,23 @@ > +/* PR tree-optimization/54676 */ > +/* { dg-do compile } */ > +/* { dg-options "-O -fno-tree-ccp -fno-tree-copy-prop -fno-tree-fre > -ftree-vrp" } */ > + > +struct S > +{ > + int s:1; > +}; > + > +struct S bar (void); > + > +int a; > + > +void > +foo (int x) > +{ > + struct S s = bar (); > + while (!a) > + { > + int l = 94967295; > + a = x || (s.s &= l); > + } > +} > > Jakub