matmul_c10.c 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013
  1. /* Implementation of the MATMUL intrinsic
  2. Copyright (C) 2002-2022 Free Software Foundation, Inc.
  3. Contributed by Paul Brook <paul@nowt.org>
  4. This file is part of the GNU Fortran runtime library (libgfortran).
  5. Libgfortran is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public
  7. License as published by the Free Software Foundation; either
  8. version 3 of the License, or (at your option) any later version.
  9. Libgfortran is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. #include "libgfortran.h"
  21. #include <string.h>
  22. #include <assert.h>
  23. #if defined (HAVE_GFC_COMPLEX_10)
  24. /* Prototype for the BLAS ?gemm subroutine, a pointer to which can be
  25. passed to us by the front-end, in which case we call it for large
  26. matrices. */
  27. typedef void (*blas_call)(const char *, const char *, const int *, const int *,
  28. const int *, const GFC_COMPLEX_10 *, const GFC_COMPLEX_10 *,
  29. const int *, const GFC_COMPLEX_10 *, const int *,
  30. const GFC_COMPLEX_10 *, GFC_COMPLEX_10 *, const int *,
  31. int, int);
  32. /* The order of loops is different in the case of plain matrix
  33. multiplication C=MATMUL(A,B), and in the frequent special case where
  34. the argument A is the temporary result of a TRANSPOSE intrinsic:
  35. C=MATMUL(TRANSPOSE(A),B). Transposed temporaries are detected by
  36. looking at their strides.
  37. The equivalent Fortran pseudo-code is:
  38. DIMENSION A(M,COUNT), B(COUNT,N), C(M,N)
  39. IF (.NOT.IS_TRANSPOSED(A)) THEN
  40. C = 0
  41. DO J=1,N
  42. DO K=1,COUNT
  43. DO I=1,M
  44. C(I,J) = C(I,J)+A(I,K)*B(K,J)
  45. ELSE
  46. DO J=1,N
  47. DO I=1,M
  48. S = 0
  49. DO K=1,COUNT
  50. S = S+A(I,K)*B(K,J)
  51. C(I,J) = S
  52. ENDIF
  53. */
  54. /* If try_blas is set to a nonzero value, then the matmul function will
  55. see if there is a way to perform the matrix multiplication by a call
  56. to the BLAS gemm function. */
  57. extern void matmul_c10 (gfc_array_c10 * const restrict retarray,
  58. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  59. int blas_limit, blas_call gemm);
  60. export_proto(matmul_c10);
  61. /* Put exhaustive list of possible architectures here here, ORed together. */
  62. #if defined(HAVE_AVX) || defined(HAVE_AVX2) || defined(HAVE_AVX512F)
  63. #ifdef HAVE_AVX
  64. static void
  65. matmul_c10_avx (gfc_array_c10 * const restrict retarray,
  66. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  67. int blas_limit, blas_call gemm) __attribute__((__target__("avx")));
  68. static void
  69. matmul_c10_avx (gfc_array_c10 * const restrict retarray,
  70. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  71. int blas_limit, blas_call gemm)
  72. {
  73. const GFC_COMPLEX_10 * restrict abase;
  74. const GFC_COMPLEX_10 * restrict bbase;
  75. GFC_COMPLEX_10 * restrict dest;
  76. index_type rxstride, rystride, axstride, aystride, bxstride, bystride;
  77. index_type x, y, n, count, xcount, ycount;
  78. assert (GFC_DESCRIPTOR_RANK (a) == 2
  79. || GFC_DESCRIPTOR_RANK (b) == 2);
  80. /* C[xcount,ycount] = A[xcount, count] * B[count,ycount]
  81. Either A or B (but not both) can be rank 1:
  82. o One-dimensional argument A is implicitly treated as a row matrix
  83. dimensioned [1,count], so xcount=1.
  84. o One-dimensional argument B is implicitly treated as a column matrix
  85. dimensioned [count, 1], so ycount=1.
  86. */
  87. if (retarray->base_addr == NULL)
  88. {
  89. if (GFC_DESCRIPTOR_RANK (a) == 1)
  90. {
  91. GFC_DIMENSION_SET(retarray->dim[0], 0,
  92. GFC_DESCRIPTOR_EXTENT(b,1) - 1, 1);
  93. }
  94. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  95. {
  96. GFC_DIMENSION_SET(retarray->dim[0], 0,
  97. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  98. }
  99. else
  100. {
  101. GFC_DIMENSION_SET(retarray->dim[0], 0,
  102. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  103. GFC_DIMENSION_SET(retarray->dim[1], 0,
  104. GFC_DESCRIPTOR_EXTENT(b,1) - 1,
  105. GFC_DESCRIPTOR_EXTENT(retarray,0));
  106. }
  107. retarray->base_addr
  108. = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_10));
  109. retarray->offset = 0;
  110. }
  111. else if (unlikely (compile_options.bounds_check))
  112. {
  113. index_type ret_extent, arg_extent;
  114. if (GFC_DESCRIPTOR_RANK (a) == 1)
  115. {
  116. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  117. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  118. if (arg_extent != ret_extent)
  119. runtime_error ("Array bound mismatch for dimension 1 of "
  120. "array (%ld/%ld) ",
  121. (long int) ret_extent, (long int) arg_extent);
  122. }
  123. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  124. {
  125. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  126. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  127. if (arg_extent != ret_extent)
  128. runtime_error ("Array bound mismatch for dimension 1 of "
  129. "array (%ld/%ld) ",
  130. (long int) ret_extent, (long int) arg_extent);
  131. }
  132. else
  133. {
  134. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  135. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  136. if (arg_extent != ret_extent)
  137. runtime_error ("Array bound mismatch for dimension 1 of "
  138. "array (%ld/%ld) ",
  139. (long int) ret_extent, (long int) arg_extent);
  140. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  141. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
  142. if (arg_extent != ret_extent)
  143. runtime_error ("Array bound mismatch for dimension 2 of "
  144. "array (%ld/%ld) ",
  145. (long int) ret_extent, (long int) arg_extent);
  146. }
  147. }
  148. if (GFC_DESCRIPTOR_RANK (retarray) == 1)
  149. {
  150. /* One-dimensional result may be addressed in the code below
  151. either as a row or a column matrix. We want both cases to
  152. work. */
  153. rxstride = rystride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  154. }
  155. else
  156. {
  157. rxstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  158. rystride = GFC_DESCRIPTOR_STRIDE(retarray,1);
  159. }
  160. if (GFC_DESCRIPTOR_RANK (a) == 1)
  161. {
  162. /* Treat it as a a row matrix A[1,count]. */
  163. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  164. aystride = 1;
  165. xcount = 1;
  166. count = GFC_DESCRIPTOR_EXTENT(a,0);
  167. }
  168. else
  169. {
  170. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  171. aystride = GFC_DESCRIPTOR_STRIDE(a,1);
  172. count = GFC_DESCRIPTOR_EXTENT(a,1);
  173. xcount = GFC_DESCRIPTOR_EXTENT(a,0);
  174. }
  175. if (count != GFC_DESCRIPTOR_EXTENT(b,0))
  176. {
  177. if (count > 0 || GFC_DESCRIPTOR_EXTENT(b,0) > 0)
  178. runtime_error ("Incorrect extent in argument B in MATMUL intrinsic "
  179. "in dimension 1: is %ld, should be %ld",
  180. (long int) GFC_DESCRIPTOR_EXTENT(b,0), (long int) count);
  181. }
  182. if (GFC_DESCRIPTOR_RANK (b) == 1)
  183. {
  184. /* Treat it as a column matrix B[count,1] */
  185. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  186. /* bystride should never be used for 1-dimensional b.
  187. The value is only used for calculation of the
  188. memory by the buffer. */
  189. bystride = 256;
  190. ycount = 1;
  191. }
  192. else
  193. {
  194. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  195. bystride = GFC_DESCRIPTOR_STRIDE(b,1);
  196. ycount = GFC_DESCRIPTOR_EXTENT(b,1);
  197. }
  198. abase = a->base_addr;
  199. bbase = b->base_addr;
  200. dest = retarray->base_addr;
  201. /* Now that everything is set up, we perform the multiplication
  202. itself. */
  203. #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
  204. #define min(a,b) ((a) <= (b) ? (a) : (b))
  205. #define max(a,b) ((a) >= (b) ? (a) : (b))
  206. if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
  207. && (bxstride == 1 || bystride == 1)
  208. && (((float) xcount) * ((float) ycount) * ((float) count)
  209. > POW3(blas_limit)))
  210. {
  211. const int m = xcount, n = ycount, k = count, ldc = rystride;
  212. const GFC_COMPLEX_10 one = 1, zero = 0;
  213. const int lda = (axstride == 1) ? aystride : axstride,
  214. ldb = (bxstride == 1) ? bystride : bxstride;
  215. if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
  216. {
  217. assert (gemm != NULL);
  218. const char *transa, *transb;
  219. if (try_blas & 2)
  220. transa = "C";
  221. else
  222. transa = axstride == 1 ? "N" : "T";
  223. if (try_blas & 4)
  224. transb = "C";
  225. else
  226. transb = bxstride == 1 ? "N" : "T";
  227. gemm (transa, transb , &m,
  228. &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
  229. &ldc, 1, 1);
  230. return;
  231. }
  232. }
  233. if (rxstride == 1 && axstride == 1 && bxstride == 1
  234. && GFC_DESCRIPTOR_RANK (b) != 1)
  235. {
  236. /* This block of code implements a tuned matmul, derived from
  237. Superscalar GEMM-based level 3 BLAS, Beta version 0.1
  238. Bo Kagstrom and Per Ling
  239. Department of Computing Science
  240. Umea University
  241. S-901 87 Umea, Sweden
  242. from netlib.org, translated to C, and modified for matmul.m4. */
  243. const GFC_COMPLEX_10 *a, *b;
  244. GFC_COMPLEX_10 *c;
  245. const index_type m = xcount, n = ycount, k = count;
  246. /* System generated locals */
  247. index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
  248. i1, i2, i3, i4, i5, i6;
  249. /* Local variables */
  250. GFC_COMPLEX_10 f11, f12, f21, f22, f31, f32, f41, f42,
  251. f13, f14, f23, f24, f33, f34, f43, f44;
  252. index_type i, j, l, ii, jj, ll;
  253. index_type isec, jsec, lsec, uisec, ujsec, ulsec;
  254. GFC_COMPLEX_10 *t1;
  255. a = abase;
  256. b = bbase;
  257. c = retarray->base_addr;
  258. /* Parameter adjustments */
  259. c_dim1 = rystride;
  260. c_offset = 1 + c_dim1;
  261. c -= c_offset;
  262. a_dim1 = aystride;
  263. a_offset = 1 + a_dim1;
  264. a -= a_offset;
  265. b_dim1 = bystride;
  266. b_offset = 1 + b_dim1;
  267. b -= b_offset;
  268. /* Empty c first. */
  269. for (j=1; j<=n; j++)
  270. for (i=1; i<=m; i++)
  271. c[i + j * c_dim1] = (GFC_COMPLEX_10)0;
  272. /* Early exit if possible */
  273. if (m == 0 || n == 0 || k == 0)
  274. return;
  275. /* Adjust size of t1 to what is needed. */
  276. index_type t1_dim, a_sz;
  277. if (aystride == 1)
  278. a_sz = rystride;
  279. else
  280. a_sz = a_dim1;
  281. t1_dim = a_sz * 256 + b_dim1;
  282. if (t1_dim > 65536)
  283. t1_dim = 65536;
  284. t1 = malloc (t1_dim * sizeof(GFC_COMPLEX_10));
  285. /* Start turning the crank. */
  286. i1 = n;
  287. for (jj = 1; jj <= i1; jj += 512)
  288. {
  289. /* Computing MIN */
  290. i2 = 512;
  291. i3 = n - jj + 1;
  292. jsec = min(i2,i3);
  293. ujsec = jsec - jsec % 4;
  294. i2 = k;
  295. for (ll = 1; ll <= i2; ll += 256)
  296. {
  297. /* Computing MIN */
  298. i3 = 256;
  299. i4 = k - ll + 1;
  300. lsec = min(i3,i4);
  301. ulsec = lsec - lsec % 2;
  302. i3 = m;
  303. for (ii = 1; ii <= i3; ii += 256)
  304. {
  305. /* Computing MIN */
  306. i4 = 256;
  307. i5 = m - ii + 1;
  308. isec = min(i4,i5);
  309. uisec = isec - isec % 2;
  310. i4 = ll + ulsec - 1;
  311. for (l = ll; l <= i4; l += 2)
  312. {
  313. i5 = ii + uisec - 1;
  314. for (i = ii; i <= i5; i += 2)
  315. {
  316. t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
  317. a[i + l * a_dim1];
  318. t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
  319. a[i + (l + 1) * a_dim1];
  320. t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
  321. a[i + 1 + l * a_dim1];
  322. t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
  323. a[i + 1 + (l + 1) * a_dim1];
  324. }
  325. if (uisec < isec)
  326. {
  327. t1[l - ll + 1 + (isec << 8) - 257] =
  328. a[ii + isec - 1 + l * a_dim1];
  329. t1[l - ll + 2 + (isec << 8) - 257] =
  330. a[ii + isec - 1 + (l + 1) * a_dim1];
  331. }
  332. }
  333. if (ulsec < lsec)
  334. {
  335. i4 = ii + isec - 1;
  336. for (i = ii; i<= i4; ++i)
  337. {
  338. t1[lsec + ((i - ii + 1) << 8) - 257] =
  339. a[i + (ll + lsec - 1) * a_dim1];
  340. }
  341. }
  342. uisec = isec - isec % 4;
  343. i4 = jj + ujsec - 1;
  344. for (j = jj; j <= i4; j += 4)
  345. {
  346. i5 = ii + uisec - 1;
  347. for (i = ii; i <= i5; i += 4)
  348. {
  349. f11 = c[i + j * c_dim1];
  350. f21 = c[i + 1 + j * c_dim1];
  351. f12 = c[i + (j + 1) * c_dim1];
  352. f22 = c[i + 1 + (j + 1) * c_dim1];
  353. f13 = c[i + (j + 2) * c_dim1];
  354. f23 = c[i + 1 + (j + 2) * c_dim1];
  355. f14 = c[i + (j + 3) * c_dim1];
  356. f24 = c[i + 1 + (j + 3) * c_dim1];
  357. f31 = c[i + 2 + j * c_dim1];
  358. f41 = c[i + 3 + j * c_dim1];
  359. f32 = c[i + 2 + (j + 1) * c_dim1];
  360. f42 = c[i + 3 + (j + 1) * c_dim1];
  361. f33 = c[i + 2 + (j + 2) * c_dim1];
  362. f43 = c[i + 3 + (j + 2) * c_dim1];
  363. f34 = c[i + 2 + (j + 3) * c_dim1];
  364. f44 = c[i + 3 + (j + 3) * c_dim1];
  365. i6 = ll + lsec - 1;
  366. for (l = ll; l <= i6; ++l)
  367. {
  368. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  369. * b[l + j * b_dim1];
  370. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  371. * b[l + j * b_dim1];
  372. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  373. * b[l + (j + 1) * b_dim1];
  374. f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  375. * b[l + (j + 1) * b_dim1];
  376. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  377. * b[l + (j + 2) * b_dim1];
  378. f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  379. * b[l + (j + 2) * b_dim1];
  380. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  381. * b[l + (j + 3) * b_dim1];
  382. f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  383. * b[l + (j + 3) * b_dim1];
  384. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  385. * b[l + j * b_dim1];
  386. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  387. * b[l + j * b_dim1];
  388. f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  389. * b[l + (j + 1) * b_dim1];
  390. f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  391. * b[l + (j + 1) * b_dim1];
  392. f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  393. * b[l + (j + 2) * b_dim1];
  394. f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  395. * b[l + (j + 2) * b_dim1];
  396. f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  397. * b[l + (j + 3) * b_dim1];
  398. f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  399. * b[l + (j + 3) * b_dim1];
  400. }
  401. c[i + j * c_dim1] = f11;
  402. c[i + 1 + j * c_dim1] = f21;
  403. c[i + (j + 1) * c_dim1] = f12;
  404. c[i + 1 + (j + 1) * c_dim1] = f22;
  405. c[i + (j + 2) * c_dim1] = f13;
  406. c[i + 1 + (j + 2) * c_dim1] = f23;
  407. c[i + (j + 3) * c_dim1] = f14;
  408. c[i + 1 + (j + 3) * c_dim1] = f24;
  409. c[i + 2 + j * c_dim1] = f31;
  410. c[i + 3 + j * c_dim1] = f41;
  411. c[i + 2 + (j + 1) * c_dim1] = f32;
  412. c[i + 3 + (j + 1) * c_dim1] = f42;
  413. c[i + 2 + (j + 2) * c_dim1] = f33;
  414. c[i + 3 + (j + 2) * c_dim1] = f43;
  415. c[i + 2 + (j + 3) * c_dim1] = f34;
  416. c[i + 3 + (j + 3) * c_dim1] = f44;
  417. }
  418. if (uisec < isec)
  419. {
  420. i5 = ii + isec - 1;
  421. for (i = ii + uisec; i <= i5; ++i)
  422. {
  423. f11 = c[i + j * c_dim1];
  424. f12 = c[i + (j + 1) * c_dim1];
  425. f13 = c[i + (j + 2) * c_dim1];
  426. f14 = c[i + (j + 3) * c_dim1];
  427. i6 = ll + lsec - 1;
  428. for (l = ll; l <= i6; ++l)
  429. {
  430. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  431. 257] * b[l + j * b_dim1];
  432. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  433. 257] * b[l + (j + 1) * b_dim1];
  434. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  435. 257] * b[l + (j + 2) * b_dim1];
  436. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  437. 257] * b[l + (j + 3) * b_dim1];
  438. }
  439. c[i + j * c_dim1] = f11;
  440. c[i + (j + 1) * c_dim1] = f12;
  441. c[i + (j + 2) * c_dim1] = f13;
  442. c[i + (j + 3) * c_dim1] = f14;
  443. }
  444. }
  445. }
  446. if (ujsec < jsec)
  447. {
  448. i4 = jj + jsec - 1;
  449. for (j = jj + ujsec; j <= i4; ++j)
  450. {
  451. i5 = ii + uisec - 1;
  452. for (i = ii; i <= i5; i += 4)
  453. {
  454. f11 = c[i + j * c_dim1];
  455. f21 = c[i + 1 + j * c_dim1];
  456. f31 = c[i + 2 + j * c_dim1];
  457. f41 = c[i + 3 + j * c_dim1];
  458. i6 = ll + lsec - 1;
  459. for (l = ll; l <= i6; ++l)
  460. {
  461. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  462. 257] * b[l + j * b_dim1];
  463. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
  464. 257] * b[l + j * b_dim1];
  465. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
  466. 257] * b[l + j * b_dim1];
  467. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
  468. 257] * b[l + j * b_dim1];
  469. }
  470. c[i + j * c_dim1] = f11;
  471. c[i + 1 + j * c_dim1] = f21;
  472. c[i + 2 + j * c_dim1] = f31;
  473. c[i + 3 + j * c_dim1] = f41;
  474. }
  475. i5 = ii + isec - 1;
  476. for (i = ii + uisec; i <= i5; ++i)
  477. {
  478. f11 = c[i + j * c_dim1];
  479. i6 = ll + lsec - 1;
  480. for (l = ll; l <= i6; ++l)
  481. {
  482. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  483. 257] * b[l + j * b_dim1];
  484. }
  485. c[i + j * c_dim1] = f11;
  486. }
  487. }
  488. }
  489. }
  490. }
  491. }
  492. free(t1);
  493. return;
  494. }
  495. else if (rxstride == 1 && aystride == 1 && bxstride == 1)
  496. {
  497. if (GFC_DESCRIPTOR_RANK (a) != 1)
  498. {
  499. const GFC_COMPLEX_10 *restrict abase_x;
  500. const GFC_COMPLEX_10 *restrict bbase_y;
  501. GFC_COMPLEX_10 *restrict dest_y;
  502. GFC_COMPLEX_10 s;
  503. for (y = 0; y < ycount; y++)
  504. {
  505. bbase_y = &bbase[y*bystride];
  506. dest_y = &dest[y*rystride];
  507. for (x = 0; x < xcount; x++)
  508. {
  509. abase_x = &abase[x*axstride];
  510. s = (GFC_COMPLEX_10) 0;
  511. for (n = 0; n < count; n++)
  512. s += abase_x[n] * bbase_y[n];
  513. dest_y[x] = s;
  514. }
  515. }
  516. }
  517. else
  518. {
  519. const GFC_COMPLEX_10 *restrict bbase_y;
  520. GFC_COMPLEX_10 s;
  521. for (y = 0; y < ycount; y++)
  522. {
  523. bbase_y = &bbase[y*bystride];
  524. s = (GFC_COMPLEX_10) 0;
  525. for (n = 0; n < count; n++)
  526. s += abase[n*axstride] * bbase_y[n];
  527. dest[y*rystride] = s;
  528. }
  529. }
  530. }
  531. else if (GFC_DESCRIPTOR_RANK (a) == 1)
  532. {
  533. const GFC_COMPLEX_10 *restrict bbase_y;
  534. GFC_COMPLEX_10 s;
  535. for (y = 0; y < ycount; y++)
  536. {
  537. bbase_y = &bbase[y*bystride];
  538. s = (GFC_COMPLEX_10) 0;
  539. for (n = 0; n < count; n++)
  540. s += abase[n*axstride] * bbase_y[n*bxstride];
  541. dest[y*rxstride] = s;
  542. }
  543. }
  544. else if (axstride < aystride)
  545. {
  546. for (y = 0; y < ycount; y++)
  547. for (x = 0; x < xcount; x++)
  548. dest[x*rxstride + y*rystride] = (GFC_COMPLEX_10)0;
  549. for (y = 0; y < ycount; y++)
  550. for (n = 0; n < count; n++)
  551. for (x = 0; x < xcount; x++)
  552. /* dest[x,y] += a[x,n] * b[n,y] */
  553. dest[x*rxstride + y*rystride] +=
  554. abase[x*axstride + n*aystride] *
  555. bbase[n*bxstride + y*bystride];
  556. }
  557. else
  558. {
  559. const GFC_COMPLEX_10 *restrict abase_x;
  560. const GFC_COMPLEX_10 *restrict bbase_y;
  561. GFC_COMPLEX_10 *restrict dest_y;
  562. GFC_COMPLEX_10 s;
  563. for (y = 0; y < ycount; y++)
  564. {
  565. bbase_y = &bbase[y*bystride];
  566. dest_y = &dest[y*rystride];
  567. for (x = 0; x < xcount; x++)
  568. {
  569. abase_x = &abase[x*axstride];
  570. s = (GFC_COMPLEX_10) 0;
  571. for (n = 0; n < count; n++)
  572. s += abase_x[n*aystride] * bbase_y[n*bxstride];
  573. dest_y[x*rxstride] = s;
  574. }
  575. }
  576. }
  577. }
  578. #undef POW3
  579. #undef min
  580. #undef max
  581. #endif /* HAVE_AVX */
  582. #ifdef HAVE_AVX2
  583. static void
  584. matmul_c10_avx2 (gfc_array_c10 * const restrict retarray,
  585. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  586. int blas_limit, blas_call gemm) __attribute__((__target__("avx2,fma")));
  587. static void
  588. matmul_c10_avx2 (gfc_array_c10 * const restrict retarray,
  589. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  590. int blas_limit, blas_call gemm)
  591. {
  592. const GFC_COMPLEX_10 * restrict abase;
  593. const GFC_COMPLEX_10 * restrict bbase;
  594. GFC_COMPLEX_10 * restrict dest;
  595. index_type rxstride, rystride, axstride, aystride, bxstride, bystride;
  596. index_type x, y, n, count, xcount, ycount;
  597. assert (GFC_DESCRIPTOR_RANK (a) == 2
  598. || GFC_DESCRIPTOR_RANK (b) == 2);
  599. /* C[xcount,ycount] = A[xcount, count] * B[count,ycount]
  600. Either A or B (but not both) can be rank 1:
  601. o One-dimensional argument A is implicitly treated as a row matrix
  602. dimensioned [1,count], so xcount=1.
  603. o One-dimensional argument B is implicitly treated as a column matrix
  604. dimensioned [count, 1], so ycount=1.
  605. */
  606. if (retarray->base_addr == NULL)
  607. {
  608. if (GFC_DESCRIPTOR_RANK (a) == 1)
  609. {
  610. GFC_DIMENSION_SET(retarray->dim[0], 0,
  611. GFC_DESCRIPTOR_EXTENT(b,1) - 1, 1);
  612. }
  613. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  614. {
  615. GFC_DIMENSION_SET(retarray->dim[0], 0,
  616. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  617. }
  618. else
  619. {
  620. GFC_DIMENSION_SET(retarray->dim[0], 0,
  621. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  622. GFC_DIMENSION_SET(retarray->dim[1], 0,
  623. GFC_DESCRIPTOR_EXTENT(b,1) - 1,
  624. GFC_DESCRIPTOR_EXTENT(retarray,0));
  625. }
  626. retarray->base_addr
  627. = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_10));
  628. retarray->offset = 0;
  629. }
  630. else if (unlikely (compile_options.bounds_check))
  631. {
  632. index_type ret_extent, arg_extent;
  633. if (GFC_DESCRIPTOR_RANK (a) == 1)
  634. {
  635. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  636. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  637. if (arg_extent != ret_extent)
  638. runtime_error ("Array bound mismatch for dimension 1 of "
  639. "array (%ld/%ld) ",
  640. (long int) ret_extent, (long int) arg_extent);
  641. }
  642. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  643. {
  644. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  645. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  646. if (arg_extent != ret_extent)
  647. runtime_error ("Array bound mismatch for dimension 1 of "
  648. "array (%ld/%ld) ",
  649. (long int) ret_extent, (long int) arg_extent);
  650. }
  651. else
  652. {
  653. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  654. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  655. if (arg_extent != ret_extent)
  656. runtime_error ("Array bound mismatch for dimension 1 of "
  657. "array (%ld/%ld) ",
  658. (long int) ret_extent, (long int) arg_extent);
  659. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  660. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
  661. if (arg_extent != ret_extent)
  662. runtime_error ("Array bound mismatch for dimension 2 of "
  663. "array (%ld/%ld) ",
  664. (long int) ret_extent, (long int) arg_extent);
  665. }
  666. }
  667. if (GFC_DESCRIPTOR_RANK (retarray) == 1)
  668. {
  669. /* One-dimensional result may be addressed in the code below
  670. either as a row or a column matrix. We want both cases to
  671. work. */
  672. rxstride = rystride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  673. }
  674. else
  675. {
  676. rxstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  677. rystride = GFC_DESCRIPTOR_STRIDE(retarray,1);
  678. }
  679. if (GFC_DESCRIPTOR_RANK (a) == 1)
  680. {
  681. /* Treat it as a a row matrix A[1,count]. */
  682. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  683. aystride = 1;
  684. xcount = 1;
  685. count = GFC_DESCRIPTOR_EXTENT(a,0);
  686. }
  687. else
  688. {
  689. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  690. aystride = GFC_DESCRIPTOR_STRIDE(a,1);
  691. count = GFC_DESCRIPTOR_EXTENT(a,1);
  692. xcount = GFC_DESCRIPTOR_EXTENT(a,0);
  693. }
  694. if (count != GFC_DESCRIPTOR_EXTENT(b,0))
  695. {
  696. if (count > 0 || GFC_DESCRIPTOR_EXTENT(b,0) > 0)
  697. runtime_error ("Incorrect extent in argument B in MATMUL intrinsic "
  698. "in dimension 1: is %ld, should be %ld",
  699. (long int) GFC_DESCRIPTOR_EXTENT(b,0), (long int) count);
  700. }
  701. if (GFC_DESCRIPTOR_RANK (b) == 1)
  702. {
  703. /* Treat it as a column matrix B[count,1] */
  704. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  705. /* bystride should never be used for 1-dimensional b.
  706. The value is only used for calculation of the
  707. memory by the buffer. */
  708. bystride = 256;
  709. ycount = 1;
  710. }
  711. else
  712. {
  713. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  714. bystride = GFC_DESCRIPTOR_STRIDE(b,1);
  715. ycount = GFC_DESCRIPTOR_EXTENT(b,1);
  716. }
  717. abase = a->base_addr;
  718. bbase = b->base_addr;
  719. dest = retarray->base_addr;
  720. /* Now that everything is set up, we perform the multiplication
  721. itself. */
  722. #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
  723. #define min(a,b) ((a) <= (b) ? (a) : (b))
  724. #define max(a,b) ((a) >= (b) ? (a) : (b))
  725. if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
  726. && (bxstride == 1 || bystride == 1)
  727. && (((float) xcount) * ((float) ycount) * ((float) count)
  728. > POW3(blas_limit)))
  729. {
  730. const int m = xcount, n = ycount, k = count, ldc = rystride;
  731. const GFC_COMPLEX_10 one = 1, zero = 0;
  732. const int lda = (axstride == 1) ? aystride : axstride,
  733. ldb = (bxstride == 1) ? bystride : bxstride;
  734. if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
  735. {
  736. assert (gemm != NULL);
  737. const char *transa, *transb;
  738. if (try_blas & 2)
  739. transa = "C";
  740. else
  741. transa = axstride == 1 ? "N" : "T";
  742. if (try_blas & 4)
  743. transb = "C";
  744. else
  745. transb = bxstride == 1 ? "N" : "T";
  746. gemm (transa, transb , &m,
  747. &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
  748. &ldc, 1, 1);
  749. return;
  750. }
  751. }
  752. if (rxstride == 1 && axstride == 1 && bxstride == 1
  753. && GFC_DESCRIPTOR_RANK (b) != 1)
  754. {
  755. /* This block of code implements a tuned matmul, derived from
  756. Superscalar GEMM-based level 3 BLAS, Beta version 0.1
  757. Bo Kagstrom and Per Ling
  758. Department of Computing Science
  759. Umea University
  760. S-901 87 Umea, Sweden
  761. from netlib.org, translated to C, and modified for matmul.m4. */
  762. const GFC_COMPLEX_10 *a, *b;
  763. GFC_COMPLEX_10 *c;
  764. const index_type m = xcount, n = ycount, k = count;
  765. /* System generated locals */
  766. index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
  767. i1, i2, i3, i4, i5, i6;
  768. /* Local variables */
  769. GFC_COMPLEX_10 f11, f12, f21, f22, f31, f32, f41, f42,
  770. f13, f14, f23, f24, f33, f34, f43, f44;
  771. index_type i, j, l, ii, jj, ll;
  772. index_type isec, jsec, lsec, uisec, ujsec, ulsec;
  773. GFC_COMPLEX_10 *t1;
  774. a = abase;
  775. b = bbase;
  776. c = retarray->base_addr;
  777. /* Parameter adjustments */
  778. c_dim1 = rystride;
  779. c_offset = 1 + c_dim1;
  780. c -= c_offset;
  781. a_dim1 = aystride;
  782. a_offset = 1 + a_dim1;
  783. a -= a_offset;
  784. b_dim1 = bystride;
  785. b_offset = 1 + b_dim1;
  786. b -= b_offset;
  787. /* Empty c first. */
  788. for (j=1; j<=n; j++)
  789. for (i=1; i<=m; i++)
  790. c[i + j * c_dim1] = (GFC_COMPLEX_10)0;
  791. /* Early exit if possible */
  792. if (m == 0 || n == 0 || k == 0)
  793. return;
  794. /* Adjust size of t1 to what is needed. */
  795. index_type t1_dim, a_sz;
  796. if (aystride == 1)
  797. a_sz = rystride;
  798. else
  799. a_sz = a_dim1;
  800. t1_dim = a_sz * 256 + b_dim1;
  801. if (t1_dim > 65536)
  802. t1_dim = 65536;
  803. t1 = malloc (t1_dim * sizeof(GFC_COMPLEX_10));
  804. /* Start turning the crank. */
  805. i1 = n;
  806. for (jj = 1; jj <= i1; jj += 512)
  807. {
  808. /* Computing MIN */
  809. i2 = 512;
  810. i3 = n - jj + 1;
  811. jsec = min(i2,i3);
  812. ujsec = jsec - jsec % 4;
  813. i2 = k;
  814. for (ll = 1; ll <= i2; ll += 256)
  815. {
  816. /* Computing MIN */
  817. i3 = 256;
  818. i4 = k - ll + 1;
  819. lsec = min(i3,i4);
  820. ulsec = lsec - lsec % 2;
  821. i3 = m;
  822. for (ii = 1; ii <= i3; ii += 256)
  823. {
  824. /* Computing MIN */
  825. i4 = 256;
  826. i5 = m - ii + 1;
  827. isec = min(i4,i5);
  828. uisec = isec - isec % 2;
  829. i4 = ll + ulsec - 1;
  830. for (l = ll; l <= i4; l += 2)
  831. {
  832. i5 = ii + uisec - 1;
  833. for (i = ii; i <= i5; i += 2)
  834. {
  835. t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
  836. a[i + l * a_dim1];
  837. t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
  838. a[i + (l + 1) * a_dim1];
  839. t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
  840. a[i + 1 + l * a_dim1];
  841. t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
  842. a[i + 1 + (l + 1) * a_dim1];
  843. }
  844. if (uisec < isec)
  845. {
  846. t1[l - ll + 1 + (isec << 8) - 257] =
  847. a[ii + isec - 1 + l * a_dim1];
  848. t1[l - ll + 2 + (isec << 8) - 257] =
  849. a[ii + isec - 1 + (l + 1) * a_dim1];
  850. }
  851. }
  852. if (ulsec < lsec)
  853. {
  854. i4 = ii + isec - 1;
  855. for (i = ii; i<= i4; ++i)
  856. {
  857. t1[lsec + ((i - ii + 1) << 8) - 257] =
  858. a[i + (ll + lsec - 1) * a_dim1];
  859. }
  860. }
  861. uisec = isec - isec % 4;
  862. i4 = jj + ujsec - 1;
  863. for (j = jj; j <= i4; j += 4)
  864. {
  865. i5 = ii + uisec - 1;
  866. for (i = ii; i <= i5; i += 4)
  867. {
  868. f11 = c[i + j * c_dim1];
  869. f21 = c[i + 1 + j * c_dim1];
  870. f12 = c[i + (j + 1) * c_dim1];
  871. f22 = c[i + 1 + (j + 1) * c_dim1];
  872. f13 = c[i + (j + 2) * c_dim1];
  873. f23 = c[i + 1 + (j + 2) * c_dim1];
  874. f14 = c[i + (j + 3) * c_dim1];
  875. f24 = c[i + 1 + (j + 3) * c_dim1];
  876. f31 = c[i + 2 + j * c_dim1];
  877. f41 = c[i + 3 + j * c_dim1];
  878. f32 = c[i + 2 + (j + 1) * c_dim1];
  879. f42 = c[i + 3 + (j + 1) * c_dim1];
  880. f33 = c[i + 2 + (j + 2) * c_dim1];
  881. f43 = c[i + 3 + (j + 2) * c_dim1];
  882. f34 = c[i + 2 + (j + 3) * c_dim1];
  883. f44 = c[i + 3 + (j + 3) * c_dim1];
  884. i6 = ll + lsec - 1;
  885. for (l = ll; l <= i6; ++l)
  886. {
  887. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  888. * b[l + j * b_dim1];
  889. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  890. * b[l + j * b_dim1];
  891. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  892. * b[l + (j + 1) * b_dim1];
  893. f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  894. * b[l + (j + 1) * b_dim1];
  895. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  896. * b[l + (j + 2) * b_dim1];
  897. f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  898. * b[l + (j + 2) * b_dim1];
  899. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  900. * b[l + (j + 3) * b_dim1];
  901. f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  902. * b[l + (j + 3) * b_dim1];
  903. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  904. * b[l + j * b_dim1];
  905. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  906. * b[l + j * b_dim1];
  907. f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  908. * b[l + (j + 1) * b_dim1];
  909. f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  910. * b[l + (j + 1) * b_dim1];
  911. f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  912. * b[l + (j + 2) * b_dim1];
  913. f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  914. * b[l + (j + 2) * b_dim1];
  915. f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  916. * b[l + (j + 3) * b_dim1];
  917. f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  918. * b[l + (j + 3) * b_dim1];
  919. }
  920. c[i + j * c_dim1] = f11;
  921. c[i + 1 + j * c_dim1] = f21;
  922. c[i + (j + 1) * c_dim1] = f12;
  923. c[i + 1 + (j + 1) * c_dim1] = f22;
  924. c[i + (j + 2) * c_dim1] = f13;
  925. c[i + 1 + (j + 2) * c_dim1] = f23;
  926. c[i + (j + 3) * c_dim1] = f14;
  927. c[i + 1 + (j + 3) * c_dim1] = f24;
  928. c[i + 2 + j * c_dim1] = f31;
  929. c[i + 3 + j * c_dim1] = f41;
  930. c[i + 2 + (j + 1) * c_dim1] = f32;
  931. c[i + 3 + (j + 1) * c_dim1] = f42;
  932. c[i + 2 + (j + 2) * c_dim1] = f33;
  933. c[i + 3 + (j + 2) * c_dim1] = f43;
  934. c[i + 2 + (j + 3) * c_dim1] = f34;
  935. c[i + 3 + (j + 3) * c_dim1] = f44;
  936. }
  937. if (uisec < isec)
  938. {
  939. i5 = ii + isec - 1;
  940. for (i = ii + uisec; i <= i5; ++i)
  941. {
  942. f11 = c[i + j * c_dim1];
  943. f12 = c[i + (j + 1) * c_dim1];
  944. f13 = c[i + (j + 2) * c_dim1];
  945. f14 = c[i + (j + 3) * c_dim1];
  946. i6 = ll + lsec - 1;
  947. for (l = ll; l <= i6; ++l)
  948. {
  949. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  950. 257] * b[l + j * b_dim1];
  951. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  952. 257] * b[l + (j + 1) * b_dim1];
  953. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  954. 257] * b[l + (j + 2) * b_dim1];
  955. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  956. 257] * b[l + (j + 3) * b_dim1];
  957. }
  958. c[i + j * c_dim1] = f11;
  959. c[i + (j + 1) * c_dim1] = f12;
  960. c[i + (j + 2) * c_dim1] = f13;
  961. c[i + (j + 3) * c_dim1] = f14;
  962. }
  963. }
  964. }
  965. if (ujsec < jsec)
  966. {
  967. i4 = jj + jsec - 1;
  968. for (j = jj + ujsec; j <= i4; ++j)
  969. {
  970. i5 = ii + uisec - 1;
  971. for (i = ii; i <= i5; i += 4)
  972. {
  973. f11 = c[i + j * c_dim1];
  974. f21 = c[i + 1 + j * c_dim1];
  975. f31 = c[i + 2 + j * c_dim1];
  976. f41 = c[i + 3 + j * c_dim1];
  977. i6 = ll + lsec - 1;
  978. for (l = ll; l <= i6; ++l)
  979. {
  980. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  981. 257] * b[l + j * b_dim1];
  982. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
  983. 257] * b[l + j * b_dim1];
  984. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
  985. 257] * b[l + j * b_dim1];
  986. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
  987. 257] * b[l + j * b_dim1];
  988. }
  989. c[i + j * c_dim1] = f11;
  990. c[i + 1 + j * c_dim1] = f21;
  991. c[i + 2 + j * c_dim1] = f31;
  992. c[i + 3 + j * c_dim1] = f41;
  993. }
  994. i5 = ii + isec - 1;
  995. for (i = ii + uisec; i <= i5; ++i)
  996. {
  997. f11 = c[i + j * c_dim1];
  998. i6 = ll + lsec - 1;
  999. for (l = ll; l <= i6; ++l)
  1000. {
  1001. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1002. 257] * b[l + j * b_dim1];
  1003. }
  1004. c[i + j * c_dim1] = f11;
  1005. }
  1006. }
  1007. }
  1008. }
  1009. }
  1010. }
  1011. free(t1);
  1012. return;
  1013. }
  1014. else if (rxstride == 1 && aystride == 1 && bxstride == 1)
  1015. {
  1016. if (GFC_DESCRIPTOR_RANK (a) != 1)
  1017. {
  1018. const GFC_COMPLEX_10 *restrict abase_x;
  1019. const GFC_COMPLEX_10 *restrict bbase_y;
  1020. GFC_COMPLEX_10 *restrict dest_y;
  1021. GFC_COMPLEX_10 s;
  1022. for (y = 0; y < ycount; y++)
  1023. {
  1024. bbase_y = &bbase[y*bystride];
  1025. dest_y = &dest[y*rystride];
  1026. for (x = 0; x < xcount; x++)
  1027. {
  1028. abase_x = &abase[x*axstride];
  1029. s = (GFC_COMPLEX_10) 0;
  1030. for (n = 0; n < count; n++)
  1031. s += abase_x[n] * bbase_y[n];
  1032. dest_y[x] = s;
  1033. }
  1034. }
  1035. }
  1036. else
  1037. {
  1038. const GFC_COMPLEX_10 *restrict bbase_y;
  1039. GFC_COMPLEX_10 s;
  1040. for (y = 0; y < ycount; y++)
  1041. {
  1042. bbase_y = &bbase[y*bystride];
  1043. s = (GFC_COMPLEX_10) 0;
  1044. for (n = 0; n < count; n++)
  1045. s += abase[n*axstride] * bbase_y[n];
  1046. dest[y*rystride] = s;
  1047. }
  1048. }
  1049. }
  1050. else if (GFC_DESCRIPTOR_RANK (a) == 1)
  1051. {
  1052. const GFC_COMPLEX_10 *restrict bbase_y;
  1053. GFC_COMPLEX_10 s;
  1054. for (y = 0; y < ycount; y++)
  1055. {
  1056. bbase_y = &bbase[y*bystride];
  1057. s = (GFC_COMPLEX_10) 0;
  1058. for (n = 0; n < count; n++)
  1059. s += abase[n*axstride] * bbase_y[n*bxstride];
  1060. dest[y*rxstride] = s;
  1061. }
  1062. }
  1063. else if (axstride < aystride)
  1064. {
  1065. for (y = 0; y < ycount; y++)
  1066. for (x = 0; x < xcount; x++)
  1067. dest[x*rxstride + y*rystride] = (GFC_COMPLEX_10)0;
  1068. for (y = 0; y < ycount; y++)
  1069. for (n = 0; n < count; n++)
  1070. for (x = 0; x < xcount; x++)
  1071. /* dest[x,y] += a[x,n] * b[n,y] */
  1072. dest[x*rxstride + y*rystride] +=
  1073. abase[x*axstride + n*aystride] *
  1074. bbase[n*bxstride + y*bystride];
  1075. }
  1076. else
  1077. {
  1078. const GFC_COMPLEX_10 *restrict abase_x;
  1079. const GFC_COMPLEX_10 *restrict bbase_y;
  1080. GFC_COMPLEX_10 *restrict dest_y;
  1081. GFC_COMPLEX_10 s;
  1082. for (y = 0; y < ycount; y++)
  1083. {
  1084. bbase_y = &bbase[y*bystride];
  1085. dest_y = &dest[y*rystride];
  1086. for (x = 0; x < xcount; x++)
  1087. {
  1088. abase_x = &abase[x*axstride];
  1089. s = (GFC_COMPLEX_10) 0;
  1090. for (n = 0; n < count; n++)
  1091. s += abase_x[n*aystride] * bbase_y[n*bxstride];
  1092. dest_y[x*rxstride] = s;
  1093. }
  1094. }
  1095. }
  1096. }
  1097. #undef POW3
  1098. #undef min
  1099. #undef max
  1100. #endif /* HAVE_AVX2 */
  1101. #ifdef HAVE_AVX512F
  1102. static void
  1103. matmul_c10_avx512f (gfc_array_c10 * const restrict retarray,
  1104. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  1105. int blas_limit, blas_call gemm) __attribute__((__target__("avx512f")));
  1106. static void
  1107. matmul_c10_avx512f (gfc_array_c10 * const restrict retarray,
  1108. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  1109. int blas_limit, blas_call gemm)
  1110. {
  1111. const GFC_COMPLEX_10 * restrict abase;
  1112. const GFC_COMPLEX_10 * restrict bbase;
  1113. GFC_COMPLEX_10 * restrict dest;
  1114. index_type rxstride, rystride, axstride, aystride, bxstride, bystride;
  1115. index_type x, y, n, count, xcount, ycount;
  1116. assert (GFC_DESCRIPTOR_RANK (a) == 2
  1117. || GFC_DESCRIPTOR_RANK (b) == 2);
  1118. /* C[xcount,ycount] = A[xcount, count] * B[count,ycount]
  1119. Either A or B (but not both) can be rank 1:
  1120. o One-dimensional argument A is implicitly treated as a row matrix
  1121. dimensioned [1,count], so xcount=1.
  1122. o One-dimensional argument B is implicitly treated as a column matrix
  1123. dimensioned [count, 1], so ycount=1.
  1124. */
  1125. if (retarray->base_addr == NULL)
  1126. {
  1127. if (GFC_DESCRIPTOR_RANK (a) == 1)
  1128. {
  1129. GFC_DIMENSION_SET(retarray->dim[0], 0,
  1130. GFC_DESCRIPTOR_EXTENT(b,1) - 1, 1);
  1131. }
  1132. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  1133. {
  1134. GFC_DIMENSION_SET(retarray->dim[0], 0,
  1135. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  1136. }
  1137. else
  1138. {
  1139. GFC_DIMENSION_SET(retarray->dim[0], 0,
  1140. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  1141. GFC_DIMENSION_SET(retarray->dim[1], 0,
  1142. GFC_DESCRIPTOR_EXTENT(b,1) - 1,
  1143. GFC_DESCRIPTOR_EXTENT(retarray,0));
  1144. }
  1145. retarray->base_addr
  1146. = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_10));
  1147. retarray->offset = 0;
  1148. }
  1149. else if (unlikely (compile_options.bounds_check))
  1150. {
  1151. index_type ret_extent, arg_extent;
  1152. if (GFC_DESCRIPTOR_RANK (a) == 1)
  1153. {
  1154. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  1155. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  1156. if (arg_extent != ret_extent)
  1157. runtime_error ("Array bound mismatch for dimension 1 of "
  1158. "array (%ld/%ld) ",
  1159. (long int) ret_extent, (long int) arg_extent);
  1160. }
  1161. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  1162. {
  1163. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  1164. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  1165. if (arg_extent != ret_extent)
  1166. runtime_error ("Array bound mismatch for dimension 1 of "
  1167. "array (%ld/%ld) ",
  1168. (long int) ret_extent, (long int) arg_extent);
  1169. }
  1170. else
  1171. {
  1172. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  1173. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  1174. if (arg_extent != ret_extent)
  1175. runtime_error ("Array bound mismatch for dimension 1 of "
  1176. "array (%ld/%ld) ",
  1177. (long int) ret_extent, (long int) arg_extent);
  1178. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  1179. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
  1180. if (arg_extent != ret_extent)
  1181. runtime_error ("Array bound mismatch for dimension 2 of "
  1182. "array (%ld/%ld) ",
  1183. (long int) ret_extent, (long int) arg_extent);
  1184. }
  1185. }
  1186. if (GFC_DESCRIPTOR_RANK (retarray) == 1)
  1187. {
  1188. /* One-dimensional result may be addressed in the code below
  1189. either as a row or a column matrix. We want both cases to
  1190. work. */
  1191. rxstride = rystride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  1192. }
  1193. else
  1194. {
  1195. rxstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  1196. rystride = GFC_DESCRIPTOR_STRIDE(retarray,1);
  1197. }
  1198. if (GFC_DESCRIPTOR_RANK (a) == 1)
  1199. {
  1200. /* Treat it as a a row matrix A[1,count]. */
  1201. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  1202. aystride = 1;
  1203. xcount = 1;
  1204. count = GFC_DESCRIPTOR_EXTENT(a,0);
  1205. }
  1206. else
  1207. {
  1208. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  1209. aystride = GFC_DESCRIPTOR_STRIDE(a,1);
  1210. count = GFC_DESCRIPTOR_EXTENT(a,1);
  1211. xcount = GFC_DESCRIPTOR_EXTENT(a,0);
  1212. }
  1213. if (count != GFC_DESCRIPTOR_EXTENT(b,0))
  1214. {
  1215. if (count > 0 || GFC_DESCRIPTOR_EXTENT(b,0) > 0)
  1216. runtime_error ("Incorrect extent in argument B in MATMUL intrinsic "
  1217. "in dimension 1: is %ld, should be %ld",
  1218. (long int) GFC_DESCRIPTOR_EXTENT(b,0), (long int) count);
  1219. }
  1220. if (GFC_DESCRIPTOR_RANK (b) == 1)
  1221. {
  1222. /* Treat it as a column matrix B[count,1] */
  1223. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  1224. /* bystride should never be used for 1-dimensional b.
  1225. The value is only used for calculation of the
  1226. memory by the buffer. */
  1227. bystride = 256;
  1228. ycount = 1;
  1229. }
  1230. else
  1231. {
  1232. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  1233. bystride = GFC_DESCRIPTOR_STRIDE(b,1);
  1234. ycount = GFC_DESCRIPTOR_EXTENT(b,1);
  1235. }
  1236. abase = a->base_addr;
  1237. bbase = b->base_addr;
  1238. dest = retarray->base_addr;
  1239. /* Now that everything is set up, we perform the multiplication
  1240. itself. */
  1241. #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
  1242. #define min(a,b) ((a) <= (b) ? (a) : (b))
  1243. #define max(a,b) ((a) >= (b) ? (a) : (b))
  1244. if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
  1245. && (bxstride == 1 || bystride == 1)
  1246. && (((float) xcount) * ((float) ycount) * ((float) count)
  1247. > POW3(blas_limit)))
  1248. {
  1249. const int m = xcount, n = ycount, k = count, ldc = rystride;
  1250. const GFC_COMPLEX_10 one = 1, zero = 0;
  1251. const int lda = (axstride == 1) ? aystride : axstride,
  1252. ldb = (bxstride == 1) ? bystride : bxstride;
  1253. if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
  1254. {
  1255. assert (gemm != NULL);
  1256. const char *transa, *transb;
  1257. if (try_blas & 2)
  1258. transa = "C";
  1259. else
  1260. transa = axstride == 1 ? "N" : "T";
  1261. if (try_blas & 4)
  1262. transb = "C";
  1263. else
  1264. transb = bxstride == 1 ? "N" : "T";
  1265. gemm (transa, transb , &m,
  1266. &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
  1267. &ldc, 1, 1);
  1268. return;
  1269. }
  1270. }
  1271. if (rxstride == 1 && axstride == 1 && bxstride == 1
  1272. && GFC_DESCRIPTOR_RANK (b) != 1)
  1273. {
  1274. /* This block of code implements a tuned matmul, derived from
  1275. Superscalar GEMM-based level 3 BLAS, Beta version 0.1
  1276. Bo Kagstrom and Per Ling
  1277. Department of Computing Science
  1278. Umea University
  1279. S-901 87 Umea, Sweden
  1280. from netlib.org, translated to C, and modified for matmul.m4. */
  1281. const GFC_COMPLEX_10 *a, *b;
  1282. GFC_COMPLEX_10 *c;
  1283. const index_type m = xcount, n = ycount, k = count;
  1284. /* System generated locals */
  1285. index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
  1286. i1, i2, i3, i4, i5, i6;
  1287. /* Local variables */
  1288. GFC_COMPLEX_10 f11, f12, f21, f22, f31, f32, f41, f42,
  1289. f13, f14, f23, f24, f33, f34, f43, f44;
  1290. index_type i, j, l, ii, jj, ll;
  1291. index_type isec, jsec, lsec, uisec, ujsec, ulsec;
  1292. GFC_COMPLEX_10 *t1;
  1293. a = abase;
  1294. b = bbase;
  1295. c = retarray->base_addr;
  1296. /* Parameter adjustments */
  1297. c_dim1 = rystride;
  1298. c_offset = 1 + c_dim1;
  1299. c -= c_offset;
  1300. a_dim1 = aystride;
  1301. a_offset = 1 + a_dim1;
  1302. a -= a_offset;
  1303. b_dim1 = bystride;
  1304. b_offset = 1 + b_dim1;
  1305. b -= b_offset;
  1306. /* Empty c first. */
  1307. for (j=1; j<=n; j++)
  1308. for (i=1; i<=m; i++)
  1309. c[i + j * c_dim1] = (GFC_COMPLEX_10)0;
  1310. /* Early exit if possible */
  1311. if (m == 0 || n == 0 || k == 0)
  1312. return;
  1313. /* Adjust size of t1 to what is needed. */
  1314. index_type t1_dim, a_sz;
  1315. if (aystride == 1)
  1316. a_sz = rystride;
  1317. else
  1318. a_sz = a_dim1;
  1319. t1_dim = a_sz * 256 + b_dim1;
  1320. if (t1_dim > 65536)
  1321. t1_dim = 65536;
  1322. t1 = malloc (t1_dim * sizeof(GFC_COMPLEX_10));
  1323. /* Start turning the crank. */
  1324. i1 = n;
  1325. for (jj = 1; jj <= i1; jj += 512)
  1326. {
  1327. /* Computing MIN */
  1328. i2 = 512;
  1329. i3 = n - jj + 1;
  1330. jsec = min(i2,i3);
  1331. ujsec = jsec - jsec % 4;
  1332. i2 = k;
  1333. for (ll = 1; ll <= i2; ll += 256)
  1334. {
  1335. /* Computing MIN */
  1336. i3 = 256;
  1337. i4 = k - ll + 1;
  1338. lsec = min(i3,i4);
  1339. ulsec = lsec - lsec % 2;
  1340. i3 = m;
  1341. for (ii = 1; ii <= i3; ii += 256)
  1342. {
  1343. /* Computing MIN */
  1344. i4 = 256;
  1345. i5 = m - ii + 1;
  1346. isec = min(i4,i5);
  1347. uisec = isec - isec % 2;
  1348. i4 = ll + ulsec - 1;
  1349. for (l = ll; l <= i4; l += 2)
  1350. {
  1351. i5 = ii + uisec - 1;
  1352. for (i = ii; i <= i5; i += 2)
  1353. {
  1354. t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
  1355. a[i + l * a_dim1];
  1356. t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
  1357. a[i + (l + 1) * a_dim1];
  1358. t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
  1359. a[i + 1 + l * a_dim1];
  1360. t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
  1361. a[i + 1 + (l + 1) * a_dim1];
  1362. }
  1363. if (uisec < isec)
  1364. {
  1365. t1[l - ll + 1 + (isec << 8) - 257] =
  1366. a[ii + isec - 1 + l * a_dim1];
  1367. t1[l - ll + 2 + (isec << 8) - 257] =
  1368. a[ii + isec - 1 + (l + 1) * a_dim1];
  1369. }
  1370. }
  1371. if (ulsec < lsec)
  1372. {
  1373. i4 = ii + isec - 1;
  1374. for (i = ii; i<= i4; ++i)
  1375. {
  1376. t1[lsec + ((i - ii + 1) << 8) - 257] =
  1377. a[i + (ll + lsec - 1) * a_dim1];
  1378. }
  1379. }
  1380. uisec = isec - isec % 4;
  1381. i4 = jj + ujsec - 1;
  1382. for (j = jj; j <= i4; j += 4)
  1383. {
  1384. i5 = ii + uisec - 1;
  1385. for (i = ii; i <= i5; i += 4)
  1386. {
  1387. f11 = c[i + j * c_dim1];
  1388. f21 = c[i + 1 + j * c_dim1];
  1389. f12 = c[i + (j + 1) * c_dim1];
  1390. f22 = c[i + 1 + (j + 1) * c_dim1];
  1391. f13 = c[i + (j + 2) * c_dim1];
  1392. f23 = c[i + 1 + (j + 2) * c_dim1];
  1393. f14 = c[i + (j + 3) * c_dim1];
  1394. f24 = c[i + 1 + (j + 3) * c_dim1];
  1395. f31 = c[i + 2 + j * c_dim1];
  1396. f41 = c[i + 3 + j * c_dim1];
  1397. f32 = c[i + 2 + (j + 1) * c_dim1];
  1398. f42 = c[i + 3 + (j + 1) * c_dim1];
  1399. f33 = c[i + 2 + (j + 2) * c_dim1];
  1400. f43 = c[i + 3 + (j + 2) * c_dim1];
  1401. f34 = c[i + 2 + (j + 3) * c_dim1];
  1402. f44 = c[i + 3 + (j + 3) * c_dim1];
  1403. i6 = ll + lsec - 1;
  1404. for (l = ll; l <= i6; ++l)
  1405. {
  1406. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1407. * b[l + j * b_dim1];
  1408. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1409. * b[l + j * b_dim1];
  1410. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1411. * b[l + (j + 1) * b_dim1];
  1412. f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1413. * b[l + (j + 1) * b_dim1];
  1414. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1415. * b[l + (j + 2) * b_dim1];
  1416. f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1417. * b[l + (j + 2) * b_dim1];
  1418. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1419. * b[l + (j + 3) * b_dim1];
  1420. f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1421. * b[l + (j + 3) * b_dim1];
  1422. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1423. * b[l + j * b_dim1];
  1424. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1425. * b[l + j * b_dim1];
  1426. f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1427. * b[l + (j + 1) * b_dim1];
  1428. f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1429. * b[l + (j + 1) * b_dim1];
  1430. f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1431. * b[l + (j + 2) * b_dim1];
  1432. f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1433. * b[l + (j + 2) * b_dim1];
  1434. f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1435. * b[l + (j + 3) * b_dim1];
  1436. f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1437. * b[l + (j + 3) * b_dim1];
  1438. }
  1439. c[i + j * c_dim1] = f11;
  1440. c[i + 1 + j * c_dim1] = f21;
  1441. c[i + (j + 1) * c_dim1] = f12;
  1442. c[i + 1 + (j + 1) * c_dim1] = f22;
  1443. c[i + (j + 2) * c_dim1] = f13;
  1444. c[i + 1 + (j + 2) * c_dim1] = f23;
  1445. c[i + (j + 3) * c_dim1] = f14;
  1446. c[i + 1 + (j + 3) * c_dim1] = f24;
  1447. c[i + 2 + j * c_dim1] = f31;
  1448. c[i + 3 + j * c_dim1] = f41;
  1449. c[i + 2 + (j + 1) * c_dim1] = f32;
  1450. c[i + 3 + (j + 1) * c_dim1] = f42;
  1451. c[i + 2 + (j + 2) * c_dim1] = f33;
  1452. c[i + 3 + (j + 2) * c_dim1] = f43;
  1453. c[i + 2 + (j + 3) * c_dim1] = f34;
  1454. c[i + 3 + (j + 3) * c_dim1] = f44;
  1455. }
  1456. if (uisec < isec)
  1457. {
  1458. i5 = ii + isec - 1;
  1459. for (i = ii + uisec; i <= i5; ++i)
  1460. {
  1461. f11 = c[i + j * c_dim1];
  1462. f12 = c[i + (j + 1) * c_dim1];
  1463. f13 = c[i + (j + 2) * c_dim1];
  1464. f14 = c[i + (j + 3) * c_dim1];
  1465. i6 = ll + lsec - 1;
  1466. for (l = ll; l <= i6; ++l)
  1467. {
  1468. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1469. 257] * b[l + j * b_dim1];
  1470. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1471. 257] * b[l + (j + 1) * b_dim1];
  1472. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1473. 257] * b[l + (j + 2) * b_dim1];
  1474. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1475. 257] * b[l + (j + 3) * b_dim1];
  1476. }
  1477. c[i + j * c_dim1] = f11;
  1478. c[i + (j + 1) * c_dim1] = f12;
  1479. c[i + (j + 2) * c_dim1] = f13;
  1480. c[i + (j + 3) * c_dim1] = f14;
  1481. }
  1482. }
  1483. }
  1484. if (ujsec < jsec)
  1485. {
  1486. i4 = jj + jsec - 1;
  1487. for (j = jj + ujsec; j <= i4; ++j)
  1488. {
  1489. i5 = ii + uisec - 1;
  1490. for (i = ii; i <= i5; i += 4)
  1491. {
  1492. f11 = c[i + j * c_dim1];
  1493. f21 = c[i + 1 + j * c_dim1];
  1494. f31 = c[i + 2 + j * c_dim1];
  1495. f41 = c[i + 3 + j * c_dim1];
  1496. i6 = ll + lsec - 1;
  1497. for (l = ll; l <= i6; ++l)
  1498. {
  1499. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1500. 257] * b[l + j * b_dim1];
  1501. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
  1502. 257] * b[l + j * b_dim1];
  1503. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
  1504. 257] * b[l + j * b_dim1];
  1505. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
  1506. 257] * b[l + j * b_dim1];
  1507. }
  1508. c[i + j * c_dim1] = f11;
  1509. c[i + 1 + j * c_dim1] = f21;
  1510. c[i + 2 + j * c_dim1] = f31;
  1511. c[i + 3 + j * c_dim1] = f41;
  1512. }
  1513. i5 = ii + isec - 1;
  1514. for (i = ii + uisec; i <= i5; ++i)
  1515. {
  1516. f11 = c[i + j * c_dim1];
  1517. i6 = ll + lsec - 1;
  1518. for (l = ll; l <= i6; ++l)
  1519. {
  1520. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1521. 257] * b[l + j * b_dim1];
  1522. }
  1523. c[i + j * c_dim1] = f11;
  1524. }
  1525. }
  1526. }
  1527. }
  1528. }
  1529. }
  1530. free(t1);
  1531. return;
  1532. }
  1533. else if (rxstride == 1 && aystride == 1 && bxstride == 1)
  1534. {
  1535. if (GFC_DESCRIPTOR_RANK (a) != 1)
  1536. {
  1537. const GFC_COMPLEX_10 *restrict abase_x;
  1538. const GFC_COMPLEX_10 *restrict bbase_y;
  1539. GFC_COMPLEX_10 *restrict dest_y;
  1540. GFC_COMPLEX_10 s;
  1541. for (y = 0; y < ycount; y++)
  1542. {
  1543. bbase_y = &bbase[y*bystride];
  1544. dest_y = &dest[y*rystride];
  1545. for (x = 0; x < xcount; x++)
  1546. {
  1547. abase_x = &abase[x*axstride];
  1548. s = (GFC_COMPLEX_10) 0;
  1549. for (n = 0; n < count; n++)
  1550. s += abase_x[n] * bbase_y[n];
  1551. dest_y[x] = s;
  1552. }
  1553. }
  1554. }
  1555. else
  1556. {
  1557. const GFC_COMPLEX_10 *restrict bbase_y;
  1558. GFC_COMPLEX_10 s;
  1559. for (y = 0; y < ycount; y++)
  1560. {
  1561. bbase_y = &bbase[y*bystride];
  1562. s = (GFC_COMPLEX_10) 0;
  1563. for (n = 0; n < count; n++)
  1564. s += abase[n*axstride] * bbase_y[n];
  1565. dest[y*rystride] = s;
  1566. }
  1567. }
  1568. }
  1569. else if (GFC_DESCRIPTOR_RANK (a) == 1)
  1570. {
  1571. const GFC_COMPLEX_10 *restrict bbase_y;
  1572. GFC_COMPLEX_10 s;
  1573. for (y = 0; y < ycount; y++)
  1574. {
  1575. bbase_y = &bbase[y*bystride];
  1576. s = (GFC_COMPLEX_10) 0;
  1577. for (n = 0; n < count; n++)
  1578. s += abase[n*axstride] * bbase_y[n*bxstride];
  1579. dest[y*rxstride] = s;
  1580. }
  1581. }
  1582. else if (axstride < aystride)
  1583. {
  1584. for (y = 0; y < ycount; y++)
  1585. for (x = 0; x < xcount; x++)
  1586. dest[x*rxstride + y*rystride] = (GFC_COMPLEX_10)0;
  1587. for (y = 0; y < ycount; y++)
  1588. for (n = 0; n < count; n++)
  1589. for (x = 0; x < xcount; x++)
  1590. /* dest[x,y] += a[x,n] * b[n,y] */
  1591. dest[x*rxstride + y*rystride] +=
  1592. abase[x*axstride + n*aystride] *
  1593. bbase[n*bxstride + y*bystride];
  1594. }
  1595. else
  1596. {
  1597. const GFC_COMPLEX_10 *restrict abase_x;
  1598. const GFC_COMPLEX_10 *restrict bbase_y;
  1599. GFC_COMPLEX_10 *restrict dest_y;
  1600. GFC_COMPLEX_10 s;
  1601. for (y = 0; y < ycount; y++)
  1602. {
  1603. bbase_y = &bbase[y*bystride];
  1604. dest_y = &dest[y*rystride];
  1605. for (x = 0; x < xcount; x++)
  1606. {
  1607. abase_x = &abase[x*axstride];
  1608. s = (GFC_COMPLEX_10) 0;
  1609. for (n = 0; n < count; n++)
  1610. s += abase_x[n*aystride] * bbase_y[n*bxstride];
  1611. dest_y[x*rxstride] = s;
  1612. }
  1613. }
  1614. }
  1615. }
  1616. #undef POW3
  1617. #undef min
  1618. #undef max
  1619. #endif /* HAVE_AVX512F */
  1620. /* AMD-specifix funtions with AVX128 and FMA3/FMA4. */
  1621. #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
  1622. void
  1623. matmul_c10_avx128_fma3 (gfc_array_c10 * const restrict retarray,
  1624. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  1625. int blas_limit, blas_call gemm) __attribute__((__target__("avx,fma")));
  1626. internal_proto(matmul_c10_avx128_fma3);
  1627. #endif
  1628. #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
  1629. void
  1630. matmul_c10_avx128_fma4 (gfc_array_c10 * const restrict retarray,
  1631. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  1632. int blas_limit, blas_call gemm) __attribute__((__target__("avx,fma4")));
  1633. internal_proto(matmul_c10_avx128_fma4);
  1634. #endif
  1635. /* Function to fall back to if there is no special processor-specific version. */
  1636. static void
  1637. matmul_c10_vanilla (gfc_array_c10 * const restrict retarray,
  1638. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  1639. int blas_limit, blas_call gemm)
  1640. {
  1641. const GFC_COMPLEX_10 * restrict abase;
  1642. const GFC_COMPLEX_10 * restrict bbase;
  1643. GFC_COMPLEX_10 * restrict dest;
  1644. index_type rxstride, rystride, axstride, aystride, bxstride, bystride;
  1645. index_type x, y, n, count, xcount, ycount;
  1646. assert (GFC_DESCRIPTOR_RANK (a) == 2
  1647. || GFC_DESCRIPTOR_RANK (b) == 2);
  1648. /* C[xcount,ycount] = A[xcount, count] * B[count,ycount]
  1649. Either A or B (but not both) can be rank 1:
  1650. o One-dimensional argument A is implicitly treated as a row matrix
  1651. dimensioned [1,count], so xcount=1.
  1652. o One-dimensional argument B is implicitly treated as a column matrix
  1653. dimensioned [count, 1], so ycount=1.
  1654. */
  1655. if (retarray->base_addr == NULL)
  1656. {
  1657. if (GFC_DESCRIPTOR_RANK (a) == 1)
  1658. {
  1659. GFC_DIMENSION_SET(retarray->dim[0], 0,
  1660. GFC_DESCRIPTOR_EXTENT(b,1) - 1, 1);
  1661. }
  1662. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  1663. {
  1664. GFC_DIMENSION_SET(retarray->dim[0], 0,
  1665. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  1666. }
  1667. else
  1668. {
  1669. GFC_DIMENSION_SET(retarray->dim[0], 0,
  1670. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  1671. GFC_DIMENSION_SET(retarray->dim[1], 0,
  1672. GFC_DESCRIPTOR_EXTENT(b,1) - 1,
  1673. GFC_DESCRIPTOR_EXTENT(retarray,0));
  1674. }
  1675. retarray->base_addr
  1676. = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_10));
  1677. retarray->offset = 0;
  1678. }
  1679. else if (unlikely (compile_options.bounds_check))
  1680. {
  1681. index_type ret_extent, arg_extent;
  1682. if (GFC_DESCRIPTOR_RANK (a) == 1)
  1683. {
  1684. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  1685. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  1686. if (arg_extent != ret_extent)
  1687. runtime_error ("Array bound mismatch for dimension 1 of "
  1688. "array (%ld/%ld) ",
  1689. (long int) ret_extent, (long int) arg_extent);
  1690. }
  1691. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  1692. {
  1693. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  1694. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  1695. if (arg_extent != ret_extent)
  1696. runtime_error ("Array bound mismatch for dimension 1 of "
  1697. "array (%ld/%ld) ",
  1698. (long int) ret_extent, (long int) arg_extent);
  1699. }
  1700. else
  1701. {
  1702. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  1703. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  1704. if (arg_extent != ret_extent)
  1705. runtime_error ("Array bound mismatch for dimension 1 of "
  1706. "array (%ld/%ld) ",
  1707. (long int) ret_extent, (long int) arg_extent);
  1708. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  1709. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
  1710. if (arg_extent != ret_extent)
  1711. runtime_error ("Array bound mismatch for dimension 2 of "
  1712. "array (%ld/%ld) ",
  1713. (long int) ret_extent, (long int) arg_extent);
  1714. }
  1715. }
  1716. if (GFC_DESCRIPTOR_RANK (retarray) == 1)
  1717. {
  1718. /* One-dimensional result may be addressed in the code below
  1719. either as a row or a column matrix. We want both cases to
  1720. work. */
  1721. rxstride = rystride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  1722. }
  1723. else
  1724. {
  1725. rxstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  1726. rystride = GFC_DESCRIPTOR_STRIDE(retarray,1);
  1727. }
  1728. if (GFC_DESCRIPTOR_RANK (a) == 1)
  1729. {
  1730. /* Treat it as a a row matrix A[1,count]. */
  1731. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  1732. aystride = 1;
  1733. xcount = 1;
  1734. count = GFC_DESCRIPTOR_EXTENT(a,0);
  1735. }
  1736. else
  1737. {
  1738. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  1739. aystride = GFC_DESCRIPTOR_STRIDE(a,1);
  1740. count = GFC_DESCRIPTOR_EXTENT(a,1);
  1741. xcount = GFC_DESCRIPTOR_EXTENT(a,0);
  1742. }
  1743. if (count != GFC_DESCRIPTOR_EXTENT(b,0))
  1744. {
  1745. if (count > 0 || GFC_DESCRIPTOR_EXTENT(b,0) > 0)
  1746. runtime_error ("Incorrect extent in argument B in MATMUL intrinsic "
  1747. "in dimension 1: is %ld, should be %ld",
  1748. (long int) GFC_DESCRIPTOR_EXTENT(b,0), (long int) count);
  1749. }
  1750. if (GFC_DESCRIPTOR_RANK (b) == 1)
  1751. {
  1752. /* Treat it as a column matrix B[count,1] */
  1753. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  1754. /* bystride should never be used for 1-dimensional b.
  1755. The value is only used for calculation of the
  1756. memory by the buffer. */
  1757. bystride = 256;
  1758. ycount = 1;
  1759. }
  1760. else
  1761. {
  1762. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  1763. bystride = GFC_DESCRIPTOR_STRIDE(b,1);
  1764. ycount = GFC_DESCRIPTOR_EXTENT(b,1);
  1765. }
  1766. abase = a->base_addr;
  1767. bbase = b->base_addr;
  1768. dest = retarray->base_addr;
  1769. /* Now that everything is set up, we perform the multiplication
  1770. itself. */
  1771. #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
  1772. #define min(a,b) ((a) <= (b) ? (a) : (b))
  1773. #define max(a,b) ((a) >= (b) ? (a) : (b))
  1774. if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
  1775. && (bxstride == 1 || bystride == 1)
  1776. && (((float) xcount) * ((float) ycount) * ((float) count)
  1777. > POW3(blas_limit)))
  1778. {
  1779. const int m = xcount, n = ycount, k = count, ldc = rystride;
  1780. const GFC_COMPLEX_10 one = 1, zero = 0;
  1781. const int lda = (axstride == 1) ? aystride : axstride,
  1782. ldb = (bxstride == 1) ? bystride : bxstride;
  1783. if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
  1784. {
  1785. assert (gemm != NULL);
  1786. const char *transa, *transb;
  1787. if (try_blas & 2)
  1788. transa = "C";
  1789. else
  1790. transa = axstride == 1 ? "N" : "T";
  1791. if (try_blas & 4)
  1792. transb = "C";
  1793. else
  1794. transb = bxstride == 1 ? "N" : "T";
  1795. gemm (transa, transb , &m,
  1796. &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
  1797. &ldc, 1, 1);
  1798. return;
  1799. }
  1800. }
  1801. if (rxstride == 1 && axstride == 1 && bxstride == 1
  1802. && GFC_DESCRIPTOR_RANK (b) != 1)
  1803. {
  1804. /* This block of code implements a tuned matmul, derived from
  1805. Superscalar GEMM-based level 3 BLAS, Beta version 0.1
  1806. Bo Kagstrom and Per Ling
  1807. Department of Computing Science
  1808. Umea University
  1809. S-901 87 Umea, Sweden
  1810. from netlib.org, translated to C, and modified for matmul.m4. */
  1811. const GFC_COMPLEX_10 *a, *b;
  1812. GFC_COMPLEX_10 *c;
  1813. const index_type m = xcount, n = ycount, k = count;
  1814. /* System generated locals */
  1815. index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
  1816. i1, i2, i3, i4, i5, i6;
  1817. /* Local variables */
  1818. GFC_COMPLEX_10 f11, f12, f21, f22, f31, f32, f41, f42,
  1819. f13, f14, f23, f24, f33, f34, f43, f44;
  1820. index_type i, j, l, ii, jj, ll;
  1821. index_type isec, jsec, lsec, uisec, ujsec, ulsec;
  1822. GFC_COMPLEX_10 *t1;
  1823. a = abase;
  1824. b = bbase;
  1825. c = retarray->base_addr;
  1826. /* Parameter adjustments */
  1827. c_dim1 = rystride;
  1828. c_offset = 1 + c_dim1;
  1829. c -= c_offset;
  1830. a_dim1 = aystride;
  1831. a_offset = 1 + a_dim1;
  1832. a -= a_offset;
  1833. b_dim1 = bystride;
  1834. b_offset = 1 + b_dim1;
  1835. b -= b_offset;
  1836. /* Empty c first. */
  1837. for (j=1; j<=n; j++)
  1838. for (i=1; i<=m; i++)
  1839. c[i + j * c_dim1] = (GFC_COMPLEX_10)0;
  1840. /* Early exit if possible */
  1841. if (m == 0 || n == 0 || k == 0)
  1842. return;
  1843. /* Adjust size of t1 to what is needed. */
  1844. index_type t1_dim, a_sz;
  1845. if (aystride == 1)
  1846. a_sz = rystride;
  1847. else
  1848. a_sz = a_dim1;
  1849. t1_dim = a_sz * 256 + b_dim1;
  1850. if (t1_dim > 65536)
  1851. t1_dim = 65536;
  1852. t1 = malloc (t1_dim * sizeof(GFC_COMPLEX_10));
  1853. /* Start turning the crank. */
  1854. i1 = n;
  1855. for (jj = 1; jj <= i1; jj += 512)
  1856. {
  1857. /* Computing MIN */
  1858. i2 = 512;
  1859. i3 = n - jj + 1;
  1860. jsec = min(i2,i3);
  1861. ujsec = jsec - jsec % 4;
  1862. i2 = k;
  1863. for (ll = 1; ll <= i2; ll += 256)
  1864. {
  1865. /* Computing MIN */
  1866. i3 = 256;
  1867. i4 = k - ll + 1;
  1868. lsec = min(i3,i4);
  1869. ulsec = lsec - lsec % 2;
  1870. i3 = m;
  1871. for (ii = 1; ii <= i3; ii += 256)
  1872. {
  1873. /* Computing MIN */
  1874. i4 = 256;
  1875. i5 = m - ii + 1;
  1876. isec = min(i4,i5);
  1877. uisec = isec - isec % 2;
  1878. i4 = ll + ulsec - 1;
  1879. for (l = ll; l <= i4; l += 2)
  1880. {
  1881. i5 = ii + uisec - 1;
  1882. for (i = ii; i <= i5; i += 2)
  1883. {
  1884. t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
  1885. a[i + l * a_dim1];
  1886. t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
  1887. a[i + (l + 1) * a_dim1];
  1888. t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
  1889. a[i + 1 + l * a_dim1];
  1890. t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
  1891. a[i + 1 + (l + 1) * a_dim1];
  1892. }
  1893. if (uisec < isec)
  1894. {
  1895. t1[l - ll + 1 + (isec << 8) - 257] =
  1896. a[ii + isec - 1 + l * a_dim1];
  1897. t1[l - ll + 2 + (isec << 8) - 257] =
  1898. a[ii + isec - 1 + (l + 1) * a_dim1];
  1899. }
  1900. }
  1901. if (ulsec < lsec)
  1902. {
  1903. i4 = ii + isec - 1;
  1904. for (i = ii; i<= i4; ++i)
  1905. {
  1906. t1[lsec + ((i - ii + 1) << 8) - 257] =
  1907. a[i + (ll + lsec - 1) * a_dim1];
  1908. }
  1909. }
  1910. uisec = isec - isec % 4;
  1911. i4 = jj + ujsec - 1;
  1912. for (j = jj; j <= i4; j += 4)
  1913. {
  1914. i5 = ii + uisec - 1;
  1915. for (i = ii; i <= i5; i += 4)
  1916. {
  1917. f11 = c[i + j * c_dim1];
  1918. f21 = c[i + 1 + j * c_dim1];
  1919. f12 = c[i + (j + 1) * c_dim1];
  1920. f22 = c[i + 1 + (j + 1) * c_dim1];
  1921. f13 = c[i + (j + 2) * c_dim1];
  1922. f23 = c[i + 1 + (j + 2) * c_dim1];
  1923. f14 = c[i + (j + 3) * c_dim1];
  1924. f24 = c[i + 1 + (j + 3) * c_dim1];
  1925. f31 = c[i + 2 + j * c_dim1];
  1926. f41 = c[i + 3 + j * c_dim1];
  1927. f32 = c[i + 2 + (j + 1) * c_dim1];
  1928. f42 = c[i + 3 + (j + 1) * c_dim1];
  1929. f33 = c[i + 2 + (j + 2) * c_dim1];
  1930. f43 = c[i + 3 + (j + 2) * c_dim1];
  1931. f34 = c[i + 2 + (j + 3) * c_dim1];
  1932. f44 = c[i + 3 + (j + 3) * c_dim1];
  1933. i6 = ll + lsec - 1;
  1934. for (l = ll; l <= i6; ++l)
  1935. {
  1936. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1937. * b[l + j * b_dim1];
  1938. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1939. * b[l + j * b_dim1];
  1940. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1941. * b[l + (j + 1) * b_dim1];
  1942. f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1943. * b[l + (j + 1) * b_dim1];
  1944. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1945. * b[l + (j + 2) * b_dim1];
  1946. f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1947. * b[l + (j + 2) * b_dim1];
  1948. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  1949. * b[l + (j + 3) * b_dim1];
  1950. f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  1951. * b[l + (j + 3) * b_dim1];
  1952. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1953. * b[l + j * b_dim1];
  1954. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1955. * b[l + j * b_dim1];
  1956. f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1957. * b[l + (j + 1) * b_dim1];
  1958. f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1959. * b[l + (j + 1) * b_dim1];
  1960. f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1961. * b[l + (j + 2) * b_dim1];
  1962. f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1963. * b[l + (j + 2) * b_dim1];
  1964. f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  1965. * b[l + (j + 3) * b_dim1];
  1966. f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  1967. * b[l + (j + 3) * b_dim1];
  1968. }
  1969. c[i + j * c_dim1] = f11;
  1970. c[i + 1 + j * c_dim1] = f21;
  1971. c[i + (j + 1) * c_dim1] = f12;
  1972. c[i + 1 + (j + 1) * c_dim1] = f22;
  1973. c[i + (j + 2) * c_dim1] = f13;
  1974. c[i + 1 + (j + 2) * c_dim1] = f23;
  1975. c[i + (j + 3) * c_dim1] = f14;
  1976. c[i + 1 + (j + 3) * c_dim1] = f24;
  1977. c[i + 2 + j * c_dim1] = f31;
  1978. c[i + 3 + j * c_dim1] = f41;
  1979. c[i + 2 + (j + 1) * c_dim1] = f32;
  1980. c[i + 3 + (j + 1) * c_dim1] = f42;
  1981. c[i + 2 + (j + 2) * c_dim1] = f33;
  1982. c[i + 3 + (j + 2) * c_dim1] = f43;
  1983. c[i + 2 + (j + 3) * c_dim1] = f34;
  1984. c[i + 3 + (j + 3) * c_dim1] = f44;
  1985. }
  1986. if (uisec < isec)
  1987. {
  1988. i5 = ii + isec - 1;
  1989. for (i = ii + uisec; i <= i5; ++i)
  1990. {
  1991. f11 = c[i + j * c_dim1];
  1992. f12 = c[i + (j + 1) * c_dim1];
  1993. f13 = c[i + (j + 2) * c_dim1];
  1994. f14 = c[i + (j + 3) * c_dim1];
  1995. i6 = ll + lsec - 1;
  1996. for (l = ll; l <= i6; ++l)
  1997. {
  1998. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  1999. 257] * b[l + j * b_dim1];
  2000. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2001. 257] * b[l + (j + 1) * b_dim1];
  2002. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2003. 257] * b[l + (j + 2) * b_dim1];
  2004. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2005. 257] * b[l + (j + 3) * b_dim1];
  2006. }
  2007. c[i + j * c_dim1] = f11;
  2008. c[i + (j + 1) * c_dim1] = f12;
  2009. c[i + (j + 2) * c_dim1] = f13;
  2010. c[i + (j + 3) * c_dim1] = f14;
  2011. }
  2012. }
  2013. }
  2014. if (ujsec < jsec)
  2015. {
  2016. i4 = jj + jsec - 1;
  2017. for (j = jj + ujsec; j <= i4; ++j)
  2018. {
  2019. i5 = ii + uisec - 1;
  2020. for (i = ii; i <= i5; i += 4)
  2021. {
  2022. f11 = c[i + j * c_dim1];
  2023. f21 = c[i + 1 + j * c_dim1];
  2024. f31 = c[i + 2 + j * c_dim1];
  2025. f41 = c[i + 3 + j * c_dim1];
  2026. i6 = ll + lsec - 1;
  2027. for (l = ll; l <= i6; ++l)
  2028. {
  2029. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2030. 257] * b[l + j * b_dim1];
  2031. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
  2032. 257] * b[l + j * b_dim1];
  2033. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
  2034. 257] * b[l + j * b_dim1];
  2035. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
  2036. 257] * b[l + j * b_dim1];
  2037. }
  2038. c[i + j * c_dim1] = f11;
  2039. c[i + 1 + j * c_dim1] = f21;
  2040. c[i + 2 + j * c_dim1] = f31;
  2041. c[i + 3 + j * c_dim1] = f41;
  2042. }
  2043. i5 = ii + isec - 1;
  2044. for (i = ii + uisec; i <= i5; ++i)
  2045. {
  2046. f11 = c[i + j * c_dim1];
  2047. i6 = ll + lsec - 1;
  2048. for (l = ll; l <= i6; ++l)
  2049. {
  2050. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2051. 257] * b[l + j * b_dim1];
  2052. }
  2053. c[i + j * c_dim1] = f11;
  2054. }
  2055. }
  2056. }
  2057. }
  2058. }
  2059. }
  2060. free(t1);
  2061. return;
  2062. }
  2063. else if (rxstride == 1 && aystride == 1 && bxstride == 1)
  2064. {
  2065. if (GFC_DESCRIPTOR_RANK (a) != 1)
  2066. {
  2067. const GFC_COMPLEX_10 *restrict abase_x;
  2068. const GFC_COMPLEX_10 *restrict bbase_y;
  2069. GFC_COMPLEX_10 *restrict dest_y;
  2070. GFC_COMPLEX_10 s;
  2071. for (y = 0; y < ycount; y++)
  2072. {
  2073. bbase_y = &bbase[y*bystride];
  2074. dest_y = &dest[y*rystride];
  2075. for (x = 0; x < xcount; x++)
  2076. {
  2077. abase_x = &abase[x*axstride];
  2078. s = (GFC_COMPLEX_10) 0;
  2079. for (n = 0; n < count; n++)
  2080. s += abase_x[n] * bbase_y[n];
  2081. dest_y[x] = s;
  2082. }
  2083. }
  2084. }
  2085. else
  2086. {
  2087. const GFC_COMPLEX_10 *restrict bbase_y;
  2088. GFC_COMPLEX_10 s;
  2089. for (y = 0; y < ycount; y++)
  2090. {
  2091. bbase_y = &bbase[y*bystride];
  2092. s = (GFC_COMPLEX_10) 0;
  2093. for (n = 0; n < count; n++)
  2094. s += abase[n*axstride] * bbase_y[n];
  2095. dest[y*rystride] = s;
  2096. }
  2097. }
  2098. }
  2099. else if (GFC_DESCRIPTOR_RANK (a) == 1)
  2100. {
  2101. const GFC_COMPLEX_10 *restrict bbase_y;
  2102. GFC_COMPLEX_10 s;
  2103. for (y = 0; y < ycount; y++)
  2104. {
  2105. bbase_y = &bbase[y*bystride];
  2106. s = (GFC_COMPLEX_10) 0;
  2107. for (n = 0; n < count; n++)
  2108. s += abase[n*axstride] * bbase_y[n*bxstride];
  2109. dest[y*rxstride] = s;
  2110. }
  2111. }
  2112. else if (axstride < aystride)
  2113. {
  2114. for (y = 0; y < ycount; y++)
  2115. for (x = 0; x < xcount; x++)
  2116. dest[x*rxstride + y*rystride] = (GFC_COMPLEX_10)0;
  2117. for (y = 0; y < ycount; y++)
  2118. for (n = 0; n < count; n++)
  2119. for (x = 0; x < xcount; x++)
  2120. /* dest[x,y] += a[x,n] * b[n,y] */
  2121. dest[x*rxstride + y*rystride] +=
  2122. abase[x*axstride + n*aystride] *
  2123. bbase[n*bxstride + y*bystride];
  2124. }
  2125. else
  2126. {
  2127. const GFC_COMPLEX_10 *restrict abase_x;
  2128. const GFC_COMPLEX_10 *restrict bbase_y;
  2129. GFC_COMPLEX_10 *restrict dest_y;
  2130. GFC_COMPLEX_10 s;
  2131. for (y = 0; y < ycount; y++)
  2132. {
  2133. bbase_y = &bbase[y*bystride];
  2134. dest_y = &dest[y*rystride];
  2135. for (x = 0; x < xcount; x++)
  2136. {
  2137. abase_x = &abase[x*axstride];
  2138. s = (GFC_COMPLEX_10) 0;
  2139. for (n = 0; n < count; n++)
  2140. s += abase_x[n*aystride] * bbase_y[n*bxstride];
  2141. dest_y[x*rxstride] = s;
  2142. }
  2143. }
  2144. }
  2145. }
  2146. #undef POW3
  2147. #undef min
  2148. #undef max
  2149. /* Compiling main function, with selection code for the processor. */
  2150. /* Currently, this is i386 only. Adjust for other architectures. */
  2151. void matmul_c10 (gfc_array_c10 * const restrict retarray,
  2152. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  2153. int blas_limit, blas_call gemm)
  2154. {
  2155. static void (*matmul_p) (gfc_array_c10 * const restrict retarray,
  2156. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  2157. int blas_limit, blas_call gemm);
  2158. void (*matmul_fn) (gfc_array_c10 * const restrict retarray,
  2159. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  2160. int blas_limit, blas_call gemm);
  2161. matmul_fn = __atomic_load_n (&matmul_p, __ATOMIC_RELAXED);
  2162. if (matmul_fn == NULL)
  2163. {
  2164. matmul_fn = matmul_c10_vanilla;
  2165. if (__builtin_cpu_is ("intel"))
  2166. {
  2167. /* Run down the available processors in order of preference. */
  2168. #ifdef HAVE_AVX512F
  2169. if (__builtin_cpu_supports ("avx512f"))
  2170. {
  2171. matmul_fn = matmul_c10_avx512f;
  2172. goto store;
  2173. }
  2174. #endif /* HAVE_AVX512F */
  2175. #ifdef HAVE_AVX2
  2176. if (__builtin_cpu_supports ("avx2")
  2177. && __builtin_cpu_supports ("fma"))
  2178. {
  2179. matmul_fn = matmul_c10_avx2;
  2180. goto store;
  2181. }
  2182. #endif
  2183. #ifdef HAVE_AVX
  2184. if (__builtin_cpu_supports ("avx"))
  2185. {
  2186. matmul_fn = matmul_c10_avx;
  2187. goto store;
  2188. }
  2189. #endif /* HAVE_AVX */
  2190. }
  2191. else if (__builtin_cpu_is ("amd"))
  2192. {
  2193. #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
  2194. if (__builtin_cpu_supports ("avx")
  2195. && __builtin_cpu_supports ("fma"))
  2196. {
  2197. matmul_fn = matmul_c10_avx128_fma3;
  2198. goto store;
  2199. }
  2200. #endif
  2201. #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
  2202. if (__builtin_cpu_supports ("avx")
  2203. && __builtin_cpu_supports ("fma4"))
  2204. {
  2205. matmul_fn = matmul_c10_avx128_fma4;
  2206. goto store;
  2207. }
  2208. #endif
  2209. }
  2210. store:
  2211. __atomic_store_n (&matmul_p, matmul_fn, __ATOMIC_RELAXED);
  2212. }
  2213. (*matmul_fn) (retarray, a, b, try_blas, blas_limit, gemm);
  2214. }
  2215. #else /* Just the vanilla function. */
  2216. void
  2217. matmul_c10 (gfc_array_c10 * const restrict retarray,
  2218. gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
  2219. int blas_limit, blas_call gemm)
  2220. {
  2221. const GFC_COMPLEX_10 * restrict abase;
  2222. const GFC_COMPLEX_10 * restrict bbase;
  2223. GFC_COMPLEX_10 * restrict dest;
  2224. index_type rxstride, rystride, axstride, aystride, bxstride, bystride;
  2225. index_type x, y, n, count, xcount, ycount;
  2226. assert (GFC_DESCRIPTOR_RANK (a) == 2
  2227. || GFC_DESCRIPTOR_RANK (b) == 2);
  2228. /* C[xcount,ycount] = A[xcount, count] * B[count,ycount]
  2229. Either A or B (but not both) can be rank 1:
  2230. o One-dimensional argument A is implicitly treated as a row matrix
  2231. dimensioned [1,count], so xcount=1.
  2232. o One-dimensional argument B is implicitly treated as a column matrix
  2233. dimensioned [count, 1], so ycount=1.
  2234. */
  2235. if (retarray->base_addr == NULL)
  2236. {
  2237. if (GFC_DESCRIPTOR_RANK (a) == 1)
  2238. {
  2239. GFC_DIMENSION_SET(retarray->dim[0], 0,
  2240. GFC_DESCRIPTOR_EXTENT(b,1) - 1, 1);
  2241. }
  2242. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  2243. {
  2244. GFC_DIMENSION_SET(retarray->dim[0], 0,
  2245. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  2246. }
  2247. else
  2248. {
  2249. GFC_DIMENSION_SET(retarray->dim[0], 0,
  2250. GFC_DESCRIPTOR_EXTENT(a,0) - 1, 1);
  2251. GFC_DIMENSION_SET(retarray->dim[1], 0,
  2252. GFC_DESCRIPTOR_EXTENT(b,1) - 1,
  2253. GFC_DESCRIPTOR_EXTENT(retarray,0));
  2254. }
  2255. retarray->base_addr
  2256. = xmallocarray (size0 ((array_t *) retarray), sizeof (GFC_COMPLEX_10));
  2257. retarray->offset = 0;
  2258. }
  2259. else if (unlikely (compile_options.bounds_check))
  2260. {
  2261. index_type ret_extent, arg_extent;
  2262. if (GFC_DESCRIPTOR_RANK (a) == 1)
  2263. {
  2264. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  2265. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  2266. if (arg_extent != ret_extent)
  2267. runtime_error ("Array bound mismatch for dimension 1 of "
  2268. "array (%ld/%ld) ",
  2269. (long int) ret_extent, (long int) arg_extent);
  2270. }
  2271. else if (GFC_DESCRIPTOR_RANK (b) == 1)
  2272. {
  2273. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  2274. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  2275. if (arg_extent != ret_extent)
  2276. runtime_error ("Array bound mismatch for dimension 1 of "
  2277. "array (%ld/%ld) ",
  2278. (long int) ret_extent, (long int) arg_extent);
  2279. }
  2280. else
  2281. {
  2282. arg_extent = GFC_DESCRIPTOR_EXTENT(a,0);
  2283. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
  2284. if (arg_extent != ret_extent)
  2285. runtime_error ("Array bound mismatch for dimension 1 of "
  2286. "array (%ld/%ld) ",
  2287. (long int) ret_extent, (long int) arg_extent);
  2288. arg_extent = GFC_DESCRIPTOR_EXTENT(b,1);
  2289. ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,1);
  2290. if (arg_extent != ret_extent)
  2291. runtime_error ("Array bound mismatch for dimension 2 of "
  2292. "array (%ld/%ld) ",
  2293. (long int) ret_extent, (long int) arg_extent);
  2294. }
  2295. }
  2296. if (GFC_DESCRIPTOR_RANK (retarray) == 1)
  2297. {
  2298. /* One-dimensional result may be addressed in the code below
  2299. either as a row or a column matrix. We want both cases to
  2300. work. */
  2301. rxstride = rystride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  2302. }
  2303. else
  2304. {
  2305. rxstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
  2306. rystride = GFC_DESCRIPTOR_STRIDE(retarray,1);
  2307. }
  2308. if (GFC_DESCRIPTOR_RANK (a) == 1)
  2309. {
  2310. /* Treat it as a a row matrix A[1,count]. */
  2311. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  2312. aystride = 1;
  2313. xcount = 1;
  2314. count = GFC_DESCRIPTOR_EXTENT(a,0);
  2315. }
  2316. else
  2317. {
  2318. axstride = GFC_DESCRIPTOR_STRIDE(a,0);
  2319. aystride = GFC_DESCRIPTOR_STRIDE(a,1);
  2320. count = GFC_DESCRIPTOR_EXTENT(a,1);
  2321. xcount = GFC_DESCRIPTOR_EXTENT(a,0);
  2322. }
  2323. if (count != GFC_DESCRIPTOR_EXTENT(b,0))
  2324. {
  2325. if (count > 0 || GFC_DESCRIPTOR_EXTENT(b,0) > 0)
  2326. runtime_error ("Incorrect extent in argument B in MATMUL intrinsic "
  2327. "in dimension 1: is %ld, should be %ld",
  2328. (long int) GFC_DESCRIPTOR_EXTENT(b,0), (long int) count);
  2329. }
  2330. if (GFC_DESCRIPTOR_RANK (b) == 1)
  2331. {
  2332. /* Treat it as a column matrix B[count,1] */
  2333. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  2334. /* bystride should never be used for 1-dimensional b.
  2335. The value is only used for calculation of the
  2336. memory by the buffer. */
  2337. bystride = 256;
  2338. ycount = 1;
  2339. }
  2340. else
  2341. {
  2342. bxstride = GFC_DESCRIPTOR_STRIDE(b,0);
  2343. bystride = GFC_DESCRIPTOR_STRIDE(b,1);
  2344. ycount = GFC_DESCRIPTOR_EXTENT(b,1);
  2345. }
  2346. abase = a->base_addr;
  2347. bbase = b->base_addr;
  2348. dest = retarray->base_addr;
  2349. /* Now that everything is set up, we perform the multiplication
  2350. itself. */
  2351. #define POW3(x) (((float) (x)) * ((float) (x)) * ((float) (x)))
  2352. #define min(a,b) ((a) <= (b) ? (a) : (b))
  2353. #define max(a,b) ((a) >= (b) ? (a) : (b))
  2354. if (try_blas && rxstride == 1 && (axstride == 1 || aystride == 1)
  2355. && (bxstride == 1 || bystride == 1)
  2356. && (((float) xcount) * ((float) ycount) * ((float) count)
  2357. > POW3(blas_limit)))
  2358. {
  2359. const int m = xcount, n = ycount, k = count, ldc = rystride;
  2360. const GFC_COMPLEX_10 one = 1, zero = 0;
  2361. const int lda = (axstride == 1) ? aystride : axstride,
  2362. ldb = (bxstride == 1) ? bystride : bxstride;
  2363. if (lda > 0 && ldb > 0 && ldc > 0 && m > 1 && n > 1 && k > 1)
  2364. {
  2365. assert (gemm != NULL);
  2366. const char *transa, *transb;
  2367. if (try_blas & 2)
  2368. transa = "C";
  2369. else
  2370. transa = axstride == 1 ? "N" : "T";
  2371. if (try_blas & 4)
  2372. transb = "C";
  2373. else
  2374. transb = bxstride == 1 ? "N" : "T";
  2375. gemm (transa, transb , &m,
  2376. &n, &k, &one, abase, &lda, bbase, &ldb, &zero, dest,
  2377. &ldc, 1, 1);
  2378. return;
  2379. }
  2380. }
  2381. if (rxstride == 1 && axstride == 1 && bxstride == 1
  2382. && GFC_DESCRIPTOR_RANK (b) != 1)
  2383. {
  2384. /* This block of code implements a tuned matmul, derived from
  2385. Superscalar GEMM-based level 3 BLAS, Beta version 0.1
  2386. Bo Kagstrom and Per Ling
  2387. Department of Computing Science
  2388. Umea University
  2389. S-901 87 Umea, Sweden
  2390. from netlib.org, translated to C, and modified for matmul.m4. */
  2391. const GFC_COMPLEX_10 *a, *b;
  2392. GFC_COMPLEX_10 *c;
  2393. const index_type m = xcount, n = ycount, k = count;
  2394. /* System generated locals */
  2395. index_type a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset,
  2396. i1, i2, i3, i4, i5, i6;
  2397. /* Local variables */
  2398. GFC_COMPLEX_10 f11, f12, f21, f22, f31, f32, f41, f42,
  2399. f13, f14, f23, f24, f33, f34, f43, f44;
  2400. index_type i, j, l, ii, jj, ll;
  2401. index_type isec, jsec, lsec, uisec, ujsec, ulsec;
  2402. GFC_COMPLEX_10 *t1;
  2403. a = abase;
  2404. b = bbase;
  2405. c = retarray->base_addr;
  2406. /* Parameter adjustments */
  2407. c_dim1 = rystride;
  2408. c_offset = 1 + c_dim1;
  2409. c -= c_offset;
  2410. a_dim1 = aystride;
  2411. a_offset = 1 + a_dim1;
  2412. a -= a_offset;
  2413. b_dim1 = bystride;
  2414. b_offset = 1 + b_dim1;
  2415. b -= b_offset;
  2416. /* Empty c first. */
  2417. for (j=1; j<=n; j++)
  2418. for (i=1; i<=m; i++)
  2419. c[i + j * c_dim1] = (GFC_COMPLEX_10)0;
  2420. /* Early exit if possible */
  2421. if (m == 0 || n == 0 || k == 0)
  2422. return;
  2423. /* Adjust size of t1 to what is needed. */
  2424. index_type t1_dim, a_sz;
  2425. if (aystride == 1)
  2426. a_sz = rystride;
  2427. else
  2428. a_sz = a_dim1;
  2429. t1_dim = a_sz * 256 + b_dim1;
  2430. if (t1_dim > 65536)
  2431. t1_dim = 65536;
  2432. t1 = malloc (t1_dim * sizeof(GFC_COMPLEX_10));
  2433. /* Start turning the crank. */
  2434. i1 = n;
  2435. for (jj = 1; jj <= i1; jj += 512)
  2436. {
  2437. /* Computing MIN */
  2438. i2 = 512;
  2439. i3 = n - jj + 1;
  2440. jsec = min(i2,i3);
  2441. ujsec = jsec - jsec % 4;
  2442. i2 = k;
  2443. for (ll = 1; ll <= i2; ll += 256)
  2444. {
  2445. /* Computing MIN */
  2446. i3 = 256;
  2447. i4 = k - ll + 1;
  2448. lsec = min(i3,i4);
  2449. ulsec = lsec - lsec % 2;
  2450. i3 = m;
  2451. for (ii = 1; ii <= i3; ii += 256)
  2452. {
  2453. /* Computing MIN */
  2454. i4 = 256;
  2455. i5 = m - ii + 1;
  2456. isec = min(i4,i5);
  2457. uisec = isec - isec % 2;
  2458. i4 = ll + ulsec - 1;
  2459. for (l = ll; l <= i4; l += 2)
  2460. {
  2461. i5 = ii + uisec - 1;
  2462. for (i = ii; i <= i5; i += 2)
  2463. {
  2464. t1[l - ll + 1 + ((i - ii + 1) << 8) - 257] =
  2465. a[i + l * a_dim1];
  2466. t1[l - ll + 2 + ((i - ii + 1) << 8) - 257] =
  2467. a[i + (l + 1) * a_dim1];
  2468. t1[l - ll + 1 + ((i - ii + 2) << 8) - 257] =
  2469. a[i + 1 + l * a_dim1];
  2470. t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] =
  2471. a[i + 1 + (l + 1) * a_dim1];
  2472. }
  2473. if (uisec < isec)
  2474. {
  2475. t1[l - ll + 1 + (isec << 8) - 257] =
  2476. a[ii + isec - 1 + l * a_dim1];
  2477. t1[l - ll + 2 + (isec << 8) - 257] =
  2478. a[ii + isec - 1 + (l + 1) * a_dim1];
  2479. }
  2480. }
  2481. if (ulsec < lsec)
  2482. {
  2483. i4 = ii + isec - 1;
  2484. for (i = ii; i<= i4; ++i)
  2485. {
  2486. t1[lsec + ((i - ii + 1) << 8) - 257] =
  2487. a[i + (ll + lsec - 1) * a_dim1];
  2488. }
  2489. }
  2490. uisec = isec - isec % 4;
  2491. i4 = jj + ujsec - 1;
  2492. for (j = jj; j <= i4; j += 4)
  2493. {
  2494. i5 = ii + uisec - 1;
  2495. for (i = ii; i <= i5; i += 4)
  2496. {
  2497. f11 = c[i + j * c_dim1];
  2498. f21 = c[i + 1 + j * c_dim1];
  2499. f12 = c[i + (j + 1) * c_dim1];
  2500. f22 = c[i + 1 + (j + 1) * c_dim1];
  2501. f13 = c[i + (j + 2) * c_dim1];
  2502. f23 = c[i + 1 + (j + 2) * c_dim1];
  2503. f14 = c[i + (j + 3) * c_dim1];
  2504. f24 = c[i + 1 + (j + 3) * c_dim1];
  2505. f31 = c[i + 2 + j * c_dim1];
  2506. f41 = c[i + 3 + j * c_dim1];
  2507. f32 = c[i + 2 + (j + 1) * c_dim1];
  2508. f42 = c[i + 3 + (j + 1) * c_dim1];
  2509. f33 = c[i + 2 + (j + 2) * c_dim1];
  2510. f43 = c[i + 3 + (j + 2) * c_dim1];
  2511. f34 = c[i + 2 + (j + 3) * c_dim1];
  2512. f44 = c[i + 3 + (j + 3) * c_dim1];
  2513. i6 = ll + lsec - 1;
  2514. for (l = ll; l <= i6; ++l)
  2515. {
  2516. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  2517. * b[l + j * b_dim1];
  2518. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  2519. * b[l + j * b_dim1];
  2520. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  2521. * b[l + (j + 1) * b_dim1];
  2522. f22 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  2523. * b[l + (j + 1) * b_dim1];
  2524. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  2525. * b[l + (j + 2) * b_dim1];
  2526. f23 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  2527. * b[l + (j + 2) * b_dim1];
  2528. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) - 257]
  2529. * b[l + (j + 3) * b_dim1];
  2530. f24 += t1[l - ll + 1 + ((i - ii + 2) << 8) - 257]
  2531. * b[l + (j + 3) * b_dim1];
  2532. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  2533. * b[l + j * b_dim1];
  2534. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  2535. * b[l + j * b_dim1];
  2536. f32 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  2537. * b[l + (j + 1) * b_dim1];
  2538. f42 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  2539. * b[l + (j + 1) * b_dim1];
  2540. f33 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  2541. * b[l + (j + 2) * b_dim1];
  2542. f43 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  2543. * b[l + (j + 2) * b_dim1];
  2544. f34 += t1[l - ll + 1 + ((i - ii + 3) << 8) - 257]
  2545. * b[l + (j + 3) * b_dim1];
  2546. f44 += t1[l - ll + 1 + ((i - ii + 4) << 8) - 257]
  2547. * b[l + (j + 3) * b_dim1];
  2548. }
  2549. c[i + j * c_dim1] = f11;
  2550. c[i + 1 + j * c_dim1] = f21;
  2551. c[i + (j + 1) * c_dim1] = f12;
  2552. c[i + 1 + (j + 1) * c_dim1] = f22;
  2553. c[i + (j + 2) * c_dim1] = f13;
  2554. c[i + 1 + (j + 2) * c_dim1] = f23;
  2555. c[i + (j + 3) * c_dim1] = f14;
  2556. c[i + 1 + (j + 3) * c_dim1] = f24;
  2557. c[i + 2 + j * c_dim1] = f31;
  2558. c[i + 3 + j * c_dim1] = f41;
  2559. c[i + 2 + (j + 1) * c_dim1] = f32;
  2560. c[i + 3 + (j + 1) * c_dim1] = f42;
  2561. c[i + 2 + (j + 2) * c_dim1] = f33;
  2562. c[i + 3 + (j + 2) * c_dim1] = f43;
  2563. c[i + 2 + (j + 3) * c_dim1] = f34;
  2564. c[i + 3 + (j + 3) * c_dim1] = f44;
  2565. }
  2566. if (uisec < isec)
  2567. {
  2568. i5 = ii + isec - 1;
  2569. for (i = ii + uisec; i <= i5; ++i)
  2570. {
  2571. f11 = c[i + j * c_dim1];
  2572. f12 = c[i + (j + 1) * c_dim1];
  2573. f13 = c[i + (j + 2) * c_dim1];
  2574. f14 = c[i + (j + 3) * c_dim1];
  2575. i6 = ll + lsec - 1;
  2576. for (l = ll; l <= i6; ++l)
  2577. {
  2578. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2579. 257] * b[l + j * b_dim1];
  2580. f12 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2581. 257] * b[l + (j + 1) * b_dim1];
  2582. f13 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2583. 257] * b[l + (j + 2) * b_dim1];
  2584. f14 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2585. 257] * b[l + (j + 3) * b_dim1];
  2586. }
  2587. c[i + j * c_dim1] = f11;
  2588. c[i + (j + 1) * c_dim1] = f12;
  2589. c[i + (j + 2) * c_dim1] = f13;
  2590. c[i + (j + 3) * c_dim1] = f14;
  2591. }
  2592. }
  2593. }
  2594. if (ujsec < jsec)
  2595. {
  2596. i4 = jj + jsec - 1;
  2597. for (j = jj + ujsec; j <= i4; ++j)
  2598. {
  2599. i5 = ii + uisec - 1;
  2600. for (i = ii; i <= i5; i += 4)
  2601. {
  2602. f11 = c[i + j * c_dim1];
  2603. f21 = c[i + 1 + j * c_dim1];
  2604. f31 = c[i + 2 + j * c_dim1];
  2605. f41 = c[i + 3 + j * c_dim1];
  2606. i6 = ll + lsec - 1;
  2607. for (l = ll; l <= i6; ++l)
  2608. {
  2609. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2610. 257] * b[l + j * b_dim1];
  2611. f21 += t1[l - ll + 1 + ((i - ii + 2) << 8) -
  2612. 257] * b[l + j * b_dim1];
  2613. f31 += t1[l - ll + 1 + ((i - ii + 3) << 8) -
  2614. 257] * b[l + j * b_dim1];
  2615. f41 += t1[l - ll + 1 + ((i - ii + 4) << 8) -
  2616. 257] * b[l + j * b_dim1];
  2617. }
  2618. c[i + j * c_dim1] = f11;
  2619. c[i + 1 + j * c_dim1] = f21;
  2620. c[i + 2 + j * c_dim1] = f31;
  2621. c[i + 3 + j * c_dim1] = f41;
  2622. }
  2623. i5 = ii + isec - 1;
  2624. for (i = ii + uisec; i <= i5; ++i)
  2625. {
  2626. f11 = c[i + j * c_dim1];
  2627. i6 = ll + lsec - 1;
  2628. for (l = ll; l <= i6; ++l)
  2629. {
  2630. f11 += t1[l - ll + 1 + ((i - ii + 1) << 8) -
  2631. 257] * b[l + j * b_dim1];
  2632. }
  2633. c[i + j * c_dim1] = f11;
  2634. }
  2635. }
  2636. }
  2637. }
  2638. }
  2639. }
  2640. free(t1);
  2641. return;
  2642. }
  2643. else if (rxstride == 1 && aystride == 1 && bxstride == 1)
  2644. {
  2645. if (GFC_DESCRIPTOR_RANK (a) != 1)
  2646. {
  2647. const GFC_COMPLEX_10 *restrict abase_x;
  2648. const GFC_COMPLEX_10 *restrict bbase_y;
  2649. GFC_COMPLEX_10 *restrict dest_y;
  2650. GFC_COMPLEX_10 s;
  2651. for (y = 0; y < ycount; y++)
  2652. {
  2653. bbase_y = &bbase[y*bystride];
  2654. dest_y = &dest[y*rystride];
  2655. for (x = 0; x < xcount; x++)
  2656. {
  2657. abase_x = &abase[x*axstride];
  2658. s = (GFC_COMPLEX_10) 0;
  2659. for (n = 0; n < count; n++)
  2660. s += abase_x[n] * bbase_y[n];
  2661. dest_y[x] = s;
  2662. }
  2663. }
  2664. }
  2665. else
  2666. {
  2667. const GFC_COMPLEX_10 *restrict bbase_y;
  2668. GFC_COMPLEX_10 s;
  2669. for (y = 0; y < ycount; y++)
  2670. {
  2671. bbase_y = &bbase[y*bystride];
  2672. s = (GFC_COMPLEX_10) 0;
  2673. for (n = 0; n < count; n++)
  2674. s += abase[n*axstride] * bbase_y[n];
  2675. dest[y*rystride] = s;
  2676. }
  2677. }
  2678. }
  2679. else if (GFC_DESCRIPTOR_RANK (a) == 1)
  2680. {
  2681. const GFC_COMPLEX_10 *restrict bbase_y;
  2682. GFC_COMPLEX_10 s;
  2683. for (y = 0; y < ycount; y++)
  2684. {
  2685. bbase_y = &bbase[y*bystride];
  2686. s = (GFC_COMPLEX_10) 0;
  2687. for (n = 0; n < count; n++)
  2688. s += abase[n*axstride] * bbase_y[n*bxstride];
  2689. dest[y*rxstride] = s;
  2690. }
  2691. }
  2692. else if (axstride < aystride)
  2693. {
  2694. for (y = 0; y < ycount; y++)
  2695. for (x = 0; x < xcount; x++)
  2696. dest[x*rxstride + y*rystride] = (GFC_COMPLEX_10)0;
  2697. for (y = 0; y < ycount; y++)
  2698. for (n = 0; n < count; n++)
  2699. for (x = 0; x < xcount; x++)
  2700. /* dest[x,y] += a[x,n] * b[n,y] */
  2701. dest[x*rxstride + y*rystride] +=
  2702. abase[x*axstride + n*aystride] *
  2703. bbase[n*bxstride + y*bystride];
  2704. }
  2705. else
  2706. {
  2707. const GFC_COMPLEX_10 *restrict abase_x;
  2708. const GFC_COMPLEX_10 *restrict bbase_y;
  2709. GFC_COMPLEX_10 *restrict dest_y;
  2710. GFC_COMPLEX_10 s;
  2711. for (y = 0; y < ycount; y++)
  2712. {
  2713. bbase_y = &bbase[y*bystride];
  2714. dest_y = &dest[y*rystride];
  2715. for (x = 0; x < xcount; x++)
  2716. {
  2717. abase_x = &abase[x*axstride];
  2718. s = (GFC_COMPLEX_10) 0;
  2719. for (n = 0; n < count; n++)
  2720. s += abase_x[n*aystride] * bbase_y[n*bxstride];
  2721. dest_y[x*rxstride] = s;
  2722. }
  2723. }
  2724. }
  2725. }
  2726. #undef POW3
  2727. #undef min
  2728. #undef max
  2729. #endif
  2730. #endif