Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion ci/intrinsic-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ case ${TARGET} in
TEST_CXX_COMPILER="clang++"
TEST_RUNNER="${CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER}"
TEST_SKIP_INTRINSICS=crates/intrinsic-test/missing_x86.txt
: "${TEST_SAMPLE_INTRINSICS_PERCENTAGE:=5}"
: "${TEST_SAMPLE_INTRINSICS_PERCENTAGE:=30}"
Copy link
Contributor

Choose a reason for hiding this comment

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

please adjust this so that it is not the longest CI job. I think the next-longest job is 11 minutes now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, let me dial it down to 20%.

;;
*)
;;
Expand Down
3 changes: 1 addition & 2 deletions crates/intrinsic-test/missing_x86.txt
Original file line number Diff line number Diff line change
Expand Up @@ -890,15 +890,14 @@ _mm256_extract_epi16
_mm256_extract_epi8
_mm512_castsi128_si512
_mm512_castsi256_si512
# _mm512_conj_pch
_mm512_conj_pch
_mm512_mask_reduce_max_pd
_mm512_mask_reduce_max_ps
_mm512_mask_reduce_min_pd
_mm512_mask_reduce_min_ps
_mm_comineq_sh
_mm_extract_epi16
_mm_extract_epi8
_mm_mask_cvtepi16_epi8
_mm_mask_cvtpd_epi32
_mm_mask_cvtpd_ps
_mm_ucomineq_sh
6 changes: 0 additions & 6 deletions crates/intrinsic-test/src/common/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ pub enum Language {
C,
}

pub enum FailureReason {
RunC(String),
RunRust(String),
Difference(String, String, String),
}

/// Intrinsic test tool
#[derive(clap::Parser)]
#[command(
Expand Down
140 changes: 79 additions & 61 deletions crates/intrinsic-test/src/common/compare.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::cli::FailureReason;
use itertools::Itertools;
use rayon::prelude::*;
use std::process::Command;
use std::{collections::HashMap, process::Command};

