Well, after talking with Andrew it seems that X << Y being non-zero
also implies X is non-zero.  So we don't even need relationals here.

So, I leave gori relationals in his capable hands, while I test this
much simpler patch which fixes the PR with no additional
infrastructure ;-).

Will push pending tests.
Aldy

On Fri, Oct 1, 2021 at 2:43 PM Aldy Hernandez <al...@redhat.com> wrote:
>
> Knowing that X << X is non-zero means X is also non-zero.  This patch
> teaches this this to range-ops.
>
> As usual, the big twiddling experts could come up with all sorts of
> fancy enhancements in this area, and we welcome all patches :).
>
> I will push this pending tests.
>
> gcc/ChangeLog:
>
>         PR tree-optimization/102546
>         * range-op.cc (operator_lshift::op1_range): Handle EQ_EXPR
>         relation.
> ---
>  gcc/range-op.cc                          | 19 ++++++++++++++++---
>  gcc/testsuite/gcc.dg/tree-ssa/pr102546.c | 23 +++++++++++++++++++++++
>  2 files changed, 39 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
>
> diff --git a/gcc/range-op.cc b/gcc/range-op.cc
> index 5e37133026d..53f3be4266e 100644
> --- a/gcc/range-op.cc
> +++ b/gcc/range-op.cc
> @@ -2075,9 +2075,14 @@ operator_lshift::op1_range (irange &r,
>                             tree type,
>                             const irange &lhs,
>                             const irange &op2,
> -                           relation_kind rel ATTRIBUTE_UNUSED) const
> +                           relation_kind rel) const
>  {
>    tree shift_amount;
> +  int_range<2> adjust (type);
> +
> +  if (rel == EQ_EXPR && !lhs.contains_p (build_zero_cst (type)))
> +    adjust.set_nonzero (type);
> +
>    if (op2.singleton_p (&shift_amount))
>      {
>        wide_int shift = wi::to_wide (shift_amount);
> @@ -2086,10 +2091,11 @@ operator_lshift::op1_range (irange &r,
>        if (wi::ge_p (shift, wi::uhwi (TYPE_PRECISION (type),
>                                      TYPE_PRECISION (op2.type ())),
>                     UNSIGNED))
> -       return false;
> +       goto done;
>        if (shift == 0)
>         {
>           r = lhs;
> +         r.intersect (adjust);
>           return true;
>         }
>
> @@ -2126,9 +2132,16 @@ operator_lshift::op1_range (irange &r,
>
>        if (utype != type)
>         range_cast (r, type);
> +      r.intersect (adjust);
>        return true;
>      }
> -  return false;
> +
> + done:
> +  if (adjust.varying_p ())
> +    return false;
> +
> +  r = adjust;
> +  return true;
>  }
>
>  bool
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
> new file mode 100644
> index 00000000000..4bd98747732
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
> @@ -0,0 +1,23 @@
> +// { dg-do compile }
> +// { dg-options "-O3 -fdump-tree-optimized" }
> +
> +static int a;
> +static char b, c, d;
> +void bar(void);
> +void foo(void);
> +
> +int main() {
> +    int f = 0;
> +    for (; f <= 5; f++) {
> +        bar();
> +        b = b && f;
> +        d = f << f;
> +        if (!(a >= d || f))
> +            foo();
> +        c = 1;
> +        for (; c; c = 0)
> +            ;
> +    }
> +}
> +
> +// { dg-final { scan-tree-dump-not "foo" "optimized" } }
> --
> 2.31.1
>
From fa11285b9ff1d75c877369c1df7760c3f76a4fe5 Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <al...@redhat.com>
Date: Fri, 1 Oct 2021 13:05:36 +0200
Subject: [PATCH] [PR102546] X << Y being non-zero implies X is also non-zero.

This patch teaches this to range-ops.

Tested on x86-64 Linux.

gcc/ChangeLog:

	PR tree-optimization/102546
	* range-op.cc (operator_lshift::op1_range): Teach range-ops that
	X << Y is non-zero implies X is also non-zero.
---
 gcc/range-op.cc                          | 18 ++++++++++++++----
 gcc/testsuite/gcc.dg/tree-ssa/pr102546.c | 23 +++++++++++++++++++++++
 2 files changed, 37 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr102546.c

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 5e37133026d..2baca4a197f 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2078,6 +2078,12 @@ operator_lshift::op1_range (irange &r,
 			    relation_kind rel ATTRIBUTE_UNUSED) const
 {
   tree shift_amount;
+
+  if (!lhs.contains_p (build_zero_cst (type)))
+    r.set_nonzero (type);
+  else
+    r.set_varying (type);
+
   if (op2.singleton_p (&shift_amount))
     {
       wide_int shift = wi::to_wide (shift_amount);
@@ -2089,21 +2095,24 @@ operator_lshift::op1_range (irange &r,
 	return false;
       if (shift == 0)
 	{
-	  r = lhs;
+	  r.intersect (lhs);
 	  return true;
 	}
 
       // Work completely in unsigned mode to start.
       tree utype = type;
+      int_range_max tmp_range;
       if (TYPE_SIGN (type) == SIGNED)
 	{
 	  int_range_max tmp = lhs;
 	  utype = unsigned_type_for (type);
 	  range_cast (tmp, utype);
-	  op_rshift.fold_range (r, utype, tmp, op2);
+	  op_rshift.fold_range (tmp_range, utype, tmp, op2);
 	}
       else
-	op_rshift.fold_range (r, utype, lhs, op2);
+	op_rshift.fold_range (tmp_range, utype, lhs, op2);
+
+      r.intersect (tmp_range);
 
       // Start with ranges which can produce the LHS by right shifting the
       // result by the shift amount.
@@ -2128,7 +2137,8 @@ operator_lshift::op1_range (irange &r,
 	range_cast (r, type);
       return true;
     }
-  return false;
+
+  return !r.varying_p ();
 }
 
 bool
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
new file mode 100644
index 00000000000..4bd98747732
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-O3 -fdump-tree-optimized" }
+
+static int a;
+static char b, c, d;
+void bar(void);
+void foo(void);
+
+int main() {
+    int f = 0;
+    for (; f <= 5; f++) {
+        bar();
+        b = b && f;
+        d = f << f;
+        if (!(a >= d || f))
+            foo();
+        c = 1;
+        for (; c; c = 0)
+            ;
+    }
+}
+
+// { dg-final { scan-tree-dump-not "foo" "optimized" } }
-- 
2.31.1

Reply via email to