As I raised in this question , gcc removes (yes, with -O0 ) the line of code _mm_div_ss(s1, s2); presumably because the result is not saved, however, this should raise a floating point exception and raise SIGFPE, which cannot happen if the call is deleted.
Question : Is there a flag or several flags to pass to gcc so that the code is compiled as-is? I think something like fno-remove-unused , but I don't see anything like it. Ideally, this would be a compiler flag instead of changing the source code, but if it is not supported, is there any gcc attribute / pragma to use?
Things I tried:
$ gcc --help=optimizers | grep -i remove
No results.
$ gcc --help=optimizers | grep -i unused
No results.
And explicitly disabling all dead code / exception flags - note that there is no warning about unused code:
$ gcc -O0 -msse2 -Wall -Wextra -pedantic -Winline \ -fno-dce -fno-dse -fno-tree-dce \ -fno-tree-dse -fno-tree-fre -fno-compare-elim -fno-gcse \ -fno-gcse-after-reload -fno-gcse-las -fno-rerun-cse-after-loop \ -fno-tree-builtin-call-dce -fno-tree-cselim ac ac: In function 'main': ac:25:5: warning: ISO C90 forbids mixed declarations and code [-Wpedantic] __m128 s1, s2; ^ $
Source program
#include <stdio.h> #include <signal.h> #include <string.h> #include <xmmintrin.h> static void sigaction_sfpe(int signal, siginfo_t *si, void *arg) { printf("%d,%d,%d\n", signal, si!=NULL?1:0, arg!=NULL?1:0); printf("inside SIGFPE handler\nexit now.\n"); exit(1); } int main() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_sigaction = sigaction_sfpe; sa.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &sa, NULL); _mm_setcsr(0x00001D80); __m128 s1, s2; s1 = _mm_set_ps(1.0, 1.0, 1.0, 1.0); s2 = _mm_set_ps(0.0, 0.0, 0.0, 0.0); _mm_div_ss(s1, s2); printf("done (no error).\n"); return 0; }
Compiling the above program gives
$ ./a.out done (no error).
Row change
_mm_div_ss(s1, s2);
to
s2 = _mm_div_ss(s1, s2); // add "s2 = "
gives the expected result:
$ ./a.out inside SIGFPE handler
Edit with more details.
This is similar to the __always_inline__ attribute in the __always_inline__ definition.
$ cat tc int div(int b) { return 1/b; } int main() { div(0); return 0; } $ gcc -O0 -Wall -Wextra -pedantic -Winline tc -o t.out $
(no warnings or errors)
$ ./t.out Floating point exception $
vs lower (same except function attributes)
$ cat tc __inline int __attribute__((__always_inline__)) div(int b) { return 1/b; } int main() { div(0); return 0; } $ gcc -O0 -Wall -Wextra -pedantic -Winline tc -o t.out $
(no warnings or errors)
$ ./t.out $
Adding the __warn_unused_result__ function attribute at least gives a useful message:
$ gcc -O0 -Wall -Wextra -pedantic -Winline tc -o t.out tc: In function 'main': tc:9:5: warning: ignoring return value of 'div', declared with attribute warn_unused_result [-Wunused-result] div(0); ^
edit:
Some discussions of the gcc mailing list . Ultimately, I think that everything works as intended.