aboutsummaryrefslogtreecommitdiff
path: root/gcc/omp-general.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/omp-general.c')
-rw-r--r--gcc/omp-general.c116
1 files changed, 108 insertions, 8 deletions
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index a8efc10..c9c4f3a 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -939,6 +939,21 @@ omp_context_selector_matches (tree ctx)
isa);
if (r == 0 || (r == -1 && symtab->state != PARSING))
{
+ /* If isa is valid on the target, but not in the
+ current function and current function has
+ #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)
+ {
+ tree attrs
+ = DECL_ATTRIBUTES (current_function_decl);
+ if (lookup_attribute ("omp declare simd", attrs))
+ {
+ ret = -1;
+ continue;
+ }
+ }
/* If we are or might be in a target region or
declare target function, need to take into account
also offloading values. */
@@ -1355,12 +1370,13 @@ omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
bool ret = false;
*score = 1;
for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
- for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
- if (tree t3 = TREE_VALUE (t2))
- if (TREE_PURPOSE (t3)
- && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)), " score") == 0
- && TREE_CODE (TREE_VALUE (t3)) == INTEGER_CST)
- *score += wi::to_widest (TREE_VALUE (t3));
+ if (TREE_VALUE (t1) != construct)
+ for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+ if (tree t3 = TREE_VALUE (t2))
+ if (TREE_PURPOSE (t3)
+ && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)), " score") == 0
+ && TREE_CODE (TREE_VALUE (t3)) == INTEGER_CST)
+ *score += wi::to_widest (TREE_VALUE (t3));
if (construct || has_kind || has_arch || has_isa)
{
int scores[12];
@@ -1378,7 +1394,7 @@ omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
{
if (scores[b + n] < 0)
{
- *score = 0;
+ *score = -1;
return ret;
}
*score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
@@ -1407,6 +1423,8 @@ omp_resolve_declare_variant (tree base)
{
tree variant1 = NULL_TREE, variant2 = NULL_TREE;
auto_vec <tree, 16> variants;
+ auto_vec <bool, 16> defer;
+ bool any_deferred = false;
for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
{
attr = lookup_attribute ("omp declare variant base", attr);
@@ -1421,13 +1439,95 @@ omp_resolve_declare_variant (tree base)
break;
case -1:
/* Needs to be deferred. */
- return base;
+ any_deferred = true;
+ variants.safe_push (attr);
+ defer.safe_push (true);
+ break;
default:
variants.safe_push (attr);
+ defer.safe_push (false);
+ break;
}
}
if (variants.length () == 0)
return base;
+
+ if (any_deferred)
+ {
+ widest_int max_score1 = 0;
+ widest_int max_score2 = 0;
+ bool first = true;
+ unsigned int i;
+ tree attr1, attr2;
+ FOR_EACH_VEC_ELT (variants, i, attr1)
+ {
+ widest_int score1;
+ widest_int score2;
+ bool need_two;
+ tree ctx = TREE_VALUE (TREE_VALUE (attr1));
+ need_two = omp_context_compute_score (ctx, &score1, false);
+ if (need_two)
+ omp_context_compute_score (ctx, &score2, true);
+ else
+ score2 = score1;
+ if (first)
+ {
+ first = false;
+ max_score1 = score1;
+ max_score2 = score2;
+ if (!defer[i])
+ {
+ variant1 = attr1;
+ variant2 = attr1;
+ }
+ }
+ else
+ {
+ if (max_score1 == score1)
+ variant1 = NULL_TREE;
+ else if (score1 > max_score1)
+ {
+ max_score1 = score1;
+ variant1 = defer[i] ? NULL_TREE : attr1;
+ }
+ if (max_score2 == score2)
+ variant2 = NULL_TREE;
+ else if (score2 > max_score2)
+ {
+ max_score2 = score2;
+ variant2 = defer[i] ? NULL_TREE : attr1;
+ }
+ }
+ }
+
+ /* If there is a clear winner variant with the score which is not
+ deferred, verify it is not a strict subset of any other context
+ selector and if it is not, it is the best alternative no matter
+ whether the others do or don't match. */
+ if (variant1 && variant1 == variant2)
+ {
+ tree ctx1 = TREE_VALUE (TREE_VALUE (variant1));
+ FOR_EACH_VEC_ELT (variants, i, attr2)
+ {
+ if (attr2 == variant1)
+ continue;
+ tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
+ int r = omp_context_selector_compare (ctx1, ctx2);
+ if (r == -1)
+ {
+ /* The winner is a strict subset of ctx2, can't
+ decide now. */
+ variant1 = NULL_TREE;
+ break;
+ }
+ }
+ if (variant1)
+ return TREE_PURPOSE (TREE_VALUE (variant1));
+ }
+
+ return base;
+ }
+
if (variants.length () == 1)
return TREE_PURPOSE (TREE_VALUE (variants[0]));