Auto merge of #3393 - eduardosm:x86-pause-without-sse2, r=RalfJung

Allow `llvm.x86.sse2.pause` instrinsic to be called without SSE2

The instrinsic is compiled to a `pause` instruction, which behaves like a no-op when SSE2 is not available.

https://www.felixcloutier.com/x86/pause.html
This commit is contained in:
bors 2024-03-21 18:37:34 +00:00
commit f61f45f233
4 changed files with 43 additions and 6 deletions

View File

@ -88,6 +88,19 @@ fn emulate_x86_intrinsic(
this.write_immediate(*sub, &this.project_field(dest, 1)?)?;
}
// Used to implement the `_mm_pause` function.
// The intrinsic is used to hint the processor that the code is in a spin-loop.
// It is compiled down to a `pause` instruction. When SSE2 is not available,
// the instruction behaves like a no-op, so it is always safe to call the
// intrinsic.
"sse2.pause" => {
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
// Only exhibit the spin-loop hint behavior when SSE2 is enabled.
if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) {
this.yield_active_thread();
}
}
name if name.starts_with("sse.") => {
return sse::EvalContextExt::emulate_x86_sse_intrinsic(
this, link_name, abi, args, dest,

View File

@ -580,12 +580,6 @@ enum ShiftOp {
this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?;
}
}
// Used to implement the `_mm_pause` function.
// The intrinsic is used to hint the processor that the code is in a spin-loop.
"pause" => {
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.yield_active_thread();
}
_ => return Ok(EmulateForeignItemResult::NotSupported),
}
Ok(EmulateForeignItemResult::NeedsJumping)

View File

@ -0,0 +1,25 @@
// Ignore everything except x86 and x86_64
// Any new targets that are added to CI should be ignored here.
// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
//@ignore-target-aarch64
//@ignore-target-arm
//@ignore-target-avr
//@ignore-target-s390x
//@ignore-target-thumbv7em
//@ignore-target-wasm32
//@compile-flags: -C target-feature=-sse2
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
fn main() {
assert!(!is_x86_feature_detected!("sse2"));
unsafe {
// This is a SSE2 intrinsic, but it behaves as a no-op when SSE2
// is not available, so it is always safe to call.
_mm_pause();
}
}

View File

@ -54,6 +54,11 @@ unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
}
}
fn test_mm_pause() {
unsafe { _mm_pause() }
}
test_mm_pause();
#[target_feature(enable = "sse2")]
unsafe fn test_mm_avg_epu8() {
let (a, b) = (_mm_set1_epi8(3), _mm_set1_epi8(9));