Ah, but this is now equivalent instead to
if (func1()&&func2()&&func3()&&func4())
do_something();
else
complain();
But of course, you're right, in the structured way it is too difficult
to code different cleanup depending on where I failed, while in the goto
case all the dirty stuff goes out of the normal flow.
>
> Even the usual loop-counters often produce bad, bad, bad code.
>
> for(i=0; i< MAX; i++)
> do_something();
>
> You would think that, since this construct is so often used, the 'C'
> compilers would at least optimize this. Nope, guess again. Even telling
> the compiler to use 'register int i`, even if it does, the loop test
> and the increment end up being in the wrong order, forcing extra code
> to determine the terminating condition.
valid point.
>
> You see, if `i` is used only as a count, not as an index, and if the
> value of `i` is not used after the loop terminates, the compiler could
> decrement a starting value to zero instead of starting at zero and
> incrementing to some limit. In this case there would be no need to
> compare against a final value because on most/many/(all?) processors
> the flags change automatically when decrementing to zero or decrementing
> to a negative number.
>
> To get around the bad code generation, programmers who understand
> these things often code....
>
> while(i--)
> ;
>
> However, gcc will usually mess with this and end up decrementing a
> value on the stack or in the register-variable case, add extra code.
>
mm.. not with me. using egcs-1.1.1
> Like:
>
> void foo()
> {
> puts("Do not optimize this away!");
> }
> main()
> {
> register int i;
> i = 10;
> while(i--)
> foo();
> }
> main:
> pushl %ebp
> movl %esp,%ebp
> pushl %ebx
> movl $10,%ebx
> .L3:
> decl %ebx # This changes the sign flag.
> cmpl $-1,%ebx # This is NOT necessary
> jne .L5 # Should be js .L4 (terminating condition)
> jmp .L4 # Should fall through to `call foo`
> .align 4 # Should not exist
> .L5:
> call foo
> jmp .L3
> .align 4
> .L4:
> .L2:
> movl -4(%ebp),%ebx
> movl %ebp,%esp
> popl %ebp
> ret
Here's what I got:
main:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl $9,%ebx
.p2align 4,,7
.L5:
pushl $.LC0 # this was the string
call puts # even inlines foo() for you :-)
addl $4,%esp
subl $1,%ebx # mm.. ah! decl doesn't affect the flags
jnc .L5
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
I think writing code cleanly has the advantage that you don't carry around
stuff that was optimized for the 386 because gcc 2.6 or whatever had a poor
optimizer even when current compilers can do a good job.
Besides, if the code was written by someone with x86 experience, it is possible
that a different version would actually be faster on a RISC architecture like
the sparc. Leaving decisions up to the compiler might be better, and should get
less costly as compilers get better.
-- arvind
-
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/