From 62d78d61fa0d2a0aeb375f0cded57434721c4f3f Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Wed, 18 Mar 2026 05:13:44 +0900 Subject: [PATCH] src: Allow clang-style `+`/`-` for target features This largely works as expected, except that as far as I can tell, without explicit annotations added to the caller, (or a `#force_inline`), the LLVM `target-features` function attribute gets ignored by the inliner under the rationale of `-sse,-avx,-avx2` is a subset of `+sse,+avx,+avx2`. With `#force_no_inline` the correct code does get generated, but in the regression I am trying to fix, the caller gratuitously also uses SIMD, leading to horrific performance. --- src/build_settings.cpp | 27 ++++++++++++++++++++------- src/llvm_backend_proc.cpp | 5 ++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d52553d65..9663d5db5 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2160,8 +2160,15 @@ gb_internal bool check_target_feature_is_valid(String const &feature, TargetArch String_Iterator it = {feature, 0}; for (;;) { String str = string_split_iterator(&it, ','); - if (str == "") break; - if (!check_single_target_feature_is_valid(feature_list, str)) { + String feature_str = str; + if (string_starts_with(feature_str, '+') || string_starts_with(feature_str, '-')) { + feature_str = substring(feature_str, 1, feature_str.len); + if (feature_str == "") { + return false; + } + } + if (feature_str == "") break; + if (!check_single_target_feature_is_valid(feature_list, feature_str)) { if (invalid) *invalid = str; return false; } @@ -2201,20 +2208,26 @@ gb_internal bool check_target_feature_is_enabled(String const &feature, String * String_Iterator it = {feature, 0}; for (;;) { String str = string_split_iterator(&it, ','); - if (str == "") break; + String feature_str = str; + bool want_enabled = true; + if (string_starts_with(feature_str, '+') || string_starts_with(feature_str, '-')) { + want_enabled = feature_str[0] == '+'; + feature_str = substring(feature_str, 1, feature_str.len); + } + if (feature_str == "") break; if (!string_set_exists(&build_context.target_features_set, str)) { - String plus_str = concatenate_strings(temporary_allocator(), make_string_c("+"), str); + String plus_str = concatenate_strings(temporary_allocator(), make_string_c("+"), feature_str); - if (!string_set_exists(&build_context.target_features_set, plus_str)) { + if (want_enabled && !string_set_exists(&build_context.target_features_set, plus_str)) { if (not_enabled) *not_enabled = str; return false; } } - String minus_str = concatenate_strings(temporary_allocator(), make_string_c("-"), str); + String minus_str = concatenate_strings(temporary_allocator(), make_string_c("-"), feature_str); - if (string_set_exists(&build_context.target_features_set, minus_str)) { + if (!want_enabled && !string_set_exists(&build_context.target_features_set, minus_str)) { if (not_enabled) *not_enabled = str; return false; } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 36d736b0f..7d0379e9a 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -201,12 +201,15 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i for (;;) { String str = string_split_iterator(&it, ','); if (str == "") break; + bool add_prefix = !(string_starts_with(str, '+') || string_starts_with(str, '-')); if (!first) { feature_str = gb_string_appendc(feature_str, ","); } first = false; - feature_str = gb_string_appendc(feature_str, "+"); + if (add_prefix) { + feature_str = gb_string_appendc(feature_str, "+"); + } feature_str = gb_string_append_length(feature_str, str.text, str.len); }