2016-05-02 24 views
7

Ho scritto un file cpp illustrato di seguitoL'ottimizzatore LLVM non è in grado di gestire un caso semplice?

int main() { 
    int a, b; 
    scanf("%d", &b); 

    for (int i = 0 ; i < 1000 ; i++) { 
    a = 0; 
    if (b > 10) 
     a = 3; 
    } 
    return a; 
} 

poi ho compilato questo codice da clang con -O3 opzione, il file di output .ll è

define i32 @main() #0 { 
entry: 
    %b = alloca i32, align 4 
    %call = call i32 (i8*, ...)* @scanf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %b) 
    %0 = load i32* %b, align 4, !tbaa !1 
    %cmp1 = icmp sgt i32 %0, 10 
    %. = select i1 %cmp1, i32 3, i32 0 
    ret i32 %. 
} 
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 

Questa uscita è buona. L'ottimizzatore LLVM ha rimosso il codice forloop privo di significato e quindi ha assegnato tre o zero per restituire il valore direttamente.

Ora cerco un altro caso come

int main() { 
    int a, b; 
    scanf("%d", &b); 

    for (int i = 0 ; i < 1000 ; i++) { 
    a = 0; 
    if (true) // I modified here only 
     a = 3; 
    } 
    return a; 
} 

e il file di output è

define i32 @main() #0 { 
entry: 
    %b = alloca i32, align 4 
    %call = call i32 (i8*, ...)* @scanf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %b) 
    br label %for.cond 

for.cond:           ; preds = %for.cond, %entry 
    %a.0 = phi i32 [ 0, %entry ], [ 3, %for.cond ] 
    %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.cond ] 
    %inc = add nsw i32 %i.0, 1 
    %exitcond = icmp eq i32 %inc, 1001 
    br i1 %exitcond, label %for.end, label %for.cond 

for.end:           ; preds = %for.cond 
ret i32 %a.0 
} 
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 

Anche se questo codice è più facile da analizzare (ramo è sempre preso), LLVM ottimizzatore non elimina senza senso forloop

Se fossi ottimizzatore, vorrei generare questo codice ottimizzato come

define i32 @main() #0 { 
entry: 
    %b = alloca i32, align 4 
    %call = call i32 (i8*, ...)* @scanf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %b) 
    ret i32 3 
} 

Qualcuno può dirmi perché l'ottimizzatore non è in grado di analizzare un codice più semplice?

+0

Suoni come un bug di ottimizzatore per me – MikeMB

+0

quale versione quale piattaforma? – xaxxon

+0

Non sono un dio dell'assemblea, ma questo mi sembra buono (i colori sono belli) https://godbolt.org/g/qxf6jR - Ho incontrato tutte le versioni di clang sul sito e non sono riuscito a riprodurlo con nessuno di loro. – xaxxon

risposta

5

ho testato lo snippet di codice con llvm 3.9 e genera:

define i32 @main() #0 { 
    %1 = alloca i32, align 4 
    %2 = bitcast i32* %1 to i8* 
    call void @llvm.lifetime.start(i64 4, i8* %2) #3 
    %3 = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i32* nonnull %1) 
    call void @llvm.lifetime.end(i64 4, i8* %2) #3 
    ret i32 3 
} 

Come accennato da MikeMB, credo che sia un bug nel ottimizzatore che ora è stato risolto. Qual è stata la tua versione llvm?

+0

https://godbolt.org/g/qxf6jR - la codifica a colori lo rende palesemente evidente anche per uno come me – xaxxon

+0

3.4 e 3.8, entrambi hanno gli stessi risultati. Secondo i tuoi test, penso che questo bug sia corretto in 3.9 ma non ho aggiornato il mio LLVM. Grazie per il tuo test :) – hwliu