[multiple changes]
authorJerry DeLisle <jvdelisle@gcc.gnu.org>
Tue, 15 Nov 2016 23:03:00 +0000 (23:03 +0000)
committerJerry DeLisle <jvdelisle@gcc.gnu.org>
Tue, 15 Nov 2016 23:03:00 +0000 (23:03 +0000)
2016-11-15  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
    Thomas Koenig  <tkoenig@gcc.gnu.org>

PR libgfortran/51119
* Makefile.am: Add new optimization flags matmul.
* Makefile.in: Regenerate.
* m4/matmul.m4: For the case of all strides = 1, implement a
fast blocked matrix multiply. Fix some whitespace.
* generated/matmul_c10.c: Regenerate.
* generated/matmul_c16.c: Regenerate.
* generated/matmul_c4.c: Regenerate.
* generated/matmul_c8.c: Regenerate.
* generated/matmul_i1.c: Regenerate.
* generated/matmul_i16.c: Regenerate.
* generated/matmul_i2.c: Regenerate.
* generated/matmul_i4.c: Regenerate.
* generated/matmul_i8.c: Regenerate.
* generated/matmul_r10.c: Regenerate.
* generated/matmul_r16.c: Regenerate.
* generated/matmul_r4.c: Regenerate.
* generated/matmul_r8.c: Regenerate.

2016-11-15  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR libgfortran/51119
* gfortran.dg/matmul_12.f90: New test case.

From-SVN: r242462

19 files changed:
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/matmul_12.f90 [new file with mode: 0644]
libgfortran/ChangeLog
libgfortran/Makefile.am
libgfortran/Makefile.in
libgfortran/generated/matmul_c10.c
libgfortran/generated/matmul_c16.c
libgfortran/generated/matmul_c4.c
libgfortran/generated/matmul_c8.c
libgfortran/generated/matmul_i1.c
libgfortran/generated/matmul_i16.c
libgfortran/generated/matmul_i2.c
libgfortran/generated/matmul_i4.c
libgfortran/generated/matmul_i8.c
libgfortran/generated/matmul_r10.c
libgfortran/generated/matmul_r16.c
libgfortran/generated/matmul_r4.c
libgfortran/generated/matmul_r8.c
libgfortran/m4/matmul.m4

index 74a84a38e50a26165b04a77c7ac2ff1e702bbf7f..65dac88b2bd8d216436505a12c9e7083e92f53c8 100644 (file)
@@ -1,3 +1,8 @@
+2016-11-15  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR libgfortran/51119
+       * gfortran.dg/matmul_12.f90: New test case.
+
 2016-11-15  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/i386/funcspec-56.inc: New file.
diff --git a/gcc/testsuite/gfortran.dg/matmul_12.f90 b/gcc/testsuite/gfortran.dg/matmul_12.f90
new file mode 100644 (file)
index 0000000..5badd3f
--- /dev/null
@@ -0,0 +1,22 @@
+! { dg-do run }
+program main
+  integer, parameter :: sz=5, su=3
+  integer, parameter :: l=2
+  integer, parameter :: u=l-1+su
+  integer(kind=4), dimension(sz,sz) :: r,a,b
+  integer :: i,j
+  do i=1,4
+     do j=1,4
+        a(i,j) = i*10+j
+        b(i,j) = 100+i*10+j
+     end do
+  end do
+  r = -1
+  b(l:u,l:u) = reshape([(i,i=1,su*su)],[su,su]);
+  a(l:u,l:u) = reshape([(i,i=1,su*su)],[su,su]);
+
+  r(1:su,1:su) = matmul(a(l:u,l:u),b(l:u,l:u))
+  if (any(reshape(r,[sz*sz]) /= [30, 36, 42, -1, -1, 66, 81, 96, -1, -1,&
+       & 102, 126, 150, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1])) &
+       call abort
+end program main
index da3b3e0878fa9f7725ade5ce05cef3a607f39833..50305af70a881d9667d74b0ed676c07206cfc5ef 100644 (file)
@@ -1,3 +1,25 @@
+2016-11-15  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
+           Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR libgfortran/51119
+       * Makefile.am: Add new optimization flags matmul.
+       * Makefile.in: Regenerate.
+       * m4/matmul.m4: For the case of all strides = 1, implement a
+       fast blocked matrix multiply. Fix some whitespace.
+       * generated/matmul_c10.c: Regenerate.
+       * generated/matmul_c16.c: Regenerate.
+       * generated/matmul_c4.c: Regenerate.
+       * generated/matmul_c8.c: Regenerate.
+       * generated/matmul_i1.c: Regenerate.
+       * generated/matmul_i16.c: Regenerate.
+       * generated/matmul_i2.c: Regenerate.
+       * generated/matmul_i4.c: Regenerate.
+       * generated/matmul_i8.c: Regenerate.
+       * generated/matmul_r10.c: Regenerate.
+       * generated/matmul_r16.c: Regenerate.
+       * generated/matmul_r4.c: Regenerate.
+       * generated/matmul_r8.c: Regenerate.
+
 2016-11-15  Matthias Klose  <doko@ubuntu.com>
 
        * configure: Regenerate.
