Skip to content

Commit 3ef10b0

Browse files
authored
Merge pull request #1952 from madhav-madhusoodanan/intrinsic-test-updates
`intrinsic-test`: Coalescing all intrinsic tests into a single run of the test-file binaries
2 parents 16826ee + 1fc1197 commit 3ef10b0

File tree

6 files changed

+98
-92
lines changed

6 files changed

+98
-92
lines changed

ci/intrinsic-test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ case ${TARGET} in
7575
TEST_CXX_COMPILER="clang++"
7676
TEST_RUNNER="${CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER}"
7777
TEST_SKIP_INTRINSICS=crates/intrinsic-test/missing_x86.txt
78-
: "${TEST_SAMPLE_INTRINSICS_PERCENTAGE:=5}"
78+
: "${TEST_SAMPLE_INTRINSICS_PERCENTAGE:=20}"
7979
;;
8080
*)
8181
;;

crates/intrinsic-test/src/common/cli.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@ pub enum Language {
77
C,
88
}
99

10-
pub enum FailureReason {
11-
RunC(String),
12-
RunRust(String),
13-
Difference(String, String, String),
14-
}
15-
1610
/// Intrinsic test tool
1711
#[derive(clap::Parser)]
1812
#[command(
Lines changed: 82 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use super::cli::FailureReason;
1+
use itertools::Itertools;
22
use rayon::prelude::*;
3-
use std::process::Command;
3+
use std::{collections::HashMap, process::Command};
44

