5

Is something like

__m128 a = something;
__m128i b = reinterpret_cast<__m128i>(a);

safe or undefined? If it is undefined, will it at least work on all of the major compilers (gcc,clang,msvc,icc)? I tested it on my computer with gcc and it works, but I'm not sure if its portable. I know that I can use _mm_castps_si128(), but because of templates, the first way happens to be more convenient.

BadProgrammer99
  • 759
  • 1
  • 5
  • 13
  • You should probably include a compiler tag. MSVC states you should [never access __m128i directly](https://msdn.microsoft.com/en-us/library/26232t5c.aspx) for example. I don't know you are using MSVC, but their docs are pretty clear on that matter (and the same for __m128 I suspect). – Yakk - Adam Nevraumont Jul 06 '18 at 20:18
  • @Yakk-AdamNevraumont What exactly would "access" entail? Anything other than using the intrinsics? – BadProgrammer99 Jul 06 '18 at 22:31
  • 1
    Isn't that about the fields *of* `__m128i`? Eg `b.m128i_i16[0]`. In MSVC it's unioned with arrays of scalars that you could access. But that's unrelated to this question. – harold Jul 06 '18 at 22:57

2 Answers2

4

No it's not portable and the behavior is undefined; __m128 is for float and __m128i is for integer types, these are not compatible types.

In fact, it doesn't even compile in MSVC 2017:

error C2440: 'reinterpret_cast': cannot convert from '__m128' to '__m128i'

Use the cast intrinsic:

__m128 a = something;
__m128i b = _mm_castps_si128(a);
rustyx
  • 80,671
  • 25
  • 200
  • 267
  • To cast between ``_m128`` and ``_m128i``, the casting intrinsics is the correct solution. That said, you can do things like ``reinterpret_cast<__m128i*>(/* address of __m128 data in memory */)`` when dealing with pointers to the SSE data types. It is possible to cast to a ``float*`` as well, but be careful with the reverse since ``__m128*`` requires 16-byte aligned memory. See [DirectXMath](https://github.com/Microsoft/DirectXMath) – Chuck Walbourn Jul 07 '18 at 16:26
  • Related re: casting pointers like `(__m128*)`: [Is \`reinterpret\_cast\`ing between hardware SIMD vector pointer and the corresponding type an undefined behavior?](https://stackoverflow.com/q/52112605) - yes, it's the same as an alignment-required `_mm_load_si128`, rather than `loadu`. – Peter Cordes Jan 23 '22 at 23:23
0

An integer type may be reinterpret_cast-ed to a pointer, a reference, or its own type.

Therefore, casting between two integer types is only well-defined if the compiler considers them to be the same type.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180