index 39d3e11d223ca9885b5d433fc50c44e6c453de16..7f4002dcad48ba0d5a30a02725e38173d4840e62 100644 (file)
@@ -850,7 +850,7 @@ intrinsics/dprod_r8.f90 \
 intrinsics/f2c_specifics.F90
 
 # Turn on vectorization and loop unrolling for matmul.
-$(patsubst %.c,%.lo,$(notdir $(i_matmul_c))): AM_CFLAGS += -ftree-vectorize -funroll-loops
+$(patsubst %.c,%.lo,$(notdir $(i_matmul_c))): AM_CFLAGS += -ffast-math -fno-protect-parens -fstack-arrays -ftree-vectorize -funroll-loops --param max-unroll-times=4 
 # Logical matmul doesn't vectorize.
 $(patsubst %.c,%.lo,$(notdir $(i_matmull_c))): AM_CFLAGS += -funroll-loops
 
index 7ed080cf7b0d4c006263a90596187b07a1d48a03..c1a37d78c40bb47abb8a45c459b20b82ac77d40f 100644 (file)
@@ -5956,7 +5956,7 @@ uninstall-am: uninstall-cafexeclibLTLIBRARIES \
 @LIBGFOR_USE_SYMVER_SUN_TRUE@@LIBGFOR_USE_SYMVER_TRUE@  > $@ || (rm -f $@ ; exit 1)
 
 # Turn on vectorization and loop unrolling for matmul.
-$(patsubst %.c,%.lo,$(notdir $(i_matmul_c))): AM_CFLAGS += -ftree-vectorize -funroll-loops
+$(patsubst %.c,%.lo,$(notdir $(i_matmul_c))): AM_CFLAGS += -ffast-math -fno-protect-parens -fstack-arrays -ftree-vectorize -funroll-loops --param max-unroll-times=4 
 # Logical matmul doesn't vectorize.
 $(patsubst %.c,%.lo,$(notdir $(i_matmull_c))): AM_CFLAGS += -funroll-loops
 
index c95581849886384eff4fe00e41501580898854c8..c784a2630cdfb49478fcf15e87ca012ec12ca328 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_COMPLEX_10)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_c10 (gfc_array_c10 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_c10 (gfc_array_c10 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_10));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_c10 (gfc_array_c10 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_COMPLEX_10 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_COMPLEX_10 * restrict bbase_y;
-      GFC_COMPLEX_10 * restrict dest_y;
-      const GFC_COMPLEX_10 * restrict abase_n;
-      GFC_COMPLEX_10 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_COMPLEX_10 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_COMPLEX_10) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_COMPLEX_10)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_COMPLEX_10 *a, *b;
+      GFC_COMPLEX_10 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_COMPLEX_10 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_COMPLEX_10)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_c10 (gfc_array_c10 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_c10 (gfc_array_c10 * const restrict retarray,
        }
     }
 }
-
 #endif
