Skip to content

Commit 5e4168b

Browse files
committed
partially revert 8d597aa
1 parent 7434dd6 commit 5e4168b

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

src/tools/miri/src/shims/x86/avx2.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,42 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
224224

225225
shift_simd_by_scalar(this, left, right, which, dest)?;
226226
}
227+
// Used to implement the _mm256_madd_epi16 function.
228+
// Multiplies packed signed 16-bit integers in `left` and `right`, producing
229+
// intermediate signed 32-bit integers. Horizontally add adjacent pairs of
230+
// intermediate 32-bit integers, and pack the results in `dest`.
231+
"pmadd.wd" => {
232+
let [left, right] =
233+
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
234+
235+
let (left, left_len) = this.project_to_simd(left)?;
236+
let (right, right_len) = this.project_to_simd(right)?;
237+
let (dest, dest_len) = this.project_to_simd(dest)?;
238+
239+
assert_eq!(left_len, right_len);
240+
assert_eq!(dest_len.strict_mul(2), left_len);
241+
242+
for i in 0..dest_len {
243+
let j1 = i.strict_mul(2);
244+
let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?;
245+
let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?;
246+
247+
let j2 = j1.strict_add(1);
248+
let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?;
249+
let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?;
250+
251+
let dest = this.project_index(&dest, i)?;
252+
253+
// Multiplications are i16*i16->i32, which will not overflow.
254+
let mul1 = i32::from(left1).strict_mul(right1.into());
255+
let mul2 = i32::from(left2).strict_mul(right2.into());
256+
// However, this addition can overflow in the most extreme case
257+
// (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000
258+
let res = mul1.wrapping_add(mul2);
259+
260+
this.write_scalar(Scalar::from_i32(res), &dest)?;
261+
}
262+
}
227263
_ => return interp_ok(EmulateItemResult::NotSupported),
228264
}
229265
interp_ok(EmulateItemResult::NeedsReturn)

src/tools/miri/src/shims/x86/sse2.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,42 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
278278
this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?;
279279
}
280280
}
281+
// Used to implement the _mm_madd_epi16 function.
282+
// Multiplies packed signed 16-bit integers in `left` and `right`, producing
283+
// intermediate signed 32-bit integers. Horizontally add adjacent pairs of
284+
// intermediate 32-bit integers, and pack the results in `dest`.
285+
"pmadd.wd" => {
286+
let [left, right] =
287+
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
288+
289+
let (left, left_len) = this.project_to_simd(left)?;
290+
let (right, right_len) = this.project_to_simd(right)?;
291+
let (dest, dest_len) = this.project_to_simd(dest)?;
292+
293+
assert_eq!(left_len, right_len);
294+
assert_eq!(dest_len.strict_mul(2), left_len);
295+
296+
for i in 0..dest_len {
297+
let j1 = i.strict_mul(2);
298+
let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?;
299+
let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?;
300+
301+
let j2 = j1.strict_add(1);
302+
let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?;
303+
let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?;
304+
305+
let dest = this.project_index(&dest, i)?;
306+
307+
// Multiplications are i16*i16->i32, which will not overflow.
308+
let mul1 = i32::from(left1).strict_mul(right1.into());
309+
let mul2 = i32::from(left2).strict_mul(right2.into());
310+
// However, this addition can overflow in the most extreme case
311+
// (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000
312+
let res = mul1.wrapping_add(mul2);
313+
314+
this.write_scalar(Scalar::from_i32(res), &dest)?;
315+
}
316+
}
281317
_ => return interp_ok(EmulateItemResult::NotSupported),
282318
}
283319
interp_ok(EmulateItemResult::NeedsReturn)

0 commit comments

Comments
 (0)