Bug 43331 - Cray pointers generate bogus IL for the middle-end
Summary: Cray pointers generate bogus IL for the middle-end
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Tobias Burnus
URL:
Keywords: wrong-code
Depends on:
Blocks: 42361
  Show dependency treegraph
 
Reported: 2010-03-11 12:10 UTC by Richard Biener
Modified: 2010-03-17 10:03 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-03-12 10:50:33


Attachments
Lightly tested patch (1.65 KB, patch)
2010-03-11 15:58 UTC, Tobias Burnus
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2010-03-11 12:10:45 UTC
I have a patch that exposes this and causes a "miscompile" of
gfortran.dg/cray_pointers_2.f90.  Reduced testcase:

! { dg-do run }
! { dg-options "-fcray-pointer -fbounds-check" }
! Series of routines for testing a Cray pointer implementation
program craytest
  call ptr5
end program craytest

subroutine ptr5
  logical :: intne
  integer :: i
  integer, parameter :: n = 9
  integer itarg1 (n)
  integer ipte1 (*)

  pointer(iptr4,ipte1)

  iptr4 = loc(itarg1)

  do, i=1,n
     ipte1(i) = i
     if (intne(ipte1(i), itarg1(i))) then
        ! Error #143
        call abort()
     endif
  end do

end subroutine ptr5

! Separate function calls to break Cray pointer-indifferent optimization
logical function intne(ii,jj)
  integer :: i,j
  intne = ii.ne.jj
  if (intne) then
     write (*,*) ii," doesn't equal ",jj
  endif
end function intne


where we can see the following IL created by the FE:

ptr5 ()
{
  integer(kind=4) i;
  integer(kind=8) iptr4;
  integer(kind=4) ipte1[1] [value-expr: *(integer(kind=4)[1] *) iptr4];
  integer(kind=4) itarg1[9];

  {
    integer(kind=8) D.1548;

    D.1548 = (integer(kind=8)) &itarg1;
    iptr4 = D.1548;
  }
...
            ipte1[NON_LVALUE_EXPR <SAVE_EXPR <(integer(kind=8)) i>> + -1] = i;
...
            if (intne (&ipte1[NON_LVALUE_EXPR <SAVE_EXPR <(integer(kind=8)) i>> + -1], &itarg1[NON_LVALUE_EXPR <SAVE_EXPR <(integer(kind=8)) i>> + -1]))


you can clearly see that substituting the value-expr
*(integer(kind=4)[1] *) iptr4 for ipte1 will expose an array size of 1 (!)
to the middle-end, which it will happily oblige to and optimize
&ipte1[i - 1] to &ipte1[0].

If the array size is not known the FE should generate
*(integer(kind=4)[] *) iptr4
Comment 1 Tobias Burnus 2010-03-11 14:50:19 UTC
I think the "1" comes about due to the following. That can either leave that part as is and change it back in in trans*.c via "cp_was_assumed" -- or one removes that part and sees what will break ;-)

From decl.c:

/* Cray Pointees can be declared as:
      pointer (ipt, a (n,m,...,*))
   By default, this is treated as an AS_ASSUMED_SIZE array.  We'll
   cheat and set a constant bound of 1 for the last dimension, if this
   is the case. Since there is no bounds-checking for Cray Pointees,
   this will be okay.  */

match
gfc_mod_pointee_as (gfc_array_spec *as)
{
  as->cray_pointee = true; /* This will be useful to know later.  */
  if (as->type == AS_ASSUMED_SIZE)
    {
      as->type = AS_EXPLICIT;
      as->upper[as->rank - 1] = gfc_int_expr (1);
      as->cp_was_assumed = true;
    }
Comment 2 Dominique d'Humieres 2010-03-11 15:10:38 UTC
What is done for assumed-size arrays such as a(*)?
Comment 3 Tobias Burnus 2010-03-11 15:58:04 UTC
Created attachment 20083 [details]
Lightly tested patch
Comment 4 Tobias Burnus 2010-03-12 10:50:33 UTC
Accept. (Draft?) patches:
- Part 1: http://gcc.gnu.org/ml/fortran/2010-03/msg00061.html
- Part 2: http://gcc.gnu.org/ml/fortran/2010-03/msg00062.html
Comment 5 Tobias Burnus 2010-03-17 09:53:53 UTC
Subject: Bug 43331

Author: burnus
Date: Wed Mar 17 09:53:40 2010
New Revision: 157512

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=157512
Log:
2010-03-17  Tobias Burnus  <burnus@net-b.de>

        PR fortran/43331
        * trans-array.c (gfc_conv_array_index_offset,gfc_conv_array_ref,
        gfc_conv_ss_startstride): Remove no-longer-needed cp_was_assumed
        check.
        * decl.c (gfc_match_derived_decl): Don't mark assumed-size Cray
        pointees as having explizit size.
        * expr.c (gfc_check_assign): Remove now unreachable Cray pointee
        check.
        * trans-types.c (gfc_is_nodesc_array): Add cp_was_assumed to
        * assert.
        (gfc_sym_type): Don't mark Cray pointees as restricted pointers.
        * resolve.c (resolve_symbol): Handle cp_was_assumed.
        * trans-decl.c (gfc_trans_deferred_vars): Ditto.
        (gfc_finish_var_decl): Don't mark Cray pointees as restricted
        pointers.

2010-03-17  Tobias Burnus  <burnus@net-b.de>

        PR fortran/43331
        * gfortran.dg/cray_pointers_1.f90: Update dg-error message.


Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/decl.c
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-types.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/cray_pointers_1.f90

Comment 6 Tobias Burnus 2010-03-17 10:03:22 UTC
FIXED on the trunk (4.5).

Richard: Thanks for the clear bug report! And for making the middle-end smarter with regards to bonds.

Actually, will this middle-end change cause problems for inlining such old-style Fortran code as below?

  real A(100)
  call sub(A(1), 100)  ! Correct syntax: "call sub(A, 100)"

  subroutine sub(x, n)
    integer n
    real x(*) ! Or: "real x(n)" to be slightly more modern
    x(n) = 5

(I think the code was never valid but one can find it quite often in old code that it passes the first array element to a procedure, which expects an array.)
Comment 7 rguenther@suse.de 2010-03-17 10:07:50 UTC
Subject: Re:  Cray pointers generate bogus IL for the
 middle-end

On Wed, 17 Mar 2010, burnus at gcc dot gnu dot org wrote:

> ------- Comment #6 from burnus at gcc dot gnu dot org  2010-03-17 10:03 -------
> FIXED on the trunk (4.5).
> 
> Richard: Thanks for the clear bug report! And for making the middle-end smarter
> with regards to bonds.
> 
> Actually, will this middle-end change cause problems for inlining such
> old-style Fortran code as below?
> 
>   real A(100)
>   call sub(A(1), 100)  ! Correct syntax: "call sub(A, 100)"
> 
>   subroutine sub(x, n)
>     integer n
>     real x(*) ! Or: "real x(n)" to be slightly more modern
>     x(n) = 5
> 
> (I think the code was never valid but one can find it quite often in old code
> that it passes the first array element to a procedure, which expects an array.)

The middle-end should be able to deal with this (well, worst case by
refusing to inline).

Richard.