Skip to content
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

Add ARMv8.x feature flags #4489

Merged
merged 13 commits into from
Jul 23, 2024
8 changes: 8 additions & 0 deletions python_bindings/src/halide/halide_/PyEnums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ void define_enums(py::module &m) {
.value("LLVMLargeCodeModel", Target::Feature::LLVMLargeCodeModel)
.value("RVV", Target::Feature::RVV)
.value("ARMv81a", Target::Feature::ARMv81a)
.value("ARMv82a", Target::Feature::ARMv82a)
.value("ARMv83a", Target::Feature::ARMv83a)
.value("ARMv84a", Target::Feature::ARMv84a)
.value("ARMv85a", Target::Feature::ARMv85a)
.value("ARMv86a", Target::Feature::ARMv86a)
.value("ARMv87a", Target::Feature::ARMv87a)
.value("ARMv88a", Target::Feature::ARMv88a)
.value("ARMv89a", Target::Feature::ARMv89a)
.value("SanitizerCoverage", Target::Feature::SanitizerCoverage)
.value("ProfileByTimer", Target::Feature::ProfileByTimer)
.value("SPIRV", Target::Feature::SPIRV)
Expand Down
67 changes: 63 additions & 4 deletions src/CodeGen_ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,41 @@ using namespace llvm;

namespace {

// Populate feature flags in a target according to those implied by
// existing flags, so that instruction patterns can just check for the
// oldest feature flag that supports an instruction.
//
// According to LLVM, ARM architectures have the following is-a-superset-of
// relationships:
//
// v9.5a > v9.4a > v9.3a > v9.2a > v9.1a > v9a;
// v v v v v
// v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > v8.4a > ... > v8a;
//
// v8r has no relation to anything.
Target complete_arm_target(Target t) {
constexpr int num_arm_v8_features = 9;
static const Target::Feature arm_v8_features[num_arm_v8_features] = {
Target::ARMv89a,
Target::ARMv88a,
Target::ARMv87a,
Target::ARMv86a,
Target::ARMv85a,
Target::ARMv84a,
Target::ARMv83a,
Target::ARMv82a,
Target::ARMv81a,
};

for (int i = 0; i < num_arm_v8_features - 1; i++) {
if (t.has_feature(arm_v8_features[i])) {
t.set_feature(arm_v8_features[i + 1]);
}
}

return t;
}

// Substitute in loads that feed into slicing shuffles, to help with vld2/3/4
// emission. These are commonly lifted as lets because they get used by multiple
// interleaved slices of the same load.
Expand Down Expand Up @@ -201,7 +236,7 @@ class CodeGen_ARM : public CodeGen_Posix {
};

CodeGen_ARM::CodeGen_ARM(const Target &target)
: CodeGen_Posix(target) {
: CodeGen_Posix(complete_arm_target(target)) {

// TODO(https://github.com/halide/Halide/issues/8088): See if
// use_llvm_vp_intrinsics can replace architecture specific code in this
Expand Down Expand Up @@ -2445,9 +2480,9 @@ string CodeGen_ARM::mcpu_target() const {
}
} else {
if (target.os == Target::IOS) {
return "cyclone";
return "apple-a7";
} else if (target.os == Target::OSX) {
return "apple-a12";
return "apple-m1";
} else if (target.has_feature(Target::SVE2)) {
return "cortex-x1";
} else {
Expand All @@ -2468,6 +2503,30 @@ string CodeGen_ARM::mattrs() const {
if (target.has_feature(Target::ARMv81a)) {
attrs.emplace_back("+v8.1a");
}
if (target.has_feature(Target::ARMv82a)) {
attrs.emplace_back("+v8.2a");
}
if (target.has_feature(Target::ARMv83a)) {
attrs.emplace_back("+v8.3a");
}
if (target.has_feature(Target::ARMv84a)) {
attrs.emplace_back("+v8.4a");
}
if (target.has_feature(Target::ARMv85a)) {
attrs.emplace_back("+v8.5a");
}
if (target.has_feature(Target::ARMv86a)) {
attrs.emplace_back("+v8.6a");
}
if (target.has_feature(Target::ARMv87a)) {
attrs.emplace_back("+v8.7a");
}
if (target.has_feature(Target::ARMv88a)) {
attrs.emplace_back("+v8.8a");
}
if (target.has_feature(Target::ARMv89a)) {
attrs.emplace_back("+v8.9a");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If target has been completed at this point, isn't this going to add attrs for everything requested and below? Is LLVM cool with that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, good question.

if (target.has_feature(Target::ARMDotProd)) {
attrs.emplace_back("+dotprod");
}
Expand All @@ -2482,7 +2541,7 @@ string CodeGen_ARM::mattrs() const {
}
} else {
// TODO: Should Halide's SVE flags be 64-bit only?
// TODO: Sound we ass "-neon" if NoNEON is set? Does this make any sense?
// TODO: Should we add "-neon" if NoNEON is set? Does this make any sense?
if (target.has_feature(Target::SVE2)) {
attrs.emplace_back("+sve2");
} else if (target.has_feature(Target::SVE)) {
Expand Down
18 changes: 17 additions & 1 deletion src/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,14 @@ const std::map<std::string, Target::Feature> feature_name_map = {
{"llvm_large_code_model", Target::LLVMLargeCodeModel},
{"rvv", Target::RVV},
{"armv81a", Target::ARMv81a},
{"armv82a", Target::ARMv82a},
{"armv83a", Target::ARMv83a},
{"armv84a", Target::ARMv84a},
{"armv85a", Target::ARMv85a},
{"armv86a", Target::ARMv86a},
{"armv87a", Target::ARMv87a},
{"armv88a", Target::ARMv88a},
{"armv89a", Target::ARMv89a},
{"sanitizer_coverage", Target::SanitizerCoverage},
{"profile_by_timer", Target::ProfileByTimer},
{"spirv", Target::SPIRV},
Expand Down Expand Up @@ -1385,9 +1393,17 @@ bool Target::get_runtime_compatible_target(const Target &other, Target &result)
// clang-format on

// clang-format off
const std::array<Feature, 15> intersection_features = {{
const std::array<Feature, 23> intersection_features = {{
ARMv7s,
ARMv81a,
ARMv82a,
ARMv83a,
ARMv84a,
ARMv85a,
ARMv86a,
ARMv87a,
ARMv88a,
ARMv89a,
alexreinking marked this conversation as resolved.
Show resolved Hide resolved
AVX,
AVX2,
AVX512,
Expand Down
8 changes: 8 additions & 0 deletions src/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ struct Target {
LLVMLargeCodeModel = halide_llvm_large_code_model,
RVV = halide_target_feature_rvv,
ARMv81a = halide_target_feature_armv81a,
ARMv82a = halide_target_feature_armv82a,
ARMv83a = halide_target_feature_armv83a,
ARMv84a = halide_target_feature_armv84a,
ARMv85a = halide_target_feature_armv85a,
ARMv86a = halide_target_feature_armv86a,
ARMv87a = halide_target_feature_armv87a,
ARMv88a = halide_target_feature_armv88a,
ARMv89a = halide_target_feature_armv89a,
SanitizerCoverage = halide_target_feature_sanitizer_coverage,
ProfileByTimer = halide_target_feature_profile_by_timer,
SPIRV = halide_target_feature_spirv,
Expand Down
10 changes: 9 additions & 1 deletion src/runtime/HalideRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -1434,7 +1434,15 @@ typedef enum halide_target_feature_t {
halide_target_feature_arm_fp16, ///< Enable ARMv8.2-a half-precision floating point data processing
halide_llvm_large_code_model, ///< Use the LLVM large code model to compile
halide_target_feature_rvv, ///< Enable RISCV "V" Vector Extension
halide_target_feature_armv81a, ///< Enable ARMv8.1-a instructions
halide_target_feature_armv81a, ///< Enable ARMv8.1a instructions
halide_target_feature_armv82a, ///< Enable ARMv8.2a instructions
halide_target_feature_armv83a, ///< Enable ARMv8.3a instructions
halide_target_feature_armv84a, ///< Enable ARMv8.4a instructions
halide_target_feature_armv85a, ///< Enable ARMv8.5a instructions
halide_target_feature_armv86a, ///< Enable ARMv8.6a instructions
halide_target_feature_armv87a, ///< Enable ARMv8.7a instructions
halide_target_feature_armv88a, ///< Enable ARMv8.8a instructions
halide_target_feature_armv89a, ///< Enable ARMv8.9a instructions
halide_target_feature_sanitizer_coverage, ///< Enable hooks for SanitizerCoverage support.
halide_target_feature_profile_by_timer, ///< Alternative to halide_target_feature_profile using timer interrupt for systems without threads or applicartions that need to avoid them.
halide_target_feature_spirv, ///< Enable SPIR-V code generation support.
Expand Down
9 changes: 9 additions & 0 deletions test/correctness/cross_compilation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ int main(int argc, char **argv) {
"arm-64-android",
"arm-64-android-hvx",
"arm-64-ios",
"arm-64-ios-armv81a",
"arm-64-ios-armv82a",
"arm-64-ios-armv83a",
"arm-64-ios-armv84a",
"arm-64-ios-armv85a",
"arm-64-ios-armv86a",
"arm-64-ios-armv87a",
"arm-64-ios-armv88a",
"arm-64-ios-armv89a",
"arm-64-linux",
"arm-64-noos-semihosting",
"arm-64-windows",
Expand Down
8 changes: 8 additions & 0 deletions test/correctness/simd_op_check.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ class SimdOpCheckTest {
Target::ARMFp16,
Target::ARMv7s,
Target::ARMv81a,
Target::ARMv82a,
Target::ARMv83a,
Target::ARMv84a,
Target::ARMv85a,
Target::ARMv86a,
Target::ARMv87a,
Target::ARMv88a,
Target::ARMv89a,
Target::AVX,
Target::AVX2,
Target::AVX512,
Expand Down
Loading