+2019-11-15 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (gimplify_call_expr): Don't call
+ omp_resolve_declare_variant after gimplification.
+ * omp-general.c (omp_context_selector_matches): For isa that might
+ match in some other function, defer if in declare simd function.
+ (omp_context_compute_score): Don't look for " score" in construct
+ trait set. Set *score to -1 if it can't ever match.
+ (omp_resolve_declare_variant): If any variants need to be deferred,
+ don't punt immediately, but compute scores of all variants and if
+ ther eis a score winner that doesn't need to be deferred, return that.
+
2019-11-15 Luo Xiong Hu <luoxhu@linux.ibm.com>
* ipa-comdats.c: Fix comments typo.
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. */
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];
{
if (scores[b + n] < 0)
{
- *score = 0;
+ *score = -1;
return ret;
}
*score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
{
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);
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]));
--- /dev/null
+/* { dg-do compile { target vect_simd_clones } } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+/* { dg-additional-options "-mno-sse3" { target { i?86-*-* x86_64-*-* } } } */
+
+int f01 (int);
+int f02 (int);
+int f03 (int);
+int f04 (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 (user={condition(score(9):1)})
+#pragma omp declare variant (f04) match (implementation={vendor(score(6):gnu)},device={kind(host)}) /* (1 or 2) + 6 */
+int f05 (int);
+
+#pragma omp declare simd
+int
+test1 (int x)
+{
+ /* 0 or 1 (the latter if in a declare simd clone) constructs in OpenMP context,
+ isa has score 2^2 or 2^3. We can't decide on whether avx512f will match or
+ not, that also depends on whether it is a declare simd clone or not and which
+ one, but the f03 variant has a higher score anyway. */
+ return f05 (x); /* { dg-final { scan-tree-dump-times "f03 \\\(x" 1 "gimple" } } */
+}