Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/shims/x86/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
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,
Expand Down
6 changes: 0 additions & 6 deletions src/shims/x86/sse2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,12 +580,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
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)
Expand Down
25 changes: 25 additions & 0 deletions tests/pass/intrinsics-x86-pause-without-sse2.rs
Original file line number Diff line number Diff line change
@@ -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();
}
}
5 changes: 5 additions & 0 deletions tests/pass/intrinsics-x86-sse2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ mod tests {
}
}

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));
Expand Down