Skip to content

Commit 50afa9f

Browse files
authored
Merge pull request #2191 from folkertdev/sse4a-compare-lower-quad
for sse4a functions compare only the lower quadword
2 parents 594ef8b + bd6e145 commit 50afa9f

1 file changed

Lines changed: 38 additions & 5 deletions

File tree

crates/core_arch/src/x86/sse4a.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ unsafe extern "unadjusted" {
2828
///
2929
/// If `length == 0 && index > 0` or `length + index > 64` the result is
3030
/// undefined.
31+
///
32+
/// The extracted bits are saved in the least-significant bit positions of the lower
33+
/// quadword of the destination; the remaining bits in the lower quadword of the
34+
/// destination register are cleared to 0. The upper quadword of the destination
35+
/// register is undefined.
3136
#[inline]
3237
#[target_feature(enable = "sse4a")]
3338
#[cfg_attr(test, assert_instr(extrq))]
@@ -43,7 +48,10 @@ pub fn _mm_extract_si64(x: __m128i, y: __m128i) -> __m128i {
4348
/// and index are both zero, bits `[63:0]` of parameter `x` are extracted. It is a compile-time error
4449
/// for `len + idx` to be greater than 64 or for `len` to be zero and `idx` to be non-zero.
4550
///
46-
/// Returns a 128-bit integer vector whose lower 64 bits contain the extracted bits.
51+
/// The extracted bits are saved in the least-significant bit positions of the lower
52+
/// quadword of the destination; the remaining bits in the lower quadword of the
53+
/// destination register are cleared to 0. The upper quadword of the destination
54+
/// register is undefined.
4755
#[inline]
4856
#[target_feature(enable = "sse4a")]
4957
#[cfg_attr(test, assert_instr(extrq, LEN = 5, IDX = 5))]
@@ -66,6 +74,8 @@ pub fn _mm_extracti_si64<const LEN: i32, const IDX: i32>(x: __m128i) -> __m128i
6674
///
6775
/// If the `length` is zero it is interpreted as `64`. If `index + length > 64`
6876
/// or `index > 0 && length == 0` the result is undefined.
77+
///
78+
/// The upper 64 bits of the destination are undefined.
6979
#[inline]
7080
#[target_feature(enable = "sse4a")]
7181
#[cfg_attr(test, assert_instr(insertq))]
@@ -80,6 +90,8 @@ pub fn _mm_insert_si64(x: __m128i, y: __m128i) -> __m128i {
8090
/// `idx` specifies the index of the LSB. `len` specifies the number of bits to insert. If length and index
8191
/// are both zero, bits `[63:0]` of parameter `x` are replaced with bits `[63:0]` of parameter `y`. It is a
8292
/// compile-time error for `len + idx` to be greater than 64 or for `len` to be zero and `idx` to be non-zero.
93+
///
94+
/// The upper 64 bits of the destination are undefined.
8395
#[inline]
8496
#[target_feature(enable = "sse4a")]
8597
#[cfg_attr(test, assert_instr(insertq, LEN = 5, IDX = 5))]
@@ -150,6 +162,11 @@ mod tests {
150162
use crate::core_arch::x86::*;
151163
use stdarch_test::simd_test;
152164

165+
// Normally this requires SSE2, but for tests it does not matter whether we use the instruction.
166+
fn _mm_cvtsi128_si64(a: __m128i) -> i64 {
167+
unsafe { simd_extract!(a.as_i64x2(), 0) }
168+
}
169+
153170
#[simd_test(enable = "sse4a")]
154171
fn test_mm_extract_si64() {
155172
let b = 0b0110_0000_0000_i64;
@@ -160,15 +177,23 @@ mod tests {
160177
let y = _mm_setr_epi64x(v, 0);
161178
let e = _mm_setr_epi64x(0b0110_i64, 0);
162179
let r = _mm_extract_si64(x, y);
163-
assert_eq_m128i(r, e);
180+
181+
// The upper quadword of the destination register is undefined.
182+
let r = _mm_cvtsi128_si64(r);
183+
let e = _mm_cvtsi128_si64(e);
184+
assert_eq!(r, e);
164185
}
165186

166187
#[simd_test(enable = "sse4a")]
167188
fn test_mm_extracti_si64() {
168189
let a = _mm_setr_epi64x(0x0123456789abcdef, 0);
169190
let r = _mm_extracti_si64::<8, 8>(a);
170191
let e = _mm_setr_epi64x(0xcd, 0);
171-
assert_eq_m128i(r, e);
192+
193+
// The upper quadword of the destination register is undefined.
194+
let r = _mm_cvtsi128_si64(r);
195+
let e = _mm_cvtsi128_si64(e);
196+
assert_eq!(r, e);
172197
}
173198

174199
#[simd_test(enable = "sse4a")]
@@ -185,7 +210,11 @@ mod tests {
185210
// ^idx: 2^3 = 8 ^length = 2^2 = 4
186211
let y = _mm_setr_epi64x(i, v);
187212
let r = _mm_insert_si64(x, y);
188-
assert_eq_m128i(r, expected);
213+
214+
// The upper quadword of the destination register is undefined.
215+
let r = _mm_cvtsi128_si64(r);
216+
let expected = _mm_cvtsi128_si64(expected);
217+
assert_eq!(r, expected);
189218
}
190219

191220
#[simd_test(enable = "sse4a")]
@@ -194,7 +223,11 @@ mod tests {
194223
let b = _mm_setr_epi64x(0x0011223344556677, 0);
195224
let r = _mm_inserti_si64::<8, 8>(a, b);
196225
let e = _mm_setr_epi64x(0x0123456789ab77ef, 0);
197-
assert_eq_m128i(r, e);
226+
227+
// The upper quadword of the destination register is undefined.
228+
let r = _mm_cvtsi128_si64(r);
229+
let e = _mm_cvtsi128_si64(e);
230+
assert_eq!(r, e);
198231
}
199232

200233
#[repr(align(16))]

0 commit comments

Comments
 (0)