كيف يمكنك ملء سجل X86 XMM مع 4 عوامات متطابقة من إدخال تسجيل XMM آخر؟
-
19-09-2019 - |
سؤال
أحاول تنفيذ بعض المجمع المضمن (في كود C / C ++) للاستفادة من SSE. أرغب في نسخ وقيم مكررة (من سجل XMM أو من الذاكرة) إلى سجل XMM آخر. على سبيل المثال، لنفترض أن لدي بعض القيم {1، 2، 3، 4} في الذاكرة. أرغب في نسخ هذه القيم بحيث يتم ملء xmm1 ب {1 و 1 و 1 و 1} و xmm2 مع {2 و 2 و 2 و 2} وما إلى ذلك وما إلى ذلك.
بالنظر إلى أدلة Intel المرجعية، لم أستطع العثور على تعليمات للقيام بذلك. هل أحتاج فقط إلى استخدام مزيج من المباريات المتكررة وتدوير (عبر Pshufd؟)؟
المحلول
هناك طريقتان:
يستخدم
shufps
حصريا:__m128 first = ...; __m128 xxxx = _mm_shuffle_ps(first, first, 0x00); // _MM_SHUFFLE(0, 0, 0, 0) __m128 yyyy = _mm_shuffle_ps(first, first, 0x55); // _MM_SHUFFLE(1, 1, 1, 1) __m128 zzzz = _mm_shuffle_ps(first, first, 0xAA); // _MM_SHUFFLE(2, 2, 2, 2) __m128 wwww = _mm_shuffle_ps(first, first, 0xFF); // _MM_SHUFFLE(3, 3, 3, 3)
دع المترجم يختار أفضل طريقة باستخدام
_mm_set1_ps
و_mm_cvtss_f32
:__m128 first = ...; __m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
لاحظ أن الطريقة الثانية سوف تنتج رمز فظيع على MSVC، كما تمت مناقشته هنا, ، وسوف تنتج فقط 'xxxx' نتيجة لذلك، على عكس الخيار الأول.
أحاول تنفيذ بعض المجمع المضمن (في كود C / C ++) للاستفادة من SSE
هذا غير قابل للتحويل للغاية. استخدام جوهري.
نصائح أخرى
انقل المصدر إلى DEST السجل. استخدم "shufps" واستخدم فقط تسجيل المسجل الجديد مرتين ثم حدد القناع المناسب.
يبث المثال التالي قيم xmm2.x إلى xmm0.xyzw
MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
إذا كانت قيمك 16 بايت محاذاة في الذاكرة:
movdqa (mem), %xmm1
pshufd $0xff, %xmm1, %xmm4
pshufd $0xaa, %xmm1, %xmm3
pshufd $0x55, %xmm1, %xmm2
pshufd $0x00, %xmm1, %xmm1
إذا لم يكن الأمر كذلك، فيمكنك القيام بتحميل غير إجمالي، أو أربعة الأحمال العددية. على منصات أحدث، يجب أن يكون الحمل غير المعالج بشكل أسرع؛ على المنصات القديمة قد تفوز الأحمال العددية.
كما لاحظ الآخرون، يمكنك أيضا استخدام shufps
.