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

            Bug ID: 126078
           Summary: guaranteed power of two value is not recognized,
                    leading to div instead and operation
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gcc at breakpoint dot cc
  Target Milestone: ---

The following code:

 #define EINVAL          22
 #define FLAGS_NUMA              0x0080
 #define FLAGS_SIZE_MASK         0x0003

 static inline unsigned int futex_size(unsigned int flags)
 {
         return 1 << (flags & FLAGS_SIZE_MASK);
 }

 int get_futex_key(unsigned int *uaddr, unsigned flags)
 {
         unsigned long address = (unsigned long)uaddr;
         int size;

         size = futex_size(flags);
         if (flags & FLAGS_NUMA)
                 size *= 2;

         if ((address % size) != 0)
                 return -EINVAL;
         return 0;
 }

guarantees that size is always power of two. The check
"(address % size) != 0" is translated into a div operation at -O2:

        movl    %esi, %ecx
        movq    %rdi, %rax
        movl    $2, %edx
        movl    %esi, %edi
        andl    $3, %ecx
        movl    $1, %esi
        sall    %cl, %esi
        sall    %cl, %edx
        andl    $128, %edi
        cmove   %esi, %edx
        movslq  %edx, %rcx
        xorl    %edx, %edx
        divq    %rcx
        testq   %rdx, %rdx
        jne     .L5
        xorl    %eax, %eax
        ret

but this could be avoided if it knew that it is the same as "(address &
(size-1)) != 0" due to "1 << val" in futex_size. clang figures it out:

        movl    %esi, %ecx
        xorl    %eax, %eax
        testb   %cl, %cl
        sets    %al
        incl    %eax
        andb    $3, %cl

        shll    %cl, %eax
        decq    %rax
        xorl    %ecx, %ecx
        testq   %rdi, %rax
        movl    $-22, %eax
        cmovel  %ecx, %eax
        retq

Could we have the same for gcc, please?

Reply via email to