1 /*
2 * Copyright (c) 1994-2019, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 /**
19 \file
20 \brief rewrite function args, etc
21 */
22
23 #include "gbldefs.h"
24 #include "global.h"
25 #include "error.h"
26 #include "comm.h"
27 #include "symtab.h"
28 #include "symutl.h"
29 #include "dtypeutl.h"
30 #include "soc.h"
31 #include "semant.h"
32 #include "ast.h"
33 #include "transfrm.h"
34 #include "gramtk.h"
35 #include "extern.h"
36 #include "hpfutl.h"
37 #include "ccffinfo.h"
38 #include "dinit.h"
39 #include "rte.h"
40 #include "direct.h"
41 #ifdef TARGET_X86
42 #include "x86.h"
43 #endif
44 #include "rtlRtns.h"
45
46 static LOGICAL matmul_use_lhs(int, int, int);
47 static int triplet_extent(int);
48 static int misalignment(int, int, int);
49
50 static LOGICAL is_another_shift(int, int, int, int);
51 static LOGICAL _is_another_shift(int, LOGICAL *);
52 static int transform_associated(int, int);
53 static void transform_mvbits(int, int);
54 static void transform_merge(int, int);
55 static void transform_elemental(int, int);
56 static void transform_c_f_pointer(int, int);
57 static void transform_c_f_procpointer(int, int);
58 static void transform_move_alloc(int, int);
59
60 static void check_arg_isalloc(int);
61 static int rewrite_func_ast(int, int, int);
62 static int rewrite_intr_allocatable(int, int, int);
63 static LOGICAL ast_has_allocatable_member(int);
64 static int rewrite_sub_ast(int, int);
65 static int mk_result_sptr(int, int, int *, int, int, int *);
66 static LOGICAL take_out_user_def_func(int);
67 static int matmul(int, int, int);
68 static int mmul(int, int, int); /* fast matmul */
69 static int reshape(int, int, int);
70 static int _reshape(int, DTYPE, int);
71
72 static int inline_reduction_f90(int ast, int dest, int lc, LOGICAL *doremove);
73 static int inline_reduction_craft(int, int, int);
74
75 static void nop_dealloc(int, int);
76 static void handle_shift(int s);
77
78 /*------ Argument & Expression Rewriting ----------*/
79 int
gen_islocal_index(int ast,int sptr,int dim,int subAst)80 gen_islocal_index(int ast, int sptr, int dim, int subAst)
81 {
82 int nargs, argt;
83 int newast;
84 int align;
85 int descr;
86 int olb, oub;
87 int tmp1, tmp2;
88
89 align = ALIGNG(sptr);
90 descr = DESCRG(sptr);
91 DESCUSEDP(sptr, TRUE);
92 if (!XBIT(47, 0x80) && align) {
93 /* inline it; if (idx.ge.sd$desc(olb).and.idx.le.sd$descr(oub)) then */
94 olb = check_member(ast, get_owner_lower(descr, dim));
95 oub = check_member(ast, get_owner_upper(descr, dim));
96 if (normalize_bounds(sptr)) {
97 olb = add_lbnd(DTYPEG(sptr), dim, olb, ast);
98 oub = add_lbnd(DTYPEG(sptr), dim, oub, ast);
99 }
100 tmp1 = mk_binop(OP_GE, subAst, olb, DT_LOG);
101 tmp2 = mk_binop(OP_LE, subAst, oub, DT_LOG);
102 newast = mk_binop(OP_LAND, tmp1, tmp2, DT_LOG);
103 return newast;
104 }
105
106 nargs = 3;
107 argt = mk_argt(nargs);
108 ARGT_ARG(argt, 0) = check_member(ast, mk_id(descr));
109 ARGT_ARG(argt, 1) = mk_cval(dim + 1, astb.bnd.dtype);
110 newast = mk_default_int(subAst);
111 if (normalize_bounds(sptr))
112 newast = sub_lbnd(DTYPEG(sptr), dim, newast, ast);
113 ARGT_ARG(argt, 2) = newast;
114 newast = mk_func_node(A_FUNC,
115 mk_id(sym_mkfunc(mkRteRtnNm(RTE_islocal_idx), DT_LOG)),
116 nargs, argt);
117 NODESCP(A_SPTRG(A_LOPG(newast)), 1);
118 A_DTYPEP(newast, DT_LOG);
119 return newast;
120 } /* gen_islocal_index */
121
122 static int
gen_scalar_mask(int ast,int list)123 gen_scalar_mask(int ast, int list)
124 {
125 return 0;
126 } /* gen_scalar_mask */
127
128 /*
129 * SUM and PRODUCT reductions use a longer datatype for
130 * the reduction temporary; for instance, they use
131 * REAL*8 for a REAL*4 SUM call
132 */
133 static int
reduction_type(DTYPE dtype)134 reduction_type(DTYPE dtype)
135 {
136 switch (DTY(dtype)) {
137 case TY_BINT:
138 case TY_SINT:
139 case TY_INT:
140 return DT_INT;
141 case TY_INT8:
142 return dtype;
143
144 case TY_REAL:
145 return DT_REAL8;
146 case TY_DBLE:
147 if (XBIT(57, 0x14) || XBIT(51, 0x80)) {
148 /* no real*16, or map real*16 to real*8,
149 * or don't use quad precision accumulators */
150 return dtype;
151 } else {
152 return DT_QUAD;
153 }
154 case TY_QUAD:
155 return dtype;
156
157 case TY_CMPLX:
158 return DT_CMPLX16;
159 case TY_DCMPLX:
160 if (XBIT(57, 0x18) || XBIT(51, 0x80)) {
161 /* no complex*32, or map complex*32 to complex*16,
162 * or don't use quad precision accumulators */
163 return dtype;
164 } else {
165 return DT_QCMPLX;
166 }
167 case TY_QCMPLX:
168 return dtype;
169 default:
170 return dtype;
171 }
172 } /* reduction_type */
173
174 static int
assign_result(int sptr,int ast,DTYPE dtype,DTYPE dtyperes,int stdnext,int lineno)175 assign_result(int sptr, int ast, DTYPE dtype, DTYPE dtyperes, int stdnext,
176 int lineno)
177 {
178 int tsclr, tsclrAst, asn, std;
179 if (dtyperes == dtype)
180 return ast;
181 /* we had a SUM or PRODUCT where we used a REAL*8 temp for a REAL*4
182 * reduction, for instance. Now, coerce back to REAL*4 */
183 tsclr = sym_get_scalar(SYMNAME(sptr), "rr", dtyperes);
184 tsclrAst = mk_id(tsclr);
185 asn = mk_assn_stmt(tsclrAst, ast, dtyperes);
186 std = add_stmt_before(asn, stdnext);
187 STD_LINENO(std) = lineno;
188 STD_LOCAL(std) = 1;
189 STD_PAR(std) = STD_PAR(stdnext);
190 STD_TASK(std) = STD_TASK(stdnext);
191 STD_ACCEL(std) = STD_ACCEL(stdnext);
192 STD_KERNEL(std) = STD_KERNEL(stdnext);
193 return tsclrAst;
194 } /* assign_result */
195
196 /* this will check whether cshift or eoshift needs any communication. */
197 static LOGICAL
is_no_comm_shift(int func_ast,int func_args)198 is_no_comm_shift(int func_ast, int func_args)
199 {
200 return TRUE;
201 }
202
203 /*
204 * generate inline loops for CSHIFT and EOSHIFT
205 */
206 #define SHIFTMAX 7
207 /* shift structure */
208 static struct {
209 int shift; /* shift distance */
210 int dim, cdim; /* which dimension being shifted */
211 int boundary; /* for EOSHIFT, boundary value */
212 int shifttype; /* CSHIFT or EOSHIFT */
213 int dim_dest, dim_src; /* which dimensions get shifted */
214 int n, m, k; /* extent, positive shift amount */
215 int nc, mc, kc; /* constant value of above */
216 LOGICAL lt; /* less than */
217 LOGICAL then_part, else_part; /* nonzero shift, zero shift */
218 } ss[SHIFTMAX]; /* shift data */
219
220 static struct {
221 int shiftcount; /* how many nested shifts */
222 int subssrc[MAXSUBS], subsdest[MAXSUBS];
223 int src, dest;
224 int ndimsrc, ndimdest;
225 } sg; /* shift global data */
226
227 static void
recurse_shift(int s)228 recurse_shift(int s)
229 {
230 if (s < sg.shiftcount) {
231 handle_shift(s);
232 } else {
233 int ast_lhs, ast_rhs, ast;
234 ast_lhs =
235 mk_subscr(A_LOPG(sg.dest), sg.subsdest, sg.ndimdest, A_DTYPEG(sg.dest));
236 ast_rhs =
237 mk_subscr(A_LOPG(sg.src), sg.subssrc, sg.ndimsrc, A_DTYPEG(sg.src));
238 ast = mk_assn_stmt(ast_lhs, ast_rhs, DTY(A_DTYPEG(A_LOPG(sg.dest)) + 1));
239 add_stmt_before(ast, arg_gbl.std);
240 }
241 } /* recurse_shift */
242
243 static void
recurse_eoshift(int s)244 recurse_eoshift(int s)
245 {
246 if (s < sg.shiftcount) {
247 handle_shift(s);
248 } else {
249 int ast_lhs, ast_rhs, ast;
250 ast_lhs =
251 mk_subscr(A_LOPG(sg.dest), sg.subsdest, sg.ndimdest, A_DTYPEG(sg.dest));
252 ast_rhs = ss[s - 1].boundary;
253 ast = mk_assn_stmt(ast_lhs, ast_rhs, DTY(A_DTYPEG(A_LOPG(sg.dest)) + 1));
254 add_stmt_before(ast, arg_gbl.std);
255 }
256 } /* recurse_eoshift */
257
258 static void
handle_shift(int s)259 handle_shift(int s)
260 {
261 if (A_TYPEG(ss[s].m) != A_CNST) {
262 int ast, expr;
263 ast = mk_stmt(A_IFTHEN, 0);
264 expr = mk_binop(OP_NE, ss[s].m, astb.bnd.zero, DT_LOG);
265 A_IFEXPRP(ast, expr);
266 add_stmt_before(ast, arg_gbl.std);
267 }
268 if (ss[s].then_part) {
269 int ta, la, ua, xa, lla, uua, sa;
270 int tb, lb, ub, xb, llb, uub, sb;
271 int tmp1, tmp2;
272 ta = sg.subsdest[ss[s].dim_dest];
273 la = A_LBDG(ta);
274 ua = A_UPBDG(ta);
275 sa = A_STRIDEG(ta);
276 xa = triplet_extent(ta);
277 tb = sg.subssrc[ss[s].dim_src];
278 lb = A_LBDG(tb);
279 ub = A_UPBDG(tb);
280 sb = A_STRIDEG(tb);
281 xb = triplet_extent(tb);
282 if (ss[s].shifttype == I_CSHIFT) {
283 /* a(la : ua - m*sa : sa) = b(lb + m*sb : ub : sb) */
284 tmp1 = opt_binop(OP_MUL, ss[s].m, sa, astb.bnd.dtype);
285 uua = opt_binop(OP_SUB, ua, tmp1, astb.bnd.dtype);
286 sg.subsdest[ss[s].dim_dest] = mk_triple(la, uua, sa);
287
288 tmp1 = opt_binop(OP_MUL, ss[s].m, sb, astb.bnd.dtype);
289 llb = opt_binop(OP_ADD, lb, tmp1, astb.bnd.dtype);
290 sg.subssrc[ss[s].dim_src] = mk_triple(llb, ub, sb);
291 recurse_shift(s + 1);
292
293 /* a(la + (n - m)*sa : ua : sa) = b(lb : ub - (n - m)*sb : sb) */
294 tmp1 = opt_binop(OP_SUB, xa, ss[s].m, astb.bnd.dtype);
295 tmp2 = opt_binop(OP_MUL, tmp1, sa, astb.bnd.dtype);
296 lla = opt_binop(OP_ADD, la, tmp2, astb.bnd.dtype);
297 sg.subsdest[ss[s].dim_dest] = mk_triple(lla, ua, sa);
298
299 tmp1 = opt_binop(OP_SUB, xb, ss[s].m, astb.bnd.dtype);
300 tmp2 = opt_binop(OP_MUL, tmp1, sb, astb.bnd.dtype);
301 uub = opt_binop(OP_SUB, ub, tmp2, astb.bnd.dtype);
302 sg.subssrc[ss[s].dim_src] = mk_triple(lb, uub, sb);
303 recurse_shift(s + 1);
304 } else if (ss[s].shifttype == I_EOSHIFT) {
305 int ast_lhs, ast_rhs, ast, x;
306 /* handle case with m > 0 */
307 x = 0;
308 if (A_TYPEG(ss[s].m) == A_CNST) {
309 if (ss[s].mc > 0) {
310 x = 1;
311 }
312 } else {
313 int ast, expr;
314 x = 1;
315 /* test whether the shift distance is < 0 or > 0 */
316 ast = mk_stmt(A_IFTHEN, 0);
317 expr = mk_binop(OP_GT, ss[s].m, astb.bnd.zero, DT_LOG);
318 A_IFEXPRP(ast, expr);
319 add_stmt_before(ast, arg_gbl.std);
320 }
321 if (x) {
322 /* a(la : ua - m*sa : sa) = b(lb + m*sb : ub : sb) */
323 tmp1 = opt_binop(OP_MUL, ss[s].m, sa, astb.bnd.dtype);
324 uua = opt_binop(OP_SUB, ua, tmp1, astb.bnd.dtype);
325 sg.subsdest[ss[s].dim_dest] = mk_triple(la, uua, sa);
326
327 tmp1 = opt_binop(OP_MUL, ss[s].m, sb, astb.bnd.dtype);
328 llb = opt_binop(OP_ADD, lb, tmp1, astb.bnd.dtype);
329 sg.subssrc[ss[s].dim_src] = mk_triple(llb, ub, sb);
330 recurse_shift(s + 1);
331
332 /* a(la + (n - m)*sa : ua : sa) = boundary */
333 tmp1 = opt_binop(OP_SUB, xa, ss[s].m, astb.bnd.dtype);
334 tmp2 = opt_binop(OP_MUL, tmp1, sa, astb.bnd.dtype);
335 lla = opt_binop(OP_ADD, la, tmp2, astb.bnd.dtype);
336 sg.subsdest[ss[s].dim_dest] = mk_triple(lla, ua, sa);
337
338 ast_lhs = mk_subscr(A_LOPG(sg.dest), sg.subsdest, sg.ndimdest,
339 A_DTYPEG(sg.dest));
340 ast_rhs = ss[s].boundary; /* boundary have to be spread if array */
341 if (A_SHAPEG(ast_rhs)) {
342 /* add spread call */
343 int newargt, spread;
344 newargt = mk_argt(3);
345 ARGT_ARG(newargt, 0) = ast_rhs;
346 ARGT_ARG(newargt, 1) = mk_cval(ss[s].dim_dest + 1, astb.bnd.dtype);
347 tmp2 = opt_binop(OP_SUB, ua, lla, astb.bnd.dtype);
348 if (sa != astb.i1 && sa != astb.bnd.one) {
349 tmp2 = opt_binop(OP_DIV, tmp2, sa, astb.bnd.dtype);
350 }
351 ARGT_ARG(newargt, 2) = mk_cval(tmp2, astb.bnd.dtype);
352 spread = mk_id(intast_sym[I_SPREAD]);
353 ast_rhs = mk_func_node(A_INTR, spread, 3, newargt);
354 A_OPTYPEP(ast_rhs, I_SPREAD);
355 }
356 ast =
357 mk_assn_stmt(ast_lhs, ast_rhs, DTY(A_DTYPEG(A_LOPG(sg.dest)) + 1));
358 add_stmt_before(ast, arg_gbl.std);
359 }
360 /* handle case with m < 0 */
361 x = 0;
362 if (A_TYPEG(ss[s].m) == A_CNST) {
363 if (ss[s].mc < 0) {
364 x = 1;
365 }
366 } else {
367 int ast, expr;
368 x = 1;
369 ast = mk_stmt(A_ELSE, 0);
370 add_stmt_before(ast, arg_gbl.std);
371 }
372 if (x) {
373 /* a(la - m*sa : ua : sa) = b(lb : ub - m*sb : sb) */
374 tmp1 = opt_binop(OP_MUL, ss[s].m, sa, astb.bnd.dtype);
375 lla = opt_binop(OP_SUB, la, tmp1, astb.bnd.dtype);
376 sg.subsdest[ss[s].dim_dest] = mk_triple(lla, ua, sa);
377
378 tmp1 = opt_binop(OP_MUL, ss[s].m, sb, astb.bnd.dtype);
379 uub = opt_binop(OP_SUB, ub, tmp1, astb.bnd.dtype);
380 sg.subssrc[ss[s].dim_src] = mk_triple(lb, uub, sb);
381 recurse_shift(s + 1);
382
383 /* a(la : (la-m*sa)-1 : sa) = boundary */
384 lla = opt_binop(OP_SUB, lla, astb.bnd.one, astb.bnd.dtype);
385 sg.subsdest[ss[s].dim_dest] = mk_triple(la, lla, sa);
386
387 ast_lhs = mk_subscr(A_LOPG(sg.dest), sg.subsdest, sg.ndimdest,
388 A_DTYPEG(sg.dest));
389 ast_rhs = ss[s].boundary; /* boundary have to be spread if array */
390 if (A_SHAPEG(ast_rhs)) {
391 /* add spread call */
392 int newargt, spread;
393 newargt = mk_argt(3);
394 ARGT_ARG(newargt, 0) = ast_rhs;
395 ARGT_ARG(newargt, 1) = mk_cval(ss[s].dim_dest + 1, astb.bnd.dtype);
396 tmp2 = opt_binop(OP_SUB, ua, lla, astb.bnd.dtype);
397 if (sa != astb.i1 && sa != astb.bnd.one) {
398 tmp2 = opt_binop(OP_DIV, tmp2, sa, astb.bnd.dtype);
399 }
400 ARGT_ARG(newargt, 2) = mk_cval(tmp2, astb.bnd.dtype);
401 spread = mk_id(intast_sym[I_SPREAD]);
402 ast_rhs = mk_func_node(A_INTR, spread, 3, newargt);
403 A_OPTYPEP(ast_rhs, I_SPREAD);
404 }
405 ast =
406 mk_assn_stmt(ast_lhs, ast_rhs, DTY(A_DTYPEG(A_LOPG(sg.dest)) + 1));
407 add_stmt_before(ast, arg_gbl.std);
408 }
409 if (A_TYPEG(ss[s].m) != A_CNST) {
410 int ast, expr;
411 ast = mk_stmt(A_ENDIF, 0);
412 add_stmt_before(ast, arg_gbl.std);
413 }
414 }
415
416 sg.subsdest[ss[s].dim_dest] = ta;
417 sg.subssrc[ss[s].dim_src] = tb;
418 }
419
420 if (A_TYPEG(ss[s].m) != A_CNST) {
421 int ast;
422 ast = mk_stmt(A_ELSE, 0);
423 add_stmt_before(ast, arg_gbl.std);
424 }
425
426 if (ss[s].else_part) {
427 /* a(la:ua:sa) = b(lb:ub:sb) */
428 if (ss[s].shifttype == I_EOSHIFT)
429 recurse_eoshift(s + 1);
430 else
431 recurse_shift(s + 1);
432 }
433
434 if (A_TYPEG(ss[s].m) != A_CNST) {
435 int ast;
436 ast = mk_stmt(A_ENDIF, 0);
437 add_stmt_before(ast, arg_gbl.std);
438 }
439 } /* handle_shift */
440
441 /*
442 * for an EOSHIFT call with an omitted boundary value,
443 * use zero. This functions returns an AST referencing
444 * an appropriate 'zero' value for the given array datatype.
445 */
446 static int
_makezero(DTYPE dtype)447 _makezero(DTYPE dtype)
448 {
449 int v[4], w[4], sptr;
450 INT V;
451 int sub, ndims, i;
452 int firstast, lastast, ast, member;
453 char *str;
454 int l, len;
455 switch (DTY(dtype)) {
456 case TY_HOLL:
457 case TY_WORD:
458 case TY_INT:
459 case TY_LOG:
460 case TY_REAL:
461 case TY_SINT:
462 case TY_BINT:
463 case TY_SLOG:
464 case TY_BLOG:
465 V = 0;
466 return mk_cval1(V, dtype);
467
468 case TY_DBLE:
469 case TY_QUAD:
470 case TY_DWORD:
471 case TY_LOG8:
472 case TY_INT8:
473 v[0] = v[1] = v[2] = v[3] = 0;
474 sptr = getcon(v, dtype);
475 return mk_cval1((INT)sptr, dtype);
476
477 case TY_CMPLX:
478 v[0] = stb.flt0;
479 v[1] = stb.flt0;
480 sptr = getcon(v, dtype);
481 return mk_cval(sptr, dtype);
482 case TY_DCMPLX:
483 v[0] = stb.dbl0;
484 v[1] = stb.dbl0;
485 sptr = getcon(v, dtype);
486 return mk_cval1(sptr, dtype);
487 case TY_QCMPLX:
488 v[0] = v[1] = v[2] = v[3] = 0;
489 v[0] = getcon(v, DT_QUAD);
490 v[1] = v[0];
491 sptr = getcon(v, dtype);
492 return mk_cval1(sptr, dtype);
493
494 case TY_CHAR:
495 case TY_NCHAR:
496 /* make blank */
497 len = DTY(dtype + 1);
498 if (!A_ALIASG(len)) {
499 len = 1;
500 } else {
501 len = A_ALIASG(len);
502 len = A_SPTRG(len);
503 len = CONVAL2G(len);
504 }
505 str = (char *)malloc(len + 1);
506 for (l = 0; l < len; ++l)
507 str[l] = ' ';
508 str[len] = '\0';
509 sptr = getstring(str, len);
510 free(str);
511 return mk_id(sptr);
512 break;
513
514 case TY_ARRAY:
515 /* make an array of zeros */
516 sub = _makezero(DTY(dtype + 1));
517 ndims = ADD_NUMDIM(dtype);
518 for (i = 0; i < ndims; ++i) {
519 int j, extent, prevast, ast;
520 extent = ADD_EXTNTAST(dtype, i);
521 if (!A_ALIASG(extent)) {
522 extent = 1;
523 } else {
524 extent = A_ALIASG(extent);
525 extent = A_SPTRG(extent);
526 extent = CONVAL2G(extent);
527 }
528 prevast = 0;
529 for (j = 0; j < extent; ++j) {
530 ast = mk_init(sub, DTY(dtype + 1));
531 A_RIGHTP(ast, prevast);
532 prevast = ast;
533 }
534 sub = ast;
535 }
536 return sub;
537
538 case TY_STRUCT:
539 case TY_DERIVED:
540 /* make a structure of zeros */
541 firstast = 0;
542 lastast = 0;
543 for (member = DTY(dtype + 1); member > NOSYM; member = SYMLKG(member)) {
544 sub = _makezero(DTYPEG(member));
545 ast = mk_init(sub, DTYPEG(member));
546 if (firstast == 0) {
547 firstast = ast;
548 } else {
549 A_RIGHTP(lastast, ast);
550 }
551 lastast = ast;
552 A_SPTRP(ast, member);
553 }
554 return firstast;
555
556 case TY_UNION:
557 case TY_PTR:
558 case TY_NONE:
559 default:
560 interr("makezero: unknown datatype", DTY(dtype), 4);
561 break;
562 }
563 return 0;
564 } /* _makezero */
565
566 /*
567 * write data-initialization to dinit file for array/structure
568 */
569 static void
putzero(int ast)570 putzero(int ast)
571 {
572 /* derived type? */
573 for (; ast; ast = A_RIGHTG(ast)) {
574 int a, dtype, sptr;
575 a = A_LEFTG(ast);
576 switch (A_TYPEG(a)) {
577 case A_INIT:
578 dtype = A_DTYPEG(a);
579 if (DTY(dtype) == TY_DERIVED || DTY(dtype) == TY_STRUCT) {
580 if (DTY(dtype + 3)) {
581 dinit_put(DINIT_TYPEDEF, DTY(dtype + 3));
582 }
583 }
584 putzero(a);
585 if (DTY(dtype) == TY_DERIVED || DTY(dtype) == TY_STRUCT) {
586 if (DTY(dtype + 3)) {
587 dinit_put(DINIT_ENDTYPE, DTY(dtype + 3));
588 }
589 }
590 break;
591 case A_ID:
592 case A_CNST:
593 sptr = A_SPTRG(a);
594 dtype = DTYPEG(sptr);
595 switch (DTY(dtype)) {
596 case TY_BINT:
597 case TY_SINT:
598 case TY_INT:
599 case TY_BLOG:
600 case TY_SLOG:
601 case TY_LOG:
602 case TY_FLOAT:
603 dinit_put(dtype, CONVAL2G(sptr));
604 break;
605 case TY_DBLE:
606 case TY_CMPLX:
607 case TY_DCMPLX:
608 case TY_QUAD:
609 case TY_QCMPLX:
610 case TY_INT8:
611 case TY_LOG8:
612 case TY_CHAR:
613 dinit_put(dtype, sptr);
614 break;
615 }
616 break;
617 }
618 }
619 } /* putzero */
620
621 /*
622 * for an EOSHIFT call with an omitted boundary value,
623 * use zero. This functions returns an AST referencing
624 * an appropriate 'zero' value for the given array datatype.
625 */
626 static int
makezero(DTYPE dtype)627 makezero(DTYPE dtype)
628 {
629 int sub, sptr;
630 switch (DTY(dtype)) {
631 default:
632 return _makezero(dtype);
633
634 case TY_ARRAY:
635 /* make an array of zeros */
636 sub = _makezero(dtype);
637 sptr = get_next_sym("init", "r");
638 STYPEP(sptr, ST_ARRAY);
639 DTYPEP(sptr, dtype);
640 SCP(sptr, SC_STATIC);
641 DINITP(sptr, 1);
642 SEQP(sptr, 1);
643 PARAMP(sptr, 1);
644 PARAMVALP(sptr, sub);
645 dinit_put(DINIT_LOC, sptr);
646 putzero(sub);
647 dinit_put(DINIT_END, 0);
648 return mk_id(sptr);
649
650 case TY_STRUCT:
651 case TY_UNION:
652 case TY_DERIVED:
653 /* make an array of zeros */
654 sub = _makezero(dtype);
655 sptr = get_next_sym("init", "r");
656 STYPEP(sptr, ST_VAR);
657 DTYPEP(sptr, dtype);
658 SCP(sptr, SC_STATIC);
659 DINITP(sptr, 1);
660 SEQP(sptr, 1);
661 PARAMP(sptr, 1);
662 PARAMVALP(sptr, sub);
663 /* dump out the values to the data initialization file */
664 dinit_put(DINIT_LOC, sptr);
665 if (DTY(dtype + 3)) {
666 dinit_put(DINIT_TYPEDEF, DTY(dtype + 3));
667 }
668 putzero(sub);
669 if (DTY(dtype + 3)) {
670 dinit_put(DINIT_ENDTYPE, DTY(dtype + 3));
671 }
672 dinit_put(DINIT_END, 0);
673 return mk_id(sptr);
674 }
675 } /* makezero */
676
677 static void
inline_shifts(int func_ast,int func_args,int lhs)678 inline_shifts(int func_ast, int func_args, int lhs)
679 {
680 int srcarray;
681 int s;
682
683 int sptrsrc, sptrdest;
684 int asdsrc, asddest;
685 int count;
686 int i;
687 int args;
688
689 sg.shiftcount = 0;
690 srcarray = func_ast;
691 args = func_args;
692 /* find all nested cshift/eoshift calls */
693 while (A_TYPEG(srcarray) == A_INTR) {
694 if (A_OPTYPEG(srcarray) == I_CSHIFT) {
695 /* cshift(array, shift, [dim]) */
696 assert(sg.shiftcount < SHIFTMAX, "inline_shifts: too many nested shifts",
697 func_ast, 3);
698 srcarray = ARGT_ARG(args, 0);
699 s = sg.shiftcount;
700 ss[s].shift = ARGT_ARG(args, 1);
701 ss[s].dim = ARGT_ARG(args, 2);
702 ss[s].shifttype = I_CSHIFT;
703 } else if (A_OPTYPEG(srcarray) == I_EOSHIFT) {
704 /* eoshift(array, shift, [boundary, dim]); */
705 assert(sg.shiftcount < SHIFTMAX, "inline_shifts: too many nested shifts",
706 func_ast, 3);
707 srcarray = ARGT_ARG(args, 0);
708 s = sg.shiftcount;
709 ss[s].shift = ARGT_ARG(args, 1);
710 ss[s].boundary = ARGT_ARG(args, 2);
711 if (ss[s].boundary == 0) {
712 /* must create a 'zero' */
713 if (DTY(A_DTYPEG(srcarray)) == TY_ARRAY) {
714 ss[s].boundary = makezero(DTY(A_DTYPEG(srcarray) + 1));
715 } else {
716 ss[s].boundary = makezero(A_DTYPEG(srcarray));
717 }
718 }
719 ss[s].dim = ARGT_ARG(args, 3);
720 ss[s].shifttype = I_EOSHIFT;
721 } else {
722 interr("inline_shifts: must be CSHIFT or EOSHIFT", srcarray, 3);
723 }
724 if (ss[s].dim == 0)
725 ss[s].dim = mk_cval(1, astb.bnd.dtype);
726 assert(A_TYPEG(ss[s].dim) == A_CNST,
727 "inline_shifts: variable dimension not implemented", srcarray, 3);
728 ss[s].cdim = get_int_cval(A_SPTRG(A_ALIASG(ss[s].dim)));
729 ++sg.shiftcount;
730 args = A_ARGSG(srcarray);
731 }
732 assert(lhs, "inline_shifts: no lhs", func_ast, 3);
733 assert(A_TYPEG(lhs) == A_ID || A_TYPEG(lhs) == A_SUBSCR ||
734 A_TYPEG(lhs) == A_MEM,
735 "inline_shifts: bad lhs type", func_ast, 3);
736 assert(A_TYPEG(srcarray) == A_ID || A_TYPEG(srcarray) == A_SUBSCR ||
737 A_TYPEG(srcarray) == A_MEM,
738 "inline_shifts: bad source type", func_ast, 3);
739
740 sg.src = convert_subscript(srcarray);
741 sg.dest = convert_subscript(lhs);
742 sptrsrc = memsym_of_ast(sg.src);
743 sptrdest = memsym_of_ast(sg.dest);
744
745 asdsrc = A_ASDG(sg.src);
746 sg.ndimsrc = ASD_NDIM(asdsrc);
747 for (s = 0; s < sg.shiftcount; ++s) {
748 if (ss[s].cdim > sg.ndimsrc || (ss[s].cdim < 1 || ss[s].cdim > 7)) {
749 error(504, 3, gbl.lineno, SYMNAME(sptrsrc), CNULL);
750 ss[s].cdim = 1;
751 }
752 }
753 count = 0;
754 for (i = 0; i < sg.ndimsrc; ++i) {
755 if (A_TYPEG(ASD_SUBS(asdsrc, i)) == A_TRIPLE ||
756 A_SHAPEG(ASD_SUBS(asdsrc, i))) {
757 ++count;
758 for (s = 0; s < sg.shiftcount; ++s) {
759 if (count == ss[s].cdim) {
760 ss[s].dim_src = i;
761 break;
762 }
763 }
764 }
765 }
766
767 asddest = A_ASDG(sg.dest);
768 sg.ndimdest = ASD_NDIM(asddest);
769 count = 0;
770 for (i = 0; i < sg.ndimdest; ++i) {
771 if (A_TYPEG(ASD_SUBS(asddest, i)) == A_TRIPLE ||
772 A_SHAPEG(ASD_SUBS(asddest, i))) {
773 ++count;
774 for (s = 0; s < sg.shiftcount; ++s) {
775 if (count == ss[s].cdim) {
776 ss[s].dim_dest = i;
777 break;
778 }
779 }
780 }
781 }
782
783 /* Determine the section extent */
784 for (s = 0; s < sg.shiftcount; ++s) {
785 ss[s].n = triplet_extent(ASD_SUBS(asdsrc, ss[s].dim_src));
786 if (A_TYPEG(ss[s].n) != A_CNST) {
787 int tmp, ast;
788 tmp = sym_get_scalar("n", "s", astb.bnd.dtype);
789 ast = mk_assn_stmt(mk_id(tmp), ss[s].n, astb.bnd.dtype);
790 add_stmt_before(ast, arg_gbl.std);
791 ss[s].n = mk_id(tmp);
792 } else {
793 ss[s].nc = get_int_cval(A_SPTRG(A_ALIASG(ss[s].n)));
794 }
795
796 /* Determine the net positive shift amount for CSHIFT
797 * m = MOD(k, n)
798 * if (m .lt. 0) then
799 * m = n + m
800 * endif
801 */
802
803 ss[s].k = ss[s].shift;
804 if (A_TYPEG(ss[s].k) == A_CNST && A_TYPEG(ss[s].n) == A_CNST) {
805 int result;
806 ss[s].kc = get_int_cval(A_SPTRG(A_ALIASG(ss[s].k)));
807 result = ss[s].kc % ss[s].nc;
808 ss[s].m = mk_cval(result, astb.bnd.dtype);
809 } else {
810 int mod, tmp, ast;
811 mod = ast_intr(I_MOD, DT_INT, 2, ss[s].k, ss[s].n);
812 tmp = sym_get_scalar("m", "s", astb.bnd.dtype);
813 ss[s].m = mk_id(tmp);
814 ast = mk_assn_stmt(ss[s].m, mod, astb.bnd.dtype);
815 add_stmt_before(ast, arg_gbl.std);
816 }
817 ss[s].lt = TRUE;
818 if (A_TYPEG(ss[s].m) == A_CNST) {
819 ss[s].mc = get_int_cval(A_SPTRG(A_ALIASG(ss[s].m)));
820 if (ss[s].mc >= 0) {
821 ss[s].lt = FALSE;
822 } else if (ss[s].shifttype == I_CSHIFT) {
823 if (A_TYPEG(ss[s].n) == A_CNST) {
824 ss[s].mc = ss[s].mc + ss[s].nc;
825 ss[s].m = mk_cval(ss[s].mc, astb.bnd.dtype);
826 ss[s].lt = FALSE;
827 } else {
828 int ast, tmp;
829 ast = opt_binop(OP_ADD, ss[s].m, ss[s].n, astb.bnd.dtype);
830 tmp = sym_get_scalar("m", "s", astb.bnd.dtype);
831 ss[s].m = mk_id(tmp);
832 ast = mk_assn_stmt(ss[s].m, ast, astb.bnd.dtype);
833 add_stmt_before(ast, arg_gbl.std);
834 }
835 }
836 }
837
838 if (ss[s].lt && ss[s].shifttype == I_CSHIFT) {
839 int ast, expr;
840 ast = mk_stmt(A_IFTHEN, 0);
841 expr = mk_binop(OP_LT, ss[s].m, astb.bnd.zero, DT_LOG);
842 A_IFEXPRP(ast, expr);
843 add_stmt_before(ast, arg_gbl.std);
844 ast = mk_assn_stmt(ss[s].m,
845 opt_binop(OP_ADD, ss[s].n, ss[s].m, astb.bnd.dtype),
846 astb.bnd.dtype);
847 add_stmt_before(ast, arg_gbl.std);
848 ast = mk_stmt(A_ENDIF, 0);
849 add_stmt_before(ast, arg_gbl.std);
850 }
851
852 ss[s].then_part = FALSE;
853 ss[s].else_part = FALSE;
854 if (A_TYPEG(ss[s].m) != A_CNST) {
855 ss[s].then_part = TRUE;
856 ss[s].else_part = TRUE;
857 } else if (ss[s].mc != 0) {
858 ss[s].then_part = TRUE;
859 } else {
860 ss[s].else_part = TRUE;
861 }
862 }
863 for (i = 0; i < sg.ndimdest; ++i) {
864 sg.subsdest[i] = ASD_SUBS(asddest, i);
865 }
866 for (i = 0; i < sg.ndimsrc; ++i) {
867 sg.subssrc[i] = ASD_SUBS(asdsrc, i);
868 }
869
870 handle_shift(0);
871
872 } /* inline_shifts */
873
874 /* Determine the section extent
875 * n = (ub - lb + sb) / sb
876 */
877 static int
triplet_extent(int t)878 triplet_extent(int t)
879 {
880 int lb, ub, sb;
881 int tmp1, tmp2, tmp3;
882
883 assert(A_TYPEG(t) == A_TRIPLE, "triplet_extent: should be triplet", t, 3);
884 lb = A_LBDG(t);
885 ub = A_UPBDG(t);
886 sb = A_STRIDEG(t);
887 tmp1 = opt_binop(OP_SUB, ub, lb, astb.bnd.dtype);
888 tmp2 = opt_binop(OP_ADD, tmp1, sb, astb.bnd.dtype);
889 tmp3 = opt_binop(OP_DIV, tmp2, sb, astb.bnd.dtype);
890 return tmp3;
891 }
892
893 static LOGICAL
is_inline_overlap_shifts(int func_ast,int func_args,int lhs)894 is_inline_overlap_shifts(int func_ast, int func_args, int lhs)
895 {
896 return FALSE;
897 }
898
899 LOGICAL
is_shift_conflict(int func_ast,int func_args,int expr)900 is_shift_conflict(int func_ast, int func_args, int expr)
901 {
902 int srcarray;
903 int boundary;
904 int sptr;
905
906 srcarray = ARGT_ARG(func_args, 0);
907 sptr = memsym_of_ast(srcarray);
908 boundary = -1;
909 if (A_OPTYPEG(func_ast) == I_EOSHIFT)
910 boundary = ARGT_ARG(func_args, 2);
911 if (A_OPTYPEG(func_ast) == I_CSHIFT)
912 if (expr && is_another_shift(expr, sptr, I_EOSHIFT, boundary))
913 return TRUE;
914 if (A_OPTYPEG(func_ast) == I_EOSHIFT) {
915 if (expr && is_another_shift(expr, sptr, I_CSHIFT, boundary))
916 return TRUE;
917 if (expr && is_another_shift(expr, sptr, I_EOSHIFT, boundary))
918 return TRUE;
919 }
920 return FALSE;
921 }
922
923 static struct {
924 int sptr;
925 int type;
926 int boundary;
927 } expp;
928
929 static LOGICAL
is_another_shift(int expr,int sptr,int type,int boundary)930 is_another_shift(int expr, int sptr, int type, int boundary)
931 {
932 LOGICAL result = FALSE;
933
934 expp.sptr = sptr;
935 expp.type = type;
936 expp.boundary = boundary;
937 ast_visit(1, 1);
938 ast_traverse(expr, _is_another_shift, NULL, &result);
939 ast_unvisit();
940 return result;
941 }
942
943 static LOGICAL
_is_another_shift(int targast,LOGICAL * pflag)944 _is_another_shift(int targast, LOGICAL *pflag)
945 {
946 int boundary;
947 int sptr;
948 int type;
949 int srcarray;
950 int args;
951 int check_boundary;
952
953 if (A_TYPEG(targast) == A_INTR) {
954 if (A_OPTYPEG(targast) == I_CSHIFT || A_OPTYPEG(targast) == I_EOSHIFT) {
955 type = A_OPTYPEG(targast);
956 args = A_ARGSG(targast);
957 srcarray = ARGT_ARG(args, 0);
958 boundary = 0;
959 if (type == I_EOSHIFT)
960 boundary = ARGT_ARG(args, 2);
961 sptr = 0;
962 switch (A_TYPEG(srcarray)) {
963 case A_ID:
964 case A_SUBSCR:
965 sptr = memsym_of_ast(srcarray);
966 break;
967 }
968 check_boundary = 1;
969 if (expp.boundary != -1)
970 if (expp.boundary == boundary)
971 check_boundary = 0;
972 if (expp.sptr == sptr && expp.type == type && check_boundary) {
973 *pflag = TRUE;
974 return TRUE;
975 }
976 }
977 }
978 return FALSE;
979 }
980
981 static int
stride_one(int lw,int up)982 stride_one(int lw, int up)
983 {
984 if (A_TYPEG(lw) == A_CNST && A_TYPEG(up) == A_CNST &&
985 ad_val_of(A_SPTRG(lw)) > ad_val_of(A_SPTRG(up)))
986 return mk_isz_cval((ISZ_T)-1, astb.bnd.dtype);
987 return astb.bnd.one;
988 }
989
990 int
convert_subscript(int a)991 convert_subscript(int a)
992 {
993 ADSC *ad;
994 int sptr, parent, member;
995 int ndim;
996 int lb, ub, st;
997 int i;
998 int subs[MAXSUBS];
999 int asd;
1000
1001 if (A_TYPEG(a) == A_ID) {
1002 sptr = A_SPTRG(a);
1003 if (!is_array_type(sptr))
1004 return a;
1005 ad = AD_DPTR(DTYPEG(sptr));
1006 ndim = AD_NUMDIM(ad);
1007 for (i = 0; i < ndim; i++) {
1008 subs[i] = mk_triple(AD_LWAST(ad, i), AD_UPAST(ad, i),
1009 stride_one(AD_LWAST(ad, i), AD_UPAST(ad, i)));
1010 }
1011 return mk_subscr(mk_id(sptr), subs, ndim, A_DTYPEG(a));
1012 }
1013
1014 if (A_TYPEG(a) == A_MEM) {
1015 /* do the parent first */
1016 parent = convert_subscript(A_PARENTG(a));
1017 member = A_MEMG(a);
1018 a = mk_member(parent, member, A_DTYPEG(member));
1019 sptr = A_SPTRG(member);
1020 if (!is_array_type(sptr))
1021 return a;
1022 ad = AD_DPTR(DTYPEG(sptr));
1023 ndim = AD_NUMDIM(ad);
1024 for (i = 0; i < ndim; i++) {
1025 subs[i] = mk_triple(check_member(a, AD_LWAST(ad, i)),
1026 check_member(a, AD_UPAST(ad, i)), astb.bnd.one);
1027 }
1028 return mk_subscr(a, subs, ndim, A_DTYPEG(a));
1029 }
1030
1031 if (A_TYPEG(a) == A_SUBSCR) {
1032 int lop, anytriple;
1033 sptr = sptr_of_subscript(a);
1034 assert(is_array_type(sptr), "convert_subscript: must be array", 2, a);
1035 lop = A_LOPG(a);
1036 ad = AD_DPTR(DTYPEG(sptr));
1037 asd = A_ASDG(a);
1038 ndim = ASD_NDIM(asd);
1039 anytriple = 0;
1040 for (i = 0; i < ndim; i++) {
1041 subs[i] = ASD_SUBS(asd, i);
1042 if (A_TYPEG(subs[i]) == A_TRIPLE) {
1043 anytriple = 1;
1044 lb = A_LBDG(subs[i]);
1045 if (!lb)
1046 lb = AD_LWAST(ad, i);
1047 ub = A_UPBDG(subs[i]);
1048 if (!ub)
1049 ub = AD_UPAST(ad, i);
1050 st = A_STRIDEG(subs[i]);
1051 if (!st)
1052 st = astb.bnd.one;
1053 subs[i] = mk_triple(lb, ub, st);
1054 }
1055 }
1056 /* was the triplet at this level? */
1057 if (anytriple)
1058 return mk_subscr(lop, subs, ndim, A_DTYPEG(a));
1059
1060 if (A_TYPEG(lop) == A_MEM) {
1061 parent = convert_subscript(A_PARENTG(lop));
1062 member = A_MEMG(lop);
1063 lop = mk_member(parent, member, A_DTYPEG(member));
1064 }
1065 return mk_subscr(lop, subs, ndim, A_DTYPEG(a));
1066 }
1067 assert(0, "convert_subscript: it must be array", 0, a);
1068 return a;
1069 }
1070
1071 static int
convert_subscript_in_expr(int expr)1072 convert_subscript_in_expr(int expr)
1073 {
1074 int l, r, d, o;
1075 int i, nargs, argt;
1076 int newargt;
1077
1078 if (expr == 0)
1079 return expr;
1080 switch (A_TYPEG(expr)) {
1081 /* expressions */
1082 case A_BINOP:
1083 o = A_OPTYPEG(expr);
1084 d = A_DTYPEG(expr);
1085 l = convert_subscript_in_expr(A_LOPG(expr));
1086 r = convert_subscript_in_expr(A_ROPG(expr));
1087 return mk_binop(o, l, r, d);
1088 case A_UNOP:
1089 o = A_OPTYPEG(expr);
1090 d = A_DTYPEG(expr);
1091 l = convert_subscript_in_expr(A_LOPG(expr));
1092 return mk_unop(o, l, d);
1093 case A_CONV:
1094 d = A_DTYPEG(expr);
1095 l = convert_subscript_in_expr(A_LOPG(expr));
1096 if (DT_ISSCALAR(A_DTYPEG(l)) && DTY(d) == TY_ARRAY) {
1097 return mk_promote_scalar(l, d, A_SHAPEG(expr));
1098 } else {
1099 return mk_convert(l, d);
1100 }
1101 case A_PAREN:
1102 d = A_DTYPEG(expr);
1103 l = convert_subscript_in_expr(A_LOPG(expr));
1104 return mk_paren(l, d);
1105 case A_SUBSTR:
1106 d = A_DTYPEG(expr);
1107 o = convert_subscript_in_expr(A_LOPG(expr));
1108 l = convert_subscript_in_expr(A_LEFTG(expr));
1109 r = convert_subscript_in_expr(A_RIGHTG(expr));
1110 return mk_substr(o, l, r, d);
1111 case A_INTR:
1112 /* some intrinsic calls get shared trees, so make new tree */
1113 /* leave present alone */
1114 if (A_OPTYPEG(expr) == I_PRESENT)
1115 return expr;
1116 nargs = A_ARGCNTG(expr);
1117 newargt = mk_argt(nargs);
1118 argt = A_ARGSG(expr);
1119 for (i = 0; i < nargs; ++i) {
1120 ARGT_ARG(newargt, i) = convert_subscript_in_expr(ARGT_ARG(argt, i));
1121 }
1122 l = mk_func_node(A_INTR, A_LOPG(expr), nargs, newargt);
1123 A_DTYPEP(l, A_DTYPEG(expr));
1124 A_OPTYPEP(l, A_OPTYPEG(expr));
1125 A_SHAPEP(l, A_SHAPEG(expr));
1126 return l;
1127 case A_FUNC:
1128 nargs = A_ARGCNTG(expr);
1129 argt = A_ARGSG(expr);
1130 for (i = 0; i < nargs; ++i) {
1131 ARGT_ARG(argt, i) = convert_subscript_in_expr(ARGT_ARG(argt, i));
1132 }
1133 return expr;
1134 case A_CNST:
1135 case A_CMPLXC:
1136 return expr;
1137 case A_MEM:
1138 case A_ID:
1139 case A_SUBSCR:
1140 if (!A_SHAPEG(expr))
1141 return expr;
1142 expr = convert_subscript(expr);
1143 return expr;
1144 default:
1145 interr("convert_subscript_in_expr: unknown expression", expr, 2);
1146 return expr;
1147 }
1148 }
1149
1150 static LOGICAL
stride1_triple(int triple)1151 stride1_triple(int triple)
1152 {
1153 #if DEBUG
1154 assert(A_TYPEG(triple) == A_TRIPLE, "stride1_triple: not A_TRIPLE", triple,
1155 4);
1156 #endif
1157 if (A_STRIDEG(triple) && A_STRIDEG(triple) != astb.i1 &&
1158 A_STRIDEG(triple) != astb.bnd.one)
1159 return FALSE;
1160 return TRUE;
1161 }
1162
1163 LOGICAL
contiguous_section(int arr_ast)1164 contiguous_section(int arr_ast)
1165 {
1166 int asd;
1167 int ndims, dim;
1168 int astsub;
1169 int sptr;
1170 int ast1;
1171 LOGICAL nonfull = FALSE;
1172
1173 /* only for data references */
1174 if (A_TYPEG(arr_ast) != A_ID && A_TYPEG(arr_ast) != A_SUBSCR &&
1175 A_TYPEG(arr_ast) != A_MEM)
1176 return FALSE;
1177
1178 for (ast1 = arr_ast; A_TYPEG(ast1) == A_MEM || A_TYPEG(ast1) == A_SUBSCR;
1179 ast1 = A_PARENTG(ast1)) {
1180 if (!A_SHAPEG(ast1))
1181 return TRUE; /* everything is contiguous so far and no more subscripting
1182 */
1183 if (A_TYPEG(ast1) == A_MEM) {
1184 /* must be the first and only member */
1185 sptr = A_SPTRG(A_MEMG(ast1));
1186 if (ADDRESSG(sptr) != 0 || SYMLKG(sptr) != NOSYM)
1187 return FALSE;
1188 } else if (A_TYPEG(ast1) == A_SUBSCR) {
1189 /* must be contiguous subscripting */
1190 asd = A_ASDG(ast1);
1191 ndims = ASD_NDIM(asd);
1192 /* Find the 1st non-scalar dimension. */
1193 for (dim = ndims - 1; dim >= 0; --dim) {
1194 int ss = ASD_SUBS(asd, dim);
1195 if (A_TYPEG(ss) == A_TRIPLE)
1196 break;
1197 if (A_SHAPEG(ss))
1198 return FALSE; /* non-triplet shaped subscript */
1199 }
1200 if (dim < 0) {
1201 nonfull = TRUE; /* all parent subscripts must be scalar as well */
1202 } else if (nonfull) {
1203 return FALSE; /* already had a deeper non-full dimension */
1204 } else {
1205 astsub = ASD_SUBS(asd, dim);
1206 sptr = memsym_of_ast(ast1);
1207 if (!stride1_triple(astsub))
1208 return FALSE; /* not-stride-1 */
1209 if (!is_whole_dim(ast1, dim))
1210 nonfull = TRUE;
1211 /* Leading dimensions must be full. */
1212 for (--dim; dim >= 0; --dim) {
1213 if (!is_whole_dim(ast1, dim))
1214 return FALSE;
1215 }
1216 }
1217 }
1218 }
1219 if (A_TYPEG(ast1) != A_ID)
1220 return FALSE;
1221 return TRUE;
1222 }
1223
1224 /* Check if array section is contiguous, does not have to be whole array */
1225 static LOGICAL
contiguous_section_array(int arr_ast)1226 contiguous_section_array(int arr_ast)
1227 {
1228 int asd, ss;
1229 int ndims, dim;
1230 int astsub;
1231 int sptr;
1232 int ast1 = A_TYPEG(arr_ast) == A_MEM ? A_MEMG(arr_ast) : arr_ast;
1233
1234 if (!ast1)
1235 return FALSE;
1236
1237 if (!A_SHAPEG(ast1) || A_TYPEG(ast1) == A_ID)
1238 return TRUE;
1239 asd = A_ASDG(ast1);
1240 ndims = ASD_NDIM(asd);
1241 for (dim = ndims - 1; dim >= 0; dim--) {
1242 ss = ASD_SUBS(asd, dim);
1243 if (A_TYPEG(ss) == A_TRIPLE) {
1244 continue;
1245 }
1246 if (A_TYPEG(ss) == A_SUBSCR) {
1247 if (!is_whole_dim(arr_ast, dim))
1248 return FALSE;
1249 }
1250 if (A_TYPEG(ss) == A_ID && (DTY(A_DTYPEG(ss))) == TY_ARRAY) {
1251 if (!is_whole_dim(arr_ast, dim))
1252 return FALSE;
1253 }
1254 }
1255 return TRUE;
1256 }
1257
1258 static int
extract_shape_from_args(int func_ast)1259 extract_shape_from_args(int func_ast)
1260 {
1261 int funcsptr, iface;
1262 int dscptr;
1263 int dummy_sptr;
1264 int shape = A_SHAPEG(func_ast);
1265 int arg_shape;
1266 int argt;
1267 int nargs;
1268 int i;
1269
1270 funcsptr = procsym_of_ast(A_LOPG(func_ast));
1271 proc_arginfo(funcsptr, NULL, &dscptr, &iface);
1272 nargs = A_ARGCNTG(func_ast);
1273 argt = A_ARGSG(func_ast);
1274 for (i = 0; i < nargs; ++i) {
1275 if (dscptr) {
1276 dummy_sptr = aux.dpdsc_base[dscptr + i];
1277 if (ARGT_ARG(argt, i) == astb.ptr0 && OPTARGG(dummy_sptr)) {
1278 continue;
1279 }
1280 }
1281 arg_shape = A_SHAPEG(ARGT_ARG(argt, i));
1282 /* scalars are always conformable */
1283 if (arg_shape) {
1284 if (shape) {
1285 if (!conform_shape(arg_shape, shape) &&
1286 ((iface && FVALG(iface)) || !dummy_sptr ||
1287 INTENTG(dummy_sptr) != INTENT_IN)) {
1288 error(508, 3, gbl.lineno, SYMNAME(funcsptr), CNULL);
1289 break;
1290 }
1291 } else {
1292 shape = arg_shape;
1293 }
1294 }
1295 }
1296 return shape;
1297 }
1298
1299 static int alloc_char_temp(int, char *, int, int, int);
1300 static int get_charintrin_temp(int, char *);
1301
1302 static struct {
1303 int continue_std, func_std;
1304 } difficult = {0, 0};
1305
1306 void
check_pointer_type(int past,int tast,int stmt,LOGICAL is_sourced_allocation)1307 check_pointer_type(int past, int tast, int stmt, LOGICAL is_sourced_allocation)
1308 {
1309 /* For type pointers, we want to set the type field of its
1310 * descriptor to whatever type we're assigning it to. Used for
1311 * polymorphic entities. The flag argument is set when we call this
1312 * function due to a sourced allocation.
1313 */
1314
1315 int psptr, tsptr, dt1, dt2, desc1, type2;
1316 int newargt, func, astnew, is_inline, intrin_type;
1317 static int tmp = 0;
1318 int nullptr;
1319 bool isNullAssn = false;
1320
1321 if (DT_PTR == DT_INT8)
1322 nullptr = astb.k0;
1323 else
1324 nullptr = astb.i0;
1325 if (A_TYPEG(tast) == A_SUBSCR)
1326 tast = A_LOPG(tast);
1327
1328 dt1 = A_DTYPEG(past);
1329 if (DTY(dt1) == TY_ARRAY) {
1330 dt1 = DTY(dt1 + 1);
1331 }
1332 dt2 = A_DTYPEG(tast);
1333 if (DTY(dt2) == TY_ARRAY) {
1334 dt2 = DTY(dt2 + 1);
1335 }
1336
1337 if (DTY(dt1) != TY_DERIVED) {
1338 return;
1339 }
1340
1341 if (DTY(dt2) != TY_DERIVED) {
1342 if (!UNLPOLYG(DTY(dt1 + 3))) {
1343 return;
1344 }
1345 intrin_type = 1;
1346 } else {
1347 intrin_type = 0;
1348 }
1349
1350 psptr = memsym_of_ast(past);
1351
1352 if (!CLASSG(psptr)) {
1353 return;
1354 }
1355
1356 switch (A_TYPEG(tast)) {
1357 case A_ID:
1358 case A_LABEL:
1359 case A_ENTRY:
1360 case A_SUBSCR:
1361 case A_SUBSTR:
1362 case A_MEM:
1363 tsptr = memsym_of_ast(tast);
1364 break;
1365 case A_INTR:
1366 if (A_OPTYPEG(tast) == I_NULL) {
1367 tsptr = psptr;
1368 isNullAssn = true;
1369 break;
1370 }
1371 default:
1372 return;
1373 }
1374
1375 if (ALLOCDESCG(psptr)) {
1376 desc1 = DESCRG(psptr);
1377 DESCUSEDP(psptr, TRUE);
1378 if (!desc1 || SDSCG(psptr)) {
1379 desc1 = SDSCG(psptr);
1380 }
1381 if (!intrin_type) {
1382 if (CLASSG(tsptr) || (is_sourced_allocation && ALLOCATTRG(tsptr))) {
1383 type2 = get_type_descr_arg(gbl.currsub, tsptr);
1384 } else {
1385 type2 = getccsym('P', tmp++, ST_VAR);
1386 DTYPEP(type2, dt2);
1387 type2 = get_static_type_descriptor(type2);
1388 }
1389 } else {
1390 type2 = dtype_to_arg(dt2);
1391 type2 = mk_cval1(type2, DT_INT);
1392 type2 = mk_unop(OP_VAL, type2, DT_INT);
1393 }
1394
1395 /*
1396 * Beware! If intrin_type is TRUE, 'type2' is the index of an AST (that
1397 * corresponds to the code number of the intrinsic type). But if it's
1398 * false, 'type2' is a symbol table pointer (to a descriptor).
1399 */
1400 if (desc1 && type2 && !XBIT(68, 0x4)) {
1401
1402 if (isNullAssn) {
1403 int src_ast, astnew;
1404 if (intrin_type) {
1405 src_ast = type2;
1406 } else {
1407 type2 = getccsym('P', tmp++, ST_VAR);
1408 DTYPEP(type2, dt2);
1409 type2 = get_static_type_descriptor(type2);
1410 src_ast = mk_id(type2);
1411 }
1412 if (STYPEG(psptr) != ST_MEMBER) {
1413 astnew = mk_set_type_call(mk_id(desc1), src_ast, intrin_type);
1414 } else {
1415 int sdsc_mem = get_member_descriptor(psptr);
1416 int dest_ast = check_member(past, mk_id(sdsc_mem));
1417 astnew = mk_set_type_call(dest_ast, src_ast, intrin_type);
1418 }
1419 add_stmt_after(astnew, stmt);
1420 return;
1421 }
1422
1423 if (STYPEG(psptr) != ST_MEMBER &&
1424 (STYPEG(tsptr) != ST_MEMBER || !CLASSG(tsptr))) {
1425 is_inline = (!intrin_type)
1426 ? inline_RTE_set_type(desc1, type2, stmt, 1, dt2, 0)
1427 : 0;
1428 if (!is_inline) {
1429 int dest_ast = mk_id(desc1);
1430 int src_ast =
1431 intrin_type ? type2 : check_member(dest_ast, mk_id(type2));
1432
1433 gen_set_type(dest_ast, src_ast, stmt, FALSE, intrin_type);
1434 }
1435 } else if ((STYPEG(psptr) == ST_MEMBER && (STYPEG(tsptr) != ST_MEMBER)) ||
1436 !CLASSG(tsptr)) {
1437 int sdsc_mem = get_member_descriptor(psptr);
1438 assert(sdsc_mem > NOSYM, "no descriptor for member", psptr, 3);
1439 is_inline = 0; /* TBD: inline_RTE_set_type( ) */
1440 if (!is_inline) {
1441 int nz_ast, if_ast, ptr_ast;
1442 int dest_ast = check_member(past, mk_id(sdsc_mem));
1443 int src_ast =
1444 intrin_type ? type2 : check_member(dest_ast, mk_id(type2));
1445 astnew = mk_set_type_call(dest_ast, src_ast, intrin_type);
1446 ptr_ast = mk_unop(OP_LOC, A_PARENTG(past), DT_PTR);
1447 nz_ast = mk_binop(OP_NE, ptr_ast, nullptr, DT_LOG);
1448 if_ast = mk_stmt(A_IF, 0);
1449 A_IFEXPRP(if_ast, nz_ast);
1450 A_IFSTMTP(if_ast, astnew);
1451 /* Use add_stmt_after() instead of add_stmt_before() below.
1452 * This appears to be the right thing to do in the event that you
1453 * have something like recordPtr%next => recordPtr2.
1454 * We want to access next's descriptor (embedded in recordPtr),
1455 * but we have to do it before we assign/change recordPtr%next
1456 * address.
1457 */
1458 add_stmt_before(if_ast, stmt);
1459 }
1460 } else if (STYPEG(psptr) != ST_MEMBER && STYPEG(tsptr) == ST_MEMBER) {
1461 int sdsc_mem = get_member_descriptor(tsptr);
1462 assert(sdsc_mem > NOSYM, "no descriptor for member", tsptr, 3);
1463 is_inline = 0; /* TBD: inline_RTE_set_type( ) */
1464 if (!is_inline) {
1465 int nz_ast, if_ast, ptr_ast;
1466 int dest_ast = mk_id(desc1);
1467 int src_ast =
1468 intrin_type
1469 ? type2
1470 : mk_member(A_PARENTG(tast), mk_id(sdsc_mem), A_DTYPEG(tast));
1471 astnew = mk_set_type_call(dest_ast, src_ast, intrin_type);
1472
1473 /* if (tast .ne. 0) */
1474
1475 ptr_ast = mk_unop(OP_LOC, A_PARENTG(tast), DT_PTR);
1476 nz_ast = mk_binop(OP_NE, ptr_ast, nullptr, DT_LOG);
1477 if_ast = mk_stmt(A_IF, 0);
1478 A_IFEXPRP(if_ast, nz_ast);
1479 A_IFSTMTP(if_ast, astnew);
1480 /* Use add_stmt_after() instead of add_stmt_before() below.
1481 * This appears to be the right thing to do in the event that you
1482 * have something like recordPtr => recordPtr%next. We want to
1483 * access next's descriptor (embedded in recordPtr), but we have to
1484 * do it before we assign/change recordPtr's address.
1485 */
1486 add_stmt_before(if_ast, stmt);
1487 }
1488 } else {
1489 int sdsc_mem = get_member_descriptor(tsptr);
1490 int sdsc_mem2 = get_member_descriptor(psptr);
1491 assert(sdsc_mem > NOSYM, "no descriptor for member", tsptr, 3);
1492 assert(sdsc_mem2 > NOSYM, "no descriptor for member", psptr, 3);
1493 is_inline = 0; /* TBD: inline_RTE_set_type( ) */
1494 if (!is_inline) {
1495 int nz_ast, if_ast, ptr_ast;
1496 int dest_ast =
1497 mk_member(A_PARENTG(past), mk_id(sdsc_mem2), A_DTYPEG(past));
1498 int src_ast =
1499 intrin_type
1500 ? type2
1501 : mk_member(A_PARENTG(tast), mk_id(sdsc_mem), A_DTYPEG(tast));
1502 astnew = mk_set_type_call(dest_ast, src_ast, intrin_type);
1503
1504 /* if (tast .ne. 0) */
1505 ptr_ast = mk_unop(OP_LOC, A_PARENTG(tast), DT_PTR);
1506 nz_ast = mk_binop(OP_NE, ptr_ast, nullptr, DT_LOG);
1507 if_ast = mk_stmt(A_IF, 0);
1508 A_IFEXPRP(if_ast, nz_ast);
1509 A_IFSTMTP(if_ast, astnew);
1510 /* Use add_stmt_after() instead of add_stmt_before() below.
1511 * This appears to be the right thing to do in the event that you
1512 * have something like recordPtr%next => recordPtr%next%next.
1513 * We want to access next's descriptor (embedded in recordPtr),
1514 * but we have to do it before we assign/change recordPtr%next
1515 * address.
1516 */
1517 add_stmt_before(if_ast, stmt);
1518 }
1519 }
1520 }
1521 }
1522
1523 if (!is_sourced_allocation && POINTERG(psptr) && UNLPOLYG(DTY(dt1 + 3)) &&
1524 UNLPOLYG(DTY(dt2 + 3)) && SDSCG(psptr) && SDSCG(tsptr)) {
1525 /* init unlimited polymorphic descriptor for pointer.
1526 * We do not have to do this for the sourced allocation case since
1527 * the sourced allocation case is handled in semant3.c with the
1528 * ALLOCATE productions.
1529 */
1530 int psdsc, tsdsc, dest_sdsc_ast, src_sdsc_ast;
1531 int fsptr, argt, val, ast;
1532 if (STYPEG(psptr) == ST_MEMBER) {
1533 psdsc = get_member_descriptor(psptr);
1534 } else {
1535 psdsc = SDSCG(psptr);
1536 }
1537 assert(psdsc > NOSYM, "no descriptor for psptr", psptr, 3);
1538 if (STYPEG(tsptr) == ST_MEMBER) {
1539 tsdsc = get_member_descriptor(tsptr);
1540 } else {
1541 tsdsc = SDSCG(tsptr);
1542 }
1543 assert(tsdsc > NOSYM, "no descriptor for tsptr", tsptr, 3);
1544 fsptr = sym_mkfunc_nodesc(mkRteRtnNm(RTE_init_unl_poly_desc), DT_NONE);
1545 dest_sdsc_ast = check_member(past, mk_id(psdsc));
1546 src_sdsc_ast = check_member(tast, mk_id(tsdsc));
1547
1548 argt = mk_argt(3);
1549 ARGT_ARG(argt, 0) = dest_sdsc_ast;
1550 ARGT_ARG(argt, 1) = src_sdsc_ast;
1551 val = mk_cval1(43, DT_INT);
1552 val = mk_unop(OP_VAL, val, DT_INT);
1553 ARGT_ARG(argt, 2) = val;
1554 ast = mk_id(fsptr);
1555 ast = mk_func_node(A_CALL, ast, 3, argt);
1556 add_stmt_after(ast, stmt);
1557 }
1558 }
1559
1560 /* Given one of the arguments to move_alloc (either from or to), return the
1561 * corresponding symbol and pointer to the arg. */
1562 static void
move_alloc_arg(int arg,SPTR * sptr,int * pvar)1563 move_alloc_arg(int arg, SPTR *sptr, int *pvar)
1564 {
1565 if (A_TYPEG(arg) == A_ID)
1566 *sptr = A_SPTRG(arg);
1567 else if (A_TYPEG(arg) == A_MEM)
1568 *sptr = A_SPTRG(A_MEMG(arg));
1569 else
1570 *sptr = 0;
1571
1572 if (MIDNUMG(*sptr)) {
1573 *pvar = check_member(arg, mk_id(MIDNUMG(*sptr)));
1574 } else if (!ALLOCATTRG(*sptr)) {
1575 error(507, ERR_Fatal, gbl.lineno, SYMNAME(*sptr), 0);
1576 } else {
1577 *pvar = mk_unop(OP_LOC, mk_id(*sptr), DT_PTR);
1578 }
1579 }
1580
1581 void
check_alloc_ptr_type(int psptr,int stmt,DTYPE dt1,int flag,LOGICAL after,int past,int astmem)1582 check_alloc_ptr_type(int psptr, int stmt, DTYPE dt1, int flag, LOGICAL after,
1583 int past, int astmem)
1584 {
1585 /* For allocatable/pointer objects, we assign a type to its dynamic type.
1586 * The psptr is the sptr of the allocatable/pointer object.
1587 * The stmt arg is the current statement to insert the type assign.
1588 * The typespec is the dynamic type. If it's 0, we assign the object's
1589 * declared type to its dynamic type.
1590 * The flag arg is set when we want to assign type to psptr's descriptor. It's
1591 * also set to 2 when psptr is used as an actual arg passed to a unlimited
1592 * polymorphic argument.
1593 * If flag is not set, then we just want to reserve space for type in
1594 * psptr's descriptor.
1595 * The after flag is set when we want to insert the type assignment after
1596 * the current statement. If it's 0, then we insert it before current stmt.
1597 */
1598
1599 LOGICAL intrin_type;
1600 LOGICAL no_alloc_ptr = FALSE;
1601
1602 if (dt1 <= DT_NONE)
1603 dt1 = DTYPEG(psptr);
1604 if (is_array_dtype(dt1))
1605 dt1 = array_element_dtype(dt1);
1606 intrin_type = DTY(dt1) != TY_DERIVED;
1607
1608 if (!ALLOCDESCG(psptr) && !is_array_dtype(DTYPEG(psptr))) {
1609 if (!SDSCG(psptr) || DTY(DTYPEG(psptr)) == TY_DERIVED) {
1610 set_descriptor_rank(TRUE);
1611 get_static_descriptor(psptr);
1612 set_descriptor_rank(FALSE);
1613 ALLOCDESCP(psptr, TRUE);
1614 no_alloc_ptr = TRUE;
1615 } else if (flag == 2 && (ALLOCATTRG(psptr) || POINTERG(psptr))) {
1616 /* allocatable or pointer actual and unlimited polymorphic dummy */
1617 set_descriptor_rank(TRUE);
1618 get_static_descriptor(psptr);
1619 set_descriptor_rank(FALSE);
1620 if (ALLOCATTRG(psptr))
1621 ALLOCDESCP(psptr, TRUE);
1622 }
1623 }
1624
1625 if (intrin_type) {
1626 DTYPE dt2 = DTYPEG(psptr);
1627 if (is_array_dtype(dt2))
1628 dt2 = array_element_dtype(dt2);
1629 if (flag != 2 && (DTY(dt2) != TY_DERIVED || !UNLPOLYG(DTY(dt2 + 3)))) {
1630 /* ignore non-derived type and unlimited polymorphic objects
1631 * unless flag is set to 2.
1632 */
1633 flag = 0;
1634 }
1635 /* otherwise we are allocating an intrinsic type to an unlimited polymorphic
1636 * object */
1637 }
1638
1639 if (flag != 0 && (ALLOCDESCG(psptr) || intrin_type)) {
1640 int desc1_sptr = 0;
1641 LOGICAL is_member = past && STYPEG(psptr) == ST_MEMBER &&
1642 (CLASSG(psptr) || FINALIZEDG(psptr));
1643 if (is_member) {
1644 /* copy type into member type descriptor.*/
1645 desc1_sptr = get_member_descriptor(psptr);
1646 } else {
1647 desc1_sptr = SDSCG(psptr);
1648 if (!desc1_sptr)
1649 desc1_sptr = DESCRG(psptr);
1650 if (desc1_sptr)
1651 DESCUSEDP(psptr, TRUE);
1652 }
1653 if (desc1_sptr) {
1654 int newargt = 0;
1655 int type2_sptr = 0, type2_ast = 0;
1656 if (intrin_type) {
1657 type2_ast = mk_cval1(dtype_to_arg(dt1), DT_INT);
1658 type2_ast = mk_unop(OP_VAL, type2_ast, DT_INT);
1659 } else {
1660 static int tmp = 0;
1661 type2_sptr = getccsym('A', tmp++, ST_VAR);
1662 DTYPEP(type2_sptr, dt1);
1663 type2_sptr = get_static_type_descriptor(type2_sptr);
1664 if (type2_sptr > NOSYM)
1665 type2_ast = mk_id(type2_sptr);
1666 }
1667 if (is_member ||
1668 (type2_ast && !XBIT(68, 0x4) &&
1669 (intrin_type || !inline_RTE_set_type(desc1_sptr, type2_sptr, stmt,
1670 after, dt1, astmem)))) {
1671 int desc1_ast = get_desc_tag(desc1_sptr);
1672 int tagdesc = get_desc_tag(desc1_sptr);
1673 if (is_member) {
1674 desc1_ast = check_member(past, desc1_ast);
1675 tagdesc = check_member(past, tagdesc);
1676
1677 } else if (astmem) {
1678 desc1_ast = check_member(astmem, desc1_ast);
1679 tagdesc = check_member(astmem, tagdesc);
1680 }
1681 stmt = gen_set_type(desc1_ast, type2_ast, stmt, !after, intrin_type);
1682 if (no_alloc_ptr) {
1683 int tag = mk_isz_cval(intrin_type ? __TAGPOLY : __TAGDESC, DT_INT);
1684 int astnew = mk_assn_stmt(tagdesc, tag, 0);
1685 stmt = add_stmt_before(astnew, stmt);
1686 }
1687 }
1688 }
1689 }
1690 }
1691
1692 /* if argument(s) is non-member allocatable, ALLOCDESC must be
1693 * set because RTE_sect2 can be called, then full descriptor must
1694 * be passed. They can be arguments to other routine before matmul
1695 * and can be allocated in the subroutine.
1696 */
1697 static void
check_arg_isalloc(int arg)1698 check_arg_isalloc(int arg)
1699 {
1700 int lop;
1701 int sptr = 0;
1702 if (A_TYPEG(arg) == A_SUBSCR) {
1703 lop = A_LOPG(arg);
1704 if (A_TYPEG(lop) == A_ID)
1705 sptr = A_SPTRG(lop);
1706 } else if (A_TYPEG(arg) == A_ID) {
1707 sptr = A_SPTRG(arg);
1708 }
1709 if (sptr && ALLOCATTRG(sptr)) {
1710 ALLOCDESCP(sptr, 1);
1711 }
1712 }
1713
1714 static int forall_indx[MAXSUBS];
1715
1716 static LOGICAL
id_dep_in_forall_idxlist(int ast)1717 id_dep_in_forall_idxlist(int ast)
1718 {
1719 int i;
1720
1721 for (i = 0; forall_indx[i] && i < MAXSUBS; i++) {
1722 if (A_SPTRG(ast) == forall_indx[i]) {
1723 return TRUE;
1724 }
1725 }
1726 return 0;
1727 }
1728
1729 static LOGICAL
_arg_forall_depnd(int ast,int * is_dep)1730 _arg_forall_depnd(int ast, int *is_dep)
1731 {
1732 if (A_TYPEG(ast) == A_ID) {
1733 *is_dep = id_dep_in_forall_idxlist(ast);
1734 return TRUE;
1735 }
1736
1737 return FALSE;
1738 }
1739
1740 static void
init_idx_list(int forall)1741 init_idx_list(int forall)
1742 {
1743 int triplet_list;
1744 int i;
1745
1746 for (i = 0; i < MAXSUBS; i++)
1747 forall_indx[i] = 0;
1748
1749 triplet_list = A_LISTG(forall);
1750 for (i = 0; i < MAXSUBS && triplet_list;
1751 i++, triplet_list = ASTLI_NEXT(triplet_list)) {
1752 forall_indx[i] = ASTLI_SPTR(triplet_list);
1753 }
1754 }
1755
1756 static LOGICAL
charintr_arg_forall_depnd(int ast_arg)1757 charintr_arg_forall_depnd(int ast_arg)
1758 {
1759 LOGICAL is_dep = FALSE;
1760 int asd;
1761 int ndims;
1762 int i;
1763
1764 if (A_TYPEG(ast_arg) != A_SUBSCR) {
1765 return FALSE;
1766 }
1767
1768 init_idx_list(STD_AST(arg_gbl.std));
1769
1770 asd = A_ASDG(ast_arg);
1771 ndims = ASD_NDIM(asd);
1772 for (i = 0; i < ndims && !is_dep; i++) {
1773 ast_visit(1, 1);
1774 ast_traverse(ASD_SUBS(asd, i), _arg_forall_depnd, NULL, &is_dep);
1775 ast_unvisit();
1776 }
1777 return is_dep;
1778 }
1779
1780 /** \brief func_ast is a function or intrinsic call. If it is a
1781 transformational intrinsic, create an appropriate temp, rewrite, and return
1782 a load of that temp.
1783 For now, don't do anything with user-defined functions.
1784 \param func_ast A_INTR, A_FUNC, or A_ICALL
1785 \param func_args rewritten args for the function
1786 \param lhs ast for lhs (temp) if non-zero
1787
1788 If lhs is non-zero, check lhs to see if it is OK for the intended
1789 use; if so, return 0.
1790 */
1791 static int
rewrite_func_ast(int func_ast,int func_args,int lhs)1792 rewrite_func_ast(int func_ast, int func_args, int lhs)
1793 {
1794 int shape = A_SHAPEG(func_ast);
1795 DTYPE dtype = A_DTYPEG(func_ast);
1796 int dim, ndims, cdim;
1797 int shift;
1798 int newsym;
1799 int temp_arr;
1800 int newargt;
1801 int srcarray;
1802 int rank;
1803 int retval = 0;
1804 int ast;
1805 int nargs;
1806 int mask;
1807 int value;
1808 LOGICAL back;
1809 int is_back_true;
1810 int vector;
1811 FtnRtlEnum rtlRtn;
1812 char *root;
1813 int i;
1814 int subscr[MAXSUBS];
1815 int sptr;
1816 int astnew;
1817 int temp_sptr;
1818 LOGICAL is_icall; /* iff its first arg is changable */
1819 int ast_from_len = 0;
1820 int arg1;
1821 int dtnew;
1822 LOGICAL forall_depnd_intrin;
1823 const int type = A_TYPEG(func_ast);
1824 const int optype = A_OPTYPEG(func_ast);
1825
1826 /* it only handles calls */
1827 if (type != A_INTR && type != A_FUNC && type != A_ICALL) {
1828 return func_ast;
1829 }
1830 if (type == A_FUNC) {
1831 if (elemental_func_call(func_ast)) {
1832 shape = extract_shape_from_args(func_ast);
1833 }
1834 goto ret_norm;
1835 }
1836 if (type == A_ICALL) {
1837 switch (optype) {
1838 case I_MOVE_ALLOC:
1839 transform_move_alloc(func_ast, func_args);
1840 return -1;
1841 case I_MVBITS:
1842 transform_mvbits(func_ast, func_args);
1843 return -1;
1844 case I_MERGE:
1845 transform_merge(func_ast, func_args);
1846 return -1;
1847 case I_NULLIFY:
1848 return -1;
1849 #ifdef I_C_F_POINTER
1850 case I_C_F_POINTER:
1851 transform_c_f_pointer(func_ast, func_args);
1852 return -1;
1853 #endif
1854 #ifdef I_C_F_POINTER
1855 case I_C_F_PROCPOINTER:
1856 transform_c_f_procpointer(func_ast, func_args);
1857 return -1;
1858 #endif
1859 }
1860 }
1861 if (type == A_INTR && optype == I_ASSOCIATED) {
1862 return transform_associated(arg_gbl.std, func_ast);
1863 }
1864
1865 if (type == A_INTR) {
1866 switch (optype) {
1867 case I_ADJUSTL: /* adjustl(string) */
1868 case I_ADJUSTR: /* adjustr(string) */
1869 if (STYPEG(A_SPTRG(A_LOPG(func_ast))) == ST_PD)
1870 /* it's an IK_ELEMENTAL, but needs special processing */
1871 break;
1872 /*
1873 * ADJUSTL/ADJUSTR has been replaced, so this A_INTR
1874 * is just a function call
1875 */
1876 goto ret_norm;
1877 default:
1878 if (INKINDG(A_SPTRG(A_LOPG(func_ast))) == IK_ELEMENTAL)
1879 goto ret_norm;
1880 }
1881 }
1882 is_icall = TRUE;
1883 switch (optype) {
1884 case I_NUMBER_OF_PROCESSORS:
1885 retval = mk_id(sym_mknproc());
1886 A_DTYPEP(retval, DT_INT);
1887 A_SHAPEP(retval, 0);
1888 return retval;
1889 case I_ALL: /* all(mask, [dim]) */
1890 case I_ANY: /* any(mask, [dim]) */
1891 case I_COUNT: /* count(mask, [dim]) */
1892 srcarray = ARGT_ARG(func_args, 0);
1893 dim = ARGT_ARG(func_args, 1);
1894
1895 /* check dim range if constant */
1896 cdim = -1;
1897 if (dim != 0 && A_TYPEG(dim) == A_CNST) {
1898 cdim = get_int_cval(A_SPTRG(A_ALIASG(dim)));
1899 if (A_SHAPEG(srcarray) &&
1900 ((int)SHD_NDIM(A_SHAPEG(srcarray)) < cdim || 1 > cdim))
1901 error(505, 3, gbl.lineno, SYMNAME(A_SPTRG(A_LOPG(func_ast))), CNULL);
1902 }
1903
1904 if (shape == 0 && (dim == 0 || cdim != -1)) {
1905 /*E.g., pghpf_anys(result, mask) */
1906 rtlRtn =
1907 optype == I_ALL ? RTE_alls : optype == I_ANY ? RTE_anys : RTE_counts;
1908 nargs = 2;
1909 } else {
1910 /* E.g., pghpf_any(result, mask, dim) */
1911 rtlRtn =
1912 optype == I_ALL ? RTE_all : optype == I_ANY ? RTE_any : RTE_count;
1913 nargs = 3;
1914 }
1915 newargt = mk_argt(nargs);
1916 if (dim == 0) {
1917 dim = mk_cval(0, DT_INT);
1918 }
1919 ARGT_ARG(newargt, 1) = srcarray;
1920 if (nargs == 3) {
1921 ARGT_ARG(newargt, 2) = dim;
1922 }
1923 goto ret_new;
1924 case I_PRODUCT: /* product(array, [dim, mask]) */
1925 case I_SUM: /* sum(array, [dim, mask]) */
1926 mask = ARGT_ARG(func_args, 2);
1927
1928 srcarray = ARGT_ARG(func_args, 0);
1929 dim = ARGT_ARG(func_args, 1);
1930
1931 /* check dim range if constant */
1932 cdim = -1;
1933 if (dim != 0 && A_TYPEG(dim) == A_CNST) {
1934 cdim = get_int_cval(A_SPTRG(A_ALIASG(dim)));
1935 if (A_SHAPEG(srcarray) &&
1936 ((int)SHD_NDIM(A_SHAPEG(srcarray)) < cdim || 1 > cdim))
1937 error(505, 3, gbl.lineno, SYMNAME(A_SPTRG(A_LOPG(func_ast))), CNULL);
1938 if (!XBIT(47, 0x80) && !XBIT(70, 0x1000000) && cdim == 1 && mask == 0) {
1939 /* Other than meeting the usual requirements, continue with
1940 * transforming the call if we inhibit inlining reductions
1941 * controlled by XBIT(47,0x80); otherwise, an ICE,
1942 * "rewrite_func_ast: bad dim for sum/prod" will occur
1943 * in an ensuing call
1944 */
1945 return func_ast;
1946 }
1947 }
1948 if (mask == 0) {
1949 mask = mk_cval(1, DT_LOG);
1950 }
1951
1952 if (shape == 0 && (dim == 0 || cdim != -1)) {
1953 /* E.g,. pghpf_sums(result, array, mask) */
1954 rtlRtn = optype == I_PRODUCT ? RTE_products : RTE_sums;
1955 nargs = 3;
1956 } else {
1957 /* E.g., pghpf_sum(result, array, mask, dim) */
1958 rtlRtn = optype == I_PRODUCT ? RTE_product : RTE_sum;
1959 nargs = 4;
1960 }
1961
1962 newargt = mk_argt(nargs);
1963 ARGT_ARG(newargt, 1) = srcarray;
1964 mask = misalignment(srcarray, mask, arg_gbl.std);
1965 ARGT_ARG(newargt, 2) = mask;
1966 if (nargs == 4) {
1967 assert(dim != 0, "rewrite_func_ast: bad dim for sum/prod", func_ast, 4);
1968 ARGT_ARG(newargt, 3) = dim;
1969 }
1970 goto ret_new;
1971 case I_NORM2: /* norm2(array, [dim]) */
1972 srcarray = ARGT_ARG(func_args, 0);
1973 dim = ARGT_ARG(func_args, 1);
1974 rank = get_ast_rank(srcarray);
1975 shape = dim ? A_SHAPEG(srcarray) : 0;
1976
1977 // If dim is supplied for a one dimensional array, result is still a scalar.
1978 shape = (shape && (rank == 1)) ? 0 : shape;
1979
1980 if (dim == 0) {
1981 rtlRtn = RTE_norm2_nodim;
1982 nargs = 3;
1983 } else {
1984 rtlRtn = RTE_norm2;
1985 nargs = 4;
1986 }
1987 newargt = mk_argt(nargs);
1988 ARGT_ARG(newargt, 1) = srcarray;
1989
1990 if (!flg.ieee) { // fast. Currently also mapped to relaxed
1991 ARGT_ARG(newargt, 2) = mk_cval(1, DT_INT4);
1992 } else { // Precise
1993 ARGT_ARG(newargt, 2) = mk_cval(2, DT_INT4);
1994 }
1995
1996 if (nargs == 4) {
1997 ARGT_ARG(newargt, 3) = dim;
1998 }
1999 goto ret_new;
2000 case I_MAXVAL: /* maxval(array, [dim, mask]) */
2001 case I_MINVAL: /* minval(array, [dim, mask]) */
2002 mask = ARGT_ARG(func_args, 2);
2003 srcarray = ARGT_ARG(func_args, 0);
2004 dim = ARGT_ARG(func_args, 1);
2005
2006 if (mask == 0) {
2007 mask = mk_cval(1, DT_LOG);
2008 }
2009 mask = misalignment(srcarray, mask, arg_gbl.std);
2010
2011 if (dim == 0) {
2012 rtlRtn = optype == I_MAXVAL ? RTE_maxvals : RTE_minvals;
2013 nargs = 3;
2014 } else {
2015 rtlRtn = optype == I_MAXVAL ? RTE_maxval : RTE_minval;
2016 nargs = 4;
2017 }
2018 newargt = mk_argt(nargs);
2019 ARGT_ARG(newargt, 1) = srcarray;
2020 ARGT_ARG(newargt, 2) = mask;
2021 if (nargs == 4) {
2022 ARGT_ARG(newargt, 3) = dim;
2023 }
2024 goto ret_new;
2025 case I_CSHIFT: /* cshift(array, shift, [dim]) */
2026 if (A_SHAPEG(ARGT_ARG(func_args, 1)))
2027 goto unch;
2028 dim = ARGT_ARG(func_args, 2);
2029 if (dim == 0)
2030 dim = mk_cval(1, DT_INT);
2031 if (A_TYPEG(dim) != A_CNST)
2032 goto unch;
2033 /* don't inline forall(i=1:n) a(i,:) = cshift(b(i,:)) */
2034
2035 if (!arg_gbl.inforall &&
2036 is_inline_overlap_shifts(func_ast, func_args, lhs))
2037 goto ret_norm;
2038 if (!is_no_comm_shift(func_ast, func_args))
2039 goto unch;
2040 if (arg_gbl.inforall)
2041 goto unch;
2042 /* the following can inline cshift and eoshift
2043 * (without no_comm or comm restriction )
2044 * but it is restricted no_comm shift for performance reason only
2045 */
2046
2047 assert(shape != 0, "expected non-zero shape", 0, ERR_Fatal);
2048 /* need to put this into a temp */
2049 temp_arr = mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1), lhs,
2050 &retval);
2051 if (temp_arr != 0) {
2052 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, 0);
2053 mk_mem_deallocate(mk_id(temp_arr), arg_gbl.std);
2054 }
2055 inline_shifts(func_ast, func_args, retval);
2056 return temp_arr == 0 && lhs != 0 ? 0 : retval;
2057
2058 unch:
2059 srcarray = ARGT_ARG(func_args, 0);
2060 dim = ARGT_ARG(func_args, 2);
2061 if (dim == 0)
2062 dim = mk_cval(1, DT_INT);
2063 shift = ARGT_ARG(func_args, 1);
2064 nargs = 4;
2065 if (A_SHAPEG(shift) == 0) {
2066 shift = convert_int(shift, astb.bnd.dtype);
2067 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_cshiftsca : RTE_cshifts;
2068 } else {
2069 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_cshiftca : RTE_cshift;
2070 }
2071 newargt = mk_argt(nargs);
2072 ARGT_ARG(newargt, 1) = srcarray;
2073 ARGT_ARG(newargt, 2) = shift;
2074 ARGT_ARG(newargt, 3) = convert_int(dim, astb.bnd.dtype);
2075 goto ret_new;
2076
2077 case I_DOT_PRODUCT: /* dot_product(vector_a, vector_b) */
2078 nargs = 3;
2079 rtlRtn = RTE_dotpr;
2080 newargt = mk_argt(nargs);
2081 srcarray = ARGT_ARG(func_args, 0);
2082 ARGT_ARG(newargt, 1) = srcarray;
2083 ARGT_ARG(newargt, 2) = ARGT_ARG(func_args, 1);
2084 goto ret_new;
2085 case I_EOSHIFT: /* eoshift(array, shift, [boundary, dim]); */
2086 if (A_SHAPEG(ARGT_ARG(func_args, 1)))
2087 goto eoshiftcall; /* shift not a scalar */
2088
2089 if (!arg_gbl.inforall &&
2090 is_inline_overlap_shifts(func_ast, func_args, lhs))
2091 goto ret_norm;
2092
2093 if (!is_no_comm_shift(func_ast, func_args))
2094 goto eoshiftcall;
2095 if (A_TYPEG(ARGT_ARG(func_args, 3)) != A_CNST)
2096 goto eoshiftcall;
2097 if (arg_gbl.inforall)
2098 goto eoshiftcall;
2099 /* the following can inline cshift and eoshift
2100 * (without no_comm or comm restriction )
2101 * but it is restricted no_comm shift for performance reason only
2102 */
2103
2104 if (shape) {
2105 /* need to put this into a temp */
2106 temp_arr = mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1),
2107 lhs, &retval);
2108 if (temp_arr != 0) {
2109 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, 0);
2110 mk_mem_deallocate(mk_id(temp_arr), arg_gbl.std);
2111 }
2112 }
2113 inline_shifts(func_ast, func_args, retval);
2114 return temp_arr == 0 && lhs != 0 ? 0 : retval;
2115
2116 eoshiftcall:
2117 srcarray = ARGT_ARG(func_args, 0);
2118 dim = ARGT_ARG(func_args, 3);
2119 if (dim == 0)
2120 dim = mk_cval(1, DT_INT);
2121 nargs = 5;
2122 shift = ARGT_ARG(func_args, 1);
2123 if (A_SHAPEG(shift) == 0) {
2124 /* shift is scalar */
2125 shift = convert_int(shift, astb.bnd.dtype);
2126 /* boundary is... */
2127 if (ARGT_ARG(func_args, 2) == 0) { /* absent */
2128 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_eoshiftszca : RTE_eoshiftsz;
2129 --nargs;
2130 } else if (A_SHAPEG(ARGT_ARG(func_args, 2)) == 0) /* scalar */
2131 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_eoshiftssca : RTE_eoshiftss;
2132 else /* array */
2133 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_eoshiftsaca : RTE_eoshiftsa;
2134 } else {
2135 /* shift is array */
2136 /* boundary is... */
2137 if (ARGT_ARG(func_args, 2) == 0) { /* absent */
2138 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_eoshiftzca : RTE_eoshiftz;
2139 --nargs;
2140 } else if (A_SHAPEG(ARGT_ARG(func_args, 2)) == 0) /* scalar */
2141 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_eoshiftsca : RTE_eoshifts;
2142 else /* array */
2143 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_eoshiftca : RTE_eoshift;
2144 }
2145 newargt = mk_argt(nargs);
2146 ARGT_ARG(newargt, 1) = srcarray;
2147 ARGT_ARG(newargt, 2) = shift;
2148 ARGT_ARG(newargt, 3) = convert_int(dim, astb.bnd.dtype);
2149 if (nargs == 5)
2150 ARGT_ARG(newargt, 4) = ARGT_ARG(func_args, 2);
2151 goto ret_new;
2152 case I_MATMUL: /* matmul(matrix_a, matrix_b) */
2153 case I_MATMUL_TRANSPOSE: /* matmul((transpose(matrix_a), matrix_b) */
2154 return matmul(func_ast, func_args, lhs);
2155 case I_FINDLOC: /* minloc(array, [dim, mask]) */
2156 srcarray = ARGT_ARG(func_args, 0);
2157 value = ARGT_ARG(func_args, 1);
2158 back = ARGT_ARG(func_args, 4);
2159 mask = ARGT_ARG(func_args, 3);
2160 mask = misalignment(srcarray, mask, arg_gbl.std);
2161 if (mask == 0)
2162 mask = mk_cval(1, DT_LOG);
2163 dim = ARGT_ARG(func_args, 2);
2164
2165 if (DTY(A_DTYPEG(value)) == TY_CHAR || DTY(A_DTYPEG(value)) == TY_NCHAR) {
2166 temp_sptr = memsym_of_ast(value);
2167 /* e.g., pghpf_any(result, mask, dim) */
2168 if (dim == 0) {
2169 newsym = sym_mkfunc(mkRteRtnNm(RTE_findlocstrs), DT_NONE);
2170 nargs = 6;
2171 /* scalar findloc, result must be replicated */
2172 /* get the temp and add the necessary statements */
2173 temp_arr = mk_maxloc_sptr(
2174 shape, DDTG(dtype) == DT_INT8 ? DT_INT8 : astb.bnd.dtype);
2175 retval = mk_id(temp_arr);
2176 /* add args */
2177 newargt = mk_argt(nargs);
2178 ARGT_ARG(newargt, 0) = retval;
2179 ARGT_ARG(newargt, 1) = srcarray;
2180 ARGT_ARG(newargt, 2) = value;
2181 ARGT_ARG(newargt, 3) = size_ast(temp_sptr, DTYPEG(temp_sptr));
2182 ARGT_ARG(newargt, 4) = mask;
2183 ARGT_ARG(newargt, 5) = back;
2184 goto ret_call;
2185 } else {
2186 /* pghpf_findloc(result, array, mask, dim) */
2187 rtlRtn = RTE_findlocstr;
2188 nargs = 7;
2189 newargt = mk_argt(nargs);
2190 ARGT_ARG(newargt, 1) = srcarray;
2191 ARGT_ARG(newargt, 2) = value;
2192 ARGT_ARG(newargt, 3) = size_ast(temp_sptr, DTYPEG(temp_sptr));
2193 ARGT_ARG(newargt, 4) = mask;
2194 ARGT_ARG(newargt, 5) = dim;
2195 ARGT_ARG(newargt, 6) = back;
2196 goto ret_new;
2197 }
2198 } else {
2199 if (dim == 0) {
2200 nargs = 5;
2201 newsym = sym_mkfunc(mkRteRtnNm(RTE_findlocs), DT_NONE);
2202 /* scalar findloc, result must be replicated */
2203 /* get the temp and add the necessary statements */
2204 temp_arr = mk_maxloc_sptr(
2205 shape, DDTG(dtype) == DT_INT8 ? DT_INT8 : astb.bnd.dtype);
2206 retval = mk_id(temp_arr);
2207 /* add args */
2208 newargt = mk_argt(nargs);
2209 ARGT_ARG(newargt, 0) = retval;
2210 ARGT_ARG(newargt, 1) = srcarray;
2211 ARGT_ARG(newargt, 2) = value;
2212 ARGT_ARG(newargt, 3) = mask;
2213 ARGT_ARG(newargt, 4) = back;
2214 goto ret_call;
2215 } else {
2216 /* pghpf_findloc(result, array, mask, dim) */
2217 rtlRtn = RTE_findloc;
2218 nargs = 6;
2219 newargt = mk_argt(nargs);
2220 ARGT_ARG(newargt, 1) = srcarray;
2221 ARGT_ARG(newargt, 2) = value;
2222 ARGT_ARG(newargt, 3) = mask;
2223 ARGT_ARG(newargt, 4) = dim;
2224 ARGT_ARG(newargt, 5) = back;
2225 goto ret_new;
2226 }
2227 }
2228
2229 case I_MAXLOC: /* maxloc(array, [dim, mask]) */
2230 case I_MINLOC: /* minloc(array, [dim, mask]) */
2231 srcarray = ARGT_ARG(func_args, 0);
2232 back = ARGT_ARG(func_args, 3);
2233 is_back_true = get_int_cval(sym_of_ast(back));
2234 mask = ARGT_ARG(func_args, 2);
2235 mask = misalignment(srcarray, mask, arg_gbl.std);
2236 if (mask == 0)
2237 mask = mk_cval(1, DT_LOG);
2238 dim = ARGT_ARG(func_args, 1);
2239 if (dim == 0) {
2240 if (is_back_true) {
2241 rtlRtn = optype == I_MAXLOC ? RTE_maxlocs_b : RTE_minlocs_b;
2242 } else {
2243 rtlRtn = optype == I_MAXLOC ? RTE_maxlocs : RTE_minlocs;
2244 }
2245 newsym = sym_mkfunc(mkRteRtnNm(rtlRtn), DT_NONE);
2246 nargs = is_back_true ? 4 : 3;
2247 /* get the temp and add the necessary statements */
2248 temp_arr = mk_maxloc_sptr(shape, DDTG(dtype) == DT_INT8 ? DT_INT8
2249 : astb.bnd.dtype);
2250 retval = mk_id(temp_arr);
2251 /* add args */
2252 newargt = mk_argt(nargs);
2253 ARGT_ARG(newargt, 0) = retval;
2254 ARGT_ARG(newargt, 1) = srcarray;
2255 ARGT_ARG(newargt, 2) = mask;
2256 if (is_back_true)
2257 ARGT_ARG(newargt, 3) = back;
2258 goto ret_call;
2259 } else {
2260 /* pghpf_minloc(result, array, mask, dim) */
2261 if (is_back_true) {
2262 rtlRtn = optype == I_MAXLOC ? RTE_maxloc_b : RTE_minloc_b;
2263 } else {
2264 rtlRtn = optype == I_MAXLOC ? RTE_maxloc : RTE_minloc;
2265 }
2266 nargs = is_back_true ? 5 : 4;
2267 newargt = mk_argt(nargs);
2268 ARGT_ARG(newargt, 1) = srcarray;
2269 ARGT_ARG(newargt, 2) = mask;
2270 ARGT_ARG(newargt, 3) = dim;
2271 if (is_back_true)
2272 ARGT_ARG(newargt, 4) = back;
2273 goto ret_new;
2274 }
2275 case I_PACK: /* pack(array, mask, [vector]) */
2276 srcarray = ARGT_ARG(func_args, 0);
2277 mask = ARGT_ARG(func_args, 1);
2278 vector = ARGT_ARG(func_args, 2);
2279
2280 if (vector == 0) {
2281 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_packzca : RTE_packz;
2282 } else {
2283 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_packca : RTE_pack;
2284 }
2285
2286 if (mask == 0)
2287 mask = mk_cval(1, DT_LOG);
2288 if (DTYG(dtype) == TY_CHAR) {
2289 ast_from_len = srcarray;
2290 }
2291 if (vector == 0) {
2292 nargs = 3;
2293 /* pghpf_packz(result, array, mask) */
2294 } else {
2295 nargs = 4;
2296 /* pghpf_pack(result, array, mask, vector) */
2297 }
2298 newargt = mk_argt(nargs);
2299 ARGT_ARG(newargt, 1) = srcarray;
2300 ARGT_ARG(newargt, 2) = mask;
2301 if (nargs == 4) {
2302 ARGT_ARG(newargt, 3) = vector;
2303 }
2304 goto ret_new;
2305 case I_RESHAPE: /* reshape(source, shape, [pad, order]) */
2306 return reshape(func_ast, func_args, lhs);
2307 case I_SPREAD: /* spread(source, dim, ncopies) */
2308 dim = ARGT_ARG(func_args, 1);
2309 srcarray = ARGT_ARG(func_args, 0);
2310 if (!A_SHAPEG(srcarray))
2311 dim = astb.i1;
2312 if (A_ALIASG(dim) != 0) {
2313 int temp_arr = rewrite_intr_allocatable(func_ast, func_args, lhs);
2314 if (temp_arr != 0) {
2315 return temp_arr;
2316 }
2317 goto ret_norm;
2318 }
2319 if (DTYG(dtype) == TY_CHAR) {
2320 rtlRtn = A_SHAPEG(srcarray) == 0 ? RTE_spreadcs : RTE_spreadca;
2321 ast_from_len = srcarray;
2322 } else {
2323 rtlRtn = A_SHAPEG(srcarray) == 0 ? RTE_spreadsa : RTE_spread;
2324 }
2325 nargs = 4;
2326 newargt = mk_argt(nargs);
2327 ARGT_ARG(newargt, 1) = srcarray;
2328 ARGT_ARG(newargt, 2) = ARGT_ARG(func_args, 1);
2329 ARGT_ARG(newargt, 3) = ARGT_ARG(func_args, 2);
2330 goto ret_new;
2331 case I_TRANSPOSE: /* transpose(matrix) */
2332 temp_arr = rewrite_intr_allocatable(func_ast, func_args, lhs);
2333 if (temp_arr != 0) {
2334 return temp_arr;
2335 }
2336 goto ret_norm;
2337 case I_UNPACK: /* unpack(vector, mask, field) */
2338 rtlRtn = DTYG(dtype) == TY_CHAR ? RTE_unpackca : RTE_unpack;
2339 nargs = 4;
2340 srcarray = ARGT_ARG(func_args, 0);
2341
2342 newargt = mk_argt(nargs);
2343 ARGT_ARG(newargt, 1) = srcarray;
2344 ARGT_ARG(newargt, 2) = ARGT_ARG(func_args, 1);
2345 ARGT_ARG(newargt, 3) = ARGT_ARG(func_args, 2);
2346 goto ret_new;
2347 case I_TRANSFER: /* transfer(source, mold [, size]) */
2348 /* If the result is an array, then the size is either taken
2349 * from the size argument, or is based on the size of the source
2350 * and the mold.
2351 */
2352 srcarray = ARGT_ARG(func_args, 0);
2353 mask = ARGT_ARG(func_args, 1); /* mold */
2354 vector = ARGT_ARG(func_args, 2); /* size */
2355 /* pghpf_transfer(result, src, sizeof(src), sizeof(mold)) */
2356 nargs = 4;
2357 newargt = mk_argt(nargs);
2358 ARGT_ARG(newargt, 1) = srcarray;
2359 ARGT_ARG(newargt, 2) = size_ast(sym_of_ast(mask), DDTG(A_DTYPEG(mask)));
2360 ARGT_ARG(newargt, 3) = size_ast_of(srcarray, DDTG(A_DTYPEG(srcarray)));
2361 /* get the name of the library routine */
2362 newsym = sym_mkfunc(mkRteRtnNm(RTE_transfer), DT_NONE);
2363 /* get the temp and add the necessary statements */
2364 if (shape) {
2365 /* need to put this into a temp */
2366 temp_arr = mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1), 0,
2367 &retval);
2368 /* add temp_arr as argument */
2369 ARGT_ARG(newargt, 0) = retval;
2370 if (ALLOCG(temp_arr)) {
2371 int ddtg = DDTG(A_DTYPEG(mask));
2372 if (ddtg == DT_ASSCHAR || ddtg == DT_ASSNCHAR || ddtg == DT_DEFERCHAR ||
2373 ddtg == DT_DEFERNCHAR)
2374 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, mask);
2375 else
2376 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, 0);
2377 mk_mem_deallocate(mk_id(temp_arr), arg_gbl.std);
2378 }
2379 } else if (dtype == DT_ASSCHAR || dtype == DT_DEFERCHAR
2380 || dtype == DT_ASSNCHAR || dtype == DT_DEFERNCHAR
2381 ) {
2382 retval = alloc_char_temp(dtype, "transfer", ARGT_ARG(newargt, 2),
2383 arg_gbl.std, 0);
2384 ARGT_ARG(newargt, 0) = retval;
2385 } else if ((DTY(dtype) == TY_CHAR
2386 || DTY(dtype) == TY_NCHAR
2387 ) &&
2388 A_ALIASG(DTY(dtype + 1)) == 0) {
2389 /* the result has adjustable length */
2390 retval = alloc_char_temp(dtype, "transfer", ARGT_ARG(newargt, 2),
2391 arg_gbl.std, 0);
2392 ARGT_ARG(newargt, 0) = retval;
2393 } else {
2394 /* need to put this into a scalar temp */
2395 int temp_sclr = sym_get_scalar("transfer", "r", dtype);
2396 /* add temp_sclr as argument */
2397 retval = mk_id(temp_sclr);
2398 ARGT_ARG(newargt, 0) = retval;
2399 }
2400 goto ret_call;
2401
2402 case I_ADJUSTL: /* adjustl(string) */
2403 case I_ADJUSTR: /* adjustr(string) */
2404 if (optype == I_ADJUSTL) {
2405 rtlRtn = DTY(DDTG(dtype)) == TY_CHAR ? RTE_adjustla : RTE_nadjustl;
2406 root = "adjl";
2407 } else {
2408 rtlRtn = DTY(DDTG(dtype)) == TY_CHAR ? RTE_adjustra : RTE_nadjustr;
2409 root = "adjr";
2410 }
2411 newsym = sym_mkfunc_nodesc(mkRteRtnNm(rtlRtn), DT_INT);
2412 arg1 = ARGT_ARG(func_args, 0);
2413 /* len = RTE_[n]adjust[lr](string) */
2414 nargs = 2;
2415 newargt = mk_argt(nargs);
2416 ARGT_ARG(newargt, 1) = arg1;
2417
2418 /* the result has adjustable length */
2419 forall_depnd_intrin = arg_gbl.inforall && charintr_arg_forall_depnd(arg1);
2420 if (forall_depnd_intrin) {
2421 /* ADJUST[rl] in a FORALL, need an array temp subscr'd using
2422 * the subscripts on the original assign LHS */
2423 ast = A_LOPG(arg1);
2424 shape = A_SHAPEG(ast);
2425 retval = get_charintrin_temp(ast, root);
2426 retval = mk_subscr_copy(retval, A_ASDG(arg1), A_DTYPEG(ast));
2427 } else {
2428 ast = arg1;
2429 retval = get_charintrin_temp(ast, root);
2430 }
2431
2432 if (A_TYPEG(ast) == A_SUBSTR) {
2433 /* We need to preserve the substring argument unless the
2434 * string that we're taking the substring of is adjustable.
2435 */
2436 switch (A_DTYPEG(A_LOPG(ast))) {
2437 case DT_ASSCHAR:
2438 case DT_ASSNCHAR:
2439 case DT_DEFERCHAR:
2440 case DT_DEFERNCHAR:
2441 break;
2442 default:
2443 /*
2444 * First, create a temporary and then propagate the substring
2445 * expression normalized to 1 to the temporary. Normalization
2446 * is required since for adjustr(aaa(ii:jj)), the temp space
2447 * requirement will be computed as (jj - ii + 1) and the result
2448 * will be expressed as tmp(ii:jj), thus exceeded the space
2449 * allocated. Need to express the result as tmp(1:sz), where
2450 * sz is 'jj - ii + 1'.
2451 */
2452 if (A_LEFTG(ast) && A_LEFTG(ast) != astb.i1) {
2453 int r = A_RIGHTG(ast);
2454 int temp_ast;
2455 if (!r) {
2456 r = string_expr_length(A_LOPG(ast));
2457 }
2458 temp_ast = mk_binop(OP_SUB, r, A_LEFTG(ast), DT_INT);
2459 temp_ast = mk_binop(OP_ADD, temp_ast, astb.i1, DT_INT);
2460 retval = mk_substr(retval, 0, temp_ast, A_DTYPEG(retval));
2461 } else
2462 retval = mk_substr(retval, 0, A_RIGHTG(ast), A_DTYPEG(retval));
2463 }
2464 }
2465
2466 ARGT_ARG(newargt, 0) = retval;
2467 if (shape) {
2468 ADSC *ad;
2469 dtnew = get_array_dtype(SHD_NDIM(shape), DT_INT);
2470 ad = AD_DPTR(dtnew);
2471 for (i = 0; i < (int)SHD_NDIM(shape); i++) {
2472 AD_LWBD(ad, i) = AD_LWAST(ad, i) = SHD_LWB(shape, i);
2473 AD_UPBD(ad, i) = AD_UPAST(ad, i) = SHD_UPB(shape, i);
2474 AD_EXTNTAST(ad, i) = mk_extent(AD_LWAST(ad, i), AD_UPAST(ad, i), i);
2475 }
2476 temp_sptr = get_adjlr_arr_temp(dtnew);
2477 astnew = mk_id(temp_sptr);
2478 ast = mk_func_node(A_INTR, mk_id(newsym), nargs, newargt);
2479 A_OPTYPEP(ast, optype);
2480 } else {
2481 dtnew = DT_INT;
2482 astnew = mk_id(get_temp(DT_INT));
2483 ast = mk_func_node(A_FUNC, mk_id(newsym), nargs, newargt);
2484 }
2485
2486 A_DTYPEP(ast, dtnew);
2487 A_SHAPEP(ast, shape);
2488
2489 if (forall_depnd_intrin) {
2490 /* ADJUST[rl] in a FORALL, generate the a FORALL that assigns
2491 * the ADJUST[rl] to the subscr'd temp */
2492 int newforall;
2493 int forall = STD_AST(arg_gbl.std);
2494 astnew = mk_subscr_copy(astnew, A_ASDG(arg1), A_DTYPEG(ast));
2495
2496 ast = mk_assn_stmt(astnew, ast, dtnew);
2497 newforall = mk_stmt(A_FORALL, 0);
2498 A_LISTP(newforall, A_LISTG(forall));
2499 A_IFEXPRP(newforall, 0);
2500 A_IFSTMTP(newforall, ast);
2501 add_stmt_before(newforall, arg_gbl.std);
2502 } else {
2503 ast = mk_assn_stmt(astnew, ast, dtnew);
2504 add_stmt_before(ast, arg_gbl.std);
2505 }
2506 return retval;
2507
2508 case I_TRIM: /* trim(string) */
2509 arg1 = ARGT_ARG(func_args, 0);
2510 /* len = RTE_[n]trim(string) */
2511 nargs = 2;
2512 newargt = mk_argt(nargs);
2513 ARGT_ARG(newargt, 1) = arg1;
2514 rtlRtn = DTY(dtype) == TY_CHAR ? RTE_trima : RTE_ntrim;
2515 newsym = sym_mkfunc_nodesc(mkRteRtnNm(rtlRtn), DT_INT);
2516 /* the result has adjustable length */
2517 if (arg_gbl.inforall && charintr_arg_forall_depnd(arg1)) {
2518 /* The call to RTE_trim must be in
2519 * a FORALL and the result(s) must be arrays */
2520 int forall = STD_AST(arg_gbl.std);
2521 int newforall;
2522 ADSC *ad;
2523
2524 ast = A_LOPG(arg1);
2525 retval = get_charintrin_temp(ast, "trim");
2526 retval = mk_subscr_copy(retval, A_ASDG(arg1), A_DTYPEG(ast));
2527 ARGT_ARG(newargt, 0) = retval;
2528
2529 shape = A_SHAPEG(ast);
2530 dtnew = get_array_dtype(SHD_NDIM(shape), DT_INT);
2531 ad = AD_DPTR(dtnew);
2532 for (i = 0; i < (int)SHD_NDIM(shape); i++) {
2533 AD_LWBD(ad, i) = AD_LWAST(ad, i) = SHD_LWB(shape, i);
2534 AD_UPBD(ad, i) = AD_UPAST(ad, i) = SHD_UPB(shape, i);
2535 AD_EXTNTAST(ad, i) = mk_extent(AD_LWAST(ad, i), AD_UPAST(ad, i), i);
2536 }
2537 temp_sptr = get_adjlr_arr_temp(dtnew);
2538 astnew = mk_id(temp_sptr);
2539
2540 mk_mem_allocate(astnew, 0, arg_gbl.std, 0);
2541 mk_mem_deallocate(astnew, arg_gbl.std);
2542 astnew = mk_subscr_copy(astnew, A_ASDG(arg1), DT_INT);
2543
2544 ast = mk_func_node(A_INTR, mk_id(newsym), nargs, newargt);
2545 A_DTYPEP(ast, DT_INT);
2546 A_SHAPEP(ast, 0);
2547 A_OPTYPEP(ast, I_TRIM);
2548 ast = mk_assn_stmt(astnew, ast, DT_INT);
2549
2550 retval = mk_substr(retval, 0, astnew, A_DTYPEG(retval));
2551
2552 newforall = mk_stmt(A_FORALL, 0);
2553 A_LISTP(newforall, A_LISTG(forall));
2554 A_IFEXPRP(newforall, 0);
2555 A_IFSTMTP(newforall, ast);
2556 add_stmt_before(newforall, arg_gbl.std);
2557 } else {
2558 int len_ast;
2559 retval = get_charintrin_temp(arg1, "trim");
2560 ARGT_ARG(newargt, 0) = retval;
2561 temp_sptr = A_SPTRG(retval);
2562 if (DTY(DTYPEG(temp_sptr)) == DT_DEFERCHAR ||
2563 DTY(DTYPEG(temp_sptr)) == DT_DEFERNCHAR) {
2564 len_ast = get_len_of_deferchar_ast(retval);
2565 } else if (SCG(temp_sptr) == SC_BASED) {
2566 len_ast = mk_id(CVLENG(temp_sptr));
2567 } else {
2568 int len_sptr = get_next_sym(SYMNAME(temp_sptr), "cl");
2569 STYPEP(len_sptr, ST_VAR);
2570 DTYPEP(len_sptr, DT_INT);
2571 SCP(len_sptr, symutl.sc);
2572 len_ast = mk_id(len_sptr);
2573 }
2574 /* add call to function; function returns the len */
2575 ast = mk_func_node(A_FUNC, mk_id(newsym), nargs, newargt);
2576 A_DTYPEP(ast, DT_INT);
2577 A_SHAPEP(ast, 0);
2578 ast = mk_assn_stmt(len_ast, ast, DT_INT);
2579 add_stmt_before(ast, arg_gbl.std);
2580 retval = mk_substr(retval, 0, len_ast, dtype);
2581 }
2582 return retval;
2583
2584 case I_DATE_AND_TIME:
2585 rtlRtn = RTE_dandta;
2586 is_icall = FALSE;
2587 nargs = 4;
2588 goto opt_common;
2589 case I_SYSTEM_CLOCK:
2590 rtlRtn = RTE_sysclk;
2591 is_icall = FALSE;
2592 nargs = 3;
2593 goto opt_common;
2594 case I_CPU_TIME:
2595 is_icall = FALSE;
2596 arg1 = ARGT_ARG(func_args, 0);
2597 rtlRtn = DTYG(A_DTYPEG(arg1)) == TY_DBLE ? RTE_cpu_timed : RTE_cpu_time;
2598 nargs = 1;
2599 goto opt_common;
2600 case I_RANDOM_NUMBER:
2601 is_icall = FALSE;
2602 arg1 = ARGT_ARG(func_args, 0);
2603 rtlRtn = DTYG(A_DTYPEG(arg1)) == TY_DBLE ? RTE_rnumd : RTE_rnum;
2604 nargs = 1;
2605 goto opt_common;
2606 case I_RANDOM_SEED:
2607 rtlRtn = RTE_rseed;
2608 is_icall = FALSE;
2609 nargs = 3;
2610 opt_common:
2611 newargt = mk_argt(nargs);
2612 for (i = 0; i < nargs; ++i) {
2613 if (ARGT_ARG(func_args, i) == 0)
2614 ARGT_ARG(newargt, i) = astb.ptr0;
2615 else
2616 ARGT_ARG(newargt, i) = ARGT_ARG(func_args, i);
2617 }
2618 newsym = sym_mkfunc(mkRteRtnNm(rtlRtn), DT_NONE);
2619 retval = 0;
2620 goto ret_call;
2621 case I_PRESENT:
2622 /* present(a) will be present(a$b) a$b base of dummy */
2623 srcarray = ARGT_ARG(func_args, 0);
2624 if (A_TYPEG(srcarray) == A_ID && (sptr = A_SPTRG(srcarray)) &&
2625 SCG(sptr) == SC_DUMMY &&
2626 !HCCSYMG(sptr) && /* compiler's PRESENT is correct */
2627 STYPEG(sptr) == ST_ARRAY) {
2628 if (!normalize_bounds(sptr) || needs_redim(sptr)) {
2629 sptr = NEWARGG(sptr);
2630 }
2631 assert(sptr, "rewrite_func_ast: no formal symbol", func_ast, 3);
2632 ARGT_ARG(func_args, 0) = mk_id(sptr);
2633 }
2634 goto ret_norm;
2635 case I_SECNDS:
2636 nargs = 1;
2637 is_icall = FALSE;
2638 arg1 = ARGT_ARG(func_args, 0);
2639 rtlRtn = DTY(A_DTYPEG(arg1)) == TY_DBLE ? RTE_secndsd : RTE_secnds;
2640 newsym = sym_mkfunc(mkRteRtnNm(rtlRtn), dtype);
2641 retval = mk_func_node(A_FUNC, mk_id(newsym), nargs, func_args);
2642 A_DTYPEP(retval, dtype);
2643 A_SHAPEP(retval, 0);
2644 return retval;
2645 case I_TIME:
2646 is_icall = FALSE;
2647 arg1 = ARGT_ARG(func_args, 0);
2648 rtlRtn = DTY(A_DTYPEG(arg1)) == TY_CHAR ? RTE_ftimea : RTE_ftimew;
2649 goto sub_common;
2650 case I_DATE:
2651 is_icall = FALSE;
2652 arg1 = ARGT_ARG(func_args, 0);
2653 rtlRtn = DTY(A_DTYPEG(arg1)) == TY_CHAR ? RTE_datea : RTE_datew;
2654 goto sub_common;
2655 case I_IDATE:
2656 is_icall = FALSE;
2657 arg1 = ARGT_ARG(func_args, 0);
2658 rtlRtn = DTY(A_DTYPEG(arg1)) == TY_SINT ? RTE_idate : RTE_jdate;
2659 goto sub_common;
2660 case I_LASTVAL:
2661 rtlRtn = RTE_lastval;
2662 is_icall = FALSE;
2663 goto sub_common;
2664 case I_REDUCE_SUM:
2665 rtlRtn = RTE_global_sum;
2666 is_icall = TRUE;
2667 goto sub_common;
2668 case I_REDUCE_PRODUCT:
2669 rtlRtn = RTE_global_product;
2670 is_icall = TRUE;
2671 goto sub_common;
2672 case I_REDUCE_ANY:
2673 rtlRtn = RTE_global_any;
2674 is_icall = TRUE;
2675 goto sub_common;
2676 case I_REDUCE_ALL:
2677 rtlRtn = RTE_global_all;
2678 is_icall = TRUE;
2679 goto sub_common;
2680 case I_REDUCE_PARITY:
2681 rtlRtn = RTE_global_parity;
2682 is_icall = TRUE;
2683 goto sub_common;
2684 case I_REDUCE_IANY:
2685 rtlRtn = RTE_global_iany;
2686 is_icall = TRUE;
2687 goto sub_common;
2688 case I_REDUCE_IALL:
2689 rtlRtn = RTE_global_iall;
2690 is_icall = TRUE;
2691 goto sub_common;
2692 case I_REDUCE_IPARITY:
2693 rtlRtn = RTE_global_iparity;
2694 is_icall = TRUE;
2695 goto sub_common;
2696 case I_REDUCE_MINVAL:
2697 rtlRtn = RTE_global_minval;
2698 is_icall = TRUE;
2699 goto sub_common;
2700 case I_REDUCE_MAXVAL:
2701 rtlRtn = RTE_global_maxval;
2702 is_icall = TRUE;
2703 goto sub_common;
2704 case I_REDUCE_FIRSTMAX:
2705 rtlRtn = RTE_global_firstmax;
2706 is_icall = FALSE;
2707 /*********************************************
2708 ====================================
2709 POSSIBLY NEED THIS SINCE is_icall = FALSE...
2710 THIS IS OFTEN IN OTHER SUCH CASES. IN THIS CASE, NEED TO OVER-RIDE WHAT'S
2711 DONE IN sub_common).
2712 *BUT*, NOT DONE FOR _SECNDS, I_TIME, I_IDATE OR I_LASTVAL (THE LAST OF
2713 WHICH LOOKS JUST LIKE REDUCE_MAXVAL.)
2714 HENCE, TRY WITHOUT THE FOLLOWING TO START WITH!
2715 ====================================
2716 newargt = mk_argt(nargs);
2717 for (i = 0; i < nargs; ++i) {
2718 ARGT_ARG(newargt, i) = ARGT_ARG(func_args, i);
2719 }
2720 *********************************************/
2721 goto sub_common;
2722 case I_REDUCE_FIRSTMIN:
2723 rtlRtn = RTE_global_firstmin;
2724 is_icall = FALSE;
2725 goto sub_common;
2726 case I_REDUCE_LASTMAX:
2727 rtlRtn = RTE_global_lastmax;
2728 is_icall = FALSE;
2729 goto sub_common;
2730 case I_REDUCE_LASTMIN:
2731 rtlRtn = RTE_global_lastmin;
2732 is_icall = FALSE;
2733 goto sub_common;
2734 sub_common:
2735 nargs = ARGT_CNT(func_args);
2736 newargt = func_args;
2737 newsym = sym_mkfunc(mkRteRtnNm(rtlRtn), DT_NONE);
2738 retval = 0;
2739 goto ret_call;
2740 case I_PTR2_ASSIGN:
2741 check_pointer_type(ARGT_ARG(func_args, 0), ARGT_ARG(func_args, 1),
2742 arg_gbl.std, 0);
2743 if (!XBIT(58, 0x22)) {
2744 /* ...no changes unless caller remapping. */
2745 return -1;
2746 }
2747 ast = ARGT_ARG(func_args, 1);
2748 if (A_TYPEG(ast) != A_ID || STYPEG(A_SPTRG(ast)) != ST_ARRAY ||
2749 POINTERG(A_SPTRG(ast))) {
2750 /* ...no changes unless pointer assigned to whole array. */
2751 return -1;
2752 }
2753 /* Create call:
2754 * pghpf_ptr_asgn[_char](ptr_base, ptr_desc, arr_base, arr_desc, vlb),
2755 * where vlb is a vector of lower bounds of arr_base. */
2756 sptr = A_SPTRG(ARGT_ARG(func_args, 0));
2757 nargs = 5;
2758 if (XBIT(70, 0x20)) {
2759 if (MIDNUMG(sptr))
2760 ++nargs;
2761 if (PTROFFG(sptr))
2762 ++nargs;
2763 }
2764 rtlRtn = DTYG(A_DTYPEG(ast)) == TY_CHAR ? RTE_ptr_asgn_chara : RTE_ptr_asgn;
2765 newsym = sym_mkfunc_nodesc(mkRteRtnNm(rtlRtn), dtype);
2766 newargt = mk_argt(nargs);
2767 ARGT_ARG(newargt, 0) = ARGT_ARG(func_args, 0);
2768 ARGT_ARG(newargt, 1) = mk_id(DESCRG(sptr));
2769 DESCUSEDP(sptr, TRUE);
2770 ARGT_ARG(newargt, 2) = ARGT_ARG(func_args, 1);
2771 temp_sptr = A_SPTRG(ARGT_ARG(func_args, 1));
2772 ARGT_ARG(newargt, 3) = mk_id(DESCRG(temp_sptr));
2773 DESCUSEDP(temp_sptr, TRUE);
2774 temp_arr = sym_get_array(SYMNAME(temp_sptr), "v", DT_INT, 1);
2775 NODESCP(temp_arr, TRUE);
2776 ALLOCP(temp_arr, FALSE);
2777 dtype = DTYPEG(temp_arr);
2778 ADD_NOBOUNDS(dtype) = 0;
2779 ADD_MLPYR(dtype, 0) = astb.i1;
2780 ADD_LWAST(dtype, 0) = ADD_LWBD(dtype, 0) = astb.i1;
2781 ndims = rank_of_sym(temp_sptr);
2782 ADD_UPAST(dtype, 0) = ADD_UPBD(dtype, 0) = mk_cval(ndims, DT_INT);
2783 ARGT_ARG(newargt, 4) = mk_id(temp_arr);
2784 nargs = 5;
2785 if (XBIT(70, 0x20)) {
2786 /* add pointer, offset to argument list */
2787 if (MIDNUMG(sptr)) {
2788 ARGT_ARG(newargt, nargs) = mk_id(MIDNUMG(sptr));
2789 ++nargs;
2790 }
2791 if (PTROFFG(sptr)) {
2792 ARGT_ARG(newargt, nargs) = mk_id(PTROFFG(sptr));
2793 ++nargs;
2794 }
2795 }
2796 dtype = DTYPEG(temp_sptr);
2797 for (dim = 0; dim < ndims; dim++) {
2798 subscr[0] = mk_cval(dim + 1, DT_INT);
2799 ast = mk_subscr(mk_id(temp_arr), subscr, 1, DT_INT);
2800 ast = mk_assn_stmt(ast, ADD_LWAST(dtype, dim), DT_INT);
2801 add_stmt_before(ast, arg_gbl.std);
2802 }
2803 if (XBIT(49, 0x8000)) {
2804 /* ...no Cray pointers. */
2805 /* Set the offset to 1 because every destination pointer P will
2806 * be transformed later to P(offset). */
2807 temp_sptr = A_SPTRG(ARGT_ARG(func_args, 0));
2808 temp_sptr = PTROFFG(temp_sptr);
2809 assert(temp_sptr, "rewrite_func_ast: no pointer offset", func_ast, 3);
2810 ast = mk_assn_stmt(mk_id(temp_sptr), astb.i1, DT_INT);
2811 add_stmt_before(ast, arg_gbl.std);
2812 }
2813 is_icall = FALSE;
2814 goto ret_call;
2815 case I_GET_COMMAND:
2816 case I_GET_COMMAND_ARGUMENT:
2817 if (optype == I_GET_COMMAND) {
2818 rtlRtn = RTE_get_cmda;
2819 nargs = 4;
2820 } else {
2821 rtlRtn = RTE_get_cmd_arga;
2822 nargs = 5;
2823 }
2824 newsym = sym_mkfunc_nodesc(mkRteRtnNm(rtlRtn), DT_INT);
2825 newargt = mk_argt(nargs);
2826 for (i = 0; i < nargs - 1; i++) {
2827 int arg = ARGT_ARG(func_args, i);
2828 ARGT_ARG(newargt, i) = arg != 0 ? arg : i == 0 ? astb.ptr0c : astb.ptr0;
2829 }
2830 ARGT_ARG(newargt, nargs - 1) =
2831 mk_cval(size_of(stb.user.dt_int), astb.bnd.dtype);
2832 is_icall = FALSE;
2833 goto ret_call;
2834 case I_GET_ENVIRONMENT_VARIABLE:
2835 newsym = sym_mkfunc_nodesc(mkRteRtnNm(RTE_get_env_vara), DT_INT);
2836 nargs = 6;
2837 newargt = mk_argt(nargs);
2838 for (i = 0; i < nargs - 1; i++) {
2839 int arg = ARGT_ARG(func_args, i);
2840 ARGT_ARG(newargt, i) = arg != 0 ? arg : i == 1 ? astb.ptr0c : astb.ptr0;
2841 }
2842 ARGT_ARG(newargt, 5) = mk_cval(size_of(stb.user.dt_int), DT_INT4);
2843 is_icall = FALSE;
2844 goto ret_call;
2845 default:
2846 goto ret_norm;
2847 }
2848
2849 ret_new:
2850 /* get the name of the library routine */
2851 newsym = sym_mkfunc(mkRteRtnNm(rtlRtn), DT_NONE);
2852 /* get the temp and add the necessary statements */
2853 if (shape != 0) {
2854 /* need to put this into a temp */
2855 temp_arr = mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1), lhs,
2856 &retval);
2857 if (temp_arr != 0) {
2858 /* add temp_arr as argument */
2859 ARGT_ARG(newargt, 0) = retval;
2860 if (ALLOCG(temp_arr)) {
2861 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, ast_from_len);
2862 mk_mem_deallocate(mk_id(temp_arr), arg_gbl.std);
2863 }
2864 } else {
2865 /* lhs was distributed properly for this intr */
2866 ARGT_ARG(newargt, 0) = lhs;
2867 retval = 0;
2868 }
2869 } else {
2870 /* need to put this into a scalar temp */
2871 int temp_sclr = sym_get_scalar("tmp", "r", dtype);
2872 /* add temp_sclr as argument */
2873 retval = mk_id(temp_sclr);
2874 ARGT_ARG(newargt, 0) = retval;
2875 }
2876
2877 ret_call:
2878 /* add call to function */
2879 /* make every call ICALL iff call changes the first argument and
2880 no side effect, this will help optimizer */
2881 ast =
2882 mk_func_node(is_icall ? A_ICALL : A_CALL, mk_id(newsym), nargs, newargt);
2883 A_OPTYPEP(ast, optype);
2884 add_stmt_before(ast, arg_gbl.std);
2885 return retval;
2886
2887 ret_norm:
2888 retval = mk_func_node(type, A_LOPG(func_ast), A_ARGCNTG(func_ast), func_args);
2889 if (A_SRCG(func_ast)) { /* type bound procedure pass_arg%member part */
2890 A_SRCP(retval, A_SRCG(func_ast));
2891 }
2892 A_DTYPEP(retval, dtype);
2893 A_SHAPEP(retval, shape);
2894 A_OPTYPEP(retval, optype);
2895
2896 if (shape == 0 && take_out_user_def_func(func_ast)) {
2897 int temp_ast, temp_sptr;
2898 if (arg_gbl.lhs == 0) {
2899 int func = procsym_of_ast(A_LOPG(func_ast));
2900 if (STYPEG(func) == ST_MEMBER && CLASSG(func) && CCSYMG(func) &&
2901 VTABLEG(func)) {
2902 func = VTABLEG(func);
2903 }
2904 sptr = func;
2905 } else if (A_TYPEG(arg_gbl.lhs) == A_SUBSCR) {
2906 sptr = sptr_of_subscript(arg_gbl.lhs);
2907 } else {
2908 sptr = sym_of_ast(arg_gbl.lhs);
2909 }
2910 temp_sptr = sym_get_scalar(SYMNAME(sptr), "scl", A_DTYPEG(retval));
2911 temp_ast = mk_id(temp_sptr);
2912 astnew = mk_assn_stmt(temp_ast, retval, 0);
2913 add_stmt_before(astnew, arg_gbl.std);
2914 retval = temp_ast;
2915 }
2916
2917 return retval;
2918 }
2919
2920 /* func_ast is an intrinsic that might be computed directly into its LHS
2921 * (e.g. TRANPOSE, SPREAD, UNPACK).
2922 * If lhs has an allocatable member, compute into a temp and return it.
2923 * Otherwise return 0.
2924 * This allows allocatable assignments to be handled correctly.
2925 */
2926 static int
rewrite_intr_allocatable(int func_ast,int func_args,int lhs)2927 rewrite_intr_allocatable(int func_ast, int func_args, int lhs)
2928 {
2929 if (!ast_has_allocatable_member(lhs)) {
2930 return 0;
2931 } else {
2932 /* compute into a temp and copy that to lhs to handle allocatables */
2933 int new_rhs, assn_ast;
2934 int subscr[MAXSUBS];
2935 int tmp_ast = 0;
2936 DTYPE dtype = A_DTYPEG(func_ast);
2937 int tmp_sptr = mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1),
2938 lhs, &tmp_ast);
2939 assert(tmp_sptr != 0, "sptr=0 from mk_result_sptr", 0, ERR_Fatal);
2940 assert(tmp_ast != 0, "tmp_ast=0 from mk_result_sptr", 0, ERR_Fatal);
2941 mk_mem_allocate(mk_id(tmp_sptr), subscr, arg_gbl.std, 0);
2942 mk_mem_deallocate(mk_id(tmp_sptr), arg_gbl.std);
2943 new_rhs = rewrite_func_ast(func_ast, func_args, tmp_ast);
2944 if (new_rhs != 0) {
2945 assn_ast = mk_assn_stmt(tmp_ast, new_rhs, dtype);
2946 add_stmt_before(assn_ast, arg_gbl.std);
2947 }
2948 return tmp_ast;
2949 }
2950 }
2951
2952 static LOGICAL
ast_has_allocatable_member(int ast)2953 ast_has_allocatable_member(int ast)
2954 {
2955 if (ast == 0) {
2956 return FALSE;
2957 } else {
2958 int sptr = memsym_of_ast(ast);
2959 return !HCCSYMG(sptr) && allocatable_member(sptr);
2960 }
2961 }
2962
2963 /* take out user-defined function to eliminate multiple invocation of function
2964 */
2965 static LOGICAL
take_out_user_def_func(int func_ast)2966 take_out_user_def_func(int func_ast)
2967 {
2968 if (A_TYPEG(func_ast) == A_FUNC && arg_gbl.lhs != 0 &&
2969 A_SHAPEG(arg_gbl.lhs) != 0 && !arg_gbl.inforall) {
2970 return TRUE;
2971 }
2972
2973 /* if the function call is in a difficult statement, like an IF or
2974 * DO or computed GOTO, difficult.continue_std holds the temporary
2975 * CONTINUE statement inserted around which temp statements were
2976 * inserted, and difficult.func_std holds the original statement.
2977 * If any statements were inserted between the CONTINUE and the original
2978 * statement, these statements should follow the function call,
2979 * so we must move the function call, store the result, and then
2980 * use the result in the IF, DO, etc. */
2981 if (difficult.continue_std != 0 && difficult.func_std != 0 &&
2982 STD_NEXT(difficult.continue_std) != difficult.func_std) {
2983 return TRUE;
2984 }
2985 return FALSE;
2986 }
2987
2988 /*
2989 * Create an alloctable char temp of length 'len' within the context of
2990 * of a statement. The temp's len assignment and allocate statements are
2991 * added before 'std'; the temp's deallocate statement is added after 'std'.
2992 */
2993 static int
alloc_char_temp(int basetype,char * basename,int len,int std,int use_basetype)2994 alloc_char_temp(int basetype, char *basename, int len, int std,
2995 int use_basetype)
2996 {
2997 int dtype;
2998 int tempsptr;
2999 int tempast;
3000 int newasn;
3001 int tempbase, templen, alloc, lenasn;
3002
3003 if (!use_basetype)
3004 dtype = get_type(2, DTY(basetype), len);
3005 else
3006 dtype = basetype;
3007 tempsptr = get_next_sym(basename, "c");
3008 DTYPEP(tempsptr, dtype);
3009 STYPEP(tempsptr, ST_VAR);
3010 DCLDP(tempsptr, 1);
3011 SCP(tempsptr, SC_BASED);
3012 tempast = mk_id(tempsptr);
3013
3014 /* create a pointer variable */
3015 tempbase = get_next_sym(SYMNAME(tempsptr), "cp");
3016 templen = get_next_sym(SYMNAME(tempsptr), "cl");
3017
3018 /* make the pointer point to sptr */
3019 STYPEP(tempbase, ST_VAR);
3020 DTYPEP(tempbase, DT_PTR);
3021 SCP(tempbase, symutl.sc);
3022
3023 /* set length variable */
3024 STYPEP(templen, ST_VAR);
3025 DTYPEP(templen, DT_INT);
3026 SCP(templen, symutl.sc);
3027
3028 MIDNUMP(tempsptr, tempbase);
3029 CVLENP(tempsptr, templen);
3030 ADJLENP(tempsptr, 1);
3031
3032 /* add char length variable assignment */
3033 lenasn = mk_assn_stmt(mk_id(templen), len, 0);
3034 add_stmt_before(lenasn, std);
3035
3036 /* add an allocate statement */
3037 alloc = mk_stmt(A_ALLOC, 0);
3038 A_TKNP(alloc, TK_ALLOCATE);
3039 A_LOPP(alloc, 0);
3040 A_SRCP(alloc, tempast);
3041 add_stmt_before(alloc, std);
3042
3043 alloc = mk_stmt(A_ALLOC, 0);
3044 A_TKNP(alloc, TK_DEALLOCATE);
3045 A_LOPP(alloc, 0);
3046 A_SRCP(alloc, tempast);
3047 add_stmt_after(alloc, std);
3048
3049 return tempast;
3050 }
3051
3052 static int
get_charintrin_temp(int arg,char * nm)3053 get_charintrin_temp(int arg, char *nm)
3054 {
3055 int adt;
3056 int dtype;
3057 int shape;
3058 int temp;
3059 int ast;
3060 int len;
3061
3062 adt = A_DTYPEG(arg);
3063 dtype = adjust_ch_length(adt, arg);
3064 shape = A_SHAPEG(arg);
3065
3066 /* get the temp and add the necessary statements */
3067 if (shape) {
3068 int subscr[MAXSUBS];
3069 /* need to put this into a temp */
3070
3071 temp = mk_shape_sptr(shape, subscr, dtype);
3072 ast = mk_id(temp);
3073 if (ALLOCG(temp)) {
3074 mk_mem_allocate(ast, subscr, arg_gbl.std, 0);
3075 mk_mem_deallocate(ast, arg_gbl.std);
3076 }
3077 } else if (A_ALIASG(DTY(dtype + 1))) {
3078 temp = get_next_sym(nm, "c");
3079 DTYPEP(temp, dtype);
3080 STYPEP(temp, ST_VAR);
3081 DCLDP(temp, 1);
3082 SCP(temp, symutl.sc);
3083 ast = mk_id(temp);
3084 } else {
3085 if (A_TYPEG(arg) == A_ID) {
3086 /* check if arg has early spec */
3087 int sptr = A_SPTRG(arg);
3088 if (sptr && (ERLYSPECG(sptr) ||
3089 (HCCSYMG(sptr) && ADJLENG(sptr) && CVLENG(sptr)))) {
3090 int clen = CVLENG(sptr);
3091 ast = alloc_char_temp(dtype, "trim", mk_id(clen), arg_gbl.std, 1);
3092 return ast;
3093 }
3094 }
3095 len = rewrite_sub_ast(DTY(dtype + 1), 0);
3096 ast = alloc_char_temp(dtype, nm, len, arg_gbl.std, 1);
3097 }
3098
3099 return ast;
3100 }
3101
3102 /* This routine takes two array section, dest and src.
3103 * if there is communication from src to destination.
3104 * it creates a new temporary which is same shape and subscript
3105 * and alignment and assign src to that temp and return the temp.
3106 */
3107
3108 static int
misalignment(int dest,int src,int std)3109 misalignment(int dest, int src, int std)
3110 {
3111 return src;
3112 }
3113
3114 /* arr: array ast */
3115 /* arg_ast: call ast */
3116 /* argn: argument number */
3117 static void
check_assumed_size(int arr,int arg_ast,int argn)3118 check_assumed_size(int arr, int arg_ast, int argn)
3119 {
3120 /* In the presence of an interface, need to check if the formal
3121 * argument is assumed-size, and mark the array sequential. */
3122 int dp, iface;
3123 int ext;
3124 int arg1;
3125 }
3126
3127 static int rewrite_sub_args(int arg_ast, int lc);
3128
3129 /* keep track of which dimensions have been as dim= for CSHIFT/EOSHIFT calls */
3130 static int inshift[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3131
3132 /*
3133 * return '1' for a simple reference (scalar, member, array element)
3134 * return '1' for unary or binary op of simple reference operands
3135 * return '0' otherwise
3136 */
3137 static int
simple_reference(int ast)3138 simple_reference(int ast)
3139 {
3140 switch (A_TYPEG(ast)) {
3141 case A_MEM:
3142 case A_ID:
3143 case A_SUBSCR:
3144 case A_CNST:
3145 return 1;
3146 case A_BINOP:
3147 if (!simple_reference(A_LOPG(ast)))
3148 return 0;
3149 if (!simple_reference(A_ROPG(ast)))
3150 return 0;
3151 return 1;
3152 case A_UNOP:
3153 case A_PAREN:
3154 if (!simple_reference(A_LOPG(ast)))
3155 return 0;
3156 return 1;
3157 default:
3158 return 0;
3159 }
3160 } /* simple_reference */
3161
3162 /*
3163 * return '1' if the argument should not be rewritten;
3164 * This occurs for nested CSHIFT or EOSHIFT calls.
3165 * in that case, call rewrite_sub_args for the nested call.
3166 */
3167 static int
leave_arg(int ast,int i,int * parg,int lc)3168 leave_arg(int ast, int i, int *parg, int lc)
3169 {
3170 int arg;
3171 arg = *parg;
3172 /* 'ast', the calling ast, must be EOSHIFT or CSHIFT
3173 * if the first argument is also EOSHIFT or CSHIFT, return 1 */
3174 if (ast && (A_TYPEG(ast) == A_INTR) &&
3175 (A_OPTYPEG(ast) == I_EOSHIFT || A_OPTYPEG(ast) == I_CSHIFT) && (i == 0) &&
3176 (arg) && (A_TYPEG(arg) == A_INTR) &&
3177 (A_OPTYPEG(arg) == I_EOSHIFT || A_OPTYPEG(arg) == I_CSHIFT)) {
3178 int astarglist, argarglist, astdim, argdim, save;
3179 astarglist = A_ARGSG(ast);
3180 argarglist = A_ARGSG(arg);
3181
3182 if (A_OPTYPEG(ast) == I_CSHIFT) {
3183 astdim = ARGT_ARG(astarglist, 2);
3184 } else if (A_OPTYPEG(ast) == I_EOSHIFT) {
3185 astdim = ARGT_ARG(astarglist, 3);
3186 }
3187 if (astdim == 0) {
3188 astdim = 1;
3189 } else {
3190 assert(A_TYPEG(astdim) == A_CNST,
3191 "inline_shifts: variable dim not implemented", ast, 3);
3192 astdim = get_int_cval(A_SPTRG(A_ALIASG(astdim)));
3193 }
3194 if (A_OPTYPEG(arg) == I_CSHIFT) {
3195 argdim = ARGT_ARG(argarglist, 2);
3196 } else if (A_OPTYPEG(arg) == I_EOSHIFT) {
3197 argdim = ARGT_ARG(argarglist, 3);
3198 }
3199 if (argdim == 0) {
3200 argdim = 1;
3201 } else {
3202 assert(A_TYPEG(argdim) == A_CNST,
3203 "inline_shifts: variable dim not implemented", ast, 3);
3204 argdim = get_int_cval(A_SPTRG(A_ALIASG(argdim)));
3205 }
3206 save = inshift[astdim];
3207 inshift[astdim] = 1;
3208 if (inshift[argdim]) {
3209 /* there may be further nested shifts as well */
3210 arg = rewrite_sub_ast(arg, lc);
3211 *parg = arg;
3212 } else {
3213 int args;
3214 args = rewrite_sub_args(arg, lc);
3215 A_ARGSP(arg, args);
3216 }
3217 inshift[astdim] = save;
3218 return 1;
3219 }
3220 if (!XBIT(70, 0x200000) && ast && (A_TYPEG(ast) == A_INTR)) {
3221 int astdim, dim, args, dtype, mask;
3222 mask = 0;
3223 switch (A_OPTYPEG(ast)) {
3224 case I_SUM:
3225 case I_PRODUCT:
3226 case I_MAXVAL:
3227 case I_MINVAL:
3228 case I_ALL:
3229 case I_ANY:
3230 case I_COUNT:
3231 if (i != 0)
3232 return 0;
3233 args = A_ARGSG(ast);
3234 astdim = ARGT_ARG(args, 1);
3235 mask = ARGT_ARG(args, 2);
3236 break;
3237 case I_NORM2:
3238 if (i != 0)
3239 return 0;
3240 args = A_ARGSG(ast);
3241 astdim = ARGT_ARG(args, 1);
3242 break;
3243 case I_DOT_PRODUCT:
3244 if (i > 1)
3245 return 0;
3246 dtype = A_DTYPEG(ast);
3247 if (DT_ISCMPLX(DDTG(dtype)) && (XBIT(70, 0x4000000)
3248 || DDTG(dtype) == DT_QCMPLX
3249 ))
3250 return 0;
3251 astdim = 0;
3252 break;
3253 default:
3254 return 0;
3255 }
3256 if (mask)
3257 return 0;
3258 /* for a reduction function, 1st argument, leave it alone
3259 * if the 'dim' argument (if any) is '1' */
3260 if (astdim != 0) {
3261 if (A_TYPEG(astdim) != A_CNST)
3262 return 0;
3263 if (!XBIT(70, 0x400000)) {
3264 dim = get_int_cval(A_SPTRG(astdim));
3265 if (dim != 1)
3266 return 0;
3267 }
3268 }
3269 /* make sure the argument is an array, or expression of array
3270 * (no function calls) */
3271 if (!simple_reference(arg)) {
3272 return 0;
3273 }
3274 return 1;
3275 }
3276 return 0;
3277 } /* leave_arg */
3278
3279 /*
3280 * return TRUE for TRANSPOSE, and for 1st argument of SPREAD
3281 * these arguments can be left as expressions
3282 */
3283 static LOGICAL
leave_elemental_argument(int func_ast,int argnum)3284 leave_elemental_argument(int func_ast, int argnum)
3285 {
3286 if (A_TYPEG(func_ast) == A_INTR) {
3287 if (A_OPTYPEG(func_ast) == I_TRANSPOSE ||
3288 (A_OPTYPEG(func_ast) == I_SPREAD && argnum == 0)) {
3289 return TRUE;
3290 }
3291 }
3292 return FALSE;
3293 } /* leave_elemental_argument */
3294
3295 /*
3296 * if the actual argument is a scalar of intrinsic type
3297 * and the dummy argument is a pass-by-reference intent(in) argument,
3298 * then copy the scalar to a temp
3299 */
3300 static int
copy_scalar_intent_in(int arg,int dummy_sptr,int std)3301 copy_scalar_intent_in(int arg, int dummy_sptr, int std)
3302 {
3303 int dtype, sptr, newsptr, destast, asnast, newstd;
3304 if (!dummy_sptr)
3305 return arg;
3306 if (INTENTG(dummy_sptr) != INTENT_IN)
3307 return arg;
3308 if (PASSBYVALG(dummy_sptr))
3309 return arg;
3310 if (ALLOCATTRG(dummy_sptr))
3311 return arg;
3312 if (POINTERG(dummy_sptr))
3313 return arg;
3314 if (OPTARGG(dummy_sptr))
3315 return arg;
3316 if (ALLOCG(dummy_sptr))
3317 return arg;
3318 dtype = A_DTYPEG(arg);
3319 if (!DT_ISBASIC(dtype))
3320 return arg;
3321 if (DTY(dtype) == TY_CHAR)
3322 return arg;
3323 if (A_SHAPEG(arg))
3324 return arg;
3325 if (A_TYPEG(arg) != A_ID)
3326 return arg;
3327 sptr = A_SPTRG(arg);
3328 if (OPTARGG(sptr))
3329 return arg; /* may be a missing argument */
3330 newsptr = sym_get_scalar(SYMNAME(sptr), "a", dtype);
3331 destast = mk_id(newsptr);
3332 asnast = mk_assn_stmt(destast, arg, dtype);
3333 add_stmt_before(asnast, std);
3334 return mk_id(newsptr);
3335 } /* copy_scalar_intent_in */
3336
3337 /*
3338 * rewrite arguments of a function or subroutine call
3339 */
3340 static int
rewrite_sub_args(int arg_ast,int lc)3341 rewrite_sub_args(int arg_ast, int lc)
3342 {
3343 int argt;
3344 int newargt = 0;
3345 int arg, subarg;
3346 int shape;
3347 int nargs;
3348 int i, j, n;
3349 int asd;
3350 int temp_arr;
3351 int dtype, eldtype;
3352 int asn_ast;
3353 int ast;
3354 int std;
3355 int arr;
3356 int subscr[MAXSUBS];
3357 int func_args;
3358 int retval;
3359 int dscptr;
3360 int dummy_sptr;
3361 int func_sptr;
3362 int iface;
3363 LOGICAL caller_copies;
3364 int cloc_ast;
3365
3366 std = arg_gbl.std;
3367 argt = A_ARGSG(arg_ast);
3368 nargs = A_ARGCNTG(arg_ast);
3369 func_sptr = procsym_of_ast(A_LOPG(arg_ast));
3370 if (STYPEG(func_sptr) == ST_MEMBER && CLASSG(func_sptr) &&
3371 CCSYMG(func_sptr) && VTABLEG(func_sptr)) {
3372 func_sptr = VTABLEG(func_sptr);
3373 }
3374 proc_arginfo(func_sptr, NULL, &dscptr, &iface);
3375 newargt = mk_argt(nargs);
3376 for (i = 0; i < nargs; ++i) {
3377 if (ARGT_ARG(argt, i) == 0) {
3378 ARGT_ARG(newargt, i) = 0;
3379 continue;
3380 }
3381 caller_copies = FALSE;
3382 arg = ARGT_ARG(argt, i);
3383 dummy_sptr = 0;
3384 if (dscptr && i < PARAMCTG(func_sptr))
3385 dummy_sptr = aux.dpdsc_base[dscptr + i];
3386 if (leave_arg(arg_ast, i, &arg, lc)) {
3387 ARGT_ARG(newargt, i) = arg;
3388 continue;
3389 }
3390 /* iso_c c_loc , c_funloc are noops as function arguments:
3391 pass their arg up to this func as an arg
3392 */
3393 if (is_iso_cloc(arg)) {
3394 cloc_ast = ARGT_ARG(A_ARGSG(arg), 0);
3395 /* take out CLOC for both byval and byref arguments */
3396 if ((dummy_sptr == 0) || (func_sptr == 0)) {
3397
3398 ARGT_ARG(newargt, i) = cloc_ast;
3399 continue;
3400 }
3401 }
3402
3403 if (A_TYPEG(arg_ast) == A_INTR && A_OPTYPEG(arg_ast) == I_DOT_PRODUCT &&
3404 i == 2 && arg == ARGT_ARG(argt, 0)) {
3405 /* optimize the case of DOTPRODUCT(a(:)%mem,a(:)%mem) */
3406 ARGT_ARG(newargt, i) = ARGT_ARG(newargt, 0);
3407 continue;
3408 }
3409 arg = rewrite_sub_ast(arg, lc);
3410 /* arg = rewrite_interface_args(arg_ast, arg, i);*/
3411 /* leave elementals alone */
3412 if (A_TYPEG(arg_ast) == A_INTR && INKINDG(func_sptr) == IK_ELEMENTAL) {
3413 ARGT_ARG(newargt, i) = arg;
3414 continue;
3415 }
3416 /* leave pointer assign alone */
3417 if (A_TYPEG(arg_ast) == A_ICALL && A_OPTYPEG(arg_ast) == I_PTR2_ASSIGN) {
3418 ARGT_ARG(newargt, i) = arg;
3419 continue;
3420 }
3421 if (A_TYPEG(arg_ast) == A_INTR) {
3422 /* leave elementals alone, leave pointer assign alone */
3423 if (INKINDG(func_sptr) == IK_ELEMENTAL ||
3424 A_OPTYPEG(arg_ast) == I_PTR2_ASSIGN) {
3425 ARGT_ARG(newargt, i) = arg;
3426 continue;
3427 }
3428 }
3429 if (iface && ELEMENTALG(iface)) {
3430 /* leave alone if arg is not an elemental function,
3431 * else process function below
3432 */
3433 if (A_TYPEG(arg) == A_FUNC) {
3434 int sym;
3435 switch (A_TYPEG(A_LOPG(arg))) {
3436 case A_ID:
3437 case A_LABEL:
3438 case A_ENTRY:
3439 case A_SUBSCR:
3440 case A_SUBSTR:
3441 case A_MEM:
3442 sym = memsym_of_ast(A_LOPG(arg));
3443 if (CLASSG(sym) && VTABLEG(sym) && BINDG(sym)) {
3444 sym = VTABLEG(sym);
3445 break;
3446 }
3447 /* Fall Thru */
3448 default:
3449 sym = A_SPTRG(A_LOPG(arg));
3450 }
3451 if (ELEMENTALG(sym)) {
3452 ARGT_ARG(newargt, i) = arg;
3453 continue;
3454 }
3455 } else if (A_TYPEG(arg) != A_FUNC || !ELEMENTALG(A_SPTRG(A_LOPG(arg)))) {
3456 ARGT_ARG(newargt, i) = arg;
3457 continue;
3458 }
3459 }
3460 /* don't touch %val, %loc, and %ref operators even their shape is
3461 * not NULL
3462 */
3463 if (A_TYPEG(arg) == A_UNOP) {
3464 if (A_OPTYPEG(arg) == OP_VAL || A_OPTYPEG(arg) == OP_BYVAL ||
3465 A_OPTYPEG(arg) == OP_LOC || A_OPTYPEG(arg) == OP_REF) {
3466 ARGT_ARG(newargt, i) = arg;
3467 continue;
3468 }
3469 }
3470 /* if this is a scalar expression variable passed to
3471 * a non-value intent(in) argument, copy to a temp
3472 * so we don't have to mark the variable as ADDRTKN */
3473 if (dummy_sptr && XBIT(68, 8))
3474 arg = copy_scalar_intent_in(arg, dummy_sptr, std);
3475 shape = A_SHAPEG(arg);
3476 dtype = A_DTYPEG(arg);
3477 subarg = arg;
3478 if (A_TYPEG(subarg) == A_SUBSTR)
3479 subarg = A_LOPG(subarg);
3480 if (A_TYPEG(subarg) == A_ID) {
3481 ARGT_ARG(newargt, i) = arg;
3482 continue;
3483 }
3484 if (A_TYPEG(subarg) == A_MEM) {
3485 /* if this is an array of derived types, then it needs
3486 * to be rewritten */
3487 if (A_SHAPEG(A_PARENTG(subarg))) {
3488 caller_copies = TRUE;
3489 goto rewrite_this;
3490 }
3491 if (A_TYPEG(A_MEMG(subarg)) == A_ID) {
3492 ARGT_ARG(newargt, i) = arg;
3493 continue;
3494 }
3495 }
3496 if (shape) {
3497 /* for transpose(elementalexpression) or
3498 * spread(elementalexpression,dim,size),
3499 * leave the elemental expressions in place, don't assign
3500 * to a temp. They will be expanded when the transpose or spread
3501 * are inlined */
3502 if (leave_elemental_argument(arg_ast, i)) {
3503 ARGT_ARG(newargt, i) = arg;
3504 continue;
3505 }
3506 /* argument may be an array, but not a whole array */
3507 /* check for a(:)%b(9) */
3508 if (A_TYPEG(subarg) == A_SUBSCR) {
3509 int lop = A_LOPG(subarg);
3510 if (A_TYPEG(lop) == A_MEM && A_SHAPEG(A_PARENTG(lop))) {
3511 /* shape comes from parent of A_MEM; copy */
3512 caller_copies = TRUE;
3513 goto rewrite_this;
3514 }
3515 }
3516
3517 /* need to check for vector subscripts here */
3518 if (subarg == arg && A_TYPEG(subarg) == A_SUBSCR) {
3519 asd = A_ASDG(subarg);
3520 n = ASD_NDIM(asd);
3521 for (j = 0; j < n; ++j)
3522 if (A_TYPEG(ASD_SUBS(asd, j)) != A_TRIPLE &&
3523 A_SHAPEG(ASD_SUBS(asd, j)) != 0)
3524 goto rewrite_this;
3525 ARGT_ARG(newargt, i) = arg;
3526 continue;
3527 }
3528 rewrite_this:
3529 assert(!arg_gbl.inforall, "rewrite_sub_args: can not handle PURE arg",
3530 arg, 2);
3531 if (arg_gbl.inforall) {
3532 ARGT_ARG(newargt, i) = arg;
3533 continue;
3534 }
3535
3536 /* either vector subscript, or array expression */
3537 /* need to put this into a temp */
3538 ast = search_conform_array(subarg, FALSE);
3539 if (ast == 0)
3540 ast = search_conform_array(subarg, TRUE);
3541 assert(ast != 0, "rewrite_sub_args: can't find array", arg, 4);
3542 eldtype = DDTG(dtype);
3543 if (eldtype == DT_ASSCHAR || eldtype == DT_ASSNCHAR ||
3544 eldtype == DT_DEFERCHAR || eldtype == DT_DEFERNCHAR) {
3545 /* make up fake datatype with actual length */
3546 if (A_TYPEG(ast) == A_INTR) {
3547 eldtype =
3548 fix_dtype(memsym_of_ast(ARGT_ARG(A_ARGSG(ast), 0)), eldtype);
3549 } else {
3550 eldtype = get_type(2, DTY(eldtype), string_expr_length(arg));
3551 }
3552 }
3553
3554 if (A_TYPEG(ast) == A_INTR) {
3555 func_args = A_ARGSG(ast);
3556 temp_arr = mk_result_sptr(ast, func_args, subscr, eldtype, 0, &retval);
3557 ast = retval;
3558 } else {
3559 temp_arr = mk_assign_sptr(ast, "a", subscr, eldtype, &ast);
3560 }
3561 /* make assignment to temp_arr */
3562 asn_ast = mk_assn_stmt(ast, arg, dtype);
3563 ARGT_ARG(newargt, i) = ast;
3564 if (ALLOCG(temp_arr)) {
3565 mk_mem_allocate(mk_id(temp_arr), subscr, std, 0);
3566 }
3567 add_stmt_before(asn_ast, std);
3568 if (ALLOCG(temp_arr))
3569 mk_mem_deallocate(mk_id(temp_arr), std);
3570 if (caller_copies && (!dummy_sptr || INTENTG(dummy_sptr) != INTENT_IN)) {
3571 /* make assignment from temp_arr */
3572
3573 asn_ast = mk_assn_stmt(arg, ast, dtype);
3574 add_stmt_after(asn_ast, std);
3575 }
3576 } else if (A_TYPEG(subarg) == A_SUBSCR) {
3577 /*
3578 * argument is a subscripted reference. If the array is
3579 * distributed, then this needs to be put into a scalar temp
3580 * before the call and copied back to the array element after
3581 * the call. Note, this should probably be done in a later
3582 * phase
3583 */
3584
3585 arr = A_LOPG(subarg);
3586 check_assumed_size(arr, arg_ast, i);
3587 if (A_TYPEG(arr) != A_ID || !ALIGNG(A_SPTRG(arr)))
3588 goto lval;
3589 ARGT_ARG(newargt, i) = subarg;
3590 } else if (A_ISLVAL(A_TYPEG(subarg))) {
3591 lval:
3592 /* This reference is an lvalue. We want to leave it alone.
3593 * However, it may be necessary to pull out subcomponents
3594 * of it. Example: substr(idx(1):idx(2)) where idx is distributed.
3595 */
3596 ARGT_ARG(newargt, i) = arg;
3597 } else
3598 ARGT_ARG(newargt, i) = arg;
3599 }
3600 return newargt;
3601 }
3602
3603 /*
3604 * rewrite subprogram call
3605 */
3606 static int
rewrite_sub_ast(int ast,int lc)3607 rewrite_sub_ast(int ast, int lc)
3608 {
3609 int shape;
3610 int l, r, lop;
3611 int dtype;
3612 int args;
3613 int asd;
3614 int numdim;
3615 int i;
3616 int subs[MAXSUBS];
3617
3618 if (ast == 0)
3619 return 0;
3620 shape = A_SHAPEG(ast);
3621 switch (A_TYPEG(ast)) {
3622 case A_NULL:
3623 case A_CMPLXC:
3624 case A_CNST:
3625 case A_ID:
3626 case A_LABEL:
3627 return ast;
3628 case A_MP_ATOMICREAD:
3629 dtype = A_DTYPEG(ast);
3630 r = rewrite_sub_ast(A_SRCG(ast), lc);
3631 r = mk_atomic(A_MP_ATOMICREAD, 0, r, dtype);
3632 A_MEM_ORDERP(r, A_MEM_ORDERG(ast));
3633 return r;
3634 case A_MEM:
3635 dtype = A_DTYPEG(ast);
3636 r = rewrite_sub_ast((int)A_MEMG(ast), lc);
3637 l = rewrite_sub_ast(A_PARENTG(ast), lc);
3638 return mk_member(l, r, dtype);
3639 case A_BINOP:
3640 dtype = A_DTYPEG(ast);
3641 l = rewrite_sub_ast(A_LOPG(ast), lc);
3642 r = rewrite_sub_ast(A_ROPG(ast), lc);
3643 return mk_binop(A_OPTYPEG(ast), l, r, dtype);
3644 case A_UNOP:
3645 dtype = A_DTYPEG(ast);
3646 l = rewrite_sub_ast(A_LOPG(ast), lc);
3647 return mk_unop(A_OPTYPEG(ast), l, dtype);
3648 case A_PAREN:
3649 dtype = A_DTYPEG(ast);
3650 l = rewrite_sub_ast(A_LOPG(ast), lc);
3651 return mk_paren(l, dtype);
3652 case A_CONV:
3653 dtype = A_DTYPEG(ast);
3654 l = rewrite_sub_ast(A_LOPG(ast), lc);
3655 /* If the operand is a scalar and the result has a shape, we
3656 * can't use mk_convert */
3657 if (!A_SHAPEG(l) && A_SHAPEG(ast)) {
3658 r = mk_promote_scalar(l, dtype, A_SHAPEG(ast));
3659 A_DTYPEP(r, dtype);
3660 } else
3661 r = mk_convert(l, dtype);
3662 return r;
3663 case A_SUBSTR:
3664 lop = rewrite_sub_ast(A_LOPG(ast), lc);
3665 l = rewrite_sub_ast(A_LEFTG(ast), lc);
3666 r = rewrite_sub_ast(A_RIGHTG(ast), lc);
3667 return mk_substr(lop, l, r, A_DTYPEG(ast));
3668 case A_SUBSCR:
3669 dtype = A_DTYPEG(ast);
3670 asd = A_ASDG(ast);
3671 numdim = ASD_NDIM(asd);
3672 assert(numdim > 0 && numdim <= 7, "rewrite_sub_ast: bad numdim", ast, 4);
3673 for (i = 0; i < numdim; ++i) {
3674 l = rewrite_sub_ast(ASD_SUBS(asd, i), lc);
3675 subs[i] = l;
3676 }
3677 /* return mk_subscr(A_LOPG(ast), subs, numdim, DTY(dtype+1)); */
3678 return mk_subscr(A_LOPG(ast), subs, numdim, dtype);
3679 case A_TRIPLE:
3680 l = rewrite_sub_ast(A_LBDG(ast), lc);
3681 r = rewrite_sub_ast(A_UPBDG(ast), lc);
3682 i = rewrite_sub_ast(A_STRIDEG(ast), lc);
3683 return mk_triple(l, r, i);
3684 case A_INTR:
3685 case A_FUNC:
3686 ast = inline_reduction_f90(ast, 0, lc, NULL);
3687 if (A_TYPEG(ast) != A_INTR && A_TYPEG(ast) != A_FUNC)
3688 return ast;
3689 args = rewrite_sub_args(ast, lc);
3690
3691 /* try again to inline it */
3692 ast = inline_reduction_f90(ast, 0, lc, NULL);
3693 l = rewrite_func_ast(ast, args, 0);
3694 return l;
3695 case A_ICALL:
3696 ast = inline_reduction_f90(ast, 0, lc, NULL);
3697 if (A_TYPEG(ast) != A_ICALL)
3698 return ast;
3699 args = rewrite_sub_args(ast, lc);
3700 A_ARGSP(ast, args);
3701 /* try again to inline it */
3702 ast = inline_reduction_f90(ast, 0, lc, NULL);
3703 l = rewrite_func_ast(ast, args, 0);
3704 return l;
3705 case A_CALL:
3706 assert(elemental_func_call(ast),
3707 "rewrite_sub_ast: attempt to rewrite call to non elemental subr",
3708 ast, 3);
3709 args = rewrite_sub_args(ast, lc);
3710 A_ARGSP(ast, args);
3711 transform_elemental(ast, args);
3712 return -1;
3713 default:
3714 interr("rewrite_sub_ast: unexpected ast", ast, 2);
3715 return ast;
3716 }
3717 }
3718
3719 /* We are using the lhs for the result of an inline intrinsic.
3720 * Allocate it if necessary. */
3721 static void
allocate_lhs_if_needed(int lhs,int rhs,int std)3722 allocate_lhs_if_needed(int lhs, int rhs, int std)
3723 {
3724 int astif, new_lhs;
3725 if (!XBIT(54, 1))
3726 return;
3727 if (A_TYPEG(lhs) == A_SUBSCR)
3728 return;
3729 if (!ast_is_sym(lhs) || !ALLOCATTRG(sym_of_ast(lhs)))
3730 return;
3731 astif = mk_conformable_test(lhs, rhs, OP_LE);
3732 add_stmt_before(astif, std);
3733 gen_dealloc_if_allocated(lhs, std);
3734 new_lhs = add_shapely_subscripts(lhs, rhs, A_DTYPEG(rhs),
3735 array_element_dtype(A_DTYPEG(lhs)));
3736 add_stmt_before(mk_allocate(new_lhs), std);
3737 add_stmt_before(mk_stmt(A_ENDIF, 0), std);
3738 }
3739
3740 void
rewrite_asn(int ast,int std,bool flag,int lc)3741 rewrite_asn(int ast, int std, bool flag, int lc)
3742 {
3743 int rhs, lhs;
3744 int args;
3745 int l;
3746 int asd, j, n;
3747 int new_rhs;
3748 LOGICAL doremove;
3749
3750 rhs = A_SRCG(ast);
3751 lhs = A_DESTG(ast);
3752 arg_gbl.lhs = lhs;
3753
3754 lhs = rewrite_sub_ast(A_DESTG(ast), lc);
3755 A_DESTP(ast, lhs);
3756 arg_gbl.lhs = lhs;
3757
3758 if (A_TYPEG(rhs) == A_MP_ATOMICREAD)
3759 return;
3760
3761 /* If this is an assignment of an intrinsic directly into
3762 * the LHS, avoid the temp */
3763 if (flag && A_SHAPEG(lhs) &&
3764 (A_TYPEG(rhs) == A_FUNC || A_TYPEG(rhs) == A_INTR)) {
3765 int std_prev = STD_PREV(std); /* for allocate_lhs_if_needed case */
3766 if (A_TYPEG(lhs) == A_SUBSCR) {
3767 asd = A_ASDG(lhs);
3768 n = ASD_NDIM(asd);
3769 for (j = 0; j < n; ++j)
3770 if (A_TYPEG(ASD_SUBS(asd, j)) != A_TRIPLE &&
3771 A_SHAPEG(ASD_SUBS(asd, j)) != 0)
3772 goto rewrite_this; /* vector subscript */
3773 }
3774 /* Otherwise, we can use lhs directly */
3775 args = rewrite_sub_args(rhs, lc);
3776 A_ARGSP(rhs, args);
3777 new_rhs = inline_reduction_f90(rhs, lhs, lc, &doremove);
3778 if (new_rhs == rhs) {
3779 new_rhs = rewrite_func_ast(rhs, args, lhs);
3780 doremove = new_rhs == 0;
3781 }
3782 if (doremove) {
3783 allocate_lhs_if_needed(lhs, rhs, STD_NEXT(std_prev));
3784 if (std)
3785 delete_stmt(std);
3786 } else {
3787 A_SRCP(ast, new_rhs);
3788 }
3789 return;
3790 }
3791
3792 rewrite_this:
3793 l = rewrite_sub_ast(rhs, lc);
3794 A_SRCP(ast, l);
3795 }
3796
3797 void
rewrite_calls(void)3798 rewrite_calls(void)
3799 {
3800 int std, stdnext, stdnew;
3801 int ast, rhs, lhs, astnew;
3802 int sptr;
3803 int args, a;
3804 int type;
3805 int sptr_lhs;
3806 int prevstd, src;
3807 int parallel_depth;
3808 int task_depth;
3809 int doif;
3810 /*
3811 * Transform subroutine/function call arguments.
3812 * 1. If they contain array expressions, a temp must be allocated and
3813 * the expression must be copied into the temp.
3814 * 2. If they contain references to array elements, then the elements must
3815 * be copied into a scalar, the scalar passed, and the elements
3816 * copied back. Some of this can be avoided if the INTENT is known.
3817 * 3. Scalars aren't interfered with, except scalar arguments to
3818 * intent(in) dummy arguments are copied to a temp, and the temp
3819 * is passed instead.
3820 */
3821
3822 parallel_depth = 0;
3823 task_depth = 0;
3824 for (std = STD_NEXT(0); std; std = stdnext) {
3825 stdnext = STD_NEXT(std);
3826 arg_gbl.std = std;
3827 arg_gbl.lhs = 0;
3828 arg_gbl.used = FALSE;
3829 arg_gbl.inforall = FALSE;
3830 gbl.lineno = STD_LINENO(std);
3831 ast = STD_AST(std);
3832 switch (type = A_TYPEG(ast)) {
3833 case A_ASN:
3834 rhs = A_SRCG(ast);
3835 if (A_TYPEG(rhs) == A_HOVLPSHIFT || A_TYPEG(rhs) == A_HCSTART)
3836 break;
3837 lhs = A_DESTG(ast);
3838 sptr_lhs = sym_of_ast(lhs);
3839 open_pragma(STD_LINENO(std));
3840 if (expr_dependent(A_SRCG(ast), lhs, std, std))
3841 arg_gbl.used = TRUE;
3842 close_pragma();
3843 rewrite_asn(ast, std, TRUE, 0);
3844 break;
3845 case A_WHERE:
3846 lhs = A_DESTG(A_IFSTMTG(ast));
3847 sptr_lhs = sym_of_ast(lhs);
3848 if (expr_dependent(A_IFEXPRG(ast), lhs, std, std))
3849 arg_gbl.used = TRUE;
3850 assert(A_IFSTMTG(ast), "rewrite_calls: block where", 0, 4);
3851 rewrite_asn(A_IFSTMTG(ast), std, FALSE, 0);
3852 a = rewrite_sub_ast(A_IFEXPRG(ast), 0);
3853 A_IFEXPRP(ast, a);
3854 break;
3855 case A_IFTHEN:
3856 case A_IF:
3857 case A_AIF:
3858 case A_ELSEIF:
3859 case A_DOWHILE:
3860 case A_CGOTO:
3861 case A_DO:
3862 case A_MP_PDO:
3863 /* If the expression requires a temporary as part of its
3864 * evaluation, must make sure that the temp is freed before
3865 * the IF statement. Insert a dummy statement, then delete it.
3866 */
3867 astnew = mk_stmt(A_CONTINUE, 0);
3868 stdnew = add_stmt_before(astnew, std);
3869 arg_gbl.std = stdnew;
3870
3871 difficult.continue_std = stdnew;
3872 difficult.func_std = std;
3873 switch (type) {
3874 extern int assign_scalar(int, int); /* vsub.c */
3875 case A_IF:
3876 case A_ELSEIF:
3877 case A_AIF:
3878 case A_DOWHILE:
3879 case A_IFTHEN:
3880 a = rewrite_sub_ast(A_IFEXPRG(ast), 0);
3881 A_IFEXPRP(ast, a);
3882 break;
3883 case A_CGOTO:
3884 a = rewrite_sub_ast(A_LOPG(ast), 0);
3885 A_LOPP(ast, a);
3886 break;
3887 case A_DO:
3888 case A_MP_PDO:
3889 a = rewrite_sub_ast(A_M1G(ast), 0);
3890 if (a && contains_call(a)) {
3891 a = assign_scalar(std, a);
3892 }
3893 A_M1P(ast, a);
3894 a = rewrite_sub_ast(A_M2G(ast), 0);
3895 if (a && contains_call(a)) {
3896 a = assign_scalar(std, a);
3897 }
3898 A_M2P(ast, a);
3899 a = rewrite_sub_ast(A_M3G(ast), 0);
3900 if (a && contains_call(a)) {
3901 a = assign_scalar(std, a);
3902 }
3903 A_M3P(ast, a);
3904 a = rewrite_sub_ast(A_M4G(ast), 0);
3905 if (a && contains_call(a)) {
3906 a = assign_scalar(std, a);
3907 }
3908 A_M4P(ast, a);
3909 if (type == A_MP_PDO) {
3910 a = rewrite_sub_ast(A_LASTVALG(ast), 0);
3911 if (a && contains_call(a)) {
3912 a = assign_scalar(std, a);
3913 }
3914 A_LASTVALP(ast, a);
3915 }
3916 break;
3917 default:
3918 interr("rewrite_calls: unknown control ", ast, 4);
3919 break;
3920 }
3921 difficult.continue_std = difficult.func_std = 0;
3922 /* unlink the dummy statement */
3923 STD_NEXT(STD_PREV(stdnew)) = STD_NEXT(stdnew);
3924 STD_PREV(STD_NEXT(stdnew)) = STD_PREV(stdnew);
3925 arg_gbl.std = std;
3926 break;
3927 case A_ICALL:
3928 if (rewrite_sub_ast(ast, 0) != -1)
3929 ast_to_comment(ast);
3930 break;
3931 case A_CALL:
3932 if (elemental_func_call(ast)) {
3933 if (rewrite_sub_ast(ast, 0) != -1)
3934 ast_to_comment(ast);
3935 } else {
3936 args = rewrite_sub_args(ast, 0);
3937 A_ARGSP(ast, args);
3938 }
3939 break;
3940 case A_ALLOC:
3941 if (A_TKNG(ast) == TK_DEALLOCATE && !A_DALLOCMEMG(ast)) {
3942 if (A_TYPEG(A_SRCG(ast)) == A_SUBSCR) {
3943 A_SRCP(ast, A_LOPG(A_SRCG(ast)));
3944 }
3945 sptr_lhs = memsym_of_ast(A_SRCG(ast));
3946 if (allocatable_member(sptr_lhs)) {
3947 rewrite_deallocate(A_SRCG(ast), false, std);
3948 if (!ALLOCG(sptr_lhs) && !ALLOCATTRG(sptr_lhs) &&
3949 !POINTERG(sptr_lhs)) {
3950 /* Has allocatable members but item itself is not
3951 * allocatable nor pointer
3952 */
3953 nop_dealloc(sptr_lhs, ast);
3954 }
3955 }
3956 } else if (A_TKNG(ast) == TK_ALLOCATE) {
3957 int a, sptr2, astmem;
3958 sptr_lhs = memsym_of_ast(A_SRCG(ast));
3959 if (STYPEG(sptr_lhs) == ST_MEMBER) {
3960 astmem = A_SRCG(ast);
3961 } else {
3962 astmem = 0;
3963 }
3964 switch (A_TYPEG(A_STARTG(ast))) {
3965 case A_ID:
3966 case A_LABEL:
3967 case A_ENTRY:
3968 case A_SUBSCR:
3969 case A_SUBSTR:
3970 case A_MEM:
3971 sptr2 = (A_STARTG(ast)) ? memsym_of_ast(A_STARTG(ast)) : 0;
3972 break;
3973 default:
3974 sptr2 = 0;
3975 }
3976 if (sptr2 > NOSYM &&
3977 (CLASSG(sptr2) || (CLASSG(sptr_lhs) && ALLOCATTRG(sptr2)))) {
3978 check_pointer_type(A_SRCG(ast), A_STARTG(ast), std, 1);
3979 } else {
3980 a = A_DTYPEG(ast);
3981 if (DTY(a) == TY_ARRAY)
3982 a = DTY(a + 1);
3983
3984 if (CLASSG(sptr_lhs) || ALLOCDESCG(sptr_lhs) ||
3985 has_tbp_or_final(DTYPEG(sptr_lhs)) || has_tbp_or_final(a) ||
3986 is_or_has_poly(sptr_lhs) ||
3987 has_length_type_parameter_use(DTYPEG(sptr_lhs)) ||
3988 (sptr2 && !ALLOCATTRG(sptr_lhs) && has_poly_mbr(sptr_lhs, 1))) {
3989 check_alloc_ptr_type(sptr_lhs, std, a, 1, 1, A_SRCG(ast), astmem);
3990 }
3991 }
3992 }
3993 break;
3994 case A_ELSEWHERE:
3995 case A_ENDWHERE:
3996 case A_END:
3997 case A_STOP:
3998 case A_RETURN:
3999 case A_ELSE:
4000 case A_ENDIF:
4001 case A_ENDDO:
4002 case A_CONTINUE:
4003 case A_GOTO:
4004 case A_ASNGOTO:
4005 case A_AGOTO:
4006 case A_ENTRY:
4007 case A_PAUSE:
4008 case A_COMMENT:
4009 case A_COMSTR:
4010 case A_REDISTRIBUTE:
4011 case A_REALIGN:
4012 case A_HCFINISH:
4013 case A_MASTER:
4014 case A_ENDMASTER:
4015 case A_CRITICAL:
4016 case A_ENDCRITICAL:
4017 case A_ATOMIC:
4018 case A_ATOMICCAPTURE:
4019 case A_ATOMICREAD:
4020 case A_ATOMICWRITE:
4021 case A_ENDATOMIC:
4022 case A_BARRIER:
4023 case A_NOBARRIER:
4024 case A_MP_CRITICAL:
4025 case A_MP_ENDCRITICAL:
4026 case A_MP_ATOMIC:
4027 case A_MP_ENDATOMIC:
4028 case A_MP_MASTER:
4029 case A_MP_ENDMASTER:
4030 case A_MP_SINGLE:
4031 case A_MP_ENDSINGLE:
4032 case A_MP_BARRIER:
4033 case A_MP_TASKWAIT:
4034 case A_MP_TASKYIELD:
4035 case A_MP_ENDPDO:
4036 case A_MP_ENDSECTIONS:
4037 case A_MP_WORKSHARE:
4038 case A_MP_ENDWORKSHARE:
4039 case A_MP_BPDO:
4040 case A_MP_EPDO:
4041 case A_MP_SECTION:
4042 case A_MP_LSECTION:
4043 case A_MP_PRE_TLS_COPY:
4044 case A_MP_BCOPYIN:
4045 case A_MP_COPYIN:
4046 case A_MP_ECOPYIN:
4047 case A_MP_BCOPYPRIVATE:
4048 case A_MP_COPYPRIVATE:
4049 case A_MP_ECOPYPRIVATE:
4050 case A_MP_EMPSCOPE:
4051 case A_MP_BORDERED:
4052 case A_MP_EORDERED:
4053 case A_MP_FLUSH:
4054 case A_MP_TASKGROUP:
4055 case A_MP_ETASKGROUP:
4056 case A_MP_DISTRIBUTE:
4057 case A_MP_ENDDISTRIBUTE:
4058 case A_MP_ENDTARGETDATA:
4059 case A_MP_TASKREG:
4060 case A_MP_TASKDUP:
4061 case A_MP_ETASKDUP:
4062 break;
4063 case A_MP_TASKLOOPREG:
4064 case A_MP_ETASKLOOPREG:
4065 break;
4066 case A_MP_TASK:
4067 case A_MP_TASKLOOP:
4068 a = rewrite_sub_ast(A_IFPARG(ast), 0);
4069 A_IFPARP(ast, a);
4070 a = rewrite_sub_ast(A_FINALPARG(ast), 0);
4071 A_FINALPARP(ast, a);
4072 a = rewrite_sub_ast(A_PRIORITYG(ast), 0);
4073 A_PRIORITYP(ast, a);
4074 ++task_depth;
4075 set_descriptor_sc(SC_PRIVATE);
4076 break;
4077 case A_MP_ENDTASK:
4078 case A_MP_ETASKLOOP:
4079 --task_depth;
4080 if (parallel_depth == 0 && task_depth == 0) {
4081 set_descriptor_sc(SC_LOCAL);
4082 }
4083 break;
4084 case A_MP_BMPSCOPE:
4085 a = rewrite_sub_ast(A_STBLKG(ast), 0);
4086 A_STBLKP(ast, a);
4087 break;
4088 case A_MP_TASKFIRSTPRIV:
4089 a = rewrite_sub_ast(A_LOPG(ast), 0);
4090 A_LOPP(ast, a);
4091 a = rewrite_sub_ast(A_ROPG(ast), 0);
4092 A_ROPP(ast, a);
4093 break;
4094 case A_MP_PARALLEL:
4095 a = rewrite_sub_ast(A_IFPARG(ast), 0);
4096 A_IFPARP(ast, a);
4097 a = rewrite_sub_ast(A_NPARG(ast), 0);
4098 A_NPARP(ast, a);
4099 /* proc_bind is constant
4100 a = rewrite_sub_ast(A_PROCBINDG(ast), 0);
4101 A_PROCBINDP(ast, a);
4102 */
4103 ++parallel_depth;
4104 /*symutl.sc = SC_PRIVATE;*/
4105 set_descriptor_sc(SC_PRIVATE);
4106 break;
4107 case A_MP_TEAMS:
4108 a = rewrite_sub_ast(A_NTEAMSG(ast), 0);
4109 A_NTEAMSP(ast, a);
4110 a = rewrite_sub_ast(A_THRLIMITG(ast), 0);
4111 A_THRLIMITP(ast, a);
4112 break;
4113 case A_MP_ENDPARALLEL:
4114 --parallel_depth;
4115 if (parallel_depth == 0 && task_depth == 0) {
4116 /*symutl.sc = SC_LOCAL;*/
4117 set_descriptor_sc(SC_LOCAL);
4118 }
4119 break;
4120 case A_MP_ATOMICREAD:
4121 a = rewrite_sub_ast(A_SRCG(ast), 0);
4122 A_SRCP(ast, a);
4123 break;
4124 case A_MP_ATOMICWRITE:
4125 case A_MP_ATOMICUPDATE:
4126 case A_MP_ATOMICCAPTURE:
4127 a = rewrite_sub_ast(A_LOPG(ast), 0);
4128 A_LOPP(ast, a);
4129 a = rewrite_sub_ast(A_ROPG(ast), 0);
4130 A_ROPP(ast, a);
4131 break;
4132 case A_MP_ENDTEAMS:
4133 case A_MP_ENDTARGET:
4134 case A_MP_TARGET:
4135 break;
4136 case A_MP_CANCEL:
4137 a = rewrite_sub_ast(A_IFPARG(ast), 0);
4138 A_IFPARP(ast, a);
4139 case A_MP_SECTIONS:
4140 case A_MP_CANCELLATIONPOINT:
4141 a = rewrite_sub_ast(A_ENDLABG(ast), 0);
4142 A_ENDLABP(ast, a);
4143 break;
4144 case A_MP_TARGETDATA:
4145 case A_MP_TARGETENTERDATA:
4146 case A_MP_TARGETEXITDATA:
4147 case A_MP_TARGETUPDATE:
4148 a = rewrite_sub_ast(A_IFPARG(ast), 0);
4149 A_IFPARP(ast, a);
4150 break;
4151 case A_FORALL:
4152 arg_gbl.used = TRUE; /* don't use lhs for intrinsics */
4153 arg_gbl.inforall = TRUE;
4154 src = A_SRCG(ast);
4155 prevstd = STD_PREV(std);
4156 a = rewrite_sub_ast(A_IFEXPRG(ast), 0);
4157 A_IFEXPRP(ast, a);
4158 rewrite_asn(A_IFSTMTG(ast), std, TRUE, 0);
4159 arg_gbl.inforall = FALSE;
4160
4161 /* there is no std created from forall before, if it is
4162 * created now, show the first one */
4163 if (src == 0 && STD_PREV(std) != prevstd) {
4164 A_SRCP(ast, STD_NEXT(prevstd));
4165 assert(STD_NEXT(prevstd) != std, "rewrite_calls: something is wrong",
4166 std, 3);
4167 }
4168 break;
4169 case A_HLOCALIZEBNDS:
4170 case A_HCYCLICLP:
4171 lhs = A_LOPG(ast);
4172 assert(A_TYPEG(lhs) == A_ID, "rewrite_calls: id not found", ast, 3);
4173 sptr_lhs = A_SPTRG(lhs);
4174 assert(STYPEG(sptr_lhs) == ST_ARRDSC || STYPEG(sptr_lhs) == ST_ARRAY,
4175 "rewrite_calls: array not found", ast, 3);
4176 break;
4177 case A_HGETSCLR:
4178 case A_HOWNERPROC:
4179 break;
4180 case A_PREFETCH:
4181 break;
4182 case A_PRAGMA:
4183 a = rewrite_sub_ast(A_LOPG(ast), 0);
4184 A_LOPP(ast, a);
4185 a = rewrite_sub_ast(A_ROPG(ast), 0);
4186 A_ROPP(ast, a);
4187 break;
4188 case A_MP_EMAP:
4189 case A_MP_MAP:
4190 case A_MP_TARGETLOOPTRIPCOUNT:
4191 case A_MP_EREDUCTION:
4192 case A_MP_BREDUCTION:
4193 case A_MP_REDUCTIONITEM:
4194 break;
4195 default:
4196 interr("rewrite_subroutine: unknown stmt found", ast, 4);
4197 break;
4198 }
4199 }
4200 }
4201
4202 static void
nop_dealloc(int sptr,int ast)4203 nop_dealloc(int sptr, int ast)
4204 {
4205 if (SCG(sptr) == SC_LOCAL && AUTOBJG(sptr) && has_allocattr(sptr))
4206 return;
4207 ast_to_comment(ast);
4208 }
4209
4210 /*
4211 * call pghpf_reduce_descriptor(result$sd, kind, len, array$sd, dim)
4212 *
4213 * set up result descriptor for reduction intrinsic -- used when the
4214 * dim arg is variable. result dimensions are aligned with the
4215 * corresponding source dimensions and the result array becomes
4216 * replicated over the reduction dimension.
4217 */
4218
4219 static void
add_reduce_descriptor(int temp_sptr,int arr_sptr,int arr_ast,int dim)4220 add_reduce_descriptor(int temp_sptr, int arr_sptr, int arr_ast, int dim)
4221 {
4222 DTYPE dtype = DTYPEG(temp_sptr);
4223 int kind = mk_cval(dtype_to_arg(DTY(dtype + 1)), astb.bnd.dtype);
4224 int len = size_ast(temp_sptr, DDTG(dtype));
4225 int sptrFunc = sym_mkfunc_nodesc(mkRteRtnNm(RTE_reduce_descriptor), 0);
4226 int astStmt = begin_call(A_CALL, sptrFunc, 5);
4227 add_arg(mk_id(DESCRG(temp_sptr)));
4228 add_arg(kind);
4229 add_arg(len);
4230 add_arg(check_member(arr_ast, mk_id(DESCRG(arr_sptr))));
4231 add_arg(convert_int(dim, astb.bnd.dtype));
4232 add_stmt_before(astStmt, arg_gbl.std);
4233 }
4234
4235 /* call pghpf_spread_descriptor(result$sd, source$sd, dim, ncopies)
4236 *
4237 * set up result descriptor for spread intrinsic -- used when the dim
4238 * arg is variable. the added spread dimension is given a collapsed
4239 * distribution and the remaining dimensions are aligned with the
4240 * corresponding source dimensions. overlap allowances are set to
4241 * zero.
4242 */
4243
4244 static void
add_spread_descriptor(int temp_sptr,int arr_sptr,int arr_ast,int dim,int ncopies)4245 add_spread_descriptor(int temp_sptr, int arr_sptr, int arr_ast, int dim,
4246 int ncopies)
4247 {
4248 int sptrFunc;
4249 int astStmt;
4250
4251 dim = convert_int(dim, astb.bnd.dtype);
4252 ncopies = convert_int(ncopies, astb.bnd.dtype);
4253 sptrFunc = sym_mkfunc_nodesc(mkRteRtnNm(RTE_spread_descriptor), 0);
4254 astStmt = begin_call(A_CALL, sptrFunc, 4);
4255 add_arg(mk_id(DESCRG(temp_sptr)));
4256 add_arg(check_member(arr_ast, mk_id(DESCRG(arr_sptr))));
4257 add_arg(dim);
4258 add_arg(ncopies);
4259 add_stmt_before(astStmt, arg_gbl.std);
4260 }
4261
4262 /** \brief Make a temporary to be used as the argument to an intrinsic that
4263 returns an array.
4264 \param func_ast ast for the intrinsic call
4265 \param func_args rewritten args for the function
4266 \param subscr returned subscripts
4267 \param elem_dty data type of elements
4268 \param lhs passed lhs or zero
4269 \param retval returned ast for lhs
4270
4271 The actual size of this temp is derived from the
4272 arguments to the intrinsic. The subscripts of the temp may not
4273 be the entire temp; this is derived from the arguments as well.
4274
4275 If lhs is non-zero, check lhs to see if it is OK for the intended
4276 use; if so, return 0.
4277 */
4278 static int
mk_result_sptr(int func_ast,int func_args,int * subscr,int elem_dty,int lhs,int * retval)4279 mk_result_sptr(int func_ast, int func_args, int *subscr, int elem_dty, int lhs,
4280 int *retval)
4281 {
4282 int temp_sptr;
4283 int dim;
4284 int shape;
4285 int shape1;
4286 int rank, rank1;
4287 int arg;
4288 int ncopies;
4289
4290 shape = A_SHAPEG(func_ast);
4291 switch (A_OPTYPEG(func_ast)) {
4292 case I_MINLOC:
4293 case I_MAXLOC:
4294 case I_FINDLOC:
4295 case I_ALL:
4296 case I_ANY:
4297 case I_COUNT:
4298 case I_MAXVAL:
4299 case I_MINVAL:
4300 case I_PRODUCT:
4301 case I_SUM:
4302 case I_NORM2:
4303 arg = ARGT_ARG(func_args, 0);
4304 /* first arg with dimension removed */
4305 dim = A_OPTYPEG(func_ast) == I_FINDLOC ? ARGT_ARG(func_args, 2)
4306 : ARGT_ARG(func_args, 1);
4307 assert(dim != 0, "mk_result_sptr: dim must be constant", 0, 4);
4308 /* We know that the first argument is an array section or whole
4309 * array, so we can squeeze out the dimension & just use the
4310 * existing subscripts.
4311 */
4312 temp_sptr = chk_reduc_sptr(arg, "r", subscr, elem_dty, dim, lhs, retval);
4313 /* non-constant DIM */
4314 if (!A_ALIASG(dim) && temp_sptr && A_SHAPEG(arg)) {
4315 int array, arrayast;
4316 array = find_array(arg, &arrayast);
4317 add_reduce_descriptor(temp_sptr, array, arrayast, dim);
4318 }
4319
4320 /* make the subscripts for the result */
4321 break;
4322 case I_UNPACK:
4323 /* mask (second arg) */
4324 arg = ARGT_ARG(func_args, 1);
4325 goto easy;
4326 case I_CSHIFT:
4327 case I_EOSHIFT:
4328 arg = ARGT_ARG(func_args, 0);
4329 while (A_TYPEG(arg) == A_INTR &&
4330 (A_OPTYPEG(arg) == I_CSHIFT || A_OPTYPEG(arg) == I_EOSHIFT)) {
4331 int fargs = A_ARGSG(arg);
4332 arg = ARGT_ARG(fargs, 0);
4333 }
4334 if (lhs == 0)
4335 goto easy;
4336 rank = SHD_NDIM(shape);
4337 if (arg_gbl.lhs) {
4338 shape1 = A_SHAPEG(arg_gbl.lhs);
4339 rank1 = SHD_NDIM(shape1);
4340 if (rank == rank1 && !arg_gbl.used &&
4341 DTY(A_DTYPEG(arg_gbl.lhs) + 1) == elem_dty) {
4342 *retval = arg_gbl.lhs;
4343 temp_sptr = 0;
4344 arg_gbl.used = TRUE;
4345 break;
4346 }
4347 if (rank == rank1) {
4348 temp_sptr =
4349 chk_assign_sptr(arg_gbl.lhs, "r", subscr, elem_dty, lhs, retval);
4350 break;
4351 }
4352 }
4353 goto easy;
4354
4355 easy:
4356 if (ast_has_allocatable_member(lhs)) {
4357 goto temp_from_shape;
4358 }
4359 temp_sptr = chk_assign_sptr(arg, "r", subscr, elem_dty, lhs, retval);
4360 break;
4361 case I_SPREAD:
4362 /* first arg with dimension added */
4363 arg = ARGT_ARG(func_args, 0);
4364 dim = ARGT_ARG(func_args, 1);
4365 ncopies = ARGT_ARG(func_args, 2);
4366 assert(dim != 0, "mk_result_sptr: dim must be constant", 0, 4);
4367
4368 temp_sptr =
4369 mk_spread_sptr(arg, "r", subscr, elem_dty, dim, ncopies, lhs, retval);
4370 /* non-constant DIM */
4371 if (!A_ALIASG(dim) && temp_sptr && A_SHAPEG(arg)) {
4372 int array, arrayast;
4373 array = find_array(arg, &arrayast);
4374 add_spread_descriptor(temp_sptr, array, arrayast, dim, ncopies);
4375 }
4376
4377 break;
4378 case I_MATMUL:
4379 case I_MATMUL_TRANSPOSE:
4380 rank = SHD_NDIM(shape);
4381 if (matmul_use_lhs(lhs, rank, elem_dty)) {
4382 *retval = arg_gbl.lhs;
4383 temp_sptr = 0;
4384 arg_gbl.used = TRUE;
4385 break;
4386 }
4387 if (A_OPTYPEG(func_ast) == I_MATMUL_TRANSPOSE) {
4388 /* NOTE: this assumes that I_MATMUL_TRANSPOSE is
4389 * generated for the transpose of the first arg only
4390 */
4391 int tmp_shape = A_SHAPEG(ARGT_ARG(func_args, 0));
4392 arg = mk_id(mk_shape_sptr(tmp_shape, subscr, elem_dty));
4393 arg = mk_id(mk_transpose_sptr(arg, "r", subscr, elem_dty, retval));
4394 } else {
4395 arg = ARGT_ARG(func_args, 0);
4396 }
4397
4398 /* first and second args */
4399 temp_sptr = mk_matmul_sptr(arg, ARGT_ARG(func_args, 1), "r", subscr,
4400 elem_dty, retval);
4401 break;
4402 case I_TRANSPOSE:
4403 /* first arg */
4404 goto temp_from_shape;
4405 case I_PACK:
4406 /* problem */
4407 /* just make a 1-d temp with the appropriate size and no dist */
4408 temp_sptr = mk_pack_sptr(shape, elem_dty);
4409 subscr[0] = mk_triple(SHD_LWB(shape, 0), SHD_UPB(shape, 0), 0);
4410 *retval = mk_id(temp_sptr);
4411 break;
4412 case I_RESHAPE:
4413 case I_TRANSFER:
4414 temp_from_shape:
4415 /* make a temp out of the shape, no distribution */
4416 temp_sptr = mk_shape_sptr(shape, subscr, elem_dty);
4417 *retval = mk_id(temp_sptr);
4418 break;
4419 default:
4420 interr("mk_result_sptr: can't handle intrinsic", func_ast, 4);
4421 break;
4422 }
4423 return temp_sptr;
4424 }
4425
4426 static LOGICAL
matmul_use_lhs(int lhs,int rank,int elem_dty)4427 matmul_use_lhs(int lhs, int rank, int elem_dty)
4428 {
4429 if (lhs && arg_gbl.lhs) {
4430 /*
4431 * the LHS cannot be a member whose shape comes froms a parent
4432 */
4433 int array;
4434 if (A_TYPEG(arg_gbl.lhs) == A_MEM && A_SHAPEG(A_PARENTG(arg_gbl.lhs)) != 0)
4435 return FALSE;
4436 /*
4437 * the LHS cannot be an allocatable if -Mallocatable=03 is enabled
4438 */
4439 array = find_array(arg_gbl.lhs, NULL);
4440 if (XBIT(54, 0x1) && ALLOCATTRG(array))
4441 return FALSE;
4442 if (rank == SHD_NDIM(A_SHAPEG(arg_gbl.lhs)) && arg_gbl.used == 0 &&
4443 DTY(A_DTYPEG(arg_gbl.lhs) + 1) == elem_dty) {
4444 return TRUE;
4445 }
4446 }
4447 return FALSE;
4448 }
4449
4450 int
search_conform_array(int ast,int flag)4451 search_conform_array(int ast, int flag)
4452 {
4453 int i;
4454 int argt;
4455 int nargs;
4456 int j;
4457
4458 switch (A_TYPEG(ast)) {
4459 case A_SUBSCR:
4460 if (A_SHAPEG(ast) != 0 && flag &&
4461 (A_TYPEG(A_LOPG(ast)) == A_ID || A_TYPEG(A_LOPG(ast)) == A_MEM))
4462 return ast;
4463 return 0;
4464 case A_SUBSTR:
4465 return search_conform_array(A_LOPG(ast), flag);
4466 case A_ID:
4467 if (A_SHAPEG(ast))
4468 return ast;
4469 return 0;
4470 case A_BINOP:
4471 i = search_conform_array(A_LOPG(ast), flag);
4472 if (i != 0)
4473 return i;
4474 return search_conform_array(A_ROPG(ast), flag);
4475 case A_UNOP:
4476 case A_CONV:
4477 return search_conform_array(A_LOPG(ast), flag);
4478 case A_MEM:
4479 if (A_SHAPEG(A_MEMG(ast)))
4480 return ast;
4481 return search_conform_array(A_PARENTG(ast), flag);
4482 case A_INTR:
4483 argt = A_ARGSG(ast);
4484 nargs = A_ARGCNTG(ast);
4485 if (INKINDG(A_SPTRG(A_LOPG(ast))) != IK_ELEMENTAL) {
4486 switch (A_OPTYPEG(ast)) {
4487 case I_CSHIFT:
4488 case I_EOSHIFT:
4489 return search_conform_array(ARGT_ARG(argt, 0), flag);
4490 case I_SPREAD:
4491 case I_SUM:
4492 case I_PRODUCT:
4493 case I_MAXVAL:
4494 case I_MINVAL:
4495 case I_DOT_PRODUCT:
4496 case I_ALL:
4497 case I_ANY:
4498 case I_COUNT:
4499 return ast;
4500 case I_TRANSPOSE:
4501 return ast;
4502 default:
4503 return 0;
4504 }
4505 }
4506 for (i = 0; i < nargs; ++i)
4507 if (A_SHAPEG(ARGT_ARG(argt, i)))
4508 if ((j = search_conform_array(ARGT_ARG(argt, i), flag)) != 0)
4509 return j;
4510 case A_FUNC:
4511 if (elemental_func_call(ast)) {
4512 /* search up to all arguments of elemental function for
4513 * a conformable array -- not just the first argument.
4514 */
4515 argt = A_ARGSG(ast);
4516 nargs = A_ARGCNTG(ast);
4517 for (i = 0; i < nargs; ++i) {
4518 if ((j = search_conform_array(ARGT_ARG(argt, i), flag)))
4519 return j;
4520 }
4521 }
4522 return 0;
4523 default:
4524 return 0;
4525 }
4526 }
4527
4528 /* Pointer association status (logical function):
4529 * associated(pv [, target] )
4530 * external pghpf_associated
4531 * logical pghpf_associated
4532 * ( pghpf_associated(pv, pv$sdsc, target, target$d) )
4533 */
4534 static int
transform_associated(int std,int ast)4535 transform_associated(int std, int ast)
4536 {
4537 int ast1;
4538 int argt, nargs;
4539 int pv, arr;
4540 int pv_sptr, arr_sptr;
4541 int arr_desc, static_desc;
4542 int dtype;
4543 int func;
4544 int ty;
4545 int with_target;
4546
4547 assert(A_TYPEG(ast) == A_INTR && A_OPTYPEG(ast) == I_ASSOCIATED,
4548 "transform_associated: not ASSOCIATED call", 2, ast);
4549
4550 with_target = 0;
4551 argt = A_ARGSG(ast);
4552 nargs = A_ARGCNTG(ast);
4553 assert(nargs == 2,
4554 "transform_associated: ASSOCIATED with wrong number arguments", 2,
4555 ast);
4556 pv = ARGT_ARG(argt, 0);
4557 arr = ARGT_ARG(argt, 1);
4558 arr_desc = 0;
4559 assert(A_TYPEG(pv) == A_ID || A_TYPEG(pv) == A_MEM,
4560 "transform_associated: ASSOCIATED(V) where V is not an ID", 2, ast);
4561 if (A_TYPEG(pv) == A_ID) {
4562 pv_sptr = A_SPTRG(pv);
4563 } else if (A_TYPEG(pv) == A_MEM) {
4564 pv_sptr = A_SPTRG(A_MEMG(pv));
4565 }
4566 dtype = DTYPEG(pv_sptr);
4567 DESCUSEDP(pv_sptr, 1);
4568
4569 arr_sptr = 0;
4570 if (arr) {
4571 switch (A_TYPEG(arr)) {
4572 case A_SUBSCR:
4573 case A_MEM:
4574 case A_ID:
4575 arr_sptr = memsym_of_ast(arr);
4576 break;
4577 default:
4578 assert(0, "transform_associated: ASSOCIATED(V,P) where P is not an ID", 2,
4579 ast);
4580 }
4581 }
4582
4583 if (!arr)
4584 return ast;
4585 /* if this is an undistributed scalar pointer,
4586 * and there is no array 2nd argument, leave this as it is */
4587 if (DTY(dtype) != TY_ARRAY) {
4588 /* 2nd argument must also be scalar */
4589 switch (A_TYPEG(arr)) {
4590 case A_ID:
4591 case A_MEM:
4592 /* must not be an array */
4593 if (DTY(DTYPEG(arr_sptr)) != TY_ARRAY)
4594 return ast;
4595 break;
4596 }
4597 }
4598
4599 if (arr) {
4600 with_target = 1;
4601 DESCUSEDP(arr_sptr, 1);
4602 if (A_SHAPEG(arr) && A_TYPEG(arr) == A_SUBSCR) {
4603 arr_desc = mk_id(make_sec_from_ast(arr, std, std, 0, 0));
4604 arr = A_LOPG(arr);
4605 } else if (A_SHAPEG(arr) && (A_TYPEG(arr) == A_ID || A_TYPEG(arr) == A_MEM))
4606 arr_desc = mk_id(DESCRG(arr_sptr));
4607 else {
4608 ty = dtype_to_arg(A_DTYPEG(arr));
4609 arr_desc = mk_isz_cval(ty, astb.bnd.dtype);
4610 }
4611 } else {
4612 if (DTYG(dtype) == TY_CHAR)
4613 arr = astb.ptr0c;
4614 else
4615 arr = astb.ptr0;
4616 arr_desc = astb.bnd.one;
4617 }
4618 assert(arr_desc, "transform_associated: need descriptor", 2, arr);
4619
4620 if (!POINTERG(pv_sptr))
4621 error(506, 3, STD_LINENO(std), SYMNAME(pv_sptr), CNULL);
4622 static_desc = mk_id(SDSCG(pv_sptr));
4623
4624 nargs = 4;
4625 if (XBIT(70, 0x20)) {
4626 if (MIDNUMG(pv_sptr))
4627 ++nargs;
4628 if (PTROFFG(pv_sptr))
4629 ++nargs;
4630 }
4631 argt = mk_argt(nargs);
4632 ARGT_ARG(argt, 0) = pv;
4633 ARGT_ARG(argt, 1) = check_member(pv, static_desc);
4634 ARGT_ARG(argt, 2) = arr;
4635 ARGT_ARG(argt, 3) = check_member(arr, arr_desc);
4636 nargs = 4;
4637 if (XBIT(70, 0x20)) {
4638 if (MIDNUMG(pv_sptr)) {
4639 ARGT_ARG(argt, nargs) = check_member(pv, mk_id(MIDNUMG(pv_sptr)));
4640 ++nargs;
4641 }
4642 if (PTROFFG(pv_sptr)) {
4643 ARGT_ARG(argt, nargs) = check_member(pv, mk_id(PTROFFG(pv_sptr)));
4644 ++nargs;
4645 }
4646 }
4647
4648 if (with_target) {
4649 if (DTYG(dtype) == TY_CHAR)
4650 func = mk_id(sym_mkfunc(mkRteRtnNm(RTE_associated_tchara), DT_LOG));
4651 else
4652 func = mk_id(sym_mkfunc(mkRteRtnNm(RTE_associated_t), DT_LOG));
4653 } else {
4654 if (DTYG(dtype) == TY_CHAR)
4655 func = mk_id(sym_mkfunc(mkRteRtnNm(RTE_associated_chara), DT_LOG));
4656 else
4657 func = mk_id(sym_mkfunc(mkRteRtnNm(RTE_associated), DT_LOG));
4658 }
4659
4660 ast1 = mk_func_node(A_FUNC, func, nargs, argt);
4661
4662 NODESCP(A_SPTRG(A_LOPG(ast1)), 1);
4663 A_DTYPEP(ast1, DT_LOG);
4664 return ast1;
4665 }
4666
4667 /* func_ast: A_FUNC or A_INTR */
4668 /* func_args: rewritten args */
4669 static void
transform_mvbits(int func_ast,int func_args)4670 transform_mvbits(int func_ast, int func_args)
4671 {
4672 int lb, ub, st;
4673 int forall, dovar;
4674 int ast;
4675 int lineno;
4676 int stdnext, std;
4677 int newast;
4678 int to;
4679 int shape;
4680 int i, n;
4681 int triplet_list, index_var;
4682 int triplet;
4683 int newargt;
4684 int nargs;
4685
4686 assert(A_TYPEG(func_ast) == A_ICALL && A_OPTYPEG(func_ast) == I_MVBITS,
4687 "transform_mvbits: something is wrong", 2, func_ast);
4688
4689 stdnext = arg_gbl.std;
4690 lineno = STD_LINENO(stdnext);
4691
4692 to = ARGT_ARG(func_args, 3);
4693 shape = A_SHAPEG(to);
4694 if (!shape) {
4695 return;
4696 }
4697
4698 forall = make_forall(shape, to, 0, 0);
4699
4700 n = 0;
4701 triplet_list = A_LISTG(forall);
4702 for (; triplet_list; triplet_list = ASTLI_NEXT(triplet_list)) {
4703 n++;
4704 newast = mk_stmt(A_DO, 0);
4705 index_var = ASTLI_SPTR(triplet_list);
4706 triplet = ASTLI_TRIPLE(triplet_list);
4707 dovar = mk_id(index_var);
4708 A_DOVARP(newast, dovar);
4709 lb = A_LBDG(triplet);
4710 ub = A_UPBDG(triplet);
4711 st = A_STRIDEG(triplet);
4712
4713 A_M1P(newast, lb);
4714 A_M2P(newast, ub);
4715 A_M3P(newast, st);
4716 A_M4P(newast, 0);
4717
4718 std = add_stmt_before(newast, stdnext);
4719 STD_LINENO(std) = lineno;
4720 STD_PAR(std) = STD_PAR(stdnext);
4721 STD_TASK(std) = STD_TASK(stdnext);
4722 STD_ACCEL(std) = STD_ACCEL(stdnext);
4723 STD_KERNEL(std) = STD_KERNEL(stdnext);
4724 }
4725
4726 nargs = 5;
4727 newargt = mk_argt(nargs);
4728
4729 for (i = 0; i < 5; i++) {
4730 ast = ARGT_ARG(func_args, i);
4731 ast = normalize_forall(forall, ast, 0);
4732 ARGT_ARG(newargt, i) = ast;
4733 }
4734
4735 newast = mk_func_node(A_ICALL, A_LOPG(func_ast), nargs, newargt);
4736 A_OPTYPEP(newast, A_OPTYPEG(func_ast));
4737 std = add_stmt_before(newast, stdnext);
4738 STD_LINENO(std) = lineno;
4739 STD_PAR(std) = STD_PAR(stdnext);
4740 STD_TASK(std) = STD_TASK(stdnext);
4741 STD_ACCEL(std) = STD_ACCEL(stdnext);
4742 STD_KERNEL(std) = STD_KERNEL(stdnext);
4743
4744 for (i = 0; i < n; i++) {
4745 newast = mk_stmt(A_ENDDO, 0);
4746 std = add_stmt_before(newast, stdnext);
4747 STD_LINENO(std) = lineno;
4748 STD_PAR(std) = STD_PAR(stdnext);
4749 STD_TASK(std) = STD_TASK(stdnext);
4750 STD_ACCEL(std) = STD_ACCEL(stdnext);
4751 STD_KERNEL(std) = STD_KERNEL(stdnext);
4752 }
4753 delete_stmt(arg_gbl.std);
4754 }
4755
4756 /* func_ast: A_FUNC or A_INTR */
4757 /* func_args: rewritten args */
4758 static void
transform_merge(int func_ast,int func_args)4759 transform_merge(int func_ast, int func_args)
4760 {
4761 int lb, ub, st;
4762 int forall, dovar;
4763 int ast;
4764 int lineno;
4765 int stdnext, std;
4766 int newast;
4767 int temp;
4768 int shape;
4769 int i, n;
4770 int triplet_list, index_var;
4771 int triplet;
4772 int newargt;
4773 int nargs;
4774
4775 assert(A_TYPEG(func_ast) == A_ICALL && A_OPTYPEG(func_ast) == I_MERGE,
4776 "transform_merge: something is wrong", 2, func_ast);
4777
4778 stdnext = arg_gbl.std;
4779 lineno = STD_LINENO(stdnext);
4780
4781 temp = ARGT_ARG(func_args, 0);
4782 shape = A_SHAPEG(temp);
4783 if (!shape) {
4784 A_TYPEP(func_ast, A_CALL);
4785 return;
4786 }
4787
4788 forall = make_forall(shape, temp, 0, 0);
4789
4790 n = 0;
4791 triplet_list = A_LISTG(forall);
4792 for (; triplet_list; triplet_list = ASTLI_NEXT(triplet_list)) {
4793 n++;
4794 newast = mk_stmt(A_DO, 0);
4795 index_var = ASTLI_SPTR(triplet_list);
4796 triplet = ASTLI_TRIPLE(triplet_list);
4797 dovar = mk_id(index_var);
4798 A_DOVARP(newast, dovar);
4799 lb = A_LBDG(triplet);
4800 ub = A_UPBDG(triplet);
4801 st = A_STRIDEG(triplet);
4802
4803 A_M1P(newast, lb);
4804 A_M2P(newast, ub);
4805 A_M3P(newast, st);
4806 A_M4P(newast, 0);
4807
4808 std = add_stmt_before(newast, stdnext);
4809 STD_LINENO(std) = lineno;
4810 STD_PAR(std) = STD_PAR(stdnext);
4811 STD_TASK(std) = STD_TASK(stdnext);
4812 STD_ACCEL(std) = STD_ACCEL(stdnext);
4813 STD_KERNEL(std) = STD_KERNEL(stdnext);
4814 }
4815
4816 nargs = ARGT_CNT(func_args);
4817 newargt = mk_argt(nargs);
4818
4819 for (i = 0; i < nargs; i++) {
4820 ast = ARGT_ARG(func_args, i);
4821 ast = normalize_forall(forall, ast, 0);
4822 ARGT_ARG(newargt, i) = ast;
4823 }
4824
4825 newast = mk_func_node(A_CALL, A_LOPG(func_ast), nargs, newargt);
4826 A_OPTYPEP(newast, A_OPTYPEG(func_ast));
4827 std = add_stmt_before(newast, stdnext);
4828 STD_LINENO(std) = lineno;
4829 STD_PAR(std) = STD_PAR(stdnext);
4830 STD_TASK(std) = STD_TASK(stdnext);
4831 STD_ACCEL(std) = STD_ACCEL(stdnext);
4832 STD_KERNEL(std) = STD_KERNEL(stdnext);
4833
4834 for (i = 0; i < n; i++) {
4835 newast = mk_stmt(A_ENDDO, 0);
4836 std = add_stmt_before(newast, stdnext);
4837 STD_LINENO(std) = lineno;
4838 STD_PAR(std) = STD_PAR(stdnext);
4839 STD_TASK(std) = STD_TASK(stdnext);
4840 STD_ACCEL(std) = STD_ACCEL(stdnext);
4841 STD_KERNEL(std) = STD_KERNEL(stdnext);
4842 }
4843 delete_stmt(arg_gbl.std);
4844 }
4845
4846 static void
transform_elemental(int func_ast,int func_args)4847 transform_elemental(int func_ast, int func_args)
4848 {
4849 int lb, ub, st;
4850 int forall, dovar;
4851 int ast;
4852 int lineno;
4853 int stdnext, std;
4854 int newast;
4855 int temp;
4856 int shape;
4857 int i, n;
4858 int triplet_list, index_var;
4859 int triplet;
4860 int newargt;
4861 int nargs;
4862
4863 assert(A_TYPEG(func_ast) == A_CALL && elemental_func_call(func_ast),
4864 "transform_merge: something is wrong", func_ast, 3);
4865
4866 stdnext = arg_gbl.std;
4867 lineno = STD_LINENO(stdnext);
4868
4869 temp = ARGT_ARG(func_args, 0);
4870 shape = extract_shape_from_args(func_ast);
4871 if (!shape) {
4872 A_TYPEP(func_ast, A_CALL);
4873 return;
4874 }
4875
4876 forall = make_forall(shape, temp, 0, 0);
4877
4878 n = 0;
4879 triplet_list = A_LISTG(forall);
4880 for (; triplet_list; triplet_list = ASTLI_NEXT(triplet_list)) {
4881 n++;
4882 newast = mk_stmt(A_DO, 0);
4883 index_var = ASTLI_SPTR(triplet_list);
4884 triplet = ASTLI_TRIPLE(triplet_list);
4885 dovar = mk_id(index_var);
4886 A_DOVARP(newast, dovar);
4887 lb = A_LBDG(triplet);
4888 ub = A_UPBDG(triplet);
4889 st = A_STRIDEG(triplet);
4890
4891 A_M1P(newast, lb);
4892 A_M2P(newast, ub);
4893 A_M3P(newast, st);
4894 A_M4P(newast, 0);
4895
4896 std = add_stmt_before(newast, stdnext);
4897 STD_LINENO(std) = lineno;
4898 STD_PAR(std) = STD_PAR(stdnext);
4899 STD_TASK(std) = STD_TASK(stdnext);
4900 STD_ACCEL(std) = STD_ACCEL(stdnext);
4901 STD_KERNEL(std) = STD_KERNEL(stdnext);
4902 }
4903
4904 nargs = ARGT_CNT(func_args);
4905 newargt = mk_argt(nargs);
4906
4907 for (i = 0; i < nargs; i++) {
4908 ast = ARGT_ARG(func_args, i);
4909 ast = normalize_forall(forall, ast, 0);
4910 ARGT_ARG(newargt, i) = ast;
4911 }
4912
4913 newast = mk_func_node(A_CALL, A_LOPG(func_ast), nargs, newargt);
4914 A_OPTYPEP(newast, A_OPTYPEG(func_ast));
4915 A_INVOKING_DESCP(newast, A_INVOKING_DESCG(func_ast));
4916 std = add_stmt_before(newast, stdnext);
4917 STD_LINENO(std) = lineno;
4918 STD_PAR(std) = STD_PAR(stdnext);
4919 STD_TASK(std) = STD_TASK(stdnext);
4920 STD_ACCEL(std) = STD_ACCEL(stdnext);
4921 STD_KERNEL(std) = STD_KERNEL(stdnext);
4922
4923 for (i = 0; i < n; i++) {
4924 newast = mk_stmt(A_ENDDO, 0);
4925 std = add_stmt_before(newast, stdnext);
4926 STD_LINENO(std) = lineno;
4927 STD_PAR(std) = STD_PAR(stdnext);
4928 STD_TASK(std) = STD_TASK(stdnext);
4929 STD_ACCEL(std) = STD_ACCEL(stdnext);
4930 STD_KERNEL(std) = STD_KERNEL(stdnext);
4931 }
4932 delete_stmt(arg_gbl.std);
4933 }
4934
4935 /* move_alloc(from, to) */
4936 static void
transform_move_alloc(int func_ast,int func_args)4937 transform_move_alloc(int func_ast, int func_args)
4938 {
4939 int std;
4940 int pvar, pvar2;
4941 int shape, shape2;
4942 int desc, desc2;
4943 SPTR sptr, sptr2;
4944 int func, nargs, newast, newargt;
4945 int stdnext = arg_gbl.std;
4946 int lineno = STD_LINENO(stdnext);
4947 int fptr = ARGT_ARG(func_args, 0);
4948 int fptr2 = ARGT_ARG(func_args, 1);
4949
4950 move_alloc_arg(fptr, &sptr, &pvar);
4951 move_alloc_arg(fptr2, &sptr2, &pvar2);
4952
4953 desc = find_descriptor_ast(sptr, fptr);
4954 assert(desc, "transform_move_alloc: invalid 'from' descriptor", sptr,
4955 ERR_Fatal);
4956 desc2 = find_descriptor_ast(sptr2, fptr2);
4957 assert(desc2, "transform_move_alloc: invalid 'to' descriptor", sptr2,
4958 ERR_Fatal);
4959
4960 func = mk_id(sym_mkfunc_nodesc_expst(mkRteRtnNm(RTE_move_alloc), DT_INT));
4961 nargs = 4;
4962 newargt = mk_argt(nargs);
4963 ARGT_ARG(newargt, 0) = pvar; /* from ptr */
4964 ARGT_ARG(newargt, 1) = desc; /* from descriptor */
4965 ARGT_ARG(newargt, 2) = pvar2; /* to ptr */
4966 ARGT_ARG(newargt, 3) = desc2; /* to descriptor */
4967 newast = mk_func_node(A_CALL, func, nargs, newargt);
4968 std = add_stmt_before(newast, stdnext);
4969
4970 STD_LINENO(std) = lineno;
4971 STD_PAR(std) = STD_PAR(stdnext);
4972 STD_TASK(std) = STD_TASK(stdnext);
4973 STD_ACCEL(std) = STD_ACCEL(stdnext);
4974 STD_KERNEL(std) = STD_KERNEL(stdnext);
4975 if (A_SHAPEG(fptr2) && sptr != sptr2 && !SDSCG(sptr2)) {
4976 int parent = STYPEG(sptr) == ST_MEMBER ? A_PARENTG(fptr) : 0;
4977 int parent2 = STYPEG(sptr2) == ST_MEMBER ? A_PARENTG(fptr2) : 0;
4978 copy_surrogate_to_bnds_vars(DTYPEG(sptr2), parent2, DTYPEG(sptr), parent,
4979 STD_NEXT(std));
4980 }
4981
4982 delete_stmt(arg_gbl.std);
4983 }
4984
4985 static void
transform_c_f_pointer(int func_ast,int func_args)4986 transform_c_f_pointer(int func_ast, int func_args)
4987 {
4988 /*
4989 * c_f_pointer(cptr, fptr) -- fptr is scalar
4990 * c_f_pointer(cptr, fptr, shape) -- fptr is array
4991 */
4992 int lineno;
4993 int stdnext, std;
4994 int newast;
4995 int rank;
4996 int fptr;
4997 int cptr, newcptrarg;
4998 int pvar;
4999 int shape;
5000 int desc;
5001 int fty;
5002 int dtype;
5003 int func;
5004 int nargs;
5005 int newargt;
5006 int sptr;
5007 int shpty;
5008 int sz;
5009
5010 stdnext = arg_gbl.std;
5011 lineno = STD_LINENO(stdnext);
5012 fptr = ARGT_ARG(func_args, 1);
5013 cptr = ARGT_ARG(func_args, 0);
5014 /*
5015 * pass the address of fptr$p instead of just referencing fptr.
5016 */
5017 dtype = A_DTYPEG(fptr);
5018 if (A_TYPEG(fptr) == A_ID)
5019 sptr = A_SPTRG(fptr);
5020 else if (A_TYPEG(fptr) == A_MEM)
5021 sptr = A_SPTRG(A_MEMG(fptr));
5022 else
5023 sptr = 0;
5024 if (sptr && MIDNUMG(sptr)) {
5025 pvar = check_member(fptr, mk_id(MIDNUMG(sptr)));
5026 } else {
5027 interr("FPTR error in c_f_pointer()", fptr, 4);
5028 }
5029
5030 /* if argument:cptr does not have type(c_ptr), create a temporary
5031 * and assign its location to that temp. Pass that temp to
5032 * c_f_pointer.
5033 */
5034 if (!is_iso_c_ptr(A_DTYPEG(cptr)) && !is_cuf_c_devptr(A_DTYPEG(cptr))) {
5035 DTYPE dt = get_iso_c_ptr();
5036 if (dt <= DT_NONE)
5037 interr("Error in c_f_pointer() - unable to find c_ptr type", fptr, 4);
5038 newcptrarg = mk_id(get_temp(dt));
5039 cptr = mk_unop(OP_LOC, cptr, DT_PTR);
5040 cptr = mk_assn_stmt(newcptrarg, cptr, dt);
5041 add_stmt_before(cptr, arg_gbl.std);
5042 cptr = newcptrarg;
5043 }
5044
5045 shape = A_SHAPEG(fptr);
5046 if (!shape) { /* scalar */
5047 rank = 0;
5048 desc = astb.i0;
5049 shape = astb.i0;
5050 shpty = astb.i0;
5051 } else {
5052 /*
5053 * pass the address of fptr$sd
5054 */
5055 rank = SHD_NDIM(shape);
5056 if (SDSCG(sptr)) {
5057 desc = check_member(fptr, mk_id(SDSCG(sptr)));
5058 DESCUSEDP(sptr, 1);
5059 NODESCP(sptr, 0);
5060 } else {
5061 desc = check_member(fptr, mk_id(DESCRG(sptr)));
5062 DESCUSEDP(sptr, 1);
5063 NODESCP(sptr, 0);
5064 }
5065 shape = ARGT_ARG(func_args, 2);
5066 shpty = dtype_to_arg(DTY(A_DTYPEG(shape) + 1));
5067 shpty = mk_cval(shpty, astb.bnd.dtype);
5068 }
5069
5070 dtype = DDTG(dtype);
5071 fty = dtype_to_arg(dtype);
5072 fty = mk_cval(fty, astb.bnd.dtype);
5073 switch (DTY(dtype)) {
5074 case TY_CHAR:
5075 case TY_NCHAR:
5076 sz = ast_intr(I_LEN, astb.bnd.dtype, 1, fptr);
5077 break;
5078 default:
5079 sz = mk_cval(size_of(dtype), astb.bnd.dtype);
5080 break;
5081 }
5082 func = mk_id(sym_mkfunc_nodesc_expst(mkRteRtnNm(RTE_c_f_ptr), DT_INT));
5083
5084 nargs = 8;
5085 newargt = mk_argt(nargs);
5086 ARGT_ARG(newargt, 0) = cptr; /* cptr */
5087 ARGT_ARG(newargt, 1) = mk_cval(rank, astb.bnd.dtype); /* rank */
5088 ARGT_ARG(newargt, 2) = sz; /* len/size of fptr */
5089 ARGT_ARG(newargt, 3) = pvar; /* fptr$p */
5090 ARGT_ARG(newargt, 4) = desc; /* fptr$sd */
5091 ARGT_ARG(newargt, 5) = fty; /* eltype of fptr */
5092 ARGT_ARG(newargt, 6) = shape; /* shape */
5093 ARGT_ARG(newargt, 7) = shpty; /* eltype of shape */
5094 newast = mk_func_node(A_CALL, func, nargs, newargt);
5095 std = add_stmt_before(newast, stdnext);
5096 STD_LINENO(std) = lineno;
5097 STD_PAR(std) = STD_PAR(stdnext);
5098 STD_TASK(std) = STD_TASK(stdnext);
5099 STD_ACCEL(std) = STD_ACCEL(stdnext);
5100 STD_KERNEL(std) = STD_KERNEL(stdnext);
5101 delete_stmt(arg_gbl.std);
5102 }
5103
5104 static void
transform_c_f_procpointer(int func_ast,int func_args)5105 transform_c_f_procpointer(int func_ast, int func_args)
5106 {
5107 /*
5108 * c_f_procpointer(cptr, fptr)
5109 * call RTE_c_f_procptr, passing the address of cptr and fptr$p.
5110 * lower() could turn this into an assignment of the form:
5111 * fptr$p = cptr%val
5112 * But today, I do not want to deal with assigning an integer (cptr%val)
5113 * to a pointer variable.
5114 */
5115 int lineno;
5116 int stdnext, std;
5117 int newast;
5118 int fptr;
5119 int pvar;
5120 int dtype;
5121 int func;
5122 int nargs;
5123 int newargt;
5124 int sptr;
5125
5126 stdnext = arg_gbl.std;
5127 lineno = STD_LINENO(stdnext);
5128 fptr = ARGT_ARG(func_args, 1);
5129 /*
5130 * pass the address of fptr$p instead of just referencing fptr.
5131 */
5132 dtype = A_DTYPEG(fptr);
5133 if (A_TYPEG(fptr) == A_ID)
5134 sptr = A_SPTRG(fptr);
5135 else if (A_TYPEG(fptr) == A_MEM)
5136 sptr = A_SPTRG(A_MEMG(fptr));
5137 else
5138 sptr = 0;
5139 if (sptr && MIDNUMG(sptr)) {
5140 pvar = check_member(fptr, mk_id(MIDNUMG(sptr)));
5141 } else {
5142 interr("FPTR error in c_f_procpointer()", fptr, 4);
5143 }
5144
5145 func = mk_id(sym_mkfunc_nodesc_expst(mkRteRtnNm(RTE_c_f_procptr), DT_INT));
5146 nargs = 2;
5147 newargt = mk_argt(nargs);
5148 ARGT_ARG(newargt, 0) = ARGT_ARG(func_args, 0); /* cptr */
5149 ARGT_ARG(newargt, 1) = pvar; /* fptr$p */
5150 newast = mk_func_node(A_CALL, func, nargs, newargt);
5151 std = add_stmt_before(newast, stdnext);
5152 STD_LINENO(std) = lineno;
5153 STD_PAR(std) = STD_PAR(stdnext);
5154 STD_TASK(std) = STD_TASK(stdnext);
5155 STD_ACCEL(std) = STD_ACCEL(stdnext);
5156 STD_KERNEL(std) = STD_KERNEL(stdnext);
5157 delete_stmt(arg_gbl.std);
5158 }
5159
5160 static void
_rewrite_scalar_fuctions(int astx,int * std)5161 _rewrite_scalar_fuctions(int astx, int *std)
5162 {
5163 int sptrretval;
5164 int sptrtmp;
5165 int funcsptr;
5166 int iface;
5167 int ast;
5168 int asttmp;
5169 int args;
5170
5171 if (A_TYPEG(astx) == A_FUNC && DT_ISSCALAR(A_DTYPEG(astx))) {
5172 funcsptr = procsym_of_ast(A_LOPG(astx));
5173 proc_arginfo(funcsptr, NULL, NULL, &iface);
5174 if (iface && FVALG(iface)) {
5175 args = rewrite_sub_args(astx, 0);
5176 A_ARGSP(astx, args);
5177 sptrretval = FVALG(iface);
5178 sptrtmp = sym_get_scalar(SYMNAME(sptrretval), "r", A_DTYPEG(astx));
5179 asttmp = mk_id(sptrtmp);
5180 ast = mk_assn_stmt(asttmp, astx, A_DTYPEG(astx));
5181 add_stmt_before(ast, *std);
5182 ast_replace(astx, asttmp);
5183 }
5184 }
5185 }
5186
5187 static int
rewrite_scalar_functions(int astx,int std)5188 rewrite_scalar_functions(int astx, int std)
5189 {
5190 int ast;
5191
5192 ast_visit(1, 1);
5193 ast_traverse(astx, NULL, _rewrite_scalar_fuctions, &std);
5194 ast = ast_rewrite(astx);
5195 ast_unvisit();
5196 return ast;
5197 }
5198
5199 /*
5200 * Return TRUE if AST astx contains an intrinsic or external call.
5201 * allow calls to user or intrinsic elementals
5202 */
5203 static LOGICAL
_contains_any_call(int astx,LOGICAL * pflag)5204 _contains_any_call(int astx, LOGICAL *pflag)
5205 {
5206 if (A_TYPEG(astx) == A_INTR) {
5207 /* allow elemental intrinsic call s*/
5208 if (INKINDG(procsym_of_ast(A_LOPG(astx))) == IK_ELEMENTAL) {
5209 return FALSE;
5210 }
5211 *pflag = TRUE;
5212 return TRUE;
5213 } else if (A_TYPEG(astx) == A_CALL || A_TYPEG(astx) == A_FUNC) {
5214 if (elemental_func_call(astx)) {
5215 return FALSE;
5216 }
5217 *pflag = TRUE;
5218 return TRUE;
5219
5220 } else if (A_TYPEG(astx) == A_ICALL) {
5221 *pflag = TRUE;
5222 return TRUE;
5223 }
5224 return FALSE;
5225 }
5226
5227 /*
5228 * Return TRUE if AST astx contains an intrinsic or external call.
5229 * allow calls to user or intrinsic elementals
5230 */
5231 static LOGICAL
contains_any_call(int astx)5232 contains_any_call(int astx)
5233 {
5234 LOGICAL flag = FALSE;
5235 ast_visit(1, 1);
5236 ast_traverse(astx, _contains_any_call, NULL, &flag);
5237 ast_unvisit();
5238 return flag;
5239 }
5240
5241 static int subscript_lhs(int, int *, int, DTYPE, int, int);
5242
5243 static LOGICAL
ast_cval(int ast,ISZ_T * value)5244 ast_cval(int ast, ISZ_T *value)
5245 {
5246 if (ast && A_ALIASG(ast))
5247 ast = A_ALIASG(ast);
5248 if (ast && A_TYPEG(ast) == A_CNST) {
5249 int sptr = A_SPTRG(ast);
5250 if (sptr && STYPEG(sptr) == ST_CONST) {
5251 *value = get_isz_cval(sptr);
5252 return TRUE;
5253 }
5254 }
5255 return FALSE;
5256 } /* ast_cval */
5257
5258 /*
5259 * from a(1:3:1,2:4:2) given offsets 'i' and 'j' for subscripts 'si' and 'sj',
5260 * build the reference a(1+i, 2+j*2) and return that
5261 * This routine does the array reference rewrite
5262 */
5263 static int
build_array_reference(int ast,int si,int vi,int sj,int vj)5264 build_array_reference(int ast, int si, int vi, int sj, int vj)
5265 {
5266 int asd, numdim, k, ss, iss;
5267 int subs[MAXSUBS];
5268 asd = A_ASDG(ast);
5269 numdim = ASD_NDIM(asd);
5270 iss = 0;
5271 for (k = 0; k < numdim; ++k) {
5272 ss = ASD_SUBS(asd, k);
5273 if (A_TYPEG(ss) == A_TRIPLE) {
5274 int v, a;
5275 if (iss == si) {
5276 v = vi;
5277 } else if (iss == sj) {
5278 v = vj;
5279 } else {
5280 return 0;
5281 }
5282 /* return A_LBDG(ss) + A_STRIDEG(ss) * v */
5283 a = mk_cval(v, A_DTYPEG(A_STRIDEG(ss)));
5284 a = mk_binop(OP_MUL, a, A_STRIDEG(ss), A_DTYPEG(A_STRIDEG(ss)));
5285 a = mk_binop(OP_ADD, a, A_LBDG(ss), A_DTYPEG(A_LBDG(ss)));
5286 subs[k] = a;
5287 ++iss;
5288 } else if (A_SHAPEG(ss)) {
5289 return 0;
5290 } else {
5291 subs[k] = ss;
5292 }
5293 }
5294 ast = mk_subscr(A_LOPG(ast), subs, numdim, DDTG(A_DTYPEG(ast)));
5295 return ast;
5296 } /* build_array_reference */
5297
5298 /*
5299 * from a(1:3:1,2:4:2) given offsets 'i' and 'j' for subscripts 'si' and 'sj',
5300 * build the reference a(1+i, 2+j*2) and return that
5301 * This routine walks the expression tree to find the array reference(s)
5302 */
5303 static int
build_array_ref(int inast,int si,int vi,int sj,int vj)5304 build_array_ref(int inast, int si, int vi, int sj, int vj)
5305 {
5306 int ast1, ast2, dtype, args, arg1;
5307 int shape, argt, nargs, k;
5308 switch (A_TYPEG(inast)) {
5309 case A_BINOP:
5310 ast1 = build_array_ref(A_LOPG(inast), si, vi, sj, vj);
5311 if (ast1 == 0)
5312 return 0;
5313 ast2 = build_array_ref(A_ROPG(inast), si, vi, sj, vj);
5314 if (ast2 == 0)
5315 return 0;
5316 dtype = A_DTYPEG(inast);
5317 if (DTY(dtype) == TY_ARRAY)
5318 dtype = DTY(dtype + 1);
5319 return mk_binop(A_OPTYPEG(inast), ast1, ast2, dtype);
5320 case A_UNOP:
5321 ast1 = build_array_ref(A_LOPG(inast), si, vi, sj, vj);
5322 if (ast1 == 0)
5323 return 0;
5324 dtype = A_DTYPEG(inast);
5325 if (DTY(dtype) == TY_ARRAY)
5326 dtype = DTY(dtype + 1);
5327 return mk_unop(A_OPTYPEG(inast), ast1, dtype);
5328 case A_CONV:
5329 ast1 = build_array_ref(A_LOPG(inast), si, vi, sj, vj);
5330 if (ast1 == 0)
5331 return 0;
5332 dtype = A_DTYPEG(inast);
5333 if (DTY(dtype) == TY_ARRAY)
5334 dtype = DTY(dtype + 1);
5335 return mk_convert(ast1, dtype);
5336 case A_CMPLXC:
5337 case A_CNST:
5338 return inast;
5339 case A_SUBSTR:
5340 ast1 = build_array_ref(A_LOPG(inast), si, vi, sj, vj);
5341 if (ast1 == 0)
5342 return 0;
5343 return mk_substr(ast1, A_LEFTG(inast), A_RIGHTG(inast), A_DTYPEG(inast));
5344 case A_PAREN:
5345 ast1 = build_array_ref(A_LOPG(inast), si, vi, sj, vj);
5346 if (ast1 == 0)
5347 return 0;
5348 return mk_paren(ast1, A_DTYPEG(ast1));
5349
5350 case A_FUNC:
5351 shape = A_SHAPEG(inast);
5352 if (shape) {
5353 argt = A_ARGSG(inast);
5354 nargs = A_ARGCNTG(inast);
5355 for (k = 0; k < nargs; ++k) {
5356 ast1 = build_array_ref(ARGT_ARG(argt, k), si, vi, sj, vj);
5357 if (ast1 == 0)
5358 return 0;
5359 }
5360 /* now for real */
5361 for (k = 0; k < nargs; ++k) {
5362 ARGT_ARG(argt, k) = build_array_ref(ARGT_ARG(argt, k), si, vi, sj, vj);
5363 }
5364 dtype = A_DTYPEG(inast);
5365 if (DTY(dtype) == TY_ARRAY && elemental_func_call(inast)) {
5366 A_DTYPEP(inast, DTY(dtype + 1));
5367 A_SHAPEP(inast, 0);
5368 }
5369 }
5370 return inast;
5371 case A_SUBSCR:
5372 /* does this subscript have any triplet entries */
5373 if (vector_member(inast)) {
5374 inast = build_array_reference(inast, si, vi, sj, vj);
5375 }
5376 if (A_TYPEG(A_LOPG(inast)) == A_MEM) {
5377 /* the parent might have an array index */
5378 int asd = A_ASDG(inast);
5379 ast1 = build_array_ref(A_PARENTG(A_LOPG(inast)), si, vi, sj, vj);
5380 if (ast1 == 0)
5381 return 0;
5382 if (ast1 != A_PARENTG(A_LOPG(inast))) {
5383 DTYPE dtype = A_DTYPEG(A_MEMG(A_LOPG(inast)));
5384 ast1 = mk_member(ast1, A_MEMG(A_LOPG(inast)), dtype);
5385 if (is_array_dtype(dtype))
5386 dtype = array_element_dtype(dtype);
5387 /* add the member subscripts */
5388 inast = mk_subscr_copy(ast1, asd, dtype);
5389 }
5390 }
5391 return inast;
5392 case A_MEM:
5393 /* the parent might have an array index */
5394 ast1 = build_array_ref(A_PARENTG(inast), si, vi, sj, vj);
5395 if (ast1 == 0)
5396 return 0;
5397 /* member should be a scalar here */
5398 return mk_member(ast1, A_MEMG(inast), A_DTYPEG(A_MEMG(inast)));
5399 case A_ID:
5400 return inast;
5401 case A_INTR:
5402 /* allow transpose() call */
5403 if (A_OPTYPEG(inast) != I_TRANSPOSE) {
5404 return 0;
5405 }
5406 args = A_ARGSG(inast);
5407 arg1 = ARGT_ARG(args, 0);
5408 ast1 = build_array_ref(arg1, sj, vi, si, vj);
5409 return ast1;
5410 default:
5411 return 0;
5412 }
5413
5414 } /* build_array_ref */
5415
5416 /*
5417 * a = matmul( b, c )
5418 * where the extent of a, b, c is less than 3 in each dimension
5419 * inline to
5420 * a(i,j) = sum(b(i,k) * c(k,j))
5421 * where we expand i, j, k at compile time from 1 to the extent.
5422 * for I_MATMUL_TRANSPOSE, we transpose the first argument:
5423 * a(i,j) = sum(b(k,i) * c(k,j))
5424 * if dest is zero, we have to create a temp array of the appropriate size
5425 * and return a reference to that array.
5426 */
5427
5428 static int
inline_small_matmul(int ast,int dest)5429 inline_small_matmul(int ast, int dest)
5430 {
5431 ISZ_T ilow, ihigh, istride, iextent;
5432 ISZ_T jlow, jhigh, jstride, jextent;
5433 ISZ_T klow, khigh, kstride, kextent;
5434 ISZ_T klowx, khighx, kstridex, kextentx;
5435 int ii, kk;
5436 int args, arg1, arg2, array1, array2, arraydest;
5437 int shape1, shape2;
5438 int stdnext, lineno;
5439 int i, j, k;
5440 int subscr[MAXSUBS];
5441 int mulop, addop;
5442 int stdprev;
5443 if (XBIT(47, 0x200))
5444 return ast;
5445 args = A_ARGSG(ast);
5446 arg1 = ARGT_ARG(args, 0);
5447 arg2 = ARGT_ARG(args, 1);
5448 if (!arg1 || !arg2)
5449 return ast;
5450
5451 stdprev = STD_PREV(arg_gbl.std);
5452 arg1 = rewrite_scalar_functions(arg1, arg_gbl.std);
5453 if (contains_any_call(arg1)) {
5454 arg1 = rewrite_sub_ast(arg1, 0);
5455 if (arg1 == -1)
5456 return ast;
5457 }
5458 arg2 = rewrite_scalar_functions(arg2, arg_gbl.std);
5459 if (contains_any_call(arg2)) {
5460 arg2 = rewrite_sub_ast(arg2, 0);
5461 if (arg2 == -1)
5462 return ast;
5463 }
5464 if (stdprev != STD_PREV(arg_gbl.std)) {
5465 /*
5466 * Allocatable temps could have been created while processing
5467 * the arguments and would degrade performance if we don't cleanup.
5468 * So, if any statements were created for the * arguments, just
5469 * make a new matmul ast
5470 */
5471 int argtnew, astnew;
5472 argtnew = mk_argt(2);
5473 ARGT_ARG(argtnew, 0) = arg1;
5474 ARGT_ARG(argtnew, 1) = arg2;
5475 astnew = mk_func_node(A_TYPEG(ast), A_LOPG(ast), 2, argtnew);
5476 A_OPTYPEP(astnew, A_OPTYPEG(ast));
5477 A_SHAPEP(astnew, A_SHAPEG(ast));
5478 A_DTYPEP(astnew, A_DTYPEG(ast));
5479 ast = astnew;
5480 }
5481 shape1 = A_SHAPEG(arg1);
5482 shape2 = A_SHAPEG(arg2);
5483 /* must be (n,k)x(k,m), or (k)x(k,m) or (n,k)x(k) */
5484 if (SHD_NDIM(shape1) != 2 && SHD_NDIM(shape1) != 1)
5485 return ast;
5486 if (SHD_NDIM(shape2) != 2 && SHD_NDIM(shape2) != 1)
5487 return ast;
5488 if (SHD_NDIM(shape1) == 1 && SHD_NDIM(shape2) == 1)
5489 return ast;
5490 /* check for transposed 1st argument */
5491 ii = 0;
5492 kk = 1;
5493 if (A_OPTYPEG(ast) == I_MATMUL_TRANSPOSE) {
5494 ii = 1;
5495 kk = 0;
5496 }
5497 /* the shapes must be constant sizes */
5498 if (SHD_NDIM(shape1) == 1) {
5499 ilow = 0;
5500 ihigh = 0;
5501 istride = 1;
5502 ii = 1;
5503 kk = 0;
5504 if (!ast_cval(SHD_LWB(shape1, kk), &klow))
5505 return ast;
5506 if (!ast_cval(SHD_UPB(shape1, kk), &khigh))
5507 return ast;
5508 if (!ast_cval(SHD_STRIDE(shape1, kk), &kstride))
5509 return ast;
5510 } else {
5511 if (!ast_cval(SHD_LWB(shape1, ii), &ilow))
5512 return ast;
5513 if (!ast_cval(SHD_UPB(shape1, ii), &ihigh))
5514 return ast;
5515 if (!ast_cval(SHD_STRIDE(shape1, ii), &istride))
5516 return ast;
5517 if (!ast_cval(SHD_LWB(shape1, kk), &klow))
5518 return ast;
5519 if (!ast_cval(SHD_UPB(shape1, kk), &khigh))
5520 return ast;
5521 if (!ast_cval(SHD_STRIDE(shape1, kk), &kstride))
5522 return ast;
5523 }
5524 if (SHD_NDIM(shape2) == 1) {
5525 jlow = 0;
5526 jhigh = 0;
5527 jstride = 1;
5528 if (!ast_cval(SHD_LWB(shape2, 0), &klowx))
5529 return ast;
5530 if (!ast_cval(SHD_UPB(shape2, 0), &khighx))
5531 return ast;
5532 if (!ast_cval(SHD_STRIDE(shape2, 0), &kstridex))
5533 return ast;
5534 } else {
5535 if (!ast_cval(SHD_LWB(shape2, 0), &klowx))
5536 return ast;
5537 if (!ast_cval(SHD_UPB(shape2, 0), &khighx))
5538 return ast;
5539 if (!ast_cval(SHD_STRIDE(shape2, 0), &kstridex))
5540 return ast;
5541 if (!ast_cval(SHD_LWB(shape2, 1), &jlow))
5542 return ast;
5543 if (!ast_cval(SHD_UPB(shape2, 1), &jhigh))
5544 return ast;
5545 if (!ast_cval(SHD_STRIDE(shape2, 1), &jstride))
5546 return ast;
5547 }
5548 if (istride == 0 || kstride == 0 || kstridex == 0 || jstride == 0)
5549 return ast;
5550 iextent = (ihigh - ilow + istride) / istride;
5551 jextent = (jhigh - jlow + jstride) / jstride;
5552 kextent = (khigh - klow + kstride) / kstride;
5553 kextentx = (khighx - klowx + kstridex) / kstridex;
5554 if (kextent != kextentx)
5555 return ast;
5556
5557 /* See if it's small enough */
5558 if (iextent <= 0 || iextent > 4)
5559 return ast;
5560 if (jextent <= 0 || jextent > 4)
5561 return ast;
5562 if (kextent <= 0 || kextent > 4)
5563 return ast;
5564 if (iextent * jextent * kextent > 32)
5565 return ast;
5566
5567 array1 = convert_subscript_in_expr(arg1);
5568 array2 = convert_subscript_in_expr(arg2);
5569 stdnext = arg_gbl.std;
5570 lineno = STD_LINENO(stdnext);
5571 if (1 || !dest) {
5572 int sptr, dtnew, eldtype;
5573 ADSC *ad;
5574 eldtype = DDTG(A_DTYPEG(ast));
5575 if (SHD_NDIM(shape1) == 1) {
5576 dtnew = get_array_dtype(1, eldtype);
5577 ad = AD_DPTR(dtnew);
5578 AD_LWBD(ad, 0) = AD_LWAST(ad, 0) = mk_cval(1, DT_INT);
5579 AD_UPBD(ad, 0) = AD_UPAST(ad, 0) = mk_cval(jextent, DT_INT);
5580 AD_EXTNTAST(ad, 0) = AD_UPBD(ad, 0);
5581 } else if (SHD_NDIM(shape2) == 1) {
5582 dtnew = get_array_dtype(1, eldtype);
5583 ad = AD_DPTR(dtnew);
5584 AD_LWBD(ad, 0) = AD_LWAST(ad, 0) = mk_cval(1, DT_INT);
5585 AD_UPBD(ad, 0) = AD_UPAST(ad, 0) = mk_cval(iextent, DT_INT);
5586 AD_EXTNTAST(ad, 0) = AD_UPBD(ad, 0);
5587 } else {
5588 dtnew = get_array_dtype(2, eldtype);
5589 ad = AD_DPTR(dtnew);
5590 AD_LWBD(ad, 0) = AD_LWAST(ad, 0) = mk_cval(1, DT_INT);
5591 AD_UPBD(ad, 0) = AD_UPAST(ad, 0) = mk_cval(iextent, DT_INT);
5592 AD_EXTNTAST(ad, 0) = AD_UPBD(ad, 0);
5593 AD_LWBD(ad, 1) = AD_LWAST(ad, 1) = mk_cval(1, DT_INT);
5594 AD_UPBD(ad, 1) = AD_UPAST(ad, 1) = mk_cval(jextent, DT_INT);
5595 AD_EXTNTAST(ad, 1) = AD_UPBD(ad, 1);
5596 }
5597 sptr = get_arr_temp(dtnew, TRUE, FALSE, FALSE);
5598 trans_mkdescr(sptr);
5599 dest = mk_id(sptr);
5600 }
5601 arraydest = convert_subscript_in_expr(dest);
5602 mulop = OP_MUL;
5603 addop = OP_ADD;
5604 if (TY_ISLOG(DTYG(A_DTYPEG(ast)))) {
5605 mulop = OP_LAND;
5606 addop = OP_LOR;
5607 } else if (!TY_ISNUMERIC(DTYG(A_DTYPEG(ast)))) {
5608 return ast;
5609 }
5610 /* build assignment statements */
5611 for (j = 0; j < jextent; ++j) {
5612 for (i = 0; i < iextent; ++i) {
5613 int lhs, rhs, std;
5614 if (SHD_NDIM(shape1) == 1) {
5615 lhs = build_array_ref(arraydest, 0, j, 1, i);
5616 } else {
5617 lhs = build_array_ref(arraydest, 0, i, 1, j);
5618 }
5619 if (lhs == 0)
5620 return ast;
5621 rhs = 0;
5622 for (k = 0; k < kextent; ++k) {
5623 int opnd1, opnd2;
5624 opnd1 = build_array_ref(array1, ii, i, kk, k);
5625 if (opnd1 == 0)
5626 return ast;
5627 opnd2 = build_array_ref(array2, 0, k, 1, j);
5628 if (opnd2 == 0)
5629 return ast;
5630 opnd1 = mk_binop(mulop, opnd1, opnd2, A_DTYPEG(opnd1));
5631 if (!rhs) {
5632 rhs = opnd1;
5633 } else {
5634 rhs = mk_binop(addop, rhs, opnd1, A_DTYPEG(opnd1));
5635 }
5636 }
5637 lhs = mk_assn_stmt(lhs, rhs, A_DTYPEG(rhs));
5638 std = add_stmt_before(lhs, stdnext);
5639 STD_LINENO(std) = lineno;
5640 STD_PAR(std) = STD_PAR(stdnext);
5641 STD_TASK(std) = STD_TASK(stdnext);
5642 STD_ACCEL(std) = STD_ACCEL(stdnext);
5643 STD_KERNEL(std) = STD_KERNEL(stdnext);
5644 }
5645 }
5646 /* return the destination array */
5647 return arraydest;
5648 } /* inline_small_matmul */
5649
5650 static int
inline_reduction_f90(int ast,int dest,int lc,LOGICAL * doremove)5651 inline_reduction_f90(int ast, int dest, int lc, LOGICAL *doremove)
5652 {
5653 int astdim, dim, mask, astmask;
5654 int args;
5655 int src1, src2, std;
5656 int dtype, dtypetmp, dtyperes, dtsclr, eldtype;
5657 int dtypetmpval, sptrtmpval, asttmpval, dtypeval, astsubscrtmpval;
5658 int dealloc_tmpval = FALSE;
5659 int srcarray;
5660 int home, homeforall;
5661 int lb, ub, st;
5662 int forall;
5663 int asn;
5664 int lineno;
5665 int stdnext;
5666 int newast;
5667 int ast2;
5668 int allocobj;
5669 int sptrtmp, asttmp, astsubscrtmp;
5670 int tmpndim;
5671 int descr;
5672 int i, j, n;
5673 int triplet_list, index_var;
5674 int triplet;
5675 int align;
5676 int shape;
5677 int dest_shape;
5678 int sptr;
5679 int argt, nargs;
5680 int ndim, asd;
5681 int list;
5682 int endif_ast, ifastnew;
5683 char sReduc[128];
5684 int ReducType;
5685 int astInit;
5686 int operator, operand;
5687 int ifast, endif;
5688 int i1, i2, dovar;
5689 int subs[MAXSUBS];
5690 int loopidx[MAXSUBS];
5691 int DOs[MAXSUBS];
5692 int curloop;
5693 int tmpidx[MAXSUBS];
5694 int nbrloops;
5695 int dimdo;
5696 int destndim;
5697 int destsub;
5698 int destsptr;
5699 int destref;
5700 ADSC *ad;
5701 int dealloc_dest = FALSE;
5702
5703 if (XBIT(47, 0x80))
5704 return ast;
5705 if (A_TYPEG(ast) != A_INTR)
5706 return ast;
5707
5708 /* if not reduction, return */
5709 switch (A_OPTYPEG(ast)) {
5710 case I_ALL:
5711 case I_ANY:
5712 case I_COUNT:
5713 case I_DOT_PRODUCT:
5714 case I_MAXVAL:
5715 case I_MINVAL:
5716 case I_PRODUCT:
5717 case I_SUM:
5718 if (doremove)
5719 *doremove = TRUE;
5720 break;
5721 case I_MAXLOC:
5722 case I_MINLOC:
5723 return ast;
5724 /* simple cases only */
5725 if (dest) {
5726 if (A_TYPEG(dest) == A_SUBSCR) {
5727 shape = A_SHAPEG(dest);
5728 if (SHD_NDIM(shape) != 1 || SHD_LWB(shape, 0) != SHD_UPB(shape, 0))
5729 return ast;
5730 } else if (A_TYPEG(dest) != A_ID)
5731 return ast;
5732 }
5733 if (doremove)
5734 *doremove = TRUE;
5735 break;
5736 case I_MATMUL:
5737 case I_MATMUL_TRANSPOSE:
5738 if (doremove)
5739 *doremove = FALSE;
5740 return inline_small_matmul(ast, dest);
5741 default:
5742 return ast;
5743 }
5744
5745 /* collect args */
5746 mask = 0;
5747 strcpy(sReduc, SYMNAME(A_SPTRG(A_LOPG(ast))));
5748 dtype = A_DTYPEG(ast);
5749 dtyperes = DDTG(dtype);
5750 args = A_ARGSG(ast);
5751 switch (A_OPTYPEG(ast)) {
5752 case I_SUM:
5753 case I_PRODUCT:
5754 astdim = ARGT_ARG(args, 1);
5755 mask = ARGT_ARG(args, 2);
5756 srcarray = ARGT_ARG(args, 0);
5757 if (arg_gbl.inforall)
5758 if (contiguous_section_array(srcarray))
5759 return ast;
5760 break;
5761 case I_MAXLOC:
5762 case I_MINLOC:
5763 dtypeval = DDTG(A_DTYPEG(ARGT_ARG(args, 0)));
5764 /* fall through */
5765 case I_MAXVAL:
5766 case I_MINVAL:
5767 astdim = ARGT_ARG(args, 1);
5768 mask = ARGT_ARG(args, 2);
5769 srcarray = ARGT_ARG(args, 0);
5770 if (DTYG(dtype) == TY_CHAR || DTYG(dtype) == TY_NCHAR)
5771 return ast;
5772 if (arg_gbl.inforall)
5773 if (contiguous_section_array(srcarray))
5774 return ast;
5775 break;
5776 case I_DOT_PRODUCT:
5777 astdim = 0;
5778 src1 = ARGT_ARG(args, 0);
5779 src2 = ARGT_ARG(args, 1);
5780 if (DT_ISCMPLX(DDTG(dtype)) && (XBIT(70, 0x4000000)
5781 || dtyperes == DT_QCMPLX
5782 ))
5783 return ast;
5784 if (arg_gbl.inforall) {
5785 if (contiguous_section_array(src1) && contiguous_section_array(src2))
5786 return ast;
5787 }
5788 if (DT_ISLOG(DDTG(dtype)))
5789 operator= OP_LAND;
5790 else
5791 operator= OP_MUL;
5792 if (DT_ISCMPLX(DDTG(dtype))) {
5793 int newargt, conjg, nast;
5794 if (dtyperes == DT_CMPLX) {
5795 conjg = I_CONJG;
5796 } else if (dtyperes == DT_CMPLX16) {
5797 conjg = I_DCONJG;
5798 } else {
5799 return ast;
5800 }
5801 newargt = mk_argt(1);
5802 ARGT_ARG(newargt, 0) = src1;
5803 nast = mk_func_node(A_INTR, mk_id(intast_sym[conjg]), 1, newargt);
5804 A_OPTYPEP(nast, conjg);
5805 A_DTYPEP(nast, A_DTYPEG(src1));
5806 src1 = nast;
5807 }
5808 srcarray = mk_binop(operator, src1, src2, dtype);
5809 break;
5810 case I_ALL:
5811 case I_ANY:
5812 case I_COUNT:
5813 astdim = ARGT_ARG(args, 1);
5814 srcarray = ARGT_ARG(args, 0);
5815 if (arg_gbl.inforall)
5816 if (contiguous_section_array(srcarray))
5817 return ast;
5818 break;
5819 }
5820
5821 if (astdim) {
5822 if (A_TYPEG(astdim) != A_CNST) {
5823 return ast;
5824 }
5825 dim = get_int_cval(A_SPTRG(astdim));
5826 } else {
5827 dim = 0;
5828 }
5829
5830 if ((A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC) && dim > 1)
5831 return ast;
5832
5833 if (!XBIT(70, 0x1000000) && dim == 1 && arg_gbl.inforall) {
5834 return ast;
5835 }
5836
5837 srcarray = rewrite_scalar_functions(srcarray, arg_gbl.std);
5838 if (contains_any_call(srcarray)) { /* return ast; */
5839 srcarray = rewrite_sub_ast(srcarray, 0);
5840 if (srcarray == -1)
5841 /* source is not something convert_subscript can handle and
5842 * computing it into an allocated temp is probably too
5843 * expensive. Don't inline it; call the subroutine.
5844 */
5845 return ast;
5846 home = search_conform_array(srcarray, TRUE);
5847 if (!home)
5848 /* source is not something convert_subscript can handle and
5849 * computing it into an allocated temp is probably too
5850 * expensive. Don't inline it; call the subroutine.
5851 */
5852 return ast;
5853 if (A_TYPEG(home) != A_ID && A_TYPEG(home) != A_MEM &&
5854 A_TYPEG(home) != A_TRIPLE && A_TYPEG(home) != A_SUBSCR)
5855 /* source is not something convert_subscript can handle and
5856 * computing it into an allocated temp is probably too
5857 * expensive. Don't inline it; call the subroutine.
5858 */
5859 return ast;
5860 /*
5861 fprintf(STDERR,
5862 "%s:%s:%d - inline_reduction_f90 change in behavior\n",
5863 gbl.src_file,
5864 SYMNAME(gbl.currsub), gbl.lineno);
5865 dbg_print_ast(srcarray, 0);
5866 dump_one_ast(srcarray);
5867 */
5868 }
5869 home = search_conform_array(srcarray, TRUE);
5870 if (!home)
5871 return ast;
5872 if (mask) {
5873 mask = rewrite_scalar_functions(mask, arg_gbl.std);
5874 if (contains_any_call(mask)) { /* return ast; */
5875 mask = rewrite_sub_ast(mask, 0);
5876 if (mask == -1) {
5877 /* source is not something convert_subscript can handle and
5878 * computing it into an allocated temp is probably too
5879 * expensive. Don't inline it; call the subroutine.
5880 */
5881 return ast;
5882 }
5883 }
5884 }
5885 ast2 = convert_subscript_in_expr(srcarray);
5886 home = convert_subscript(home);
5887 if (mask) {
5888 astmask = convert_subscript_in_expr(mask);
5889 } else {
5890 astmask = 0;
5891 }
5892
5893 sptr = sptr_of_subscript(home);
5894
5895 shape = A_SHAPEG(home);
5896 forall = make_forall(shape, home, astmask,
5897 lc + SHD_NDIM(shape)); /*TODO: need correct triple */
5898 homeforall = normalize_forall(forall, home, 0);
5899 ast2 = normalize_forall(forall, ast2, 0);
5900 if (mask) {
5901 astmask = normalize_forall(forall, astmask, 0);
5902 }
5903 list = A_LISTG(forall);
5904 asd = A_ASDG(homeforall);
5905 ndim = ASD_NDIM(asd); /* MORE ndim and nbrloops are NOT the same!!! */
5906 nbrloops = SHD_NDIM(shape);
5907
5908 stdnext = arg_gbl.std;
5909 lineno = STD_LINENO(stdnext);
5910
5911 if (A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC) {
5912 /* build temp */
5913 sptrtmp = sym_get_scalar(SYMNAME(sptr), "r", dtyperes);
5914 dtypetmp = DTYPEG(sptrtmp);
5915 asttmp = mk_id(sptrtmp);
5916 dtypetmp = DTYPEG(sptrtmp);
5917 asttmp = mk_id(sptrtmp);
5918
5919 /* build temp to hold values for I_MAXLOC, I_MINLOC */
5920 if (dim <= 1 || nbrloops == 1) {
5921 sptrtmpval = sym_get_scalar(SYMNAME(sptr), "vr", dtypeval);
5922 dtypetmpval = DTYPEG(sptrtmpval);
5923 asttmpval = mk_id(sptrtmpval);
5924 } else {
5925 reset_init_idx();
5926 dest_shape = A_SHAPEG(ast);
5927 sptrtmpval = sym_get_array(SYMNAME(sptr), "vr", dtypeval, dim - 1);
5928 dtypetmpval = DTYPEG(sptrtmpval);
5929 for (i = 0; i < dim - 1; ++i) {
5930 ADD_LWBD(dtypetmpval, i) = ADD_LWAST(dtypetmpval, i) =
5931 SHD_LWB(dest_shape, i);
5932 ADD_UPBD(dtypetmpval, i) = ADD_UPAST(dtypetmpval, i) =
5933 SHD_UPB(dest_shape, i);
5934 ADD_EXTNTAST(dtypetmpval, i) =
5935 mk_extent(ADD_LWAST(dtypetmpval, i), ADD_UPAST(dtypetmpval, i), i);
5936 subs[i] = mk_triple(SHD_LWB(dest_shape, i), SHD_UPB(dest_shape, i),
5937 astb.bnd.one);
5938 }
5939 dtypetmpval = DTYPEG(sptrtmpval);
5940 NODESCP(sptrtmpval, 1);
5941 check_small_allocatable(sptrtmpval);
5942 asttmpval = mk_id(sptrtmpval);
5943
5944 if (ALLOCG(sptrtmpval)) {
5945 allocobj = mk_subscr(asttmpval, subs, dim - 1, DDTG(dtypetmpval));
5946 newast = mk_stmt(A_ALLOC, 0);
5947 A_TKNP(newast, TK_ALLOCATE);
5948 A_LOPP(newast, 0);
5949 A_SRCP(newast, allocobj);
5950 std = add_stmt_before(newast, stdnext);
5951 STD_LINENO(std) = lineno;
5952 STD_LOCAL(std) = 1;
5953 STD_PAR(std) = STD_PAR(stdnext);
5954 STD_TASK(std) = STD_TASK(stdnext);
5955 STD_ACCEL(std) = STD_ACCEL(stdnext);
5956 STD_KERNEL(std) = STD_KERNEL(stdnext);
5957 if (STD_ACCEL(std))
5958 STD_RESCOPE(std) = 1;
5959 dealloc_tmpval = TRUE;
5960 }
5961 }
5962 } else {
5963 /* build temp */
5964 if (dim <= 1 || nbrloops == 1) {
5965 sptrtmp = sym_get_scalar(SYMNAME(sptr), "r", dtyperes);
5966 dtypetmp = DTYPEG(sptrtmp);
5967 asttmp = mk_id(sptrtmp);
5968 } else {
5969 reset_init_idx();
5970 dest_shape = A_SHAPEG(ast);
5971 sptrtmp = sym_get_array(SYMNAME(sptr), "r", dtyperes, dim - 1);
5972 dtypetmp = DTYPEG(sptrtmp);
5973 ad = AD_DPTR(dtype);
5974 for (i = 0; i < dim - 1; ++i) {
5975 if (SHD_STRIDE(dest_shape, i) == astb.i1 ||
5976 SHD_STRIDE(dest_shape, i) == astb.bnd.one) {
5977 ADD_LWBD(dtypetmp, i) = ADD_LWAST(dtypetmp, i) =
5978 SHD_LWB(dest_shape, i);
5979 ADD_UPBD(dtypetmp, i) = ADD_UPAST(dtypetmp, i) =
5980 SHD_UPB(dest_shape, i);
5981 ADD_EXTNTAST(dtypetmp, i) =
5982 mk_extent(ADD_LWAST(dtypetmp, i), ADD_UPAST(dtypetmp, i), i);
5983 subs[i] = mk_triple(SHD_LWB(dest_shape, i), SHD_UPB(dest_shape, i),
5984 astb.bnd.one);
5985 } else {
5986 ADD_LWBD(dtypetmp, i) = ADD_LWAST(dtypetmp, i) =
5987 SHD_LWB(dest_shape, i);
5988 ADD_UPBD(dtypetmp, i) = ADD_UPAST(dtypetmp, i) = mk_binop(
5989 OP_DIV,
5990 mk_binop(OP_ADD,
5991 mk_binop(OP_SUB, SHD_UPB(dest_shape, i),
5992 SHD_LWB(dest_shape, i), astb.bnd.dtype),
5993 SHD_STRIDE(dest_shape, i), astb.bnd.dtype),
5994 SHD_STRIDE(dest_shape, i), astb.bnd.dtype);
5995
5996 ADD_EXTNTAST(dtypetmp, i) =
5997 mk_extent(ADD_LWAST(dtypetmp, i), ADD_UPAST(dtypetmp, i), i);
5998 subs[i] = mk_triple(ADD_LWAST(dtypetmp, i), ADD_UPAST(dtypetmp, i),
5999 astb.bnd.one);
6000 }
6001 }
6002 dtypetmp = DTYPEG(sptrtmp);
6003 NODESCP(sptrtmp, 1);
6004 check_small_allocatable(sptrtmp);
6005 asttmp = mk_id(sptrtmp);
6006
6007 if (ALLOCG(sptrtmp)) {
6008 allocobj = mk_subscr(asttmp, subs, dim - 1, DDTG(dtypetmp));
6009 newast = mk_stmt(A_ALLOC, 0);
6010 A_TKNP(newast, TK_ALLOCATE);
6011 A_LOPP(newast, 0);
6012 A_SRCP(newast, allocobj);
6013 std = add_stmt_before(newast, stdnext);
6014 STD_LINENO(std) = lineno;
6015 STD_LOCAL(std) = 1;
6016 STD_PAR(std) = STD_PAR(stdnext);
6017 STD_TASK(std) = STD_TASK(stdnext);
6018 STD_ACCEL(std) = STD_ACCEL(stdnext);
6019 STD_KERNEL(std) = STD_KERNEL(stdnext);
6020 if (STD_ACCEL(std))
6021 STD_RESCOPE(std) = 1;
6022 }
6023 }
6024 }
6025
6026 /* if necessary, build destination */
6027 if (!dest) {
6028 if (DTY(dtype) == TY_ARRAY) {
6029 if (DTY(dtypetmp) == TY_ARRAY && ADD_NUMDIM(dtypetmp) == ndim - 1) {
6030 /* use temp from above as dest */
6031 destsptr = sptrtmp;
6032 dest = asttmp;
6033 NODESCP(sptrtmp, 0);
6034 trans_mkdescr(destsptr); /* MORE is this needed??? */
6035 } else {
6036 ADSC *addest;
6037 reset_init_idx();
6038 destsptr = sym_get_array(SYMNAME(sptr), "tr", dtyperes, nbrloops - 1);
6039 addest = AD_DPTR(DTYPEG(destsptr));
6040 AD_NUMDIM(addest) = nbrloops - 1;
6041 j = 0;
6042 shape = A_SHAPEG(home);
6043 for (i = 0; i < nbrloops; ++i) {
6044 if (i != dim - 1) {
6045 AD_LWAST(addest, j) = AD_LWBD(addest, j) = SHD_LWB(shape, i);
6046 AD_UPAST(addest, j) = AD_UPBD(addest, j) = SHD_UPB(shape, i);
6047 AD_EXTNTAST(addest, j) =
6048 mk_extent(AD_LWAST(addest, j), AD_UPAST(addest, j), j);
6049 subs[j] = mk_triple(AD_LWBD(addest, j), AD_UPBD(addest, j),
6050 SHD_STRIDE(shape, i));
6051 j++;
6052 }
6053 }
6054 dest = mk_id(destsptr);
6055 A_SHAPEP(dest, reduc_shape(shape, astdim, STD_PREV(stdnext)));
6056
6057 trans_mkdescr(destsptr); /* MORE is this needed??? */
6058 check_small_allocatable(destsptr);
6059
6060 if (ALLOCG(destsptr)) {
6061 allocobj = mk_subscr(dest, subs, nbrloops - 1, dtyperes);
6062 newast = mk_stmt(A_ALLOC, 0);
6063 A_TKNP(newast, TK_ALLOCATE);
6064 A_LOPP(newast, 0);
6065 A_SRCP(newast, allocobj);
6066 std = add_stmt_before(newast, stdnext);
6067 STD_LINENO(std) = lineno;
6068 STD_LOCAL(std) = 1;
6069 STD_PAR(std) = STD_PAR(stdnext);
6070 STD_TASK(std) = STD_TASK(stdnext);
6071 STD_ACCEL(std) = STD_ACCEL(stdnext);
6072 STD_KERNEL(std) = STD_KERNEL(stdnext);
6073 if (STD_ACCEL(std))
6074 STD_RESCOPE(std) = 1;
6075 dealloc_dest = TRUE;
6076 }
6077 }
6078 } else {
6079 dest = asttmp;
6080 }
6081 }
6082
6083 /* select reduction type */
6084
6085 switch (A_OPTYPEG(ast)) {
6086 case I_SUM:
6087 case I_COUNT:
6088 ReducType = I_REDUCE_SUM;
6089 astInit = mk_convert(astb.i0, DDTG(dtypetmp));
6090 break;
6091 case I_DOT_PRODUCT:
6092 ReducType = I_REDUCE_SUM;
6093 if (DT_ISLOG(DDTG(dtypetmp)))
6094 astInit = mk_cval(SCFTN_FALSE, DT_LOG);
6095 else
6096 astInit = mk_convert(astb.i0, DDTG(dtypetmp));
6097 break;
6098 case I_PRODUCT:
6099 ReducType = I_REDUCE_PRODUCT;
6100 astInit = mk_convert(astb.i1, DDTG(dtypetmp));
6101 break;
6102 case I_MAXVAL:
6103 ReducType = I_REDUCE_MAXVAL;
6104 astInit = mk_smallest_val(DDTG(dtypetmp));
6105 break;
6106 case I_MAXLOC:
6107 ReducType = I_REDUCE_MAXVAL;
6108 astInit = mk_smallest_val(DDTG(dtypetmpval));
6109 break;
6110 case I_MINVAL:
6111 ReducType = I_REDUCE_MINVAL;
6112 astInit = mk_largest_val(DDTG(dtypetmp));
6113 break;
6114 case I_MINLOC:
6115 ReducType = I_REDUCE_MINVAL;
6116 astInit = mk_largest_val(DDTG(dtypetmpval));
6117 break;
6118 case I_ALL:
6119 ReducType = I_REDUCE_ALL;
6120 astInit = mk_cval(SCFTN_TRUE, DDTG(dtypetmp));
6121 break;
6122 case I_ANY:
6123 ReducType = I_REDUCE_ANY;
6124 astInit = mk_cval(SCFTN_FALSE, DDTG(dtypetmp));
6125 break;
6126 default:
6127 assert(0, "inline_reduction_f90: unknown type", ast, 4);
6128 }
6129
6130 if (dim == 0) {
6131 /* initialize temp */
6132 if (A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC)
6133 asn = mk_assn_stmt(asttmpval, astInit, dtypetmpval);
6134 else
6135 asn = mk_assn_stmt(asttmp, astInit, dtypetmp);
6136 std = add_stmt_before(asn, stdnext);
6137 STD_LINENO(std) = lineno;
6138 STD_LOCAL(std) = 1;
6139 STD_PAR(std) = STD_PAR(stdnext);
6140 STD_TASK(std) = STD_TASK(stdnext);
6141 STD_ACCEL(std) = STD_ACCEL(stdnext);
6142 STD_KERNEL(std) = STD_KERNEL(stdnext);
6143 }
6144
6145 n = nbrloops;
6146 j = nbrloops - 1;
6147 triplet_list = A_LISTG(forall);
6148 for (; triplet_list; triplet_list = ASTLI_NEXT(triplet_list)) {
6149 index_var = ASTLI_SPTR(triplet_list);
6150 /* find the matching home dimension */
6151 for (i = 0; i < ndim; i++)
6152 if (is_name_in_expr(ASD_SUBS(asd, i), index_var))
6153 break;
6154 triplet = ASTLI_TRIPLE(triplet_list);
6155 st = A_STRIDEG(triplet);
6156 if (!st)
6157 st = astb.i1;
6158
6159 newast = mk_stmt(A_DO, 0);
6160 lb = A_LBDG(triplet);
6161 ub = A_UPBDG(triplet);
6162
6163 dovar = mk_id(index_var);
6164 loopidx[j] = dovar;
6165 A_DOVARP(newast, dovar);
6166 A_M1P(newast, lb);
6167 A_M2P(newast, ub);
6168 A_M3P(newast, st);
6169 A_M4P(newast, 0);
6170 DOs[j] = newast;
6171
6172 if (n-- == dim) {
6173 /* initialize temp */
6174 if (A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC)
6175 asn = mk_assn_stmt(asttmpval, astInit, dtypetmpval);
6176 else
6177 asn = mk_assn_stmt(asttmp, astInit, dtypetmp);
6178 std = add_stmt_before(asn, stdnext);
6179 STD_LINENO(std) = lineno;
6180 STD_LOCAL(std) = 1;
6181 STD_PAR(std) = STD_PAR(stdnext);
6182 STD_TASK(std) = STD_TASK(stdnext);
6183 STD_ACCEL(std) = STD_ACCEL(stdnext);
6184 STD_KERNEL(std) = STD_KERNEL(stdnext);
6185 } else {
6186 tmpidx[j] = dovar;
6187 }
6188
6189 std = add_stmt_before(newast, stdnext);
6190 STD_LINENO(std) = lineno;
6191 STD_LOCAL(std) = 1;
6192 STD_PAR(std) = STD_PAR(stdnext);
6193 STD_TASK(std) = STD_TASK(stdnext);
6194 STD_ACCEL(std) = STD_ACCEL(stdnext);
6195 STD_KERNEL(std) = STD_KERNEL(stdnext);
6196 i++;
6197 j--;
6198 }
6199
6200 if (mask) {
6201 ifastnew = mk_stmt(A_IFTHEN, 0);
6202 A_IFEXPRP(ifastnew, astmask);
6203 std = add_stmt_before(ifastnew, stdnext);
6204 STD_LINENO(std) = lineno;
6205 STD_LOCAL(std) = 1;
6206 STD_PAR(std) = STD_PAR(stdnext);
6207 STD_TASK(std) = STD_TASK(stdnext);
6208 STD_ACCEL(std) = STD_ACCEL(stdnext);
6209 STD_KERNEL(std) = STD_KERNEL(stdnext);
6210 }
6211
6212 /* select reduction stmt */
6213 if (dim > 1 && nbrloops != 1) {
6214 ad = AD_DPTR(DTYPEG(sptrtmp));
6215 tmpndim = AD_NUMDIM(ad);
6216 for (j = 0; j < tmpndim; i++, j++) {
6217 if (SHD_STRIDE(dest_shape, j) == astb.i1 ||
6218 SHD_STRIDE(dest_shape, j) == astb.bnd.one) {
6219 subs[j] = loopidx[j];
6220 } else
6221 subs[j] = mk_binop(OP_ADD,
6222 mk_binop(OP_DIV, loopidx[j],
6223 SHD_STRIDE(dest_shape, j), astb.bnd.dtype),
6224 SHD_LWB(dest_shape, j), astb.bnd.dtype);
6225 }
6226 astsubscrtmp = mk_subscr(asttmp, subs, tmpndim, DDTG(dtypetmp));
6227 A_SHAPEP(astsubscrtmp, 0);
6228 if (A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC) {
6229 astsubscrtmpval = mk_subscr(asttmpval, subs, tmpndim, DDTG(dtypetmpval));
6230 A_SHAPEP(astsubscrtmpval, 0);
6231 }
6232 } else {
6233 if (A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC) {
6234 astsubscrtmpval = asttmpval;
6235 astsubscrtmp = dest;
6236 } else
6237 astsubscrtmp = asttmp;
6238 if (A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC ||
6239 A_OPTYPEG(ast) == I_MAXVAL || A_OPTYPEG(ast) == I_MINVAL) {
6240 /* if the expression being reduced is nontrivial, assign to a temp */
6241 if (A_TYPEG(ast2) == A_SUBSCR || A_TYPEG(ast2) == A_ID) {
6242 } else {
6243 /* create a temporary scalar */
6244 int temprhs = sym_get_scalar(SYMNAME(sptr), "l", dtyperes);
6245 /* assign the RHS to temprhs */
6246 int std = mk_assn_stmt(mk_id(temprhs), ast2, dtyperes);
6247 add_stmt_before(std, stdnext);
6248 ast2 = mk_id(temprhs);
6249 }
6250 }
6251 }
6252 dtsclr = DDTG(dtypetmp);
6253 switch (A_OPTYPEG(ast)) {
6254 case I_SUM:
6255 case I_DOT_PRODUCT:
6256 if (DT_ISLOG(dtsclr))
6257 operator= OP_LOR;
6258 else
6259 operator= OP_ADD;
6260 newast = mk_binop(operator, astsubscrtmp, ast2, dtsclr);
6261 asn = mk_assn_stmt(astsubscrtmp, newast, dtsclr);
6262
6263 std = add_stmt_before(asn, stdnext);
6264 STD_LINENO(std) = lineno;
6265 STD_LOCAL(std) = 1;
6266 STD_PAR(std) = STD_PAR(stdnext);
6267 STD_TASK(std) = STD_TASK(stdnext);
6268 STD_ACCEL(std) = STD_ACCEL(stdnext);
6269 STD_KERNEL(std) = STD_KERNEL(stdnext);
6270 break;
6271 case I_COUNT:
6272 newast = mk_binop(OP_ADD, astsubscrtmp, astb.i1, dtsclr);
6273 asn = mk_assn_stmt(astsubscrtmp, newast, dtsclr);
6274
6275 ifast = mk_stmt(A_IFTHEN, 0);
6276 A_IFEXPRP(ifast, ast2);
6277 std = add_stmt_before(ifast, stdnext);
6278 STD_LINENO(std) = lineno;
6279 STD_LOCAL(std) = 1;
6280 STD_PAR(std) = STD_PAR(stdnext);
6281 STD_TASK(std) = STD_TASK(stdnext);
6282 STD_ACCEL(std) = STD_ACCEL(stdnext);
6283 STD_KERNEL(std) = STD_KERNEL(stdnext);
6284
6285 std = add_stmt_before(asn, stdnext);
6286 STD_LINENO(std) = lineno;
6287 STD_LOCAL(std) = 1;
6288 STD_PAR(std) = STD_PAR(stdnext);
6289 STD_TASK(std) = STD_TASK(stdnext);
6290 STD_ACCEL(std) = STD_ACCEL(stdnext);
6291 STD_KERNEL(std) = STD_KERNEL(stdnext);
6292
6293 endif = mk_stmt(A_ENDIF, 0);
6294 std = add_stmt_before(endif, stdnext);
6295 STD_LINENO(std) = lineno;
6296 STD_LOCAL(std) = 1;
6297 STD_PAR(std) = STD_PAR(stdnext);
6298 STD_TASK(std) = STD_TASK(stdnext);
6299 STD_ACCEL(std) = STD_ACCEL(stdnext);
6300 STD_KERNEL(std) = STD_KERNEL(stdnext);
6301 break;
6302 case I_PRODUCT:
6303 newast = mk_binop(OP_MUL, astsubscrtmp, ast2, dtsclr);
6304 asn = mk_assn_stmt(astsubscrtmp, newast, dtsclr);
6305 std = add_stmt_before(asn, stdnext);
6306 STD_LINENO(std) = lineno;
6307 STD_LOCAL(std) = 1;
6308 STD_PAR(std) = STD_PAR(stdnext);
6309 STD_TASK(std) = STD_TASK(stdnext);
6310 STD_ACCEL(std) = STD_ACCEL(stdnext);
6311 STD_KERNEL(std) = STD_KERNEL(stdnext);
6312 break;
6313 case I_MAXVAL:
6314 newast = mk_binop(OP_GT, ast2, astsubscrtmp, DT_LOG);
6315 asn = mk_assn_stmt(astsubscrtmp, ast2, dtsclr);
6316 goto max_min_common;
6317 case I_MINVAL:
6318 newast = mk_binop(OP_LT, ast2, astsubscrtmp, DT_LOG);
6319 asn = mk_assn_stmt(astsubscrtmp, ast2, dtsclr);
6320 goto max_min_common;
6321 case I_MAXLOC:
6322 newast = mk_binop(OP_GT, ast2, astsubscrtmpval, DT_LOG);
6323 asn = mk_assn_stmt(astsubscrtmpval, ast2, DDTG(dtypetmpval));
6324 goto max_min_common;
6325 case I_MINLOC:
6326 newast = mk_binop(OP_LT, ast2, astsubscrtmpval, DT_LOG);
6327 asn = mk_assn_stmt(astsubscrtmpval, ast2, DDTG(dtypetmpval));
6328
6329 max_min_common:
6330 ifast = mk_stmt(A_IFTHEN, 0);
6331 A_IFEXPRP(ifast, newast);
6332 std = add_stmt_before(ifast, stdnext);
6333 STD_LINENO(std) = lineno;
6334 STD_LOCAL(std) = 1;
6335 STD_PAR(std) = STD_PAR(stdnext);
6336 STD_TASK(std) = STD_TASK(stdnext);
6337 STD_ACCEL(std) = STD_ACCEL(stdnext);
6338 STD_KERNEL(std) = STD_KERNEL(stdnext);
6339
6340 std = add_stmt_before(asn, stdnext);
6341 STD_LINENO(std) = lineno;
6342 STD_LOCAL(std) = 1;
6343 STD_PAR(std) = STD_PAR(stdnext);
6344 STD_TASK(std) = STD_TASK(stdnext);
6345 STD_ACCEL(std) = STD_ACCEL(stdnext);
6346 STD_KERNEL(std) = STD_KERNEL(stdnext);
6347
6348 if (A_OPTYPEG(ast) == I_MAXLOC || A_OPTYPEG(ast) == I_MINLOC) {
6349 if (nbrloops > 1) {
6350 for (j = 0; j < nbrloops; j++) {
6351 int subscr;
6352
6353 subscr = mk_cval(j + 1, astb.bnd.dtype);
6354 ast2 = mk_subscr(astsubscrtmp, &subscr, 1, dtyperes);
6355 asn = mk_assn_stmt(ast2, A_DOVARG(DOs[j]), dtyperes);
6356 std = add_stmt_before(asn, stdnext);
6357 STD_LINENO(std) = lineno;
6358 STD_LOCAL(std) = 1;
6359 STD_PAR(std) = STD_PAR(stdnext);
6360 STD_TASK(std) = STD_TASK(stdnext);
6361 STD_ACCEL(std) = STD_ACCEL(stdnext);
6362 STD_KERNEL(std) = STD_KERNEL(stdnext);
6363 }
6364 } else {
6365 asn = mk_assn_stmt(astsubscrtmp, A_DOVARG(DOs[0]), dtyperes);
6366 std = add_stmt_before(asn, stdnext);
6367 STD_LINENO(std) = lineno;
6368 STD_LOCAL(std) = 1;
6369 STD_PAR(std) = STD_PAR(stdnext);
6370 STD_TASK(std) = STD_TASK(stdnext);
6371 STD_ACCEL(std) = STD_ACCEL(stdnext);
6372 STD_KERNEL(std) = STD_KERNEL(stdnext);
6373 }
6374 }
6375
6376 endif = mk_stmt(A_ENDIF, 0);
6377 std = add_stmt_before(endif, stdnext);
6378 STD_LINENO(std) = lineno;
6379 STD_LOCAL(std) = 1;
6380 STD_PAR(std) = STD_PAR(stdnext);
6381 STD_TASK(std) = STD_TASK(stdnext);
6382 STD_ACCEL(std) = STD_ACCEL(stdnext);
6383 STD_KERNEL(std) = STD_KERNEL(stdnext);
6384 break;
6385 case I_ALL:
6386 case I_ANY:
6387 if (A_OPTYPEG(ast) == I_ALL) {
6388 newast = mk_unop(OP_LNOT, ast2, DT_LOG);
6389 operand = mk_cval(SCFTN_FALSE, DT_LOG);
6390 } else {
6391 newast = ast2;
6392 operand = mk_cval(SCFTN_TRUE, DT_LOG);
6393 }
6394 asn = mk_assn_stmt(astsubscrtmp, operand, dtsclr);
6395
6396 ifast = mk_stmt(A_IFTHEN, 0);
6397 A_IFEXPRP(ifast, newast);
6398 std = add_stmt_before(ifast, stdnext);
6399 STD_LINENO(std) = lineno;
6400 STD_LOCAL(std) = 1;
6401 STD_PAR(std) = STD_PAR(stdnext);
6402 STD_TASK(std) = STD_TASK(stdnext);
6403 STD_ACCEL(std) = STD_ACCEL(stdnext);
6404 STD_KERNEL(std) = STD_KERNEL(stdnext);
6405
6406 std = add_stmt_before(asn, stdnext);
6407 STD_LINENO(std) = lineno;
6408 STD_LOCAL(std) = 1;
6409 STD_PAR(std) = STD_PAR(stdnext);
6410 STD_TASK(std) = STD_TASK(stdnext);
6411 STD_ACCEL(std) = STD_ACCEL(stdnext);
6412 STD_KERNEL(std) = STD_KERNEL(stdnext);
6413
6414 endif = mk_stmt(A_ENDIF, 0);
6415 std = add_stmt_before(endif, stdnext);
6416 STD_LINENO(std) = lineno;
6417 STD_LOCAL(std) = 1;
6418 STD_PAR(std) = STD_PAR(stdnext);
6419 STD_TASK(std) = STD_TASK(stdnext);
6420 STD_ACCEL(std) = STD_ACCEL(stdnext);
6421 STD_KERNEL(std) = STD_KERNEL(stdnext);
6422 break;
6423 default:
6424 assert(0, "inline_reduction_f90: unknown type", ast, 4);
6425 }
6426
6427 if (mask) {
6428 endif_ast = mk_stmt(A_ENDIF, 0);
6429 std = add_stmt_before(endif_ast, stdnext);
6430 STD_LINENO(std) = lineno;
6431 STD_LOCAL(std) = 1;
6432 STD_PAR(std) = STD_PAR(stdnext);
6433 STD_TASK(std) = STD_TASK(stdnext);
6434 STD_ACCEL(std) = STD_ACCEL(stdnext);
6435 STD_KERNEL(std) = STD_KERNEL(stdnext);
6436 }
6437
6438 destref = dest;
6439 eldtype = dtypetmp; /* assume subscripted object is the immediate lhs */
6440 destsptr = memsym_of_ast(dest);
6441 ast2 = search_conform_array(dest, TRUE);
6442 if (ast2) {
6443 /* array-valued result. The result could be something like
6444 * dt(:)%mem, du%amem(:), arr(:)
6445 * Need to locate the array in the lhs which needs to be subscripted.
6446 */
6447 int ss;
6448 if (A_TYPEG(ast2) == A_SUBSCR)
6449 ss = sptr_of_subscript(ast2);
6450 else
6451 ss = memsym_of_ast(ast2);
6452 if (ss != destsptr) {
6453 /* subscripted object is some aggregate */
6454 destsptr = ss;
6455 eldtype = DTY(DTYPEG(destsptr) + 1);
6456 destref = ast2;
6457 }
6458 }
6459 ast2 = mk_id(destsptr);
6460 ast2 = check_member(ast_is_sym(dest) &&
6461 (sym_of_ast(dest) != pass_sym_of_ast(dest))
6462 ? A_PARENTG(dest)
6463 : dest,
6464 ast2);
6465 ad = AD_DPTR(DTYPEG(destsptr));
6466 destndim = AD_NUMDIM(ad);
6467 for (i = 1; i <= nbrloops; i++) {
6468 newast = mk_stmt(A_ENDDO, 0);
6469 std = add_stmt_before(newast, stdnext);
6470 STD_LINENO(std) = lineno;
6471 STD_LOCAL(std) = 1;
6472 STD_PAR(std) = STD_PAR(stdnext);
6473 STD_TASK(std) = STD_TASK(stdnext);
6474 STD_ACCEL(std) = STD_ACCEL(stdnext);
6475 STD_KERNEL(std) = STD_KERNEL(stdnext);
6476 if (i == dim && destref != asttmp) {
6477 if (nbrloops > 1) {
6478 if (A_TYPEG(destref) == A_SUBSCR) {
6479 asd = A_ASDG(destref);
6480 curloop = 0;
6481 for (j = 0; j < destndim; j++) {
6482 destsub = ASD_SUBS(asd, j);
6483 if (A_TYPEG(destsub) != A_TRIPLE) {
6484 subs[j] = destsub;
6485 } else if (curloop < dim - 1) {
6486 subs[j] = destsub;
6487 curloop++;
6488 } else {
6489 /*
6490 * for DO i$a = m1, m2, m3
6491 * the subscripting of
6492 * dest(lb:ub:st)
6493 *
6494 * ( (i$a - m1)/m3 ) * st + lb
6495 *
6496 */
6497 int o;
6498 int mdo;
6499 subs[j] = loopidx[++curloop];
6500 mdo = DOs[curloop];
6501 o = mk_binop(OP_SUB, subs[j], A_M1G(mdo), astb.bnd.dtype);
6502 if ((A_M3G(mdo) != astb.i1) && (A_M3G(mdo) != astb.k1))
6503 o = mk_binop(OP_DIV, o, A_M3G(mdo), astb.bnd.dtype);
6504 if (A_STRIDEG(destsub))
6505 o = mk_binop(OP_MUL, o, A_STRIDEG(destsub), astb.bnd.dtype);
6506 o = mk_binop(OP_ADD, o, A_LBDG(destsub), astb.bnd.dtype);
6507 subs[j] = o;
6508 }
6509 }
6510 } else {
6511 for (j = 0; j < destndim; j++) {
6512 if (j < dim - 1) {
6513 int lb, ub;
6514 lb = check_member(destref, AD_LWBD(ad, j));
6515 ub = check_member(destref, AD_UPBD(ad, j));
6516 subs[j] = mk_triple(lb, ub, astb.bnd.one);
6517 } else {
6518 subs[j] = loopidx[j + 1];
6519 }
6520 }
6521 }
6522 ast2 = subscript_lhs(ast2, subs, destndim, eldtype, dest, destref);
6523 ast2 = convert_subscript_in_expr(ast2);
6524 ast2 = mk_assn_stmt(ast2, asttmp, dtypetmp);
6525 std = add_stmt_before(ast2, stdnext);
6526 STD_LINENO(std) = lineno;
6527 STD_LOCAL(std) = 1;
6528 STD_PAR(std) = STD_PAR(stdnext);
6529 STD_TASK(std) = STD_TASK(stdnext);
6530 STD_ACCEL(std) = STD_ACCEL(stdnext);
6531 STD_KERNEL(std) = STD_KERNEL(stdnext);
6532 }
6533 }
6534 }
6535
6536 if (ALLOCG(sptrtmp)) {
6537 newast = mk_stmt(A_ALLOC, 0);
6538 A_TKNP(newast, TK_DEALLOCATE);
6539 A_LOPP(newast, 0);
6540 A_SRCP(newast, asttmp);
6541 if (dest != asttmp)
6542 std = add_stmt_before(newast, stdnext);
6543 else
6544 std = add_stmt_before(newast, STD_NEXT(stdnext));
6545 STD_LINENO(std) = lineno;
6546 STD_LOCAL(std) = 1;
6547 STD_PAR(std) = STD_PAR(stdnext);
6548 STD_TASK(std) = STD_TASK(stdnext);
6549 STD_ACCEL(std) = STD_ACCEL(stdnext);
6550 STD_KERNEL(std) = STD_KERNEL(stdnext);
6551 if (STD_ACCEL(std))
6552 STD_RESCOPE(std) = 1;
6553 }
6554
6555 if (dealloc_tmpval) {
6556 newast = mk_stmt(A_ALLOC, 0);
6557 A_TKNP(newast, TK_DEALLOCATE);
6558 A_LOPP(newast, 0);
6559 A_SRCP(newast, asttmpval);
6560 std = add_stmt_before(newast, stdnext);
6561 STD_LINENO(std) = lineno;
6562 STD_LOCAL(std) = 1;
6563 STD_PAR(std) = STD_PAR(stdnext);
6564 STD_TASK(std) = STD_TASK(stdnext);
6565 STD_ACCEL(std) = STD_ACCEL(stdnext);
6566 STD_KERNEL(std) = STD_KERNEL(stdnext);
6567 if (STD_ACCEL(std))
6568 STD_RESCOPE(std) = 1;
6569 }
6570
6571 if (dealloc_dest) {
6572 newast = mk_stmt(A_ALLOC, 0);
6573 A_TKNP(newast, TK_DEALLOCATE);
6574 A_LOPP(newast, 0);
6575 A_SRCP(newast, dest);
6576 std = add_stmt_before(newast, STD_NEXT(stdnext));
6577 STD_LINENO(std) = lineno;
6578 STD_LOCAL(std) = 1;
6579 STD_PAR(std) = STD_PAR(stdnext);
6580 STD_TASK(std) = STD_TASK(stdnext);
6581 STD_ACCEL(std) = STD_ACCEL(stdnext);
6582 STD_KERNEL(std) = STD_KERNEL(stdnext);
6583 if (STD_ACCEL(std))
6584 STD_RESCOPE(std) = 1;
6585 }
6586
6587 ccff_info(MSGOPT, "OPT022", 1, STD_LINENO(arg_gbl.std),
6588 "%reduction reduction inlined", "reduction=%s", sReduc, NULL);
6589
6590 return dest;
6591 }
6592
6593 static int
subscript_lhs(int arr,int * subs,int dim,DTYPE dtype,int origlhs,int destref)6594 subscript_lhs(int arr, int *subs, int dim, DTYPE dtype, int origlhs,
6595 int destref)
6596 {
6597 /*
6598 * need to subscript an array in the lhs. The origlhs could be something
6599 * like dt(:)%mem, du%amem(:), arr(:).
6600 * If the array is an aggregate, then need to just replace the array
6601 * in the origlhs with the subscripted form of the array and then apply
6602 * the remaining portion of the lhs; e.g.,
6603 * arr%m1%m2%...mem becomes arr(i$a)%m1%m2%...mem
6604 */
6605 int ast = mk_subscr(arr, subs, dim, dtype);
6606 if (origlhs == destref)
6607 return ast;
6608 ast = replace_ast_subtree(origlhs, destref, ast);
6609 return ast;
6610 }
6611
6612 /*
6613 * func_ast: A_FUNC or A_INTR
6614 * func_args: rewritten args
6615 * lhs: ast for lhs (temp) if non-zero
6616 */
6617 static int
matmul(int func_ast,int func_args,int lhs)6618 matmul(int func_ast, int func_args, int lhs)
6619 {
6620 /* func_ast is a function or intrinsic call. If it is a transformational
6621 * intrinsic, create an appropriate temp, rewrite, and return a load
6622 * of that temp.
6623 * For now, don't do anything with user-defined functions.
6624 */
6625 int shape;
6626 DTYPE dtype;
6627 int dim, ndims;
6628 int proc;
6629 int newsym;
6630 int temp_arr;
6631 int newargt;
6632 int srcarray;
6633 int retval;
6634 int ast;
6635 int nargs;
6636 char *name;
6637 FtnRtlEnum rtlRtn;
6638 int i;
6639 int subscr[MAXSUBS];
6640 int argt;
6641 int std;
6642 int indx;
6643 int sptr;
6644 int astnew;
6645 int temp_sptr, temp_ast, func;
6646 int arg1, arg2;
6647 int arg1_sptr, arg2_sptr;
6648 int arg1_rank, arg2_rank;
6649 LOGICAL tmp_lhs_array;
6650 LOGICAL matmul_transpose;
6651
6652 retval = mmul(func_ast, func_args, lhs);
6653 if (retval >= 0)
6654 return retval;
6655
6656 tmp_lhs_array = FALSE;
6657 /* it only handles calls */
6658 shape = A_SHAPEG(func_ast);
6659 dtype = A_DTYPEG(func_ast);
6660
6661 matmul_transpose = A_OPTYPEG(func_ast) == I_MATMUL_TRANSPOSE ? TRUE : FALSE;
6662
6663 /*
6664 * A_OPTYPEG(func_ast):
6665 * case I_MATMUL: matmul(matrix_a, matrix_b)
6666 * case I_MATMUL_TRANSPOSE: matmul(transpose(matrix_a), matrix_b)
6667 */
6668 switch (DTYG(A_DTYPEG(func_ast))) {
6669 case TY_BINT:
6670 rtlRtn = RTE_matmul_int1;
6671 break;
6672 case TY_SINT:
6673 rtlRtn = RTE_matmul_int2;
6674 break;
6675 case TY_INT:
6676 rtlRtn = RTE_matmul_int4;
6677 break;
6678 case TY_INT8:
6679 rtlRtn = RTE_matmul_int8;
6680 break;
6681 case TY_REAL:
6682 if (matmul_transpose) {
6683 rtlRtn = RTE_matmul_real4mxv_t;
6684 } else {
6685 rtlRtn = RTE_matmul_real4;
6686 }
6687 break;
6688 case TY_DBLE:
6689 if (matmul_transpose) {
6690 rtlRtn = RTE_matmul_real8mxv_t;
6691 } else {
6692 rtlRtn = RTE_matmul_real8;
6693 }
6694 break;
6695 case TY_CMPLX:
6696 if (matmul_transpose) {
6697 rtlRtn = RTE_matmul_cplx8mxv_t;
6698 } else {
6699 rtlRtn = RTE_matmul_cplx8;
6700 }
6701 break;
6702 case TY_DCMPLX:
6703 if (matmul_transpose) {
6704 rtlRtn = RTE_matmul_cplx16mxv_t;
6705 } else {
6706 rtlRtn = RTE_matmul_cplx16;
6707 }
6708 break;
6709 case TY_BLOG:
6710 rtlRtn = RTE_matmul_log1;
6711 break;
6712 case TY_SLOG:
6713 rtlRtn = RTE_matmul_log2;
6714 break;
6715 case TY_LOG:
6716 rtlRtn = RTE_matmul_log4;
6717 break;
6718 case TY_LOG8:
6719 rtlRtn = RTE_matmul_log8;
6720 break;
6721 default:
6722 error(456, 3, gbl.lineno, CNULL, CNULL);
6723 }
6724
6725 /* MORE if shape is set appropriately, the requirement that lhs is
6726 * contiguous can be dropped
6727 */
6728 arg1 = ARGT_ARG(func_args, 0);
6729 arg2 = ARGT_ARG(func_args, 1);
6730 check_arg_isalloc(arg1);
6731 check_arg_isalloc(arg2);
6732
6733 if (matmul_transpose) {
6734 nargs = 4;
6735 newargt = mk_argt(nargs);
6736 srcarray = ARGT_ARG(func_args, 0);
6737 ARGT_ARG(newargt, 1) = srcarray;
6738 ARGT_ARG(newargt, 2) = ARGT_ARG(func_args, 1);
6739 ARGT_ARG(newargt, 3) = astb.i1; /* place holder in case we recognize
6740 * more than this one case
6741 */
6742 } else {
6743 /* use general purpose F90 matmul */
6744 nargs = 3;
6745 newargt = mk_argt(nargs);
6746 srcarray = ARGT_ARG(func_args, 0);
6747 ARGT_ARG(newargt, 1) = srcarray;
6748 ARGT_ARG(newargt, 2) = ARGT_ARG(func_args, 1);
6749 }
6750
6751 name = mkRteRtnNm(rtlRtn);
6752
6753 newsym = sym_mkfunc(name, DT_NONE);
6754 /* get the temp and add the necessary statements */
6755 temp_arr =
6756 mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1), lhs, &retval);
6757 if (temp_arr != 0) {
6758 /* add temp_arr as argument */
6759 ARGT_ARG(newargt, 0) = retval;
6760 if (ALLOCG(temp_arr)) {
6761 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, 0);
6762 mk_mem_deallocate(mk_id(temp_arr), arg_gbl.std);
6763 }
6764 tmp_lhs_array = TRUE;
6765 } else {
6766 /* lhs was distributed properly for this intr */
6767 ARGT_ARG(newargt, 0) = lhs;
6768 retval = 0;
6769 }
6770 /* add call to function */
6771 /* make every call ICALL iff call changes the first argument and
6772 no side effect, this will help optimizer
6773 */
6774 ast = mk_func_node(A_ICALL, mk_id(newsym), nargs, newargt);
6775 A_OPTYPEP(ast, A_OPTYPEG(func_ast));
6776 add_stmt_before(ast, arg_gbl.std);
6777 return retval;
6778 }
6779
6780 typedef struct { /* info for each fast matmul array/vector argument */
6781 int rank; /* at most 2 */
6782 int ldim; /* "leading dimension" */
6783 int extent[2]; /* number of elements for each dimension */
6784 int addr; /* beginning address of the argument */
6785 } MMUL;
6786 static LOGICAL mmul_arg(int, int, MMUL *);
6787 static LOGICAL mmul_array(int);
6788 static int add_byval(int);
6789
6790 /*
6791 * func_ast: A_FUNC or A_INTR
6792 * func_args: rewritten args
6793 * lhs: ast for lhs (temp) if non-zero
6794 */
6795 static int
mmul(int func_ast,int func_args,int lhs)6796 mmul(int func_ast, int func_args, int lhs)
6797 {
6798 /* func_ast is a function or intrinsic call. If it is a transformational
6799 * intrinsic, create an appropriate temp, rewrite, and return a load
6800 * of that temp.
6801 * For now, don't do anything with user-defined functions.
6802 *
6803 * RTE_mmul_real4(ta,tb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
6804 * performs
6805 *
6806 * C = alpha*MATMUL(op(A), op(B)) + beta*C
6807 * where
6808 * op(X) = X
6809 * op(X) = TRANSPOSE(X)
6810 * op(X) = CONJG(X)
6811 *
6812 * V ta : Integer(32 bits)
6813 * 0: no TRANSPOSE nor CONJG
6814 * 1: TRANSPOSE(A)
6815 * 2: CONJG(A)
6816 * V tb : Integer(32 bits)
6817 * 0: no TRANSPOSE nor CONJG
6818 * 1: TRANSPOSE(B)
6819 * 2: CONJG(B)
6820 * V m : Integer
6821 * The number of rows of (transposed) A and C
6822 * V n : Integer
6823 * The number of columns of B and C
6824 * V k : Integer
6825 * The number of columns of (transposed) A and the number of
6826 * rows of B
6827 * R alpha: <matrix element type>
6828 * The scalar alpha.
6829 * R a : <matrix element type>
6830 * Matrix A.
6831 * V lda : Integer
6832 * Leading dimension of (pre-transposed) A
6833 * R b : <matrix element type>
6834 * Matrix B.
6835 * V ldb : Integer
6836 * Leading dimension of B
6837 * R beta : <matrix element type>
6838 * The scalar beta.
6839 * R c : <matrix element type>
6840 * Output Matrix C.
6841 * V ldc : Integer
6842 * Leading dimension of C
6843 *
6844 * V - pass by value; unless specified, value is a 64-bit integer
6845 * for a 64-bit target and 32-bit, otherwise,
6846 * R - pass by reference
6847 *
6848 * Our interface allows for
6849 * VxM - matmul(vectorA, matrixB) -> vectorC
6850 * MxV - matmul(matrixA, vectorB) -> vectorC
6851 *
6852 * For VxM:
6853 * m = 1
6854 * k = length of A & number of rows of B
6855 * n = number of columns of B and the length of C
6856 * lda = 1
6857 * ldb = as before
6858 * ldc = 1
6859 *
6860 * For MxV:
6861 * m = number of rows of A and the length of C
6862 * k = number of columns of A and the length of B
6863 * n = 1
6864 * lda = as before
6865 * ldb = k
6866 * ldc = m
6867 */
6868 int shape, rank;
6869 int dtype, elem_dty;
6870 int proc;
6871 int newsym;
6872 int temp_arr;
6873 int newargt;
6874 int arrA, arrB;
6875 INT ta, tb; /* transpose flags, actual values */
6876 MMUL mmA, mmB, mmC;
6877 int alpha, beta; /* ST_CONST symtab entries */
6878 INT num[2];
6879 int retval;
6880 int ast;
6881 int nargs;
6882 int subscr[MAXSUBS];
6883 int sptr;
6884 FtnRtlEnum rtlRtn;
6885
6886 retval = -1;
6887 if (XBIT(47, 0x10000000))
6888 return -1;
6889 /*
6890 * A_OPTYPEG(func_ast):
6891 * case I_MATMUL: matmul(matrix_a, matrix_b)
6892 * case I_MATMUL_TRANSPOSE: matmul(transpose(matrix_a), matrix_b)
6893 */
6894 dtype = A_DTYPEG(func_ast);
6895 elem_dty = DTY(dtype + 1);
6896 switch (elem_dty) {
6897 case DT_REAL4:
6898 alpha = stb.flt1;
6899 beta = stb.flt0;
6900 rtlRtn = RTE_mmul_real4;
6901 break;
6902 case DT_REAL8:
6903 alpha = stb.dbl1;
6904 beta = stb.dbl0;
6905 rtlRtn = RTE_mmul_real8;
6906 break;
6907 case DT_CMPLX8:
6908 num[0] = CONVAL2G(stb.flt1);
6909 num[1] = CONVAL2G(stb.flt0);
6910 alpha = getcon(num, DT_CMPLX8);
6911 num[0] = CONVAL2G(stb.flt0);
6912 num[1] = CONVAL2G(stb.flt0);
6913 beta = getcon(num, DT_CMPLX8);
6914 rtlRtn = RTE_mmul_cmplx8;
6915 break;
6916 case DT_CMPLX16:
6917 num[0] = stb.dbl1;
6918 num[1] = stb.dbl0;
6919 alpha = getcon(num, DT_CMPLX16);
6920 num[0] = stb.dbl0;
6921 num[1] = stb.dbl0;
6922 beta = getcon(num, DT_CMPLX16);
6923 rtlRtn = RTE_mmul_cmplx16;
6924 break;
6925 default:
6926 return -1;
6927 }
6928 ta = tb = 0;
6929 if (A_OPTYPEG(func_ast) == I_MATMUL_TRANSPOSE) {
6930 /*
6931 * First argument is a transpose of a 2D matrix.
6932 * Second argument is a vector.
6933 */
6934 ta = 1;
6935 }
6936 /* it only handles calls */
6937 shape = A_SHAPEG(func_ast);
6938 rank = SHD_NDIM(shape);
6939
6940 /* MORE if shape is set appropriately, the requirement that lhs is
6941 * contiguous can be dropped
6942 */
6943 arrA = ARGT_ARG(func_args, 0);
6944 arrB = ARGT_ARG(func_args, 1);
6945 if (!mmul_arg(arrA, ta, &mmA))
6946 return -1;
6947 if (!mmul_arg(arrB, 0, &mmB))
6948 return -1;
6949 if (matmul_use_lhs(lhs, rank, elem_dty)) {
6950 if (!mmul_arg(lhs, 0, &mmC))
6951 return -1;
6952 /*
6953 * A question here is if the lhs is not suitable as C, should
6954 * we go ahead and create a temp and call the fast matmul at
6955 * expense of 2 sets of copying memory, i.e.,
6956 * tmp = matmu(A, B);
6957 * C = tmp;
6958 * If YES, need to restructure when/how we perform
6959 * temp_arr = mk_result_sptr(func_ast, ... ;
6960 * which is currently done below ...
6961 */
6962 }
6963 if (mmA.rank == 1) {
6964 /* VxM */
6965 mmA.extent[0] = mmA.extent[1]; /* m is 1 */
6966 mmA.extent[1] = mmB.extent[0]; /* k from B */
6967 mmA.ldim = mmA.extent[0]; /* 1 */
6968 } else if (mmB.rank == 1) {
6969 /* MxV */
6970 /* n is 1 */
6971 mmB.extent[0] = mmA.extent[1]; /* k */
6972 }
6973 nargs = 13;
6974 newargt = mk_argt(nargs);
6975 newsym = sym_mkfunc_nodesc(mkRteRtnNm(rtlRtn), DT_NONE);
6976 ARGT_ARG(newargt, 0) = add_byval(mk_cval1(ta, DT_INT4));
6977 ARGT_ARG(newargt, 1) = add_byval(mk_cval1(tb, DT_INT4));
6978 ARGT_ARG(newargt, 2) = add_byval(mmA.extent[0]); /* m */
6979 ARGT_ARG(newargt, 3) = add_byval(mmB.extent[1]); /* n */
6980 ARGT_ARG(newargt, 4) = add_byval(mmA.extent[1]); /* k */
6981 ARGT_ARG(newargt, 5) = mk_cnst(alpha);
6982 ARGT_ARG(newargt, 6) = mmA.addr;
6983 ARGT_ARG(newargt, 7) = add_byval(mmA.ldim);
6984 ARGT_ARG(newargt, 8) = mmB.addr;
6985 ARGT_ARG(newargt, 9) = add_byval(mmB.ldim);
6986 ARGT_ARG(newargt, 10) = mk_cnst(beta);
6987
6988 /* get the temp and add the necessary statements */
6989 temp_arr =
6990 mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1), lhs, &retval);
6991 if (temp_arr != 0) {
6992 /* add temp_arr as argument */
6993 (void)mmul_arg(retval, 0, &mmC);
6994 if (ALLOCG(temp_arr)) {
6995 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, 0);
6996 mk_mem_deallocate(mk_id(temp_arr), arg_gbl.std);
6997 }
6998 } else {
6999 /* lhs was distributed properly for this intr */
7000 ARGT_ARG(newargt, 11) = lhs;
7001 retval = 0;
7002 }
7003 if (mmA.rank == 1) {
7004 mmC.ldim = mmA.extent[0]; /* 1 */
7005 }
7006 ARGT_ARG(newargt, 11) = mmC.addr;
7007 ARGT_ARG(newargt, 12) = add_byval(mmC.ldim);
7008
7009 /* add call to function */
7010 /* make every call ICALL iff call changes the first argument and
7011 no side effect, this will help optimizer
7012 */
7013 ast = mk_func_node(A_ICALL, mk_id(newsym), nargs, newargt);
7014 A_OPTYPEP(ast, A_OPTYPEG(func_ast));
7015 add_stmt_before(ast, arg_gbl.std);
7016 #if DEBUG
7017 ccff_info(MSGOPT, "OPT049", 1, STD_LINENO(arg_gbl.std),
7018 "MATMUL replaced by call to %mmul", "mmul=%s", mkRteRtnNm(rtlRtn),
7019 NULL);
7020 #endif
7021
7022 return retval;
7023 }
7024
7025 static LOGICAL
mmul_arg(int arr,int transpose,MMUL * mm)7026 mmul_arg(int arr, int transpose, MMUL *mm)
7027 {
7028 int sptr;
7029 int shape;
7030 int ldim;
7031 int rank, dt, i;
7032 int lb, ub, stride;
7033 int m;
7034
7035 sptr = find_array(arr, NULL);
7036 if (POINTERG(sptr)
7037 #ifdef CONTIGATTRG
7038 && !CONTIGATTRG(sptr)
7039 #endif
7040 )
7041 return FALSE;
7042 shape = A_SHAPEG(arr);
7043 if (!shape)
7044 return FALSE;
7045 mm->rank = SHD_NDIM(shape);
7046 if (ASSUMSHPG(sptr) && mm->rank != 1
7047 #ifdef CONTIGATTRG
7048 && !CONTIGATTRG(sptr)
7049 #endif
7050 ) {
7051 /*
7052 * assumed-shaped arrays are guaranteed to be stride 1 in
7053 * just the first dimension.
7054 */
7055 return FALSE;
7056 }
7057 if (A_TYPEG(arr) == A_ID) {
7058 /* whole */
7059 mm->addr = arr;
7060 } else if (A_TYPEG(arr) == A_MEM) {
7061 /* whole -- allowing unsubscripted members is new as of 5/25/2012;
7062 * so to back out, just add 'return FALSE;' here.
7063 */
7064 mm->addr = arr;
7065 } else if (mmul_array(arr)) {
7066 int asd;
7067 int subscr[MAXSUBS];
7068 asd = A_ASDG(arr);
7069 rank = ASD_NDIM(asd);
7070 for (i = 0; i < rank; ++i) {
7071 int ss;
7072 ss = ASD_SUBS(asd, i);
7073 if (A_TYPEG(ss) == A_TRIPLE) {
7074 subscr[i] = A_LBDG(ss);
7075 } else {
7076 subscr[i] = ss;
7077 }
7078 }
7079 mm->addr = mk_subscr(A_LOPG(arr), subscr, rank, DDTG(A_DTYPEG(arr)));
7080 } else
7081 return FALSE;
7082
7083 for (i = 0; i < mm->rank; i++) {
7084 lb = SHD_LWB(shape, i);
7085 ub = SHD_UPB(shape, i);
7086 stride = SHD_STRIDE(shape, i);
7087 m = mk_binop(OP_SUB, ub, lb, astb.bnd.dtype);
7088 m = mk_binop(OP_ADD, m, stride, astb.bnd.dtype);
7089 mm->extent[i] = m;
7090 }
7091 /* ldim must be before any tranpose */
7092 if (STYPEG(sptr) == ST_MEMBER) {
7093 ldim = ADD_EXTNTAST(DTYPEG(sptr), 0);
7094 ldim = check_member(mm->addr, ldim);
7095 }
7096 #ifdef NOEXTENTG
7097 else if (HCCSYMG(sptr) && SCG(sptr) == SC_LOCAL && ALLOCG(sptr) &&
7098 (NOEXTENTG(sptr) || simply_contiguous(arr))) {
7099 /*
7100 * the EXTNTAST temp may not be defined for compiler-created
7101 * allocatable temps assigned the value of the argument.
7102 */
7103 ADSC *tad;
7104 tad = AD_DPTR(DTYPEG(sptr));
7105 ldim = mk_extent_expr(AD_LWBD(tad, 0), AD_UPBD(tad, 0));
7106 }
7107 #endif
7108 #ifdef CONTIGATTRG
7109 else if (CONTIGATTRG(sptr)) {
7110 ADSC *tad;
7111 tad = AD_DPTR(DTYPEG(sptr));
7112 ldim = mk_extent_expr(AD_LWBD(tad, 0), AD_UPBD(tad, 0));
7113 }
7114 #endif
7115 else {
7116 ldim = ADD_EXTNTAST(DTYPEG(sptr), 0);
7117 }
7118 if (transpose) {
7119 /* extents are post-tranposed */
7120 m = mm->extent[0];
7121 mm->extent[0] = mm->extent[1];
7122 mm->extent[1] = m;
7123 }
7124 if (astb.bnd.dtype != DT_INT8) {
7125 ldim = mk_convert(ldim, DT_INT8);
7126 for (i = 0; i < mm->rank; i++) {
7127 mm->extent[i] = mk_convert(mm->extent[i], DT_INT8);
7128 }
7129 }
7130 if (mm->rank == 1)
7131 mm->extent[1] = astb.k1;
7132 mm->ldim = ldim;
7133 return TRUE;
7134 }
7135
7136 /* Check if each section is contiguous or whole */
7137 static LOGICAL
mmul_array(int arr_ast)7138 mmul_array(int arr_ast)
7139 {
7140 int asd, ss;
7141 int ndims, dim;
7142 int astsub;
7143 int sptr;
7144 int ast1;
7145 LOGICAL any;
7146
7147 ast1 = A_TYPEG(arr_ast) == A_MEM ? A_MEMG(arr_ast) : arr_ast;
7148 if (!ast1)
7149 return FALSE;
7150
7151 if (!A_SHAPEG(ast1) || A_TYPEG(ast1) == A_ID)
7152 return TRUE;
7153 asd = A_ASDG(ast1);
7154 ndims = ASD_NDIM(asd);
7155 any = FALSE;
7156 for (dim = ndims - 1; dim >= 0; dim--) {
7157 ss = ASD_SUBS(asd, dim);
7158 if (A_TYPEG(ss) == A_TRIPLE) {
7159 if (!stride1_triple(ss)) {
7160 return FALSE;
7161 }
7162 any = TRUE;
7163 continue;
7164 }
7165 if (DTY(A_DTYPEG(ss)) == TY_ARRAY) {
7166 /*
7167 * No vector indexing ...
7168 */
7169 return FALSE;
7170 }
7171 if (any) {
7172 /*
7173 * The sections must be in consecutive leading dimensions
7174 */
7175 return FALSE;
7176 }
7177 }
7178 return TRUE;
7179 }
7180
7181 static int
add_byval(int arg)7182 add_byval(int arg)
7183 {
7184 int ast;
7185 ast = mk_unop(OP_VAL, arg, A_DTYPEG(arg));
7186 return ast;
7187 }
7188
7189 /* reshape(source, shape, [pad, order]) */
7190 static int
reshape(int func_ast,int func_args,int lhs)7191 reshape(int func_ast, int func_args, int lhs)
7192 {
7193 int dtype;
7194 int proc;
7195 int newsym;
7196 int temp_arr;
7197 int newargt;
7198 int srcarray;
7199 int retval;
7200 int ast;
7201 int nargs;
7202 FtnRtlEnum rtlRtn;
7203 int i;
7204 int subscr[MAXSUBS];
7205 int argt;
7206 int std;
7207 int sptr;
7208 int astnew;
7209 int ast_from_len;
7210 int temp_sptr, temp_ast, func;
7211 LOGICAL tmp_lhs_array;
7212
7213 dtype = A_DTYPEG(func_ast);
7214 retval = _reshape(func_args, dtype, lhs);
7215 if (retval > 0) {
7216 return retval;
7217 }
7218 ast_from_len = 0;
7219 tmp_lhs_array = FALSE;
7220 if (DTYG(dtype) == TY_CHAR) {
7221 rtlRtn = RTE_reshapeca;
7222 if (DDTG(dtype) == DT_ASSCHAR || DDTG(dtype) == DT_ASSNCHAR ||
7223 DDTG(dtype) == DT_DEFERCHAR || DDTG(dtype) == DT_DEFERNCHAR) {
7224 ast_from_len = ARGT_ARG(func_args, 0);
7225 }
7226 } else
7227 rtlRtn = RTE_reshape;
7228 nargs = 5;
7229 srcarray = ARGT_ARG(func_args, 0);
7230 newargt = mk_argt(nargs);
7231 ARGT_ARG(newargt, 1) = srcarray;
7232 ARGT_ARG(newargt, 2) = ARGT_ARG(func_args, 1);
7233 if (ARGT_ARG(func_args, 2) == 0)
7234 if (DTYG(dtype) == TY_CHAR)
7235 ARGT_ARG(newargt, 3) = astb.ptr0c;
7236 else
7237 ARGT_ARG(newargt, 3) = astb.ptr0;
7238 else
7239 ARGT_ARG(newargt, 3) = ARGT_ARG(func_args, 2);
7240 if (ARGT_ARG(func_args, 3) == 0)
7241 ARGT_ARG(newargt, 4) = astb.ptr0;
7242 else
7243 ARGT_ARG(newargt, 4) = ARGT_ARG(func_args, 3);
7244 /* get the name of the library routine */
7245 newsym = sym_mkfunc(mkRteRtnNm(rtlRtn), DT_NONE);
7246 /* get the temp and add the necessary statements */
7247 /* need to put this into a temp */
7248 temp_arr =
7249 mk_result_sptr(func_ast, func_args, subscr, DTY(dtype + 1), lhs, &retval);
7250 if (temp_arr != 0) {
7251 /* add temp_arr as argument */
7252 ARGT_ARG(newargt, 0) = retval;
7253 if (ALLOCG(temp_arr)) {
7254 mk_mem_allocate(mk_id(temp_arr), subscr, arg_gbl.std, ast_from_len);
7255 mk_mem_deallocate(mk_id(temp_arr), arg_gbl.std);
7256 }
7257 tmp_lhs_array = TRUE;
7258 } else {
7259 /* lhs was distributed properly for this intr */
7260 ARGT_ARG(newargt, 0) = lhs;
7261 retval = 0;
7262 }
7263 /* add call to function */
7264 /* make every call ICALL iff call changes the first argument and
7265 * no side effect, this will help optimizer
7266 */
7267 ast = mk_func_node(A_ICALL, mk_id(newsym), nargs, newargt);
7268 A_OPTYPEP(ast, A_OPTYPEG(func_ast));
7269 add_stmt_before(ast, arg_gbl.std);
7270 return retval;
7271 }
7272
7273 /* reshape(source, shape, [pad, order])
7274 *
7275 * Attempt to optimize reshape by representing the result of the reshape
7276 * as a (Cray) pointer of the source argument. The requirements for this
7277 * optimization are:
7278 * o pad & order are not present
7279 * o the source:
7280 * o + is not pointer
7281 * o + is not assumed-shape array with rank > 1 unless the shape is in the
7282 * first dimension
7283 * o + is contiguous
7284 * o + if character, has constant length
7285 * o + if member, shape is not in the parent
7286 * o the extent of the shape array is constant
7287 */
7288 static int
_reshape(int func_args,DTYPE dtype,int lhs)7289 _reshape(int func_args, DTYPE dtype, int lhs)
7290 {
7291 int retval;
7292 int srcarr, shparr; /* source & shape arguments, resp. */
7293 int sptr;
7294 int i, extnt;
7295 int shpdt, edt;
7296 int arrelem;
7297 int subs, subs_dt, stride;
7298 int ast, ast2, asn;
7299 int subscr[MAXSUBS];
7300 int resdt;
7301 int temp;
7302 int temp_p;
7303 ADSC *ad;
7304 int mult;
7305 int zbase;
7306
7307 retval = 0;
7308 if (XBIT(47, 0x20000000))
7309 return 0;
7310 if (ARGT_ARG(func_args, 2) || ARGT_ARG(func_args, 3))
7311 /* pad and order must not be present */
7312 return 0;
7313 if (DTYG(dtype) == TY_CHAR) {
7314 if (DDTG(dtype) == DT_ASSCHAR || DDTG(dtype) == DT_ASSNCHAR ||
7315 DDTG(dtype) == DT_DEFERCHAR || DDTG(dtype) == DT_DEFERNCHAR) {
7316 return 0;
7317 }
7318 }
7319 srcarr = ARGT_ARG(func_args, 0);
7320 sptr = find_array(srcarr, NULL);
7321 if (POINTERG(sptr))
7322 return 0;
7323 if (STYPEG(sptr) != ST_MEMBER && SCG(sptr) == SC_DUMMY && ASSUMSHPG(sptr) &&
7324 rank_of_sym(sptr) > 1) {
7325 int shd;
7326 shd = A_SHAPEG(srcarr);
7327 if (SHD_NDIM(shd) > 1)
7328 return 0;
7329 /*
7330 * is the shape in the first dimension and contiguous?
7331 * will be decided a few lines below by the call to
7332 * contiguous_section()
7333 */
7334 }
7335 /*
7336 * Ignore member reference whose shape is in the parent.
7337 */
7338 if (A_TYPEG(srcarr) == A_MEM && !A_SHAPEG(A_MEMG(srcarr)))
7339 return 0;
7340 /*
7341 * if subscripted, make sure the source is contiguous.
7342 */
7343 if (A_TYPEG(srcarr) == A_SUBSCR && !contiguous_section(srcarr))
7344 return 0;
7345 shparr = ARGT_ARG(func_args, 1);
7346 if (A_TYPEG(shparr) == A_MEM && !A_SHAPEG(A_MEMG(shparr)))
7347 /*
7348 * At this time, ignore if the parent has 'shape'; generating the
7349 * subscripted refs of the shape array is currently relatively simple.
7350 */
7351 return 0;
7352
7353 shpdt = A_DTYPEG(shparr);
7354 extnt = extent_of_shape(A_SHAPEG(shparr), 0);
7355 if (!extnt || !A_ALIASG(extnt))
7356 return 0;
7357 extnt = get_int_cval(A_SPTRG(A_ALIASG(extnt)));
7358 edt = DTY(shpdt + 1);
7359 /*
7360 * Someday, it sure would be nice if we could detect that the shape
7361 * array represents an array constructor of 'contant' values.
7362 * But for now, just make the 'shape' adjustable.
7363 *
7364 * Create a adjustable array (Cray) pointer temp. It will by
7365 * marked 'RESHAPED' indicating that it will be representing a
7366 * section of memory that has been reshape and that the address
7367 * will be stored in its 'hidden' the pointer variable.
7368 */
7369 temp = sym_get_array("reshap", "r", DTY(A_DTYPEG(srcarr) + 1), extnt);
7370 SCP(temp, SC_BASED);
7371 RESHAPEDP(temp, 1);
7372 /*
7373 * Create the 'hidden' pointer that will locate the beginning of the
7374 * memory.
7375 */
7376 temp_p = sym_get_ptr(temp);
7377 MIDNUMP(temp, temp_p);
7378 ADJARRP(temp, 1);
7379 SEQP(temp, 1);
7380 /*
7381 * Generate the subscripted references of the shape argument to
7382 * represent the upper bounds of each dimension of the result.
7383 * The bounds will be:
7384 * ( 1:SHAPE(1), 1:SHAPE(2), ... )
7385 * Also, create the bounds temps for the upper bound(s), multiplier(s),
7386 * and 'zbase'
7387 */
7388 /*fprintf(STDERR, "RESHAPE SHP ");dbg_print_ast(shparr,0);*/
7389 arrelem = first_element(shparr);
7390 /*fprintf(STDERR, "RESHAPE SHP1");dbg_print_ast(arrelem,0);*/
7391 subs = ASD_SUBS(A_ASDG(arrelem), 0); /* the first subscript value */
7392 subs_dt = A_DTYPEG(subs);
7393 stride = SHD_STRIDE(A_SHAPEG(shparr), 0);
7394 if (!stride || stride == astb.bnd.one)
7395 stride = mk_cval(1, subs_dt);
7396 else if (A_DTYPEG(stride) != subs_dt) {
7397 stride = mk_convert(stride, subs_dt);
7398 }
7399 ad = AD_DPTR(DTYPEG(temp));
7400 AD_ADJARR(ad) = 1;
7401 i = 0;
7402 while (1) {
7403 AD_LWBD(ad, i) = 0;
7404 AD_LWAST(ad, i) = astb.bnd.one;
7405 if (A_DTYPEG(arrelem) == astb.bnd.dtype)
7406 AD_UPBD(ad, i) = arrelem;
7407 else
7408 AD_UPBD(ad, i) = mk_convert(arrelem, astb.bnd.dtype);
7409 AD_UPAST(ad, i) = mk_bnd_ast();
7410 AD_EXTNTAST(ad, i) = AD_UPAST(ad, i);
7411 if (i == 0) {
7412 AD_MLPYR(ad, i) = astb.bnd.one;
7413 } else {
7414 AD_MLPYR(ad, i) = mk_bnd_ast();
7415 }
7416 i++;
7417 if (i >= extnt)
7418 break;
7419 subs = mk_binop(OP_ADD, subs, stride, subs_dt);
7420 subscr[0] = subs;
7421 arrelem = mk_subscr(A_LOPG(arrelem), subscr, 1, edt);
7422 }
7423 /*
7424 * Generate
7425 * 'hidden pointer' = loc(source)
7426 */
7427 ast = ast_intr(I_LOC, DT_PTR, 1, first_element(srcarr));
7428 ast2 = mk_id(temp_p);
7429 asn = mk_assn_stmt(ast2, ast, DT_PTR);
7430 add_stmt_before(asn, arg_gbl.std);
7431 /*fprintf(STDERR, "RESHAPE LOC");dbg_print_ast(asn,0);*/
7432 /*
7433 * Generate
7434 * the assignments to the upper bound and zbase temps
7435 */
7436 mult = astb.bnd.one;
7437 AD_MLPYR(ad, 0) = mult;
7438 for (i = 0; i < extnt; i++) {
7439 asn = mk_assn_stmt(AD_UPAST(ad, i), AD_UPBD(ad, i), astb.bnd.dtype);
7440 add_stmt_before(asn, arg_gbl.std);
7441 if (i) {
7442 mult = mk_mlpyr_expr(astb.bnd.one, AD_UPAST(ad, i - 1), mult);
7443 asn = mk_assn_stmt(AD_MLPYR(ad, i), mult, astb.bnd.dtype);
7444 add_stmt_before(asn, arg_gbl.std);
7445 }
7446 }
7447 zbase = mk_zbase_expr(ad);
7448 if (A_ALIASG(zbase)) {
7449 AD_ZBASE(ad) = zbase;
7450 } else {
7451 AD_ZBASE(ad) = mk_bnd_ast();
7452 asn = mk_assn_stmt(AD_ZBASE(ad), zbase, astb.bnd.dtype);
7453 add_stmt_before(asn, arg_gbl.std);
7454 }
7455 /*
7456 * Return the temp, expressed as a whole section in each dimension,
7457 * Simply returning 'temp' is not sufficient if we need to build a
7458 * descriptor, such as in
7459 * print *, reshape(yy,[3,4]) !!! need descriptor for reshape
7460 */
7461 retval = mk_id(temp);
7462 retval = convert_subscript_in_expr(retval);
7463 /*fprintf(STDERR, "RESHAPE"); dbg_print_ast(retval,0);*/
7464
7465 return retval;
7466 }
7467