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