gpt4 book ai didi

c - LLVM IR 浮点转换

转载 作者:太空宇宙 更新时间:2023-11-04 03:33:21 25 4
gpt4 key购买 nike

今天我在 LLVM IR 中遇到了浮点转换的奇怪问题。我正在使用 Windows 10 和 llvm-3.5.2。我用 C 写了这段代码:

#include <stdio.h>
int main() {
double b = 2.0;
float c = b;
printf("%d\n", c == 2.0);
return 0;
}

然后我使用了 clang -S -emit-llvm 并获得了这个 LLVM IR:

@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1

; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%retval = alloca i32, align 4
%b = alloca double, align 8
%c = alloca float, align 4
store i32 0, i32* %retval
store double 2.000000e+00, double* %b, align 8
%0 = load double* %b, align 8
%conv = fptrunc double %0 to float
store float %conv, float* %c, align 4
%1 = load float* %c, align 4
%conv1 = fpext float %1 to double
%cmp = fcmp oeq double %conv1, 2.000000e+00
%conv2 = zext i1 %cmp to i32
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %conv2) #1
ret i32 0
}

; Function Attrs: nounwind
declare i32 @printf(i8*, ...) #0

执行(在 llvm-aslli 之后)给出了错误的结果 0 !

问题似乎出在 fpext 中,这不是很直观,因为它应该是这种“安全”转换(比 fptrunc 从 double 到 float )。

我认为是的,因为当我改变这一行时:

%cmp = fcmp oeq 双 %conv1, 2.000000e+00

为此:

%cmp = fcmp oeq float %1, 2.000000e+00

那么结果就是预期的1

所以我的问题是为什么会这样,为什么这个转换失败了?这是 LLVM 中的某种错误吗?或者存在这种类型的转换的一些更好的方法?或者也许我用 C 写了一个不安全的代码?如果是这样,那么使用 float 就有很大的问题了。执行此转换时,我对 clang 没有影响。例如,假设我想输出上面的 c。然后我编写 printf("%f", c),clang 生成代码,在将 c 传递给 printf 之前将其转换为 double。结果又不正确了。那么如何安全地打印一个 float 呢?如何安全地使用花车?

我不确定这个问题是否也出现在 Linux 上。

最佳答案

我在ubuntu14.04 LLVM3.6上工作,我有像你一样的保存输出,但也得到了正确的答案。

我认为你应该检查你的 clang 版本,如果 clang 使用其他版本的 llvm,你可能会有意想不到的答案。

像这样:

clang --version

Ubuntu clang version 3.6.0-2ubuntu1~trusty1 (tags/RELEASE_360/final) (based on LLVM 3.6.0)
Target: x86_64-pc-linux-gnu
Thread model: posix

llvm-IR:

; ModuleID = 'main.c'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1

; Function Attrs: nounwind uwtable
define i32 @main() #0 {
%1 = alloca i32, align 4
%b = alloca double, align 8
%c = alloca float, align 4
store i32 0, i32* %1
store double 2.000000e+00, double* %b, align 8
%2 = load double* %b, align 8
%3 = fptrunc double %2 to float
store float %3, float* %c, align 4
%4 = load float* %c, align 4
%5 = fpext float %4 to double
%6 = fcmp oeq double %5, 2.000000e+00
%7 = zext i1 %6 to i32
%8 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %7)
ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.ident = !{!0}

!0 = !{!"Ubuntu clang version 3.6.0-2ubuntu1~trusty1 (tags/RELEASE_360/final) (based on LLVM 3.6.0)"}

关于c - LLVM IR 浮点转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34380045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com