Intel® C++ Compiler
Support and discussions for creating C++ code that runs on platforms based on Intel® processors.
7731 Discussions

__STDC_IEC_559__ is defined to 1, but SNAN - SNAN does not raise FE_INVALID

pmor
Beginner
1,458 Views

This code:

#include <stdio.h>
#include <stdint.h>
#include <fenv.h>
#include <math.h>

#pragma	STDC FENV_ACCESS ON

int	main			(void)
{
#if __STDC_IEC_559__ == 1
        typedef	union
        {
                uint32_t	u;
                float		v;
        }	u_t;
        u_t snan = { .u = 0x7FA00000 };
        float f = snan.v - snan.v;
        if ((fetestexcept(FE_INVALID) & FE_INVALID) == 0)
        {
                printf("error: no FE_INVALID raised\n");
                return 1;
        }
        (void)f;
#endif
        return 0;
}

compiled with: icc -std=c11 -pedantic -Wall -Wextra

leads to: error: no FE_INVALID raised

which is expected because __STDC_IEC_559__ is 1.

This is because subss is not generated.

Version: x86-64 icc 2021.1.2 on Linux

Notes:
1. Yes, the __SUPPORT_SNAN__ is not defined.
2. The  -fp-model=strict solves the issue.

0 Kudos
14 Replies
DitiD_Intel
Moderator
1,427 Views

Hi,


Thanks for posting in Intel Communities.


Yes, you are absolutely right. 


By using -fp-model=strict, the code works fine because strict enables pragma stdc fenv_access.


For more information, please refer to the link mentioned below.


https://www.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-refer...


Thanks & Regards,

Ditipriya.


pmor
Beginner
1,382 Views

Why under -fp-model= ! strict (non-strict) __STDC_IEC_559__ is 1?

DitiD_Intel
Moderator
1,326 Views

Hi,

 

The flag (-fp-model=strict) being used here to compile the code is disabling optimization, thus, giving us the exact values as the output. There is no direct relation between the macro and the flag being used here. The value of __STDC_IEC_559__ depends on the host platform, by default, it is 0 for windows and 1 for Linux. Please check the attachments for more information.

 

While executing the code on Visual Studios (using -fp-model=strict), the value of the macro is set to 0 by default during compilation and thus, it is not satisfying the if condition (#if __STDC_IEC_559__ == 1), thereby, not executing the statements within the if block. As for Linux, the value of the macro is set to 1 and it is satisfying the if condition and hence, executing the statements within the if block (using -fp-model=strict). 

 

Please let us know whether the information provided above was helpful in resolving your issue.

 

Thanks & Regards,

Ditipriya.

 

 

pmor
Beginner
1,299 Views

If Intel C compiler under non-strict floating-point models does not conform to the specifications in the Annex F, then for which purpose it defines __STDC_IEC_559__ to 1?

pmor
Beginner
1,100 Views

It seems that there is a typo.
Before: "which is expected because __STDC_IEC_559__ is 1".
After: "which is unexpected because __STDC_IEC_559__ is 1".

DitiD_Intel
Moderator
939 Views

Hi,


We are working on this issue and we will get back to you soon. 


Thanks and Regards,

Ditipriya.


Viet_H_Intel
Moderator
927 Views

 

I don’t think this issue is related to __STDC_IEC_559__, but rather related to floating-point computations.

When come to floating-point calculations, we optimize more aggressively at default. These optimizations increase speed but may affect the accuracy or reproducibility of floating-point computations.

 

Let’s look at your example after removed #if __STDC_IEC_559__ and #endif

 

$cat t.c

#include <stdio.h>

#include <stdint.h>

#include <fenv.h>

#include <math.h>

 

#pragma STDC FENV_ACCESS ON

 

int    main                   (void)

{

       typedef union

       {

               uint32_t       u;

               float          v;

       }      u_t;

       u_t snan = { .u = 0x7FA00000 };

       float f = snan.v - snan.v;

       if ((fetestexcept(FE_INVALID) & FE_INVALID) == 0)

       {

               printf("error: no FE_INVALID raised\n");

               return 1;

       }

       else

       {

               printf ("hello \n");

       }

       (void)f;

       return 0;

}

 

$ rm a.out; icc t.c -c ;icc t.o &&./a.out

error: no FE_INVALID raised

$ rm a.out; icc t.c -c -fp-model precise;icc t.o &&./a.out

hello

 

=== gcc at default has the same output as icc and -fp-model precise/strict

$ rm a.out; gcc t.c -c ;g++ t.o &&./a.out

hello

=== icc at default has the same output as gcc and -ffast-math

$ rm a.out; gcc t.c -c -ffast-math ;g++ t.o &&./a.out

error: no FE_INVALID raised

$

 

So, depending on which compilers and options you select, the floating-point calculation’s results might be different. More info about Intel floating point calculations can be seen https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-an...

 

Thanks,

 

 

 

pmor
Beginner
911 Views

If Intel C compiler under non-strict floating-point models does not conform to the specifications in the Annex F, then for which purpose it defines __STDC_IEC_559__ to 1?

Viet_H_Intel
Moderator
903 Views

Can you elaborate why you think Intel C compiler under non-strict floating-point models does not conform to the specifications in the Annex F? What the differences you see between ICC vs. GCC wrt __STDC_IEC_559__ ?

 

pmor
Beginner
875 Views

Because the documentation says so (one example):

> These optimizations increase speed, but may affect the accuracy or reproducibility of floating-point computations.

As I understand, the Annex F does not allow to "affect the accuracy or reproducibility of floating-point computations".

Another example:

#include <stdio.h>

#if __STDC_IEC_559__ == 1
float f(float a, float b, float c) __attribute__((noinline));
float f(float a, float b, float c)
{
    return a * c + b * c;
}

int main(void)
{
    void* p = f;
    printf("%a\n", f(4476.0f, 20439.0f, 4915.0f));
    return 0;
}
#endif

gcc -std=c11
0x1.d32324p+26

icc -std=c11 -fp-model=fast -O0
0x1.d32324p+26

icc -std=c11 -fp-model=fast -O1
0x1.d32322p+26


Here we see that icc:
- produces different results

- __STDC_IEC_559__ is 1

Viet_H_Intel
Moderator
707 Views

As I understand, the Annex F does not allow to "affect the accuracy or reproducibility of floating-point computations"

If you can send a link to show that the above statement is true at the default (no other options are needed), then I can forward it to our the developer.

As I've mentioned you can use -fp-model precise to get the same output as gcc.

Thanks,


pmor
Beginner
668 Views

C11, F.3 Operators and functions, 1:
> C operators and functions provide IEC 60559 required and recommended facilities as listed below.
> — The +, −, *, and / operators provide the IEC 60559 add, subtract, multiply, and divide operations.

If Intel C compiler under non-strict floating-point models does not conform to the specifications in the Annex F, then for which purpose it defines __STDC_IEC_559__ to 1?

 

 

Viet_H_Intel
Moderator
650 Views

I see what you meant. icc somehow always defines this macro whereas gcc isn't.

Let me work with our Front End team and get back to you.


Thanks,


Viet_H_Intel
Moderator
642 Views

Looks like there is an issue on how icc defines _STDC_IEC_559__.

I've reported this bug to our Front End team and will keep you updated once I hear from them.


Thanks,



Reply