Skip to content

Commit

Permalink
Auto merge of #3393 - eduardosm:x86-pause-without-sse2, r=RalfJung
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Mar 21, 2024
2 parents addad82 + d086522 commit 862915a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 6 deletions.
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

0 comments on commit 862915a

Please sign in to comment.