re PR fortran/37131 (inline matmul for small matrix sizes)
authorThomas Koenig <tkoenig@gcc.gnu.org>
Mon, 29 May 2017 06:03:23 +0000 (06:03 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Mon, 29 May 2017 06:03:23 +0000 (06:03 +0000)
2017-05-29  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR fortran/37131
* frontend-passes.c (check_conjg_transpose_variable):
Add prototype.
(has_dimen_vector_ref):  Likewise
(matmul_temp_args):  New function. Add prototype.
(optimize_namespace):  Call matmul_temp_args.

2017-05-29  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR fortran/37131
* gfortran.dg/promotion_2.f90: Add -finline-matmul-limit=0 to
flags.
* gfortran.dg/transpose_optimization_1.f90: Likewise.
* gfortran.dg/inline_matmul_17.f90:  New test.

From-SVN: r248553

gcc/fortran/ChangeLog
gcc/fortran/frontend-passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/inline_matmul_17.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/promotion_2.f90
gcc/testsuite/gfortran.dg/transpose_optimization_1.f90

index c9c6a027d87ecf5a8ffe20b00feb21ad6022ae0a..093c36c7e21a1b81c01a40c89cf0f2029430f49c 100644 (file)
@@ -1,3 +1,12 @@
+2017-05-29  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR fortran/37131
+       * frontend-passes.c (check_conjg_transpose_variable):
+       Add prototype.
+       (has_dimen_vector_ref):  Likewise
+       (matmul_temp_args):  New function. Add prototype.
+       (optimize_namespace):  Call matmul_temp_args.
+
 2017-05-28  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        * frontend-passes.c (matmul_lhs_realloc):  Correct
index 62cccc81b67120d747fc1f2b613341ac2c264b36..be02dce05ea15a09a31fde562518c57ce2a8d0c0 100644 (file)
@@ -49,6 +49,10 @@ static int inline_matmul_assign (gfc_code **, int *, void *);
 static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
                                  locus *, gfc_namespace *,
                                  char *vname=NULL);
+static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *,
+                                                bool *);
+static bool has_dimen_vector_ref (gfc_expr *);
+static int matmul_temp_args (gfc_code **, int *,void *data);
 
 #ifdef CHECKING_P
 static void check_locus (gfc_namespace *);
@@ -1087,11 +1091,13 @@ optimize_namespace (gfc_namespace *ns)
                           (void *) &found);
        }
       while (found);
-       
+
+      gfc_code_walker (&ns->code, matmul_temp_args, dummy_expr_callback,
+                      NULL);
       gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
                       NULL);
     }
-  
+
   /* BLOCKs are handled in the expression walker below.  */
   for (ns = ns->contained; ns; ns = ns->sibling)
     {
@@ -2157,6 +2163,92 @@ matmul_to_var_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
 }
 
 
+/* Take a statement of the shape c = matmul(a,b) and create temporaries
+   for a and b if there is a dependency between the arguments and the
+   result variable or if a or b are the result of calculations that cannot
+   be handled by the inliner.  */
+
+static int
+matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
+                 void *data ATTRIBUTE_UNUSED)
+{
+  gfc_expr *expr1, *expr2;
+  gfc_code *co;
+  gfc_actual_arglist *a, *b;
+  bool a_tmp, b_tmp;
+  gfc_expr *matrix_a, *matrix_b;
+  bool conjg_a, conjg_b, transpose_a, transpose_b;
+  
+  co = *c;
+
+  if (co->op != EXEC_ASSIGN)
+    return 0;
+
+  if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
+      || in_where)
+    return 0;
+
+  /* This has some duplication with inline_matmul_assign.  This
+     is because the creation of temporary variables could still fail,
+     and inline_matmul_assign still needs to be able to handle these
+     cases.  */
+  expr1 = co->expr1;
+  expr2 = co->expr2;
+
+  if (expr2->expr_type != EXPR_FUNCTION
+      || expr2->value.function.isym == NULL
+      || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
+    return 0;
+
+  a_tmp = false;
+  a = expr2->value.function.actual;
+  matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
+  if (matrix_a != NULL)
+    {
+      if (matrix_a->expr_type == EXPR_VARIABLE
+         && (gfc_check_dependency (matrix_a, expr1, true)
+             || has_dimen_vector_ref (matrix_a)))
+       a_tmp = true;
+    }
+  else
+    a_tmp = true;
+
+  b_tmp = false;
+  b = a->next;
+  matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
+  if (matrix_b != NULL)
+    {
+      if (matrix_b->expr_type == EXPR_VARIABLE
+         && (gfc_check_dependency (matrix_b, expr1, true)
+             || has_dimen_vector_ref (matrix_b)))
+       b_tmp = true;
+    }
+  else
+    b_tmp = true;
+
+  if (!a_tmp && !b_tmp)
+    return 0;
+  
+  current_code = c;
+  inserted_block = NULL;
+  changed_statement = NULL;
+  if (a_tmp)
+    {
+      gfc_expr *at;
+      at = create_var (a->expr,"mma");
+      if (at)
+       a->expr = at;
+    }
+  if (b_tmp)
+    {
+      gfc_expr *bt;
+      bt = create_var (b->expr,"mmb");
+      if (bt)
+       b->expr = bt;
+    }
+  return 0;
+}
+
 /* Auxiliary function to build and simplify an array inquiry function.
    dim is zero-based.  */
 
