Hello. I'm a developer for the open source project LinuxCNC (http://linuxcnc.org). I hope someone can help me understand the details or limitations of pragma GCC optimize / attribute optimize as they apply to a specific case we've encountered, and how to get the results we desire from gcc. Our project uses FP math in kernel space, and one of the GNU standard functions we supply an implementation of is sincos(3). Our implementation of sincos looks like this: void sincos(double x, double *sx, double *cx) { *sx = sin(x); *cx = cos(x); } Unfortunately, on amd64 platforms under most optimization flags, this compiles into a call to sincos, leading to unbounded recursion at runtime. This optimization is only natural, since the form of the body is *exactly* sincos. Of course, this optimization is inappropriate in this specific case, when processing the implementation of sincos. Adding -fno-builtin-sin to the commandline inhibits this transformation. As a result, I expected the following declaration to inhibit the transformation too: __attribute__((optimize("no-builtin-sin"))) void sincos(double x, double *sx, double *cx); however, the assembly *still* contains a call to sincos. This was also true for any of the following: #pragma GCC optimize "no-builtin-sin" #pragma GCC optimize "no-builtin-cos" #pragma GCC optimize "freestanding" __attribute__((optimize("no-builtin-cos"))) void sincos(double x, double *sx, double *cx); __attribute__((optimize("freestanding"))) void sincos(double x, double *sx, double *cx); and in a range of gcc versions (4.6, 4.7, 4.8, 4.9 all as packaged by Debian for the upcoming Jessie release) I think I don't completely misunderstand how to apply __attribute__ ((optimize)) and #pragma GCC, because these alternatives do work: #pragma GCC optimize "0" __attribute__((optimize("0"))) void sincos(double x, double *sx, double *cx); as well as some more exotic trickery such as extern double sin_(double) __asm__("sin"); #define sin sin_ (which of course is not going to work on platforms that prefix extern identifiers with _, if any such environments exist anymore) I've prepared a test program and script that should allow you to recreate my results. Save ctest.sh and sc.c in the same directory, customize the top of ctest.sh according to the gcc versions you have installed, and run it with bash. The test works by grepping the assembler output for 'sincos', which is presumably a synthesized call to that function. (Possibly because we supply an inline asm implementation of sin/cos as fsin/fcos on i386 we haven't heard about this problem on i386 systems, and on arm systems we aren't using the kernel-space model for our software at all. so mentioning amd64 specifically may be a red herring in terms of gcc's behavior) Thanks for any replies! I am subscribed to the list but would appreciate a courtesy copy of responses if it's considered good etiquette around here. Jeff ## Cut here for ctest.sh #!/bin/bash versions="gcc-4.6 gcc-4.7 gcc-4.8 gcc-4.9" set -o pipefail for cc in $versions; do for opt in -ffreestanding -fno-builtin-sin -DUSE_PRAGMA_FREESTANDING \ -DUSE_PRAGMA_NO_BUILTIN -DUSE_PRAGMA_NO_OPTIMIZE \ -DUSE_ATTRIBUTE_FREESTANDING -DUSE_ATTRIBUTE_NO_BUILTIN \ -DUSE_ATTRIBUTE_NO_OPTIMIZE -DUSE_ASM_TRICKERY; do echo -n $cc - $opt "" if $cc -Os -Wall $opt -S -o- sc.c | grep -q sincos; then echo "BAD" else echo "GOOD" fi done echo done exit 0 // cut here for sc.c // (declare sin/cos ourselves to avoid any header cleverness) extern double sin(double); extern double cos(double); #ifdef USE_PRAGMA_FREESTANDING #pragma GCC optimize "freestanding" #endif #ifdef USE_PRAGMA_NO_BUILTIN #pragma GCC optimize "no-builtin-sin" #pragma GCC optimize "no-builtin-cos" #endif #ifdef USE_PRAGMA_NO_OPTIMIZE #pragma GCC optimize "0" #endif void fn(double x, double *sx, double *cx) #ifdef USE_ATTRIBUTE_FREESTANDING __attribute__((optimize("freestanding"))) #endif #ifdef USE_ATTRIBUTE_NO_BUILTIN __attribute__((optimize("no-builtin-sin"))) __attribute__((optimize("no-builtin-cos"))) #endif #ifdef USE_ATTRIBUTE_NO_OPTIMIZE __attribute__((optimize("0"))) #endif ; #ifdef USE_ASM_TRICKERY extern double sin_(double) __asm__("sin"); #define sin sin_ #endif void fn(double x, double *sx, double *cx) { *sx = sin(x); *cx = cos(x); }