Is SSE2 an undefined integer overflow character?

Signed undefined integer overflow in C and C ++. But what about signed integer overflow on separate fields __m128i

? In other words, is this behavior defined in Intel standards?

#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <emmintrin.h>

union SSE2
{
    __m128i m_vector;
    uint32_t m_dwords[sizeof(__m128i) / sizeof(uint32_t)];
};

int main()
{
    union SSE2 reg = {_mm_set_epi32(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX)};
    reg.m_vector = _mm_add_epi32(reg.m_vector, _mm_set_epi32(1, 1, 1, 1));

    printf("%08" PRIX32 "\n", (uint32_t) reg.m_dwords[0]);
    return 0;
}

      

[myria@polaris tests]$ gcc -m64 -msse2 -std=c11 -O3 sse2defined.c -o sse2defined
[myria@polaris tests]$ ./sse2defined
80000000

      

Note that fields of 4 bytes SSE2 __m128i

are considered signed.

+3


source to share


2 answers


There are three things about this question: not ok, but how you "don't understand", so I think you came here).

1) You are asking a question about a specific implementation issue (using SSE2), not a standard. You answered your question, "Integer undefined chain overflow in C".

2) When you're dealing with c intrinsics, you don't even program in C! They insert assembly instructions into the line. It does it in some portable way, but it's no longer that your data is integers. This is the vector passed to the SSE command. Then you cast that at an integer and tell C that you want to see the result of this operation. Whatever bytes are there when you cast, this is what you'll see and has nothing to do with signed arithmetic in the C standard.

3) There were only two wrong assumptions. I made an assumption about the number of errors and was wrong.

Things are slightly different if the compiler enters SSE instructions (say in a loop). The compiler now guarantees that the result is the same as the signed 32-bit operation ... IF there is undefined behavior (like overflow), in which case it can do whatever it likes.

Note also that undefined does not mean unexpected ... any behavior that your observer might be consistent and repeatable (it might always wrap your machine ... it might not be true for all compilers, or even all processors ... even all processors that implement SSE instructions).



EDIT:

Ok, now when we ask about "Intel standards" (which don't exist, I think you mean x86 standards), I may add something to my answer. Things are a little confusing.

First, the _mm_add_epi32 command is not defined by Intel, but Microsoft . They cleverly define it as an x86 PADD instruction without discussing it (for example, is it a compilation error on ARM or should it be simulated?).

Secondly, PADD is not a subscription add-on! This is a 32 bit addon. For all x86 instructions are there .

So what does this mean: again, the assumption in your question is wrong, because there isn't even overflow. Therefore, the output you see must be behavior driven. Note that it is defined by Microsoft and x86 (not the C or Intel standard).

+6


source


This is not an "integer overflow in fields __m128i

". This is a function call. (Being an inline compiler is just an optimization, very similar to inlining, and which does not interact with the C standard if the as-if rule is followed)



Its behavior must conform to the contract (preconditions, postconditions) that the function developer has documented. Usually intrinsics are documented by the compiler vendor, although they tend to coordinate the naming and contract of built-in functions to help port code.

+2


source







All Articles