I'm using gcc-4.5.0-1 of MinGW with Intel x86.
When I execute the following test code with '-O -msse' compiler options, it
outputs the wrong value.
I'm expecting that v2.e[3] will be 7.0f.

And, when I exclude LINE_A, LINE_B, LINE_C or LINE_D as a comment, the program
outputs the expected value.

-- begin test code --
// g++ -O -msse test.cpp
typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
typedef float __v4sf __attribute__ ((__vector_size__ (16)));

extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__,
__artificial__))
_mm_set_ps (const float __Z, const float __Y, const float __X, const float __W)
{
  return __extension__ (__m128)(__v4sf){ __W, __X, __Y, __Z };
}

struct vec
{
        union {
                __m128 v;
                float  e[4];
        };

        static const vec & zero()
        {
                static const vec v = _mm_set_ps(0, 0, 0, 0);
                return v;
        }

        vec() {}
        vec(const __m128 & a) : v(a) {}

        operator const __m128&() const { return v; }
};

struct vec2
{
        vec _v1;
        vec _v2;

        vec2() {}
        vec2(const vec & a, const vec & b) : _v1(a), _v2(b) {}

        static vec2 load(const float * a)
        {
                return vec2(
                        __builtin_ia32_loadups(&a[0]),
                        __builtin_ia32_loadups(&a[4]));
        }

        const vec & v1() const { return _v1; }
        const vec & v2() const { return _v2; }
};

extern "C" {
        int* _errno(void);
        int  printf (const char*, ...);
}

inline bool test_assert( bool is_succeed, const char * file_name, int line_num
)
{
        if ( !is_succeed )
        {
                printf("error: %s(%d)\n", file_name, line_num);
                if ( *_errno() ) // LINE_A
                {
                        printf("errno: %d\n", *_errno());
                }
        }

        return is_succeed;
}

inline bool operator==(const vec & a, const vec & b)
{ return 0xf == __builtin_ia32_movmskps(__builtin_ia32_cmpeqps(a, b)); }

#define test(x, y) test_assert( (x)==(y), __FILE__, __LINE__ )

int main( int argc, char * argv[] )
{
        __attribute__((aligned(16))) float data[] =
        { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5 };

        float * p = &data[2];
        vec2 a;

        a = vec2::load(p);

        vec v1 = a.v1();
        vec v2 = a.v2();
        printf(
                "v1: %f, %f, %f, %f\n"
                "v2: %f, %f, %f, %f\n",
                v1.e[0], v1.e[1], v1.e[2], v1.e[3],
                v2.e[0], v2.e[1], v2.e[2], v2.e[3]);

        test(_mm_set_ps(11, 12, 13, 14), a.v1()); // LINE_B
        test(_mm_set_ps( 7,  8,  9, 10), a.v2()); // LINE_C

        a._v1 = vec::zero();

        test(_mm_set_ps(0, 0, 0, 0), a.v1()); // LINE_D

        return 0;
}
-- end test code --

-- begin output --
v1: 14.000000, 13.000000, 12.000000, 11.000000
v2: 10.000000, 9.000000, 8.000000, 0.000000
error: test.cpp(92)
-- end output --


-- 
           Summary: The variable of SSE will be broken
           Product: gcc
           Version: 4.5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: yottui at yahoo dot co dot jp


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44900

Reply via email to