7

I am trying to understand how the std::pow function works in GCC. I was looking at the source code for the cmath library here https://code.woboq.org/gcc/libstdc++-v3/include/c_global/cmath.html#_ZSt3powff.

On line 388 of that file, they give the definition of pow when float types are passed as the argument as shown here

#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
  inline _GLIBCXX_CONSTEXPR float
  pow(float __x, float __y)
  { return __builtin_powf(__x, __y); }

This pow function calls another function __builtin_powf.

What I want to know is, where is __builtin_powf defined? I read that it is a built in function, but that still does not help me understand where its implementation lives. I can not seem to find __builtin_powf anywhere else in the GCC source code. Also, how is it translated to assembly?

7
  • 3
    Note to those that follow: Anytime you see an identifier with two underscores in a row, it means you've found a implementation specific detail (or someone <expletive deleted>ed up). In this case, it should be in the GCC source code somewhere because it's open source, but in a closed-source compiler it could be buried in a library file where you'll have to work ad decompiling it. Commented Jul 6, 2020 at 22:37
  • 1
    They sure don't make that source easy to find. It looks like it's generated by some macro wizardry that cranks out float (f), double (w) int, long (l) and other variants of several mathematical functions automatically. See f95-lang.c.
    – tadman
    Commented Jul 6, 2020 at 22:38
  • 3
    You picked one of the hardest math functions to implement and the implementation has many special cases e.g., y is an integer, x < 0 and 0 < y < 1, etc.... for example, in one of the cases you first massage the input by performing range reduction and then compute 2^(y*log2(x)) using the FYL2X and F2XM1 x86 instructions on an x86 chip. You can find glib version at github.com/lattera/glibc/blob/master/sysdeps/x86_64/fpu/… BTW, I always get a good laugh when someone use pow(x,2) to square a number. That's like using a sledge hammer on a thumbtack.
    – wcochran
    Commented Jul 6, 2020 at 22:58
  • 2
    The short answer is that they are built or baked into the compiler itself. gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html If you dig further into the gcc source code, you'll almost certainly find that the implementation of built in functions is configurable (e.g. using the ./configure script that must be executed before the building of the compiler from source) so the versions of gcc, when built for a specified target system (hardware and OS), makes use of known libraries or machine instructions on that target system.
    – Peter
    Commented Jul 6, 2020 at 23:16
  • 1
    The whole point of the __builtin_XXX syntax is for things that can't be implemented as ordinary functions, but instead need to trigger some special handling at compile time. In this case it's merely constant folding where possible, but many of the other builtins do stuff that isn't remotely like anything a real function could do. Asking for their source code is like asking for the source code of the sizeof function - there isn't a single function written down that it could be. Commented Jul 7, 2020 at 0:14

1 Answer 1

2

where is __builtin_powf defined?

It is defined in your C standard library implementation. There no implementation of powf in gcc.

The __builtin_powf exists so that gcc could detect pow usage and compute the result at compile time if it can. Well, the string "__builtin_powf" is "defined" in gcc/builtins.def#L541 (but really only exists as function argument) and builtins seem to be handled at gcc/builtins.c#L2100, but on the end pow is handled by the C standard library. When fold_const_call_sss() in fold-const-call.c#L1393 returned success, that means pow was folded constantly. The call could be vectorized/substituted in tree-vect-patterns.c. But on the end the "implementation" is in your C standard library.

Not the answer you're looking for? Browse other questions tagged or ask your own question.