11

Passing aligned types or structures with aligned types by value doesn't work with some implementations. This breaks STL containers, because some of the methods (such as resize) take their arguments by value.

I run some tests with Visual Studio 2008 and not entirely sure when and how pass by value fails. My main concern is function foo. It seems to work fine, but could it be a result of inlining or some other coincidence? What if I change its signature to void foo(const __m128&)?

Your input is greatly appreciated. Thank you.

struct A
{
    __m128 x;
    int n;
};

void foo(__m128);
void bar(A);

void f1()
{
    // won't compile
    // std::vector<A> vec1(3);

    // compiles, but fails at runtime when elements are accessed
    std::vector<__m128> vec2(3);

    // this seems to work. WHY???
    std::vector<__m128, some_16_byte_aligned_allocator<__m128> > vec3(3);

    __m128 x;
    A a;

    // passed by value, is it OK?
    foo(x);

    // won't compile
    //bar(a);
}

EDIT. STL fails even with aligned allocator, because pass by value problem remains.

Found this link pass __m128 by value

Laurent Parenteau
  • 2,516
  • 20
  • 31
watson1180
  • 2,015
  • 1
  • 18
  • 24
  • What are the compile errors/warnings you're getting? I assume something like "formal parameter ... won't be aligned"? – celion Dec 13 '10 at 00:31
  • This is what I get. error C2719: 'unnamed-parameter': formal parameter with __declspec(align('16')) won't be aligned – watson1180 Dec 13 '10 at 00:43
  • In x64, function arguments support 16-byte alignment, so this problem goes away. I know that doesn't solve your immediate problem, but hey, it's marginally better than nothing. ;) – jalf Dec 13 '10 at 05:44
  • It turns out that passing __m128 by value is OK. Follow the web link. – watson1180 Dec 13 '10 at 07:26
  • What sort of busted compiler "supports" a type for which it can't actually satisfy the alignment requirements? – Stephen Canon Dec 13 '10 at 07:46
  • @Stephen Canon. GCC is affected too. You can't store structures with aligned members in STL containers. Could it be related to hardware design? – watson1180 Dec 13 '10 at 14:41
  • @watson1180 -- what does an STL container do with 32- or 64-bit members on platforms where the hardware doesn't support misaligned access? – Stephen Canon Dec 13 '10 at 20:02
  • @Stephen Canon. Only passing by value is problematic. Stored objects are always properly aligned. For some strange reason, resize method takes its argument by value. If you open STL header file and change pass by value into pass by const reference, the problem will go away. AFAIK, it shouldn't break anything. – watson1180 Dec 14 '10 at 02:09

2 Answers2

2

I think the only safe way to do this in general is to pass by reference. Some platforms (e.g. Xbox 360) support passing vector arguments in registers, but I don't think this is possible on x86.

For the std::vector case, you'll need to make sure that the memory allocated is aligned to 16 bytes; otherwise you'll get crashes when you try to perform most operations on unaligned vectors.

If you're supporting multiple platforms, a safe plan is to use a typedef e.g.

typedef const MyVector& MyVectorParameter;

You can then change the typedef on platforms that support vector pass-by-value.

celion
  • 3,864
  • 25
  • 19
1

the oftenly used resize() function is causing all the alignment and perhaps you can try to specialise vector template for __m128 ?

YeenFei
  • 3,180
  • 18
  • 26