Я нарушаю строгие правила псевдонимов?
Я хотел бы знать, нарушаю ли я строгие правила сглаживания с помощью этого фрагмента. (Я так думаю, так как это разыгрывает планетарный указатель, однако это делается в одном выражении и /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];
?