bool f(bool c) { return c << 1; } This can be optimized to `return c;`. This transformation is done by LLVM, but not by GCC.
Can be generalized to more arithmetic ops.
(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.
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
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
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.
This should now be fixed on mainline.