Reputation: 83
Is it faster to skip if
statement if the statement is true? For example:
if (a = true) {
blah blah...
goto end;
} else {
blah blah..
}
label: end;
Would this code be faster than:
if (a = true) {
blah blah...
} else {
blah blah..
}
Upvotes: 2
Views: 295
Reputation: 16184
When your code compiles, it would probably (i.e. on most decent compilers) translate to something similar to the following pseudo code:
if (a != true)
jump else
foo() * will not execute if a is false
* because of the `jump else`
jump end
else:
bar() * will not execute if a is true
* because of the `jump end`
end:
where else
and end
are labels (try to run it with true and false a
on paper).
Basically, both snippets will translate to the same compiled version, and your goto
will have no effect on the result because it is included in the branching. At most, it will make your compiler to sweat for another 2 milliseconds to detect and ignore it.
When considering performance, a manual jump that is semi-implicated has not much significance. Breaking loops, non-redeclaration and other programmer-end optimization activities contributes much more.
As a note, this branching is how assembly conditions are built, as one stores the logical operation in a register and compare it to check whether to jump or not. A more precise pseudo code would be
cmp a, true /or/ xor a, a ; 0 if true, 1 if false
jne else /or/ jnz else ; jump if not equal / zero
foo()
jmp end ; jump to
else:
bar()
end:
Upvotes: 5
Reputation: 21316
I would be surprised if any decent compiler didn't emit the same assembler for these two possibilities. Here is a simple C program that compiles and runs:
#include <stdio.h>
int main(void)
{
int c = getchar();
if (c == 'y') {
++c;
goto end;
} else {
--c;
}
end:
putchar(c);
putchar('\n');
return 0;
}
Compiled with gcc -S
, no optimization flags, here is the output:
.file "goto_skip_41709548.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
call getchar
movl %eax, -4(%rbp)
cmpl $121, -4(%rbp)
jne .L2
addl $1, -4(%rbp)
jmp .L3
.L2:
subl $1, -4(%rbp)
.L3:
movl -4(%rbp), %eax
movl %eax, %edi
call putchar
movl $10, %edi
call putchar
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4"
.section .note.GNU-stack,"",@progbits
The compiler gave the exact same output for the same code with the goto
removed. Verified with a diff
:
λ> diff w_goto.s wo_goto.s
1c1
< .file "goto_skip_41709548.c"
---
> .file "no_goto_skip_41709548.c"
Upvotes: 6