Skip to content

Commit f417aaa

Browse files
committed
intrinsic-test: combine C files for more efficient compilation
1 parent ea60cd8 commit f417aaa

File tree

6 files changed

+259
-230
lines changed

6 files changed

+259
-230
lines changed

crates/intrinsic-test/src/arm/mod.rs

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ mod intrinsic;
44
mod json_parser;
55
mod types;
66

7+
use std::fs::File;
8+
9+
use rayon::prelude::*;
10+
11+
use crate::arm::config::POLY128_OSTREAM_DEF;
712
use crate::common::SupportedArchitectureTest;
813
use crate::common::cli::ProcessedCli;
914
use crate::common::compare::compare_outputs;
10-
use crate::common::gen_c::compile_c_programs;
15+
use crate::common::gen_c::{write_main_cpp, write_mod_cpp};
1116
use crate::common::gen_rust::compile_rust_programs;
1217
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
1318
use crate::common::intrinsic_helpers::TypeKind;
14-
use crate::common::write_file::{write_c_testfiles, write_rust_testfiles};
15-
use config::{AARCH_CONFIGURATIONS, F16_FORMATTING_DEF, POLY128_OSTREAM_DEF, build_notices};
19+
use crate::common::write_file::write_rust_testfiles;
20+
use config::{AARCH_CONFIGURATIONS, F16_FORMATTING_DEF, build_notices};
1621
use intrinsic::ArmIntrinsicType;
1722
use json_parser::get_neon_intrinsics;
1823

@@ -21,6 +26,13 @@ pub struct ArmArchitectureTest {
2126
cli_options: ProcessedCli,
2227
}
2328

29+
fn chunk_info(intrinsic_count: usize) -> (usize, usize) {
30+
let available_parallelism = std::thread::available_parallelism().unwrap().get();
31+
let chunk_size = intrinsic_count.div_ceil(Ord::min(available_parallelism, intrinsic_count));
32+
33+
(chunk_size, intrinsic_count.div_ceil(chunk_size))
34+
}
35+
2436
impl SupportedArchitectureTest for ArmArchitectureTest {
2537
fn create(cli_options: ProcessedCli) -> Box<Self> {
2638
let a32 = cli_options.target.contains("v7");
@@ -51,24 +63,58 @@ impl SupportedArchitectureTest for ArmArchitectureTest {
5163
}
5264

5365
fn build_c_file(&self) -> bool {
54-
let target = &self.cli_options.target;
5566
let c_target = "aarch64";
67+
let platform_headers = &["arm_neon.h", "arm_acle.h", "arm_fp16.h"];
5668

57-
let intrinsics_name_list = write_c_testfiles(
58-
&self
59-
.intrinsics
60-
.iter()
61-
.map(|i| i as &dyn IntrinsicDefinition<_>)
62-
.collect::<Vec<_>>(),
63-
target,
69+
let (chunk_size, chunk_count) = chunk_info(self.intrinsics.len());
70+
71+
let cpp_compiler = compile::build_cpp_compilation(&self.cli_options).unwrap();
72+
73+
let notice = &build_notices("// ");
74+
self.intrinsics
75+
.par_chunks(chunk_size)
76+
.enumerate()
77+
.map(|(i, chunk)| {
78+
let c_filename = format!("c_programs/mod_{i}.cpp");
79+
let mut file = File::create(&c_filename).unwrap();
80+
write_mod_cpp(&mut file, notice, c_target, platform_headers, chunk).unwrap();
81+
82+
// compile this cpp file into a .o file
83+
let output = cpp_compiler
84+
.compile_object_file(&format!("mod_{i}.cpp"), &format!("mod_{i}.o"))?;
85+
assert!(output.status.success());
86+
87+
Ok(())
88+
})
89+
.collect::<Result<(), std::io::Error>>()
90+
.unwrap();
91+
92+
let mut file = File::create("c_programs/main.cpp").unwrap();
93+
write_main_cpp(
94+
&mut file,
6495
c_target,
65-
&["arm_neon.h", "arm_acle.h", "arm_fp16.h"],
66-
&build_notices("// "),
67-
&[POLY128_OSTREAM_DEF],
68-
);
96+
POLY128_OSTREAM_DEF,
97+
self.intrinsics.iter().map(|i| i.name.as_str()),
98+
)
99+
.unwrap();
100+
101+
// compile this cpp file into a .o file
102+
info!("compiling main.cpp");
103+
let output = cpp_compiler
104+
.compile_object_file("main.cpp", "intrinsic-test-programs.o")
105+
.unwrap();
106+
assert!(output.status.success());
107+
108+
let object_files = (0..chunk_count)
109+
.map(|i| format!("mod_{i}.o"))
110+
.chain(["intrinsic-test-programs.o".to_owned()]);
111+
112+
let output = cpp_compiler
113+
.link_executable(object_files, "intrinsic-test-programs")
114+
.unwrap();
115+
assert!(output.status.success());
69116

70-
let pipeline = compile::build_cpp_compilation(&self.cli_options).unwrap();
71-
compile_c_programs(&pipeline, &intrinsics_name_list)
117+
true
72118
}
73119

74120
fn build_rust_file(&self) -> bool {

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

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,23 @@ where
125125
/// Creates a line for each argument that initializes an array for C from which `loads` argument
126126
/// values can be loaded as a sliding window.
127127
/// e.g `const int32x2_t a_vals = {0x3effffff, 0x3effffff, 0x3f7fffff}`, if loads=2.
128-
pub fn gen_arglists_c(&self, indentation: Indentation, loads: u32) -> String {
129-
self.iter()
130-
.filter(|&arg| !arg.has_constraint())
131-
.map(|arg| {
132-
format!(
133-
"{indentation}const {ty} {name}_vals[] = {values};",
134-
ty = arg.ty.c_scalar_type(),
135-
name = arg.name,
136-
values = arg.ty.populate_random(indentation, loads, &Language::C)
137-
)
138-
})
139-
.collect::<Vec<_>>()
140-
.join("\n")
128+
pub fn gen_arglists_c(
129+
&self,
130+
w: &mut impl std::io::Write,
131+
indentation: Indentation,
132+
loads: u32,
133+
) -> std::io::Result<()> {
134+
for arg in self.iter().filter(|&arg| !arg.has_constraint()) {
135+
writeln!(
136+
w,
137+
"{indentation}const {ty} {name}_vals[] = {values};",
138+
ty = arg.ty.c_scalar_type(),
139+
name = arg.name,
140+
values = arg.ty.populate_random(indentation, loads, &Language::C)
141+
)?
142+
}
143+
144+
Ok(())
141145
}
142146

143147
/// Creates a line for each argument that initializes an array for Rust from which `loads` argument

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ pub fn compare_outputs(intrinsic_name_list: &Vec<String>, runner: &str, target:
1515
.par_iter()
1616
.filter_map(|intrinsic_name| {
1717
let c = runner_command(runner)
18-
.arg(format!("./c_programs/{intrinsic_name}"))
18+
.arg("./c_programs/intrinsic-test-programs")
19+
.arg(intrinsic_name)
1920
.output();
2021

2122
let rust = runner_command(runner)
2223
.arg(format!("target/{target}/release/{intrinsic_name}"))
23-
.env("RUSTFLAGS", "-Cdebuginfo=0")
2424
.output();
2525

2626
let (c, rust) = match (c, rust) {

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,24 @@ impl CppCompilation {
112112
&mut self.0
113113
}
114114

115-
pub fn run(&self, inputs: &[String], output: &str) -> std::io::Result<std::process::Output> {
115+
pub fn compile_object_file(
116+
&self,
117+
input: &str,
118+
output: &str,
119+
) -> std::io::Result<std::process::Output> {
120+
let mut cmd = clone_command(&self.0);
121+
cmd.args([input, "-c", "-o", output]);
122+
cmd.output()
123+
}
124+
125+
pub fn link_executable(
126+
&self,
127+
inputs: impl Iterator<Item = String>,
128+
output: &str,
129+
) -> std::io::Result<std::process::Output> {
116130
let mut cmd = clone_command(&self.0);
117131
cmd.args(inputs);
118132
cmd.args(["-o", output]);
119-
120133
cmd.output()
121134
}
122135
}

0 commit comments

Comments
 (0)