为什么Clang自动向我的函数添加属性? [英] Why is Clang automatically adding attributes to my functions?

查看:120
本文介绍了为什么Clang自动向我的函数添加属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段代码正试图转换为LLVM位代码:

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

生成以下LLVM位代码(请注意第6行,即"Function Attrs"):

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)"}

为什么clang将optnone属性添加到main?我需要LLVM在位码上运行各种转换,并且optnone属性导致LLVM跳过main ...我需要不添加此属性.

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.

使用-O1进行编译似乎可以解决此问题,但是这是不可接受的,因为我需要使用Clang来提供未优化的代码.我希望LLVM优化Clang给我的未优化代码,但是optnone属性的存在导致LLVM不执行任何优化.

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.

推荐答案

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

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

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

(The resolution of that discussion was commit rL290392: Make '-disable-llvm-optzns' an alias for '-disable-llvm-passes', so current clang only needs one.)

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

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

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

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).

这是由/foo\|bar/地址正则表达式控制的s///命令,用于选择要在其上操作的行.

It's an s/// command controlled by a /foo\|bar/ address regex to select which lines it operates on.

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

这篇关于为什么Clang自动向我的函数添加属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