Should SSE data types be passed around or created for each operation?
===

I'm currently trying my hand at making my own C++ vector math library and I'm interested in optimizing it with SSE. For my vec2 and vec3 data types I can't store the __m128 type directly since they have to be their expected sizes, but what about vec4? Suppose my vec4 type looks something like this (ignoring 16-byte alignment requirement for simplicity of discussion):

    union vec4 {
      struct {float x, y, z, w;};
      __m128 sse;
    }

    vec4 operator+(const vec4& left, const vec4& right) {
      vec4 result;
      result.sse = _mm_add_ps(left.sse, right.sse);
      return result;
    }

Is that the suggested way to do it or is there some big reason not to I can't think of? I.e., should I do this instead:

    struct vec4 {
      float x, y, z, w;
    };

    vec4 operator+(const vec4& left, const vec4& right) {
      __m128 leftSSE = _mm_load_ps(reinterpret_cast<const float*>(&left));
      __m128 rightSSE = _mm_load_ps(reinterpret_cast<const float*>(&right));
      __m128 resultSSE = _mm_add_ps(leftSSE, rightSSE);
      vec4 result;
      _mm_store_ps(reinterpret_cast<float*>(&result), resultSSE);
      return result;
    }

And while we're at it, what about my theoretical vec2 and vec3 types? Would it be faster to convert them to vec4 first and then use SIMD instructions or just handle their scalar elements individually?