diff mbox

[Fortran] Simplify lbound

Message ID 553B7BA4.6040103@netcologne.de
State New
Headers show

Commit Message

Thomas Koenig April 25, 2015, 11:33 a.m. UTC
Hello world,

this is a simplification for calculating the lboud of assumed-shape
arrays - it is usually one, or whatever the user specified as
lower bound (if constant).

The surprising thing was that the current code generated for the
array descriptor for

  subroutine foo(a, b, n, m)
    integer, dimension(:), intent(inout) :: a
    integer, dimension(-2:), intent(inout) :: b
    integer, intent(out) :: n,m
    n = lbound(a,1)
    m = lbound(b,1)
  end subroutine foo

was not simplified to the simple assignment even at -O.  This is
what the assembly looks like with the patch:

        movl    $1, (%rdx)
        movl    $-2, (%rcx)
        ret

and this is what it looks like without the patch:

        movq    24(%rsi), %rax
        testq   %rax, %rax
        movl    $1, %edi
        cmove   %rdi, %rax
        movq    40(%rsi), %rdi
        subq    32(%rsi), %rdi
        movq    %rdi, %rsi
        subq    $2, %rsi
        movl    $1, (%rdx)
        movq    %rax, %rdx
        notq    %rdx
        shrq    $63, %rdx
        cmpq    $-2, %rsi
        setge   %sil
        movzbl  %sil, %esi
        testl   %edx, %esi
        jne     .L6
        shrq    $63, %rax
        movl    $1, %edx
        testl   %eax, %eax
        je      .L3
.L6:
        movl    $-2, %edx
.L3:
        movl    %edx, (%rcx)
        ret

This is important for the matmul inline patch, because I am using
lbound extensively there.  The other cases (allocatables and
pointers as dummy arguments) are already covered.

Regression-tested.  OK for trunk?


2015-04-25  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/37131
	* simplify.c (simplify_bound): Get constant lower bounds
	from array spec for assumed shape arrays.

2015-04-25  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/37131
	* gfortran.dg/coarray_lib_this_image_2.f90:  Adjust
	scan pattern.
	* gfortran.dg/bound_9.f90:  New test case.

Comments

Mikael Morin April 25, 2015, 6:12 p.m. UTC | #1
Le 25/04/2015 13:33, Thomas Koenig a écrit :
> Hello world,
> 
> this is a simplification for calculating the lboud of assumed-shape
> arrays - it is usually one, or whatever the user specified as
> lower bound (if constant).
> 
Hello,

I've double-checked in the standard, and it seems it is not possible to
simplify after all:

	If ARRAY is a whole array and either ARRAY is an assumed-size
	array of rank DIM or dimension DIM of ARRAY has nonzero extent,
	LBOUND (ARRAY, DIM) has a value equal to the lower bound for
	subscript DIM of ARRAY. Otherwise the result value is 1.

We can't tell whether the array is zero-sized, so we can't tell the
lbound value.


As you may want to simplify in the limited scope of the matmul inlining,
I'm giving comments about the patch (otherwise you can ignore them):
 - No need to check for allocatable or pointer, it should be excluded by
as->type == AS_ASSUMED_SHAPE (but does no harm either).
 - Please modify the early return condition:
     if (as && (as->type == AS_DEFERRED || as->type == AS_ASSUMED_SHAPE
	        || as->type == AS_ASSUMED_RANK))
       return NULL;
   and let the existing code do the simplification work.


Or drop the lbound simplification idea, and fetch the lbound "by hand"
at matmul inline time.

Mikael
diff mbox

Patch

Index: fortran/simplify.c
===================================================================
--- fortran/simplify.c	(Revision 222431)
+++ fortran/simplify.c	(Arbeitskopie)
@@ -3445,6 +3445,32 @@  simplify_bound (gfc_expr *array, gfc_expr *dim, gf
 
  done:
 
+
+  if (!upper && as && as->type == AS_ASSUMED_SHAPE && dim
+      && dim->expr_type == EXPR_CONSTANT && ref->u.ar.type != AR_SECTION)
+    {
+      if (!(array->symtree && array->symtree->n.sym
+	    && (array->symtree->n.sym->attr.allocatable
+		|| array->symtree->n.sym->attr.pointer)))
+	{
+	  unsigned long int ndim;
+	  gfc_expr *lower, *res;
+
+	  ndim = mpz_get_si (dim->value.integer) - 1;
+	  lower = as->lower[ndim];
+	  if (lower->expr_type == EXPR_CONSTANT)
+	    {
+	      res = gfc_copy_expr (lower);
+	      if (kind)
+		{
+		  int nkind = mpz_get_si (kind->value.integer);
+		  res->ts.kind = nkind;
+		}
+	      return res;
+	    }
+	}
+    }
+
   if (as && (as->type == AS_DEFERRED || as->type == AS_ASSUMED_SHAPE
 	     || as->type == AS_ASSUMED_RANK))
     return NULL;
Index: testsuite/gfortran.dg/coarray_lib_this_image_2.f90
===================================================================
--- testsuite/gfortran.dg/coarray_lib_this_image_2.f90	(Revision 222431)
+++ testsuite/gfortran.dg/coarray_lib_this_image_2.f90	(Arbeitskopie)
@@ -20,7 +20,7 @@  end
 ! { dg-final { scan-tree-dump-times "mylcobound = 5;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "parm...dim\\\[1\\\].lbound = 5;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "myucobound =\[^\n\r\]* parm...dim\\\[1\\\].lbound \\+ \[^\n\r\]*_gfortran_caf_num_images \\(0, -1\\).? \\+ -?\[0-9\]+\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "mylbound = parm...dim\\\[0\\\].stride >= 0 && parm...dim\\\[0\\\].ubound >= parm...dim\\\[0\\\].lbound \\|\\| parm...dim\\\[0\\\].stride < 0 \\?\[^\n\r\]* parm...dim\\\[0\\\].lbound : 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "mylbound = 1;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "mythis_image = _gfortran_caf_this_image \\(0\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "bar \\(&parm.\[0-9\]+, caf_token.\[0-9\]+, \\(integer\\(kind=\[48\]\\)\\) parm.\[0-9\]+.data - \\(integer\\(kind=\[48\]\\)\\) x\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_init \\(&argc, &argv\\);" 1 "original" } }