Slightly cleaned-up version: use omp_find_clause,
set location of the body and not of the clause
fix block in bind.

I have now installed that version as Rev. r17-2401-g97a43fc4dbc5cf

Tobias Burnus wrote:

The attached patch now permits

#pragma omp target device_type(nohost)
  f();

which gets turned into

#pragma omp target
  if (__builtin_is_initial_device() != 0)
    GOMP_error (...);
  else
    f();

...

Comments before I push his patch?

... or afterwards?

Tobias
OpenMP: Handle 'device_type(nohost)' on 'target'

The parsing support was already there, this just adds code to handle
'nohost' in the middle end.

That's handled by adding if-else code to the target's structure block
using the omp_is_initial_device builtin in the condition that is
replaced by a constant (late) during compilation. Thus, with optimization
turned on, only the error message or the target body remains for the host
and the nonhost region, respectively.

Note that 'device_type(host)' is not yet implemented.

Note also there is no change to implicit handling, i.e. functions called
in the region will implicitly 'declare target' with 'device_type(any)',
i.e. there is no attempt made to add those with 'nohost', which is also
the most sensible.

gcc/ChangeLog:

	* gimplify.cc (gimplify_omp_workshare): Handle 'device_type(nohost)'
	on 'target'.
	* omp-low.cc (lower_omp_target): Remove sorry for this case.

libgomp/ChangeLog:

	* error.c (GOMP_error): When passing msglen == (size_t) -2,
	do not show 'error directive encountered:' in the message.
	* libgomp.texi (Implementation Status): Mark target + device_type
	as partially implemented.
	* testsuite/libgomp.c/target-device-type-1.c: New test.
	* testsuite/libgomp.c/target-device-type-2.c: New test.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/target-device-type-1.c: Update dg-sorry
	as now only device_type(host) remains unimplemented.
	* gfortran.dg/gomp/target-device-type-1.f90: Likewise.

 gcc/gimplify.cc                                    | 40 ++++++++++++++++++++++
 gcc/omp-low.cc                                     |  4 +--
 .../c-c++-common/gomp/target-device-type-1.c       |  4 +--
 .../gfortran.dg/gomp/target-device-type-1.f90      |  4 +--
 libgomp/error.c                                    |  6 ++++
 libgomp/libgomp.texi                               | 13 +++++--
 libgomp/testsuite/libgomp.c/target-device-type-1.c | 21 ++++++++++++
 libgomp/testsuite/libgomp.c/target-device-type-2.c | 27 +++++++++++++++
 8 files changed, 111 insertions(+), 8 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 6c5d182ffab..223b55b7e93 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -18990,6 +18990,46 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
       stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
       break;
     case OMP_TARGET:
+      /* Handle 'device_type(nohost)'.  */
+      if (tree c = omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_DEVICE_TYPE))
+	if (OMP_CLAUSE_DEVICE_TYPE_KIND (c) == OMP_CLAUSE_DEVICE_TYPE_NOHOST)
+	  {
+	    location_t loc = gimple_location (body);
+	    tree fn = builtin_decl_explicit (BUILT_IN_OMP_IS_INITIAL_DEVICE);
+	    fn = build_call_expr_loc (loc, fn, 0);
+	    tree err = builtin_decl_explicit (BUILT_IN_GOMP_ERROR);
+	    const char *str = "Executing device-type 'nohost' target region "
+			      "on the host";
+	    const int len = strlen (str) + 1;
+	    tree msg = build_string (len, str);
+	    TREE_TYPE (msg) = build_array_type_nelts (char_type_node, len);
+	    TREE_READONLY (msg) = 1;
+	    TREE_STATIC (msg) = 1;
+	    msg = build_fold_addr_expr (msg);
+	    tree msglen = fold_build2 (MINUS_EXPR, size_type_node,
+				       build_all_ones_cst (size_type_node),
+				       size_one_node);
+	    err = build_call_expr_loc (loc, err, 2, msg, msglen);
+	    tree l1 = create_artificial_label (UNKNOWN_LOCATION);
+	    tree l2 = create_artificial_label (UNKNOWN_LOCATION);
+	    tree l3 = create_artificial_label (UNKNOWN_LOCATION);
+
+	    gimple_seq new_body = NULL;
+
+	    gimplify_expr (&fn, &new_body, NULL, is_gimple_val, fb_rvalue);
+	    gcond *cond = gimple_build_cond (NE_EXPR, fn,
+					     build_int_cst (TREE_TYPE (fn), 0),
+					     l1, l2);
+	    gimplify_seq_add_stmt (&new_body, cond);
+	    gimplify_seq_add_stmt (&new_body, gimple_build_label (l1));
+	    gimplify_and_add (err, &new_body);
+	    gimplify_seq_add_stmt (&new_body, gimple_build_goto (l3));
+	    gimplify_seq_add_stmt (&new_body, gimple_build_label (l2));
+	    gimple_seq_add_seq (&new_body, body);
+	    gimplify_seq_add_stmt (&new_body, gimple_build_label (l3));
+	    body = gimple_build_bind (NULL_TREE, new_body, make_node (BLOCK));
+	    gimple_set_location (body, loc);
+	  }
       stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
 				      OMP_CLAUSES (expr), iterator_loops_seq);
       break;
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index c578e8ece49..99f73e501c0 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -13287,9 +13287,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 	case OMP_CLAUSE_DEVICE_TYPE:
 	  /* FIXME: Ensure that 'nohost' also has not implied before that
 	     'g->have_offload = true' or an implicit declare target.  */
