Comme je l'ai mis dans cette question, gcc est la suppression (oui, avec -O0
) une ligne de code _mm_div_ss(s1, s2);
sans doute parce que le résultat n'est pas enregistré. Toutefois, cela devrait déclencher une exception de virgule flottante et d'élever SIGFPE, qui ne peut pas se produire si l'appel est supprimé.
Question: Est-il d'un drapeau, d'un ou de plusieurs indicateurs, pour passer à gcc de sorte que le code est compilé en tant que-est? Je suis en train de penser à quelque chose comme fno-remove-unused
mais je ne vois pas de quoi que ce soit. Dans l'idéal, ce serait un compilateur drapeau au lieu d'avoir à changer mon code source, mais si que n'est pas pris en charge est-il un gcc attribut/pragma à utiliser à la place?
Les choses que j'ai essayé:
$ gcc --help=optimizers | grep -i remove
pas de résultats.
$ gcc --help=optimizers | grep -i unused
pas de résultats.
Et explicitement la désactivation de tous les morts de code d'élimination des drapeaux -- notez qu'il n'y a pas d'avertissement à propos de code inutilisé:
$ 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 a.c
a.c: In function ‘main':
a.c:25:5: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
__m128 s1, s2;
^
$
Le programme Source
#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;
}
La compilation du programme ci-dessus donne
$ ./a.out
done (no error).
La modification de la ligne
_mm_div_ss(s1, s2);
pour
s2 = _mm_div_ss(s1, s2); // add "s2 = "
produit le résultat attendu:
$ ./a.out
inside SIGFPE handler
Modifier avec plus de détails.
Cela semble être lié à l' __always_inline__
l'attribut dans l' _mm_div_ss
définition.
$ cat t.c
int
div(int b)
{
return 1/b;
}
int main()
{
div(0);
return 0;
}
$ gcc -O0 -Wall -Wextra -pedantic -Winline t.c -o t.out
$
(pas d'avertissements ou d'erreurs)
$ ./t.out
Floating point exception
$
vs ci-dessous (même à l'exception de la fonction d'attributs)
$ cat t.c
__inline int __attribute__((__always_inline__))
div(int b)
{
return 1/b;
}
int main()
{
div(0);
return 0;
}
$ gcc -O0 -Wall -Wextra -pedantic -Winline t.c -o t.out
$
(pas d'avertissements ou d'erreurs)
$ ./t.out
$
Ajout de la fonction d'attribut __warn_unused_result__
en donne au moins un message utile:
$ gcc -O0 -Wall -Wextra -pedantic -Winline t.c -o t.out
t.c: In function ‘main':
t.c:9:5: warning: ignoring return value of ‘div', declared with attribute warn_unused_result [-Wunused-result]
div(0);
^
edit:
D'un débat sur la gcc liste de diffusion. En fin de compte, je pense que tout fonctionne comme prévu.