如何在LLVM bitcode中实现floor,ceil和round?

时间:2010-08-17 22:40:40

标签: math compiler-construction llvm primitive

我正在编写基于LLVM的小型编程语言的数学函数, 而我目前对如何实现常见的舍入函数floor,ceil和round(to even)感到困惑。首先是因为我没有找到这些函数的任何算法描述,其次是因为我不熟悉LLVM具有的功能。四舍五入。

能够正确地舍入负数是必须的,舍入到特定的精度不是。舍入为整数值即可。简单地指出可以从LLVM bitcode使用的任何现有实现也将起作用。

3 个答案:

答案 0 :(得分:1)

如果您查看Google代码搜索,则会有一些results。链接的示例假设IEEE浮点数。通常,普通PC的编译器只需将floor编译为浮点指令。例如,原始的387算术处理器具有FPREM指令,该指令或多或少地为floor所需的一部分。

答案 1 :(得分:1)

您将要开始使用LLVM language reference manual

你可以从实现trunc( )开始,就像沿着这些方向做某事一样(警告,实际上不要使用它;它只是作为一个例子,并且不正确。见下面的讨论):

define float @trunc(float %x) {
    %rounded = fptosi float %x to i32
    %asFloat = sitofp i32 %rounded to float
    ret float %asFloat
}

fptosi ... to ...指令记录为根据舍入到零舍入模式将浮点值舍入为整数值。 sitofp ... to ...指令将该值转换回浮点值以返回。

但是,这个实现存在问题;读取我链接的语言参考,“如果舍入到最接近的整数的结果不适合目标类型,则fptosi ... to ...的行为是未定义的。”

这很容易解决,因为所有足够大的浮点数都已经是整数,并且不需要舍入;如果x的绝对值大于或等于2 ^ 23,则可以返回x本身。

(这是单精度的全部;对于double,你可能想要使用i64,你需要使用2 ^ 52的阈值

对于其他操作,例如floorround,您可以从trunc开始,然后检查剩余x - trunc(x)并相应地调整结果。

或者,您可以调用主机平台的C库,该库已包含这些功能。这是许多编程语言采用的方法。

答案 2 :(得分:1)

我已经通过以下方式实现了浮点向量的底层:'截断'值x,然后比较x和trunc(x)。其中trunc(x)> x,减去1,因为floor(x)必须始终最多为x。 我在Haskell编写了这个代码。我不知道,这是否对你有所帮助。见floorLogical in http://code.haskell.org/~thielema/llvm-extra/src/LLVM/Extra/Vector.hs

圆形到均匀通常是昂贵的并且没有多大用处。我只是使用floor(x + 0.5)。 在SSE4.1中还有roundss,roundps et.al。