aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-07-08 11:39:57 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2014-07-08 11:39:57 +0200
commitb48e3948be3320071d3cd3a0894b04082eef8643 (patch)
treedee539372edbfbfbff7ec1bc9dc933297b8b1367 /gcc
parenta59d8e8eb67086eb6df936074ef6d8fb4834bcc2 (diff)
downloadgcc-b48e3948be3320071d3cd3a0894b04082eef8643.zip
gcc-b48e3948be3320071d3cd3a0894b04082eef8643.tar.gz
gcc-b48e3948be3320071d3cd3a0894b04082eef8643.tar.bz2
re PR middle-end/61725 (__builtin_ffs(0) leads to wrong code generation)
PR tree-optimization/61725 * tree-vrp.c (extract_range_basic): Don't assume vr0 is unsigned range, use range_includes_zerop_p instead of integer_zerop on vr0->min, only use log2 of max if min is not negative. * gcc.dg/tree-ssa/vrp93.c: New test. * gcc.c-torture/execute/pr61725.c: New test. From-SVN: r212353
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr61725.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp93.c36
-rw-r--r--gcc/tree-vrp.c9
5 files changed, 69 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f333d61..c4563ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-07-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/61725
+ * tree-vrp.c (extract_range_basic): Don't assume vr0 is unsigned
+ range, use range_includes_zerop_p instead of integer_zerop on
+ vr0->min, only use log2 of max if min is not negative.
+
2014-07-08 Richard Biener <rguenther@suse.de>
* tree-ssa-dom.h (loop_depth_of_name): Remove.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d933972..765eb9f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2014-07-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/61725
+ * gcc.dg/tree-ssa/vrp93.c: New test.
+ * gcc.c-torture/execute/pr61725.c: New test.
+
2014-07-08 Richard Biener <rguenther@suse.de>
* tree-ssa-dom.h (loop_depth_of_name): Remove.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr61725.c b/gcc/testsuite/gcc.c-torture/execute/pr61725.c
new file mode 100644
index 0000000..0aa6daf
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr61725.c
@@ -0,0 +1,14 @@
+/* PR tree-optimization/61725 */
+
+int
+main ()
+{
+ int x;
+ for (x = -128; x <= 128; x++)
+ {
+ int a = __builtin_ffs (x);
+ if (x == 0 && a != 0)
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp93.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp93.c
new file mode 100644
index 0000000..d78c399
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp93.c
@@ -0,0 +1,36 @@
+/* PR target/29776 */
+/* PR tree-optimization/61725 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-final { scan-tree-dump-not "link_error" "vrp1"} } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
+
+#define A(fn, arg, min, max) \
+ if (__builtin_##fn (arg) < min || __builtin_##fn (arg) > max) \
+ link_error ();
+#define B(fn, min, max) \
+ A (fn, a, min, max) A (fn##l, b, min, max) A (fn##ll, c, min, max)
+#define C(fn, min, sub) \
+ A (fn, a, min, ((int) sizeof (a) * __CHAR_BIT__ - sub)) \
+ A (fn##l, b, min, ((int) sizeof (b) * __CHAR_BIT__ - sub)) \
+ A (fn##ll, c, min, ((int) sizeof (c) * __CHAR_BIT__ - sub))
+
+extern void link_error (void);
+
+unsigned int d;
+unsigned long e;
+unsigned long long f;
+
+void
+foo (int a, long b, long long c)
+{
+ C (ffs, 0, 0)
+ a &= 63; b &= 63; c &= 63;
+ B (ffs, 0, 6)
+ a++; b++; c++;
+ B (ffs, 1, 7)
+ a -= 2; b -= 2; c -= 2;
+ C (ffs, 0, 0)
+ a -= 63; b -= 63; c -= 63;
+ C (ffs, 1, 0)
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 3d0916d..5fc1351 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3536,15 +3536,18 @@ extract_range_basic (value_range_t *vr, gimple stmt)
/* If arg is non-zero, then ffs or popcount
are non-zero. */
if (((vr0->type == VR_RANGE
- && integer_nonzerop (vr0->min))
+ && range_includes_zero_p (vr0->min, vr0->max) == 0)
|| (vr0->type == VR_ANTI_RANGE
- && integer_zerop (vr0->min)))
- && !is_overflow_infinity (vr0->min))
+ && range_includes_zero_p (vr0->min, vr0->max) == 1))
+ && !is_overflow_infinity (vr0->min)
+ && !is_overflow_infinity (vr0->max))
mini = 1;
/* If some high bits are known to be zero,
we can decrease the maximum. */
if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->max) == INTEGER_CST
+ && !operand_less_p (vr0->min,
+ build_zero_cst (TREE_TYPE (vr0->min)))
&& !is_overflow_infinity (vr0->max))
maxi = tree_floor_log2 (vr0->max) + 1;
}