1

I'm using Apple GCC 4.2.1 and I've stumbled upon a strange problem with the following code... I always get EXC_BAD_ACCESS exception when trying to initialize __m128 class member variable. Unfortunately the following simplified code works in a test application, but maybe you can still help me locate the root of this problem?

I fail to understand the reason behind EXC_BAD_ACCESS exception - __m128 type is not a pointer and all other MyClass members are initialized and accessed without any problems, there are no signs of stack / heap corruption, everything works if I use local variables and there are no problems under MSVC... Maybe something is wrong with alignment?

Please help!

class MyClass
{
    public:
    // lots of members
    __m128 vect;

    MyClass()
    {
        vect = _mm_setr_ps (0.f, 0.f, 0.f, 10.0f); // Program received signal: “EXC_BAD_ACCESS”.
    }

    void iniialize()
    {
        __m128 localVector = _mm_setr_ps (0.f, 0.f, 0.f, 10.0f); // No problems
        vect = localVector; // Program received signal: “EXC_BAD_ACCESS”.
    }
};
Ryan
  • 1,451
  • 2
  • 27
  • 36
  • Thank you, Sehe and Paul! However, specifying 16 bytes alignment solved nothing :( Please tell me, what else may cause this problem? – Ryan Jun 23 '11 at 12:44
  • Are you creating an instance of the class on the stack or via `new` ? If you are using `new` then did you override it to use e.g. `posix_memalign` ? Set a breakpoint at each of the the vect assignments and check the alignment (the vect member should have a hex address ending in 0). – Paul R Jun 23 '11 at 16:20

3 Answers3

2

From the top of my mind: i'd say alignment issues

Especially, the part where it says 'lot's of members'

Look at __attribute__ aligned

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Sehe, you are confirming my worst nightmares... In MSVC project the 16 bytes alignment is forced, but I wasn't able to find a way to do this in GCC and I'm afraid I'd die from manually adding the alignment attributes to all __m128 members and their wrappers in thousands of source files... Maybe I'm missing something, maybe there is some other way? – Ryan Jun 23 '11 at 10:07
  • You could apply the same gcc attribute to the __m128 type. I suspect that involves editing the Windows header file, but it should work. – Alan Stokes Jun 23 '11 at 10:30
  • I'm sure Google `gcc +"__m128"` would uncover better tips here than mine. For now i think you can typedef say `aligned_m128`, if you care into a namespace. You shouldn't overload the _reserved identifier_ `__m128` so you'd need to use a preprocessor macro to avoid having to change your code – sehe Jun 23 '11 at 11:19
  • I fixed the problem by applying the __attribute__ aligned to the whole class, because using it only for __m128 members didn't align them properly. – Ryan Jun 29 '11 at 09:08
0

gcc will automatically align __m128 members correctly if the object is created on the stack, but for objects allocated via new you are at the mercy of the memory allocator, which is typically only 8 byte aligned on Linux. You may need to override operator new for your class so that it calls posix_memalign so that you always get 16 byte aligned objects.

Having said that, if you're getting into SSE code optimisation then you may want to re-evaluate how you do the coding - since performance is usually the motivation for SIMD optimisation you may want to work at a somewhat lower level than C++ classes - typically you just want to operate homogeneously on big chunks of contiguous data, i.e. 1D or 2D arrays.

Paul R
  • 208,748
  • 37
  • 389
  • 560
0

If stack misalignment is the problem, you should check the -mstackrealign command line option, see GCC documentation. This solved my issues on MinGW target. See also the discussion on stack alignment. Finally, you might want to update GCC to a newer version.

On the other hand, if you allocate objects dynamically, you must make sure that the memory is aligned, as Paul noted. There are methods like _mm_malloc and _mm_free that can help you with that.

Community
  • 1
  • 1
Norbert P.
  • 2,767
  • 1
  • 18
  • 22