https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127239

            Bug ID: 127239
           Summary: Missed optimization: same-width unsigned casts prevent
                    folding `X % Y < Y`
           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 remainder comparison when two known-nonnegative values
are converted from int to unsigned before the comparison. In the testcase
below, every defined execution satisfies

  0 <= aa % bb < bb

so the function can be folded to return 1.



Testcase:

int
f (unsigned short a, unsigned short b)
{
  int aa = a;
  int bb = b;
  int c = aa % bb;
  return (unsigned) c < (unsigned) bb;
}



The issue reproduces with GCC 17 trunk at -O1, -O2, and -O3.

For example:

  gcc -O2 -Wall -Wextra -S -fdump-tree-optimized test.c



Actual result:

GCC keeps the remainder and comparison:

  aa_5 = (int) a_4(D);
  bb_7 = (int) b_6(D);
  c_8 = aa_5 % bb_7;
  c.0_1 = (unsigned int) c_8;
  bb.1_2 = (unsigned int) b_6(D);
  _3 = c.0_1 < bb.1_2;
  _9 = (int) _3;
  return _9;

On x86-64 this produces:

  movzwl  %di, %eax
  movzwl  %si, %esi
  cltd
  idivl   %esi
  xorl    %eax, %eax
  cmpl    %esi, %edx
  setb    %al
  ret



Expected result:

For every defined execution, bb != 0 and both operands are nonnegative.
Therefore,

  0 <= aa % bb < bb

Converting them to unsigned does not change their values or ordering, so the
expression can be folded to:

  return 1;

On x86-64, this would eliminate the integer division and reduce to:

  movl    $1, %eax
  ret

GCC already has a match.pd optimization for the direct nonnegative X % Y < Y
form, but the intervening same-width signed-to-unsigned conversions prevent
that fold from matching here.



Compiler:

  Target: x86_64-pc-linux-gnu
  Configure options: --enable-languages=c,c++ --disable-bootstrap
                     --disable-multilib --enable-checking=release
  gcc version 17.0.0 20260827 (experimental) (GCC)
  GCC source: g:d38b7b3
  • [Bug tree-optimization/127239]... mikaseianatsu at proton dot me via Gcc-bugs

Reply via email to