Bug 50069 - FORALL fails on a character array
Summary: FORALL fails on a character array
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.8.0
: P3 major
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2011-08-13 07:05 UTC by Vittorio Zecca
Modified: 2017-01-18 21:51 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.1.2, 4.3.4, 4.4.0, 4.5.1, 4.6.1, 4.7.0
Last reconfirmed: 2011-08-17 00:00:00


Attachments
compile it and run (178 bytes, text/plain)
2011-08-13 07:05 UTC, Vittorio Zecca
Details
patch.55086_50069.txt (2.50 KB, text/plain)
2016-11-07 11:34 UTC, louis.krupp
Details
patch.55086_50069-1.txt (292 bytes, text/plain)
2016-11-08 20:52 UTC, louis.krupp
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Vittorio Zecca 2011-08-13 07:05:01 UTC
Created attachment 24997 [details]
compile it and run

Must be compiled and run. g95 and Intel ifort deliver the correct result.
Comment 1 Tobias Burnus 2011-08-15 12:12:12 UTC
Wild guess: Dependency analysis (forward/backward etc.) does not take character substrings into account. If so, it vaguely reminds me of PR 47674.
Comment 2 Tobias Burnus 2011-08-17 08:21:34 UTC
Draft patch:

diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index a911a5b..7d85413 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -2452,6 +2452,9 @@ forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
          tmp = gfc_conv_array_offset (old_sym->backend_decl);
          gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
        }
