Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Bézier curves  (Read 36846 times)

0 Members and 1 Guest are viewing this topic.

Silvah

  • Guest
Re: Bézier curves
« Reply #45 on: July 12, 2013, 03:31:00 pm »
It's not even the compiler, it's the standard library implementation. libstdc++ defines std::pow(double, int) as a call to __builtin_powi. Since 10 is a compile-time constant, the compiler is then able to emit the operation inline instead of making a library call to pow.

And what? He "knows" that this is a function that computes a power, and apply its own optimized algorithm instead? This is just a function call, the compiler knows nothing about it.
The standard library is special, the implementation is free to assume all kinds of things, as long as they don't violate the spec. The standard library may not even exist except in the form of rules hard-coded in the compiler.
« Last Edit: July 12, 2013, 03:33:42 pm by Silvah »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Bézier curves
« Reply #46 on: July 12, 2013, 03:32:26 pm »
When using the headers that are provided by the compiler, std::pow calls the built-in pow function. In GCC it's __builtin_pow which the compiler knows it should optimize. Compilers basically have a table of functions that they know how to optimize, so when calling those, they get immediately translated to asm.

GCC Builtins: http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Other-Builtins.html
VS12 Intrinsics: http://msdn.microsoft.com/en-us/library/26td21ds%28v=vs.110%29.aspx
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Silvah

  • Guest
Re: Bézier curves
« Reply #47 on: July 12, 2013, 03:39:17 pm »
In GCC it's __builtin_pow which the compiler knows it should optimize.
Uhm, no. GCC doesn't optimize __builtin_pow nearly as much as it optimizes __builtin_powi. In particular
double foo(double p)
{
  return __builtin_pow(p, 10);
}

double bar(double p)
{
  return __builtin_powi(p, 10);
}
compiles down on my machine to the following assembly:
        .text
        .p2align 4,,15
        .globl  _Z3food
        .def    _Z3food;        .scl    2;      .type   32;     .endef
        .seh_proc       _Z3food
_Z3food:
.LFB0:
        .seh_endprologue
        movsd   .LC0(%rip), %xmm1
        jmp     pow
        .seh_endproc
        .p2align 4,,15
        .globl  _Z3bard
        .def    _Z3bard;        .scl    2;      .type   32;     .endef
        .seh_proc       _Z3bard
_Z3bard:
.LFB1:
        .seh_endprologue
        movapd  %xmm0, %xmm1
        mulsd   %xmm0, %xmm1
        mulsd   %xmm1, %xmm0
        mulsd   %xmm1, %xmm0
        mulsd   %xmm0, %xmm0
        ret
        .seh_endproc



What may be interesting is that this optimization takes place only when C++11 mode is disabled. With -std=c++11, or even -std=gnu++11, for
double qux(double p)
{
  return std::pow(p, 10);
}
GCC 4.8.2 20130701 generates a library call:
        .p2align 4,,15
        .globl  _Z3quxd
        .def    _Z3quxd;        .scl    2;      .type   32;     .endef
        .seh_proc       _Z3quxd
_Z3quxd:
.LFB258:
        .seh_endprologue
        movsd   .LC0(%rip), %xmm1
        jmp     pow
        .seh_endproc
« Last Edit: July 12, 2013, 03:45:27 pm by Silvah »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Bézier curves
« Reply #48 on: July 12, 2013, 04:06:38 pm »
GCC doesn't even have a __builtin_pow. I was referring to the family of builtin power functions such as __builtin_powi, __builtin_powif and __builtin_powil.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Silvah

  • Guest
Re: Bézier curves
« Reply #49 on: July 12, 2013, 04:10:15 pm »
GCC doesn't even have a __builtin_pow.
It does. See the documentation:
Quote
The ISO C90 functions abort, abs, acos, asin, atan2, atan, calloc, ceil, cosh, cos, exit, exp, fabs, floor, fmod, fprintf, fputs, frexp, fscanf, isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit, tolower, toupper, labs, ldexp, log10, log, malloc, memchr, memcmp, memcpy, memset, modf, pow, printf, putchar, puts, scanf, sinh, sin, snprintf, sprintf, sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strpbrk, strrchr, strspn, strstr, tanh, tan, vfprintf, vprintf and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function). All of these functions have corresponding versions prefixed with __builtin_.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Bézier curves
« Reply #50 on: July 12, 2013, 04:38:59 pm »
Hmm yeah I just saw myself. If you look at the description for __builtin_powi it states:
Quote
Returns the first argument raised to the power of the second. Unlike the pow function no guarantees about precision and rounding are made.
no guarantees about precision and rounding = enable optimization
So I guess __builtin_pow is really equivalent to the explicit multiplication.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

cpolymeris

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
    • Email
Re: Bézier curves
« Reply #51 on: July 12, 2013, 09:55:28 pm »
This is very interesting but I still wonder how the compiler does. So it's probably not an effect of generic optimization rules, but rather a hard-coded one (std::pow + integer arg = this specific code).

It's been a while since I used C++, but couldn't something like that be templated?
float template <0> float _pow(float)
{
   return 1;
}

float template <int n> float _pow(float x)
{
   return x * _pow<n - 1>;
}

float std::pow(float x, const int n)
{
  return _pow<n>(x);
}
 

If that works (or something similar, don't remember the syntax), maybe it's not a compiler optimization at all, but rather a std:: optimization.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Bézier curves
« Reply #52 on: July 12, 2013, 11:28:36 pm »
Boost actually employs such template meta programming black magic to optimize some things to compute stuff at compile time. Nice side effect: your compiler blows up half the time with some obscure error because the template recursion depth was set to something like 100.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).