Line data Source code
1 : /* Pass manager for Fortran front end.
2 : Copyright (C) 2010-2026 Free Software Foundation, Inc.
3 : Contributed by Thomas König.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it under
8 : the terms of the GNU General Public License as published by the Free
9 : Software Foundation; either version 3, or (at your option) any later
10 : version.
11 :
12 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "options.h"
25 : #include "gfortran.h"
26 : #include "dependency.h"
27 : #include "constructor.h"
28 : #include "intrinsic.h"
29 :
30 : /* Forward declarations. */
31 :
32 : static void strip_function_call (gfc_expr *);
33 : static void optimize_namespace (gfc_namespace *);
34 : static void optimize_assignment (gfc_code *);
35 : static bool optimize_op (gfc_expr *);
36 : static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op);
37 : static bool optimize_trim (gfc_expr *);
38 : static bool optimize_lexical_comparison (gfc_expr *);
39 : static bool is_empty_string (gfc_expr *e);
40 : static void doloop_warn (gfc_namespace *);
41 : static int do_intent (gfc_expr **);
42 : static int do_subscript (gfc_expr **);
43 : static void optimize_reduction (gfc_namespace *);
44 : static int callback_reduction (gfc_expr **, int *, void *);
45 : static void realloc_strings (gfc_namespace *);
46 : static gfc_expr *create_var (gfc_expr *, const char *vname=NULL);
47 : static int matmul_to_var_expr (gfc_expr **, int *, void *);
48 : static int matmul_to_var_code (gfc_code **, int *, void *);
49 : static int inline_matmul_assign (gfc_code **, int *, void *);
50 : static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
51 : locus *, gfc_namespace *,
52 : char *vname=NULL);
53 : static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *,
54 : bool *);
55 : static int call_external_blas (gfc_code **, int *, void *);
56 : static int matmul_temp_args (gfc_code **, int *,void *data);
57 : static int index_interchange (gfc_code **, int*, void *);
58 : static bool is_fe_temp (gfc_expr *e);
59 :
60 : #ifdef CHECKING_P
61 : static void check_locus (gfc_namespace *);
62 : #endif
63 :
64 : /* How deep we are inside an argument list. */
65 :
66 : static int count_arglist;
67 :
68 : /* Vector of gfc_expr ** we operate on. */
69 :
70 : static vec<gfc_expr **> expr_array;
71 :
72 : /* Pointer to the gfc_code we currently work on - to be able to insert
73 : a block before the statement. */
74 :
75 : static gfc_code **current_code;
76 :
77 : /* Pointer to the block to be inserted, and the statement we are
78 : changing within the block. */
79 :
80 : static gfc_code *inserted_block, **changed_statement;
81 :
82 : /* The namespace we are currently dealing with. */
83 :
84 : static gfc_namespace *current_ns;
85 :
86 : /* If we are within any forall loop. */
87 :
88 : static int forall_level;
89 :
90 : /* Keep track of whether we are within an OMP workshare. */
91 :
92 : static bool in_omp_workshare;
93 :
94 : /* Keep track of whether we are within an OMP atomic. */
95 :
96 : static bool in_omp_atomic;
97 :
98 : /* Keep track of whether we are within a WHERE statement. */
99 :
100 : static bool in_where;
101 :
102 : /* Keep track of iterators for array constructors. */
103 :
104 : static int iterator_level;
105 :
106 : /* Keep track of DO loop levels. */
107 :
108 : typedef struct {
109 : gfc_code *c;
110 : int branch_level;
111 : bool seen_goto;
112 : } do_t;
113 :
114 : static vec<do_t> doloop_list;
115 : static int doloop_level;
116 :
117 : /* Keep track of if and select case levels. */
118 :
119 : static int if_level;
120 : static int select_level;
121 :
122 : /* Vector of gfc_expr * to keep track of DO loops. */
123 :
124 : struct my_struct *evec;
125 :
126 : /* Keep track of association lists. */
127 :
128 : static bool in_assoc_list;
129 :
130 : /* Counter for temporary variables. */
131 :
132 : static int var_num = 1;
133 :
134 : /* What sort of matrix we are dealing with when inlining MATMUL. */
135 :
136 : enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T, A2TB2, A2TB2T, A2TB1 };
137 :
138 : /* Keep track of the number of expressions we have inserted so far
139 : using create_var. */
140 :
141 : int n_vars;
142 :
143 : /* Entry point - run all passes for a namespace. */
144 :
145 : void
146 316385 : gfc_run_passes (gfc_namespace *ns)
147 : {
148 :
149 : /* Warn about dubious DO loops where the index might
150 : change. */
151 :
152 316385 : doloop_level = 0;
153 316385 : if_level = 0;
154 316385 : select_level = 0;
155 316385 : doloop_warn (ns);
156 316385 : doloop_list.release ();
157 316385 : int w, e;
158 :
159 : #ifdef CHECKING_P
160 316385 : check_locus (ns);
161 : #endif
162 :
163 316385 : gfc_get_errors (&w, &e);
164 316385 : if (e > 0)
165 6034 : return;
166 :
167 310351 : if (flag_frontend_optimize || flag_frontend_loop_interchange)
168 261854 : optimize_namespace (ns);
169 :
170 310351 : if (flag_frontend_optimize)
171 : {
172 261838 : optimize_reduction (ns);
173 261838 : if (flag_dump_fortran_optimized)
174 0 : gfc_dump_parse_tree (ns, stdout);
175 :
176 261838 : expr_array.release ();
177 : }
178 :
179 310351 : if (flag_realloc_lhs)
180 310214 : realloc_strings (ns);
181 : }
182 :
183 : #ifdef CHECKING_P
184 :
185 : /* Callback function: Warn if there is no location information in a
186 : statement. */
187 :
188 : static int
189 1264395 : check_locus_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
190 : void *data ATTRIBUTE_UNUSED)
191 : {
192 1264395 : current_code = c;
193 1264395 : if (c
194 1264395 : && *c
195 1264395 : && (((*c)->loc.nextc == NULL)
196 1264395 : || ((*c)->loc.nextc == (gfc_char_t *) -1
197 1447 : && (*c)->loc.u.location == UNKNOWN_LOCATION)
198 1264395 : || ((*c)->loc.nextc != (gfc_char_t *) -1
199 1262948 : && ((*c)->loc.u.lb == NULL))))
200 :
201 0 : gfc_warning_internal (0, "Inconsistent internal state: "
202 : "No location in statement");
203 :
204 1264395 : return 0;
205 : }
206 :
207 :
208 : /* Callback function: Warn if there is no location information in an
209 : expression. */
210 :
211 : static int
212 3858095 : check_locus_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
213 : void *data ATTRIBUTE_UNUSED)
214 : {
215 :
216 3858095 : if (e
217 3858095 : && *e
218 3858095 : && (((*e)->where.nextc == NULL)
219 3858095 : || ((*e)->where.nextc == (gfc_char_t *) -1
220 395112 : && (*e)->where.u.location == UNKNOWN_LOCATION)
221 3858095 : || ((*e)->where.nextc != (gfc_char_t *) -1
222 3462983 : && ((*e)->where.u.lb == NULL))))
223 0 : gfc_warning_internal (0, "Inconsistent internal state: "
224 : "No location in expression near %L",
225 0 : &((*current_code)->loc));
226 3858095 : return 0;
227 : }
228 :
229 : /* Run check for missing location information. */
230 :
231 : static void
232 367350 : check_locus (gfc_namespace *ns)
233 : {
234 367350 : gfc_code_walker (&ns->code, check_locus_code, check_locus_expr, NULL);
235 :
236 419390 : for (ns = ns->contained; ns; ns = ns->sibling)
237 : {
238 52040 : if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
239 50965 : check_locus (ns);
240 : }
241 367350 : }
242 :
243 : #endif
244 :
245 : /* Callback for each gfc_code node invoked from check_realloc_strings.
246 : For an allocatable LHS string which also appears as a variable on
247 : the RHS, replace
248 :
249 : a = a(x:y)
250 :
251 : with
252 :
253 : tmp = a(x:y)
254 : a = tmp
255 : */
256 :
257 : static int
258 1249461 : realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
259 : void *data ATTRIBUTE_UNUSED)
260 : {
261 1249461 : gfc_expr *expr1, *expr2;
262 1249461 : gfc_code *co = *c;
263 1249461 : gfc_expr *n;
264 1249461 : gfc_ref *ref;
265 1249461 : bool found_substr;
266 :
267 1249461 : if (co->op != EXEC_ASSIGN)
268 : return 0;
269 :
270 324001 : expr1 = co->expr1;
271 324001 : if (expr1->ts.type != BT_CHARACTER
272 324655 : || !gfc_expr_attr(expr1).allocatable
273 327216 : || !expr1->ts.deferred)
274 : return 0;
275 :
276 7591 : if (is_fe_temp (expr1))
277 : return 0;
278 :
279 2469 : expr2 = gfc_discard_nops (co->expr2);
280 :
281 2469 : if (expr2->expr_type == EXPR_VARIABLE)
282 : {
283 516 : found_substr = false;
284 748 : for (ref = expr2->ref; ref; ref = ref->next)
285 : {
286 371 : if (ref->type == REF_SUBSTRING)
287 : {
288 : found_substr = true;
289 : break;
290 : }
291 : }
292 516 : if (!found_substr)
293 : return 0;
294 : }
295 1953 : else if (expr2->expr_type != EXPR_ARRAY
296 1513 : && (expr2->expr_type != EXPR_OP
297 75 : || expr2->value.op.op != INTRINSIC_CONCAT))
298 : return 0;
299 :
300 654 : if (!gfc_check_dependency (expr1, expr2, true))
301 : return 0;
302 :
303 : /* gfc_check_dependency doesn't always pick up identical expressions.
304 : However, eliminating the above sends the compiler into an infinite
305 : loop on valid expressions. Without this check, the gimplifier emits
306 : an ICE for a = a, where a is deferred character length. */
307 131 : if (!gfc_dep_compare_expr (expr1, expr2))
308 : return 0;
309 :
310 131 : current_code = c;
311 131 : inserted_block = NULL;
312 131 : changed_statement = NULL;
313 131 : n = create_var (expr2, "realloc_string");
314 131 : co->expr2 = n;
315 131 : return 0;
316 : }
317 :
318 : /* Callback for each gfc_code node invoked through gfc_code_walker
319 : from optimize_namespace. */
320 :
321 : static int
322 1053858 : optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
323 : void *data ATTRIBUTE_UNUSED)
324 : {
325 :
326 1053858 : gfc_exec_op op;
327 :
328 1053858 : op = (*c)->op;
329 :
330 1053858 : if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL
331 1053858 : || op == EXEC_CALL_PPC)
332 : count_arglist = 1;
333 : else
334 979581 : count_arglist = 0;
335 :
336 1053858 : current_code = c;
337 1053858 : inserted_block = NULL;
338 1053858 : changed_statement = NULL;
339 :
340 1053858 : if (op == EXEC_ASSIGN)
341 273567 : optimize_assignment (*c);
342 1053858 : return 0;
343 : }
344 :
345 : /* Callback for each gfc_expr node invoked through gfc_code_walker
346 : from optimize_namespace. */
347 :
348 : static int
349 3230762 : optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
350 : void *data ATTRIBUTE_UNUSED)
351 : {
352 3230762 : bool function_expr;
353 :
354 3230762 : if ((*e)->expr_type == EXPR_FUNCTION)
355 : {
356 254277 : count_arglist ++;
357 254277 : function_expr = true;
358 : }
359 : else
360 : function_expr = false;
361 :
362 3230762 : if (optimize_trim (*e))
363 366 : gfc_simplify_expr (*e, 0);
364 :
365 3230762 : if (optimize_lexical_comparison (*e))
366 4 : gfc_simplify_expr (*e, 0);
367 :
368 3230762 : if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
369 1211 : gfc_simplify_expr (*e, 0);
370 :
371 3230762 : if (function_expr)
372 254277 : count_arglist --;
373 :
374 3230762 : return 0;
375 : }
376 :
377 : /* Auxiliary function to handle the arguments to reduction intrinsics. If the
378 : function is a scalar, just copy it; otherwise returns the new element, the
379 : old one can be freed. */
380 :
381 : static gfc_expr *
382 398 : copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn)
383 : {
384 398 : gfc_expr *fcn, *e = c->expr;
385 :
386 398 : fcn = gfc_copy_expr (e);
387 398 : if (c->iterator)
388 : {
389 84 : gfc_constructor_base newbase;
390 84 : gfc_expr *new_expr;
391 84 : gfc_constructor *new_c;
392 :
393 84 : newbase = NULL;
394 84 : new_expr = gfc_get_expr ();
395 84 : new_expr->expr_type = EXPR_ARRAY;
396 84 : new_expr->ts = e->ts;
397 84 : new_expr->where = e->where;
398 84 : new_expr->rank = 1;
399 84 : new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where));
400 84 : new_c->iterator = c->iterator;
401 84 : new_expr->value.constructor = newbase;
402 84 : c->iterator = NULL;
403 :
404 84 : fcn = new_expr;
405 : }
406 :
407 398 : if (fcn->rank != 0)
408 : {
409 122 : gfc_isym_id id = fn->value.function.isym->id;
410 :
411 122 : if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
412 85 : fcn = gfc_build_intrinsic_call (current_ns, id,
413 : fn->value.function.isym->name,
414 : fn->where, 3, fcn, NULL, NULL);
415 37 : else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL)
416 37 : fcn = gfc_build_intrinsic_call (current_ns, id,
417 : fn->value.function.isym->name,
418 : fn->where, 2, fcn, NULL);
419 : else
420 0 : gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
421 :
422 122 : fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
423 : }
424 :
425 398 : return fcn;
426 : }
427 :
428 : /* Callback function for optimization of reductions to scalars. Transform ANY
429 : ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
430 : correspondingly. Handle only the simple cases without MASK and DIM. */
431 :
432 : static int
433 3274706 : callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
434 : void *data ATTRIBUTE_UNUSED)
435 : {
436 3274706 : gfc_expr *fn, *arg;
437 3274706 : gfc_intrinsic_op op;
438 3274706 : gfc_isym_id id;
439 3274706 : gfc_actual_arglist *a;
440 3274706 : gfc_actual_arglist *dim;
441 3274706 : gfc_constructor *c;
442 3274706 : gfc_expr *res, *new_expr;
443 3274706 : gfc_actual_arglist *mask;
444 :
445 3274706 : fn = *e;
446 :
447 3274706 : if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
448 219910 : || fn->value.function.isym == NULL)
449 : return 0;
450 :
451 179435 : id = fn->value.function.isym->id;
452 :
453 179435 : if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
454 177833 : && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
455 : return 0;
456 :
457 36800 : a = fn->value.function.actual;
458 :
459 : /* Don't handle MASK or DIM. */
460 :
461 36800 : dim = a->next;
462 :
463 36800 : if (dim->expr != NULL)
464 : return 0;
465 :
466 36673 : if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
467 : {
468 1476 : mask = dim->next;
469 1476 : if ( mask->expr != NULL)
470 : return 0;
471 : }
472 :
473 36549 : arg = a->expr;
474 :
475 36549 : if (arg->expr_type != EXPR_ARRAY)
476 : return 0;
477 :
478 177 : switch (id)
479 : {
480 : case GFC_ISYM_SUM:
481 : op = INTRINSIC_PLUS;
482 : break;
483 :
484 13 : case GFC_ISYM_PRODUCT:
485 13 : op = INTRINSIC_TIMES;
486 13 : break;
487 :
488 85 : case GFC_ISYM_ANY:
489 85 : op = INTRINSIC_OR;
490 85 : break;
491 :
492 6 : case GFC_ISYM_ALL:
493 6 : op = INTRINSIC_AND;
494 6 : break;
495 :
496 : default:
497 : return 0;
498 : }
499 :
500 177 : c = gfc_constructor_first (arg->value.constructor);
501 :
502 : /* Don't do any simplififcation if we have
503 : - no element in the constructor or
504 : - only have a single element in the array which contains an
505 : iterator. */
506 :
507 177 : if (c == NULL)
508 : return 0;
509 :
510 169 : res = copy_walk_reduction_arg (c, fn);
511 :
512 169 : c = gfc_constructor_next (c);
513 567 : while (c)
514 : {
515 229 : new_expr = gfc_get_expr ();
516 229 : new_expr->ts = fn->ts;
517 229 : new_expr->expr_type = EXPR_OP;
518 229 : new_expr->rank = fn->rank;
519 229 : new_expr->corank = fn->corank;
520 229 : new_expr->where = fn->where;
521 229 : new_expr->value.op.op = op;
522 229 : new_expr->value.op.op1 = res;
523 229 : new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn);
524 229 : res = new_expr;
525 229 : c = gfc_constructor_next (c);
526 : }
527 :
528 169 : gfc_simplify_expr (res, 0);
529 169 : *e = res;
530 169 : gfc_free_expr (fn);
531 :
532 169 : return 0;
533 : }
534 :
535 : /* Callback function for common function elimination, called from cfe_expr_0.
536 : Put all eligible function expressions into expr_array. */
537 :
538 : static int
539 3204666 : cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
540 : void *data ATTRIBUTE_UNUSED)
541 : {
542 :
543 3204666 : if ((*e)->expr_type != EXPR_FUNCTION)
544 : return 0;
545 :
546 : /* We don't do character functions with unknown charlens. */
547 253655 : if ((*e)->ts.type == BT_CHARACTER
548 9875 : && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
549 6957 : || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
550 : return 0;
551 :
552 : /* We don't do function elimination within FORALL statements, it can
553 : lead to wrong-code in certain circumstances. */
554 :
555 248919 : if (forall_level > 0)
556 : return 0;
557 :
558 : /* Function elimination inside an iterator could lead to functions which
559 : depend on iterator variables being moved outside. FIXME: We should check
560 : if the functions do indeed depend on the iterator variable. */
561 :
562 247808 : if (iterator_level > 0)
563 : return 0;
564 :
565 : /* If we don't know the shape at compile time, we create an allocatable
566 : temporary variable to hold the intermediate result, but only if
567 : allocation on assignment is active. */
568 :
569 247421 : if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
570 : return 0;
571 :
572 : /* Skip the test for pure functions if -faggressive-function-elimination
573 : is specified. */
574 247404 : if ((*e)->value.function.esym)
575 : {
576 : /* Don't create an array temporary for elemental functions. */
577 38898 : if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0)
578 : return 0;
579 :
580 : /* Only eliminate potentially impure functions if the
581 : user specifically requested it. */
582 38075 : if (!flag_aggressive_function_elimination
583 38059 : && !(*e)->value.function.esym->attr.pure
584 23664 : && !(*e)->value.function.esym->attr.implicit_pure)
585 : return 0;
586 : }
587 :
588 226764 : if ((*e)->value.function.isym)
589 : {
590 : /* Conversions are handled on the fly by the middle end,
591 : transpose during trans-* stages and TRANSFER by the middle end. */
592 205838 : if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION
593 177363 : || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER
594 379805 : || gfc_inline_intrinsic_function_p (*e))
595 : return 0;
596 :
597 : /* Don't create an array temporary for elemental functions,
598 : as this would be wasteful of memory.
599 : FIXME: Create a scalar temporary during scalarization. */
600 162434 : if ((*e)->value.function.isym->elemental && (*e)->rank > 0)
601 : return 0;
602 :
603 158363 : if (!(*e)->value.function.isym->pure)
604 : return 0;
605 : }
606 :
607 172517 : expr_array.safe_push (e);
608 172517 : return 0;
609 : }
610 :
611 : /* Auxiliary function to check if an expression is a temporary created by
612 : create var. */
613 :
614 : static bool
615 3831 : is_fe_temp (gfc_expr *e)
616 : {
617 3831 : if (e->expr_type != EXPR_VARIABLE)
618 : return false;
619 :
620 2561 : return e->symtree->n.sym->attr.fe_temp;
621 : }
622 :
623 : /* Determine the length of a string, if it can be evaluated as a constant
624 : expression. Return a newly allocated gfc_expr or NULL on failure.
625 : If the user specified a substring which is potentially longer than
626 : the string itself, the string will be padded with spaces, which
627 : is harmless. */
628 :
629 : static gfc_expr *
630 133 : constant_string_length (gfc_expr *e)
631 : {
632 :
633 133 : gfc_expr *length;
634 133 : gfc_ref *ref;
635 133 : gfc_expr *res;
636 133 : mpz_t value;
637 :
638 133 : if (e->ts.u.cl)
639 : {
640 133 : length = e->ts.u.cl->length;
641 133 : if (length && length->expr_type == EXPR_CONSTANT)
642 29 : return gfc_copy_expr(length);
643 : }
644 :
645 : /* See if there is a substring. If it has a constant length, return
646 : that and NULL otherwise. */
647 122 : for (ref = e->ref; ref; ref = ref->next)
648 : {
649 54 : if (ref->type == REF_SUBSTRING)
650 : {
651 36 : if (gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value))
652 : {
653 0 : res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
654 : &e->where);
655 :
656 0 : mpz_add_ui (res->value.integer, value, 1);
657 0 : mpz_clear (value);
658 0 : return res;
659 : }
660 : else
661 : return NULL;
662 : }
663 : }
664 :
665 : /* Return length of char symbol, if constant. */
666 68 : if (e->symtree && e->symtree->n.sym->ts.u.cl
667 0 : && e->symtree->n.sym->ts.u.cl->length
668 0 : && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
669 0 : return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length);
670 :
671 : return NULL;
672 :
673 : }
674 :
675 : /* Insert a block at the current position unless it has already
676 : been inserted; in this case use the one already there. */
677 :
678 : static gfc_namespace*
679 1954 : insert_block ()
680 : {
681 1954 : gfc_namespace *ns;
682 :
683 : /* If the block hasn't already been created, do so. */
684 1954 : if (inserted_block == NULL)
685 : {
686 1671 : inserted_block = XCNEW (gfc_code);
687 1671 : inserted_block->op = EXEC_BLOCK;
688 1671 : inserted_block->loc = (*current_code)->loc;
689 1671 : ns = gfc_build_block_ns (current_ns);
690 1671 : inserted_block->ext.block.ns = ns;
691 1671 : inserted_block->ext.block.assoc = NULL;
692 :
693 1671 : ns->code = *current_code;
694 :
695 : /* If the statement has a label, make sure it is transferred to
696 : the newly created block. */
697 :
698 1671 : if ((*current_code)->here)
699 : {
700 6 : inserted_block->here = (*current_code)->here;
701 6 : (*current_code)->here = NULL;
702 : }
703 :
704 1671 : inserted_block->next = (*current_code)->next;
705 1671 : changed_statement = &(inserted_block->ext.block.ns->code);
706 1671 : (*current_code)->next = NULL;
707 : /* Insert the BLOCK at the right position. */
708 1671 : *current_code = inserted_block;
709 1671 : ns->parent = current_ns;
710 : }
711 : else
712 283 : ns = inserted_block->ext.block.ns;
713 :
714 1954 : return ns;
715 : }
716 :
717 :
718 : /* Insert a call to the intrinsic len. Use a different name for
719 : the symbol tree so we don't run into trouble when the user has
720 : renamed len for some reason. */
721 :
722 : static gfc_expr*
723 18 : get_len_call (gfc_expr *str)
724 : {
725 18 : gfc_expr *fcn;
726 18 : gfc_actual_arglist *actual_arglist;
727 :
728 18 : fcn = gfc_get_expr ();
729 18 : fcn->expr_type = EXPR_FUNCTION;
730 18 : fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN);
731 18 : actual_arglist = gfc_get_actual_arglist ();
732 18 : actual_arglist->expr = str;
733 :
734 18 : fcn->value.function.actual = actual_arglist;
735 18 : fcn->where = str->where;
736 18 : fcn->ts.type = BT_INTEGER;
737 18 : fcn->ts.kind = gfc_charlen_int_kind;
738 :
739 18 : gfc_get_sym_tree ("__internal_len", current_ns, &fcn->symtree, false);
740 18 : fcn->symtree->n.sym->ts = fcn->ts;
741 18 : fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
742 18 : fcn->symtree->n.sym->attr.function = 1;
743 18 : fcn->symtree->n.sym->attr.elemental = 1;
744 18 : fcn->symtree->n.sym->attr.referenced = 1;
745 18 : fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
746 18 : gfc_commit_symbol (fcn->symtree->n.sym);
747 :
748 18 : return fcn;
749 : }
750 :
751 :
752 : /* Returns a new expression (a variable) to be used in place of the old one,
753 : with an optional assignment statement before the current statement to set
754 : the value of the variable. Creates a new BLOCK for the statement if that
755 : hasn't already been done and puts the statement, plus the newly created
756 : variables, in that block. Special cases: If the expression is constant or
757 : a temporary which has already been created, just copy it. */
758 :
759 : static gfc_expr*
760 1293 : create_var (gfc_expr * e, const char *vname)
761 : {
762 1293 : char name[GFC_MAX_SYMBOL_LEN +1];
763 1293 : gfc_symtree *symtree;
764 1293 : gfc_symbol *symbol;
765 1293 : gfc_expr *result;
766 1293 : gfc_code *n;
767 1293 : gfc_namespace *ns;
768 1293 : int i;
769 1293 : bool deferred;
770 :
771 1402 : if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
772 23 : return gfc_copy_expr (e);
773 :
774 : /* Creation of an array of unknown size requires realloc on assignment.
775 : If that is not possible, just return NULL. */
776 1270 : if (flag_realloc_lhs == 0 && e->rank > 0 && e->shape == NULL)
777 : return NULL;
778 :
779 1269 : ns = insert_block ();
780 :
781 1269 : if (vname)
782 1269 : snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname);
783 : else
784 0 : snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++);
785 :
786 1269 : if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
787 0 : gcc_unreachable ();
788 :
789 1269 : symbol = symtree->n.sym;
790 1269 : symbol->ts = e->ts;
791 :
792 1269 : if (e->rank > 0)
793 : {
794 406 : symbol->as = gfc_get_array_spec ();
795 406 : symbol->as->rank = e->rank;
796 406 : symbol->as->corank = e->corank;
797 :
798 406 : if (e->shape == NULL)
799 : {
800 : /* We don't know the shape at compile time, so we use an
801 : allocatable. */
802 206 : symbol->as->type = AS_DEFERRED;
803 206 : symbol->attr.allocatable = 1;
804 : }
805 : else
806 : {
807 200 : symbol->as->type = AS_EXPLICIT;
808 : /* Copy the shape. */
809 538 : for (i=0; i<e->rank; i++)
810 : {
811 338 : gfc_expr *p, *q;
812 :
813 338 : p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
814 : &(e->where));
815 338 : mpz_set_si (p->value.integer, 1);
816 338 : symbol->as->lower[i] = p;
817 :
818 338 : q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
819 : &(e->where));
820 338 : mpz_set (q->value.integer, e->shape[i]);
821 338 : symbol->as->upper[i] = q;
822 : }
823 : }
824 : }
825 :
826 1269 : deferred = 0;
827 1269 : if (e->ts.type == BT_CHARACTER)
828 : {
829 133 : gfc_expr *length;
830 :
831 133 : symbol->ts.u.cl = gfc_new_charlen (ns, NULL);
832 133 : length = constant_string_length (e);
833 133 : if (length)
834 29 : symbol->ts.u.cl->length = length;
835 104 : else if (e->expr_type == EXPR_VARIABLE
836 36 : && e->symtree->n.sym->ts.type == BT_CHARACTER
837 30 : && e->ts.u.cl->length)
838 : {
839 18 : symbol->ts.u.cl->length = get_len_call (gfc_copy_expr (e));
840 18 : symbol->ts.deferred = 0;
841 : }
842 : else
843 : {
844 86 : symbol->attr.allocatable = 1;
845 86 : symbol->ts.u.cl->length = NULL;
846 86 : symbol->ts.deferred = 1;
847 86 : deferred = 1;
848 : }
849 : }
850 :
851 1269 : symbol->attr.flavor = FL_VARIABLE;
852 1269 : symbol->attr.referenced = 1;
853 1269 : symbol->attr.dimension = e->rank > 0;
854 1269 : symbol->attr.fe_temp = 1;
855 1269 : symbol->attr.automatic = 1;
856 1269 : gfc_commit_symbol (symbol);
857 :
858 1269 : result = gfc_get_expr ();
859 1269 : result->expr_type = EXPR_VARIABLE;
860 1269 : result->ts = symbol->ts;
861 1269 : result->ts.deferred = deferred;
862 1269 : result->rank = e->rank;
863 1269 : result->corank = e->corank;
864 1269 : result->shape = gfc_copy_shape (e->shape, e->rank);
865 1269 : result->symtree = symtree;
866 1269 : result->where = e->where;
867 1269 : if (e->rank > 0)
868 : {
869 406 : result->ref = gfc_get_ref ();
870 406 : result->ref->type = REF_ARRAY;
871 406 : result->ref->u.ar.type = AR_FULL;
872 406 : result->ref->u.ar.where = e->where;
873 406 : result->ref->u.ar.dimen = e->rank;
874 812 : result->ref->u.ar.as = symbol->ts.type == BT_CLASS
875 406 : ? CLASS_DATA (symbol)->as : symbol->as;
876 406 : if (warn_array_temporaries)
877 15 : gfc_warning (OPT_Warray_temporaries,
878 : "Creating array temporary at %L", &(e->where));
879 : }
880 :
881 : /* Generate the new assignment. */
882 1269 : n = XCNEW (gfc_code);
883 1269 : n->op = EXEC_ASSIGN;
884 1269 : n->loc = (*current_code)->loc;
885 1269 : n->next = *changed_statement;
886 1269 : n->expr1 = gfc_copy_expr (result);
887 1269 : n->expr2 = e;
888 1269 : *changed_statement = n;
889 1269 : n_vars ++;
890 :
891 1269 : return result;
892 : }
893 :
894 : /* Warn about function elimination. */
895 :
896 : static void
897 6 : do_warn_function_elimination (gfc_expr *e)
898 : {
899 6 : const char *name;
900 6 : if (e->expr_type == EXPR_FUNCTION
901 6 : && !gfc_pure_function (e, &name) && !gfc_implicit_pure_function (e))
902 : {
903 2 : if (name)
904 2 : gfc_warning (OPT_Wfunction_elimination,
905 : "Removing call to impure function %qs at %L", name,
906 : &(e->where));
907 : else
908 0 : gfc_warning (OPT_Wfunction_elimination,
909 : "Removing call to impure function at %L",
910 : &(e->where));
911 : }
912 6 : }
913 :
914 :
915 : /* Callback function for the code walker for doing common function
916 : elimination. This builds up the list of functions in the expression
917 : and goes through them to detect duplicates, which it then replaces
918 : by variables. */
919 :
920 : static int
921 1446616 : cfe_expr_0 (gfc_expr **e, int *walk_subtrees,
922 : void *data ATTRIBUTE_UNUSED)
923 : {
924 1446616 : int i,j;
925 1446616 : gfc_expr *newvar;
926 1446616 : gfc_expr **ei, **ej;
927 :
928 : /* Don't do this optimization within OMP workshare/atomic or ASSOC lists. */
929 :
930 1446616 : if (in_omp_workshare || in_omp_atomic || in_assoc_list)
931 : {
932 11751 : *walk_subtrees = 0;
933 11751 : return 0;
934 : }
935 :
936 1434865 : expr_array.release ();
937 :
938 1434865 : gfc_expr_walker (e, cfe_register_funcs, NULL);
939 :
940 : /* Walk through all the functions. */
941 :
942 2895211 : FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1)
943 : {
944 : /* Skip if the function has been replaced by a variable already. */
945 25481 : if ((*ei)->expr_type == EXPR_VARIABLE)
946 0 : continue;
947 :
948 : newvar = NULL;
949 58690 : for (j=0; j<i; j++)
950 : {
951 33209 : ej = expr_array[j];
952 33209 : if (gfc_dep_compare_functions (*ei, *ej, true) == 0)
953 : {
954 566 : if (newvar == NULL)
955 566 : newvar = create_var (*ei, "fcn");
956 :
957 566 : if (warn_function_elimination)
958 6 : do_warn_function_elimination (*ej);
959 :
960 566 : free (*ej);
961 566 : *ej = gfc_copy_expr (newvar);
962 : }
963 : }
964 25481 : if (newvar)
965 566 : *ei = newvar;
966 : }
967 :
968 : /* We did all the necessary walking in this function. */
969 1434865 : *walk_subtrees = 0;
970 1434865 : return 0;
971 : }
972 :
973 : /* Callback function for common function elimination, called from
974 : gfc_code_walker. This keeps track of the current code, in order
975 : to insert statements as needed. */
976 :
977 : static int
978 1052040 : cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
979 : {
980 1052040 : current_code = c;
981 1052040 : inserted_block = NULL;
982 1052040 : changed_statement = NULL;
983 :
984 : /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
985 : and allocation on assignment are prohibited inside WHERE, and finally
986 : masking an expression would lead to wrong-code when replacing
987 :
988 : WHERE (a>0)
989 : b = sum(foo(a) + foo(a))
990 : END WHERE
991 :
992 : with
993 :
994 : WHERE (a > 0)
995 : tmp = foo(a)
996 : b = sum(tmp + tmp)
997 : END WHERE
998 : */
999 :
1000 1052040 : if ((*c)->op == EXEC_WHERE)
1001 : {
1002 352 : *walk_subtrees = 0;
1003 352 : return 0;
1004 : }
1005 :
1006 :
1007 : return 0;
1008 : }
1009 :
1010 : /* Dummy function for expression call back, for use when we
1011 : really don't want to do any walking. */
1012 :
1013 : static int
1014 10354693 : dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
1015 : void *data ATTRIBUTE_UNUSED)
1016 : {
1017 10354693 : *walk_subtrees = 0;
1018 10354693 : return 0;
1019 : }
1020 :
1021 : /* Dummy function for code callback, for use when we really
1022 : don't want to do anything. */
1023 : int
1024 1216559 : gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED,
1025 : int *walk_subtrees ATTRIBUTE_UNUSED,
1026 : void *data ATTRIBUTE_UNUSED)
1027 : {
1028 1216559 : return 0;
1029 : }
1030 :
1031 : /* Code callback function for converting
1032 : do while(a)
1033 : end do
1034 : into the equivalent
1035 : do
1036 : if (.not. a) exit
1037 : end do
1038 : This is because common function elimination would otherwise place the
1039 : temporary variables outside the loop. */
1040 :
1041 : static int
1042 1050957 : convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1043 : void *data ATTRIBUTE_UNUSED)
1044 : {
1045 1050957 : gfc_code *co = *c;
1046 1050957 : gfc_code *c_if1, *c_if2, *c_exit;
1047 1050957 : gfc_code *loopblock;
1048 1050957 : gfc_expr *e_not, *e_cond;
1049 :
1050 1050957 : if (co->op != EXEC_DO_WHILE)
1051 : return 0;
1052 :
1053 466 : if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
1054 : return 0;
1055 :
1056 240 : e_cond = co->expr1;
1057 :
1058 : /* Generate the condition of the if statement, which is .not. the original
1059 : statement. */
1060 240 : e_not = gfc_get_expr ();
1061 240 : e_not->ts = e_cond->ts;
1062 240 : e_not->where = e_cond->where;
1063 240 : e_not->expr_type = EXPR_OP;
1064 240 : e_not->value.op.op = INTRINSIC_NOT;
1065 240 : e_not->value.op.op1 = e_cond;
1066 :
1067 : /* Generate the EXIT statement. */
1068 240 : c_exit = XCNEW (gfc_code);
1069 240 : c_exit->op = EXEC_EXIT;
1070 240 : c_exit->ext.which_construct = co;
1071 240 : c_exit->loc = co->loc;
1072 :
1073 : /* Generate the IF statement. */
1074 240 : c_if2 = XCNEW (gfc_code);
1075 240 : c_if2->op = EXEC_IF;
1076 240 : c_if2->expr1 = e_not;
1077 240 : c_if2->next = c_exit;
1078 240 : c_if2->loc = co->loc;
1079 :
1080 : /* ... plus the one to chain it to. */
1081 240 : c_if1 = XCNEW (gfc_code);
1082 240 : c_if1->op = EXEC_IF;
1083 240 : c_if1->block = c_if2;
1084 240 : c_if1->loc = co->loc;
1085 :
1086 : /* Make the DO WHILE loop into a DO block by replacing the condition
1087 : with a true constant. */
1088 240 : co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
1089 :
1090 : /* Hang the generated if statement into the loop body. */
1091 :
1092 240 : loopblock = co->block->next;
1093 240 : co->block->next = c_if1;
1094 240 : c_if1->next = loopblock;
1095 :
1096 240 : return 0;
1097 : }
1098 :
1099 : /* Code callback function for converting
1100 : if (a) then
1101 : ...
1102 : else if (b) then
1103 : end if
1104 :
1105 : into
1106 : if (a) then
1107 : else
1108 : if (b) then
1109 : end if
1110 : end if
1111 :
1112 : because otherwise common function elimination would place the BLOCKs
1113 : into the wrong place. */
1114 :
1115 : static int
1116 1052699 : convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1117 : void *data ATTRIBUTE_UNUSED)
1118 : {
1119 1052699 : gfc_code *co = *c;
1120 1052699 : gfc_code *c_if1, *c_if2, *else_stmt;
1121 :
1122 1052699 : if (co->op != EXEC_IF)
1123 : return 0;
1124 :
1125 : /* This loop starts out with the first ELSE statement. */
1126 215595 : else_stmt = co->block->block;
1127 :
1128 217337 : while (else_stmt != NULL)
1129 : {
1130 7504 : gfc_code *next_else;
1131 :
1132 : /* If there is no condition, we're done. */
1133 7504 : if (else_stmt->expr1 == NULL)
1134 : break;
1135 :
1136 1742 : next_else = else_stmt->block;
1137 :
1138 : /* Generate the new IF statement. */
1139 1742 : c_if2 = XCNEW (gfc_code);
1140 1742 : c_if2->op = EXEC_IF;
1141 1742 : c_if2->expr1 = else_stmt->expr1;
1142 1742 : c_if2->next = else_stmt->next;
1143 1742 : c_if2->loc = else_stmt->loc;
1144 1742 : c_if2->block = next_else;
1145 :
1146 : /* ... plus the one to chain it to. */
1147 1742 : c_if1 = XCNEW (gfc_code);
1148 1742 : c_if1->op = EXEC_IF;
1149 1742 : c_if1->block = c_if2;
1150 1742 : c_if1->loc = else_stmt->loc;
1151 :
1152 : /* Insert the new IF after the ELSE. */
1153 1742 : else_stmt->expr1 = NULL;
1154 1742 : else_stmt->next = c_if1;
1155 1742 : else_stmt->block = NULL;
1156 :
1157 1742 : else_stmt = next_else;
1158 : }
1159 : /* Don't walk subtrees. */
1160 : return 0;
1161 : }
1162 :
1163 : /* Callback function to var_in_expr - return true if expr1 and
1164 : expr2 are identical variables. */
1165 : static int
1166 78 : var_in_expr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1167 : void *data)
1168 : {
1169 78 : gfc_expr *expr1 = (gfc_expr *) data;
1170 78 : gfc_expr *expr2 = *e;
1171 :
1172 78 : if (expr2->expr_type != EXPR_VARIABLE)
1173 : return 0;
1174 :
1175 43 : return expr1->symtree->n.sym == expr2->symtree->n.sym;
1176 : }
1177 :
1178 : /* Return true if expr1 is found in expr2. */
1179 :
1180 : static bool
1181 57 : var_in_expr (gfc_expr *expr1, gfc_expr *expr2)
1182 : {
1183 57 : gcc_assert (expr1->expr_type == EXPR_VARIABLE);
1184 :
1185 57 : return gfc_expr_walker (&expr2, var_in_expr_callback, (void *) expr1);
1186 : }
1187 :
1188 : struct do_stack
1189 : {
1190 : struct do_stack *prev;
1191 : gfc_iterator *iter;
1192 : gfc_code *code;
1193 : } *stack_top;
1194 :
1195 : /* Recursively traverse the block of a WRITE or READ statement, and maybe
1196 : optimize by replacing do loops with their analog array slices. For
1197 : example:
1198 :
1199 : write (*,*) (a(i), i=1,4)
1200 :
1201 : is replaced with
1202 :
1203 : write (*,*) a(1:4:1) . */
1204 :
1205 : static bool
1206 521 : traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev)
1207 : {
1208 521 : gfc_code *curr;
1209 521 : gfc_expr *new_e, *expr, *start;
1210 521 : gfc_ref *ref;
1211 521 : struct do_stack ds_push;
1212 521 : int i, future_rank = 0;
1213 521 : gfc_iterator *iters[GFC_MAX_DIMENSIONS];
1214 521 : gfc_expr *e;
1215 :
1216 : /* Find the first transfer/do statement. */
1217 521 : for (curr = code; curr; curr = curr->next)
1218 : {
1219 521 : if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
1220 : break;
1221 : }
1222 :
1223 : /* Ensure it is the only transfer/do statement because cases like
1224 :
1225 : write (*,*) (a(i), b(i), i=1,4)
1226 :
1227 : cannot be optimized. */
1228 :
1229 521 : if (!curr || curr->next)
1230 : return false;
1231 :
1232 493 : if (curr->op == EXEC_DO)
1233 : {
1234 76 : if (curr->ext.iterator->var->ref)
1235 : return false;
1236 76 : ds_push.prev = stack_top;
1237 76 : ds_push.iter = curr->ext.iterator;
1238 76 : ds_push.code = curr;
1239 76 : stack_top = &ds_push;
1240 76 : if (traverse_io_block (curr->block->next, has_reached, prev))
1241 : {
1242 48 : if (curr != stack_top->code && !*has_reached)
1243 : {
1244 33 : curr->block->next = NULL;
1245 33 : gfc_free_statements (curr);
1246 : }
1247 : else
1248 15 : *has_reached = true;
1249 : return true;
1250 : }
1251 : return false;
1252 : }
1253 :
1254 417 : gcc_assert (curr->op == EXEC_TRANSFER);
1255 :
1256 417 : e = curr->expr1;
1257 417 : ref = e->ref;
1258 417 : if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0 || ref->next)
1259 : return false;
1260 :
1261 : /* Find the iterators belonging to each variable and check conditions. */
1262 825 : for (i = 0; i < ref->u.ar.dimen; i++)
1263 : {
1264 503 : if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
1265 503 : || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
1266 : return false;
1267 :
1268 503 : start = ref->u.ar.start[i];
1269 503 : gfc_simplify_expr (start, 0);
1270 503 : switch (start->expr_type)
1271 : {
1272 482 : case EXPR_VARIABLE:
1273 :
1274 : /* write (*,*) (a(i), i=a%b,1) not handled yet. */
1275 482 : if (start->ref)
1276 : return false;
1277 :
1278 : /* Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4). */
1279 482 : if (!stack_top || !stack_top->iter
1280 460 : || stack_top->iter->var->symtree != start->symtree)
1281 : {
1282 : /* Check for (a(i,i), i=1,3). */
1283 : int j;
1284 :
1285 157 : for (j=0; j<i; j++)
1286 47 : if (iters[j] && iters[j]->var->symtree == start->symtree)
1287 : return false;
1288 :
1289 110 : iters[i] = NULL;
1290 110 : }
1291 : else
1292 : {
1293 360 : iters[i] = stack_top->iter;
1294 360 : stack_top = stack_top->prev;
1295 360 : future_rank++;
1296 : }
1297 : break;
1298 2 : case EXPR_CONSTANT:
1299 2 : iters[i] = NULL;
1300 2 : break;
1301 19 : case EXPR_OP:
1302 19 : switch (start->value.op.op)
1303 : {
1304 19 : case INTRINSIC_PLUS:
1305 19 : case INTRINSIC_TIMES:
1306 19 : if (start->value.op.op1->expr_type != EXPR_VARIABLE)
1307 0 : std::swap (start->value.op.op1, start->value.op.op2);
1308 19 : gcc_fallthrough ();
1309 19 : case INTRINSIC_MINUS:
1310 19 : if (start->value.op.op1->expr_type!= EXPR_VARIABLE
1311 19 : || start->value.op.op2->expr_type != EXPR_CONSTANT
1312 14 : || start->value.op.op1->ref)
1313 : return false;
1314 14 : if (!stack_top || !stack_top->iter
1315 8 : || stack_top->iter->var->symtree
1316 8 : != start->value.op.op1->symtree)
1317 : return false;
1318 8 : iters[i] = stack_top->iter;
1319 8 : stack_top = stack_top->prev;
1320 8 : break;
1321 : default:
1322 : return false;
1323 : }
1324 8 : future_rank++;
1325 8 : break;
1326 : default:
1327 : return false;
1328 : }
1329 : }
1330 :
1331 : /* Check for cases like ((a(i, j), i=1, j), j=1, 2). */
1332 444 : for (int i = 1; i < ref->u.ar.dimen; i++)
1333 : {
1334 134 : if (iters[i])
1335 : {
1336 103 : gfc_expr *var = iters[i]->var;
1337 209 : for (int j = 0; j < i; j++)
1338 : {
1339 118 : if (iters[j]
1340 118 : && (var_in_expr (var, iters[j]->start)
1341 23 : || var_in_expr (var, iters[j]->end)
1342 11 : || var_in_expr (var, iters[j]->step)))
1343 : return false;
1344 : }
1345 : }
1346 : }
1347 :
1348 : /* Create new expr. */
1349 310 : new_e = gfc_copy_expr (curr->expr1);
1350 310 : new_e->expr_type = EXPR_VARIABLE;
1351 310 : new_e->rank = future_rank;
1352 310 : if (curr->expr1->shape)
1353 0 : new_e->shape = gfc_get_shape (new_e->rank);
1354 :
1355 : /* Assign new starts, ends and strides if necessary. */
1356 732 : for (i = 0; i < ref->u.ar.dimen; i++)
1357 : {
1358 422 : if (!iters[i])
1359 107 : continue;
1360 315 : start = ref->u.ar.start[i];
1361 315 : switch (start->expr_type)
1362 : {
1363 0 : case EXPR_CONSTANT:
1364 0 : gfc_internal_error ("bad expression");
1365 313 : break;
1366 313 : case EXPR_VARIABLE:
1367 313 : new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1368 313 : new_e->ref->u.ar.type = AR_SECTION;
1369 313 : gfc_free_expr (new_e->ref->u.ar.start[i]);
1370 313 : new_e->ref->u.ar.start[i] = gfc_copy_expr (iters[i]->start);
1371 313 : new_e->ref->u.ar.end[i] = gfc_copy_expr (iters[i]->end);
1372 313 : new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1373 313 : break;
1374 2 : case EXPR_OP:
1375 2 : new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1376 2 : new_e->ref->u.ar.type = AR_SECTION;
1377 2 : gfc_free_expr (new_e->ref->u.ar.start[i]);
1378 2 : expr = gfc_copy_expr (start);
1379 2 : expr->value.op.op1 = gfc_copy_expr (iters[i]->start);
1380 2 : new_e->ref->u.ar.start[i] = expr;
1381 2 : gfc_simplify_expr (new_e->ref->u.ar.start[i], 0);
1382 2 : expr = gfc_copy_expr (start);
1383 2 : expr->value.op.op1 = gfc_copy_expr (iters[i]->end);
1384 2 : new_e->ref->u.ar.end[i] = expr;
1385 2 : gfc_simplify_expr (new_e->ref->u.ar.end[i], 0);
1386 2 : switch (start->value.op.op)
1387 : {
1388 1 : case INTRINSIC_MINUS:
1389 1 : case INTRINSIC_PLUS:
1390 1 : new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1391 1 : break;
1392 1 : case INTRINSIC_TIMES:
1393 1 : expr = gfc_copy_expr (start);
1394 1 : expr->value.op.op1 = gfc_copy_expr (iters[i]->step);
1395 1 : new_e->ref->u.ar.stride[i] = expr;
1396 1 : gfc_simplify_expr (new_e->ref->u.ar.stride[i], 0);
1397 1 : break;
1398 0 : default:
1399 0 : gfc_internal_error ("bad op");
1400 : }
1401 : break;
1402 0 : default:
1403 0 : gfc_internal_error ("bad expression");
1404 : }
1405 : }
1406 310 : curr->expr1 = new_e;
1407 :
1408 : /* Insert modified statement. Check whether the statement needs to be
1409 : inserted at the lowest level. */
1410 310 : if (!stack_top->iter)
1411 : {
1412 282 : if (prev)
1413 : {
1414 282 : curr->next = prev->next->next;
1415 282 : prev->next = curr;
1416 : }
1417 : else
1418 : {
1419 0 : curr->next = stack_top->code->block->next->next->next;
1420 0 : stack_top->code->block->next = curr;
1421 : }
1422 : }
1423 : else
1424 28 : stack_top->code->block->next = curr;
1425 : return true;
1426 : }
1427 :
1428 : /* Function for the gfc_code_walker. If code is a READ or WRITE statement, it
1429 : tries to optimize its block. */
1430 :
1431 : static int
1432 982133 : simplify_io_impl_do (gfc_code **code, int *walk_subtrees,
1433 : void *data ATTRIBUTE_UNUSED)
1434 : {
1435 982133 : gfc_code **curr, *prev = NULL;
1436 982133 : struct do_stack write, first;
1437 982133 : bool b = false;
1438 982133 : *walk_subtrees = 1;
1439 982133 : if (!(*code)->block
1440 305951 : || ((*code)->block->op != EXEC_WRITE
1441 305951 : && (*code)->block->op != EXEC_READ))
1442 : return 0;
1443 :
1444 27933 : *walk_subtrees = 0;
1445 27933 : write.prev = NULL;
1446 27933 : write.iter = NULL;
1447 27933 : write.code = *code;
1448 :
1449 123922 : for (curr = &(*code)->block; *curr; curr = &(*curr)->next)
1450 : {
1451 95989 : if ((*curr)->op == EXEC_DO)
1452 : {
1453 445 : first.prev = &write;
1454 445 : first.iter = (*curr)->ext.iterator;
1455 445 : first.code = *curr;
1456 445 : stack_top = &first;
1457 445 : traverse_io_block ((*curr)->block->next, &b, prev);
1458 445 : stack_top = NULL;
1459 : }
1460 95989 : prev = *curr;
1461 : }
1462 : return 0;
1463 : }
1464 :
1465 : /* Optimize a namespace, including all contained namespaces.
1466 : flag_frontend_optimize and flag_frontend_loop_interchange are
1467 : handled separately. */
1468 :
1469 : static void
1470 303632 : optimize_namespace (gfc_namespace *ns)
1471 : {
1472 303632 : gfc_namespace *saved_ns = gfc_current_ns;
1473 303632 : current_ns = ns;
1474 303632 : gfc_current_ns = ns;
1475 303632 : forall_level = 0;
1476 303632 : iterator_level = 0;
1477 303632 : in_assoc_list = false;
1478 303632 : in_omp_workshare = false;
1479 303632 : in_omp_atomic = false;
1480 :
1481 303632 : if (flag_frontend_optimize)
1482 : {
1483 303607 : gfc_code_walker (&ns->code, simplify_io_impl_do, dummy_expr_callback, NULL);
1484 303607 : gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
1485 303607 : gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL);
1486 303607 : gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
1487 303607 : gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
1488 303607 : if (flag_inline_matmul_limit != 0 || flag_external_blas
1489 95 : || flag_external_blas64)
1490 : {
1491 303581 : bool found;
1492 303581 : do
1493 : {
1494 303581 : found = false;
1495 303581 : gfc_code_walker (&ns->code, matmul_to_var_code, matmul_to_var_expr,
1496 : (void *) &found);
1497 : }
1498 : while (found);
1499 :
1500 303512 : gfc_code_walker (&ns->code, matmul_temp_args, dummy_expr_callback,
1501 : NULL);
1502 : }
1503 :
1504 303607 : if (flag_external_blas || flag_external_blas64)
1505 38 : gfc_code_walker (&ns->code, call_external_blas, dummy_expr_callback,
1506 : NULL);
1507 :
1508 303607 : if (flag_inline_matmul_limit != 0)
1509 303511 : gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
1510 : NULL);
1511 : }
1512 :
1513 303632 : if (flag_frontend_loop_interchange)
1514 303572 : gfc_code_walker (&ns->code, index_interchange, dummy_expr_callback,
1515 : NULL);
1516 :
1517 : /* BLOCKs are handled in the expression walker below. */
1518 346288 : for (ns = ns->contained; ns; ns = ns->sibling)
1519 : {
1520 42656 : if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1521 41778 : optimize_namespace (ns);
1522 : }
1523 303632 : gfc_current_ns = saved_ns;
1524 303632 : }
1525 :
1526 : /* Handle dependencies for allocatable strings which potentially redefine
1527 : themselves in an assignment. */
1528 :
1529 : static void
1530 359347 : realloc_strings (gfc_namespace *ns)
1531 : {
1532 359347 : current_ns = ns;
1533 359347 : gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL);
1534 :
1535 409578 : for (ns = ns->contained; ns; ns = ns->sibling)
1536 : {
1537 50231 : if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1538 49133 : realloc_strings (ns);
1539 : }
1540 :
1541 359347 : }
1542 :
1543 : static void
1544 303549 : optimize_reduction (gfc_namespace *ns)
1545 : {
1546 303549 : current_ns = ns;
1547 303549 : gfc_code_walker (&ns->code, gfc_dummy_code_callback,
1548 : callback_reduction, NULL);
1549 :
1550 : /* BLOCKs are handled in the expression walker below. */
1551 346196 : for (ns = ns->contained; ns; ns = ns->sibling)
1552 : {
1553 42647 : if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1554 41711 : optimize_reduction (ns);
1555 : }
1556 303549 : }
1557 :
1558 : /* Replace code like
1559 : a = matmul(b,c) + d
1560 : with
1561 : a = matmul(b,c) ; a = a + d
1562 : where the array function is not elemental and not allocatable
1563 : and does not depend on the left-hand side.
1564 : */
1565 :
1566 : static bool
1567 50286 : optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
1568 : {
1569 53726 : gfc_expr *e;
1570 :
1571 53726 : if (!*rhs)
1572 : return false;
1573 :
1574 53724 : e = *rhs;
1575 53724 : if (e->expr_type == EXPR_OP)
1576 : {
1577 3502 : switch (e->value.op.op)
1578 : {
1579 : /* Unary operators and exponentiation: Only look at a single
1580 : operand. */
1581 321 : case INTRINSIC_NOT:
1582 321 : case INTRINSIC_UPLUS:
1583 321 : case INTRINSIC_UMINUS:
1584 321 : case INTRINSIC_PARENTHESES:
1585 321 : case INTRINSIC_POWER:
1586 321 : if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
1587 : return true;
1588 : break;
1589 :
1590 : case INTRINSIC_CONCAT:
1591 : /* Do not do string concatenations. */
1592 : break;
1593 :
1594 3154 : default:
1595 : /* Binary operators. */
1596 3154 : if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
1597 : return true;
1598 :
1599 3119 : if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
1600 : return true;
1601 :
1602 : break;
1603 : }
1604 : }
1605 5984 : else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
1606 179 : && ! (e->value.function.esym
1607 45 : && (e->value.function.esym->attr.elemental
1608 25 : || e->value.function.esym->attr.allocatable
1609 25 : || e->value.function.esym->ts.type != c->expr1->ts.type
1610 24 : || e->value.function.esym->ts.kind != c->expr1->ts.kind))
1611 158 : && ! (e->value.function.isym
1612 134 : && (e->value.function.isym->elemental
1613 52 : || e->ts.type != c->expr1->ts.type
1614 52 : || e->ts.kind != c->expr1->ts.kind))
1615 50298 : && ! gfc_inline_intrinsic_function_p (e))
1616 : {
1617 :
1618 74 : gfc_code *n;
1619 74 : gfc_expr *new_expr;
1620 :
1621 : /* Insert a new assignment statement after the current one. */
1622 74 : n = XCNEW (gfc_code);
1623 74 : n->op = EXEC_ASSIGN;
1624 74 : n->loc = c->loc;
1625 74 : n->next = c->next;
1626 74 : c->next = n;
1627 :
1628 74 : n->expr1 = gfc_copy_expr (c->expr1);
1629 74 : n->expr2 = c->expr2;
1630 74 : new_expr = gfc_copy_expr (c->expr1);
1631 74 : c->expr2 = e;
1632 74 : *rhs = new_expr;
1633 :
1634 74 : return true;
1635 :
1636 : }
1637 :
1638 : /* Nothing to optimize. */
1639 : return false;
1640 : }
1641 :
1642 : /* Remove unneeded TRIMs at the end of expressions. */
1643 :
1644 : static bool
1645 448973 : remove_trim (gfc_expr *rhs)
1646 : {
1647 448973 : bool ret;
1648 :
1649 448973 : ret = false;
1650 448973 : if (!rhs)
1651 : return ret;
1652 :
1653 : /* Check for a // b // trim(c). Looping is probably not
1654 : necessary because the parser usually generates
1655 : (// (// a b ) trim(c) ) , but better safe than sorry. */
1656 :
1657 449402 : while (rhs->expr_type == EXPR_OP
1658 449402 : && rhs->value.op.op == INTRINSIC_CONCAT)
1659 429 : rhs = rhs->value.op.op2;
1660 :
1661 69353 : while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym
1662 506263 : && rhs->value.function.isym->id == GFC_ISYM_TRIM)
1663 : {
1664 1175 : strip_function_call (rhs);
1665 : /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1666 1175 : remove_trim (rhs);
1667 1175 : ret = true;
1668 : }
1669 :
1670 : return ret;
1671 : }
1672 :
1673 : /* Optimizations for an assignment. */
1674 :
1675 : static void
1676 273567 : optimize_assignment (gfc_code * c)
1677 : {
1678 273567 : gfc_expr *lhs, *rhs;
1679 :
1680 273567 : lhs = c->expr1;
1681 273567 : rhs = c->expr2;
1682 :
1683 273567 : if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred)
1684 : {
1685 : /* Optimize a = trim(b) to a = b. */
1686 23018 : remove_trim (rhs);
1687 :
1688 : /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1689 23018 : if (is_empty_string (rhs))
1690 1672 : rhs->value.character.length = 0;
1691 : }
1692 :
1693 273567 : if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
1694 47132 : optimize_binop_array_assignment (c, &rhs, false);
1695 273567 : }
1696 :
1697 :
1698 : /* Remove an unneeded function call, modifying the expression.
1699 : This replaces the function call with the value of its
1700 : first argument. The rest of the argument list is freed. */
1701 :
1702 : static void
1703 1541 : strip_function_call (gfc_expr *e)
1704 : {
1705 1541 : gfc_expr *e1;
1706 1541 : gfc_actual_arglist *a;
1707 :
1708 1541 : a = e->value.function.actual;
1709 :
1710 : /* We should have at least one argument. */
1711 1541 : gcc_assert (a->expr != NULL);
1712 :
1713 1541 : e1 = a->expr;
1714 :
1715 : /* Free the remaining arglist, if any. */
1716 1541 : if (a->next)
1717 0 : gfc_free_actual_arglist (a->next);
1718 :
1719 : /* Graft the argument expression onto the original function. */
1720 1541 : *e = *e1;
1721 1541 : free (e1);
1722 :
1723 1541 : }
1724 :
1725 : /* Optimization of lexical comparison functions. */
1726 :
1727 : static bool
1728 3230762 : optimize_lexical_comparison (gfc_expr *e)
1729 : {
1730 3230762 : if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL)
1731 : return false;
1732 :
1733 210123 : switch (e->value.function.isym->id)
1734 : {
1735 17 : case GFC_ISYM_LLE:
1736 17 : return optimize_comparison (e, INTRINSIC_LE);
1737 :
1738 17 : case GFC_ISYM_LGE:
1739 17 : return optimize_comparison (e, INTRINSIC_GE);
1740 :
1741 32 : case GFC_ISYM_LGT:
1742 32 : return optimize_comparison (e, INTRINSIC_GT);
1743 :
1744 25 : case GFC_ISYM_LLT:
1745 25 : return optimize_comparison (e, INTRINSIC_LT);
1746 :
1747 : default:
1748 : break;
1749 : }
1750 : return false;
1751 : }
1752 :
1753 : /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1754 : do CHARACTER because of possible pessimization involving character
1755 : lengths. */
1756 :
1757 : static bool
1758 314520 : combine_array_constructor (gfc_expr *e)
1759 : {
1760 :
1761 314520 : gfc_expr *op1, *op2;
1762 314520 : gfc_expr *scalar;
1763 314520 : gfc_expr *new_expr;
1764 314520 : gfc_constructor *c, *new_c;
1765 314520 : gfc_constructor_base oldbase, newbase;
1766 314520 : bool scalar_first;
1767 314520 : int n_elem;
1768 314520 : bool all_const;
1769 :
1770 : /* Array constructors have rank one. */
1771 314520 : if (e->rank != 1)
1772 : return false;
1773 :
1774 : /* Don't try to combine association lists, this makes no sense
1775 : and leads to an ICE. */
1776 35154 : if (in_assoc_list)
1777 : return false;
1778 :
1779 : /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1780 35144 : if (forall_level > 0)
1781 : return false;
1782 :
1783 : /* Inside an iterator, things can get hairy; we are likely to create
1784 : an invalid temporary variable. */
1785 35057 : if (iterator_level > 0)
1786 : return false;
1787 :
1788 : /* WHERE also doesn't work. */
1789 35019 : if (in_where > 0)
1790 : return false;
1791 :
1792 34512 : op1 = e->value.op.op1;
1793 34512 : op2 = e->value.op.op2;
1794 :
1795 34512 : if (!op1 || !op2)
1796 : return false;
1797 :
1798 34511 : if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
1799 : scalar_first = false;
1800 34424 : else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
1801 : {
1802 : scalar_first = true;
1803 : op1 = e->value.op.op2;
1804 : op2 = e->value.op.op1;
1805 : }
1806 : else
1807 : return false;
1808 :
1809 152 : if (op2->ts.type == BT_CHARACTER)
1810 : return false;
1811 :
1812 : /* This might be an expanded constructor with very many constant values. If
1813 : we perform the operation here, we might end up with a long compile time
1814 : and actually longer execution time, so a length bound is in order here.
1815 : If the constructor contains something which is not a constant, it did
1816 : not come from an expansion, so leave it alone. */
1817 :
1818 : #define CONSTR_LEN_MAX 4
1819 :
1820 104 : oldbase = op1->value.constructor;
1821 :
1822 104 : n_elem = 0;
1823 104 : all_const = true;
1824 1366 : for (c = gfc_constructor_first (oldbase); c; c = gfc_constructor_next(c))
1825 : {
1826 1292 : if (c->expr->expr_type != EXPR_CONSTANT)
1827 : {
1828 : all_const = false;
1829 : break;
1830 : }
1831 1262 : n_elem += 1;
1832 : }
1833 :
1834 104 : if (all_const && n_elem > CONSTR_LEN_MAX)
1835 : return false;
1836 :
1837 : #undef CONSTR_LEN_MAX
1838 :
1839 88 : newbase = NULL;
1840 88 : e->expr_type = EXPR_ARRAY;
1841 :
1842 88 : scalar = create_var (gfc_copy_expr (op2), "constr");
1843 :
1844 378 : for (c = gfc_constructor_first (oldbase); c;
1845 290 : c = gfc_constructor_next (c))
1846 : {
1847 290 : new_expr = gfc_get_expr ();
1848 290 : new_expr->ts = e->ts;
1849 290 : new_expr->expr_type = EXPR_OP;
1850 290 : new_expr->rank = c->expr->rank;
1851 290 : new_expr->corank = c->expr->corank;
1852 290 : new_expr->where = c->expr->where;
1853 290 : new_expr->value.op.op = e->value.op.op;
1854 :
1855 290 : if (scalar_first)
1856 : {
1857 113 : new_expr->value.op.op1 = gfc_copy_expr (scalar);
1858 113 : new_expr->value.op.op2 = gfc_copy_expr (c->expr);
1859 : }
1860 : else
1861 : {
1862 177 : new_expr->value.op.op1 = gfc_copy_expr (c->expr);
1863 177 : new_expr->value.op.op2 = gfc_copy_expr (scalar);
1864 : }
1865 :
1866 290 : new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
1867 290 : new_c->iterator = c->iterator;
1868 290 : c->iterator = NULL;
1869 : }
1870 :
1871 88 : gfc_free_expr (op1);
1872 88 : gfc_free_expr (op2);
1873 88 : gfc_free_expr (scalar);
1874 :
1875 88 : e->value.constructor = newbase;
1876 88 : return true;
1877 : }
1878 :
1879 : /* Recursive optimization of operators. */
1880 :
1881 : static bool
1882 451027 : optimize_op (gfc_expr *e)
1883 : {
1884 451027 : bool changed;
1885 :
1886 451027 : gfc_intrinsic_op op = e->value.op.op;
1887 :
1888 451027 : changed = false;
1889 :
1890 : /* Only use new-style comparisons. */
1891 451027 : switch(op)
1892 : {
1893 : case INTRINSIC_EQ_OS:
1894 : op = INTRINSIC_EQ;
1895 : break;
1896 :
1897 : case INTRINSIC_GE_OS:
1898 : op = INTRINSIC_GE;
1899 : break;
1900 :
1901 : case INTRINSIC_LE_OS:
1902 : op = INTRINSIC_LE;
1903 : break;
1904 :
1905 : case INTRINSIC_NE_OS:
1906 : op = INTRINSIC_NE;
1907 : break;
1908 :
1909 : case INTRINSIC_GT_OS:
1910 : op = INTRINSIC_GT;
1911 : break;
1912 :
1913 : case INTRINSIC_LT_OS:
1914 : op = INTRINSIC_LT;
1915 : break;
1916 :
1917 : default:
1918 : break;
1919 : }
1920 :
1921 386683 : switch (op)
1922 : {
1923 212297 : case INTRINSIC_EQ:
1924 212297 : case INTRINSIC_GE:
1925 212297 : case INTRINSIC_LE:
1926 212297 : case INTRINSIC_NE:
1927 212297 : case INTRINSIC_GT:
1928 212297 : case INTRINSIC_LT:
1929 212297 : changed = optimize_comparison (e, op);
1930 :
1931 314520 : gcc_fallthrough ();
1932 : /* Look at array constructors. */
1933 314520 : case INTRINSIC_PLUS:
1934 314520 : case INTRINSIC_MINUS:
1935 314520 : case INTRINSIC_TIMES:
1936 314520 : case INTRINSIC_DIVIDE:
1937 314520 : return combine_array_constructor (e) || changed;
1938 :
1939 : default:
1940 : break;
1941 : }
1942 :
1943 : return false;
1944 : }
1945 :
1946 :
1947 : /* Return true if a constant string contains only blanks. */
1948 :
1949 : static bool
1950 74618 : is_empty_string (gfc_expr *e)
1951 : {
1952 74618 : int i;
1953 :
1954 74618 : if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1955 : return false;
1956 :
1957 46850 : for (i=0; i < e->value.character.length; i++)
1958 : {
1959 44422 : if (e->value.character.string[i] != ' ')
1960 : return false;
1961 : }
1962 :
1963 : return true;
1964 : }
1965 :
1966 :
1967 : /* Insert a call to the intrinsic len_trim. Use a different name for
1968 : the symbol tree so we don't run into trouble when the user has
1969 : renamed len_trim for some reason. */
1970 :
1971 : static gfc_expr*
1972 1122 : get_len_trim_call (gfc_expr *str, int kind)
1973 : {
1974 1122 : gfc_expr *fcn;
1975 1122 : gfc_actual_arglist *actual_arglist, *next;
1976 :
1977 1122 : fcn = gfc_get_expr ();
1978 1122 : fcn->expr_type = EXPR_FUNCTION;
1979 1122 : fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM);
1980 1122 : actual_arglist = gfc_get_actual_arglist ();
1981 1122 : actual_arglist->expr = str;
1982 1122 : next = gfc_get_actual_arglist ();
1983 1122 : next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind);
1984 1122 : actual_arglist->next = next;
1985 :
1986 1122 : fcn->value.function.actual = actual_arglist;
1987 1122 : fcn->where = str->where;
1988 1122 : fcn->ts.type = BT_INTEGER;
1989 1122 : fcn->ts.kind = gfc_charlen_int_kind;
1990 :
1991 1122 : gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false);
1992 1122 : fcn->symtree->n.sym->ts = fcn->ts;
1993 1122 : fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
1994 1122 : fcn->symtree->n.sym->attr.function = 1;
1995 1122 : fcn->symtree->n.sym->attr.elemental = 1;
1996 1122 : fcn->symtree->n.sym->attr.referenced = 1;
1997 1122 : fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
1998 1122 : gfc_commit_symbol (fcn->symtree->n.sym);
1999 :
2000 1122 : return fcn;
2001 : }
2002 :
2003 :
2004 : /* Optimize expressions for equality. */
2005 :
2006 : static bool
2007 212390 : optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
2008 : {
2009 212390 : gfc_expr *op1, *op2;
2010 212390 : bool change;
2011 212390 : int eq;
2012 212390 : bool result;
2013 212390 : gfc_actual_arglist *firstarg, *secondarg;
2014 :
2015 212390 : if (e->expr_type == EXPR_OP)
2016 : {
2017 212299 : firstarg = NULL;
2018 212299 : secondarg = NULL;
2019 212299 : op1 = e->value.op.op1;
2020 212299 : op2 = e->value.op.op2;
2021 : }
2022 91 : else if (e->expr_type == EXPR_FUNCTION)
2023 : {
2024 : /* One of the lexical comparison functions. */
2025 91 : firstarg = e->value.function.actual;
2026 91 : secondarg = firstarg->next;
2027 91 : op1 = firstarg->expr;
2028 91 : op2 = secondarg->expr;
2029 : }
2030 : else
2031 0 : gcc_unreachable ();
2032 :
2033 : /* Strip off unneeded TRIM calls from string comparisons. */
2034 :
2035 212390 : change = remove_trim (op1);
2036 :
2037 212390 : if (remove_trim (op2))
2038 100 : change = true;
2039 :
2040 : /* An expression of type EXPR_CONSTANT is only valid for scalars. */
2041 : /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
2042 : handles them well). However, there are also cases that need a non-scalar
2043 : argument. For example the any intrinsic. See PR 45380. */
2044 212390 : if (e->rank > 0)
2045 : return change;
2046 :
2047 : /* Replace a == '' with len_trim(a) == 0 and a /= '' with
2048 : len_trim(a) != 0 */
2049 176358 : if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
2050 26247 : && (op == INTRINSIC_EQ || op == INTRINSIC_NE))
2051 : {
2052 25800 : bool empty_op1, empty_op2;
2053 25800 : empty_op1 = is_empty_string (op1);
2054 25800 : empty_op2 = is_empty_string (op2);
2055 :
2056 25800 : if (empty_op1 || empty_op2)
2057 : {
2058 756 : gfc_expr *fcn;
2059 756 : gfc_expr *zero;
2060 756 : gfc_expr *str;
2061 :
2062 : /* This can only happen when an error for comparing
2063 : characters of different kinds has already been issued. */
2064 756 : if (empty_op1 && empty_op2)
2065 : return false;
2066 :
2067 756 : zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0);
2068 756 : str = empty_op1 ? op2 : op1;
2069 :
2070 756 : fcn = get_len_trim_call (str, gfc_charlen_int_kind);
2071 :
2072 :
2073 756 : if (empty_op1)
2074 0 : gfc_free_expr (op1);
2075 : else
2076 756 : gfc_free_expr (op2);
2077 :
2078 756 : op1 = fcn;
2079 756 : op2 = zero;
2080 756 : e->value.op.op1 = fcn;
2081 756 : e->value.op.op2 = zero;
2082 : }
2083 : }
2084 :
2085 :
2086 : /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
2087 :
2088 176358 : if (flag_finite_math_only
2089 176174 : || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL
2090 158447 : && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
2091 : {
2092 157544 : eq = gfc_dep_compare_expr (op1, op2);
2093 157544 : if (eq <= -2)
2094 : {
2095 : /* Replace A // B < A // C with B < C, and A // B < C // B
2096 : with A < C. */
2097 157458 : if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
2098 25450 : && op1->expr_type == EXPR_OP
2099 47 : && op1->value.op.op == INTRINSIC_CONCAT
2100 47 : && op2->expr_type == EXPR_OP
2101 4 : && op2->value.op.op == INTRINSIC_CONCAT)
2102 : {
2103 4 : gfc_expr *op1_left = op1->value.op.op1;
2104 4 : gfc_expr *op2_left = op2->value.op.op1;
2105 4 : gfc_expr *op1_right = op1->value.op.op2;
2106 4 : gfc_expr *op2_right = op2->value.op.op2;
2107 :
2108 4 : if (gfc_dep_compare_expr (op1_left, op2_left) == 0)
2109 : {
2110 : /* Watch out for 'A ' // x vs. 'A' // x. */
2111 :
2112 3 : if (op1_left->expr_type == EXPR_CONSTANT
2113 3 : && op2_left->expr_type == EXPR_CONSTANT
2114 3 : && op1_left->value.character.length
2115 3 : != op2_left->value.character.length)
2116 : return change;
2117 : else
2118 : {
2119 1 : free (op1_left);
2120 1 : free (op2_left);
2121 1 : if (firstarg)
2122 : {
2123 0 : firstarg->expr = op1_right;
2124 0 : secondarg->expr = op2_right;
2125 : }
2126 : else
2127 : {
2128 1 : e->value.op.op1 = op1_right;
2129 1 : e->value.op.op2 = op2_right;
2130 : }
2131 1 : optimize_comparison (e, op);
2132 1 : return true;
2133 : }
2134 : }
2135 1 : if (gfc_dep_compare_expr (op1_right, op2_right) == 0)
2136 : {
2137 1 : free (op1_right);
2138 1 : free (op2_right);
2139 1 : if (firstarg)
2140 : {
2141 0 : firstarg->expr = op1_left;
2142 0 : secondarg->expr = op2_left;
2143 : }
2144 : else
2145 : {
2146 1 : e->value.op.op1 = op1_left;
2147 1 : e->value.op.op2 = op2_left;
2148 : }
2149 :
2150 1 : optimize_comparison (e, op);
2151 1 : return true;
2152 : }
2153 : }
2154 : }
2155 : else
2156 : {
2157 : /* eq can only be -1, 0 or 1 at this point. */
2158 86 : switch (op)
2159 : {
2160 10 : case INTRINSIC_EQ:
2161 10 : result = eq == 0;
2162 10 : break;
2163 :
2164 5 : case INTRINSIC_GE:
2165 5 : result = eq >= 0;
2166 5 : break;
2167 :
2168 5 : case INTRINSIC_LE:
2169 5 : result = eq <= 0;
2170 5 : break;
2171 :
2172 54 : case INTRINSIC_NE:
2173 54 : result = eq != 0;
2174 54 : break;
2175 :
2176 7 : case INTRINSIC_GT:
2177 7 : result = eq > 0;
2178 7 : break;
2179 :
2180 5 : case INTRINSIC_LT:
2181 5 : result = eq < 0;
2182 5 : break;
2183 :
2184 0 : default:
2185 0 : gfc_internal_error ("illegal OP in optimize_comparison");
2186 86 : break;
2187 : }
2188 :
2189 : /* Replace the expression by a constant expression. The typespec
2190 : and where remains the way it is. */
2191 86 : free (op1);
2192 86 : free (op2);
2193 86 : e->expr_type = EXPR_CONSTANT;
2194 86 : e->value.logical = result;
2195 86 : return true;
2196 : }
2197 : }
2198 :
2199 : return change;
2200 : }
2201 :
2202 : /* Optimize a trim function by replacing it with an equivalent substring
2203 : involving a call to len_trim. This only works for expressions where
2204 : variables are trimmed. Return true if anything was modified. */
2205 :
2206 : static bool
2207 3230762 : optimize_trim (gfc_expr *e)
2208 : {
2209 3230762 : gfc_expr *a;
2210 3230762 : gfc_ref *ref;
2211 3230762 : gfc_expr *fcn;
2212 3230762 : gfc_ref **rr = NULL;
2213 :
2214 : /* Don't do this optimization within an argument list, because
2215 : otherwise aliasing issues may occur. */
2216 :
2217 3230762 : if (count_arglist != 1)
2218 : return false;
2219 :
2220 438951 : if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION
2221 7721 : || e->value.function.isym == NULL
2222 5292 : || e->value.function.isym->id != GFC_ISYM_TRIM)
2223 : return false;
2224 :
2225 496 : a = e->value.function.actual->expr;
2226 :
2227 496 : if (a->expr_type != EXPR_VARIABLE)
2228 : return false;
2229 :
2230 : /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
2231 :
2232 485 : if (a->symtree->n.sym->attr.allocatable)
2233 : return false;
2234 :
2235 : /* Follow all references to find the correct place to put the newly
2236 : created reference. FIXME: Also handle substring references and
2237 : array references. Array references cause strange regressions at
2238 : the moment. */
2239 :
2240 463 : if (a->ref)
2241 : {
2242 143 : for (rr = &(a->ref); *rr; rr = &((*rr)->next))
2243 : {
2244 120 : if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY)
2245 : return false;
2246 : }
2247 : }
2248 :
2249 366 : strip_function_call (e);
2250 :
2251 366 : if (e->ref == NULL)
2252 343 : rr = &(e->ref);
2253 :
2254 : /* Create the reference. */
2255 :
2256 366 : ref = gfc_get_ref ();
2257 366 : ref->type = REF_SUBSTRING;
2258 :
2259 : /* Set the start of the reference. */
2260 :
2261 366 : ref->u.ss.start = gfc_get_int_expr (gfc_charlen_int_kind, NULL, 1);
2262 :
2263 : /* Build the function call to len_trim(x, gfc_default_integer_kind). */
2264 :
2265 366 : fcn = get_len_trim_call (gfc_copy_expr (e), gfc_charlen_int_kind);
2266 :
2267 : /* Set the end of the reference to the call to len_trim. */
2268 :
2269 366 : ref->u.ss.end = fcn;
2270 366 : gcc_assert (rr != NULL && *rr == NULL);
2271 366 : *rr = ref;
2272 366 : return true;
2273 : }
2274 :
2275 : /* Data package to hand down for DO loop checks in a contained
2276 : procedure. */
2277 : typedef struct contained_info
2278 : {
2279 : gfc_symbol *do_var;
2280 : gfc_symbol *procedure;
2281 : locus where_do;
2282 : } contained_info;
2283 :
2284 : static enum gfc_exec_op last_io_op;
2285 :
2286 : /* Callback function to check for INTENT(OUT) and INTENT(INOUT) in a
2287 : contained function call. */
2288 :
2289 : static int
2290 5956 : doloop_contained_function_call (gfc_expr **e,
2291 : int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
2292 : {
2293 5956 : gfc_expr *expr = *e;
2294 5956 : gfc_formal_arglist *f;
2295 5956 : gfc_actual_arglist *a;
2296 5956 : gfc_symbol *sym, *do_var;
2297 5956 : contained_info *info;
2298 :
2299 5956 : if (expr->expr_type != EXPR_FUNCTION || expr->value.function.isym
2300 16 : || expr->value.function.esym == NULL)
2301 : return 0;
2302 :
2303 15 : sym = expr->value.function.esym;
2304 15 : f = gfc_sym_get_dummy_args (sym);
2305 15 : if (f == NULL)
2306 : return 0;
2307 :
2308 14 : info = (contained_info *) data;
2309 14 : do_var = info->do_var;
2310 14 : a = expr->value.function.actual;
2311 :
2312 41 : while (a && f)
2313 : {
2314 29 : if (a->expr && a->expr->symtree && a->expr->symtree->n.sym == do_var)
2315 : {
2316 3 : if (f->sym->attr.intent == INTENT_OUT)
2317 : {
2318 1 : gfc_error_now ("Index variable %qs set to undefined as "
2319 : "INTENT(OUT) argument at %L in procedure %qs "
2320 : "called from within DO loop at %L", do_var->name,
2321 1 : &a->expr->where, info->procedure->name,
2322 : &info->where_do);
2323 1 : return 1;
2324 : }
2325 2 : else if (f->sym->attr.intent == INTENT_INOUT)
2326 : {
2327 1 : gfc_error_now ("Index variable %qs not definable as "
2328 : "INTENT(INOUT) argument at %L in procedure %qs "
2329 : "called from within DO loop at %L", do_var->name,
2330 1 : &a->expr->where, info->procedure->name,
2331 : &info->where_do);
2332 1 : return 1;
2333 : }
2334 : }
2335 27 : a = a->next;
2336 27 : f = f->next;
2337 : }
2338 : return 0;
2339 : }
2340 :
2341 : /* Callback function that goes through the code in a contained
2342 : procedure to make sure it does not change a variable in a DO
2343 : loop. */
2344 :
2345 : static int
2346 2723 : doloop_contained_procedure_code (gfc_code **c,
2347 : int *walk_subtrees ATTRIBUTE_UNUSED,
2348 : void *data)
2349 : {
2350 2723 : gfc_code *co = *c;
2351 2723 : contained_info *info = (contained_info *) data;
2352 2723 : gfc_symbol *do_var = info->do_var;
2353 2723 : const char *errmsg = _("Index variable %qs redefined at %L in procedure %qs "
2354 : "called from within DO loop at %L");
2355 2723 : static enum gfc_exec_op saved_io_op;
2356 :
2357 2723 : switch (co->op)
2358 : {
2359 658 : case EXEC_ASSIGN:
2360 658 : if (co->expr1->symtree && co->expr1->symtree->n.sym == do_var)
2361 4 : gfc_error_now (errmsg, do_var->name, &co->loc, info->procedure->name,
2362 : &info->where_do);
2363 : break;
2364 :
2365 131 : case EXEC_DO:
2366 131 : if (co->ext.iterator && co->ext.iterator->var
2367 131 : && co->ext.iterator->var->symtree->n.sym == do_var)
2368 1 : gfc_error (errmsg, do_var->name, &co->loc, info->procedure->name,
2369 : &info->where_do);
2370 : break;
2371 :
2372 69 : case EXEC_READ:
2373 69 : case EXEC_WRITE:
2374 69 : case EXEC_INQUIRE:
2375 69 : case EXEC_IOLENGTH:
2376 69 : saved_io_op = last_io_op;
2377 69 : last_io_op = co->op;
2378 69 : break;
2379 :
2380 1 : case EXEC_OPEN:
2381 1 : if (co->ext.open && co->ext.open->iostat
2382 1 : && co->ext.open->iostat->symtree->n.sym == do_var)
2383 1 : gfc_error_now (errmsg, do_var->name, &co->ext.open->iostat->where,
2384 1 : info->procedure->name, &info->where_do);
2385 : break;
2386 :
2387 0 : case EXEC_CLOSE:
2388 0 : if (co->ext.close && co->ext.close->iostat
2389 0 : && co->ext.close->iostat->symtree->n.sym == do_var)
2390 0 : gfc_error_now (errmsg, do_var->name, &co->ext.close->iostat->where,
2391 0 : info->procedure->name, &info->where_do);
2392 : break;
2393 :
2394 127 : case EXEC_TRANSFER:
2395 127 : switch (last_io_op)
2396 : {
2397 :
2398 0 : case EXEC_INQUIRE:
2399 : #define CHECK_INQ(a) do { if (co->ext.inquire && \
2400 : co->ext.inquire->a && \
2401 : co->ext.inquire->a->symtree->n.sym == do_var) \
2402 : gfc_error_now (errmsg, do_var->name, \
2403 : &co->ext.inquire->a->where, \
2404 : info->procedure->name, \
2405 : &info->where_do); \
2406 : } while (0)
2407 :
2408 0 : CHECK_INQ(iostat);
2409 0 : CHECK_INQ(number);
2410 0 : CHECK_INQ(position);
2411 0 : CHECK_INQ(recl);
2412 0 : CHECK_INQ(position);
2413 0 : CHECK_INQ(iolength);
2414 0 : CHECK_INQ(strm_pos);
2415 : break;
2416 : #undef CHECK_INQ
2417 :
2418 0 : case EXEC_READ:
2419 0 : if (co->expr1 && co->expr1->symtree
2420 0 : && co->expr1->symtree->n.sym == do_var)
2421 0 : gfc_error_now (errmsg, do_var->name, &co->expr1->where,
2422 0 : info->procedure->name, &info->where_do);
2423 :
2424 : /* Fallthrough. */
2425 :
2426 124 : case EXEC_WRITE:
2427 124 : if (co->ext.dt && co->ext.dt->iostat && co->ext.dt->iostat->symtree
2428 0 : && co->ext.dt->iostat->symtree->n.sym == do_var)
2429 0 : gfc_error_now (errmsg, do_var->name, &co->ext.dt->iostat->where,
2430 0 : info->procedure->name, &info->where_do);
2431 : break;
2432 :
2433 3 : case EXEC_IOLENGTH:
2434 3 : if (co->expr1 && co->expr1->symtree
2435 2 : && co->expr1->symtree->n.sym == do_var)
2436 1 : gfc_error_now (errmsg, do_var->name, &co->expr1->where,
2437 1 : info->procedure->name, &info->where_do);
2438 : break;
2439 :
2440 0 : default:
2441 0 : gcc_unreachable ();
2442 : }
2443 : break;
2444 :
2445 69 : case EXEC_DT_END:
2446 69 : last_io_op = saved_io_op;
2447 69 : break;
2448 :
2449 92 : case EXEC_CALL:
2450 92 : gfc_formal_arglist *f;
2451 92 : gfc_actual_arglist *a;
2452 :
2453 92 : f = gfc_sym_get_dummy_args (co->resolved_sym);
2454 92 : if (f == NULL)
2455 : break;
2456 65 : a = co->ext.actual;
2457 : /* Slightly different error message here. If there is an error,
2458 : return 1 to avoid an infinite loop. */
2459 188 : while (a && f)
2460 : {
2461 123 : if (a->expr && a->expr->symtree && a->expr->symtree->n.sym == do_var)
2462 : {
2463 2 : if (f->sym->attr.intent == INTENT_OUT)
2464 : {
2465 0 : gfc_error_now ("Index variable %qs set to undefined as "
2466 : "INTENT(OUT) argument at %L in subroutine %qs "
2467 : "called from within DO loop at %L",
2468 : do_var->name, &a->expr->where,
2469 0 : info->procedure->name, &info->where_do);
2470 0 : return 1;
2471 : }
2472 2 : else if (f->sym->attr.intent == INTENT_INOUT)
2473 : {
2474 0 : gfc_error_now ("Index variable %qs not definable as "
2475 : "INTENT(INOUT) argument at %L in subroutine %qs "
2476 : "called from within DO loop at %L", do_var->name,
2477 0 : &a->expr->where, info->procedure->name,
2478 : &info->where_do);
2479 0 : return 1;
2480 : }
2481 : }
2482 123 : a = a->next;
2483 123 : f = f->next;
2484 : }
2485 : break;
2486 : default:
2487 : break;
2488 : }
2489 : return 0;
2490 : }
2491 :
2492 : /* Callback function for code checking that we do not pass a DO variable to an
2493 : INTENT(OUT) or INTENT(INOUT) dummy variable. */
2494 :
2495 : static int
2496 1264395 : doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2497 : void *data ATTRIBUTE_UNUSED)
2498 : {
2499 1264395 : gfc_code *co;
2500 1264395 : int i;
2501 1264395 : gfc_formal_arglist *f;
2502 1264395 : gfc_actual_arglist *a;
2503 1264395 : gfc_code *cl;
2504 1264395 : do_t loop, *lp;
2505 1264395 : bool seen_goto;
2506 :
2507 1264395 : co = *c;
2508 :
2509 : /* If the doloop_list grew, we have to truncate it here. */
2510 :
2511 1264395 : if ((unsigned) doloop_level < doloop_list.length())
2512 32841 : doloop_list.truncate (doloop_level);
2513 :
2514 1264395 : seen_goto = false;
2515 1264395 : switch (co->op)
2516 : {
2517 42576 : case EXEC_DO:
2518 :
2519 42576 : if (co->ext.iterator && co->ext.iterator->var)
2520 42576 : loop.c = co;
2521 : else
2522 0 : loop.c = NULL;
2523 :
2524 42576 : loop.branch_level = if_level + select_level;
2525 42576 : loop.seen_goto = false;
2526 42576 : doloop_list.safe_push (loop);
2527 42576 : break;
2528 :
2529 : /* If anything could transfer control away from a suspicious
2530 : subscript, make sure to set seen_goto in the current DO loop
2531 : (if any). */
2532 : case EXEC_GOTO:
2533 : case EXEC_EXIT:
2534 : case EXEC_STOP:
2535 : case EXEC_ERROR_STOP:
2536 : case EXEC_CYCLE:
2537 : seen_goto = true;
2538 : break;
2539 :
2540 3967 : case EXEC_OPEN:
2541 3967 : if (co->ext.open->err)
2542 : seen_goto = true;
2543 : break;
2544 :
2545 3160 : case EXEC_CLOSE:
2546 3160 : if (co->ext.close->err)
2547 : seen_goto = true;
2548 : break;
2549 :
2550 2875 : case EXEC_BACKSPACE:
2551 2875 : case EXEC_ENDFILE:
2552 2875 : case EXEC_REWIND:
2553 2875 : case EXEC_FLUSH:
2554 :
2555 2875 : if (co->ext.filepos->err)
2556 : seen_goto = true;
2557 : break;
2558 :
2559 838 : case EXEC_INQUIRE:
2560 838 : if (co->ext.inquire->err)
2561 : seen_goto = true;
2562 : break;
2563 :
2564 34674 : case EXEC_READ:
2565 34674 : case EXEC_WRITE:
2566 34674 : if (co->ext.dt->err || co->ext.dt->end || co->ext.dt->eor)
2567 : seen_goto = true;
2568 : break;
2569 :
2570 : case EXEC_WAIT:
2571 : if (co->ext.wait->err || co->ext.wait->end || co->ext.wait->eor)
2572 : loop.seen_goto = true;
2573 : break;
2574 :
2575 89651 : case EXEC_CALL:
2576 89651 : if (co->resolved_sym == NULL)
2577 : break;
2578 :
2579 : /* Test if somebody stealthily changes the DO variable from
2580 : under us by changing it in a host-associated procedure. */
2581 89287 : if (co->resolved_sym->attr.contained)
2582 : {
2583 50619 : FOR_EACH_VEC_ELT (doloop_list, i, lp)
2584 : {
2585 4040 : gfc_symbol *sym = co->resolved_sym;
2586 4040 : contained_info info;
2587 4040 : gfc_namespace *ns;
2588 :
2589 4040 : cl = lp->c;
2590 4040 : info.do_var = cl->ext.iterator->var->symtree->n.sym;
2591 4040 : info.procedure = co->resolved_sym; /* sym? */
2592 4040 : info.where_do = co->loc;
2593 : /* Look contained procedures under the namespace of the
2594 : variable. */
2595 4716 : for (ns = info.do_var->ns->contained; ns; ns = ns->sibling)
2596 676 : if (ns->proc_name && ns->proc_name == sym)
2597 264 : gfc_code_walker (&ns->code, doloop_contained_procedure_code,
2598 : doloop_contained_function_call, &info);
2599 : }
2600 : }
2601 :
2602 89287 : f = gfc_sym_get_dummy_args (co->resolved_sym);
2603 :
2604 : /* Without a formal arglist, there is only unknown INTENT,
2605 : which we don't check for. */
2606 89287 : if (f == NULL)
2607 : break;
2608 :
2609 63403 : a = co->ext.actual;
2610 :
2611 222489 : while (a && f)
2612 : {
2613 177777 : FOR_EACH_VEC_ELT (doloop_list, i, lp)
2614 : {
2615 18691 : gfc_symbol *do_sym;
2616 18691 : cl = lp->c;
2617 :
2618 18691 : if (cl == NULL)
2619 : break;
2620 :
2621 18691 : do_sym = cl->ext.iterator->var->symtree->n.sym;
2622 :
2623 18691 : if (a->expr && a->expr->symtree && f->sym
2624 9479 : && a->expr->symtree->n.sym == do_sym)
2625 : {
2626 1546 : if (f->sym->attr.intent == INTENT_OUT)
2627 2 : gfc_error_now ("Variable %qs at %L set to undefined "
2628 : "value inside loop beginning at %L as "
2629 : "INTENT(OUT) argument to subroutine %qs",
2630 : do_sym->name, &a->expr->where,
2631 1 : &(doloop_list[i].c->loc),
2632 1 : co->symtree->n.sym->name);
2633 1545 : else if (f->sym->attr.intent == INTENT_INOUT)
2634 2 : gfc_error_now ("Variable %qs at %L not definable inside "
2635 : "loop beginning at %L as INTENT(INOUT) "
2636 : "argument to subroutine %qs",
2637 : do_sym->name, &a->expr->where,
2638 1 : &(doloop_list[i].c->loc),
2639 1 : co->symtree->n.sym->name);
2640 : }
2641 : }
2642 159086 : a = a->next;
2643 159086 : f = f->next;
2644 : }
2645 :
2646 : break;
2647 :
2648 : default:
2649 : break;
2650 : }
2651 277568 : if (seen_goto && doloop_level > 0)
2652 10463 : doloop_list[doloop_level-1].seen_goto = true;
2653 :
2654 1264395 : return 0;
2655 : }
2656 :
2657 : /* Callback function to warn about different things within DO loops. */
2658 :
2659 : static int
2660 3858095 : do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2661 : void *data ATTRIBUTE_UNUSED)
2662 : {
2663 3858095 : do_t *last;
2664 :
2665 3858095 : if (doloop_list.length () == 0)
2666 : return 0;
2667 :
2668 718603 : if ((*e)->expr_type == EXPR_FUNCTION)
2669 47233 : do_intent (e);
2670 :
2671 718603 : last = &doloop_list.last();
2672 718603 : if (last->seen_goto && !warn_do_subscript)
2673 : return 0;
2674 :
2675 670753 : if ((*e)->expr_type == EXPR_VARIABLE)
2676 331278 : do_subscript (e);
2677 :
2678 : return 0;
2679 : }
2680 :
2681 : typedef struct
2682 : {
2683 : gfc_symbol *sym;
2684 : mpz_t val;
2685 : } insert_index_t;
2686 :
2687 : /* Callback function - if the expression is the variable in data->sym,
2688 : replace it with a constant from data->val. */
2689 :
2690 : static int
2691 162497 : callback_insert_index (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2692 : void *data)
2693 : {
2694 162497 : insert_index_t *d;
2695 162497 : gfc_expr *ex, *n;
2696 :
2697 162497 : ex = (*e);
2698 162497 : if (ex->expr_type != EXPR_VARIABLE)
2699 : return 0;
2700 :
2701 101020 : d = (insert_index_t *) data;
2702 101020 : if (ex->symtree->n.sym != d->sym)
2703 : return 0;
2704 :
2705 55809 : n = gfc_get_constant_expr (BT_INTEGER, ex->ts.kind, &ex->where);
2706 55809 : mpz_set (n->value.integer, d->val);
2707 :
2708 55809 : gfc_free_expr (ex);
2709 55809 : *e = n;
2710 55809 : return 0;
2711 : }
2712 :
2713 : /* In the expression e, replace occurrences of the variable sym with
2714 : val. If this results in a constant expression, return true and
2715 : return the value in ret. Return false if the expression already
2716 : is a constant. Caller has to clear ret in that case. */
2717 :
2718 : static bool
2719 96991 : insert_index (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret)
2720 : {
2721 96991 : gfc_expr *n;
2722 96991 : insert_index_t data;
2723 96991 : bool rc;
2724 :
2725 96991 : if (e->expr_type == EXPR_CONSTANT)
2726 : return false;
2727 :
2728 93183 : n = gfc_copy_expr (e);
2729 93183 : data.sym = sym;
2730 93183 : mpz_init_set (data.val, val);
2731 93183 : gfc_expr_walker (&n, callback_insert_index, (void *) &data);
2732 :
2733 : /* Suppress errors here - we could get errors here such as an
2734 : out of bounds access for arrays, see PR 90563. */
2735 93183 : gfc_push_suppress_errors ();
2736 93183 : gfc_simplify_expr (n, 0);
2737 93183 : gfc_pop_suppress_errors ();
2738 :
2739 93183 : if (n->expr_type == EXPR_CONSTANT)
2740 : {
2741 51512 : rc = true;
2742 51512 : mpz_init_set (ret, n->value.integer);
2743 : }
2744 : else
2745 : rc = false;
2746 :
2747 93183 : mpz_clear (data.val);
2748 93183 : gfc_free_expr (n);
2749 93183 : return rc;
2750 :
2751 : }
2752 :
2753 : static bool
2754 96813 : evaluate_loop_bound (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret)
2755 : {
2756 96813 : if (e->expr_type == EXPR_CONSTANT)
2757 : {
2758 84766 : mpz_init_set (ret, e->value.integer);
2759 84766 : return true;
2760 : }
2761 :
2762 12047 : return insert_index (e, sym, val, ret);
2763 : }
2764 :
2765 : /* Return true if any loop nested inside LOOP_INDEX is not provably entered
2766 : after substituting OUTER_VAL for OUTER_SYM. In that case the guarded array
2767 : reference may never be evaluated, so do not warn from the outer loop alone. */
2768 :
2769 : static bool
2770 73067 : inner_loop_may_be_skipped (int loop_index, gfc_symbol *outer_sym, mpz_t outer_val)
2771 : {
2772 73067 : int k;
2773 73067 : do_t *lp;
2774 :
2775 93750 : FOR_EACH_VEC_ELT_FROM (doloop_list, k, lp, loop_index + 1)
2776 : {
2777 32387 : gfc_code *loop = lp->c;
2778 32387 : int sgn, cmp;
2779 32387 : mpz_t do_start, do_end, do_step;
2780 :
2781 32387 : if (loop == NULL || loop->ext.iterator == NULL || loop->ext.iterator->var == NULL)
2782 11704 : return true;
2783 :
2784 32387 : if (loop->ext.iterator->var->symtree->n.sym->ts.type != BT_INTEGER)
2785 : return true;
2786 :
2787 32385 : if (!evaluate_loop_bound (loop->ext.iterator->step, outer_sym, outer_val, do_step))
2788 : return true;
2789 :
2790 32353 : sgn = mpz_cmp_ui (do_step, 0);
2791 32130 : if (sgn == 0)
2792 : {
2793 0 : mpz_clear (do_step);
2794 0 : return true;
2795 : }
2796 :
2797 32353 : if (!evaluate_loop_bound (loop->ext.iterator->start, outer_sym, outer_val,
2798 : do_start))
2799 : {
2800 278 : mpz_clear (do_step);
2801 278 : return true;
2802 : }
2803 :
2804 32075 : if (!evaluate_loop_bound (loop->ext.iterator->end, outer_sym, outer_val,
2805 : do_end))
2806 : {
2807 11332 : mpz_clear (do_start);
2808 11332 : mpz_clear (do_step);
2809 11332 : return true;
2810 : }
2811 :
2812 20743 : cmp = mpz_cmp (do_end, do_start);
2813 20743 : mpz_clear (do_start);
2814 20743 : mpz_clear (do_end);
2815 20743 : mpz_clear (do_step);
2816 :
2817 20743 : if ((sgn > 0 && cmp < 0) || (sgn < 0 && cmp > 0))
2818 : return true;
2819 : }
2820 :
2821 : return false;
2822 : }
2823 :
2824 : /* Check array subscripts for possible out-of-bounds accesses in DO
2825 : loops with constant bounds. */
2826 :
2827 : static int
2828 331278 : do_subscript (gfc_expr **e)
2829 : {
2830 331278 : gfc_expr *v;
2831 331278 : gfc_array_ref *ar;
2832 331278 : gfc_ref *ref;
2833 331278 : int i,j;
2834 331278 : gfc_code *dl;
2835 331278 : do_t *lp;
2836 :
2837 331278 : v = *e;
2838 : /* Constants are already checked. */
2839 331278 : if (v->expr_type == EXPR_CONSTANT)
2840 : return 0;
2841 :
2842 : /* Wrong warnings will be generated in an associate list. */
2843 331278 : if (in_assoc_list)
2844 : return 0;
2845 :
2846 : /* We already warned about this. */
2847 331115 : if (v->do_not_warn)
2848 : return 0;
2849 :
2850 304751 : v->do_not_warn = 1;
2851 :
2852 391106 : for (ref = v->ref; ref; ref = ref->next)
2853 : {
2854 88792 : if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT)
2855 : {
2856 : ar = & ref->u.ar;
2857 198140 : FOR_EACH_VEC_ELT (doloop_list, j, lp)
2858 : {
2859 75800 : gfc_symbol *do_sym;
2860 75800 : mpz_t do_start, do_step, do_end;
2861 75800 : bool have_do_start, have_do_end;
2862 75800 : bool error_not_proven;
2863 75800 : int warn;
2864 75800 : int sgn;
2865 :
2866 75800 : dl = lp->c;
2867 75800 : if (dl == NULL)
2868 : break;
2869 :
2870 : /* If we are within a branch, or a goto or equivalent
2871 : was seen in the DO loop before, then we cannot prove that
2872 : this expression is actually evaluated. Don't do anything
2873 : unless we want to see it all. */
2874 75800 : error_not_proven = lp->seen_goto
2875 75800 : || lp->branch_level < if_level + select_level;
2876 :
2877 19436 : if (error_not_proven && !warn_do_subscript)
2878 : break;
2879 :
2880 : if (error_not_proven)
2881 : warn = OPT_Wdo_subscript;
2882 : else
2883 : warn = 0;
2884 :
2885 56370 : do_sym = dl->ext.iterator->var->symtree->n.sym;
2886 56370 : if (do_sym->ts.type != BT_INTEGER)
2887 715 : continue;
2888 :
2889 : /* If we do not know about the stepsize, the loop may be zero trip.
2890 : Do not warn in this case. */
2891 :
2892 56363 : if (dl->ext.iterator->step->expr_type == EXPR_CONSTANT)
2893 : {
2894 55656 : sgn = mpz_cmp_ui (dl->ext.iterator->step->value.integer, 0);
2895 : /* This can happen, but then the error has been
2896 : reported previously. */
2897 55219 : if (sgn == 0)
2898 1 : continue;
2899 :
2900 55655 : mpz_init_set (do_step, dl->ext.iterator->step->value.integer);
2901 : }
2902 :
2903 : else
2904 707 : continue;
2905 :
2906 55655 : if (dl->ext.iterator->start->expr_type == EXPR_CONSTANT)
2907 : {
2908 53111 : have_do_start = true;
2909 53111 : mpz_init_set (do_start, dl->ext.iterator->start->value.integer);
2910 : }
2911 : else
2912 : have_do_start = false;
2913 :
2914 55655 : if (dl->ext.iterator->end->expr_type == EXPR_CONSTANT)
2915 : {
2916 20006 : have_do_end = true;
2917 20006 : mpz_init_set (do_end, dl->ext.iterator->end->value.integer);
2918 : }
2919 : else
2920 : have_do_end = false;
2921 :
2922 55655 : if (!have_do_start && !have_do_end)
2923 : {
2924 2437 : mpz_clear (do_step);
2925 2437 : return 0;
2926 : }
2927 :
2928 : /* No warning inside a zero-trip loop. */
2929 53218 : if (have_do_start && have_do_end)
2930 : {
2931 19899 : int cmp;
2932 :
2933 19899 : cmp = mpz_cmp (do_end, do_start);
2934 19899 : if ((sgn > 0 && cmp < 0) || (sgn < 0 && cmp > 0))
2935 : {
2936 25 : mpz_clear (do_start);
2937 25 : mpz_clear (do_end);
2938 25 : mpz_clear (do_step);
2939 25 : break;
2940 : }
2941 : }
2942 :
2943 : /* May have to correct the end value if the step does not equal
2944 : one. */
2945 53193 : if (have_do_start && have_do_end && mpz_cmp_ui (do_step, 1) != 0)
2946 : {
2947 790 : mpz_t diff, rem;
2948 :
2949 790 : mpz_init (diff);
2950 790 : mpz_init (rem);
2951 790 : mpz_sub (diff, do_end, do_start);
2952 790 : mpz_tdiv_r (rem, diff, do_step);
2953 790 : mpz_sub (do_end, do_end, rem);
2954 790 : mpz_clear (diff);
2955 790 : mpz_clear (rem);
2956 : }
2957 :
2958 53193 : bool skip_start = have_do_start
2959 53193 : && inner_loop_may_be_skipped (j, do_sym, do_start);
2960 53193 : bool skip_end = have_do_end
2961 53193 : && inner_loop_may_be_skipped (j, do_sym, do_end);
2962 :
2963 124818 : for (i = 0; i< ar->dimen; i++)
2964 : {
2965 71625 : mpz_t val;
2966 71625 : if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start && !skip_start
2967 127117 : && insert_index (ar->start[i], do_sym, do_start, val))
2968 : {
2969 36046 : if (ar->as->lower[i]
2970 31780 : && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2971 31716 : && ar->as->lower[i]->ts.type == BT_INTEGER
2972 31716 : && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2973 14 : gfc_warning (warn, "Array reference at %L out of bounds "
2974 : "(%ld < %ld) in loop beginning at %L",
2975 7 : &ar->start[i]->where, mpz_get_si (val),
2976 : mpz_get_si (ar->as->lower[i]->value.integer),
2977 7 : &doloop_list[j].c->loc);
2978 :
2979 36046 : if (ar->as->upper[i]
2980 29561 : && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2981 11302 : && ar->as->upper[i]->ts.type == BT_INTEGER
2982 11301 : && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2983 62 : gfc_warning (warn, "Array reference at %L out of bounds "
2984 : "(%ld > %ld) in loop beginning at %L",
2985 31 : &ar->start[i]->where, mpz_get_si (val),
2986 : mpz_get_si (ar->as->upper[i]->value.integer),
2987 31 : &doloop_list[j].c->loc);
2988 :
2989 36046 : mpz_clear (val);
2990 : }
2991 :
2992 71625 : if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end && !skip_end
2993 101077 : && insert_index (ar->start[i], do_sym, do_end, val))
2994 : {
2995 15061 : if (ar->as->lower[i]
2996 12362 : && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2997 12360 : && ar->as->lower[i]->ts.type == BT_INTEGER
2998 12360 : && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2999 4 : gfc_warning (warn, "Array reference at %L out of bounds "
3000 : "(%ld < %ld) in loop beginning at %L",
3001 2 : &ar->start[i]->where, mpz_get_si (val),
3002 : mpz_get_si (ar->as->lower[i]->value.integer),
3003 2 : &doloop_list[j].c->loc);
3004 :
3005 15061 : if (ar->as->upper[i]
3006 10939 : && ar->as->upper[i]->expr_type == EXPR_CONSTANT
3007 10305 : && ar->as->upper[i]->ts.type == BT_INTEGER
3008 10304 : && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
3009 16 : gfc_warning (warn, "Array reference at %L out of bounds "
3010 : "(%ld > %ld) in loop beginning at %L",
3011 8 : &ar->start[i]->where, mpz_get_si (val),
3012 : mpz_get_si (ar->as->upper[i]->value.integer),
3013 8 : &doloop_list[j].c->loc);
3014 :
3015 15061 : mpz_clear (val);
3016 : }
3017 : }
3018 :
3019 53193 : if (have_do_start)
3020 53086 : mpz_clear (do_start);
3021 53193 : if (have_do_end)
3022 19981 : mpz_clear (do_end);
3023 53193 : mpz_clear (do_step);
3024 : }
3025 : }
3026 : }
3027 : return 0;
3028 : }
3029 : /* Function for functions checking that we do not pass a DO variable
3030 : to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
3031 :
3032 : static int
3033 47233 : do_intent (gfc_expr **e)
3034 : {
3035 47233 : gfc_formal_arglist *f;
3036 47233 : gfc_actual_arglist *a;
3037 47233 : gfc_expr *expr;
3038 47233 : gfc_code *dl;
3039 47233 : do_t *lp;
3040 47233 : int i;
3041 47233 : gfc_symbol *sym;
3042 :
3043 47233 : expr = *e;
3044 47233 : if (expr->expr_type != EXPR_FUNCTION)
3045 : return 0;
3046 :
3047 : /* Intrinsic functions don't modify their arguments. */
3048 :
3049 47233 : if (expr->value.function.isym)
3050 : return 0;
3051 :
3052 3010 : sym = expr->value.function.esym;
3053 3010 : if (sym == NULL)
3054 : return 0;
3055 :
3056 2799 : if (sym->attr.contained)
3057 : {
3058 1106 : FOR_EACH_VEC_ELT (doloop_list, i, lp)
3059 : {
3060 669 : contained_info info;
3061 669 : gfc_namespace *ns;
3062 :
3063 669 : dl = lp->c;
3064 669 : info.do_var = dl->ext.iterator->var->symtree->n.sym;
3065 669 : info.procedure = sym;
3066 669 : info.where_do = expr->where;
3067 : /* Look contained procedures under the namespace of the
3068 : variable. */
3069 1054 : for (ns = info.do_var->ns->contained; ns; ns = ns->sibling)
3070 385 : if (ns->proc_name && ns->proc_name == sym)
3071 212 : gfc_code_walker (&ns->code, doloop_contained_procedure_code,
3072 : dummy_expr_callback, &info);
3073 : }
3074 : }
3075 :
3076 2799 : f = gfc_sym_get_dummy_args (sym);
3077 :
3078 : /* Without a formal arglist, there is only unknown INTENT,
3079 : which we don't check for. */
3080 2799 : if (f == NULL)
3081 : return 0;
3082 :
3083 1526 : a = expr->value.function.actual;
3084 :
3085 4143 : while (a && f)
3086 : {
3087 6560 : FOR_EACH_VEC_ELT (doloop_list, i, lp)
3088 : {
3089 3943 : gfc_symbol *do_sym;
3090 3943 : dl = lp->c;
3091 3943 : if (dl == NULL)
3092 : break;
3093 :
3094 3943 : do_sym = dl->ext.iterator->var->symtree->n.sym;
3095 :
3096 3943 : if (a->expr && a->expr->symtree
3097 2935 : && a->expr->symtree->n.sym == do_sym
3098 497 : && f->sym)
3099 : {
3100 496 : if (f->sym->attr.intent == INTENT_OUT)
3101 2 : gfc_error_now ("Variable %qs at %L set to undefined value "
3102 : "inside loop beginning at %L as INTENT(OUT) "
3103 : "argument to function %qs", do_sym->name,
3104 1 : &a->expr->where, &doloop_list[i].c->loc,
3105 1 : expr->symtree->n.sym->name);
3106 495 : else if (f->sym->attr.intent == INTENT_INOUT)
3107 2 : gfc_error_now ("Variable %qs at %L not definable inside loop"
3108 : " beginning at %L as INTENT(INOUT) argument to"
3109 : " function %qs", do_sym->name,
3110 1 : &a->expr->where, &doloop_list[i].c->loc,
3111 1 : expr->symtree->n.sym->name);
3112 : }
3113 : }
3114 2617 : a = a->next;
3115 2617 : f = f->next;
3116 : }
3117 :
3118 : return 0;
3119 : }
3120 :
3121 : static void
3122 367350 : doloop_warn (gfc_namespace *ns)
3123 : {
3124 367350 : gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
3125 :
3126 419390 : for (ns = ns->contained; ns; ns = ns->sibling)
3127 : {
3128 52040 : if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
3129 50965 : doloop_warn (ns);
3130 : }
3131 367350 : }
3132 :
3133 : /* This section deals with inlining calls to MATMUL. */
3134 :
3135 : /* Replace calls to matmul outside of straight assignments with a temporary
3136 : variable so that later inlining will work. */
3137 :
3138 : static int
3139 3230655 : matmul_to_var_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
3140 : void *data)
3141 : {
3142 3230655 : gfc_expr *e, *n;
3143 3230655 : bool *found = (bool *) data;
3144 :
3145 3230655 : e = *ep;
3146 :
3147 3230655 : if (e->expr_type != EXPR_FUNCTION
3148 254132 : || e->value.function.isym == NULL
3149 210428 : || e->value.function.isym->id != GFC_ISYM_MATMUL)
3150 : return 0;
3151 :
3152 875 : if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
3153 873 : || in_omp_atomic || in_where || in_assoc_list)
3154 : return 0;
3155 :
3156 : /* Check if this is already in the form c = matmul(a,b). */
3157 :
3158 869 : if ((*current_code)->expr2 == e)
3159 : return 0;
3160 :
3161 133 : n = create_var (e, "matmul");
3162 :
3163 : /* If create_var is unable to create a variable (for example if
3164 : -fno-realloc-lhs is in force with a variable that does not have bounds
3165 : known at compile-time), just return. */
3166 :
3167 133 : if (n == NULL)
3168 : return 0;
3169 :
3170 132 : *ep = n;
3171 132 : *found = true;
3172 132 : return 0;
3173 : }
3174 :
3175 : /* Set current_code and associated variables so that matmul_to_var_expr can
3176 : work. */
3177 :
3178 : static int
3179 1054592 : matmul_to_var_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
3180 : void *data ATTRIBUTE_UNUSED)
3181 : {
3182 1054592 : if (current_code != c)
3183 : {
3184 1039894 : current_code = c;
3185 1039894 : inserted_block = NULL;
3186 1039894 : changed_statement = NULL;
3187 : }
3188 :
3189 1054592 : return 0;
3190 : }
3191 :
3192 :
3193 : /* Take a statement of the shape c = matmul(a,b) and create temporaries
3194 : for a and b if there is a dependency between the arguments and the
3195 : result variable or if a or b are the result of calculations that cannot
3196 : be handled by the inliner. */
3197 :
3198 : static int
3199 1052623 : matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
3200 : void *data ATTRIBUTE_UNUSED)
3201 : {
3202 1052623 : gfc_expr *expr1, *expr2;
3203 1052623 : gfc_code *co;
3204 1052623 : gfc_actual_arglist *a, *b;
3205 1052623 : bool a_tmp, b_tmp;
3206 1052623 : gfc_expr *matrix_a, *matrix_b;
3207 1052623 : bool conjg_a, conjg_b, transpose_a, transpose_b;
3208 :
3209 1052623 : co = *c;
3210 :
3211 1052623 : if (co->op != EXEC_ASSIGN)
3212 : return 0;
3213 :
3214 273572 : if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
3215 271177 : || in_omp_atomic || in_where)
3216 : return 0;
3217 :
3218 : /* This has some duplication with inline_matmul_assign. This
3219 : is because the creation of temporary variables could still fail,
3220 : and inline_matmul_assign still needs to be able to handle these
3221 : cases. */
3222 267923 : expr1 = co->expr1;
3223 267923 : expr2 = co->expr2;
3224 :
3225 267923 : if (expr2->expr_type != EXPR_FUNCTION
3226 37878 : || expr2->value.function.isym == NULL
3227 28795 : || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
3228 : return 0;
3229 :
3230 855 : a_tmp = false;
3231 855 : a = expr2->value.function.actual;
3232 855 : matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
3233 855 : if (matrix_a != NULL)
3234 : {
3235 784 : if (matrix_a->expr_type == EXPR_VARIABLE
3236 784 : && (gfc_check_dependency (matrix_a, expr1, true)
3237 755 : || gfc_has_dimen_vector_ref (matrix_a)))
3238 : a_tmp = true;
3239 : }
3240 : else
3241 : a_tmp = true;
3242 :
3243 855 : b_tmp = false;
3244 855 : b = a->next;
3245 855 : matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
3246 855 : if (matrix_b != NULL)
3247 : {
3248 786 : if (matrix_b->expr_type == EXPR_VARIABLE
3249 786 : && (gfc_check_dependency (matrix_b, expr1, true)
3250 778 : || gfc_has_dimen_vector_ref (matrix_b)))
3251 : b_tmp = true;
3252 : }
3253 : else
3254 : b_tmp = true;
3255 :
3256 777 : if (!a_tmp && !b_tmp)
3257 : return 0;
3258 :
3259 156 : current_code = c;
3260 156 : inserted_block = NULL;
3261 156 : changed_statement = NULL;
3262 156 : if (a_tmp)
3263 : {
3264 102 : gfc_expr *at;
3265 102 : at = create_var (a->expr,"mma");
3266 102 : if (at)
3267 102 : a->expr = at;
3268 : }
3269 156 : if (b_tmp)
3270 : {
3271 78 : gfc_expr *bt;
3272 78 : bt = create_var (b->expr,"mmb");
3273 78 : if (bt)
3274 78 : b->expr = bt;
3275 : }
3276 : return 0;
3277 : }
3278 :
3279 : /* Auxiliary function to build and simplify an array inquiry function.
3280 : dim is zero-based. */
3281 :
3282 : static gfc_expr *
3283 7497 : get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim, int okind = 0)
3284 : {
3285 7497 : gfc_expr *fcn;
3286 7497 : gfc_expr *dim_arg, *kind;
3287 7497 : const char *name;
3288 7497 : gfc_expr *ec;
3289 :
3290 7497 : switch (id)
3291 : {
3292 : case GFC_ISYM_LBOUND:
3293 : name = "_gfortran_lbound";
3294 : break;
3295 :
3296 0 : case GFC_ISYM_UBOUND:
3297 0 : name = "_gfortran_ubound";
3298 0 : break;
3299 :
3300 4148 : case GFC_ISYM_SIZE:
3301 4148 : name = "_gfortran_size";
3302 4148 : break;
3303 :
3304 0 : default:
3305 0 : gcc_unreachable ();
3306 : }
3307 :
3308 7497 : dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
3309 7497 : if (okind != 0)
3310 228 : kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
3311 : okind);
3312 : else
3313 7269 : kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
3314 : gfc_index_integer_kind);
3315 :
3316 7497 : ec = gfc_copy_expr (e);
3317 :
3318 : /* No bounds checking, this will be done before the loops if -fcheck=bounds
3319 : is in effect. */
3320 7497 : ec->no_bounds_check = 1;
3321 7497 : fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
3322 : ec, dim_arg, kind);
3323 7497 : gfc_simplify_expr (fcn, 0);
3324 7497 : fcn->no_bounds_check = 1;
3325 7497 : return fcn;
3326 : }
3327 :
3328 : /* Builds a logical expression. */
3329 :
3330 : static gfc_expr*
3331 1416 : build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
3332 : {
3333 1416 : gfc_typespec ts;
3334 1416 : gfc_expr *res;
3335 :
3336 1416 : ts.type = BT_LOGICAL;
3337 1416 : ts.kind = gfc_default_logical_kind;
3338 1416 : res = gfc_get_expr ();
3339 1416 : res->where = e1->where;
3340 1416 : res->expr_type = EXPR_OP;
3341 1416 : res->value.op.op = op;
3342 1416 : res->value.op.op1 = e1;
3343 1416 : res->value.op.op2 = e2;
3344 1416 : res->ts = ts;
3345 :
3346 1416 : return res;
3347 : }
3348 :
3349 :
3350 : /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
3351 : compatible typespecs. */
3352 :
3353 : static gfc_expr *
3354 6794 : get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
3355 : {
3356 6794 : gfc_expr *res;
3357 :
3358 6794 : res = gfc_get_expr ();
3359 6794 : res->ts = e1->ts;
3360 6794 : res->where = e1->where;
3361 6794 : res->expr_type = EXPR_OP;
3362 6794 : res->value.op.op = op;
3363 6794 : res->value.op.op1 = e1;
3364 6794 : res->value.op.op2 = e2;
3365 6794 : gfc_simplify_expr (res, 0);
3366 6794 : return res;
3367 : }
3368 :
3369 : /* Generate the IF statement for a runtime check if we want to do inlining or
3370 : not - putting in the code for both branches and putting it into the syntax
3371 : tree is the caller's responsibility. For fixed array sizes, this should be
3372 : removed by DCE. Only called for rank-two matrices A and B. */
3373 :
3374 : static gfc_code *
3375 591 : inline_limit_check (gfc_expr *a, gfc_expr *b, int limit, int rank_a)
3376 : {
3377 591 : gfc_expr *inline_limit;
3378 591 : gfc_code *if_1, *if_2, *else_2;
3379 591 : gfc_expr *b2, *a2, *a1, *m1, *m2;
3380 591 : gfc_typespec ts;
3381 591 : gfc_expr *cond;
3382 :
3383 591 : gcc_assert (rank_a == 1 || rank_a == 2);
3384 :
3385 : /* Calculation is done in real to avoid integer overflow. */
3386 :
3387 591 : inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
3388 : &a->where);
3389 591 : mpfr_set_si (inline_limit->value.real, limit, GFC_RND_MODE);
3390 :
3391 : /* Set the limit according to the rank. */
3392 591 : mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, rank_a + 1,
3393 : GFC_RND_MODE);
3394 :
3395 591 : a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3396 :
3397 : /* For a_rank = 1, must use one as the size of a along the second
3398 : dimension as to avoid too much code duplication. */
3399 :
3400 591 : if (rank_a == 2)
3401 484 : a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3402 : else
3403 107 : a2 = gfc_get_int_expr (gfc_index_integer_kind, &a->where, 1);
3404 :
3405 591 : b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3406 :
3407 591 : gfc_clear_ts (&ts);
3408 591 : ts.type = BT_REAL;
3409 591 : ts.kind = gfc_default_real_kind;
3410 591 : gfc_convert_type_warn (a1, &ts, 2, 0);
3411 591 : gfc_convert_type_warn (a2, &ts, 2, 0);
3412 591 : gfc_convert_type_warn (b2, &ts, 2, 0);
3413 :
3414 591 : m1 = get_operand (INTRINSIC_TIMES, a1, a2);
3415 591 : m2 = get_operand (INTRINSIC_TIMES, m1, b2);
3416 :
3417 591 : cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
3418 591 : gfc_simplify_expr (cond, 0);
3419 :
3420 591 : else_2 = XCNEW (gfc_code);
3421 591 : else_2->op = EXEC_IF;
3422 591 : else_2->loc = a->where;
3423 :
3424 591 : if_2 = XCNEW (gfc_code);
3425 591 : if_2->op = EXEC_IF;
3426 591 : if_2->expr1 = cond;
3427 591 : if_2->loc = a->where;
3428 591 : if_2->block = else_2;
3429 :
3430 591 : if_1 = XCNEW (gfc_code);
3431 591 : if_1->op = EXEC_IF;
3432 591 : if_1->block = if_2;
3433 591 : if_1->loc = a->where;
3434 :
3435 591 : return if_1;
3436 : }
3437 :
3438 :
3439 : /* Insert code to issue a runtime error if the expressions are not equal. */
3440 :
3441 : static gfc_code *
3442 393 : runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
3443 : {
3444 393 : gfc_expr *cond;
3445 393 : gfc_code *if_1, *if_2;
3446 393 : gfc_code *c;
3447 393 : gfc_actual_arglist *a1, *a2, *a3;
3448 :
3449 393 : gcc_assert (GFC_LOCUS_IS_SET (e1->where));
3450 : /* Build the call to runtime_error. */
3451 393 : c = XCNEW (gfc_code);
3452 393 : c->op = EXEC_CALL;
3453 393 : c->loc = e1->where;
3454 :
3455 : /* Get a null-terminated message string. */
3456 :
3457 393 : a1 = gfc_get_actual_arglist ();
3458 786 : a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
3459 393 : msg, strlen(msg)+1);
3460 393 : c->ext.actual = a1;
3461 :
3462 : /* Pass the value of the first expression. */
3463 393 : a2 = gfc_get_actual_arglist ();
3464 393 : a2->expr = gfc_copy_expr (e1);
3465 393 : a1->next = a2;
3466 :
3467 : /* Pass the value of the second expression. */
3468 393 : a3 = gfc_get_actual_arglist ();
3469 393 : a3->expr = gfc_copy_expr (e2);
3470 393 : a2->next = a3;
3471 :
3472 393 : gfc_check_fe_runtime_error (c->ext.actual);
3473 393 : gfc_resolve_fe_runtime_error (c);
3474 :
3475 393 : if_2 = XCNEW (gfc_code);
3476 393 : if_2->op = EXEC_IF;
3477 393 : if_2->loc = e1->where;
3478 393 : if_2->next = c;
3479 :
3480 393 : if_1 = XCNEW (gfc_code);
3481 393 : if_1->op = EXEC_IF;
3482 393 : if_1->block = if_2;
3483 393 : if_1->loc = e1->where;
3484 :
3485 393 : cond = build_logical_expr (INTRINSIC_NE, e1, e2);
3486 393 : gfc_simplify_expr (cond, 0);
3487 393 : if_2->expr1 = cond;
3488 :
3489 393 : return if_1;
3490 : }
3491 :
3492 : /* Handle matrix reallocation. Caller is responsible to insert into
3493 : the code tree.
3494 :
3495 : For the two-dimensional case, build
3496 :
3497 : if (allocated(c)) then
3498 : if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
3499 : deallocate(c)
3500 : allocate (c(size(a,1), size(b,2)))
3501 : end if
3502 : else
3503 : allocate (c(size(a,1),size(b,2)))
3504 : end if
3505 :
3506 : and for the other cases correspondingly.
3507 : */
3508 :
3509 : static gfc_code *
3510 188 : matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
3511 : enum matrix_case m_case)
3512 : {
3513 :
3514 188 : gfc_expr *allocated, *alloc_expr;
3515 188 : gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
3516 188 : gfc_code *else_alloc;
3517 188 : gfc_code *deallocate, *allocate1, *allocate_else;
3518 188 : gfc_array_ref *ar;
3519 188 : gfc_expr *cond, *ne1, *ne2;
3520 :
3521 188 : if (warn_realloc_lhs)
3522 23 : gfc_warning (OPT_Wrealloc_lhs,
3523 : "Code for reallocating the allocatable array at %L will "
3524 : "be added", &c->where);
3525 :
3526 188 : alloc_expr = gfc_copy_expr (c);
3527 :
3528 188 : ar = gfc_find_array_ref (alloc_expr);
3529 188 : gcc_assert (ar && ar->type == AR_FULL);
3530 :
3531 : /* c comes in as a full ref. Change it into a copy and make it into an
3532 : element ref so it has the right form for ALLOCATE. In the same
3533 : switch statement, also generate the size comparison for the second IF
3534 : statement. */
3535 :
3536 188 : ar->type = AR_ELEMENT;
3537 :
3538 188 : switch (m_case)
3539 : {
3540 101 : case A2B2:
3541 101 : ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3542 101 : ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3543 101 : ne1 = build_logical_expr (INTRINSIC_NE,
3544 : get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3545 : get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3546 101 : ne2 = build_logical_expr (INTRINSIC_NE,
3547 : get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3548 : get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3549 101 : cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3550 101 : break;
3551 :
3552 17 : case A2B2T:
3553 17 : ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3554 17 : ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3555 :
3556 17 : ne1 = build_logical_expr (INTRINSIC_NE,
3557 : get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3558 : get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3559 17 : ne2 = build_logical_expr (INTRINSIC_NE,
3560 : get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3561 : get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3562 17 : cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3563 17 : break;
3564 :
3565 4 : case A2TB2:
3566 :
3567 4 : ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3568 4 : ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3569 :
3570 4 : ne1 = build_logical_expr (INTRINSIC_NE,
3571 : get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3572 : get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3573 4 : ne2 = build_logical_expr (INTRINSIC_NE,
3574 : get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3575 : get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3576 4 : cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3577 4 : break;
3578 :
3579 43 : case A2B1:
3580 43 : ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3581 43 : cond = build_logical_expr (INTRINSIC_NE,
3582 : get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3583 : get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3584 43 : break;
3585 :
3586 7 : case A2TB1:
3587 7 : ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3588 7 : cond = build_logical_expr (INTRINSIC_NE,
3589 : get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3590 : get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3591 7 : break;
3592 :
3593 16 : case A1B2:
3594 16 : ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3595 16 : cond = build_logical_expr (INTRINSIC_NE,
3596 : get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3597 : get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3598 16 : break;
3599 :
3600 0 : case A2TB2T:
3601 : /* This can only happen for BLAS, we do not handle that case in
3602 : inline mamtul. */
3603 0 : ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3604 0 : ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3605 :
3606 0 : ne1 = build_logical_expr (INTRINSIC_NE,
3607 : get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3608 : get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3609 0 : ne2 = build_logical_expr (INTRINSIC_NE,
3610 : get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3611 : get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3612 :
3613 0 : cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3614 0 : break;
3615 :
3616 0 : default:
3617 0 : gcc_unreachable();
3618 :
3619 : }
3620 :
3621 188 : gfc_simplify_expr (cond, 0);
3622 :
3623 : /* We need two identical allocate statements in two
3624 : branches of the IF statement. */
3625 :
3626 188 : allocate1 = XCNEW (gfc_code);
3627 188 : allocate1->op = EXEC_ALLOCATE;
3628 188 : allocate1->ext.alloc.list = gfc_get_alloc ();
3629 188 : allocate1->loc = c->where;
3630 188 : allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
3631 :
3632 188 : allocate_else = XCNEW (gfc_code);
3633 188 : allocate_else->op = EXEC_ALLOCATE;
3634 188 : allocate_else->ext.alloc.list = gfc_get_alloc ();
3635 188 : allocate_else->loc = c->where;
3636 188 : allocate_else->ext.alloc.list->expr = alloc_expr;
3637 :
3638 188 : allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
3639 : "_gfortran_allocated", c->where,
3640 : 1, gfc_copy_expr (c));
3641 :
3642 188 : deallocate = XCNEW (gfc_code);
3643 188 : deallocate->op = EXEC_DEALLOCATE;
3644 188 : deallocate->ext.alloc.list = gfc_get_alloc ();
3645 188 : deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
3646 188 : deallocate->next = allocate1;
3647 188 : deallocate->loc = c->where;
3648 :
3649 188 : if_size_2 = XCNEW (gfc_code);
3650 188 : if_size_2->op = EXEC_IF;
3651 188 : if_size_2->expr1 = cond;
3652 188 : if_size_2->loc = c->where;
3653 188 : if_size_2->next = deallocate;
3654 :
3655 188 : if_size_1 = XCNEW (gfc_code);
3656 188 : if_size_1->op = EXEC_IF;
3657 188 : if_size_1->block = if_size_2;
3658 188 : if_size_1->loc = c->where;
3659 :
3660 188 : else_alloc = XCNEW (gfc_code);
3661 188 : else_alloc->op = EXEC_IF;
3662 188 : else_alloc->loc = c->where;
3663 188 : else_alloc->next = allocate_else;
3664 :
3665 188 : if_alloc_2 = XCNEW (gfc_code);
3666 188 : if_alloc_2->op = EXEC_IF;
3667 188 : if_alloc_2->expr1 = allocated;
3668 188 : if_alloc_2->loc = c->where;
3669 188 : if_alloc_2->next = if_size_1;
3670 188 : if_alloc_2->block = else_alloc;
3671 :
3672 188 : if_alloc_1 = XCNEW (gfc_code);
3673 188 : if_alloc_1->op = EXEC_IF;
3674 188 : if_alloc_1->block = if_alloc_2;
3675 188 : if_alloc_1->loc = c->where;
3676 :
3677 188 : return if_alloc_1;
3678 : }
3679 :
3680 : /* Callback function for has_function_or_op. */
3681 :
3682 : static int
3683 675 : is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
3684 : void *data ATTRIBUTE_UNUSED)
3685 : {
3686 675 : if ((*e) == 0)
3687 : return 0;
3688 : else
3689 675 : return (*e)->expr_type == EXPR_FUNCTION
3690 675 : || (*e)->expr_type == EXPR_OP;
3691 : }
3692 :
3693 : /* Returns true if the expression contains a function. */
3694 :
3695 : static bool
3696 1306 : has_function_or_op (gfc_expr **e)
3697 : {
3698 1306 : if (e == NULL)
3699 : return false;
3700 : else
3701 1306 : return gfc_expr_walker (e, is_function_or_op, NULL);
3702 : }
3703 :
3704 : /* Freeze (assign to a temporary variable) a single expression. */
3705 :
3706 : static void
3707 1306 : freeze_expr (gfc_expr **ep)
3708 : {
3709 1306 : gfc_expr *ne;
3710 1306 : if (has_function_or_op (ep))
3711 : {
3712 195 : ne = create_var (*ep, "freeze");
3713 195 : *ep = ne;
3714 : }
3715 1306 : }
3716 :
3717 : /* Go through an expression's references and assign them to temporary
3718 : variables if they contain functions. This is usually done prior to
3719 : front-end scalarization to avoid multiple invocations of functions. */
3720 :
3721 : static void
3722 2055 : freeze_references (gfc_expr *e)
3723 : {
3724 2055 : gfc_ref *r;
3725 2055 : gfc_array_ref *ar;
3726 2055 : int i;
3727 :
3728 4115 : for (r=e->ref; r; r=r->next)
3729 : {
3730 2060 : if (r->type == REF_SUBSTRING)
3731 : {
3732 0 : if (r->u.ss.start != NULL)
3733 0 : freeze_expr (&r->u.ss.start);
3734 :
3735 0 : if (r->u.ss.end != NULL)
3736 0 : freeze_expr (&r->u.ss.end);
3737 : }
3738 2060 : else if (r->type == REF_ARRAY)
3739 : {
3740 2055 : ar = &r->u.ar;
3741 2055 : switch (ar->type)
3742 : {
3743 : case AR_FULL:
3744 : break;
3745 :
3746 : case AR_SECTION:
3747 700 : for (i=0; i<ar->dimen; i++)
3748 : {
3749 456 : if (ar->dimen_type[i] == DIMEN_RANGE)
3750 : {
3751 425 : freeze_expr (&ar->start[i]);
3752 425 : freeze_expr (&ar->end[i]);
3753 425 : freeze_expr (&ar->stride[i]);
3754 : }
3755 31 : else if (ar->dimen_type[i] == DIMEN_ELEMENT)
3756 : {
3757 31 : freeze_expr (&ar->start[i]);
3758 : }
3759 : }
3760 : break;
3761 :
3762 : case AR_ELEMENT:
3763 0 : for (i=0; i<ar->dimen; i++)
3764 0 : freeze_expr (&ar->start[i]);
3765 : break;
3766 :
3767 : default:
3768 : break;
3769 : }
3770 : }
3771 : }
3772 2055 : }
3773 :
3774 : /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
3775 :
3776 : static gfc_expr *
3777 3632 : convert_to_index_kind (gfc_expr *e)
3778 : {
3779 3632 : gfc_expr *res;
3780 :
3781 3632 : gcc_assert (e != NULL);
3782 :
3783 3632 : res = gfc_copy_expr (e);
3784 :
3785 3632 : gcc_assert (e->ts.type == BT_INTEGER);
3786 :
3787 3632 : if (res->ts.kind != gfc_index_integer_kind)
3788 : {
3789 0 : gfc_typespec ts;
3790 0 : gfc_clear_ts (&ts);
3791 0 : ts.type = BT_INTEGER;
3792 0 : ts.kind = gfc_index_integer_kind;
3793 :
3794 0 : gfc_convert_type_warn (e, &ts, 2, 0);
3795 : }
3796 :
3797 3632 : return res;
3798 : }
3799 :
3800 : /* Function to create a DO loop including creation of the
3801 : iteration variable. gfc_expr are copied.*/
3802 :
3803 : static gfc_code *
3804 1816 : create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
3805 : gfc_namespace *ns, char *vname)
3806 : {
3807 :
3808 1816 : char name[GFC_MAX_SYMBOL_LEN +1];
3809 1816 : gfc_symtree *symtree;
3810 1816 : gfc_symbol *symbol;
3811 1816 : gfc_expr *i;
3812 1816 : gfc_code *n, *n2;
3813 :
3814 : /* Create an expression for the iteration variable. */
3815 1816 : if (vname)
3816 0 : sprintf (name, "__var_%d_do_%s", var_num++, vname);
3817 : else
3818 1816 : sprintf (name, "__var_%d_do", var_num++);
3819 :
3820 :
3821 1816 : if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
3822 0 : gcc_unreachable ();
3823 :
3824 : /* Create the loop variable. */
3825 :
3826 1816 : symbol = symtree->n.sym;
3827 1816 : symbol->ts.type = BT_INTEGER;
3828 1816 : symbol->ts.kind = gfc_index_integer_kind;
3829 1816 : symbol->attr.flavor = FL_VARIABLE;
3830 1816 : symbol->attr.referenced = 1;
3831 1816 : symbol->attr.dimension = 0;
3832 1816 : symbol->attr.fe_temp = 1;
3833 1816 : symbol->attr.automatic = 1;
3834 1816 : gfc_commit_symbol (symbol);
3835 :
3836 1816 : i = gfc_get_expr ();
3837 1816 : i->expr_type = EXPR_VARIABLE;
3838 1816 : i->ts = symbol->ts;
3839 1816 : i->rank = 0;
3840 1816 : i->where = *where;
3841 1816 : i->symtree = symtree;
3842 :
3843 : /* ... and the nested DO statements. */
3844 1816 : n = XCNEW (gfc_code);
3845 1816 : n->op = EXEC_DO;
3846 1816 : n->loc = *where;
3847 1816 : n->ext.iterator = gfc_get_iterator ();
3848 1816 : n->ext.iterator->var = i;
3849 1816 : n->ext.iterator->start = convert_to_index_kind (start);
3850 1816 : n->ext.iterator->end = convert_to_index_kind (end);
3851 1816 : if (step)
3852 0 : n->ext.iterator->step = convert_to_index_kind (step);
3853 : else
3854 1816 : n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
3855 : where, 1);
3856 :
3857 1816 : n2 = XCNEW (gfc_code);
3858 1816 : n2->op = EXEC_DO;
3859 1816 : n2->loc = *where;
3860 1816 : n2->next = NULL;
3861 1816 : n->block = n2;
3862 1816 : return n;
3863 : }
3864 :
3865 : /* Get the upper bound of the DO loops for matmul along a dimension. This
3866 : is one-based. */
3867 :
3868 : static gfc_expr*
3869 1816 : get_size_m1 (gfc_expr *e, int dimen)
3870 : {
3871 1816 : mpz_t size;
3872 1816 : gfc_expr *res;
3873 :
3874 1816 : if (gfc_array_dimen_size (e, dimen - 1, &size))
3875 : {
3876 1278 : res = gfc_get_constant_expr (BT_INTEGER,
3877 : gfc_index_integer_kind, &e->where);
3878 1278 : mpz_sub_ui (res->value.integer, size, 1);
3879 1278 : mpz_clear (size);
3880 : }
3881 : else
3882 : {
3883 538 : res = get_operand (INTRINSIC_MINUS,
3884 : get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
3885 : gfc_get_int_expr (gfc_index_integer_kind,
3886 : &e->where, 1));
3887 538 : gfc_simplify_expr (res, 0);
3888 : }
3889 :
3890 1816 : return res;
3891 : }
3892 :
3893 : /* Function to return a scalarized expression. It is assumed that indices are
3894 : zero based to make generation of DO loops easier. A zero as index will
3895 : access the first element along a dimension. Single element references will
3896 : be skipped. A NULL as an expression will be replaced by a full reference.
3897 : This assumes that the index loops have gfc_index_integer_kind, and that all
3898 : references have been frozen. */
3899 :
3900 : static gfc_expr*
3901 2055 : scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
3902 : {
3903 2055 : gfc_array_ref *ar;
3904 2055 : int i;
3905 2055 : int rank;
3906 2055 : gfc_expr *e;
3907 2055 : int i_index;
3908 2055 : bool was_fullref;
3909 :
3910 2055 : e = gfc_copy_expr(e_in);
3911 :
3912 2055 : rank = e->rank;
3913 :
3914 2055 : ar = gfc_find_array_ref (e);
3915 :
3916 : /* We scalarize count_index variables, reducing the rank by count_index. */
3917 :
3918 2055 : e->rank = rank - count_index;
3919 :
3920 2055 : was_fullref = ar->type == AR_FULL;
3921 :
3922 2055 : if (e->rank == 0)
3923 : ar->type = AR_ELEMENT;
3924 : else
3925 0 : ar->type = AR_SECTION;
3926 :
3927 : /* Loop over the indices. For each index, create the expression
3928 : index * stride + lbound(e, dim). */
3929 :
3930 2055 : i_index = 0;
3931 5718 : for (i=0; i < ar->dimen; i++)
3932 : {
3933 3663 : if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
3934 : {
3935 3632 : if (index[i_index] != NULL)
3936 : {
3937 3632 : gfc_expr *lbound, *nindex;
3938 3632 : gfc_expr *loopvar;
3939 :
3940 3632 : loopvar = gfc_copy_expr (index[i_index]);
3941 :
3942 3632 : if (ar->stride[i])
3943 : {
3944 72 : gfc_expr *tmp;
3945 :
3946 72 : tmp = gfc_copy_expr(ar->stride[i]);
3947 72 : if (tmp->ts.kind != gfc_index_integer_kind)
3948 : {
3949 0 : gfc_typespec ts;
3950 0 : gfc_clear_ts (&ts);
3951 0 : ts.type = BT_INTEGER;
3952 0 : ts.kind = gfc_index_integer_kind;
3953 0 : gfc_convert_type (tmp, &ts, 2);
3954 : }
3955 72 : nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
3956 : }
3957 : else
3958 : nindex = loopvar;
3959 :
3960 : /* Calculate the lower bound of the expression. */
3961 3632 : if (ar->start[i])
3962 : {
3963 283 : lbound = gfc_copy_expr (ar->start[i]);
3964 283 : if (lbound->ts.kind != gfc_index_integer_kind)
3965 : {
3966 283 : gfc_typespec ts;
3967 283 : gfc_clear_ts (&ts);
3968 283 : ts.type = BT_INTEGER;
3969 283 : ts.kind = gfc_index_integer_kind;
3970 283 : gfc_convert_type (lbound, &ts, 2);
3971 :
3972 : }
3973 : }
3974 : else
3975 : {
3976 3349 : gfc_expr *lbound_e;
3977 3349 : gfc_ref *ref;
3978 :
3979 3349 : lbound_e = gfc_copy_expr (e_in);
3980 :
3981 3349 : for (ref = lbound_e->ref; ref; ref = ref->next)
3982 3349 : if (ref->type == REF_ARRAY
3983 3349 : && (ref->u.ar.type == AR_FULL
3984 142 : || ref->u.ar.type == AR_SECTION))
3985 : break;
3986 :
3987 3349 : if (ref->next)
3988 : {
3989 9 : gfc_free_ref_list (ref->next);
3990 9 : ref->next = NULL;
3991 : }
3992 :
3993 3349 : if (!was_fullref)
3994 : {
3995 : /* Look at full individual sections, like a(:). The first index
3996 : is the lbound of a full ref. */
3997 142 : int j;
3998 142 : gfc_array_ref *ar;
3999 142 : int to;
4000 :
4001 142 : ar = &ref->u.ar;
4002 :
4003 : /* For assumed size, we need to keep around the final
4004 : reference in order not to get an error on resolution
4005 : below, and we cannot use AR_FULL. */
4006 :
4007 142 : if (ar->as->type == AS_ASSUMED_SIZE)
4008 : {
4009 2 : ar->type = AR_SECTION;
4010 2 : to = ar->dimen - 1;
4011 : }
4012 : else
4013 : {
4014 140 : to = ar->dimen;
4015 140 : ar->type = AR_FULL;
4016 : }
4017 :
4018 430 : for (j = 0; j < to; j++)
4019 : {
4020 288 : gfc_free_expr (ar->start[j]);
4021 288 : ar->start[j] = NULL;
4022 288 : gfc_free_expr (ar->end[j]);
4023 288 : ar->end[j] = NULL;
4024 288 : gfc_free_expr (ar->stride[j]);
4025 288 : ar->stride[j] = NULL;
4026 : }
4027 :
4028 : /* We have to get rid of the shape, if there is one. Do
4029 : so by freeing it and calling gfc_resolve to rebuild
4030 : it, if necessary. */
4031 :
4032 142 : if (lbound_e->shape)
4033 48 : gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
4034 :
4035 142 : lbound_e->rank = ar->dimen;
4036 142 : gfc_resolve_expr (lbound_e);
4037 : }
4038 3349 : lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
4039 : i + 1);
4040 3349 : gfc_free_expr (lbound_e);
4041 : }
4042 :
4043 3632 : ar->dimen_type[i] = DIMEN_ELEMENT;
4044 :
4045 3632 : gfc_free_expr (ar->start[i]);
4046 3632 : ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
4047 :
4048 3632 : gfc_free_expr (ar->end[i]);
4049 3632 : ar->end[i] = NULL;
4050 3632 : gfc_free_expr (ar->stride[i]);
4051 3632 : ar->stride[i] = NULL;
4052 3632 : gfc_simplify_expr (ar->start[i], 0);
4053 : }
4054 0 : else if (was_fullref)
4055 : {
4056 0 : gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
4057 : }
4058 3632 : i_index ++;
4059 : }
4060 : }
4061 :
4062 : /* Bounds checking will be done before the loops if -fcheck=bounds
4063 : is in effect. */
4064 2055 : e->no_bounds_check = 1;
4065 2055 : return e;
4066 : }
4067 :
4068 : /* Helper function to check for a dimen vector as subscript. */
4069 :
4070 : bool
4071 3987 : gfc_has_dimen_vector_ref (gfc_expr *e)
4072 : {
4073 3987 : gfc_array_ref *ar;
4074 3987 : int i;
4075 :
4076 3987 : ar = gfc_find_array_ref (e);
4077 3987 : gcc_assert (ar);
4078 3987 : if (ar->type == AR_FULL)
4079 : return false;
4080 :
4081 1954 : for (i=0; i<ar->dimen; i++)
4082 1244 : if (ar->dimen_type[i] == DIMEN_VECTOR)
4083 : return true;
4084 :
4085 : return false;
4086 : }
4087 :
4088 : /* If handed an expression of the form
4089 :
4090 : TRANSPOSE(CONJG(A))
4091 :
4092 : check if A can be handled by matmul and return if there is an uneven number
4093 : of CONJG calls. Return a pointer to the array when everything is OK, NULL
4094 : otherwise. The caller has to check for the correct rank. */
4095 :
4096 : static gfc_expr*
4097 3182 : check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
4098 : {
4099 3182 : *conjg = false;
4100 3182 : *transpose = false;
4101 :
4102 3966 : do
4103 : {
4104 3574 : if (e->expr_type == EXPR_VARIABLE)
4105 : {
4106 3042 : gcc_assert (e->rank == 1 || e->rank == 2);
4107 : return e;
4108 : }
4109 532 : else if (e->expr_type == EXPR_FUNCTION)
4110 : {
4111 477 : if (e->value.function.isym == NULL)
4112 : return NULL;
4113 :
4114 454 : if (e->value.function.isym->id == GFC_ISYM_CONJG)
4115 68 : *conjg = !*conjg;
4116 386 : else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE)
4117 324 : *transpose = !*transpose;
4118 : else return NULL;
4119 : }
4120 : else
4121 : return NULL;
4122 :
4123 392 : e = e->value.function.actual->expr;
4124 : }
4125 : while(1);
4126 :
4127 : return NULL;
4128 : }
4129 :
4130 : /* Macros for unified error messages. */
4131 :
4132 : #define B_ERROR_1 _("Incorrect extent in argument B in MATMUL intrinsic in " \
4133 : "dimension 1: is %ld, should be %ld")
4134 :
4135 : #define C_ERROR_1 _("Array bound mismatch for dimension 1 of array " \
4136 : "(%ld/%ld)")
4137 :
4138 : #define C_ERROR_2 _("Array bound mismatch for dimension 2 of array " \
4139 : "(%ld/%ld)")
4140 :
4141 :
4142 : /* Inline assignments of the form c = matmul(a,b).
4143 : Handle only the cases currently where b and c are rank-two arrays.
4144 :
4145 : This basically translates the code to
4146 :
4147 : BLOCK
4148 : integer i,j,k
4149 : c = 0
4150 : do j=0, size(b,2)-1
4151 : do k=0, size(a, 2)-1
4152 : do i=0, size(a, 1)-1
4153 : c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
4154 : c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
4155 : a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
4156 : b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
4157 : end do
4158 : end do
4159 : end do
4160 : END BLOCK
4161 :
4162 : */
4163 :
4164 : static int
4165 1052907 : inline_matmul_assign (gfc_code **c, int *walk_subtrees,
4166 : void *data ATTRIBUTE_UNUSED)
4167 : {
4168 1052907 : gfc_code *co = *c;
4169 1052907 : gfc_expr *expr1, *expr2;
4170 1052907 : gfc_expr *matrix_a, *matrix_b;
4171 1052907 : gfc_actual_arglist *a, *b;
4172 1052907 : gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
4173 1052907 : gfc_expr *zero_e;
4174 1052907 : gfc_expr *u1, *u2, *u3;
4175 1052907 : gfc_expr *list[2];
4176 1052907 : gfc_expr *ascalar, *bscalar, *cscalar;
4177 1052907 : gfc_expr *mult;
4178 1052907 : gfc_expr *var_1, *var_2, *var_3;
4179 1052907 : gfc_expr *zero;
4180 1052907 : gfc_namespace *ns;
4181 1052907 : gfc_intrinsic_op op_times, op_plus;
4182 1052907 : enum matrix_case m_case;
4183 1052907 : int i;
4184 1052907 : gfc_code *if_limit = NULL;
4185 1052907 : gfc_code **next_code_point;
4186 1052907 : bool conjg_a, conjg_b, transpose_a, transpose_b;
4187 1052907 : bool realloc_c;
4188 :
4189 1052907 : if (co->op != EXEC_ASSIGN)
4190 : return 0;
4191 :
4192 273413 : if (in_where || in_assoc_list)
4193 : return 0;
4194 :
4195 : /* The BLOCKS generated for the temporary variables and FORALL don't
4196 : mix. */
4197 272842 : if (forall_level > 0)
4198 : return 0;
4199 :
4200 : /* For now don't do anything in OpenMP workshare, it confuses
4201 : its translation, which expects only the allowed statements in there.
4202 : We should figure out how to parallelize this eventually. */
4203 270662 : if (in_omp_workshare || in_omp_atomic)
4204 : return 0;
4205 :
4206 267764 : expr1 = co->expr1;
4207 267764 : expr2 = co->expr2;
4208 267764 : if (expr2->expr_type != EXPR_FUNCTION
4209 37721 : || expr2->value.function.isym == NULL
4210 28638 : || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
4211 : return 0;
4212 :
4213 698 : current_code = c;
4214 698 : inserted_block = NULL;
4215 698 : changed_statement = NULL;
4216 :
4217 698 : a = expr2->value.function.actual;
4218 698 : matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
4219 698 : if (matrix_a == NULL)
4220 : return 0;
4221 :
4222 698 : b = a->next;
4223 698 : matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
4224 698 : if (matrix_b == NULL)
4225 : return 0;
4226 :
4227 1394 : if (gfc_has_dimen_vector_ref (expr1) || gfc_has_dimen_vector_ref (matrix_a)
4228 1394 : || gfc_has_dimen_vector_ref (matrix_b))
4229 : return 0;
4230 :
4231 : /* We do not handle data dependencies yet. */
4232 696 : if (gfc_check_dependency (expr1, matrix_a, true)
4233 696 : || gfc_check_dependency (expr1, matrix_b, true))
4234 : return 0;
4235 :
4236 696 : m_case = none;
4237 696 : if (matrix_a->rank == 2)
4238 : {
4239 584 : if (transpose_a)
4240 : {
4241 49 : if (matrix_b->rank == 2 && !transpose_b)
4242 : m_case = A2TB2;
4243 12 : else if (matrix_b->rank == 1)
4244 : m_case = A2TB1;
4245 : }
4246 : else
4247 : {
4248 535 : if (matrix_b->rank == 1)
4249 : m_case = A2B1;
4250 : else /* matrix_b->rank == 2 */
4251 : {
4252 415 : if (transpose_b)
4253 : m_case = A2B2T;
4254 : else
4255 339 : m_case = A2B2;
4256 : }
4257 : }
4258 : }
4259 : else /* matrix_a->rank == 1 */
4260 : {
4261 112 : if (matrix_b->rank == 2)
4262 : {
4263 112 : if (!transpose_b)
4264 : m_case = A1B2;
4265 : }
4266 : }
4267 :
4268 339 : if (m_case == none)
4269 : return 0;
4270 :
4271 : /* We only handle assignment to numeric or logical variables. */
4272 691 : switch(expr1->ts.type)
4273 : {
4274 685 : case BT_INTEGER:
4275 685 : case BT_LOGICAL:
4276 685 : case BT_REAL:
4277 685 : case BT_COMPLEX:
4278 685 : break;
4279 :
4280 : default:
4281 : return 0;
4282 : }
4283 :
4284 685 : ns = insert_block ();
4285 :
4286 : /* Assign the type of the zero expression for initializing the resulting
4287 : array, and the expression (+ and * for real, integer and complex;
4288 : .and. and .or for logical. */
4289 :
4290 685 : switch(expr1->ts.type)
4291 : {
4292 145 : case BT_INTEGER:
4293 145 : zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
4294 145 : op_times = INTRINSIC_TIMES;
4295 145 : op_plus = INTRINSIC_PLUS;
4296 145 : break;
4297 :
4298 15 : case BT_LOGICAL:
4299 15 : op_times = INTRINSIC_AND;
4300 15 : op_plus = INTRINSIC_OR;
4301 15 : zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
4302 : 0);
4303 15 : break;
4304 449 : case BT_REAL:
4305 449 : zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
4306 : &expr1->where);
4307 449 : mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
4308 449 : op_times = INTRINSIC_TIMES;
4309 449 : op_plus = INTRINSIC_PLUS;
4310 449 : break;
4311 :
4312 76 : case BT_COMPLEX:
4313 76 : zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
4314 : &expr1->where);
4315 76 : mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
4316 76 : op_times = INTRINSIC_TIMES;
4317 76 : op_plus = INTRINSIC_PLUS;
4318 :
4319 76 : break;
4320 :
4321 0 : default:
4322 0 : gcc_unreachable();
4323 : }
4324 :
4325 685 : current_code = &ns->code;
4326 :
4327 : /* Freeze the references, keeping track of how many temporary variables were
4328 : created. */
4329 685 : n_vars = 0;
4330 685 : freeze_references (matrix_a);
4331 685 : freeze_references (matrix_b);
4332 685 : freeze_references (expr1);
4333 :
4334 685 : if (n_vars == 0)
4335 616 : next_code_point = current_code;
4336 : else
4337 : {
4338 : next_code_point = &ns->code;
4339 264 : for (i=0; i<n_vars; i++)
4340 195 : next_code_point = &(*next_code_point)->next;
4341 : }
4342 :
4343 : /* Take care of the inline flag. If the limit check evaluates to a
4344 : constant, dead code elimination will eliminate the unneeded branch. */
4345 :
4346 685 : if (flag_inline_matmul_limit > 0
4347 685 : && (matrix_a->rank == 1 || matrix_a->rank == 2)
4348 685 : && matrix_b->rank == 2)
4349 : {
4350 553 : if_limit = inline_limit_check (matrix_a, matrix_b,
4351 : flag_inline_matmul_limit,
4352 : matrix_a->rank);
4353 :
4354 : /* Insert the original statement into the else branch. */
4355 553 : if_limit->block->block->next = co;
4356 553 : co->next = NULL;
4357 :
4358 : /* ... and the new ones go into the original one. */
4359 553 : *next_code_point = if_limit;
4360 553 : next_code_point = &if_limit->block->next;
4361 : }
4362 :
4363 685 : zero_e->no_bounds_check = 1;
4364 :
4365 685 : assign_zero = XCNEW (gfc_code);
4366 685 : assign_zero->op = EXEC_ASSIGN;
4367 685 : assign_zero->loc = co->loc;
4368 685 : assign_zero->expr1 = gfc_copy_expr (expr1);
4369 685 : assign_zero->expr1->no_bounds_check = 1;
4370 685 : assign_zero->expr2 = zero_e;
4371 :
4372 685 : realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
4373 :
4374 685 : if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4375 : {
4376 122 : gfc_code *test;
4377 122 : gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
4378 :
4379 122 : switch (m_case)
4380 : {
4381 15 : case A2B1:
4382 :
4383 15 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4384 15 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4385 15 : test = runtime_error_ne (b1, a2, B_ERROR_1);
4386 15 : *next_code_point = test;
4387 15 : next_code_point = &test->next;
4388 :
4389 15 : if (!realloc_c)
4390 : {
4391 11 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4392 11 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4393 11 : test = runtime_error_ne (c1, a1, C_ERROR_1);
4394 11 : *next_code_point = test;
4395 11 : next_code_point = &test->next;
4396 : }
4397 : break;
4398 :
4399 0 : case A2TB1:
4400 0 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4401 0 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4402 0 : test = runtime_error_ne (b1, a1, B_ERROR_1);
4403 0 : *next_code_point = test;
4404 0 : next_code_point = &test->next;
4405 :
4406 0 : if (!realloc_c)
4407 : {
4408 0 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4409 0 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4410 0 : test = runtime_error_ne (c1, a2, C_ERROR_1);
4411 0 : *next_code_point = test;
4412 0 : next_code_point = &test->next;
4413 : }
4414 : break;
4415 :
4416 16 : case A1B2:
4417 :
4418 16 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4419 16 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4420 16 : test = runtime_error_ne (b1, a1, B_ERROR_1);
4421 16 : *next_code_point = test;
4422 16 : next_code_point = &test->next;
4423 :
4424 16 : if (!realloc_c)
4425 : {
4426 11 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4427 11 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4428 11 : test = runtime_error_ne (c1, b2, C_ERROR_1);
4429 11 : *next_code_point = test;
4430 11 : next_code_point = &test->next;
4431 : }
4432 : break;
4433 :
4434 34 : case A2B2:
4435 :
4436 34 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4437 34 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4438 34 : test = runtime_error_ne (b1, a2, B_ERROR_1);
4439 34 : *next_code_point = test;
4440 34 : next_code_point = &test->next;
4441 :
4442 34 : if (!realloc_c)
4443 : {
4444 27 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4445 27 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4446 27 : test = runtime_error_ne (c1, a1, C_ERROR_1);
4447 27 : *next_code_point = test;
4448 27 : next_code_point = &test->next;
4449 :
4450 27 : c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4451 27 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4452 27 : test = runtime_error_ne (c2, b2, C_ERROR_2);
4453 27 : *next_code_point = test;
4454 27 : next_code_point = &test->next;
4455 : }
4456 : break;
4457 :
4458 44 : case A2B2T:
4459 :
4460 44 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4461 44 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4462 : /* matrix_b is transposed, hence dimension 1 for the error message. */
4463 44 : test = runtime_error_ne (b2, a2, B_ERROR_1);
4464 44 : *next_code_point = test;
4465 44 : next_code_point = &test->next;
4466 :
4467 44 : if (!realloc_c)
4468 : {
4469 39 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4470 39 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4471 39 : test = runtime_error_ne (c1, a1, C_ERROR_1);
4472 39 : *next_code_point = test;
4473 39 : next_code_point = &test->next;
4474 :
4475 39 : c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4476 39 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4477 39 : test = runtime_error_ne (c2, b1, C_ERROR_2);
4478 39 : *next_code_point = test;
4479 39 : next_code_point = &test->next;
4480 : }
4481 : break;
4482 :
4483 13 : case A2TB2:
4484 :
4485 13 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4486 13 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4487 13 : test = runtime_error_ne (b1, a1, B_ERROR_1);
4488 13 : *next_code_point = test;
4489 13 : next_code_point = &test->next;
4490 :
4491 13 : if (!realloc_c)
4492 : {
4493 12 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4494 12 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4495 12 : test = runtime_error_ne (c1, a2, C_ERROR_1);
4496 12 : *next_code_point = test;
4497 12 : next_code_point = &test->next;
4498 :
4499 12 : c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4500 12 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4501 12 : test = runtime_error_ne (c2, b2, C_ERROR_2);
4502 12 : *next_code_point = test;
4503 12 : next_code_point = &test->next;
4504 : }
4505 : break;
4506 :
4507 : default:
4508 : gcc_unreachable ();
4509 : }
4510 : }
4511 :
4512 : /* Handle the reallocation, if needed. */
4513 :
4514 663 : if (realloc_c)
4515 : {
4516 182 : gfc_code *lhs_alloc;
4517 :
4518 182 : lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
4519 :
4520 182 : *next_code_point = lhs_alloc;
4521 182 : next_code_point = &lhs_alloc->next;
4522 :
4523 : }
4524 :
4525 685 : *next_code_point = assign_zero;
4526 :
4527 685 : zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
4528 :
4529 685 : assign_matmul = XCNEW (gfc_code);
4530 685 : assign_matmul->op = EXEC_ASSIGN;
4531 685 : assign_matmul->loc = co->loc;
4532 :
4533 : /* Get the bounds for the loops, create them and create the scalarized
4534 : expressions. */
4535 :
4536 685 : switch (m_case)
4537 : {
4538 333 : case A2B2:
4539 :
4540 333 : u1 = get_size_m1 (matrix_b, 2);
4541 333 : u2 = get_size_m1 (matrix_a, 2);
4542 333 : u3 = get_size_m1 (matrix_a, 1);
4543 :
4544 333 : do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4545 333 : do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4546 333 : do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4547 :
4548 333 : do_1->block->next = do_2;
4549 333 : do_2->block->next = do_3;
4550 333 : do_3->block->next = assign_matmul;
4551 :
4552 333 : var_1 = do_1->ext.iterator->var;
4553 333 : var_2 = do_2->ext.iterator->var;
4554 333 : var_3 = do_3->ext.iterator->var;
4555 :
4556 333 : list[0] = var_3;
4557 333 : list[1] = var_1;
4558 333 : cscalar = scalarized_expr (co->expr1, list, 2);
4559 :
4560 333 : list[0] = var_3;
4561 333 : list[1] = var_2;
4562 333 : ascalar = scalarized_expr (matrix_a, list, 2);
4563 :
4564 333 : list[0] = var_2;
4565 333 : list[1] = var_1;
4566 333 : bscalar = scalarized_expr (matrix_b, list, 2);
4567 :
4568 333 : break;
4569 :
4570 76 : case A2B2T:
4571 :
4572 76 : u1 = get_size_m1 (matrix_b, 1);
4573 76 : u2 = get_size_m1 (matrix_a, 2);
4574 76 : u3 = get_size_m1 (matrix_a, 1);
4575 :
4576 76 : do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4577 76 : do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4578 76 : do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4579 :
4580 76 : do_1->block->next = do_2;
4581 76 : do_2->block->next = do_3;
4582 76 : do_3->block->next = assign_matmul;
4583 :
4584 76 : var_1 = do_1->ext.iterator->var;
4585 76 : var_2 = do_2->ext.iterator->var;
4586 76 : var_3 = do_3->ext.iterator->var;
4587 :
4588 76 : list[0] = var_3;
4589 76 : list[1] = var_1;
4590 76 : cscalar = scalarized_expr (co->expr1, list, 2);
4591 :
4592 76 : list[0] = var_3;
4593 76 : list[1] = var_2;
4594 76 : ascalar = scalarized_expr (matrix_a, list, 2);
4595 :
4596 76 : list[0] = var_1;
4597 76 : list[1] = var_2;
4598 76 : bscalar = scalarized_expr (matrix_b, list, 2);
4599 :
4600 76 : break;
4601 :
4602 37 : case A2TB2:
4603 :
4604 37 : u1 = get_size_m1 (matrix_a, 2);
4605 37 : u2 = get_size_m1 (matrix_b, 2);
4606 37 : u3 = get_size_m1 (matrix_a, 1);
4607 :
4608 37 : do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4609 37 : do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4610 37 : do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4611 :
4612 37 : do_1->block->next = do_2;
4613 37 : do_2->block->next = do_3;
4614 37 : do_3->block->next = assign_matmul;
4615 :
4616 37 : var_1 = do_1->ext.iterator->var;
4617 37 : var_2 = do_2->ext.iterator->var;
4618 37 : var_3 = do_3->ext.iterator->var;
4619 :
4620 37 : list[0] = var_1;
4621 37 : list[1] = var_2;
4622 37 : cscalar = scalarized_expr (co->expr1, list, 2);
4623 :
4624 37 : list[0] = var_3;
4625 37 : list[1] = var_1;
4626 37 : ascalar = scalarized_expr (matrix_a, list, 2);
4627 :
4628 37 : list[0] = var_3;
4629 37 : list[1] = var_2;
4630 37 : bscalar = scalarized_expr (matrix_b, list, 2);
4631 :
4632 37 : break;
4633 :
4634 120 : case A2B1:
4635 120 : u1 = get_size_m1 (matrix_b, 1);
4636 120 : u2 = get_size_m1 (matrix_a, 1);
4637 :
4638 120 : do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4639 120 : do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4640 :
4641 120 : do_1->block->next = do_2;
4642 120 : do_2->block->next = assign_matmul;
4643 :
4644 120 : var_1 = do_1->ext.iterator->var;
4645 120 : var_2 = do_2->ext.iterator->var;
4646 :
4647 120 : list[0] = var_2;
4648 120 : cscalar = scalarized_expr (co->expr1, list, 1);
4649 :
4650 120 : list[0] = var_2;
4651 120 : list[1] = var_1;
4652 120 : ascalar = scalarized_expr (matrix_a, list, 2);
4653 :
4654 120 : list[0] = var_1;
4655 120 : bscalar = scalarized_expr (matrix_b, list, 1);
4656 :
4657 120 : break;
4658 :
4659 12 : case A2TB1:
4660 :
4661 : /* Ordering here is
4662 : do i=1,size(a,2)
4663 : do j=1,size(b,1)
4664 : c(i) = c(i) + a(j,i) * b(j)
4665 : end do
4666 : end do
4667 : where i is var_1 and j is var_2. */
4668 :
4669 12 : u1 = get_size_m1 (matrix_a, 2);
4670 12 : u2 = get_size_m1 (matrix_b, 1);
4671 :
4672 12 : do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4673 12 : do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4674 :
4675 12 : do_1->block->next = do_2;
4676 12 : do_2->block->next = assign_matmul;
4677 :
4678 12 : var_1 = do_1->ext.iterator->var;
4679 12 : var_2 = do_2->ext.iterator->var;
4680 :
4681 12 : list[0] = var_1;
4682 12 : cscalar = scalarized_expr (co->expr1, list, 1);
4683 :
4684 12 : list[0] = var_2;
4685 12 : list[1] = var_1;
4686 12 : ascalar = scalarized_expr (matrix_a, list, 2);
4687 :
4688 12 : list[0] = var_2;
4689 12 : bscalar = scalarized_expr (matrix_b, list, 1);
4690 :
4691 12 : break;
4692 :
4693 107 : case A1B2:
4694 107 : u1 = get_size_m1 (matrix_b, 2);
4695 107 : u2 = get_size_m1 (matrix_a, 1);
4696 :
4697 107 : do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4698 107 : do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4699 :
4700 107 : do_1->block->next = do_2;
4701 107 : do_2->block->next = assign_matmul;
4702 :
4703 107 : var_1 = do_1->ext.iterator->var;
4704 107 : var_2 = do_2->ext.iterator->var;
4705 :
4706 107 : list[0] = var_1;
4707 107 : cscalar = scalarized_expr (co->expr1, list, 1);
4708 :
4709 107 : list[0] = var_2;
4710 107 : ascalar = scalarized_expr (matrix_a, list, 1);
4711 :
4712 107 : list[0] = var_2;
4713 107 : list[1] = var_1;
4714 107 : bscalar = scalarized_expr (matrix_b, list, 2);
4715 :
4716 107 : break;
4717 :
4718 : default:
4719 : gcc_unreachable();
4720 : }
4721 :
4722 : /* Build the conjg call around the variables. Set the typespec manually
4723 : because gfc_build_intrinsic_call sometimes gets this wrong. */
4724 685 : if (conjg_a)
4725 : {
4726 16 : gfc_typespec ts;
4727 16 : ts = matrix_a->ts;
4728 16 : ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4729 : matrix_a->where, 1, ascalar);
4730 16 : ascalar->ts = ts;
4731 : }
4732 :
4733 685 : if (conjg_b)
4734 : {
4735 8 : gfc_typespec ts;
4736 8 : ts = matrix_b->ts;
4737 8 : bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4738 : matrix_b->where, 1, bscalar);
4739 8 : bscalar->ts = ts;
4740 : }
4741 : /* First loop comes after the zero assignment. */
4742 685 : assign_zero->next = do_1;
4743 :
4744 : /* Build the assignment expression in the loop. */
4745 685 : assign_matmul->expr1 = gfc_copy_expr (cscalar);
4746 :
4747 685 : mult = get_operand (op_times, ascalar, bscalar);
4748 685 : assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
4749 :
4750 : /* If we don't want to keep the original statement around in
4751 : the else branch, we can free it. */
4752 :
4753 685 : if (if_limit == NULL)
4754 132 : gfc_free_statements(co);
4755 : else
4756 553 : co->next = NULL;
4757 :
4758 685 : gfc_free_expr (zero);
4759 685 : *walk_subtrees = 0;
4760 685 : return 0;
4761 : }
4762 :
4763 : /* Change matmul function calls in the form of
4764 :
4765 : c = matmul(a,b)
4766 :
4767 : to the corresponding call to a BLAS routine, if applicable. */
4768 :
4769 : static int
4770 2806 : call_external_blas (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
4771 : void *data ATTRIBUTE_UNUSED)
4772 : {
4773 2806 : gfc_code *co, *co_next;
4774 2806 : gfc_expr *expr1, *expr2;
4775 2806 : gfc_expr *matrix_a, *matrix_b;
4776 2806 : gfc_code *if_limit = NULL;
4777 2806 : gfc_actual_arglist *a, *b;
4778 2806 : bool conjg_a, conjg_b, transpose_a, transpose_b;
4779 2806 : gfc_code *call;
4780 2806 : const char *blas_name;
4781 2806 : const char *transa, *transb;
4782 2806 : gfc_expr *c1, *c2, *b1;
4783 2806 : gfc_actual_arglist *actual, *next;
4784 2806 : bt type;
4785 2806 : int kind;
4786 2806 : enum matrix_case m_case;
4787 2806 : bool realloc_c;
4788 2806 : gfc_code **next_code_point;
4789 2806 : int arg_kind;
4790 :
4791 : /* Many of the tests for inline matmul also apply here. */
4792 :
4793 2806 : co = *c;
4794 :
4795 2806 : if (co->op != EXEC_ASSIGN)
4796 : return 0;
4797 :
4798 910 : if (in_where || in_assoc_list)
4799 : return 0;
4800 :
4801 : /* The BLOCKS generated for the temporary variables and FORALL don't
4802 : mix. */
4803 910 : if (forall_level > 0)
4804 : return 0;
4805 :
4806 : /* For now don't do anything in OpenMP workshare, it confuses
4807 : its translation, which expects only the allowed statements in there. */
4808 :
4809 910 : if (in_omp_workshare || in_omp_atomic)
4810 : return 0;
4811 :
4812 910 : expr1 = co->expr1;
4813 910 : expr2 = co->expr2;
4814 910 : if (expr2->expr_type != EXPR_FUNCTION
4815 156 : || expr2->value.function.isym == NULL
4816 108 : || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
4817 : return 0;
4818 :
4819 76 : type = expr2->ts.type;
4820 76 : kind = expr2->ts.kind;
4821 :
4822 : /* Guard against recursion. */
4823 :
4824 76 : if (expr2->external_blas)
4825 : return 0;
4826 :
4827 38 : if (type != expr1->ts.type || kind != expr1->ts.kind)
4828 : return 0;
4829 :
4830 38 : if (type == BT_REAL)
4831 : {
4832 18 : if (kind == 4)
4833 : blas_name = "sgemm";
4834 7 : else if (kind == 8)
4835 : blas_name = "dgemm";
4836 : else
4837 : return 0;
4838 : }
4839 20 : else if (type == BT_COMPLEX)
4840 : {
4841 20 : if (kind == 4)
4842 : blas_name = "cgemm";
4843 10 : else if (kind == 8)
4844 : blas_name = "zgemm";
4845 : else
4846 : return 0;
4847 : }
4848 : else
4849 : return 0;
4850 :
4851 38 : a = expr2->value.function.actual;
4852 38 : if (a->expr->rank != 2)
4853 : return 0;
4854 :
4855 38 : b = a->next;
4856 38 : if (b->expr->rank != 2)
4857 : return 0;
4858 :
4859 38 : matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
4860 38 : if (matrix_a == NULL)
4861 : return 0;
4862 :
4863 38 : if (transpose_a)
4864 : {
4865 13 : if (conjg_a)
4866 : transa = "C";
4867 : else
4868 9 : transa = "T";
4869 : }
4870 : else
4871 : transa = "N";
4872 :
4873 38 : matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
4874 38 : if (matrix_b == NULL)
4875 : return 0;
4876 :
4877 38 : if (transpose_b)
4878 : {
4879 12 : if (conjg_b)
4880 : transb = "C";
4881 : else
4882 8 : transb = "T";
4883 : }
4884 : else
4885 : transb = "N";
4886 :
4887 38 : if (transpose_a)
4888 : {
4889 13 : if (transpose_b)
4890 : m_case = A2TB2T;
4891 : else
4892 13 : m_case = A2TB2;
4893 : }
4894 : else
4895 : {
4896 25 : if (transpose_b)
4897 : m_case = A2B2T;
4898 : else
4899 13 : m_case = A2B2;
4900 : }
4901 :
4902 38 : current_code = c;
4903 38 : inserted_block = NULL;
4904 38 : changed_statement = NULL;
4905 :
4906 38 : expr2->external_blas = 1;
4907 :
4908 : /* We do not handle data dependencies yet. */
4909 38 : if (gfc_check_dependency (expr1, matrix_a, true)
4910 38 : || gfc_check_dependency (expr1, matrix_b, true))
4911 : return 0;
4912 :
4913 : /* Generate the if statement and hang it into the tree. */
4914 38 : if_limit = inline_limit_check (matrix_a, matrix_b, flag_blas_matmul_limit, 2);
4915 38 : co_next = co->next;
4916 38 : (*current_code) = if_limit;
4917 38 : co->next = NULL;
4918 38 : if_limit->block->next = co;
4919 :
4920 38 : call = XCNEW (gfc_code);
4921 38 : call->loc = co->loc;
4922 :
4923 : /* Bounds checking - a bit simpler than for inlining since we only
4924 : have to take care of two-dimensional arrays here. */
4925 :
4926 38 : realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
4927 38 : next_code_point = &(if_limit->block->block->next);
4928 :
4929 38 : if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4930 : {
4931 35 : gfc_code *test;
4932 : // gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
4933 35 : gfc_expr *c1, *a1, *c2, *b2, *a2;
4934 35 : switch (m_case)
4935 : {
4936 10 : case A2B2:
4937 10 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4938 10 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4939 10 : test = runtime_error_ne (b1, a2, B_ERROR_1);
4940 10 : *next_code_point = test;
4941 10 : next_code_point = &test->next;
4942 :
4943 10 : if (!realloc_c)
4944 : {
4945 5 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4946 5 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4947 5 : test = runtime_error_ne (c1, a1, C_ERROR_1);
4948 5 : *next_code_point = test;
4949 5 : next_code_point = &test->next;
4950 :
4951 5 : c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4952 5 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4953 5 : test = runtime_error_ne (c2, b2, C_ERROR_2);
4954 5 : *next_code_point = test;
4955 5 : next_code_point = &test->next;
4956 : }
4957 : break;
4958 :
4959 12 : case A2B2T:
4960 :
4961 12 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4962 12 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4963 : /* matrix_b is transposed, hence dimension 1 for the error message. */
4964 12 : test = runtime_error_ne (b2, a2, B_ERROR_1);
4965 12 : *next_code_point = test;
4966 12 : next_code_point = &test->next;
4967 :
4968 12 : if (!realloc_c)
4969 : {
4970 12 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4971 12 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4972 12 : test = runtime_error_ne (c1, a1, C_ERROR_1);
4973 12 : *next_code_point = test;
4974 12 : next_code_point = &test->next;
4975 :
4976 12 : c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4977 12 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4978 12 : test = runtime_error_ne (c2, b1, C_ERROR_2);
4979 12 : *next_code_point = test;
4980 12 : next_code_point = &test->next;
4981 : }
4982 : break;
4983 :
4984 13 : case A2TB2:
4985 :
4986 13 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4987 13 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4988 13 : test = runtime_error_ne (b1, a1, B_ERROR_1);
4989 13 : *next_code_point = test;
4990 13 : next_code_point = &test->next;
4991 :
4992 13 : if (!realloc_c)
4993 : {
4994 12 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4995 12 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4996 12 : test = runtime_error_ne (c1, a2, C_ERROR_1);
4997 12 : *next_code_point = test;
4998 12 : next_code_point = &test->next;
4999 :
5000 12 : c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
5001 12 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
5002 12 : test = runtime_error_ne (c2, b2, C_ERROR_2);
5003 12 : *next_code_point = test;
5004 12 : next_code_point = &test->next;
5005 : }
5006 : break;
5007 :
5008 0 : case A2TB2T:
5009 0 : b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
5010 0 : a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
5011 0 : test = runtime_error_ne (b2, a1, B_ERROR_1);
5012 0 : *next_code_point = test;
5013 0 : next_code_point = &test->next;
5014 :
5015 0 : if (!realloc_c)
5016 : {
5017 0 : c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
5018 0 : a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
5019 0 : test = runtime_error_ne (c1, a2, C_ERROR_1);
5020 0 : *next_code_point = test;
5021 0 : next_code_point = &test->next;
5022 :
5023 0 : c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
5024 0 : b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
5025 0 : test = runtime_error_ne (c2, b1, C_ERROR_2);
5026 0 : *next_code_point = test;
5027 0 : next_code_point = &test->next;
5028 : }
5029 : break;
5030 :
5031 : default:
5032 : gcc_unreachable ();
5033 : }
5034 : }
5035 :
5036 : /* Handle the reallocation, if needed. */
5037 :
5038 32 : if (realloc_c)
5039 : {
5040 6 : gfc_code *lhs_alloc;
5041 :
5042 6 : lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
5043 6 : *next_code_point = lhs_alloc;
5044 6 : next_code_point = &lhs_alloc->next;
5045 : }
5046 :
5047 38 : *next_code_point = call;
5048 38 : if_limit->next = co_next;
5049 :
5050 : /* Set up the BLAS call. */
5051 :
5052 38 : call->op = EXEC_CALL;
5053 :
5054 38 : gfc_get_sym_tree (blas_name, current_ns, &(call->symtree), true);
5055 38 : call->symtree->n.sym->attr.subroutine = 1;
5056 38 : call->symtree->n.sym->attr.procedure = 1;
5057 38 : call->symtree->n.sym->attr.flavor = FL_PROCEDURE;
5058 38 : call->resolved_sym = call->symtree->n.sym;
5059 38 : gfc_commit_symbol (call->resolved_sym);
5060 :
5061 : /* Argument TRANSA. */
5062 38 : next = gfc_get_actual_arglist ();
5063 38 : next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
5064 : transa, 1);
5065 :
5066 38 : call->ext.actual = next;
5067 :
5068 : /* Argument TRANSB. */
5069 38 : actual = next;
5070 38 : next = gfc_get_actual_arglist ();
5071 38 : next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
5072 : transb, 1);
5073 38 : actual->next = next;
5074 :
5075 38 : if (flag_external_blas)
5076 : arg_kind = gfc_integer_4_kind;
5077 : else
5078 : {
5079 1 : gcc_assert (flag_external_blas64);
5080 : arg_kind = gfc_integer_8_kind;
5081 : }
5082 :
5083 38 : c1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (a->expr), 1,
5084 : arg_kind);
5085 38 : c2 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 2,
5086 : arg_kind);
5087 38 : b1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 1,
5088 : arg_kind);
5089 :
5090 : /* Argument M. */
5091 38 : actual = next;
5092 38 : next = gfc_get_actual_arglist ();
5093 38 : next->expr = c1;
5094 38 : actual->next = next;
5095 :
5096 : /* Argument N. */
5097 38 : actual = next;
5098 38 : next = gfc_get_actual_arglist ();
5099 38 : next->expr = c2;
5100 38 : actual->next = next;
5101 :
5102 : /* Argument K. */
5103 38 : actual = next;
5104 38 : next = gfc_get_actual_arglist ();
5105 38 : next->expr = b1;
5106 38 : actual->next = next;
5107 :
5108 : /* Argument ALPHA - set to one. */
5109 38 : actual = next;
5110 38 : next = gfc_get_actual_arglist ();
5111 38 : next->expr = gfc_get_constant_expr (type, kind, &co->loc);
5112 38 : if (type == BT_REAL)
5113 18 : mpfr_set_ui (next->expr->value.real, 1, GFC_RND_MODE);
5114 : else
5115 20 : mpc_set_ui (next->expr->value.complex, 1, GFC_MPC_RND_MODE);
5116 38 : actual->next = next;
5117 :
5118 : /* Argument A. */
5119 38 : actual = next;
5120 38 : next = gfc_get_actual_arglist ();
5121 38 : next->expr = gfc_copy_expr (matrix_a);
5122 38 : actual->next = next;
5123 :
5124 : /* Argument LDA. */
5125 38 : actual = next;
5126 38 : next = gfc_get_actual_arglist ();
5127 38 : next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_a),
5128 : 1, arg_kind);
5129 38 : actual->next = next;
5130 :
5131 : /* Argument B. */
5132 38 : actual = next;
5133 38 : next = gfc_get_actual_arglist ();
5134 38 : next->expr = gfc_copy_expr (matrix_b);
5135 38 : actual->next = next;
5136 :
5137 : /* Argument LDB. */
5138 38 : actual = next;
5139 38 : next = gfc_get_actual_arglist ();
5140 38 : next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_b),
5141 : 1, arg_kind);
5142 38 : actual->next = next;
5143 :
5144 : /* Argument BETA - set to zero. */
5145 38 : actual = next;
5146 38 : next = gfc_get_actual_arglist ();
5147 38 : next->expr = gfc_get_constant_expr (type, kind, &co->loc);
5148 38 : if (type == BT_REAL)
5149 18 : mpfr_set_ui (next->expr->value.real, 0, GFC_RND_MODE);
5150 : else
5151 20 : mpc_set_ui (next->expr->value.complex, 0, GFC_MPC_RND_MODE);
5152 38 : actual->next = next;
5153 :
5154 : /* Argument C. */
5155 :
5156 38 : actual = next;
5157 38 : next = gfc_get_actual_arglist ();
5158 38 : next->expr = gfc_copy_expr (expr1);
5159 38 : actual->next = next;
5160 :
5161 : /* Argument LDC. */
5162 38 : actual = next;
5163 38 : next = gfc_get_actual_arglist ();
5164 38 : next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (expr1),
5165 : 1, arg_kind);
5166 38 : actual->next = next;
5167 :
5168 38 : return 0;
5169 : }
5170 :
5171 :
5172 : /* Code for index interchange for loops which are grouped together in DO
5173 : CONCURRENT or FORALL statements. This is currently only applied if the
5174 : iterations are grouped together in a single statement.
5175 :
5176 : For this transformation, it is assumed that memory access in strides is
5177 : expensive, and that loops which access later indices (which access memory
5178 : in bigger strides) should be moved to the first loops.
5179 :
5180 : For this, a loop over all the statements is executed, counting the times
5181 : that the loop iteration values are accessed in each index. The loop
5182 : indices are then sorted to minimize access to later indices from inner
5183 : loops. */
5184 :
5185 : /* Type for holding index information. */
5186 :
5187 : typedef struct {
5188 : gfc_symbol *sym;
5189 : gfc_forall_iterator *fa;
5190 : int num;
5191 : int n[GFC_MAX_DIMENSIONS];
5192 : } ind_type;
5193 :
5194 : /* Callback function to determine if an expression is the
5195 : corresponding variable. */
5196 :
5197 : static int
5198 293806 : has_var (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
5199 : {
5200 293806 : gfc_expr *expr = *e;
5201 293806 : gfc_symbol *sym;
5202 :
5203 293806 : if (expr->expr_type != EXPR_VARIABLE)
5204 : return 0;
5205 :
5206 224934 : sym = (gfc_symbol *) data;
5207 224934 : return sym == expr->symtree->n.sym;
5208 : }
5209 :
5210 : /* Callback function to calculate the cost of a certain index. */
5211 :
5212 : static int
5213 1119092 : index_cost (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
5214 : void *data)
5215 : {
5216 1119092 : ind_type *ind;
5217 1119092 : gfc_expr *expr;
5218 1119092 : gfc_array_ref *ar;
5219 1119092 : gfc_ref *ref;
5220 1119092 : int i,j;
5221 :
5222 1119092 : expr = *e;
5223 1119092 : if (expr->expr_type != EXPR_VARIABLE)
5224 : return 0;
5225 :
5226 474408 : ar = NULL;
5227 501198 : for (ref = expr->ref; ref; ref = ref->next)
5228 : {
5229 86561 : if (ref->type == REF_ARRAY)
5230 : {
5231 59771 : ar = &ref->u.ar;
5232 59771 : break;
5233 : }
5234 : }
5235 59771 : if (ar == NULL || ar->type != AR_ELEMENT)
5236 : return 0;
5237 :
5238 : ind = (ind_type *) data;
5239 128311 : for (i = 0; i < ar->dimen; i++)
5240 : {
5241 324142 : for (j=0; ind[j].sym != NULL; j++)
5242 : {
5243 232546 : if (gfc_expr_walker (&ar->start[i], has_var, (void *) (ind[j].sym)))
5244 75654 : ind[j].n[i]++;
5245 : }
5246 : }
5247 : return 0;
5248 : }
5249 :
5250 : /* Callback function for qsort, to sort the loop indices. */
5251 :
5252 : static int
5253 13502 : loop_comp (const void *e1, const void *e2)
5254 : {
5255 13502 : const ind_type *i1 = (const ind_type *) e1;
5256 13502 : const ind_type *i2 = (const ind_type *) e2;
5257 13502 : int i;
5258 :
5259 179826 : for (i=GFC_MAX_DIMENSIONS-1; i >= 0; i--)
5260 : {
5261 179262 : if (i1->n[i] != i2->n[i])
5262 12938 : return i1->n[i] - i2->n[i];
5263 : }
5264 : /* All other things being equal, let's not change the ordering. */
5265 564 : return i2->num - i1->num;
5266 : }
5267 :
5268 : /* Main function to do the index interchange. */
5269 :
5270 : static int
5271 1060484 : index_interchange (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
5272 : void *data ATTRIBUTE_UNUSED)
5273 : {
5274 1060484 : gfc_code *co;
5275 1060484 : co = *c;
5276 1060484 : int n_iter;
5277 1060484 : gfc_forall_iterator *fa;
5278 1060484 : ind_type *ind;
5279 1060484 : int i, j;
5280 :
5281 1060484 : if (co->op != EXEC_FORALL && co->op != EXEC_DO_CONCURRENT)
5282 : return 0;
5283 :
5284 2558 : n_iter = 0;
5285 7686 : for (fa = co->ext.concur.forall_iterator; fa; fa = fa->next)
5286 5128 : n_iter ++;
5287 :
5288 : /* Nothing to reorder. */
5289 2558 : if (n_iter < 2)
5290 : return 0;
5291 :
5292 1672 : ind = XALLOCAVEC (ind_type, n_iter + 1);
5293 :
5294 1672 : i = 0;
5295 5914 : for (fa = co->ext.concur.forall_iterator; fa; fa = fa->next)
5296 : {
5297 4242 : ind[i].sym = fa->var->symtree->n.sym;
5298 4242 : ind[i].fa = fa;
5299 67872 : for (j=0; j<GFC_MAX_DIMENSIONS; j++)
5300 63630 : ind[i].n[j] = 0;
5301 4242 : ind[i].num = i;
5302 4242 : i++;
5303 : }
5304 1672 : ind[n_iter].sym = NULL;
5305 1672 : ind[n_iter].fa = NULL;
5306 :
5307 1672 : gfc_code_walker (c, gfc_dummy_code_callback, index_cost, (void *) ind);
5308 1672 : qsort ((void *) ind, n_iter, sizeof (ind_type), loop_comp);
5309 :
5310 : /* Do the actual index interchange. */
5311 1672 : co->ext.concur.forall_iterator = fa = ind[0].fa;
5312 4242 : for (i=1; i<n_iter; i++)
5313 : {
5314 2570 : fa->next = ind[i].fa;
5315 2570 : fa = fa->next;
5316 : }
5317 1672 : fa->next = NULL;
5318 :
5319 1672 : if (flag_warn_frontend_loop_interchange)
5320 : {
5321 1 : for (i=1; i<n_iter; i++)
5322 : {
5323 1 : if (ind[i-1].num > ind[i].num)
5324 : {
5325 1 : gfc_warning (OPT_Wfrontend_loop_interchange,
5326 : "Interchanging loops at %L", &co->loc);
5327 1 : break;
5328 : }
5329 : }
5330 : }
5331 :
5332 : return 0;
5333 : }
5334 :
5335 : #define WALK_SUBEXPR(NODE) \
5336 : do \
5337 : { \
5338 : result = gfc_expr_walker (&(NODE), exprfn, data); \
5339 : if (result) \
5340 : return result; \
5341 : } \
5342 : while (0)
5343 : #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
5344 :
5345 : /* Walk expression *E, calling EXPRFN on each expression in it. */
5346 :
5347 : int
5348 111299115 : gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
5349 : {
5350 115536496 : while (*e)
5351 : {
5352 41629500 : int walk_subtrees = 1;
5353 41629500 : gfc_actual_arglist *a;
5354 41629500 : gfc_ref *r;
5355 41629500 : gfc_constructor *c;
5356 :
5357 41629500 : int result = exprfn (e, &walk_subtrees, data);
5358 41629500 : if (result)
5359 37392119 : return result;
5360 41553452 : if (walk_subtrees)
5361 29706929 : switch ((*e)->expr_type)
5362 : {
5363 4250008 : case EXPR_OP:
5364 4250008 : WALK_SUBEXPR ((*e)->value.op.op1);
5365 4237381 : WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
5366 : /* No fallthru because of the tail recursion above. */
5367 2228464 : case EXPR_FUNCTION:
5368 6507505 : for (a = (*e)->value.function.actual; a; a = a->next)
5369 4279162 : WALK_SUBEXPR (a->expr);
5370 : break;
5371 1279 : case EXPR_CONDITIONAL:
5372 1279 : WALK_SUBEXPR ((*e)->value.conditional.condition);
5373 1278 : WALK_SUBEXPR ((*e)->value.conditional.true_expr);
5374 1277 : WALK_SUBEXPR ((*e)->value.conditional.false_expr);
5375 : break;
5376 75 : case EXPR_COMPCALL:
5377 75 : case EXPR_PPC:
5378 75 : WALK_SUBEXPR ((*e)->value.compcall.base_object);
5379 89 : for (a = (*e)->value.compcall.actual; a; a = a->next)
5380 14 : WALK_SUBEXPR (a->expr);
5381 : break;
5382 :
5383 397764 : case EXPR_ARRAY:
5384 397764 : if ((*e)->ts.type == BT_CHARACTER)
5385 64137 : WALK_SUBEXPR ((*e)->ts.u.cl->length);
5386 :
5387 517165 : gcc_fallthrough ();
5388 :
5389 517165 : case EXPR_STRUCTURE:
5390 :
5391 3407671 : for (c = gfc_constructor_first ((*e)->value.constructor); c;
5392 2890506 : c = gfc_constructor_next (c))
5393 : {
5394 2890506 : if (c->iterator == NULL)
5395 2879284 : WALK_SUBEXPR (c->expr);
5396 : else
5397 : {
5398 11222 : iterator_level ++;
5399 11222 : WALK_SUBEXPR (c->expr);
5400 11222 : iterator_level --;
5401 11222 : WALK_SUBEXPR (c->iterator->var);
5402 11222 : WALK_SUBEXPR (c->iterator->start);
5403 11222 : WALK_SUBEXPR (c->iterator->end);
5404 2890506 : WALK_SUBEXPR (c->iterator->step);
5405 : }
5406 : }
5407 :
5408 517165 : if ((*e)->expr_type != EXPR_ARRAY)
5409 : break;
5410 :
5411 : /* Fall through to the variable case in order to walk the
5412 : reference. */
5413 11297351 : gcc_fallthrough ();
5414 :
5415 11297351 : case EXPR_SUBSTRING:
5416 11297351 : case EXPR_VARIABLE:
5417 15291988 : for (r = (*e)->ref; r; r = r->next)
5418 : {
5419 3994668 : gfc_array_ref *ar;
5420 3994668 : int i;
5421 :
5422 3994668 : switch (r->type)
5423 : {
5424 3203595 : case REF_ARRAY:
5425 3203595 : ar = &r->u.ar;
5426 3203595 : if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
5427 : {
5428 3087312 : for (i=0; i< ar->dimen; i++)
5429 : {
5430 1736414 : WALK_SUBEXPR (ar->start[i]);
5431 1736383 : WALK_SUBEXPR (ar->end[i]);
5432 1736383 : WALK_SUBEXPR (ar->stride[i]);
5433 : }
5434 : }
5435 :
5436 : break;
5437 :
5438 88692 : case REF_SUBSTRING:
5439 88692 : WALK_SUBEXPR (r->u.ss.start);
5440 88692 : WALK_SUBEXPR (r->u.ss.end);
5441 : break;
5442 :
5443 : case REF_COMPONENT:
5444 : case REF_INQUIRY:
5445 : break;
5446 : }
5447 : }
5448 :
5449 : default:
5450 : break;
5451 4237381 : }
5452 : return 0;
5453 : }
5454 : return 0;
5455 : }
5456 :
5457 : #define WALK_SUBCODE(NODE) \
5458 : do \
5459 : { \
5460 : result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
5461 : if (result) \
5462 : return result; \
5463 : } \
5464 : while (0)
5465 :
5466 : /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
5467 : on each expression in it. If any of the hooks returns non-zero, that
5468 : value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
5469 : no subcodes or subexpressions are traversed. */
5470 :
5471 : int
5472 9137678 : gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
5473 : void *data)
5474 : {
5475 24821773 : for (; *c; c = &(*c)->next)
5476 : {
5477 15684560 : int walk_subtrees = 1;
5478 15684560 : int result = codefn (c, &walk_subtrees, data);
5479 15684560 : if (result)
5480 465 : return result;
5481 :
5482 15684196 : if (walk_subtrees)
5483 : {
5484 15654215 : gfc_code *b;
5485 15654215 : gfc_actual_arglist *a;
5486 15654215 : gfc_code *co;
5487 15654215 : gfc_association_list *alist;
5488 15654215 : bool saved_in_omp_workshare;
5489 15654215 : bool saved_in_omp_atomic;
5490 15654215 : bool saved_in_where;
5491 :
5492 : /* There might be statement insertions before the current code,
5493 : which must not affect the expression walker. */
5494 :
5495 15654215 : co = *c;
5496 15654215 : saved_in_omp_workshare = in_omp_workshare;
5497 15654215 : saved_in_omp_atomic = in_omp_atomic;
5498 15654215 : saved_in_where = in_where;
5499 :
5500 15654215 : switch (co->op)
5501 : {
5502 :
5503 159305 : case EXEC_BLOCK:
5504 159305 : case EXEC_CHANGE_TEAM:
5505 159305 : WALK_SUBCODE (co->ext.block.ns->code);
5506 159299 : if (co->ext.block.assoc)
5507 : {
5508 81322 : bool saved_in_assoc_list = in_assoc_list;
5509 :
5510 81322 : in_assoc_list = true;
5511 164739 : for (alist = co->ext.block.assoc; alist; alist = alist->next)
5512 83417 : WALK_SUBEXPR (alist->target);
5513 :
5514 81322 : in_assoc_list = saved_in_assoc_list;
5515 : }
5516 :
5517 : break;
5518 :
5519 540071 : case EXEC_DO:
5520 540071 : doloop_level ++;
5521 540071 : WALK_SUBEXPR (co->ext.iterator->var);
5522 540071 : WALK_SUBEXPR (co->ext.iterator->start);
5523 540071 : WALK_SUBEXPR (co->ext.iterator->end);
5524 540070 : WALK_SUBEXPR (co->ext.iterator->step);
5525 : break;
5526 :
5527 3195949 : case EXEC_IF:
5528 3195949 : if_level ++;
5529 3195949 : break;
5530 :
5531 5479 : case EXEC_WHERE:
5532 5479 : in_where = true;
5533 5479 : break;
5534 :
5535 1128088 : case EXEC_CALL:
5536 1128088 : case EXEC_ASSIGN_CALL:
5537 3636351 : for (a = co->ext.actual; a; a = a->next)
5538 2508263 : WALK_SUBEXPR (a->expr);
5539 : break;
5540 :
5541 1459 : case EXEC_CALL_PPC:
5542 1459 : WALK_SUBEXPR (co->expr1);
5543 3454 : for (a = co->ext.actual; a; a = a->next)
5544 1995 : WALK_SUBEXPR (a->expr);
5545 : break;
5546 :
5547 14599 : case EXEC_SELECT:
5548 14599 : WALK_SUBEXPR (co->expr1);
5549 14599 : select_level ++;
5550 44870 : for (b = co->block; b; b = b->block)
5551 : {
5552 30271 : gfc_case *cp;
5553 63020 : for (cp = b->ext.block.case_list; cp; cp = cp->next)
5554 : {
5555 32749 : WALK_SUBEXPR (cp->low);
5556 32749 : WALK_SUBEXPR (cp->high);
5557 : }
5558 30271 : WALK_SUBCODE (b->next);
5559 : }
5560 14599 : continue;
5561 :
5562 189674 : case EXEC_ALLOCATE:
5563 189674 : if (co->ext.alloc.ts.type == BT_CHARACTER)
5564 6344 : WALK_SUBEXPR (co->ext.alloc.ts.u.cl->length);
5565 :
5566 306148 : gcc_fallthrough();
5567 :
5568 306148 : case EXEC_DEALLOCATE:
5569 306148 : {
5570 306148 : gfc_alloc *a;
5571 680159 : for (a = co->ext.alloc.list; a; a = a->next)
5572 374011 : WALK_SUBEXPR (a->expr);
5573 : break;
5574 : }
5575 :
5576 50494 : case EXEC_FORALL:
5577 50494 : case EXEC_DO_CONCURRENT:
5578 50494 : {
5579 50494 : gfc_forall_iterator *fa;
5580 157633 : for (fa = co->ext.concur.forall_iterator; fa; fa = fa->next)
5581 : {
5582 107139 : WALK_SUBEXPR (fa->var);
5583 107139 : WALK_SUBEXPR (fa->start);
5584 107139 : WALK_SUBEXPR (fa->end);
5585 107139 : WALK_SUBEXPR (fa->stride);
5586 : }
5587 50494 : if (co->op == EXEC_FORALL)
5588 46486 : forall_level ++;
5589 : break;
5590 : }
5591 :
5592 45805 : case EXEC_OPEN:
5593 45805 : WALK_SUBEXPR (co->ext.open->unit);
5594 45805 : WALK_SUBEXPR (co->ext.open->file);
5595 45805 : WALK_SUBEXPR (co->ext.open->status);
5596 45805 : WALK_SUBEXPR (co->ext.open->access);
5597 45805 : WALK_SUBEXPR (co->ext.open->form);
5598 45805 : WALK_SUBEXPR (co->ext.open->recl);
5599 45805 : WALK_SUBEXPR (co->ext.open->blank);
5600 45805 : WALK_SUBEXPR (co->ext.open->position);
5601 45805 : WALK_SUBEXPR (co->ext.open->action);
5602 45805 : WALK_SUBEXPR (co->ext.open->delim);
5603 45805 : WALK_SUBEXPR (co->ext.open->pad);
5604 45805 : WALK_SUBEXPR (co->ext.open->iostat);
5605 45805 : WALK_SUBEXPR (co->ext.open->iomsg);
5606 45805 : WALK_SUBEXPR (co->ext.open->convert);
5607 45805 : WALK_SUBEXPR (co->ext.open->decimal);
5608 45805 : WALK_SUBEXPR (co->ext.open->encoding);
5609 45805 : WALK_SUBEXPR (co->ext.open->round);
5610 45805 : WALK_SUBEXPR (co->ext.open->sign);
5611 45805 : WALK_SUBEXPR (co->ext.open->asynchronous);
5612 45805 : WALK_SUBEXPR (co->ext.open->id);
5613 45805 : WALK_SUBEXPR (co->ext.open->newunit);
5614 45805 : WALK_SUBEXPR (co->ext.open->share);
5615 45805 : WALK_SUBEXPR (co->ext.open->cc);
5616 : break;
5617 :
5618 38514 : case EXEC_CLOSE:
5619 38514 : WALK_SUBEXPR (co->ext.close->unit);
5620 38514 : WALK_SUBEXPR (co->ext.close->status);
5621 38514 : WALK_SUBEXPR (co->ext.close->iostat);
5622 38514 : WALK_SUBEXPR (co->ext.close->iomsg);
5623 : break;
5624 :
5625 34837 : case EXEC_BACKSPACE:
5626 34837 : case EXEC_ENDFILE:
5627 34837 : case EXEC_REWIND:
5628 34837 : case EXEC_FLUSH:
5629 34837 : WALK_SUBEXPR (co->ext.filepos->unit);
5630 34837 : WALK_SUBEXPR (co->ext.filepos->iostat);
5631 34837 : WALK_SUBEXPR (co->ext.filepos->iomsg);
5632 : break;
5633 :
5634 9734 : case EXEC_INQUIRE:
5635 9734 : WALK_SUBEXPR (co->ext.inquire->unit);
5636 9734 : WALK_SUBEXPR (co->ext.inquire->file);
5637 9734 : WALK_SUBEXPR (co->ext.inquire->iomsg);
5638 9734 : WALK_SUBEXPR (co->ext.inquire->iostat);
5639 9734 : WALK_SUBEXPR (co->ext.inquire->exist);
5640 9734 : WALK_SUBEXPR (co->ext.inquire->opened);
5641 9734 : WALK_SUBEXPR (co->ext.inquire->number);
5642 9734 : WALK_SUBEXPR (co->ext.inquire->named);
5643 9734 : WALK_SUBEXPR (co->ext.inquire->name);
5644 9734 : WALK_SUBEXPR (co->ext.inquire->access);
5645 9734 : WALK_SUBEXPR (co->ext.inquire->sequential);
5646 9734 : WALK_SUBEXPR (co->ext.inquire->direct);
5647 9734 : WALK_SUBEXPR (co->ext.inquire->form);
5648 9734 : WALK_SUBEXPR (co->ext.inquire->formatted);
5649 9734 : WALK_SUBEXPR (co->ext.inquire->unformatted);
5650 9734 : WALK_SUBEXPR (co->ext.inquire->recl);
5651 9734 : WALK_SUBEXPR (co->ext.inquire->nextrec);
5652 9734 : WALK_SUBEXPR (co->ext.inquire->blank);
5653 9734 : WALK_SUBEXPR (co->ext.inquire->position);
5654 9734 : WALK_SUBEXPR (co->ext.inquire->action);
5655 9734 : WALK_SUBEXPR (co->ext.inquire->read);
5656 9734 : WALK_SUBEXPR (co->ext.inquire->write);
5657 9734 : WALK_SUBEXPR (co->ext.inquire->readwrite);
5658 9734 : WALK_SUBEXPR (co->ext.inquire->delim);
5659 9734 : WALK_SUBEXPR (co->ext.inquire->encoding);
5660 9734 : WALK_SUBEXPR (co->ext.inquire->pad);
5661 9734 : WALK_SUBEXPR (co->ext.inquire->iolength);
5662 9734 : WALK_SUBEXPR (co->ext.inquire->convert);
5663 9734 : WALK_SUBEXPR (co->ext.inquire->strm_pos);
5664 9734 : WALK_SUBEXPR (co->ext.inquire->asynchronous);
5665 9734 : WALK_SUBEXPR (co->ext.inquire->decimal);
5666 9734 : WALK_SUBEXPR (co->ext.inquire->pending);
5667 9734 : WALK_SUBEXPR (co->ext.inquire->id);
5668 9734 : WALK_SUBEXPR (co->ext.inquire->sign);
5669 9734 : WALK_SUBEXPR (co->ext.inquire->size);
5670 9734 : WALK_SUBEXPR (co->ext.inquire->round);
5671 : break;
5672 :
5673 961 : case EXEC_WAIT:
5674 961 : WALK_SUBEXPR (co->ext.wait->unit);
5675 961 : WALK_SUBEXPR (co->ext.wait->iostat);
5676 961 : WALK_SUBEXPR (co->ext.wait->iomsg);
5677 961 : WALK_SUBEXPR (co->ext.wait->id);
5678 : break;
5679 :
5680 387286 : case EXEC_READ:
5681 387286 : case EXEC_WRITE:
5682 387286 : WALK_SUBEXPR (co->ext.dt->io_unit);
5683 387286 : WALK_SUBEXPR (co->ext.dt->format_expr);
5684 387286 : WALK_SUBEXPR (co->ext.dt->rec);
5685 387286 : WALK_SUBEXPR (co->ext.dt->advance);
5686 387286 : WALK_SUBEXPR (co->ext.dt->iostat);
5687 387286 : WALK_SUBEXPR (co->ext.dt->size);
5688 387286 : WALK_SUBEXPR (co->ext.dt->iomsg);
5689 387286 : WALK_SUBEXPR (co->ext.dt->id);
5690 387286 : WALK_SUBEXPR (co->ext.dt->pos);
5691 387286 : WALK_SUBEXPR (co->ext.dt->asynchronous);
5692 387286 : WALK_SUBEXPR (co->ext.dt->blank);
5693 387286 : WALK_SUBEXPR (co->ext.dt->decimal);
5694 387286 : WALK_SUBEXPR (co->ext.dt->delim);
5695 387286 : WALK_SUBEXPR (co->ext.dt->pad);
5696 387286 : WALK_SUBEXPR (co->ext.dt->round);
5697 387286 : WALK_SUBEXPR (co->ext.dt->sign);
5698 387286 : WALK_SUBEXPR (co->ext.dt->extra_comma);
5699 : break;
5700 :
5701 34002 : case EXEC_OACC_ATOMIC:
5702 34002 : case EXEC_OMP_ATOMIC:
5703 34002 : in_omp_atomic = true;
5704 34002 : break;
5705 :
5706 44630 : case EXEC_OMP_PARALLEL:
5707 44630 : case EXEC_OMP_PARALLEL_DO:
5708 44630 : case EXEC_OMP_PARALLEL_DO_SIMD:
5709 44630 : case EXEC_OMP_PARALLEL_LOOP:
5710 44630 : case EXEC_OMP_PARALLEL_MASKED:
5711 44630 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
5712 44630 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
5713 44630 : case EXEC_OMP_PARALLEL_MASTER:
5714 44630 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
5715 44630 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
5716 44630 : case EXEC_OMP_PARALLEL_SECTIONS:
5717 :
5718 44630 : in_omp_workshare = false;
5719 :
5720 : /* This goto serves as a shortcut to avoid code
5721 : duplication or a larger if or switch statement. */
5722 44630 : goto check_omp_clauses;
5723 :
5724 1139 : case EXEC_OMP_WORKSHARE:
5725 1139 : case EXEC_OMP_PARALLEL_WORKSHARE:
5726 :
5727 1139 : in_omp_workshare = true;
5728 :
5729 : /* Fall through */
5730 :
5731 193994 : case EXEC_OMP_CRITICAL:
5732 193994 : case EXEC_OMP_DISTRIBUTE:
5733 193994 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5734 193994 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5735 193994 : case EXEC_OMP_DISTRIBUTE_SIMD:
5736 193994 : case EXEC_OMP_DO:
5737 193994 : case EXEC_OMP_DO_SIMD:
5738 193994 : case EXEC_OMP_LOOP:
5739 193994 : case EXEC_OMP_ORDERED:
5740 193994 : case EXEC_OMP_SECTIONS:
5741 193994 : case EXEC_OMP_SINGLE:
5742 193994 : case EXEC_OMP_END_SINGLE:
5743 193994 : case EXEC_OMP_SIMD:
5744 193994 : case EXEC_OMP_TASKLOOP:
5745 193994 : case EXEC_OMP_TASKLOOP_SIMD:
5746 193994 : case EXEC_OMP_TARGET:
5747 193994 : case EXEC_OMP_TARGET_DATA:
5748 193994 : case EXEC_OMP_TARGET_ENTER_DATA:
5749 193994 : case EXEC_OMP_TARGET_EXIT_DATA:
5750 193994 : case EXEC_OMP_TARGET_PARALLEL:
5751 193994 : case EXEC_OMP_TARGET_PARALLEL_DO:
5752 193994 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5753 193994 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
5754 193994 : case EXEC_OMP_TARGET_SIMD:
5755 193994 : case EXEC_OMP_TARGET_TEAMS:
5756 193994 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5757 193994 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5758 193994 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5759 193994 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5760 193994 : case EXEC_OMP_TARGET_TEAMS_LOOP:
5761 193994 : case EXEC_OMP_TARGET_UPDATE:
5762 193994 : case EXEC_OMP_TASK:
5763 193994 : case EXEC_OMP_TEAMS:
5764 193994 : case EXEC_OMP_TEAMS_DISTRIBUTE:
5765 193994 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5766 193994 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5767 193994 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5768 193994 : case EXEC_OMP_TEAMS_LOOP:
5769 :
5770 : /* Come to this label only from the
5771 : EXEC_OMP_PARALLEL_* cases above. */
5772 :
5773 193994 : check_omp_clauses:
5774 :
5775 193994 : if (co->ext.omp_clauses)
5776 : {
5777 193994 : gfc_omp_namelist *n;
5778 193994 : static int list_types[]
5779 : = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
5780 : OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
5781 193994 : size_t idx;
5782 193994 : WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
5783 2133934 : for (idx = 0; idx < OMP_IF_LAST; idx++)
5784 1939940 : WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
5785 193994 : WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
5786 193994 : WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
5787 193994 : WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
5788 193994 : WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
5789 193994 : WALK_SUBEXPR (co->ext.omp_clauses->device);
5790 193994 : WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
5791 193994 : WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
5792 193994 : WALK_SUBEXPR (co->ext.omp_clauses->hint);
5793 193994 : WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
5794 193994 : WALK_SUBEXPR (co->ext.omp_clauses->priority);
5795 193994 : WALK_SUBEXPR (co->ext.omp_clauses->detach);
5796 193994 : WALK_SUBEXPR (co->ext.omp_clauses->dyn_groupprivate);
5797 193994 : WALK_SUBEXPR (co->ext.omp_clauses->novariants);
5798 193994 : WALK_SUBEXPR (co->ext.omp_clauses->nocontext);
5799 193994 : gfc_expr_list *el = co->ext.omp_clauses->num_teams_list;
5800 196364 : for ( ; el; el = el->next)
5801 2370 : WALK_SUBEXPR (el->expr);
5802 193994 : el = co->ext.omp_clauses->thread_limit_list;
5803 195410 : for ( ; el; el = el->next)
5804 1416 : WALK_SUBEXPR (el->expr);
5805 193994 : el = co->ext.omp_clauses->num_threads_list;
5806 207113 : for ( ; el; el = el->next)
5807 13119 : WALK_SUBEXPR (el->expr);
5808 1357958 : for (idx = 0; idx < ARRAY_SIZE (list_types); idx++)
5809 1163964 : for (n = co->ext.omp_clauses->lists[list_types[idx]];
5810 1314223 : n; n = n->next)
5811 150259 : WALK_SUBEXPR (n->expr);
5812 : }
5813 : break;
5814 :
5815 4578 : case EXEC_OACC_INIT:
5816 4578 : case EXEC_OACC_SHUTDOWN:
5817 4578 : case EXEC_OACC_SET:
5818 4578 : if (co->ext.omp_clauses)
5819 4578 : WALK_SUBEXPR (co->ext.omp_clauses->device_num_expr);
5820 : break;
5821 :
5822 : default:
5823 : break;
5824 14599 : }
5825 :
5826 15639609 : WALK_SUBEXPR (co->expr1);
5827 15639597 : WALK_SUBEXPR (co->expr2);
5828 15639556 : WALK_SUBEXPR (co->expr3);
5829 15639549 : WALK_SUBEXPR (co->expr4);
5830 20335605 : for (b = co->block; b; b = b->block)
5831 : {
5832 4696090 : WALK_SUBEXPR (b->expr1);
5833 4696090 : WALK_SUBEXPR (b->expr2);
5834 4696090 : WALK_SUBCODE (b->next);
5835 : }
5836 :
5837 15639515 : if (co->op == EXEC_FORALL)
5838 46486 : forall_level --;
5839 :
5840 15639515 : if (co->op == EXEC_DO)
5841 540070 : doloop_level --;
5842 :
5843 15639515 : if (co->op == EXEC_IF)
5844 3195915 : if_level --;
5845 :
5846 15639515 : if (co->op == EXEC_SELECT)
5847 0 : select_level --;
5848 :
5849 15639515 : in_omp_workshare = saved_in_omp_workshare;
5850 15639515 : in_omp_atomic = saved_in_omp_atomic;
5851 15639515 : in_where = saved_in_where;
5852 : }
5853 : }
5854 : return 0;
5855 : }
5856 :
5857 : /* As a post-resolution step, check that all global symbols which are
5858 : not declared in the source file match in their call signatures.
5859 : We do this by looping over the code (and expressions). The first call
5860 : we happen to find is assumed to be canonical. */
5861 :
5862 :
5863 : /* Common tests for argument checking for both functions and subroutines. */
5864 :
5865 : static int
5866 134676 : check_externals_procedure (gfc_symbol *sym, locus *loc,
5867 : gfc_actual_arglist *actual)
5868 : {
5869 134676 : gfc_gsymbol *gsym;
5870 134676 : gfc_symbol *def_sym = NULL;
5871 :
5872 134676 : if (sym == NULL || sym->attr.is_bind_c)
5873 : return 0;
5874 :
5875 127549 : if (sym->attr.proc != PROC_EXTERNAL && sym->attr.proc != PROC_UNKNOWN)
5876 : return 0;
5877 :
5878 26198 : if (sym->attr.if_source == IFSRC_IFBODY || sym->attr.if_source == IFSRC_DECL)
5879 : return 0;
5880 :
5881 16540 : gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name);
5882 16540 : if (gsym == NULL)
5883 : return 0;
5884 :
5885 15734 : if (gsym->ns)
5886 14540 : gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
5887 :
5888 15734 : if (gsym->bind_c && def_sym && def_sym->binding_label == NULL)
5889 : return 0;
5890 :
5891 15733 : if (def_sym)
5892 : {
5893 14539 : gfc_compare_actual_formal (&actual, def_sym->formal, 0, 0, 0, loc);
5894 14539 : return 0;
5895 : }
5896 :
5897 : /* First time we have seen this procedure called. Let's create an
5898 : "interface" from the call and put it into a new namespace. */
5899 1194 : gfc_namespace *save_ns;
5900 1194 : gfc_symbol *new_sym;
5901 :
5902 1194 : gsym->where = *loc;
5903 1194 : save_ns = gfc_current_ns;
5904 1194 : gsym->ns = gfc_get_namespace (gfc_current_ns, 0);
5905 1194 : gsym->ns->proc_name = sym;
5906 :
5907 1194 : gfc_get_symbol (sym->name, gsym->ns, &new_sym);
5908 1194 : gcc_assert (new_sym);
5909 1194 : new_sym->attr = sym->attr;
5910 1194 : new_sym->attr.if_source = IFSRC_DECL;
5911 1194 : new_sym->ts = sym->ts;
5912 1194 : gfc_current_ns = gsym->ns;
5913 :
5914 1194 : gfc_get_formal_from_actual_arglist (new_sym, actual);
5915 1194 : new_sym->declared_at = *loc;
5916 1194 : gfc_current_ns = save_ns;
5917 :
5918 1194 : return 0;
5919 :
5920 : }
5921 :
5922 : /* Callback for calls of external routines. */
5923 :
5924 : static int
5925 1221299 : check_externals_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
5926 : void *data ATTRIBUTE_UNUSED)
5927 : {
5928 1221299 : gfc_code *co = *c;
5929 1221299 : gfc_symbol *sym;
5930 1221299 : locus *loc;
5931 1221299 : gfc_actual_arglist *actual;
5932 :
5933 1221299 : if (co->op != EXEC_CALL)
5934 : return 0;
5935 :
5936 86478 : sym = co->resolved_sym;
5937 86478 : loc = &co->loc;
5938 86478 : actual = co->ext.actual;
5939 :
5940 86478 : return check_externals_procedure (sym, loc, actual);
5941 :
5942 : }
5943 :
5944 : /* Callback for external functions. */
5945 :
5946 : static int
5947 3722333 : check_externals_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
5948 : void *data ATTRIBUTE_UNUSED)
5949 : {
5950 3722333 : gfc_expr *e = *ep;
5951 3722333 : gfc_symbol *sym;
5952 3722333 : locus *loc;
5953 3722333 : gfc_actual_arglist *actual;
5954 :
5955 3722333 : if (e->expr_type != EXPR_FUNCTION)
5956 : return 0;
5957 :
5958 295411 : if (e->symtree && e->symtree->n.sym->attr.subroutine)
5959 : return 0;
5960 :
5961 294166 : sym = e->value.function.esym;
5962 294166 : if (sym == NULL)
5963 : return 0;
5964 :
5965 48198 : loc = &e->where;
5966 48198 : actual = e->value.function.actual;
5967 :
5968 48198 : return check_externals_procedure (sym, loc, actual);
5969 : }
5970 :
5971 : /* Function to check if any interface clashes with a global
5972 : identifier, to be invoked via gfc_traverse_ns. */
5973 :
5974 : static void
5975 915276 : check_against_globals (gfc_symbol *sym)
5976 : {
5977 915276 : gfc_gsymbol *gsym;
5978 915276 : gfc_symbol *def_sym = NULL;
5979 915276 : const char *sym_name;
5980 915276 : char buf [200];
5981 :
5982 915276 : if (sym->attr.if_source != IFSRC_IFBODY || sym->attr.flavor != FL_PROCEDURE
5983 171171 : || sym->attr.generic || sym->error || sym->attr.abstract
5984 156520 : || sym->attr.dummy)
5985 885920 : return;
5986 :
5987 156471 : if (sym->error)
5988 : return;
5989 :
5990 156471 : if (sym->binding_label)
5991 : sym_name = sym->binding_label;
5992 128993 : else if (sym->attr.use_rename
5993 39 : && sym->ns->use_stmts->rename
5994 39 : && sym->ns->use_stmts->rename->local_name[0] != '\0')
5995 6 : sym_name = sym->ns->use_stmts->rename->local_name;
5996 : else
5997 128987 : sym_name = sym->name;
5998 :
5999 156471 : gsym = gfc_find_gsymbol (gfc_gsym_root, sym_name);
6000 156471 : if (gsym && gsym->ns)
6001 29403 : gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
6002 :
6003 156471 : if (!def_sym || def_sym->error || def_sym->attr.generic)
6004 : return;
6005 :
6006 29356 : buf[0] = 0;
6007 29356 : gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1, buf, sizeof(buf),
6008 : NULL, NULL, NULL);
6009 29356 : if (buf[0] != 0)
6010 : {
6011 4 : gfc_warning (0, "%s between %L and %L", buf, &def_sym->declared_at,
6012 : &sym->declared_at);
6013 4 : sym->error = 1;
6014 4 : def_sym->error = 1;
6015 : }
6016 :
6017 : }
6018 :
6019 : /* Do the code-walkling part for gfc_check_externals. */
6020 :
6021 : static void
6022 103245 : gfc_check_externals0 (gfc_namespace *ns)
6023 : {
6024 103245 : gfc_code_walker (&ns->code, check_externals_code, check_externals_expr, NULL);
6025 :
6026 156830 : for (ns = ns->contained; ns; ns = ns->sibling)
6027 : {
6028 53585 : if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
6029 52446 : gfc_check_externals0 (ns);
6030 : }
6031 :
6032 103245 : }
6033 :
6034 : /* Called routine. */
6035 :
6036 : void
6037 50799 : gfc_check_externals (gfc_namespace *ns)
6038 : {
6039 50799 : gfc_clear_error ();
6040 :
6041 : /* Turn errors into warnings if the user indicated this. */
6042 :
6043 50799 : if (!pedantic && flag_allow_argument_mismatch)
6044 1037 : gfc_errors_to_warnings (true);
6045 :
6046 50799 : gfc_check_externals0 (ns);
6047 50799 : gfc_traverse_ns (ns, check_against_globals);
6048 :
6049 50799 : gfc_errors_to_warnings (false);
6050 50799 : }
6051 :
6052 : /* Callback function. If there is a call to a subroutine which is
6053 : neither pure nor implicit_pure, unset the implicit_pure flag for
6054 : the caller and return -1. */
6055 :
6056 : static int
6057 29343 : implicit_pure_call (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
6058 : void *sym_data)
6059 : {
6060 29343 : gfc_code *co = *c;
6061 29343 : gfc_symbol *caller_sym;
6062 29343 : symbol_attribute *a;
6063 :
6064 29343 : if (co->op != EXEC_CALL || co->resolved_sym == NULL)
6065 : return 0;
6066 :
6067 102 : a = &co->resolved_sym->attr;
6068 102 : if (a->intrinsic || a->pure || a->implicit_pure)
6069 : return 0;
6070 :
6071 67 : caller_sym = (gfc_symbol *) sym_data;
6072 67 : gfc_unset_implicit_pure (caller_sym);
6073 67 : return 1;
6074 : }
6075 :
6076 : /* Callback function. If there is a call to a function which is
6077 : neither pure nor implicit_pure, unset the implicit_pure flag for
6078 : the caller and return 1. */
6079 :
6080 : static int
6081 61849 : implicit_pure_expr (gfc_expr **e, int *walk ATTRIBUTE_UNUSED, void *sym_data)
6082 : {
6083 61849 : gfc_expr *expr = *e;
6084 61849 : gfc_symbol *caller_sym;
6085 61849 : gfc_symbol *sym;
6086 61849 : symbol_attribute *a;
6087 :
6088 61849 : if (expr->expr_type != EXPR_FUNCTION || expr->value.function.isym)
6089 : return 0;
6090 :
6091 420 : sym = expr->symtree->n.sym;
6092 420 : a = &sym->attr;
6093 420 : if (a->pure || a->implicit_pure)
6094 : return 0;
6095 :
6096 59 : caller_sym = (gfc_symbol *) sym_data;
6097 59 : gfc_unset_implicit_pure (caller_sym);
6098 59 : return 1;
6099 : }
6100 :
6101 : /* Go through all procedures in the namespace and unset the
6102 : implicit_pure attribute for any procedure that calls something not
6103 : pure or implicit pure. */
6104 :
6105 : bool
6106 144760 : gfc_fix_implicit_pure (gfc_namespace *ns)
6107 : {
6108 144760 : bool changed = false;
6109 144760 : gfc_symbol *proc = ns->proc_name;
6110 :
6111 144711 : if (proc && proc->attr.flavor == FL_PROCEDURE && proc->attr.implicit_pure
6112 11308 : && ns->code
6113 156050 : && gfc_code_walker (&ns->code, implicit_pure_call, implicit_pure_expr,
6114 : (void *) ns->proc_name))
6115 : changed = true;
6116 :
6117 228063 : for (ns = ns->contained; ns; ns = ns->sibling)
6118 : {
6119 83303 : if (gfc_fix_implicit_pure (ns))
6120 127 : changed = true;
6121 : }
6122 :
6123 144760 : return changed;
6124 : }
|