index 25fe56e767472bc093011bae2d39cf8f158a25df..47e1bea729b5353c5f06db0caa2727990f8b8a40 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_COMPLEX_16)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_c16 (gfc_array_c16 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_c16 (gfc_array_c16 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_16));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_c16 (gfc_array_c16 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_COMPLEX_16 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_COMPLEX_16 * restrict bbase_y;
-      GFC_COMPLEX_16 * restrict dest_y;
-      const GFC_COMPLEX_16 * restrict abase_n;
-      GFC_COMPLEX_16 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_COMPLEX_16 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_COMPLEX_16) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_COMPLEX_16)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_COMPLEX_16 *a, *b;
+      GFC_COMPLEX_16 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_COMPLEX_16 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_COMPLEX_16)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_c16 (gfc_array_c16 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_c16 (gfc_array_c16 * const restrict retarray,
        }
     }
 }
-
 #endif
index e9d2ed33d5c4a8742ef556181d8ba9dda8267eef..4eb18965d91ab4a523e944a0847a7b1e2c4862af 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_COMPLEX_4)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_c4 (gfc_array_c4 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_c4 (gfc_array_c4 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_4));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_c4 (gfc_array_c4 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_COMPLEX_4 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_COMPLEX_4 * restrict bbase_y;
-      GFC_COMPLEX_4 * restrict dest_y;
-      const GFC_COMPLEX_4 * restrict abase_n;
-      GFC_COMPLEX_4 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_COMPLEX_4 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_COMPLEX_4) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_COMPLEX_4)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_COMPLEX_4 *a, *b;
+      GFC_COMPLEX_4 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_COMPLEX_4 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_COMPLEX_4)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_c4 (gfc_array_c4 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_c4 (gfc_array_c4 * const restrict retarray,
        }
     }
 }
-
 #endif
index 8a127da860ecec2c9ccfe242f162355929e38cd0..2321b9effbd69942cfa7b2fdf63254ef1f4ab54e 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_COMPLEX_8)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_c8 (gfc_array_c8 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_c8 (gfc_array_c8 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_8));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_c8 (gfc_array_c8 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_COMPLEX_8 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_COMPLEX_8 * restrict bbase_y;
-      GFC_COMPLEX_8 * restrict dest_y;
-      const GFC_COMPLEX_8 * restrict abase_n;
-      GFC_COMPLEX_8 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_COMPLEX_8 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_COMPLEX_8) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_COMPLEX_8)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_COMPLEX_8 *a, *b;
+      GFC_COMPLEX_8 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_COMPLEX_8 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_COMPLEX_8)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_c8 (gfc_array_c8 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_c8 (gfc_array_c8 * const restrict retarray,
        }
     }
 }
-
 #endif
index fdb309269110266bc05c4d2629aba77a12f926bc..81c067b2ce1ef1524470ebefe96c3d40f5b899be 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_INTEGER_1)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_i1 (gfc_array_i1 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_i1 (gfc_array_i1 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_INTEGER_1));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_i1 (gfc_array_i1 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_INTEGER_1 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_INTEGER_1 * restrict bbase_y;
-      GFC_INTEGER_1 * restrict dest_y;
-      const GFC_INTEGER_1 * restrict abase_n;
-      GFC_INTEGER_1 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_INTEGER_1 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_INTEGER_1) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_INTEGER_1)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_INTEGER_1 *a, *b;
+      GFC_INTEGER_1 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_INTEGER_1 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_INTEGER_1)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_i1 (gfc_array_i1 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_i1 (gfc_array_i1 * const restrict retarray,
        }
     }
 }
-
 #endif
index 80eb63c31ceb9b130a9f598618200c83b4b42b83..d1b1761014a263c8adea4a0bedebead061c3679f 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_INTEGER_16)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_i16 (gfc_array_i16 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_i16 (gfc_array_i16 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_INTEGER_16));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_i16 (gfc_array_i16 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_INTEGER_16 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_INTEGER_16 * restrict bbase_y;
-      GFC_INTEGER_16 * restrict dest_y;
-      const GFC_INTEGER_16 * restrict abase_n;
-      GFC_INTEGER_16 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_INTEGER_16 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_INTEGER_16) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_INTEGER_16)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_INTEGER_16 *a, *b;
+      GFC_INTEGER_16 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_INTEGER_16 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_INTEGER_16)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_i16 (gfc_array_i16 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_i16 (gfc_array_i16 * const restrict retarray,
        }
     }
 }
