Why is Clang automatically adding attributes to my functions?

。_饼干妹妹 提交于 2019-12-19 09:49:43

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!