[gomp4] Fix handling of subarrays with update directive

2016-01-22 Thread James Norris

Hi,

The attached patch fixes a defect reported with gcc 5.2
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69414).
It is also the case, the issue is present in the gomp4
branch. The patch also adds additional testing.

Committed to gomp4 after bootstrap and regtesting.

Thanks,
Jim

Index: ChangeLog.gomp
===
--- ChangeLog.gomp	(revision 232740)
+++ ChangeLog.gomp	(revision 232741)
@@ -1,3 +1,11 @@
+2016-01-22  James Norris  
+
+	* oacc-mem.c (delete_copyout, update_dev_host): Fix device address.
+	* testsuite/libgomp.oacc-c-c++-common/update-1.c: Additional tests.
+	* testsuite/libgomp.oacc-c-c++-common/update-1-2.c: Likewise.
+	* testsuite/libgomp.oacc-fortran/update-1.f90: New file.
+	* testsuite/libgomp.oacc-fortran/update-1-2.f90: Likewise.
+
 2016-01-22  Nathan Sidwell  
 
 	* testsuite/libgomp.oacc-c-c++-common/routine-1.c: Specify vector.
Index: oacc-mem.c
===
--- oacc-mem.c	(revision 232740)
+++ oacc-mem.c	(revision 232741)
@@ -509,7 +509,7 @@
   gomp_fatal ("[%p,%d] is not mapped", (void *)h, (int)s);
 }
 
-  d = (void *) (n->tgt->tgt_start + n->tgt_offset);
+  d = (void *) (n->tgt->tgt_start + n->tgt_offset + h - n->host_start);
 
   host_size = n->host_end - n->host_start;
 
@@ -562,7 +562,7 @@
   gomp_fatal ("[%p,%d] is not mapped", h, (int)s);
 }
 
-  d = (void *) (n->tgt->tgt_start + n->tgt_offset);
+  d = (void *) (n->tgt->tgt_start + n->tgt_offset + h - n->host_start);
 
   gomp_mutex_unlock (&acc_dev->lock);
 
Index: testsuite/libgomp.oacc-fortran/update-1-2.f90
===
--- testsuite/libgomp.oacc-fortran/update-1-2.f90	(revision 0)
+++ testsuite/libgomp.oacc-fortran/update-1-2.f90	(revision 232741)
@@ -0,0 +1,239 @@
+! Copy of update-1.f90 with self exchanged with host for !$acc update
+
+! { dg-do run }
+! { dg-skip-if "" { *-*-* } { "*" } { "-DACC_MEM_SHARED=0" } }
+
+program update
+  use openacc
+  implicit none 
+  integer, parameter :: N = 8
+  real :: a(N), b(N)
+  integer i
+
+  do i = 1, N
+a(i) = 3.0
+b(i) = 0.0
+  end do
+
+  !$acc enter data copyin (a, b)
+
+  !$acc parallel present (a, b)
+do i = 1, N
+  b(i) = a(i)
+end do
+  !$acc end parallel
+
+  !$acc update self (a, b)
+
+  do i = 1, N
+if (a(i) .ne. 3.0) call abort
+if (b(i) .ne. 3.0) call abort
+  end do
+
+  if (acc_is_present (a) .neqv. .TRUE.) call abort
+  if (acc_is_present (b) .neqv. .TRUE.) call abort
+
+  do i = 1, N
+a(i) = 5.0
+b(i) = 1.0
+  end do
+
+  !$acc update device (a, b)
+
+  !$acc parallel present (a, b)
+do i = 1, N
+  b(i) = a(i)
+end do 
+  !$acc end parallel
+
+  !$acc update self (a, b)
+
+  do i = 1, N
+if (a(i) .ne. 5.0) call abort
+if (b(i) .ne. 5.0) call abort
+ end do
+
+  if (acc_is_present (a) .neqv. .TRUE.) call abort
+  if (acc_is_present (b) .neqv. .TRUE.) call abort
+
+  !$acc parallel present (a, b)
+  do i = 1, N
+b(i) = a(i)
+  end do
+  !$acc end parallel
+
+  !$acc update self (a, b)
+
+  do i = 1, N
+if (a(i) .ne. 5.0) call abort
+if (b(i) .ne. 5.0) call abort
+  end do
+
+  do i = 1, N
+a(i) = 6.0
+b(i) = 0.0
+  end do
+
+  !$acc update device (a, b)
+
+  do i = 1, N
+a(i) = 9.0
+  end do
+
+  !$acc parallel present (a, b)
+do i = 1, N
+  b(i) = a(i)
+end do
+  !$acc end parallel
+
+  !$acc update self (a, b)
+
+  do i = 1, N
+if (a(i) .ne. 6.0) call abort
+if (b(i) .ne. 6.0) call abort
+  end do
+
+  if (acc_is_present (a) .neqv. .TRUE.) call abort
+  if (acc_is_present (b) .neqv. .TRUE.) call abort
+
+  do i = 1, N
+a(i) = 7.0
+b(i) = 2.0
+  end do
+
+  !$acc update device (a, b)
+
+  do i = 1, N
+a(i) = 9.0
+  end do
+
+  !$acc parallel present (a, b)
+do i = 1, N
+  b(i) = a(i)
+end do
+  !$acc end parallel
+
+  !$acc update self (a, b)
+
+  do i = 1, N
+if (a(i) .ne. 7.0) call abort
+if (b(i) .ne. 7.0) call abort
+  end do
+
+  do i = 1, N
+a(i) = 9.0
+  end do
+
+  !$acc update device (a)
+
+  !$acc parallel present (a, b)
+do i = 1, N
+  b(i) = a(i)
+end do
+  !$acc end parallel
+
+  !$acc update self (a, b)
+
+  do i = 1, N
+if (a(i) .ne. 9.0) call abort
+if (b(i) .ne. 9.0) call abort
+  end do
+
+  if (acc_is_present (a) .neqv. .TRUE.) call abort
+  if (acc_is_present (b) .neqv. .TRUE.) call abort
+
+  do i = 1, N
+a(i) = 5.0
+  end do
+
+  !$acc update device (a)
+
+  do i = 1, N
+a(i) = 6.0
+  end do
+
+  !$acc update device (a(1:rshift (N, 1)))
+
+  !$acc parallel present (a, b)
+do i = 1, N
+  b(i) = a(i)
+end do
+  !$acc end parallel
+
+  !$acc update self (a, b)
+
+  do i = 1, rshift (N, 1)
+if (a(i) .ne. 6.0) call abort
+if (b(i) .ne. 6.0) call abort
+  end do
+
+  do i = rsh

Re: [PATCH] Fix use of declare'd vars by routine procedures.

2016-01-28 Thread James Norris

Jakub,

On 01/22/2016 04:39 AM, Jakub Jelinek wrote:


As for the extra error, I think it would be better to diagnose this during
gimplification, that way you do it for all FEs, plus you have the omp
context in there, etc.  The error wording is weird, the diagnostic
should make it clear use of what is invalid in what and why.

Jakub



I think the attached change is what you had in mind with
regard to doing the check at gimplification time.

OK?

Thanks for taking the time to review,
Jim


ChangeLog entries

gcc/
* gimplify.c (gimplify_var_or_parm_decl): Add variable usage check.
gcc/testsuite/
* c-c++-common/goacc/routine-5.c: Add tests.

Index: gcc/ChangeLog
===
diff --git a/trunk/gcc/ChangeLog b/trunk/gcc/ChangeLog
--- a/trunk/gcc/ChangeLog	(revision 232802)
+++ b/trunk/gcc/ChangeLog	(working copy)
@@ -1,3 +1,7 @@
+2016-01-XX  James Norris  
+
+	* gimplify.c (gimplify_var_or_parm_decl): Add usage check.
+
 2016-01-25  Jeff Law  
 
 	PR tree-optimization/69196
Index: gcc/gimplify.c
===
diff --git a/trunk/gcc/gimplify.c b/trunk/gcc/gimplify.c
--- a/trunk/gcc/gimplify.c	(revision 232802)
+++ b/trunk/gcc/gimplify.c	(working copy)
@@ -1841,6 +1841,33 @@
   return GS_ERROR;
 }
 
+  /* Validate variable for use within routine function.  */
+  if (gimplify_omp_ctxp && gimplify_omp_ctxp->region_type == ORT_TARGET
+  && get_oacc_fn_attrib (current_function_decl)
+  && TREE_CODE (decl) == VAR_DECL
+  && is_global_var (decl)
+  && ((TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+	  || (!TREE_STATIC (decl) && DECL_EXTERNAL (decl
+{
+  location_t loc = DECL_SOURCE_LOCATION (decl);
+
+  if (lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (decl)))
+	{
+	  error_at (loc,
+		"%qE with % clause used in % function",
+		DECL_NAME (decl));
+	  return GS_ERROR;
+	}
+  else if (!lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
+	{
+	  error_at (loc,
+		"storage class of %qE cannot be ", DECL_NAME (decl));
+	  error_at (gimplify_omp_ctxp->location,
+		"used in enclosing % function");
+	  return GS_ERROR;
+	}
+}
+
   /* When within an OMP context, notice uses of variables.  */
   if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
 return GS_ALL_DONE;
Index: gcc/testsuite/ChangeLog
===
diff --git a/trunk/gcc/testsuite/ChangeLog b/trunk/gcc/testsuite/ChangeLog
--- a/trunk/gcc/testsuite/ChangeLog	(revision 232802)
+++ b/trunk/gcc/testsuite/ChangeLog	(working copy)
@@ -1,3 +1,7 @@
+2016-01-XX  James Norris  
+
+	* c-c++-common/goacc/routine-5.c: Add tests.
+
 2016-01-25  Jeff Law  
 
 	PR tree-optimization/69196
Index: gcc/testsuite/c-c++-common/goacc/routine-5.c
===
diff --git a/trunk/gcc/testsuite/c-c++-common/goacc/routine-5.c b/trunk/gcc/testsuite/c-c++-common/goacc/routine-5.c
--- a/trunk/gcc/testsuite/c-c++-common/goacc/routine-5.c	(revision 232802)
+++ b/trunk/gcc/testsuite/c-c++-common/goacc/routine-5.c	(working copy)
@@ -45,3 +45,70 @@
 #pragma acc routine (a) /* { dg-error "does not refer to" } */
   
 #pragma acc routine (c) /* { dg-error "does not refer to" } */
+
+float vb1; /* { dg-error "storage class of" } */
+
+#pragma acc routine
+int
+func1 (int a)		/* { dg-error "used in enclosing" } */
+{
+  vb1 = a + 1;
+
+  return vb1;
+}
+
+#pragma acc routine
+int
+func2 (int a)		/* { dg-error "used in enclosing" } */
+{
+  static int vb2;	/* { dg-error "storage class of" } */
+
+  vb2 = a + 1;
+
+  return vb2;
+}
+
+float vb3;		/* { dg-error "'link' clause used" } */
+#pragma acc declare link (vb3)
+
+#pragma acc routine
+int
+func3 (int a)
+{
+  vb3 = a + 1;
+
+  return vb3;
+}
+
+float vb4;
+#pragma acc declare create (vb4)
+
+#pragma acc routine
+int
+func4 (int a)
+{
+  vb4 = a + 1;
+
+  return vb4;
+}
+
+extern float vb5;	/* { dg-error "storage class of" } */
+
+#pragma acc routine
+int
+func5 (int a)		/* { dg-error "used in enclosing" } */
+{
+  vb5 = a + 1;
+
+  return vb5;
+}
+
+#pragma acc routine
+int
+func6 (int a)		/* { dg-error "used in enclosing" } */
+{
+  extern float vb6;	/* { dg-error "storage class of" } */
+  vb6 = a + 1;
+
+  return vb6;
+}


Re: [PATCH] Fix use of declare'd vars by routine procedures.

2016-02-01 Thread James Norris

Hi!

On 01/29/2016 02:31 AM, Jakub Jelinek wrote:

On Thu, Jan 28, 2016 at 12:26:38PM -0600, James Norris wrote:

I think the attached change is what you had in mind with
regard to doing the check at gimplification time.


Nope, this is still a wrong location for that.
If you look at the next line after the block you've added, you'll see
if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
And that function fairly early calls is_global_var (decl).  So you know
already gimplify_omp_ctxp && is_global_var (decl), just put the rest into
that block.


When said you said "rest into that block", I assumed you meant
the block in omp_notice_variable () that has the function call
to is_global_var () as the if condition.


The TREE_CODE (decl) == VAR_DECL check is VAR_P (decl).


Fixed.


What do you want to achieve with


+  && ((TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+   || (!TREE_STATIC (decl) && DECL_EXTERNAL (decl


?  is_global_var already guarantees you that it is either TREE_STATIC
or DECL_EXTERNAL, why is that not good enough?


As you pointed out above, the check is not necessary.




[snip snip]

+  /* Validate variable for use within routine function.  */
+  if (gimplify_omp_ctxp && gimplify_omp_ctxp->region_type == ORT_TARGET
+  && get_oacc_fn_attrib (current_function_decl)


If you only care about the implicit target region of acc routine, I think
you also want to check that gimplify_omp_ctxp->outer_context == NULL.


Check added.




[snip snip]


And I'm really confused by this error message.  If you are complaining that
the variable is not listed in acc declare clauses, why don't you say that?
What does the error have to do with its storage class?
Also, splitting one error into two is weird, usually there would be one
error message and perhaps inform after it.


Error messages re-written to make better sense.

Thanks!

Jim

= ChangeLog entries

gcc/
* gimplify.c (omp_notice_variable): Add variable usage check.
gcc/testsuite/
* c-c++-common/goacc/routine-5.c: Add tests.



diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9f99842..41cd7a7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-XX  James Norris  
+
+	* gimplify.c (omp_notice_variable): Add usage check.
+
 2016-01-29  Jakub Jelinek  
 
 	PR target/69551
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 32bc1fd..5833605 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6087,9 +6087,9 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
   if (ctx->region_type == ORT_NONE)
 return lang_hooks.decls.omp_disregard_value_expr (decl, false);
 
-  /* Threadprivate variables are predetermined.  */
   if (is_global_var (decl))
 {
+  /* Threadprivate variables are predetermined.  */
   if (DECL_THREAD_LOCAL_P (decl))
 	return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
 
@@ -6100,6 +6100,30 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
 	  if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
 	return omp_notice_threadprivate_variable (ctx, decl, value);
 	}
+
+  if (gimplify_omp_ctxp->outer_context == NULL
+	  && VAR_P (decl)
+	  && get_oacc_fn_attrib (current_function_decl))
+	{
+	  location_t loc = DECL_SOURCE_LOCATION (decl);
+
+	  if (lookup_attribute ("omp declare target link",
+DECL_ATTRIBUTES (decl)))
+	{
+	  error_at (loc,
+			"%qE with % clause used in % function",
+			DECL_NAME (decl));
+	  return false;
+	}
+	  else if (!lookup_attribute ("omp declare target",
+  DECL_ATTRIBUTES (decl)))
+	{
+	  error_at (loc,
+			"%qE requires a % directive for use "
+			"in a % function", DECL_NAME (decl));
+	  return false;
+	}
+	}
 }
 
   n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
@@ -8223,7 +8247,7 @@ gimplify_oacc_declare (tree *expr_p, gimple_seq *pre_p)
 	  if (oacc_declare_returns == NULL)
 		oacc_declare_returns = new hash_map;
 
-	  oacc_declare_returns->put (decl, c);
+		oacc_declare_returns->put (decl, c);
 	}
 	}
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 150ebc8..61003c2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-XX  James Norris  
+
+	* c-c++-common/goacc/routine-5.c: Add tests.
+
 2016-01-29  Jakub Jelinek  
 
 	PR target/69551
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-5.c b/gcc/testsuite/c-c++-common/goacc/routine-5.c
index ccda097..c34838f 100644
--- a/gcc/testsuite/c-c++-common/goacc/routine-5.c
+++ b/gcc/testsuite/c-c++-common/goacc/routine-5.c
@@ -45,3 +45,97 @@ using namespace g;
 #pragma acc routine (a) /* { dg-error "does not refer to" } */
   
 #pragma acc rou

[PATCH] Fix PR64748

2016-02-01 Thread James Norris

Hi,

The attached patch resolves c/PR64748. The patch
adds the use of parm's with the deviceptr clause.

Question

As there is VAR_P (), could there be a PARM_P ()?
Or would that obscure something I'm not aware of?

Regtested and bootstrapped on x86_64.

Thanks,
Jim

 ChangeLog entries...

gcc/c/
PR c/64748
* c-parser.c (c_parser_oacc_data_clause_deviceptr): Allow parms.

gcc/cp/
PR c/64748
* parser.c (cp_parser_oacc_data_clause_deviceptr): Allow parms.

gcc/testsuite/
PR c/64748
* c-c++-common/goacc/deviceptr-1.c: Add tests.

diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 5341f04..f2d114c 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-XX  James Norris  
+
+	PR c/64748
+	* c-parser.c (c_parser_oacc_data_clause_deviceptr): Allow parms.
+
 2016-01-27  Jakub Jelinek  
 
 	PR debug/66869
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index eede3a7..f61f559 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -10760,7 +10760,7 @@ c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
 	 c_parser_omp_var_list_parens() should construct a list of
 	 locations to go along with the var list.  */
 
-  if (!VAR_P (v))
+  if (!VAR_P (v) && !(TREE_CODE (v) == PARM_DECL))
 	error_at (loc, "%qD is not a variable", v);
   else if (TREE_TYPE (v) == error_mark_node)
 	;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3b5c9d5..b11b859 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-XX  James Norris  
+
+	PR c/64748
+	* parser.c (cp_parser_oacc_data_clause_deviceptr): Allow parms.
+
 2016-01-29  Jakub Jelinek  
 
 	PR debug/66869
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d03b0c9..de96b44 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30087,7 +30087,7 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list)
 	 c_parser_omp_var_list_parens should construct a list of
 	 locations to go along with the var list.  */
 
-  if (!VAR_P (v))
+  if (!VAR_P (v) && !(TREE_CODE (v) == PARM_DECL))
 	error_at (loc, "%qD is not a variable", v);
   else if (TREE_TYPE (v) == error_mark_node)
 	;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 150ebc8..db281cd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-XX  James Norris  
+
+	PR c/64748
+	* c-c++-common/goacc/deviceptr-1.c: Add tests.
+
 2016-01-29  Jakub Jelinek  
 
 	PR target/69551
diff --git a/gcc/testsuite/c-c++-common/goacc/deviceptr-1.c b/gcc/testsuite/c-c++-common/goacc/deviceptr-1.c
index 546fa82..6edbdb1 100644
--- a/gcc/testsuite/c-c++-common/goacc/deviceptr-1.c
+++ b/gcc/testsuite/c-c++-common/goacc/deviceptr-1.c
@@ -84,3 +84,21 @@ fun4 (void)
 #pragma acc parallel deviceptr(s2_p)
   s2_p = 0;
 }
+
+void
+func5 (float *fp)
+{
+
+#pragma acc data deviceptr (fp)
+{ }
+
+}
+
+void
+func6 (float fp)
+{
+
+#pragma acc data deviceptr (fp)	/* { dg-error "is not a pointer variable" } */
+{ }
+
+}


Re: [PATCH] Fix PR64748

2016-02-02 Thread James Norris

Hi!

On 02/01/2016 02:03 PM, Jakub Jelinek wrote:

On Mon, Feb 01, 2016 at 01:41:50PM -0600, James Norris wrote:

The attached patch resolves c/PR64748. The patch
adds the use of parm's with the deviceptr clause.


 [snip snip]

--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -10760,7 +10760,7 @@ c_parser_oacc_data_clause_deviceptr (c_parser *parser, 
tree list)
 c_parser_omp_var_list_parens() should construct a list of
 locations to go along with the var list.  */

-  if (!VAR_P (v))
+  if (!VAR_P (v) && !(TREE_CODE (v) == PARM_DECL))


Please don't write !(x == y) but x != y.


Fixed.




--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30087,7 +30087,7 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser 
*parser, tree list)
 c_parser_omp_var_list_parens should construct a list of
 locations to go along with the var list.  */

-  if (!VAR_P (v))
+  if (!VAR_P (v) && !(TREE_CODE (v) == PARM_DECL))
error_at (loc, "%qD is not a variable", v);
else if (TREE_TYPE (v) == error_mark_node)
;


For C++, all this diagnostics is premature, if processing_template_decl
you really often don't know what the type will be, not sure if you always
know at least if it is a VAR_DECL, PARM_DECL or something else.  I bet you
can easily ICE with the current POINTER_TYPE_P (TREE_TYPE (v)) check as
in templates the type can be NULL, or it could be some lang type and only
later on become POINTER_TYPE, etc.
For C++ the diagnostics need to be done during finish_omp_clauses or so, not
earlier.


The check has been moved to finish_omp_clause (). I put the check at
the tail end of the checking, as I wasn't able to determine if there
was a checking precedence done by the if-else-if sequence.

Thanks for the review!

Jim


= ChangeLog entries...

gcc/testsuite/

PR c/64748
* c-c++-common/goacc/deviceptr-1.c: Add tests.
* g++.dg/goacc/deviceptr-1.c: New file.


gcc/cp/

PR c/64748
* parser.c (cp_parser_oacc_data_clause_deviceptr): Remove checking.
* semantics.c (finish_omp_clauses): Add deviceptr checking.


gcc/c/

PR c/64748
* c-parser.c (c_parser_oacc_data_clause_deviceptr): Allow parms.



diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 5341f04..f2d114c 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-XX  James Norris  
+
+	PR c/64748
+	* c-parser.c (c_parser_oacc_data_clause_deviceptr): Allow parms.
+
 2016-01-27  Jakub Jelinek  
 
 	PR debug/66869
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index eede3a7..229fd6e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -10760,7 +10760,7 @@ c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
 	 c_parser_omp_var_list_parens() should construct a list of
 	 locations to go along with the var list.  */
 
-  if (!VAR_P (v))
+  if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
 	error_at (loc, "%qD is not a variable", v);
   else if (TREE_TYPE (v) == error_mark_node)
 	;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3b5c9d5..76cf5b1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2016-02-XX  James Norris  
+
+	PR c/64748
+	* parser.c (cp_parser_oacc_data_clause_deviceptr): Remove checking.
+	* semantics.c (finish_omp_clauses): Add deviceptr checking.
+
 2016-01-29  Jakub Jelinek  
 
 	PR debug/66869
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d03b0c9..10f3627 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30080,20 +30080,6 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list)
   for (t = vars; t; t = TREE_CHAIN (t))
 {
   tree v = TREE_PURPOSE (t);
-
-  /* FIXME diagnostics: Ideally we should keep individual
-	 locations for all the variables in the var list to make the
-	 following errors more precise.  Perhaps
-	 c_parser_omp_var_list_parens should construct a list of
-	 locations to go along with the var list.  */
-
-  if (!VAR_P (v))
-	error_at (loc, "%qD is not a variable", v);
-  else if (TREE_TYPE (v) == error_mark_node)
-	;
-  else if (!POINTER_TYPE_P (TREE_TYPE (v)))
-	error_at (loc, "%qD is not a pointer variable", v);
-
   tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
   OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
   OMP_CLAUSE_DECL (u) = v;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 95c4f19..1e376b1 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6683,6 +6683,14 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	  error ("%qD appears both in data and map clauses", t);
 	  remove = true;
 	}
+	  else if (!processing_template_decl
+		   && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+		   && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR
+		   && !POINTER_TYPE_

[gomp4] Fix use of declare'd vars by routine procedures.

2016-02-03 Thread James Norris



I've backported this patch from trunk to gomp-4_0-branch. This patch
updates a previous patch to gomp4 in dealing with variables used
within a routine procedure.

Reference:

https://gcc.gnu.org/ml/gcc-patches/2016-01/msg01231.html

Thanks,
Jim


 ChangeLog entries...

gcc/
* gimplify.c (omp_notice_variable): Add usage check.

gcc/testsuite/
* c-c++-common/goacc/routine-5.c: Add tests.

gcc/c/
* c-typeck.c (build_external_ref): Remove usage check.

gcc/cp/
* semantics.c (finish_id_expression): Remove usage check.
Index: gcc/ChangeLog.gomp
===
--- gcc/ChangeLog.gomp	(revision 233104)
+++ gcc/ChangeLog.gomp	(working copy)
@@ -1,3 +1,9 @@
+2016-02-03  James Norris  
+	* gimplify.c (omp_notice_variable): Add usage check.
+
 2016-01-22  Nathan Sidwell  
 
 	* omp-low.c (struct oacc_loop): Add 'inner' field.
Index: gcc/c/ChangeLog.gomp
===
--- gcc/c/ChangeLog.gomp	(revision 233104)
+++ gcc/c/ChangeLog.gomp	(working copy)
@@ -1,3 +1,7 @@
+2016-02-03  James Norris  
+
+	* c-typeck.c (build_external_ref): Remove usage check.
+
 2016-01-14  James Norris  
 
 	* c-parser.c (c_finish_oacc_routine): Remove attribute.
Index: gcc/c/c-typeck.c
===
--- gcc/c/c-typeck.c	(revision 233104)
+++ gcc/c/c-typeck.c	(working copy)
@@ -2677,26 +2677,6 @@
   tree ref;
   tree decl = lookup_name (id);
 
-  if (decl
-  && decl != error_mark_node
-  && current_function_decl
-  && TREE_CODE (decl) == VAR_DECL
-  && is_global_var (decl)
-  && get_oacc_fn_attrib (current_function_decl))
-{
-  /* Validate data type for use with routine directive.  */
-  if (lookup_attribute ("omp declare target link",
-			DECL_ATTRIBUTES (decl))
-	  || ((!lookup_attribute ("omp declare target",
-  DECL_ATTRIBUTES (decl))
-	   && ((TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
-		   || (!TREE_STATIC (decl) && DECL_EXTERNAL (decl))
-	{
-	  error_at (loc, "invalid use in % function");
-	  return error_mark_node;
-	}
-}
-
   /* In Objective-C, an instance variable (ivar) may be preferred to
  whatever lookup_name() found.  */
   decl = objc_lookup_ivar (decl, id);
Index: gcc/cp/ChangeLog.gomp
===
--- gcc/cp/ChangeLog.gomp	(revision 233104)
+++ gcc/cp/ChangeLog.gomp	(working copy)
@@ -1,3 +1,7 @@
+2016-02-03  James Norris  
+
+	* semantics.c (finish_id_expression): Remove usage check.
+
 2016-01-20  Cesar Philippidis  
 
 	* parser.c (cp_parser_oacc_all_clauses): Call finish_omp_clauses
Index: gcc/cp/semantics.c
===
--- gcc/cp/semantics.c	(revision 233104)
+++ gcc/cp/semantics.c	(working copy)
@@ -3712,25 +3712,6 @@
 
 	  decl = convert_from_reference (decl);
 	}
-
-  if (decl != error_mark_node
-	  && current_function_decl
-	  && TREE_CODE (decl) == VAR_DECL
-	  && is_global_var (decl)
-  && get_oacc_fn_attrib (current_function_decl))
-	{
-	  /* Validate data type for use with routine directive.  */
-	  if (lookup_attribute ("omp declare target link",
-DECL_ATTRIBUTES (decl))
-	  || ((!lookup_attribute ("omp declare target",
-  DECL_ATTRIBUTES (decl))
-		   && ((TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
-			|| (!TREE_STATIC (decl) && DECL_EXTERNAL (decl))
-	{
-	  *error_msg = "invalid use in % function";
-	  return error_mark_node;
-	}
-	}
 }
 
   return cp_expr (decl, location);
Index: gcc/gimplify.c
===
--- gcc/gimplify.c	(revision 233104)
+++ gcc/gimplify.c	(working copy)
@@ -6095,9 +6095,9 @@
   if (ctx->region_type == ORT_NONE)
 return lang_hooks.decls.omp_disregard_value_expr (decl, false);
 
-  /* Threadprivate variables are predetermined.  */
   if (is_global_var (decl))
 {
+  /* Threadprivate variables are predetermined.  */
   if (DECL_THREAD_LOCAL_P (decl))
 	return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
 
@@ -6108,6 +6108,30 @@
 	  if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
 	return omp_notice_threadprivate_variable (ctx, decl, value);
 	}
+
+  if (gimplify_omp_ctxp->outer_context == NULL
+	  && VAR_P (decl)
+	  && get_oacc_fn_attrib (current_function_decl))
+	{
+	  location_t loc = DECL_SOURCE_LOCATION (decl);
+
+	  if (lookup_attribute ("omp declare target link",
+DECL_ATTRIBUTES (decl)))
+	{
+	  error_at (loc,
+			"%qE with % clause used in % function",
+

Re: [PATCH] Fix PR64748

2016-02-15 Thread James Norris

Hi,


Ping!

Thanks,
Jim


On 02/02/2016 08:51 AM, James Norris wrote:

Hi!

On 02/01/2016 02:03 PM, Jakub Jelinek wrote:

On Mon, Feb 01, 2016 at 01:41:50PM -0600, James Norris wrote:

The attached patch resolves c/PR64748. The patch
adds the use of parm's with the deviceptr clause.


 [snip snip]

--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -10760,7 +10760,7 @@ c_parser_oacc_data_clause_deviceptr (c_parser
*parser, tree list)
   c_parser_omp_var_list_parens() should construct a list of
   locations to go along with the var list.  */

-  if (!VAR_P (v))
+  if (!VAR_P (v) && !(TREE_CODE (v) == PARM_DECL))


Please don't write !(x == y) but x != y.


Fixed.




--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30087,7 +30087,7 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser
*parser, tree list)
   c_parser_omp_var_list_parens should construct a list of
   locations to go along with the var list.  */

-  if (!VAR_P (v))
+  if (!VAR_P (v) && !(TREE_CODE (v) == PARM_DECL))
  error_at (loc, "%qD is not a variable", v);
else if (TREE_TYPE (v) == error_mark_node)
  ;


For C++, all this diagnostics is premature, if processing_template_decl
you really often don't know what the type will be, not sure if you always
know at least if it is a VAR_DECL, PARM_DECL or something else.  I bet you
can easily ICE with the current POINTER_TYPE_P (TREE_TYPE (v)) check as
in templates the type can be NULL, or it could be some lang type and only
later on become POINTER_TYPE, etc.
For C++ the diagnostics need to be done during finish_omp_clauses or so, not
earlier.


The check has been moved to finish_omp_clause (). I put the check at
the tail end of the checking, as I wasn't able to determine if there
was a checking precedence done by the if-else-if sequence.

Thanks for the review!

Jim


= ChangeLog entries...

 gcc/testsuite/

 PR c/64748
 * c-c++-common/goacc/deviceptr-1.c: Add tests.
 * g++.dg/goacc/deviceptr-1.c: New file.


 gcc/cp/

 PR c/64748
 * parser.c (cp_parser_oacc_data_clause_deviceptr): Remove checking.
 * semantics.c (finish_omp_clauses): Add deviceptr checking.


 gcc/c/

 PR c/64748
 * c-parser.c (c_parser_oacc_data_clause_deviceptr): Allow parms.







[gomp4] Fix PR64748

2016-02-16 Thread James Norris

Hi,

The attached patch is a backport of the fix for PR64748.

Thanks,
Jim

 ChangeLog entries



Backport from trunk:
PR c/64748

gcc/cp/
* parser.c (cp_parser_oacc_data_clause_deviceptr): Remove checking.
* semantics.c (finish_omp_clauses): Add deviceptr checking.

gcc/testsuite/
* c-c++-common/goacc/deviceptr-1.c: Add tests.
* g++.dg/goacc/deviceptr-1.c: New file.
Index: gcc/cp/ChangeLog.gomp
===
--- gcc/cp/ChangeLog.gomp	(revision 233463)
+++ gcc/cp/ChangeLog.gomp	(working copy)
@@ -1,3 +1,10 @@
+2016-02-15  James Norris  
+
+	Backport from trunk:
+	PR c/64748
+	* parser.c (cp_parser_oacc_data_clause_deviceptr): Remove checking.
+	* semantics.c (finish_omp_clauses): Add deviceptr checking.
+
 2016-02-03  James Norris  
 
 	* semantics.c (finish_id_expression): Remove usage check.
Index: gcc/cp/parser.c
===
--- gcc/cp/parser.c	(revision 233463)
+++ gcc/cp/parser.c	(working copy)
@@ -30093,20 +30093,6 @@
   for (t = vars; t; t = TREE_CHAIN (t))
 {
   tree v = TREE_PURPOSE (t);
-
-  /* FIXME diagnostics: Ideally we should keep individual
-	 locations for all the variables in the var list to make the
-	 following errors more precise.  Perhaps
-	 c_parser_omp_var_list_parens should construct a list of
-	 locations to go along with the var list.  */
-
-  if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
-	error_at (loc, "%qD is not a variable", v);
-  else if (TREE_TYPE (v) == error_mark_node)
-	;
-  else if (!POINTER_TYPE_P (TREE_TYPE (v)))
-	error_at (loc, "%qD is not a pointer variable", v);
-
   tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
   OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
   OMP_CLAUSE_DECL (u) = v;
Index: gcc/cp/semantics.c
===
--- gcc/cp/semantics.c	(revision 233463)
+++ gcc/cp/semantics.c	(working copy)
@@ -6729,6 +6729,14 @@
 	  remove = true;
 	}
 	  else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+		   && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR
+		   && !type_dependent_expression_p (t)
+		   && !POINTER_TYPE_P (TREE_TYPE (t)))
+	{
+	  error ("%qD is not a pointer variable", t);
+	  remove = true;
+	}
+	  else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
 		   && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
 	{
 	  if (bitmap_bit_p (&generic_head, DECL_UID (t))
Index: gcc/testsuite/ChangeLog.gomp
===
--- gcc/testsuite/ChangeLog.gomp	(revision 233463)
+++ gcc/testsuite/ChangeLog.gomp	(working copy)
@@ -1,3 +1,10 @@
+2016-02-15  James Norris  
+
+	Backport from trunk:
+	PR c/64748
+	* c-c++-common/goacc/deviceptr-1.c: Add tests.
+	* g++.dg/goacc/deviceptr-1.c: New file.
+
 2016-02-03  James Norris  
 
 	Backport from trunk:
Index: gcc/testsuite/c-c++-common/goacc/deviceptr-1.c
===
--- gcc/testsuite/c-c++-common/goacc/deviceptr-1.c	(revision 233463)
+++ gcc/testsuite/c-c++-common/goacc/deviceptr-1.c	(working copy)
@@ -84,3 +84,17 @@
 #pragma acc parallel deviceptr(s2_p)
   s2_p = 0;
 }
+
+void
+func5 (float *fp)
+{
+#pragma acc data deviceptr (fp)
+  ;
+}
+
+void
+func6 (float fp)
+{
+#pragma acc data deviceptr (fp)	/* { dg-error "is not a pointer variable" } */
+  ;
+}
Index: gcc/testsuite/g++.dg/goacc/deviceptr-1.C
===
--- gcc/testsuite/g++.dg/goacc/deviceptr-1.C	(revision 0)
+++ gcc/testsuite/g++.dg/goacc/deviceptr-1.C	(working copy)
@@ -0,0 +1,38 @@
+// { dg-do compile }
+
+template 
+void
+func1 (P p)
+{
+#pragma acc data deviceptr (p)// { dg-bogus "is not a pointer" }
+  ;
+}
+
+void
+func2 (int *p)
+{
+  func1 (p);
+}
+
+template 
+void
+func3 (P p)
+{
+#pragma acc data deviceptr (p)// { dg-error "is not a pointer" }
+  ;
+}
+void
+func4 (int p)
+{
+  func3 (p);
+}
+
+template 
+void
+func5 (int *p, int q)
+{
+#pragma acc data deviceptr (p)// { dg-bogus "is not a pointer" }
+  ;
+#pragma acc data deviceptr (q)// { dg-error "is not a pointer" }
+  ;
+}


[gomp4] splay tree implementation for future OpenACC runtime library usage.

2013-12-05 Thread James Norris

Hi!

Here is a patch that changes the splay tree implementation. Specifically,
generalizes the implementation so that it can be used by other functions
outside of its use by the functions within target.c.

Would appreciate review of the changes.

Thanks!



Generalize splay tree implementation for future OpenACC Runtime
Library usage.

* Makefile.am (libgomp_la_SOURCES): Add splay-tree.c.
* Makefile.in: Regenerate.
* target.c: Move definition of splay_tree_key_s to target.h
* target.h: New file with definition from target.c.
* splay-tree.h: (rotate_left, rotate_right, splay_tree_splay,
  splay_tree_insert, splay_tree_remove, splay_tree_lookup):
  Move functions to splay-tree.c.
  (splay_tree_lookup, splay_tree_insert, splay_tree_remove,
  splay_compare): New declarations.
* splay-tree.c: New file with functions from splay-tree.h.
   
Index: splay-tree.c
===
--- splay-tree.c(revision 0)
+++ splay-tree.c(revision 0)
@@ -0,0 +1,227 @@
+/* A splay-tree datatype.
+   Copyright 1998-2013
+   Free Software Foundation, Inc.
+   Contributed by Mark Mitchell (m...@markmitchell.com).
+
+   This file is part of the GNU OpenMP Library (libgomp).
+
+   Libgomp is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+   more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   .  */
+
+/* The splay tree code copied from include/splay-tree.h and adjusted,
+   so that all the data lives directly in splay_tree_node_s structure
+   and no extra allocations are needed.
+
+   Files including this header should before including it add:
+typedef struct splay_tree_node_s *splay_tree_node;
+typedef struct splay_tree_s *splay_tree;
+typedef struct splay_tree_key_s *splay_tree_key;
+   define splay_tree_key_s structure, and define
+   splay_compare inline function.  */
+
+/* For an easily readable description of splay-trees, see:
+
+ Lewis, Harry R. and Denenberg, Larry.  Data Structures and Their
+ Algorithms.  Harper-Collins, Inc.  1991.
+
+   The major feature of splay trees is that all basic tree operations
+   are amortized O(log n) time for a tree with n nodes.  */
+
+/* Forward declaration for a node in the tree.  */
+typedef struct splay_tree_node_s *splay_tree_node;
+typedef struct splay_tree_s *splay_tree;
+typedef struct splay_tree_key_s *splay_tree_key;
+
+#include "libgomp.h"
+#include "splay-tree.h"
+
+/* Rotate the edge joining the left child N with its parent P.  PP is the
+   grandparents' pointer to P.  */
+
+static inline void
+rotate_left (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
+{
+  splay_tree_node tmp;
+  tmp = n->right;
+  n->right = p;
+  p->left = tmp;
+  *pp = n;
+}
+
+/* Rotate the edge joining the right child N with its parent P.  PP is the
+   grandparents' pointer to P.  */
+
+static inline void
+rotate_right (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
+{
+  splay_tree_node tmp;
+  tmp = n->left;
+  n->left = p;
+  p->right = tmp;
+  *pp = n;
+}
+
+/* Bottom up splay of KEY.  */
+
+static void
+splay_tree_splay (splay_tree sp, splay_tree_key key)
+{
+  if (sp->root == NULL)
+return;
+
+  do {
+int cmp1, cmp2;
+splay_tree_node n, c;
+
+n = sp->root;
+cmp1 = splay_compare (key, &n->key);
+
+/* Found.  */
+if (cmp1 == 0)
+  return;
+
+/* Left or right?  If no child, then we're done.  */
+if (cmp1 < 0)
+  c = n->left;
+else
+  c = n->right;
+if (!c)
+  return;
+
+/* Next one left or right?  If found or no child, we're done
+   after one rotation.  */
+cmp2 = splay_compare (key, &c->key);
+if (cmp2 == 0
+   || (cmp2 < 0 && !c->left)
+   || (cmp2 > 0 && !c->right))
+  {
+   if (cmp1 < 0)
+ rotate_left (&sp->root, n, c);
+   else
+ rotate_right (&sp->root, n, c);
+   return;
+  }
+
+/* Now we have the four cases of double-rotation.  */
+if (cmp1 < 0 && cmp2 < 0)
+  {
+   rotate_left (&n->left, c, c->left);
+   rotate_left (&sp->root, n, n->left);
+  }
+els

[ping][gomp4] splay tree implementation for future OpenACC runtime library usage.

2013-12-22 Thread James Norris

Hi!

Ping!

http://gcc.gnu.org/ml/gcc-patches/2013-12/msg00527.html


[ping][gomp4] splay tree implementation for future OpenACC runtime library usage.

2014-01-06 Thread James Norris

Hi!

Ping * 2

http://gcc.gnu.org/ml/gcc-patches/2013-12/msg00527.html

Thanks!




Re: [gomp4] Handle deviceptr from an outer directive

2015-07-10 Thread James Norris

Hi Thomas!

On 07/09/2015 03:51 AM, Thomas Schwinge wrote:

Hi Jim!

On Tue, 7 Jul 2015 10:19:39 -0500, James Norris  
wrote:

This patch fixes an issue where the deviceptr clause in an outer
directive was being ignored during implicit variable definition
on a nested directive.



Committed to gomp-4_0-branch.



--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c


I'm sorry, have not yet tried very hard; but I can't claim to understand
the logic here -- why is the OpenACC deviceptr clause so special?  :-|


Because no data movement should be initiated on behalf of the user.

Prior to the fix, a map (tofrom) was being inserted when the variable
in question was implied within a nested directive. This is wrong.
No movement should occur as the memory for the variable is already
present on the target. Therefore, the use of 'present' is the correct
specification.





@@ -116,6 +116,9 @@ enum gimplify_omp_var_data
/* Gang-local OpenACC variable.  */
GOVD_GANGLOCAL = (1 << 16),

+  /* OpenACC deviceptr clause.  */
+  GOVD_USE_DEVPTR = (1 << 17),
+
GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
   | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
   | GOVD_LOCAL)
@@ -6274,7 +6277,10 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq 
*pre_p,
}
  break;
}
+
  flags = GOVD_MAP | GOVD_EXPLICIT;
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR)
+   flags |= GOVD_USE_DEVPTR;
  goto do_add;

case OMP_CLAUSE_DEPEND:
@@ -6662,6 +6668,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void 
*data)
   : (flags & GOVD_FORCE_MAP
  ? GOMP_MAP_FORCE_TOFROM
  : GOMP_MAP_TOFROM));
+
if (DECL_SIZE (decl)
  && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
{
@@ -6687,7 +6694,17 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void 
*data)
  OMP_CLAUSE_CHAIN (clause) = nc;
}
else
-   OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
+   {
+ if (gimplify_omp_ctxp->outer_context)
+   {
+ struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
+ splay_tree_node on
+   = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ if (on && (on->value & GOVD_USE_DEVPTR))
+   OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_PRESENT);
+   }
+ OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
+   }
  }
if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
  {


The patch that you committed (r225518) also includes a test case
(thanks!) as follows:

 --- /dev/null
 +++ gcc/testsuite/c-c++-common/goacc/deviceptr-4.c
 @@ -0,0 +1,12 @@
 +/* { dg-additional-options "-fdump-tree-gimple" } */
 +
 +void
 +subr (int *a)
 +{
 +#pragma acc data deviceptr (a)
 +#pragma acc parallel
 +  a[0] += 1.0;
 +}
 +
 +/* { dg-final { scan-tree-dump-times "#pragma omp target 
oacc_parallel.*map\\(force_present:a \\\[len: 8\\\]\\)" 1 "gimple" } } */
 +/* { dg-final { cleanup-tree-dump "gimple" } } */

That len: 8 is obviously valid only for 64-bit configurations, so will
cause a FAIL on anything else.




Fixed and committed to gomp-4_0-branch.

Thank you, thank you,
Jim

diff --git a/gcc/testsuite/c-c++-common/goacc/deviceptr-4.c b/gcc/testsuite/c-c++-common/goacc/deviceptr-4.c
index 4f6184c..0fef364 100644
--- a/gcc/testsuite/c-c++-common/goacc/deviceptr-4.c
+++ b/gcc/testsuite/c-c++-common/goacc/deviceptr-4.c
@@ -8,5 +8,5 @@ subr (int *a)
   a[0] += 1.0;
 }
 
-/* { dg-final { scan-tree-dump-times "#pragma omp target oacc_parallel.*map\\(force_present:a \\\[len: 8\\\]\\)" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target oacc_parallel.*map\\(force_present:a" 1 "gimple" } } */
 /* { dg-final { cleanup-tree-dump "gimple" } } */


Re: [gomp4] Handle Fortran deviceptr clause.

2015-07-10 Thread James Norris

Hi Thomas,

On 07/09/2015 03:29 AM, Thomas Schwinge wrote:

Hi Jim!

On Wed, 8 Jul 2015 13:00:16 -0500, James Norris  
wrote:

This patch adds handling of the deviceptr clause when
used within a Fortran program.


Please motivate such non-obvious code changes by a test case.  At least
to me, it's not at all obvious what's going on here...


Attached are two files which allow the testing of the fix.
I wasn't able to figure out how to get the testsuite to
compile a c source file and a fortran source file. So the
following should suffice until I figure something out.


/opt/codesourcery/trunk/bin/x86_64-none-linux-gnu-gcc -fopenacc -Wall -c 
dp-1.c
/opt/codesourcery/trunk/bin/x86_64-none-linux-gnu-gfortran -fopenacc 
-Wall -c dp-2.f90
/opt/codesourcery/trunk/bin/x86_64-none-linux-gnu-gcc -fopenacc -Wall -o 
dp dp-1.o dp-2.o






Committed to gomp-4_0-branch



+   * oacc-parallel.c (GOACC_parallel GOACC_data_start): Handle Fortran
+   deviceptr clause.



--- a/libgomp/oacc-parallel.c
+++ b/libgomp/oacc-parallel.c
@@ -211,6 +211,21 @@ GOACC_parallel (int device, void (*fn) (void *),
thr = goacc_thread ();
acc_dev = thr->dev;

+  for (i = 0; i < mapnum; i++)
+{
+  unsigned short kind1 = kinds[i] & 0xff;
+  unsigned short kind2 = kinds[i+1] & 0xff;
+
+  if ((kind1 == GOMP_MAP_FORCE_DEVICEPTR && kind2 == GOMP_MAP_POINTER)
+  && (sizes[i + 1] == 0)
+  && (hostaddrs[i] == *(void **)hostaddrs[i + 1]))
+   {
+ kinds[i+1] = kinds[i];
+ sizes[i+1] = sizeof (void *);
+ hostaddrs[i] = NULL;
+   }
+}


Ugh.  That loop should be bounded by mapnum - 1 to avoid out-of-bounds
array accesses.  And, such "voodoo" code constructs do need a comment,
please


The 'Ugh' is fixed, comment added, and committed to gomp-4_0-branch.


Why does this processing need to happen at run-time, in libgomp?
Should something else be done during OMP lowering, for example?


The code in question is for the handling of the deviceptr clause
when presented via Fortran. As there is special code to handle
PSETs, which are Fortran specific, in the run-time, I felt that
there shouldn't be an issue with handling the deviceptr clause
there as well.

Thank you, thank you,
Jim
diff --git a/libgomp/oacc-parallel.c b/libgomp/oacc-parallel.c
index eeb08c4..91a5e7d 100644
--- a/libgomp/oacc-parallel.c
+++ b/libgomp/oacc-parallel.c
@@ -187,7 +187,7 @@ GOACC_parallel (int device, void (*fn) (void *),
   struct gomp_device_descr *acc_dev;
   struct target_mem_desc *tgt;
   void **devaddrs;
-  unsigned int i;
+  int i;
   struct splay_tree_key_s k;
   splay_tree_key tgt_fn_key;
   void (*tgt_fn);
@@ -211,11 +211,12 @@ GOACC_parallel (int device, void (*fn) (void *),
   thr = goacc_thread ();
   acc_dev = thr->dev;
 
-  for (i = 0; i < mapnum; i++)
+  for (i = 0; i < (signed)(mapnum - 1); i++)
 {
   unsigned short kind1 = kinds[i] & 0xff;
   unsigned short kind2 = kinds[i+1] & 0xff;
 
+  /* Handle Fortran deviceptr clause.  */
   if ((kind1 == GOMP_MAP_FORCE_DEVICEPTR && kind2 == GOMP_MAP_POINTER)
 	   && (sizes[i + 1] == 0)
 	   && (hostaddrs[i] == *(void **)hostaddrs[i + 1]))
@@ -326,11 +327,12 @@ GOACC_data_start (int device, size_t mapnum,
   struct goacc_thread *thr = goacc_thread ();
   struct gomp_device_descr *acc_dev = thr->dev;
 
-  for (i = 0; i < mapnum; i++)
+  for (i = 0; i < (signed)(mapnum - 1); i++)
 {
   unsigned short kind1 = kinds[i] & 0xff;
   unsigned short kind2 = kinds[i+1] & 0xff;
 
+  /* Handle Fortran deviceptr clause.  */
   if ((kind1 == GOMP_MAP_FORCE_DEVICEPTR && kind2 == GOMP_MAP_POINTER)
 	   && (sizes[i + 1] == 0)
 	   && (hostaddrs[i] == *(void **)hostaddrs[i + 1]))
/* { dg-do run } */

#include 
#include 
#include 
#include 

extern void subr1_ (int *);
extern void subr2_ (int *);
extern void subr3 (int *);
extern void subr4 (int *);

void
subr (int *a)
{
#pragma acc data deviceptr (a)
  {
#pragma acc parallel
{
  int i;

  for (i = 0; i < 8; i++)
a[i] = i + 1;
}
  }
}

int
main (int argc, char **argv)
{
  int  N = 8;
  int  nbytes;
  int  *a, *b;
  int  i;

  nbytes = N * sizeof (int);

  a = (int *) acc_malloc (nbytes);
  b = (int *) malloc (nbytes);

  memset (&b[0], 0, nbytes);

  subr1_ (a);

  acc_memcpy_from_device (b, a, nbytes);

  for (i = 0; i < N; i++)
{
  if (b[i] != i + 1)
abort ();
}

  memset (&b[0], 0, nbytes);

  subr2_ (a);

  acc_memcpy_from_device (b, a, nbytes);

  for (i = 0; i < N; i++)
{
  if (b[i] != i + 1)
abort ();
}

  memset (&b[0], 0, nbytes);

  subr3 (a);

  acc_memcpy_from_device (b, a, nbytes);

  for (i = 0; i < N; i++)
{
  if (b[i] != i + 1)
abort ();
}

  memset (&b[0], 0, nbytes);

  subr4 (a);

 

[gomp4] Add additional test for declare directive

2015-07-13 Thread James Norris

Hi,

The attached patch adds a test for the copyout clause with
the declare directive. The testing of this clause was
overlooked.

Committed to gomp-4_0-branch.

Jim
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c
index 584b921..8fbec4d 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c
@@ -7,6 +7,23 @@
 #define N 8
 
 void
+subr2 (int *a)
+{
+  int i;
+  int f[N];
+#pragma acc declare copyout (f)
+
+#pragma acc parallel copy (a[0:N])
+  {
+for (i = 0; i < N; i++)
+  {
+	f[i] = a[i];
+	a[i] = f[i] + f[i] + f[i];
+  }
+  }
+}
+
+void
 subr1 (int *a)
 {
   int f[N];
@@ -93,5 +110,13 @@ main (int argc, char **argv)
 	abort ();
 }
 
+  subr2 (&a[0]);
+
+  for (i = 0; i < 1; i++)
+{
+  if (a[i] != 1234 * 6)
+	abort ();
+}
+
   return 0;
 }


[gomp4] New test loop independent clause

2015-07-14 Thread James Norris

Hi,

The attached adds testing for the independent clause
with the loop directive in Fortran.

Committed to gomp-4_0-branch.

Jim
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/kernels-independent.f90 b/libgomp/testsuite/libgomp.oacc-fortran/kernels-independent.f90
new file mode 100644
index 000..9f17308
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/kernels-independent.f90
@@ -0,0 +1,43 @@
+! { dg-do run } */
+! { dg-additional-options "-cpp" }
+! { dg-additional-options "-ftree-parallelize-loops=32" }
+
+#define N (1024 * 512)
+
+subroutine foo (a,  b,  c)
+  integer, parameter :: n = N
+  integer, dimension (n) :: a
+  integer, dimension (n) :: b
+  integer, dimension (n) :: c
+  integer i, ii
+
+  do i = 1, n
+a(i) = i * 2;
+  end do
+
+  do i = 1, n
+b(i) = i * 4;
+  end do
+
+  !$acc kernels copyin (a(1:n), b(1:n)) copyout (c(1:n))
+!$acc loop independent
+do ii = 1, n
+  c(ii) = a(ii) + b(ii)
+end do
+  !$acc end kernels
+
+  do i = 1, n
+if (c(i) .ne. a(i) + b(i)) call abort
+  end do
+
+end subroutine
+
+program main
+  integer, parameter :: n = N
+  integer :: a(n)
+  integer :: b(n)
+  integer :: c(n)
+
+  call foo (a, b, c)
+
+end program main


[gomp4] Additional tests

2015-07-15 Thread James Norris

Hi,

The attached patch add tests for combined directives for, i.e.,
the parallel + loop directive and the kernel + loop directive
for C/C++/Fortran. Tests also added for the private, num_gangs,
num_workers, and vector_length clauses with the parallel
directive in Fortran.

Jim
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/combdir-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/combdir-1.c
new file mode 100644
index 000..a7def92
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/combdir-1.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+
+#include 
+
+int
+main (int argc, char **argv)
+{
+  const int N = 32;
+  float a[N], b[N];
+  int i;
+
+  for (i = 0; i < N; i++)
+{
+  a[i] = 1.0;
+  b[i] = 0.0;
+}
+
+#pragma acc parallel loop copy (a[0:N]) copy (b[0:N])
+  for (i = 0; i < N; i++)
+{
+  b[i] = 2.0;
+  a[i] = a[i] + b[i];
+}
+
+  for (i = 0; i < N; i++)
+{
+  if (a[i] != 3.0)
+	abort ();
+
+  if (b[i] != 2.0)
+	abort ();
+}
+
+#pragma acc kernels loop copy (a[0:N]) copy (b[0:N])
+  for (i = 0; i < N; i++)
+{
+  b[i] = 3.0;
+  a[i] = a[i] + b[i];
+}
+
+  for (i = 0; i < N; i++)
+{
+  if (a[i] != 6.0)
+	abort ();
+
+  if (b[i] != 3.0)
+	abort ();
+}
+
+  return 0;
+
+} 
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/combdir-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/combdir-1.f90
new file mode 100644
index 000..0cd8a67
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/combdir-1.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+
+program main
+  integer, parameter :: n = 32
+  real :: a(n), b(n);
+  integer :: i
+
+  do i = 1, n
+a(i) = 1.0
+b(i) = 0.0
+  end do
+
+  !$acc parallel loop copy (a(1:n)) copy (b(1:n))
+  do i = 1, n
+b(i) = 2.0
+a(i) = a(i) + b(i)
+  end do
+
+  do i = 1, n
+if (a(i) .ne. 3.0) call abort
+
+if (b(i) .ne. 2.0) call abort
+  end do
+
+  !$acc kernels loop copy (a(1:n)) copy (b(1:n))
+  do i = 1, n
+b(i) = 3.0;
+a(i) = a(i) + b(i)
+  end do
+
+  do i = 1, n
+if (a(i) .ne. 6.0) call abort
+
+if (b(i) .ne. 3.0) call abort
+  end do
+
+end program main
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/private-vars-par-gang-2.f90 b/libgomp/testsuite/libgomp.oacc-fortran/private-vars-par-gang-2.f90
new file mode 100644
index 000..bb0891c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/private-vars-par-gang-2.f90
@@ -0,0 +1,37 @@
+
+! { dg-additional-options "-cpp" }
+
+! Test of gang-private variables declared on the parallel directive.
+
+#if defined(ACC_DEVICE_TYPE_host) || defined(ACC_DEVICE_TYPE_host_nonshm)
+#define ACTUAL_GANGS 1
+#else
+#define ACTUAL_GANGS 32
+#endif
+
+program main
+  integer :: x = 5
+  integer, parameter :: n = ACTUAL_GANGS
+  integer :: arr(n)
+
+  do i = 1, n
+arr(i) = 3
+  end do
+
+  !$acc parallel private(x) copy(arr) num_gangs(n) num_workers(8) vector_length(32)
+!$acc loop gang(static:1)
+do i = 1, n
+  x = i * 2;
+end do
+
+   !$acc loop gang(static:1)
+do i = 1, n
+  arr(i) = arr(i) + x
+end do
+  !$acc end parallel
+
+  do i = 1, n
+if (arr(i) .ne. (3 + i * 2)) call abort
+  end do
+
+end program main


Re: [gomp4.1] Handle new form of #pragma omp declare target

2015-07-17 Thread James Norris

Jakub,

On 07/17/2015 08:05 AM, Jakub Jelinek wrote:

Hi!

...

I believe OpenACC has something similar, but no idea if it is already
implemented.


Yes, it is implemented in gomp-4_0-branch.

While the purpose for 'omp declare target' and 'acc declare' are 
similar, the data movement, via the clauses, provided with the latter 
make it very different than the former.


The data movement requires that data be moved at the entry and
exit of an 'associated region'. Associated region to mean either
a function, subroutine, entire program or Fortran module. I choose
to implement this in the front-ends.

For discussion purposes, I'll use the C front-end: c_parser_oacc_declare 
and finish_oacc_declare.


As far as the syntax, OpenMP is alot easier to deal with than
OpenACC. The handling of said is reflected in c_parser_oacc_declare.
Here also is the handling of the numerous data movement clauses.
One in particular requires special handling: create. This can
be seen toward the end of the function, There is a libgomp
component GOACC_register_static (oacc-parallel.c) that is used
in conjunction with the create clause.

The creation and deletion of the 'associated region' is done
in finish_oacc_declare. Depending upon where the directive was
found requires different handling, i.e., global variable scope
versus local variable scope. In addition, if there is data
movement from target -> host, this must be handled appropriately.



...

Ilya, Thomas, thoughts on this?



Jim answering at the behest of Thomas

If the above explanation is not sufficient please yell. It may
make more sense to carve out the code in question and document
it more thoroughly for discussion purposes. Also the implementation 
approach in the front-ends may be entirely wrong. There may be an 
approach to do it in the 'middle'. However, my lack of experience in the 
middle may have caused me to go down the wrong path.


Jim





[gomp4] Fix acc_shutdown issue.

2015-07-21 Thread James Norris

Hi,

The attached patch fixes an issue that showed up
when running the C/C++ version of asyncwait-1
within the libgomp testsuite. The issue arose
because the entries added for the address
mapping tables were not complete. Now that they
are, a special function is no longer needed to
remove the entries and gomp_unmap_vars can be
used.

Committed to gomp-4_0-branch.

Jim
diff --git a/libgomp/oacc-init.c b/libgomp/oacc-init.c
index 3a1aa28..63ac710 100644
--- a/libgomp/oacc-init.c
+++ b/libgomp/oacc-init.c
@@ -293,9 +293,12 @@ acc_shutdown_1 (acc_device_t d)
 
   if (walk->dev)
 	{
-	  gomp_mutex_lock (&walk->dev->lock);
-	  gomp_free_memmap (&walk->dev->mem_map);
-	  gomp_mutex_unlock (&walk->dev->lock);
+	  while (walk->dev->mem_map.root)
+	{
+	  struct target_mem_desc *tgt = walk->dev->mem_map.root->key.tgt;
+
+	  gomp_unmap_vars (tgt, false);
+	}
 
 	  walk->dev = NULL;
 	  walk->base_dev = NULL;
diff --git a/libgomp/target.c b/libgomp/target.c
index 1062998..227fe26 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -680,14 +680,17 @@ gomp_load_image_to_device (struct gomp_device_descr *devicep,
 }
 
   /* Insert host-target address mapping into splay tree.  */
-  struct target_mem_desc *tgt = gomp_malloc (sizeof (*tgt));
+  struct target_mem_desc *tgt =
+	  gomp_malloc (sizeof (*tgt)
+		   + sizeof (tgt->list[0])
+		   * (num_funcs + num_vars) * sizeof (*tgt->array));
   tgt->array = gomp_malloc ((num_funcs + num_vars) * sizeof (*tgt->array));
   tgt->refcount = 1;
   tgt->tgt_start = 0;
   tgt->tgt_end = 0;
   tgt->to_free = NULL;
   tgt->prev = NULL;
-  tgt->list_count = 0;
+  tgt->list_count = num_funcs + num_vars;
   tgt->device_descr = devicep;
   splay_tree_node array = tgt->array;
 
@@ -702,6 +705,8 @@ gomp_load_image_to_device (struct gomp_device_descr *devicep,
   k->async_refcount = 0;
   k->copy_from = false;
   k->dealloc_host = false;
+  tgt->list[i] = k;
+  tgt->refcount++;
   array->left = NULL;
   array->right = NULL;
   splay_tree_insert (&devicep->mem_map, array);
@@ -729,6 +734,8 @@ gomp_load_image_to_device (struct gomp_device_descr *devicep,
   k->async_refcount = 0;
   k->copy_from = false;
   k->dealloc_host = false;
+  tgt->list[i] = k;
+  tgt->refcount++;
   array->left = NULL;
   array->right = NULL;
   splay_tree_insert (&devicep->mem_map, array);
@@ -898,22 +905,6 @@ gomp_unload_device (struct gomp_device_descr *devicep)
 }
 }
 
-/* Free address mapping tables.  MM must be locked on entry, and remains locked
-   on return.  */
-
-attribute_hidden void
-gomp_free_memmap (struct splay_tree_s *mem_map)
-{
-  while (mem_map->root)
-{
-  struct target_mem_desc *tgt = mem_map->root->key.tgt;
-
-  splay_tree_remove (mem_map, &mem_map->root->key);
-  free (tgt->array);
-  free (tgt);
-}
-}
-
 /* This function de-initializes the target device, specified by DEVICEP.
DEVICEP must be locked on entry, and remains locked on return.  */
 


[gomp4] Additional tests for kernels directive.

2015-07-21 Thread James Norris

Hi,

The attached file contains additional tests for the
if, async, and wait clauses associated with the
kernels directive.

Jim

diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/asyncwait-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/asyncwait-1.c
index 22cef6d..d478ce2 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/asyncwait-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/asyncwait-1.c
@@ -460,6 +460,438 @@ main (int argc, char **argv)
 abort ();
 }
 
+for (i = 0; i < N; i++)
+{
+a[i] = 3.0;
+b[i] = 0.0;
+}
+
+#pragma acc data copy (a[0:N]) copy (b[0:N]) copyin (N)
+{
+
+#pragma acc kernels async
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+b[ii] = a[ii];
+}
+
+#pragma acc wait
+
+}
+
+for (i = 0; i < N; i++)
+{
+if (a[i] != 3.0)
+abort ();
+
+if (b[i] != 3.0)
+abort ();
+}
+
+for (i = 0; i < N; i++)
+{
+a[i] = 2.0;
+b[i] = 0.0;
+}
+
+#pragma acc data copy (a[0:N]) copy (b[0:N]) copyin (N)
+{
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+b[ii] = a[ii];
+}
+
+#pragma acc wait (1)
+
+}
+
+for (i = 0; i < N; i++)
+{
+if (a[i] != 2.0)
+abort ();
+
+if (b[i] != 2.0)
+abort ();
+}
+
+for (i = 0; i < N; i++)
+{
+a[i] = 3.0;
+b[i] = 0.0;
+c[i] = 0.0;
+d[i] = 0.0;
+}
+
+#pragma acc data copy (a[0:N]) copy (b[0:N]) copy (c[0:N]) copy (d[0:N]) copyin (N)
+{
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+b[ii] = (a[ii] * a[ii] * a[ii]) / a[ii];
+}
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+c[ii] = (a[ii] + a[ii] + a[ii] + a[ii]) / a[ii];
+}
+
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+d[ii] = ((a[ii] * a[ii] + a[ii]) / a[ii]) - a[ii];
+}
+
+#pragma acc wait (1)
+
+}
+
+for (i = 0; i < N; i++)
+{
+if (a[i] != 3.0)
+abort ();
+
+if (b[i] != 9.0)
+abort ();
+
+if (c[i] != 4.0)
+abort ();
+
+if (d[i] != 1.0)
+abort ();
+}
+
+for (i = 0; i < N; i++)
+{
+a[i] = 2.0;
+b[i] = 0.0;
+c[i] = 0.0;
+d[i] = 0.0;
+e[i] = 0.0;
+}
+
+#pragma acc data copy (a[0:N], b[0:N], c[0:N], d[0:N], e[0:N]) copyin (N)
+{
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+b[ii] = (a[ii] * a[ii] * a[ii]) / a[ii];
+}
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+c[ii] = (a[ii] + a[ii] + a[ii] + a[ii]) / a[ii];
+}
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+d[ii] = ((a[ii] * a[ii] + a[ii]) / a[ii]) - a[ii];
+}
+
+#pragma acc kernels wait (1) async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+e[ii] = a[ii] + b[ii] + c[ii] + d[ii];
+}
+
+#pragma acc wait (1)
+
+}
+
+for (i = 0; i < N; i++)
+{
+if (a[i] != 2.0)
+abort ();
+
+if (b[i] != 4.0)
+abort ();
+
+if (c[i] != 4.0)
+abort ();
+
+if (d[i] != 1.0)
+abort ();
+
+if (e[i] != 11.0)
+abort ();
+}
+
+
+r = cuStreamCreate (&stream1, CU_STREAM_NON_BLOCKING);
+if (r != CUDA_SUCCESS)
+{
+fprintf (stderr, "cuStreamCreate failed: %d\n", r);
+abort ();
+}
+
+acc_set_cuda_stream (1, stream1);
+
+for (i = 0; i < N; i++)
+{
+a[i] = 5.0;
+b[i] = 0.0;
+}
+
+#pragma acc data copy (a[0:N], b[0:N]) copyin (N)
+{
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+b[ii] = a[ii];
+}
+
+#pragma acc wait (1)
+
+}
+
+for (i = 0; i < N; i++)
+{
+if (a[i] != 5.0)
+abort ();
+
+if (b[i] != 5.0)
+abort ();
+}
+
+for (i = 0; i < N; i++)
+{
+a[i] = 7.0;
+b[i] = 0.0;
+c[i] = 0.0;
+d[i] = 0.0;
+}
+
+#pragma acc data copy (a[0:N]) copy (b[0:N]) copy (c[0:N]) copy (d[0:N]) copyin (N)
+{
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+b[ii] = (a[ii] * a[ii] * a[ii]) / a[ii];
+}
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+c[ii] = (a[ii] + a[ii] + a[ii] + a[ii]) / a[ii];
+}
+
+#pragma acc kernels async (1)
+{
+int ii;
+
+for (ii = 0; ii < N; ii++)
+d[ii] = ((a[ii] * a[ii] + a[ii]) / a[ii]) - a

[gomp4] Fix variable initialization

2015-07-24 Thread James Norris

Hi,

The attached patch fixes a couple of missing variable
initializations.

Committed to gomp-4_0-branch.

Jim

diff --git a/libgomp/target.c b/libgomp/target.c
index 16283ad..0470d3b 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -1130,7 +1130,7 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
 			 const char *plugin_name)
 {
   const char *err = NULL, *last_missing = NULL;
-  int optional_present, optional_total;
+  int optional_present = 0, optional_total = 0;
 
   /* Clear any existing error.  */
   dlerror ();


[gomp4] Additional tests for routine directive

2015-07-24 Thread James Norris

Hi,

The attached patch adds additional test for the routine
directive for C/C++/Fortran.

Committed to gomp-4_0-branch.

Jim
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-3.c
new file mode 100644
index 000..73ca528
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-3.c
@@ -0,0 +1,32 @@
+
+/* { dg-do run } */
+
+#include 
+
+#pragma acc routine nohost
+int
+foo (int n)
+{
+  if (n == 0 || n == 1)
+return 1;
+
+  return n * n;
+}
+
+int
+main()
+{
+  int a, n = 10;
+
+#pragma acc parallel copy (a, n)
+  {
+a = foo (n);
+  }
+
+  if (a != n * n)
+abort ();
+
+  return 0;
+}
+
+/* { dg-output "foo not found" { target openacc_host_selected } } */
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-4.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-4.c
new file mode 100644
index 000..c73400c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-4.c
@@ -0,0 +1,127 @@
+
+/* { dg-do run } */
+
+#include 
+
+#define M 8
+#define N 32
+
+#pragma acc routine vector
+void
+vector (int *a)
+{
+  int i;
+
+#pragma acc loop vector
+  for (i = 0; i < N; i++)
+a[i] -= a[i]; 
+}
+
+#pragma acc routine worker
+void
+worker (int *b)
+{
+  int i, j;
+
+#pragma acc loop gang
+  for (i = 0; i < N; i++)
+{
+#pragma acc loop worker
+  for (j = 0; j < M; j++)
+b[i * M + j] += b[i  * M + j]; 
+}
+}
+
+#pragma acc routine gang
+void
+gang (int *a)
+{
+  int i;
+
+#pragma acc loop gang
+  for (i = 0; i < N; i++)
+a[i] -= i; 
+}
+
+#pragma acc routine seq
+void
+seq (int *a)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+a[i] += 1;
+}
+
+#include 
+
+int
+main(int argc, char **argv)
+{
+  int i;
+  int a[N];
+  int b[M * N];
+
+  i = 0;
+
+  for (i = 0; i < N; i++)
+a[i] = 0;
+
+#pragma acc parallel copy (a[0:N])
+  {
+#pragma acc loop seq
+for (i = 0; i < N; i++)
+  seq (&a[0]);
+  }
+
+  for (i = 0; i < N; i++)
+{
+  if (a[i] != N)
+	abort ();
+}
+
+#pragma acc parallel copy (a[0:N])
+  {
+#pragma acc loop seq
+for (i = 0; i < N; i++)
+  gang (&a[0]);
+  }
+
+  for (i = 0; i < N; i++)
+{
+  if (a[i] != N + (N * (-1 * i)))
+	abort ();
+}
+
+  for (i = 0; i < N; i++)
+a[i] = i;
+
+#pragma acc parallel copy (b[0:M*N])
+  {
+worker (&b[0]);
+  }
+
+  for (i = 0; i < N; i++)
+{
+  if (a[i] != i)
+	abort ();
+}
+
+  for (i = 0; i < N; i++)
+a[i] = i;
+
+#pragma acc parallel copy (a[0:N])
+  {
+#pragma acc loop vector
+for (i = 0; i < N; i++)
+  vector (&a[0]);
+  }
+
+  for (i = 0; i < N; i++)
+{
+  if (a[i] != 0)
+	abort ();
+}
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-5.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-5.c
new file mode 100644
index 000..6d0fbe3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-5.c
@@ -0,0 +1,62 @@
+
+/* { dg-do run } */
+
+#include 
+#include 
+
+#pragma acc routine bind (foo)
+int
+subr1 (int n)
+{
+  if (n == 0 || n == 1)
+return 1;
+
+  return n * foo (n - 1);
+}
+
+#pragma acc routine bind ("bar")
+int
+subr2 (int n)
+{
+  if (n == 0 || n == 1)
+return 1;
+
+  return n * bar (n - 1);
+}
+
+int
+main()
+{
+  int *a, i, n = 10;
+
+  a = (int *)malloc (sizeof (int) * n);
+
+#pragma acc parallel copy (a[0:n]) vector_length (5)
+  {
+#pragma acc loop
+for (i = 0; i < n; i++)
+  a[i] = foo (i);
+  }
+
+  for (i = 0; i < n; i++)
+if (a[i] != subr1 (i))
+  abort ();
+
+  for (i = 0; i < n; i++)
+a[i] = 0;
+
+#pragma acc parallel copy (a[0:n]) vector_length (5)
+  {
+#pragma acc loop
+for (i = 0; i < n; i++)
+  a[i] = bar (i);
+  }
+
+  for (i = 0; i < n; i++)
+if (a[i] != subr2 (i))
+  abort ();
+
+  free (a);
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/routine-5.f90 b/libgomp/testsuite/libgomp.oacc-fortran/routine-5.f90
index aaeb994..956da8e 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/routine-5.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/routine-5.f90
@@ -15,7 +15,7 @@ program main
 contains
 
 function func (n) result (rc)
-!$acc routine gang worker vector seq nohost
+!$acc routine
 integer, intent (in) :: n
 integer :: rc
 
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/routine-6.f90 b/libgomp/testsuite/libgomp.oacc-fortran/routine-6.f90
new file mode 100644
index 000..4b7b707
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/routine-6.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+
+program main
+  integer :: a, n
+  
+  n = 10
+
+  !$acc parallel copy (a, n)
+ a = foo (n)
+  !$acc end parallel 
+
+  if (a .ne. n * n) call abort
+
+contains
+
+function foo (n) result (rc)
+  !$acc routine nohost
+
+  integer, intent (in) :: n
+  integer :: rc
+
+  rc = n * n
+
+end function
+
+end program main
+
+! { dg-output "not found" { target openacc_host_sele

Re: [gomp4] Additional tests for routine directive

2015-07-27 Thread James Norris

Thomas,

The attached patch adds XFAILs so as to quiet the errors
until such time as the development is complete.

Committed to gomp-4_0-branch.

Thank you, thank you
Jim

On 07/27/2015 08:36 AM, Thomas Schwinge wrote:

Hi!

On Fri, 24 Jul 2015 15:43:36 -0500, James Norris  
wrote:

The attached patch adds additional test for the routine
directive for C/C++/Fortran.

Committed to gomp-4_0-branch.


Thanks, but I see a number of FAILs, including the following:

 FAIL: libgomp.oacc-c/../libgomp.oacc-c-c++-common/routine-5.c 
-DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for excess errors)
 UNRESOLVED: libgomp.oacc-c/../libgomp.oacc-c-c++-common/routine-5.c 
-DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 compilation failed to produce 
executable

 PASS: libgomp.oacc-c/../libgomp.oacc-c-c++-common/routine-3.c 
-DACC_DEVICE_TYPE_host=1 -DACC_MEM_SHARED=1 (test for excess errors)
 PASS: libgomp.oacc-c/../libgomp.oacc-c-c++-common/routine-3.c 
-DACC_DEVICE_TYPE_host=1 -DACC_MEM_SHARED=1 execution test
 FAIL: libgomp.oacc-c/../libgomp.oacc-c-c++-common/routine-3.c 
-DACC_DEVICE_TYPE_host=1 -DACC_MEM_SHARED=1 output pattern test, is , should 
match foo not found

 FAIL: libgomp.oacc-fortran/routine-8.f90 -DACC_DEVICE_TYPE_nvidia=1 
-DACC_MEM_SHARED=0  -O0  (test for excess errors)
 UNRESOLVED: libgomp.oacc-fortran/routine-8.f90 -DACC_DEVICE_TYPE_nvidia=1 
-DACC_MEM_SHARED=0  -O0  compilation failed to produce executable
 [same for other torture testing flags]

 PASS: libgomp.oacc-fortran/routine-6.f90 -DACC_DEVICE_TYPE_host=1 
-DACC_MEM_SHARED=1  -O0  (test for excess errors)
 PASS: libgomp.oacc-fortran/routine-6.f90 -DACC_DEVICE_TYPE_host=1 
-DACC_MEM_SHARED=1  -O0  execution test
 FAIL: libgomp.oacc-fortran/routine-6.f90 -DACC_DEVICE_TYPE_host=1 
-DACC_MEM_SHARED=1  -O0  output pattern test, is , should match not found
 [same for other torture testing flags]

(I have not reviewed your test case changes.)


Grüße,
  Thomas



diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-3.c
index 73ca528..a191758 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-3.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-3.c
@@ -1,5 +1,6 @@
 
 /* { dg-do run } */
+/* { dg-xfail-if "foo not found" { openacc_host_selected } } */
 
 #include 
 
@@ -28,5 +29,3 @@ main()
 
   return 0;
 }
-
-/* { dg-output "foo not found" { target openacc_host_selected } } */
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-5.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-5.c
index 6d0fbe3..4e34f78 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-5.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-5.c
@@ -1,7 +1,9 @@
 
 /* { dg-do run } */
+/* { dg-warning "TODO" "implicit" { xfail *-*-* } 17 } */
+/* { dg-warning "TODO" "implicit" { xfail *-*-* } 27 } */
+/* { dg-xfail-if "unresolved symbol" { *-*-* } } */
 
-#include 
 #include 
 
 #pragma acc routine bind (foo)
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/routine-6.f90 b/libgomp/testsuite/libgomp.oacc-fortran/routine-6.f90
index 4b7b707..9ba6da8 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/routine-6.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/routine-6.f90
@@ -1,4 +1,5 @@
 ! { dg-do run }
+! { dg-xfail-if "not found" { openacc_host_selected } }
 
 program main
   integer :: a, n
@@ -25,4 +26,3 @@ end function
 
 end program main
 
-! { dg-output "not found" { target openacc_host_selected } }
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/routine-8.f90 b/libgomp/testsuite/libgomp.oacc-fortran/routine-8.f90
index 2060740..5c58b43 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/routine-8.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/routine-8.f90
@@ -1,5 +1,6 @@
 
 ! { dg-do run } 
+! { dg-error "Invalid" "TODO" { xfail *-*-* } 51 }
 
 program main
   integer, parameter :: n = 10


[gomp4] finish_oacc_declare fix

2015-07-31 Thread James Norris

Hi,

The attached patch adds a constraint to prevent finish_oacc_declare
from being passed thru multiple times when dealing with a template and
and instance of a template.

Also cleaned up the interface to finish_oacc_declare.

Committed to gomp-4_0-branch.

Jim
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f6cc32d..1d80ef2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14229,17 +14229,22 @@ find_oacc_return (tree *tp, int *, void *)
 }
 
 static void
-finish_oacc_declare (tree fndecl, tree decls)
+finish_oacc_declare (tree fndecl)
 {
-  tree t, stmt, list, c, ret_clauses, clauses;
+  tree t, stmt, list, c, ret_clauses, clauses, decls;
   location_t loc;
   tree_stmt_iterator i;
 
+  if (DECL_USE_TEMPLATE (fndecl))
+return;
+
   list = cur_stmt_list;
 
+  decls = lookup_attribute ("oacc declare", DECL_ATTRIBUTES (fndecl));
+
   if (lookup_attribute ("oacc function", DECL_ATTRIBUTES (fndecl)))
 {
-  if (lookup_attribute ("oacc declare", DECL_ATTRIBUTES (fndecl)))
+  if (decls)
 	{
 	  location_t loc = DECL_SOURCE_LOCATION (fndecl);
 	  error_at (loc, "%<#pragma acc declare%> not allowed in %qE", fndecl);
@@ -14463,8 +14468,7 @@ finish_function (int flags)
   gcc_assert (!defer_mark_used_calls);
   defer_mark_used_calls = true;
 
-  tree decls = lookup_attribute ("oacc declare", DECL_ATTRIBUTES (fndecl));
-  finish_oacc_declare (fndecl, decls);
+  finish_oacc_declare (fndecl);
 
   record_key_method_defined (fndecl);
 


[PATCH] Remove restriction for remote testing

2015-09-28 Thread James Norris

Hi,

The attached patch fixes a problem when doing remote testing.
Specifically, testing of the atomic tests found in gcc/atomic.
The code in atomic_init precludes the setting of the variable
'link_flags' when doing remote testing. The conditional test
can be safely removed as get_multilibs will return "", and
atomic_link_flags will return the necessary '-latomic' that
will allow the atomic tests to successfully link.

OK for trunk?

Thanks,
Jim

Index: gcc/testsuite/lib/atomic-dg.exp
===
--- gcc/testsuite/lib/atomic-dg.exp	(revision 227981)
+++ gcc/testsuite/lib/atomic-dg.exp	(working copy)
@@ -63,12 +63,10 @@ proc atomic_init { args } {
 global atomic_saved_TEST_ALWAYS_FLAGS
 
 set link_flags ""
-if ![is_remote host] {
-	if [info exists TOOL_OPTIONS] {
-	set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
-	} else {
-	set link_flags "[atomic_link_flags [get_multilibs]]"
-	}
+if [info exists TOOL_OPTIONS] {
+	set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
+} else {
+	set link_flags "[atomic_link_flags [get_multilibs]]"
 }
 
 if [info exists TEST_ALWAYS_FLAGS] {


[gomp4] Remove erroneous test and unreachable situation.

2015-09-28 Thread James Norris

Hi,

The attached patch removes an erroneous attribute test and
an unreachable situation. Both showed up when dealing with
the routine directive and the name option where the name
was the identical to the name of the function / subroutine.

Committed after regtest on x86_64 and powerpc64le.

Thanks!
Jim
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 55eed48..44cbec1 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -1755,14 +1755,6 @@ gfc_match_oacc_routine (void)
 	  return MATCH_ERROR;
 	}
 
-  if (!sym->attr.external && !sym->attr.function && !sym->attr.subroutine)
-	{
-	  gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, invalid"
-		 " function name %qs", sym->name);
-	  gfc_current_locus = old_loc;
-	  return MATCH_ERROR;
-	}
-
   if (gfc_match_char (')') != MATCH_YES)
 	{
 	  gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
@@ -1798,8 +1790,6 @@ gfc_match_oacc_routine (void)
   gfc_current_ns->proc_name->attr.oacc_function
 	= gfc_oacc_routine_dims (c) + 1;
 }
-  else
-gcc_unreachable ();
 
   if (n)
 n->clauses = c;


Re: [gomp4] Remove erroneous test and unreachable situation.

2015-09-29 Thread James Norris

Hi,

The original patch still missed some situations (thanks Cesar!)
and the attached patch addresses those. It also adds some new
tests.

Jim

Index: libgomp/ChangeLog.gomp
===
--- libgomp/ChangeLog.gomp	(revision 228245)
+++ libgomp/ChangeLog.gomp	(working copy)
@@ -1,3 +1,7 @@
+2015-09-29  James Norris  
+
+	* testsuite/libgomp.oacc-fortran/routine-9.f90: New test.
+
 2015-09-29  Nathan Sidwell  
 
 	* oacc-init.c (acc_on_device): Compile with optimization.
Index: libgomp/testsuite/libgomp.oacc-fortran/routine-9.f90
===
--- libgomp/testsuite/libgomp.oacc-fortran/routine-9.f90	(revision 0)
+++ libgomp/testsuite/libgomp.oacc-fortran/routine-9.f90	(revision 0)
@@ -0,0 +1,31 @@
+! { dg-do run }
+! { dg-options "-fno-inline" }
+
+program main
+  implicit none
+  integer, parameter :: n = 10
+  integer :: a(n), i
+  integer, external :: fact
+  !$acc routine (fact)
+  !$acc parallel
+  !$acc loop
+  do i = 1, n
+ a(i) = fact (i)
+  end do
+  !$acc end parallel
+  do i = 1, n
+ if (a(i) .ne. fact(i)) call abort
+  end do
+end program main
+
+recursive function fact (x) result (res)
+  implicit none
+  !$acc routine (fact)
+  integer, intent(in) :: x
+  integer :: res
+  if (x < 1) then
+ res = 1
+  else
+ res = x * fact(x - 1)
+  end if
+end function fact
Index: gcc/testsuite/ChangeLog.gomp
===
--- gcc/testsuite/ChangeLog.gomp	(revision 228245)
+++ gcc/testsuite/ChangeLog.gomp	(working copy)
@@ -1,3 +1,7 @@
+2015-08-29  James Norris  
+
+	* gfortran.dg/goacc/routine-6.f90: New test.
+
 2015-09-29  Tom de Vries  
 
 	* c-c++-common/goacc/kernels-acc-loop-smaller-equal.c: New test.
Index: gcc/testsuite/gfortran.dg/goacc/routine-6.f90
===
--- gcc/testsuite/gfortran.dg/goacc/routine-6.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/goacc/routine-6.f90	(revision 0)
@@ -0,0 +1,79 @@
+
+module m
+  integer m1int
+contains
+  subroutine subr5 (x) 
+  implicit none
+  !$acc routine (subr5)
+  !$acc routine (m1int) ! { dg-error "invalid function name" }
+  integer, intent(inout) :: x
+  if (x < 1) then
+ x = 1
+  else
+ x = x * x - 1
+  end if
+  end subroutine subr5
+end module m
+
+program main
+  implicit none
+  interface
+function subr6 (x) 
+!$acc routine (subr6) ! { dg-error "without list is allowed in interface" }
+integer, intent (in) :: x
+integer :: subr6
+end function subr6
+  end interface
+  integer, parameter :: n = 10
+  integer :: a(n), i
+  !$acc routine (subr1) ! { dg-error "invalid function name" }
+  external :: subr2
+  !$acc routine (subr2)
+  !$acc parallel
+  !$acc loop
+  do i = 1, n
+ call subr1 (i)
+ call subr2 (i)
+  end do
+  !$acc end parallel
+end program main
+
+subroutine subr1 (x) 
+  !$acc routine
+  integer, intent(inout) :: x
+  if (x < 1) then
+ x = 1
+  else
+ x = x * x - 1
+  end if
+end subroutine subr1
+
+subroutine subr2 (x) 
+  !$acc routine (subr1) ! { dg-error "invalid function name" }
+  integer, intent(inout) :: x
+  if (x < 1) then
+ x = 1
+  else
+ x = x * x - 1
+  end if
+end subroutine subr2
+
+subroutine subr3 (x) 
+  !$acc routine (subr3)
+  integer, intent(inout) :: x
+  if (x < 1) then
+ x = 1
+  else
+ call subr4 (x)
+  end if
+end subroutine subr3
+
+subroutine subr4 (x) 
+  !$acc routine (subr4)
+  integer, intent(inout) :: x
+  if (x < 1) then
+ x = 1
+  else
+ x = x * x - 1
+  end if
+end subroutine subr4
Index: gcc/fortran/openmp.c
===
--- gcc/fortran/openmp.c	(revision 228245)
+++ gcc/fortran/openmp.c	(working copy)
@@ -1745,11 +1745,35 @@ gfc_match_oacc_routine (void)
 
   if (m == MATCH_YES)
 {
-  /* Scan for a function name/string.  */
-  m = gfc_match_symbol (&sym, 0);
+  char buffer[GFC_MAX_SYMBOL_LEN + 1];
+  gfc_symtree *st;
 
-  if (m == MATCH_NO)
+  m = gfc_match_name (buffer);
+  if (m == MATCH_YES)
 	{
+	  st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
+	  if (st)
+	{
+	  sym = st->n.sym;
+	  if (strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
+	sym = NULL;
+	}
+
+	  if (st == NULL
+	  || (sym
+		  && !sym->attr.external
+		  && !sym->attr.function
+		  && !sym->attr.subroutine))
+	{
+	  gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, "
+			 "invalid function name %s",
+			 (sym) ? sym->name : buffer);
+	  gfc_current_locus = old_loc;
+	  return MATCH_ERROR;
+	}
+	}
+  else
+{
 	  gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
 	  gfc_current_locus = old_loc;
 	  re

Re: [PATCH] Remove restriction for remote testing

2015-10-05 Thread James Norris

Ping.

On 09/28/2015 07:35 AM, James Norris wrote:

Hi,

The attached patch fixes a problem when doing remote testing.
Specifically, testing of the atomic tests found in gcc/atomic.
The code in atomic_init precludes the setting of the variable
'link_flags' when doing remote testing. The conditional test
can be safely removed as get_multilibs will return "", and
atomic_link_flags will return the necessary '-latomic' that
will allow the atomic tests to successfully link.

OK for trunk?

Thanks,
Jim




[gomp4] Add -foffload-abi support for PPC

2015-10-06 Thread James Norris

Hi,

The attached patch adds the -foffload-abi option support for PPC.
Only support for the 64-bit ABI has been added.

Committed after regtesting with x86_64 and powerpc64le.

Thanks!
Jim


diff --git a/gcc/ChangeLog.gomp b/gcc/ChangeLog.gomp
index a65e652..40326cf 100644
--- a/gcc/ChangeLog.gomp
+++ b/gcc/ChangeLog.gomp
@@ -1,3 +1,11 @@
+2015-10-06 James Norris  
+
+	* common.opt (OFFLOAD_ABI_PPC64): New enum.
+	* config/nvptx/mkoffload.c (compile_native): Handle new enum.
+	(main): Handle new option.
+	* config/rs6000/rs6000.c (rs6000_offload_options): New hook.
+	* gcc/coretypes.h (OFFLOAD_ABI_PPC64): New enum.
+
 2015-10-05  Thomas Schwinge  
 
 	* config/nvptx/mkoffload.c (main): Don't explicitly pass "-lgomp"
diff --git a/gcc/common.opt b/gcc/common.opt
index 290b6b3..c37 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1730,6 +1730,9 @@ Enum(offload_abi) String(ilp32) Value(OFFLOAD_ABI_ILP32)
 EnumValue
 Enum(offload_abi) String(lp64) Value(OFFLOAD_ABI_LP64)
 
+EnumValue
+Enum(offload_abi) String(ppc64) Value(OFFLOAD_ABI_PPC64)
+
 fomit-frame-pointer
 Common Report Var(flag_omit_frame_pointer) Optimization
 When possible do not generate stack frames
diff --git a/gcc/config/nvptx/mkoffload.c b/gcc/config/nvptx/mkoffload.c
index e398b44..743df4b 100644
--- a/gcc/config/nvptx/mkoffload.c
+++ b/gcc/config/nvptx/mkoffload.c
@@ -367,6 +367,8 @@ compile_native (const char *infile, const char *outfile, const char *compiler)
 case OFFLOAD_ABI_ILP32:
   obstack_ptr_grow (&argv_obstack, "-m32");
   break;
+case OFFLOAD_ABI_PPC64:
+  break;
 default:
   gcc_unreachable ();
 }
@@ -458,6 +460,8 @@ main (int argc, char **argv)
 	offload_abi = OFFLOAD_ABI_LP64;
 	  else if (strcmp (argv[i] + strlen (STR), "ilp32") == 0)
 	offload_abi = OFFLOAD_ABI_ILP32;
+	  else if (strcmp (argv[i] + strlen (STR), "ppc64") == 0)
+	offload_abi = OFFLOAD_ABI_PPC64;
 	  else
 	fatal_error (input_location,
 			 "unrecognizable argument of option " STR);
@@ -485,6 +489,8 @@ main (int argc, char **argv)
 case OFFLOAD_ABI_ILP32:
   obstack_ptr_grow (&argv_obstack, "-m32");
   break;
+case OFFLOAD_ABI_PPC64:
+  break;
 default:
   gcc_unreachable ();
 }
@@ -518,7 +524,8 @@ main (int argc, char **argv)
 
   /* PR libgomp/65099: Currently, we only support offloading in 64-bit
  configurations, and only for OpenACC offloading.  */
-  if (offload_abi == OFFLOAD_ABI_LP64 && fopenacc)
+  if ((offload_abi == OFFLOAD_ABI_LP64
+  || (offload_abi == OFFLOAD_ABI_PPC64)) && fopenacc)
 {
   ptx_name = make_temp_file (".mkoffload");
   obstack_ptr_grow (&argv_obstack, "-o");
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 023f622..146b45b 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1688,6 +1688,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
+
+#undef TARGET_OFFLOAD_OPTIONS
+#define TARGET_OFFLOAD_OPTIONS rs6000_offload_options
 
 
 /* Processor table.  */
@@ -9532,6 +9535,13 @@ rs6000_abi_word_mode (void)
   return TARGET_32BIT ? SImode : DImode;
 }
 
+/* Implement the TARGET_OFFLOAD_OPTIONS hook.  */
+static char *
+rs6000_offload_options (void)
+{
+  return xstrdup ("-foffload-abi=ppc64");
+}
+
 /* On rs6000, function arguments are promoted, as are function return
values.  */
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 7b3df54..3bb0528 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -170,7 +170,8 @@ enum tls_model {
 enum offload_abi {
   OFFLOAD_ABI_UNSET,
   OFFLOAD_ABI_LP64,
-  OFFLOAD_ABI_ILP32
+  OFFLOAD_ABI_ILP32,
+  OFFLOAD_ABI_PPC64
 };
 
 /* Types of unwind/exception handling info that can be generated.  */


Re: [PATCH] Remove restriction for remote testing

2015-10-07 Thread James Norris

Hi,

On 10/05/2015 01:56 PM, Mike Stump wrote:


I don't think this is appropriate.  The design is for remote host testing to 
have the compete shape of an installed compiler as I recall.  When it does, it 
then is indistinguishable from an installed compiler, and when it is installed, 
then no -L nor -B flag is necessary for it to work.  The link_flags only exists 
to add these flags, not the -l flag.  That is the thing that is wrong.  Remove 
that, and add

  "libs=-latomic”

to someplace that will inject that option.  I stole that line from objc.exp:

   append options "libs=-lobjc”

or otherwise unconditionally put -latomic on the link line (some place that 
isn’t protected by is_remote host).



I've revised the patch based on the review comments from yourself,
Bernd, and Joseph (thank you for your comments).

I've moved the addition of the '-latomic' from atomic_link_flags to
atomic_init. Now atomic_link_flags just finds the library location
and sets the appropriate variables. Additional changes were added
to use the '-latomic' addition only for atomic testing.

OK?

Thanks!
Jim



diff --git a/gcc/testsuite/lib/atomic-dg.exp b/gcc/testsuite/lib/atomic-dg.exp
index fe24127..0640f3c 100644
--- a/gcc/testsuite/lib/atomic-dg.exp
+++ b/gcc/testsuite/lib/atomic-dg.exp
@@ -48,7 +48,6 @@ proc atomic_link_flags { paths } {
 
 set_ld_library_path_env_vars
 
-append flags " -latomic "
 return "$flags"
 }
 
@@ -61,6 +60,7 @@ proc atomic_init { args } {
 global ALWAYS_CXXFLAGS
 global TOOL_OPTIONS
 global atomic_saved_TEST_ALWAYS_FLAGS
+global atomic_saved_ALWAYS_CXXFLAGS
 
 set link_flags ""
 if ![is_remote host] {
@@ -71,10 +71,13 @@ proc atomic_init { args } {
 	}
 }
 
+append link_flags " -latomic "
+
 if [info exists TEST_ALWAYS_FLAGS] {
 	set atomic_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
 }
 if [info exists ALWAYS_CXXFLAGS] {
+	set atomic_saved_ALWAYS_CXXFLAGS $ALWAYS_CXXFLAGS
 	set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
 } else {
 	if [info exists TEST_ALWAYS_FLAGS] {
@@ -95,11 +98,16 @@ proc atomic_init { args } {
 proc atomic_finish { args } {
 global TEST_ALWAYS_FLAGS
 global atomic_saved_TEST_ALWAYS_FLAGS
+global atomic_saved_ALWAYS_CXXFLAGS
 
-if [info exists atomic_saved_TEST_ALWAYS_FLAGS] {
-	set TEST_ALWAYS_FLAGS $atomic_saved_TEST_ALWAYS_FLAGS
+if [info exists atomic_saved_ALWAYS_CXXFLAGS] {
+	set ALWAYS_CXXFLAGS $atomic_saved_ALWAYS_CXXFLAGS
 } else {
-	unset TEST_ALWAYS_FLAGS
+	if [info exists atomic_saved_TEST_ALWAYS_FLAGS] {
+	  set TEST_ALWAYS_FLAGS $atomic_saved_TEST_ALWAYS_FLAGS
+	} else {
+	  unset TEST_ALWAYS_FLAGS
+	}
 }
 clear_effective_target_cache
 }


[gomp4] Remove restriction for remote testing

2015-10-07 Thread James Norris

Hi,

The attached patch is a backport from trunk.

commit 3dabf8ddc9b4f0da3277991d20525d062e5b5138
Author: jnorris 
Date:   Wed Oct 7 17:09:46 2015 +

* testsuite/lib/atomic-dg.exp (atomic_link_flags): Move flag setting
to atomic_init. (atomic_init): Restrict flags usage.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@228575 
138bc75d-0d04-0410-961f-82ee72b054a4



Thanks!
Jim
diff --git a/gcc/testsuite/lib/atomic-dg.exp b/gcc/testsuite/lib/atomic-dg.exp
index fe24127..0640f3c 100644
--- a/gcc/testsuite/lib/atomic-dg.exp
+++ b/gcc/testsuite/lib/atomic-dg.exp
@@ -48,7 +48,6 @@ proc atomic_link_flags { paths } {
 
 set_ld_library_path_env_vars
 
-append flags " -latomic "
 return "$flags"
 }
 
@@ -61,6 +60,7 @@ proc atomic_init { args } {
 global ALWAYS_CXXFLAGS
 global TOOL_OPTIONS
 global atomic_saved_TEST_ALWAYS_FLAGS
+global atomic_saved_ALWAYS_CXXFLAGS
 
 set link_flags ""
 if ![is_remote host] {
@@ -71,10 +71,13 @@ proc atomic_init { args } {
 	}
 }
 
+append link_flags " -latomic "
+
 if [info exists TEST_ALWAYS_FLAGS] {
 	set atomic_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
 }
 if [info exists ALWAYS_CXXFLAGS] {
+	set atomic_saved_ALWAYS_CXXFLAGS $ALWAYS_CXXFLAGS
 	set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
 } else {
 	if [info exists TEST_ALWAYS_FLAGS] {
@@ -95,11 +98,16 @@ proc atomic_init { args } {
 proc atomic_finish { args } {
 global TEST_ALWAYS_FLAGS
 global atomic_saved_TEST_ALWAYS_FLAGS
+global atomic_saved_ALWAYS_CXXFLAGS
 
-if [info exists atomic_saved_TEST_ALWAYS_FLAGS] {
-	set TEST_ALWAYS_FLAGS $atomic_saved_TEST_ALWAYS_FLAGS
+if [info exists atomic_saved_ALWAYS_CXXFLAGS] {
+	set ALWAYS_CXXFLAGS $atomic_saved_ALWAYS_CXXFLAGS
 } else {
-	unset TEST_ALWAYS_FLAGS
+	if [info exists atomic_saved_TEST_ALWAYS_FLAGS] {
+	  set TEST_ALWAYS_FLAGS $atomic_saved_TEST_ALWAYS_FLAGS
+	} else {
+	  unset TEST_ALWAYS_FLAGS
+	}
 }
 clear_effective_target_cache
 }


Re: Add -foffload-abi support for PPC

2015-10-08 Thread James Norris

Hi!

On 10/07/2015 08:51 AM, David Edelsohn wrote:

On Wed, Oct 7, 2015 at 4:02 AM, Thomas Schwinge  wrote:


 From a quick look at the *_TYPE_SIZE definitions in
gcc/config/rs6000/rs6000.h as well as
, "3-1
Fundamental Types", and
,
I gather we're dealing with regular ilp32/lp64 here.  Then, I assume the
right thing is to use the 64BIT flag from gcc/config/rs6000/sysv4.opt
(which, per gcc/config.gcc I suppose is used for the relevant
powerpc64le-linux-gnu configuration).  (David?)


TARGET_64BIT is the appropriate macro to test.



I'm not sure where to place the TARGET_OFFLOAD_OPTIONS #define and the
function definition in rs6000.c.  (David?)


As mentioned earlier, only PPC64LE is supported.

I'm not sure if it really matters if this is defined in ELF-specific
portion of the file or a general place, although it never will be
called by other configurations.

Thanks, David



I've revised the patch from the review comments (thank you) and
is attached.

Regtested on x86_64 and powerpcle64.

OK for trunk?

Thanks!
Jim

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e095f03..e775e9a 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1690,6 +1690,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
+
+#undef TARGET_OFFLOAD_OPTIONS
+#define TARGET_OFFLOAD_OPTIONS rs6000_offload_options
 
 
 /* Processor table.  */
@@ -9530,6 +9533,13 @@ rs6000_abi_word_mode (void)
   return TARGET_32BIT ? SImode : DImode;
 }
 
+/* Implement the TARGET_OFFLOAD_OPTIONS hook.  */
+static char *
+rs6000_offload_options (void)
+{
+  return xstrdup ("-foffload-abi=lp64");
+}
+
 /* On rs6000, function arguments are promoted, as are function return
values.  */
 


Re: Add -foffload-abi support for PPC

2015-10-09 Thread James Norris

David,

On 10/08/2015 11:53 AM, David Edelsohn wrote:

On Thu, Oct 8, 2015 at 12:19 PM, James Norris  wrote:


I've revised the patch from the review comments (thank you) and
is attached.

Regtested on x86_64 and powerpcle64.

OK for trunk?


What is the goal? Do you want this to return the correct value or only
the value for the supported 64 bit PPC64LE system?

Thanks, David




The goal is to support both 32-bit and 64-bit. There was some
confusion on my part, my apologies.

Attached is the corrected patch.

Thanks!
Jim
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e095f03..8aac4f7 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1690,6 +1690,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
+
+#undef TARGET_OFFLOAD_OPTIONS
+#define TARGET_OFFLOAD_OPTIONS rs6000_offload_options
 
 
 /* Processor table.  */
@@ -9530,6 +9533,16 @@ rs6000_abi_word_mode (void)
   return TARGET_32BIT ? SImode : DImode;
 }
 
+/* Implement the TARGET_OFFLOAD_OPTIONS hook.  */
+static char *
+rs6000_offload_options (void)
+{
+  if (TARGET_64BIT)
+return xstrdup ("-foffload-abi=lp64");
+  else
+return xstrdup ("-foffload-abi=ilp32");
+}
+
 /* On rs6000, function arguments are promoted, as are function return
values.  */
 


[gomp4] Revert patch

2015-10-09 Thread James Norris

Hi,

The attached patch reverts a previously attached patch.

2015-10-06 James Norris  

* common.opt (OFFLOAD_ABI_PPC64): New enum.
* config/nvptx/mkoffload.c (compile_native): Handle new enum.
(main): Handle new option.
* config/rs6000/rs6000.c (rs6000_offload_options): New hook.
* gcc/coretypes.h (OFFLOAD_ABI_PPC64): New enum.

Thanks!
Jim
diff --git a/gcc/common.opt b/gcc/common.opt
index c37..290b6b3 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1730,9 +1730,6 @@ Enum(offload_abi) String(ilp32) Value(OFFLOAD_ABI_ILP32)
 EnumValue
 Enum(offload_abi) String(lp64) Value(OFFLOAD_ABI_LP64)
 
-EnumValue
-Enum(offload_abi) String(ppc64) Value(OFFLOAD_ABI_PPC64)
-
 fomit-frame-pointer
 Common Report Var(flag_omit_frame_pointer) Optimization
 When possible do not generate stack frames
diff --git a/gcc/config/nvptx/mkoffload.c b/gcc/config/nvptx/mkoffload.c
index 743df4b..e398b44 100644
--- a/gcc/config/nvptx/mkoffload.c
+++ b/gcc/config/nvptx/mkoffload.c
@@ -367,8 +367,6 @@ compile_native (const char *infile, const char *outfile, const char *compiler)
 case OFFLOAD_ABI_ILP32:
   obstack_ptr_grow (&argv_obstack, "-m32");
   break;
-case OFFLOAD_ABI_PPC64:
-  break;
 default:
   gcc_unreachable ();
 }
@@ -460,8 +458,6 @@ main (int argc, char **argv)
 	offload_abi = OFFLOAD_ABI_LP64;
 	  else if (strcmp (argv[i] + strlen (STR), "ilp32") == 0)
 	offload_abi = OFFLOAD_ABI_ILP32;
-	  else if (strcmp (argv[i] + strlen (STR), "ppc64") == 0)
-	offload_abi = OFFLOAD_ABI_PPC64;
 	  else
 	fatal_error (input_location,
 			 "unrecognizable argument of option " STR);
@@ -489,8 +485,6 @@ main (int argc, char **argv)
 case OFFLOAD_ABI_ILP32:
   obstack_ptr_grow (&argv_obstack, "-m32");
   break;
-case OFFLOAD_ABI_PPC64:
-  break;
 default:
   gcc_unreachable ();
 }
@@ -524,8 +518,7 @@ main (int argc, char **argv)
 
   /* PR libgomp/65099: Currently, we only support offloading in 64-bit
  configurations, and only for OpenACC offloading.  */
-  if ((offload_abi == OFFLOAD_ABI_LP64
-  || (offload_abi == OFFLOAD_ABI_PPC64)) && fopenacc)
+  if (offload_abi == OFFLOAD_ABI_LP64 && fopenacc)
 {
   ptx_name = make_temp_file (".mkoffload");
   obstack_ptr_grow (&argv_obstack, "-o");
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 146b45b..023f622 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1688,9 +1688,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
-
-#undef TARGET_OFFLOAD_OPTIONS
-#define TARGET_OFFLOAD_OPTIONS rs6000_offload_options
 
 
 /* Processor table.  */
@@ -9535,13 +9532,6 @@ rs6000_abi_word_mode (void)
   return TARGET_32BIT ? SImode : DImode;
 }
 
-/* Implement the TARGET_OFFLOAD_OPTIONS hook.  */
-static char *
-rs6000_offload_options (void)
-{
-  return xstrdup ("-foffload-abi=ppc64");
-}
-
 /* On rs6000, function arguments are promoted, as are function return
values.  */
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 3bb0528..7b3df54 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -170,8 +170,7 @@ enum tls_model {
 enum offload_abi {
   OFFLOAD_ABI_UNSET,
   OFFLOAD_ABI_LP64,
-  OFFLOAD_ABI_ILP32,
-  OFFLOAD_ABI_PPC64
+  OFFLOAD_ABI_ILP32
 };
 
 /* Types of unwind/exception handling info that can be generated.  */


[gomp4] Backport from trunk

2015-10-09 Thread James Norris

Hi,

The attached patch was backported from trunk.

commit 13d478244d380d1564eefc204201b7f681218ce3
Author: jnorris 
Date:   Fri Oct 9 12:35:58 2015 +

* config/rs6000/rs6000.c (rs6000_offload_options): New.
(TARGET_OFFLOAD_OPTIONS): New.


Jim
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 023f622..2dce709 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1688,6 +1688,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
+
+#undef TARGET_OFFLOAD_OPTIONS
+#define TARGET_OFFLOAD_OPTIONS rs6000_offload_options
 
 
 /* Processor table.  */
@@ -9532,6 +9535,16 @@ rs6000_abi_word_mode (void)
   return TARGET_32BIT ? SImode : DImode;
 }
 
+/* Implement the TARGET_OFFLOAD_OPTIONS hook.  */
+static char *
+rs6000_offload_options (void)
+{
+  if (TARGET_64BIT)
+return xstrdup ("-foffload-abi=lp64");
+  else
+return xstrdup ("-foffload-abi=ilp32");
+}
+
 /* On rs6000, function arguments are promoted, as are function return
values.  */
 


[PATCH] Fix libgomp OpenACC test

2015-10-12 Thread James Norris

Hi,

The attached patch fixes a test where the for-loop
iterator was not initialized.

Committed to trunk as obvious.

Jim
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c
index cc915a9..8a51ee3 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c
@@ -12,7 +12,7 @@ unsigned int n = N;
 int
 main (void)
 {
-  for (unsigned int i; i < n; ++i)
+  for (unsigned int i = 0; i < n; ++i)
 {
   a[i] = i % 3;
   b[i] = i % 5;
@@ -25,7 +25,7 @@ main (void)
   c[i] = a[i] + b[i];
   }
 
-  for (unsigned int i; i < n; ++i)
+  for (unsigned int i = 0; i < n; ++i)
 if (c[i] != (i % 3) + (i % 5))
   abort ();
 


[gomp4] Backport from trunk

2015-10-12 Thread James Norris

Hi,

The attached patch was backported from trunk.

commit 140722d9d2d574574c982f4616a80bb0ef766276
Author: jnorris 
Date:   Mon Oct 12 20:22:30 2015 +

* testsuite/libgomp.oacc-c-c++-common/vector-loop.c: Fix loop
initializer.


Jim
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c
index cc915a9..8a51ee3 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/vector-loop.c
@@ -12,7 +12,7 @@ unsigned int n = N;
 int
 main (void)
 {
-  for (unsigned int i; i < n; ++i)
+  for (unsigned int i = 0; i < n; ++i)
 {
   a[i] = i % 3;
   b[i] = i % 5;
@@ -25,7 +25,7 @@ main (void)
   c[i] = a[i] + b[i];
   }
 
-  for (unsigned int i; i < n; ++i)
+  for (unsigned int i = 0; i < n; ++i)
 if (c[i] != (i % 3) + (i % 5))
   abort ();
 


[OpenACC 0/7] host_data construct

2015-10-22 Thread James Norris

Hi!

This patch series adds the handling of OpenACC host_data construct
in the C and C++ front-ends, gimple, and supporting functions in
libgomp. Commentary on the changes is included in each individual
patch.

All of the code is in the gomp-4_0-branch.

Regtested on x86_64-linux.

Thanks!
Jim


[OpenACC 1/7] host_data construct (C/C++ common)

2015-10-22 Thread James Norris


gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c

- Add host_data pragma definition to list in oacc_pragma[].

gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h

- Add host_data pragma enum to list in pragma_kind[].
- Add use_device clause enum to list in pragma_omp_clause[].


diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 834a916..b748e2f 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1214,6 +1214,7 @@ static const struct omp_pragma_def oacc_pragmas[] = {
   { "data", PRAGMA_OACC_DATA },
   { "enter", PRAGMA_OACC_ENTER_DATA },
   { "exit", PRAGMA_OACC_EXIT_DATA },
+  { "host_data", PRAGMA_OACC_HOST_DATA },
   { "kernels", PRAGMA_OACC_KERNELS },
   { "loop", PRAGMA_OACC_LOOP },
   { "parallel", PRAGMA_OACC_PARALLEL },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index cec920f..23a72a3 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -31,6 +31,7 @@ enum pragma_kind {
   PRAGMA_OACC_DATA,
   PRAGMA_OACC_ENTER_DATA,
   PRAGMA_OACC_EXIT_DATA,
+  PRAGMA_OACC_HOST_DATA,
   PRAGMA_OACC_KERNELS,
   PRAGMA_OACC_LOOP,
   PRAGMA_OACC_PARALLEL,
@@ -161,6 +162,7 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE,
   PRAGMA_OACC_CLAUSE_SELF,
   PRAGMA_OACC_CLAUSE_SEQ,
+  PRAGMA_OACC_CLAUSE_USE_DEVICE,
   PRAGMA_OACC_CLAUSE_VECTOR,
   PRAGMA_OACC_CLAUSE_VECTOR_LENGTH,
   PRAGMA_OACC_CLAUSE_WAIT,


[OpenACC 3/7] host_data construct (C front-end)

2015-10-22 Thread James Norris


gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h

- Add definition for c_finish_oacc_host_data().

gcc/cp/parser.c b/gcc/cp/parser.c

- Add handling of use_device clause in cp_parser_omp_clause_name().
- Add handling of use_device clause in cp_parser_oacc_all_clauses().
- Add new macro OACC_HOST_DATA_CLAUSE_MASK.
- Add new function cp_parser_oacc_host_data() to handle host_data.
- Add handling of host_data pragma to cp_parser_omp_construct().
- Add handling of host_data pragma to cp_parser_pragma().

gcc/cp/semantics.c b/gcc/cp/semantics.c

- Add handling of use_device clause to finish_omp_clauses().
- Add new function finish_oacc_host_data().


diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 16db41f..76ece42 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6318,6 +6318,7 @@ extern void finish_omp_threadprivate		(tree);
 extern tree begin_omp_structured_block		(void);
 extern tree finish_omp_structured_block		(tree);
 extern tree finish_oacc_data			(tree, tree);
+extern tree finish_oacc_host_data		(tree, tree);
 extern tree finish_oacc_kernels			(tree, tree);
 extern tree finish_oacc_parallel		(tree, tree);
 extern tree begin_omp_parallel			(void);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f07a5e4..714e69c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -29235,6 +29235,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
 	result = PRAGMA_OMP_CLAUSE_UNTIED;
 	  else if (!strcmp ("use_device_ptr", p))
 	result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
+	  else if (!strcmp ("use_device", p))
+	result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
 	  break;
 	case 'v':
 	  if (!strcmp ("vector_length", p))
@@ -31381,6 +31383,11 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
 	  c_name = "self";
 	  break;
+	case PRAGMA_OACC_CLAUSE_USE_DEVICE:
+	  clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_USE_DEVICE,
+	clauses);
+	  c_name = "use_device";
+	  break;
 	case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
 	  clauses = cp_parser_oacc_clause_vector_length (parser, clauses);
 	  c_name = "vector_length";
@@ -34221,6 +34228,30 @@ cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok)
   return stmt;
 }
 
+#define OACC_HOST_DATA_CLAUSE_MASK	\
+  ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) )
+
+/* OpenACC 2.0:
+  # pragma acc host_data  new-line
+  structured-block  */
+
+static tree
+cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree stmt, clauses, block;
+  unsigned int save;
+
+  clauses = cp_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
+	"#pragma acc host_data", pragma_tok);
+
+  block = begin_omp_parallel ();
+  save = cp_parser_begin_omp_structured_block (parser);
+  cp_parser_statement (parser, NULL_TREE, false, NULL);
+  cp_parser_end_omp_structured_block (parser, save);
+  stmt = finish_oacc_host_data (clauses, block);
+  return stmt;
+}
+
 /* OpenACC 2.0:
# pragma acc enter data oacc-enter-data-clause[optseq] new-line
 
@@ -35288,6 +35319,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
 case PRAGMA_OACC_EXIT_DATA:
   stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, false);
   break;
+case PRAGMA_OACC_HOST_DATA:
+  stmt = cp_parser_oacc_host_data (parser, pragma_tok);
+  break;
 case PRAGMA_OACC_KERNELS:
   stmt = cp_parser_oacc_kernels (parser, pragma_tok);
   break;
@@ -35856,6 +35890,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 case PRAGMA_OACC_DATA:
 case PRAGMA_OACC_ENTER_DATA:
 case PRAGMA_OACC_EXIT_DATA:
+case PRAGMA_OACC_HOST_DATA:
 case PRAGMA_OACC_KERNELS:
 case PRAGMA_OACC_PARALLEL:
 case PRAGMA_OACC_LOOP:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c0a8b32..25482e7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6689,6 +6689,7 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 	case OMP_CLAUSE_SIMD:
 	case OMP_CLAUSE_DEFAULTMAP:
 	case OMP_CLAUSE__CILK_FOR_COUNT_:
+	case OMP_CLAUSE_USE_DEVICE:
 	  break;
 
 	case OMP_CLAUSE_INBRANCH:
@@ -7119,6 +7120,24 @@ finish_oacc_data (tree clauses, tree block)
   return add_stmt (stmt);
 }
 
+/* Generate OACC_HOST_DATA, with CLAUSES and BLOCK as its compound
+   statement.  */
+
+tree
+finish_oacc_host_data (tree clauses, tree block)
+{
+  tree stmt;
+
+  block = finish_omp_structured_block (block);
+
+  stmt = make_node (OACC_HOST_DATA);
+  TREE_TYPE (stmt) = void_type_node;
+  OACC_HOST_DATA_CLAUSES (stmt) = clauses;
+  OACC_HOST_DATA_BODY (stmt) = block;
+
+  return add_stmt (stmt);
+}
+
 /* Generate OACC_KERNELS, with CLAUSES and BLOCK as its compound
statement.  LOC is the location of the OACC_KERNELS.  */
 


[OpenACC 2/7] host_data construct (C FE)

2015-10-22 Thread James Norris


gcc/c/c-parser.c b/gcc/c/c-parser.c

- Add handling of use_device clause in c_parser_omp_clause_name().
- Add new function c_parser_oacc_clause_use_device() to handle
  use_device clause with host_data.
- Add handling of use_device clause in c_parser_oacc_all_clauses().
- Add new macro OACC_HOST_DATA_CLAUSE_MASK.
- Add new function c_parser_oacc_host_data() to handle host_data.
- Add handling of host_data pragma to c_parser_omp_construct().

gcc/c/c-tree.h b/gcc/c/c-tree.h

- Add definition for c_finish_oacc_host_data().

gcc/c/c-typeck.c b/gcc/c/c-typeck.c

- Add new function c_finish_oacc_host_data().


diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 704ebc6..ead98b9 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -10116,6 +10116,8 @@ c_parser_omp_clause_name (c_parser *parser)
 	result = PRAGMA_OMP_CLAUSE_UNTIED;
 	  else if (!strcmp ("use_device_ptr", p))
 	result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
+	  else if (!strcmp ("use_device", p))
+	result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
 	  break;
 	case 'v':
 	  if (!strcmp ("vector", p))
@@ -11219,6 +11221,15 @@ c_parser_oacc_clause_async (c_parser *parser, tree list)
   return list;
 }
 
+/* OpenACC 2.0:
+   use_device ( variable-list ) */
+
+static tree
+c_parser_oacc_clause_use_device (c_parser *parser, tree list)
+{
+  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE, list);
+}
+
 /* OpenACC:
wait ( int-expr-list ) */
 
@@ -12474,6 +12485,10 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
 	  clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
 	  c_name = "self";
 	  break;
+	case PRAGMA_OACC_CLAUSE_USE_DEVICE:
+	  clauses = c_parser_oacc_clause_use_device (parser, clauses);
+	  c_name = "use_device";
+	  break;
 	case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
 	  clauses = c_parser_omp_clause_vector_length (parser, clauses);
 	  c_name = "vector_length";
@@ -13003,6 +13018,29 @@ c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
 
 
 /* OpenACC 2.0:
+   # pragma acc host_data oacc-data-clause[optseq] new-line
+ structured-block
+*/
+
+#define OACC_HOST_DATA_CLAUSE_MASK	\
+	( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) )
+
+static tree
+c_parser_oacc_host_data (location_t loc, c_parser *parser)
+{
+  tree stmt, clauses, block;
+
+  clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
+   "#pragma acc host_data");
+
+  block = c_begin_omp_parallel ();
+  add_stmt (c_parser_omp_structured_block (parser));
+  stmt = c_finish_oacc_host_data (loc, clauses, block);
+  return stmt;
+}
+
+
+/* OpenACC 2.0:
 
# pragma acc loop oacc-loop-clause[optseq] new-line
  structured-block
@@ -16075,6 +16113,9 @@ c_parser_omp_construct (c_parser *parser)
 case PRAGMA_OACC_DATA:
   stmt = c_parser_oacc_data (loc, parser);
   break;
+case PRAGMA_OACC_HOST_DATA:
+  stmt = c_parser_oacc_host_data (loc, parser);
+  break;
 case PRAGMA_OACC_KERNELS:
   strcpy (p_name, "#pragma acc");
   stmt = c_parser_oacc_kernels (loc, parser, p_name);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index bee03d3..a9c5975 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -643,6 +643,7 @@ extern tree c_expr_to_decl (tree, bool *, bool *);
 extern tree c_finish_oacc_parallel (location_t, tree, tree);
 extern tree c_finish_oacc_kernels (location_t, tree, tree);
 extern tree c_finish_oacc_data (location_t, tree, tree);
+extern tree c_finish_oacc_host_data (location_t, tree, tree);
 extern tree c_begin_omp_parallel (void);
 extern tree c_finish_omp_parallel (location_t, tree, tree);
 extern tree c_begin_omp_task (void);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index bc43602..a5e2a4a 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -11510,6 +11510,25 @@ c_finish_oacc_data (location_t loc, tree clauses, tree block)
   return add_stmt (stmt);
 }
 
+/* Generate OACC_HOST_DATA, with CLAUSES and BLOCK as its compound
+   statement.  LOC is the location of the OACC_HOST_DATA.  */
+
+tree
+c_finish_oacc_host_data (location_t loc, tree clauses, tree block)
+{
+  tree stmt;
+
+  block = c_end_compound_stmt (loc, block, true);
+
+  stmt = make_node (OACC_HOST_DATA);
+  TREE_TYPE (stmt) = void_type_node;
+  OACC_HOST_DATA_CLAUSES (stmt) = clauses;
+  OACC_HOST_DATA_BODY (stmt) = block;
+  SET_EXPR_LOCATION (stmt, loc);
+
+  return add_stmt (stmt);
+}
+
 /* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
 
 tree
@@ -12942,6 +12961,7 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
 	case OMP_CLAUSE_GANG:
 	case OMP_CLAUSE_WORKER:
 	case OMP_CLAUSE_VECTOR:
+	case OMP_CLAUSE_USE_DEVICE:
 	  pc = &OMP_CLAUSE_CHAIN (c);
 	  continue;
 


[OpenACC 4/7] host_data construct (middle end)

2015-10-22 Thread James Norris


gcc/gimplify.c b/gcc/gimplify.c

- Add new enum for use_device clause handling to gimplify_omp_var_data.
- Add new enum for host_data regions to omp_region_type.
- Move handling of use_device clause in gimplify_scan_omp_clauses().
- Add new functions gimplify_host_data() and gimplify_host_data_1().
- Add handling of host_data to gimplify_expr().

gcc/omp-builtins.def b/gcc/omp-builtins.def

- Add builtin for GOACC_deviceptr().


diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index ab9e540..0c32219 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -93,6 +93,8 @@ enum gimplify_omp_var_data
 
   GOVD_MAP_0LEN_ARRAY = 32768,
 
+  GOVD_USE_DEVICE = 65536,
+
   GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
 			   | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
 			   | GOVD_LOCAL)
@@ -116,7 +118,9 @@ enum omp_region_type
   ORT_COMBINED_TARGET = 33,
   /* Dummy OpenMP region, used to disable expansion of
  DECL_VALUE_EXPRs in taskloop pre body.  */
-  ORT_NONE = 64
+  ORT_NONE = 64,
+  /* An OpenACC host-data region.  */
+  ORT_HOST_DATA = 128
 };
 
 /* Gimplify hashtable helper.  */
@@ -6338,6 +6342,10 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 		decl = TREE_OPERAND (decl, 0);
 	}
 	  goto do_add_decl;
+	case OMP_CLAUSE_USE_DEVICE:
+	  flags = GOVD_USE_DEVICE | GOVD_EXPLICIT;
+	  check_non_private = "use_device";
+	  goto do_add;
 	case OMP_CLAUSE_LINEAR:
 	  if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
 			 is_gimple_val, fb_rvalue) == GS_ERROR)
@@ -7005,7 +7013,6 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 	  break;
 
 	case OMP_CLAUSE_DEVICE_RESIDENT:
-	case OMP_CLAUSE_USE_DEVICE:
 	case OMP_CLAUSE_INDEPENDENT:
 	  remove = true;
 	  break;
@@ -7529,6 +7536,127 @@ gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
   *expr_p = NULL_TREE;
 }
 
+static tree
+gimplify_oacc_host_data_1 (tree *tp, int *walk_subtrees,
+			   void *data ATTRIBUTE_UNUSED)
+{
+  splay_tree_node n = NULL;
+  location_t loc = EXPR_LOCATION (*tp);
+
+  switch (TREE_CODE (*tp))
+{
+case ADDR_EXPR:
+  {
+	tree decl = TREE_OPERAND (*tp, 0);
+
+	switch (TREE_CODE (decl))
+	  {
+	  case ARRAY_REF:
+	  case ARRAY_RANGE_REF:
+	  case COMPONENT_REF:
+	  case VIEW_CONVERT_EXPR:
+	  case REALPART_EXPR:
+	  case IMAGPART_EXPR:
+	if (TREE_CODE (TREE_OPERAND (decl, 0)) == VAR_DECL)
+	  n = splay_tree_lookup (gimplify_omp_ctxp->variables,
+ (splay_tree_key) TREE_OPERAND (decl, 0));
+	break;
+
+	  case VAR_DECL:
+	n = splay_tree_lookup (gimplify_omp_ctxp->variables,
+   (splay_tree_key) decl);
+	break;
+
+	  default:
+	;
+	  }
+
+	if (n != NULL && (n->value & GOVD_USE_DEVICE) != 0)
+	  {
+	tree t = builtin_decl_explicit (BUILT_IN_GOACC_DEVICEPTR);
+	*tp = build_call_expr_loc (loc, t, 1, *tp);
+	  }
+
+	*walk_subtrees = 0;
+  }
+  break;
+
+case VAR_DECL:
+  {
+	tree decl = *tp;
+
+	n = splay_tree_lookup (gimplify_omp_ctxp->variables,
+			   (splay_tree_key) decl);
+
+	if (n != NULL && (n->value & GOVD_USE_DEVICE) != 0)
+	  {
+	if (!POINTER_TYPE_P (TREE_TYPE (decl)))
+	  return decl;
+
+	tree t = builtin_decl_explicit (BUILT_IN_GOACC_DEVICEPTR);
+	*tp = build_call_expr_loc (loc, t, 1, *tp);
+	*walk_subtrees = 0;
+	  }
+  }
+  break;
+
+case OACC_PARALLEL:
+case OACC_KERNELS:
+case OACC_LOOP:
+  *walk_subtrees = 0;
+  break;
+
+default:
+  ;
+}
+
+  return NULL_TREE;
+}
+
+static enum gimplify_status
+gimplify_oacc_host_data (tree *expr_p, gimple_seq *pre_p)
+{
+  tree expr = *expr_p, orig_body;
+  gimple_seq body = NULL;
+
+  gimplify_scan_omp_clauses (&OACC_HOST_DATA_CLAUSES (expr), pre_p,
+			 ORT_HOST_DATA, OACC_HOST_DATA);
+
+  orig_body = OACC_HOST_DATA_BODY (expr);
+
+  /* Perform a pre-pass over the host_data region's body, inserting calls to
+ GOACC_deviceptr where appropriate.  */
+
+  tree ret = walk_tree_without_duplicates (&orig_body,
+	   &gimplify_oacc_host_data_1, 0);
+
+  if (ret)
+{
+  error_at (EXPR_LOCATION (expr),
+		"undefined use of variable %qE in host_data region",
+		DECL_NAME (ret));
+  gimplify_adjust_omp_clauses (pre_p, &OACC_HOST_DATA_CLAUSES (expr),
+   OACC_HOST_DATA);
+  return GS_ERROR;
+}
+
+  push_gimplify_context ();
+
+  gimple *g = gimplify_and_return_first (orig_body, &body);
+
+  if (gimple_code (g) == GIMPLE_BIND)
+pop_gimplify_context (g);
+  else
+pop_gimplify_context (NULL);
+
+  gimplify_adjust_omp_clauses (pre_p, &OACC_HOST_DATA_CLAUSES (expr),
+			   OACC_HOST_DATA);
+
+  gimplify_seq_add_stmt (pre_p, g);
+
+  return GS_ALL_DONE;
+}
+
 /* Gimplify the contents of an OMP_PARALLEL statement.  This involves
gimplification of the body, as well as scanning the body for used
variables.  We need to do this scan now, because variable-sized
@@ -9595,6 +9723,9 @@ gimplify_

[OpenACC 5/7] host_data construct (gcc tests)

2015-10-22 Thread James Norris


gcc/testsuite/c-c++-common/goacc/host_data-1.c 
b/gcc/testsuite/c-c++-common/goacc/host_data-1.c
gcc/testsuite/c-c++-common/goacc/host_data-2.c 
b/gcc/testsuite/c-c++-common/goacc/host_data-2.c
gcc/testsuite/c-c++-common/goacc/host_data-3.c 
b/gcc/testsuite/c-c++-common/goacc/host_data-3.c
gcc/testsuite/c-c++-common/goacc/host_data-4.c 
b/gcc/testsuite/c-c++-common/goacc/host_data-4.c


- New compile time tests for host_data.


diff --git a/gcc/testsuite/c-c++-common/goacc/host_data-1.c b/gcc/testsuite/c-c++-common/goacc/host_data-1.c
new file mode 100644
index 000..521c854
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/host_data-1.c
@@ -0,0 +1,13 @@
+/* Test valid use of host_data directive.  */
+/* { dg-do compile } */
+
+int v0;
+int v1[3][3];
+
+void
+f (void)
+{
+  int v2 = 3;
+#pragma acc host_data use_device(v2, v0, v1)
+  ;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/host_data-2.c b/gcc/testsuite/c-c++-common/goacc/host_data-2.c
new file mode 100644
index 000..e5213a0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/host_data-2.c
@@ -0,0 +1,13 @@
+/* Test invalid use of host_data directive.  */
+/* { dg-do compile } */
+
+int v0;
+#pragma acc host_data use_device(v0) /* { dg-error "expected" } */
+
+void
+f (void)
+{
+  int v2 = 3;
+#pragma acc host_data copy(v2) /* { dg-error "not valid for" } */
+  ;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/host_data-3.c b/gcc/testsuite/c-c++-common/goacc/host_data-3.c
new file mode 100644
index 000..f9621c9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/host_data-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+
+int main (int argc, char* argv[])
+{
+  int x = 5, y;
+
+  #pragma acc enter data copyin (x)
+  /* It's not clear what attempts to use non-pointer variables "directly"
+ (rather than merely taking their address) should do in host_data regions. 
+ We choose to make it an error.  */
+  #pragma acc host_data use_device (x) /* TODO { dg-error "" } */
+  {
+y = x;
+  }
+  #pragma acc exit data delete (x)
+
+  return y - 5;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/host_data-4.c b/gcc/testsuite/c-c++-common/goacc/host_data-4.c
new file mode 100644
index 000..3dac5f3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/host_data-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+int main (int argc, char* argv[])
+{
+  int x[100];
+
+  #pragma acc enter data copyin (x)
+  /* Specifying an array index is not valid for host_data/use_device.  */
+  #pragma acc host_data use_device (x[4]) /* { dg-error "expected '\\\)' before '\\\[' token" } */
+;
+  #pragma acc exit data delete (x)
+
+  return 0;
+}


[OpenACC 6/7] host_data construct

2015-10-22 Thread James Norris


libgomp/libgomp.map b/libgomp/libgomp.map

- Add new symbol GOACC_deviceptr.

libgomp/oacc-mem.c b/libgomp/oacc-mem.c

- Add new function GOACC_deviceptr() to handle pointer lookup
  for host_data regions.


diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index 2153661..2a43a8c 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -378,6 +378,7 @@ GOACC_2.0 {
 	GOACC_wait;
 	GOACC_get_thread_num;
 	GOACC_get_num_threads;
+	GOACC_deviceptr;
 };
 
 GOACC_2.0.1 {
diff --git a/libgomp/oacc-mem.c b/libgomp/oacc-mem.c
index af067d6..497ab92 100644
--- a/libgomp/oacc-mem.c
+++ b/libgomp/oacc-mem.c
@@ -204,6 +204,38 @@ acc_deviceptr (void *h)
   return d;
 }
 
+/* This function is used as a helper in generated code to implement pointer
+   lookup in host_data regions.  Unlike acc_deviceptr, it returns its argument
+   unchanged on a shared-memory system (e.g. the host).  */
+
+void *
+GOACC_deviceptr (void *h)
+{
+  splay_tree_key n;
+  void *d;
+  void *offset;
+
+  goacc_lazy_initialize ();
+
+  struct goacc_thread *thr = goacc_thread ();
+
+  if ((thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) == 0)
+{
+  n = lookup_host (thr->dev, h, 1);
+
+  if (!n)
+	return NULL;
+
+  offset = h - n->host_start;
+
+  d = n->tgt->tgt_start + n->tgt_offset + offset;
+
+  return d;
+}
+  else
+return h;
+}
+
 /* Return the host pointer that corresponds to device data D.  Or NULL
if no mapping.  */
 


[OpenACC 7/7] host_data construct (runtime tests)

2015-10-22 Thread James Norris


libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-1.c 
b/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-1.c
libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-2.c 
b/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-2.c


- New runtime tests for host_data.

diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-1.c
new file mode 100644
index 000..15ccb27
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-1.c
@@ -0,0 +1,125 @@
+/* { dg-do run { target openacc_nvidia_accel_selected } } */
+/* { dg-additional-options "-lcuda -lcublas -lcudart" } */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void
+saxpy_host (int n, float a, float *x, float *y)
+{
+  int i;
+
+  for (i = 0; i < n; i++)
+y[i] = y[i] + a * x[i];
+}
+
+#pragma acc routine
+void
+saxpy_target (int n, float a, float *x, float *y)
+{
+  int i;
+
+  for (i = 0; i < n; i++)
+y[i] = y[i] + a * x[i];
+}
+
+int
+main(int argc, char **argv)
+{
+  const int N = 8;
+  int i;
+  float *x_ref, *y_ref;
+  float *x, *y;
+  cublasHandle_t h;
+  float a = 2.0;
+
+  x_ref = (float*) malloc (N * sizeof(float));
+  y_ref = (float*) malloc (N * sizeof(float));
+
+  x = (float*) malloc (N * sizeof(float));
+  y = (float*) malloc (N * sizeof(float));
+
+#pragma acc data copyin (x[0:N]) copy (y[0:N])
+  {
+float *xp, *yp;
+#pragma acc host_data use_device (x, y)
+{
+#pragma acc parallel pcopy (xp, yp) present (x, y)
+  {
+xp = x;
+	yp = y;
+  }
+}
+
+if (xp != acc_deviceptr (x) || yp != acc_deviceptr (y))
+	abort ();
+  }
+
+  for (i = 0; i < N; i++)
+{
+  x[i] = x_ref[i] = 4.0 + i;
+  y[i] = y_ref[i] = 3.0;
+}
+
+  saxpy_host (N, a, x_ref, y_ref);
+
+  cublasCreate (&h);
+
+#pragma acc data copyin (x[0:N]) copy (y[0:N])
+  {
+#pragma acc host_data use_device (x, y)
+{
+  cublasSaxpy (h, N, &a, x, 1, y, 1);
+}
+  }
+
+  for (i = 0; i < N; i++)
+{
+  if (y[i] != y_ref[i])
+abort ();
+}
+
+#pragma acc data create (x[0:N]) copyout (y[0:N])
+  {
+#pragma acc kernels
+for (i = 0; i < N; i++)
+  y[i] = 3.0;
+
+#pragma acc host_data use_device (x, y)
+{
+  cublasSaxpy (h, N, &a, x, 1, y, 1);
+}
+  }
+
+  cublasDestroy (h);
+
+  for (i = 0; i < N; i++)
+{
+  if (y[i] != y_ref[i])
+abort ();
+}
+
+  for (i = 0; i < N; i++)
+y[i] = 3.0;
+
+#pragma acc data copyin (x[0:N]) copyin (a, N) copy (y[0:N])
+  {
+#pragma acc host_data use_device (x, y)
+{
+#pragma acc parallel present (x[0:N]) pcopy (y[0:N]) present (a, N)
+  saxpy_target (N, a, x, y);
+}
+  }
+
+  for (i = 0; i < N; i++)
+{
+  if (y[i] != y_ref[i])
+abort ();
+}
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-2.c
new file mode 100644
index 000..511ec64
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/host_data-2.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+
+#include 
+
+struct by_lightning {
+  int a;
+  int b;
+  int c;
+};
+
+int main (int argc, char* argv[])
+{
+  int x;
+  void *q = NULL, *r = NULL, *p = NULL, *s = NULL, *t = NULL;
+  long u;
+  struct by_lightning on_the_head = {1, 2, 3};
+  int arr[10], *f = NULL;
+  _Complex float cf;
+  #pragma acc enter data copyin (x, arr, on_the_head, cf)
+  #pragma acc host_data use_device (x, arr, on_the_head, cf)
+  {
+q = &x;
+{
+  f = &arr[5];
+  r = f;
+  s = &__real__ cf;
+  t = &on_the_head.c;
+  u = (long) &__imag__ cf;
+  #pragma acc parallel copyout(p) present (x, arr, on_the_head, cf)
+  {
+/* This will not (and must not) call GOACC_deviceptr, but '&x' will be
+	   the address on the device (if appropriate) regardless.  */
+	p = &x;
+  }
+}
+  }
+  #pragma acc exit data delete (x)
+
+#if ACC_MEM_SHARED
+  if (q != &x || f != &arr[5] || r != f || s != &(__real__ cf)
+  || t != &on_the_head.c || u != (long) &(__imag__ cf) || p != &x)
+abort ();
+#else
+  if (q == &x || f == &arr[5] || r != f || s == &(__real__ cf)
+  || t == &on_the_head.c || u == (long) &(__imag__ cf) || p == &x)
+abort ();
+#endif
+
+  return 0;
+}


Re: [OpenACC 0/7] host_data construct

2015-10-22 Thread James Norris

To all,

On 10/22/2015 03:36 PM, Joseph Myers wrote:

I think this patch is small enough, and the pieces insufficiently
self-contained, that splitting it up rather than posting as one patch just
makes it harder to understand.  My strong preference is that the same
patch that introduces a feature should also add the testcases for that
feature, for example - they should not be split out (that's not even a
split by reviewer, testcases are critical to reviewing functionality
patches).



Okay, I'll rewrite the posting and submit it with a single patch
as a response to the initial posting. I'll also re-write the comments
as they have been pointed out by Nathan as being too terse.

My apologies for wasting people's time.
Jim





Re: [Bulk] [OpenACC 0/7] host_data construct

2015-10-23 Thread James Norris

Hi,

This a re-posting of the original note incorporating the suggestions
from Joseph and Nathan (thank you).

This patch adds the processing of OpenACC host_data construct in C
and C++. (Note: Support in Fortran is already in trunk.) The patch
also adds the required support in the middle-end and libgomp.

Background
The host data construct is used to make an address of device
data available on the host.

The following illustrates use of the host data construct in
conjunction with arrays which are already device-resident
and an accelerator-only function.

int main(int argc, char **argv)
{
  float *x, *y;
  const int n = 1024;
  int i;

  x = (float*) malloc (n * sizeof(float));
  y = (float*) malloc (n * sizeof(float));

  /* Copy the arrays out to the device. */
  #pragma acc data create(x[0:n]) copyout(y[0:n])
  {
#pragma acc parallel
{
  for (i = 0; i < n; i++)
{
  x[i] = 1.0f;
  y[i] = 0.0f;
}
}

/*
 * The arrays are already on the device, so
 * pass the device addresses to saxpy. NOTE:
 * saxpy has been previously defined as an
 * accelerator function.
 */
#pragma acc host_data use_device(x, y)
{
  saxpy(n, 2.0, x, 1, y, 1);
}
  }

  fprintf(stdout, "y[0] = %f\n", y[0]);
  return 0;
}


C and C++ front-ends

Definitions for use by C and C++ were added to identify the
host_data construct pragma and its' only valid clause: use_device.

New functionality was added to do the parsing of the host_data
pragma and validate the sole clause valid clause: use_device.
As the host_data construct has associated with it a structured
block, new functionality was added to build the compound
statement to represent the block.

Middle-end

A gimple definition: GOVD_USE_DEVICE, has been added to indicate
the use of the use_device clause. This flag is asserted as part
of installing mappings into a omp context. The flag is subsequently
reacted to during the gimplying of the host_data region's body.
When this flag is encountered, an GOACC_deviceptr builtin call
is inserted at the appropriate place.

libgomp

A new function has been added to handle pointer lookup for host
data regions. As the comment in the code describes, this function
will return the appropriate address based on whether it is called
for the host or the target. This function is used in response to
usage of the use_device clause.

Tests

New compile and runtime tests have been added.

All of the code is in the gomp-4_0-branch.

Regtested on x86_64-linux.

Thanks!
Jim


2015-10-23  Julian Brown  
    James Norris  

gcc/c-family/   
* c-pragma.c (oacc_pragmas): Add host_data pragma definition.
* c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_HOST_DATA.
(enum pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_USE_DEVICE.

gcc/c/
* c-parser.c (c_parser_omp_clause_name): Add handling of use_device
clause.
(c_parser_oacc_clause_use_device): New function.
(c_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_USE_DEVICE.
(OACC_HOST_DATA_CLAUSE_MASK): New definition.
(c_parser_oacc_host_data): New function.
(c_parser_omp_construct): Handle PRAGMA_OACC_HOST_DATA.
* c-tree.h: Add definition for c_finish_oacc_host_data.
* c-typeck.c (c_finish_oacc_host_data): New function.

gcc/cp/
* cp-tree.h (finish_oacc_host_data): New function.
* parser.c (cp_parser_omp_clause_name): Add handling of use_device
clause.
(cp_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_USE_DEVICE.
(OACC_HOST_DATA_CLAUSE_MASK): New definition.
(cp_parser_oacc_host_data): New function.
(cp_parser_omp_construct): Handle PRAGMA_OACC_HOST_DATA.
(cp_parser_pragma): Handle PRAGMA_OACC_HOST_DATA.
* semantics.c (finish_omp_clauses): Hnadle OMP_CLAUSE_USE_DEVICE.
(finish_oacc_host_data): New function.

gcc/
* gimplify.c (enum gimplify_omp_var_data): Add GOVD_USE_DEVICE.
(enum omp_region_type): Add ORT_HOST_DATA.
(gimplify_scan_omp_clauses): Adjust handling of OMP_CLAUSE_USE_DEVICE.
(gimpify_host_data, gimplify_host

[OpenACC] declare directive

2015-10-27 Thread James Norris
 of registered variables / arrays. Another function
has been added to deallocate that device. These functions are
called at the appropriate places in the runtime.

Finally, a function has been added to handle the declare builtin
which is emitted by the compiler.

Testing

New compile and runtime tests have been added. (NOTE: The numbering
for the runtime tests has a gap in it. These tests use both the
declare and routine directive. The support for the routine directive
has yet to be added to trunk, so these tests will appear once
the support has been committed.)
2015-10-27  James Norris  

gcc/
* builtin-types.def (BT_FN_VOID_PTR_INT_UINT): New type.
* c-family/c-common.c (c_common_attribute_table): New oacc_declare.
* c-family/c-pragma.c (oacc_pragmas): Add entry for declare directive. 
* c-family/c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_DECLARE.
(enum pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT.
* c/c-parser.c (c_parser_pragma): Handle PRAGMA_OACC_DECLARE.
(c_parser_omp_clause_name): Handle 'device_resident' clause.
(c_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(c_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OACC_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(c_parser_oacc_declare): New function.
* cp/parser.c (cp_parser_omp_clause_name): Handle 'device_resident'
clause.
(cp_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(cp_parser_oacc_declare): New function.
(cp_paser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(cp_parser_pragma): Handle PRAGMA_OACC_DECLARE.
* cp/pt.c (tsubst_expr): Handle OACC_DECLARE.
* fortran/types.def (BT_FN_VOID_PTR_INT_UINT): New type.
* gimple.h (enum gf_mask): Add GF_OMP_TARGET_KIND_OACC_DECLARE.
(is_gomple_omp_oacc): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* gimplify.c (struct gimplify_omp_ctx): New field.
(new_omp_context): Initialize new field.
(omp_default_clause): Handle device resident variable.
(gimplify_oacc_declare): New function.
(device_resident_p): New function.
(gimplify_expr): Handle OACC_DECLARE.
(gimplify_body): Handle updating of declare'd variables.
* omp-builtins.def (BUILT_IN_GOACC_STATIC, BUILT_IN_GOACC_DECLARE):
New builtins.
* omp-low.c (expand_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE and BUILTIN_GOACC_DECLARE.
(lower_omp_target): Handle GF_OMP_TARGET_KIND_OACC_DECLARE,
GOMP_MAP_DEVICE_RESIDENT and GOMP_MAP_LINK.
(make_gimple_omp_edges): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* testsuite/c-c++-common/goacc/declare-1.c: New test.
* testsuite/c-c++-common/goacc/declare-2.c: Likewise.
* tree.def (OACC_DECLARE): Update operands.
* tree.h (OACC_DECLARE_RETURN_CLAUSES): New definition.
* varpool.c (make_offloadable_1, make_offloadable): New functions.
(get_create): Refactor offload functionality.

include/
* gomp-constants.h (enum gomp_map_kind): Add GOMP_MAP_DEVICE_RESIDENT
and GOMP_MAP_LINK.

libgomp/
* libgomp.map (GOACC_2.0): Export GOACC_declare.
* oacc-init.c (acc_shutdown_1): Add call.
* oacc-int.h (goacc_allocate_static, goacc_deallocate_static): New
declarations.
* oacc-parallel.c (struct oacc_static): New struture.
(goacc_allocate_static, goacc_deallocate_static, GOACC_register_static,
GOACC_declare): New functions.
* testsuite/libgomp.oacc-c-c++-common/declare-1.c: New test.
* testsuite/libgomp.oacc-c-c++-common/declare-5.c: Likewise.
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index b561436..a109806 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -450,6 +450,7 @@ DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_ULONG_ULONG_ULONGPTR, BT_BOOL, BT_ULONG,
 		 BT_ULONG, BT_PTR_ULONG)
 DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, BT_BOOL,
 		 BT_ULONGLONG, BT_ULONGLONG, BT_PTR_ULONGLONG)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_UINT, BT_VOID, BT_PTR, BT_INT, BT_UINT)
 
 DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
 		 BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 1c75921..ffaa983 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -832,6 +832,7 @@ const struct attribute_spec c_common_attribute_table[] =
 			  handle_bnd_legacy, false },
   { "bnd_instr

Re: [OpenACC] declare directive

2015-10-28 Thread James Norris

Cesar,

On 10/28/2015 11:32 AM, Cesar Philippidis wrote:

On 10/27/2015 01:18 PM, James Norris wrote:


> This patch adds the processing of OpenACC declare directive in C
> and C++. (Note: Support in Fortran is already in trunk.)
> Commentary on the changes is included as an attachment (NOTES).

A quick diff of gomp4 and trunk reveals quite a few fortran changes that
aren't present in trunk. Can you post those changes as a separate patch?

Thanks,
Cesar



Yes, I will be doing that.

Thanks,
Jim


OpenACC declare directive updates

2015-11-02 Thread James Norris


This patch updates the processing of OpenACC declare directive for
Fortran in the following areas:

1) module support
2) device_resident and link clauses
3) clause checking
4) directive generation

Commentary on the changes is included as an attachment (NOTES).

All of the code is in the gomp-4_0-branch.

Regtested on x86_64-linux.

Thanks!
Jim
Background

The declare directive is used to allocate device memory for the
entire scope of a variable / array within a program, function,
or subroutine. Consider the following example.

module vars
  integer b
  !$acc declare device_resident (b)
  integer c
  !$acc declare link (c)
end module vars

program main
  use vars
  integer, parameter :: N = 8
  integer :: a(N)

  a(:) = 2
  c = 12

  !$acc parallel copy (a) present (b) copyin(c)
  do i = 1, N
b = a(i)
c = b
a(i) = c + i
  end do
  !$acc end parallel

end program

In the example, 'b' will be allocated on the device at the outset
of device activity and be available for the duration. Whereas the
allocation of 'c' will be delayed until the parallel region is
entered. The device memory for 'c' will be deallocated upon exit
of the parallel region.

Fortran front-end

The changes are concentrated into four (4) areas.

1) module support
The neccesary functionality has been added to handle the
reading in and writing out of the appropriate attributes
for the declare directive. Additional functionality has
been added at read in time to setup the required declare
handling.

2) device_resident and link clauses
Add the functionality necessary to process the link and
device_resident clauses.

3) clause checking
The clause checking has been cleaned up to better check
for duplicates and correctness.

4) directive generation

Prior to handling the fortran execution body a code
body is created to handle the clause(s) that accompany
the declare directive(s). Each clause is examined and
determined whether the clause need to be modified to 
perform an action at the beginning of the module, function,
subroutine, or program. Furthermore, an additional
clause may be added to the list to perform an action
at the time the function or subroutine returns.

Once all the clauses have been handled, the code body
is added to the chain.

libgomp

TODO

Testing

New compile and runtime tests have been added. Also some have
been modified.
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 83ecbaa..e953160 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -2572,10 +2572,14 @@ show_namespace (gfc_namespace *ns)
 
   if (ns->oacc_declare_clauses)
 {
+  struct gfc_oacc_declare *decl;
   /* Dump !$ACC DECLARE clauses.  */
-  show_indent ();
-  fprintf (dumpfile, "!$ACC DECLARE");
-  show_omp_clauses (ns->oacc_declare_clauses);
+  for (decl = ns->oacc_declare_clauses; decl; decl = decl->next)
+	{
+	  show_indent ();
+	  fprintf (dumpfile, "!$ACC DECLARE");
+	  show_omp_clauses (decl->clauses);
+	}
 }
 
   fputc ('\n', dumpfile);
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 67b0bac..2758a28 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -103,6 +103,8 @@ static const struct attribute_spec gfc_attribute_table[] =
affects_type_identity } */
   { "omp declare target", 0, 0, true,  false, false,
 gfc_handle_omp_declare_target_attribute, false },
+  { "oacc declare", 0, 0, true,  false, false,
+gfc_handle_omp_declare_target_attribute, false },
   { NULL,		  0, 0, false, false, false, NULL, false }
 };
 
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 90f63cf..17c2357 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -840,6 +840,13 @@ typedef struct
   /* Mentioned in OMP DECLARE TARGET.  */
   unsigned omp_declare_target:1;
 
+  /* Mentioned in OACC DECLARE.  */
+  unsigned oacc_declare_create:1;
+  unsigned oacc_declare_copyin:1;
+  unsigned oacc_declare_deviceptr:1;
+  unsigned oacc_declare_device_resident:1;
+  unsigned oacc_declare_link:1;
+
   /* Attributes set by compiler extensions (!GCC$ ATTRIBUTES).  */
   unsigned ext_attr:EXT_ATTR_NUM;
 
@@ -1105,7 +1112,9 @@ enum gfc_omp_map_op
   OMP_MAP_FORCE_FROM,
   OMP_MAP_FORCE_TOFROM,
   OMP_MAP_

Re: [OpenACC] declare directive

2015-11-03 Thread James Norris

On 10/27/2015 03:18 PM, James Norris wrote:

Hi!

 This patch adds the processing of OpenACC declare directive in C
 and C++. (Note: Support in Fortran is already in trunk.)
 Commentary on the changes is included as an attachment (NOTES).

 All of the code is in the gomp-4_0-branch.

 Regtested on x86_64-linux.

 Thanks!
 Jim


Ping!

I've revised the patch since I originally submitted it for review
(https://gcc.gnu.org/ml/gcc-patches/2015-10/msg02967.html). The
revision is due to Jakub and et al OpenMP 4.5 work in the area of
'omp declare target'. I now exploit that functionality and have
revised the patch accordingly.

Updated ChangeLog, patch, and commentary (NOTES) are attached.

Regtested on x86_64-linux

Thanks!
Jim

Background
The declare directive is used to allocate device memory for the
entire scope of a variable / array within a program, function,
or subroutine. Consider the following example.

int a[10];
#pragma acc declare create (a)

void func (int *a)
{
int b[10];
#pragma acc declare create (b)

#pragma acc parallel present (a, b)
{
  int i;

  for (i = 0; i < 10; i++)
  {
b[i] = a[i];
a[i] = b[i] + i;
  }

}

return;
}

int main (int argc, char **argv)
{
func (&a[0]);

return 0;
}

In the example, array 'a' will be allocated on the device at the
outset of device activity and be available for the duration.
Whereas, array 'b', will only be available when 'func' is executing.
In other words, array 'b' will be allocated at the outset of
execution of 'func' and deallocated at the return from 'func'. In
some instances, the clause may require that the host copy of a
variable / array be updated prior to a return from a function or
subroutine or exiting of the program.

C and C++ front-ends

Definitions for use in C and C++ were added to identify the
declare directive pragma and its' valid clauses. After the
clauses have been validated, if the declare directive is for a
global variable, then an attribute is created and chained.
These attributes will be used during gimplification.

Once the user-specified clauses have been parsed, the clauses
have to be examined and potentially altered and/or added to.
As mentioned in the previous section, with some clauses, e.g.,
e.g, copy, movement of data has to occur at the entry to 
something like a function as well as at exit. Hence the need
to examine/modify/add to the clauses so as to effect the
correct data movement.

For all instances of the declare directive, there is at least
one set of 'entry' clauses. If the clauses pertain to global
variables, a constructor is created. This constructor will
'register' the variable(s) / arrays so that at beginning of
OpenACC runtime the variable / arrays will be allocated and
be made available throughout program execution.

If on the other hand, the 'entry' clauses are not found to be
of a global type, then a node is created and the clauses are
associated with it. Also note that the 'return' clauses are
also associated with the node. Notice that there are 'return'
clauses only for non-global variables / arrays. The clauses
available for global variables / arrays only allow for data
movement at the initiation of program execution.

Middle-end

The OACC_DECLARE node is handled much the same as other OpenACC
nodes that represent directives. However, there is one thing
unique to declare, and that is the handling of the 'return'
clauses. The 'return' clauses are scanned and then a gimple
statment is created, but is not added. However, it is saved to
be added after the body has been gimplified.

The intent of this last-minute addition is to allow this statement
to be executed prior to returning from a function. JAKUB: While
this has been working, I'm not completely sure this is the proper
means by which to do this in order to guarantee this statement
is the last one executed. Please advise otherwise.

Callgraph

The 'make offload" functionality has been refactored to handle 
OpenACC variables / arrays. A variable is an OpenACC dec

OpenACC declare directive updates

2015-11-04 Thread James Norris


This patch updates the processing of OpenACC declare directive for
Fortran in the following areas:

1) module support
2) device_resident and link clauses
3) clause checking
4) directive generation

Commentary on the changes is included as an attachment (NOTES).

All of the code is in the gomp-4_0-branch.

Regtested on x86_64-linux.

Thanks!
Jim
Background

The declare directive is used to allocate device memory for the
entire scope of a variable / array within a program, function,
or subroutine. Consider the following example.

module vars
  integer b
  !$acc declare device_resident (b)
  integer c
  !$acc declare link (c)
end module vars

program main
  use vars
  integer, parameter :: N = 8
  integer :: a(N)

  a(:) = 2
  c = 12

  !$acc parallel copy (a) present (b) copyin(c)
  do i = 1, N
b = a(i)
c = b
a(i) = c + i
  end do
  !$acc end parallel

end program

In the example, 'b' will be allocated on the device at the outset
of device activity and be available for the duration. Whereas the
allocation of 'c' will be delayed until the parallel region is
entered. The device memory for 'c' will be deallocated upon exit
of the parallel region.

Fortran front-end

The changes are concentrated into four (4) areas.

1) module support
The neccesary functionality has been added to handle the
reading in and writing out of the appropriate attributes
for the declare directive. Additional functionality has
been added at read in time to setup the required declare
handling.

2) device_resident and link clauses
Add the functionality necessary to process the link and
device_resident clauses.

3) clause checking
The clause checking has been cleaned up to better check
for duplicates and correctness.

4) directive generation

Prior to handling the fortran execution body a code
body is created to handle the clause(s) that accompany
the declare directive(s). Each clause is examined and
determined whether the clause need to be modified to 
perform an action at the beginning of the module, function,
subroutine, or program. Furthermore, an additional
clause may be added to the list to perform an action
at the time the function or subroutine returns.

Once all the clauses have been handled, the code body
is added to the chain.

libgomp

TODO

Testing

New compile and runtime tests have been added. Also some have
    been modified.
2015-10-29  James Norris  
Cesar Philippidis  

gcc/fortran/
* dump-parse-tree.c (show_namespace): Reimplement.
* f95-lang.c (gfc_attribute_table): New entry.
* gfortran.h (struct symbol_attribute): New fields.
(enum gfc_omp_map_map): Add OMP_MAP_DEVICE_RESIDENT and OMP_MAP_LINK.
(OMP_LIST_LINK): New enum.
(struct gfc_oacc_declare): New structure.
(gfc_get_oacc_declare): New definition.
(struct gfc_namespace): Change type.
(enum gfc_exec_op): Add EXEC_OACC_DECLARE.
(struct gfc_code): New field.
* module.c (enum ab_attribute): Add AB_OACC_DECLARE_CREATE,
AB_OACC_DECLARE_COPYIN, AB_OACC_DECLARE_DEVICEPTR,
AB_OACC_DECLARE_DEVICE_RESIDENT, AB_OACC_DECLARE_LINK
(attr_bits): Add new initializers.
(mio_symbol_attribute): Handle new atributes.
* openmp.c (gfc_free_oacc_declare_clauses): New.
(OMP_CLAUSE_LINK): New definition.
(gfc_match_omp_clauses): Handle OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSES): Add OMP_CLAUSE_LINK
(gfc_match_oacc_declare): Add checking and module handling.
(resolve_omp_duplicate_list, resolve_oacc_declare_map): New.
(gfc_resolve_oacc_declare): Use duplicate detection.
* parse.c (case_decl): Add ST_OACC_DECLARE.
(parse_spec): Remove handling.
(parse_progunit): Remove handling.
* parse.h (struct gfc_state_data): Change type.
* resolve.c (gfc_resolve_blocks): Handle EXEC_OACC_DECLARE.
* st.c (gfc_free_statement): Handle EXEC_OACC_DECLARE.
* symbol.c (check_conflict): Add conflict checks.
(gfc_add_oacc_declare_create, gfc_add_oacc_declare_copyin, 
gfc_add_oacc_declare_deviceptr, gfc_add_oacc_declare_device_resident):
New functions.
(gfc_copy_attr): Handle new s

Re: [OpenACC] declare directive

2015-11-04 Thread James Norris

Hi Thomas,

On 11/04/2015 10:49 AM, Thomas Schwinge wrote:

Hi Jim!

On Tue, 3 Nov 2015 10:31:32 -0600, James Norris  
wrote:

On 10/27/2015 03:18 PM, James Norris wrote:

  This patch adds the processing of OpenACC declare directive in C
  and C++. (Note: Support in Fortran is already in trunk.)


..., and a patch adjusting some Fortran front end things is awaiting
review,
<http://news.gmane.org/find-root.php?message_id=%3C5637692F.7050306%40codesourcery.com%3E>.


  I've revised the patch since I originally submitted it for review
  (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg02967.html). The
  revision is due to Jakub and et al OpenMP 4.5 work in the area of
  'omp declare target'. I now exploit that functionality and have
  revised the patch accordingly.


Oh, wow, you could remove a lot of code!


Yes, I missed that patch when it entered into the code base. My bad.



Just a superficial review on your patch; patch re-ordered a bit for
review.


--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def



+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_UINT, BT_VOID, BT_PTR, BT_INT, BT_UINT)



--- a/gcc/fortran/types.def
+++ b/gcc/fortran/types.def



+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_UINT, BT_VOID, BT_PTR, BT_INT, BT_UINT)



--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def



+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_STATIC, "GOACC_register_static",
+  BT_FN_VOID_PTR_INT_UINT, ATTR_NOTHROW_LIST)



--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map



+   GOACC_register_static;


I think these changes can be dropped -- assuming you have not
unintentionally dropped the GOACC_register_static function/usage in your
v2 patch.


Will fix.




--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c



@@ -830,6 +830,7 @@ const struct attribute_spec c_common_attribute_table[] =



+  { "oacc declare",   0, -1, true,  false, false, NULL, false },


As far as I can tell, nothing is setting this attribute anymore in your
v2 patch, so I guess this and all handling code ("lookup_attribute",
"remove_attribute") can also be dropped?


Will fix.




--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c



  /* OpenACC 2.0:
+   # pragma acc declare oacc-data-clause[optseq] new-line
+*/
+
+#define OACC_DECLARE_CLAUSE_MASK   \
+   ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)  \
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)\
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)   \
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)\
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT)   \
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)   \


For uniformity, please use/add a new alias "PRAGMA_OACC_CLAUSE_* =
PRAGMA_OMP_CLAUSE_LINK" instead of using PRAGMA_OMP_CLAUSE_* here, and
also in c_parser_oacc_data_clause, c_parser_oacc_all_clauses, and in the
C++ front end.


Will fix.




+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)   \
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY)   \
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT)\
+   | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) )
+
+static void
+c_parser_oacc_declare (c_parser *parser)
+{



--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c



+static tree
+cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
+{
+  [...]
+  tree prev_attr = lookup_attribute ("oacc declare",
+DECL_ATTRIBUTES (decl));


Per my comment above, this would always be NULL_TREE.  The C front end is
different?


Will fix.




+
+  if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_LINK)
+   id = get_identifier ("omp declare target link");
+  else
+id = get_identifier ("omp declare target");
+
+  if (prev_attr)
+   {
+ tree p = TREE_VALUE (prev_attr);
+ tree cl = TREE_VALUE (p);
+
+ if (!devres && OMP_CLAUSE_MAP_KIND (cl) != GOMP_MAP_DEVICE_RESIDENT)
+   {
+ error_at (loc, "variable %qD used more than once with "
+   "%<#pragma acc declare%>", decl);
+ inform (OMP_CLAUSE_LOCATION (TREE_VALUE (p)),
+ "previous directive was here");
+ error = true;
+ continue;
+   }
+   }



--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15314,6 +15314,17 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl,

Re: OpenACC declare directive updates

2015-11-06 Thread James Norris

Jakub,

Ping

Do you need more information before you can review this patch?

Thanks!
Jim


On 11/04/2015 06:32 AM, James Norris wrote:


 This patch updates the processing of OpenACC declare directive for
 Fortran in the following areas:

 1) module support
 2) device_resident and link clauses
 3) clause checking
 4) directive generation

 Commentary on the changes is included as an attachment (NOTES).

 All of the code is in the gomp-4_0-branch.

 Regtested on x86_64-linux.

 Thanks!
 Jim




Re: [OpenACC] declare directive

2015-11-06 Thread James Norris

Jakub,

Ping.

Do you need more information before you can review this patch?

Thanks!
Jim


On 10/27/2015 03:18 PM, James Norris wrote:

Hi!

 This patch adds the processing of OpenACC declare directive in C
 and C++. (Note: Support in Fortran is already in trunk.)
 Commentary on the changes is included as an attachment (NOTES).

 All of the code is in the gomp-4_0-branch.

 Regtested on x86_64-linux.

 Thanks!
 Jim




Re: [OpenACC] declare directive

2015-11-06 Thread James Norris

Thomas,

I've added the issues that you pointed out. Attached
is the updated patch and ChangeLog.

Thanks for taking the time for your review!

Jakub,

Could you queue this patch ahead of my other one for
today? If it doesn't pass review, I'd like to work
the weekend and have the updated patch ready for
you when you walk in on your Monday.

Thank you,
Jim


On 11/04/2015 10:49 AM, Thomas Schwinge wrote:

Hi Jim!

On Tue, 3 Nov 2015 10:31:32 -0600, James Norris  
wrote:

On 10/27/2015 03:18 PM, James Norris wrote:

  This patch adds the processing of OpenACC declare directive in C
  and C++. (Note: Support in Fortran is already in trunk.)


..., and a patch adjusting some Fortran front end things is awaiting
review,
<http://news.gmane.org/find-root.php?message_id=%3C5637692F.7050306%40codesourcery.com%3E>.


  I've revised the patch since I originally submitted it for review
  (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg02967.html). The
  revision is due to Jakub and et al OpenMP 4.5 work in the area of
  'omp declare target'. I now exploit that functionality and have
  revised the patch accordingly.


Oh, wow, you could remove a lot of code!


Yes, I missed that patch when it entered into the code base. My bad.



Just a superficial review on your patch; patch re-ordered a bit for
review.


--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def



+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_UINT, BT_VOID, BT_PTR, BT_INT, BT_UINT)



--- a/gcc/fortran/types.def
+++ b/gcc/fortran/types.def



+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_UINT, BT_VOID, BT_PTR, BT_INT, BT_UINT)



--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def



+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_STATIC, "GOACC_register_static",
+   BT_FN_VOID_PTR_INT_UINT, ATTR_NOTHROW_LIST)



--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map



+GOACC_register_static;


I think these changes can be dropped -- assuming you have not
unintentionally dropped the GOACC_register_static function/usage in your
v2 patch.


Will fix.




--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c



@@ -830,6 +830,7 @@ const struct attribute_spec c_common_attribute_table[] =



+  { "oacc declare",   0, -1, true,  false, false, NULL, false },


As far as I can tell, nothing is setting this attribute anymore in your
v2 patch, so I guess this and all handling code ("lookup_attribute",
"remove_attribute") can also be dropped?


Will fix.




--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c



  /* OpenACC 2.0:
+   # pragma acc declare oacc-data-clause[optseq] new-line
+*/
+
+#define OACC_DECLARE_CLAUSE_MASK\
+( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)\


For uniformity, please use/add a new alias "PRAGMA_OACC_CLAUSE_* =
PRAGMA_OMP_CLAUSE_LINK" instead of using PRAGMA_OMP_CLAUSE_* here, and
also in c_parser_oacc_data_clause, c_parser_oacc_all_clauses, and in the
C++ front end.


Will fix.




+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT)\
+| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) )
+
+static void
+c_parser_oacc_declare (c_parser *parser)
+{



--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c



+static tree
+cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
+{
+  [...]
+  tree prev_attr = lookup_attribute ("oacc declare",
+ DECL_ATTRIBUTES (decl));


Per my comment above, this would always be NULL_TREE.  The C front end is
different?


Will fix.




+
+  if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_LINK)
+id = get_identifier ("omp declare target link");
+  else
+id = get_identifier ("omp declare target");
+
+  if (prev_attr)
+{
+  tree p = TREE_VALUE (prev_attr);
+  tree cl = TREE_VALUE (p);
+
+  if (!devres && OMP_CLAUSE_MAP_KIND (cl) != GOMP_MAP_DEVICE_RESIDENT)
+{
+  error_at (loc, "variable %qD used more than once with "
+"%<#pragma acc declare%>", decl);
+  inform (OMP_CLAUSE_LOCATION (TREE_VALUE (p)),
+  "previous directive was here");
+  error = true;
+  co

Re: [OpenACC] declare directive

2015-11-06 Thread James Norris

On 11/06/2015 10:08 AM, James Norris wrote:

Thomas,

I've added the issues that you pointed out. Attached
is the updated patch and ChangeLog.

Thanks for taking the time for your review!


Errr, make that 'addressed the issues that you pointed out."

Opps,
Jim



Re: OpenACC declare directive updates

2015-11-06 Thread James Norris

Jakub,


On 11/06/2015 01:31 PM, Jakub Jelinek wrote:

On Wed, Nov 04, 2015 at 06:32:00AM -0600, James Norris wrote:

+/* Node in the linked list used for storing !$oacc declare constructs.  */
+
+typedef struct gfc_oacc_declare
+{
+  struct gfc_oacc_declare *next;
+  bool module_var;
+  gfc_omp_clauses *clauses;
+  gfc_omp_clauses *return_clauses;
+}
+gfc_oacc_declare;
+
+#define gfc_get_oacc_declare() XCNEW (gfc_oacc_declare)
+
+
  /* Node in the linked list used for storing !$omp declare simd constructs.  */
  
  typedef struct gfc_omp_declare_simd

@@ -1644,7 +1668,7 @@ typedef struct gfc_namespace
struct gfc_data *data, *old_data;
  
/* !$ACC DECLARE clauses.  */

-  gfc_omp_clauses *oacc_declare_clauses;
+  struct gfc_oacc_declare *oacc_declare_clauses;

This should be renamed now that it doesn't hold just clauses,
perhaps just oacc_declare?  Also, no need to use struct keyword.


That's fine, I'll fix that.




@@ -2857,6 +2957,42 @@ oacc_compatible_clauses (gfc_omp_clauses *clauses, int 
list,
return false;
  }
  
+/* Check if a variable appears in multiple clauses.  */

+
+static void
+resolve_omp_duplicate_list (gfc_omp_namelist *clause_list, bool openacc,
+   int list)
+{
+  gfc_omp_namelist *n;
+  const char *error_msg = "Symbol %qs present on multiple clauses at %L";
+
+  /* OpenACC reduction clauses are compatible with everything.  We only
+ need to check if a reduction variable is used more than once.  */
+  if (openacc && list == OMP_LIST_REDUCTION)
+{
+  hash_set reductions;
+
+  for (n = clause_list; n; n = n->next)
+   {
+ if (reductions.contains (n->sym))
+   gfc_error (error_msg, n->sym->name, &n->expr->where);
+ else
+   reductions.add (n->sym);
+   }
+
+  return;
+}
+
+  /* Ensure that variables are only used in one clause.  */
+  for (n = clause_list; n; n = n->next)
+{
+  if (n->sym->mark)
+   gfc_error (error_msg, n->sym->name, &n->expr->where);
+  else
+   n->sym->mark = 1;
+}
+}

You are readding a function that has been rejected, OMP_LIST_REDUCTION
is handled differently now.

Jakub


Okay, I'll fix this.

After fixing, OK to commit?

Thank you for taking the time for the review.

Jim





Re: [OpenACC] declare directive

2015-11-06 Thread James Norris

Jakub,

On 11/06/2015 01:03 PM, Jakub Jelinek wrote:

On Fri, Nov 06, 2015 at 10:08:26AM -0600, James Norris wrote:

2015-10-27  James Norris  
Joseph Myers  

gcc/
* c-family/c-pragma.c (oacc_pragmas): Add entry for declare directive.
* c-family/c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_DECLARE.

c-family/, c/, cp/ have all their own ChangeLog files, and the entries
that go in there should not have the path prefixes.


Will fix.




+  for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
+{
+  location_t loc = OMP_CLAUSE_LOCATION (t);
+  tree decl = OMP_CLAUSE_DECL (t);
+  tree devres = NULL_TREE;
+  if (!DECL_P (decl))
+   {
+ error_at (loc, "subarray in %<#pragma acc declare%>");

Is that the OpenACC term that you use everywhere?  In OpenMP
those are array sections.


I can change the term so that both OpenACC and OpenMP
use the same terminology.




+   case GOMP_MAP_LINK:
+ if (!global_bindings_p () && !DECL_EXTERNAL (decl))
+   {
+ error_at (loc,
+   "%qD must be a global variable in"
+   "%<#pragma acc declare link%>",
+   decl);
+ error = true;
+ continue;

What about TREE_STATIC?


Will fix.




diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index fa34858..fbd4a69 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -157,6 +157,7 @@ struct gimplify_omp_ctx
bool target_map_scalars_firstprivate;
bool target_map_pointers_as_0len_arrays;
bool target_firstprivatize_array_bases;
+  gomp_target *declare_returns;
  };

This declare_returns stuff looks broken.
What exactly do you want to achieve?  Why do you record it
in gimplify_omp_ctx, but then only look at it in gimplify_body?
The way you abuse gimplify_omp_ctx for that is just too ugly.
All the gimplification code expects that when you enter some OpenMP/OpenACC
construct, you create new context if it needs one, then process the body
of the construct, then pop it up.  The declare_returns stuff
violates all of this.  Do you want to enqueue all the statements
at the end of the body?  Then just stick it into some gimple_seq
outside of the gimplify_omp_ctx, and process in there.  Or if you
want to process it when leaving some construct, arrange for that.


For example:

void func (int *a)
{
   int b[10];
   #pragma acc declare copyout (b)

.
.
.
}

What I was trying to do was for a copyout to be done at the
time the function return'ed. It also may be the case where
a mapping operation must be done at entry and exit to a
function. I think the approach you outline below (target data/
acc data) is the approach to use.


@@ -5841,6 +5863,8 @@ omp_default_clause (struct gimplify_omp_ctx *ctx, tree 
decl,
flags |= GOVD_FIRSTPRIVATE;
break;
  case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
+  if (is_global_var (decl) && device_resident_p (decl))
+   flags |= GOVD_MAP_TO_ONLY | GOVD_MAP;

I don't think you want to do this except for (selected or all?)
OpenACC contexts.  Say, I don't see why one couldn't e.g. try to mix
OpenMP host parallelization or tasking with OpenACC offloading,
and that affecting in weird way OpenMP semantics.


Will fix.




+  /* Any clauses that affect the state of a variable prior
+ to return are saved and dealt with after the body has
+ been gimplified.  */
+
+  gimplify_scan_omp_clauses (&clauses, pre_p, ORT_TARGET_DATA,
+OACC_DECLARE);
+
+  c = gimplify_omp_ctxp;
+  gimplify_omp_ctxp = c->outer_context;
+  delete_omp_context (c);

Why don't you call gimplify_adjust_omp_clauses instead?


What I was attempting to do was to create to sets of clauses.
One used for mapping operations at entry to a function and
the other at exit. Obviously, I've made a mess of things with
this approach.




+  stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
+ clauses);
+  gimplify_omp_ctxp->declare_returns = stmt;

But the above is the main thing I have trouble with.
What happens if you have multiple #pragma acc declare directives?
Is the stmt from the other ones lost?
I'd expect something like gimple_seq in there instead and pushing
stmts into the sequence.
I don't know what is the semantics of the construct, if it is something
close to say target data in OpenMP or acc data in OpenACC, the addition
of code to unmap the variables is performed using a cleanup, otherwise
how do you handle exceptions, or goto and all other kinds of abnormal
returns from the function.


I think the approach you've outlined is the way to go.




@@ -160,6 +151,25 @@ varpool_node::get_create (tree decl)
node->force_output = 1;
  #endif
  }
+}
+
+/* Return varpool node assigned to DECL.  Create new one

Re: [OpenACC] declare directive

2015-11-06 Thread James Norris

Jakub,

On 11/06/2015 01:22 PM, Jakub Jelinek wrote:

On Fri, Nov 06, 2015 at 08:03:52PM +0100, Jakub Jelinek wrote:

What exactly do you want to achieve?  Why do you record it
in gimplify_omp_ctx, but then only look at it in gimplify_body?
The way you abuse gimplify_omp_ctx for that is just too ugly.
All the gimplification code expects that when you enter some OpenMP/OpenACC
construct, you create new context if it needs one, then process the body
of the construct, then pop it up.  The declare_returns stuff
violates all of this.  Do you want to enqueue all the statements
at the end of the body?  Then just stick it into some gimple_seq
outside of the gimplify_omp_ctx, and process in there.  Or if you
want to process it when leaving some construct, arrange for that.

If the unmap operation is supposed to sit where the corresponding variable
goes out of scope, supposedly you would need to find out in which bind
(gimplify_ctx (not omp!)) the variable is declared and arrange for the
statement to be added as a cleanup of that region.
If you queue everything to the end of function, I'm afraid with e.g.
void foo (void)
{
   {
 char buf[2048];
 #acc declare whatever(buf)
 // ...
   }
   {
 char buf2[2048];
 #acc declare whatever(buf2)
 // ...
   }
}
both vars will be assigned overlapping ranges and you might run into
trouble trying to map buf2 while buf is still mapped.

Jakub


Good point.

Thank you again,
Jim


Re: OpenACC declare directive updates

2015-11-06 Thread James Norris

Jakub,

On 11/06/2015 01:49 PM, Jakub Jelinek wrote:

On Fri, Nov 06, 2015 at 01:45:09PM -0600, James Norris wrote:

Okay, I'll fix this.

After fixing, OK to commit?

Thank you for taking the time for the review.

Well, isn't this patch really dependent on the other one?


Yes. Should I combine the patches into a single patch?



Also, wonder about BLOCK stmt in Fortran, that can give you variables that
don't live through the whole function, but only a portion of it even in
Fortran.


Let me scratch my head on that one.


Jakub


Thanks again,
Jim



Re: [OpenACC] declare directive

2015-11-06 Thread James Norris

On 11/06/2015 02:28 PM, Jakub Jelinek wrote:

On Fri, Nov 06, 2015 at 02:18:11PM -0600, James Norris wrote:

On 11/06/2015 01:22 PM, Jakub Jelinek wrote:

On Fri, Nov 06, 2015 at 08:03:52PM +0100, Jakub Jelinek wrote:

What exactly do you want to achieve?  Why do you record it
in gimplify_omp_ctx, but then only look at it in gimplify_body?
The way you abuse gimplify_omp_ctx for that is just too ugly.
All the gimplification code expects that when you enter some OpenMP/OpenACC
construct, you create new context if it needs one, then process the body
of the construct, then pop it up.  The declare_returns stuff
violates all of this.  Do you want to enqueue all the statements
at the end of the body?  Then just stick it into some gimple_seq
outside of the gimplify_omp_ctx, and process in there.  Or if you
want to process it when leaving some construct, arrange for that.

If the unmap operation is supposed to sit where the corresponding variable
goes out of scope, supposedly you would need to find out in which bind
(gimplify_ctx (not omp!)) the variable is declared and arrange for the
statement to be added as a cleanup of that region.
If you queue everything to the end of function, I'm afraid with e.g.
void foo (void)
{
   {
 char buf[2048];
 #acc declare whatever(buf)
 // ...
   }
   {
 char buf2[2048];
 #acc declare whatever(buf2)
 // ...
   }
}
both vars will be assigned overlapping ranges and you might run into
trouble trying to map buf2 while buf is still mapped.

Jakub

Good point.

Perhaps what would work is stick the "exit" clauses you need for automatic
vars in the function inside of some pointer map / hash table / whatever,
and then in gimplify_bind_expr in the
   /* Add clobbers for all variables that go out of scope.  */
if if flag_openacc && the pointer_map /hash table has any entries look
up each variable in there and collect the clauses from those vars that go
out of scope, after the loop if any were collected construct the statement
you need prepend it to cleanup (so that it works before restoring VLA memory
and before the clobber stmts).


I like that. Thank you again.



Jakub


Jim




Re: OpenACC declare directive updates

2015-11-08 Thread James Norris

Jakub,

The attached patch and ChangeLog reflect the updates from your
review: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00714.html.
All of the issues pointed out, have been address.

With the changes made in this patch I think I'm handling the
situation that you pointed out here correctly:

On Fri, Nov 06, 2015 at 01:45:09PM -0600, James Norris wrote:

Also, wonder about BLOCK stmt in Fortran, that can give you variables that
don't live through the whole function, but only a portion of it even in
Fortran.

OK to commit to trunk?

Thanks!
Jim

2015-XX-XX  James Norris  
Cesar Philippidis  

gcc/fortran/
* dump-parse-tree.c (show_namespace): Handle declares.
* f95-lang.c (gfc_attribute_table): New entry.
* gfortran.h (struct symbol_attribute): New fields.
(enum gfc_omp_map_map): Add OMP_MAP_DEVICE_RESIDENT and OMP_MAP_LINK.
(OMP_LIST_LINK): New enum.
(struct gfc_oacc_declare): New structure.
(gfc_get_oacc_declare): New definition.
(struct gfc_namespace): Change type.
(enum gfc_exec_op): Add EXEC_OACC_DECLARE.
(struct gfc_code): New field.
* module.c (enum ab_attribute): Add AB_OACC_DECLARE_CREATE,
AB_OACC_DECLARE_COPYIN, AB_OACC_DECLARE_DEVICEPTR,
AB_OACC_DECLARE_DEVICE_RESIDENT, AB_OACC_DECLARE_LINK
(attr_bits): Add new initializers.
(mio_symbol_attribute): Handle new atributes.
* openmp.c (gfc_free_oacc_declare_clauses): New function.
(OMP_CLAUSE_LINK): New definition.
(gfc_match_omp_clauses): Handle OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSES): Add OMP_CLAUSE_LINK
(gfc_match_oacc_declare): Add checking and module handling.
(gfc_resolve_oacc_declare): Use duplicate detection.
* parse.c (case_decl): Add ST_OACC_DECLARE.
(parse_spec): Remove handling.
(parse_progunit): Remove handling.
* parse.h (struct gfc_state_data): Change type.
* resolve.c (gfc_resolve_blocks): Handle EXEC_OACC_DECLARE.
* st.c (gfc_free_statement): Handle EXEC_OACC_DECLARE.
* symbol.c (check_conflict): Add conflict checks.
(gfc_add_oacc_declare_create, gfc_add_oacc_declare_copyin, 
gfc_add_oacc_declare_deviceptr, gfc_add_oacc_declare_device_resident):
New functions.
(gfc_copy_attr): Handle new symbols.
* trans-decl.c (add_attributes_to_decl): Create identifier.
(struct oacc_return): New structure.
(find_oacc_return, add_clause, find_module_oacc_declare_clauses,
finish_oacc_declare): New functions.
(gfc_generate_function_code): Replace with call.
* trans-openmp.c (gfc_trans_omp_clauses): Add conditional.
(gfc_trans_oacc_declare): Reimplement.
(gfc_trans_oacc_directive): Handle EXEC_OACC_DECLARE.
* trans-stmt.c (gfc_trans_block_construct): Replace with call.
* trans-stmt.h (gfc_trans_oacc_declare): Remove argument.
* trans.c (trans_code): Handle EXEC_OACC_DECLARE.

gcc/testsuite
* gfortran.dg/goacc/declare-1.f95: Update test.
* gfortran.dg/goacc/declare-2.f95: New test.

libgomp/
* testsuite/libgomp.oacc-fortran/declare-1.f90: New test.
* testsuite/libgomp.oacc-fortran/declare-2.f90: Likewise.
* testsuite/libgomp.oacc-fortran/declare-3.f90: Likewise.
* testsuite/libgomp.oacc-fortran/declare-4.f90: Likewise.
* testsuite/libgomp.oacc-fortran/declare-5.f90: Likewise.
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 83ecbaa..48476af 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -2570,12 +2570,16 @@ show_namespace (gfc_namespace *ns)
   for (eq = ns->equiv; eq; eq = eq->next)
 show_equiv (eq);
 
-  if (ns->oacc_declare_clauses)
+  if (ns->oacc_declare)
 {
+  struct gfc_oacc_declare *decl;
   /* Dump !$ACC DECLARE clauses.  */
-  show_indent ();
-  fprintf (dumpfile, "!$ACC DECLARE");
-  show_omp_clauses (ns->oacc_declare_clauses);
+  for (decl = ns->oacc_declare; decl; decl = decl->next)
+	{
+	  show_indent ();
+	  fprintf (dumpfile, "!$ACC DECLARE");
+	  show_omp_clauses (decl->clauses);
+	}
 }
 
   fputc ('\n', dumpfile);
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 2e91470..a8458b0 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -99,6 +99,8 @@ static const struct attribute_spec gfc_attribute_table[] =
affects_type_identity } */
   { "omp declare target", 0, 0, true,  false, false,
 gfc_handle_omp_declare_target_attribute, false },
+  { "oacc declare", 0, 0, true,  false, false,
+gfc_handle_omp_declare_target_attribute, false },
   { NULL,		  0, 0, false, false, false, NULL, false }
 };
 
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index e13b4d4..3965b0

Re: [OpenACC] declare directive

2015-11-08 Thread James Norris

Jakub,

The attached patch and ChangeLog reflect the updates from your
review: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00703.html.

The most significant change was the one that you suggestion:

On 11/06/2015 02:28 PM, Jakub Jelinek wrote:
> Perhaps what would work is stick the exit clauses you need for automatic
> vars in the function inside of some pointer map / hash table / whatever,
> and then in gimplify_bind_expr in the
>/* Add clobbers for all variables that go out of scope.  */
> if if flag_openacc && the pointer_map /hash table has any entries look
> up each variable in there and collect the clauses from those vars that go
> out of scope, after the loop if any were collected construct the statement
> you need prepend it to cleanup (so that it works before restoring VLA memory
> and before the clobber stmts).

This particular change allowed for the removal of all the
'stuff looks broken' code. Thanks for the suggestion.

The following change I did not address:

On 11/06/2015 01:03 PM, Jakub Jelinek wrote
>> @@ -5841,6 +5863,8 @@ omp_default_clause (struct gimplify_omp_ctx *ctx, tree 
decl,

>> flags |= GOVD_FIRSTPRIVATE;
>> break;
>>   case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
>> +  if (is_global_var (decl) && device_resident_p (decl))
>> +flags |= GOVD_MAP_TO_ONLY | GOVD_MAP;
>
> I don't think you want to do this except for (selected or all?)
> OpenACC contexts.  Say, I don't see why one couldn't e.g. try to mix
> OpenMP host parallelization or tasking with OpenACC offloading,
> and that affecting in weird way OpenMP semantics.

A colleague is adding code to allow for the detection of OpenACC contexts.
This change has yet make it to trunk. I need some guidance from you whether
I can leave the code as is and resolve the issue at stage3 time,
or remove the code and the associated function device_resident_()
and address the issue at stage 3.

OK to commit to trunk?

Thanks!
Jim

2015-XX-XX  James Norris  
Joseph Myers  

gcc/c-family/
* c-pragma.c (oacc_pragmas): Add entry for declare directive. 
* c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_DECLARE.
(enum pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT and
PRAGMA_OACC_CLAUSE_LINK.

gcc/c/
* c-parser.c (c_parser_pragma): Handle PRAGMA_OACC_DECLARE.
(c_parser_omp_clause_name): Handle 'device_resident' clause.
(c_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(c_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OACC_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(c_parser_oacc_declare): New function.

gcc/cp/
* parser.c (cp_parser_omp_clause_name): Handle 'device_resident'
clause.
(cp_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(cp_paser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(cp_parser_oacc_declare): New function.
(cp_parser_pragma): Handle PRAGMA_OACC_DECLARE.
* pt.c (tsubst_expr): Handle OACC_DECLARE.

gcc/
* gimple-pretty-print.c (dump_gimple_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE. 
* gimple.h (enum gf_mask): Add GF_OMP_TARGET_KIND_OACC_DECLARE.
(is_gomple_omp_oacc): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* gimplify.c (gimplify_bind_expr): Prepend 'exit' stmt to cleanup.
* omp-builtins.def (BUILT_IN_GOACC_DECLARE): New builtin.
* omp-low.c (expand_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE and BUILTIN_GOACC_DECLARE.
(build_omp_regions_1): Handlde GF_OMP_TARGET_KIND_OACC_DECLARE.
(lower_omp_target): Handle GF_OMP_TARGET_KIND_OACC_DECLARE,
GOMP_MAP_DEVICE_RESIDENT and GOMP_MAP_LINK.
(make_gimple_omp_edges): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.

gcc/testsuite
* c-c++-common/goacc/declare-1.c: New test.
* c-c++-common/goacc/declare-2.c: Likewise.

include/
* gomp-constants.h (enum gomp_map_kind): Add GOMP_MAP_DEVICE_RESIDENT
and GOMP_MAP_LINK.

libgomp/

* libgomp.map (GOACC_2.0.1): Export GOACC_declare.
* oacc-parallel.c (GOACC_declare): New function.
* testsuite/libgomp.oacc-c-c++-common/declare-1.c: New test.
* testsuite/libgomp.oacc-c-c++-common/declare-5.c: Likewise.
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index ac11838..cd0cc27 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1207,6 +1207,7 @@ static const struct omp_pragma_def oacc_pragmas[] = {
   { &

Re: OpenACC declare directive updates

2015-11-08 Thread James Norris

Cesar,


I only noticed these because I thought I fixed them in the patch you
asked me to revert from gomp-4_0-branch. At the very least, please try
to be consistent on iterating OMP_LIST_*.

Thank you for noticing!

Jakub,

The attached patch and ChangeLog reflect the updates from your
review: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00714.html
and Cesar's review: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00885.html.

With the changes made in this patch I think I'm handling the
situation that you pointed out here correctly:

"Also, wonder about BLOCK stmt in Fortran, that can give you variables that
don't live through the whole function, but only a portion of it even in
Fortran."

OK to commit to trunk?

Thanks!
Jim

2015-XX-XX  James Norris  
Joseph Myers  

gcc/c-family/
* c-pragma.c (oacc_pragmas): Add entry for declare directive. 
* c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_DECLARE.
(enum pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT and
PRAGMA_OACC_CLAUSE_LINK.

gcc/c/
* c-parser.c (c_parser_pragma): Handle PRAGMA_OACC_DECLARE.
(c_parser_omp_clause_name): Handle 'device_resident' clause.
(c_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(c_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OACC_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(c_parser_oacc_declare): New function.

gcc/cp/
* parser.c (cp_parser_omp_clause_name): Handle 'device_resident'
clause.
(cp_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(cp_paser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(cp_parser_oacc_declare): New function.
(cp_parser_pragma): Handle PRAGMA_OACC_DECLARE.
* pt.c (tsubst_expr): Handle OACC_DECLARE.

gcc/
* gimple-pretty-print.c (dump_gimple_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE. 
* gimple.h (enum gf_mask): Add GF_OMP_TARGET_KIND_OACC_DECLARE.
(is_gomple_omp_oacc): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* gimplify.c (gimplify_bind_expr): Prepend 'exit' stmt to cleanup.
* omp-builtins.def (BUILT_IN_GOACC_DECLARE): New builtin.
* omp-low.c (expand_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE and BUILTIN_GOACC_DECLARE.
(build_omp_regions_1): Handlde GF_OMP_TARGET_KIND_OACC_DECLARE.
(lower_omp_target): Handle GF_OMP_TARGET_KIND_OACC_DECLARE,
GOMP_MAP_DEVICE_RESIDENT and GOMP_MAP_LINK.
(make_gimple_omp_edges): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.

gcc/testsuite
* c-c++-common/goacc/declare-1.c: New test.
* c-c++-common/goacc/declare-2.c: Likewise.

include/
* gomp-constants.h (enum gomp_map_kind): Add GOMP_MAP_DEVICE_RESIDENT
and GOMP_MAP_LINK.

libgomp/

* libgomp.map (GOACC_2.0.1): Export GOACC_declare.
* oacc-parallel.c (GOACC_declare): New function.
* testsuite/libgomp.oacc-c-c++-common/declare-1.c: New test.
* testsuite/libgomp.oacc-c-c++-common/declare-5.c: Likewise.
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index ac11838..cd0cc27 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1207,6 +1207,7 @@ static const struct omp_pragma_def oacc_pragmas[] = {
   { "atomic", PRAGMA_OACC_ATOMIC },
   { "cache", PRAGMA_OACC_CACHE },
   { "data", PRAGMA_OACC_DATA },
+  { "declare", PRAGMA_OACC_DECLARE },
   { "enter", PRAGMA_OACC_ENTER_DATA },
   { "exit", PRAGMA_OACC_EXIT_DATA },
   { "kernels", PRAGMA_OACC_KERNELS },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 953c4e3..c6a2981 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -30,6 +30,7 @@ enum pragma_kind {
   PRAGMA_OACC_ATOMIC,
   PRAGMA_OACC_CACHE,
   PRAGMA_OACC_DATA,
+  PRAGMA_OACC_DECLARE,
   PRAGMA_OACC_ENTER_DATA,
   PRAGMA_OACC_EXIT_DATA,
   PRAGMA_OACC_KERNELS,
@@ -151,6 +152,7 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_CREATE,
   PRAGMA_OACC_CLAUSE_DELETE,
   PRAGMA_OACC_CLAUSE_DEVICEPTR,
+  PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT,
   PRAGMA_OACC_CLAUSE_GANG,
   PRAGMA_OACC_CLAUSE_HOST,
   PRAGMA_OACC_CLAUSE_INDEPENDENT,
@@ -175,7 +177,8 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
   PRAGMA_OACC_CLAUSE_IF = PRAGMA_OMP_CLAUSE_IF,
   PRAGMA_OACC_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE,
-  PRAGMA_OACC_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION
+  PRAGMA_OACC_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION,
+  PRAGMA

Re: [OpenACC] declare directive

2015-11-09 Thread James Norris

Jakub,

This is an update of the patch from:
https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00893.html.
There was an unused variable in c/c-parser.c that was
removed.

I've included the ChangeLog as a convenience, but nothing
was changed in the file.

Thanks!
Jim

2015-XX-XX  James Norris  
Joseph Myers  

gcc/c-family/
* c-pragma.c (oacc_pragmas): Add entry for declare directive. 
* c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_DECLARE.
(enum pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT and
PRAGMA_OACC_CLAUSE_LINK.

gcc/c/
* c-parser.c (c_parser_pragma): Handle PRAGMA_OACC_DECLARE.
(c_parser_omp_clause_name): Handle 'device_resident' clause.
(c_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(c_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OACC_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(c_parser_oacc_declare): New function.

gcc/cp/
* parser.c (cp_parser_omp_clause_name): Handle 'device_resident'
clause.
(cp_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(cp_paser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(cp_parser_oacc_declare): New function.
(cp_parser_pragma): Handle PRAGMA_OACC_DECLARE.
* pt.c (tsubst_expr): Handle OACC_DECLARE.

gcc/
* gimple-pretty-print.c (dump_gimple_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE. 
* gimple.h (enum gf_mask): Add GF_OMP_TARGET_KIND_OACC_DECLARE.
(is_gomple_omp_oacc): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* gimplify.c (gimplify_bind_expr): Prepend 'exit' stmt to cleanup.
* omp-builtins.def (BUILT_IN_GOACC_DECLARE): New builtin.
* omp-low.c (expand_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE and BUILTIN_GOACC_DECLARE.
(build_omp_regions_1): Handlde GF_OMP_TARGET_KIND_OACC_DECLARE.
(lower_omp_target): Handle GF_OMP_TARGET_KIND_OACC_DECLARE,
GOMP_MAP_DEVICE_RESIDENT and GOMP_MAP_LINK.
(make_gimple_omp_edges): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.

gcc/testsuite
* c-c++-common/goacc/declare-1.c: New test.
* c-c++-common/goacc/declare-2.c: Likewise.

include/
* gomp-constants.h (enum gomp_map_kind): Add GOMP_MAP_DEVICE_RESIDENT
and GOMP_MAP_LINK.

libgomp/

* libgomp.map (GOACC_2.0.1): Export GOACC_declare.
* oacc-parallel.c (GOACC_declare): New function.
* testsuite/libgomp.oacc-c-c++-common/declare-1.c: New test.
* testsuite/libgomp.oacc-c-c++-common/declare-5.c: Likewise.
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index ac11838..cd0cc27 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1207,6 +1207,7 @@ static const struct omp_pragma_def oacc_pragmas[] = {
   { "atomic", PRAGMA_OACC_ATOMIC },
   { "cache", PRAGMA_OACC_CACHE },
   { "data", PRAGMA_OACC_DATA },
+  { "declare", PRAGMA_OACC_DECLARE },
   { "enter", PRAGMA_OACC_ENTER_DATA },
   { "exit", PRAGMA_OACC_EXIT_DATA },
   { "kernels", PRAGMA_OACC_KERNELS },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 953c4e3..c6a2981 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -30,6 +30,7 @@ enum pragma_kind {
   PRAGMA_OACC_ATOMIC,
   PRAGMA_OACC_CACHE,
   PRAGMA_OACC_DATA,
+  PRAGMA_OACC_DECLARE,
   PRAGMA_OACC_ENTER_DATA,
   PRAGMA_OACC_EXIT_DATA,
   PRAGMA_OACC_KERNELS,
@@ -151,6 +152,7 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_CREATE,
   PRAGMA_OACC_CLAUSE_DELETE,
   PRAGMA_OACC_CLAUSE_DEVICEPTR,
+  PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT,
   PRAGMA_OACC_CLAUSE_GANG,
   PRAGMA_OACC_CLAUSE_HOST,
   PRAGMA_OACC_CLAUSE_INDEPENDENT,
@@ -175,7 +177,8 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
   PRAGMA_OACC_CLAUSE_IF = PRAGMA_OMP_CLAUSE_IF,
   PRAGMA_OACC_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE,
-  PRAGMA_OACC_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION
+  PRAGMA_OACC_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION,
+  PRAGMA_OACC_CLAUSE_LINK = PRAGMA_OMP_CLAUSE_LINK
 };
 
 extern struct cpp_reader* parse_in;
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 23d0107..8edf745 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1231,6 +1231,7 @@ static vec *c_parser_expr_list (c_parser *, bool, bool,
 	 vec **, location_t *,
 	 tree *, vec *,
 	 unsigned int * = NULL);
+static void c_parser_oacc_declare (c_parser *);
 static void c_parser_oacc_enter_exit_data (c_parser *, bool);
 st

Re: [OpenACC] declare directive

2015-11-09 Thread James Norris

Jakub,

On 11/09/2015 10:21 AM, Jakub Jelinek wrote:

On Mon, Nov 09, 2015 at 10:01:32AM -0600, James Norris wrote:

+  if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))

Here you only look up "omp declare target", not "omp declare target link".
So, what happens if you mix that (once in some copy clause, once in link),
or mention twice in link, etc.?  Needs testsuite coverage and clear rules.


Will fix.




+ DECL_ATTRIBUTES (decl) =
+   tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));

Incorrect formatting, = goes already on the following line, no whitespace
at end of line, and next line is indented below CL from DECL.


Will fix.




+ t = build_omp_clause (OMP_CLAUSE_LOCATION (c) , OMP_CLAUSE_MAP);

Wrong formatting, no space before ,.


Will fix.


+if (ret_clauses)
+  {
+   tree fndecl = current_function_decl;
+   tree attrs = lookup_attribute ("oacc declare returns",
+  DECL_ATTRIBUTES (fndecl));

Why do you use an attribute for this?  I think adding the automatic
vars to hash_map during gimplification of the OACC_DECLARE is best.


See below (This doesn't scale...)




+   tree id = get_identifier ("oacc declare returns");
+   DECL_ATTRIBUTES (fndecl) =
+   tree_cons (id, ret_clauses, DECL_ATTRIBUTES (fndecl));

Formatting error.


Will fix.




--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1065,6 +1065,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
gimple_seq body, cleanup;
gcall *stack_save;
location_t start_locus = 0, end_locus = 0;
+  tree ret_clauses = NULL;
  
tree temp = voidify_wrapper_expr (bind_expr, NULL);
  
@@ -1166,9 +1167,56 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)

  clobber_stmt = gimple_build_assign (t, clobber);
  gimple_set_location (clobber_stmt, end_locus);
  gimplify_seq_add_stmt (&cleanup, clobber_stmt);
+
+ if (flag_openacc)
+   {
+ tree attrs = lookup_attribute ("oacc declare returns",
+  DECL_ATTRIBUTES (current_function_decl));
+ tree clauses, c, c_next = NULL, c_prev = NULL;
+
+ if (!attrs)
+   break;
+
+ clauses = TREE_VALUE (attrs);
+
+ for (c = clauses; c; c_prev = c, c = c_next)
+   {
+ c_next = OMP_CLAUSE_CHAIN (c);
+
+ if (t == OMP_CLAUSE_DECL (c))
+   {
+ if (ret_clauses)
+   OMP_CLAUSE_CHAIN (c) = ret_clauses;
+
+ ret_clauses = c;
+
+ if (c_prev == NULL)
+   clauses = c_next;
+ else
+   OMP_CLAUSE_CHAIN (c_prev) = c_next;
+   }
+   }

This doesn't really scale.  Consider 1 clauses on various
oacc declare constructs in a single function, and 100 automatic
variables in such a function.
So, what I'm suggesting is during gimplification of OACC_DECLARE,
if you find a clause on an automatic variable in the current function
that you want to unmap afterwards, have a
static hash_map *oacc_declare_returns;
and you just add into the hash map the VAR_DECL -> the clause you want,
then in this spot you check
   if (oacc_declare_returns)
 {
   clause = lookup in hash_map (t);
   if (clause)
{
  ...
}
 }


Now I see what you were getting at in using the hash_map. I didn't
consider creating a static hash_map and populating it as you suggest.

Thank you!




+
+ if (clauses == NULL)
+   {
+ DECL_ATTRIBUTES (current_function_decl) =
+   remove_attribute ("oacc declare returns",
+   DECL_ATTRIBUTES (current_function_decl));

Wrong formatting.


Will fix.



Jakub


Thanks for taking the time to review.

Jim




Re: [OpenACC] declare directive

2015-11-09 Thread James Norris

Jakub,


The attached patch and ChangeLog reflects the updates from your
review: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg01002.html

All of the issues you pointed out have been addressed. I've also
added a test that uses C++ templates. A bug was also fixed in the
parsers which dealt with determining which identifier to use  with
an attribute.

Thanks!
Jim




2015-XX-XX  James Norris  
Joseph Myers  

gcc/c-family/
* c-pragma.c (oacc_pragmas): Add entry for declare directive. 
* c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_DECLARE.
(enum pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT and
PRAGMA_OACC_CLAUSE_LINK.

gcc/c/
* c-parser.c (c_parser_pragma): Handle PRAGMA_OACC_DECLARE.
(c_parser_omp_clause_name): Handle 'device_resident' clause.
(c_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(c_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OACC_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(c_parser_oacc_declare): New function.

gcc/cp/
* parser.c (cp_parser_omp_clause_name): Handle 'device_resident'
clause.
(cp_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(cp_paser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(cp_parser_oacc_declare): New function.
(cp_parser_pragma): Handle PRAGMA_OACC_DECLARE.
* pt.c (tsubst_expr): Handle OACC_DECLARE.

gcc/
* gimple-pretty-print.c (dump_gimple_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE. 
* gimple.h (enum gf_mask): Add GF_OMP_TARGET_KIND_OACC_DECLARE.
(is_gomple_omp_oacc): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* gimplify.c (oacc_declare_returns): New.
(gimplify_bind_expr): Prepend 'exit' stmt to cleanup.
(device_resident_p): New function.
(omp_default_clause): Handle device_resident clause.
(gimplify_oacc_declare_1, gimplify_oacc_declare): New functions.
(gimplify_expr): Handle OACC_DECLARE.
* omp-builtins.def (BUILT_IN_GOACC_DECLARE): New builtin.
* omp-low.c (expand_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE and BUILTIN_GOACC_DECLARE.
(build_omp_regions_1): Handlde GF_OMP_TARGET_KIND_OACC_DECLARE.
(lower_omp_target): Handle GF_OMP_TARGET_KIND_OACC_DECLARE,
GOMP_MAP_DEVICE_RESIDENT and GOMP_MAP_LINK.
(make_gimple_omp_edges): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* tree-pretty-print.c (dump_omp_clause): Handle GOMP_MAP_LINK and
GOMP_MAP_DEVICE_RESIDENT.

gcc/testsuite
* c-c++-common/goacc/declare-1.c: New test.
* c-c++-common/goacc/declare-2.c: Likewise.

include/
* gomp-constants.h (enum gomp_map_kind): Add GOMP_MAP_DEVICE_RESIDENT
and GOMP_MAP_LINK.

libgomp/

* libgomp.map (GOACC_2.0.1): Export GOACC_declare.
* oacc-parallel.c (GOACC_declare): New function.
* testsuite/libgomp.oacc-c-c++-common/declare-1.c: New test.
* testsuite/libgomp.oacc-c-c++-common/declare-5.c: Likewise.
* testsuite/libgomp.oacc-c++/declare-1.C: Likewise.
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index ac11838..cd0cc27 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1207,6 +1207,7 @@ static const struct omp_pragma_def oacc_pragmas[] = {
   { "atomic", PRAGMA_OACC_ATOMIC },
   { "cache", PRAGMA_OACC_CACHE },
   { "data", PRAGMA_OACC_DATA },
+  { "declare", PRAGMA_OACC_DECLARE },
   { "enter", PRAGMA_OACC_ENTER_DATA },
   { "exit", PRAGMA_OACC_EXIT_DATA },
   { "kernels", PRAGMA_OACC_KERNELS },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 953c4e3..c6a2981 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -30,6 +30,7 @@ enum pragma_kind {
   PRAGMA_OACC_ATOMIC,
   PRAGMA_OACC_CACHE,
   PRAGMA_OACC_DATA,
+  PRAGMA_OACC_DECLARE,
   PRAGMA_OACC_ENTER_DATA,
   PRAGMA_OACC_EXIT_DATA,
   PRAGMA_OACC_KERNELS,
@@ -151,6 +152,7 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_CREATE,
   PRAGMA_OACC_CLAUSE_DELETE,
   PRAGMA_OACC_CLAUSE_DEVICEPTR,
+  PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT,
   PRAGMA_OACC_CLAUSE_GANG,
   PRAGMA_OACC_CLAUSE_HOST,
   PRAGMA_OACC_CLAUSE_INDEPENDENT,
@@ -175,7 +177,8 @@ enum pragma_omp_clause {
   PRAGMA_OACC_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
   PRAGMA_OACC_CLAUSE_IF = PRAGMA_OMP_CLAUSE_IF,
   PRAGMA_OACC_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE,
-  PRAGMA_OACC_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION
+  PRAGMA_OACC_CLAUSE_REDUCTIO

Re: [OpenACC] declare directive

2015-11-11 Thread James Norris

Jakub,

The attached patch and ChangeLog reflect the updates from your
review: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg01317.html.

Highlights

The following issue was handled by Dominique d'Humières
in: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg01375.html

On 11/11/2015 02:32 AM, Jakub Jelinek wrote:

On Mon, Nov 09, 2015 at 05:11:44PM -0600, James Norris wrote:

>diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
>index 953c4e3..c6a2981 100644
>--- a/gcc/c-family/c-pragma.h
>+++ b/gcc/c-family/c-pragma.h
>@@ -30,6 +30,7 @@ enum pragma_kind {
>PRAGMA_OACC_ATOMIC,
>PRAGMA_OACC_CACHE,
>PRAGMA_OACC_DATA,
>+  PRAGMA_OACC_DECLARE,
>PRAGMA_OACC_ENTER_DATA,
>PRAGMA_OACC_EXIT_DATA,
>PRAGMA_OACC_KERNELS,

This change will make PR68271 even worse, so would be really nice to
get that fixed first.


With the addition of: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg01372.html,
additional conditions were added to the following as you called
out in your review of: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00703.html.


On 11/06/2015 01:03 PM, Jakub Jelinek wrote:
>> @@ -5841,6 +5863,8 @@ omp_default_clause (struct gimplify_omp_ctx *ctx, tree 
decl,

>> flags |= GOVD_FIRSTPRIVATE;
>> break;
>>   case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
>> +  if (is_global_var (decl) && device_resident_p (decl))
>> +  flags |= GOVD_MAP_TO_ONLY | GOVD_MAP;
>
> I don't think you want to do this except for (selected or all?)
> OpenACC contexts.  Say, I don't see why one couldn't e.g. try to mix
> OpenMP host parallelization or tasking with OpenACC offloading,
> and that affecting in weird way OpenMP semantics.
>

With the addition of routine directive support, additional run-time tests
were added.

OK?

Thanks,
Jim
2015-XX-XX  James Norris  
Joseph Myers  

gcc/c-family/
* c-pragma.c (oacc_pragmas): Add entry for declare directive. 
* c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_DECLARE.
(enum pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT and
PRAGMA_OACC_CLAUSE_LINK.

gcc/c/
* c-parser.c (c_parser_pragma): Handle PRAGMA_OACC_DECLARE.
(c_parser_omp_clause_name): Handle 'device_resident' clause.
(c_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(c_parser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OACC_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(c_parser_oacc_declare): New function.

gcc/cp/
* parser.c (cp_parser_omp_clause_name): Handle 'device_resident'
clause.
(cp_parser_oacc_data_clause): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(cp_paser_oacc_all_clauses): Handle PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT
and PRAGMA_OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSE_MASK): New definition.
(cp_parser_oacc_declare): New function.
(cp_parser_pragma): Handle PRAGMA_OACC_DECLARE.
* pt.c (tsubst_expr): Handle OACC_DECLARE.

gcc/
* gimple-pretty-print.c (dump_gimple_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE. 
* gimple.h (enum gf_mask): Add GF_OMP_TARGET_KIND_OACC_DECLARE.
(is_gomple_omp_oacc): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* gimplify.c (oacc_declare_returns): New.
(gimplify_bind_expr): Prepend 'exit' stmt to cleanup.
(device_resident_p): New function.
(omp_default_clause): Handle device_resident clause.
(gimplify_oacc_declare_1, gimplify_oacc_declare): New functions.
(gimplify_expr): Handle OACC_DECLARE.
* omp-builtins.def (BUILT_IN_GOACC_DECLARE): New builtin.
* omp-low.c (expand_omp_target): Handle
GF_OMP_TARGET_KIND_OACC_DECLARE and BUILTIN_GOACC_DECLARE.
(build_omp_regions_1): Handlde GF_OMP_TARGET_KIND_OACC_DECLARE.
(lower_omp_target): Handle GF_OMP_TARGET_KIND_OACC_DECLARE,
GOMP_MAP_DEVICE_RESIDENT and GOMP_MAP_LINK.
(make_gimple_omp_edges): Handle GF_OMP_TARGET_KIND_OACC_DECLARE.
* tree-pretty-print.c (dump_omp_clause): Handle GOMP_MAP_LINK and
GOMP_MAP_DEVICE_RESIDENT.

gcc/testsuite
* c-c++-common/goacc/declare-1.c: New test.
* c-c++-common/goacc/declare-2.c: Likewise.

include/
* gomp-constants.h (enum gomp_map_kind): Add GOMP_MAP_DEVICE_RESIDENT
and GOMP_MAP_LINK.

libgomp/

* libgomp.map (GOACC_2.0.1): Export GOACC_declare.
* oacc-parallel.c (GOACC_declare): New function.
* testsuite/libgomp.oacc-c-c++-common/declare-1.c: New test.
* testsuite/libgomp.oacc-c-c++-common/declare-2.c: Likewise.
* testsuite/libgomp.oacc-c

Re: [OpenACC] declare directive

2015-11-12 Thread James Norris

Jakub

On 11/12/2015 03:09 AM, Jakub Jelinek wrote:

On Wed, Nov 11, 2015 at 07:07:58PM -0600, James Norris wrote:

+ oacc_declare_returns->remove (t);
+
+ if (oacc_declare_returns->elements () == 0)
+   {
+ delete oacc_declare_returns;
+ oacc_declare_returns = NULL;
+   }


Something for incremental patch:
1) might be nice to have some assertion that at the end of gimplify_body
or so oacc_declare_returns is NULL
2) what happens if you refer to automatic variables of other functions
(C or Fortran nested functions, maybe C++ lambdas); shall those be
unmapped at the end of the (nested) function's body?



Ok. Thanks! Will put on my TODO list.


@@ -5858,6 +5910,10 @@ omp_default_clause (struct gimplify_omp_ctx *ctx, tree 
decl,
flags |= GOVD_FIRSTPRIVATE;
break;
  case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
+  if (is_global_var (decl)
+ && ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)


Please put this condition as cheapest first.  I'd also surround
it into (), just to make it clear that the bitwise & is intentional.
Perhaps () != 0.


+ && device_resident_p (decl))
+   flags |= GOVD_MAP_TO_ONLY | GOVD_MAP;



+ case GOMP_MAP_FROM:
+   kinds[i] = GOMP_MAP_FORCE_FROM;
+   GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+  &kinds[i], 0, 0);


Wrong indentation.



Fixed.


Ok with those two changes and please think about the incremental stuff.


Again, thanks for taking the time for the review.

Jim



[PATCH] Fix unused variable.

2015-11-12 Thread James Norris

Hi,

As a result of an unused variable from my patch
of today, it broke bootstrap. Dominique kindly
pointed this out. Thank you.

Committed to trunk as obvious.

Jim

Index: gcc/cp/ChangeLog
===
--- gcc/cp/ChangeLog	(revision 230275)
+++ gcc/cp/ChangeLog	(working copy)
@@ -1,4 +1,8 @@
 2015-11-12  James Norris  
+
+	* parser.c (cp_parser_oacc_declare): Remove unused.
+
+2015-11-12  James Norris  
 	Joseph Myers  
 
 	* parser.c (cp_parser_omp_clause_name): Handle 'device_resident'
Index: gcc/cp/parser.c
===
--- gcc/cp/parser.c	(revision 230275)
+++ gcc/cp/parser.c	(working copy)
@@ -34562,7 +34562,7 @@
 static tree
 cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
 {
-  tree clauses, stmt, t;
+  tree clauses, stmt;
   bool error = false;
 
   clauses = cp_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,


Re: OpenACC declare directive updates

2015-11-19 Thread James Norris

Jakub,

Here's the updated version of the Fortran changes. More test
cases have been added as well as the issues that Cesar
pointed on in error checking have been addressed (Thanks).
I've also addressed the issue, described below, in dealing
with declare directives when found within a BLOCK construct.

On 11/06/2015 01:49 PM, Jakub Jelinek wrote:

On Fri, Nov 06, 2015 at 01:45:09PM -0600, James Norris wrote:

Okay, I'll fix this.

After fixing, OK to commit?

Thank you for taking the time for the review.


Well, isn't this patch really dependent on the other one?

Also, wonder about BLOCK stmt in Fortran, that can give you variables that
don't live through the whole function, but only a portion of it even in
Fortran.




On 11/18/2015 02:09 PM, Cesar Philippidis wrote:
> On 11/08/2015 08:53 PM, James Norris wrote:
>
>
> What block stmt? The most recent version of Fortran OpenACC 2.0a
> supports is 2003. The block construct is a 2008 feature. I don't think
> that's applicable to this version. Jim, maybe you should add an error
> message for variables defined in blocks.
>
> Thinking about this some more, I wonder if we should emit an error if
> any acc constructs are used inside blocks? That's probably overly
> pessimistic though.

Thanks!
Jim

2015-XX-XX  James Norris  
Cesar Philippidis  

gcc/fortran/
* dump-parse-tree.c (show_namespace): Handle declares.
* gfortran.h (struct symbol_attribute): New fields.
(enum gfc_omp_map_map): Add OMP_MAP_DEVICE_RESIDENT and OMP_MAP_LINK.
(OMP_LIST_LINK): New enum.
(struct gfc_oacc_declare): New structure.
(gfc_get_oacc_declare): New definition.
(struct gfc_namespace): Change type.
(enum gfc_exec_op): Add EXEC_OACC_DECLARE.
(struct gfc_code): New field.
* module.c (enum ab_attribute): Add AB_OACC_DECLARE_CREATE,
AB_OACC_DECLARE_COPYIN, AB_OACC_DECLARE_DEVICEPTR,
AB_OACC_DECLARE_DEVICE_RESIDENT, AB_OACC_DECLARE_LINK
(attr_bits): Add new initializers.
(mio_symbol_attribute): Handle new atributes.
* openmp.c (gfc_free_oacc_declare_clauses): New function.
(gfc_match_oacc_clause_link: Likewise.
(OMP_CLAUSE_LINK): New definition.
(gfc_match_omp_clauses): Handle OMP_CLAUSE_LINK.
(OACC_DECLARE_CLAUSES): Add OMP_CLAUSE_LINK
(gfc_match_oacc_declare): Add checking and module handling.
(gfc_resolve_oacc_declare): Reimplement.
* parse.c (case_decl): Add ST_OACC_DECLARE.
(parse_spec): Remove handling.
(parse_progunit): Remove handling.
* parse.h (struct gfc_state_data): Change type.
* resolve.c (gfc_resolve_blocks): Handle EXEC_OACC_DECLARE.
* st.c (gfc_free_statement): Handle EXEC_OACC_DECLARE.
* symbol.c (check_conflict): Add conflict checks.
(gfc_add_oacc_declare_create, gfc_add_oacc_declare_copyin, 
gfc_add_oacc_declare_deviceptr, gfc_add_oacc_declare_device_resident):
New functions.
(gfc_copy_attr): Handle new symbols.
* trans-decl.c (add_clause, find_module_oacc_declare_clauses,
finish_oacc_declare): New functions.
(gfc_generate_function_code): Replace with call.
* trans-openmp.c (gfc_trans_oacc_declare): Reimplement.
(gfc_trans_oacc_directive): Handle EXEC_OACC_DECLARE.
* trans-stmt.c (gfc_trans_block_construct): Replace with call.
* trans-stmt.h (gfc_trans_oacc_declare): Remove argument.
* trans.c (trans_code): Handle EXEC_OACC_DECLARE.

gcc/testsuite
* gfortran.dg/goacc/declare-1.f95: Update test.
* gfortran.dg/goacc/declare-2.f95: New test.

libgomp/
* testsuite/libgomp.oacc-fortran/declare-1.f90: New test.
* testsuite/libgomp.oacc-fortran/declare-2.f90: Likewise.
* testsuite/libgomp.oacc-fortran/declare-3.f90: Likewise.
* testsuite/libgomp.oacc-fortran/declare-4.f90: Likewise.
* testsuite/libgomp.oacc-fortran/declare-5.f90: Likewise.
* testsuite/libgomp.oacc-fortran/declare-5.f90: Likewise.
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 83ecbaa..48476af 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -2570,12 +2570,16 @@ show_namespace (gfc_namespace *ns)
   for (eq = ns->equiv; eq; eq = eq->next)
 show_equiv (eq);
 
-  if (ns->oacc_declare_clauses)
+  if (ns->oacc_declare)
 {
+  struct gfc_oacc_declare *decl;
   /* Dump !$ACC DECLARE clauses.  */
-  show_indent ();
-  fprintf (dumpfile, "!$ACC DECLARE");
-  show_omp_clauses (ns->oacc_declare_clauses);
+  for (decl = ns->oacc_declare; decl; decl = decl->next)
+	{
+	  show_indent ();
+	  fprintf (dumpfile, "!$ACC DECLARE");
+	  show_omp_clauses (decl->clauses);
+	}
 }
 
   fputc ('\n

Re: [PATCH] fortran/openmp.c -- Fix bootstrap

2015-11-22 Thread James Norris

Hi,

Patch committed to trunk as obvious. Thanks to Dominique and Steve.

Jim


On 11/22/2015 12:59 PM, Steve Kargl wrote:

I have no idea if this is actually correct, but it restores bootstrap.
OK to commit?

2015-11-22  Steven G. Kargl  

* openmp.c (match_oacc_clause_gang): Fix bootstrap.


Index: openmp.c
===
--- openmp.c(revision 230723)
+++ openmp.c(working copy)
@@ -415,7 +415,8 @@ match_oacc_clause_gang (gfc_omp_clauses
  static match
  gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
  {
-  gfc_omp_namelist *head, *tail, *p;
+  gfc_omp_namelist *head = NULL;
+  gfc_omp_namelist *tail, *p;
locus old_loc;
char n[GFC_MAX_SYMBOL_LEN+1];
gfc_symbol *sym;
@@ -4821,7 +4822,7 @@ gfc_resolve_oacc_declare (gfc_namespace

for (oc = ns->oacc_declare; oc; oc = oc->next)
  {
-  for (list = 0; list <= OMP_LIST_NUM; list++)
+  for (list = 0; list < OMP_LIST_NUM; list++)
for (n = oc->clauses->lists[list]; n; n = n->next)
  {
n->sym->mark = 0;
@@ -4846,7 +4847,7 @@ gfc_resolve_oacc_declare (gfc_namespace

for (oc = ns->oacc_declare; oc; oc = oc->next)
  {
-  for (list = 0; list <= OMP_LIST_NUM; list++)
+  for (list = 0; list < OMP_LIST_NUM; list++)
for (n = oc->clauses->lists[list]; n; n = n->next)
  {
if (n->sym->mark)
@@ -4862,7 +4863,7 @@ gfc_resolve_oacc_declare (gfc_namespace

for (oc = ns->oacc_declare; oc; oc = oc->next)
  {
-  for (list = 0; list <= OMP_LIST_NUM; list++)
+  for (list = 0; list < OMP_LIST_NUM; list++)
for (n = oc->clauses->lists[list]; n; n = n->next)
  n->sym->mark = 0;
  }





[gomp4] Fix Fortran deviceptr

2015-12-06 Thread James Norris

Hi,

This patch fixes a some runtime issues when dealing with
the deviceptr clause in Fortran. There were some corner
cases that were not being dealt with correctly, and the
patch resolves these. Also a new set of test cases has
been added.

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

Jim
diff --git a/libgomp/ChangeLog.gomp b/libgomp/ChangeLog.gomp
index a2f1c31..791aa4c 100644
--- a/libgomp/ChangeLog.gomp
+++ b/libgomp/ChangeLog.gomp
@@ -1,3 +1,10 @@
+2015-12-06  James Norris  
+
+	* oacc-parallel.c (GOACC_parallel_keyed, GOACC_data_start):
+	Handle Fortran deviceptr clause combination.
+	* testsuite/libgomp.oacc-fortran/deviceptr-1.f90: New test.
+	* testsuite/libgomp.oacc-fortran/declare-1.f90: Remove erroneous test.
+
 2015-12-05  Chung-Lin Tang  
 
 	* oacc-plugin.h (GOMP_PLUGIN_async_unmap_vars): Add int parameter.
diff --git a/libgomp/oacc-parallel.c b/libgomp/oacc-parallel.c
index a4b2c01..a606152 100644
--- a/libgomp/oacc-parallel.c
+++ b/libgomp/oacc-parallel.c
@@ -99,18 +99,37 @@ GOACC_parallel_keyed (int device, void (*fn) (void *),
   thr = goacc_thread ();
   acc_dev = thr->dev;
 
-  for (i = 0; i < (signed)(mapnum - 1); i++)
+  for (i = 0; i < mapnum; i++)
 {
   unsigned short kind1 = kinds[i] & 0xff;
-  unsigned short kind2 = kinds[i+1] & 0xff;
 
   /* Handle Fortran deviceptr clause.  */
-  if ((kind1 == GOMP_MAP_FORCE_DEVICEPTR && kind2 == GOMP_MAP_POINTER)
-	   && (sizes[i + 1] == 0)
-	   && (hostaddrs[i] == *(void **)hostaddrs[i + 1]))
+  if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
 	{
-	  kinds[i+1] = kinds[i];
-	  sizes[i+1] = sizeof (void *);
+	  unsigned short kind2;
+
+	  if (i < (signed)mapnum - 1)
+	kind2 = kinds[i + 1] & 0xff;
+	  else
+	kind2 = 0x;
+
+	  if (sizes[i] == sizeof (void *))
+	continue;
+
+	  /* At this point, we're dealing with a Fortran deviceptr.
+	 If the next element is not what we're expecting, then
+	 this is an instance of where the deviceptr variable was
+	 not used within the region and the pointer was removed
+	 by the gimplifier.  */
+	  if (kind2 == GOMP_MAP_POINTER
+	  && sizes[i + 1] == 0
+	  && hostaddrs[i] == *(void **)hostaddrs[i + 1])
+	{
+	  kinds[i+1] = kinds[i];
+	  sizes[i+1] = sizeof (void *);
+	}
+
+	  /* Invalidate the entry.  */
 	  hostaddrs[i] = NULL;
 	}
 }
@@ -254,18 +273,38 @@ GOACC_data_start (int device, size_t mapnum,
   struct goacc_thread *thr = goacc_thread ();
   struct gomp_device_descr *acc_dev = thr->dev;
 
-  for (i = 0; i < (signed)(mapnum - 1); i++)
+  for (i = 0; i < mapnum; i++)
 {
   unsigned short kind1 = kinds[i] & 0xff;
-  unsigned short kind2 = kinds[i+1] & 0xff;
 
   /* Handle Fortran deviceptr clause.  */
-  if ((kind1 == GOMP_MAP_FORCE_DEVICEPTR && kind2 == GOMP_MAP_POINTER)
-	   && (sizes[i + 1] == 0)
-	   && (hostaddrs[i] == *(void **)hostaddrs[i + 1]))
+  if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
 	{
-	  kinds[i+1] = kinds[i];
-	  sizes[i+1] = sizeof (void *);
+	  unsigned short kind2;
+
+	  if (i < (signed)mapnum - 1)
+	kind2 = kinds[i + 1] & 0xff;
+	  else
+	kind2 = 0x;
+
+	  /* If the size is right, skip it.  */
+	  if (sizes[i] == sizeof (void *))
+	continue;
+
+	  /* At this point, we're dealing with a Fortran deviceptr.
+	 If the next element is not what we're expecting, then
+	 this is an instance of where the deviceptr variable was
+	 not used within the region and the pointer was removed
+	 by the gimplifier.  */
+	  if (kind2 == GOMP_MAP_POINTER
+	  && sizes[i + 1] == 0
+	  && hostaddrs[i] == *(void **)hostaddrs[i + 1])
+	{
+	  kinds[i+1] = kinds[i];
+	  sizes[i+1] = sizeof (void *);
+	}
+
+	  /* Invalidate the entry.  */
 	  hostaddrs[i] = NULL;
 	}
 }
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90
index 430cd24..e781878 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90
@@ -1,6 +1,4 @@
 ! { dg-do run  { target openacc_nvidia_accel_selected } }
-! libgomp: cuStreamSynchronize error: an illegal memory access was encountered
-! { dg-xfail-run-if "TODO" { *-*-* } }
 
 module vars
   implicit none
@@ -8,24 +6,6 @@ module vars
   !$acc declare create (z)
 end module vars
 
-subroutine subr6 (a, d)
-  implicit none
-  integer, parameter :: N = 8
-  integer :: i
-  integer :: a(N)
-  !$acc declare deviceptr (a)
-  integer :: d(N)
-
-  i = 0
-
-  !$acc parallel copy (d)
-do i = 1, N
-  d(i) = a(i) + a(i)
-end do
-  !$acc end parallel
-
-end subroutine
-
 subroutine subr5 (a, b, c, d)
   implicit none
   integer, parameter :: N = 8
@@ -203,15 +183,6 @@ subroutine subr0 (a, b, c, d)
 if (d(i) .ne. 13) call abort
   end do
 

[PATCH] Fix Fortran deviceptr clause.

2015-12-06 Thread James Norris

Hi,

Attached is a patch that fixes some runtime issues dealing
with the deviceptr clause in Fortran. There were some
corner cases that were not being dealt with correctly,
e.g., specifying the deviceptr clause and not using
the variable specified by the deviceptr clause within
the associated region. Also a new set of test cases
has been added.

Regtested on x86_64-pc-linux-gnu

Ok for trunk?

Thanks!
Jim
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index cde0b5c..df26e7c 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,10 @@
+2015-12-XX  James Norris  
+
+	* oacc-parallel.c (GOACC_parallel_keyed, GOACC_data_start):
+	Handle Fortran deviceptr clause combination.
+	* testsuite/libgomp.oacc-fortran/deviceptr-1.f90: New test.
+	* testsuite/libgomp.oacc-fortran/declare-1.f90: Remove erroneous test.
+
 2015-12-02  Thomas Schwinge  
 
 	* testsuite/libgomp.oacc-c-c++-common/host_data-2.c: Restrict to
diff --git a/libgomp/oacc-parallel.c b/libgomp/oacc-parallel.c
index db7cab3..bf8cbfe 100644
--- a/libgomp/oacc-parallel.c
+++ b/libgomp/oacc-parallel.c
@@ -88,6 +88,42 @@ GOACC_parallel_keyed (int device, void (*fn) (void *),
   thr = goacc_thread ();
   acc_dev = thr->dev;
 
+  for (i = 0; i < mapnum; i++)
+{
+  unsigned short kind1 = kinds[i] & 0xff;
+
+  /* Handle Fortran deviceptr clause.  */
+  if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
+	{
+	  unsigned short kind2;
+
+	  if (i < (signed)mapnum - 1)
+	kind2 = kinds[i + 1] & 0xff;
+	  else
+	kind2 = 0x;
+
+	  /* If the size is right, skip it.  */
+	  if (sizes[i] == sizeof (void *))
+	continue;
+
+	  /* At this point, we're dealing with a Fortran deviceptr.
+	 If the next element is not what we're expecting, then
+	 this is an instance of where the deviceptr variable was
+	 not used within the region and the pointer was removed
+	 by the gimplifier.  */
+	  if (kind2 == GOMP_MAP_POINTER
+	  && sizes[i + 1] == 0
+	  && hostaddrs[i] == *(void **)hostaddrs[i + 1])
+	{
+	  kinds[i+1] = kinds[i];
+	  sizes[i+1] = sizeof (void *);
+	}
+
+	  /* Invalidate the entry.  */
+	  hostaddrs[i] = NULL;
+	}
+}
+
   /* Host fallback if "if" clause is false or if the current device is set to
  the host.  */
   if (host_fallback)
@@ -172,8 +208,13 @@ GOACC_parallel_keyed (int device, void (*fn) (void *),
 
   devaddrs = gomp_alloca (sizeof (void *) * mapnum);
   for (i = 0; i < mapnum; i++)
-devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start
-			+ tgt->list[i].key->tgt_offset);
+{
+  if (tgt->list[i].key != NULL)
+	devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start
++ tgt->list[i].key->tgt_offset);
+  else
+	devaddrs[i] = NULL;
+}
 
   acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs,
 			  async, dims, tgt);
@@ -210,6 +251,7 @@ GOACC_data_start (int device, size_t mapnum,
 {
   bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
   struct target_mem_desc *tgt;
+  int i;
 
 #ifdef HAVE_INTTYPES_H
   gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
@@ -224,6 +266,42 @@ GOACC_data_start (int device, size_t mapnum,
   struct goacc_thread *thr = goacc_thread ();
   struct gomp_device_descr *acc_dev = thr->dev;
 
+  for (i = 0; i < mapnum; i++)
+{
+  unsigned short kind1 = kinds[i] & 0xff;
+
+  /* Handle Fortran deviceptr clause.  */
+  if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
+	{
+	  unsigned short kind2;
+
+	  if (i < (signed)mapnum - 1)
+	kind2 = kinds[i + 1] & 0xff;
+	  else
+	kind2 = 0x;
+
+	  /* If the size is right, skip it.  */
+	  if (sizes[i] == sizeof (void *))
+	continue;
+
+	  /* At this point, we're dealing with a Fortran deviceptr.
+	 If the next element is not what we're expecting, then
+	 this is an instance of where the deviceptr variable was
+	 not used within the region and the pointer was removed
+	 by the gimplifier.  */
+	  if (kind2 == GOMP_MAP_POINTER
+	  && sizes[i + 1] == 0
+	  && hostaddrs[i] == *(void **)hostaddrs[i + 1])
+	{
+	  kinds[i+1] = kinds[i];
+	  sizes[i+1] = sizeof (void *);
+	}
+
+	  /* Invalidate the entry.  */
+	  hostaddrs[i] = NULL;
+	}
+}
+
   /* Host fallback or 'do nothing'.  */
   if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
   || host_fallback)
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90
index f717d1b..151f409 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/declare-1.f90
@@ -6,24 +6,6 @@ module vars
   !$acc declare create (z)
 end module vars
 
-subroutine subr6 (a, d)
-  implicit none
-  integer, parameter :: N = 8
-  integer :: i
-  integer :: a(N)
-

Re: [gomp4] Fix Fortran deviceptr

2015-12-08 Thread James Norris

Cesar,

On 12/07/2015 09:55 AM, Cesar Philippidis wrote:


[snip snip]
Two observations:

  1. Why is deviceptr so special that gomp_map_vars can't handle it
 directly?


Recall that the deviceptr clause in Fortran presents as two
mappings: FORCE_DEVICEPTR and POINTER. The former
has the device address in hostaddr, while the latter has the
host address of the pointer in hostaddr. The new code
detects a properly formed pair and if found, proceeds to
turn the latter into the FORCE_DEVICEPTR map, while the
former is effectively discarded by setting hostaddr to NULL.

This behavior is specific to OpenACC, so I decided put it where
I did. Could it be put into gomp_map_vars? Probably. Would it
be messy? Probably. But what may be a better solution would
be to use the functionality that handles the use_device_ptr
clause in OpenMP4.1 and eliminate FORCE_DEVICEPTR from
gomp_map_var. Have to look into that.




  2. It appears that deviceptr code in GOACC_parallel_keyed is mostly
 identical to GOACC_data_start. Can you put that duplicate code into
 a function? That would be easier to maintain in the long run.



Fixed.

Thanks,
Jim




[gomp4] Add Fortran runtime test

2015-12-08 Thread James Norris

Hi,

Add test to exercise the kernels construct with the
pcreate clause.

Committed to gomp-4_0-branch.

Jim

Index: libgomp/ChangeLog.gomp
===
--- libgomp/ChangeLog.gomp	(revision 231430)
+++ libgomp/ChangeLog.gomp	(working copy)
@@ -1,3 +1,7 @@
+2015-12-08  James Norris  
+
+	* testsuite/libgomp.oacc-fortran/kernels-map-1.f90: Add new test.
+
 2015-12-08  Thomas Schwinge  
 	James Norris  
 
Index: libgomp/testsuite/libgomp.oacc-fortran/kernels-map-1.f90
===
--- libgomp/testsuite/libgomp.oacc-fortran/kernels-map-1.f90	(revision 231430)
+++ libgomp/testsuite/libgomp.oacc-fortran/kernels-map-1.f90	(working copy)
@@ -1,9 +1,9 @@
-! Test the copy, copyin, copyout, pcopy, pcopyin, and pcopyout
+! Test the copy, copyin, copyout, pcopy, pcopyin, pcopyout, and pcreate
 ! clauses on kernels constructs.
 
 program map
   integer, parameter :: n = 20, c = 10
-  integer:: i, a(n), b(n)
+  integer:: i, a(n), b(n), d(n)
 
   a(:) = 0
   b(:) = 0
@@ -88,6 +88,20 @@
   !$acc end kernels
 
   call check (a, b, n)
+
+  ! PRESENT_OR_CREATE
+
+  a(:) = 0
+
+  !$acc kernels pcopyout (a) pcreate (d)
+  !$acc loop
+  do i = 1, n
+ d(i) = i
+ a(i) = d(i)
+  end do
+  !$acc end kernels
+
+  call check (a, b, n)
 end program map
 
 subroutine check (a, b, n)


Re: [gomp4] Fix Fortran deviceptr

2015-12-09 Thread James Norris

Cesar,

On 12/08/2015 11:10 AM, Cesar Philippidis wrote:

On 12/08/2015 08:22 AM, James Norris wrote:


   2. It appears that deviceptr code in GOACC_parallel_keyed is mostly
  identical to GOACC_data_start. Can you put that duplicate code into
  a function? That would be easier to maintain in the long run.



Fixed.


Where? I don't see a patch.


Opp... Now attached.




Since you're working on fortran, can you take a look at how
gfc_match_omp_clauses is handling OMP_CLAUSE_DEVICEPTR. It seems overly
confusing to me. Could it be done in a similar way as OMP_CLAUSE_COPYIN,
i.e., using gfc_match_omp_map_clause?



Confusion removed and replaced with code similar to how
the other clauses are handled.

Patch to be committed after testing completes.

Thanks!
Jim
diff --git a/gcc/fortran/ChangeLog.gomp b/gcc/fortran/ChangeLog.gomp
index 00e5746..d05326d 100644
--- a/gcc/fortran/ChangeLog.gomp
+++ b/gcc/fortran/ChangeLog.gomp
@@ -1,3 +1,8 @@
+2015-12-09  James Norris  
+
+	* openmp.c (gfc_match_omp_clauses): Re-write handling of the
+	deviceptr clause.
+
 2015-12-08  Thomas Schwinge  
 
 	* gfortran.h (symbol_attribute): Add oacc_function_nohost member.
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index b59528be..78d2e1e 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -818,19 +818,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, uint64_t mask,
    OMP_MAP_ALLOC))
 	continue;
   if ((mask & OMP_CLAUSE_DEVICEPTR)
-	  && gfc_match ("deviceptr ( ") == MATCH_YES)
-	{
-	  gfc_omp_namelist **list = &c->lists[OMP_LIST_MAP];
-	  gfc_omp_namelist **head = NULL;
-	  if (gfc_match_omp_variable_list ("", list, true, NULL, &head, false)
-	  == MATCH_YES)
-	{
-	  gfc_omp_namelist *n;
-	  for (n = *head; n; n = n->next)
-		n->u.map_op = OMP_MAP_FORCE_DEVICEPTR;
-	  continue;
-	}
-	}
+	  && gfc_match ("deviceptr ( ") == MATCH_YES
+	  && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+   OMP_MAP_FORCE_DEVICEPTR))
+	continue;
   if ((mask & OMP_CLAUSE_BIND) && c->routine_bind == NULL
 	  && gfc_match ("bind ( %s )", &c->routine_bind) == MATCH_YES)
 	{
diff --git a/libgomp/ChangeLog.gomp b/libgomp/ChangeLog.gomp
index d88cb94..ec133a7 100644
--- a/libgomp/ChangeLog.gomp
+++ b/libgomp/ChangeLog.gomp
@@ -1,3 +1,11 @@
+2015-12-09  James Norris  
+
+	* oacc-parallel.c (handle_ftn_pointers): New function.
+	(GOACC_parallel_keyed, GOACC_data_start): Factor out Fortran pointer
+	handling.
+	* testsuite/libgomp.oacc-fortran/declare-1.f90: Add comment.
+	* testsuite/libgomp.oacc-fortran/deviceptr-1.f90: Fix comment.
+
 2015-12-08  James Norris  
 
 	* testsuite/libgomp.oacc-fortran/kernels-map-1.f90: Add new test.
diff --git a/libgomp/oacc-parallel.c b/libgomp/oacc-parallel.c
index a606152..f68db78 100644
--- a/libgomp/oacc-parallel.c
+++ b/libgomp/oacc-parallel.c
@@ -57,6 +57,51 @@ find_pointer (int pos, size_t mapnum, unsigned short *kinds)
   return 0;
 }
 
+/* Handle the mapping pair that are presented when a
+   deviceptr clause is used with Fortran.  */
+
+static void
+handle_ftn_pointers (size_t mapnum, void **hostaddrs, size_t *sizes,
+		 unsigned short *kinds)
+{
+  int i;
+
+  for (i = 0; i < mapnum; i++)
+{
+  unsigned short kind1 = kinds[i] & 0xff;
+
+  /* Handle Fortran deviceptr clause.  */
+  if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
+	{
+	  unsigned short kind2;
+
+	  if (i < (signed)mapnum - 1)
+	kind2 = kinds[i + 1] & 0xff;
+	  else
+	kind2 = 0x;
+
+	  if (sizes[i] == sizeof (void *))
+	continue;
+
+	  /* At this point, we're dealing with a Fortran deviceptr.
+	 If the next element is not what we're expecting, then
+	 this is an instance of where the deviceptr variable was
+	 not used within the region and the pointer was removed
+	 by the gimplifier.  */
+	  if (kind2 == GOMP_MAP_POINTER
+	  && sizes[i + 1] == 0
+	  && hostaddrs[i] == *(void **)hostaddrs[i + 1])
+	{
+	  kinds[i+1] = kinds[i];
+	  sizes[i+1] = sizeof (void *);
+	}
+
+	  /* Invalidate the entry.  */
+	  hostaddrs[i] = NULL;
+	}
+}
+}
+
 static void goacc_wait (int async, int num_waits, va_list *ap);
 
 
@@ -99,40 +144,7 @@ GOACC_parallel_keyed (int device, void (*fn) (void *),
   thr = goacc_thread ();
   acc_dev = thr->dev;
 
-  for (i = 0; i < mapnum; i++)
-{
-  unsigned short kind1 = kinds[i] & 0xff;
-
-  /* Handle Fortran deviceptr clause.  */
-  if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
-	{
-	  unsigned short kind2;
-
-	  if (i < (signed)mapnum - 1)
-	kind2 = kinds[i + 1] & 0xff;
-	  else
-	kind2 = 0x;
-
-	  if (sizes[i] == sizeof (void *))
-	continue;
-
-	  /* At this point, we're dealing with a Fortran deviceptr.
-	 If the next element is not w

[gomp4] OpenACC / C++

2014-10-15 Thread James Norris

Hi!

This patch adds OpenACC support to C++ in the gomp4 branch.

OK to apply?

Thanks!

Jim

ChangeLog entries...

= gcc/ChangeLog.gomp

2014-10-15  James Norris  

* builtin-types.def (BT_FN_VOID_INT_PTR_INT): New type.
* oacc-builtins.def (BUILT_IN_GOACC_WAIT): New builtin.

= gcc/c-family/ChangeLog.gomp

2014-10-15  James Norris  

* c-common.h (c_finish_oacc_wait): New prototype.
* c-pragma.h (enum pragma_kind): Add PRAGMA_OACC_CACHE,
PRAGMA_OACC_WAIT.
(enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_ASYNC,
PRAGMA_OMP_CLAUSE_WAIT.
* c-omp.c (c_finish_oacc_wait): New function.

 = gcc/cp/ChangeLog.gomp

2014-10-15  James Norris  
Cesar Philippidis  
Ilmir Usmanov  

* cp-tree.h (finish_oacc_data, finish_oacc_kernels, 
finish_oacc_parallel):
New prototypes.
* parser.c (cp_parser_omp_clause_name): Add parsing of OpenACC clauses.
(cp_parser_omp_var_list_no_open): Add handling of array specifier.
(cp_parser_oacc_data_clause, cp_parser_oacc_data_clause_deviceptr,
cp_parser_oacc_vector_length, cp_parser_oacc_wait_list,
cp_parser_oacc_clause_wait, cp_parser_omp_clause_num_gangs,
cp_parser_omp_clause_num_workers, cp_parser_oacc_clause_async,
cp_parser_oacc_all_clauses, cp_parser_oacc_cache, cp_parser_oacc_data,
cp_parser_oacc_kernels, cp_paser_oacc_loop, cp_parser_oacc_parallel,
cp_parser_oacc_update, cp_parser_oacc_wait ): New functions.
(OACC_DATA_CLAUSE_MASK, OACC_KERNELS_CLAUSE_MASK, OACC_LOOP_CLAUSE_MASK,
OACC_PARALLEL_CLAUSE_MASK, OACC_UPDATE_CLAUSE_MASK,
OACC_WAIT_CLAUSE_MASK): New macros.
(cp_parser_omp_construct): Add handling of OpenACC pragmas.
(cp_parser_pragma): Add handling of OpenACC pragmas.
* semantics.c (finish_omp_clauses): Handle OpenACC clauses.
(finish_oacc_data, finish_oacc_kernels, finish_oacc_parallel): New
functions.

= gcc/fortran/ChangeLog.gomp

2014-10-14  James Norris  

* types.def (BT_FN_VOID_INT_PTR_INT): New type.


diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 7c294af..094b3a8 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -358,6 +358,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_SIZE,
 		 BT_VOID, BT_PTR, BT_INT, BT_SIZE)
 DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_INT,
 		 BT_VOID, BT_PTR, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_INT_PTR_INT,
+		 BT_VOID, BT_INT, BT_PTR, BT_INT)
 DEF_FUNCTION_TYPE_3 (BT_FN_VOID_CONST_PTR_PTR_SIZE,
 		 BT_VOID, BT_CONST_PTR, BT_PTR, BT_SIZE)
 DEF_FUNCTION_TYPE_3 (BT_FN_INT_STRING_CONST_STRING_VALIST_ARG,
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 5ec79a0..a03b3ab 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1211,6 +1211,7 @@ extern void c_finish_omp_taskwait (location_t);
 extern void c_finish_omp_taskyield (location_t);
 extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
 			  tree, tree, tree);
+extern tree c_finish_oacc_wait (location_t, tree, tree);
 extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask,
  tree, tree *);
 extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree);
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 3c3fa44..f0298e5 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -29,8 +29,47 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-pragma.h"
 #include "gimple-expr.h"
 #include "langhooks.h"
+#include "omp-low.h"
 
 
+/* Complete a #pragma oacc wait construct.  LOC is the location of
+   the #pragma.  */
+
+tree
+c_finish_oacc_wait (location_t loc, tree parms, tree clauses)
+{
+  const int nparms = list_length (parms);
+  tree stmt, t;
+  vec *args;
+
+  vec_alloc (args, nparms + 2);
+  stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
+
+  if (find_omp_clause (clauses, OMP_CLAUSE_ASYNC))
+t = OMP_CLAUSE_ASYNC_EXPR (clauses);
+  else
+t = build_int_cst (integer_type_node, -2);  /* TODO: XXX FIX -2.  */
+
+  args->quick_push (t);
+  args->quick_push (build_int_cst (integer_type_node, nparms));
+
+  for (t = parms; t; t = TREE_CHAIN (t))
+{
+  if (TREE_CODE (OMP_CLAUSE_WAIT_EXPR (t)) == INTEGER_CST)
+	args->quick_push (build_int_cst (integer_type_node,
+			TREE_INT_CST_LOW (OMP_CLAUSE_WAIT_EXPR (t;
+  else
+	args->quick_push (OMP_CLAUSE_WAIT_EXPR (t));
+}
+
+  stmt = build_call_expr_loc_vec (loc, stmt, args);
+  add_stmt (stmt);
+
+  vec_free (args);
+
+  return stmt;
+}
+
 /* Complete a #pragma omp master construct.  STMT is the structured-block
that follows the pragma.  LOC is the l*/
 
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index d83a700..4722d51 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -27,11 +27,13 @

[gomp4] Wait directive with async and wait clauses.

2014-10-22 Thread James Norris

Hi!

This patch adds code to handle the OpenACC wait directive and
the wait and async clauses for the wait directive as well as the
other directives which support them.

OK for gomp4 branch?

Thanks!

Jim

ChangeLog

2014-10-22  James Norris  

* builtin-types.def (BT_FN_VOID_INT_INT_VAR,
BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR_INT_INT_INT_INT_INT_VAR,
BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR_INT_INT_VAR): Add.
(BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR_INT_INT_INT): Remove.
* c-family/c-common.c (enum c_builtin_type, c_define_builtins): Remove
unused FUNCTION_TYPE_10. Add new FUNCTION_TYPE_VAR_8 and
FUNCTION_TYPE_VAR_12.
* c-family/c-pragma.c (oacc_pragmas): Add entry for wait directive.
* c/c-parser.c (c_parser_omp_clause_name): Add handling of wait and
async clauses.
(c_parser_oacc_wait_list, c_parser_oacc_clause_async,
c_parser_oacc_clause_wait): New.
(c_parser_oacc_all_clauses): Handle async and wait clauses.
(OACC_KERNELS_CLAUSE_MASK, OACC_PARALLEL_CLAUSE_MASK,
OACC_UPDATE_CLAUSE_MASK): Add async and wait clauses.
(OACC_WAIT_CLAUSE_MASK): New.
(c_parser_oacc_wait): New.
(c_parser_omp_construct): Handle wait directive.
* c/c-typeck.c (c_finish_omp_clauses): Handle async and wait clauses.
* fortran/f95-lang.c (gfc_init_builtin_functions): Remove unused
FUNCTION_TYPE_10. Add new FUNCTION_TYPE_VAR_2, FUNCTION_TYPE_VAR_8,
and FUNCTION_TYPE_VAR_12.
* fortran/types.def (BT_FN_VOID_INT_INT_VAR,
BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR_INT_INT_INT_INT_INT_VAR,
BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR_INT_INT_VAR): Add.
(BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR_INT_INT_INT): Remove.
* lto/lto-lang.c (enum lto_builtin_type, lto_define_builtins): Remove
unsigned FUNCTION_TYPE_10. Add new FUNCTION_TYPE_VAR_8 and
FUNCTION_TYPE_VAR_12.
* oacc-builtins.def (BUILT_IN_GOACC_KERNELS BUILT_IN_GOACC_PARALLEL,
BUILT_IN_GOACC_UPDATE, BUILT_IN_GOACC_WAIT): Change type.
* omp-low.c (scan_sharing_clauses): Handle async and wait clauses.
(expand_oacc_offload): Lower kernel directive and async and wait
clauses.


diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 094b3a8..449e05f 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -518,10 +518,6 @@ DEF_FUNCTION_TYPE_8 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR,
 		 BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
 		 BT_BOOL, BT_UINT, BT_PTR)
 
-DEF_FUNCTION_TYPE_10 (BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR_INT_INT_INT,
-		  BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_PTR, BT_SIZE,
-		  BT_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT, BT_INT)
-
 DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
 DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT)
 DEF_FUNCTION_TYPE_VAR_0 (BT_FN_PTR_VAR, BT_PTR)
@@ -545,6 +541,8 @@ DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_INT_CONST_STRING_VAR,
 			 BT_INT, BT_INT, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_VAR_2 (BT_FN_PTR_CONST_PTR_SIZE_VAR, BT_PTR,
 			 BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_VOID_INT_INT_VAR, BT_VOID,
+			 BT_INT, BT_INT)
 
 DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_STRING_SIZE_CONST_STRING_VAR,
 			 BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING)
@@ -563,6 +561,14 @@ DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR,
 DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_INT_INT_INT_INT_INT_VAR,
 			 BT_INT, BT_INT, BT_INT, BT_INT, BT_INT, BT_INT)
 
+DEF_FUNCTION_TYPE_VAR_8 (BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR_INT_INT_VAR,
+			 BT_VOID, BT_INT, BT_PTR, BT_SIZE, BT_PTR, BT_PTR,
+			 BT_PTR, BT_INT, BT_INT)
+
+DEF_FUNCTION_TYPE_VAR_12 (BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR_INT_INT_INT_INT_INT_VAR,
+	 BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_PTR, BT_SIZE, BT_PTR, BT_PTR,
+	 BT_PTR, BT_INT, BT_INT, BT_INT, BT_INT, BT_INT)
+
 DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR)
 DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
 		 BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index f074bbd..c310802 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5140,8 +5140,6 @@ enum c_builtin_type
 			ARG6, ARG7) NAME,
 #define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
 			ARG6, ARG7, ARG8) NAME,
-#define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
-			 ARG6, ARG7, ARG8, ARG9, ARG10) NAME,
 #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
 #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
 #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
@@ -5149,6 +5147,11 @@ enum c_builtin_type
 #define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
 #define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
   NAME,
+#define DEF_FUNCTION_TYPE_VAR_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ARG6, ARG7, ARG8) NAME,
+#define DEF_FUNCTION_TYPE_VAR_12(NAME, RETURN, ARG1, ARG2

[gomp4] Fix combined directives.

2014-10-27 Thread James Norris

Hi!

This patch fixes an issue in handling combined directives. The
code now accepts clauses for both the loop directive and the
other directive, i.e., parallel or kernels.

OK for gomp4 branch?

Thanks!

Jim

ChangeLog

 2014-10-27  James Norris

 * c/c-parser.c (c_parser_oacc_loop, OACC_LOOP_CLAUSE_MASK): 
Relocate.

 (c_parser_oacc_kernels, c_parser_oacc_parallel): Fix combined
 directives.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 0480932..f0d7138 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11857,6 +11857,34 @@ c_parser_oacc_data (location_t loc, c_parser *parser)
 }
 
 /* OpenACC 2.0:
+   # pragma acc loop oacc-loop-clause[optseq] new-line
+ structured-block
+
+   LOC is the location of the #pragma token.
+*/
+
+#define OACC_LOOP_CLAUSE_MASK		\
+	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)		\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) )
+
+static tree
+c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name)
+{
+  tree stmt, clauses, block;
+
+  strcat (p_name, " loop");
+
+  clauses = c_parser_oacc_all_clauses (parser, OACC_LOOP_CLAUSE_MASK, p_name);
+
+  block = c_begin_compound_stmt (true);
+  stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL);
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+
+  return stmt;
+}
+
+/* OpenACC 2.0:
# pragma acc kernels oacc-kernels-clause[optseq] new-line
  structured-block
 
@@ -11881,60 +11909,32 @@ c_parser_oacc_data (location_t loc, c_parser *parser)
 static tree
 c_parser_oacc_kernels (location_t loc, c_parser *parser, char *p_name)
 {
-  tree stmt, clauses = NULL_TREE, block;
+  tree stmt, clauses, block;
+  omp_clause_mask mask;
+  bool is_combined = false;
 
   strcat (p_name, " kernels");
 
+  mask = OACC_KERNELS_CLAUSE_MASK;
   if (c_parser_next_token_is (parser, CPP_NAME))
 {
-  const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-  if (strcmp (p, "loop") == 0)
+  stmt = c_parser_peek_token (parser)->value;
+  if (!strcmp ("loop", IDENTIFIER_POINTER (stmt)))
 	{
+	  mask |= OACC_LOOP_CLAUSE_MASK;
+	  strcat (p_name, " loop");
 	  c_parser_consume_token (parser);
-	  block = c_begin_omp_parallel ();
-	  c_parser_oacc_loop (loc, parser, p_name);
-	  stmt = c_finish_oacc_kernels (loc, clauses, block);
-	  OACC_KERNELS_COMBINED (stmt) = 1;
-	  return stmt;
+	  is_combined = true;
 	}
 }
 
-  clauses =  c_parser_oacc_all_clauses (parser, OACC_KERNELS_CLAUSE_MASK,
-	p_name);
+  clauses =  c_parser_oacc_all_clauses (parser, mask, p_name);
 
   block = c_begin_omp_parallel ();
   add_stmt (c_parser_omp_structured_block (parser));
-
   stmt = c_finish_oacc_kernels (loc, clauses, block);
-
-  return stmt;
-}
-
-/* OpenACC 2.0:
-   # pragma acc loop oacc-loop-clause[optseq] new-line
- structured-block
-
-   LOC is the location of the #pragma token.
-*/
-
-#define OACC_LOOP_CLAUSE_MASK		\
-	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)		\
-	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) )
-
-static tree
-c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name)
-{
-  tree stmt, clauses, block;
-
-  strcat (p_name, " loop");
-
-  clauses = c_parser_oacc_all_clauses (parser, OACC_LOOP_CLAUSE_MASK, p_name);
-
-  block = c_begin_compound_stmt (true);
-  stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL);
-  block = c_end_compound_stmt (loc, block, true);
-  add_stmt (block);
-
+  if (is_combined)
+OACC_KERNELS_COMBINED (stmt) = 1;
   return stmt;
 }
 
@@ -11967,32 +11967,32 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name)
 static tree
 c_parser_oacc_parallel (location_t loc, c_parser *parser, char *p_name)
 {
-  tree stmt, clauses = NULL_TREE, block;
+  tree stmt, clauses, block;
+  omp_clause_mask mask;
+  bool is_combined = false;
 
   strcat (p_name, " parallel");
 
+  mask = OACC_PARALLEL_CLAUSE_MASK;
   if (c_parser_next_token_is (parser, CPP_NAME))
 {
-  const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-  if (strcmp (p, "loop") == 0)
+  stmt = c_parser_peek_token (parser)->value;
+  if (!strcmp ("loop", IDENTIFIER_POINTER (stmt)))
 	{
+	  mask |= OACC_LOOP_CLAUSE_MASK;
+	  strcat (p_name, " loops");
 	  c_parser_consume_token (parser);
-	  block = c_begin_omp_parallel ();
-	  c_parser_oacc_loop (loc, parser, p_name);
-	  stmt = c_finish_oacc_parallel (loc, clauses, block);
-	  OACC_PARALLEL_COMBINED (stmt) = 1;
-	  return stmt;
+	  is_combined = true;
 	}
 }
 
-  clauses =  c_parser_oacc_all_clauses (parser, OACC_PARALLEL_CLAUSE_MASK,
-	p_name);
+  clauses =  c_parser_oacc_all_clauses (parser, mask, p_name);
 
   block = c_begin_omp_parallel ();
   add_stmt (c_parser_omp_structured_block (parser));
-
   stmt = c_finish_oacc_parallel (loc, clauses, block);
-
+  if (is_combined)
+OACC_PARALLEL_COMBINED (stmt) = 1;
   return stmt;
 }
 


[gomp4] declare directive [0/5]

2015-06-08 Thread James Norris

Hi!

This patch series completes the implementation of the OpenACC
declare directive.

Patches applied to gomp-4_0-branch

Thanks!
Jim

= gcc/ChangeLog.gomp

* builtin-types.def (BT_FN_VOID_PTR_INT_UINT): New type.
* gimple-pretty-print.c (dump_gimple_omp_target): Handle declare
directive.
* gimple.h (gf_mask): Add enum.
(is_gimple_omp_oacc): Add declare directive.
* gimplify.c (omp_notice_variable): Handle device_resident.
(gimplify_omp_target_update): Handle declare directive.
(gimplify_expr): Handle declare directive.
* omp-builtins.def (BUILT_IN_GOACC_STATIC, BUILT_IN_GOACC_DECLARE):
New types.
* omp-low.c (expand_omp_target): Handle declare directive.
(build_omp_regions_1): Likewise.
(lower_omp_target): Likewise.
(make_gimple_omp_edges): Likewise.
* varpool.c (gomp-constants.h): Add inclusion.
(make_offloadable_1, make_offloadable): New functions.
(get_create): Add calls to make_offloadable.

== gcc/c/ChangeLog.gomp

* c-parser.c (tree-iterator.h): Add inclusion.
(check_oacc_vars1, check_oacc_vars, find_oacc_return,
finish_oacc_declare): New functions.
(oacc_return): New structure.
(oacc_returns): New variable.
(c_parser_declaration_or_fndef): Add call to finish_oacc_declare.
(oacc_dcl_idx): New variable.
(c_parser_oacc_declare): Rewrite.

= gcc/cp/ChangeLog.gomp

* decl.c (gomp-constants.h): Add inclusion.
(check_oacc_vars1, check_oacc_vsars, find_oacc_return,
finish_oacc_declare): New functions.
(finish_function): Add call to finish_oacc_declare.
* parser.c (tree-iterator.h): Add inclusion.
(oacc_dcl_idx): New variable.
(OACC_DECLARE_CLAUSE_MASK): New macro.
(cp_parser_oacc_declare): New function.
(cp_parser_pragma): Handle parsing of declare directive.
* pt.c (tsubr_expr): Add handling of declare directive.

= gcc/fortran/ChangeLog.gomp

* f95-lang.c (gfc_attribute_table): New entry.
* gfortran.h (symbol_attribute): New attributes. 
(gfc_omp_map_op): New enums.
(OMP_LIST_LINK): New enum.
(gfc_oacc_declare): Add member: module_var.
(finish_oacc_declare): Add calling parm.
* module.c (ab_attribute): Add enums.
(attr_bits): Add initialization of new attribute bits.
(mio_symbol_attribute): Add handling of new attribute bits.
* openmp.c (OMP_CLAUSE_LINK): New defintion.
(gfc_match_omp_clauses): Add handling of link clause.
(OACC_DECLARE_CLAUSES): Update declare directive clauses.
(gfc_match_oacc_declare): Add handling of device_resident
and link clauses.
(gfc_resolve_oacc_declare): Add handling of link clause.
* symbol.c (check_conflict): Add checks for declare clauses in modules.
(gfc_add_oacc_declare_create, gfc_add_declare_copyin,
gfc_add_oacc_declare_deviceptr, gfc_add_oacc_declare_device_resident):
New functions.
(gfc_add_target): Add checks for declare attrs.
* trans-decl.c (add_attributes_to_decl): Add creation of attribute.
(oacc_return): New structure.
(oacc_returns, module_oacc_clauses): New variables.
(find_oacc_return, add_clause, find_module_oacc_declare_clauses):
New functions.
(finish_oacc_declare): Rename from insert_oacc_declare and rewrite.
(gfc_generate_function_code): Change calling of finish_oacc_declare.
* trans-openmp.c (gfc_trans_omp_clauses): Add handling of link and
device_resident clauses.
(gfc_trans_oacc_declare): Rewrite.
* trans-stmt.c (gfc_trans_block_construct): Change calling of
finish_oacc_declare.
* types.def (BT_FN_VOID_PTR_INT_UINT): New type.

= gcc/testsuite/ChangeLog.gomp

* c-c++-common/goacc/declare-1.c: Update tests.
* c-c++-common/goacc/declare-2.c: Likewise.
* gfortran.dg/goacc/declare-1.f95: Update tests.

= libgomp/ChangeLog.gomp

* libgomp.map: Add GOACC_declare and GOACC_register_static.
* oacc-init.c (acc_shutdown_1): Add call to acc_deallocate_static.
(acc_init): Add call to acc_allocate_static.
* oacc-int.h (goacc_allocate_static, goacc_deallocate_static):
New declarations.
* oacc-parallel.c (oacc_static): New structure.
(oacc_statics): New variable.
(goacc_allocate_static, goacc_deallocate_static, GOACC_register_static,
GOACC_declare): New functions.
* testsuite/libgomp.oacc-c++/declare-1.C: New file.
* testsuite/libgomp.oacc-c-c++-common/declare-1.c: New file.
* testsuite/libgomp.oacc-c-c++-common/declare-2.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/declare-3.c: Likewise.
* testsuite/libgomp.oacc-c-c++-c

[gomp4] declare directive [1/5]

2015-06-08 Thread James Norris


diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index f508b91..83c1432 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -82,6 +82,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "omp-low.h"
 #include "builtins.h"
 #include "gomp-constants.h"
+#include "tree-iterator.h"
 
 
 /* Initialization routine for this file.  */
@@ -1472,6 +1473,316 @@ c_parser_external_declaration (c_parser *parser)
 }
 }
 
+static tree
+check_oacc_vars_1 (tree *tp, int *, void *l)
+{
+  if (TREE_CODE (*tp) == VAR_DECL && TREE_PUBLIC (*tp))
+{
+  location_t loc = DECL_SOURCE_LOCATION (*tp);
+  tree attrs;
+  attrs = lookup_attribute ("oacc declare", DECL_ATTRIBUTES (*tp));
+  if (attrs)
+	{
+	  tree t;
+
+	  for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
+	{
+	  loc = EXPR_LOCATION ((tree) l);
+
+	  if (OMP_CLAUSE_MAP_KIND (TREE_VALUE (t)) == GOMP_MAP_LINK)
+		{
+		  error_at (loc, "% clause cannot be used with %qE",
+			*tp);
+		  break;
+		}
+	}
+	}
+  else
+	error_at (loc, "no %<#pragma acc declare%> for %qE", *tp);
+}
+  return NULL_TREE;
+}
+
+static tree
+check_oacc_vars (tree *tp, int *, void *)
+{
+  if (TREE_CODE (*tp) == STATEMENT_LIST)
+{
+  tree_stmt_iterator i;
+
+  for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+	{
+	  tree t = tsi_stmt (i);
+	  walk_tree_without_duplicates (&t, check_oacc_vars_1, t);
+	}
+}
+
+  return NULL_TREE;
+}
+
+static struct oacc_return
+{
+  tree_stmt_iterator iter;
+  tree stmt;
+  int op;
+  struct oacc_return *next;
+} *oacc_returns;
+
+static tree
+find_oacc_return (tree *tp, int *, void *)
+{
+  if (TREE_CODE (*tp) == STATEMENT_LIST)
+{
+  tree_stmt_iterator i;
+
+  for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+	{
+	  tree t;
+	  struct oacc_return *r;
+
+	  t = tsi_stmt (i);
+
+	  if (TREE_CODE (t) == RETURN_EXPR)
+	{
+	  r = XNEW (struct oacc_return);
+	  r->iter = i;
+	  r->stmt = NULL_TREE;
+	  r->op = 1;
+	  r->next = NULL;
+
+	  if (oacc_returns)
+		r->next = oacc_returns;
+
+	  oacc_returns = r;
+	}
+	  else if (TREE_CODE (t) == COND_EXPR)
+	{
+	   bool op1, op2;
+	   tree op;
+
+	   op1 = op2 = false;
+
+	   op = TREE_OPERAND (t, 1);
+	   op1 = (op && TREE_CODE (op) == RETURN_EXPR);
+
+	   op = TREE_OPERAND (t, 2);
+	   op2 = (op && TREE_CODE (op) == RETURN_EXPR);
+
+	   if (op1 || op2)
+		{
+		  r = XNEW (struct oacc_return);
+		  r->stmt = t;
+		  r->op = op1 ? 1 : 2;
+		  r->next = NULL;
+
+		  if (oacc_returns)
+		r->next = oacc_returns;
+
+		  oacc_returns = r;
+		}
+	}
+	}
+}
+
+  return NULL_TREE;
+}
+
+static void
+finish_oacc_declare (tree fnbody, tree decls)
+{
+  tree t, stmt, body, c, ret_clauses, clauses;
+  location_t loc;
+  tree_stmt_iterator i;
+  tree fndecl = current_function_decl;
+
+  if (lookup_attribute ("oacc function", DECL_ATTRIBUTES (fndecl)))
+{
+  if (lookup_attribute ("oacc declare", DECL_ATTRIBUTES (fndecl)))
+	{
+	  location_t loc = DECL_SOURCE_LOCATION (fndecl);
+	  error_at (loc, "%<#pragma acc declare%> not allowed in %qE", fndecl);
+	}
+
+  walk_tree_without_duplicates (&fnbody, check_oacc_vars, NULL);
+  return;
+}
+
+  if (!decls)
+return;
+
+  body = BIND_EXPR_BODY (fnbody);
+
+  if (TREE_CODE (body) != STATEMENT_LIST)
+{
+  tree list;
+
+  list = alloc_stmt_list ();
+  append_to_statement_list (body, &list);
+  BIND_EXPR_BODY (fnbody) = list;
+  body = list;
+}
+
+  walk_tree_without_duplicates (&body, find_oacc_return, NULL);
+
+  clauses = NULL_TREE;
+
+  for (t = decls; t; t = TREE_CHAIN (t))
+{
+  c = TREE_VALUE (TREE_VALUE (t));
+
+  if (clauses)
+	OMP_CLAUSE_CHAIN (c) = clauses;
+  else
+	loc = OMP_CLAUSE_LOCATION (c);
+
+  clauses = c;
+}
+
+  ret_clauses = NULL_TREE;
+
+  for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+{
+  bool ret = false;
+  HOST_WIDE_INT kind, new_op;
+
+  kind = OMP_CLAUSE_MAP_KIND (c);
+
+  switch (kind)
+	{
+	  case GOMP_MAP_ALLOC:
+	  case GOMP_MAP_FORCE_ALLOC:
+	  case GOMP_MAP_FORCE_TO:
+	new_op = GOMP_MAP_FORCE_DEALLOC;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_FORCE_FROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_ALLOC);
+	new_op = GOMP_MAP_FORCE_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_FORCE_TOFROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_TO);
+	new_op = GOMP_MAP_FORCE_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_FROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_ALLOC);
+	new_op = GOMP_MAP_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_TOFROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
+	new_op = GOMP_MAP_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_DEVICE_RESIDENT:
+	  case GOMP_MAP_FORCE_DEVICEPTR:
+	  case GOMP_MAP_FORCE_PRESENT:
+	  case GOMP_MAP_LINK:
+	  case GOMP_MAP_POINTER:
+	  cas

Re: [gomp4] declare directive [2/5]

2015-06-08 Thread James Norris


diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 261a12d..15da51e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -78,6 +78,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cilk.h"
 #include "wide-int.h"
 #include "builtins.h"
+#include "gomp-constants.h"
 
 /* Possible cases of bad specifiers type used by bad_specifiers. */
 enum bad_spec_place {
@@ -14113,6 +14114,314 @@ maybe_save_function_definition (tree fun)
 register_constexpr_fundef (fun, DECL_SAVED_TREE (fun));
 }
 
+static tree
+check_oacc_vars_1 (tree *tp, int *, void *l)
+{
+  if (TREE_CODE (*tp) == VAR_DECL && TREE_PUBLIC (*tp))
+{
+  location_t loc = DECL_SOURCE_LOCATION (*tp);
+  tree attrs;
+  attrs = lookup_attribute ("oacc declare", DECL_ATTRIBUTES (*tp));
+  if (attrs)
+	{
+	  tree t;
+
+	  for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
+	{
+	  loc = EXPR_LOCATION ((tree) l);
+
+	  if (OMP_CLAUSE_MAP_KIND (TREE_VALUE (t)) == GOMP_MAP_LINK)
+		{
+		  error_at (loc, "% clause cannot be used with %qE",
+			*tp);
+		  break;
+		}
+	}
+	}
+  else
+	error_at (loc, "no %<#pragma acc declare%> for %qE", *tp);
+}
+  return NULL_TREE;
+}
+
+static tree
+check_oacc_vars (tree *tp, int *, void *)
+{
+  if (TREE_CODE (*tp) == STATEMENT_LIST)
+{
+  tree_stmt_iterator i;
+
+  for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+	{
+	  tree t = tsi_stmt (i);
+	  walk_tree_without_duplicates (&t, check_oacc_vars_1, t);
+	}
+}
+
+  return NULL_TREE;
+}
+
+static struct oacc_return
+{
+  tree_stmt_iterator iter;
+  tree stmt;
+  int op;
+  struct oacc_return *next;
+} *oacc_returns;
+
+static tree
+find_oacc_return (tree *tp, int *, void *)
+{
+  if (TREE_CODE (*tp) == STATEMENT_LIST)
+{
+  tree_stmt_iterator i;
+
+  for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+	{
+	  tree t;
+	  struct oacc_return *r;
+
+	  t = tsi_stmt (i);
+
+	  if (TREE_CODE (t) == RETURN_EXPR)
+	{
+	  r = XNEW (struct oacc_return);
+	  r->iter = i;
+	  r->stmt = NULL_TREE;
+	  r->op = 1;
+	  r->next = NULL;
+
+	  if (oacc_returns)
+		r->next = oacc_returns;
+
+	  oacc_returns = r;
+	}
+	  else if (TREE_CODE (t) == IF_STMT)
+	{
+	   bool op1, op2;
+	   tree op;
+
+	   op1 = op2 = false;
+
+	   op = TREE_OPERAND (t, 1);
+	   op1 = (op && TREE_CODE (op) == RETURN_EXPR);
+
+	   op = TREE_OPERAND (t, 2);
+	   op2 = (op && TREE_CODE (op) == RETURN_EXPR);
+
+	   if (op1 || op2)
+		{
+		  r = XNEW (struct oacc_return);
+		  r->stmt = t;
+		  r->op = op1 ? 1 : 2;
+		  r->next = NULL;
+
+		  if (oacc_returns)
+		r->next = oacc_returns;
+
+		  oacc_returns = r;
+		}
+	}
+	}
+}
+
+  return NULL_TREE;
+}
+
+static void
+finish_oacc_declare (tree fndecl, tree decls)
+{
+  tree t, stmt, list, c, ret_clauses, clauses;
+  location_t loc;
+  tree_stmt_iterator i;
+
+  list = cur_stmt_list;
+
+  if (lookup_attribute ("oacc function", DECL_ATTRIBUTES (fndecl)))
+{
+  if (lookup_attribute ("oacc declare", DECL_ATTRIBUTES (fndecl)))
+	{
+	  location_t loc = DECL_SOURCE_LOCATION (fndecl);
+	  error_at (loc, "%<#pragma acc declare%> not allowed in %qE", fndecl);
+	}
+
+  walk_tree_without_duplicates (&list, check_oacc_vars, NULL);
+  return;
+}
+
+  if (!decls)
+return;
+
+  walk_tree_without_duplicates (&list, find_oacc_return, NULL);
+
+  clauses = NULL_TREE;
+
+  for (t = decls; t; t = TREE_CHAIN (t))
+{
+  c = TREE_VALUE (TREE_VALUE (t));
+
+  if (clauses)
+	OMP_CLAUSE_CHAIN (c) = clauses;
+  else
+	loc = OMP_CLAUSE_LOCATION (c);
+
+  clauses = c;
+}
+
+  ret_clauses = NULL_TREE;
+
+  for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+{
+  bool ret = false;
+  HOST_WIDE_INT kind, new_op;
+
+  kind = OMP_CLAUSE_MAP_KIND (c);
+
+  switch (kind)
+	{
+	  case GOMP_MAP_ALLOC:
+	  case GOMP_MAP_FORCE_ALLOC:
+	  case GOMP_MAP_FORCE_TO:
+	new_op = GOMP_MAP_FORCE_DEALLOC;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_FORCE_FROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_ALLOC);
+	new_op = GOMP_MAP_FORCE_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_FORCE_TOFROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_TO);
+	new_op = GOMP_MAP_FORCE_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_FROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_ALLOC);
+	new_op = GOMP_MAP_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_TOFROM:
+	OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
+	new_op = GOMP_MAP_FROM;
+	ret = true;
+	break;
+
+	  case GOMP_MAP_DEVICE_RESIDENT:
+	  case GOMP_MAP_FORCE_DEVICEPTR:
+	  case GOMP_MAP_FORCE_PRESENT:
+	  case GOMP_MAP_POINTER:
+	  case GOMP_MAP_TO:
+	break;
+
+	  case GOMP_MAP_LINK:
+	continue;
+
+	  default:
+	gcc_unreachable ();
+	break;
+	}
+
+  if (ret)
+	{
+	  t = copy_node (c);
+
+	  OMP_CLAUSE_SET_MAP_KIND (t, new_op);
+
+	  if 

[gomp4] declare directive [3/5]

2015-06-08 Thread James Norris


diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 5003581..a889342 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -119,6 +119,8 @@ static const struct attribute_spec gfc_attribute_table[] =
affects_type_identity } */
   { "omp declare target", 0, 0, true,  false, false,
 gfc_handle_omp_declare_target_attribute, false },
+  { "oacc declare", 0, 0, true,  false, false,
+gfc_handle_omp_declare_target_attribute, false },
   { "oacc function", 0, 0, true,  false, false,
 gfc_handle_omp_declare_target_attribute, false },
   { NULL,		  0, 0, false, false, false, NULL, false }
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index e73c269..a90b0f8 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -861,6 +861,13 @@ typedef struct
   /* Mentioned in OMP DECLARE TARGET.  */
   unsigned omp_declare_target:1;
 
+  /* Mentioned in OACC DECLARE.  */
+  unsigned oacc_declare_create:1;
+  unsigned oacc_declare_copyin:1;
+  unsigned oacc_declare_deviceptr:1;
+  unsigned oacc_declare_device_resident:1;
+  unsigned oacc_declare_link:1;
+
   /* This is an OpenACC acclerator function.  */
   unsigned oacc_function:1;
 
@@ -1132,6 +1139,8 @@ typedef enum
   OMP_MAP_FORCE_TOFROM,
   OMP_MAP_FORCE_PRESENT,
   OMP_MAP_FORCE_DEVICEPTR,
+  OMP_MAP_DEVICE_RESIDENT,
+  OMP_MAP_LINK,
   OMP_MAP_FORCE_TO_GANGLOCAL
 }
 gfc_omp_map_op;
@@ -1174,6 +1183,7 @@ enum
   OMP_LIST_FROM,
   OMP_LIST_REDUCTION,
   OMP_LIST_DEVICE_RESIDENT,
+  OMP_LIST_LINK,
   OMP_LIST_USE_DEVICE,
   OMP_LIST_CACHE,
   OMP_LIST_NUM
@@ -1269,6 +1279,7 @@ typedef struct gfc_oacc_declare
 {
   struct gfc_oacc_declare *next;
   locus where;
+  bool module_var;
   gfc_omp_clauses *clauses;
 }
 gfc_oacc_declare;
@@ -3276,6 +3287,6 @@ void gfc_convert_mpz_to_signed (mpz_t, int);
 
 /* trans-decl.c */
 
-void insert_oacc_declare (gfc_namespace *);
+void finish_oacc_declare (gfc_namespace *, enum sym_flavor);
 
 #endif /* GCC_GFORTRAN_H  */
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 1abfc46..c174902 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -1894,7 +1894,9 @@ typedef enum
   AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
   AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER,
   AB_IMPLICIT_PURE, AB_ARTIFICIAL, AB_UNLIMITED_POLY, AB_OMP_DECLARE_TARGET,
-  AB_ARRAY_OUTER_DEPENDENCY
+  AB_ARRAY_OUTER_DEPENDENCY, AB_OACC_DECLARE_CREATE, AB_OACC_DECLARE_COPYIN,
+  AB_OACC_DECLARE_DEVICEPTR, AB_OACC_DECLARE_DEVICE_RESIDENT,
+  AB_OACC_DECLARE_LINK
 }
 ab_attribute;
 
@@ -1951,6 +1953,11 @@ static const mstring attr_bits[] =
 minit ("UNLIMITED_POLY", AB_UNLIMITED_POLY),
 minit ("OMP_DECLARE_TARGET", AB_OMP_DECLARE_TARGET),
 minit ("ARRAY_OUTER_DEPENDENCY", AB_ARRAY_OUTER_DEPENDENCY),
+minit ("OACC_DECLARE_CREATE", AB_OACC_DECLARE_CREATE),
+minit ("OACC_DECLARE_COPYIN", AB_OACC_DECLARE_COPYIN),
+minit ("OACC_DECLARE_DEVICEPTR", AB_OACC_DECLARE_DEVICEPTR),
+minit ("OACC_DECLARE_DEVICE_RESIDENT", AB_OACC_DECLARE_DEVICE_RESIDENT),
+minit ("OACC_DECLARE_LINK", AB_OACC_DECLARE_LINK),
 minit (NULL, -1)
 };
 
@@ -2133,6 +2140,16 @@ mio_symbol_attribute (symbol_attribute *attr)
 	MIO_NAME (ab_attribute) (AB_OMP_DECLARE_TARGET, attr_bits);
   if (attr->array_outer_dependency)
 	MIO_NAME (ab_attribute) (AB_ARRAY_OUTER_DEPENDENCY, attr_bits);
+  if (attr->oacc_declare_create)
+	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_CREATE, attr_bits);
+  if (attr->oacc_declare_copyin)
+	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_COPYIN, attr_bits);
+  if (attr->oacc_declare_deviceptr)
+	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_DEVICEPTR, attr_bits);
+  if (attr->oacc_declare_device_resident)
+	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_DEVICE_RESIDENT, attr_bits);
+  if (attr->oacc_declare_link)
+	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_LINK, attr_bits);
 
   mio_rparen ();
 
@@ -2302,6 +2319,21 @@ mio_symbol_attribute (symbol_attribute *attr)
 	case AB_ARRAY_OUTER_DEPENDENCY:
 	  attr->array_outer_dependency =1;
 	  break;
+	case AB_OACC_DECLARE_CREATE:
+	  attr->oacc_declare_create = 1;
+	  break;
+	case AB_OACC_DECLARE_COPYIN:
+	  attr->oacc_declare_copyin = 1;
+	  break;
+	case AB_OACC_DECLARE_DEVICEPTR:
+	  attr->oacc_declare_deviceptr = 1;
+	  break;
+	case AB_OACC_DECLARE_DEVICE_RESIDENT:
+	  attr->oacc_declare_device_resident = 1;
+	  break;
+	case AB_OACC_DECLARE_LINK:
+	  attr->oacc_declare_link = 1;
+	  break;
 	}
 	}
 }
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index fc16d8c..46bf865 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -475,6 +475,7 @@ match_oacc_clause_gang (gfc_omp_clauses *cp)
 #define OMP_CLAUSE_BIND			((uint64_t) 1 << 58)
 #define OMP_CLAUSE_NOHOST		((uint64_t) 1 << 59)
 #define OMP_CLAUSE_DEVICE_TYPE		((uint64_t) 1 << 60)
+#define O

[gomp4] declare directive [4/5]

2015-06-08 Thread James Norris
",
 		  BT_FN_VOID_UINT_UINT, ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_STATIC, "GOACC_register_static",
+		   BT_FN_VOID_PTR_INT_UINT, ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DECLARE, "GOACC_declare",
+		   BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 0b31992..e1c9db4 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -9519,6 +9519,7 @@ expand_omp_target (struct omp_region *region)
 case GF_OMP_TARGET_KIND_OACC_KERNELS:
 case GF_OMP_TARGET_KIND_OACC_UPDATE:
 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
+case GF_OMP_TARGET_KIND_OACC_DECLARE:
   data_region = false;
   break;
 case GF_OMP_TARGET_KIND_DATA:
@@ -9825,6 +9826,9 @@ expand_omp_target (struct omp_region *region)
 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
   start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
   break;
+case GF_OMP_TARGET_KIND_OACC_DECLARE:
+  start_ix = BUILT_IN_GOACC_DECLARE;
+  break;
 default:
   gcc_unreachable ();
 }
@@ -9944,6 +9948,7 @@ expand_omp_target (struct omp_region *region)
   args.quick_push (build_zero_cst (ptr_type_node));
   break;
 case BUILT_IN_GOACC_DATA_START:
+case BUILT_IN_GOACC_DECLARE:
 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
 case BUILT_IN_GOACC_KERNELS:
 case BUILT_IN_GOACC_KERNELS_INTERNAL:
@@ -9960,6 +9965,7 @@ expand_omp_target (struct omp_region *region)
   switch (start_ix)
 {
 case BUILT_IN_GOACC_DATA_START:
+case BUILT_IN_GOACC_DECLARE:
 case BUILT_IN_GOMP_TARGET:
 case BUILT_IN_GOMP_TARGET_DATA:
 case BUILT_IN_GOMP_TARGET_UPDATE:
@@ -10268,6 +10274,7 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent,
 		case GF_OMP_TARGET_KIND_UPDATE:
 		case GF_OMP_TARGET_KIND_OACC_UPDATE:
 		case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
+		case GF_OMP_TARGET_KIND_OACC_DECLARE:
 		  /* ..., other than for those stand-alone directives...  */
 		  region = NULL;
 		  break;
@@ -12771,6 +12778,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 case GF_OMP_TARGET_KIND_OACC_KERNELS:
 case GF_OMP_TARGET_KIND_OACC_UPDATE:
 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
+case GF_OMP_TARGET_KIND_OACC_DECLARE:
   data_region = false;
   break;
 case GF_OMP_TARGET_KIND_DATA:
@@ -12835,6 +12843,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 	  case GOMP_MAP_FORCE_PRESENT:
 	  case GOMP_MAP_FORCE_DEALLOC:
 	  case GOMP_MAP_FORCE_DEVICEPTR:
+	  case GOMP_MAP_DEVICE_RESIDENT:
+	  case GOMP_MAP_LINK:
 	gcc_assert (is_gimple_omp_oacc (stmt));
 	break;
 	  default:
@@ -13888,6 +13898,7 @@ make_gimple_omp_edges (basic_block bb, struct omp_region **region,
 	case GF_OMP_TARGET_KIND_UPDATE:
 	case GF_OMP_TARGET_KIND_OACC_UPDATE:
 	case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
+	case GF_OMP_TARGET_KIND_OACC_DECLARE:
 	  cur_region = cur_region->outer;
 	  break;
 	default:
diff --git a/gcc/testsuite/ChangeLog.gomp b/gcc/testsuite/ChangeLog.gomp
index fb480cf..649740c 100644
--- a/gcc/testsuite/ChangeLog.gomp
+++ b/gcc/testsuite/ChangeLog.gomp
@@ -1,3 +1,10 @@
+
+2015-06-04  James Norris  
+
+	* c-c++-common/goacc/declare-1.c: Update tests.
+	* c-c++-common/goacc/declare-2.c: Likewise.
+	* gfortran.dg/goacc/declare-1.f95: Update tests.
+
 2015-06-01  Tom de Vries  
 
 	Revert:
diff --git a/gcc/testsuite/c-c++-common/goacc/declare-1.c b/gcc/testsuite/c-c++-common/goacc/declare-1.c
index cf50f02..b036c63 100644
--- a/gcc/testsuite/c-c++-common/goacc/declare-1.c
+++ b/gcc/testsuite/c-c++-common/goacc/declare-1.c
@@ -1,6 +1,5 @@
 /* Test valid uses of declare directive.  */
 /* { dg-do compile } */
-/* { dg-skip-if "not yet" { c++ } } */
 
 int v0;
 #pragma acc declare create(v0)
diff --git a/gcc/testsuite/c-c++-common/goacc/declare-2.c b/gcc/testsuite/c-c++-common/goacc/declare-2.c
index a2b5d6f..ce12463 100644
--- a/gcc/testsuite/c-c++-common/goacc/declare-2.c
+++ b/gcc/testsuite/c-c++-common/goacc/declare-2.c
@@ -1,11 +1,10 @@
 /* Test invalid uses of declare directive.  */
 /* { dg-do compile } */
-/* { dg-skip-if "not yet" { c++ } } */
 
 #pragma acc declare /* { dg-error "no valid clauses" } */
 
 #pragma acc declare create(undeclared) /* { dg-error "undeclared" } */
-/* { dg-error "no valid clauses" "second error" { target *-*-* } 7 } */
+/* { dg-error "no valid clauses" "second error" { target *-*-* } 6 } */
 
 int v0[10];
 #pragma acc declare create(v0[1:3]) /* { dg-error "subarray" } */
@@ -42,7 +41,7 @@ void
 f (void)
 {
   int va0;
-#pragma acc declare link(va0) /* { dg-error "invalid variable" } */
+#pragma acc declare link(va0) /* { dg-error "global variable" } */
 
   extern int ve0;
 #pragma acc declare copy(ve0) /* { dg-error "invalid use of" } */
diff --git a/gcc/testsuite/gfortran.dg/goacc/declare-1.f95 b/gcc/t

[gomp4] declare directive [5/5]

2015-06-08 Thread James Norris


diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index fe38dc6..663c27c 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -318,6 +318,7 @@ GOACC_2.0 {
   global:
 	GOACC_data_end;
 	GOACC_data_start;
+	GOACC_declare;
 	GOACC_enter_exit_data;
 	GOACC_parallel;
 	GOACC_update;
@@ -331,6 +332,7 @@ GOACC_2.0.GOMP_4_BRANCH {
 	GOACC_deviceptr;
 	GOACC_get_ganglocal_ptr;
 	GOACC_kernels;
+	GOACC_register_static;
 } GOACC_2.0;
 
 GOMP_PLUGIN_1.0 {
diff --git a/libgomp/oacc-init.c b/libgomp/oacc-init.c
index 9f24dc3..e772f48 100644
--- a/libgomp/oacc-init.c
+++ b/libgomp/oacc-init.c
@@ -205,6 +205,8 @@ acc_shutdown_1 (acc_device_t d)
   if (!base_dev)
 gomp_fatal ("device %s not supported", name_of_acc_device_t (d));
 
+  goacc_deallocate_static (d);
+
   gomp_mutex_lock (&goacc_thread_lock);
 
   /* Free target-specific TLS data and close all devices.  */
@@ -373,7 +375,9 @@ goacc_attach_host_thread_to_device (int ord)
 void
 acc_init (acc_device_t d)
 {
-  if (!cached_base_dev)
+  bool init = !cached_base_dev;
+
+  if (init)
 gomp_init_targets_once ();
 
   gomp_mutex_lock (&acc_device_lock);
@@ -381,6 +385,9 @@ acc_init (acc_device_t d)
   cached_base_dev = acc_init_1 (d);
 
   gomp_mutex_unlock (&acc_device_lock);
+
+  if (init)
+goacc_allocate_static (d);
   
   goacc_attach_host_thread_to_device (-1);
 }
diff --git a/libgomp/oacc-int.h b/libgomp/oacc-int.h
index 0ace737..8f4938e 100644
--- a/libgomp/oacc-int.h
+++ b/libgomp/oacc-int.h
@@ -98,6 +98,9 @@ void goacc_save_and_set_bind (acc_device_t);
 void goacc_restore_bind (void);
 void goacc_lazy_initialize (void);
 
+void goacc_allocate_static (acc_device_t);
+void goacc_deallocate_static (acc_device_t);
+
 #ifdef HAVE_ATTRIBUTE_VISIBILITY
 # pragma GCC visibility pop
 #endif
diff --git a/libgomp/oacc-parallel.c b/libgomp/oacc-parallel.c
index 513d0bc..70758bc 100644
--- a/libgomp/oacc-parallel.c
+++ b/libgomp/oacc-parallel.c
@@ -109,6 +109,68 @@ alloc_ganglocal_addrs (size_t mapnum, void **hostaddrs, size_t *sizes,
 }
 }
 
+static struct oacc_static
+{
+  void *addr;
+  size_t size;
+  unsigned short mask;
+  bool free;
+  struct oacc_static *next;
+} *oacc_statics;
+
+static bool alloc_done = false;
+
+void
+goacc_allocate_static (acc_device_t d)
+{
+  struct oacc_static *s;
+
+  if (alloc_done)
+assert (0);
+
+  for (s = oacc_statics; s; s = s->next)
+{
+  void *d;
+
+  switch (s->mask)
+	{
+	case GOMP_MAP_FORCE_ALLOC:
+	  break;
+
+	case GOMP_MAP_FORCE_TO:
+	  d = acc_deviceptr (s->addr);
+	  acc_memcpy_to_device (d, s->addr, s->size);
+	  break;
+
+	case GOMP_MAP_FORCE_DEVICEPTR:
+	case GOMP_MAP_DEVICE_RESIDENT:
+	case GOMP_MAP_LINK:
+	  break;
+
+	default:
+	  assert (0);
+	  break;
+	}
+}
+
+  alloc_done = true;
+}
+
+void
+goacc_deallocate_static (acc_device_t d)
+{
+  struct oacc_static *s;
+  unsigned short mask = GOMP_MAP_FORCE_DEALLOC;
+
+  if (!alloc_done)
+return;
+
+  for (s = oacc_statics; s; s = s->next)
+GOACC_enter_exit_data (d, 1, &s->addr, &s->size, &mask, 0, 0);
+
+  alloc_done = false;
+}
+
 static void goacc_wait (int async, int num_waits, va_list ap);
 
 void
@@ -592,3 +654,82 @@ GOACC_get_thread_num (int gang, int worker, int vector)
 {
   return 0;
 }
+
+void
+GOACC_register_static (void *addr, int size, unsigned int mask)
+{
+  struct oacc_static *s;
+
+  s = (struct oacc_static *) malloc (sizeof (struct oacc_static));
+  s->addr = addr;
+  s->size = (size_t) size;
+  s->mask = mask;
+  s->free = false;
+  s->next = NULL;
+
+  if (oacc_statics)
+s->next = oacc_statics;
+
+   oacc_statics = s;
+}
+
+#include 
+
+void
+GOACC_declare (int device, size_t mapnum,
+	   void **hostaddrs, size_t *sizes, unsigned short *kinds)
+{
+  int i;
+
+  for (i = 0; i < mapnum; i++)
+{
+  unsigned char kind = kinds[i] & 0xff;
+
+  if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
+	continue;
+
+  switch (kind)
+	{
+	  case GOMP_MAP_FORCE_ALLOC:
+	  case GOMP_MAP_FORCE_DEALLOC:
+	  case GOMP_MAP_FORCE_FROM:
+	  case GOMP_MAP_FORCE_TO:
+	  case GOMP_MAP_POINTER:
+	GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+   &kinds[i], 0, 0);
+	break;
+
+	  case GOMP_MAP_FORCE_DEVICEPTR:
+	break;
+
+	  case GOMP_MAP_ALLOC:
+	if (!acc_is_present (hostaddrs[i], sizes[i]))
+	  {
+		GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+   &kinds[i], 0, 0);
+	  }
+	break;
+
+	  case GOMP_MAP_TO:
+	GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+   &kinds[i], 0, 0);
+
+	break;
+
+	  case GOMP_MAP_FROM:
+	kinds[i] = GOMP_MAP_FORCE_FROM;
+	GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+   &kinds[i], 0, 0);
+	break;
+
+	  case GOMP_MAP_FORCE_PRESENT:
+	if (!acc_is_present (hostaddrs[i], sizes[i]))
+	  gomp_fatal ("[%p,%zd] is not mapped", hostaddrs[i], sizes[i]);
+	break;
+
+	  default:
+	assert (0);
+	break;
+	}
+}
+}
diff --git a/libg

Re: Next set of OpenACC changes: Fortran

2015-05-06 Thread James Norris

Tobias,

First, thank you for taking the time to review the patch.
Second, thank you for providing the comments. It appears
all of the comments need to be acted upon in some manner.

Thanks!


On 05/05/2015 05:01 AM, Tobias Burnus wrote:

Thomas Schwinge wrote:

In follow-up messages, I'll be posting the separated parts (for easier
review) of a next set of OpenACC changes that we'd like to commit.
ChangeLog updates not yet written; will do that before commit, obviously.

Still, it would have been nice if you had given an overview about what
the main part of the patch does. In this case, there is neither some intro
words nor a ChangeLog (which also gives an overview what the patch does).

Regarding the !$ACC ROUTINE support, which the patch adds: In my very
rough understanding, the compiler has to know at compile time whether a
procedure is a '!$ACC ROUTINE' or not. Thus, it should work if you declare
in one file:

!- file1.f90---
subroutine foo()
   !$acc routine
end subroutine foo
!--- end of file

and invoke it in a different file:
   call foo()

In order that this works in Fortran, you need to support two ways of
handling this information:


a) modules:

module m
contains
   subroutine foo()
 !$acc routine
   end subroutine foo
end module m

Thus, I had expected that you store this information (at least the relevant
parts) in the .mod file. (-> fortran/module.c)


b) interfaces, i.e. in the scope of the caller:

interface
   subroutine foo()
 !$acc routine
   end subroutine foo
end interface

!$acc parallel
...
call foo()
...
!$acc end parallel


Semantically, something like the the latter is also needed in the same file
if the procedure "foo" is stand along (i.e. neither in a module nor 'contained'
(internal procedure) of the caller nor a sibling internal procedure of the
caller). However, as the original declaration is available, supporting (b) is
only semantical sugar - especially a check whether the !$acc routine is provided
in the interface and matches the original declaration.


Thus, can you check:
* whether you need to store information in the .mod file?
* whether (b) is/should be supported? (And with how much error diagnostic
   in case of the same TU and mismatches.)
And, if needed, provide some test cases?

And if you are there:
* Whether something similar to .mod has to be done for LTO?
* Could you also create a test case, where Fortran calls C or vice versa for
   an OpenACC ROUTINE?

Tobias




Re: [PATCH] OpenACC for C++ front end

2014-11-20 Thread James Norris

Hi!

On 11/13/2014 07:02 AM, Jakub Jelinek wrote:

On Wed, Nov 05, 2014 at 03:37:08PM -0600, James Norris wrote:

2014-11-05  James Norris  
Cesar Philippidis  
Thomas Schwinge  
Ilmir Usmanov  

...

Please check formatting.  I see various spots with 8 spaces instead of tabs,
e.g. on
+  check_no_duplicate_clause (list, OMP_CLAUSE_VECTOR_LENGTH,
+"vector_length", location);
even the alignment is wrong, I see calls without space before (:
+  if (args == NULL || args->length() == 0)
...
+ error("% expression must be integral");
other spots where the alignment isn't right:


Fixed.


+static tree
+cp_parser_oacc_cache (cp_parser *parser,
+   cp_token *pragma_tok __attribute__((unused)))
(cp_token should be below cp_parser).  While at this,
__attribute__((unused)) should be replaced by ATTRIBUTE_UNUSED, or removing
the parameter name, or removing the parameter altogether even better.


Fixed by removing unused parameter.


For the formatting issues, you can easily look for them in the patch
(in lines starting with +), change the patch and apply interdiff to your
tree.


Thank you for the pointer to interdiff!




--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -29,8 +29,47 @@ along with GCC; see the file COPYING3.  If not see
  #include "c-pragma.h"
  #include "gimple-expr.h"
  #include "langhooks.h"
+#include "omp-low.h"

As Thomas? has said, you should include gomp-constants.h and use them in:


+t = build_int_cst (integer_type_node, -2);  /* TODO: XXX FIX -2.  */

spots like this.


Fixed.




--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1180,6 +1180,16 @@ typedef struct
  static vec registered_pp_pragmas;
  
  struct omp_pragma_def { const char *name; unsigned int id; };

+static const struct omp_pragma_def oacc_pragmas[] = {
+  { "data", PRAGMA_OACC_DATA },
+  { "enter", PRAGMA_OACC_ENTER_DATA },
+  { "exit", PRAGMA_OACC_EXIT_DATA },
+  { "kernels", PRAGMA_OACC_KERNELS },
+  { "loop", PRAGMA_OACC_LOOP },
+  { "parallel", PRAGMA_OACC_PARALLEL },
+  { "update", PRAGMA_OACC_UPDATE },
+  { "wait", PRAGMA_OACC_WAIT },

I'd avoid the , after the last element.


Fixed.




@@ -1383,6 +1402,17 @@ c_invoke_pragma_handler (unsigned int id)
  void
  init_pragma (void)
  {
+  if (flag_openacc)
+{
+  const int n_oacc_pragmas
+   = sizeof (oacc_pragmas) / sizeof (*oacc_pragmas);
+  int i;
+
+  for (i = 0; i < n_oacc_pragmas; ++i)
+   cpp_register_deferred_pragma (parse_in, "acc", oacc_pragmas[i].name,
+ oacc_pragmas[i].id, true, true);
+}
+
if (flag_openmp)
  {
const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);

Is -fopenmp -fopenacc tested not to run out of number of supported pragmas
by libcpp?


Tests will be added in a follow-up patch once the middle end has been 
accepted.





@@ -65,23 +74,30 @@ typedef enum pragma_kind {
  } pragma_kind;
  
  
-/* All clauses defined by OpenMP 2.5, 3.0, 3.1 and 4.0.

+/* All clauses defined by OpenACC 2.0, and OpenMP 2.5, 3.0, 3.1, and 4.0.
 Used internally by both C and C++ parsers.  */
  typedef enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_NONE = 0,
  
PRAGMA_OMP_CLAUSE_ALIGNED,

+  PRAGMA_OMP_CLAUSE_ASYNC,
PRAGMA_OMP_CLAUSE_COLLAPSE,
+  PRAGMA_OMP_CLAUSE_COPY,
PRAGMA_OMP_CLAUSE_COPYIN,
+  PRAGMA_OMP_CLAUSE_COPYOUT,
PRAGMA_OMP_CLAUSE_COPYPRIVATE,
+  PRAGMA_OMP_CLAUSE_CREATE,
PRAGMA_OMP_CLAUSE_DEFAULT,
+  PRAGMA_OMP_CLAUSE_DELETE,
PRAGMA_OMP_CLAUSE_DEPEND,
PRAGMA_OMP_CLAUSE_DEVICE,
+  PRAGMA_OMP_CLAUSE_DEVICEPTR,
PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
PRAGMA_OMP_CLAUSE_FINAL,
PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
PRAGMA_OMP_CLAUSE_FOR,
PRAGMA_OMP_CLAUSE_FROM,
+  PRAGMA_OMP_CLAUSE_HOST,
PRAGMA_OMP_CLAUSE_IF,
PRAGMA_OMP_CLAUSE_INBRANCH,
PRAGMA_OMP_CLAUSE_LASTPRIVATE,
@@ -90,16 +106,24 @@ typedef enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_MERGEABLE,
PRAGMA_OMP_CLAUSE_NOTINBRANCH,
PRAGMA_OMP_CLAUSE_NOWAIT,
+  PRAGMA_OMP_CLAUSE_NUM_GANGS,
PRAGMA_OMP_CLAUSE_NUM_TEAMS,
PRAGMA_OMP_CLAUSE_NUM_THREADS,
+  PRAGMA_OMP_CLAUSE_NUM_WORKERS,
PRAGMA_OMP_CLAUSE_ORDERED,
PRAGMA_OMP_CLAUSE_PARALLEL,
+  PRAGMA_OMP_CLAUSE_PRESENT,
+  PRAGMA_OMP_CLAUSE_PRESENT_OR_COPY,
+  PRAGMA_OMP_CLAUSE_PRESENT_OR_COPYIN,
+  PRAGMA_OMP_CLAUSE_PRESENT_OR_COPYOUT,
+  PRAGMA_OMP_CLAUSE_PRESENT_OR_CREATE,
PRAGMA_OMP_CLAUSE_PRIVATE,
PRAGMA_OMP_CLAUSE_PROC_BIND,
PRAGMA_OMP_CLAUSE_REDUCTION,
PRAGMA_OMP_CLAUSE_SAFELEN,
PRAGMA_OMP_CLAUSE_SCHEDULE,
PRAGMA_OMP_CLAUSE_SECTIONS,
+  PRAGMA_OMP_CLAUSE_SELF,
PRAGMA_OMP_CLAUSE_SHARED,
PRAGMA_OMP_CLAUSE_SIMDLEN,
P

Re: [PATCH] OpenACC for C front end

2014-11-20 Thread James Norris

Hi!

On 11/13/2014 09:04 AM, Jakub Jelinek wrote:

On Wed, Nov 05, 2014 at 03:39:44PM -0600, James Norris wrote:

* c-typeck.c (c_finish_oacc_parallel, c_finish_oacc_kernels,
c_finish_oacc_data): New functions.
(handle_omp_array_sections, c_finish_omp_clauses):

Handle should be on the above line, no need to wrap too early.


Fixed.




@@ -9763,6 +9830,10 @@ c_parser_omp_clause_name (c_parser *parser)
  else if (!strcmp ("from", p))
result = PRAGMA_OMP_CLAUSE_FROM;
  break;
+   case 'h':
+ if (!strcmp ("host", p))
+   result = PRAGMA_OMP_CLAUSE_SELF;
+ break;

Shouldn't this be PRAGMA_OMP_CLAUSE_HOST (PRAGMA_OACC_CLAUSE_HOST)
instead?  It is _HOST in the C++ patch, are there no C tests with
that clause covering it?


The "host" clause is a synonym for the "self" clause. The initial
C++ patch did not treat "host" as a synonym and has amended
accordingly.


+  tree v = TREE_PURPOSE (t);
+
+  /* FIXME diagnostics: Ideally we should keep individual
+locations for all the variables in the var list to make the
+following errors more precise.  Perhaps
+c_parser_omp_var_list_parens() should construct a list of
+locations to go along with the var list.  */

Like in C++ patch, please avoid the comment, file a PR instead,
or just queue the work for GCC 6.


Will submit a PR.


+  /* Attempt to statically determine when the number isn't positive.  */
+  c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
+  build_int_cst (TREE_TYPE (t), 0));

build_int_cst not aligned below expr_loc.


Fixed.


+  if (CAN_HAVE_LOCATION_P (c))
+   SET_EXPR_LOCATION (c, expr_loc);
+  if (c == boolean_true_node)
+   {
+ warning_at (expr_loc, 0,
+ "% value must be positive");

This would fit perfectly on one line.


Fixed.


+  tree c, t;
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  /* TODO XXX: FIX -1  (acc_async_noval).  */
+  t = build_int_cst (integer_type_node, -1);

Again, as in C++ patch, please avoid this.  Use gomp-constants.h,
or some enum, or explain what the -1 is, but avoid TODO XXX: FIX.


Fixed.


+  else
+{
+  t = c_fully_fold (t, false, NULL);
+}

Please avoid the {}s and reindent.


Fixed.




-/* OpenMP 4.0:
-   parallel
-   for
-   sections
-   taskgroup */
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+   {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+   }
  
-static tree

-c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
-   enum omp_clause_code code, tree list)
-{
-  tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
+  /* Attempt to statically determine when the number isn't positive.  */
+  c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
+  build_int_cst (TREE_TYPE (t), 0));

I wonder if it wouldn't be better to just put the new OpenACC routines
into a new block of code, not stick it in between the OpenMP handling
routines, because diff apparently lost track and I'm afraid so will svn 
blame/git blame
and we'll lose history for the OpenMP changes.


There was a mistake in naming the function: 
c_parser_omp_clause_vector_length.

Once it was renamed to: c_parser_oacc_clause_vector_length, diff was able to
keep track.


+   case PRAGMA_OMP_CLAUSE_VECTOR_LENGTH:
+ clauses = c_parser_omp_clause_vector_length (parser, clauses);
+ c_name = "vector_length";
+ break;

That is OpenACC clause, right?  Shouldn't the routine be called
c_parser_oacc_clause_vector_length?


Fixed.


+   case PRAGMA_OMP_CLAUSE_WAIT:
+ clauses = c_parser_oacc_clause_wait (parser, clauses);

E.g. c_parser_oacc_clause_wait is.


Fixed.




+  clauses =  c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
+   "#pragma acc data");

Too many spaces after =.


Fixed.


+/* OpenACC 2.0:
+   # pragma acc kernels oacc-kernels-clause[optseq] new-line
+ structured-block
+
+   LOC is the location of the #pragma token.

Again, what is LOC?


Fixed by removal of comment, along with other occurences.


+  clauses =  c_parser_oacc_all_clauses (parser, OACC_KERNELS_CLAUSE_MASK,
+   p_name);

See above.


Fixed.


+  c_parser_error (parser, enter
+ ? "expected % in %<#pragma acc enter data%>"
+ : "expected % in %<#pragma acc exit data%>");
+  c_parser_skip_to_pragma_eol (parser);
+  return;
+}
+
+  const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  if (strcmp (p, "data") != 0)
+{

Re: [PATCH] Fix PR64748

2015-03-10 Thread James Norris

Hi!

Ping.

Thanks!


On 02/16/2015 12:26 PM, James Norris wrote:


This fixes the validation of the argument to the deviceptr clause.

Bootstrapped and regtested on x86_64-unknown-linux-gnu.

OK to commit to trunk?

Jim





[gomp4] Add tests for atomic read / write.

2015-06-10 Thread James Norris

Hi,

This patch adds tests for OpenACC atomic read and atomic write.


Patch applied to gomp-4_0-branch

Regards,
Jim

diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/atomic_rw-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/atomic_rw-1.c
new file mode 100644
index 000..ae4f22e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/atomic_rw-1.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+
+#include 
+
+int
+main(int argc, char **argv)
+{
+  int v1, v2;
+  int x;
+
+  x = 99;
+
+#pragma acc parallel copy (v1, v2, x)
+  {
+
+#pragma acc atomic read
+v1 = x;
+
+#pragma acc atomic write
+x = 32;
+
+#pragma acc atomic read
+v2 = x;
+
+  }
+
+  if (v1 != 99)
+abort ();
+
+  if (v2 != 32)
+abort ();
+
+  return 0;
+}


Re: [gomp4] declare directive [3/5]

2015-06-18 Thread James Norris

Hi Thomas!

On 06/17/2015 04:59 AM, Thomas Schwinge wrote:

Hi Jim!

I had mentioned that the Fortran front end changes cause regressions in a
few libgomp execution tests, if configured for Intel MIC (emulation)
offloading.  I have now located *where* this is coming from, but would
you please work on figuring out *why*?



There are actually two bugs in find_module_oacc_declare_clauses which
are causing the issues you are seeing.

With the first bug, if none of the 'oacc_declare_*' bits were asserted,
then the referenced field within the attribute structure was set to
zero. If the referenced field was already set to one prior to
find_module_oacc_declare_clauses being called, then the field gets
incorrectly set to zero, if none of the 'oacc_declare_*' bits were
asserted.

With the second bug, if the referenced field within the attribute
structure is already set to one prior to
find_module_oacc_declare_clauses being called, then the subroutine
add_clause was called. The subroutine add_clause should only be
called if one of the 'oacc_declare_*' bits are asserted.

The attached patch resolves the above issues.

Committed to gomp-4_0-branch

Jim

diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 77fdc8b..7387a80 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -5848,11 +5848,6 @@ find_module_oacc_declare_clauses (gfc_symbol *sym)
 {
   gfc_omp_map_op map_op;
 
-  sym->attr.referenced = sym->attr.oacc_declare_create
-			 | sym->attr.oacc_declare_copyin
-			 | sym->attr.oacc_declare_deviceptr
-			 | sym->attr.oacc_declare_device_resident;
-
   if (sym->attr.oacc_declare_create)
 	map_op = OMP_MAP_FORCE_ALLOC;
 
@@ -5865,8 +5860,14 @@ find_module_oacc_declare_clauses (gfc_symbol *sym)
   if (sym->attr.oacc_declare_device_resident)
 	map_op = OMP_MAP_DEVICE_RESIDENT;
 
-  if (sym->attr.referenced)
-	add_clause (sym, map_op);
+  if (sym->attr.oacc_declare_create
+	  || sym->attr.oacc_declare_copyin
+	  || sym->attr.oacc_declare_deviceptr
+	  || sym->attr.oacc_declare_device_resident)
+	{
+	  sym->attr.referenced = 1;
+	  add_clause (sym, map_op);
+	}
 }
 }
 


[gomp4] Additional tests for the default clause

2015-06-18 Thread James Norris

Hi!

The attached patch adds additional tests for the
OpenACC default clause.

Committed to gomp-4_0-branch

Jim
diff --git a/gcc/testsuite/c-c++-common/goacc/default-1.c b/gcc/testsuite/c-c++-common/goacc/default-1.c
new file mode 100644
index 000..41757f1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/default-1.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+
+#include 
+
+int
+main (int argc, char **argv)
+{
+  float a, b;
+
+  a = 2.0;
+  b = 0.0;
+
+#pragma acc parallel default (shared) /* { dg-error "expected 'none'" } */
+  /* { dg-error "expected '\\\)'" "" { target c++ } 13 } */
+  {
+b = a;
+a = 1.0;
+a = a + b;
+  }
+
+#pragma acc parallel default (none) /* { dg-error "enclosing OpenACC parallel" } */
+  {
+b = a; /* { dg-error "in enclosing OpenACC parallel construct" } */
+a = 1.0;
+a = a + b;
+  }
+
+#pragma acc parallel create (b) default (none) /* { dg-error "enclosing OpenACC parallel" } */
+  {
+b = a; /* { dg-error "in enclosing OpenACC parallel construct" } */
+a = 1.0;
+a = a + b;
+  }
+
+#pragma acc kernels default (none) /* { dg-error "enclosing OpenACC kernels" } */
+  {
+b = a; /* { dg-error "in enclosing OpenACC kernels construct" } */
+a = 1.0;
+a = a + b;
+  }
+
+#pragma acc kernels create (b) default (none) /* { dg-error "enclosing OpenACC kernels construct" } */
+  {
+b = a; /* { dg-error "in enclosing OpenACC kernels construct" } */
+a = 1.0;
+a = a + b;
+  }
+
+#pragma acc kernels copy (a) create (b) default () /* { dg-error "expected 'none'" } */
+  {
+b = a;
+a = 1.0;
+a = a + b;
+  }
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/default-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/default-1.c
new file mode 100644
index 000..0d75f49
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/default-1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+
+#include 
+
+int
+main (int argc, char **argv)
+{
+  float a, b;
+
+  a = 2.0;
+  b = 0.0;
+
+#pragma acc kernels default (none)
+  {
+float c, d;
+
+c = 2.0;
+d = c;
+c = 1.0;
+c = c + d;
+  }
+
+#pragma acc parallel default (none)
+  {
+float c, d;
+
+c = 2.0;
+d = c;
+c = 1.0;
+c = c + d;
+  }
+
+#pragma acc parallel copy (a) create (b) default (none)
+  {
+b = a;
+a = 1.0;
+a = a + b;
+  }
+
+  if (a != 3.0)
+abort ();
+
+#pragma acc kernels copy (a) create (b) default (none)
+  {
+b = a;
+a = 1.0;
+a = a + b;
+  }
+
+  if (a != 4.0)
+abort ();
+
+#pragma acc parallel default (none) copy (a) create (b)
+  {
+b = a;
+a = 1.0;
+a = a + b;
+  }
+
+  if (a != 5.0)
+abort ();
+
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/default-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/default-1.f90
new file mode 100644
index 000..f82316e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/default-1.f90
@@ -0,0 +1,34 @@
+! { dg-do run }
+
+program main
+  implicit none
+  real a, b
+
+  a = 2.0
+  b = 0.0
+
+  !$acc parallel copy (a) create (b) default (none)
+b = a
+a = 1.0
+a = a + b
+  !$acc end parallel
+
+  if (a .ne. 3.0) call abort
+
+  !$acc kernels copy (a) create (b) default (none)
+b = a
+a = 1.0
+a = a + b
+  !$acc end kernels
+
+  if (a .ne. 4.0) call abort
+
+  !$acc parallel default (none) copy (a) create (b)
+b = a
+a = 1.0
+a = a + b
+  !$acc end parallel
+
+  if (a .ne. 5.0) call abort
+
+end program main


[gomp4] Additional testing for deviceptr clause.

2015-06-23 Thread James Norris

Hi!

The following patch adds additional testing of the deviceptr
clause.

Patch applied to gomp-4_0-branch.

Thanks!
Jim
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/deviceptr-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/deviceptr-1.c
index e271a37..e62c315 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/deviceptr-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/deviceptr-1.c
@@ -28,5 +28,26 @@ int main (void)
 abort ();
 #endif
 
+  a_1 = a_2 = 0;
+
+#pragma acc data deviceptr (a)
+#pragma acc parallel copyout (a_1, a_2)
+  {
+a_1 = a;
+a_2 = &a;
+  }
+
+  if (a != A)
+abort ();
+  if (a_1 != a)
+abort ();
+#if ACC_MEM_SHARED
+  if (a_2 != &a)
+abort ();
+#else
+  if (a_2 == &a)
+abort ();
+#endif
+
   return 0;
 }


[gomp4] Additional tests for declare directive and fixes.

2015-06-24 Thread James Norris

Hi!

The following patch adds additional testing of the declare directive
and fixes for issues that arose from the testing.


Committed to gomp-4_0-branch.

Jim
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index e7df751..bcbd163 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1767,12 +1767,15 @@ finish_oacc_declare (tree fnbody, tree decls)
 	break;
 }
 
-  stmt = make_node (OACC_DECLARE);
-  TREE_TYPE (stmt) = void_type_node;
-  OACC_DECLARE_CLAUSES (stmt) = ret_clauses;
-  SET_EXPR_LOCATION (stmt, loc);
+  if (ret_clauses)
+{
+  stmt = make_node (OACC_DECLARE);
+  TREE_TYPE (stmt) = void_type_node;
+  OACC_DECLARE_CLAUSES (stmt) = ret_clauses;
+  SET_EXPR_LOCATION (stmt, loc);
 
-  tsi_link_before (&i, stmt, TSI_CONTINUE_LINKING);
+  tsi_link_before (&i, stmt, TSI_CONTINUE_LINKING);
+}
 
   DECL_ATTRIBUTES (fndecl)
 	  = remove_attribute ("oacc declare", DECL_ATTRIBUTES (fndecl));
@@ -12812,6 +12815,14 @@ c_parser_oacc_declare (c_parser *parser)
 	  error = true;
 	  continue;
 	}
+	  else if (TREE_PUBLIC (decl))
+	{
+	  error_at (loc,
+			"invalid use of % variable %qD "
+			"in %<#pragma acc declare%>", decl);
+	  error = true;
+	  continue;
+	}
 	  break;
 	}
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 15da51e..a35f599 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14343,7 +14343,17 @@ finish_oacc_declare (tree fndecl, tree decls)
  {
 	t = tsi_stmt (i);
 	if (TREE_CODE (t) == BIND_EXPR)
-	  list = BIND_EXPR_BODY (t);
+	  {
+	list = BIND_EXPR_BODY (t);
+	if (TREE_CODE (list) != STATEMENT_LIST)
+	  {
+		stmt = list;
+		list = alloc_stmt_list ();
+		BIND_EXPR_BODY (t) = list;
+		i = tsi_start (list);
+		tsi_link_after (&i, stmt, TSI_CONTINUE_LINKING);
+	  }
+	  }
   }
 
   if (clauses)
@@ -14371,11 +14381,11 @@ finish_oacc_declare (tree fndecl, tree decls)
 	}
 	}
 
-	if (!found)
-	  {
-	i = tsi_start (list);
-	tsi_link_before (&i, stmt, TSI_CONTINUE_LINKING);
-	  }
+  if (!found)
+	{
+	  i = tsi_start (list);
+	  tsi_link_before (&i, stmt, TSI_CONTINUE_LINKING);
+	}
 }
 
 while (oacc_returns)
@@ -14405,18 +14415,21 @@ finish_oacc_declare (tree fndecl, tree decls)
 	free (r);
  }
 
-  for (i = tsi_start (list); !tsi_end_p (i); tsi_next (&i))
+  if (ret_clauses)
 {
-  if (tsi_end_p (i))
-	break;
-}
+  for (i = tsi_start (list); !tsi_end_p (i); tsi_next (&i))
+	{
+	  if (tsi_end_p (i))
+	break;
+	}
 
-  stmt = make_node (OACC_DECLARE);
-  TREE_TYPE (stmt) = void_type_node;
-  OMP_STANDALONE_CLAUSES (stmt) = ret_clauses;
-  SET_EXPR_LOCATION (stmt, loc);
+  stmt = make_node (OACC_DECLARE);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_STANDALONE_CLAUSES (stmt) = ret_clauses;
+  SET_EXPR_LOCATION (stmt, loc);
 
-  tsi_link_before (&i, stmt, TSI_CONTINUE_LINKING);
+  tsi_link_before (&i, stmt, TSI_CONTINUE_LINKING);
+}
 
   DECL_ATTRIBUTES (fndecl)
 	  = remove_attribute ("oacc declare", DECL_ATTRIBUTES (fndecl));
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 78bcb0a1..41fb35e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -32123,6 +32123,14 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
 	  error = true;
 	  continue;
 	}
+	  else if (TREE_PUBLIC (decl))
+	{
+	  error_at (loc,
+			"invalid use of % variable %qD "
+			"in %<#pragma acc declare%>", decl);
+	  error = true;
+	  continue;
+	}
 	  break;
 	}
 
diff --git a/gcc/testsuite/c-c++-common/goacc/declare-2.c b/gcc/testsuite/c-c++-common/goacc/declare-2.c
index ce12463..7979f0c 100644
--- a/gcc/testsuite/c-c++-common/goacc/declare-2.c
+++ b/gcc/testsuite/c-c++-common/goacc/declare-2.c
@@ -63,4 +63,6 @@ f (void)
 
   extern int ve6;
 #pragma acc declare present_or_create(ve6) /* { dg-error "invalid use of" } */
+
+#pragma acc declare present (v9) /* { dg-error "invalid use of" } */
 }
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c
index 59cfe51..584b921 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-1.c
@@ -4,6 +4,26 @@
 #include 
 #include 
 
+#define N 8
+
+void
+subr1 (int *a)
+{
+  int f[N];
+#pragma acc declare copy (f)
+
+#pragma acc parallel copy (a[0:N])
+  {
+int i;
+
+for (i = 0; i < N; i++)
+  {
+	f[i] = a[i];
+	a[i] = f[i] + f[i];
+  }
+  }
+}
+
 int b[8];
 #pragma acc declare create (b)
 
@@ -13,7 +33,6 @@ int d[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
 int
 main (int argc, char **argv)
 {
-  const int N = 8;
   int a[N];
   int e[N];
 #pragma acc declare create (e)
@@ -61,5 +80,18 @@ main (int argc, char **argv)
 	abort ();
 }
 
+  for (i = 0; i < N; i++)
+{
+  a[i] = 1234;
+}
+
+  subr1 (&a[0]);
+
+  for (i = 0; i < N; i++)
+{
+  if (a[i] != 1234 * 2)
+	abort ();
+}
+
   return 0;
 }
diff --git a/libgo

[gomp4] Remove unnecessary conversions

2015-06-29 Thread James Norris

Hi,

This patch removes the conversion of the arguments. As the
arguments are already of the proper type, via the front
ends, there's no need to the conversion. Furthermore, if
the node is a 'const int', then the conversion function
will create a node that can't be used as an argument to
a gimple call.

Committed to gomp-4_0-branch.


Jim
diff --git a/gcc/ChangeLog.gomp b/gcc/ChangeLog.gomp
index 4d449b0..f2b6c4b 100644
--- a/gcc/ChangeLog.gomp
+++ b/gcc/ChangeLog.gomp
@@ -1,3 +1,7 @@
+2015-06-29  James Norris  
+
+	* omp-low.c (expand_omp_target): Remove unnecessary conversion.
+
 2015-06-26  Nathan Sidwell  
 
 	* config/nvptx/nvptx.md (UNSPEC_ID): Rename to ...
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 5914fcf..24fac7c 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -10138,22 +10138,17 @@ expand_omp_target (struct omp_region *region)
 	  = fold_convert_loc (gimple_location (entry_stmt),
 			  integer_type_node, integer_one_node);
 	/* ..., but if present, use the value specified by the respective
-	   clause, making sure that are of the correct type.  */
+	   clause.  */
 	c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
 	if (c)
-	  t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
-	  integer_type_node,
-	  OMP_CLAUSE_NUM_GANGS_EXPR (c));
+	  t_num_gangs = OMP_CLAUSE_NUM_GANGS_EXPR (c);
 	c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
 	if (c)
-	  t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
-	integer_type_node,
-	OMP_CLAUSE_NUM_WORKERS_EXPR (c));
+	  t_num_workers = OMP_CLAUSE_NUM_WORKERS_EXPR (c);
 	c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
 	if (c)
-	  t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
-	  integer_type_node,
-	  OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
+	  t_vector_length = OMP_CLAUSE_VECTOR_LENGTH_EXPR (c);
+	 
 	args.quick_push (t_num_gangs);
 	args.quick_push (t_num_workers);
 	args.quick_push (t_vector_length);


[gomp4] Remove clause from device_type options

2015-07-01 Thread James Norris

Hi,

The independent clause is not available for use
with device_type clauses associated with loop
directives. This patch removes the usage.

Committed to gomp-4_0-branch

Jim
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index bcbd163..88e68ae 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -13069,7 +13069,6 @@ c_parser_oacc_host_data (location_t loc, c_parser *parser)
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR)		\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO)		\
-	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) 	\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ)			\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
 


[gomp4] Fix syntax error

2015-07-01 Thread James Norris

Hi,

The attached patch fixes a syntax error in one of
the OpenACC runtime tests.

Committed to gomp-4_0-branch

Jim
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90
index 3ea9681..1729a3b 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/if-1.f90
@@ -410,7 +410,7 @@ program main
   if (acc_is_present (b) .eqv. .TRUE.) call abort
 #endif
 
-  !$pragma acc enter data copyin (b(1:N)) if (zero == 1)
+  !$acc enter data copyin (b(1:N)) if (zero == 1)
 
 #if !ACC_MEM_SHARED
 if (acc_is_present (b) .eqv. .TRUE.) call abort


[gomp4] Allow parameter declarations with deviceptr

2015-07-01 Thread James Norris

Hi,

This patch allows parameter declarations to be used as
arguments to deviceptr for C and C++.

Committed to gomp-4_0-branch.

Jim
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 88e68ae..dc244ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -10749,7 +10749,7 @@ c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
 	 c_parser_omp_var_list_parens() should construct a list of
 	 locations to go along with the var list.  */
 
-  if (TREE_CODE (v) != VAR_DECL)
+  if (TREE_CODE (v) != VAR_DECL && TREE_CODE (v) != PARM_DECL)
 	error_at (loc, "%qD is not a variable", v);
   else if (TREE_TYPE (v) == error_mark_node)
 	;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 41fb35e..c233595 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28122,7 +28122,7 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list)
 	 c_parser_omp_var_list_parens should construct a list of
 	 locations to go along with the var list.  */
 
-  if (TREE_CODE (v) != VAR_DECL)
+  if (TREE_CODE (v) != VAR_DECL && TREE_CODE (v) != PARM_DECL)
 	error_at (loc, "%qD is not a variable", v);
   else if (TREE_TYPE (v) == error_mark_node)
 	;


[gomp4] Handle deviceptr from an outer directive

2015-07-07 Thread James Norris

Hi,

This patch fixes an issue where the deviceptr clause in an outer
directive was being ignored during implicit variable definition
on a nested directive.

Committed to gomp-4_0-branch.

Jim
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 51aadc0..a721a52 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -116,6 +116,9 @@ enum gimplify_omp_var_data
   /* Gang-local OpenACC variable.  */
   GOVD_GANGLOCAL = (1 << 16),
 
+  /* OpenACC deviceptr clause.  */
+  GOVD_USE_DEVPTR = (1 << 17),
+
   GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
 			   | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
 			   | GOVD_LOCAL)
@@ -6274,7 +6277,10 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 		}
 	  break;
 	}
+
 	  flags = GOVD_MAP | GOVD_EXPLICIT;
+	  if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR)
+	flags |= GOVD_USE_DEVPTR;
 	  goto do_add;
 
 	case OMP_CLAUSE_DEPEND:
@@ -6662,6 +6668,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
 			   : (flags & GOVD_FORCE_MAP
   ? GOMP_MAP_FORCE_TOFROM
   : GOMP_MAP_TOFROM));
+
   if (DECL_SIZE (decl)
 	  && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
 	{
@@ -6687,7 +6694,17 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
 	  OMP_CLAUSE_CHAIN (clause) = nc;
 	}
   else
-	OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
+	{
+	  if (gimplify_omp_ctxp->outer_context)
+	{
+	  struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
+	  splay_tree_node on
+		= splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+	  if (on && (on->value & GOVD_USE_DEVPTR))
+	OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_PRESENT);
+	}
+	  OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
+	}
 }
   if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
 {


  1   2   >