Re: Async I/O patch with compilation fix

2018-08-02 Thread Nicolas Koenig
On Thu, Aug 02, 2018 at 05:42:46PM +0200, Christophe Lyon wrote:
> On Thu, 2 Aug 2018 at 13:35, Nicolas Koenig  wrote:
> >
> >
> > Hello everyone,
> >
> > Here is an updated version of the patch that hopefully fixes the compilation
> > problems by disabling async I/O if conditions are not supported by the 
> > target.
> >
> > I would appreciate if people could test it on systems on which it failed
> > before. As for the array_constructor_8.f90 failure reported in the PR, why
> > it fails is beyond me, it doesn't even use I/O. Maybe/Probably something
> > unrelated?
> >
> 
> Hi,
> I'm probably missing something obvious, but after applying this patch
> on top of r263136, the builds fail while building libgfortran:
> /tmp/9271913_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgfortran/runtime/error.c:28:10:
> fatal error: async.h: No such file or directory
>  #include "async.h"
>   ^
> compilation terminated.
> make[3]: *** [error.lo] Error 1
> 

Hi,

It wasn't you who missed something obvious. Typing `svn add` is hard.
Here is a version of the patch with the two new files.

Nicolas

> > Nicolas
> >
> >
> > 2018-08-02  Nicolas Koenig  
> > Thomas Koenig 
> >
> > PR fortran/25829
> > * gfortran.texi: Add description of asynchronous I/O.
> > * trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
> > as volatile.
> > * trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
> > st_wait_async and change argument spec from ".X" to ".w".
> > (gfc_trans_wait): Pass ID argument via reference.
> >
> > 2018-08-02  Nicolas Koenig  
> > Thomas Koenig 
> >
> > PR fortran/25829
> > * gfortran.dg/f2003_inquire_1.f03: Add write statement.
> > * gfortran.dg/f2003_io_1.f03: Add wait statement.
> >
> > 2018-08-02  Nicolas Koenig  
> > Thomas Koenig 
> >
> > PR fortran/25829
> > * Makefile.am: Add async.c to gfor_io_src.
> > Add async.h to gfor_io_headers.
> > * Makefile.in: Regenerated.
> > * gfortran.map: Add _gfortran_st_wait_async.
> > * io/async.c: New file.
> > * io/async.h: New file.
> > * io/close.c: Include async.h.
> > (st_close): Call async_wait for an asynchronous unit.
> > * io/file_pos.c (st_backspace): Likewise.
> > (st_endfile): Likewise.
> > (st_rewind): Likewise.
> > (st_flush): Likewise.
> > * io/inquire.c: Add handling for asynchronous PENDING
> > and ID arguments.
> > * io/io.h (st_parameter_dt): Add async bit.
> > (st_parameter_wait): Correct.
> > (gfc_unit): Add au pointer.
> > (st_wait_async): Add prototype.
> > (transfer_array_inner): Likewise.
> > (st_write_done_worker): Likewise.
> > * io/open.c: Include async.h.
> > (new_unit): Initialize asynchronous unit.
> > * io/transfer.c (async_opt): New struct.
> > (wrap_scalar_transfer): New function.
> > (transfer_integer): Call wrap_scalar_transfer to do the work.
> > (transfer_real): Likewise.
> > (transfer_real_write): Likewise.
> > (transfer_character): Likewise.
> > (transfer_character_wide): Likewise.
> > (transfer_complex): Likewise.
> > (transfer_array_inner): New function.
> > (transfer_array): Call transfer_array_inner.
> > (transfer_derived): Call wrap_scalar_transfer.
> > (data_transfer_init): Check for asynchronous I/O.
> > Perform a wait operation on any pending asynchronous I/O
> > if the data transfer is synchronous. Copy PDT and enqueue
> > thread for data transfer.
> > (st_read_done_worker): New function.
> > (st_read_done): Enqueue transfer or call st_read_done_worker.
> > (st_write_done_worker): New function.
> > (st_write_done): Enqueue transfer or call st_read_done_worker.
> > (st_wait): Document as no-op for compatibility reasons.
> > (st_wait_async): New function.
> > * io/unit.c (insert_unit): Use macros LOCK, UNLOCK and TRYLOCK;
> > add NOTE where necessary.
> > (get_gfc_unit): Likewise.
> >     (init_units): Likewise.
> > (close_unit_1): Likewise. Call async_close if asynchronous.
> > (close_unit):

Async I/O patch with compilation fix

2018-08-02 Thread Nicolas Koenig

Hello everyone,

Here is an updated version of the patch that hopefully fixes the compilation
problems by disabling async I/O if conditions are not supported by the target.

I would appreciate if people could test it on systems on which it failed 
before. As for the array_constructor_8.f90 failure reported in the PR, why
it fails is beyond me, it doesn't even use I/O. Maybe/Probably something
unrelated?

Nicolas


2018-08-02  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* gfortran.texi: Add description of asynchronous I/O.
* trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
as volatile.
* trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
st_wait_async and change argument spec from ".X" to ".w".
(gfc_trans_wait): Pass ID argument via reference.

2018-08-02  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* gfortran.dg/f2003_inquire_1.f03: Add write statement.
* gfortran.dg/f2003_io_1.f03: Add wait statement.

2018-08-02  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* Makefile.am: Add async.c to gfor_io_src.
Add async.h to gfor_io_headers.
* Makefile.in: Regenerated.
* gfortran.map: Add _gfortran_st_wait_async.
* io/async.c: New file.
* io/async.h: New file.
* io/close.c: Include async.h.
(st_close): Call async_wait for an asynchronous unit.
* io/file_pos.c (st_backspace): Likewise.
(st_endfile): Likewise.
(st_rewind): Likewise.
(st_flush): Likewise.
* io/inquire.c: Add handling for asynchronous PENDING
and ID arguments.
* io/io.h (st_parameter_dt): Add async bit.
(st_parameter_wait): Correct.
(gfc_unit): Add au pointer.
(st_wait_async): Add prototype.
(transfer_array_inner): Likewise.
(st_write_done_worker): Likewise.
* io/open.c: Include async.h.
(new_unit): Initialize asynchronous unit.
* io/transfer.c (async_opt): New struct.
(wrap_scalar_transfer): New function.
(transfer_integer): Call wrap_scalar_transfer to do the work.
(transfer_real): Likewise.
(transfer_real_write): Likewise.
(transfer_character): Likewise.
(transfer_character_wide): Likewise.
(transfer_complex): Likewise.
(transfer_array_inner): New function.
(transfer_array): Call transfer_array_inner.
(transfer_derived): Call wrap_scalar_transfer.
(data_transfer_init): Check for asynchronous I/O.
Perform a wait operation on any pending asynchronous I/O
if the data transfer is synchronous. Copy PDT and enqueue
thread for data transfer.
(st_read_done_worker): New function.
(st_read_done): Enqueue transfer or call st_read_done_worker.
(st_write_done_worker): New function.
(st_write_done): Enqueue transfer or call st_read_done_worker.
(st_wait): Document as no-op for compatibility reasons.
(st_wait_async): New function.
* io/unit.c (insert_unit): Use macros LOCK, UNLOCK and TRYLOCK;
add NOTE where necessary.
(get_gfc_unit): Likewise.
(init_units): Likewise.
(close_unit_1): Likewise. Call async_close if asynchronous.
(close_unit): Use macros LOCK and UNLOCK.
(finish_last_advance_record): Likewise.
(newunit_alloc): Likewise.
* io/unix.c (find_file): Likewise.
(flush_all_units_1): Likewise.
(flush_all_units): Likewise.
* libgfortran.h (generate_error_common): Add prototype.
* runtime/error.c: Include io.h and async.h.
(generate_error_common): New function.

2018-08-02  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* testsuite/libgomp.fortran/async_io_1.f90: New test.
* testsuite/libgomp.fortran/async_io_2.f90: New test.
* testsuite/libgomp.fortran/async_io_3.f90: New test.
* testsuite/libgomp.fortran/async_io_4.f90: New test.
* testsuite/libgomp.fortran/async_io_5.f90: New test.
* testsuite/libgomp.fortran/async_io_6.f90: New test.
* testsuite/libgomp.fortran/async_io_7.f90: New test.
Index: gcc/fortran/gfortran.texi
===
--- gcc/fortran/gfortran.texi	(revision 263244)
+++ gcc/fortran/gfortran.texi	(working copy)
@@ -879,8 +879,7 @@ than @code{(/.../)}.  Type-specification for array
 @item Extensions to the specification and initialization expressions,
 including the support for intrinsics with real and complex arguments.
 
-@item Support for the asynchronous input/output syntax; however, the
-data transfer is currently always synchronously performed. 
+@item Support for the asynchronous input/output.
 
 @item
 @cindex @code{FLUSH} statement
@@ -1183,6 +1182,7 @@ might in some way or an

[patch, fortran] PR25829 Asynchronous I/O (patch version 2.0)

2018-06-16 Thread Nicolas Koenig

Hey everyone,

Here is the next version of the async I/O patch. It adds the 
documentation, renames the testcases, uses "gthr.h", follows the style 
guidelines and has been regression tested cleanly.


As for adding additional flags, I think it would be better to follow 
ifort to minimize complexity.


The benchmark (not for the test suite) should also run on systems with
small stack sizes.

I hope I forgot nothing.
Nicolas


2018-06-16  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* gfortran.texi: Add description of asynchronous I/O.
* trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
as volatile.
* trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
st_wait_async and change argument spec from ".X" to ".w".
(gfc_trans_wait): Pass ID argument via reference.

2018-06-16  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* gfortran.dg/f2003_inquire_1.f03: Add write statement.
* gfortran.dg/f2003_io_1.f03: Add wait statement.

