diff mbox

[4/5] OpenACC tile clause support, Fortran front-end parts

Message ID 7467e478-cee5-b694-2988-e6887f25fa17@codesourcery.com
State New
Headers show

Commit Message

Cesar Philippidis Nov. 30, 2016, 1:47 a.m. UTC
On 11/18/2016 03:24 AM, Jakub Jelinek wrote:
> On Sat, Nov 12, 2016 at 08:51:00AM -0800, Cesar Philippidis wrote:

>> On 11/11/2016 02:34 AM, Jakub Jelinek wrote:

>>> On Thu, Nov 10, 2016 at 06:46:46PM +0800, Chung-Lin Tang wrote:

>>

>> And here's the patch.

> 

> The patch doesn't look like OpenACC tile clause fortran support,

> but bind/nohost clause C/C++ support.


I think I got that patch mixed up with the acc routines patch. Here is
the fortran tile clause patch.

One notable difference between the trunk and gomp4 implementation of the
tile clause is that gomp4 errors on negative value tile arguments,
whereas trunk issues warnings. Is there a reason why the fortran FE
generally emits a warning, on say num_threads(-5), instead of an error?

Chung-Lin, I noticed in your source tree that you included a change to
gfortranspec.c. Is that necessary for trunk? I've included in this patch
just in case the other tile patches require it.

Cesar

Comments

Chung-Lin Tang Dec. 14, 2016, 8:37 a.m. UTC | #1
On 2016/11/30 10:47 AM, Cesar Philippidis wrote:
> On 11/18/2016 03:24 AM, Jakub Jelinek wrote:

>> On Sat, Nov 12, 2016 at 08:51:00AM -0800, Cesar Philippidis wrote:

>>> On 11/11/2016 02:34 AM, Jakub Jelinek wrote:

>>>> On Thu, Nov 10, 2016 at 06:46:46PM +0800, Chung-Lin Tang wrote:

>>>

>>> And here's the patch.

>>

>> The patch doesn't look like OpenACC tile clause fortran support,

>> but bind/nohost clause C/C++ support.

> 

> I think I got that patch mixed up with the acc routines patch. Here is

> the fortran tile clause patch.

> 

> One notable difference between the trunk and gomp4 implementation of the

> tile clause is that gomp4 errors on negative value tile arguments,

> whereas trunk issues warnings. Is there a reason why the fortran FE

> generally emits a warning, on say num_threads(-5), instead of an error?

> 

> Chung-Lin, I noticed in your source tree that you included a change to

> gfortranspec.c. Is that necessary for trunk? I've included in this patch

> just in case the other tile patches require it.

> 

> Cesar

> 


About the gfortranspec.c change, that's just a testing artifact, not part of the Fortran FE patch.

Chung-Lin
Chung-Lin Tang Jan. 12, 2017, 11:59 a.m. UTC | #2
[ping]

Hi Jakub,
I don't think we ever got approval for the Fortran parts of the OpenACC tile patch?
Is this okay for trunk? I'll be committing all parts of the patch once the Fortran
parts are approved.

Thanks,
Chung-Lin


On 2016/12/14 04:37 PM, Chung-Lin Tang wrote:
> On 2016/11/30 10:47 AM, Cesar Philippidis wrote:

>> On 11/18/2016 03:24 AM, Jakub Jelinek wrote:

>>> On Sat, Nov 12, 2016 at 08:51:00AM -0800, Cesar Philippidis wrote:

>>>> On 11/11/2016 02:34 AM, Jakub Jelinek wrote:

>>>>> On Thu, Nov 10, 2016 at 06:46:46PM +0800, Chung-Lin Tang wrote:

>>>>

>>>> And here's the patch.

>>>

>>> The patch doesn't look like OpenACC tile clause fortran support,

>>> but bind/nohost clause C/C++ support.

>>

>> I think I got that patch mixed up with the acc routines patch. Here is

>> the fortran tile clause patch.

>>

>> One notable difference between the trunk and gomp4 implementation of the

>> tile clause is that gomp4 errors on negative value tile arguments,

>> whereas trunk issues warnings. Is there a reason why the fortran FE

>> generally emits a warning, on say num_threads(-5), instead of an error?

>>

>> Chung-Lin, I noticed in your source tree that you included a change to

>> gfortranspec.c. Is that necessary for trunk? I've included in this patch

