理解 GCC 中 std::pow 的实现

7
我正在尝试理解GCC中std::pow函数的工作原理。我查看了cmath库的源代码,链接如下:https://code.woboq.org/gcc/libstdc++-v3/include/c_global/cmath.html#_ZSt3powff
在该文件的第388行,当浮点类型作为参数传递时,他们给出了pow的定义,如下所示:
#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
  inline _GLIBCXX_CONSTEXPR float
  pow(float __x, float __y)
  { return __builtin_powf(__x, __y); }

这个 pow 函数调用另一个函数 __builtin_powf

我想知道的是,__builtin_powf 定义在哪里?我看到它是内置函数,但这并不能帮助我理解它的实现在哪里。我似乎找不到 GCC 源代码中的其他位置有 __builtin_powf。此外,它是如何转换成汇编代码的?


3
提示给那些跟随者:每当你看到一个连续两个下划线的标识符时,它意味着你发现了一个实现特定的细节(或者有人搞砸了)。在这种情况下,它应该在GCC源代码中某处,因为它是开源的,但在闭源编译器中,它可能会被埋藏在库文件中,你需要进行反编译工作。 - user4581301
1
他们确实没有很好地公开那个源码。看起来它是由一些宏巫术生成的,这些巫术可以自动生成float(f)、double(w)、intlong(l)和其他几种数学函数的变体。请查看f95-lang.c文件。 - tadman
2
你选择了最难实现的数学函数之一,而且实现过程有许多特殊情况,例如y是整数,x < 0且0 < y < 1等等...例如,在其中一个情况下,您首先通过执行范围缩减来处理输入,然后使用x86芯片上的FYL2X和F2XM1 x86指令计算2^(y*log2(x))。您可以在https://github.com/lattera/glibc/blob/master/sysdeps/x86_64/fpu/e_powl.S找到glib版本。 顺便说一句,当有人使用pow(x,2)来平方一个数字时,我总是会开心地笑出声。这就像用大锤敲打图钉一样。 - wcochran
2
简短的回答是它们被构建或嵌入到编译器本身中。如果您深入挖掘gcc源代码,几乎可以确定内置函数的实现是可配置的(例如使用./configure脚本,在从源代码构建编译器之前必须执行),因此针对指定目标系统(硬件和操作系统)构建的gcc版本会利用该目标系统上已知的库或机器指令。 - Peter
1
__builtin_XXX 语法的整个目的是用于那些不能被实现为普通函数,而需要在编译时触发一些特殊处理的内容。 在这种情况下,它仅仅是尽可能地进行常量折叠,但是许多其他内置函数执行的操作远非任何真实函数可以执行的操作。 要求它们的源代码就像要求 sizeof 函数的源代码一样 - 没有一个写下来可以的单一函数。 - Nate Eldredge
显示剩余2条评论
1个回答

2

__builtin_powf 定义在哪里?

它定义在您的C标准库实现中。在gcc中没有powf的实现。

__builtin_powf 存在的目的是让 gcc 能够检测到 pow 的使用并在编译时计算结果(如果可以的话)。嗯,字符串 "__builtin_powf""defined" gcc/builtins.def#L541 中(但实际上 只存在于函数参数中),内建函数似乎在 gcc/builtins.c#L2100 处理,但最终 pow 由 C 标准库处理。当 fold-const-call.c#L1393 中的 pow 被不断折叠 时,调用可以在 tree-vect-patterns.c 中进行矢量化/替换。但最终的 "实现" 在您的 C 标准库中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接