2018-06-16  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* Makefile.am: Add async.c to gfor_io_src.
Add async.h to gfor_io_headers.
* Makefile.in: Regenerated.
* gfortran.map: Add _gfortran_st_wait_async.
* io/async.c: New file.
* io/async.h: New file.
* io/close.c: Include async.h.
(st_close): Call async_wait for an asynchronous unit.
* io/file_pos.c (st_backspace): Likewise.
(st_endfile): Likewise.
(st_rewind): Likewise.
(st_flush): Likewise.
* io/inquire.c: Add handling for asynchronous PENDING
and ID arguments.
* io/io.h (st_parameter_dt): Add async bit.
(st_parameter_wait): Correct.
(gfc_unit): Add au pointer.
(st_wait_async): Add prototype.
(transfer_array_inner): Likewise.
(st_write_done_worker): Likewise.
* io/open.c: Include async.h.
(new_unit): Initialize asynchronous unit.
* io/transfer.c (async_opt): New struct.
(wrap_scalar_transfer): New function.
(transfer_integer): Call wrap_scalar_transfer to do the work.
(transfer_real): Likewise.
(transfer_real_write): Likewise.
(transfer_character): Likewise.
(transfer_character_wide): Likewise.
(transfer_complex): Likewise.
(transfer_array_inner): New function.
(transfer_array): Call transfer_array_inner.
(transfer_derived): Call wrap_scalar_transfer.
(data_transfer_init): Check for asynchronous I/O.
Perform a wait operation on any pending asynchronous I/O
if the data transfer is synchronous. Copy PDT and enqueue
thread for data transfer.
(st_read_done_worker): New function.
(st_read_done): Enqueue transfer or call st_read_done_worker.
(st_write_done_worker): New function.
(st_write_done): Enqueue transfer or call st_read_done_worker.
(st_wait): Document as no-op for compatibility reasons.
(st_wait_async): New function.
* io/unit.c (insert_unit): Use macros LOCK, UNLOCK and TRYLOCK;
add NOTE where necessary.
(get_gfc_unit): Likewise.
(init_units): Likewise.
(close_unit_1): Likewise. Call async_close if asynchronous.
(close_unit): Use macros LOCK and UNLOCK.
(finish_last_advance_record): Likewise.
(newunit_alloc): Likewise.
* io/unix.c (find_file): Likewise.
(flush_all_units_1): Likewise.
(flush_all_units): Likewise.
* libgfortran.h (generate_error_common): Add prototype.
* runtime/error.c: Include io.h and async.h.
(generate_error_common): New function.

2018-06-16  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* testsuite/libgfomp.fortran/async_io_1.f90: New test.
* testsuite/libgfomp.fortran/async_io_2.f90: New test.
* testsuite/libgfomp.fortran/async_io_3.f90: New test.
program main
  implicit none
  integer, parameter :: n = 10**7
  character(3), parameter :: yes = "yes"
  real, dimension(:), allocatable :: a,b,c

  allocate (a(n), b(n), c(n))
  call random_number(a)
  call random_number(b)
  call random_number(c)
  open (10, file="a.dat",asynchronous=yes)
  open (20, file="b.dat",asynchronous=yes)
  open (30, file="c.dat",asynchronous=yes)
  write (10,*,asynchronous=yes) a
  write (20,*,asynchronous=yes) b
  write (30,*,asynchronous=yes) c
  wait (10)
  wait (20)
  wait (30)
end program main
! { dg-do run }
! Check basic functionality of async I/O
program main
  implicit none
  integer:: i=1, j=2, k, l
  real :: a, b, c, d
  character(3), parameter:: yes="yes"
  character(4) :: str
  complex :: cc, dd
  integer, dimension(4):: is = [0, 1, 2, 3]
  integer, dimension(4):: res
  character(10) :: inq

  open (

Re: [Patch, Fortran] PR25829: Asynchronous I/O (v2)

2018-06-04 Thread Nicolas Koenig

Hi Dominique and Rainer,

First of all thanks for testing!


Hi Dominique, Nicolas,


I have applied your patch on top of revision r261130 on
x86_64-apple-darwin17 (SSD with APFS file system).


I've tried it on i386-pc-solaris2.11 and sparc-sun-solaris2.11.


I also see two regressions

FAIL: gfortran.dg/f2003_inquire_1.f03   -O1  execution test

only with -m32 and -O1 (STOP 5), and


It fails for me at -O[0s] (i386) resp. -O[01] (sparc), 64-bit only.


This seems to be a bug in the test suite. It tries to find out whether 
an id is pending that is never initialized.





FAIL: gfortran.dg/f2003_io_1.f03   -O*

with both -m32 and -m64 (STOP 1).


Same here: FAILs at -O[0-3s] for both 32 and 64-bit.


And another bug in the test suite. This time the wait after the read is 
missing.





The is also typos for the added tests

s/libgfomp/libgomp/


Will fix.



Why do the tests start at asynchronous_6.f90?


Because they were originally intended for the gfortran test suite, but I 
couldn't run it there because of libpthread. I will change the numbering 
scheme.




... and asynchronous_9.f90 is missing from the ChangeLog, which
..._7.f90 is missing from the sequence.



asynchronous_7.f90 is a test for an error, but dg-shouldfail is not 
working in libgomp. Dominique is looking into this.



Besides, I see

+FAIL: libgomp.fortran/asynchronous_6.f90   -O1  execution test

STOP 2

32-bit i386 only.



I have trouble replicating this bug even with -m32. Could you get some 
more debugging info for the test on your machine?



+FAIL: libgomp.fortran/asynchronous_9.f90   -O  execution test

32 and 64-bit i386 and sparc, no error message.



This file wasn't supposed to be a test case, that's why it is not in the 
ChangeLog. It is a benchmark program, so it takes some time. Maybe a 
time out? Could you maybe try running it outside the test suite?



Rainer



Dominique wrote:
> "Treat asynchronous variables the same as volatile, for now." could 
probably simplified as

> "Treat asynchronous variables as volatile, for now."

Will do.

>
> I also wonder if
>
> +wrap_scalar_transfer (dtp, BT_INTEGER, p, kind, kind, 1);
>
> is correct without a cast to size_t for the last two arguments (and 
for the last argument in other instances). Note that I am C challenged, 
so forgive the question if it is stupid.


It atomatically casts based on the type information in the prototype in 
io.h.


>
> Thanks for the nice work.

With pleasure! :)

>
> Dominique


[Patch, Fortran] PR25829: Asynchronous I/O

2018-06-03 Thread Nicolas Koenig

Hello everyone,

this patch adds asynchronous I/O support. Thomas and I finally finished 
a feature-complete and debugged version, so here it is. In order to use 
asynchronous I/O, it is still necessary to link against libpthread, 
libgomp or another library linked against any of the aforementioned two. 
While it might not be the nicest way, it at least keeps in line with the 
likes of ifort. Two of the test I send deal with asynchronous error 
handling, so they will fail if not linked accordingly.


Since the implementation relies on pthreads, it would be great if 
somebody could try the patch on non-linux targets, to see whether it 
causes any problems there.


Let the rain of regressions begin ;)

Nicolas

P.S.: I would very much recommend removing the #undef DEBUG in async.h. 
I have to admit, I am quite proud of the debug printouts. They even 
build a data structure in the background telling you were a locked mutex 
was locked.



Regression tested cleanly on x86_64-pc-linux-gnu.

2018-06-03  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
as volatile.
* trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
st_wait_async and change argument spec from ".X" to ".w".
(gfc_trans_wait): Pass ID argument via reference.

2018-06-03  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* Makefile.am: Add async.c to gfor_io_src.
Add async.h to gfor_io_headers.
* Makefile.in: Regenerated.
* gfortran.map: Add _gfortran_st_wait_async.
* io/async.c: New file.
* io/async.h: New file.
* io/close.c: Include async.h.
(st_close): Call async_wait for an asynchronous unit.
* io/file_pos.c (st_backspace): Likewise.
(st_endfile): Likewise.
(st_rewind): Likewise.
(st_flush): Likewise.
* io/inquire.c: Add handling for asynchronous PENDING
and ID arguments.
* io/io.h (st_parameter_dt): Add async bit.
(st_parameter_wait): Correct.
(gfc_unit): Add au pointer.
(st_wait_async): Add prototype.
(transfer_array_inner): Likewise.
(st_write_done_worker): Likewise.
* io/open.c: Include async.h.
(new_unit): Initialize asynchronous unit.
* io/transfer.c (async_opt): New struct.
(wrap_scalar_transfer): New function.
(transfer_integer): Call wrap_scalar_transfer to do the work.
(transfer_real): Likewise.
(transfer_real_write): Likewise.
(transfer_character): Likewise.
(transfer_character_wide): Likewise.
(transfer_complex): Likewise.
(transfer_array_inner): New function.
(transfer_array): Call transfer_array_inner.
(transfer_derived): Call wrap_scalar_transfer.
(data_transfer_init): Check for asynchronous I/O.
Perform a wait operation on any pending asynchronous I/O
if the data transfer is synchronous. Copy PDT and enqueue
thread for data transfer.
(st_read_done_worker): New function.
(st_read_done): Enqueue transfer or call st_read_done_worker.
(st_write_done_worker): New function.
(st_write_done): Enqueue transfer or call st_read_done_worker.
(st_wait): Document as no-op for compatibility reasons.
(st_wait_async): New function.
* io/unit.c (insert_unit): Use macros LOCK, UNLOCK and TRYLOCK;
add NOTE where necessary.
(get_gfc_unit): Likewise.
(init_units): Likewise.
(close_unit_1): Likewise. Call async_close if asynchronous.
(close_unit): Use macros LOCK and UNLOCK.
(finish_last_advance_record): Likewise.
(newunit_alloc): Likewise.
* io/unix.c (find_file): Likewise.
(flush_all_units_1): Likewise.
(flush_all_units): Likewise.
* libgfortran.h (generate_error_common): Add prototype.
* runtime/error.c: Include io.h and async.h.
(generate_error_common): New function.

