Skip to content

Commit f61f45f

Browse files
committed
Auto merge of rust-lang#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
2 parents 6bcd9bc + 89bc81f commit f61f45f

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

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

+13
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
8888
this.write_immediate(*sub, &this.project_field(dest, 1)?)?;
8989
}
9090

91+
// Used to implement the `_mm_pause` function.
92+
// The intrinsic is used to hint the processor that the code is in a spin-loop.
93+
// It is compiled down to a `pause` instruction. When SSE2 is not available,
94+
// the instruction behaves like a no-op, so it is always safe to call the
95+
// intrinsic.
96+
"sse2.pause" => {
97+
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
98+
// Only exhibit the spin-loop hint behavior when SSE2 is enabled.
99+
if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) {
100+
this.yield_active_thread();
101+
}
102+
}
103+
91104
name if name.starts_with("sse.") => {
92105
return sse::EvalContextExt::emulate_x86_sse_intrinsic(
93106
this, link_name, abi, args, dest,

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

-6
Original file line numberDiff line numberDiff line change
@@ -580,12 +580,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
580580
this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?;
581581
}
582582
}
583-
// Used to implement the `_mm_pause` function.
584-
// The intrinsic is used to hint the processor that the code is in a spin-loop.
585-
"pause" => {
586-
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
587-
this.yield_active_thread();
588-
}
589583
_ => return Ok(EmulateForeignItemResult::NotSupported),
590584
}
591585
Ok(EmulateForeignItemResult::NeedsJumping)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Ignore everything except x86 and x86_64
2+
// Any new targets that are added to CI should be ignored here.
3+
// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
4+
//@ignore-target-aarch64
5+
//@ignore-target-arm
6+
//@ignore-target-avr
7+
//@ignore-target-s390x
8+
//@ignore-target-thumbv7em
9+
//@ignore-target-wasm32
10+
//@compile-flags: -C target-feature=-sse2
11+
12+
#[cfg(target_arch = "x86")]
13+
use std::arch::x86::*;
14+
#[cfg(target_arch = "x86_64")]
15+
use std::arch::x86_64::*;
16+
17+
fn main() {
18+
assert!(!is_x86_feature_detected!("sse2"));
19+
20+
unsafe {
21+
// This is a SSE2 intrinsic, but it behaves as a no-op when SSE2
22+
// is not available, so it is always safe to call.
23+
_mm_pause();
24+
}
25+
}

src/tools/miri/tests/pass/intrinsics-x86-sse2.rs

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ mod tests {
5454
}
5555
}
5656

57+
fn test_mm_pause() {
58+
unsafe { _mm_pause() }
59+
}
60+
test_mm_pause();
61+
5762
#[target_feature(enable = "sse2")]
5863
unsafe fn test_mm_avg_epu8() {
5964
let (a, b) = (_mm_set1_epi8(3), _mm_set1_epi8(9));

0 commit comments

Comments
 (0)