>> just in case the other tile patches require it.

>>

>> Cesar

>>

> 

> About the gfortranspec.c change, that's just a testing artifact, not part of the Fortran FE patch.

> 

> Chung-Lin

>
Jakub Jelinek Jan. 12, 2017, 1:06 p.m. UTC | #3
On Tue, Nov 29, 2016 at 05:47:08PM -0800, Cesar Philippidis wrote:
> On 11/18/2016 03:24 AM, Jakub Jelinek wrote:

> > On Sat, Nov 12, 2016 at 08:51:00AM -0800, Cesar Philippidis wrote:

> >> On 11/11/2016 02:34 AM, Jakub Jelinek wrote:

> >>> On Thu, Nov 10, 2016 at 06:46:46PM +0800, Chung-Lin Tang wrote:

> >>

> >> And here's the patch.

> > 

> > The patch doesn't look like OpenACC tile clause fortran support,

> > but bind/nohost clause C/C++ support.

> 

> I think I got that patch mixed up with the acc routines patch. Here is

> the fortran tile clause patch.

> 

> One notable difference between the trunk and gomp4 implementation of the

> tile clause is that gomp4 errors on negative value tile arguments,

> whereas trunk issues warnings. Is there a reason why the fortran FE

> generally emits a warning, on say num_threads(-5), instead of an error?

> 

> Chung-Lin, I noticed in your source tree that you included a change to

> gfortranspec.c. Is that necessary for trunk? I've included in this patch

> just in case the other tile patches require it.


This is ok for trunk without the gfortranspec.c hunk (please remove it also
from the ChangeLog entry).

> 2016-11-29  Cesar Philippidis  <cesar@codesourcery.com>

> 	    Joseph Myers  <joseph@codesourcery.com>

> 

> 	gcc/fortran/

> 	* gfortranspec.c (lang_specific_pre_link): Update call to do_spec.

> 	* openmp.c (resolve_omp_clauses): Error on directives

> 	containing both tile and collapse clauses.

> 	(resolve_oacc_loop_blocks): Represent '*' tile arguments as zero.

> 	* trans-openmp.c (gfc_trans_omp_do): Lower tiled loops like

>  	collapsed loops.

> 

> 	gcc/testsuite/

> 	* gfortran.dg/goacc/combined-directives.f90: Remove xfail.

> 	* gfortran.dg/goacc/tile-1.f90: New test.

> 	* gfortran.dg/goacc/tile-2.f90: New test.

> 	* gfortran.dg/goacc/tile-lowering.f95: New test.


	Jakub
Thomas Schwinge May 29, 2019, 2:42 p.m. UTC | #4
Hi Jakub!

Any comments on my question, please?

On Tue, 09 Apr 2019 17:51:46 +0200, I wrote:
> On Tue, 29 Nov 2016 17:47:08 -0800, Cesar Philippidis <cesar@codesourcery.com> wrote:

> > One notable difference between the trunk and gomp4 implementation of the

> > tile clause is that gomp4 errors on negative value tile arguments,

> > whereas trunk issues warnings.

> 

> I'm picking up these changes, which have been posted a few times, and

> have been rejected (at least in their current incarnation) a few times,

> too.  ;-\

> 

> > Is there a reason why the fortran FE

> > generally emits a warning, on say num_threads(-5), instead of an error?

> 

> Same for the C/C++ front ends, which I'm looking into first.

> 

> Jakub, is the reason that even if the user is clearly doing something

> "strage" there, the compiler doesn't have a problem to continue

> compilation for 'num_threads(-5)', so it just emits a warning, but for

> example for 'collapse(-5)' is has to stop with an error, because it can't

> continue compilation in that case?  Or, is there a different reason for

> the many 'warning_at ([...], "[...] must be positive"' (C front end, for

> example), instead of using 'error_at' for these?



Grüße
 Thomas
Jakub Jelinek May 29, 2019, 2:52 p.m. UTC | #5
On Wed, May 29, 2019 at 04:42:14PM +0200, Thomas Schwinge wrote:
> Any comments on my question, please?

> 

> On Tue, 09 Apr 2019 17:51:46 +0200, I wrote:

> > On Tue, 29 Nov 2016 17:47:08 -0800, Cesar Philippidis <cesar@codesourcery.com> wrote:

