В этом вопросе есть три ошибки (не из-за того, что голосование "против", типа "вам не хватает понимания" ... поэтому, я думаю, вы пришли сюда).
1) Вы спрашиваете о конкретной проблеме реализации (с использованием SSE2), а не о стандарте. Вы ответили на свой вопрос: «Переполнение целого числа со знаком в C не определено».
2) Когда вы имеете дело с встроенными функциями c, вы даже не программируете на C! Это вставка инструкций по сборке в строку. Он делает это каким-то переносимым способом, но уже неверно, что ваши данные представляют собой целое число со знаком. Это векторный тип, передаваемый встроенной функции SSE. Затем ВЫ преобразовываете это в целое число и говорите C, что хотите увидеть результат этой операции. Какие бы байты ни были при приведении, вы увидите их, и это не имеет ничего общего со знаковой арифметикой в стандарте C.
3) Было всего два неверных предположения. Я сделал предположение о количестве ошибок и ошибся.
Все немного иначе, если компилятор вставляет инструкции SSE (скажем, в цикле). Теперь компилятор гарантирует, что результат такой же, как и для 32-битной операции со знаком ... ЕСЛИ не существует неопределенного поведения (например, переполнения), и в этом случае он может делать все, что захочет.
Также обратите внимание, что undefined не означает неожиданность ... любое поведение, которое вы наблюдаете для автоматической векторизации, может быть согласованным и повторяемым (возможно, оно всегда переносится на вашем компьютере ... это может быть не верно для всех случаев для окружающего кода, или все компиляторы. Или, если компилятор выбирает разные инструкции в зависимости от доступности SSSE3, SSE4 или AVX *, возможно, даже не все процессоры, если он делает разные варианты генерации кода для разных наборов инструкций, которые используют или не используют преимущества подписанного переполнение UB).
РЕДАКТИРОВАТЬ:
Хорошо, теперь, когда мы спрашиваем о «стандартах Intel» (которых не существует, я думаю, вы имеете в виду стандарты x86), я могу кое-что добавить к своему ответу. Все немного запутано.
Во-первых, внутренний _mm_add_epi32 определяется Microsoft для соответствия определению Intel intrinsics API (https://software.intel.com/sites/landingpage/IntrinsicsGuide/ и внутренние примечания в руководствах Intel по сборке x86). Они ловко определяют это как выполнение __m128i
того же действия, что и инструкция x86 PADDD
с регистром XMM, без дальнейшего обсуждения (например, это ошибка компиляции на ARM или ее следует эмулировать?).
Во-вторых, PADDD - это не только подписанное дополнение! Это 32-битное двоичное сложение. x86 использует дополнение до двух для целых чисел со знаком, и их добавление является той же бинарной операцией, что и беззнаковое основание 2. Так что да, paddd
гарантированно переносится. Здесь есть хорошая ссылка на все инструкции x86, здесь.
Итак, что это означает: опять же, предположение в вашем вопросе ошибочно, потому что нет даже переполнения. Таким образом, результат, который вы видите, должен быть определен поведением. Обратите внимание, что он определяется Microsoft и x86 (а не стандартом C).
Другие компиляторы x86 также реализуют API встроенных функций Intel таким же образом, поэтому _mm_add_epi32
гарантированно переносится только на перенос.
person
dave
schedule
22.10.2014
__mi128i
(очевидно) является архитектурно-зависимой концепцией, поэтому стандарты C и C ++ ничего не говорят о типе, его поведении или внутреннем элементе. Вам необходимо изучить документацию поставщика, чтобы узнать о каких-либо гарантиях сверх того, что дают стандарты. - person CB Bailey   schedule 23.10.2014paddd
(который обертывает), я не уверен, сколько гарантии, которое должно дать, хотя - person harold   schedule 23.10.2014_mm_add_epi32
никогда не будет эмулироваться простыми оболочками C. - person that other guy   schedule 23.10.2014paddd
обернуть. - person harold   schedule 23.10.2014_mm_add_epi32()
лицензии, чтобы давать результаты, отличные отPADDD
. - person Ben Voigt   schedule 23.10.2014