Jump to content
  • Advertisement
Sign in to follow this  
janta

Alignment issue, SSE, etc.

This topic is 4525 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Please consider the following code:
typedef struct __declspec(intrin_type) __declspec(align(16)) {
	float       m128_f32[4];
} __myOwn128;

void Test(__m128 param) {} // Compiles just fine. WHY ?

void Test2(__myOwn128 param) {} // error C2719: 'param': formal parameter with __declspec(align('16')) won't be aligned --> I understand that

I don't understand why Test compiles and Test2 does not. (Actually, I am surprised that Test does compile) Anyone could enlight me please ? (And as a side question, what does __declspec(intrin_type) means ? I couldn't fint that documented anywhere, I just copy'n'pasted it from the original __m128 typedef in xmmintrin.h) Cheers, JA

Share this post


Link to post
Share on other sites
Advertisement
I think I have been fooled by both the debugger and the file xmmintrin.h that let me believe that __m128 was just a mere struct mapped into a sse register.

After a couple more tests I found out that the following would compile:

struct __declspec(intrin_type) __declspec(align(16)) __m128 {
float m128_f32[4];
};

int Test(__m128 v)
{
return 0;
}


but that the following wouldn't (just changed 128 to 127...)


struct __declspec(intrin_type) __declspec(align(16)) __m127 {
float m128_f32[4];
};

// error C2719: 'v': formal parameter with __declspec(align('16')) won't be aligned
int Test(__m127 v)

{
return 0;
}


Looks like the token "__m128" is processed by the compiler as a built-in type that still needs to be declared (unlike int and such) and that can be redefined too...

Share this post


Link to post
Share on other sites
Quote:
Original post by janta
Looks like the token "__m128" is processed by the compiler as a built-in type that still needs to be declared (unlike int and such) and that can be redefined too...


I don't think that's the case. It seems that it is struct that's blocking the compiler's cleverness... for whatever reason.

typedef __m128 orig;
typedef float __declspec(align(16)) arr[4];
typedef __declspec(align(16)) struct str {
float x[4];
};

int test_orig(orig m) { return 0; }; // ok
int test_arr(arr m) { return 0; }; // ok
int test_str(str m) { return 0; }; // C2719:



Passing aligned types by value is a common problem, especially when using std::vector (resize() won't compile). Hint: don't do that.

Unfortunately, returning aligned types by value could be buggy as well (sample) - although it happens rarely so it can be avoided.

Share this post


Link to post
Share on other sites
Looking at the docs for C2719 (you did do that right?) it says very explicity that your can't pass __declspec(align) variables as function parameters. That fact that you found a case where it "worked" is probably a compiler bug or some special case.

As to why it wouldn't be allowed, you'll have to ask MS, everything else is just speculation. My guess is that would be annoying to implement for little real value.

Share this post


Link to post
Share on other sites
__declspec(intrin_type) isn't documented because it's not supposed to be used except in MS headers declaring intrinsic types that have built in compiler support. There's no way to get the same behaviour out of your own arbitrary types as the built in __m128 type. The compiler understands those special intrinsic types and can pass them in registers and can maintain correct alignment. You should just use the compiler declared types rather than trying to declare them yourself. You can use them as data members and wrap them in your own class if you want a different interface, though you should be aware that doing so could lead to less optimal code and check the assembly that gets generated if performance is critical.

Share this post


Link to post
Share on other sites
Quote:
Original post by mattnewport
__declspec(intrin_type) isn't documented because it's not supposed to be used except in MS headers declaring intrinsic types that have built in compiler support. There's no way to get the same behaviour out of your own arbitrary types as the built in __m128 type. The compiler understands those special intrinsic types and can pass them in registers and can maintain correct alignment. You should just use the compiler declared types rather than trying to declare them yourself. You can use them as data members and wrap them in your own class if you want a different interface, though you should be aware that doing so could lead to less optimal code and check the assembly that gets generated if performance is critical.


Thanks for that reply, pretty much what as I expected. Btw I am not trying to redeclare my own stuff, I was just trying to find out why the compiler would not complain when a function such as _mm_add_ps received a __m128 parameter which is _declspec(align(16))'ed, while he would complain when another function receiving any aligned parameter.

Thanks a lot.
JA

Share this post


Link to post
Share on other sites
Quote:
Original post by janta
Please consider the following code:

typedef struct __declspec(intrin_type) __declspec(align(16)) {
float m128_f32[4];
} __myOwn128;

void Test(__m128 param) {} // Compiles just fine. WHY ?

void Test2(__myOwn128 param) {} // error C2719: 'param': formal parameter with __declspec(align('16')) won't be aligned --> I understand that




JA


try

void Test2(const __myOwn128& param) {};

it should compile and run

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!