J'ai un morceau de code que j'essaie de transformer en bitcode LLVM:

int main() {
    volatile double n = 0.45;
    for (int j = 0; j < 32; j++) {
        n *= j;
    }
    return 0;
}

J'exécute la commande suivante dessus:

clang -O0 -S -emit-llvm TrainingCode/trainingCode.cpp -o TrainingCode/trainingCode.ll

Pour générer le bitcode LLVM suivant (notez la 6ème ligne, celle avec "Function Attrs"):

; ModuleID = 'TrainingCode/trainingCode.cpp'
source_filename = "TrainingCode/trainingCode.cpp"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: noinline norecurse nounwind optnone uwtable
define i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  %n = alloca double, align 8
  %j = alloca i32, align 4
  store i32 0, i32* %retval, align 4
  store double 4.500000e-01, double* %n, align 8
  store i32 0, i32* %j, align 4
  br label %for.cond

for.cond:                                         ; preds = %for.inc, %entry
  %0 = load i32, i32* %j, align 4
  %cmp = icmp slt i32 %0, 32
  br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %for.cond
  %1 = load i32, i32* %j, align 4
  %conv = sitofp i32 %1 to double
  %2 = load double, double* %n, align 8
  %mul = fmul double %2, %conv
  store double %mul, double* %n, align 8
  br label %for.inc

for.inc:                                          ; preds = %for.body
  %3 = load i32, i32* %j, align 4
  %inc = add nsw i32 %3, 1
  store i32 %inc, i32* %j, align 4
  br label %for.cond

for.end:                                          ; preds = %for.cond
  ret i32 0
}

attributes #0 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.0 (tags/RELEASE_500/final)"}

Pourquoi clang ajoute-t-il l'attribut optnone à main? J'ai besoin de LLVM pour exécuter diverses passes de transformation sur le bitcode et l'attribut optnone amène LLVM à ignorer main ... J'ai besoin que cet attribut ne soit pas ajouté.

Compiler avec -O1 semble résoudre ce problème, mais c'est inacceptable car j'ai besoin que Clang me donne du code non optimisé. Je veux que LLVM optimise le code non optimisé qui m'a été donné par Clang, mais la présence de l'attribut optnone fait que LLVM n'effectue aucune optimisation.

4
Phidias 27 nov. 2017 à 08:02

3 réponses

Meilleure réponse

Il existe des options clang pour désactiver son optimisation du LLVM-IR. Voir https://reviews.llvm.org/D28047 pour une discussion sur un correctif qui les changerait, et Réponse de @ Anton à ce sujet question pour en savoir plus sur son utilisation. Certaines ou toutes ces options peuvent être la bonne chose:

clang -O1 -mllvm -disable-llvm-optzns -disable-llvm-passes

(La résolution de cette discussion a été commit rL290392: Make '-disable-llvm-optzns' an alias for '-disable-llvm-passes', donc le clang actuel n'en a besoin que d'un.)


Ou il y a la manière stupide: une solution de contournement simple est possible avec sed (ou votre outil de traitement de texte préféré).

Vous ne l'utilisez que sur du code généré par le compilateur, vous n'avez donc pas à vous soucier d'utiliser des expressions régulières pour analyser le code manuscrit de forme libre. Ainsi, vous pouvez faire correspondre le formatage fixe que le compilateur utilise toujours pour vous assurer que vous n'opérez que sur les lignes correctes.

# tested and works on the .ll in your question
sed -i '/^; Function Attrs:\|^attributes #/ s/optnone //'   *.ll

Remplace la première occurrence de optnone (par un espace à la fin) par la chaîne vide, sur les lignes commençant par attributes # (celle qui compte) ou par ; Function Attrs: (le commentaire).

C'est une commande s/// contrôlée par une expression régulière d'adresse /foo\|bar/ pour sélectionner les lignes sur lesquelles elle opère.

sed -i réécrit le (s) fichier (s) d'entrée sur place.

8
Peter Cordes 28 nov. 2017 à 06:40

Désolé pas une solution, mais peut-être un indice.

Mais soyez la version clang publiée ou les variables d'environnement.

Prendre votre code sous OS X avec XCODE 9:

$ clang -O0 -S -emit-llvm test.cpp  -o test2.ll

$ more test2.ll
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"

; Function Attrs: norecurse nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca double, align 8

...

; <label>:15:                                     ; preds = %4
  ret i32 0
}

attributes #0 = { norecurse nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 8.1.0 (clang-802.0.42)"}
2
Mark 27 nov. 2017 à 05:21

Ceci est attendu. La sortie -O0 n'est pas destinée à d'autres optimisations, certains bits d'IR ne sont pas émis du tout afin de réduire le temps de compilation.

Donc, vous devez utiliser -O1 -mllvm -disable-llvm-optzns si vous voulez obtenir un IR non optimisé qui peut être optimisé plus tard.

4
Anton Korobeynikov 28 nov. 2017 à 05:24
47504219