Nasıl GCC kullanılmayan bir değişken bir döngü içinde artan optimize? | Netgez.com
SORU
12 Ocak 2012, PERÅžEMBE


Nasıl GCC kullanılmayan bir değişken bir döngü içinde artan optimize?

Bu basit bir C programı yazdım:

int main() {
    int i;
    int count = 0;
    for(i = 0; i < 2000000000; i  ){
        count = count   1;
    }
}

Gcc derleyici bu döngü (açık Ekle . optimize nasıl görmek istedim ^em>12000000000 kez "ekleyin2000000000bir kez"). Yani:

gcc test.cve sonra a.out time verir:

real 0m7.717s  
user 0m7.710s  
sys 0m0.000s  

$ gcc -O2 test.cve sonra time on.` verir:

real 0m0.003s  
user 0m0.000s  
sys 0m0.000s  

Sonra gcc -S ile de tamamladım. İlk oldukça açık görünüyor:

    .file "test.c"  
    .text  
.globl main
    .type   main, @function  
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    $0, -8(%rbp)
    movl    $0, -4(%rbp)
    jmp .L2
.L3:
    addl    $1, -8(%rbp)
    addl    $1, -4(%rbp)
.L2:
    cmpl    $1999999999, -4(%rbp)
    jle .L3
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
    .section    .note.GNU-stack,"",@progbits

L3, L2 i < 2000000000 L3 1999999999 17 * ve döngüler karşılaştırın ekler.

Åžimdi optimize edilmiÅŸ

    .file "test.c"  
    .text
    .p2align 4,,15
.globl main
    .type main, @function
main:
.LFB0:
    .cfi_startproc
    rep
    ret
    .cfi_endproc
.LFE0:
    .size main, .-main
    .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
    .section .note.GNU-stack,"",@progbits

Orada neler oluyor hiç anlamıyorum! Kurul çok az bilgi var, ama gibi bir şey bekliyordum

addl $2000000000, -8(%rbp)

Ben bile çalıştıgcc -c -g -Wa,-a,-ad-O2 test.cC kodu derleme ile beraber görmek için dönüştürülmüş, ama sonuç bir önceki ve daha açıktı.

Birisi kısaca açıklayabilir:

  1. -S -O2 gccçıktı.
  2. Eğer döngü (birçok meblağlar yerine bir miktar) beklediğim gibi optimize edilmiştir?

CEVAP
12 Ocak 2012, PERÅžEMBE


Derleyici o daha akıllı. :)

Aslında döngü sonucu kullanmadığınız bunu fark eder. Tüm döngü tamamen aldı!

Bu Dead Code Elimination denir.

Daha iyi bir test baskı sonucu

#include <stdio.h>
int main(void) {
    int i; int count = 0;
    for(i = 0; i < 2000000000; i  ){
        count = count   1;
    }

    //  Print result to prevent Dead Code Elimination
    printf("%d\n", count);
}

DÜZENLEME :#include olmadan bir sürümü karşılık gelir #include <stdio.h>; MSVC montaj listesi gerekli ekledim ama aynı olmalıdır.


Windows içine çizme olduğum için şu an önümde GCC yok. Ama burada MSVC printf() ile: sürüm demontaj

EDİT : yanlış montaj çıkış vardı. İşte doğru bir tane.

; 57   : int main(){

$LN8:
    sub rsp, 40                 ; 00000028H

; 58   : 
; 59   : 
; 60   :     int i; int count = 0;
; 61   :     for(i = 0; i < 2000000000; i  ){
; 62   :         count = count   1;
; 63   :     }
; 64   : 
; 65   :     //  Print result to prevent Dead Code Elimination
; 66   :     printf("%d\n",count);

    lea rcx, OFFSET FLAT:??_C@_03PMGGPEJJ@?$CFd?6?$AA@
    mov edx, 2000000000             ; 77359400H
    call    QWORD PTR __imp_printf

; 67   : 
; 68   : 
; 69   : 
; 70   :
; 71   :     return 0;

    xor eax, eax

; 72   : }

    add rsp, 40                 ; 00000028H
    ret 0

Yani Evet, Visual Studio bu optimizasyon yapar. GCC muhtemelen de öyle kabul ediyorum.

Ve evet, GCC benzer bir optimizasyon gerçekleştirir. İşte gcc -S -O2 test.c (gcc 4.5.2, Ubuntu 11.10, 86) ile aynı program için derleme bir listesi:

        .file   "test.c"
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "%d\n"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
        pushl   ëp
        movl    %esp, ëp
        andl    $-16, %esp
        subl    $16, %esp
        movl    $2000000000, 8(%esp)
        movl    $.LC0, 4(%esp)
        movl    $1, (%esp)
        call    __printf_chk
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
        .section        .note.GNU-stack,"",@progbits

Bunu PaylaÅŸ:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VÄ°DEO

Rastgele Yazarlar

  • captainpuppys2000

    captainpuppy

    20 HAZÄ°RAN 2013
  • chickenby

    chickenby

    2 HAZÄ°RAN 2008
  • Klemens Torggler

    Klemens Torg

    11 Mart 2008