fn runner_command(runner: &str) -> Command {
let mut it = runner.split_whitespace();
Expand All @@ -11,85 +11,103 @@ fn runner_command(runner: &str) -> Command {
}

pub fn compare_outputs(intrinsic_name_list: &Vec<String>, runner: &str, target: &str) -> bool {
let intrinsics = intrinsic_name_list
.par_iter()
.filter_map(|intrinsic_name| {
let c = runner_command(runner)
let (c, rust) = rayon::join(
|| {
runner_command(runner)
.arg("./intrinsic-test-programs")
.arg(intrinsic_name)
.current_dir("c_programs")
.output();

let rust = runner_command(runner)
.output()
},
|| {
runner_command(runner)
.arg(format!("./target/{target}/release/intrinsic-test-programs"))
.arg(intrinsic_name)
.current_dir("rust_programs")
.output();

let (c, rust) = match (c, rust) {
(Ok(c), Ok(rust)) => (c, rust),
a => panic!("{a:#?}"),
};
.output()
},
);
let (c, rust) = match (c, rust) {
(Ok(c), Ok(rust)) => (c, rust),
a => panic!("{a:#?}"),
Copy link
Contributor

Choose a reason for hiding this comment

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

let's call this "failure" or something a bit more descriptive

};

if !c.status.success() {
error!(
"Failed to run C program for intrinsic `{intrinsic_name}`\nstdout: {stdout}\nstderr: {stderr}",
stdout = std::str::from_utf8(&c.stdout).unwrap_or(""),
stderr = std::str::from_utf8(&c.stderr).unwrap_or(""),
);
return Some(FailureReason::RunC(intrinsic_name.clone()));
}
if !c.status.success() {
error!(
"Failed to run C program.\nstdout: {stdout}\nstderr: {stderr}",
stdout = std::str::from_utf8(&c.stdout).unwrap_or(""),
stderr = std::str::from_utf8(&c.stderr).unwrap_or(""),
);
}

if !rust.status.success() {
error!(
"Failed to run Rust program for intrinsic `{intrinsic_name}`\nstdout: {stdout}\nstderr: {stderr}",
stdout = std::str::from_utf8(&rust.stdout).unwrap_or(""),
stderr = std::str::from_utf8(&rust.stderr).unwrap_or(""),
);
return Some(FailureReason::RunRust(intrinsic_name.clone()));
}
if !rust.status.success() {
error!(
"Failed to run Rust program.\nstdout: {stdout}\nstderr: {stderr}",
stdout = std::str::from_utf8(&rust.stdout).unwrap_or(""),
stderr = std::str::from_utf8(&rust.stderr).unwrap_or(""),
);
}

info!("Comparing intrinsic: {intrinsic_name}");
let c = std::str::from_utf8(&c.stdout)
.unwrap()
.to_lowercase()
.replace("-nan", "nan");
let rust = std::str::from_utf8(&rust.stdout)
.unwrap()
.to_lowercase()
.replace("-nan", "nan");

let c = std::str::from_utf8(&c.stdout)
.unwrap()
.to_lowercase()
.replace("-nan", "nan");
let rust = std::str::from_utf8(&rust.stdout)
.unwrap()
.to_lowercase()
.replace("-nan", "nan");
let c_output_map = c
.split("############")
Copy link
Contributor

Choose a reason for hiding this comment

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

can you put this marker into a const and use that instead of repeating the literal characters?

.filter_map(|output| output.trim().split_once("\n"))
.collect::<HashMap<&str, &str>>();
let rust_output_map = rust
.split("############")
.filter_map(|output| output.trim().split_once("\n"))
.collect::<HashMap<&str, &str>>();

if c == rust {
let intrinsics = c_output_map
.keys()
.chain(rust_output_map.keys())
.unique()
.collect_vec();
let intrinsics_diff_count = intrinsics
.par_iter()
.filter_map(|&&intrinsic| {
let c_output = c_output_map.get(intrinsic).unwrap();
let rust_output = rust_output_map.get(intrinsic).unwrap();
if rust_output.to_string() == c_output.to_string() {
None
} else {
Some(FailureReason::Difference(intrinsic_name.clone(), c, rust))
let diff = diff::lines(c_output, rust_output);
let diffs = diff
.into_iter()
.filter_map(|diff| match diff {
diff::Result::Left(_) | diff::Result::Right(_) => Some(diff),
diff::Result::Both(_, _) => None,
})
.collect_vec();
if diffs.len() > 0 {
Some((intrinsic, diffs))
} else {
None
}
}
})
.collect::<Vec<_>>();

intrinsics.iter().for_each(|reason| match reason {
FailureReason::Difference(intrinsic, c, rust) => {
.inspect(|(intrinsic, diffs)| {
println!("Difference for intrinsic: {intrinsic}");
let diff = diff::lines(c, rust);
diff.iter().for_each(|diff| match diff {
diffs.into_iter().for_each(|diff| match diff {
diff::Result::Left(c) => println!("C: {c}"),
diff::Result::Right(rust) => println!("Rust: {rust}"),
diff::Result::Both(_, _) => (),
_ => (),
});
println!("****************************************************************");
}
FailureReason::RunC(intrinsic) => {
println!("Failed to run C program for intrinsic {intrinsic}")
}
FailureReason::RunRust(intrinsic) => {
println!("Failed to run rust program for intrinsic {intrinsic}")
}
});
})
.count();

println!(
"{} differences found (tested {} intrinsics)",
intrinsics.len(),
intrinsics_diff_count,
intrinsic_name_list.len()
);
intrinsics.is_empty()

intrinsics_diff_count == 0
}
16 changes: 4 additions & 12 deletions crates/intrinsic-test/src/common/gen_c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,22 +147,14 @@ pub fn write_main_cpp<'a>(
}

writeln!(w, "int main(int argc, char **argv) {{")?;
writeln!(w, " std::string intrinsic_name = argv[1];")?;

writeln!(w, " if (false) {{")?;

for intrinsic in intrinsics {
writeln!(w, " }} else if (intrinsic_name == \"{intrinsic}\") {{")?;
writeln!(w, " return run_{intrinsic}();")?;
writeln!(w, " std::cout << \"############\" << std::endl;")?;
writeln!(w, " std::cout << \"{intrinsic}\" << std::endl;")?;
writeln!(w, " run_{intrinsic}();\n")?;
}

writeln!(w, " }} else {{")?;
writeln!(
w,
" std::cerr << \"Unknown command: \" << intrinsic_name << \"\\n\";"
)?;
writeln!(w, " return -1;")?;
writeln!(w, " }}")?;
writeln!(w, " return 0;")?;

writeln!(w, "}}")?;

Expand Down
12 changes: 3 additions & 9 deletions crates/intrinsic-test/src/common/gen_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,12 @@ pub fn write_main_rs<'a>(

writeln!(w, "fn main() {{")?;

writeln!(w, " match std::env::args().nth(1).unwrap().as_str() {{")?;

for binary in intrinsics {
writeln!(w, " \"{binary}\" => run_{binary}(),")?;
writeln!(w, " println!(\"############\");")?;
writeln!(w, " println!(\"{binary}\");")?;
writeln!(w, " run_{binary}();\n")?;
}

writeln!(
w,
" other => panic!(\"unknown intrinsic `{{}}`\", other),"
)?;

writeln!(w, " }}")?;
writeln!(w, "}}")?;

Ok(())
Expand Down