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

            Bug ID: 125708
           Summary: Missed optimization: division by (2 - bool) emits
                    idivl instead of shift/select
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: liuhongt at gcc dot gnu.org
  Target Milestone: ---

GCC fails to use value-range information for an integer division whose divisor
is 2 - bool. Since a bool is constrained to {0, 1}, the divisor 2 - b has range
[1, 2], so the division is equivalent to b ? a : a/2. GCC currently emits a
full signed idivl (~20+ cycle latency) instead of lowering it to a cheap shift
+ select (or branch).


Reduced test case

#include <stdbool.h>

int foo (int a, bool b)
{
    return a / (2 - b);
}

int foo1 (int a, bool b)
{
    return b ? a : a / 2;
}

foo and foo1 are semantically identical:

b == 1 -> a / 1 -> a
b == 0 -> a / 2



foo(int, bool):
        movl    %edi, %eax
        movzbl  %sil, %esi
        movl    $2, %ecx
        subl    %esi, %ecx
        cltd
        idivl   %ecx
        ret


foo1(int, bool):
        movl    %edi, %eax
        shrl    $31, %eax
        addl    %edi, %eax
        sarl    %eax
        testb   %sil, %sil
        cmovne  %edi, %eax
        ret

Reply via email to