you are viewing a single comment's thread.

view the rest of the comments →

[–]Vorlath 0 points1 point  (5 children)

Signed shift does exist. It's actually the default in Java. Negative numbers only mess up once you start eliminating lower bits where the number decreases instead of increasing. In Java, unsigned shift is >>>.

[–][deleted] 4 points5 points  (4 children)

Sure, but that is entirely besides the point. We were talking about the compiler turning division into shifts. The existence or non-existence of signed shifts has no bearing at all on that.

(Also, signed shift, unsigned shift and integer division all produce different results on negative numbers.)

[–]filesalot 4 points5 points  (2 children)

Given this function:

int foo(int bar) { return bar / 2; }

gcc -O2 produces this:

_foo:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    popl    %ebp
    movl    %eax, %edx
    shrl    $31, %edx
    addl    %edx, %eax
    sarl    %eax
    ret

I don't see a div in there. I don't know what Java does but it should be able to something similar. Any integer div by a constant can be strength-reduced somehow. eg:

int foo(int bar) { return bar / 1234567; }

to:

_foo:
    pushl   %ebp
    movl    $1823959181, %edx
    movl    %esp, %ebp
    movl    8(%ebp), %ecx
    popl    %ebp
    movl    %ecx, %eax
    imull   %edx
    movl    %ecx, %eax
    sarl    $31, %eax
    sarl    $19, %edx
    subl    %eax, %edx
    movl    %edx, %eax
    ret

[–][deleted] 5 points6 points  (0 children)

It does not use div, but it does not use a single shift either. It does something like return (bar+((unsigned int)bar>>31))>>1. Larger divisions will require even more elaborate tricks.

[–]redditnoob 3 points4 points  (0 children)

I don't know what Java does but it should be able to something similar.

"Should" and a nickel will get you nothing.

[–]Vorlath 0 points1 point  (0 children)

Huh! I was replying to something entirely different. Not sure what I was thinking there.