@@ -1095,13 +1095,81 @@ extern "C" JL_DLLEXPORT const std::pair<std::string,std::string> &jl_get_llvm_di
10951095 {feature_masks, 0 }, {{}, 0 }, 0 });
10961096 return res;
10971097}
1098-
1098+ # ifndef __clang_gcanalyzer__
10991099extern " C" JL_DLLEXPORT std::vector<jl_target_spec_t > jl_get_llvm_clone_targets (void )
11001100{
1101- if (jit_targets.empty ())
1102- jl_error (" JIT targets not initialized" );
1101+ auto &cmdline = get_cmdline_targets ();
1102+ check_cmdline (cmdline, true );
1103+ llvm::SmallVector<TargetData<feature_sz>, 0 > image_targets;
1104+ for (auto &arg: cmdline) {
1105+ auto data = arg_target_data (arg, image_targets.empty ());
1106+ image_targets.push_back (std::move (data));
1107+ }
1108+
1109+ auto ntargets = image_targets.size ();
1110+ // Now decide the clone condition.
1111+ for (size_t i = 1 ; i < ntargets; i++) {
1112+ auto &t = image_targets[i];
1113+ if (t.en .flags & JL_TARGET_CLONE_ALL)
1114+ continue ;
1115+ // Always clone when code checks CPU features
1116+ t.en .flags |= JL_TARGET_CLONE_CPU;
1117+ // The most useful one in general...
1118+ t.en .flags |= JL_TARGET_CLONE_LOOP;
1119+ auto &features0 = image_targets[t.base ].en .features ;
1120+ // Special case for KNL/KNM since they're so different
1121+ if (!(t.dis .flags & JL_TARGET_CLONE_ALL)) {
1122+ if ((t.name == " knl" || t.name == " knm" ) &&
1123+ image_targets[t.base ].name != " knl" && image_targets[t.base ].name != " knm" ) {
1124+ t.en .flags |= JL_TARGET_CLONE_ALL;
1125+ break ;
1126+ }
1127+ }
1128+ static constexpr uint32_t clone_math[] = {Feature::fma, Feature::fma4};
1129+ static constexpr uint32_t clone_simd[] = {Feature::sse3, Feature::ssse3,
1130+ Feature::sse41, Feature::sse42,
1131+ Feature::avx, Feature::avx2,
1132+ Feature::vaes, Feature::vpclmulqdq,
1133+ Feature::sse4a, Feature::avx512f,
1134+ Feature::avx512dq, Feature::avx512ifma,
1135+ Feature::avx512pf, Feature::avx512er,
1136+ Feature::avx512cd, Feature::avx512bw,
1137+ Feature::avx512vl, Feature::avx512vbmi,
1138+ Feature::avx512vpopcntdq, Feature::avxvnni,
1139+ Feature::avx512vbmi2, Feature::avx512vnni,
1140+ Feature::avx512bitalg, Feature::avx512bf16,
1141+ Feature::avx512vp2intersect, Feature::avx512fp16};
1142+ for (auto fe: clone_math) {
1143+ if (!test_nbit (features0, fe) && test_nbit (t.en .features , fe)) {
1144+ t.en .flags |= JL_TARGET_CLONE_MATH;
1145+ break ;
1146+ }
1147+ }
1148+ for (auto fe: clone_simd) {
1149+ if (!test_nbit (features0, fe) && test_nbit (t.en .features , fe)) {
1150+ t.en .flags |= JL_TARGET_CLONE_SIMD;
1151+ break ;
1152+ }
1153+ }
1154+ static constexpr uint32_t clone_fp16[] = {Feature::avx512fp16};
1155+ for (auto fe: clone_fp16) {
1156+ if (!test_nbit (features0, fe) && test_nbit (t.en .features , fe)) {
1157+ t.en .flags |= JL_TARGET_CLONE_FLOAT16;
1158+ break ;
1159+ }
1160+ }
1161+ static constexpr uint32_t clone_bf16[] = {Feature::avx512bf16};
1162+ for (auto fe: clone_bf16) {
1163+ if (!test_nbit (features0, fe) && test_nbit (t.en .features , fe)) {
1164+ t.en .flags |= JL_TARGET_CLONE_BFLOAT16;
1165+ break ;
1166+ }
1167+ }
1168+ }
1169+ if (image_targets.empty ())
1170+ jl_error (" No targets specified" );
11031171 std::vector<jl_target_spec_t > res;
1104- for (auto &target: jit_targets ) {
1172+ for (auto &target: image_targets ) {
11051173 auto features_en = target.en .features ;
11061174 auto features_dis = target.dis .features ;
11071175 for (auto &fename: feature_names) {
@@ -1121,6 +1189,7 @@ extern "C" JL_DLLEXPORT std::vector<jl_target_spec_t> jl_get_llvm_clone_targets(
11211189 }
11221190 return res;
11231191}
1192+ #endif
11241193
11251194extern " C" int jl_test_cpu_feature (jl_cpu_feature_t feature)
11261195{
0 commit comments