Fumerian Gaming
Fumerian Gaming

Reputation: 83

Is it faster to use goto to skip if statement

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

Answers (2)

Uriel
Uriel

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

ad absurdum
ad absurdum

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

Related Questions