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

            Bug ID: 118129
           Summary: Missed optimization for division with constant
                    comparison x / y CMP C0
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: antoshkka at gmail dot com
  Target Milestone: ---

Consider the example:

bool test0(unsigned x, unsigned y) {
    if (y == 0) __builtin_unreachable();
    return x / y < 3;
}

The sample produces an assembly with an expensive `div` instruction:

test0(unsigned int, unsigned int):
  mov eax, edi
  xor edx, edx
  div esi
  cmp eax, 2
  setbe al
  ret

However, knowing that `y` is greater than 0 both sides of the equation could be
multiplied by `y` and divided by `3`, leading to an equivalent code:

bool test01(unsigned x, unsigned y) {
    if (y == 0) __builtin_unreachable();
    return x / 3 < y;
}

The assembly becomes better:

test01(unsigned int, unsigned int):
  mov eax, 2863311531
  mov edi, edi
  imul rdi, rax
  shr rdi, 33
  cmp edi, esi
  setb al
  ret

Moreover, knowing that `y <= std::numeric_limits<unsigned>::max() / 3` the
function could be optimized even further to an equivalent of

bool test02(unsigned x, unsigned y) {
    return x < y * 3;
}

That produces a very short and fast assembly:

test02(unsigned int, unsigned int):
  lea eax, [rsi+rsi*2]
  cmp edi, eax
  setb al
  ret

Godbolt playground: https://godbolt.org/z/d7qereKsb

Reply via email to