This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] declare variant scoring when at least one variant needs to be deferred


Hi!

The following patch is in preparation of the deferred declare variant
resolution, where we need to compute the scores during gimplification
for all variants.
This patch just picks the candidate with highest score if that variant
doesn't need to be deferred and thus is an unconditional win, but
the next step will be to remember the scores, create an artificial
FUNCTION_DECL and add the scores + info on what does and what might match
for each variant on it, as e.g. the construct info will get away.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

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.

	* c-c++-common/gomp/declare-variant-13.c: New test.

--- gcc/gimplify.c.jj	2019-11-13 10:54:53.860917700 +0100
+++ gcc/gimplify.c	2019-11-14 14:17:53.693177021 +0100
@@ -3391,7 +3391,10 @@ gimplify_call_expr (tree *expr_p, gimple
   /* Remember the original function pointer type.  */
   fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
 
-  if (flag_openmp && fndecl)
+  if (flag_openmp
+      && fndecl
+      && cfun
+      && (cfun->curr_properties & PROP_gimple_any) == 0)
     {
       tree variant = omp_resolve_declare_variant (fndecl);
       if (variant != fndecl)
--- gcc/omp-general.c.jj	2019-11-14 09:10:30.016766379 +0100
+++ gcc/omp-general.c	2019-11-14 16:17:47.715869150 +0100
@@ -936,6 +936,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.  */
@@ -1352,12 +1367,13 @@ omp_context_compute_score (tree ctx, wid
   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];
@@ -1375,7 +1391,7 @@ omp_context_compute_score (tree ctx, wid
 	    {
 	      if (scores[b + n] < 0)
 		{
-		  *score = 0;
+		  *score = -1;
 		  return ret;
 		}
 	      *score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
@@ -1404,6 +1420,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);
@@ -1418,13 +1436,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]));
 
--- gcc/testsuite/c-c++-common/gomp/declare-variant-13.c.jj	2019-11-14 15:33:03.006639340 +0100
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-13.c	2019-11-14 16:32:41.981296586 +0100
@@ -0,0 +1,24 @@
+/* { 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" } } */
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]