GCC voegt rare temporele variabelen toe

Ik heb deze code gemaakt:

#include 

typedef unsigned int uint;
uint in[2]={1,2},out[2]={3,4};

int main() {

    in[0]=out[0]/10;
}

en gecompileerd met GCC (v4.4.5, geen optimalisaties) op Linux, de resulterende assembly is:

0000000000400474 
: 400474: 55 push rbp 400475: 48 89 e5 mov rbp,rsp 400478: 8b 05 ae 03 20 00 mov eax,DWORD PTR [rip+0x2003ae] # 0082c 40047e: 89 45 fc mov DWORD PTR [rbp-0x4],eax 400481: ba cd cc cc cc mov edx,0xcccccccd 400486: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 400489: f7 e2 mul edx 40048b: 89 d0 mov eax,edx 40048d: c1 e8 03 shr eax,0x3 400490: 89 05 8e 03 20 00 mov DWORD PTR [rip+0x20038e],eax # 600824 400496: c9 leave 400497: c3 ret 400498: 90 nop 400499: 90 nop 40049a: 90 nop 40049b: 90 nop 40049c: 90 nop 40049d: 90 nop 40049e: 90 nop 40049f: 90 nop

Nu is de vraag: wat doet deze code op regel # 5?

40047e:       89 45 fc                mov    DWORD PTR [rbp-0x4],eax

is het niet het opslaan van de waarde die het kreeg van uit [0] opnieuw op een plaats in het geheugen? Waarom? Ik heb het niet gezegd om meteen naar een locatie te lezen en te schrijven.

Nu verschijnt deze temporele variabele opnieuw op adres 400486 op regel # 7:

400486:       8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]

Het lijkt erop dat in dit voorbeeld GCC zeer inefficiënte code produceert en de cache-regel zal verlaten vanwege deze tijdelijke opslag. Bevestig alsjeblieft, misschien is er iets dat ik niet krijg.

0
Is rbp-0x4 niet de stapel? Het deed eerder mov rbp, rsp .
toegevoegd de auteur K-ballo, de bron
Nou, je zei geen optimalisatie.
toegevoegd de auteur Fred Larson, de bron
Natuurlijk produceert het inefficiënte code; je zei dat het niet moest optimaliseren.
toegevoegd de auteur Dave, de bron
Het slaat gewoon op en herstelt de waarde van % eax van de stapel. Uw arrays zijn op % ebx + 0x20038e .
toegevoegd de auteur Alexandre C., de bron

1 antwoord

GCC maakt zeer inefficiënte code bij het compileren op -O0 - wat u ziet is in feite een ruwe vertaling van de interne weergave van het programma. Deze interne weergave bevat een aantal tijdelijke variabelen en uw load/store-paar is hier een waarde die door zo'n tijdelijke heengaat. Op hogere optimalisatieniveaus zullen dit soort nutteloze ladingen/winkels meestal worden geëlimineerd; echter op -O0 is zelfs de eenvoudigste analyse uitgeschakeld.

5
toegevoegd
dankje ik heb het. Ik dacht dat de originele code gegenereerd door GCC zal doen wat hem verteld wordt, zelfs met -O0, niet het opslaan en herstellen van registerwaarden.
toegevoegd de auteur Nulik, de bron
@Neil: GCC heeft verschillende Intermediate Representations: GIMPLE, SSA, RTL, ... Natuurlijk maakt het SSA-formulier heel veel tijdelijke variabelen.
toegevoegd de auteur ninjalj, de bron
Ik veronderstel zijn IL een stapel-gebaseerde machine moet zijn; Ik voegde return argc; toe en het kopieerde argc naar de stapel voordat het werd teruggestuurd. (Ik heb ook geprobeerd in en uit te schakelen naar eenvoudige variabelen, en het kopieerde (1 << 32) * 0.8 naar de stapel.) Ter vergelijking, zelfs bij /Od de MSVC compiler genereert over het algemeen mov eax, _out xor edx, edx mov ecx, 10 div ecx mov _in , eax . (Het gebruikt mul op /O2 .)
toegevoegd de auteur Neil, de bron