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
134 changes: 134 additions & 0 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,140 @@ impl Step for StdarchVerify {
}
}

/// Runs stdarch's intrinsic-test binary crate to verify that Rust's `core::arch`
/// SIMD intrinsics produce the same results as their C counterparts.
///
/// First runs the `intrinsic-test` binary, which generates C wrapper programs
/// and a Rust Cargo workspace. Then runs `cargo test` on that workspace
/// which compiles both versions and compares their outputs on random inputs.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Comment thread
Kobzol marked this conversation as resolved.
pub struct IntrinsicTest {
host: TargetSelection,
}

impl Step for IntrinsicTest {
type Output = ();
const IS_HOST: bool = true;

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("library/stdarch/crates/intrinsic-test")
}
Comment on lines +1010 to +1012

@folkertdev folkertdev May 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the intrinsic tests should also run when any of the source in core_arch changes (unless I'm misinterpreting what this function does).

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No you are not misinterpreting :) . You're so right I have added the core_arch path so it triggers . Thanks for the review.


fn make_run(run: RunConfig<'_>) {
let target = run.target;
if !target.contains("aarch64-unknown-linux") && !target.contains("x86_64-unknown-linux") {
return;
}
run.builder.ensure(IntrinsicTest { host: target });
}

fn run(self, builder: &Builder<'_>) {
let host = self.host;

let (input_file, skip_file, cflags, sde_runner) = if host.contains("x86_64-unknown-linux") {
let cpuid_def =
builder.src.join("library/stdarch/ci/docker/x86_64-unknown-linux-gnu/cpuid.def");
let sde_runner = format!(
"/intel-sde/sde64 -cpuid-in {} -rtm-mode full -tsx --",
cpuid_def.display()
);
(
builder.src.join("library/stdarch/intrinsics_data/x86-intel.xml"),
[
builder
.src
.join("library/stdarch/crates/intrinsic-test/missing_x86_common.txt"),
builder.src.join("library/stdarch/crates/intrinsic-test/missing_x86_gcc.txt"),
],
"-I/usr/include/x86_64-linux-gnu/",
Some(sde_runner),
)
} else if host.contains("aarch64-unknown-linux") {
(
builder.src.join("library/stdarch/intrinsics_data/arm_intrinsics.json"),
[
builder
.src
.join("library/stdarch/crates/intrinsic-test/missing_aarch64_common.txt"),
builder
.src
.join("library/stdarch/crates/intrinsic-test/missing_aarch64_gcc.txt"),
],
"-I/usr/aarch64-linux-gnu/include/",
None,
)
} else {
panic!("intrinsic-test only supports aarch64/x86_64 Linux, got {host}");
};

let out_dir = builder.out.join(host).join("intrinsic-test");
t!(fs::create_dir_all(&out_dir));

let crates_link = out_dir.join("crates");
if !crates_link.exists() {
t!(
helpers::symlink_dir(
&builder.config,
&builder.src.join("library/stdarch/crates"),
&crates_link
),
format!("failed to symlink stdarch crates into {}", crates_link.display())
);
}

let mut cmd = builder.tool_cmd(Tool::IntrinsicTest);
cmd.current_dir(&out_dir);
cmd.arg(&input_file);
cmd.arg("--target").arg(&*host.triple);
for skip in &skip_file {
cmd.arg("--skip").arg(skip);
}
cmd.arg("--sample-percentage").arg("10");
cmd.arg("--cc-arg-style").arg("gcc");
cmd.env("CC", builder.cc(host));
cmd.env("CFLAGS", cflags);
// intrinsic-test shells out to `cargo` and `rustfmt` make bootstrap's
// managed binaries findable by prepending their dirs to PATH.
let rustfmt_path = builder.config.initial_rustfmt.clone().unwrap_or_else(|| {
eprintln!("intrinsic-test: rustfmt is required but not available on this channel");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to break on beta/stable channels (as it says) -- is the intent to not run this test in CI on those channels? I'll drop it temporarily but we should land something on main that avoids breaking CI (as seen here - #159072 (comment)).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I think we can simply print a warning and then skip the test (just return) from this function. @xonx4l Can you please send a PR that does that? Thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay got it , OTW. Thanks @Mark-Simulacrum for the catch!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here opened the PR -: #159265 .

crate::exit!(1);
});

let mut path_dirs: Vec<PathBuf> = Vec::new();
if let Some(cargo_dir) = builder.initial_cargo.parent() {
path_dirs.push(cargo_dir.to_path_buf());
}
if let Some(rustfmt_dir) = rustfmt_path.parent() {
path_dirs.push(rustfmt_dir.to_path_buf());
}
let old_path = env::var_os("PATH").unwrap_or_default();
let new_path = env::join_paths(path_dirs.into_iter().chain(env::split_paths(&old_path)))
.expect("could not build PATH for intrinsic-test");
cmd.env("PATH", new_path);
cmd.run(builder);

let tested_compiler = builder.compiler(builder.top_stage, host);
builder.std(tested_compiler, host);
let rustc = builder.rustc(tested_compiler);

let manifest = out_dir.join("rust_programs/Cargo.toml");
let mut cargo = command(&builder.initial_cargo);
cargo.arg("test");
cargo.arg("--tests");
cargo.arg("--manifest-path").arg(&manifest);
cargo.arg("--target").arg(&*host.triple);
cargo.arg("--profile").arg("release");
cargo.env("CC", builder.cc(host));
cargo.env("CFLAGS", cflags);
cargo.env("RUSTC", rustc);
cargo.env("RUSTC_BOOTSTRAP", "1");
if let Some(runner) = sde_runner {
cargo.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER", runner);
}
cargo.run(builder);
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Clippy {
compilers: RustcPrivateCompilers,
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/src/core/build_steps/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ bootstrap_tool!(
FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
RunMakeSupport, "src/tools/run-make-support", "run_make_support", artifact_kind = ToolArtifactKind::Library;
IntrinsicTest, "library/stdarch/crates/intrinsic-test", "intrinsic-test";
);

/// These are the submodules that are required for rustbook to work due to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ expression: test library
[Test] test::StdarchVerify
targets: [x86_64-unknown-linux-gnu]
- Set({test::library/stdarch/crates/stdarch-verify})
[Test] test::IntrinsicTest
targets: [x86_64-unknown-linux-gnu]
- Set({test::library/stdarch/crates/intrinsic-test})
1 change: 1 addition & 0 deletions src/bootstrap/src/core/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,7 @@ impl<'a> Builder<'a> {
test::Clippy,
test::CompiletestTest,
test::StdarchVerify,
test::IntrinsicTest,
test::CrateRunMakeSupport,
test::CrateBuildHelper,
test::RustdocJSStd,
Expand Down
9 changes: 8 additions & 1 deletion src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libzstd-dev \
&& rm -rf /var/lib/apt/lists/*

# Install Intel SDE for AVX-512 emulation
RUN curl -L http://ci-mirrors.rust-lang.org/sde-external-10.8.0-2026-03-15-lin.tar.xz -o /tmp/sde.tar.xz \
&& mkdir -p /intel-sde \
&& tar -xJf /tmp/sde.tar.xz --strip-components=1 -C /intel-sde \
&& rm /tmp/sde.tar.xz
Comment on lines +25 to +28

@folkertdev folkertdev May 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't need an instant fix, but we bump the version of this tool occasionally, so ideally we'd sync that version between the repositories.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, noted.


COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

Expand All @@ -29,4 +35,5 @@ ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \
--enable-profiler \
--enable-compiler-docs \
--set llvm.libzstd=true"
ENV SCRIPT="python3 ../x.py --stage 2 test"
ENV SCRIPT="python3 ../x.py --stage 2 test && \
python3 ../x.py --stage 2 test library/stdarch/crates/intrinsic-test"
Loading