https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127681
Bug ID: 127681
Summary: Missed optimization: unsigned casts prevent folding a
Boolean shift comparison
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: mikaseianatsu at proton dot me
Target Milestone: ---
GCC fails to simplify a Boolean shift comparison when both sides are converted
to unsigned. The same expression without the unsigned conversions is folded to
a constant.
Testcase
_Bool
f (_Bool x)
{
return (unsigned) (1 << (int) x) > (unsigned) x;
}
Reproduces on GCC 17 trunk at -O1, -O2, and -O3.
$GCC_BUILD/gcc/xgcc -B$GCC_BUILD/gcc \
-O2 -Wall -Wextra -S \
-fdump-tree-optimized=src.optimized src.c -o src.s
Actual result
The optimized GIMPLE retains the shift and unsigned comparison:
_1 = (int) x;
_2 = 1 << _1;
_3 = (unsigned int) _2;
_4 = (unsigned int) x;
return _3 > _4;
On x86-64, GCC emits six instructions plus ret, including a variable shift,
comparison, and setb.
Expected result
The parameter has exactly two possible values. For x == 0, the comparison is 1
> 0; for x == 1, it is 2 > 1. Both cases are true, and every shift is
well-defined. The function is equivalent to return 1.
Removing the two unsigned casts from the original testcase makes the compiler
fold the expression to return 1.
The <= form is the complementary instance and should be grouped with this
issue.
Relevant optimization
This appears related to the (y << x) {<,<=,>,>=} x simplification in match.pd.
The optimization was originally introduced by commit
c4ca512358be7cb1c8523f148fa84a57cbbf0060, together with the regression tests in
gcc/testsuite/gcc.dg/match-shift-cmp-1.c. The relational forms were later
reworked in PR 122733 and re-added using range information.
The corresponding form without the unsigned conversions is folded to a
constant, while introducing these conversions prevents the simplification in
this Boolean case.
Compiler
gcc version 17.0.0 20260827
Target: x86_64-pc-linux-gnu
GCC source: d38b7b34f4dc69f896e1fbd984b859365f3dd282