Does gcc (or any other compiler) (n% 2 == 1) change for (n & 1 == 1)?

To check if a number is odd or even, As I understand it, a test using

(n%2==1)

Same as

(n&1==1)

I assume the first test is faster (please correct me if I am wrong), but does the compiler recognize this and “fix” it? Does it make any difference in performance?

+4
source share
2 answers
void main()
{
    int n = 5;
    int i = n & 1;
}
    call    __main
    movl    $5, -4(%rbp)
    movl    -4(%rbp), %eax
    andl    $1, %eax
    movl    %eax, -8(%rbp)
    addq    $48, %rsp
    popq    %rbp
    ret

void main()
{
    int n = 5;
    int i = n % 2;
}
    call    __main
    movl    $5, -4(%rbp)
    movl    -4(%rbp), %eax
    cltd
    shrl    $31, %edx
    addl    %edx, %eax
    andl    $1, %eax
    subl    %edx, %eax
    movl    %eax, -8(%rbp)
    addq    $48, %rsp
    popq    %rbp
    ret

Tried gcc.exe (GCC) 4.9.2 using -S -O0
this way, that means a & 1bit better for parity.

0
source

Actually
(n%2==1) this is not the same as (n&1==1) if the type nis equal signed int, therefore the compiler code (gcc 5.1, -Ofast, 64bit):

int f(int n)
{
    return (n % 2) == 1;
0:   89 f8                   mov    %edi,%eax
2:   c1 e8 1f                shr    $0x1f,%eax
5:   01 c7                   add    %eax,%edi
7:   83 e7 01                and    $0x1,%edi
a:   29 c7                   sub    %eax,%edi
c:   31 c0                   xor    %eax,%eax
e:   83 ff 01                cmp    $0x1,%edi
11:   0f 94 c0                sete   %al
}
14:   c3                      retq

, (-):

 uint64_t edi = eax;
 eax >>= 0x1f;
 edi += eax;
 edi &= 1;
 edi -= eax;

n "unsigned int", (gcc 5.1, -Ofast):

0000000000000000 <f>:
unsigned char f(unsigned int n)
{
    return (n % 2) == 1;
0:   83 e7 01                and    $0x1,%edi
}
3:   89 f8                   mov    %edi,%eax
5:   c3                      retq   
-1

All Articles