为什么Clang会自动为我的函数添加属性?

Phi*_*ias 3 c c++ assembly llvm compiler-optimization

我有一段代码,我正试图变成LLVM bitcode:

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

我对它运行以下命令:

clang -O0 -S -emit-llvm TrainingCode/trainingCode.cpp -o TrainingCode/trainingCode.ll
Run Code Online (Sandbox Code Playgroud)

生成以下LLVM bitcode(注意第6行,带有"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)"}
Run Code Online (Sandbox Code Playgroud)

为什么clang添加optnone属性main?我需要LLVM在bitcode上运行各种转换传递,该optnone属性导致LLVM跳过main ...我需要不添加此属性.

编译-O1似乎解决了这个问题,但这是不可接受的,因为我需要Clang给我未经优化的代码.我想LLVM优化通过锵给我的未优化的代码,但存在optnone属性引起LLVM不进行任何优化.

Pet*_*des 7

有一些clang选项可以禁用LLVM-IR的优化.有关可能会更改它们的补丁的讨论,请参阅https://reviews.llvm.org/D28047 ; 有关使用它的更多信息,请参阅@ Anton对此问题的回答.部分或全部这些选项可能是正确的:

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

(该讨论的决议是提交rL290392:,Make '-disable-llvm-optzns' an alias for '-disable-llvm-passes'所以目前的clang只需要一个.)


或者是愚蠢的方式:使用sed(或您最喜欢的文本处理工具)可以实现简单的解决方法.

您只在编译器生成的代码上使用它,因此您不必担心使用正则表达式来解析自由格式的手写代码.因此,您可以匹配编译器始终使用的固定格式,以确保您只在正确的行上操作.

# tested and works on the .ll in your question
sed -i '/^; Function Attrs:\|^attributes #/ s/optnone //'   *.ll
Run Code Online (Sandbox Code Playgroud)

optnone用空字符串替换第一个(带有尾随空格)的行,在以attributes #(重要的)或; Function Attrs:(注释)开头的行上替换.

它是s////foo\|bar/地址正则表达式控制的命令,用于选择它所操作的行.

sed -i 就地重写输入文件.


Ant*_*kov 5

这是预期的。-O0 输出不是为了进一步优化,为了减少编译时间,根本不会发出一些 IR 位。

因此,如果您想获得可能稍后优化的未优化 IR,则需要使用 -O1 -mllvm -disable-llvm-optzns。