【问题标题】:How to implement floor, ceil and round in LLVM bitcode?如何在 LLVM 位码中实现 floor、ceil 和 round?
【发布时间】:2010-08-17 22:40:40
【问题描述】:

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

能够正确舍入负数是必须的,而舍入到特定精度则不是。四舍五入到整数值就可以了。简单地指出可以从 LLVM 位码中使用的任何现有实现也将起作用。

【问题讨论】:

  • 不是一个真正的答案,否则我会这样做。但只是轶事信息。我发现当我处于这样的位置时,我会编写 C 代码来重现该函数,然后用 clang 或 llvm-gcc 编译它并查看生成的 llvm ir。这通常让我对应该如何进行有足够的了解。
  • 这可能有点离题,但我认为在实现自己的数学库时了解和考虑仍然很有价值:为那些与浮点数学的怪癖正确工作的函数提出一种算法是不像最初看起来那么微不足道,例如可以看出here.

标签: math compiler-construction llvm primitive


【解决方案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本身。

(这都是单精度;对于双精度,您可能希望使用i64,并且您需要使用阈值 2^52)

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

或者,您可以调用主机平台的 C 库,其中已经包含这些函数。这是许多编程语言采用的方法。

【讨论】:

  • 调用我本地的 C 库是个好主意。但是根据 LLVM 语言。参考。 fptosi 向 0 舍入,而不是向最近的值舍入。
  • @voxcogitatio:很好;显示了我在编写 sn-p 时是多么仔细地浏览了参考资料。今天晚些时候我会更正它。
【解决方案2】:

如果您查看 Google 代码搜索,就会发现有几个 results。链接示例假定 IEEE 浮点数。通常,普通 PC 的编译器只是将floor 编译为浮点指令。例如,最初的 387 算术处理器具有指令 FPREM,它或多或少地完成了您对 floor 的需求。

【讨论】:

    【解决方案3】:

    我通过以下方式为浮点向量实现了下限:“截断”值 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

    四舍五入通常很昂贵,而且没有多大用处。我只是使用地板(x + 0.5)。 SSE4.1中还有roundss、roundps等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-19
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 2019-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多