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

Reply via email to