+      else
+       gfc_conv_descriptor_offset_set (pre, tse.expr,
+               build_int_cst (gfc_array_index_type, -1));
     }
   else
     {
Comment 3 Tobias Burnus 2011-08-17 08:44:30 UTC
(In reply to comment #2)
> Draft patch:

This patch fails for gfortran.dg/forall_12.f90 test (of PR31217 and PR33811):

    character(LEN=12) :: a(2) = "123456789012"
    forall (i = 3:10) a(:)(i:i+2) = a(:)(i-2:i)

The result with the patch is
 12@+@+
instead of
 121234567890

 * * *

For the test of comment 0, gfortran (unpatched) produces:
    atmp.1.offset = 0;
and accesses
    atmp.1.data)[atmp.1.offset + 1]

While for the now failing test case forall_12.f90, gfortran (unpatched) produces also
    atmp.1.offset = 0;
but uses
      D.1578 = atmp.1.offset;
      D.1577 = ... atmp.1.data;
      &(*D.1577)[S.5 + D.1578]
where S.5 is the loop variable, which runs from 0 to 1.


Thus, the actual problem seems to be that "a(1)" is translated into "a[1+offset]" instead of "a[0+offset]".
Comment 4 Vittorio Zecca 2013-04-16 08:50:50 UTC
I still have the same bug on gfortran 4.8.0.
Comment 5 Vittorio Zecca 2015-08-31 16:38:43 UTC
Still on gfortran 5.2.0
Comment 6 zmi 2015-10-12 01:03:16 UTC
A am not sure if its the same bug, but I get ICE for the function

!-----------------------------------------------------------------------
!Function
!-----------------------------------------------------------------------
function  reverse(string) ! bind(c, name='reverse')
implicit none
character(len=*), intent(in) :: string
character(len=:),allocatable :: reverse
reverse = string
forall (i=1:len(reverse)) reverse(i:i) = reverse(len(reverse)-i+1:len(reverse)-i+1)
end function reverse



forall (i=1:len(reverse)) reverse(i:i) = reverse(len(reverse)-i+1:len(reverse)-i+1)
 1
internal compiler error: in gfc_conv_variable, at fortran/trans-expr.c:2368


gfortran --version
GNU Fortran (SUSE Linux) 5.2.1 20150721 [gcc-5-branch revision 226027]
Comment 7 Vittorio Zecca 2016-04-28 07:13:26 UTC
Still in 5.3.0
Comment 8 Dominique d'Humieres 2016-11-06 17:09:26 UTC
Related to pr55086, but the two tests are not fixed by the patch at https://gcc.gnu.org/ml/fortran/2016-10/msg00228.html even when compiled with the option -fforce-forall-temp.
Comment 9 louis.krupp 2016-11-07 11:34:22 UTC
Created attachment 39979 [details]
patch.55086_50069.txt

The attached patch adds a slight variation of Tobias Burnus's patch for 50069 to my patch for 55086, and it seems to fix the two tests in 50069.

"make check-fortran" runs with no surprises.

Louis


 ---- On Sun, 06 Nov 2016 09:09:26 -0800 dominiq at lps dot ens.fr <gcc-bugzilla@gcc.gnu.org> wrote ---- 
 > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50069 
 >  
 > Dominique d'Humieres <dominiq at lps dot ens.fr> changed: 
 >  
 >            What    |Removed                     |Added 
 > ---------------------------------------------------------------------------- 
 >                  CC|                            |lkrupp at gcc dot gnu.org 
 >  
 > --- Comment #8 from Dominique d'Humieres <dominiq at lps dot ens.fr> --- 
 > Related to pr55086, but the two tests are not fixed by the patch at 
 > https://gcc.gnu.org/ml/fortran/2016-10/msg00228.html even when compiled with 
 > the option -fforce-forall-temp. 
 >  
 > --  
 > You are receiving this mail because: 
 > You are on the CC list for the bug.
Comment 10 Dominique d'Humieres 2016-11-08 15:03:59 UTC
> The attached patch adds a slight variation of Tobias Burnus's patch
> for 50069 to my patch for 55086, and it seems to fix the two tests in 50069.

I have applied the patch without the last hunk. It fixes the first test by supplying the needed temporary. However compiling the test (variant of the test in comment 6)

function  reverse(string) ! bind(c, name='reverse')
implicit none
character(len=*), intent(in) :: string
character(len=:),allocatable :: reverse
integer :: i
reverse = string
forall (i=1:len(reverse)) reverse(i:i) = reverse(len(reverse)-i+1:len(reverse)-i+1)
end function reverse

still gives an ICE

 forall (i=1:len(reverse)) reverse(i:i) = reverse(len(reverse)-i+1:len(reverse)-i+1)
 
internal compiler error: in gfc_conv_variable, at fortran/trans-expr.c:2550

The patch also fixes the ICE for the test reduced test from pr55086

  implicit none
  character(len=5), pointer :: c, d
  allocate (c, d)

  d = '12345'
  c = "abcde"

  call test2p (d, c)
  print *, d
  if (d /= '1cb15') stop 'WRONG'

contains
 subroutine test2p(o, i)
  character(len=*), pointer :: o, i
  integer :: nl1, nu1
  integer :: i1
  nl1 = 2
  nu1 = 4
  forall (i1 = nl1:nu1) o(i1:i1) = i(i1:i1)   ! <<<< ICE
  forall (i1 = nl1:nu1) o(i1:i1) = o(nu1+1-i1:nu1+1-i1)
 end subroutine test2p
end

but at the expense of an unneeded temporary:

  {
    integer(kind=4) i1.0;
    integer(kind=4) D.3446;
    integer(kind=8) count1.1;
    integer(kind=8) num.2;
    character(kind=1)[0:][1:1] * temp.4;
    void * restrict D.3452;

    D.3446 = nu1;
    count1.1 = 0;
    num.2 = 0;
    {
      integer(kind=4) count.3;

      i1.0 = nl1;
      count.3 = (1 - nl1) + nu1;
      while (1)
        {
          if (count.3 <= 0) goto L.1;
          num.2 = num.2 + 1;
          i1.0 = i1.0 + 1;
          count.3 = count.3 + -1;
        }
      L.1:;
    }
    D.3452 = (void * restrict) __builtin_malloc (MAX_EXPR <(unsigned long) num.2, 1>);
    temp.4 = (character(kind=1)[0:][1:1] *) D.3452;
    {
      integer(kind=4) count.5;

      i1.0 = nl1;
      count.5 = (1 - nl1) + nu1;
      while (1)
        {
          if (count.5 <= 0) goto L.2;
          (*temp.4)[count1.1][1]{lb: 1 sz: 1} = (**i)[i1.0]{lb: 1 sz: 1};
          count1.1 = count1.1 + 1;
          i1.0 = i1.0 + 1;
          count.5 = count.5 + -1;
        }
      L.2:;
    }
    count1.1 = 0;
    {
      integer(kind=4) count.6;

      i1.0 = nl1;
      count.6 = (1 - nl1) + nu1;
      while (1)
        {
          if (count.6 <= 0) goto L.3;
          (**o)[i1.0]{lb: 1 sz: 1} = (*temp.4)[count1.1][1]{lb: 1 sz: 1};
          count1.1 = count1.1 + 1;
          i1.0 = i1.0 + 1;
          count.6 = count.6 + -1;
        }
      L.3:;
    }
    __builtin_free ((void *) temp.4);
  }
Comment 11 louis.krupp 2016-11-08 20:52:55 UTC
Created attachment 39997 [details]
patch.55086_50069-1.txt

You're right.  I wasn't paying attention to the third ("function reverse ...") in the bug report.

I believe that's fixed with the attached patch to trans-expr.c along with my other patch.  I no longer see the ICE, and "make check-fortran" turns up no surprises.

I haven't tried this second patch (to trans-expr.c) by itself.

The force-forall-temp flag in the first patch isn't intended to fix anything;  its sole purpose is to get code with obscure bugs to fail sooner, in testing, instead of later when forall really needs to create and use a temporary under circumstances that no one had anticipated.

Louis


 ---- On Tue, 08 Nov 2016 07:03:59 -0800 dominiq at lps dot ens.fr <gcc-bugzilla@gcc.gnu.org> wrote ---- 
 > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50069 
 >  
 > --- Comment #10 from Dominique d'Humieres <dominiq at lps dot ens.fr> --- 
 > > The attached patch adds a slight variation of Tobias Burnus's patch 
 > > for 50069 to my patch for 55086, and it seems to fix the two tests in 50069. 
 >  
 > I have applied the patch without the last hunk. It fixes the first test by 
 > supplying the needed temporary. However compiling the test (variant of the test 
 > in comment 6) 
 >  
 > function  reverse(string) ! bind(c, name='reverse') 
 > implicit none 
 > character(len=*), intent(in) :: string 
 > character(len=:),allocatable :: reverse 
 > integer :: i 
 > reverse = string 
 > forall (i=1:len(reverse)) reverse(i:i) = 
 > reverse(len(reverse)-i+1:len(reverse)-i+1) 
 > end function reverse 
 >  
 > still gives an ICE 
 >  
 >  forall (i=1:len(reverse)) reverse(i:i) = 
 > reverse(len(reverse)-i+1:len(reverse)-i+1) 
 >  
 > internal compiler error: in gfc_conv_variable, at fortran/trans-expr.c:2550 
 >  
 > The patch also fixes the ICE for the test reduced test from pr55086 
 >  
 >   implicit none 
 >   character(len=5), pointer :: c, d 
 >   allocate (c, d) 
 >  
 >   d = '12345' 
 >   c = "abcde" 
 >  
 >   call test2p (d, c) 
 >   print *, d 
 >   if (d /= '1cb15') stop 'WRONG' 
 >  
 > contains 
 >  subroutine test2p(o, i) 
 >   character(len=*), pointer :: o, i 
 >   integer :: nl1, nu1 
 >   integer :: i1 
 >   nl1 = 2 
 >   nu1 = 4 
 >   forall (i1 = nl1:nu1) o(i1:i1) = i(i1:i1)   ! <<<< ICE 
 >   forall (i1 = nl1:nu1) o(i1:i1) = o(nu1+1-i1:nu1+1-i1) 
 >  end subroutine test2p 
 > end 
 >  
 > but at the expense of an unneeded temporary: 
 >  
 >   { 
 >     integer(kind=4) i1.0; 
 >     integer(kind=4) D.3446; 
 >     integer(kind=8) count1.1; 
 >     integer(kind=8) num.2; 
 >     character(kind=1)[0:][1:1] * temp.4; 
 >     void * restrict D.3452; 
 >  
 >     D.3446 = nu1; 
 >     count1.1 = 0; 
 >     num.2 = 0; 
 >     { 
 >       integer(kind=4) count.3; 
 >  
 >       i1.0 = nl1; 
 >       count.3 = (1 - nl1) + nu1; 
 >       while (1) 
 >         { 
 >           if (count.3 <= 0) goto L.1; 
 >           num.2 = num.2 + 1; 
 >           i1.0 = i1.0 + 1; 
 >           count.3 = count.3 + -1; 
 >         } 
 >       L.1:; 
 >     } 
 >     D.3452 = (void * restrict) __builtin_malloc (MAX_EXPR <(unsigned long) 
 > num.2, 1>); 
 >     temp.4 = (character(kind=1)[0:][1:1] *) D.3452; 
 >     { 
 >       integer(kind=4) count.5; 
 >  
 >       i1.0 = nl1; 
 >       count.5 = (1 - nl1) + nu1; 
 >       while (1) 
 >         { 
 >           if (count.5 <= 0) goto L.2; 
 >           (*temp.4)[count1.1][1]{lb: 1 sz: 1} = (**i)[i1.0]{lb: 1 sz: 1}; 
 >           count1.1 = count1.1 + 1; 
 >           i1.0 = i1.0 + 1; 
 >           count.5 = count.5 + -1; 
 >         } 
 >       L.2:; 
 >     } 
 >     count1.1 = 0; 
 >     { 
 >       integer(kind=4) count.6; 
 >  
 >       i1.0 = nl1; 
 >       count.6 = (1 - nl1) + nu1; 
 >       while (1) 
 >         { 
 >           if (count.6 <= 0) goto L.3; 
 >           (**o)[i1.0]{lb: 1 sz: 1} = (*temp.4)[count1.1][1]{lb: 1 sz: 1}; 
 >           count1.1 = count1.1 + 1; 
 >           i1.0 = i1.0 + 1; 
 >           count.6 = count.6 + -1; 
 >         } 
 >       L.3:; 
 >     } 
 >     __builtin_free ((void *) temp.4); 
 >   } 
 >  
 > --  
 > You are receiving this mail because: 
 > You are on the CC list for the bug.
Comment 12 lkrupp 2017-01-18 21:42:20 UTC
Author: lkrupp
Date: Wed Jan 18 21:41:48 2017
New Revision: 244601

URL: https://gcc.gnu.org/viewcvs?rev=244601&root=gcc&view=rev
Log:
2017-01-18  Louis Krupp  <louis.krupp@zoho.com>

	PR fortran/50069
	PR fortran/55086
	* gfortran.dg/pr50069_1.f90: New test.
	* gfortran.dg/pr50069_2.f90: New test.
	* gfortran.dg/pr55086_1.f90: New test.
	* gfortran.dg/pr55086_1_tfat.f90: New test.
	* gfortran.dg/pr55086_2.f90: New test.
	* gfortran.dg/pr55086_2_tfat.f90: New test.
	* gfortran.dg/pr55086_aliasing_dummy_4_tfat.f90: New test.

2017-01-18  Louis Krupp  <louis.krupp@zoho.com>

	PR fortran/50069
	PR fortran/55086
	* trans-expr.c (gfc_conv_variable): Don't treat temporary variables
	as function arguments.
	* trans-stmt.c (forall_make_variable_temp,
	generate_loop_for_temp_to_lhs, gfc_trans_assign_need_temp,
	gfc_trans_forall_1): Don't adjust offset of forall temporary
	for array sections, make forall temporaries work for substring
	expressions, improve test coverage by adding -ftest-forall-temp
	option to request usage of temporary array in forall code.
	* lang.opt: Add -ftest-forall-temp option.
	* invoke.texi: Add -ftest-forall-temp option.


Added:
    trunk/gcc/testsuite/gfortran.dg/pr50069_1.f90
    trunk/gcc/testsuite/gfortran.dg/pr50069_2.f90
    trunk/gcc/testsuite/gfortran.dg/pr55086_1.f90
    trunk/gcc/testsuite/gfortran.dg/pr55086_1_tfat.f90
    trunk/gcc/testsuite/gfortran.dg/pr55086_2.f90
    trunk/gcc/testsuite/gfortran.dg/pr55086_2_tfat.f90
    trunk/gcc/testsuite/gfortran.dg/pr55086_aliasing_dummy_4_tfat.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/invoke.texi
    trunk/gcc/fortran/lang.opt
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/testsuite/ChangeLog
Comment 13 lkrupp 2017-01-18 21:51:08 UTC
Fixed in revision 244601.

Offset adjustment for temporary arrays is fixed, or at least improved.

Temporary arrays created for function return values are treated as variables and not as functions when passed as procedure arguments.