This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix VRP intersect_ranges for 1-bit precision signed types (PR tree-optimization/80443)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Biener <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 18 Apr 2017 17:06:48 +0200
- Subject: [PATCH] Fix VRP intersect_ranges for 1-bit precision signed types (PR tree-optimization/80443)
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jakub at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 4DAC3369C4
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4DAC3369C4
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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?
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.
* 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