Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7943 Discussions

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

pmor
Beginner
2,649 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
15 Replies
DitiD_Intel
Moderator
2,618 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-reference/top/compiler-reference/compiler-options/compiler-option-details/floating-point-options/fp-model-fp.html


Thanks & Regards,

Ditipriya.


0 Kudos
pmor
Beginner
2,573 Views

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

0 Kudos
DitiD_Intel
Moderator
2,517 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.

 

 

0 Kudos
pmor
Beginner
2,490 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?

0 Kudos
pmor
Beginner
2,291 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".

0 Kudos
DitiD_Intel
Moderator
2,130 Views

Hi,


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


Thanks and Regards,

Ditipriya.


0 Kudos
Viet_H_Intel
Moderator
2,118 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,

 

 

 

0 Kudos
pmor
Beginner
2,102 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?

0 Kudos
Viet_H_Intel
Moderator
2,094 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__ ?

 

0 Kudos
pmor
Beginner
2,066 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

0 Kudos
Viet_H_Intel
Moderator
1,898 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,


0 Kudos
pmor
Beginner
1,859 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?

 

 

0 Kudos
Viet_H_Intel
Moderator
1,841 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,


0 Kudos
Viet_H_Intel
Moderator
1,833 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,



0 Kudos
Viet_H_Intel
Moderator
1,037 Views

Hi,

Classic Compiler (icc) will be end of life by end of 2023. Therefore, this issue won't be fixed in Classic Compiler. Please migrate to Intel oneAPI DPC++/C++ Compiler (icx).


We will close it as "will not fix"


Thanks,

Viet


0 Kudos
Reply