- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
ability to specify target CPU features #2883
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
Comments
related #2595 |
I plan to continue working on my PR (#2595) shortly. With the |
Can't we use the --target of clang for this? As far as I understand you can specify everything you can specify for -mcpu there. In addition the -mfloat and other options are specified with this as well. I am not sure whether the target tripple includes information about -mfpu and/or other cpu specifics? |
@ibutra Can you show an example of specifying all this information with |
You are right I can't specify everything. |
My PR already supports mcpu. As for the others, I would, although I am unsure of how to pass those along to LLVM. The current entry point for setting cpu and features is LLVMCreateTargetMachine, which doesn't seem to take those float options directly.
|
Matching the CLI of clang seems reasonable, however we do need to bring these concepts into zig land. A good start will be enumerating the options in target.hpp/target.cpp and exposing a corresponding type in |
This answere on StackOverflow shows how to at least get supported cpus and attributes/features by llvm. ~I couldn't find any information about fpu yet. ~ As for the float-abi I am unsure whether this is needed as it can be specified as part of the target tripple as far as I can see. Edit: I looked into this and llvm only has the values And here are the fpus for ARM: Link As far as I can see all cpus and features are defined in this folder in the |
I believe that when you select a cpu you essentially select a list of
features that are known to be implemented on that cpu.
Specifying specific features would then only be needed if there were
something special about your particular cpu that was different or if there
wasn't a pre-defined cpu that matched your specific hardware.
For example, from
http://www.llvm.org/svn/llvm-project/llvm/trunk/lib/Target/ARM/ARM.td
```
def : ProcessorModel<"cortex-m4", CortexM4Model, [ARMv7em,
FeatureVFP4_D16_SP,
FeaturePrefLoopAlign32,
FeatureHasSlowFPVMLx,
FeatureUseMISched,
FeatureUseAA,
FeatureHasNoBranchPredictor]>;
```
I think that if you were to do a triple of armv7em-freestanding-eabihf,
this is a valid triple for several cpus (Cortex-M4, Cortex-M7) with
different features.
Then if you were to further do `-mcpu=cortex-m4`, LLVM would know to
generate code that used the specific FPU on that cpu (vfp4-sp-d16), along
with the other attributes like that there is no branch predictor. The
Cortex-M7 has a different FPU (several possible ones?).
Is it possible to modify the cpu configuration further by adding and
removing attributes?
It's been a while since I looked at this, and I'm at work so I can't double
check, but the features that make up vfp4-sp-d16 are actually 3 different
attributes in the list that is returned when using ` llc -march=arm
-mattr=help`.
|
@andrewrk by "enumerating the options", do you mean enumerate all features/CPUs for each target zig supports? I ask because it is a long list that would have to be manually synchronized with LLVM, although there does not appear to be a way to query the LLVM API for the features and CPUs supported by a target (the lists are private with no clear way to retrieve them), so I am thinking that enumerating them might be the play. |
Yep that's what I mean. Currently the only backend of zig is LLVM but the language specification will not mention LLVM at all. LLVM is an implementation detail so the command line arguments and builtin declarations will not have LLVM-specific names. |
once #2883 is done this can be revisited
Until ability to specify target CPU features (#2883) is done, this commit gives riscv target better default features. This side-steps #3275 which is a deficiency in compiler-rt when features do not include 32 bit integer division. With this commit, RISC-V compiler-rt tests pass and Hello World works both pure-zig and with musl libc.
Here's a question concerning which CPUs and features to adopt... currently, the list of supported targets for Zig is based completely on what is available in LLVM, since that is the only backend as of now. Should all CPUs/features (defined for the targets supported by Zig) be blindly copied from LLVM? If not, this raises more questions concerning how to choose what CPUs/features to include. Otherwise, since the list of CPUs and features supported by LLVM is very long, future backends may not support all features. It seems as if a mapping between backends and supported targets/CPUs/features will be necessary, but not until a system to support multiple backends is in place. For now, I think that mirroring LLVM's CPUs/features is appropriate. Since a "CPU" in this case is just a list of features, the mappings here will be difficult to express using the enum-and-array situation currently used to describe the available targets/subtargets. I think having a Zig analog to LLVM's FeatureBitset would be helpful here, since each CPU could have its feature set defined in static memory. |
I've spent a bit of time researching how LLVM features and CPUs are defined, since Zig's only backend is LLVM at the moment and thus Zig's target-specific options need to map to LLVM's. Since each target is quite different, LLVM's TableGen target description language allows arbitrary feature nesting that gets resolved at compile time. Example: the AVR target defines Families, each of which contains the features of other Families and possibly additional features. From there, Devices are defined, each of which has an associated Family and possibly some additional features. Each Family is included in the final list of available features, as well as each "underlying" feature included in the Families. Thus, LLVM features can contain other features. TableGen boils these hierarchies down to a list of features when it generates subtarget code. Then the frontend How should Zig structure this information? LLVM has left the structure up to the targets since each one is quite different with respect to family/instruction set/subarch hierarchies. My proposal is to create abstract "catch-alls" for feature categories that should probably be separate. For instance, we could have A further question concerns how the initial CPU and feature data will be imported into Zig. Blindly copying LLVM will be difficult due to the arbitrary target representation mentioned above. I propose that important, well-known features be added for major targets initially, with others added as requested. This way, the new target abstractions can be tested on a minimal subset and the issues referenced above can be addressed ASAP. Thoughts? (@andrewrk) |
@layneson Your approach sounds reasonable to me.
👍
Either of these seems fine to me. One note: I think we can probably do all of this work self-hosted (in .zig code) and call into it from stage1, like we already do for lots of stuff. I believe the zig code would only have to expose to stage1 a function that essentially translated "zig format" CLI parameter data into "LLVM format". All the data structures, parsing, and understanding of what these features mean, etc, could be in zig code. |
Landed in 96e5f47 |
Zig currently will take full advantage of native CPU features when compiling for the native target, however when cross compiling, there is no way to specify which CPU features to enable.
zig targets
so that they are discoverablezig cc
when compiling C code and don't forget to add the params to the cache hash.@import("builtin")
.The text was updated successfully, but these errors were encountered: