[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-kernel
Subject:    Re: goto's ???
From:       "Richard B. Johnson" <root () chaos ! analogic ! com>
Date:       1999-05-25 12:53:12
[Download RAW message or body]

On Sun, 23 May 1999, Mofeed Shahin wrote:

> 
> G'day all,
> 
> I was just have a bit of a look at the fs code, and noticed something a
> little odd. There are alot of 'goto' statements in the code. From what I
> can see they are not needed.
> 
> eg :
> line 632 of /usr/src/linux/fs/open.c :
> 
> struct file *filp_open(const char * filename, int flags, int mode)
> {
>         struct inode * inode;
>         struct dentry * dentry;
>         struct file * f;
>         int flag,error;
>  
>         error = -ENFILE;
>         f = get_empty_filp();
>         if (!f)
>                 goto out;
> 	....
> 	<SNIP>
> 
> out:
>         return ERR_PTR(error);
> }
> 
> this seems like an extra jmp statement to me (unless the compiler
> optimises it)
> 
> ie why not just do this :
> struct file *filp_open(const char * filename, int flags, int mode)
> {
>         struct inode * inode;
>         struct dentry * dentry;
>         struct file * f;
>         int flag,error;
> 
>         error = -ENFILE;
>         f = get_empty_filp();
>         if (!f)
>                 return ERR_PTR(error);
> 	....
> 	<SNIP>
> }
> 
> Cheers Mof.
> 

Compile questionable code with the -S option, with output to a file.
Check the assembly. Usually, the gotos are important to maintain
straight-through code for the normal case. If you put a return in
the middle of the code, it doesn't return. It jumps to somewhere
where the saved registers are restored, the stack leveled, and then
a return. In other words, there is only one exit path anyway. So
the designer designed in the exit path so the compiler is less likely
to muck with the straight through code.

Given:

int foo(int bar)
{
    if (bar == 1)
        goto end;
    if (bar == 2)
        goto end;
    printf("%d\n", bar);
   end:;
   return 0;
}

You get:

foo:
	pushl %ebp
	movl %esp,%ebp
	cmpl $1,8(%ebp)		; if (bar == 1)
	jne .L2			; Not a 1, try next
	jmp .L3			; This is the goto
	.align 4
.L2:
	cmpl $2,8(%ebp)		; if (bar == 2)
	jne .L4                 ; Not a 2
	jmp .L3			; This is the goto
	.align 4
.L4:
	movl 8(%ebp),%eax	; This is where we print it.
	pushl %eax
	pushl $.LC0
	call printf
	addl $8,%esp
.L3:				; Common exit
	xorl %eax,%eax
	jmp .L1
	.align 4
.L1:
	movl %ebp,%esp
	popl %ebp
	ret

Now, you may say; "Nobody writes code like that!". True, it's a demo,
one would probably write such trivial code as:

int foo(int bar)
{
    if ((bar != 1) && (bar != 2))
        printf("%d\n", bar);
   return 0;
}

How, guess what this produces?!!

foo:
	pushl %ebp
	movl %esp,%ebp
	cmpl $1,8(%ebp)		 ; (foo != 1)
	je .L2			 ; The goto
	cmpl $2,8(%ebp)		 ; (foo != 2)
	je .L2                   ; Another goto
	movl 8(%ebp),%eax        ; Now we print it.
	pushl %eax
	pushl $.LC0
	call printf
	addl $8,%esp
.L2:
	xorl %eax,%eax
	jmp .L1
	.align 4
.L1:
	movl %ebp,%esp
	popl %ebp
	ret
.Lfe1:


By checking what the compiler produces, you can see if it might be
best to put a goto in your code even though it might bring up shreeks
of horror from some.

You will find that just ordering something a bit differently, while
maintaining the same logic, may produce a better straight-through path.
For instance everybody loves 'switches'. They make coding clear and
straight forward, however, unless the 'case' is sequential, better
code may be obtained by using 'if() else if()'.

Cheers,
Dick Johnson
                 ***** FILE SYSTEM WAS MODIFIED *****
Penguin : Linux version 2.2.6 on an i686 machine (400.59 BogoMips).
Warning : It's hard to remain at the trailing edge of technology.


-
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/

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic