-
Notifications
You must be signed in to change notification settings - Fork 287
Re-organize intrinsic-test
to enable seamless addition of behaviour testing for more architectures
#1758
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
9900e81
to
546554d
Compare
The module should be called |
@JamieCunliffe feel free to have a look at this since you are the original author of intrinsic-test. This is part of a GSoC project to extend intrinsic-test to other architectures. |
546554d
to
3ff317f
Compare
Reasoning: 1. Majority of code assumes the usage of `Intrinsic` and related types, which is derived from the JSON structure of the ARM intrinsics JSON source file 2. Further commits will start with extracting common parts of the code (eg: Create C/Rust file, Build C/Rust file, etc)
3ff317f
to
bd0a675
Compare
…ted for different architectures. Next steps: Move the existing ARM-specific implementation into one that fits well with this trait.
5dce230
to
7ff8497
Compare
Are we using the |
a12b4a4
to
ff10311
Compare
|
3068c9d
to
2d1e482
Compare
…le_rust and compare_outputs
e0b0301
to
54a678c
Compare
54a678c
to
2777ceb
Compare
448e336
to
f3f4f7c
Compare
f3f4f7c
to
358016a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! I think types.rs would map fine to x86 with a little modification.
I'd just like to add that Scalable Vectors will be added to this tool at some point - the Arm code is here and it would probably be useful for RISC-V in the future too.
Don't worry about conflicts with that PR (it's very old and needs a rework) and I don't think there's anything particularly different about how intrinsic-test needs to work but scalable vectors do add an extra dimension of complexity to the tool.
.arg(format!("{runner} ./c_programs/{intrinsic_name}")) | ||
.output(); | ||
|
||
let rust = if SPECIAL_TARGETS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be collapsed into 1 if, it's what I did with https://github.com/rust-lang/stdarch/pull/1771/files#diff-7c34e890416eb66d4462c7f31278409c662bb808a57c3e0a4d13c232c64533a9
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, let me do that.
name = "Intrinsic test tool", | ||
about = "Generates Rust and C programs for intrinsics and compares the output" | ||
)] | ||
pub struct Cli { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems an odd file name for the CLI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll need to rename the files, I started off by focussing on the code refactor side of things.
Thank you for sharing this observation with me.
Over the last 4 commits I changed from the This allowed me to refactor a lot more code into the Where it differed was in the usage of the At the moment, each architecture can define:
I've made some changes in the C testfile-generation part, will pinpoint them in the next message. After this part, I intend to work on:
|
16c89b0
to
9eb138d
Compare
Updating what I did over the last 4 commits:
What I'll do next:
|
fn gen_code_c( | ||
indentation: Indentation, | ||
intrinsic: &Intrinsic<ArmIntrinsicType, Constraint>, | ||
constraints: &[&Argument<ArmIntrinsicType, Constraint>], | ||
name: String, | ||
target: &str, | ||
) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might be best for the gen_code_c
and gen_code_rust
functions to stay module-specific. Would this be a good idea @Amanieu @adamgemmell ?
Constraints seem like a very ARM thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think overall you should try to keep as much generic as possible until you find an example of an intrinsic that wouldn't work otherwise - no point trying to guess what the thousands of intrinsics will want at this point.
If an architecture doesn't have any Constraints you could pass it an empty slice and that would be fine. Constraints are the "top-level" of generated code per intrinsic so it would be a bit awkward for the generator to go to platform-specific code and then jump back to generic code that might need to be aware of what constraints were set up and how they were named.
Constraints really are for anything const (i.e. needs to end up as an immediate at the assembly level), including enums. Scanning x86_64 intrinsics I found a few examples that would require a constraint (if you were to keep this model around):
- https://doc.rust-lang.org/core/arch/x86_64/fn._mm512_getmant_round_ps.html takes some enums - the test tool doesn't currently need to handle any enums but I chose a new Constraint variant to represent each enum in SVE. This might not be best overall given there's loads of enums x86.
- https://doc.rust-lang.org/core/arch/x86_64/fn._mm512_fpclass_pd_mask.html takes a const IMM8 from 0 to 0xFF, not using the full i32 range of the function parameter.
I think what you end up doing depends on how your intrinsic reference is written too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see
let mut command = CompilationCommandBuilder::new() | ||
.add_arch_flags(vec!["armv8.6-a", "crypto", "crc", "dotprod", "fp16"]) | ||
.set_compiler(compiler) | ||
.set_target(target) | ||
.set_opt_level("2") | ||
.set_cxx_toolchain_dir(cxx_toolchain_dir) | ||
.set_project_root("c_programs") | ||
.add_extra_flags(vec!["-ffp-contract=off", "-Wno-narrowing"]); | ||
|
||
if !target.contains("v7") { | ||
command = command.add_arch_flags(vec!["fanimalux", "lut", "sha3"]); | ||
} | ||
|
||
command = if target == "aarch64_be-unknown-linux-gnu" { | ||
command | ||
.set_linker( | ||
cxx_toolchain_dir.unwrap_or("").to_string() + "/bin/aarch64_be-none-linux-gnu-g++", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also wanted to ask if the if
blocks are being too unclean here. I adopted a factory pattern to build out these commands.
Does this look appropriate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The factory pattern looks good! If statements for these targets are unavoidable, don't worry about them.
Why do you have a set_target
call and then manually below set the target again if it's clang?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh thanks for pointing that out.
Initially I thought -target
and —target
had different meanings. I completely forgot to remove one of them upon clarification
17135e7
to
f2923fa
Compare
0eeae76
to
39091eb
Compare
39091eb
to
f4650c0
Compare
Updates so far
arm
module, exposing only atest
function atsrc/main.rs
SupportedArchitectureTest
trait that has been implemented forarm
and should be implemented for other architectures too. Allows us to expose functionality like building C/Rust test files and comparing outputs.common
module for reuse by other architectures too.match
block for selection of architectures using thetarget
CLI variable.Reasoning
Intrinsic
type may be specific to architectures, hence the implementation of a trait helps us to abstract the usage of such data types within the architecture-specific moduleNew architecture of
intrinsic-test