[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0

2021-01-16 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96669

Jakub Jelinek  changed:

   What|Removed |Added

 Resolution|--- |FIXED
 Status|NEW |RESOLVED

--- Comment #6 from Jakub Jelinek  ---
Fixed.

[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0

2021-01-16 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96669

--- Comment #5 from CVS Commits  ---
The master branch has been updated by Jakub Jelinek :

https://gcc.gnu.org/g:e2559c3945a09521ffe4f59669bc4d902ae77adb

commit r11-6748-ge2559c3945a09521ffe4f59669bc4d902ae77adb
Author: Jakub Jelinek 
Date:   Sat Jan 16 09:21:52 2021 +0100

match.pd: Optimize ((cst << x) & 1) [PR96669]

While we had a ((1 << x) & 1) != 0 to x == 0 optimization already,
this patch adds ((cst << x) & 1) optimization too, this time the
second constant must be 1 though, not some power of two, but the first
one can be any constant.  If it is even, the result is false, if it is
odd, the result is x == 0.

2021-01-16  Jakub Jelinek  

PR tree-optimization/96669
* match.pd ((CST << x) & 1 -> x == 0): New simplification.

* gcc.dg/tree-ssa/pr96669-1.c: Adjust regexp.
* gcc.dg/tree-ssa/pr96669-2.c: New test.

[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0

2021-01-15 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96669

--- Comment #4 from CVS Commits  ---
The master branch has been updated by Jakub Jelinek :

https://gcc.gnu.org/g:0425f4c1b63107bf3bc4778d1fe53c91ace7838d

commit r11-6739-g0425f4c1b63107bf3bc4778d1fe53c91ace7838d
Author: Jakub Jelinek 
Date:   Fri Jan 15 21:12:14 2021 +0100

match.pd: Generalize the PR64309 simplifications [PR96669]

The following patch generalizes the PR64309 simplifications, so that
instead
of working only with constants 1 and 1 it works with any two power of two
constants, and works also for right shift (in that case it rules out the
first one being negative, as it is arithmetic shift then).

2021-01-15  Jakub Jelinek  

PR tree-optimization/96669
* match.pd (((1 << A) & 1) != 0 -> A == 0,
((1 << A) & 1) == 0 -> A != 0): Generalize for 1s replaced by
possibly different power of two constants and to right shift too.

* gcc.dg/tree-ssa/pr96669-1.c: New test.

[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0

2021-01-15 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96669

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org

--- Comment #3 from Jakub Jelinek  ---
Seems we already since 2014 had a rule for this when the result is compared
against 0.

Anyway, here is a generalization of that plus an attempt at handling this
specific case without the comparison:

--- gcc/match.pd.jj 2021-01-15 14:00:21.567135280 +0100
+++ gcc/match.pd2021-01-15 16:55:30.658692184 +0100
@@ -3117,13 +3117,33 @@ (define_operator_list COND_TERNARY
   (op @0 { build_int_cst (TREE_TYPE (@1), low); })))


-/* ((1 << A) & 1) != 0 -> A == 0
-   ((1 << A) & 1) == 0 -> A != 0 */
+/* Simplify (CST << x) & 1 to 0 if CST is even or to x == 0 if it is odd.  /
+(simplify
+ (bit_and (lshift INTEGER_CST@1 @0) integer_onep)
+  (if ((wi::to_wide (@1) & 1) != 0)
+   (eq @0 { build_zero_cst (TREE_TYPE (@0)); })
+   ({ build_zero_cst (type); })))
+
+/* Simplify ((C << x) & D) != 0 where C and D are power of two constants,
+   either to false if D is smaller (unsigned comparison) than C, or to
+   x == log2 (D) - log2 (C).  Similarly for right shifts.  */
 (for cmp (ne eq)
  icmp (eq ne)
  (simplify
-  (cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop)
-  (icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
+  (cmp (bit_and (lshift integer_pow2p@1 @0) integer_pow2p@2) integer_zerop)
+   (with { int c1 = wi::clz (wi::to_wide (@1));
+  int c2 = wi::clz (wi::to_wide (@2)); }
+(if (c1 < c2)
+ { constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
+ (icmp @0 { build_int_cst (TREE_TYPE (@0), c1 - c2); }
+ (simplify
+  (cmp (bit_and (rshift integer_pow2p@1 @0) integer_pow2p@2) integer_zerop)
+   (if (tree_int_cst_sgn (@1) > 0)
+(with { int c1 = wi::clz (wi::to_wide (@1));
+   int c2 = wi::clz (wi::to_wide (@2)); }
+ (if (c1 > c2)
+  { constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
+  (icmp @0 { build_int_cst (TREE_TYPE (@0), c2 - c1); }))

 /* (CST1 << A) == CST2 -> A == ctz (CST2) - ctz (CST1)
(CST1 << A) != CST2 -> A != ctz (CST2) - ctz (CST1)
Unfortunately, while that extended second simplification seems to work fine,
have been using:
int
f1 (int a)
{
  return (1 << a) & 1;
}

int
f2 (int a)
{
  return (2 << a) & 1;
}

int
f3 (int a)
{
  return ((1 << a) & 1) != 0;
}

int
f4 (int a)
{
  return ((2 << a) & 1) == 0;
}

int
f5 (int a)
{
  return ((2 << a) & 16) != 0;
}

int
f6 (int a)
{
  return ((16 << a) & 32) == 0;
}

int
f7 (int a)
{
  return (1 >> a) & 1;
}

int
f8 (int a)
{
  return (2 >> a) & 1;
}

int
f9 (int a)
{
  return ((1 >> a) & 1) == 0;
}

int
f10 (int a)
{
  return ((2 >> a) & 1) != 0;
}

int
f11 (int a)
{
  return ((1 >> a) & 2) != 0;
}

int
f12 (int a)
{
  return ((32 >> a) & 16) == 0;
}
as testcase, the first simplification doesn't show up in *-match.c at all.  Any
ideas why?

[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0

2020-08-30 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96669

Andrew Pinski  changed:

   What|Removed |Added

   Severity|normal  |enhancement

[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0

2020-08-25 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96669

Richard Biener  changed:

   What|Removed |Added

   Keywords||easyhack
 Status|UNCONFIRMED |NEW
   Last reconfirmed||2020-08-25
 Ever confirmed|0   |1

--- Comment #2 from Richard Biener  ---
Confirmed.

[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0

2020-08-18 Thread gabravier at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96669

--- Comment #1 from Gabriel Ravier  ---
PS: This can also be done when the shift is a right shift instead of a left
shift (i.e. `1 >> x` is used instead of `1 << x`)