Re: Recent change in tcp_output.c is surely wrong

From: Richard B. Johnson (root@chaos.analogic.com)
Date: Tue Jan 18 2000 - 10:27:48 EST


On Tue, 18 Jan 2000, Pavel Machek wrote:

> Hi!
>
> > > If the intention is to clear bit 31, `&= 0x7fffffff' is the thing which
> > > works and is probably more efficient.
> >
> > Not true on all RISC machines I am familiar with. It's 2 instructions
> > either way. On x86 you'll end up using a larger opcode and one of
> > x86's most notable performance advantages is it's code density.
>
> Leave that to the gcc. If it is faster to clear high bit with two
> shifts, _gcc_ is the one to decide that. And yes gcc is clever enough
> to se things like that. [replacing and 0x7fffffff with shl 1 shr 1
> is really no problem].
>

Well it's a problem if it doesn't work.

Script started on Tue Jan 18 10:18:50 2000
# cat xxx.c

int foo0 (int bar)
{
    return bar & 0x7fffffff;
}

int foo1 (int bar)
{
    return ((bar << 1) >> 1);
}

int main()
{
   int xxx = 0xffffffff;
   printf("%d\n", foo0(xxx));
   printf("%d\n", foo1(xxx));
   return 0;
}

# gcc -O2 -o xxx xxx.c
# xxx
2147483647
-1
# exit
exit

Script done on Tue Jan 18 10:19:19 2000

If you want to AND off a bit, AND off a bit. Don't try to fool the
tools. Tools are often broken if you try "tricks".

The intermediate code show all:

        .file "xxx.c"
        .version "01.01"
gcc2_compiled.:
.text
        .align 4
.globl foo0
        .type foo0,@function
foo0:
        pushl %ebp
        movl %esp,%ebp
        movl 8(%ebp),%eax
        andl $2147483647,%eax ! Just AND if off, fine.
        leave
        ret
.Lfe1:
        .size foo0,.Lfe1-foo0
        .align 4
.globl foo1
        .type foo1,@function
foo1:
        pushl %ebp
        movl %esp,%ebp
        movl 8(%ebp),%edx
        leal 0(,%edx,2),%eax ! Good grief
        sarl $1,%eax ! Arithmetic shift extends sign
        leave
        ret
.Lfe2:
        .size foo1,.Lfe2-foo1
.section .rodata
.LC0:
        .string "%d\n"
.text
        .align 4
.globl main
        .type main,@function
main:
        pushl %ebp
        movl %esp,%ebp
        pushl $-1
        call foo0
        pushl %eax
        pushl $.LC0
        call printf
        pushl $-1
        call foo1
        pushl %eax
        pushl $.LC0
        call printf
        xorl %eax,%eax
        leave
        ret
.Lfe3:
        .size main,.Lfe3-main
        .ident "GCC: (GNU) 2.7.2.3"

So, the double-shift is truly broken. Just AND it and be done with it.

Cheers,
Dick Johnson

Penguin : Linux version 2.3.39 on an i686 machine (800.63 BogoMips).

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Jan 23 2000 - 21:00:18 EST