-
 #endif
index 281a0133cbbe66273f9200164566c836b989b9f6..5a06fcc6a2c0e0f2cc345537cda81d29a0a203f3 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_INTEGER_2)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_i2 (gfc_array_i2 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_i2 (gfc_array_i2 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_INTEGER_2));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_i2 (gfc_array_i2 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_INTEGER_2 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_INTEGER_2 * restrict bbase_y;
-      GFC_INTEGER_2 * restrict dest_y;
-      const GFC_INTEGER_2 * restrict abase_n;
-      GFC_INTEGER_2 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_INTEGER_2 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_INTEGER_2) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_INTEGER_2)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_INTEGER_2 *a, *b;
+      GFC_INTEGER_2 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_INTEGER_2 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_INTEGER_2)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_i2 (gfc_array_i2 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_i2 (gfc_array_i2 * const restrict retarray,
        }
     }
 }
-
 #endif
index 2dc526d9b9c2f604ea6305d7e5f652eee0dd1662..aee8e4d55d50bcb90c49819c8991b1f42eafad12 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_INTEGER_4)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_i4 (gfc_array_i4 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_i4 (gfc_array_i4 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_INTEGER_4));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_i4 (gfc_array_i4 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_INTEGER_4 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_INTEGER_4 * restrict bbase_y;
-      GFC_INTEGER_4 * restrict dest_y;
-      const GFC_INTEGER_4 * restrict abase_n;
-      GFC_INTEGER_4 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_INTEGER_4 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_INTEGER_4) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_INTEGER_4)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_INTEGER_4 *a, *b;
+      GFC_INTEGER_4 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_INTEGER_4 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_INTEGER_4)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_i4 (gfc_array_i4 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_i4 (gfc_array_i4 * const restrict retarray,
        }
     }
 }
-
 #endif
index 0ff728d90e91c1075ffc09f605447d366f2db629..902b284075137c011cfa2ac5473b1c88c9096e0f 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_INTEGER_8)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_i8 (gfc_array_i8 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_i8 (gfc_array_i8 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_INTEGER_8));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_i8 (gfc_array_i8 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_INTEGER_8 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_INTEGER_8 * restrict bbase_y;
-      GFC_INTEGER_8 * restrict dest_y;
-      const GFC_INTEGER_8 * restrict abase_n;
-      GFC_INTEGER_8 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_INTEGER_8 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_INTEGER_8) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_INTEGER_8)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_INTEGER_8 *a, *b;
+      GFC_INTEGER_8 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_INTEGER_8 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_INTEGER_8)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_i8 (gfc_array_i8 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_i8 (gfc_array_i8 * const restrict retarray,
        }
     }
 }
-
 #endif
index a34856f010f367e80d5ebd66ffb159120ee3305c..8bb1e6297bb35b871417b86da6a85aa743e01a5a 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_REAL_10)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_r10 (gfc_array_r10 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_r10 (gfc_array_r10 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_REAL_10));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_r10 (gfc_array_r10 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_REAL_10 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_REAL_10 * restrict bbase_y;
-      GFC_REAL_10 * restrict dest_y;
-      const GFC_REAL_10 * restrict abase_n;
-      GFC_REAL_10 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_REAL_10 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_REAL_10) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_REAL_10)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_REAL_10 *a, *b;
+      GFC_REAL_10 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_REAL_10 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_REAL_10)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_r10 (gfc_array_r10 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_r10 (gfc_array_r10 * const restrict retarray,
        }
     }
 }
-
 #endif