-	  if (OMP_CLAUSE_DEVICE_TYPE_KIND (c) != OMP_CLAUSE_DEVICE_TYPE_ANY)
+	  if (OMP_CLAUSE_DEVICE_TYPE_KIND (c) == OMP_CLAUSE_DEVICE_TYPE_HOST)
 	    sorry_at (OMP_CLAUSE_LOCATION (c),
-		      "only the %<device_type(any)%> is supported");
+		      "the %<device_type(host)%> is not supported");
 	  break;
       case OMP_CLAUSE_USES_ALLOCATORS:
 	allocator = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-type-1.c b/gcc/testsuite/c-c++-common/gomp/target-device-type-1.c
index e64349baae3..758330436cd 100644
--- a/gcc/testsuite/c-c++-common/gomp/target-device-type-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-type-1.c
@@ -10,10 +10,10 @@ void f ()
 #pragma omp target device_type ( any )
   ;
 
-#pragma omp target device_type ( nohost )  // { dg-message "sorry, unimplemented: only the 'device_type\\(any\\)' is supported" }
+#pragma omp target device_type ( nohost )
   ;
 
-#pragma omp target device_type ( host )
+#pragma omp target device_type ( host )  // { dg-message "sorry, unimplemented: the 'device_type\\(host\\)' is not supported" }
   ;
 
 }
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-type-1.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-type-1.f90
index be33bb6a19d..164fc4f1fd6 100644
--- a/gcc/testsuite/gfortran.dg/gomp/target-device-type-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-type-1.f90
@@ -7,10 +7,10 @@
 !$omp target device_type ( any )
 !$omp end target
 
-!$omp target device_type ( nohost )  ! { dg-message "sorry, unimplemented: only the 'device_type\\(any\\)' is supported" }
+!$omp target device_type ( nohost )
 !$omp end target
 
-!$omp target device_type ( host )
+!$omp target device_type ( host )  ! { dg-message "sorry, unimplemented: the 'device_type\\(host\\)' is not supported" }
 !$omp end target
 
 end
diff --git a/libgomp/error.c b/libgomp/error.c
index cd7c98cf25e..0fa311faeca 100644
--- a/libgomp/error.c
+++ b/libgomp/error.c
@@ -105,11 +105,17 @@ GOMP_warning (const char *msg, size_t msglen)
     gomp_error ("error directive encountered");
 }
 
+/* Handle 'omp error' directive; for msglen == -2, it is used internally
+   by the compiler-generated code such that 'error directive encountered'
+   is not printed.  */
+
 void
 GOMP_error (const char *msg, size_t msglen)
 {
   if (msg && msglen == (size_t) -1)
     gomp_fatal ("fatal error: error directive encountered: %s", msg);
+  else if (msg && msglen == (size_t) -2)
+    gomp_fatal ("fatal error: %s", msg);
   else if (msg)
     {
       fputs ("\nlibgomp: fatal error: error directive encountered: ", stderr);
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 5bbc856544e..a87600eefef 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -580,7 +580,7 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
       @code{target_data}, @code{target_exit_data} and @code{target_update}
       @tab N @tab
 @item New @code{device_type} clause to the @code{target} directive
-      @tab N @tab
+      @tab P @tab @code{device_type(host)} unsupported
 @item @code{target_data} as composite construct @tab N @tab
 @item @code{nowait} clause with reverse-offload @code{target} directives
       @tab N @tab
diff --git a/libgomp/testsuite/libgomp.c/target-device-type-1.c b/libgomp/testsuite/libgomp.c/target-device-type-1.c
new file mode 100644
index 00000000000..a1e1af6979a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-device-type-1.c
@@ -0,0 +1,21 @@
+/* { dg-do run { target offload_device } } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+int
+f (int *x)
+{
+  #pragma omp target device_type(nohost)
+    (*x)++;
+  return *x;
+}
+
+int
+main ()
+{
+  int i = 3;
+  if (f(&i) != 4)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump "= __builtin_omp_is_initial_device \\(\\);" "gimple" } } */
+/* { dg-final { scan-tree-dump "__builtin_GOMP_error \\(\"Executing device-type ..nohost.. target region on the host\"," "gimple" } } */
diff --git a/libgomp/testsuite/libgomp.c/target-device-type-2.c b/libgomp/testsuite/libgomp.c/target-device-type-2.c
new file mode 100644
index 00000000000..37fa62216c9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-device-type-2.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+#include <omp.h>
+
+int
+f (int *x)
+{
+  #pragma omp target device_type(nohost)
+    (*x)++;
+  return *x;
+}
+
+int
+main ()
+{
+  omp_set_default_device (omp_initial_device);
+  int i = 3;
+  if (f(&i) != 4)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump "= __builtin_omp_is_initial_device \\(\\);" "gimple" } } */
+/* { dg-final { scan-tree-dump "__builtin_GOMP_error \\(\"Executing device-type ..nohost.. target region on the host\"," "gimple" } } */
+
+/* { dg-output "libgomp: fatal error: Executing device-type 'nohost' target region on the host" } */
+/* { dg-shouldfail "'nohost' target region on the host" } */

Reply via email to