diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 39 | ||||
-rw-r--r-- | gcc/Makefile.in | 1 | ||||
-rw-r--r-- | gcc/cgraph.c | 2 | ||||
-rw-r--r-- | gcc/cgraph.h | 8 | ||||
-rw-r--r-- | gcc/ipa.c | 3 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 4 | ||||
-rw-r--r-- | gcc/omp-general.c | 305 | ||||
-rw-r--r-- | gcc/omp-offload.c | 22 | ||||
-rw-r--r-- | gcc/omp-simd-clone.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 2 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/declare-variant-14.c | 28 | ||||
-rw-r--r-- | gcc/tree-inline.c | 4 |
12 files changed, 409 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0f0dbd0..360ad7a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,44 @@ 2020-05-14 Jakub Jelinek <jakub@redhat.com> + * Makefile.in (GTFILES): Add omp-general.c. + * cgraph.h (struct cgraph_node): Add declare_variant_alt and + calls_declare_variant_alt members and initialize them in the + ctor. + * ipa.c (symbol_table::remove_unreachable_nodes): Handle direct + calls to declare_variant_alt nodes. + * lto-cgraph.c (lto_output_node): Write declare_variant_alt + and calls_declare_variant_alt. + (input_overwrite_node): Read them back. + * omp-simd-clone.c (simd_clone_create): Copy calls_declare_variant_alt + bit. + * tree-inline.c (expand_call_inline): Or in calls_declare_variant_alt + bit. + (tree_function_versioning): Copy calls_declare_variant_alt bit. + * omp-offload.c (execute_omp_device_lower): Call + omp_resolve_declare_variant on direct function calls. + (pass_omp_device_lower::gate): Also enable for + calls_declare_variant_alt functions. + * omp-general.c (omp_maybe_offloaded): Return false after inlining. + (omp_context_selector_matches): Handle the case when + cfun->curr_properties has PROP_gimple_any bit set. + (struct omp_declare_variant_entry): New type. + (struct omp_declare_variant_base_entry): New type. + (struct omp_declare_variant_hasher): New type. + (omp_declare_variant_hasher::hash, omp_declare_variant_hasher::equal): + New methods. + (omp_declare_variants): New variable. + (struct omp_declare_variant_alt_hasher): New type. + (omp_declare_variant_alt_hasher::hash, + omp_declare_variant_alt_hasher::equal): New methods. + (omp_declare_variant_alt): New variables. + (omp_resolve_late_declare_variant): New function. + (omp_resolve_declare_variant): Call omp_resolve_late_declare_variant + when called late. Create a magic declare_variant_alt fndecl and + cgraph node and return that if decision needs to be deferred until + after gimplification. + * cgraph.c (symbol_table::create_edge): Or in calls_declare_variant_alt + bit. + PR middle-end/95108 * omp-simd-clone.c (struct modify_stmt_info): Add after_stmt member. (ipa_simd_modify_stmt_ops): For PHIs, only add before first stmt in diff --git a/gcc/Makefile.in b/gcc/Makefile.in index b49d6b0..9ba21f7 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2616,6 +2616,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/omp-offload.h \ $(srcdir)/omp-offload.c \ $(srcdir)/omp-expand.c \ + $(srcdir)/omp-general.c \ $(srcdir)/omp-low.c \ $(srcdir)/targhooks.c $(out_file) $(srcdir)/passes.c $(srcdir)/cgraphunit.c \ $(srcdir)/cgraphclones.c \ diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 2a9813d..c0b4579 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -915,6 +915,8 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee, caller->decl); else edge->in_polymorphic_cdtor = caller->thunk.thunk_p; + if (callee) + caller->calls_declare_variant_alt |= callee->declare_variant_alt; if (callee && symtab->state != LTO_STREAMING && edge->callee->comdat_local_p ()) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 5ddeb65..cfae6e9 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -937,7 +937,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node split_part (false), indirect_call_target (false), local (false), versionable (false), can_change_signature (false), redefined_extern_inline (false), tm_may_enter_irr (false), - ipcp_clone (false), m_uid (uid), m_summary_id (-1) + ipcp_clone (false), declare_variant_alt (false), + calls_declare_variant_alt (false), m_uid (uid), m_summary_id (-1) {} /* Remove the node from cgraph and all inline clones inlined into it. @@ -1539,6 +1540,11 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node unsigned tm_may_enter_irr : 1; /* True if this was a clone created by ipa-cp. */ unsigned ipcp_clone : 1; + /* True if this is the deferred declare variant resolution artificial + function. */ + unsigned declare_variant_alt : 1; + /* True if the function calls declare_variant_alt functions. */ + unsigned calls_declare_variant_alt : 1; private: /* Unique id of the node. */ @@ -450,6 +450,9 @@ symbol_table::remove_unreachable_nodes (FILE *file) reachable.add (body); reachable.add (e->callee); } + else if (e->callee->declare_variant_alt + && !e->callee->in_other_partition) + reachable.add (e->callee); enqueue_node (e->callee, &first, &reachable); } diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index b0c7ebf..17b6cfd 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -535,6 +535,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, node->merged_extern_inline, 1); bp_pack_value (&bp, node->thunk.thunk_p, 1); bp_pack_value (&bp, node->parallelized_function, 1); + bp_pack_value (&bp, node->declare_variant_alt, 1); + bp_pack_value (&bp, node->calls_declare_variant_alt, 1); bp_pack_enum (&bp, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN, /* When doing incremental link, we will get new resolution @@ -1186,6 +1188,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->merged_extern_inline = bp_unpack_value (bp, 1); node->thunk.thunk_p = bp_unpack_value (bp, 1); node->parallelized_function = bp_unpack_value (bp, 1); + node->declare_variant_alt = bp_unpack_value (bp, 1); + node->calls_declare_variant_alt = bp_unpack_value (bp, 1); node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN); node->split_part = bp_unpack_value (bp, 1); diff --git a/gcc/omp-general.c b/gcc/omp-general.c index 49023f4..315f24a 100644 --- a/gcc/omp-general.c +++ b/gcc/omp-general.c @@ -642,6 +642,8 @@ omp_maybe_offloaded (void) if (symtab->state == PARSING) /* Maybe. */ return true; + if (cfun && cfun->after_inlining) + return false; if (current_function_decl && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (current_function_decl))) @@ -694,8 +696,7 @@ omp_context_selector_matches (tree ctx) (so in most of the cases), and we'd need to maintain set of surrounding OpenMP constructs, which is better handled during gimplification. */ - if (symtab->state == PARSING - || (cfun->curr_properties & PROP_gimple_any) != 0) + if (symtab->state == PARSING) { ret = -1; continue; @@ -704,6 +705,28 @@ omp_context_selector_matches (tree ctx) enum tree_code constructs[5]; int nconstructs = omp_constructor_traits_to_codes (TREE_VALUE (t1), constructs); + + if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0) + { + if (!cfun->after_inlining) + { + ret = -1; + continue; + } + int i; + for (i = 0; i < nconstructs; ++i) + if (constructs[i] == OMP_SIMD) + break; + if (i < nconstructs) + { + ret = -1; + continue; + } + /* If there is no simd, assume it is ok after IPA, + constructs should have been checked before. */ + continue; + } + int r = omp_construct_selector_matches (constructs, nconstructs, NULL); if (r == 0) @@ -738,6 +761,9 @@ omp_context_selector_matches (tree ctx) case 'a': if (set == 'i' && !strcmp (sel, "atomic_default_mem_order")) { + if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0) + break; + enum omp_memory_order omo = ((enum omp_memory_order) (omp_requires_mask @@ -816,6 +842,9 @@ omp_context_selector_matches (tree ctx) case 'u': if (set == 'i' && !strcmp (sel, "unified_address")) { + if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0) + break; + if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0) { if (symtab->state == PARSING) @@ -827,6 +856,9 @@ omp_context_selector_matches (tree ctx) } if (set == 'i' && !strcmp (sel, "unified_shared_memory")) { + if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0) + break; + if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0) { @@ -841,6 +873,9 @@ omp_context_selector_matches (tree ctx) case 'd': if (set == 'i' && !strcmp (sel, "dynamic_allocators")) { + if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0) + break; + if ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0) { @@ -855,6 +890,9 @@ omp_context_selector_matches (tree ctx) case 'r': if (set == 'i' && !strcmp (sel, "reverse_offload")) { + if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0) + break; + if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0) { if (symtab->state == PARSING) @@ -944,7 +982,8 @@ omp_context_selector_matches (tree ctx) #pragma omp declare simd on it, some simd clones might have the isa added later on. */ if (r == -1 - && targetm.simd_clone.compute_vecsize_and_simdlen) + && targetm.simd_clone.compute_vecsize_and_simdlen + && (cfun == NULL || !cfun->after_inlining)) { tree attrs = DECL_ATTRIBUTES (current_function_decl); @@ -1415,6 +1454,191 @@ omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd) return ret; } +/* Class describing a single variant. */ +struct GTY(()) omp_declare_variant_entry { + /* NODE of the variant. */ + cgraph_node *variant; + /* Score if not in declare simd clone. */ + widest_int score; + /* Score if in declare simd clone. */ + widest_int score_in_declare_simd_clone; + /* Context selector for the variant. */ + tree ctx; + /* True if the context selector is known to match already. */ + bool matches; +}; + +/* Class describing a function with variants. */ +struct GTY((for_user)) omp_declare_variant_base_entry { + /* NODE of the base function. */ + cgraph_node *base; + /* NODE of the artificial function created for the deferred variant + resolution. */ + cgraph_node *node; + /* Vector of the variants. */ + vec<omp_declare_variant_entry, va_gc> *variants; +}; + +struct omp_declare_variant_hasher + : ggc_ptr_hash<omp_declare_variant_base_entry> { + static hashval_t hash (omp_declare_variant_base_entry *); + static bool equal (omp_declare_variant_base_entry *, + omp_declare_variant_base_entry *); +}; + +hashval_t +omp_declare_variant_hasher::hash (omp_declare_variant_base_entry *x) +{ + inchash::hash hstate; + hstate.add_int (DECL_UID (x->base->decl)); + hstate.add_int (x->variants->length ()); + omp_declare_variant_entry *variant; + unsigned int i; + FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant) + { + hstate.add_int (DECL_UID (variant->variant->decl)); + hstate.add_wide_int (variant->score); + hstate.add_wide_int (variant->score_in_declare_simd_clone); + hstate.add_ptr (variant->ctx); + hstate.add_int (variant->matches); + } + return hstate.end (); +} + +bool +omp_declare_variant_hasher::equal (omp_declare_variant_base_entry *x, + omp_declare_variant_base_entry *y) +{ + if (x->base != y->base + || x->variants->length () != y->variants->length ()) + return false; + omp_declare_variant_entry *variant; + unsigned int i; + FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant) + if (variant->variant != (*y->variants)[i].variant + || variant->score != (*y->variants)[i].score + || (variant->score_in_declare_simd_clone + != (*y->variants)[i].score_in_declare_simd_clone) + || variant->ctx != (*y->variants)[i].ctx + || variant->matches != (*y->variants)[i].matches) + return false; + return true; +} + +static GTY(()) hash_table<omp_declare_variant_hasher> *omp_declare_variants; + +struct omp_declare_variant_alt_hasher + : ggc_ptr_hash<omp_declare_variant_base_entry> { + static hashval_t hash (omp_declare_variant_base_entry *); + static bool equal (omp_declare_variant_base_entry *, + omp_declare_variant_base_entry *); +}; + +hashval_t +omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry *x) +{ + return DECL_UID (x->node->decl); +} + +bool +omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry *x, + omp_declare_variant_base_entry *y) +{ + return x->node == y->node; +} + +static GTY(()) hash_table<omp_declare_variant_alt_hasher> + *omp_declare_variant_alt; + +/* Try to resolve declare variant after gimplification. */ + +static tree +omp_resolve_late_declare_variant (tree alt) +{ + cgraph_node *node = cgraph_node::get (alt); + cgraph_node *cur_node = cgraph_node::get (cfun->decl); + if (node == NULL + || !node->declare_variant_alt + || !cfun->after_inlining) + return alt; + + omp_declare_variant_base_entry entry; + entry.base = NULL; + entry.node = node; + entry.variants = NULL; + omp_declare_variant_base_entry *entryp + = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (alt)); + + unsigned int i, j; + omp_declare_variant_entry *varentry1, *varentry2; + auto_vec <bool, 16> matches; + unsigned int nmatches = 0; + FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1) + { + if (varentry1->matches) + { + /* This has been checked to be ok already. */ + matches.safe_push (true); + nmatches++; + continue; + } + switch (omp_context_selector_matches (varentry1->ctx)) + { + case 0: + matches.safe_push (false); + break; + case -1: + return alt; + default: + matches.safe_push (true); + nmatches++; + break; + } + } + + if (nmatches == 0) + return entryp->base->decl; + + /* A context selector that is a strict subset of another context selector + has a score of zero. */ + FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1) + if (matches[i]) + { + for (j = i + 1; + vec_safe_iterate (entryp->variants, j, &varentry2); ++j) + if (matches[j]) + { + int r = omp_context_selector_compare (varentry1->ctx, + varentry2->ctx); + if (r == -1) + { + /* ctx1 is a strict subset of ctx2, ignore ctx1. */ + matches[i] = false; + break; + } + else if (r == 1) + /* ctx2 is a strict subset of ctx1, remove ctx2. */ + matches[j] = false; + } + } + + widest_int max_score = -1; + varentry2 = NULL; + FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1) + if (matches[i]) + { + widest_int score + = (cur_node->simdclone ? varentry1->score_in_declare_simd_clone + : varentry1->score); + if (score > max_score) + { + max_score = score; + varentry2 = varentry1; + } + } + return varentry2->variant->decl; +} + /* Try to resolve declare variant, return the variant decl if it should be used instead of base, or base otherwise. */ @@ -1422,6 +1646,9 @@ tree omp_resolve_declare_variant (tree base) { tree variant1 = NULL_TREE, variant2 = NULL_TREE; + if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0) + return omp_resolve_late_declare_variant (base); + auto_vec <tree, 16> variants; auto_vec <bool, 16> defer; bool any_deferred = false; @@ -1459,6 +1686,10 @@ omp_resolve_declare_variant (tree base) bool first = true; unsigned int i; tree attr1, attr2; + omp_declare_variant_base_entry entry; + entry.base = cgraph_node::get_create (base); + entry.node = NULL; + vec_alloc (entry.variants, variants.length ()); FOR_EACH_VEC_ELT (variants, i, attr1) { widest_int score1; @@ -1498,6 +1729,14 @@ omp_resolve_declare_variant (tree base) variant2 = defer[i] ? NULL_TREE : attr1; } } + omp_declare_variant_entry varentry; + varentry.variant + = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1))); + varentry.score = score1; + varentry.score_in_declare_simd_clone = score2; + varentry.ctx = ctx; + varentry.matches = !defer[i]; + entry.variants->quick_push (varentry); } /* If there is a clear winner variant with the score which is not @@ -1522,17 +1761,67 @@ omp_resolve_declare_variant (tree base) } } if (variant1) - return TREE_PURPOSE (TREE_VALUE (variant1)); + { + vec_free (entry.variants); + return TREE_PURPOSE (TREE_VALUE (variant1)); + } + } + + if (omp_declare_variants == NULL) + omp_declare_variants + = hash_table<omp_declare_variant_hasher>::create_ggc (64); + omp_declare_variant_base_entry **slot + = omp_declare_variants->find_slot (&entry, INSERT); + if (*slot != NULL) + { + vec_free (entry.variants); + return (*slot)->node->decl; } - return base; + *slot = ggc_cleared_alloc<omp_declare_variant_base_entry> (); + (*slot)->base = entry.base; + (*slot)->node = entry.base; + (*slot)->variants = entry.variants; + tree alt = build_decl (DECL_SOURCE_LOCATION (base), FUNCTION_DECL, + DECL_NAME (base), TREE_TYPE (base)); + DECL_ARTIFICIAL (alt) = 1; + DECL_IGNORED_P (alt) = 1; + TREE_STATIC (alt) = 1; + tree attributes = DECL_ATTRIBUTES (base); + if (lookup_attribute ("noipa", attributes) == NULL) + { + attributes = tree_cons (get_identifier ("noipa"), NULL, attributes); + if (lookup_attribute ("noinline", attributes) == NULL) + attributes = tree_cons (get_identifier ("noinline"), NULL, + attributes); + if (lookup_attribute ("noclone", attributes) == NULL) + attributes = tree_cons (get_identifier ("noclone"), NULL, + attributes); + if (lookup_attribute ("no_icf", attributes) == NULL) + attributes = tree_cons (get_identifier ("no_icf"), NULL, + attributes); + } + DECL_ATTRIBUTES (alt) = attributes; + DECL_INITIAL (alt) = error_mark_node; + (*slot)->node = cgraph_node::create (alt); + (*slot)->node->declare_variant_alt = 1; + (*slot)->node->create_reference (entry.base, IPA_REF_ADDR); + omp_declare_variant_entry *varentry; + FOR_EACH_VEC_SAFE_ELT (entry.variants, i, varentry) + (*slot)->node->create_reference (varentry->variant, IPA_REF_ADDR); + if (omp_declare_variant_alt == NULL) + omp_declare_variant_alt + = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64); + *omp_declare_variant_alt->find_slot_with_hash (*slot, DECL_UID (alt), + INSERT) = *slot; + return alt; } if (variants.length () == 1) return TREE_PURPOSE (TREE_VALUE (variants[0])); - /* A context selector that is a strict subset of another context selector has a score - of zero. */ + /* A context selector that is a strict subset of another context selector + has a score of zero. */ tree attr1, attr2; unsigned int i, j; FOR_EACH_VEC_ELT (variants, i, attr1) @@ -1948,3 +2237,5 @@ oacc_get_ifn_dim_arg (const gimple *stmt) gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX); return (int) axis; } + +#include "gt-omp-general.h" diff --git a/gcc/omp-offload.c b/gcc/omp-offload.c index 3e7012d..b2df91a 100644 --- a/gcc/omp-offload.c +++ b/gcc/omp-offload.c @@ -2066,12 +2066,28 @@ execute_omp_device_lower () bool regimplify = false; basic_block bb; gimple_stmt_iterator gsi; + bool calls_declare_variant_alt + = cgraph_node::get (cfun->decl)->calls_declare_variant_alt; FOR_EACH_BB_FN (bb, cfun) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); - if (!is_gimple_call (stmt) || !gimple_call_internal_p (stmt)) + if (!is_gimple_call (stmt)) continue; + if (!gimple_call_internal_p (stmt)) + { + if (calls_declare_variant_alt) + if (tree fndecl = gimple_call_fndecl (stmt)) + { + tree new_fndecl = omp_resolve_declare_variant (fndecl); + if (new_fndecl != fndecl) + { + gimple_call_set_fndecl (stmt, new_fndecl); + update_stmt (stmt); + } + } + continue; + } tree lhs = gimple_call_lhs (stmt), rhs = NULL_TREE; tree type = lhs ? TREE_TYPE (lhs) : integer_type_node; switch (gimple_call_internal_fn (stmt)) @@ -2165,7 +2181,9 @@ public: /* opt_pass methods: */ virtual bool gate (function *fun) { - return !(fun->curr_properties & PROP_gimple_lomp_dev); + return (!(fun->curr_properties & PROP_gimple_lomp_dev) + || (flag_openmp + && cgraph_node::get (fun->decl)->calls_declare_variant_alt)); } virtual unsigned int execute (function *) { diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c index 09fdd60..942fb97 100644 --- a/gcc/omp-simd-clone.c +++ b/gcc/omp-simd-clone.c @@ -477,6 +477,7 @@ simd_clone_create (struct cgraph_node *old_node) the old node. */ new_node->local = old_node->local; new_node->externally_visible = old_node->externally_visible; + new_node->calls_declare_variant_alt = old_node->calls_declare_variant_alt; return new_node; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 13d5548..2b6d4be 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2020-05-14 Jakub Jelinek <jakub@redhat.com> + * c-c++-common/gomp/declare-variant-14.c: New test. + PR middle-end/95108 * gcc.dg/gomp/pr95108.c: New test. diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-14.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-14.c new file mode 100644 index 0000000..cdb0bb3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-14.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target vect_simd_clones } } */ +/* { dg-additional-options "-fdump-tree-gimple -fdump-tree-optimized" } */ +/* { dg-additional-options "-mno-sse3" { target { i?86-*-* x86_64-*-* } } } */ + +int f01 (int); +int f02 (int); +int f03 (int); +#pragma omp declare variant (f01) match (device={isa("avx512f")}) /* 4 or 8 */ +#pragma omp declare variant (f02) match (implementation={vendor(score(3):gnu)},device={kind(cpu)}) /* (1 or 2) + 3 */ +#pragma omp declare variant (f03) match (implementation={vendor(score(5):gnu)},device={kind(host)}) /* (1 or 2) + 5 */ +int f04 (int); + +#pragma omp declare simd +int +test1 (int x) +{ + /* At gimplification time, we can't decide yet which function to call. */ + /* { dg-final { scan-tree-dump-times "f04 \\\(x" 2 "gimple" } } */ + /* After simd clones are created, the original non-clone test1 shall + call f03 (score 6), the sse2/avx/avx2 clones too, but avx512f clones + shall call f01 with score 8. */ + /* { dg-final { scan-tree-dump-not "f04 \\\(x" "optimized" } } */ + /* { dg-final { scan-tree-dump-times "f03 \\\(x" 14 "optimized" } } */ + /* { dg-final { scan-tree-dump-times "f01 \\\(x" 4 "optimized" } } */ + int a = f04 (x); + int b = f04 (x); + return a + b; +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 8c5d5da..ee96c9c 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4900,6 +4900,8 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id, if (src_properties != prop_mask) dst_cfun->curr_properties &= src_properties | ~prop_mask; dst_cfun->calls_eh_return |= id->src_cfun->calls_eh_return; + id->dst_node->calls_declare_variant_alt + |= id->src_node->calls_declare_variant_alt; gcc_assert (!id->src_cfun->after_inlining); @@ -6231,6 +6233,8 @@ tree_function_versioning (tree old_decl, tree new_decl, DECL_ARGUMENTS (new_decl) = DECL_ARGUMENTS (old_decl); initialize_cfun (new_decl, old_decl, new_entry ? new_entry->count : old_entry_block->count); + new_version_node->calls_declare_variant_alt + = old_version_node->calls_declare_variant_alt; if (DECL_STRUCT_FUNCTION (new_decl)->gimple_df) DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta = id.src_cfun->gimple_df->ipa_pta; |