index d2f11bdd9844c9fb97496d2902abe8d0e59de506..4ebd104594bf801817ab640c5d77adc66b95e833 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_REAL_16)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_r16 (gfc_array_r16 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_r16 (gfc_array_r16 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_REAL_16));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_r16 (gfc_array_r16 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_REAL_16 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_REAL_16 * restrict bbase_y;
-      GFC_REAL_16 * restrict dest_y;
-      const GFC_REAL_16 * restrict abase_n;
-      GFC_REAL_16 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_REAL_16 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_REAL_16) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_REAL_16)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_REAL_16 *a, *b;
+      GFC_REAL_16 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_REAL_16 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_REAL_16)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_r16 (gfc_array_r16 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_r16 (gfc_array_r16 * const restrict retarray,
        }
     }
 }
-
 #endif
index ff3b93ff4d47c6c84b76286cb8af6f85bec22154..cf3ffa352328f3246ffaf14e98d8a4b6f0fe354e 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_REAL_4)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_r4 (gfc_array_r4 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_r4 (gfc_array_r4 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_REAL_4));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_r4 (gfc_array_r4 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_REAL_4 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_REAL_4 * restrict bbase_y;
-      GFC_REAL_4 * restrict dest_y;
-      const GFC_REAL_4 * restrict abase_n;
-      GFC_REAL_4 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_REAL_4 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_REAL_4) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_REAL_4)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_REAL_4 *a, *b;
+      GFC_REAL_4 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_REAL_4 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_REAL_4)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_r4 (gfc_array_r4 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_r4 (gfc_array_r4 * const restrict retarray,
        }
     }
 }
-
 #endif
index af805ee45eec21845df9d9b9784f653dae250f9d..9a70a23df0bb1a2a6bbc02ef8ec428d312808e57 100644 (file)
@@ -32,7 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #if defined (HAVE_GFC_REAL_8)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we'll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -99,7 +99,7 @@ matmul_r8 (gfc_array_r8 * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -127,47 +127,47 @@ matmul_r8 (gfc_array_r8 * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_REAL_8));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 
 
   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
@@ -230,61 +230,294 @@ matmul_r8 (gfc_array_r8 * const restrict retarray,
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we're performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const GFC_REAL_8 one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const GFC_REAL_8 * restrict bbase_y;
-      GFC_REAL_8 * restrict dest_y;
-      const GFC_REAL_8 * restrict abase_n;
-      GFC_REAL_8 bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const GFC_REAL_8 one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof (GFC_REAL_8) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = (GFC_REAL_8)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const GFC_REAL_8 *a, *b;
+      GFC_REAL_8 *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      GFC_REAL_8 t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = (GFC_REAL_8)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -334,7 +567,9 @@ matmul_r8 (gfc_array_r8 * const restrict retarray,
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -372,5 +607,4 @@ matmul_r8 (gfc_array_r8 * const restrict retarray,
        }
     }
 }
-
 #endif
index 468615b6c4255c4d7c6342b16090cecb5e539e72..77ed4408425bb47e93a2f20e908cef2ba32317ec 100644 (file)
@@ -33,7 +33,7 @@ include(iparm.m4)dnl
 `#if defined (HAVE_'rtype_name`)
 
 /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
-   passed to us by the front-end, in which case we''`ll call it for large
+   passed to us by the front-end, in which case we call it for large
    matrices.  */
 
 typedef void (*blas_call)(const char *, const char *, const int *, const int *,
@@ -100,7 +100,7 @@ matmul_'rtype_code` ('rtype` * const restrict retarray,
 
    o One-dimensional argument B is implicitly treated as a column matrix
      dimensioned [count, 1], so ycount=1.
-  */
+*/
 
   if (retarray->base_addr == NULL)
     {
@@ -128,47 +128,47 @@ matmul_'rtype_code` ('rtype` * const restrict retarray,
        = xmallocarray (size0 ((array_t *) retarray), sizeof ('rtype_name`));
       retarray->offset = 0;
     }
