Capture SIGFPE de l’instruction SIMD

J’essaie d’effacer l’indicateur de division par virgule flottante par zéro pour ignorer cette exception. J’attends qu’avec le drapeau défini (aucun changement du comportement par défaut je crois, et commenté ci-dessous), mon gestionnaire d’erreurs se déclenche. Cependant, _mm_div_ss ne semble pas élever SIGFPE. Des idées?

 #include  #include  #include  #include  static void sigaction_sfpe(int signal, siginfo_t *si, void *arg) { printf("inside SIGFPE handler\nexit now."); 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); // catch all FPE except divide by zero __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; } 

Sortie du code ci-dessus:

 $ gcc ac $ ./a.out done (no error). 

Comme vous pouvez le constater, mon gestionnaire n’est jamais atteint. Note latérale: J’ai essayé plusieurs indicateurs de compilation (-msse3, -march = native) sans aucun changement.

gcc (Debian 5.3.1-7) 5.3.1 20160121

Quelques informations de / proc / cpuinfo

 model name : Intel(R) Core(TM) i3 CPU M 380 @ 2.53GHz flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 popcnt lahf_lm arat dtherm tpr_shadow vnmi flexpriority ept vpid 

Deux choses.

Tout d’abord, j’ai mal compris la documentation. Les exceptions doivent être démasquées pour être capturées. Appel de _mm_setcsr(0x00001D80); permettra à SIGFPE de déclencher une division par zéro.

Deuxièmement, gcc optimisait mon instruction de division même avec -O0 .

Ligne source donnée

 _mm_div_ss(s1, s2); 

Comstackr avec gcc -S -O0 -msse2 ac donne

 76 movaps -24(%ebp), %xmm0 77 movaps %xmm0, -72(%ebp) 78 movaps -40(%ebp), %xmm0 79 movaps %xmm0, -88(%ebp) a1 subl $12, %esp ; renumbered to show insertion below a2 pushl $.LC2 a3 call puts a4 addl $16, %esp 

Alors que la ligne source

 s2 = _mm_div_ss(s1, s2); // add "s2 = " 

donne

 76 movaps -24(%ebp), %xmm0 77 movaps %xmm0, -72(%ebp) 78 movaps -40(%ebp), %xmm0 79 movaps %xmm0, -88(%ebp) movaps -72(%ebp), %xmm0 divss -88(%ebp), %xmm0 movaps %xmm0, -40(%ebp) a1 subl $12, %esp a2 pushl $.LC2 a3 call puts a4 addl $16, %esp 

Avec ces modifications, le gestionnaire SIGFPE est appelé en fonction de l’indicateur de division par zéro dans MXCSR.