问题
I have a piece of code that I'm trying to turn into LLVM bitcode:
int main() {
volatile double n = 0.45;
for (int j = 0; j < 32; j++) {
n *= j;
}
return 0;
}
I run the following command on it:
clang -O0 -S -emit-llvm TrainingCode/trainingCode.cpp -o TrainingCode/trainingCode.ll
to generate the following LLVM bitcode (take note of the 6th line, the one with "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)"}
Why is clang adding the optnone
attribute to main
? I need LLVM to run various transformation passes on the bitcode and the optnone
attribute is causing LLVM to skip over main... I need this attribute to not be added.
Compiling with -O1
seems to fix this, however this is unacceptable because I need Clang to give me unoptimized code. I want LLVM to optimize the unoptimized code given to me by Clang, but the presence of the optnone
attribute is causing LLVM to not perform any optimizations.
回答1:
There are clang options to disable its optimization of the LLVM-IR. See https://reviews.llvm.org/D28047 for discussion of a patch that would change them, and @Anton's answer to this question for more about using it. Some or all of these options might be the right thing:
clang -O1 -mllvm -disable-llvm-optzns -disable-llvm-passes
(The resolution of that discussion was commit rL290392: Make '-disable-llvm-optzns' an alias for '-disable-llvm-passes'
, so current clang only needs one.)
Or there's the dumb way: A simple workaround is possible with sed
(or your favourite text-processing tool).
You're only using this on compiler-generated code, so you don't have to worry about using regexes to parse free-form hand-written code. Thus you can match fixed formatting that the compiler always uses to make sure you operate only on the correct lines.
# tested and works on the .ll in your question
sed -i '/^; Function Attrs:\|^attributes #/ s/optnone //' *.ll
Replaces the first occurence of optnone
(with a trailing space) with the empty string, on lines that start with attributes #
(the one that matters) or with ; Function Attrs:
(the comment).
It's an s///
command controlled by a /foo\|bar/
address regex to select which lines it operates on.
sed -i
rewrites the input file(s) in-place.
回答2:
This is expected. The -O0 output is not intended for further optimizations, some bits of IR are not emitted at all in order to reduce the compilation time.
So, you'd need to use -O1 -mllvm -disable-llvm-optzns if you want to get unoptimized IR that may be optimized later.
回答3:
Sorry not a solution, but maybe a clue.
But be clang version released or environment variables.
Taking your code on OS X with 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)"}
来源:https://stackoverflow.com/questions/47504219/why-is-clang-automatically-adding-attributes-to-my-functions