Я нарушаю строгие правила псевдонимов?

Я хотел бы знать, нарушаю ли я строгие правила сглаживания с помощью этого фрагмента. (Я так думаю, так как это разыгрывает планетарный указатель, однако это делается в одном выражении и /Wall не плачет.)

inline double plop() const // member function
{
    __m128d x = _mm_load_pd(v);
    ... // some stuff
    return *(reinterpret_cast<double*>(&x)); // return the lower double in xmm reg referred to by x.
}

Если да, какое обходное решение? Использование разных представлений одновременно становится хардкорным, если вы хотите уважать спецификацию.

Спасибо за ваши ответы, я теряю свое хорошее настроение, пытаясь найти решение.

Ответы, которые не будут приняты и почему:

"use mm_store" → Оптимизатор не может удалить его, если следующие инструкции требуют регистра xmm, поэтому он генерирует нагрузку сразу после нее. Хранить + загружать ничего.

"use union" → Нарушение правила слияния, если используется два типа для одного и того же объекта. Если я хорошо понял статью, написанную Тьяго Масиейрой.

Ответ 1

Существует только одна внутренняя черта, которая "извлекает" двойное значение нижнего порядка из регистра xmm:

double _mm_cvtsd_f64 (__m128d a)

Вы можете использовать его следующим образом:

return _mm_cvtsd_f64(x);

Существует некоторое противоречие между различными ссылками. MSDN говорит: This intrinsic does not map to any specific machine instruction. Хотя встроенный гид Intel упоминает инструкцию movsd. В последнем случае эта дополнительная инструкция легко устраняется оптимизатором. По меньшей мере gcc 4.8.1 с флагом -O2 генерирует код без дополнительной инструкции.

Ответ 2

Точка маркера, выделенная жирным шрифтом, должна, я думаю, разрешить ваш приведение здесь, так как мы можем рассматривать __m128d как совокупность четырех double union для полного регистра. Что касается строгого сглаживания, то компилятор всегда был очень примирен вокруг объединения, где в начале координат предполагалось, что допустим только актер (char *).

§3.10: Если программа пытается получить доступ к сохраненному значению объекта через glvalue другого, чем один из следующих типов, поведение undefined (Цель этого списка - указать те обстоятельства, при которых объект может или не может быть сглажен):

  • динамический тип объекта,
  • cv-квалифицированная версия динамического типа объекта,
  • тип, аналогичный (как определено в 4.4) для динамического типа объекта,
  • тип, который является подписанным или неподписанным типом, соответствующим динамическому типу объекта,
  • тип, который является подписанным или неподписанным типом, соответствующим квитанционной версии динамического типа объекта,
  • тип агрегата или объединения, который включает один из вышеупомянутых типов среди его элементов или нестатических членов данных (включая, рекурсивно, элемент или нестатический элемент данных субагрегата или содержащий союз),
  • тип, который является (возможно, cv-квалифицированным) типом базового класса динамического типа объекта,
  • a char или неподписанный char тип.

Ответ 3

Да, я думаю, что это нарушает строгий псевдоним. Однако на практике это нормально. (Я в основном пишу это как ответ, потому что трудно описать в комментарии)

Но вместо этого вы можете сделать что-то вроде этого:

inline double plop() const // member function
{
    __m128d x = _mm_load_pd(v);
    ... // some stuff

    union {
        unsigned long long i; // 64-bit int
        double             d; // 64-bit double
    };

    i = _mm_cvtsi128_si64(_mm_castpd_si128(x)); // _mm_castpd_si128 to interpret the register as an int vector, _mm_cvtsi128_si64 to extract the lowest 64-bits

    return d; // use the union to return the value as a double without breaking strict aliasing
}

Ответ 4

Как насчет return x.m128d_f64[0];?