https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99728
--- Comment #4 from Matthias Kretz (Vir) <kretz at kde dot org> --- FWIW, using std::experimental::native_simd<double> also does not hoist the stores out of the loop. However, if you pass d by value and return d, the issue goes away. So I guess this is an aliasing pessimization. Even though you added __restrict__. In any case __m256 has the problem that it is declared with the may_alias attribute. I recommend to just never use __m256 unless you have no other choice. Note that `s0data_s<__m256d>` warns "ignoring attributes on template argument '__m256d' [-Wignored-attributes]", meaning it drops the may_alias attribute. Reduced test case (https://godbolt.org/z/PW98Wsfoj): #include <immintrin.h> struct Tvsimple { __m256d v; }; struct s0data_s { Tvsimple lam1, lam2; }; struct s0data_s_intrin { __m256d lam1, lam2; }; template <typename T> void foo(T &__restrict__ d, size_t l, size_t lmax) { while (l <= lmax) { d.lam1 = d.lam2; l += 2; } } // hoists load out of the loop but loops over the store template void foo<>(s0data_s &__restrict__ d, size_t l, size_t lmax); // turns loop into a single branch template void foo<>(s0data_s_intrin &__restrict__ d, size_t l, size_t lmax);