In the core of gori_compute::logical_combine we are suppose to combine
the calculated true and false ranges on each side of the operation.
when encountering
[0,0] = c_3 | c_4
we know we only need to consider the FALSE values of the range carried
by c_3 and c_4, but it can be EITHER of those ranges, so we need to
union them together to get the correct result.
The code was performing an intersection instead, and in this particualr
case, we knew the range carried thru c_3 was alwasy [0,0] and it was
always varying through c_4.... instead of returning varying, we were
returning [0,0] which then caused some folding which was incorrect.
Fixed by correctly calling union...
Bootstrapped on x86_64-pc-linux-gnu, no regressions, and pushed.
Andrew
commit 48722d158cbf692c24025e345ecbbbb570f66aa5
Author: Andrew MacLeod <amacl...@redhat.com>
Date: Mon Oct 26 14:55:00 2020 -0400
Combine logical OR ranges properly.
When combining logical OR operands with a FALSE result, union the false
ranges for operand1 and operand2... not intersection.
gcc/
PR tree-optimization/97567
* gimple-range-gori.cc (gori_compute::logical_combine): Union the
ranges of operand1 and operand2, not intersect.
gcc/testsuite/
* gcc.dg/pr97567.c: New.
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 5d50b111d2a..de0f653860d 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -730,10 +730,10 @@ gori_compute::logical_combine (irange &r, enum tree_code code,
if (lhs.zero_p ())
{
// An OR operation will only take the FALSE path if both
- // operands are false, so [20, 255] intersect [0, 5] is the
+ // operands are false, so either [20, 255] or [0, 5] is the
// union: [0,5][20,255].
r = op1.false_range;
- r.intersect (op2.false_range);
+ r.union_ (op2.false_range);
}
else
{
diff --git a/gcc/testsuite/gcc.dg/pr97567.c b/gcc/testsuite/gcc.dg/pr97567.c
new file mode 100644
index 00000000000..b2b72a4d2a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97567.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int a, b, c, d;
+void k() {
+ unsigned f = 1;
+ long g = 4073709551615;
+ for (; a; a++)
+ for (;;) {
+ d = 0;
+ L1:
+ break;
+ }
+ if (f)
+ for (; a; a++)
+ ;
+ g || f;
+ int i = 0 - f || g;
+ long j = g - f;
+ if (j || f) {
+ if (g < 4073709551615)
+ for (;;)
+ ;
+ int e = ~f, h = b / ~e;
+ if (c)
+ goto L2;
+ g = f = h;
+ }
+ g || d;
+L2:
+ if (c)
+ goto L1;
+}
+int main() { k(); return 0; }