Bug 98956 - Failure to optimize out boolean left shift
Summary: Failure to optimize out boolean left shift
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 11.0
: P3 enhancement
Target Milestone: 13.0
Assignee: Andrew Pinski
URL:
Keywords: missed-optimization
Depends on: 64992
Blocks:
  Show dependency treegraph
 
Reported: 2021-02-03 16:03 UTC by Gabriel Ravier
Modified: 2023-09-21 10:21 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-02-04 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Gabriel Ravier 2021-02-03 16:03:25 UTC
bool f(bool c)
{
    return c << 1;
}

This can be optimized to `return c;`. This transformation is done by LLVM, but not by GCC.
Comment 1 Richard Biener 2021-02-04 07:45:43 UTC
Can be generalized to more arithmetic ops.
Comment 2 Andrew Pinski 2021-07-16 23:06:22 UTC
(for cmp (eq ne)
 (simplify
  (cmp (lshift truth_value@0 INTEGER_CST@1) zero_p@2)
  (cmp @0 @2)))

Something like the above, might apply to rotate too.
Comment 3 Navid Rahimi 2021-11-17 04:59:41 UTC
I am sending a patch for this:

/* cmp : ==, != */
/* ((B0 << CST) cmp 0) -> B0 cmp 0 */
(for cmp (eq ne)
 (simplify
  (cmp (lshift (convert @0) INTEGER_CST@1) integer_zerop@2)
  (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE) (cmp @0 @2))))


This does not apply to other arithmetic operations (at least it is not verifiable). and for cases that it does apply to other arithmetic operators, GCC already produces optimized code. You can play with the codegen I link below:

Codegen:
https://compiler-explorer.com/z/nj4PTrecW

Proof:
https://alive2.llvm.org/ce/z/jyJAoS
Comment 4 Andrew Pinski 2021-11-30 21:55:58 UTC
I just realized this is the same as PR 64992 which I almost have a patch. You don't even need bools.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64992#c8
Comment 5 GCC Commits 2022-08-15 16:41:00 UTC
The master branch has been updated by Roger Sayle <sayle@gcc.gnu.org>:

https://gcc.gnu.org/g:418b71c0d535bf91df78bad2e198c57934682eaa

commit r13-2048-g418b71c0d535bf91df78bad2e198c57934682eaa
Author: Roger Sayle <roger@nextmovesoftware.com>
Date:   Mon Aug 15 17:39:47 2022 +0100

    PR tree-optimization/64992: (B << 2) != 0 is B when B is Boolean.
    
    This patch resolves both PR tree-optimization/64992 and PR
    tree-optimization/98956 which are missed optimization enhancement
    request, for which Andrew Pinski already has a proposed solution
    (related to a fix for PR tree-optimization/98954).  Yesterday,
    I proposed an alternate improved patch for PR98954, which although
    superior in most respects, alas didn't address this case [which
    doesn't include a BIT_AND_EXPR], hence this follow-up fix.
    
    For many functions, F(B), of a (zero-one) Boolean value B, the
    expression F(B) != 0 can often be simplified to just B.  Hence
    "(B * 5) != 0" is B, "-B != 0" is B, "bswap(B) != 0" is B,
    "(B >>r 3) != 0" is B.  These are all currently optimized by GCC,
    with the strange exception of left shifts by a constant (possibly
    due to the undefined/implementation defined behaviour when the
    shift constant is larger than the first operand's precision).
    This patch adds support for this particular case, when the shift
    constant is valid.
    
    2022-08-15  Roger Sayle  <roger@nextmovesoftware.com>
    
    gcc/ChangeLog
            PR tree-optimization/64992
            PR tree-optimization/98956
            * match.pd (ne (lshift @0 @1) 0): Simplify (X << C) != 0 to X
            when X is zero_one_valued_p and the shift constant C is valid.
            (eq (lshift @0 @1) 0): Likewise, simplify (X << C) == 0 to !X
            when X is zero_one_valued_p and the shift constant C is valid.
    
    gcc/testsuite/ChangeLog
            PR tree-optimization/64992
            * gcc.dg/pr64992.c: New test case.
Comment 6 Roger Sayle 2022-09-10 21:11:36 UTC
This should now be fixed on mainline.