On April 18, 2017 5:06:48 PM GMT+02:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >As can be seen on the testcase, intersect_ranges in some cases attempts >to add or subtract 1 from one of the bounds. That is fine except for >1-bit signed type, where 1 is not a value in the range of the type, >so already build_int_cst yields (OVF) constant. > >The following patch fixes it by special casing those, instead of >adding/subtracting 1 for those types it subtracts/adds -1. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ick. OK. Richard. >2017-04-18 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/80443 > * tree-vrp.c (intersect_ranges): For signed 1-bit precision type, > instead of adding 1, subtract -1 and similarly instead of subtracting > 1 add -1. > > * gcc.c-torture/compile/pr80443.c: New test. > >--- gcc/tree-vrp.c.jj 2017-03-23 15:49:55.000000000 +0100 >+++ gcc/tree-vrp.c 2017-04-18 10:09:44.560549718 +0200 >@@ -8756,20 +8756,32 @@ intersect_ranges (enum value_range_type > /* Choose the right gap if the left one is empty. */ > if (mineq) > { >- if (TREE_CODE (vr1max) == INTEGER_CST) >- *vr0min = int_const_binop (PLUS_EXPR, vr1max, >- build_int_cst (TREE_TYPE (vr1max), >1)); >- else >+ if (TREE_CODE (vr1max) != INTEGER_CST) > *vr0min = vr1max; >+ else if (TYPE_PRECISION (TREE_TYPE (vr1max)) == 1 >+ && !TYPE_UNSIGNED (TREE_TYPE (vr1max))) >+ *vr0min >+ = int_const_binop (MINUS_EXPR, vr1max, >+ build_int_cst (TREE_TYPE (vr1max), -1)); >+ else >+ *vr0min >+ = int_const_binop (PLUS_EXPR, vr1max, >+ build_int_cst (TREE_TYPE (vr1max), 1)); > } > /* Choose the left gap if the right one is empty. */ > else if (maxeq) > { >- if (TREE_CODE (vr1min) == INTEGER_CST) >- *vr0max = int_const_binop (MINUS_EXPR, vr1min, >- build_int_cst (TREE_TYPE (vr1min), >1)); >- else >+ if (TREE_CODE (vr1min) != INTEGER_CST) > *vr0max = vr1min; >+ else if (TYPE_PRECISION (TREE_TYPE (vr1min)) == 1 >+ && !TYPE_UNSIGNED (TREE_TYPE (vr1min))) >+ *vr0max >+ = int_const_binop (PLUS_EXPR, vr1min, >+ build_int_cst (TREE_TYPE (vr1min), -1)); >+ else >+ *vr0max >+ = int_const_binop (MINUS_EXPR, vr1min, >+ build_int_cst (TREE_TYPE (vr1min), 1)); > } > /* Choose the anti-range if the range is effectively varying. */ > else if (vrp_val_is_min (*vr0min) >@@ -8811,22 +8823,34 @@ intersect_ranges (enum value_range_type > if (mineq) > { > *vr0type = VR_RANGE; >- if (TREE_CODE (*vr0max) == INTEGER_CST) >- *vr0min = int_const_binop (PLUS_EXPR, *vr0max, >- build_int_cst (TREE_TYPE (*vr0max), >1)); >- else >+ if (TREE_CODE (*vr0max) != INTEGER_CST) > *vr0min = *vr0max; >+ else if (TYPE_PRECISION (TREE_TYPE (*vr0max)) == 1 >+ && !TYPE_UNSIGNED (TREE_TYPE (*vr0max))) >+ *vr0min >+ = int_const_binop (MINUS_EXPR, *vr0max, >+ build_int_cst (TREE_TYPE (*vr0max), -1)); >+ else >+ *vr0min >+ = int_const_binop (PLUS_EXPR, *vr0max, >+ build_int_cst (TREE_TYPE (*vr0max), 1)); > *vr0max = vr1max; > } > /* Choose the left gap if the right is empty. */ > else if (maxeq) > { > *vr0type = VR_RANGE; >- if (TREE_CODE (*vr0min) == INTEGER_CST) >- *vr0max = int_const_binop (MINUS_EXPR, *vr0min, >- build_int_cst (TREE_TYPE (*vr0min), >1)); >- else >+ if (TREE_CODE (*vr0min) != INTEGER_CST) > *vr0max = *vr0min; >+ else if (TYPE_PRECISION (TREE_TYPE (*vr0min)) == 1 >+ && !TYPE_UNSIGNED (TREE_TYPE (*vr0min))) >+ *vr0max >+ = int_const_binop (PLUS_EXPR, *vr0min, >+ build_int_cst (TREE_TYPE (*vr0min), -1)); >+ else >+ *vr0max >+ = int_const_binop (MINUS_EXPR, *vr0min, >+ build_int_cst (TREE_TYPE (*vr0min), 1)); > *vr0min = vr1min; > } > /* Choose the anti-range if the range is effectively varying. */ >--- gcc/testsuite/gcc.c-torture/compile/pr80443.c.jj 2017-04-18 >10:16:35.867952863 +0200 >+++ gcc/testsuite/gcc.c-torture/compile/pr80443.c 2017-04-18 >10:16:21.000000000 +0200 >@@ -0,0 +1,20 @@ >+/* PR tree-optimization/80443 */ >+ >+struct S { int a : 1; } b, c; >+signed char d, e, f; >+ >+void >+foo () >+{ >+ while (f) >+ { >+ signed char g = b.a; >+ if (g) >+ b.a = ~(1 + (d || c.a)); >+ if (b.a < g && b.a) >+ g = 0; >+ if (b.a > c.a) >+ b.a = g; >+ c.a = e; >+ } >+} > > Jakub