index bdad0677a3ea7882b47721391ec723aa4a9b3757..accf635d258287c78511e644937f6a2ba29ad479 100644 (file)
@@ -1,3 +1,11 @@
+2017-05-29  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR fortran/37131
+       * gfortran.dg/promotion_2.f90: Add -finline-matmul-limit=0 to
+       flags.
+       * gfortran.dg/transpose_optimization_1.f90: Likewise.
+       * gfortran.dg/inline_matmul_17.f90:  New test.
+
 2017-05-28  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        * gfortran.dg/matmul_bounds_12.f90:  New test.
diff --git a/gcc/testsuite/gfortran.dg/inline_matmul_17.f90 b/gcc/testsuite/gfortran.dg/inline_matmul_17.f90
new file mode 100644 (file)
index 0000000..053dc38
--- /dev/null
@@ -0,0 +1,48 @@
+! { dg-do  run }
+! { dg-options "-O -fdump-tree-optimized -finline-matmul-limit=1000" }
+module x
+  implicit none
+contains
+  function afunc()
+    real, dimension(3,3) :: afunc
+    afunc = reshape([ 2., 3., 5., 7., 11., 13., 17., 19., 23. ], [3,3])
+  end function afunc
+  
+  function bfunc()
+    real, dimension(3,3) :: bfunc
+    bfunc = reshape([29., 31., 37., 41., 43., 47., 53., 59., 61., 67.],[3,3])
+  end function bfunc
+end module x
+
+program main
+  use x
+  implicit none
+  real, dimension(3,3), parameter :: &
+       & aval = reshape([ 2., 3., 5., 7., 11., 13., 17., 19., 23. ], [3,3]), &
+       & bval = reshape([29., 31., 37., 41., 43., 47., 53., 59., 61., 67.],[3,3])
+  integer, dimension(3) :: ind
+  real, dimension(3,3) :: a, b,c,d, ri
+  data ri /120430., 187861., 151737., 161022., 251139., 202847., 212566., 331537., 267781./
+  data d/904., 1131., 1399., 1182., 1489., 1845., 1556., 1967., 2435. /
+  a = aval
+  b = bval
+  c = matmul(a,b)
+  a = matmul(a,b)
+  if (any(a-c /= 0)) call abort
+  a = aval
+  b = bval
+  b = matmul(a,b)
+  if (any(b-c /= 0)) call abort
+  b = bval
+  a = matmul(aval, b)
+  if (any(a-c /= 0)) call abort
+  ind = [1, 3, 2]
+  c = matmul(a(ind,:),b)
+  if (any(c-ri /= 0)) call abort
+  c = matmul(afunc(),b)
+  if (any(c-d /= 0)) call abort
+  a = afunc()
+  c = matmul(a, bfunc())
+  if (any(c-d /= 0)) call abort
+end program main
+! { dg-final { scan-tree-dump-times "matmul_r4" 2 "optimized" } }
index e5365093da754d4a2505b31327e9ff12d8ff15a0..7e3c6c920103d220cef9711b548c756e76b753ae 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdefault-real-8 -fexternal-blas -fdump-tree-original" }
+! { dg-options "-fdefault-real-8 -fexternal-blas -fdump-tree-original -finline-matmul-limit=0" }
 !
 ! PR fortran/54463
 !
index 82116e7f87facfda8389aa1e9c72dc8318b843e9..f1f58322694c56a968284631a9414464b65afa55 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-Warray-temporaries -fdump-tree-original" }
+! { dg-options "-Warray-temporaries -fdump-tree-original -finline-matmul-limit=0" }
 !
 ! PR fortran/45648
 ! Non-copying descriptor transpose optimization (for function call args).