[committed] OpenMP declare variant template handling
diff mbox series

Message ID 20191105074731.GQ4650@tucnak
State New
Headers show
Series
  • [committed] OpenMP declare variant template handling
Related show

Commit Message

Jakub Jelinek Nov. 5, 2019, 7:47 a.m. UTC
Hi!

The following patch handles declare variant in templates, including
instantiating the "omp declare variant base" attribute value.

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

2019-11-05  Jakub Jelinek  <jakub@redhat.com>

	* decl.c (omp_declare_variant_finalize_one): Call
	declare_simd_adjust_this not just on the context, but also on the
	variant-id expression for methods.  Don't call
	cp_get_callee_fndecl_nofold, call cp_get_callee and only if it is
	safe cp_get_fndecl_from_callee.  Don't try to print as %qD
	NULL in diagnostics.
	* pt.c (tsubst_attribute): Handle "omp declare variant base"
	attribute.
	(tsubst_function_decl): Call omp_declare_variant_finalize
	if there are any "omp declare variant base" attributes left.

	* g++.dg/gomp/declare-variant-7.C: New test.
	* g++.dg/gomp/declare-variant-8.C: New test.


	Jakub

Patch
diff mbox series

--- gcc/cp/decl.c.jj	2019-11-02 10:00:59.646252496 +0100
+++ gcc/cp/decl.c	2019-11-04 19:05:24.292235486 +0100
@@ -7099,8 +7099,12 @@  static bool
 omp_declare_variant_finalize_one (tree decl, tree attr)
 {
   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-    walk_tree (&TREE_VALUE (TREE_VALUE (attr)), declare_simd_adjust_this,
-	       DECL_ARGUMENTS (decl), NULL);
+    {
+      walk_tree (&TREE_VALUE (TREE_VALUE (attr)), declare_simd_adjust_this,
+		 DECL_ARGUMENTS (decl), NULL);
+      walk_tree (&TREE_PURPOSE (TREE_VALUE (attr)), declare_simd_adjust_this,
+		 DECL_ARGUMENTS (decl), NULL);
+    }
 
   tree ctx = TREE_VALUE (TREE_VALUE (attr));
   tree simd = omp_get_context_selector (ctx, "construct", "simd");
@@ -7179,7 +7183,16 @@  omp_declare_variant_finalize_one (tree d
   if (variant == error_mark_node && !processing_template_decl)
     return true;
 
-  variant = cp_get_callee_fndecl_nofold (variant);
+  variant = cp_get_callee (variant);
+  if (variant)
+    {
+      if (TREE_CODE (variant) == FUNCTION_DECL)
+	;
+      else if (TREE_TYPE (variant) && INDIRECT_TYPE_P (TREE_TYPE (variant)))
+	variant = cp_get_fndecl_from_callee (variant, false);
+      else
+	variant = NULL_TREE;
+    }
 
   input_location = save_loc;
 
@@ -7211,7 +7224,7 @@  omp_declare_variant_finalize_one (tree d
     }
   else if (!processing_template_decl)
     {
-      error_at (varid_loc, "could not find variant %qD declaration", variant);
+      error_at (varid_loc, "could not find variant declaration");
       return true;
     }
 
--- gcc/cp/pt.c.jj	2019-10-31 08:08:42.883786288 +0100
+++ gcc/cp/pt.c	2019-11-04 19:29:54.115165644 +0100
@@ -11119,6 +11119,76 @@  tsubst_attribute (tree t, tree *decl_p,
       else
 	val = NULL_TREE;
     }
+  else if (flag_openmp
+	   && is_attribute_p ("omp declare variant base",
+			      get_attribute_name (t)))
+    {
+      ++cp_unevaluated_operand;
+      tree varid
+	= tsubst_expr (TREE_PURPOSE (val), args, complain,
+		       in_decl, /*integral_constant_expression_p=*/false);
+      --cp_unevaluated_operand;
+      tree chain = TREE_CHAIN (val);
+      location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
+      tree ctx = copy_list (TREE_VALUE (val));
+      tree simd = get_identifier ("simd");
+      tree score = get_identifier (" score");
+      tree condition = get_identifier ("condition");
+      for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
+	{
+	  const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
+	  TREE_VALUE (t1) = copy_list (TREE_VALUE (t1));
+	  for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+	    {
+	      if (TREE_PURPOSE (t2) == simd && set[0] == 'c')
+		{
+		  tree clauses = TREE_VALUE (t2);
+		  clauses = tsubst_omp_clauses (clauses,
+						C_ORT_OMP_DECLARE_SIMD, args,
+						complain, in_decl);
+		  c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
+		  clauses = finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
+		  TREE_VALUE (t2) = clauses;
+		}
+	      else
+		{
+		  TREE_VALUE (t2) = copy_list (TREE_VALUE (t2));
+		  for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+		    if (TREE_VALUE (t3))
+		      {
+			bool allow_string
+			  = ((TREE_PURPOSE (t2) != condition || set[0] != 'u')
+			     && TREE_PURPOSE (t3) != score);
+			if (TREE_CODE (t3) == STRING_CST && allow_string)
+			  continue;
+			tree v = TREE_VALUE (t3);
+			v = tsubst_expr (v, args, complain, in_decl, true);
+			v = fold_non_dependent_expr (v);
+			if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
+			    || !tree_fits_shwi_p (v))
+			  {
+			    location_t loc
+			      = cp_expr_loc_or_loc (TREE_VALUE (t3),
+						    match_loc);
+			    if (TREE_PURPOSE (t3) == score)
+			      error_at (loc, "score argument must be "
+					     "constant integer expression");
+			    else if (allow_string)
+			      error_at (loc, "property must be constant "
+					     "integer expression or string "
+					     "literal");
+			    else
+			      error_at (loc, "property must be constant "
+					     "integer expression");
+			    return NULL_TREE;
+			  }
+			TREE_VALUE (t3) = v;
+		      }
+		}
+	    }
+	}
+      val = tree_cons (varid, ctx, chain);
+    }
   /* If the first attribute argument is an identifier, don't
      pass it through tsubst.  Attributes like mode, format,
      cleanup and several target specific attributes expect it
@@ -13579,6 +13649,11 @@  tsubst_function_decl (tree t, tree args,
 
   apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
 				  args, complain, in_decl);
+  if (flag_openmp)
+    if (tree attr = lookup_attribute ("omp declare variant base",
+				      DECL_ATTRIBUTES (r)))
+      omp_declare_variant_finalize (r, attr);
+
   return r;
 }
 
--- gcc/testsuite/g++.dg/gomp/declare-variant-7.C.jj	2019-11-04 19:35:26.351176805 +0100
+++ gcc/testsuite/g++.dg/gomp/declare-variant-7.C	2019-11-04 19:35:18.165299723 +0100
@@ -0,0 +1,75 @@ 
+// Test parsing of #pragma omp declare variant
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+void f01 ();
+#pragma omp declare variant (f01) match (user={condition(1)},device={arch(x86_64)})
+template <int N>
+void f02 ();
+void f03 ();
+#pragma omp declare variant (f03) match (user={condition(score(N+2):N)})
+template <int N>
+void f04 ();
+template <int N>
+void f05 ();
+#pragma omp declare variant (f05<N>) match (user={condition((T)N)},implementation={vendor(gnu)})
+template <int N, typename T>
+void f06 ();
+void f07 ();
+#pragma omp declare variant (f07) match (user={condition(score(N+2):N)})
+template <int N>
+void f08 ();
+template <int N>
+void f09 ();
+#pragma omp declare variant (f09<N>) match (user={condition((T) N)})
+template <int N, typename T>
+void f10 ();
+template <int N>
+struct S
+{
+  template <typename T>
+  void f11 (T) {}
+  #pragma omp declare variant (f11<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f12 (T) {}
+  template <typename T>
+  void f13 (T);
+  #pragma omp declare variant (f13<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f14 (T);
+  int s;
+};
+template <int N>
+struct T
+{
+  template <typename T>
+  void f15 (T) {}
+  #pragma omp declare variant (f15<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f16 (T) {}
+  template <typename T>
+  void f17 (T);
+  #pragma omp declare variant (f17<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f18 (T);
+  int t;
+};
+
+void
+test ()
+{
+  f02<1> ();	// { dg-final { scan-tree-dump-times "f01 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && lp64 } } } }
+		// { dg-final { scan-tree-dump-times "f02<1> \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && { ! lp64 } } } } }
+		// { dg-final { scan-tree-dump-times "f02<1> \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+  f04<1> ();		// { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" } }
+  f06<1, long> ();	// { dg-final { scan-tree-dump-times "f05<1> \\\(\\\);" 1 "gimple" } }
+  f08<0> ();		// { dg-final { scan-tree-dump-times "f08<0> \\\(\\\);" 1 "gimple" } }
+  f10<0, short int> ();	// { dg-final { scan-tree-dump-times "f10<0, short int> \\\(\\\);" 1 "gimple" } }
+  S<1> s;
+  s.f12 (0);		// { dg-final { scan-tree-dump-times "S<1>::f11<int> \\\(&s, 0\\\);" 1 "gimple" } }
+  s.f12 (0.0);		// { dg-final { scan-tree-dump-times "S<1>::f11<double> \\\(&s, 0.0\\\);" 1 "gimple" } }
+  s.f14 (0LL);		// { dg-final { scan-tree-dump-times "S<1>::f13<long long int> \\\(&s, 0\\\);" 1 "gimple" } }
+  T<0> t;
+  t.f16 (s);		// { dg-final { scan-tree-dump-times "T<0>::f16<S<1> > \\\(&t, s\\\);" 1 "gimple" } }
+  t.f18 (s);		// { dg-final { scan-tree-dump-times "T<0>::f18<S<1> > \\\(&t, s\\\);" 1 "gimple" } }
+}
--- gcc/testsuite/g++.dg/gomp/declare-variant-8.C.jj	2019-11-04 19:46:20.060360684 +0100
+++ gcc/testsuite/g++.dg/gomp/declare-variant-8.C	2019-11-04 19:48:27.344449360 +0100
@@ -0,0 +1,18 @@ 
+// Test parsing of #pragma omp declare variant
+// { dg-do compile }
+
+void f01 ();
+#pragma omp declare variant (f01) match (user={condition((T) 1)})	// { dg-error "property must be constant integer expression" }
+template <typename T>
+void f02 ();
+void f03 ();
+#pragma omp declare variant (f03) match (user={condition(score((T) 1):1)})	// { dg-error "score argument must be constant integer expression" }
+template <typename T>
+void f04 ();
+
+void
+test ()
+{
+  f02 <double> ();
+  f04 <float> ();
+}