From db9899a38f0fef1b11aafb97b079602ff2eb0807 Mon Sep 17 00:00:00 2001 From: wangcheng22 Date: Thu, 23 May 2024 16:32:35 -0700 Subject: [PATCH] Add HVX_v68 target to support Hexagon HVX v68. --- .../src/halide/halide_/PyEnums.cpp | 1 + src/CodeGen_Hexagon.cpp | 14 ++++++++++-- src/CodeGen_Internal.cpp | 10 ++++++++- src/HexagonOffload.cpp | 6 ++++- src/HexagonOptimize.cpp | 22 ++++++++++++++++--- src/LLVM_Runtime_Linker.cpp | 3 ++- src/Target.cpp | 10 +++++++++ src/Target.h | 1 + src/runtime/HalideRuntime.h | 1 + test/correctness/gather.cpp | 3 ++- test/correctness/hexagon_scatter.cpp | 3 ++- test/correctness/histogram.cpp | 3 ++- test/correctness/simd_op_check_hvx.cpp | 7 ++++-- 13 files changed, 71 insertions(+), 13 deletions(-) diff --git a/python_bindings/src/halide/halide_/PyEnums.cpp b/python_bindings/src/halide/halide_/PyEnums.cpp index 4edd8029c340..5a442bdca737 100644 --- a/python_bindings/src/halide/halide_/PyEnums.cpp +++ b/python_bindings/src/halide/halide_/PyEnums.cpp @@ -148,6 +148,7 @@ void define_enums(py::module &m) { .value("HVX_v62", Target::Feature::HVX_v62) .value("HVX_v65", Target::Feature::HVX_v65) .value("HVX_v66", Target::Feature::HVX_v66) + .value("HVX_v68", Target::Feature::HVX_v68) .value("FuzzFloatStores", Target::Feature::FuzzFloatStores) .value("SoftFloatABI", Target::Feature::SoftFloatABI) .value("MSAN", Target::Feature::MSAN) diff --git a/src/CodeGen_Hexagon.cpp b/src/CodeGen_Hexagon.cpp index a77e9c7c1a76..8c27fadf82f0 100644 --- a/src/CodeGen_Hexagon.cpp +++ b/src/CodeGen_Hexagon.cpp @@ -128,7 +128,9 @@ class CodeGen_Hexagon : public CodeGen_Posix { CodeGen_Hexagon::CodeGen_Hexagon(const Target &t) : CodeGen_Posix(t) { - if (target.has_feature(Halide::Target::HVX_v66)) { + if (target.has_feature(Halide::Target::HVX_v68)) { + isa_version = 68; + } else if (target.has_feature(Halide::Target::HVX_v66)) { isa_version = 66; } else if (target.has_feature(Halide::Target::HVX_v65)) { isa_version = 65; @@ -1787,7 +1789,9 @@ Value *CodeGen_Hexagon::call_intrin(llvm::Type *result_type, const string &name, } string CodeGen_Hexagon::mcpu_target() const { - if (target.has_feature(Halide::Target::HVX_v66)) { + if (target.has_feature(Halide::Target::HVX_v68)) { + return "hexagonv68"; + } else if (target.has_feature(Halide::Target::HVX_v66)) { return "hexagonv66"; } else if (target.has_feature(Halide::Target::HVX_v65)) { return "hexagonv65"; @@ -1856,6 +1860,12 @@ void CodeGen_Hexagon::visit(const Mul *op) { return; } + // v68 has vector support for single-precision float. + if (target.has_feature(Halide::Target::HVX_v68) && + op->type.is_float() && op->type.bits() == 32) { + CodeGen_Posix::visit(op); + return; + } internal_error << "Unhandled HVX multiply " << op->a.type() << "*" << op->b.type() << "\n" << Expr(op) << "\n"; diff --git a/src/CodeGen_Internal.cpp b/src/CodeGen_Internal.cpp index 697b9200fa33..b68373f23ccf 100644 --- a/src/CodeGen_Internal.cpp +++ b/src/CodeGen_Internal.cpp @@ -674,8 +674,16 @@ std::unique_ptr make_target_machine(const llvm::Module &mod #else const auto opt_level = llvm::CodeGenOpt::Aggressive; #endif + + // Get module mcpu_target and mattrs. + std::string mcpu_target; + get_md_string(module.getModuleFlag("halide_mcpu_target"), mcpu_target); + std::string mattrs; + get_md_string(module.getModuleFlag("halide_mattrs"), mattrs); + auto *tm = llvm_target->createTargetMachine(module.getTargetTriple(), - /*CPU target=*/"", /*Features=*/"", + mcpu_target, + mattrs, options, use_pic ? llvm::Reloc::PIC_ : llvm::Reloc::Static, use_large_code_model ? llvm::CodeModel::Large : llvm::CodeModel::Small, diff --git a/src/HexagonOffload.cpp b/src/HexagonOffload.cpp index 99db0413a5ba..221eb9fbd042 100644 --- a/src/HexagonOffload.cpp +++ b/src/HexagonOffload.cpp @@ -43,6 +43,7 @@ enum { EF_HEXAGON_MACH_V62 = 0x62, EF_HEXAGON_MACH_V65 = 0x65, EF_HEXAGON_MACH_V66 = 0x66, + EF_HEXAGON_MACH_V68 = 0x68, }; enum { @@ -551,7 +552,9 @@ class HexagonLinker : public Linker { uint32_t flags; HexagonLinker(const Target &target) { - if (target.has_feature(Target::HVX_v66)) { + if (target.has_feature(Target::HVX_v68)) { + flags = Elf::EF_HEXAGON_MACH_V68; + } else if (target.has_feature(Target::HVX_v66)) { flags = Elf::EF_HEXAGON_MACH_V66; } else if (target.has_feature(Target::HVX_v65)) { flags = Elf::EF_HEXAGON_MACH_V65; @@ -983,6 +986,7 @@ Stmt inject_hexagon_rpc(Stmt s, const Target &host_target, Target::HVX_v62, Target::HVX_v65, Target::HVX_v66, + Target::HVX_v68, }; for (Target::Feature i : shared_features) { if (host_target.has_feature(i)) { diff --git a/src/HexagonOptimize.cpp b/src/HexagonOptimize.cpp index a123738fe298..6834d4abe7f3 100644 --- a/src/HexagonOptimize.cpp +++ b/src/HexagonOptimize.cpp @@ -106,6 +106,13 @@ string type_suffix(Type type, bool signed_variants) { default: break; } + } else if (type.is_float()) { + switch (type.bits()) { + case 32: + return prefix + "sf"; + default: + break; + } } internal_error << "Unsupported HVX type: " << type << "\n"; return ""; @@ -194,6 +201,7 @@ struct Pattern { v65orLater = 1 << 11, // Pattern should be matched only for v65 target or later v66orLater = 1 << 12, // Pattern should be matched only for v66 target or later + v68orLater = 1 << 13, // Pattern should be matched only for v68 target or later }; string intrin; // Name of the intrinsic @@ -227,11 +235,16 @@ Expr wild_i64x = Variable::make(Type(Type::Int, 64, 0), "*"); // Check if a pattern with flags 'flags' is supported on the target. bool check_pattern_target(int flags, const Target &target) { if ((flags & (Pattern::v65orLater)) && - !target.features_any_of({Target::HVX_v65, Target::HVX_v66})) { + !target.features_any_of({Target::HVX_v65, Target::HVX_v66, + Target::HVX_v68})) { return false; } if ((flags & (Pattern::v66orLater)) && - !target.features_any_of({Target::HVX_v66})) { + !target.features_any_of({Target::HVX_v66, Target::HVX_v68})) { + return false; + } + if ((flags & (Pattern::v68orLater)) && + !target.features_any_of({Target::HVX_v68})) { return false; } return true; @@ -1722,6 +1735,7 @@ class EliminateInterleaves : public IRMutator { v62orLater, // Use for Hexagon v62 target or later v65orLater, // Use for Hexagon v65 target or later v66orLater, // Use for Hexagon v66 target or later + v68orLater, // Use for Hexagon v68 target or later }; HvxTarget hvx_target; @@ -1943,6 +1957,8 @@ class EliminateInterleaves : public IRMutator { hvx_target = HvxTarget::v65orLater; } else if (t.features_any_of({Target::HVX_v66})) { hvx_target = HvxTarget::v66orLater; + } else if (t.features_any_of({Target::HVX_v68})) { + hvx_target = HvxTarget::v68orLater; } else { hvx_target = HvxTarget::v62orLater; } @@ -2294,4 +2310,4 @@ Stmt optimize_hexagon_instructions(Stmt s, const Target &t) { } } // namespace Internal -} // namespace Halide \ No newline at end of file +} // namespace Halide diff --git a/src/LLVM_Runtime_Linker.cpp b/src/LLVM_Runtime_Linker.cpp index e85331ee4eca..69f32c35831e 100644 --- a/src/LLVM_Runtime_Linker.cpp +++ b/src/LLVM_Runtime_Linker.cpp @@ -1129,7 +1129,8 @@ std::unique_ptr get_initial_module_for_target(Target t, llvm::LLVM if (t.arch == Target::Hexagon) { modules.push_back(get_initmod_qurt_hvx(c, bits_64, debug)); modules.push_back(get_initmod_hvx_128_ll(c)); - if (t.features_any_of({Target::HVX_v65, Target::HVX_v66})) { + if (t.features_any_of({Target::HVX_v65, Target::HVX_v66, + Target::HVX_v68})) { modules.push_back(get_initmod_qurt_hvx_vtcm(c, bits_64, debug)); } diff --git a/src/Target.cpp b/src/Target.cpp index ac96ae019065..53e85196dae3 100644 --- a/src/Target.cpp +++ b/src/Target.cpp @@ -338,6 +338,7 @@ bool is_using_hexagon(const Target &t) { t.has_feature(Target::HVX_v62) || t.has_feature(Target::HVX_v65) || t.has_feature(Target::HVX_v66) || + t.has_feature(Target::HVX_v68) || t.has_feature(Target::HexagonDma) || t.arch == Target::Hexagon); } @@ -355,6 +356,9 @@ int get_hvx_lower_bound(const Target &t) { if (t.has_feature(Target::HVX_v66)) { return 66; } + if (t.has_feature(Target::HVX_v68)) { + return 68; + } return 60; } @@ -543,6 +547,7 @@ const std::map feature_name_map = { {"hvx_v62", Target::HVX_v62}, {"hvx_v65", Target::HVX_v65}, {"hvx_v66", Target::HVX_v66}, + {"hvx_v68", Target::HVX_v68}, {"fuzz_float_stores", Target::FuzzFloatStores}, {"soft_float_abi", Target::SoftFloatABI}, {"msan", Target::MSAN}, @@ -892,6 +897,7 @@ void Target::validate_features() const { HVX_v62, HVX_v65, HVX_v66, + HVX_v68, NoNEON, POWER_ARCH_2_07, RVV, @@ -1371,6 +1377,7 @@ bool Target::get_runtime_compatible_target(const Target &other, Target &result) HVX_v62, HVX_v65, HVX_v66, + HVX_v68, VulkanV10, VulkanV12, VulkanV13, @@ -1515,6 +1522,9 @@ bool Target::get_runtime_compatible_target(const Target &other, Target &result) if (hvx_version < 66) { output.features.reset(HVX_v66); } + if (hvx_version < 68) { + output.features.reset(HVX_v68); + } result = output; return true; diff --git a/src/Target.h b/src/Target.h index 3bc586822f75..7150513e6451 100644 --- a/src/Target.h +++ b/src/Target.h @@ -122,6 +122,7 @@ struct Target { HVX_v62 = halide_target_feature_hvx_v62, HVX_v65 = halide_target_feature_hvx_v65, HVX_v66 = halide_target_feature_hvx_v66, + HVX_v68 = halide_target_feature_hvx_v68, FuzzFloatStores = halide_target_feature_fuzz_float_stores, SoftFloatABI = halide_target_feature_soft_float_abi, MSAN = halide_target_feature_msan, diff --git a/src/runtime/HalideRuntime.h b/src/runtime/HalideRuntime.h index b02890a23f55..3a70babf1e7d 100644 --- a/src/runtime/HalideRuntime.h +++ b/src/runtime/HalideRuntime.h @@ -1409,6 +1409,7 @@ typedef enum halide_target_feature_t { halide_target_feature_trace_pipeline, ///< Trace the pipeline. halide_target_feature_hvx_v65, ///< Enable Hexagon v65 architecture. halide_target_feature_hvx_v66, ///< Enable Hexagon v66 architecture. + halide_target_feature_hvx_v68, ///< Enable Hexagon v68 architecture. halide_target_feature_cl_half, ///< Enable half support on OpenCL targets halide_target_feature_strict_float, ///< Turn off all non-IEEE floating-point optimization. Currently applies only to LLVM targets. halide_target_feature_tsan, ///< Enable hooks for TSAN support. diff --git a/test/correctness/gather.cpp b/test/correctness/gather.cpp index 2d9bef71f326..8be533be9c9b 100644 --- a/test/correctness/gather.cpp +++ b/test/correctness/gather.cpp @@ -49,7 +49,8 @@ bool test() { .parallel(y) .vectorize(x, vector_size); - if (target.features_any_of({Target::HVX_v65, Target::HVX_v66})) { + if (target.features_any_of({Target::HVX_v65, Target::HVX_v66, + Target::HVX_v68})) { lut_vtcm .store_in(MemoryType::VTCM) .compute_at(output, Var::outermost()) diff --git a/test/correctness/hexagon_scatter.cpp b/test/correctness/hexagon_scatter.cpp index 6fde0669ac19..83181d4f813a 100644 --- a/test/correctness/hexagon_scatter.cpp +++ b/test/correctness/hexagon_scatter.cpp @@ -76,7 +76,8 @@ int test() { .parallel(y) .vectorize(x, vector_size / 2); - if (target.features_any_of({Target::HVX_v65, Target::HVX_v66})) { + if (target.features_any_of({Target::HVX_v65, Target::HVX_v66, + Target::HVX_v68})) { f.store_in(MemoryType::VTCM); } } diff --git a/test/correctness/histogram.cpp b/test/correctness/histogram.cpp index bfb69058402d..b21363745487 100644 --- a/test/correctness/histogram.cpp +++ b/test/correctness/histogram.cpp @@ -50,7 +50,8 @@ bool test() { .compute_at(g, Var::outermost()) .vectorize(x, vector_size); - if (target.features_any_of({Target::HVX_v65, Target::HVX_v66})) { + if (target.features_any_of({Target::HVX_v65, Target::HVX_v66, + Target::HVX_v68})) { hist.store_in(MemoryType::VTCM); hist diff --git a/test/correctness/simd_op_check_hvx.cpp b/test/correctness/simd_op_check_hvx.cpp index db9564b9e460..d07a74989773 100644 --- a/test/correctness/simd_op_check_hvx.cpp +++ b/test/correctness/simd_op_check_hvx.cpp @@ -13,7 +13,7 @@ // simd_op_check into two tests, simd_op_check.cpp and simd_op_check_hvx.cpp // so that the latter is free to do its own thing - for simd_op_check_hvx.cpp // to run any tests, all that is needed is that HL_TARGET have a HVX related -// target feature, i.e. one of HVX, HVX_v62, HVX_v65 and HVX_v66. +// target feature, i.e. one of HVX, HVX_v62, HVX_v65, HVX_v66 and HVX_v68. using namespace Halide; using namespace Halide::ConciseCasts; @@ -44,7 +44,9 @@ class SimdOpCheckHVX : public SimdOpCheckTest { constexpr int hvx_width = 128; int isa_version; - if (target.has_feature(Halide::Target::HVX_v66)) { + if (target.has_feature(Halide::Target::HVX_v68)) { + isa_version = 68; + } else if (target.has_feature(Halide::Target::HVX_v66)) { isa_version = 66; } else if (target.has_feature(Halide::Target::HVX_v65)) { isa_version = 65; @@ -718,5 +720,6 @@ int main(int argc, char **argv) { Target("hexagon-32-noos-hvx-hvx_128-hvx_v62"), Target("hexagon-32-noos-hvx-hvx_128-hvx_v65"), Target("hexagon-32-noos-hvx-hvx_128-hvx_v66"), + Target("hexagon-32-noos-hvx-hvx_128-hvx_v68"), }); }