diff mbox

[gomp4] error on duplicate acc device_type entries

Message ID 557AD862.2020704@codesourcery.com
State New
Headers show

Commit Message

Cesar Philippidis June 12, 2015, 1:02 p.m. UTC
This patch teaches all of the front ends how to error on duplicate
device_type entries such as

  #pragma acc parallel  device_type (nvidia) num_gangs (1) \
     device_type (nvidia) num_gangs (20)

Before such clauses were silently ignored. I also fixed how invalid
device_type claues are reported in the fortran front end. It used report
"Invalid character" and now it states "Unclassifiable OpenACC directive".

I applied this patch to gomp-4_0-branch.

Cesar
diff mbox

Patch

2015-06-12  Cesar Philippidis  <cesar@codesourcery.com>

	gcc/c-family/
	* c-omp.c (oacc_extract_device_id): Recognize GOMP_DEVICE_DEFAULT.
	(struct identifier_hasher): New struct declaration.
	(oacc_filter_device_types): Report errors on duplicate device_type
	entries.

	gcc/c/
	* c-parser.c (c_parser_oacc_clause_device_type): Switch
	OMP_CLAUSE_DEVICE_TYPE_DEVICES to tree instead of an int.

	gcc/cp/
	* parser.c (cp_parser_oacc_clause_device_type): Likewise.

	gcc/fortran/
	* openmp.c (gfc_match_omp_clauses): Report errors on duplicate
	device_type entries.

	gcc/testsuite/
	* c-c++-common/goacc/dtype-4.c: New test.
	* gfortran.dg/goacc/dtype-2.f95: Update error messages.
	* gfortran.dg/goacc/dtype-3.f: New test.

diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index c30e0d8..bcb6ff4 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -41,6 +41,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "omp-low.h"
 #include "gomp-constants.h"
+#include "tree-hasher.h"
 
 
 /* Complete a #pragma oacc wait construct.  LOC is the location of
@@ -1097,9 +1098,20 @@  oacc_extract_device_id (const char *device)
 {
   if (!strcasecmp (device, "nvidia"))
     return GOMP_DEVICE_NVIDIA_PTX;
+  else if (!strcmp (device, "*"))
+    return GOMP_DEVICE_DEFAULT;
   return GOMP_DEVICE_NONE;
 }
 
+struct identifier_hasher : ggc_cache_hasher<tree>
+{
+  static hashval_t hash (tree t) { return htab_hash_pointer (t); }
+  static bool equal (tree a, tree b)
+  {
+    return !strcmp(IDENTIFIER_POINTER (a), IDENTIFIER_POINTER (b));
+  }
+};
+
 /* Filter out the list of unsupported OpenACC device_types.  */
 
 tree
@@ -1109,56 +1121,55 @@  oacc_filter_device_types (tree clauses)
   tree dtype = NULL_TREE;
   tree seen_nvidia = NULL_TREE;
   tree seen_default = NULL_TREE;
-  int device = 0;
+  hash_table<identifier_hasher> *dt_htab
+    = hash_table<identifier_hasher>::create_ggc (10);
 
   /* First scan for all device_type clauses.  */
   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
     {
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
 	{
-	  int code = TREE_INT_CST_LOW (OMP_CLAUSE_DEVICE_TYPE_DEVICES (c));
+	  tree t;
 
-	  if (code == GOMP_DEVICE_DEFAULT)
+	  for (t = OMP_CLAUSE_DEVICE_TYPE_DEVICES (c); t; t = TREE_CHAIN (t))
 	    {
-	      if (device & (1 << GOMP_DEVICE_DEFAULT))
+	      if (dt_htab->find (t))
 		{
-		  seen_default = NULL_TREE;
 		  error_at (OMP_CLAUSE_LOCATION (c),
-			    "duplicate device_type (*)");
-		  goto filter_error;
+			    "duplicate device_type (%s)",
+			    IDENTIFIER_POINTER (t));
+		  goto filter_dtype;
 		}
 
-	      seen_default = OMP_CLAUSE_DEVICE_TYPE_CLAUSES (c);
-	    }
-	  else if (code & (1 << GOMP_DEVICE_NVIDIA_PTX))
-	    {
-	      if (device & code)
-		{
-		  seen_nvidia = NULL_TREE;
-		  error_at (OMP_CLAUSE_LOCATION (c),
-			    "duplicate device_type (nvidia)");
-		  goto filter_error;
-		}
+	      int code = oacc_extract_device_id (IDENTIFIER_POINTER (t));
 
-	      seen_nvidia = OMP_CLAUSE_DEVICE_TYPE_CLAUSES (c);
-	    }
-	  else
-	    {
-	      if (device & (1 << code))
+	      if (code == GOMP_DEVICE_DEFAULT)
+		seen_default = OMP_CLAUSE_DEVICE_TYPE_CLAUSES (c);
+	      else if (code == GOMP_DEVICE_NVIDIA_PTX)
+		seen_nvidia = OMP_CLAUSE_DEVICE_TYPE_CLAUSES (c);
+	      else
 		{
-		  error_at (OMP_CLAUSE_LOCATION (c),
-			    "duplicate device_type");
-		  goto filter_error;
+		  /* The OpenACC technical committee advises compilers
+		     to silently ignore unknown devices.  */
 		}
+
+	      tree *slot = dt_htab->find_slot (t, INSERT);
+	      *slot = t;
 	    }
-	  device |= (1 << code);
 	}
     }
 
   /* Don't do anything if there aren't any device_type clauses.  */
