Skip to content
Draft
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
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:=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
142 changes: 82 additions & 60 deletions crates/intrinsic-test/src/common/compare.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use super::cli::FailureReason;
use itertools::Itertools;
use rayon::prelude::*;
use std::process::Command;
use std::{collections::HashMap, process::Command};

pub const INTRINSIC_DELIMITER: &str = "############";
fn runner_command(runner: &str) -> Command {
let mut it = runner.split_whitespace();
let mut cmd = Command::new(it.next().unwrap());
Expand All @@ -11,85 +12,106 @@ 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();
.output()
},
);
let (c, rust) = match (c, rust) {
(Ok(c), Ok(rust)) => (c, rust),
failure => panic!("Failed to run: {failure:#?}"),
};

let (c, rust) = match (c, rust) {
(Ok(c), Ok(rust)) => (c, rust),
a => panic!("{a:#?}"),
};
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 !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 !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(""),
);
}

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()));
}
info!("Completed running C++ and Rust test binaries");
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");

info!("Comparing intrinsic: {intrinsic_name}");
let c_output_map = c
.split(INTRINSIC_DELIMITER)
.filter_map(|output| output.trim().split_once("\n"))
.collect::<HashMap<&str, &str>>();
let rust_output_map = rust
.split(INTRINSIC_DELIMITER)
.filter_map(|output| output.trim().split_once("\n"))
.collect::<HashMap<&str, &str>>();

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 intrinsics = c_output_map
.keys()
.chain(rust_output_map.keys())
.unique()
.collect_vec();

if c == rust {
info!("Comparing outputs");
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.eq(c_output) {
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
}
20 changes: 8 additions & 12 deletions crates/intrinsic-test/src/common/gen_c.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::common::intrinsic::Intrinsic;

use super::argument::Argument;
use super::compare::INTRINSIC_DELIMITER;
use super::indentation::Indentation;
use super::intrinsic_helpers::IntrinsicTypeDefinition;

Expand Down Expand Up @@ -147,22 +148,17 @@ 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 << \"{INTRINSIC_DELIMITER}\" << 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
18 changes: 6 additions & 12 deletions crates/intrinsic-test/src/common/gen_rust.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use itertools::Itertools;
use std::process::Command;

use crate::common::argument::ArgumentList;
use crate::common::intrinsic::Intrinsic;

use super::compare::INTRINSIC_DELIMITER;
use super::indentation::Indentation;
use super::intrinsic_helpers::IntrinsicTypeDefinition;
use crate::common::argument::ArgumentList;
use crate::common::intrinsic::Intrinsic;

// The number of times each intrinsic will be called.
pub(crate) const PASSES: u32 = 20;
Expand Down 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!(\"{INTRINSIC_DELIMITER}\");")?;
writeln!(w, " println!(\"{binary}\");")?;
writeln!(w, " run_{binary}();\n")?;
}

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

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

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/intrinsic-test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn run(test_environment: impl SupportedArchitectureTest) {
if !test_environment.build_rust_file() {
std::process::exit(3);
}
info!("comparing outputs");
info!("Running binaries");
if !test_environment.compare_outputs() {
std::process::exit(1);
}
Expand Down