-    else if (unlikely (compile_options.bounds_check))
-      {
-       index_type ret_extent, arg_extent;
-
-       if (GFC_DESCRIPTOR_RANK (a) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-       else if (GFC_DESCRIPTOR_RANK (b) == 1)
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic: is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);         
-         }
-       else
-         {
-           arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 1:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-
-           arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
-           ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
-           if (arg_extent != ret_extent)
-             runtime_error ("Incorrect extent in return array in"
-                            " MATMUL intrinsic for dimension 2:"
-                            " is %ld, should be %ld",
-                            (long int) ret_extent, (long int) arg_extent);
-         }
-      }
+  else if (unlikely (compile_options.bounds_check))
+    {
+      index_type ret_extent, arg_extent;
+
+      if (GFC_DESCRIPTOR_RANK (a) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else if (GFC_DESCRIPTOR_RANK (b) == 1)
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic: is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+      else
+       {
+         arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 1:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+
+         arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
+         ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
+         if (arg_extent != ret_extent)
+           runtime_error ("Incorrect extent in return array in"
+                          " MATMUL intrinsic for dimension 2:"
+                          " is %ld, should be %ld",
+                          (long int) ret_extent, (long int) arg_extent);
+       }
+    }
 '
 sinclude(`matmul_asm_'rtype_code`.m4')dnl
 `
@@ -232,61 +232,294 @@ sinclude(`matmul_asm_'rtype_code`.m4')dnl
   bbase = b->base_addr;
   dest = retarray->base_addr;
 
-
-  /* Now that everything is set up, we''`re performing the multiplication
+  /* Now that everything is set up, we perform the multiplication
      itself.  */
 
 #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
 
   if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
       && (bxstride == 1 || bystride == 1)
       && (((float) xcount) * ((float) ycount) * ((float) count)
           > POW3(blas_limit)))
