Handle EQ_EXPR relation for operator_lshift.

Message ID 20211001124306.1458223-3-aldyh@redhat.com
State New
Headers
Series Handle EQ_EXPR relation for operator_lshift. |

Commit Message

Aldy Hernandez Oct. 1, 2021, 12:43 p.m. UTC
  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
  

Comments

Aldy Hernandez Oct. 1, 2021, 2:52 p.m. UTC | #1
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 <aldyh@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
>
  
Aldy Hernandez Oct. 2, 2021, 7:50 p.m. UTC | #2
Bah.  The range was being clobbered half way through the calculation.

Tested on x86-64 Linux.

Pushed.

On Fri, Oct 1, 2021 at 4:52 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> 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 <aldyh@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
> >
  
Jeff Law Oct. 2, 2021, 8:53 p.m. UTC | #3
On 10/2/2021 1:50 PM, Aldy Hernandez via Gcc-patches wrote:
> Bah.  The range was being clobbered half way through the calculation.
>
> Tested on x86-64 Linux.
>
> Pushed.
>
> On Fri, Oct 1, 2021 at 4:52 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>> 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 <aldyh@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.
I'm going to assume this also fixes a similar ICE building the linux 
kernel.  One less thing to bisect today :-)

jeff
  

Patch

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" } }