2018-06-03  Nicolas Koenig  
Thomas Koenig 

PR fortran/25829
* testsuite/libgfomp.fortran/asynchronous_6.f90: New test.
* testsuite/libgfomp.fortran/asynchronous_8.f90: New test.

Index: gcc/fortran/trans-decl.c
===
--- gcc/fortran/trans-decl.c	(Revision 259739)
+++ gcc/fortran/trans-decl.c	(Arbeitskopie)
@@ -699,7 +699,8 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
 	  && CLASS_DATA (sym)->ts.u.derived->attr.has_dtio_procs)))
 TREE_STATIC (decl) = 1;
 
-  if (sym->attr.volatile_)
+  /* Treat asynchronous variables the same as volatile, for now.  */
+  if (sym->attr.volatile_ || sym->attr.asynchronous)
 {
   TREE_THIS_VOLATILE (decl) = 1;
   TREE_SIDE_EFFECT

[patch, rfc] Fortran async I/O support

2018-05-21 Thread Nicolas Koenig
 --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT associated.lo -MD -MP -MF $(DEPDIR)/associated.Tpo -c -o associated.lo `test -f 'intrinsics/associated.c' || echo '$(srcdir)/'`intrinsics/associated.c
 @am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/associated.Tpo $(DEPDIR)/associated.Plo
Index: libgfortran/io/async.c
===
--- libgfortran/io/async.c	(nicht existent)
+++ libgfortran/io/async.c	(Arbeitskopie)
@@ -0,0 +1,380 @@
+/* Copyright (C) 2018 Free Software Foundation, Inc.
+   Contributed by Nicolas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran 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.
+
+Libgfortran 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
+<http://www.gnu.org/licenses/>.  */
+
+#define _GTHREAD_USE_COND_INIT_FUNC
+#include "../../libgcc/gthr-posix.h"
+#include "io.h"
+#include "fbuf.h"
+#include "format.h"
+#include "unix.h"
+#include 
+#include 
+
+#include 
+
+#include "async.h"
+
+DEBUG_LINE(__thread const char *aio_prefix = MPREFIX);
+
+__thread gfc_unit *thread_unit = NULL;
+
+typedef struct transfer_queue
+{
+  enum aio_do type;
+  struct transfer_queue *next;
+  struct st_parameter_dt *new_pdt;
+  transfer_args arg;
+  _Bool has_id;
+} transfer_queue;
+
+struct error {
+  st_parameter_dt *dtp;
+  int id;
+};
+
+static void
+update_pdt(st_parameter_dt **old, st_parameter_dt *new) {
+  st_parameter_dt *temp;
+  NOTE("Changing pdts");
+  temp = *old;
+  *old = new;
+  if(temp)
+free(temp);
+}
+
+static void
+destroy_adv_cond (struct adv_cond * ac)
+{
+  T_ERROR (__gthread_mutex_destroy, >lock);
+  T_ERROR (__gthread_cond_destroy, >signal);
+}
+
+static void *
+async_io (void *arg)
+{
+  DEBUG_LINE(aio_prefix = TPREFIX);
+  transfer_queue *ctq = NULL, *prev = NULL;
+  gfc_unit *u = (gfc_unit *) arg;
+  async_unit *au = u->au;
+  thread_unit = u;
+  LOCK (au, lock);
+  au->thread = __gthread_self ();
+  UNLOCK (au, lock);
+  while (true)
+{
+  WAIT_SIGNAL (>work, au->tail || au->finished);
+  LOCK (au, lock);
+  ctq = au->head;
+  prev = NULL;
+  while (ctq)
+	{
+	  if (prev)
+	free (prev);
+	  prev = ctq;
+	  if (!au->error.has_error)
+	{
+	  UNLOCK (au, lock);
+	  
+	  switch(ctq->type)
+		{
+		case AIO_WRITE_DONE:
+		  NOTE("Finalizing write");
+		  st_write_done_worker (au->pdt); 
+		  break;
+		case AIO_READ_DONE:
+		  NOTE("Finalizing read");
+		  st_read_done_worker (au->pdt);
+		  break;
+		case AIO_CHANGE_PDT: 
+		  update_pdt(>pdt, ctq->new_pdt); 
+		  break; 
+		case AIO_TRANSFER_SCALAR:
+		  NOTE("Starting scalar transfer");
+		  ctq->arg.scalar.transfer (au->pdt, ctq->arg.scalar.arg_bt, 
+	ctq->arg.scalar.data,
+	ctq->arg.scalar.i,
+	ctq->arg.scalar.s1,
+	ctq->arg.scalar.s2);
+		  break;
+		case AIO_TRANSFER_ARRAY:
+		  NOTE("Starting array transfer");
+		  transfer_array_inner(au->pdt, ctq->arg.array.desc, 
+   ctq->arg.array.kind, 
+   ctq->arg.array.charlen);
+		  break;
+		default:
+		  ERROR(-1, "Invalid queue type %d", ctq->type);
+		  break;
+		}
+	  LOCK (au, lock);
+	  if (unlikely (au->error.has_error))
+		{
+		  au->error.last_good_id = au->id.low - 1;
+		  unlock_unit (au->pdt->u.p.current_unit);
+		}
+	}
+  	  NOTE("Current id: %d", au->id.low);
+  	  if (ctq->has_id && au->id.waiting == au->id.low++)
+	SIGNAL (>id.done);
+	  ctq = ctq->next;
+	}
+  au->tail = NULL;
+  au->head = NULL;
+  SIGNAL (>emptysignal);
+  au->empty = 1;
+  if (au->finished)
+	break;
+  UNLOCK (au, lock);
+}
+  UNLOCK (au, lock);
+  return NULL;
+}
+
+
+static void
+free_async_unit (async_unit * au)
+{
+  if (au->tail)
+ERROR (1, "Trying to free nonempty unit");
+  destroy_adv_cond (>work);
+  destroy_adv_cond (>emptysignal);
+  

Re: [Patch, fortran] PR35339 Optimize implied do loops in io statements

2017-06-05 Thread Nicolas Koenig

With all the style fixes committed as r248877.

Thanks for the review.

Nicolas


On 06/03/2017 06:25 PM, Jerry DeLisle wrote:

On 06/03/2017 06:48 AM, Nicolas Koenig wrote:

Hello everyone,

here is a version of the patch that includes a workaround for PR 80960. I have
also included a separate test case for the failure that Dominique detected. The
style issues should be fixed.

Regression-tested. OK for trunk?


Yes, OK.

Thanks for the work.

Jerry




Re: [Patch, fortran] PR35339 Optimize implied do loops in io statements

2017-06-03 Thread Nicolas Koenig

Hello everyone,

here is a version of the patch that includes a workaround for PR 80960. 
I have also included a separate test case for the failure that Dominique 
detected. The style issues should be fixed.


Regression-tested. OK for trunk?

Nicolas

Changelog:

2017-06-03  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/35339
* frontend-passes.c (traverse_io_block): New function.
(simplify_io_impl_do): New function.
(optimize_namespace): Invoke gfc_code_walker with
simplify_io_impl_do.

2017-06-03  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/35339
* gfortran.dg/implied_do_io_1.f90: New Test.
* gfortran.dg/implied_do_io_2.f90: New Test.


Index: frontend-passes.c
===
--- frontend-passes.c	(Revision 248553)
+++ frontend-passes.c	(Arbeitskopie)
@@ -1064,6 +1064,263 @@ convert_elseif (gfc_code **c, int *walk_subtrees A
   return 0;
 }
 
+struct do_stack
+{
+  struct do_stack *prev;
+  gfc_iterator *iter;
+  gfc_code *code;
+} *stack_top;
+
+/* Recursively traverse the block of a WRITE or READ statement, and maybe
+   optimize by replacing do loops with their analog array slices. For example:
+   
+ write (*,*) (a(i), i=1,4)
+ 
+   is replaced with
+ 
+ write (*,*) a(1:4:1) .  */
+
+static bool 
+traverse_io_block(gfc_code *code, bool *has_reached, gfc_code *prev)
+{
+  gfc_code *curr; 
+  gfc_expr *new_e, *expr, *start;
+  gfc_ref *ref;
+  struct do_stack ds_push;
+  int i, future_rank = 0;
+  gfc_iterator *iters[GFC_MAX_DIMENSIONS];
+  gfc_expr *e;
+
+  /* Find the first transfer/do statement.  */
+  for (curr = code; curr; curr = curr->next)
+{
+  if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
+break;
+}
+
+  /* Ensure it is the only transfer/do statement because cases like
+   
+ write (*,*) (a(i), b(i), i=1,4)
+
+ cannot be optimized.  */
+
+  if (!curr || curr->next)
+return false;
+
+  if (curr->op == EXEC_DO)
+{
+  if (curr->ext.iterator->var->ref)
+return false;
+  ds_push.prev = stack_top;
+  ds_push.iter = curr->ext.iterator;
+  ds_push.code = curr;
+  stack_top = _push;
+  if (traverse_io_block(curr->block->next, has_reached, prev))
+{
+	  if (curr != stack_top->code && !*has_reached)
+	{
+  curr->block->next = NULL;
+  gfc_free_statements(curr);
+	}
+	  else
+	*has_reached = true;
+	  return true;
+}
+  return false;
+}
+
+  gcc_assert(curr->op == EXEC_TRANSFER);
+
+  /* FIXME: Workaround for PR 80945 - array slices with deferred character
+ lenghts do not work.  Remove this section when the PR is fixed.  */
+  e = curr->expr1;
+  if (e->expr_type == EXPR_VARIABLE && e->ts.type == BT_CHARACTER
+  && e->ts.deferred)
+return false;
+  /* End of section to be removed.  */
+
+  ref = e->ref;
+  if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0 || ref->next)
+return false;
+
+  /* Find the iterators belonging to each variable and check conditions.  */
+  for (i = 0; i < ref->u.ar.dimen; i++)
+{
+  if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
+  || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
+return false;
+  
+  start = ref->u.ar.start[i];
+  gfc_simplify_expr(start, 0);
+  switch (start->expr_type)
+{
+	case EXPR_VARIABLE:
+
+	  /* write (*,*) (a(i), i=a%b,1) not handled yet.  */
+	  if (start->ref)
+	return false;
+
+	  /*  Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4).  */
+	  if (!stack_top || !stack_top->iter 
+	  || stack_top->iter->var->symtree != start->symtree)
+	iters[i] = NULL; 
+	  else
+	{
+  iters[i] = stack_top->iter;
+	  stack_top = stack_top->prev;
+	  future_rank++;
+	}
+	  break;
+case EXPR_CONSTANT:
+	  iters[i] = NULL;
+	  break;
+	case EXPR_OP:
+  switch (start->value.op.op)
+	{
+	case INTRINSIC_PLUS:
+	case INTRINSIC_TIMES:
+	  if (start->value.op.op1->expr_type != EXPR_VARIABLE)
+	std::swap(start->value.op.op1, start->value.op.op2);
+	  gcc_fallthrough();
+	case INTRINSIC_MINUS:
+	  if ((start->value.op.op1->expr_type!= EXPR_VARIABLE 
+		   && start->value.op.op2->expr_type != EXPR_CONSTANT)
+	  || start->value.op.op1->ref)
+	return false;
+  if (!stack_top || !stack_top->iter 
+		  || stack_top->iter->var->symtree 
+		  != start->value.op.op1->symtree)
+	return false;
+	  iters[i] = stack_top->iter; 
+	  stack_top = stack_top->prev;
+	  break;
+	default:
+	  return false;
+	}
+	  future_rank++;
+	  break;
+	default:
+	  return fal

Re: [Patch, fortran] PR35339 Optimize implied do loops in io statements

2017-05-31 Thread Nicolas Koenig

Hello Dominique,

attached is the next try, this time without stupidities (I hope). Both 
test cases you posted don't ICE anymore.


Ok for trunk?

Nicolas

Regression tested for x86_64-pc-linux-gnu.

Changelog (still the same):
2017-05-27  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/35339
* frontend-passes.c (traverse_io_block): New function.
(simplify_io_impl_do): New function.
(optimize_namespace): Invoke gfc_code_walker with
simplify_io_impl_do.

2017-05-27  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/35339
* gfortran.dg/implied_do_io_1.f90: New Test.

On 05/31/2017 05:49 PM, Dominique d'Humières wrote:

Le 31 mai 2017 à 17:40, Dominique d'Humières <domi...@lps.ens.fr> a écrit :

If I am not mistaken, compiling the following code with the patch applied

simpler test

   print *,(huge(0),i=1,6)
!  print*,(i,i=1,6)
!  print*,(i,i=1,6,1)
   end


gives an ICE.

TIA

Dominique


Index: frontend-passes.c
===
--- frontend-passes.c	(revision 248539)
+++ frontend-passes.c	(working copy)
@@ -1060,6 +1060,257 @@ convert_elseif (gfc_code **c, int *walk_subtrees A
   return 0;
 }
 
+struct do_stack
+{
+  struct do_stack *prev;
+  gfc_iterator *iter;
+  gfc_code *code;
+} *stack_top;
+
+/* Recursivly traverse the block of a WRITE or READ statement, and, can it be
+   optimized, do so. It optimizes it by replacing do loops with their analog
+   array slices. For example:
+   
+ write (*,*) (a(i), i=1,4)
+ 
+   is replaced with
+ 
+ write (*,*) a(1:4:1) .  */
+
+static bool 
+traverse_io_block(gfc_code *code, bool *has_reached, gfc_code *prev)
+{
+  gfc_code *curr; 
+  gfc_expr *new_e, *expr, *start;
+  gfc_ref *ref;
+  struct do_stack ds_push;
+  int i, future_rank = 0;
+  gfc_iterator *iters[GFC_MAX_DIMENSIONS];
+
+  /* Find the first transfer/do statement.  */
+  for (curr = code; curr; curr = curr->next)
+{
+  if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
+break;
+}
+
+  /* Ensure it is the only transfer/do statement because cases like
+   
+   write (*,*) (a(i), b(i), i=1,4)
+
+ cannot be optimized.  */
+
+  if (!curr || curr->next)
+return false;
+
+  if (curr->op == EXEC_DO)
+{
+  if (curr->ext.iterator->var->ref)
+return false;
+  ds_push.prev = stack_top;
+  ds_push.iter = curr->ext.iterator;
+  ds_push.code = curr;
+  stack_top = _push;
+  if (traverse_io_block(curr->block->next, has_reached, prev))
+{
+	  if (curr != stack_top->code && !*has_reached)
+	{
+  curr->block->next = NULL;
+  gfc_free_statements(curr);
+	}
+	  else
+	*has_reached = true;
+	  return true;
+}
+  return false;
+}
+
+  gcc_assert(curr->op == EXEC_TRANSFER);
+
+  ref = curr->expr1->ref;
+  if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0 || ref->next)
+return false;
+
+  /* Find the iterators belonging to each variable and check conditions.  */
+  for (i = 0; i < ref->u.ar.dimen; i++)
+{
+  if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
+  || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
+return false;
+  
+  start = ref->u.ar.start[i];
+  gfc_simplify_expr(start, 0);
+  switch (start->expr_type)
+{
+	case EXPR_VARIABLE:
+
+	  /* write (*,*) (a(i), i=a%b,1) not handled yet.  */
+	  if (start->ref)
+	return false;
+
+	  /*  Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4).  */
+	  if (!stack_top || !stack_top->iter 
+	 || stack_top->iter->var->symtree != start->symtree)
+	iters[i] = NULL; 
+	  else
+	{
+  iters[i] = stack_top->iter;
+	  stack_top = stack_top->prev;
+	  future_rank++;
+	}
+	  break;
+case EXPR_CONSTANT:
+	  iters[i] = NULL;
+	  break;
+	case EXPR_OP:
+  switch (start->value.op.op)
+	{
+	case INTRINSIC_PLUS:
+	case INTRINSIC_TIMES:
+	  if (start->value.op.op1->expr_type != EXPR_VARIABLE)
+	std::swap(start->value.op.op1, start->value.op.op2);
+	gcc_fallthrough();
+	case INTRINSIC_MINUS:
+	  if ((start->value.op.op1->expr_type!= EXPR_VARIABLE 
+	&& start->value.op.op2->expr_type != EXPR_CONSTANT)
+	  || start->value.op.op1->ref)
+	return false;
+  if (!stack_top || !stack_top->iter 
+	 || stack_top->iter->var->symtree 
+		!= start->value.op.op1->symtree)
+	return false;
+	  iters[i] = stack_top->iter; 
+	  stack_top = stack_top->prev;
+	  break;
+	default:
+	  return false;
+	}
+	future_rank++;
+	  break;
+	default:
+	  return false;
+}
+}
+
+  /* Create new

Re: [Patch, fortran] PR35339 Optimize implied do loops in io statements

2017-05-29 Thread Nicolas Koenig

Hello Dominique,

mea culpa, their was a bit confusion with the file being open in emacs
and vi at the same time. Attached is the new patch with the #define removed.

Nicolas


On 05/29/2017 05:32 PM, Dominique d'Humières wrote:

Hi Nicolas,

Updating gfortran with your patch fails with

../../work/gcc/fortran/frontend-passes.c: In function 'bool 
traverse_io_block(gfc_code*, bool*, gfc_code*)':
../../work/gcc/fortran/frontend-passes.c:1067:20: error: expected 
unqualified-id before '(' token
  #define swap(x, y) (x) ^= (y), (y) ^= (x), (x) ^= (y);
 ^
../../work/gcc/fortran/frontend-passes.c:1180:15: note: in expansion of macro 
'swap'
   std::swap(start->value.op.op1, start->value.op.op2);
^~~~
../../work/gcc/fortran/frontend-passes.c:1067:36: error: invalid operands of 
types 'gfc_expr*' and 'gfc_expr*' to binary 'operator^'
  #define swap(x, y) (x) ^= (y), (y) ^= (x), (x) ^= (y);
 ^~
../../work/gcc/fortran/frontend-passes.c:1180:15: note: in expansion of macro 
'swap'
   std::swap(start->value.op.op1, start->value.op.op2);
^~~~
../../work/gcc/fortran/frontend-passes.c:1067:41: error:   in evaluation of 
'operator^=(struct gfc_expr*, struct gfc_expr*)'
  #define swap(x, y) (x) ^= (y), (y) ^= (x), (x) ^= (y);
  ^
../../work/gcc/fortran/frontend-passes.c:1180:15: note: in expansion of macro 
'swap'
   std::swap(start->value.op.op1, start->value.op.op2);
^~~~
../../work/gcc/fortran/frontend-passes.c:1067:48: error: invalid operands of 
types 'gfc_expr*' and 'gfc_expr*' to binary 'operator^'
  #define swap(x, y) (x) ^= (y), (y) ^= (x), (x) ^= (y);
 ^~
../../work/gcc/fortran/frontend-passes.c:1180:15: note: in expansion of macro 
'swap'
   std::swap(start->value.op.op1, start->value.op.op2);
^~~~
../../work/gcc/fortran/frontend-passes.c:1067:53: error:   in evaluation of 
'operator^=(struct gfc_expr*, struct gfc_expr*)'
  #define swap(x, y) (x) ^= (y), (y) ^= (x), (x) ^= (y);
  ^
../../work/gcc/fortran/frontend-passes.c:1180:15: note: in expansion of macro 
'swap'
   std::swap(start->value.op.op1, start->value.op.op2);
^~~~

TIA

Dominique



Index: frontend-passes.c
===
--- frontend-passes.c	(revision 248539)
+++ frontend-passes.c	(working copy)
@@ -1060,6 +1060,256 @@ convert_elseif (gfc_code **c, int *walk_subtrees A
   return 0;
 }
 
+struct do_stack
+{
+  struct do_stack *prev;
+  gfc_iterator *iter;
+  gfc_code *code;
+} *stack_top;
+
+/* Recursivly traverse the block of a WRITE or READ statement, and, can it be
+   optimized, do so. It optimizes it by replacing do loops with their analog
+   array slices. For example:
+   
+ write (*,*) (a(i), i=1,4)
+ 
+   is replaced with
+ 
+ write (*,*) a(1:4:1) .  */
+
+static bool 
+traverse_io_block(gfc_code *code, bool *has_reached, gfc_code *prev)
+{
+  gfc_code *curr; 
+  gfc_expr *new_e, *expr, *start;
+  gfc_ref *ref;
+  struct do_stack ds_push;
+  int i, future_rank = 0;
+  gfc_iterator *iters[GFC_MAX_DIMENSIONS];
+
+  /* Find the first transfer/do statement.  */
+  for (curr = code; curr; curr = curr->next)
+{
+  if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
+break;
+}
+
+  /* Ensure it is the only transfer/do statement because cases like
+   
+   write (*,*) (a(i), b(i), i=1,4)
+
+ cannot be optimized.  */
+
+  if (!curr || curr->next)
+return false;
+
+  if (curr->op == EXEC_DO)
+{
+  if (curr->ext.iterator->var->ref)
+return false;
+  ds_push.prev = stack_top;
+  ds_push.iter = curr->ext.iterator;
+  ds_push.code = curr;
+  stack_top = _push;
+  if (traverse_io_block(curr->block->next, has_reached, prev))
+{
+	  if (curr != stack_top->code && !*has_reached)
+	{
+  curr->block->next = NULL;
+  gfc_free_statements(curr);
+	}
+	  else
+	*has_reached = true;
+	  return true;
+}
+  return false;
+}
+
+  gcc_assert(curr->op == EXEC_TRANSFER);
+
+  if (curr->expr1->symtree->n.sym->attr.allocatable)
+return false;
+
+  ref = curr->expr1->ref;
+  if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0)
+return false;
+
+  /* Find the iterators belonging to each variable and check conditions.  */
+  for (i = 0; i < ref->u.ar.dimen; i++)
+{
+  if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
+  || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
+return false;
+  
+  start = ref->u.ar.start[i];
+  gfc_simplify_expr(start, 0);
+  switch (start->expr_type)
+{
+	case EXPR_VARIABLE:
+
+	  /* write (*,*) (a(i), i=a%b,1) not handled yet.  */
+	  if (start->ref)
+	return 

[Patch, fortran] PR35339 Optimize implied do loops in io statements

2017-05-27 Thread Nicolas Koenig

Hello everyone,

attached is a patch to simplify implied do loops in io statements by 
replacing them with their respective array slices. For example "WRITE 
(*,*) (a(i), i=1,4,2)" becomes "WRITE (*,*) a(1:4:2)".


Ok for trunk?

Nicolas

Regression tested for x85_64-pc-linux-gnu.

Changelog:
2017-05-27  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/35339
* frontend-passes.c (traverse_io_block): New function.
(simplify_io_impl_do): New function.
(optimize_namespace): Invoke gfc_code_walker with
simplify_io_impl_do.

2017-05-27  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/35339
* gfortran.dg/implied_do_io_1.f90: New Test.

Index: frontend-passes.c
===
--- frontend-passes.c	(revision 248539)
+++ frontend-passes.c	(working copy)
@@ -1060,6 +1060,258 @@ convert_elseif (gfc_code **c, int *walk_subtrees A
   return 0;
 }
 
+#define swap(x, y) (x) ^= (y), (y) ^= (x), (x) ^= (y);
+
+struct do_stack
+{
+  struct do_stack *prev;
+  gfc_iterator *iter;
+  gfc_code *code;
+} *stack_top;
+
+/* Recursivly traverse the block of a WRITE or READ statement, and, can it be
+   optimized, do so. It optimizes it by replacing do loops with their analog
+   array slices. For example:
+   
+ write (*,*) (a(i), i=1,4)
+ 
+   is replaced with
+ 
+ write (*,*) a(1:4:1) .  */
+
+static bool 
+traverse_io_block(gfc_code *code, bool *has_reached, gfc_code *prev)
+{
+  gfc_code *curr; 
+  gfc_expr *new_e, *expr, *start;
+  gfc_ref *ref;
+  struct do_stack ds_push;
+  int i, future_rank = 0;
+  gfc_iterator *iters[GFC_MAX_DIMENSIONS];
+
+  /* Find the first transfer/do statement.  */
+  for (curr = code; curr; curr = curr->next)
+{
+  if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
+break;
+}
+
+  /* Ensure it is the only transfer/do statement because cases like
+   
+   write (*,*) (a(i), b(i), i=1,4)
+
+ cannot be optimized.  */
+
+  if (!curr || curr->next)
+return false;
+
+  if (curr->op == EXEC_DO)
+{
+  if (curr->ext.iterator->var->ref)
+return false;
+  ds_push.prev = stack_top;
+  ds_push.iter = curr->ext.iterator;
+  ds_push.code = curr;
+  stack_top = _push;
+  if (traverse_io_block(curr->block->next, has_reached, prev))
+{
+	  if (curr != stack_top->code && !*has_reached)
+	{
+  curr->block->next = NULL;
+  gfc_free_statements(curr);
+	}
+	  else
+	*has_reached = true;
+	  return true;
+}
+  return false;
+}
+
+  gcc_assert(curr->op == EXEC_TRANSFER);
+
+  if (curr->expr1->symtree->n.sym->attr.allocatable)
+return false;
+
+  ref = curr->expr1->ref;
+  if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0)
+return false;
+
+  /* Find the iterators belonging to each variable and check conditions.  */
+  for (i = 0; i < ref->u.ar.dimen; i++)
+{
+  if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
+  || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
+return false;
+  
+  start = ref->u.ar.start[i];
+  gfc_simplify_expr(start, 0);
+  switch (start->expr_type)
+{
+	case EXPR_VARIABLE:
+
+	  /* write (*,*) (a(i), i=a%b,1) not handled yet.  */
+	  if (start->ref)
+	return false;
+
+	  /*  Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4).  */
+	  if (!stack_top || !stack_top->iter 
+	 || stack_top->iter->var->symtree != start->symtree)
+	iters[i] = NULL; 
+	  else
+	{
+  iters[i] = stack_top->iter;
+	  stack_top = stack_top->prev;
+	  future_rank++;
+	}
+	  break;
+case EXPR_CONSTANT:
+	  iters[i] = NULL;
+	  break;
+	case EXPR_OP:
+  switch (start->value.op.op)
+	{
+	case INTRINSIC_PLUS:
+	case INTRINSIC_TIMES:
+	  if (start->value.op.op1->expr_type != EXPR_VARIABLE)
+	std::swap(start->value.op.op1, start->value.op.op2);
+	__attribute__((fallthrough));
+	case INTRINSIC_MINUS:
+	  if ((start->value.op.op1->expr_type!= EXPR_VARIABLE 
+	&& start->value.op.op2->expr_type != EXPR_CONSTANT)
+	  || start->value.op.op1->ref)
+	return false;
+  if (!stack_top || !stack_top->iter 
+	 || stack_top->iter->var->symtree 
+		!= start->value.op.op1->symtree)
+	return false;
+	  iters[i] = stack_top->iter; 
+	  stack_top = stack_top->prev;
+	  break;
+	default:
+	  return false;
+	}
+	future_rank++;
+	  break;
+	default:
+	  return false;
+}
+}
+
+  /* Create new expr.  */
+  new_e = gfc_copy_expr(curr->expr1);
+  new_e->expr_type = EXPR_VARIABLE;
+  new_e->rank = fut

Re: [Patch, fortran] PR80442 Handle DATA statement with iteration var in array slice

2017-05-13 Thread Nicolas Koenig

Hello Jerry,

Thanks for the review. Committed as r248012.

Nicolas


On 05/13/2017 06:30 PM, Jerry DeLisle wrote:

On 05/13/2017 04:56 AM, Nicolas Koenig wrote:

Ping
Also, attached is a better test case.


On 05/09/2017 10:49 PM, Nicolas Koenig wrote:

Hello everyone,

since everybody seems to be submitting patches the last few days, I thought I
might as well :)
Attached is a patch that makes the compiler capable of dealing with implied do
variables in
array slices in data statements.
The copying of the expressions is necessary since gfc_simplify_expr(expr, 1)
substitutes every
symbol in expr that is on the iter_stack with its value.

Ok for trunk?

It looks OK and thanks for patch.

Jerry



Nicolas

Regression tested for x86_64-pc-linux-gnu.

Changelog:
2017-05-09  Nicolas Koenig  <koeni...@student.ethz.ch>

 PR fortran/80442
 * array.c (gfc_ref_dimen_size): Simplify stride
 expression
 * data.c (gfc_advance_section): Simplify start,
 end and stride expressions
 (gfc_advance_section): Simplify start and end
 expressions
 (gfc_get_section_index): Simplify start expression

2017-05-09  Nicolas Koenig  <koeni...@student.ethz.ch>

 PR fortran/80442
 * gfortran.dg/impl_do_var_data.f90: New Test






Re: [Patch, fortran] PR80442 Handle DATA statement with iteration var in array slice

2017-05-13 Thread Nicolas Koenig

Ping
Also, attached is a better test case.


On 05/09/2017 10:49 PM, Nicolas Koenig wrote:

Hello everyone,

since everybody seems to be submitting patches the last few days, I 
thought I might as well :)
Attached is a patch that makes the compiler capable of dealing with 
implied do variables in

array slices in data statements.
The copying of the expressions is necessary since 
gfc_simplify_expr(expr, 1) substitutes every

symbol in expr that is on the iter_stack with its value.

Ok for trunk?

Nicolas

Regression tested for x86_64-pc-linux-gnu.

Changelog:
2017-05-09  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/80442
* array.c (gfc_ref_dimen_size): Simplify stride
expression
* data.c (gfc_advance_section): Simplify start,
end and stride expressions
(gfc_advance_section): Simplify start and end
expressions
(gfc_get_section_index): Simplify start expression

2017-05-09  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/80442
* gfortran.dg/impl_do_var_data.f90: New Test




! { dg-do run }
! PR 80442
! This test case used to produce an bogus error
! about the variables being below the lower
! array bounds
program main
implicit none
integer:: i
integer, dimension(3):: A
data (A(i:i+2:i+1), i=1,2) /1, 2, 3/
if(any(A .ne. [1,3,2])) call abort()
end program
Index: array.c
===
--- array.c	(revision 247809)
+++ array.c	(working copy)
@@ -2201,6 +2201,7 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen,
   mpz_t upper, lower, stride;
   mpz_t diff;
   bool t;
+  gfc_expr *stride_expr = NULL;
 
   if (dimen < 0 || ar == NULL || dimen > ar->dimen - 1)
 gfc_internal_error ("gfc_ref_dimen_size(): Bad dimension");
@@ -2225,12 +2226,16 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen,
 	mpz_set_ui (stride, 1);
   else
 	{
-	  if (ar->stride[dimen]->expr_type != EXPR_CONSTANT)
+	  stride_expr = gfc_copy_expr(ar->stride[dimen]); 
+	  if(!gfc_simplify_expr(stride_expr, 1))
+	gfc_internal_error("Simplification error");
+	  if (stride_expr->expr_type != EXPR_CONSTANT)
 	{
 	  mpz_clear (stride);
 	  return false;
 	}
-	  mpz_set (stride, ar->stride[dimen]->value.integer);
+	  mpz_set (stride, stride_expr->value.integer);
+	  gfc_free_expr(stride_expr);
 	}
 
   /* Calculate the number of elements via gfc_dep_differce, but only if
Index: data.c
===
--- data.c	(revision 247809)
+++ data.c	(working copy)
@@ -539,6 +539,7 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
   mpz_t tmp; 
   bool forwards;
   int cmp;
+  gfc_expr *start, *end, *stride;
 
   for (i = 0; i < ar->dimen; i++)
 {
@@ -547,12 +548,16 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
 
   if (ar->stride[i])
 	{
+	  stride = gfc_copy_expr(ar->stride[i]);
+	  if(!gfc_simplify_expr(stride, 1))
+	gfc_internal_error("Simplification error");
 	  mpz_add (section_index[i], section_index[i],
-		   ar->stride[i]->value.integer);
-	if (mpz_cmp_si (ar->stride[i]->value.integer, 0) >= 0)
-	  forwards = true;
-	else
-	  forwards = false;
+		   stride->value.integer);
+	  if (mpz_cmp_si (stride->value.integer, 0) >= 0)
+	forwards = true;
+	  else
+	forwards = false;
+	  gfc_free_expr(stride);	
 	}
   else
 	{
@@ -561,7 +566,13 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
 	}
   
   if (ar->end[i])
-	cmp = mpz_cmp (section_index[i], ar->end[i]->value.integer);
+{
+	  end = gfc_copy_expr(ar->end[i]);
+	  if(!gfc_simplify_expr(end, 1))
+	gfc_internal_error("Simplification error");
+	  cmp = mpz_cmp (section_index[i], end->value.integer);
+	  gfc_free_expr(end);	
+	}
   else
 	cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);
 
@@ -569,7 +580,13 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
 	{
 	  /* Reset index to start, then loop to advance the next index.  */
 	  if (ar->start[i])
-	mpz_set (section_index[i], ar->start[i]->value.integer);
+	{
+	  start = gfc_copy_expr(ar->start[i]);
+	  if(!gfc_simplify_expr(start, 1))
+	gfc_internal_error("Simplification error");
+	  mpz_set (section_index[i], start->value.integer);
+	  gfc_free_expr(start); 
+	}
 	  else
 	mpz_set (section_index[i], ar->as->lower[i]->value.integer);
 	}
@@ -679,6 +696,7 @@ gfc_get_section_index (gfc_array_ref *ar, mpz_t *s
   int i;
   mpz_t delta;
   mpz_t tmp;
+  gfc_expr *start;
 
   mpz_set_si (*offset, 0);
   mpz_init (tmp);
@@ -692,11 +710,15 @@ gfc_get_section_index (gfc_array_ref *ar, mpz_t *s
 	case DIMEN_RANGE:
 	  if (ar->start[i])
 	{
-	  mpz_sub (tmp, ar->start[i]->value.integer,
+	  sta

[Patch, fortran] PR80442 Handle DATA statement with iteration var in array slice

2017-05-09 Thread Nicolas Koenig

Hello everyone,

since everybody seems to be submitting patches the last few days, I 
thought I might as well :)
Attached is a patch that makes the compiler capable of dealing with 
implied do variables in

array slices in data statements.
The copying of the expressions is necessary since 
gfc_simplify_expr(expr, 1) substitutes every

symbol in expr that is on the iter_stack with its value.

Ok for trunk?

Nicolas

Regression tested for x86_64-pc-linux-gnu.

Changelog:
2017-05-09  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/80442
* array.c (gfc_ref_dimen_size): Simplify stride
expression
* data.c (gfc_advance_section): Simplify start,
end and stride expressions
(gfc_advance_section): Simplify start and end
expressions
(gfc_get_section_index): Simplify start expression

2017-05-09  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/80442
* gfortran.dg/impl_do_var_data.f90: New Test


Index: array.c
===
--- array.c	(revision 247809)
+++ array.c	(working copy)
@@ -2201,6 +2201,7 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen,
   mpz_t upper, lower, stride;
   mpz_t diff;
   bool t;
+  gfc_expr *stride_expr = NULL;
 
   if (dimen < 0 || ar == NULL || dimen > ar->dimen - 1)
 gfc_internal_error ("gfc_ref_dimen_size(): Bad dimension");
@@ -2225,12 +2226,16 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen,
 	mpz_set_ui (stride, 1);
   else
 	{
-	  if (ar->stride[dimen]->expr_type != EXPR_CONSTANT)
+	  stride_expr = gfc_copy_expr(ar->stride[dimen]); 
+	  if(!gfc_simplify_expr(stride_expr, 1))
+	gfc_internal_error("Simplification error");
+	  if (stride_expr->expr_type != EXPR_CONSTANT)
 	{
 	  mpz_clear (stride);
 	  return false;
 	}
-	  mpz_set (stride, ar->stride[dimen]->value.integer);
+	  mpz_set (stride, stride_expr->value.integer);
+	  gfc_free_expr(stride_expr);
 	}
 
   /* Calculate the number of elements via gfc_dep_differce, but only if
Index: data.c
===
--- data.c	(revision 247809)
+++ data.c	(working copy)
@@ -539,6 +539,7 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
   mpz_t tmp; 
   bool forwards;
   int cmp;
+  gfc_expr *start, *end, *stride;
 
   for (i = 0; i < ar->dimen; i++)
 {
@@ -547,12 +548,16 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
 
   if (ar->stride[i])
 	{
+	  stride = gfc_copy_expr(ar->stride[i]);
+	  if(!gfc_simplify_expr(stride, 1))
+	gfc_internal_error("Simplification error");
 	  mpz_add (section_index[i], section_index[i],
-		   ar->stride[i]->value.integer);
-	if (mpz_cmp_si (ar->stride[i]->value.integer, 0) >= 0)
-	  forwards = true;
-	else
-	  forwards = false;
+		   stride->value.integer);
+	  if (mpz_cmp_si (stride->value.integer, 0) >= 0)
+	forwards = true;
+	  else
+	forwards = false;
+	  gfc_free_expr(stride);	
 	}
   else
 	{
@@ -561,7 +566,13 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
 	}
   
   if (ar->end[i])
-	cmp = mpz_cmp (section_index[i], ar->end[i]->value.integer);
+{
+	  end = gfc_copy_expr(ar->end[i]);
+	  if(!gfc_simplify_expr(end, 1))
+	gfc_internal_error("Simplification error");
+	  cmp = mpz_cmp (section_index[i], end->value.integer);
+	  gfc_free_expr(end);	
+	}
   else
 	cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);
 
@@ -569,7 +580,13 @@ gfc_advance_section (mpz_t *section_index, gfc_arr
 	{
 	  /* Reset index to start, then loop to advance the next index.  */
 	  if (ar->start[i])
-	mpz_set (section_index[i], ar->start[i]->value.integer);
+	{
+	  start = gfc_copy_expr(ar->start[i]);
+	  if(!gfc_simplify_expr(start, 1))
+	gfc_internal_error("Simplification error");
+	  mpz_set (section_index[i], start->value.integer);
+	  gfc_free_expr(start); 
+	}
 	  else
 	mpz_set (section_index[i], ar->as->lower[i]->value.integer);
 	}
@@ -679,6 +696,7 @@ gfc_get_section_index (gfc_array_ref *ar, mpz_t *s
   int i;
   mpz_t delta;
   mpz_t tmp;
+  gfc_expr *start;
 
   mpz_set_si (*offset, 0);
   mpz_init (tmp);
@@ -692,11 +710,15 @@ gfc_get_section_index (gfc_array_ref *ar, mpz_t *s
 	case DIMEN_RANGE:
 	  if (ar->start[i])
 	{
-	  mpz_sub (tmp, ar->start[i]->value.integer,
+	  start = gfc_copy_expr(ar->start[i]);
+	  if(!gfc_simplify_expr(start, 1))
+	gfc_internal_error("Simplification error");
+	  mpz_sub (tmp, start->value.integer,
 		   ar->as->lower[i]->value.integer);
 	  mpz_mul (tmp, tmp, delta);
 	  mpz_add (*offset, tmp, *offset);
-	  mpz_set (section_index[i], ar->start[i]->value.integer);
+	

Re: [Patch, fortran] PR69498 ICE on unexpected Submodule

2017-04-10 Thread Nicolas Koenig

Hello Paul,

I would argue that this is but an elaborate plan to teach a newbie the 
ways of the bugzilla and enable him to properly close his first bug ;)


Anyway, committed as r246826.

Thanks for the review.

Nicolas


On 04/10/2017 08:07 PM, Paul Richard Thomas wrote:

Dear Nicolas,

The reasons are (i) moving country and (ii) the daytime job :-)

I think that in the circumstances somebody else should OK the patch,
although I think that it is perfect in every way possible.

Actually, perhaps it is sufficiently obvious that I would and should
have committed it - OK for trunk.

Thanks

Paul


On 10 April 2017 at 17:53, Nicolas Koenig <koeni...@student.ethz.ch> wrote:

Hello everyone,

Dominique send me this patch written by Paul some time ago. For some reason
it was never committed, so here we go :)

Ok for trunk?

Nicolas

Regression tested for x86_64-pc-linux-gnu.

Changelog:
2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
 PR fortran/69498
 * module.c (gfc_match_submodule): Add error
 if function is called in the wrong state.

2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
 PR fortran/69498
 * gfortran.dg/submodule_unexp.f90: Modified test
 to account for new error.









Re: [Patch, fortran] PR69498 ICE on unexpected Submodule

2017-04-10 Thread Nicolas Koenig

Hello again,

I forgot to add the test case this patch fixes and to give Paul the 
credit. Attached the new test case.


Nicolas

New & improved changelog:

2017-04-10  Nicolas Koenig  <koeni...@student.ethz.ch>
Paul Thomas  <pa...@gcc.gnu.org>
PR fortran/69498
* module.c (gfc_match_submodule): Add error
if function is called in the wrong state.

2017-04-10  Nicolas Koenig  <koeni...@student.ethz.ch>
PR fortran/69498
* gfortran.dg/submodule_unexp.f90: Modified test
to account for new error.
* gfortran.dg/submodule_twice.f90: New Test


On 04/10/2017 06:53 PM, Nicolas Koenig wrote:

Hello everyone,

Dominique send me this patch written by Paul some time ago. For some 
reason it was never committed, so here we go :)


Ok for trunk?

Nicolas

Regression tested for x86_64-pc-linux-gnu.

Changelog:
2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
PR fortran/69498
* module.c (gfc_match_submodule): Add error
if function is called in the wrong state.

2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
PR fortran/69498
* gfortran.dg/submodule_unexp.f90: Modified test
to account for new error.




! { dg-do compile }
! PR fortran/69498
! This used to ICE
program main
submodule (m) sm ! { dg-error "SUBMODULE declaration at" }
submodule (m2) sm2  ! { dg-error "SUBMODULE declaration at" }
end program


[Patch, fortran] PR69498 ICE on unexpected Submodule

2017-04-10 Thread Nicolas Koenig

Hello everyone,

Dominique send me this patch written by Paul some time ago. For some 
reason it was never committed, so here we go :)


Ok for trunk?

Nicolas

Regression tested for x86_64-pc-linux-gnu.

Changelog:
2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
PR fortran/69498
* module.c (gfc_match_submodule): Add error
if function is called in the wrong state.

2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
PR fortran/69498
* gfortran.dg/submodule_unexp.f90: Modified test
to account for new error.


Index: gcc/fortran/module.c
===
--- gcc/fortran/module.c	(revision 246743)
+++ gcc/fortran/module.c	(working copy)
@@ -741,6 +741,13 @@ gfc_match_submodule (void)
   if (!gfc_notify_std (GFC_STD_F2008, "SUBMODULE declaration at %C"))
 return MATCH_ERROR;
 
+  if (gfc_current_state () != COMP_NONE)
+{
+  gfc_error ("SUBMODULE declaration at %C cannot appear within "
+		 "another scoping unit");
+  return MATCH_ERROR;
+}
+
   gfc_new_block = NULL;
   gcc_assert (module_list == NULL);
 
Index: gcc/testsuite/gfortran.dg/submodule_unexp.f90
===
--- gcc/testsuite/gfortran.dg/submodule_unexp.f90	(revision 246743)
+++ gcc/testsuite/gfortran.dg/submodule_unexp.f90	(working copy)
@@ -3,6 +3,6 @@
 ! This used to ICE
 program p
type t
-   submodule (m) sm ! { dg-error "Unexpected SUBMODULE statement at" }
+   submodule (m) sm ! { dg-error "SUBMODULE declaration at" }
end type
 end


[Patch, fortran] PR69498 Fix ICE on unexpected submodule

2017-03-25 Thread Nicolas Koenig

Hello everyone,

this fixes the ICE. The problem was a discrepancy between the name of 
the submodules symbol and the name of its symtree node.


Nicolas

2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
PR fortran/69498
* symbol.c (gfc_delete_symtree): If there is a period 
in the name, ignore

everything before it.

2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>
PR fortran/69498
* gfortran.dg/submodule_unexp.f90: New test



Index: symbol.c
===
--- symbol.c	(Revision 246320)
+++ symbol.c	(Arbeitskopie)
@@ -2782,10 +2782,20 @@ void
 gfc_delete_symtree (gfc_symtree **root, const char *name)
 {
   gfc_symtree st, *st0;
+  const char *p;
 
-  st0 = gfc_find_symtree (*root, name);
+  /* Submodules are marked as mod.submod.  When freeing a submodule
+ symbol, the symtree only has "submod", so adjust that here.  */
 
-  st.name = gfc_get_string ("%s", name);
+  p = strchr(name, '.');
+  if (p)
+p++;
+  else
+p = name;
+
+  st0 = gfc_find_symtree (*root, p);
+
+  st.name = gfc_get_string ("%s", p);
   gfc_delete_bbt (root, , compare_symtree);
 
   free (st0);
! { dg-do compile }
! PR fortran/69498
! This used to ICE
program p
   type t
   submodule (m) sm ! { dg-error "Unexpected SUBMODULE statement at" }
   end type
end


[Patch, fortran] PR69498 Fixing ICE with double free on symbol

2017-03-19 Thread Nicolas Koenig

Hello everyone,

a one-line-fix for one of the test cases in pr69498. The refs count of 
the ppr@ symbol wasn't set properly. Attached are the patch & the test case.


If I understand the 'Write Access' page correctly, this would be the 
kind of patch I would not have to bother the mailing list with but 
instead could commit directly? Would this count as an "obvious fix"?


Nicolas

Regression tested for x86_64-pc-linux-gnu.

2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/69498
* decl.c (add_hidden_procptr_result): Fixed Refs count 
of the created "ppr@" symbol.


2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/69498
* gfortran.dg/unexp_attribute.f90: New test


! { dg-do compile }
! This test used to result in an internal compiler error
function f()
interface
external f ! { dg-error "Unexpected attribute declaration statement in INTERFACE" }
end interface
end function
Index: decl.c
===
--- decl.c	(revision 246260)
+++ decl.c	(working copy)
@@ -5430,6 +5430,7 @@ add_hidden_procptr_result (gfc_symbol *sym)
 	  gfc_get_sym_tree ("ppr@", gfc_current_ns->parent, , false);
 	  st2 = gfc_new_symtree (_current_ns->sym_root, "ppr@");
 	  st2->n.sym = stree->n.sym;
+	  stree->n.sym->refs++;
 	}
   sym->result = stree->n.sym;


[Patch, fortran] PR39239 EQUIVALENCE and BIND(C)

2017-03-18 Thread Nicolas Koenig

Hello everyone,

I submitted this patch a week ago, but I think it got lost. It adds an 
error if BIND(C) is used with EQUIVALENCE.


Nicolas

Regression tested for x86_64-pc-linux-gnu.

2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/39239
* resolve.c (resolve_equivalence): report an error if 
an equivalence variable is BIND(C).


2017-03-18  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/39239
* gfortran.dg/equiv_constraint_bind_c.f90: New test.

Index: resolve.c
===
--- resolve.c	(revision 246070)
+++ resolve.c	(working copy)
@@ -15675,6 +15675,13 @@ resolve_equivalence (gfc_equiv *eq)
 	  && !resolve_equivalence_derived (e->ts.u.derived, sym, e))
 	continue;
 
+  if (sym->attr.is_bind_c)
+	{
+  	  gfc_error ("EQUIVALENCE object %qs at %L cannot be BIND(C)",
+ sym->name, >where);
+	  continue;
+	}
+
   /* Check that the types correspond correctly:
 	 Note 5.28:
 	 A numeric sequence structure may be equivalenced to another sequence
! Testcase for using EQUIVALENCE with BIND(C)
! See PR fortran/39239
! { dg-do compile }
module m
  use iso_c_binding
  implicit none
  integer(c_int) :: i1, i2
  bind(C) :: i2 
  equivalence(i1,i2) ! { dg-error "cannot be BIND" }
end module m



Re: [patch, fortran] PR39239 Warning about EQUIVALENCE and VOLATILE

2017-03-14 Thread Nicolas Koenig



On 03/14/2017 10:42 PM, Jerry DeLisle wrote:

On 03/14/2017 01:17 PM, Nicolas Koenig wrote:

Hello everyone,

a simple patch to throw a warning if not all and not none of the equivalence
objects are volatile. (And the according modification of
gfortran.dg/volatile11.f90)

Nicolas

Regression tested for:

GNU Fortran (GCC) 7.0.1 20170311 (experimental)

Changelog:

2017-03-13  Nicolas Koenig  <koeni...@student.ethz.ch>

 PR fortran/39239
 * resolve.c (resolve_equivalence): Warn if not either none or
all equivalence objects are volatile
 * gfortran.dg/volatile11.f90: Changed test to test for the new
warning



Hi Nicolas,

Thanks for starting in on this.

Since this results in a warning, maybe change the wording from 'shall' to 
should.

I did not dig into the Fortran Standards so I assume it need not be an error.

Also when you submit a patch, please also let us know what platform you
regression tested on, such as x86-64-linux, or Windows, or similar. (You can get
the whole string from subdirectory names in build directory. On mine its
x86_64-pc-linux-gnu) Sometimes we accidentally break things on different
platforms. so this way we can see it tested ok over here and seems to fail over
there.

Your patch has changed some of the scan dumps and I am wondering if you have
deleted something we use to check for?

Jerry


Hello Jerry,
I have to thank for the kind feedback.
Attached is a reworked version of the patch with the changes applied. It 
also should  have the same scan dump now, one of the test cases was 
edited stupidly.
The regression tests for both the old as well as the new test have been 
performed on an x86-64-linux (x86_64-pc-linux-gnu).

Nicolas

Index: fortran/resolve.c
===
--- fortran/resolve.c	(revision 246143)
+++ fortran/resolve.c	(working copy)
@@ -15560,7 +15560,7 @@ resolve_equivalence (gfc_equiv *eq)
   locus *last_where = NULL;
   seq_type eq_type, last_eq_type;
   gfc_typespec *last_ts;
-  int object, cnt_protected;
+  int object, cnt_protected, cnt_volatile;
   const char *msg;
 
   last_ts = >expr->symtree->n.sym->ts;
@@ -15569,6 +15569,8 @@ resolve_equivalence (gfc_equiv *eq)
 
   cnt_protected = 0;
 
+  cnt_volatile = 0;
+
   for (object = 1; eq; eq = eq->eq, object++)
 {
   e = eq->expr;
@@ -15641,6 +15643,17 @@ resolve_equivalence (gfc_equiv *eq)
 
   sym = e->symtree->n.sym;
 
+  if(sym->attr.volatile_)
+cnt_volatile++;
+  if(cnt_volatile > 0 && cnt_volatile != object)
+	{
+	  gfc_warning (0, "Either all or none of the objects in "
+	  	   "the EQUIVALENCE set at %L should have the "
+		   "VOLATILE attribute",
+		   >where);
+	  break;
+	}
+
   if (sym->attr.is_protected)
 	cnt_protected++;
   if (cnt_protected > 0 && cnt_protected != object)
Index: testsuite/gfortran.dg/volatile11.f90
===
--- testsuite/gfortran.dg/volatile11.f90	(revision 246140)
+++ testsuite/gfortran.dg/volatile11.f90	(working copy)
@@ -3,6 +3,7 @@
 ! Tests that volatile can be applied to members of common blocks or
 ! equivalence groups (PR fortran/35037)
 !
+
 subroutine wait1
   logical event
   volatile event
@@ -16,7 +17,7 @@ end subroutine
 subroutine wait2
   logical event, foo
   volatile event
-  equivalence (event, foo)
+  equivalence (event, foo) ! { dg-warning "in the EQUIVALENCE set" }
   event = .false.
   do
 if (event) print *, 'NotOptimizedAway2'
@@ -27,7 +28,7 @@ subroutine wait3
   logical event
   integer foo
   volatile foo
-  equivalence (event, foo)
+  equivalence (event, foo) ! { dg-warning "in the EQUIVALENCE set" }
   event = .false.
   do
 if (event) print *, 'IsOptimizedAway'


[patch, fortran] PR39239 Warning about EQUIVALENCE and VOLATILE

2017-03-14 Thread Nicolas Koenig

Hello everyone,

a simple patch to throw a warning if not all and not none of the 
equivalence objects are volatile. (And the according modification of 
gfortran.dg/volatile11.f90)


Nicolas

Regression tested for:

GNU Fortran (GCC) 7.0.1 20170311 (experimental)

Changelog:

2017-03-13  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/39239
* resolve.c (resolve_equivalence): Warn if not either 
none or all equivalence objects are volatile
* gfortran.dg/volatile11.f90: Changed test to test for 
the new warning



Index: fortran/resolve.c
===
--- fortran/resolve.c	(revision 246070)
+++ fortran/resolve.c	(working copy)
@@ -15560,7 +15560,7 @@ resolve_equivalence (gfc_equiv *eq)
   locus *last_where = NULL;
   seq_type eq_type, last_eq_type;
   gfc_typespec *last_ts;
-  int object, cnt_protected;
+  int object, cnt_protected, cnt_volatile;
   const char *msg;
 
   last_ts = >expr->symtree->n.sym->ts;
@@ -15569,6 +15569,8 @@ resolve_equivalence (gfc_equiv *eq)
 
   cnt_protected = 0;
 
+  cnt_volatile = 0;
+
   for (object = 1; eq; eq = eq->eq, object++)
 {
   e = eq->expr;
@@ -15641,6 +15643,17 @@ resolve_equivalence (gfc_equiv *eq)
 
   sym = e->symtree->n.sym;
 
+  if(sym->attr.volatile_)
+cnt_volatile++;
+  if(cnt_volatile > 0 && cnt_volatile != object)
+	{
+	  gfc_warning (0, "Either all or none of the objects in "
+	  	   "the EQUIVALENCE set at %L shall have the "
+		   "VOLATILE attribute",
+		   >where);
+	  break;
+	}
+
   if (sym->attr.is_protected)
 	cnt_protected++;
   if (cnt_protected > 0 && cnt_protected != object)
Index: testsuite/gfortran.dg/volatile11.f90
===
--- testsuite/gfortran.dg/volatile11.f90	(revision 246070)
+++ testsuite/gfortran.dg/volatile11.f90	(working copy)
@@ -1,8 +1,9 @@
 ! { dg-do compile }
-! { dg-options "-O2 -fdump-tree-optimized" }
+! { dg-options "-Wall -O2 -fdump-tree-optimized" }
 ! Tests that volatile can be applied to members of common blocks or
 ! equivalence groups (PR fortran/35037)
 !
+
 subroutine wait1
   logical event
   volatile event
@@ -14,26 +15,10 @@ subroutine wait1
 end subroutine
 
 subroutine wait2
-  logical event, foo
-  volatile event
-  equivalence (event, foo)
-  event = .false.
-  do
-if (event) print *, 'NotOptimizedAway2'
-  end do
-end subroutine
-
-subroutine wait3
   logical event
   integer foo
   volatile foo
-  equivalence (event, foo)
-  event = .false.
-  do
-if (event) print *, 'IsOptimizedAway'
-  end do
+  equivalence (event, foo) ! { dg-warning "in the EQUIVALENCE set" } 
 end subroutine
 
 ! { dg-final { scan-tree-dump "NotOptimizedAway1" "optimized" } } */
-! { dg-final { scan-tree-dump "NotOptimizedAway2" "optimized" } } */
-! { dg-final { scan-tree-dump-not "IsOptimizedAway" "optimized" } } */


[patch, fortran] PR39239 reject BIND(C) in EQUIVALENCE

2017-03-12 Thread Nicolas Koenig

Hello everyone,

this is my first attempt at a patch. The necessary paperwork for me to 
contribute is all said & done. I'm looking forward to some more compiler 
hacking :)


Nicolas

Here is the changelog:

2017-03-12  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/39239
* resolve.c (resolve_equivalence): report an error if 
an equivalence variable is BIND(C).


2017-03-12  Nicolas Koenig  <koeni...@student.ethz.ch>

PR fortran/39239
* gfortran.dg/equiv_constraint_bind_c.f90: New test.

Index: resolve.c
===
--- resolve.c	(revision 246070)
+++ resolve.c	(working copy)
@@ -15675,6 +15675,13 @@ resolve_equivalence (gfc_equiv *eq)
 	  && !resolve_equivalence_derived (e->ts.u.derived, sym, e))
 	continue;
 
+  if (sym->attr.is_bind_c)
+	{
+  	  gfc_error ("EQUIVALENCE object %qs at %L cannot be C interop",
+ sym->name, >where);
+	  continue;
+	}
+
   /* Check that the types correspond correctly:
 	 Note 5.28:
 	 A numeric sequence structure may be equivalenced to another sequence
! Testcase for using EQUIVALENCE with BIND(C)
! See PR fortran/39239
! { dg-do compile }
module m
  use iso_c_binding
  implicit none
  integer(c_int) :: i1, i2
  bind(C) :: i2 
  equivalence(i1,i2) ! { dg-error "cannot be C interop" }
end module m