diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0278e495ef58dac933a912c0041494f6061659e0..ea44ddb553ea3f015ada80eb38d706f25b14fdf2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-04-18 Jakub Jelinek <jakub@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. + 2017-04-18 Richard Sandiford <richard.sandiford@arm.com> PR rtl-optimization/80357 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 05c5e23f07e34fcaa965ea3dff816afcaa767531..11410bb7045f8364664fc77a927346fd361a8d9a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-04-18 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/80443 + * gcc.c-torture/compile/pr80443.c: New test. + 2017-04-18 Richard Sandiford <richard.sandiford@arm.com> PR rtl-optimization/80357 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr80443.c b/gcc/testsuite/gcc.c-torture/compile/pr80443.c new file mode 100644 index 0000000000000000000000000000000000000000..8c30cce3488badf128b37f44b3aa79cdc325c9e5 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr80443.c @@ -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; + } +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 28d9c175dcd45497154494c92e83874e2f2a4111..6d802de29a802376efd5e164091bdb1a740edbb8 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -8756,20 +8756,32 @@ intersect_ranges (enum value_range_type *vr0type, /* 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 *vr0type, 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. */