> > > One notable difference between the trunk and gomp4 implementation of the

> > > tile clause is that gomp4 errors on negative value tile arguments,

> > > whereas trunk issues warnings.

> > 

> > I'm picking up these changes, which have been posted a few times, and

> > have been rejected (at least in their current incarnation) a few times,

> > too.  ;-\

> > 

> > > Is there a reason why the fortran FE

> > > generally emits a warning, on say num_threads(-5), instead of an error?

> > 

> > Same for the C/C++ front ends, which I'm looking into first.

> > 

> > Jakub, is the reason that even if the user is clearly doing something

> > "strage" there, the compiler doesn't have a problem to continue

> > compilation for 'num_threads(-5)', so it just emits a warning, but for

> > example for 'collapse(-5)' is has to stop with an error, because it can't

> > continue compilation in that case?  Or, is there a different reason for

> > the many 'warning_at ([...], "[...] must be positive"' (C front end, for

> > example), instead of using 'error_at' for these?


collapse has a constant expression argument and if the value is negative (or
0), then parsing doesn't make sense, so that case is clearly something where
an error is in order.  num_threads is an example of where the standard is
not completely clear if it is or is not ok to reject compilation as opposed
to just UB at runtime if that happens and no problem if that construct is
never encoutered at runtime.

Kind like a C++ difference between:
void
foo ()
{
  constexpr int a = __INT_MAX__ + 1;
  int b = __INT_MAX__ + 1;
}

where for a we need to error, but for b we just warn (by default, of course
one can use -Werror).

	Jakub
Thomas Schwinge June 6, 2019, 8:06 a.m. UTC | #6
Hi Jakub!

On Wed, 29 May 2019 16:52:45 +0200, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, May 29, 2019 at 04:42:14PM +0200, Thomas Schwinge wrote:

> > On Tue, 09 Apr 2019 17:51:46 +0200, I wrote:

> > > On Tue, 29 Nov 2016 17:47:08 -0800, Cesar Philippidis <cesar@codesourcery.com> wrote:

> > > > One notable difference between the trunk and gomp4 implementation of the

> > > > tile clause is that gomp4 errors on negative value tile arguments,

> > > > whereas trunk issues warnings.


> > > > Is there a reason why the fortran FE

> > > > generally emits a warning, on say num_threads(-5), instead of an error?

> > > 

> > > Same for the C/C++ front ends, which I'm looking into first.

> > > 

> > > Jakub, is the reason that even if the user is clearly doing something

> > > "strage" there, the compiler doesn't have a problem to continue

> > > compilation for 'num_threads(-5)', so it just emits a warning, but for

> > > example for 'collapse(-5)' is has to stop with an error, because it can't

> > > continue compilation in that case?  Or, is there a different reason for

> > > the many 'warning_at ([...], "[...] must be positive"' (C front end, for

> > > example), instead of using 'error_at' for these?

> 

> collapse has a constant expression argument and if the value is negative (or

> 0), then parsing doesn't make sense, so that case is clearly something where

> an error is in order.  num_threads is an example of where the standard is

> not completely clear if it is or is not ok to reject compilation as opposed

> to just UB at runtime if that happens and no problem if that construct is

> never encoutered at runtime.


Thanks, so that matches my understanding, and we shall thus retract the
OpenACC "update gfortran's tile clause error handling" patch, that got
posted several times in several variations.


Later, we shall audit all front end clauses handling to make sure that
this is done consistently.


Grüße
 Thomas
diff mbox

Patch

2016-11-29  Cesar Philippidis  <cesar@codesourcery.com>
	    Joseph Myers  <joseph@codesourcery.com>

	gcc/fortran/
	* gfortranspec.c (lang_specific_pre_link): Update call to do_spec.
	* openmp.c (resolve_omp_clauses): Error on directives
	containing both tile and collapse clauses.
	(resolve_oacc_loop_blocks): Represent '*' tile arguments as zero.
	* trans-openmp.c (gfc_trans_omp_do): Lower tiled loops like
 	collapsed loops.

	gcc/testsuite/
	* gfortran.dg/goacc/combined-directives.f90: Remove xfail.
	* gfortran.dg/goacc/tile-1.f90: New test.
	* gfortran.dg/goacc/tile-2.f90: New test.
	* gfortran.dg/goacc/tile-lowering.f95: New test.


diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c
index 8a0e19a..6dc6fbe 100644
--- a/gcc/fortran/gfortranspec.c
+++ b/gcc/fortran/gfortranspec.c
@@ -439,7 +439,7 @@  int
 lang_specific_pre_link (void)
 {
   if (library)
-    do_spec ("%:include(libgfortran.spec)");
+    do_spec ("%:include(libgfortran.spec)", 0);
 
   return 0;
 }
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 11ffb5d..81f758e 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -4757,6 +4757,8 @@  resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
     if (omp_clauses->wait_list)
       for (el = omp_clauses->wait_list; el; el = el->next)
 	resolve_scalar_int_expr (el->expr, "WAIT");
+  if (omp_clauses->collapse && omp_clauses->tile_list)
+    gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
   if (omp_clauses->depend_source && code->op != EXEC_OMP_ORDERED)
     gfc_error ("SOURCE dependence type only allowed "
 	       "on ORDERED directive at %L", &code->loc);
@@ -5903,11 +5905,11 @@  resolve_oacc_loop_blocks (gfc_code *code)
 	  if (el->expr == NULL)
 	    {
 	      /* NULL expressions are used to represent '*' arguments.
-		 Convert those to a -1 expressions.  */
+		 Convert those to a 0 expressions.  */
 	      el->expr = gfc_get_constant_expr (BT_INTEGER,
 						gfc_default_integer_kind,
 						&code->loc);
-	      mpz_set_si (el->expr->value.integer, -1);
+	      mpz_set_si (el->expr->value.integer, 0);
 	    }
 	  else
 	    {
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 59fd6b3..d38bebc 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -3455,6 +3455,17 @@  gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
   dovar_init *di;
   unsigned ix;
   vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
+  gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list;
+
+  /* Both collapsed and tiled loops are lowered the same way.  In
+     OpenACC, those clauses are not compatible, so prioritize the tile
+     clause, if present.  */
+  if (tile)
+    {
+      collapse = 0;
+      for (gfc_expr_list *el = tile; el; el = el->next)
+	collapse++;
+    }
 
   doacross_steps = NULL;
   if (clauses->orderedc)
diff --git a/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90 b/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90
index abb5e6b..42a447a 100644
--- a/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90
@@ -143,8 +143,7 @@  end subroutine test
 ! { dg-final { scan-tree-dump-times "acc loop private.i. private.j. vector" 2 "gimple" } }
 ! { dg-final { scan-tree-dump-times "acc loop private.i. private.j. seq" 2 "gimple" } }
 ! { dg-final { scan-tree-dump-times "acc loop private.i. private.j. auto" 2 "gimple" } }
-! XFAILed: OpenACC tile clauses are discarded during gimplification.
-! { dg-final { scan-tree-dump-times "acc loop private.i. private.j. tile.2, 3" 2 "gimple" { xfail *-*-* } } }
+! { dg-final { scan-tree-dump-times "acc loop private.i. private.j. tile.2, 3" 2 "gimple" } }
 ! { dg-final { scan-tree-dump-times "acc loop private.i. independent" 2 "gimple" } }
 ! { dg-final { scan-tree-dump-times "private.z" 2 "gimple" } }
 ! { dg-final { scan-tree-dump-times "omp target oacc_\[^ \]+ map.force_tofrom:y" 2 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/tile-1.f90 b/gcc/testsuite/gfortran.dg/goacc/tile-1.f90
new file mode 100644
index 0000000..3dbabda
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/tile-1.f90
@@ -0,0 +1,339 @@ 
+subroutine parloop
+  integer, parameter :: n = 100
+  integer i, j, k, a
+
+  !$acc parallel loop tile(10)
+  do i = 1, n
+  end do
+  
+  !$acc parallel loop tile(*)
+  do i = 1, n
+  end do
+
+  !$acc parallel loop tile(10, *)
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+ 
+  !$acc parallel loop tile(10, *, i) ! { dg-error "" }
+  do i = 1, n
+     do j = 1, n
+        do k = 1, n
+        end do
+     end do
+  end do 
+
+  !$acc parallel loop tile ! { dg-error "Unclassifiable" }
+  do i = 1, n
+  end do
+
+  !$acc parallel loop tile() ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc parallel loop tile(,1) ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc parallel loop tile(,,) ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc parallel loop tile(1.1) ! { dg-error "requires a scalar INTEGER" }
+  do i = 1, n
+  end do
+
+  !$acc parallel loop tile(-3) ! { dg-warning "must be positive" }
+  do i = 1, n
+  end do
+
+  !$acc parallel loop tile(10, -3) ! { dg-warning "must be positive" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc parallel loop tile(-100, 10, 5) ! { dg-warning "must be positive" }
+  do i = 1, n
+     do j = 1, n
+        do k = 1, n
+        end do
+     end do
+  end do 
+
+  !$acc parallel loop tile(10, .true.) ! { dg-error "requires a scalar" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc parallel loop tile(1, a) ! { dg-error "constant expression" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc parallel loop tile(a, 1) ! { dg-error "constant expression" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc parallel loop tile(2, 3) collapse (2) ! { dg-error "Incompatible use" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+end subroutine parloop
+
+subroutine par
+  integer, parameter :: n = 100
+  integer i, j, k
+
+  !$acc parallel
+  !$acc loop tile ! { dg-error "Unclassifiable" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile() ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile(1)
+  do i = 1, n
+  end do
+
+  !$acc loop tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop tile(2)
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc loop tile(-2) ! { dg-warning "must be positive" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile(i) ! { dg-error "constant expression" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile(2, 2, 1)
+  do i = 1, n
+     do j = 1, n
+        do k = 1, n
+        end do
+     end do
+  end do 
+
+  !$acc parallel loop tile(2, 2)
+  do i = 1, n
+     do j = i+1, n, j ! { dg-error "rectangular iteration space" }
+     end do
+  end do
+
+  !$acc loop vector tile(*)
+  do i = 1, n
+  end do
+  
+  !$acc loop worker tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop gang tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop vector gang tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop vector worker tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop gang worker tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop tile(2, 3) collapse (2) ! { dg-error "Incompatible use" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+  !$acc end parallel
+end subroutine par
+
+subroutine kern
+  integer, parameter :: n = 100
+  integer i, j, k
+
+  !$acc kernels
+  !$acc loop tile  ! { dg-error "Unclassifiable" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile() ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile(1)
+  do i = 1, n
+  end do
+
+  !$acc loop tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop tile(2)
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc loop tile(-2) ! { dg-warning "must be positive" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile(i) ! { dg-error "constant expression" }
+  do i = 1, n
+  end do
+
+  !$acc loop tile(2, 2, 1)
+  do i = 1, n
+     do j = 1, n
+        do k = 1, n
+        end do
+     end do
+  end do 
+
+  !$acc parallel loop tile(2, 2)
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc loop vector tile(*)
+  do i = 1, n
+  end do
+  
+  !$acc loop worker tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop gang tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop vector gang tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop vector worker tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop gang worker tile(*)
+  do i = 1, n
+  end do
+
+  !$acc loop tile(2, 3) collapse (2) ! { dg-error "Incompatible use" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+  !$acc end kernels
+end subroutine kern
+
+subroutine kernsloop
+  integer, parameter :: n = 100
+  integer i, j, k, a
+
+  !$acc kernels loop tile(10)
+  do i = 1, n
+  end do
+  
+  !$acc kernels loop tile(*)
+  do i = 1, n
+  end do
+
+  !$acc kernels loop tile(10, *)
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+ 
+  !$acc kernels loop tile(10, *, i) ! { dg-error "" }
+  do i = 1, n
+     do j = 1, n
+        do k = 1, n
+        end do
+     end do
+  end do 
+
+  !$acc kernels loop tile ! { dg-error "Unclassifiable" }
+  do i = 1, n
+  end do
+
+  !$acc kernels loop tile() ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc kernels loop tile(,1) ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc kernels loop tile(,,) ! { dg-error "Syntax error" }
+  do i = 1, n
+  end do
+
+  !$acc kernels loop tile(1.1) ! { dg-error "requires a scalar INTEGER" }
+  do i = 1, n
+  end do
+
+  !$acc kernels loop tile(-3) ! { dg-warning "must be positive" }
+  do i = 1, n
+  end do
+
+  !$acc kernels loop tile(10, -3) ! { dg-warning "must be positive" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc kernels loop tile(-100, 10, 5) ! { dg-warning "must be positive" }
+  do i = 1, n
+     do j = 1, n
+        do k = 1, n
+        end do
+     end do
+  end do 
+
+  !$acc kernels loop tile(10, .true.) ! { dg-error "requires a scalar" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc kernels loop tile(1, a) ! { dg-error "constant expression" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc kernels loop tile(a, 1) ! { dg-error "constant expression" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+
+  !$acc kernels loop tile(2, 3) collapse (2) ! { dg-error "Incompatible use" }
+  do i = 1, n
+     do j = 1, n
+     end do
+  end do
+end subroutine kernsloop
diff --git a/gcc/testsuite/gfortran.dg/goacc/tile-2.f90 b/gcc/testsuite/gfortran.dg/goacc/tile-2.f90
new file mode 100644
index 0000000..c567543
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/tile-2.f90
@@ -0,0 +1,21 @@ 
+subroutine par
+  integer ix, jx
+
+  !$acc parallel
+  !$acc loop tile (*,*) ! { dg-error "not enough DO loops for tiled" }
+  do ix = 1, 30
+  end do
+
+  !$acc loop tile (*,*)
+  do ix = 1, 30
+     do jx = 1, ix ! { dg-error "tiled loops don.t form rectangular" }
+     end do
+  end do
+
+  !$acc loop tile (*)
+  do ix = 1, 30
+     do jx = 1, ix
+     end do
+  end do
+  !$acc end parallel
+end subroutine par
diff --git a/gcc/testsuite/gfortran.dg/goacc/tile-lowering.f95 b/gcc/testsuite/gfortran.dg/goacc/tile-lowering.f95
new file mode 100644
index 0000000..1cb8b9c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/tile-lowering.f95
@@ -0,0 +1,292 @@ 
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+subroutine par
+  integer i, j, k
+
+  !$acc parallel
+  !$acc loop tile (1)
+  do i = 1, 10
+  end do
+
+  !$acc loop tile (*)
+  do i = 1, 10
+  end do
+
+  !$acc loop tile (1,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (*,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (1,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (*,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (1,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc loop tile (*,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc loop tile (1,*,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc loop tile (1,2,*)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+  !$acc end parallel
+end subroutine par
+
+subroutine kerns
+  integer i, j, k
+
+  !$acc kernels
+  !$acc loop tile (1)
+  do i = 1, 10
+  end do
+
+  !$acc loop tile (*)
+  do i = 1, 10
+  end do
+
+  !$acc loop tile (1,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (*,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (1,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (*,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc loop tile (1,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc loop tile (*,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc loop tile (1,*,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc loop tile (1,2,*)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+  !$acc end kernels
+end subroutine kerns
+
+subroutine parloop
+  integer i, j, k
+
+  !$acc parallel loop tile (1)
+  do i = 1, 10
+  end do
+
+  !$acc parallel loop tile (*)
+  do i = 1, 10
+  end do
+
+  !$acc parallel loop tile (1,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc parallel loop tile (*,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc parallel loop tile (1,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc parallel loop tile (*,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc parallel loop tile (1,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc parallel loop tile (*,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc parallel loop tile (1,*,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc parallel loop tile (1,2,*)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+end subroutine parloop
+
+subroutine kernloop
+  integer i, j, k
+
+  !$acc kernels loop tile (1)
+  do i = 1, 10
+  end do
+
+  !$acc kernels loop tile (*)
+  do i = 1, 10
+  end do
+
+  !$acc kernels loop tile (1,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc kernels loop tile (*,2)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc kernels loop tile (1,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc kernels loop tile (*,*)
+  do i = 1, 10
+     do j = 1, 10
+     end do
+  end do
+
+  !$acc kernels loop tile (1,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc kernels loop tile (*,2,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc kernels loop tile (1,*,3)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+
+  !$acc kernels loop tile (1,2,*)
+  do i = 1, 10
+     do j = 1, 10
+        do k = 1, 10
+        end do
+     end do
+  end do
+end subroutine kernloop
+
+
+! { dg-final { scan-tree-dump-times "tile\\(1\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(0\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(1, 2\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(0, 2\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(1, 0\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(0, 0\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(1, 2, 3\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(0, 2, 3\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(1, 0, 3\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "tile\\(1, 2, 0\\)" 4 "original" } }
+! { dg-final { scan-tree-dump-times "for \\(" 88 "original" } }
+! { dg-final { scan-tree-dump-times "while \\(" 0 "original" } }