-  if (device == 0)
+  if (dt_htab->elements () == 0)
     return clauses;
 
+  if (seen_nvidia)
+    dtype = seen_nvidia;
+  else if (seen_default)
+    dtype = seen_default;
+  else
+    goto filter_dtype;
+
   dtype = seen_nvidia ? seen_nvidia : seen_default;
 
   /* Now filter out clauses if necessary.  */
@@ -1186,7 +1197,7 @@  oacc_filter_device_types (tree clauses)
       prev = c;
     }
   
- filter_error:
+ filter_dtype:
   /* Remove all device_type clauses.  Those clauses are located at the
      beginning of the clause list.  */
   for (c = clauses; c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE;
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index cef56dc..f37a8f7 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11246,7 +11246,7 @@  c_parser_oacc_clause_device_type (c_parser *parser, omp_clause_mask mask,
 {
   tree c, clauses;
   location_t loc;
-  int dev_id = GOMP_DEVICE_NONE;
+  tree dev_id = NULL_TREE;
 
   loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -11255,7 +11255,7 @@  c_parser_oacc_clause_device_type (c_parser *parser, omp_clause_mask mask,
   if (c_parser_next_token_is (parser, CPP_MULT))
     {
       c_parser_consume_token (parser);
-      dev_id = GOMP_DEVICE_DEFAULT;
+      dev_id = get_identifier ("*");
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
 	return list;
     }
@@ -11264,7 +11264,6 @@  c_parser_oacc_clause_device_type (c_parser *parser, omp_clause_mask mask,
       do
 	{
 	  tree keyword = error_mark_node;
-	  int dev = 0;
 
 	  if (c_parser_next_token_is (parser, CPP_NAME))
 	    {
@@ -11280,9 +11279,10 @@  c_parser_oacc_clause_device_type (c_parser *parser, omp_clause_mask mask,
 	      return list;
 	    }
 
-	  dev = oacc_extract_device_id (IDENTIFIER_POINTER (keyword));
-	  if (dev)
-	    dev_id |= 1 << dev;
+	  if (dev_id)
+	    dev_id = chainon (dev_id, keyword);
+	  else
+	    dev_id = keyword;
 
 	  if (c_parser_next_token_is (parser, CPP_COMMA))
 	    c_parser_consume_token (parser);
@@ -11297,8 +11297,7 @@  c_parser_oacc_clause_device_type (c_parser *parser, omp_clause_mask mask,
   clauses = c_parser_oacc_all_clauses (parser, mask, "device_type", 0, false,
 				       false);
   OMP_CLAUSE_DEVICE_TYPE_CLAUSES (c) = clauses;
-  OMP_CLAUSE_DEVICE_TYPE_DEVICES (c) = build_int_cst (integer_type_node,
-						      dev_id);
+  OMP_CLAUSE_DEVICE_TYPE_DEVICES (c) = dev_id;
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ca4bb68..60bc287 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28356,7 +28356,7 @@  cp_parser_oacc_clause_device_type (cp_parser *parser, omp_clause_mask mask,
 {
   tree c, clauses;
   location_t loc;
-  int dev_id = GOMP_DEVICE_NONE;
+  tree dev_id = NULL_TREE;
 
   loc = cp_lexer_peek_token (parser->lexer)->location;
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
@@ -28365,7 +28365,7 @@  cp_parser_oacc_clause_device_type (cp_parser *parser, omp_clause_mask mask,
   if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
     {
       cp_lexer_consume_token (parser->lexer);
-      dev_id = GOMP_DEVICE_DEFAULT;
+      dev_id = get_identifier ("*");
       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
 	return list;
     }
@@ -28374,7 +28374,6 @@  cp_parser_oacc_clause_device_type (cp_parser *parser, omp_clause_mask mask,
       do
 	{
 	  tree keyword = error_mark_node;
-	  int dev = 0;
 
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
 	    {
@@ -28390,9 +28389,10 @@  cp_parser_oacc_clause_device_type (cp_parser *parser, omp_clause_mask mask,
 	      return list;
 	    }
 
-	  dev = oacc_extract_device_id (IDENTIFIER_POINTER (keyword));
-	  if (dev)
-	    dev_id |= 1 << dev;
+	  if (dev_id)
+	    dev_id = chainon (dev_id, keyword);
+	  else
+	    dev_id = keyword;
 
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 	    cp_lexer_consume_token (parser->lexer);
@@ -28407,8 +28407,7 @@  cp_parser_oacc_clause_device_type (cp_parser *parser, omp_clause_mask mask,
   clauses = cp_parser_oacc_all_clauses (parser, mask, "device_type",
 					pragma_tok, 0, false, false);
   OMP_CLAUSE_DEVICE_TYPE_CLAUSES (c) = clauses;
-  OMP_CLAUSE_DEVICE_TYPE_DEVICES (c) = build_int_cst (integer_type_node,
-						      dev_id);
+  OMP_CLAUSE_DEVICE_TYPE_DEVICES (c) = dev_id;
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 46bf865..b98a933 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -1171,17 +1171,23 @@  gfc_match_omp_clauses (gfc_omp_clauses **cp, uint64_t mask,
 	    {
 	      char n[GFC_MAX_SYMBOL_LEN + 1];
 
-	      while (gfc_match (" %n ", n) == MATCH_YES)
-		{
-		  if (!strcasecmp ("nvidia", n))
-		    device = GOMP_DEVICE_NVIDIA_PTX;
-		  else
-		    {
-		      /* The OpenACC technical committee advises compilers
-			 to silently ignore unknown devices.  */
-		    }
-		  gfc_match (" , ");
-		}
+	      do {
+		if (gfc_match (" %n ", n) == MATCH_YES)
+		  {
+		    if (!strcasecmp ("nvidia", n))
+		      device = GOMP_DEVICE_NVIDIA_PTX;
+		    else
+		      {
+			/* The OpenACC technical committee advises compilers
+			   to silently ignore unknown devices.  */
+		      }
+		  }
+		else
+		  {
+		    gfc_error ("missing device_type argument");
+		    continue;
+		  }
+	      } while (gfc_match (" , ") == MATCH_YES);
 	    }
 
 	  /* Consume the trailing ')'.  */
diff --git a/gcc/testsuite/c-c++-common/goacc/dtype-4.c b/gcc/testsuite/c-c++-common/goacc/dtype-4.c
new file mode 100644
index 0000000..f49d522
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/dtype-4.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+
+int
+main (int argc, char **argv)
+{
+  float a, b;
+
+  a = 2.0;
+  b = 0.0;
+
+  #pragma acc parallel copy (a, b) device_type (acc_device_host) num_gangs (1) device_type (acc_device_nvidia) num_gangs (2)
+  {
+  }
+
+  #pragma acc parallel copy (a, b) num_gangs (3) device_type (acc_device_host) num_gangs (1) device_type (acc_device_nvidia) num_gangs (2)
+  {
+  }
+
+#pragma acc parallel copy (a, b) device_type (acc_device_host) num_gangs (1) device_type (acc_device_nvidia) num_gangs (2) device_type (acc_device_host) num_gangs (60) /* { dg-error "duplicate device_type" } */
+  {
+  }
+  
+#pragma acc parallel copy (a, b) num_gangs (3) device_type (nvidia) num_gangs (1) device_type (nvidia) num_gangs (2) /* { dg-error "duplicate device_type" } */
+  {
+  }
+
+  return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/goacc/dtype-2.f95 b/gcc/testsuite/gfortran.dg/goacc/dtype-2.f95
index a4573e9..0d96e37 100644
--- a/gcc/testsuite/gfortran.dg/goacc/dtype-2.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/dtype-2.f95
@@ -28,12 +28,12 @@  program dtype
 
 end program dtype
 
-! { dg-error "Invalid character" "" { target *-*-* } 8 }
+! { dg-error "Unclassifiable OpenACC directive" "" { target *-*-* } 8 }
 ! { dg-error "Unexpected" "" { target *-*-* } 10 }
 
-! { dg-error "Invalid character" "" { target *-*-* } 14 }
+! { dg-error "Unclassifiable OpenACC directive" "" { target *-*-* } 14 }
 ! { dg-error "Unexpected" "" { target *-*-* } 15 }
 
-! { dg-error "Invalid character" "" { target *-*-* } 20 }
+! { dg-error "Unclassifiable OpenACC directive" "" { target *-*-* } 20 }
 
-! { dg-error "Invalid character" "" { target *-*-* } 27 }
+! { dg-error "Unclassifiable OpenACC directive" "" { target *-*-* } 27 }
diff --git a/gcc/testsuite/gfortran.dg/goacc/dtype-3.f b/gcc/testsuite/gfortran.dg/goacc/dtype-3.f
new file mode 100644
index 0000000..2b2d45f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/dtype-3.f
@@ -0,0 +1,11 @@ 
+! { dg-do compile }
+
+      IMPLICIT NONE
+
+      INTEGER X
+
+!$ACC PARALLEL DTYPE (NVIDIA) NUM_GANGS(10) COPYOUT(X) ! { dg-error "Unclassifiable OpenACC directive" }
+      X = 0
+!$ACC END PARALLEL ! { dg-error "Unexpected" }
+
+      END