-  {
-    const int m = xcount, n = ycount, k = count, ldc = rystride;
-    const 'rtype_name` one = 1, zero = 0;
-    const int lda = (axstride == 1) ? aystride : axstride,
-              ldb = (bxstride == 1) ? bystride : bxstride;
-
-    if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
-      {
-        assert (gemm != NULL);
-        gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m, &n, &k,
-              &one, abase, &lda, bbase, &ldb, &zero, dest, &ldc, 1, 1);
-        return;
-      }
-  }
-
-  if (rxstride == 1 && axstride == 1 && bxstride == 1)
     {
-      const 'rtype_name` * restrict bbase_y;
-      'rtype_name` * restrict dest_y;
-      const 'rtype_name` * restrict abase_n;
-      'rtype_name` bbase_yn;
+      const int m = xcount, n = ycount, k = count, ldc = rystride;
+      const 'rtype_name` one = 1, zero = 0;
+      const int lda = (axstride == 1) ? aystride : axstride,
+               ldb = (bxstride == 1) ? bystride : bxstride;
 
-      if (rystride == xcount)
-       memset (dest, 0, (sizeof ('rtype_name`) * xcount * ycount));
-      else
+      if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
        {
-         for (y = 0; y < ycount; y++)
-           for (x = 0; x < xcount; x++)
-             dest[x + y*rystride] = ('rtype_name`)0;
+         assert (gemm != NULL);
+         gemm (axstride == 1 ? "N" : "T", bxstride == 1 ? "N" : "T", &m,
+               &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
+               &ldc, 1, 1);
+         return;
        }
+    }
 
-      for (y = 0; y < ycount; y++)
+  if (rxstride == 1 && axstride == 1 && bxstride == 1)
+    {
+      /* This block of code implements a tuned matmul, derived from
+         Superscalar GEMM-based level 3 BLAS,  Beta version 0.1
+
+               Bo Kagstrom and Per Ling
+               Department of Computing Science
+               Umea University
+               S-901 87 Umea, Sweden
+
+        from netlib.org, translated to C, and modified for matmul.m4.  */
+
+      const 'rtype_name` *a, *b;
+      'rtype_name` *c;
+      const index_type m = xcount, n = ycount, k = count;
+
+      /* System generated locals */
+      index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
+                i1, i2, i3, i4, i5, i6;
+
+      /* Local variables */
+      'rtype_name` t1[65536], /* was [256][256] */
+                f11, f12, f21, f22, f31, f32, f41, f42,
+                f13, f14, f23, f24, f33, f34, f43, f44;
+      index_type i, j, l, ii, jj, ll;
+      index_type isec, jsec, lsec, uisec, ujsec, ulsec;
+
+      a = abase;
+      b = bbase;
+      c = retarray->base_addr;
+
+      /* Parameter adjustments */
+      c_dim1 = rystride;
+      c_offset = 1 + c_dim1;
+      c -= c_offset;
+      a_dim1 = aystride;
+      a_offset = 1 + a_dim1;
+      a -= a_offset;
+      b_dim1 = bystride;
+      b_offset = 1 + b_dim1;
+      b -= b_offset;
+
+      /* Early exit if possible */
+      if (m == 0 || n == 0 || k == 0)
+       return;
+
+      /* Empty c first.  */
+      for (j=1; j<=n; j++)
+       for (i=1; i<=m; i++)
+         c[i + j * c_dim1] = ('rtype_name`)0;
+
+      /* Start turning the crank. */
+      i1 = n;
+      for (jj = 1; jj <= i1; jj += 512)
        {
-         bbase_y = bbase + y*bystride;
-         dest_y = dest + y*rystride;
-         for (n = 0; n < count; n++)
+         /* Computing MIN */
+         i2 = 512;
+         i3 = n - jj + 1;
+         jsec = min(i2,i3);
+         ujsec = jsec - jsec % 4;
+         i2 = k;
+         for (ll = 1; ll <= i2; ll += 256)
            {
-             abase_n = abase + n*aystride;
-             bbase_yn = bbase_y[n];
-             for (x = 0; x < xcount; x++)
+             /* Computing MIN */
+             i3 = 256;
+             i4 = k - ll + 1;
+             lsec = min(i3,i4);
+             ulsec = lsec - lsec % 2;
+
+             i3 = m;
+             for (ii = 1; ii <= i3; ii += 256)
                {
-                 dest_y[x] += abase_n[x] * bbase_yn;
+                 /* Computing MIN */
+                 i4 = 256;
+                 i5 = m - ii + 1;
+                 isec = min(i4,i5);
+                 uisec = isec - isec % 2;
+                 i4 = ll + ulsec - 1;
+                 for (l = ll; l <= i4; l += 2)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 2)
+                       {
+                         t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
+                                       a[i + (l + 1) * a_dim1];
+                         t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + l * a_dim1];
+                         t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
+                                       a[i + 1 + (l + 1) * a_dim1];
+                       }
+                     if (uisec < isec)
+                       {
+                         t1[l - ll + 1 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + l * a_dim1];
+                         t1[l - ll + 2 + (isec << 8) - 257] =
+                                   a[ii + isec - 1 + (l + 1) * a_dim1];
+                       }
+                   }
+                 if (ulsec < lsec)
+                   {
+                     i4 = ii + isec - 1;
+                     for (i = ii; i<= i4; ++i)
+                       {
+                         t1[lsec + ((i - ii + 1) << 8) - 257] =
+                                   a[i + (ll + lsec - 1) * a_dim1];
+                       }
+                   }
+
+                 uisec = isec - isec % 4;
+                 i4 = jj + ujsec - 1;
+                 for (j = jj; j <= i4; j += 4)
+                   {
+                     i5 = ii + uisec - 1;
+                     for (i = ii; i <= i5; i += 4)
+                       {
+                         f11 = c[i + j * c_dim1];
+                         f21 = c[i + 1 + j * c_dim1];
+                         f12 = c[i + (j + 1) * c_dim1];
+                         f22 = c[i + 1 + (j + 1) * c_dim1];
+                         f13 = c[i + (j + 2) * c_dim1];
+                         f23 = c[i + 1 + (j + 2) * c_dim1];
+                         f14 = c[i + (j + 3) * c_dim1];
+                         f24 = c[i + 1 + (j + 3) * c_dim1];
+                         f31 = c[i + 2 + j * c_dim1];
+                         f41 = c[i + 3 + j * c_dim1];
+                         f32 = c[i + 2 + (j + 1) * c_dim1];
+                         f42 = c[i + 3 + (j + 1) * c_dim1];
+                         f33 = c[i + 2 + (j + 2) * c_dim1];
+                         f43 = c[i + 3 + (j + 2) * c_dim1];
+                         f34 = c[i + 2 + (j + 3) * c_dim1];
+                         f44 = c[i + 3 + (j + 3) * c_dim1];
+                         i6 = ll + lsec - 1;
+                         for (l = ll; l <= i6; ++l)
+                           {
+                             f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + j * b_dim1];
+                             f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 1) * b_dim1];
+                             f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 2) * b_dim1];
+                             f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                             f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
+                                     * b[l + (j + 3) * b_dim1];
+                           }
+                         c[i + j * c_dim1] = f11;
+                         c[i + 1 + j * c_dim1] = f21;
+                         c[i + (j + 1) * c_dim1] = f12;
+                         c[i + 1 + (j + 1) * c_dim1] = f22;
+                         c[i + (j + 2) * c_dim1] = f13;
+                         c[i + 1 + (j + 2) * c_dim1] = f23;
+                         c[i + (j + 3) * c_dim1] = f14;
+                         c[i + 1 + (j + 3) * c_dim1] = f24;
+                         c[i + 2 + j * c_dim1] = f31;
+                         c[i + 3 + j * c_dim1] = f41;
+                         c[i + 2 + (j + 1) * c_dim1] = f32;
+                         c[i + 3 + (j + 1) * c_dim1] = f42;
+                         c[i + 2 + (j + 2) * c_dim1] = f33;
+                         c[i + 3 + (j + 2) * c_dim1] = f43;
+                         c[i + 2 + (j + 3) * c_dim1] = f34;
+                         c[i + 3 + (j + 3) * c_dim1] = f44;
+                       }
+                     if (uisec < isec)
+                       {
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f12 = c[i + (j + 1) * c_dim1];
+                             f13 = c[i + (j + 2) * c_dim1];
+                             f14 = c[i + (j + 3) * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 1) * b_dim1];
+                                 f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 2) * b_dim1];
+                                 f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + (j + 3) * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + (j + 1) * c_dim1] = f12;
+                             c[i + (j + 2) * c_dim1] = f13;
+                             c[i + (j + 3) * c_dim1] = f14;
+                           }
+                       }
+                   }
+                 if (ujsec < jsec)
+                   {
+                     i4 = jj + jsec - 1;
+                     for (j = jj + ujsec; j <= i4; ++j)
+                       {
+                         i5 = ii + uisec - 1;
+                         for (i = ii; i <= i5; i += 4)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             f21 = c[i + 1 + j * c_dim1];
+                             f31 = c[i + 2 + j * c_dim1];
+                             f41 = c[i + 3 + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
+                                         257] * b[l + j * b_dim1];
+                                 f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                             c[i + 1 + j * c_dim1] = f21;
+                             c[i + 2 + j * c_dim1] = f31;
+                             c[i + 3 + j * c_dim1] = f41;
+                           }
+                         i5 = ii + isec - 1;
+                         for (i = ii + uisec; i <= i5; ++i)
+                           {
+                             f11 = c[i + j * c_dim1];
+                             i6 = ll + lsec - 1;
+                             for (l = ll; l <= i6; ++l)
+                               {
+                                 f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
+                                         257] * b[l + j * b_dim1];
+                               }
+                             c[i + j * c_dim1] = f11;
+                           }
+                       }
+                   }
                }
            }
        }
+      return;
     }
   else if (rxstride == 1 && aystride == 1 && bxstride == 1)
     {
@@ -336,7 +569,9 @@ sinclude(`matmul_asm_'rtype_code`.m4')dnl
        for (n = 0; n < count; n++)
          for (x = 0; x < xcount; x++)
            /* dest[x,y] += a[x,n] * b[n,y] */
-           dest[x*rxstride + y*rystride] += abase[x*axstride + n*aystride] * bbase[n*bxstride + y*bystride];
+           dest[x*rxstride + y*rystride] +=
+                                       abase[x*axstride + n*aystride] *
+                                       bbase[n*bxstride + y*bystride];
     }
   else if (GFC_DESCRIPTOR_RANK (a) == 1)
     {
@@ -373,6 +608,5 @@ sinclude(`matmul_asm_'rtype_code`.m4')dnl
            }
        }
     }
-}
-
-#endif'
+}'
+#endif