2013-03-13 17 views
10

Le persone hanno affermato che Delphi produce codice ottimizzato per le operazioni integer. Provo il seguente esempio in Delphi 2007 e vedo il suo codice assembly prodotto dal compilatore.Perché l'ottimizzatore non elimina High in loop?

program p1000; 
{$APPTYPE CONSOLE} 

procedure test; 
var 
    arr: array of integer; 
    i: integer; 

begin 
    SetLength(arr, 100); 
    for i := 0 to High(arr) do 
    begin 
    if (i = High(arr)) then 
    begin 
     arr[i] := -9; 
    end; 
    end; 
end; 

begin 
    test; 
    readln; 
end. 

Quando si costruisce configurazione è impostato a DEBUG, è possibile impostare un punto di interruzione e utilizzare ShortKey Ctrl + Alt + D per vedere il codice assembly, come questo:

Project3.dpr.11: for i := 0 to High(arr) do 
004045A1 8B45FC   mov eax,[ebp-$04] 
004045A4 E8F7FAFFFF  call @DynArrayHigh 
004045A9 8BF0    mov esi,eax 
004045AB 85F6    test esi,esi 
004045AD 7C1D    jl $004045cc 
004045AF 46    inc esi 
004045B0 33DB    xor ebx,ebx 
Project3.dpr.13: if (i = High(arr)) then 
004045B2 8B45FC   mov eax,[ebp-$04] 
004045B5 E8E6FAFFFF  **call @DynArrayHigh** 
004045BA 3BD8    cmp ebx,eax 
004045BC 750A    jnz $004045c8 
Project3.dpr.15: arr[i] := -9; 
004045BE 8B45FC   mov eax,[ebp-$04] 
004045C1 C70498F7FFFFFF mov [eax+ebx*4],$fffffff7 
Project3.dpr.17: end; 
004045C8 43    inc ebx 
Project3.dpr.11: for i := 0 to High(arr) do 
004045C9 4E    dec esi 
004045CA 75E6    jnz $004045b2 

Per quanto posso capire, chiama la funzione High() ancora e ancora nel ciclo:

Project3.dpr.13: if (i = High(arr)) then 
    004045B2 8B45FC   mov eax,[ebp-$04] 
    004045B5 E8E6FAFFFF  **call @DynArrayHigh** 
    004045BA 3BD8    cmp ebx,eax 

Quando la configurazione dell'edificio è impostata su RILASCIO, il punto di interruzione non è disponibile, quindi preme F8/F7 per entrare nel ciclo.

00404589 6A64    push $64 
0040458B 8D45FC   lea eax,[ebp-$04] 
0040458E B901000000  mov ecx,$00000001 
00404593 8B1554454000  mov edx,[$00404554] 
00404599 E8B6FCFFFF  call @DynArraySetLength 
0040459E 83C404   add esp,$04 
004045A1 8B45FC   mov eax,[ebp-$04] 
004045A4 E8F7FAFFFF  call @DynArrayHigh 
004045A9 8BF0    mov esi,eax 
004045AB 85F6    test esi,esi 
004045AD 7C1D    jl $004045cc 
004045AF 46    inc esi 
004045B0 33DB    xor ebx,ebx 
004045B2 8B45FC   mov eax,[ebp-$04] 
004045B5 E8E6FAFFFF  call @DynArrayHigh 
004045BA 3BD8    cmp ebx,eax 
004045BC 750A    jnz $004045c8 
004045BE 8B45FC   mov eax,[ebp-$04] 
004045C1 C70498F7FFFFFF mov [eax+ebx*4],$fffffff7 
004045C8 43    inc ebx 
004045C9 4E    dec esi 
004045CA 75E6    jnz $004045b2 
004045CC 33C0    xor eax,eax 
004045BC 750A    jnz $004045c8 

Anche in questo caso, lo stesso call @DynArrayHigh viene prodotto ...
Quindi la mia domanda è, perché il compilatore non può ottimizzare questo? è sufficiente salvare il valore High() in un registro/variabile locale poiché la dimensione dell'array non viene modificata.

+2

Non è cambiato in * questa * discussione, ma il compilatore non ha modo di sapere se è cambiato da un altro thread - Immagino che ci sia così tanto che può controllare prima di ottimizzare in modo sicuro. –

+0

ma 'arr' è un array locale, quindi gli altri thread non possono eventualmente cambiarlo. –

+2

@roger, quella matrice è una variabile locale, quindi dovrebbe essere semplicemente riconoscibile. – TLama

risposta

9

Questa non è una risposta, ma piuttosto una (auto distruggersi) commento :)

A mio avviso, il compilatore non deve tentare di ottimizzare questo.

Perché il compilatore deve tentare di ottimizzare una funzione (non deterministica) High rispetto ad altre? (Come Length)

La dinamica lunghezza array potrebbe essere modificato all'interno del ciclo mediante SetLenth, o con altri mezzi. la matrice potrebbe essere ri-initilzed a run-time e il vostro codice potrebbe dipendere da quello:

for i := 0 to High(arr) do 
begin 
    if (i = High(arr)) then 
    arr[i] := -9 
    else 
    if foo() then 
     arr := nil; // or SetLength(arr, 0); 

    if High(arr) = -1 then Exit; // arr is nil 
end; 

Come vi proponiamo questo dovrebbe essere ottimizzato? Il compilatore dovrebbe anche tentare di ottimizzarlo? Non vedo nulla speciale su High functionm anche se il compilatore lo traduce in @DynArrayHigh.

Se si desidera che il codice per essere ottimizzato, ottimizzarlo te .EG:

var 
    arrHigh: Integer; 

    arrHigh := High(arr); 
    for i := 0 to arrHigh do 
    if i = arrHigh then... 
+0

grazie .. sono d'accordo. mi chiedo solo che il compilatore sia abbastanza intelligente da capirlo. :) –