2013-03-30 6 views
5

Mam następujący prosty program, którego używam do odświeżenia mojej pamięci GDB (której nie dotykałem od wielu lat).Zmiany GCC mniejsze niż lub mniejsze niż

#include <stdio.h> 

int main() 
{ 
    int i; 

    for (i = 0; i < 10; i++) 
    { 
    printf("Hello World\n"); 
    } 

    return 0; 
} 

Kompiluję to z gcc -g for-test.c -o for-test. Na podstawie strony podręcznika nie oczekuję żadnych optymalizacji, ponieważ nie określiłem żadnego.

Kiedy załadować to do GDB i uruchomić disassemble main porównanie i < 10 generuje następujące:

cmp DWORD PTR [rbp-0x4],0x9 
jle 0x4004fe <main+10> 

Wydaje skutecznie zmieniły porównanie i < 10 do i <= 9. Biorąc pod uwagę, że są to porównania całkowite, nie powinno być różnicy, ale zastanawiałem się, czy istnieje jakiś powód, dla którego GCC wyprowadza to zgromadzenie, zamiast porównywania z 10 i skakania, jeśli jest mniejsze niż (JL)?

Edytuj: To jest na komputerze z procesorem 64-bitowym, z systemem Ubuntu z GCC 4.6.3 i GDB 7.4-2012.04.

+0

Obie metody są w 100% identyczne (to samo zachowanie, ten sam rozmiar kodu, ta sama szybkość na każdym procesorze). Nie wiem o wewnętrznych elementach GCC, więc nie mogę zgadnąć, dlaczego tak się stało. Bardziej interesujące jest to, że nie wydaje mi się, że włączyłeś optymalizację (w przeciwnym razie użyłbym rejestru zamiast zmiennej lokalnej dla 'i'). – Brendan

+2

Być może w ten sposób normalizuje porównania .. – harold

+0

Jeśli istniała jakakolwiek szansa, że ​​te dwie wartości nie będą takie same, nie zrobiłoby to tego bez optymalizacji. na przykład 'if (a + 1> 1)' zostanie uproszczone do 'if (a> 0)' z optymalizacją, ale jest potencjalnie niebezpieczne, więc nie zostanie wykonane inaczej. – teppic

Odpowiedz

5

Nie powinno być różnicy w prędkości wykonania. Myślę, że gcc zwykle emituje jle dla takich porównań i robi to dla spójności wygenerowanego zespołu.

+0

Wydaje się, że tak jest. Co ciekawe, spróbowałem tego samego kodu w klangu, a wynik był odwrotny - zamieniłby on na "kontynuującą się pętlę, jeśli jest mniejsza niż" na "przerwaną pętlę, jeśli jest większa lub równa". Nie jestem pewien, dlaczego dwa kompilatory wybrały różne trasy, lub jeśli jest z natury bardziej wydajny niż inne. – pwaring

0

To nie jest skuteczna optymalizacja, tylko inny sposób na to samo. Kompilowanie z opcją -O generuje o wiele bardziej złożone optymalizacje.

2

Kompilatory mogą wykonywać optymalizacje, o ile obserwowalne zachowanie jest takie samo. Jest to znane jako As-If rule. Ponieważ obserwowalne zachowanie dla obu przypadków jest takie samo, kompilator może wygenerować kod zespołu w jednym z dwóch. Jest to prawdą, nawet jeśli nie masz włączonych żadnych optymalizacji.

+0

+1. Może nawet rozwinąć pętlę (faktycznie robi to za pomocą '-O3'). A może nawet wydrukować pojedynczy ciąg, który ma 10 kopii oryginału. –

+0

To nie jest tak naprawdę optymalizacja, chyba że porównanie z 9 i skakanie, jeśli jest mniejsze lub równe, jest szybsze (lub większa pamięć, lub inna miara) niż porównanie z 10 i skakanie, jeśli jest mniejsze niż. – pwaring