Fix #3863: Correct _mm_shuffle_pd immediate decoding and add tests
- Fixed _mm_shuffle_pd to use 1-bit selector fields instead of 2-bit fields - The intrinsic now correctly interprets the immediate as two 1-bit selectors (one for each output lane) instead of treating it like _mm_shuffle_ps - Added LIT test covering all four shuffle masks: (0,0), (0,1), (1,0), (1,1) - Added functional test to verify runtime correctness - Updated copyright year to 2026 Co-authored-by: aneshlya <aneshlya@users.noreply.github.com>
This commit is contained in:
committed by
aneshlya
co-authored by
aneshlya
parent
f6fed70a43
commit
122ade2f96
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2010-2025, Intel Corporation
|
||||
Copyright (c) 2010-2026, Intel Corporation
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@@ -569,8 +569,8 @@ static inline unmasked uniform int _mm_movemask_pd(uniform __m128d _A) {
|
||||
|
||||
static inline unmasked uniform __m128d _mm_shuffle_pd(uniform __m128d _A, uniform __m128d _B, uniform unsigned int _I) {
|
||||
uniform double<2> _R;
|
||||
_R[0] = _A.m128d_f64[_I & 0x3];
|
||||
_R[1] = _B.m128d_f64[(_I >> 2) & 0x3];
|
||||
_R[0] = _A.m128d_f64[_I & 0x1];
|
||||
_R[1] = _B.m128d_f64[(_I >> 1) & 0x1];
|
||||
return *((uniform __m128d * uniform) & _R);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2026, Intel Corporation
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Test for _mm_shuffle_pd SSE2 intrinsic correctness (#3863)
|
||||
// This runtime test verifies that _mm_shuffle_pd correctly uses 1-bit selector
|
||||
// fields for each output lane, not 2-bit fields like _mm_shuffle_ps.
|
||||
//
|
||||
// RUN: %{ispc} %s -o %t.o
|
||||
// RUN: %{cc} %S/../test_static.c %t.o -o %t.exe
|
||||
// RUN: %t.exe
|
||||
//
|
||||
// REQUIRES: X86_ENABLED
|
||||
|
||||
#include "../test_static.isph"
|
||||
#include "intrinsics/emmintrin.isph"
|
||||
|
||||
// Test all four possible shuffle masks: (0,0), (0,1), (1,0), (1,1)
|
||||
// _MM_SHUFFLE2(x, y) produces ((x << 1) | y)
|
||||
// Expected behavior:
|
||||
// result[0] = A[y]
|
||||
// result[1] = B[x]
|
||||
|
||||
task void f_v(uniform float RET[]) {
|
||||
uniform __m128d a = _mm_setr_pd(1.0, 2.0);
|
||||
uniform __m128d b = _mm_setr_pd(3.0, 4.0);
|
||||
|
||||
// Test 1: _MM_SHUFFLE2(0, 0) = 0: select A[0], B[0] -> {1.0, 3.0}
|
||||
uniform __m128d r0 = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(0, 0));
|
||||
uniform double result0[2];
|
||||
*((uniform __m128d * uniform)result0) = r0;
|
||||
RET[0] = (result0[0] == 1.0 && result0[1] == 3.0) ? 1.0 : 0.0;
|
||||
|
||||
// Test 2: _MM_SHUFFLE2(0, 1) = 1: select A[1], B[0] -> {2.0, 3.0}
|
||||
uniform __m128d r1 = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(0, 1));
|
||||
uniform double result1[2];
|
||||
*((uniform __m128d * uniform)result1) = r1;
|
||||
RET[1] = (result1[0] == 2.0 && result1[1] == 3.0) ? 1.0 : 0.0;
|
||||
|
||||
// Test 3: _MM_SHUFFLE2(1, 0) = 2: select A[0], B[1] -> {1.0, 4.0}
|
||||
uniform __m128d r2 = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(1, 0));
|
||||
uniform double result2[2];
|
||||
*((uniform __m128d * uniform)result2) = r2;
|
||||
RET[2] = (result2[0] == 1.0 && result2[1] == 4.0) ? 1.0 : 0.0;
|
||||
|
||||
// Test 4: _MM_SHUFFLE2(1, 1) = 3: select A[1], B[1] -> {2.0, 4.0}
|
||||
uniform __m128d r3 = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(1, 1));
|
||||
uniform double result3[2];
|
||||
*((uniform __m128d * uniform)result3) = r3;
|
||||
RET[3] = (result3[0] == 2.0 && result3[1] == 4.0) ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
task void result(uniform float RET[]) {
|
||||
// All tests should pass (return 1.0)
|
||||
RET[0] = 1.0;
|
||||
RET[1] = 1.0;
|
||||
RET[2] = 1.0;
|
||||
RET[3] = 1.0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2026, Intel Corporation
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Test for _mm_shuffle_pd SSE2 intrinsic correctness (#3863)
|
||||
// This test verifies that _mm_shuffle_pd correctly uses 1-bit selector fields
|
||||
// for each output lane, not 2-bit fields like _mm_shuffle_ps.
|
||||
//
|
||||
// RUN: %{ispc} %s --target=sse2-i32x4 --emit-llvm-text --nostdlib -o - | FileCheck %s
|
||||
// RUN: %{ispc} %s --target=sse4-i32x4 --emit-llvm-text --nostdlib -o - | FileCheck %s
|
||||
// RUN: %{ispc} %s --target=avx1-i32x4 --emit-llvm-text --nostdlib -o - | FileCheck %s
|
||||
// RUN: %{ispc} %s --target=avx2-i32x8 --emit-llvm-text --nostdlib -o - | FileCheck %s
|
||||
|
||||
// REQUIRES: X86_ENABLED
|
||||
|
||||
#include "intrinsics/emmintrin.isph"
|
||||
|
||||
// Test all four possible shuffle masks: (0,0), (0,1), (1,0), (1,1)
|
||||
// _MM_SHUFFLE2(x, y) produces ((x << 1) | y)
|
||||
// Expected behavior:
|
||||
// result[0] = A[y]
|
||||
// result[1] = B[x]
|
||||
|
||||
export void test_shuffle_pd_00() {
|
||||
uniform __m128d a = _mm_setr_pd(1.0, 2.0);
|
||||
uniform __m128d b = _mm_setr_pd(3.0, 4.0);
|
||||
// _MM_SHUFFLE2(0, 0) = 0: select A[0], B[0] -> {1.0, 3.0}
|
||||
uniform __m128d r = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(0, 0));
|
||||
// CHECK-LABEL: @test_shuffle_pd_00
|
||||
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 0, i32 2>
|
||||
}
|
||||
|
||||
export void test_shuffle_pd_01() {
|
||||
uniform __m128d a = _mm_setr_pd(1.0, 2.0);
|
||||
uniform __m128d b = _mm_setr_pd(3.0, 4.0);
|
||||
// _MM_SHUFFLE2(0, 1) = 1: select A[1], B[0] -> {2.0, 3.0}
|
||||
uniform __m128d r = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(0, 1));
|
||||
// CHECK-LABEL: @test_shuffle_pd_01
|
||||
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 1, i32 2>
|
||||
}
|
||||
|
||||
export void test_shuffle_pd_10() {
|
||||
uniform __m128d a = _mm_setr_pd(1.0, 2.0);
|
||||
uniform __m128d b = _mm_setr_pd(3.0, 4.0);
|
||||
// _MM_SHUFFLE2(1, 0) = 2: select A[0], B[1] -> {1.0, 4.0}
|
||||
uniform __m128d r = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(1, 0));
|
||||
// CHECK-LABEL: @test_shuffle_pd_10
|
||||
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 0, i32 3>
|
||||
}
|
||||
|
||||
export void test_shuffle_pd_11() {
|
||||
uniform __m128d a = _mm_setr_pd(1.0, 2.0);
|
||||
uniform __m128d b = _mm_setr_pd(3.0, 4.0);
|
||||
// _MM_SHUFFLE2(1, 1) = 3: select A[1], B[1] -> {2.0, 4.0}
|
||||
uniform __m128d r = _mm_shuffle_pd(a, b, _MM_SHUFFLE2(1, 1));
|
||||
// CHECK-LABEL: @test_shuffle_pd_11
|
||||
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 1, i32 3>
|
||||
}
|
||||
Reference in New Issue
Block a user