[Bug tree-optimization/96669] Failure to optimize shift by variable+and by 1 to test for 0
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
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
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
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
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
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
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`)