5+
pub const INTRINSIC_DELIMITER: &str = "############";
56
fn runner_command(runner: &str) -> Command {
67
let mut it = runner.split_whitespace();
78
let mut cmd = Command::new(it.next().unwrap());
@@ -11,85 +12,106 @@ fn runner_command(runner: &str) -> Command {
1112
}
1213

1314
pub fn compare_outputs(intrinsic_name_list: &Vec<String>, runner: &str, target: &str) -> bool {
14-
let intrinsics = intrinsic_name_list
15-
.par_iter()
16-
.filter_map(|intrinsic_name| {
17-
let c = runner_command(runner)
15+
let (c, rust) = rayon::join(
16+
|| {
17+
runner_command(runner)
1818
.arg("./intrinsic-test-programs")
19-
.arg(intrinsic_name)
2019
.current_dir("c_programs")
21-
.output();
22-
23-
let rust = runner_command(runner)
20+
.output()
21+
},
22+
|| {
23+
runner_command(runner)
2424
.arg(format!("./target/{target}/release/intrinsic-test-programs"))
25-
.arg(intrinsic_name)
2625
.current_dir("rust_programs")
27-
.output();
26+
.output()
27+
},
28+
);
29+
let (c, rust) = match (c, rust) {
30+
(Ok(c), Ok(rust)) => (c, rust),
31+
failure => panic!("Failed to run: {failure:#?}"),
32+
};
2833

29-
let (c, rust) = match (c, rust) {
30-
(Ok(c), Ok(rust)) => (c, rust),
31-
a => panic!("{a:#?}"),
32-
};
34+
if !c.status.success() {
35+
error!(
36+
"Failed to run C program.\nstdout: {stdout}\nstderr: {stderr}",
37+
stdout = std::str::from_utf8(&c.stdout).unwrap_or(""),
38+
stderr = std::str::from_utf8(&c.stderr).unwrap_or(""),
39+
);
40+
}
3341

34-
if !c.status.success() {
35-
error!(
36-
"Failed to run C program for intrinsic `{intrinsic_name}`\nstdout: {stdout}\nstderr: {stderr}",
37-
stdout = std::str::from_utf8(&c.stdout).unwrap_or(""),
38-
stderr = std::str::from_utf8(&c.stderr).unwrap_or(""),
39-
);
40-
return Some(FailureReason::RunC(intrinsic_name.clone()));
41-
}
42+
if !rust.status.success() {
43+
error!(
44+
"Failed to run Rust program.\nstdout: {stdout}\nstderr: {stderr}",
45+
stdout = std::str::from_utf8(&rust.stdout).unwrap_or(""),
46+
stderr = std::str::from_utf8(&rust.stderr).unwrap_or(""),
47+
);
48+
}
4249

43-
if !rust.status.success() {
44-
error!(
45-
"Failed to run Rust program for intrinsic `{intrinsic_name}`\nstdout: {stdout}\nstderr: {stderr}",
46-
stdout = std::str::from_utf8(&rust.stdout).unwrap_or(""),
47-
stderr = std::str::from_utf8(&rust.stderr).unwrap_or(""),
48-
);
49-
return Some(FailureReason::RunRust(intrinsic_name.clone()));
50-
}
50+
info!("Completed running C++ and Rust test binaries");
51+
let c = std::str::from_utf8(&c.stdout)
52+
.unwrap()
53+
.to_lowercase()
54+
.replace("-nan", "nan");
55+
let rust = std::str::from_utf8(&rust.stdout)
56+
.unwrap()
57+
.to_lowercase()
58+
.replace("-nan", "nan");
5159

52-
info!("Comparing intrinsic: {intrinsic_name}");
60+
let c_output_map = c
61+
.split(INTRINSIC_DELIMITER)
62+
.filter_map(|output| output.trim().split_once("\n"))
63+
.collect::<HashMap<&str, &str>>();
64+
let rust_output_map = rust
65+
.split(INTRINSIC_DELIMITER)
66+
.filter_map(|output| output.trim().split_once("\n"))
67+
.collect::<HashMap<&str, &str>>();
5368

54-
let c = std::str::from_utf8(&c.stdout)
55-
.unwrap()
56-
.to_lowercase()
57-
.replace("-nan", "nan");
58-
let rust = std::str::from_utf8(&rust.stdout)
59-
.unwrap()
60-
.to_lowercase()
61-
.replace("-nan", "nan");
69+
let intrinsics = c_output_map
70+
.keys()
71+
.chain(rust_output_map.keys())
72+
.unique()
73+
.collect_vec();
6274

63-
if c == rust {
75+
info!("Comparing outputs");
76+
let intrinsics_diff_count = intrinsics
77+
.par_iter()
78+
.filter_map(|&&intrinsic| {
79+
let c_output = c_output_map.get(intrinsic).unwrap();
80+
let rust_output = rust_output_map.get(intrinsic).unwrap();
81+
if rust_output.eq(c_output) {
6482
None
6583
} else {
66-
Some(FailureReason::Difference(intrinsic_name.clone(), c, rust))
84+
let diff = diff::lines(c_output, rust_output);
85+
let diffs = diff
86+
.into_iter()
87+
.filter_map(|diff| match diff {
88+
diff::Result::Left(_) | diff::Result::Right(_) => Some(diff),
89+
diff::Result::Both(_, _) => None,
90+
})
91+
.collect_vec();
92+
if diffs.len() > 0 {
93+
Some((intrinsic, diffs))
94+
} else {
95+
None
96+
}
6797
}
6898
})
69-
.collect::<Vec<_>>();
70-
71-
intrinsics.iter().for_each(|reason| match reason {
72-
FailureReason::Difference(intrinsic, c, rust) => {
99+
.inspect(|(intrinsic, diffs)| {
73100
println!("Difference for intrinsic: {intrinsic}");
74-
let diff = diff::lines(c, rust);
75-
diff.iter().for_each(|diff| match diff {
101+
diffs.into_iter().for_each(|diff| match diff {
76102
diff::Result::Left(c) => println!("C: {c}"),
77103
diff::Result::Right(rust) => println!("Rust: {rust}"),
78-
diff::Result::Both(_, _) => (),
104+
_ => (),
79105
});
80106
println!("****************************************************************");
81-
}
82-
FailureReason::RunC(intrinsic) => {
83-
println!("Failed to run C program for intrinsic {intrinsic}")
84-
}
85-
FailureReason::RunRust(intrinsic) => {
86-
println!("Failed to run rust program for intrinsic {intrinsic}")
87-
}
88-
});
107+
})
108+
.count();
109+
89110
println!(
90111
"{} differences found (tested {} intrinsics)",
91-
intrinsics.len(),
112+
intrinsics_diff_count,
92113
intrinsic_name_list.len()
93114
);
94-
intrinsics.is_empty()
115+
116+
intrinsics_diff_count == 0
95117
}

crates/intrinsic-test/src/common/gen_c.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::common::intrinsic::Intrinsic;
22

33
use super::argument::Argument;
4+
use super::compare::INTRINSIC_DELIMITER;
45
use super::indentation::Indentation;
56
use super::intrinsic_helpers::IntrinsicTypeDefinition;
67

@@ -147,22 +148,17 @@ pub fn write_main_cpp<'a>(
147148
}
148149

149150
writeln!(w, "int main(int argc, char **argv) {{")?;
150-
writeln!(w, " std::string intrinsic_name = argv[1];")?;
151-
152-
writeln!(w, " if (false) {{")?;
153151

154152
for intrinsic in intrinsics {
155-
writeln!(w, " }} else if (intrinsic_name == \"{intrinsic}\") {{")?;
156-
writeln!(w, " return run_{intrinsic}();")?;
153+
writeln!(
154+
w,
155+
" std::cout << \"{INTRINSIC_DELIMITER}\" << std::endl;"
156+
)?;
157+
writeln!(w, " std::cout << \"{intrinsic}\" << std::endl;")?;
158+
writeln!(w, " run_{intrinsic}();\n")?;
157159
}
158160

159-
writeln!(w, " }} else {{")?;
160-
writeln!(
161-
w,
162-
" std::cerr << \"Unknown command: \" << intrinsic_name << \"\\n\";"
163-
)?;
164-
writeln!(w, " return -1;")?;
165-
writeln!(w, " }}")?;
161+
writeln!(w, " return 0;")?;
166162

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

crates/intrinsic-test/src/common/gen_rust.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use itertools::Itertools;
22
use std::process::Command;
33

4-
use crate::common::argument::ArgumentList;
5-
use crate::common::intrinsic::Intrinsic;
6-
4+
use super::compare::INTRINSIC_DELIMITER;
75
use super::indentation::Indentation;
86
use super::intrinsic_helpers::IntrinsicTypeDefinition;
7+
use crate::common::argument::ArgumentList;
8+
use crate::common::intrinsic::Intrinsic;
99

1010
// The number of times each intrinsic will be called.
1111
pub(crate) const PASSES: u32 = 20;
@@ -86,18 +86,12 @@ pub fn write_main_rs<'a>(
8686

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

89-
writeln!(w, " match std::env::args().nth(1).unwrap().as_str() {{")?;
90-
9189
for binary in intrinsics {
92-
writeln!(w, " \"{binary}\" => run_{binary}(),")?;
90+
writeln!(w, " println!(\"{INTRINSIC_DELIMITER}\");")?;
91+
writeln!(w, " println!(\"{binary}\");")?;
92+
writeln!(w, " run_{binary}();\n")?;
9393
}
9494

95-
writeln!(
96-
w,
97-
" other => panic!(\"unknown intrinsic `{{}}`\", other),"
98-
)?;
99-
100-
writeln!(w, " }}")?;
10195
writeln!(w, "}}")?;
10296

10397
Ok(())

crates/intrinsic-test/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn run(test_environment: impl SupportedArchitectureTest) {
3434
if !test_environment.build_rust_file() {
3535
std::process::exit(3);
3636
}
37-
info!("comparing outputs");
37+
info!("Running binaries");
3838
if !test_environment.compare_outputs() {
3939
std::process::exit(1);
4040
}

0 commit comments

Comments
 (0)