]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/fortran/frontend-passes.c
lang.opt: Add -Wdo-subscript.
[thirdparty/gcc.git] / gcc / fortran / frontend-passes.c
1 /* Pass manager for Fortran front end.
2 Copyright (C) 2010-2017 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 void optimize_minmaxloc (gfc_expr **);
40 static bool is_empty_string (gfc_expr *e);
41 static void doloop_warn (gfc_namespace *);
42 static int do_intent (gfc_expr **);
43 static int do_subscript (gfc_expr **);
44 static void optimize_reduction (gfc_namespace *);
45 static int callback_reduction (gfc_expr **, int *, void *);
46 static void realloc_strings (gfc_namespace *);
47 static gfc_expr *create_var (gfc_expr *, const char *vname=NULL);
48 static int matmul_to_var_expr (gfc_expr **, int *, void *);
49 static int matmul_to_var_code (gfc_code **, int *, void *);
50 static int inline_matmul_assign (gfc_code **, int *, void *);
51 static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
52 locus *, gfc_namespace *,
53 char *vname=NULL);
54 static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *,
55 bool *);
56 static bool has_dimen_vector_ref (gfc_expr *);
57 static int matmul_temp_args (gfc_code **, int *,void *data);
58
59 #ifdef CHECKING_P
60 static void check_locus (gfc_namespace *);
61 #endif
62
63 /* How deep we are inside an argument list. */
64
65 static int count_arglist;
66
67 /* Vector of gfc_expr ** we operate on. */
68
69 static vec<gfc_expr **> expr_array;
70
71 /* Pointer to the gfc_code we currently work on - to be able to insert
72 a block before the statement. */
73
74 static gfc_code **current_code;
75
76 /* Pointer to the block to be inserted, and the statement we are
77 changing within the block. */
78
79 static gfc_code *inserted_block, **changed_statement;
80
81 /* The namespace we are currently dealing with. */
82
83 static gfc_namespace *current_ns;
84
85 /* If we are within any forall loop. */
86
87 static int forall_level;
88
89 /* Keep track of whether we are within an OMP workshare. */
90
91 static bool in_omp_workshare;
92
93 /* Keep track of whether we are within a WHERE statement. */
94
95 static bool in_where;
96
97 /* Keep track of iterators for array constructors. */
98
99 static int iterator_level;
100
101 /* Keep track of DO loop levels. */
102
103 typedef struct {
104 gfc_code *c;
105 int branch_level;
106 bool seen_goto;
107 } do_t;
108
109 static vec<do_t> doloop_list;
110 static int doloop_level;
111
112 /* Keep track of if and select case levels. */
113
114 static int if_level;
115 static int select_level;
116
117 /* Vector of gfc_expr * to keep track of DO loops. */
118
119 struct my_struct *evec;
120
121 /* Keep track of association lists. */
122
123 static bool in_assoc_list;
124
125 /* Counter for temporary variables. */
126
127 static int var_num = 1;
128
129 /* What sort of matrix we are dealing with when inlining MATMUL. */
130
131 enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T, A2TB2 };
132
133 /* Keep track of the number of expressions we have inserted so far
134 using create_var. */
135
136 int n_vars;
137
138 /* Entry point - run all passes for a namespace. */
139
140 void
141 gfc_run_passes (gfc_namespace *ns)
142 {
143
144 /* Warn about dubious DO loops where the index might
145 change. */
146
147 doloop_level = 0;
148 if_level = 0;
149 select_level = 0;
150 doloop_warn (ns);
151 doloop_list.release ();
152 int w, e;
153
154 #ifdef CHECKING_P
155 check_locus (ns);
156 #endif
157
158 if (flag_frontend_optimize)
159 {
160 optimize_namespace (ns);
161 optimize_reduction (ns);
162 if (flag_dump_fortran_optimized)
163 gfc_dump_parse_tree (ns, stdout);
164
165 expr_array.release ();
166 }
167
168 gfc_get_errors (&w, &e);
169 if (e > 0)
170 return;
171
172 if (flag_realloc_lhs)
173 realloc_strings (ns);
174 }
175
176 #ifdef CHECKING_P
177
178 /* Callback function: Warn if there is no location information in a
179 statement. */
180
181 static int
182 check_locus_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
183 void *data ATTRIBUTE_UNUSED)
184 {
185 current_code = c;
186 if (c && *c && (((*c)->loc.nextc == NULL) || ((*c)->loc.lb == NULL)))
187 gfc_warning_internal (0, "No location in statement");
188
189 return 0;
190 }
191
192
193 /* Callback function: Warn if there is no location information in an
194 expression. */
195
196 static int
197 check_locus_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
198 void *data ATTRIBUTE_UNUSED)
199 {
200
201 if (e && *e && (((*e)->where.nextc == NULL || (*e)->where.lb == NULL)))
202 gfc_warning_internal (0, "No location in expression near %L",
203 &((*current_code)->loc));
204 return 0;
205 }
206
207 /* Run check for missing location information. */
208
209 static void
210 check_locus (gfc_namespace *ns)
211 {
212 gfc_code_walker (&ns->code, check_locus_code, check_locus_expr, NULL);
213
214 for (ns = ns->contained; ns; ns = ns->sibling)
215 {
216 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
217 check_locus (ns);
218 }
219 }
220
221 #endif
222
223 /* Callback for each gfc_code node invoked from check_realloc_strings.
224 For an allocatable LHS string which also appears as a variable on
225 the RHS, replace
226
227 a = a(x:y)
228
229 with
230
231 tmp = a(x:y)
232 a = tmp
233 */
234
235 static int
236 realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
237 void *data ATTRIBUTE_UNUSED)
238 {
239 gfc_expr *expr1, *expr2;
240 gfc_code *co = *c;
241 gfc_expr *n;
242 gfc_ref *ref;
243 bool found_substr;
244
245 if (co->op != EXEC_ASSIGN)
246 return 0;
247
248 expr1 = co->expr1;
249 if (expr1->ts.type != BT_CHARACTER || expr1->rank != 0
250 || !gfc_expr_attr(expr1).allocatable
251 || !expr1->ts.deferred)
252 return 0;
253
254 expr2 = gfc_discard_nops (co->expr2);
255
256 if (expr2->expr_type == EXPR_VARIABLE)
257 {
258 found_substr = false;
259 for (ref = expr2->ref; ref; ref = ref->next)
260 {
261 if (ref->type == REF_SUBSTRING)
262 {
263 found_substr = true;
264 break;
265 }
266 }
267 if (!found_substr)
268 return 0;
269 }
270 else if (expr2->expr_type != EXPR_OP
271 || expr2->value.op.op != INTRINSIC_CONCAT)
272 return 0;
273
274 if (!gfc_check_dependency (expr1, expr2, true))
275 return 0;
276
277 /* gfc_check_dependency doesn't always pick up identical expressions.
278 However, eliminating the above sends the compiler into an infinite
279 loop on valid expressions. Without this check, the gimplifier emits
280 an ICE for a = a, where a is deferred character length. */
281 if (!gfc_dep_compare_expr (expr1, expr2))
282 return 0;
283
284 current_code = c;
285 inserted_block = NULL;
286 changed_statement = NULL;
287 n = create_var (expr2, "realloc_string");
288 co->expr2 = n;
289 return 0;
290 }
291
292 /* Callback for each gfc_code node invoked through gfc_code_walker
293 from optimize_namespace. */
294
295 static int
296 optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
297 void *data ATTRIBUTE_UNUSED)
298 {
299
300 gfc_exec_op op;
301
302 op = (*c)->op;
303
304 if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL
305 || op == EXEC_CALL_PPC)
306 count_arglist = 1;
307 else
308 count_arglist = 0;
309
310 current_code = c;
311 inserted_block = NULL;
312 changed_statement = NULL;
313
314 if (op == EXEC_ASSIGN)
315 optimize_assignment (*c);
316 return 0;
317 }
318
319 /* Callback for each gfc_expr node invoked through gfc_code_walker
320 from optimize_namespace. */
321
322 static int
323 optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
324 void *data ATTRIBUTE_UNUSED)
325 {
326 bool function_expr;
327
328 if ((*e)->expr_type == EXPR_FUNCTION)
329 {
330 count_arglist ++;
331 function_expr = true;
332 }
333 else
334 function_expr = false;
335
336 if (optimize_trim (*e))
337 gfc_simplify_expr (*e, 0);
338
339 if (optimize_lexical_comparison (*e))
340 gfc_simplify_expr (*e, 0);
341
342 if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
343 gfc_simplify_expr (*e, 0);
344
345 if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym)
346 switch ((*e)->value.function.isym->id)
347 {
348 case GFC_ISYM_MINLOC:
349 case GFC_ISYM_MAXLOC:
350 optimize_minmaxloc (e);
351 break;
352 default:
353 break;
354 }
355
356 if (function_expr)
357 count_arglist --;
358
359 return 0;
360 }
361
362 /* Auxiliary function to handle the arguments to reduction intrnisics. If the
363 function is a scalar, just copy it; otherwise returns the new element, the
364 old one can be freed. */
365
366 static gfc_expr *
367 copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn)
368 {
369 gfc_expr *fcn, *e = c->expr;
370
371 fcn = gfc_copy_expr (e);
372 if (c->iterator)
373 {
374 gfc_constructor_base newbase;
375 gfc_expr *new_expr;
376 gfc_constructor *new_c;
377
378 newbase = NULL;
379 new_expr = gfc_get_expr ();
380 new_expr->expr_type = EXPR_ARRAY;
381 new_expr->ts = e->ts;
382 new_expr->where = e->where;
383 new_expr->rank = 1;
384 new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where));
385 new_c->iterator = c->iterator;
386 new_expr->value.constructor = newbase;
387 c->iterator = NULL;
388
389 fcn = new_expr;
390 }
391
392 if (fcn->rank != 0)
393 {
394 gfc_isym_id id = fn->value.function.isym->id;
395
396 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
397 fcn = gfc_build_intrinsic_call (current_ns, id,
398 fn->value.function.isym->name,
399 fn->where, 3, fcn, NULL, NULL);
400 else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL)
401 fcn = gfc_build_intrinsic_call (current_ns, id,
402 fn->value.function.isym->name,
403 fn->where, 2, fcn, NULL);
404 else
405 gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
406
407 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
408 }
409
410 return fcn;
411 }
412
413 /* Callback function for optimzation of reductions to scalars. Transform ANY
414 ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
415 correspondingly. Handly only the simple cases without MASK and DIM. */
416
417 static int
418 callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
419 void *data ATTRIBUTE_UNUSED)
420 {
421 gfc_expr *fn, *arg;
422 gfc_intrinsic_op op;
423 gfc_isym_id id;
424 gfc_actual_arglist *a;
425 gfc_actual_arglist *dim;
426 gfc_constructor *c;
427 gfc_expr *res, *new_expr;
428 gfc_actual_arglist *mask;
429
430 fn = *e;
431
432 if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
433 || fn->value.function.isym == NULL)
434 return 0;
435
436 id = fn->value.function.isym->id;
437
438 if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
439 && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
440 return 0;
441
442 a = fn->value.function.actual;
443
444 /* Don't handle MASK or DIM. */
445
446 dim = a->next;
447
448 if (dim->expr != NULL)
449 return 0;
450
451 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
452 {
453 mask = dim->next;
454 if ( mask->expr != NULL)
455 return 0;
456 }
457
458 arg = a->expr;
459
460 if (arg->expr_type != EXPR_ARRAY)
461 return 0;
462
463 switch (id)
464 {
465 case GFC_ISYM_SUM:
466 op = INTRINSIC_PLUS;
467 break;
468
469 case GFC_ISYM_PRODUCT:
470 op = INTRINSIC_TIMES;
471 break;
472
473 case GFC_ISYM_ANY:
474 op = INTRINSIC_OR;
475 break;
476
477 case GFC_ISYM_ALL:
478 op = INTRINSIC_AND;
479 break;
480
481 default:
482 return 0;
483 }
484
485 c = gfc_constructor_first (arg->value.constructor);
486
487 /* Don't do any simplififcation if we have
488 - no element in the constructor or
489 - only have a single element in the array which contains an
490 iterator. */
491
492 if (c == NULL)
493 return 0;
494
495 res = copy_walk_reduction_arg (c, fn);
496
497 c = gfc_constructor_next (c);
498 while (c)
499 {
500 new_expr = gfc_get_expr ();
501 new_expr->ts = fn->ts;
502 new_expr->expr_type = EXPR_OP;
503 new_expr->rank = fn->rank;
504 new_expr->where = fn->where;
505 new_expr->value.op.op = op;
506 new_expr->value.op.op1 = res;
507 new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn);
508 res = new_expr;
509 c = gfc_constructor_next (c);
510 }
511
512 gfc_simplify_expr (res, 0);
513 *e = res;
514 gfc_free_expr (fn);
515
516 return 0;
517 }
518
519 /* Callback function for common function elimination, called from cfe_expr_0.
520 Put all eligible function expressions into expr_array. */
521
522 static int
523 cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
524 void *data ATTRIBUTE_UNUSED)
525 {
526
527 if ((*e)->expr_type != EXPR_FUNCTION)
528 return 0;
529
530 /* We don't do character functions with unknown charlens. */
531 if ((*e)->ts.type == BT_CHARACTER
532 && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
533 || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
534 return 0;
535
536 /* We don't do function elimination within FORALL statements, it can
537 lead to wrong-code in certain circumstances. */
538
539 if (forall_level > 0)
540 return 0;
541
542 /* Function elimination inside an iterator could lead to functions which
543 depend on iterator variables being moved outside. FIXME: We should check
544 if the functions do indeed depend on the iterator variable. */
545
546 if (iterator_level > 0)
547 return 0;
548
549 /* If we don't know the shape at compile time, we create an allocatable
550 temporary variable to hold the intermediate result, but only if
551 allocation on assignment is active. */
552
553 if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
554 return 0;
555
556 /* Skip the test for pure functions if -faggressive-function-elimination
557 is specified. */
558 if ((*e)->value.function.esym)
559 {
560 /* Don't create an array temporary for elemental functions. */
561 if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0)
562 return 0;
563
564 /* Only eliminate potentially impure functions if the
565 user specifically requested it. */
566 if (!flag_aggressive_function_elimination
567 && !(*e)->value.function.esym->attr.pure
568 && !(*e)->value.function.esym->attr.implicit_pure)
569 return 0;
570 }
571
572 if ((*e)->value.function.isym)
573 {
574 /* Conversions are handled on the fly by the middle end,
575 transpose during trans-* stages and TRANSFER by the middle end. */
576 if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION
577 || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER
578 || gfc_inline_intrinsic_function_p (*e))
579 return 0;
580
581 /* Don't create an array temporary for elemental functions,
582 as this would be wasteful of memory.
583 FIXME: Create a scalar temporary during scalarization. */
584 if ((*e)->value.function.isym->elemental && (*e)->rank > 0)
585 return 0;
586
587 if (!(*e)->value.function.isym->pure)
588 return 0;
589 }
590
591 expr_array.safe_push (e);
592 return 0;
593 }
594
595 /* Auxiliary function to check if an expression is a temporary created by
596 create var. */
597
598 static bool
599 is_fe_temp (gfc_expr *e)
600 {
601 if (e->expr_type != EXPR_VARIABLE)
602 return false;
603
604 return e->symtree->n.sym->attr.fe_temp;
605 }
606
607 /* Determine the length of a string, if it can be evaluated as a constant
608 expression. Return a newly allocated gfc_expr or NULL on failure.
609 If the user specified a substring which is potentially longer than
610 the string itself, the string will be padded with spaces, which
611 is harmless. */
612
613 static gfc_expr *
614 constant_string_length (gfc_expr *e)
615 {
616
617 gfc_expr *length;
618 gfc_ref *ref;
619 gfc_expr *res;
620 mpz_t value;
621
622 if (e->ts.u.cl)
623 {
624 length = e->ts.u.cl->length;
625 if (length && length->expr_type == EXPR_CONSTANT)
626 return gfc_copy_expr(length);
627 }
628
629 /* Return length of substring, if constant. */
630 for (ref = e->ref; ref; ref = ref->next)
631 {
632 if (ref->type == REF_SUBSTRING
633 && gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value))
634 {
635 res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
636 &e->where);
637
638 mpz_add_ui (res->value.integer, value, 1);
639 mpz_clear (value);
640 return res;
641 }
642 }
643
644 /* Return length of char symbol, if constant. */
645
646 if (e->symtree && e->symtree->n.sym->ts.u.cl
647 && e->symtree->n.sym->ts.u.cl->length
648 && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
649 return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length);
650
651 return NULL;
652
653 }
654
655 /* Insert a block at the current position unless it has already
656 been inserted; in this case use the one already there. */
657
658 static gfc_namespace*
659 insert_block ()
660 {
661 gfc_namespace *ns;
662
663 /* If the block hasn't already been created, do so. */
664 if (inserted_block == NULL)
665 {
666 inserted_block = XCNEW (gfc_code);
667 inserted_block->op = EXEC_BLOCK;
668 inserted_block->loc = (*current_code)->loc;
669 ns = gfc_build_block_ns (current_ns);
670 inserted_block->ext.block.ns = ns;
671 inserted_block->ext.block.assoc = NULL;
672
673 ns->code = *current_code;
674
675 /* If the statement has a label, make sure it is transferred to
676 the newly created block. */
677
678 if ((*current_code)->here)
679 {
680 inserted_block->here = (*current_code)->here;
681 (*current_code)->here = NULL;
682 }
683
684 inserted_block->next = (*current_code)->next;
685 changed_statement = &(inserted_block->ext.block.ns->code);
686 (*current_code)->next = NULL;
687 /* Insert the BLOCK at the right position. */
688 *current_code = inserted_block;
689 ns->parent = current_ns;
690 }
691 else
692 ns = inserted_block->ext.block.ns;
693
694 return ns;
695 }
696
697 /* Returns a new expression (a variable) to be used in place of the old one,
698 with an optional assignment statement before the current statement to set
699 the value of the variable. Creates a new BLOCK for the statement if that
700 hasn't already been done and puts the statement, plus the newly created
701 variables, in that block. Special cases: If the expression is constant or
702 a temporary which has already been created, just copy it. */
703
704 static gfc_expr*
705 create_var (gfc_expr * e, const char *vname)
706 {
707 char name[GFC_MAX_SYMBOL_LEN +1];
708 gfc_symtree *symtree;
709 gfc_symbol *symbol;
710 gfc_expr *result;
711 gfc_code *n;
712 gfc_namespace *ns;
713 int i;
714 bool deferred;
715
716 if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
717 return gfc_copy_expr (e);
718
719 ns = insert_block ();
720
721 if (vname)
722 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname);
723 else
724 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++);
725
726 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
727 gcc_unreachable ();
728
729 symbol = symtree->n.sym;
730 symbol->ts = e->ts;
731
732 if (e->rank > 0)
733 {
734 symbol->as = gfc_get_array_spec ();
735 symbol->as->rank = e->rank;
736
737 if (e->shape == NULL)
738 {
739 /* We don't know the shape at compile time, so we use an
740 allocatable. */
741 symbol->as->type = AS_DEFERRED;
742 symbol->attr.allocatable = 1;
743 }
744 else
745 {
746 symbol->as->type = AS_EXPLICIT;
747 /* Copy the shape. */
748 for (i=0; i<e->rank; i++)
749 {
750 gfc_expr *p, *q;
751
752 p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
753 &(e->where));
754 mpz_set_si (p->value.integer, 1);
755 symbol->as->lower[i] = p;
756
757 q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
758 &(e->where));
759 mpz_set (q->value.integer, e->shape[i]);
760 symbol->as->upper[i] = q;
761 }
762 }
763 }
764
765 deferred = 0;
766 if (e->ts.type == BT_CHARACTER && e->rank == 0)
767 {
768 gfc_expr *length;
769
770 symbol->ts.u.cl = gfc_new_charlen (ns, NULL);
771 length = constant_string_length (e);
772 if (length)
773 symbol->ts.u.cl->length = length;
774 else
775 {
776 symbol->attr.allocatable = 1;
777 deferred = 1;
778 }
779 }
780
781 symbol->attr.flavor = FL_VARIABLE;
782 symbol->attr.referenced = 1;
783 symbol->attr.dimension = e->rank > 0;
784 symbol->attr.fe_temp = 1;
785 gfc_commit_symbol (symbol);
786
787 result = gfc_get_expr ();
788 result->expr_type = EXPR_VARIABLE;
789 result->ts = e->ts;
790 result->ts.deferred = deferred;
791 result->rank = e->rank;
792 result->shape = gfc_copy_shape (e->shape, e->rank);
793 result->symtree = symtree;
794 result->where = e->where;
795 if (e->rank > 0)
796 {
797 result->ref = gfc_get_ref ();
798 result->ref->type = REF_ARRAY;
799 result->ref->u.ar.type = AR_FULL;
800 result->ref->u.ar.where = e->where;
801 result->ref->u.ar.dimen = e->rank;
802 result->ref->u.ar.as = symbol->ts.type == BT_CLASS
803 ? CLASS_DATA (symbol)->as : symbol->as;
804 if (warn_array_temporaries)
805 gfc_warning (OPT_Warray_temporaries,
806 "Creating array temporary at %L", &(e->where));
807 }
808
809 /* Generate the new assignment. */
810 n = XCNEW (gfc_code);
811 n->op = EXEC_ASSIGN;
812 n->loc = (*current_code)->loc;
813 n->next = *changed_statement;
814 n->expr1 = gfc_copy_expr (result);
815 n->expr2 = e;
816 *changed_statement = n;
817 n_vars ++;
818
819 return result;
820 }
821
822 /* Warn about function elimination. */
823
824 static void
825 do_warn_function_elimination (gfc_expr *e)
826 {
827 if (e->expr_type != EXPR_FUNCTION)
828 return;
829 if (e->value.function.esym)
830 gfc_warning (OPT_Wfunction_elimination,
831 "Removing call to function %qs at %L",
832 e->value.function.esym->name, &(e->where));
833 else if (e->value.function.isym)
834 gfc_warning (OPT_Wfunction_elimination,
835 "Removing call to function %qs at %L",
836 e->value.function.isym->name, &(e->where));
837 }
838 /* Callback function for the code walker for doing common function
839 elimination. This builds up the list of functions in the expression
840 and goes through them to detect duplicates, which it then replaces
841 by variables. */
842
843 static int
844 cfe_expr_0 (gfc_expr **e, int *walk_subtrees,
845 void *data ATTRIBUTE_UNUSED)
846 {
847 int i,j;
848 gfc_expr *newvar;
849 gfc_expr **ei, **ej;
850
851 /* Don't do this optimization within OMP workshare or ASSOC lists. */
852
853 if (in_omp_workshare || in_assoc_list)
854 {
855 *walk_subtrees = 0;
856 return 0;
857 }
858
859 expr_array.release ();
860
861 gfc_expr_walker (e, cfe_register_funcs, NULL);
862
863 /* Walk through all the functions. */
864
865 FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1)
866 {
867 /* Skip if the function has been replaced by a variable already. */
868 if ((*ei)->expr_type == EXPR_VARIABLE)
869 continue;
870
871 newvar = NULL;
872 for (j=0; j<i; j++)
873 {
874 ej = expr_array[j];
875 if (gfc_dep_compare_functions (*ei, *ej, true) == 0)
876 {
877 if (newvar == NULL)
878 newvar = create_var (*ei, "fcn");
879
880 if (warn_function_elimination)
881 do_warn_function_elimination (*ej);
882
883 free (*ej);
884 *ej = gfc_copy_expr (newvar);
885 }
886 }
887 if (newvar)
888 *ei = newvar;
889 }
890
891 /* We did all the necessary walking in this function. */
892 *walk_subtrees = 0;
893 return 0;
894 }
895
896 /* Callback function for common function elimination, called from
897 gfc_code_walker. This keeps track of the current code, in order
898 to insert statements as needed. */
899
900 static int
901 cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
902 {
903 current_code = c;
904 inserted_block = NULL;
905 changed_statement = NULL;
906
907 /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
908 and allocation on assigment are prohibited inside WHERE, and finally
909 masking an expression would lead to wrong-code when replacing
910
911 WHERE (a>0)
912 b = sum(foo(a) + foo(a))
913 END WHERE
914
915 with
916
917 WHERE (a > 0)
918 tmp = foo(a)
919 b = sum(tmp + tmp)
920 END WHERE
921 */
922
923 if ((*c)->op == EXEC_WHERE)
924 {
925 *walk_subtrees = 0;
926 return 0;
927 }
928
929
930 return 0;
931 }
932
933 /* Dummy function for expression call back, for use when we
934 really don't want to do any walking. */
935
936 static int
937 dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
938 void *data ATTRIBUTE_UNUSED)
939 {
940 *walk_subtrees = 0;
941 return 0;
942 }
943
944 /* Dummy function for code callback, for use when we really
945 don't want to do anything. */
946 int
947 gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED,
948 int *walk_subtrees ATTRIBUTE_UNUSED,
949 void *data ATTRIBUTE_UNUSED)
950 {
951 return 0;
952 }
953
954 /* Code callback function for converting
955 do while(a)
956 end do
957 into the equivalent
958 do
959 if (.not. a) exit
960 end do
961 This is because common function elimination would otherwise place the
962 temporary variables outside the loop. */
963
964 static int
965 convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
966 void *data ATTRIBUTE_UNUSED)
967 {
968 gfc_code *co = *c;
969 gfc_code *c_if1, *c_if2, *c_exit;
970 gfc_code *loopblock;
971 gfc_expr *e_not, *e_cond;
972
973 if (co->op != EXEC_DO_WHILE)
974 return 0;
975
976 if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
977 return 0;
978
979 e_cond = co->expr1;
980
981 /* Generate the condition of the if statement, which is .not. the original
982 statement. */
983 e_not = gfc_get_expr ();
984 e_not->ts = e_cond->ts;
985 e_not->where = e_cond->where;
986 e_not->expr_type = EXPR_OP;
987 e_not->value.op.op = INTRINSIC_NOT;
988 e_not->value.op.op1 = e_cond;
989
990 /* Generate the EXIT statement. */
991 c_exit = XCNEW (gfc_code);
992 c_exit->op = EXEC_EXIT;
993 c_exit->ext.which_construct = co;
994 c_exit->loc = co->loc;
995
996 /* Generate the IF statement. */
997 c_if2 = XCNEW (gfc_code);
998 c_if2->op = EXEC_IF;
999 c_if2->expr1 = e_not;
1000 c_if2->next = c_exit;
1001 c_if2->loc = co->loc;
1002
1003 /* ... plus the one to chain it to. */
1004 c_if1 = XCNEW (gfc_code);
1005 c_if1->op = EXEC_IF;
1006 c_if1->block = c_if2;
1007 c_if1->loc = co->loc;
1008
1009 /* Make the DO WHILE loop into a DO block by replacing the condition
1010 with a true constant. */
1011 co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
1012
1013 /* Hang the generated if statement into the loop body. */
1014
1015 loopblock = co->block->next;
1016 co->block->next = c_if1;
1017 c_if1->next = loopblock;
1018
1019 return 0;
1020 }
1021
1022 /* Code callback function for converting
1023 if (a) then
1024 ...
1025 else if (b) then
1026 end if
1027
1028 into
1029 if (a) then
1030 else
1031 if (b) then
1032 end if
1033 end if
1034
1035 because otherwise common function elimination would place the BLOCKs
1036 into the wrong place. */
1037
1038 static int
1039 convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1040 void *data ATTRIBUTE_UNUSED)
1041 {
1042 gfc_code *co = *c;
1043 gfc_code *c_if1, *c_if2, *else_stmt;
1044
1045 if (co->op != EXEC_IF)
1046 return 0;
1047
1048 /* This loop starts out with the first ELSE statement. */
1049 else_stmt = co->block->block;
1050
1051 while (else_stmt != NULL)
1052 {
1053 gfc_code *next_else;
1054
1055 /* If there is no condition, we're done. */
1056 if (else_stmt->expr1 == NULL)
1057 break;
1058
1059 next_else = else_stmt->block;
1060
1061 /* Generate the new IF statement. */
1062 c_if2 = XCNEW (gfc_code);
1063 c_if2->op = EXEC_IF;
1064 c_if2->expr1 = else_stmt->expr1;
1065 c_if2->next = else_stmt->next;
1066 c_if2->loc = else_stmt->loc;
1067 c_if2->block = next_else;
1068
1069 /* ... plus the one to chain it to. */
1070 c_if1 = XCNEW (gfc_code);
1071 c_if1->op = EXEC_IF;
1072 c_if1->block = c_if2;
1073 c_if1->loc = else_stmt->loc;
1074
1075 /* Insert the new IF after the ELSE. */
1076 else_stmt->expr1 = NULL;
1077 else_stmt->next = c_if1;
1078 else_stmt->block = NULL;
1079
1080 else_stmt = next_else;
1081 }
1082 /* Don't walk subtrees. */
1083 return 0;
1084 }
1085
1086 struct do_stack
1087 {
1088 struct do_stack *prev;
1089 gfc_iterator *iter;
1090 gfc_code *code;
1091 } *stack_top;
1092
1093 /* Recursively traverse the block of a WRITE or READ statement, and maybe
1094 optimize by replacing do loops with their analog array slices. For
1095 example:
1096
1097 write (*,*) (a(i), i=1,4)
1098
1099 is replaced with
1100
1101 write (*,*) a(1:4:1) . */
1102
1103 static bool
1104 traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev)
1105 {
1106 gfc_code *curr;
1107 gfc_expr *new_e, *expr, *start;
1108 gfc_ref *ref;
1109 struct do_stack ds_push;
1110 int i, future_rank = 0;
1111 gfc_iterator *iters[GFC_MAX_DIMENSIONS];
1112 gfc_expr *e;
1113
1114 /* Find the first transfer/do statement. */
1115 for (curr = code; curr; curr = curr->next)
1116 {
1117 if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
1118 break;
1119 }
1120
1121 /* Ensure it is the only transfer/do statement because cases like
1122
1123 write (*,*) (a(i), b(i), i=1,4)
1124
1125 cannot be optimized. */
1126
1127 if (!curr || curr->next)
1128 return false;
1129
1130 if (curr->op == EXEC_DO)
1131 {
1132 if (curr->ext.iterator->var->ref)
1133 return false;
1134 ds_push.prev = stack_top;
1135 ds_push.iter = curr->ext.iterator;
1136 ds_push.code = curr;
1137 stack_top = &ds_push;
1138 if (traverse_io_block (curr->block->next, has_reached, prev))
1139 {
1140 if (curr != stack_top->code && !*has_reached)
1141 {
1142 curr->block->next = NULL;
1143 gfc_free_statements (curr);
1144 }
1145 else
1146 *has_reached = true;
1147 return true;
1148 }
1149 return false;
1150 }
1151
1152 gcc_assert (curr->op == EXEC_TRANSFER);
1153
1154 /* FIXME: Workaround for PR 80945 - array slices with deferred character
1155 lenghts do not work. Remove this section when the PR is fixed. */
1156 e = curr->expr1;
1157 if (e->expr_type == EXPR_VARIABLE && e->ts.type == BT_CHARACTER
1158 && e->ts.deferred)
1159 return false;
1160 /* End of section to be removed. */
1161
1162 ref = e->ref;
1163 if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0 || ref->next)
1164 return false;
1165
1166 /* Find the iterators belonging to each variable and check conditions. */
1167 for (i = 0; i < ref->u.ar.dimen; i++)
1168 {
1169 if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
1170 || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
1171 return false;
1172
1173 start = ref->u.ar.start[i];
1174 gfc_simplify_expr (start, 0);
1175 switch (start->expr_type)
1176 {
1177 case EXPR_VARIABLE:
1178
1179 /* write (*,*) (a(i), i=a%b,1) not handled yet. */
1180 if (start->ref)
1181 return false;
1182
1183 /* Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4). */
1184 if (!stack_top || !stack_top->iter
1185 || stack_top->iter->var->symtree != start->symtree)
1186 {
1187 /* Check for (a(i,i), i=1,3). */
1188 int j;
1189
1190 for (j=0; j<i; j++)
1191 if (iters[j] && iters[j]->var->symtree == start->symtree)
1192 return false;
1193
1194 iters[i] = NULL;
1195 }
1196 else
1197 {
1198 iters[i] = stack_top->iter;
1199 stack_top = stack_top->prev;
1200 future_rank++;
1201 }
1202 break;
1203 case EXPR_CONSTANT:
1204 iters[i] = NULL;
1205 break;
1206 case EXPR_OP:
1207 switch (start->value.op.op)
1208 {
1209 case INTRINSIC_PLUS:
1210 case INTRINSIC_TIMES:
1211 if (start->value.op.op1->expr_type != EXPR_VARIABLE)
1212 std::swap (start->value.op.op1, start->value.op.op2);
1213 gcc_fallthrough ();
1214 case INTRINSIC_MINUS:
1215 if ((start->value.op.op1->expr_type!= EXPR_VARIABLE
1216 && start->value.op.op2->expr_type != EXPR_CONSTANT)
1217 || start->value.op.op1->ref)
1218 return false;
1219 if (!stack_top || !stack_top->iter
1220 || stack_top->iter->var->symtree
1221 != start->value.op.op1->symtree)
1222 return false;
1223 iters[i] = stack_top->iter;
1224 stack_top = stack_top->prev;
1225 break;
1226 default:
1227 return false;
1228 }
1229 future_rank++;
1230 break;
1231 default:
1232 return false;
1233 }
1234 }
1235
1236 /* Create new expr. */
1237 new_e = gfc_copy_expr (curr->expr1);
1238 new_e->expr_type = EXPR_VARIABLE;
1239 new_e->rank = future_rank;
1240 if (curr->expr1->shape)
1241 new_e->shape = gfc_get_shape (new_e->rank);
1242
1243 /* Assign new starts, ends and strides if necessary. */
1244 for (i = 0; i < ref->u.ar.dimen; i++)
1245 {
1246 if (!iters[i])
1247 continue;
1248 start = ref->u.ar.start[i];
1249 switch (start->expr_type)
1250 {
1251 case EXPR_CONSTANT:
1252 gfc_internal_error ("bad expression");
1253 break;
1254 case EXPR_VARIABLE:
1255 new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1256 new_e->ref->u.ar.type = AR_SECTION;
1257 gfc_free_expr (new_e->ref->u.ar.start[i]);
1258 new_e->ref->u.ar.start[i] = gfc_copy_expr (iters[i]->start);
1259 new_e->ref->u.ar.end[i] = gfc_copy_expr (iters[i]->end);
1260 new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1261 break;
1262 case EXPR_OP:
1263 new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1264 new_e->ref->u.ar.type = AR_SECTION;
1265 gfc_free_expr (new_e->ref->u.ar.start[i]);
1266 expr = gfc_copy_expr (start);
1267 expr->value.op.op1 = gfc_copy_expr (iters[i]->start);
1268 new_e->ref->u.ar.start[i] = expr;
1269 gfc_simplify_expr (new_e->ref->u.ar.start[i], 0);
1270 expr = gfc_copy_expr (start);
1271 expr->value.op.op1 = gfc_copy_expr (iters[i]->end);
1272 new_e->ref->u.ar.end[i] = expr;
1273 gfc_simplify_expr (new_e->ref->u.ar.end[i], 0);
1274 switch (start->value.op.op)
1275 {
1276 case INTRINSIC_MINUS:
1277 case INTRINSIC_PLUS:
1278 new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1279 break;
1280 case INTRINSIC_TIMES:
1281 expr = gfc_copy_expr (start);
1282 expr->value.op.op1 = gfc_copy_expr (iters[i]->step);
1283 new_e->ref->u.ar.stride[i] = expr;
1284 gfc_simplify_expr (new_e->ref->u.ar.stride[i], 0);
1285 break;
1286 default:
1287 gfc_internal_error ("bad op");
1288 }
1289 break;
1290 default:
1291 gfc_internal_error ("bad expression");
1292 }
1293 }
1294 curr->expr1 = new_e;
1295
1296 /* Insert modified statement. Check whether the statement needs to be
1297 inserted at the lowest level. */
1298 if (!stack_top->iter)
1299 {
1300 if (prev)
1301 {
1302 curr->next = prev->next->next;
1303 prev->next = curr;
1304 }
1305 else
1306 {
1307 curr->next = stack_top->code->block->next->next->next;
1308 stack_top->code->block->next = curr;
1309 }
1310 }
1311 else
1312 stack_top->code->block->next = curr;
1313 return true;
1314 }
1315
1316 /* Function for the gfc_code_walker. If code is a READ or WRITE statement, it
1317 tries to optimize its block. */
1318
1319 static int
1320 simplify_io_impl_do (gfc_code **code, int *walk_subtrees,
1321 void *data ATTRIBUTE_UNUSED)
1322 {
1323 gfc_code **curr, *prev = NULL;
1324 struct do_stack write, first;
1325 bool b = false;
1326 *walk_subtrees = 1;
1327 if (!(*code)->block
1328 || ((*code)->block->op != EXEC_WRITE
1329 && (*code)->block->op != EXEC_READ))
1330 return 0;
1331
1332 *walk_subtrees = 0;
1333 write.prev = NULL;
1334 write.iter = NULL;
1335 write.code = *code;
1336
1337 for (curr = &(*code)->block; *curr; curr = &(*curr)->next)
1338 {
1339 if ((*curr)->op == EXEC_DO)
1340 {
1341 first.prev = &write;
1342 first.iter = (*curr)->ext.iterator;
1343 first.code = *curr;
1344 stack_top = &first;
1345 traverse_io_block ((*curr)->block->next, &b, prev);
1346 stack_top = NULL;
1347 }
1348 prev = *curr;
1349 }
1350 return 0;
1351 }
1352
1353 /* Optimize a namespace, including all contained namespaces. */
1354
1355 static void
1356 optimize_namespace (gfc_namespace *ns)
1357 {
1358 gfc_namespace *saved_ns = gfc_current_ns;
1359 current_ns = ns;
1360 gfc_current_ns = ns;
1361 forall_level = 0;
1362 iterator_level = 0;
1363 in_assoc_list = false;
1364 in_omp_workshare = false;
1365
1366 gfc_code_walker (&ns->code, simplify_io_impl_do, dummy_expr_callback, NULL);
1367 gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
1368 gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL);
1369 gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
1370 gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
1371 if (flag_inline_matmul_limit != 0)
1372 {
1373 bool found;
1374 do
1375 {
1376 found = false;
1377 gfc_code_walker (&ns->code, matmul_to_var_code, matmul_to_var_expr,
1378 (void *) &found);
1379 }
1380 while (found);
1381
1382 gfc_code_walker (&ns->code, matmul_temp_args, dummy_expr_callback,
1383 NULL);
1384 gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
1385 NULL);
1386 }
1387
1388 /* BLOCKs are handled in the expression walker below. */
1389 for (ns = ns->contained; ns; ns = ns->sibling)
1390 {
1391 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1392 optimize_namespace (ns);
1393 }
1394 gfc_current_ns = saved_ns;
1395 }
1396
1397 /* Handle dependencies for allocatable strings which potentially redefine
1398 themselves in an assignment. */
1399
1400 static void
1401 realloc_strings (gfc_namespace *ns)
1402 {
1403 current_ns = ns;
1404 gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL);
1405
1406 for (ns = ns->contained; ns; ns = ns->sibling)
1407 {
1408 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1409 realloc_strings (ns);
1410 }
1411
1412 }
1413
1414 static void
1415 optimize_reduction (gfc_namespace *ns)
1416 {
1417 current_ns = ns;
1418 gfc_code_walker (&ns->code, gfc_dummy_code_callback,
1419 callback_reduction, NULL);
1420
1421 /* BLOCKs are handled in the expression walker below. */
1422 for (ns = ns->contained; ns; ns = ns->sibling)
1423 {
1424 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1425 optimize_reduction (ns);
1426 }
1427 }
1428
1429 /* Replace code like
1430 a = matmul(b,c) + d
1431 with
1432 a = matmul(b,c) ; a = a + d
1433 where the array function is not elemental and not allocatable
1434 and does not depend on the left-hand side.
1435 */
1436
1437 static bool
1438 optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
1439 {
1440 gfc_expr *e;
1441
1442 if (!*rhs)
1443 return false;
1444
1445 e = *rhs;
1446 if (e->expr_type == EXPR_OP)
1447 {
1448 switch (e->value.op.op)
1449 {
1450 /* Unary operators and exponentiation: Only look at a single
1451 operand. */
1452 case INTRINSIC_NOT:
1453 case INTRINSIC_UPLUS:
1454 case INTRINSIC_UMINUS:
1455 case INTRINSIC_PARENTHESES:
1456 case INTRINSIC_POWER:
1457 if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
1458 return true;
1459 break;
1460
1461 case INTRINSIC_CONCAT:
1462 /* Do not do string concatenations. */
1463 break;
1464
1465 default:
1466 /* Binary operators. */
1467 if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
1468 return true;
1469
1470 if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
1471 return true;
1472
1473 break;
1474 }
1475 }
1476 else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
1477 && ! (e->value.function.esym
1478 && (e->value.function.esym->attr.elemental
1479 || e->value.function.esym->attr.allocatable
1480 || e->value.function.esym->ts.type != c->expr1->ts.type
1481 || e->value.function.esym->ts.kind != c->expr1->ts.kind))
1482 && ! (e->value.function.isym
1483 && (e->value.function.isym->elemental
1484 || e->ts.type != c->expr1->ts.type
1485 || e->ts.kind != c->expr1->ts.kind))
1486 && ! gfc_inline_intrinsic_function_p (e))
1487 {
1488
1489 gfc_code *n;
1490 gfc_expr *new_expr;
1491
1492 /* Insert a new assignment statement after the current one. */
1493 n = XCNEW (gfc_code);
1494 n->op = EXEC_ASSIGN;
1495 n->loc = c->loc;
1496 n->next = c->next;
1497 c->next = n;
1498
1499 n->expr1 = gfc_copy_expr (c->expr1);
1500 n->expr2 = c->expr2;
1501 new_expr = gfc_copy_expr (c->expr1);
1502 c->expr2 = e;
1503 *rhs = new_expr;
1504
1505 return true;
1506
1507 }
1508
1509 /* Nothing to optimize. */
1510 return false;
1511 }
1512
1513 /* Remove unneeded TRIMs at the end of expressions. */
1514
1515 static bool
1516 remove_trim (gfc_expr *rhs)
1517 {
1518 bool ret;
1519
1520 ret = false;
1521 if (!rhs)
1522 return ret;
1523
1524 /* Check for a // b // trim(c). Looping is probably not
1525 necessary because the parser usually generates
1526 (// (// a b ) trim(c) ) , but better safe than sorry. */
1527
1528 while (rhs->expr_type == EXPR_OP
1529 && rhs->value.op.op == INTRINSIC_CONCAT)
1530 rhs = rhs->value.op.op2;
1531
1532 while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym
1533 && rhs->value.function.isym->id == GFC_ISYM_TRIM)
1534 {
1535 strip_function_call (rhs);
1536 /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1537 remove_trim (rhs);
1538 ret = true;
1539 }
1540
1541 return ret;
1542 }
1543
1544 /* Optimizations for an assignment. */
1545
1546 static void
1547 optimize_assignment (gfc_code * c)
1548 {
1549 gfc_expr *lhs, *rhs;
1550
1551 lhs = c->expr1;
1552 rhs = c->expr2;
1553
1554 if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred)
1555 {
1556 /* Optimize a = trim(b) to a = b. */
1557 remove_trim (rhs);
1558
1559 /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1560 if (is_empty_string (rhs))
1561 rhs->value.character.length = 0;
1562 }
1563
1564 if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
1565 optimize_binop_array_assignment (c, &rhs, false);
1566 }
1567
1568
1569 /* Remove an unneeded function call, modifying the expression.
1570 This replaces the function call with the value of its
1571 first argument. The rest of the argument list is freed. */
1572
1573 static void
1574 strip_function_call (gfc_expr *e)
1575 {
1576 gfc_expr *e1;
1577 gfc_actual_arglist *a;
1578
1579 a = e->value.function.actual;
1580
1581 /* We should have at least one argument. */
1582 gcc_assert (a->expr != NULL);
1583
1584 e1 = a->expr;
1585
1586 /* Free the remaining arglist, if any. */
1587 if (a->next)
1588 gfc_free_actual_arglist (a->next);
1589
1590 /* Graft the argument expression onto the original function. */
1591 *e = *e1;
1592 free (e1);
1593
1594 }
1595
1596 /* Optimization of lexical comparison functions. */
1597
1598 static bool
1599 optimize_lexical_comparison (gfc_expr *e)
1600 {
1601 if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL)
1602 return false;
1603
1604 switch (e->value.function.isym->id)
1605 {
1606 case GFC_ISYM_LLE:
1607 return optimize_comparison (e, INTRINSIC_LE);
1608
1609 case GFC_ISYM_LGE:
1610 return optimize_comparison (e, INTRINSIC_GE);
1611
1612 case GFC_ISYM_LGT:
1613 return optimize_comparison (e, INTRINSIC_GT);
1614
1615 case GFC_ISYM_LLT:
1616 return optimize_comparison (e, INTRINSIC_LT);
1617
1618 default:
1619 break;
1620 }
1621 return false;
1622 }
1623
1624 /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1625 do CHARACTER because of possible pessimization involving character
1626 lengths. */
1627
1628 static bool
1629 combine_array_constructor (gfc_expr *e)
1630 {
1631
1632 gfc_expr *op1, *op2;
1633 gfc_expr *scalar;
1634 gfc_expr *new_expr;
1635 gfc_constructor *c, *new_c;
1636 gfc_constructor_base oldbase, newbase;
1637 bool scalar_first;
1638
1639 /* Array constructors have rank one. */
1640 if (e->rank != 1)
1641 return false;
1642
1643 /* Don't try to combine association lists, this makes no sense
1644 and leads to an ICE. */
1645 if (in_assoc_list)
1646 return false;
1647
1648 /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1649 if (forall_level > 0)
1650 return false;
1651
1652 /* Inside an iterator, things can get hairy; we are likely to create
1653 an invalid temporary variable. */
1654 if (iterator_level > 0)
1655 return false;
1656
1657 op1 = e->value.op.op1;
1658 op2 = e->value.op.op2;
1659
1660 if (!op1 || !op2)
1661 return false;
1662
1663 if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
1664 scalar_first = false;
1665 else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
1666 {
1667 scalar_first = true;
1668 op1 = e->value.op.op2;
1669 op2 = e->value.op.op1;
1670 }
1671 else
1672 return false;
1673
1674 if (op2->ts.type == BT_CHARACTER)
1675 return false;
1676
1677 scalar = create_var (gfc_copy_expr (op2), "constr");
1678
1679 oldbase = op1->value.constructor;
1680 newbase = NULL;
1681 e->expr_type = EXPR_ARRAY;
1682
1683 for (c = gfc_constructor_first (oldbase); c;
1684 c = gfc_constructor_next (c))
1685 {
1686 new_expr = gfc_get_expr ();
1687 new_expr->ts = e->ts;
1688 new_expr->expr_type = EXPR_OP;
1689 new_expr->rank = c->expr->rank;
1690 new_expr->where = c->expr->where;
1691 new_expr->value.op.op = e->value.op.op;
1692
1693 if (scalar_first)
1694 {
1695 new_expr->value.op.op1 = gfc_copy_expr (scalar);
1696 new_expr->value.op.op2 = gfc_copy_expr (c->expr);
1697 }
1698 else
1699 {
1700 new_expr->value.op.op1 = gfc_copy_expr (c->expr);
1701 new_expr->value.op.op2 = gfc_copy_expr (scalar);
1702 }
1703
1704 new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
1705 new_c->iterator = c->iterator;
1706 c->iterator = NULL;
1707 }
1708
1709 gfc_free_expr (op1);
1710 gfc_free_expr (op2);
1711 gfc_free_expr (scalar);
1712
1713 e->value.constructor = newbase;
1714 return true;
1715 }
1716
1717 /* Change (-1)**k into 1-ishift(iand(k,1),1) and
1718 2**k into ishift(1,k) */
1719
1720 static bool
1721 optimize_power (gfc_expr *e)
1722 {
1723 gfc_expr *op1, *op2;
1724 gfc_expr *iand, *ishft;
1725
1726 if (e->ts.type != BT_INTEGER)
1727 return false;
1728
1729 op1 = e->value.op.op1;
1730
1731 if (op1 == NULL || op1->expr_type != EXPR_CONSTANT)
1732 return false;
1733
1734 if (mpz_cmp_si (op1->value.integer, -1L) == 0)
1735 {
1736 gfc_free_expr (op1);
1737
1738 op2 = e->value.op.op2;
1739
1740 if (op2 == NULL)
1741 return false;
1742
1743 iand = gfc_build_intrinsic_call (current_ns, GFC_ISYM_IAND,
1744 "_internal_iand", e->where, 2, op2,
1745 gfc_get_int_expr (e->ts.kind,
1746 &e->where, 1));
1747
1748 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1749 "_internal_ishft", e->where, 2, iand,
1750 gfc_get_int_expr (e->ts.kind,
1751 &e->where, 1));
1752
1753 e->value.op.op = INTRINSIC_MINUS;
1754 e->value.op.op1 = gfc_get_int_expr (e->ts.kind, &e->where, 1);
1755 e->value.op.op2 = ishft;
1756 return true;
1757 }
1758 else if (mpz_cmp_si (op1->value.integer, 2L) == 0)
1759 {
1760 gfc_free_expr (op1);
1761
1762 op2 = e->value.op.op2;
1763 if (op2 == NULL)
1764 return false;
1765
1766 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1767 "_internal_ishft", e->where, 2,
1768 gfc_get_int_expr (e->ts.kind,
1769 &e->where, 1),
1770 op2);
1771 *e = *ishft;
1772 return true;
1773 }
1774
1775 else if (mpz_cmp_si (op1->value.integer, 1L) == 0)
1776 {
1777 op2 = e->value.op.op2;
1778 if (op2 == NULL)
1779 return false;
1780
1781 gfc_free_expr (op1);
1782 gfc_free_expr (op2);
1783
1784 e->expr_type = EXPR_CONSTANT;
1785 e->value.op.op1 = NULL;
1786 e->value.op.op2 = NULL;
1787 mpz_init_set_si (e->value.integer, 1);
1788 /* Typespec and location are still OK. */
1789 return true;
1790 }
1791
1792 return false;
1793 }
1794
1795 /* Recursive optimization of operators. */
1796
1797 static bool
1798 optimize_op (gfc_expr *e)
1799 {
1800 bool changed;
1801
1802 gfc_intrinsic_op op = e->value.op.op;
1803
1804 changed = false;
1805
1806 /* Only use new-style comparisons. */
1807 switch(op)
1808 {
1809 case INTRINSIC_EQ_OS:
1810 op = INTRINSIC_EQ;
1811 break;
1812
1813 case INTRINSIC_GE_OS:
1814 op = INTRINSIC_GE;
1815 break;
1816
1817 case INTRINSIC_LE_OS:
1818 op = INTRINSIC_LE;
1819 break;
1820
1821 case INTRINSIC_NE_OS:
1822 op = INTRINSIC_NE;
1823 break;
1824
1825 case INTRINSIC_GT_OS:
1826 op = INTRINSIC_GT;
1827 break;
1828
1829 case INTRINSIC_LT_OS:
1830 op = INTRINSIC_LT;
1831 break;
1832
1833 default:
1834 break;
1835 }
1836
1837 switch (op)
1838 {
1839 case INTRINSIC_EQ:
1840 case INTRINSIC_GE:
1841 case INTRINSIC_LE:
1842 case INTRINSIC_NE:
1843 case INTRINSIC_GT:
1844 case INTRINSIC_LT:
1845 changed = optimize_comparison (e, op);
1846
1847 gcc_fallthrough ();
1848 /* Look at array constructors. */
1849 case INTRINSIC_PLUS:
1850 case INTRINSIC_MINUS:
1851 case INTRINSIC_TIMES:
1852 case INTRINSIC_DIVIDE:
1853 return combine_array_constructor (e) || changed;
1854
1855 case INTRINSIC_POWER:
1856 return optimize_power (e);
1857
1858 default:
1859 break;
1860 }
1861
1862 return false;
1863 }
1864
1865
1866 /* Return true if a constant string contains only blanks. */
1867
1868 static bool
1869 is_empty_string (gfc_expr *e)
1870 {
1871 int i;
1872
1873 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1874 return false;
1875
1876 for (i=0; i < e->value.character.length; i++)
1877 {
1878 if (e->value.character.string[i] != ' ')
1879 return false;
1880 }
1881
1882 return true;
1883 }
1884
1885
1886 /* Insert a call to the intrinsic len_trim. Use a different name for
1887 the symbol tree so we don't run into trouble when the user has
1888 renamed len_trim for some reason. */
1889
1890 static gfc_expr*
1891 get_len_trim_call (gfc_expr *str, int kind)
1892 {
1893 gfc_expr *fcn;
1894 gfc_actual_arglist *actual_arglist, *next;
1895
1896 fcn = gfc_get_expr ();
1897 fcn->expr_type = EXPR_FUNCTION;
1898 fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM);
1899 actual_arglist = gfc_get_actual_arglist ();
1900 actual_arglist->expr = str;
1901 next = gfc_get_actual_arglist ();
1902 next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind);
1903 actual_arglist->next = next;
1904
1905 fcn->value.function.actual = actual_arglist;
1906 fcn->where = str->where;
1907 fcn->ts.type = BT_INTEGER;
1908 fcn->ts.kind = gfc_charlen_int_kind;
1909
1910 gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false);
1911 fcn->symtree->n.sym->ts = fcn->ts;
1912 fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
1913 fcn->symtree->n.sym->attr.function = 1;
1914 fcn->symtree->n.sym->attr.elemental = 1;
1915 fcn->symtree->n.sym->attr.referenced = 1;
1916 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
1917 gfc_commit_symbol (fcn->symtree->n.sym);
1918
1919 return fcn;
1920 }
1921
1922 /* Optimize expressions for equality. */
1923
1924 static bool
1925 optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
1926 {
1927 gfc_expr *op1, *op2;
1928 bool change;
1929 int eq;
1930 bool result;
1931 gfc_actual_arglist *firstarg, *secondarg;
1932
1933 if (e->expr_type == EXPR_OP)
1934 {
1935 firstarg = NULL;
1936 secondarg = NULL;
1937 op1 = e->value.op.op1;
1938 op2 = e->value.op.op2;
1939 }
1940 else if (e->expr_type == EXPR_FUNCTION)
1941 {
1942 /* One of the lexical comparison functions. */
1943 firstarg = e->value.function.actual;
1944 secondarg = firstarg->next;
1945 op1 = firstarg->expr;
1946 op2 = secondarg->expr;
1947 }
1948 else
1949 gcc_unreachable ();
1950
1951 /* Strip off unneeded TRIM calls from string comparisons. */
1952
1953 change = remove_trim (op1);
1954
1955 if (remove_trim (op2))
1956 change = true;
1957
1958 /* An expression of type EXPR_CONSTANT is only valid for scalars. */
1959 /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
1960 handles them well). However, there are also cases that need a non-scalar
1961 argument. For example the any intrinsic. See PR 45380. */
1962 if (e->rank > 0)
1963 return change;
1964
1965 /* Replace a == '' with len_trim(a) == 0 and a /= '' with
1966 len_trim(a) != 0 */
1967 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
1968 && (op == INTRINSIC_EQ || op == INTRINSIC_NE))
1969 {
1970 bool empty_op1, empty_op2;
1971 empty_op1 = is_empty_string (op1);
1972 empty_op2 = is_empty_string (op2);
1973
1974 if (empty_op1 || empty_op2)
1975 {
1976 gfc_expr *fcn;
1977 gfc_expr *zero;
1978 gfc_expr *str;
1979
1980 /* This can only happen when an error for comparing
1981 characters of different kinds has already been issued. */
1982 if (empty_op1 && empty_op2)
1983 return false;
1984
1985 zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0);
1986 str = empty_op1 ? op2 : op1;
1987
1988 fcn = get_len_trim_call (str, gfc_charlen_int_kind);
1989
1990
1991 if (empty_op1)
1992 gfc_free_expr (op1);
1993 else
1994 gfc_free_expr (op2);
1995
1996 op1 = fcn;
1997 op2 = zero;
1998 e->value.op.op1 = fcn;
1999 e->value.op.op2 = zero;
2000 }
2001 }
2002
2003
2004 /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
2005
2006 if (flag_finite_math_only
2007 || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL
2008 && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
2009 {
2010 eq = gfc_dep_compare_expr (op1, op2);
2011 if (eq <= -2)
2012 {
2013 /* Replace A // B < A // C with B < C, and A // B < C // B
2014 with A < C. */
2015 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
2016 && op1->expr_type == EXPR_OP
2017 && op1->value.op.op == INTRINSIC_CONCAT
2018 && op2->expr_type == EXPR_OP
2019 && op2->value.op.op == INTRINSIC_CONCAT)
2020 {
2021 gfc_expr *op1_left = op1->value.op.op1;
2022 gfc_expr *op2_left = op2->value.op.op1;
2023 gfc_expr *op1_right = op1->value.op.op2;
2024 gfc_expr *op2_right = op2->value.op.op2;
2025
2026 if (gfc_dep_compare_expr (op1_left, op2_left) == 0)
2027 {
2028 /* Watch out for 'A ' // x vs. 'A' // x. */
2029
2030 if (op1_left->expr_type == EXPR_CONSTANT
2031 && op2_left->expr_type == EXPR_CONSTANT
2032 && op1_left->value.character.length
2033 != op2_left->value.character.length)
2034 return change;
2035 else
2036 {
2037 free (op1_left);
2038 free (op2_left);
2039 if (firstarg)
2040 {
2041 firstarg->expr = op1_right;
2042 secondarg->expr = op2_right;
2043 }
2044 else
2045 {
2046 e->value.op.op1 = op1_right;
2047 e->value.op.op2 = op2_right;
2048 }
2049 optimize_comparison (e, op);
2050 return true;
2051 }
2052 }
2053 if (gfc_dep_compare_expr (op1_right, op2_right) == 0)
2054 {
2055 free (op1_right);
2056 free (op2_right);
2057 if (firstarg)
2058 {
2059 firstarg->expr = op1_left;
2060 secondarg->expr = op2_left;
2061 }
2062 else
2063 {
2064 e->value.op.op1 = op1_left;
2065 e->value.op.op2 = op2_left;
2066 }
2067
2068 optimize_comparison (e, op);
2069 return true;
2070 }
2071 }
2072 }
2073 else
2074 {
2075 /* eq can only be -1, 0 or 1 at this point. */
2076 switch (op)
2077 {
2078 case INTRINSIC_EQ:
2079 result = eq == 0;
2080 break;
2081
2082 case INTRINSIC_GE:
2083 result = eq >= 0;
2084 break;
2085
2086 case INTRINSIC_LE:
2087 result = eq <= 0;
2088 break;
2089
2090 case INTRINSIC_NE:
2091 result = eq != 0;
2092 break;
2093
2094 case INTRINSIC_GT:
2095 result = eq > 0;
2096 break;
2097
2098 case INTRINSIC_LT:
2099 result = eq < 0;
2100 break;
2101
2102 default:
2103 gfc_internal_error ("illegal OP in optimize_comparison");
2104 break;
2105 }
2106
2107 /* Replace the expression by a constant expression. The typespec
2108 and where remains the way it is. */
2109 free (op1);
2110 free (op2);
2111 e->expr_type = EXPR_CONSTANT;
2112 e->value.logical = result;
2113 return true;
2114 }
2115 }
2116
2117 return change;
2118 }
2119
2120 /* Optimize a trim function by replacing it with an equivalent substring
2121 involving a call to len_trim. This only works for expressions where
2122 variables are trimmed. Return true if anything was modified. */
2123
2124 static bool
2125 optimize_trim (gfc_expr *e)
2126 {
2127 gfc_expr *a;
2128 gfc_ref *ref;
2129 gfc_expr *fcn;
2130 gfc_ref **rr = NULL;
2131
2132 /* Don't do this optimization within an argument list, because
2133 otherwise aliasing issues may occur. */
2134
2135 if (count_arglist != 1)
2136 return false;
2137
2138 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION
2139 || e->value.function.isym == NULL
2140 || e->value.function.isym->id != GFC_ISYM_TRIM)
2141 return false;
2142
2143 a = e->value.function.actual->expr;
2144
2145 if (a->expr_type != EXPR_VARIABLE)
2146 return false;
2147
2148 /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
2149
2150 if (a->symtree->n.sym->attr.allocatable)
2151 return false;
2152
2153 /* Follow all references to find the correct place to put the newly
2154 created reference. FIXME: Also handle substring references and
2155 array references. Array references cause strange regressions at
2156 the moment. */
2157
2158 if (a->ref)
2159 {
2160 for (rr = &(a->ref); *rr; rr = &((*rr)->next))
2161 {
2162 if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY)
2163 return false;
2164 }
2165 }
2166
2167 strip_function_call (e);
2168
2169 if (e->ref == NULL)
2170 rr = &(e->ref);
2171
2172 /* Create the reference. */
2173
2174 ref = gfc_get_ref ();
2175 ref->type = REF_SUBSTRING;
2176
2177 /* Set the start of the reference. */
2178
2179 ref->u.ss.start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
2180
2181 /* Build the function call to len_trim(x, gfc_default_integer_kind). */
2182
2183 fcn = get_len_trim_call (gfc_copy_expr (e), gfc_default_integer_kind);
2184
2185 /* Set the end of the reference to the call to len_trim. */
2186
2187 ref->u.ss.end = fcn;
2188 gcc_assert (rr != NULL && *rr == NULL);
2189 *rr = ref;
2190 return true;
2191 }
2192
2193 /* Optimize minloc(b), where b is rank 1 array, into
2194 (/ minloc(b, dim=1) /), and similarly for maxloc,
2195 as the latter forms are expanded inline. */
2196
2197 static void
2198 optimize_minmaxloc (gfc_expr **e)
2199 {
2200 gfc_expr *fn = *e;
2201 gfc_actual_arglist *a;
2202 char *name, *p;
2203
2204 if (fn->rank != 1
2205 || fn->value.function.actual == NULL
2206 || fn->value.function.actual->expr == NULL
2207 || fn->value.function.actual->expr->rank != 1)
2208 return;
2209
2210 *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
2211 (*e)->shape = fn->shape;
2212 fn->rank = 0;
2213 fn->shape = NULL;
2214 gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
2215
2216 name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
2217 strcpy (name, fn->value.function.name);
2218 p = strstr (name, "loc0");
2219 p[3] = '1';
2220 fn->value.function.name = gfc_get_string ("%s", name);
2221 if (fn->value.function.actual->next)
2222 {
2223 a = fn->value.function.actual->next;
2224 gcc_assert (a->expr == NULL);
2225 }
2226 else
2227 {
2228 a = gfc_get_actual_arglist ();
2229 fn->value.function.actual->next = a;
2230 }
2231 a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
2232 &fn->where);
2233 mpz_set_ui (a->expr->value.integer, 1);
2234 }
2235
2236 /* Callback function for code checking that we do not pass a DO variable to an
2237 INTENT(OUT) or INTENT(INOUT) dummy variable. */
2238
2239 static int
2240 doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2241 void *data ATTRIBUTE_UNUSED)
2242 {
2243 gfc_code *co;
2244 int i;
2245 gfc_formal_arglist *f;
2246 gfc_actual_arglist *a;
2247 gfc_code *cl;
2248 do_t loop, *lp;
2249 bool seen_goto;
2250
2251 co = *c;
2252
2253 /* If the doloop_list grew, we have to truncate it here. */
2254
2255 if ((unsigned) doloop_level < doloop_list.length())
2256 doloop_list.truncate (doloop_level);
2257
2258 seen_goto = false;
2259 switch (co->op)
2260 {
2261 case EXEC_DO:
2262
2263 if (co->ext.iterator && co->ext.iterator->var)
2264 loop.c = co;
2265 else
2266 loop.c = NULL;
2267
2268 loop.branch_level = if_level + select_level;
2269 loop.seen_goto = false;
2270 doloop_list.safe_push (loop);
2271 break;
2272
2273 /* If anything could transfer control away from a suspicious
2274 subscript, make sure to set seen_goto in the current DO loop
2275 (if any). */
2276 case EXEC_GOTO:
2277 case EXEC_EXIT:
2278 case EXEC_STOP:
2279 case EXEC_ERROR_STOP:
2280 case EXEC_CYCLE:
2281 seen_goto = true;
2282 break;
2283
2284 case EXEC_OPEN:
2285 if (co->ext.open->err)
2286 seen_goto = true;
2287 break;
2288
2289 case EXEC_CLOSE:
2290 if (co->ext.close->err)
2291 seen_goto = true;
2292 break;
2293
2294 case EXEC_BACKSPACE:
2295 case EXEC_ENDFILE:
2296 case EXEC_REWIND:
2297 case EXEC_FLUSH:
2298
2299 if (co->ext.filepos->err)
2300 seen_goto = true;
2301 break;
2302
2303 case EXEC_INQUIRE:
2304 if (co->ext.filepos->err)
2305 seen_goto = true;
2306 break;
2307
2308 case EXEC_READ:
2309 case EXEC_WRITE:
2310 if (co->ext.dt->err || co->ext.dt->end || co->ext.dt->eor)
2311 seen_goto = true;
2312 break;
2313
2314 case EXEC_WAIT:
2315 if (co->ext.wait->err || co->ext.wait->end || co->ext.wait->eor)
2316 loop.seen_goto = true;
2317 break;
2318
2319 case EXEC_CALL:
2320
2321 if (co->resolved_sym == NULL)
2322 break;
2323
2324 f = gfc_sym_get_dummy_args (co->resolved_sym);
2325
2326 /* Withot a formal arglist, there is only unknown INTENT,
2327 which we don't check for. */
2328 if (f == NULL)
2329 break;
2330
2331 a = co->ext.actual;
2332
2333 while (a && f)
2334 {
2335 FOR_EACH_VEC_ELT (doloop_list, i, lp)
2336 {
2337 gfc_symbol *do_sym;
2338 cl = lp->c;
2339
2340 if (cl == NULL)
2341 break;
2342
2343 do_sym = cl->ext.iterator->var->symtree->n.sym;
2344
2345 if (a->expr && a->expr->symtree
2346 && a->expr->symtree->n.sym == do_sym)
2347 {
2348 if (f->sym->attr.intent == INTENT_OUT)
2349 gfc_error_now ("Variable %qs at %L set to undefined "
2350 "value inside loop beginning at %L as "
2351 "INTENT(OUT) argument to subroutine %qs",
2352 do_sym->name, &a->expr->where,
2353 &(doloop_list[i].c->loc),
2354 co->symtree->n.sym->name);
2355 else if (f->sym->attr.intent == INTENT_INOUT)
2356 gfc_error_now ("Variable %qs at %L not definable inside "
2357 "loop beginning at %L as INTENT(INOUT) "
2358 "argument to subroutine %qs",
2359 do_sym->name, &a->expr->where,
2360 &(doloop_list[i].c->loc),
2361 co->symtree->n.sym->name);
2362 }
2363 }
2364 a = a->next;
2365 f = f->next;
2366 }
2367 break;
2368
2369 default:
2370 break;
2371 }
2372 if (seen_goto && doloop_level > 0)
2373 doloop_list[doloop_level-1].seen_goto = true;
2374
2375 return 0;
2376 }
2377
2378 /* Callback function to warn about different things within DO loops. */
2379
2380 static int
2381 do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2382 void *data ATTRIBUTE_UNUSED)
2383 {
2384 do_t *last;
2385
2386 if (doloop_list.length () == 0)
2387 return 0;
2388
2389 if ((*e)->expr_type == EXPR_FUNCTION)
2390 do_intent (e);
2391
2392 last = &doloop_list.last();
2393 if (last->seen_goto && !warn_do_subscript)
2394 return 0;
2395
2396 if ((*e)->expr_type == EXPR_VARIABLE)
2397 do_subscript (e);
2398
2399 return 0;
2400 }
2401
2402 typedef struct
2403 {
2404 gfc_symbol *sym;
2405 mpz_t val;
2406 } insert_index_t;
2407
2408 /* Callback function - if the expression is the variable in data->sym,
2409 replace it with a constant from data->val. */
2410
2411 static int
2412 callback_insert_index (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2413 void *data)
2414 {
2415 insert_index_t *d;
2416 gfc_expr *ex, *n;
2417
2418 ex = (*e);
2419 if (ex->expr_type != EXPR_VARIABLE)
2420 return 0;
2421
2422 d = (insert_index_t *) data;
2423 if (ex->symtree->n.sym != d->sym)
2424 return 0;
2425
2426 n = gfc_get_constant_expr (BT_INTEGER, ex->ts.kind, &ex->where);
2427 mpz_set (n->value.integer, d->val);
2428
2429 gfc_free_expr (ex);
2430 *e = n;
2431 return 0;
2432 }
2433
2434 /* In the expression e, replace occurrences of the variable sym with
2435 val. If this results in a constant expression, return true and
2436 return the value in ret. Return false if the expression already
2437 is a constant. Caller has to clear ret in that case. */
2438
2439 static bool
2440 insert_index (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret)
2441 {
2442 gfc_expr *n;
2443 insert_index_t data;
2444 bool rc;
2445
2446 if (e->expr_type == EXPR_CONSTANT)
2447 return false;
2448
2449 n = gfc_copy_expr (e);
2450 data.sym = sym;
2451 mpz_init_set (data.val, val);
2452 gfc_expr_walker (&n, callback_insert_index, (void *) &data);
2453 gfc_simplify_expr (n, 0);
2454
2455 if (n->expr_type == EXPR_CONSTANT)
2456 {
2457 rc = true;
2458 mpz_init_set (ret, n->value.integer);
2459 }
2460 else
2461 rc = false;
2462
2463 mpz_clear (data.val);
2464 gfc_free_expr (n);
2465 return rc;
2466
2467 }
2468
2469 /* Check array subscripts for possible out-of-bounds accesses in DO
2470 loops with constant bounds. */
2471
2472 static int
2473 do_subscript (gfc_expr **e)
2474 {
2475 gfc_expr *v;
2476 gfc_array_ref *ar;
2477 gfc_ref *ref;
2478 int i,j;
2479 gfc_code *dl;
2480 do_t *lp;
2481
2482 v = *e;
2483 /* Constants are already checked. */
2484 if (v->expr_type == EXPR_CONSTANT)
2485 return 0;
2486
2487 for (ref = v->ref; ref; ref = ref->next)
2488 {
2489 if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT)
2490 {
2491 ar = & ref->u.ar;
2492 FOR_EACH_VEC_ELT (doloop_list, j, lp)
2493 {
2494 gfc_symbol *do_sym;
2495 mpz_t do_start, do_step, do_end;
2496 bool have_do_start, have_do_end;
2497 bool error_not_proven;
2498 int warn;
2499
2500 dl = lp->c;
2501 if (dl == NULL)
2502 break;
2503
2504 /* If we are within a branch, or a goto or equivalent
2505 was seen in the DO loop before, then we cannot prove that
2506 this expression is actually evaluated. Don't do anything
2507 unless we want to see it all. */
2508 error_not_proven = lp->seen_goto
2509 || lp->branch_level < if_level + select_level;
2510
2511 if (error_not_proven && !warn_do_subscript)
2512 break;
2513
2514 if (error_not_proven)
2515 warn = OPT_Wdo_subscript;
2516 else
2517 warn = 0;
2518
2519 do_sym = dl->ext.iterator->var->symtree->n.sym;
2520 if (do_sym->ts.type != BT_INTEGER)
2521 continue;
2522
2523 /* If we do not know about the stepsize, the loop may be zero trip.
2524 Do not warn in this case. */
2525
2526 if (dl->ext.iterator->step->expr_type == EXPR_CONSTANT)
2527 mpz_init_set (do_step, dl->ext.iterator->step->value.integer);
2528 else
2529 continue;
2530
2531 if (dl->ext.iterator->start->expr_type == EXPR_CONSTANT)
2532 {
2533 have_do_start = true;
2534 mpz_init_set (do_start, dl->ext.iterator->start->value.integer);
2535 }
2536 else
2537 have_do_start = false;
2538
2539
2540 if (dl->ext.iterator->end->expr_type == EXPR_CONSTANT)
2541 {
2542 have_do_end = true;
2543 mpz_init_set (do_end, dl->ext.iterator->end->value.integer);
2544 }
2545 else
2546 have_do_end = false;
2547
2548 if (!have_do_start && !have_do_end)
2549 return 0;
2550
2551 /* May have to correct the end value if the step does not equal
2552 one. */
2553 if (have_do_start && have_do_end && mpz_cmp_ui (do_step, 1) != 0)
2554 {
2555 mpz_t diff, rem;
2556
2557 mpz_init (diff);
2558 mpz_init (rem);
2559 mpz_sub (diff, do_end, do_start);
2560 mpz_tdiv_r (rem, diff, do_step);
2561 mpz_sub (do_end, do_end, rem);
2562 mpz_clear (diff);
2563 mpz_clear (rem);
2564 }
2565
2566 for (i = 0; i< ar->dimen; i++)
2567 {
2568 mpz_t val;
2569 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start
2570 && insert_index (ar->start[i], do_sym, do_start, val))
2571 {
2572 if (ar->as->lower[i]
2573 && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2574 && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2575 gfc_warning (warn, "Array reference at %L out of bounds "
2576 "(%ld < %ld) in loop beginning at %L",
2577 &ar->start[i]->where, mpz_get_si (val),
2578 mpz_get_si (ar->as->lower[i]->value.integer),
2579 &doloop_list[j].c->loc);
2580
2581 if (ar->as->upper[i]
2582 && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2583 && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2584 gfc_warning (warn, "Array reference at %L out of bounds "
2585 "(%ld > %ld) in loop beginning at %L",
2586 &ar->start[i]->where, mpz_get_si (val),
2587 mpz_get_si (ar->as->upper[i]->value.integer),
2588 &doloop_list[j].c->loc);
2589
2590 mpz_clear (val);
2591 }
2592
2593 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end
2594 && insert_index (ar->start[i], do_sym, do_end, val))
2595 {
2596 if (ar->as->lower[i]
2597 && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2598 && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2599 gfc_warning (warn, "Array reference at %L out of bounds "
2600 "(%ld < %ld) in loop beginning at %L",
2601 &ar->start[i]->where, mpz_get_si (val),
2602 mpz_get_si (ar->as->lower[i]->value.integer),
2603 &doloop_list[j].c->loc);
2604
2605 if (ar->as->upper[i]
2606 && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2607 && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2608 gfc_warning (warn, "Array reference at %L out of bounds "
2609 "(%ld > %ld) in loop beginning at %L",
2610 &ar->start[i]->where, mpz_get_si (val),
2611 mpz_get_si (ar->as->upper[i]->value.integer),
2612 &doloop_list[j].c->loc);
2613
2614 mpz_clear (val);
2615 }
2616 }
2617 }
2618 }
2619 }
2620 return 0;
2621 }
2622 /* Function for functions checking that we do not pass a DO variable
2623 to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
2624
2625 static int
2626 do_intent (gfc_expr **e)
2627 {
2628 gfc_formal_arglist *f;
2629 gfc_actual_arglist *a;
2630 gfc_expr *expr;
2631 gfc_code *dl;
2632 do_t *lp;
2633 int i;
2634
2635 expr = *e;
2636 if (expr->expr_type != EXPR_FUNCTION)
2637 return 0;
2638
2639 /* Intrinsic functions don't modify their arguments. */
2640
2641 if (expr->value.function.isym)
2642 return 0;
2643
2644 f = gfc_sym_get_dummy_args (expr->symtree->n.sym);
2645
2646 /* Without a formal arglist, there is only unknown INTENT,
2647 which we don't check for. */
2648 if (f == NULL)
2649 return 0;
2650
2651 a = expr->value.function.actual;
2652
2653 while (a && f)
2654 {
2655 FOR_EACH_VEC_ELT (doloop_list, i, lp)
2656 {
2657 gfc_symbol *do_sym;
2658 dl = lp->c;
2659 if (dl == NULL)
2660 break;
2661
2662 do_sym = dl->ext.iterator->var->symtree->n.sym;
2663
2664 if (a->expr && a->expr->symtree
2665 && a->expr->symtree->n.sym == do_sym)
2666 {
2667 if (f->sym->attr.intent == INTENT_OUT)
2668 gfc_error_now ("Variable %qs at %L set to undefined value "
2669 "inside loop beginning at %L as INTENT(OUT) "
2670 "argument to function %qs", do_sym->name,
2671 &a->expr->where, &doloop_list[i].c->loc,
2672 expr->symtree->n.sym->name);
2673 else if (f->sym->attr.intent == INTENT_INOUT)
2674 gfc_error_now ("Variable %qs at %L not definable inside loop"
2675 " beginning at %L as INTENT(INOUT) argument to"
2676 " function %qs", do_sym->name,
2677 &a->expr->where, &doloop_list[i].c->loc,
2678 expr->symtree->n.sym->name);
2679 }
2680 }
2681 a = a->next;
2682 f = f->next;
2683 }
2684
2685 return 0;
2686 }
2687
2688 static void
2689 doloop_warn (gfc_namespace *ns)
2690 {
2691 gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
2692 }
2693
2694 /* This selction deals with inlining calls to MATMUL. */
2695
2696 /* Replace calls to matmul outside of straight assignments with a temporary
2697 variable so that later inlining will work. */
2698
2699 static int
2700 matmul_to_var_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
2701 void *data)
2702 {
2703 gfc_expr *e, *n;
2704 bool *found = (bool *) data;
2705
2706 e = *ep;
2707
2708 if (e->expr_type != EXPR_FUNCTION
2709 || e->value.function.isym == NULL
2710 || e->value.function.isym->id != GFC_ISYM_MATMUL)
2711 return 0;
2712
2713 if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
2714 || in_where)
2715 return 0;
2716
2717 /* Check if this is already in the form c = matmul(a,b). */
2718
2719 if ((*current_code)->expr2 == e)
2720 return 0;
2721
2722 n = create_var (e, "matmul");
2723
2724 /* If create_var is unable to create a variable (for example if
2725 -fno-realloc-lhs is in force with a variable that does not have bounds
2726 known at compile-time), just return. */
2727
2728 if (n == NULL)
2729 return 0;
2730
2731 *ep = n;
2732 *found = true;
2733 return 0;
2734 }
2735
2736 /* Set current_code and associated variables so that matmul_to_var_expr can
2737 work. */
2738
2739 static int
2740 matmul_to_var_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2741 void *data ATTRIBUTE_UNUSED)
2742 {
2743 if (current_code != c)
2744 {
2745 current_code = c;
2746 inserted_block = NULL;
2747 changed_statement = NULL;
2748 }
2749
2750 return 0;
2751 }
2752
2753
2754 /* Take a statement of the shape c = matmul(a,b) and create temporaries
2755 for a and b if there is a dependency between the arguments and the
2756 result variable or if a or b are the result of calculations that cannot
2757 be handled by the inliner. */
2758
2759 static int
2760 matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2761 void *data ATTRIBUTE_UNUSED)
2762 {
2763 gfc_expr *expr1, *expr2;
2764 gfc_code *co;
2765 gfc_actual_arglist *a, *b;
2766 bool a_tmp, b_tmp;
2767 gfc_expr *matrix_a, *matrix_b;
2768 bool conjg_a, conjg_b, transpose_a, transpose_b;
2769
2770 co = *c;
2771
2772 if (co->op != EXEC_ASSIGN)
2773 return 0;
2774
2775 if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
2776 || in_where)
2777 return 0;
2778
2779 /* This has some duplication with inline_matmul_assign. This
2780 is because the creation of temporary variables could still fail,
2781 and inline_matmul_assign still needs to be able to handle these
2782 cases. */
2783 expr1 = co->expr1;
2784 expr2 = co->expr2;
2785
2786 if (expr2->expr_type != EXPR_FUNCTION
2787 || expr2->value.function.isym == NULL
2788 || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
2789 return 0;
2790
2791 a_tmp = false;
2792 a = expr2->value.function.actual;
2793 matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
2794 if (matrix_a != NULL)
2795 {
2796 if (matrix_a->expr_type == EXPR_VARIABLE
2797 && (gfc_check_dependency (matrix_a, expr1, true)
2798 || has_dimen_vector_ref (matrix_a)))
2799 a_tmp = true;
2800 }
2801 else
2802 a_tmp = true;
2803
2804 b_tmp = false;
2805 b = a->next;
2806 matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
2807 if (matrix_b != NULL)
2808 {
2809 if (matrix_b->expr_type == EXPR_VARIABLE
2810 && (gfc_check_dependency (matrix_b, expr1, true)
2811 || has_dimen_vector_ref (matrix_b)))
2812 b_tmp = true;
2813 }
2814 else
2815 b_tmp = true;
2816
2817 if (!a_tmp && !b_tmp)
2818 return 0;
2819
2820 current_code = c;
2821 inserted_block = NULL;
2822 changed_statement = NULL;
2823 if (a_tmp)
2824 {
2825 gfc_expr *at;
2826 at = create_var (a->expr,"mma");
2827 if (at)
2828 a->expr = at;
2829 }
2830 if (b_tmp)
2831 {
2832 gfc_expr *bt;
2833 bt = create_var (b->expr,"mmb");
2834 if (bt)
2835 b->expr = bt;
2836 }
2837 return 0;
2838 }
2839
2840 /* Auxiliary function to build and simplify an array inquiry function.
2841 dim is zero-based. */
2842
2843 static gfc_expr *
2844 get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim)
2845 {
2846 gfc_expr *fcn;
2847 gfc_expr *dim_arg, *kind;
2848 const char *name;
2849 gfc_expr *ec;
2850
2851 switch (id)
2852 {
2853 case GFC_ISYM_LBOUND:
2854 name = "_gfortran_lbound";
2855 break;
2856
2857 case GFC_ISYM_UBOUND:
2858 name = "_gfortran_ubound";
2859 break;
2860
2861 case GFC_ISYM_SIZE:
2862 name = "_gfortran_size";
2863 break;
2864
2865 default:
2866 gcc_unreachable ();
2867 }
2868
2869 dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
2870 kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
2871 gfc_index_integer_kind);
2872
2873 ec = gfc_copy_expr (e);
2874 fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
2875 ec, dim_arg, kind);
2876 gfc_simplify_expr (fcn, 0);
2877 return fcn;
2878 }
2879
2880 /* Builds a logical expression. */
2881
2882 static gfc_expr*
2883 build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2884 {
2885 gfc_typespec ts;
2886 gfc_expr *res;
2887
2888 ts.type = BT_LOGICAL;
2889 ts.kind = gfc_default_logical_kind;
2890 res = gfc_get_expr ();
2891 res->where = e1->where;
2892 res->expr_type = EXPR_OP;
2893 res->value.op.op = op;
2894 res->value.op.op1 = e1;
2895 res->value.op.op2 = e2;
2896 res->ts = ts;
2897
2898 return res;
2899 }
2900
2901
2902 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
2903 compatible typespecs. */
2904
2905 static gfc_expr *
2906 get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2907 {
2908 gfc_expr *res;
2909
2910 res = gfc_get_expr ();
2911 res->ts = e1->ts;
2912 res->where = e1->where;
2913 res->expr_type = EXPR_OP;
2914 res->value.op.op = op;
2915 res->value.op.op1 = e1;
2916 res->value.op.op2 = e2;
2917 gfc_simplify_expr (res, 0);
2918 return res;
2919 }
2920
2921 /* Generate the IF statement for a runtime check if we want to do inlining or
2922 not - putting in the code for both branches and putting it into the syntax
2923 tree is the caller's responsibility. For fixed array sizes, this should be
2924 removed by DCE. Only called for rank-two matrices A and B. */
2925
2926 static gfc_code *
2927 inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case)
2928 {
2929 gfc_expr *inline_limit;
2930 gfc_code *if_1, *if_2, *else_2;
2931 gfc_expr *b2, *a2, *a1, *m1, *m2;
2932 gfc_typespec ts;
2933 gfc_expr *cond;
2934
2935 gcc_assert (m_case == A2B2 || m_case == A2B2T || m_case == A2TB2);
2936
2937 /* Calculation is done in real to avoid integer overflow. */
2938
2939 inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
2940 &a->where);
2941 mpfr_set_si (inline_limit->value.real, flag_inline_matmul_limit,
2942 GFC_RND_MODE);
2943 mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, 3,
2944 GFC_RND_MODE);
2945
2946 a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2947 a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
2948 b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
2949
2950 gfc_clear_ts (&ts);
2951 ts.type = BT_REAL;
2952 ts.kind = gfc_default_real_kind;
2953 gfc_convert_type_warn (a1, &ts, 2, 0);
2954 gfc_convert_type_warn (a2, &ts, 2, 0);
2955 gfc_convert_type_warn (b2, &ts, 2, 0);
2956
2957 m1 = get_operand (INTRINSIC_TIMES, a1, a2);
2958 m2 = get_operand (INTRINSIC_TIMES, m1, b2);
2959
2960 cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
2961 gfc_simplify_expr (cond, 0);
2962
2963 else_2 = XCNEW (gfc_code);
2964 else_2->op = EXEC_IF;
2965 else_2->loc = a->where;
2966
2967 if_2 = XCNEW (gfc_code);
2968 if_2->op = EXEC_IF;
2969 if_2->expr1 = cond;
2970 if_2->loc = a->where;
2971 if_2->block = else_2;
2972
2973 if_1 = XCNEW (gfc_code);
2974 if_1->op = EXEC_IF;
2975 if_1->block = if_2;
2976 if_1->loc = a->where;
2977
2978 return if_1;
2979 }
2980
2981
2982 /* Insert code to issue a runtime error if the expressions are not equal. */
2983
2984 static gfc_code *
2985 runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
2986 {
2987 gfc_expr *cond;
2988 gfc_code *if_1, *if_2;
2989 gfc_code *c;
2990 gfc_actual_arglist *a1, *a2, *a3;
2991
2992 gcc_assert (e1->where.lb);
2993 /* Build the call to runtime_error. */
2994 c = XCNEW (gfc_code);
2995 c->op = EXEC_CALL;
2996 c->loc = e1->where;
2997
2998 /* Get a null-terminated message string. */
2999
3000 a1 = gfc_get_actual_arglist ();
3001 a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
3002 msg, strlen(msg)+1);
3003 c->ext.actual = a1;
3004
3005 /* Pass the value of the first expression. */
3006 a2 = gfc_get_actual_arglist ();
3007 a2->expr = gfc_copy_expr (e1);
3008 a1->next = a2;
3009
3010 /* Pass the value of the second expression. */
3011 a3 = gfc_get_actual_arglist ();
3012 a3->expr = gfc_copy_expr (e2);
3013 a2->next = a3;
3014
3015 gfc_check_fe_runtime_error (c->ext.actual);
3016 gfc_resolve_fe_runtime_error (c);
3017
3018 if_2 = XCNEW (gfc_code);
3019 if_2->op = EXEC_IF;
3020 if_2->loc = e1->where;
3021 if_2->next = c;
3022
3023 if_1 = XCNEW (gfc_code);
3024 if_1->op = EXEC_IF;
3025 if_1->block = if_2;
3026 if_1->loc = e1->where;
3027
3028 cond = build_logical_expr (INTRINSIC_NE, e1, e2);
3029 gfc_simplify_expr (cond, 0);
3030 if_2->expr1 = cond;
3031
3032 return if_1;
3033 }
3034
3035 /* Handle matrix reallocation. Caller is responsible to insert into
3036 the code tree.
3037
3038 For the two-dimensional case, build
3039
3040 if (allocated(c)) then
3041 if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
3042 deallocate(c)
3043 allocate (c(size(a,1), size(b,2)))
3044 end if
3045 else
3046 allocate (c(size(a,1),size(b,2)))
3047 end if
3048
3049 and for the other cases correspondingly.
3050 */
3051
3052 static gfc_code *
3053 matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
3054 enum matrix_case m_case)
3055 {
3056
3057 gfc_expr *allocated, *alloc_expr;
3058 gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
3059 gfc_code *else_alloc;
3060 gfc_code *deallocate, *allocate1, *allocate_else;
3061 gfc_array_ref *ar;
3062 gfc_expr *cond, *ne1, *ne2;
3063
3064 if (warn_realloc_lhs)
3065 gfc_warning (OPT_Wrealloc_lhs,
3066 "Code for reallocating the allocatable array at %L will "
3067 "be added", &c->where);
3068
3069 alloc_expr = gfc_copy_expr (c);
3070
3071 ar = gfc_find_array_ref (alloc_expr);
3072 gcc_assert (ar && ar->type == AR_FULL);
3073
3074 /* c comes in as a full ref. Change it into a copy and make it into an
3075 element ref so it has the right form for for ALLOCATE. In the same
3076 switch statement, also generate the size comparison for the secod IF
3077 statement. */
3078
3079 ar->type = AR_ELEMENT;
3080
3081 switch (m_case)
3082 {
3083 case A2B2:
3084 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3085 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3086 ne1 = build_logical_expr (INTRINSIC_NE,
3087 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3088 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3089 ne2 = build_logical_expr (INTRINSIC_NE,
3090 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3091 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3092 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3093 break;
3094
3095 case A2B2T:
3096 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3097 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3098
3099 ne1 = build_logical_expr (INTRINSIC_NE,
3100 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3101 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3102 ne2 = build_logical_expr (INTRINSIC_NE,
3103 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3104 get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3105 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3106 break;
3107
3108 case A2TB2:
3109
3110 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3111 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3112
3113 ne1 = build_logical_expr (INTRINSIC_NE,
3114 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3115 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3116 ne2 = build_logical_expr (INTRINSIC_NE,
3117 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3118 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3119 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3120 break;
3121
3122 case A2B1:
3123 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3124 cond = build_logical_expr (INTRINSIC_NE,
3125 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3126 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3127 break;
3128
3129 case A1B2:
3130 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3131 cond = build_logical_expr (INTRINSIC_NE,
3132 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3133 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3134 break;
3135
3136 default:
3137 gcc_unreachable();
3138
3139 }
3140
3141 gfc_simplify_expr (cond, 0);
3142
3143 /* We need two identical allocate statements in two
3144 branches of the IF statement. */
3145
3146 allocate1 = XCNEW (gfc_code);
3147 allocate1->op = EXEC_ALLOCATE;
3148 allocate1->ext.alloc.list = gfc_get_alloc ();
3149 allocate1->loc = c->where;
3150 allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
3151
3152 allocate_else = XCNEW (gfc_code);
3153 allocate_else->op = EXEC_ALLOCATE;
3154 allocate_else->ext.alloc.list = gfc_get_alloc ();
3155 allocate_else->loc = c->where;
3156 allocate_else->ext.alloc.list->expr = alloc_expr;
3157
3158 allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
3159 "_gfortran_allocated", c->where,
3160 1, gfc_copy_expr (c));
3161
3162 deallocate = XCNEW (gfc_code);
3163 deallocate->op = EXEC_DEALLOCATE;
3164 deallocate->ext.alloc.list = gfc_get_alloc ();
3165 deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
3166 deallocate->next = allocate1;
3167 deallocate->loc = c->where;
3168
3169 if_size_2 = XCNEW (gfc_code);
3170 if_size_2->op = EXEC_IF;
3171 if_size_2->expr1 = cond;
3172 if_size_2->loc = c->where;
3173 if_size_2->next = deallocate;
3174
3175 if_size_1 = XCNEW (gfc_code);
3176 if_size_1->op = EXEC_IF;
3177 if_size_1->block = if_size_2;
3178 if_size_1->loc = c->where;
3179
3180 else_alloc = XCNEW (gfc_code);
3181 else_alloc->op = EXEC_IF;
3182 else_alloc->loc = c->where;
3183 else_alloc->next = allocate_else;
3184
3185 if_alloc_2 = XCNEW (gfc_code);
3186 if_alloc_2->op = EXEC_IF;
3187 if_alloc_2->expr1 = allocated;
3188 if_alloc_2->loc = c->where;
3189 if_alloc_2->next = if_size_1;
3190 if_alloc_2->block = else_alloc;
3191
3192 if_alloc_1 = XCNEW (gfc_code);
3193 if_alloc_1->op = EXEC_IF;
3194 if_alloc_1->block = if_alloc_2;
3195 if_alloc_1->loc = c->where;
3196
3197 return if_alloc_1;
3198 }
3199
3200 /* Callback function for has_function_or_op. */
3201
3202 static int
3203 is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
3204 void *data ATTRIBUTE_UNUSED)
3205 {
3206 if ((*e) == 0)
3207 return 0;
3208 else
3209 return (*e)->expr_type == EXPR_FUNCTION
3210 || (*e)->expr_type == EXPR_OP;
3211 }
3212
3213 /* Returns true if the expression contains a function. */
3214
3215 static bool
3216 has_function_or_op (gfc_expr **e)
3217 {
3218 if (e == NULL)
3219 return false;
3220 else
3221 return gfc_expr_walker (e, is_function_or_op, NULL);
3222 }
3223
3224 /* Freeze (assign to a temporary variable) a single expression. */
3225
3226 static void
3227 freeze_expr (gfc_expr **ep)
3228 {
3229 gfc_expr *ne;
3230 if (has_function_or_op (ep))
3231 {
3232 ne = create_var (*ep, "freeze");
3233 *ep = ne;
3234 }
3235 }
3236
3237 /* Go through an expression's references and assign them to temporary
3238 variables if they contain functions. This is usually done prior to
3239 front-end scalarization to avoid multiple invocations of functions. */
3240
3241 static void
3242 freeze_references (gfc_expr *e)
3243 {
3244 gfc_ref *r;
3245 gfc_array_ref *ar;
3246 int i;
3247
3248 for (r=e->ref; r; r=r->next)
3249 {
3250 if (r->type == REF_SUBSTRING)
3251 {
3252 if (r->u.ss.start != NULL)
3253 freeze_expr (&r->u.ss.start);
3254
3255 if (r->u.ss.end != NULL)
3256 freeze_expr (&r->u.ss.end);
3257 }
3258 else if (r->type == REF_ARRAY)
3259 {
3260 ar = &r->u.ar;
3261 switch (ar->type)
3262 {
3263 case AR_FULL:
3264 break;
3265
3266 case AR_SECTION:
3267 for (i=0; i<ar->dimen; i++)
3268 {
3269 if (ar->dimen_type[i] == DIMEN_RANGE)
3270 {
3271 freeze_expr (&ar->start[i]);
3272 freeze_expr (&ar->end[i]);
3273 freeze_expr (&ar->stride[i]);
3274 }
3275 else if (ar->dimen_type[i] == DIMEN_ELEMENT)
3276 {
3277 freeze_expr (&ar->start[i]);
3278 }
3279 }
3280 break;
3281
3282 case AR_ELEMENT:
3283 for (i=0; i<ar->dimen; i++)
3284 freeze_expr (&ar->start[i]);
3285 break;
3286
3287 default:
3288 break;
3289 }
3290 }
3291 }
3292 }
3293
3294 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
3295
3296 static gfc_expr *
3297 convert_to_index_kind (gfc_expr *e)
3298 {
3299 gfc_expr *res;
3300
3301 gcc_assert (e != NULL);
3302
3303 res = gfc_copy_expr (e);
3304
3305 gcc_assert (e->ts.type == BT_INTEGER);
3306
3307 if (res->ts.kind != gfc_index_integer_kind)
3308 {
3309 gfc_typespec ts;
3310 gfc_clear_ts (&ts);
3311 ts.type = BT_INTEGER;
3312 ts.kind = gfc_index_integer_kind;
3313
3314 gfc_convert_type_warn (e, &ts, 2, 0);
3315 }
3316
3317 return res;
3318 }
3319
3320 /* Function to create a DO loop including creation of the
3321 iteration variable. gfc_expr are copied.*/
3322
3323 static gfc_code *
3324 create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
3325 gfc_namespace *ns, char *vname)
3326 {
3327
3328 char name[GFC_MAX_SYMBOL_LEN +1];
3329 gfc_symtree *symtree;
3330 gfc_symbol *symbol;
3331 gfc_expr *i;
3332 gfc_code *n, *n2;
3333
3334 /* Create an expression for the iteration variable. */
3335 if (vname)
3336 sprintf (name, "__var_%d_do_%s", var_num++, vname);
3337 else
3338 sprintf (name, "__var_%d_do", var_num++);
3339
3340
3341 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
3342 gcc_unreachable ();
3343
3344 /* Create the loop variable. */
3345
3346 symbol = symtree->n.sym;
3347 symbol->ts.type = BT_INTEGER;
3348 symbol->ts.kind = gfc_index_integer_kind;
3349 symbol->attr.flavor = FL_VARIABLE;
3350 symbol->attr.referenced = 1;
3351 symbol->attr.dimension = 0;
3352 symbol->attr.fe_temp = 1;
3353 gfc_commit_symbol (symbol);
3354
3355 i = gfc_get_expr ();
3356 i->expr_type = EXPR_VARIABLE;
3357 i->ts = symbol->ts;
3358 i->rank = 0;
3359 i->where = *where;
3360 i->symtree = symtree;
3361
3362 /* ... and the nested DO statements. */
3363 n = XCNEW (gfc_code);
3364 n->op = EXEC_DO;
3365 n->loc = *where;
3366 n->ext.iterator = gfc_get_iterator ();
3367 n->ext.iterator->var = i;
3368 n->ext.iterator->start = convert_to_index_kind (start);
3369 n->ext.iterator->end = convert_to_index_kind (end);
3370 if (step)
3371 n->ext.iterator->step = convert_to_index_kind (step);
3372 else
3373 n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
3374 where, 1);
3375
3376 n2 = XCNEW (gfc_code);
3377 n2->op = EXEC_DO;
3378 n2->loc = *where;
3379 n2->next = NULL;
3380 n->block = n2;
3381 return n;
3382 }
3383
3384 /* Get the upper bound of the DO loops for matmul along a dimension. This
3385 is one-based. */
3386
3387 static gfc_expr*
3388 get_size_m1 (gfc_expr *e, int dimen)
3389 {
3390 mpz_t size;
3391 gfc_expr *res;
3392
3393 if (gfc_array_dimen_size (e, dimen - 1, &size))
3394 {
3395 res = gfc_get_constant_expr (BT_INTEGER,
3396 gfc_index_integer_kind, &e->where);
3397 mpz_sub_ui (res->value.integer, size, 1);
3398 mpz_clear (size);
3399 }
3400 else
3401 {
3402 res = get_operand (INTRINSIC_MINUS,
3403 get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
3404 gfc_get_int_expr (gfc_index_integer_kind,
3405 &e->where, 1));
3406 gfc_simplify_expr (res, 0);
3407 }
3408
3409 return res;
3410 }
3411
3412 /* Function to return a scalarized expression. It is assumed that indices are
3413 zero based to make generation of DO loops easier. A zero as index will
3414 access the first element along a dimension. Single element references will
3415 be skipped. A NULL as an expression will be replaced by a full reference.
3416 This assumes that the index loops have gfc_index_integer_kind, and that all
3417 references have been frozen. */
3418
3419 static gfc_expr*
3420 scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
3421 {
3422 gfc_array_ref *ar;
3423 int i;
3424 int rank;
3425 gfc_expr *e;
3426 int i_index;
3427 bool was_fullref;
3428
3429 e = gfc_copy_expr(e_in);
3430
3431 rank = e->rank;
3432
3433 ar = gfc_find_array_ref (e);
3434
3435 /* We scalarize count_index variables, reducing the rank by count_index. */
3436
3437 e->rank = rank - count_index;
3438
3439 was_fullref = ar->type == AR_FULL;
3440
3441 if (e->rank == 0)
3442 ar->type = AR_ELEMENT;
3443 else
3444 ar->type = AR_SECTION;
3445
3446 /* Loop over the indices. For each index, create the expression
3447 index * stride + lbound(e, dim). */
3448
3449 i_index = 0;
3450 for (i=0; i < ar->dimen; i++)
3451 {
3452 if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
3453 {
3454 if (index[i_index] != NULL)
3455 {
3456 gfc_expr *lbound, *nindex;
3457 gfc_expr *loopvar;
3458
3459 loopvar = gfc_copy_expr (index[i_index]);
3460
3461 if (ar->stride[i])
3462 {
3463 gfc_expr *tmp;
3464
3465 tmp = gfc_copy_expr(ar->stride[i]);
3466 if (tmp->ts.kind != gfc_index_integer_kind)
3467 {
3468 gfc_typespec ts;
3469 gfc_clear_ts (&ts);
3470 ts.type = BT_INTEGER;
3471 ts.kind = gfc_index_integer_kind;
3472 gfc_convert_type (tmp, &ts, 2);
3473 }
3474 nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
3475 }
3476 else
3477 nindex = loopvar;
3478
3479 /* Calculate the lower bound of the expression. */
3480 if (ar->start[i])
3481 {
3482 lbound = gfc_copy_expr (ar->start[i]);
3483 if (lbound->ts.kind != gfc_index_integer_kind)
3484 {
3485 gfc_typespec ts;
3486 gfc_clear_ts (&ts);
3487 ts.type = BT_INTEGER;
3488 ts.kind = gfc_index_integer_kind;
3489 gfc_convert_type (lbound, &ts, 2);
3490
3491 }
3492 }
3493 else
3494 {
3495 gfc_expr *lbound_e;
3496 gfc_ref *ref;
3497
3498 lbound_e = gfc_copy_expr (e_in);
3499
3500 for (ref = lbound_e->ref; ref; ref = ref->next)
3501 if (ref->type == REF_ARRAY
3502 && (ref->u.ar.type == AR_FULL
3503 || ref->u.ar.type == AR_SECTION))
3504 break;
3505
3506 if (ref->next)
3507 {
3508 gfc_free_ref_list (ref->next);
3509 ref->next = NULL;
3510 }
3511
3512 if (!was_fullref)
3513 {
3514 /* Look at full individual sections, like a(:). The first index
3515 is the lbound of a full ref. */
3516 int j;
3517 gfc_array_ref *ar;
3518
3519 ar = &ref->u.ar;
3520 ar->type = AR_FULL;
3521 for (j = 0; j < ar->dimen; j++)
3522 {
3523 gfc_free_expr (ar->start[j]);
3524 ar->start[j] = NULL;
3525 gfc_free_expr (ar->end[j]);
3526 ar->end[j] = NULL;
3527 gfc_free_expr (ar->stride[j]);
3528 ar->stride[j] = NULL;
3529 }
3530
3531 /* We have to get rid of the shape, if there is one. Do
3532 so by freeing it and calling gfc_resolve to rebuild
3533 it, if necessary. */
3534
3535 if (lbound_e->shape)
3536 gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
3537
3538 lbound_e->rank = ar->dimen;
3539 gfc_resolve_expr (lbound_e);
3540 }
3541 lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
3542 i + 1);
3543 gfc_free_expr (lbound_e);
3544 }
3545
3546 ar->dimen_type[i] = DIMEN_ELEMENT;
3547
3548 gfc_free_expr (ar->start[i]);
3549 ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
3550
3551 gfc_free_expr (ar->end[i]);
3552 ar->end[i] = NULL;
3553 gfc_free_expr (ar->stride[i]);
3554 ar->stride[i] = NULL;
3555 gfc_simplify_expr (ar->start[i], 0);
3556 }
3557 else if (was_fullref)
3558 {
3559 gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
3560 }
3561 i_index ++;
3562 }
3563 }
3564
3565 return e;
3566 }
3567
3568 /* Helper function to check for a dimen vector as subscript. */
3569
3570 static bool
3571 has_dimen_vector_ref (gfc_expr *e)
3572 {
3573 gfc_array_ref *ar;
3574 int i;
3575
3576 ar = gfc_find_array_ref (e);
3577 gcc_assert (ar);
3578 if (ar->type == AR_FULL)
3579 return false;
3580
3581 for (i=0; i<ar->dimen; i++)
3582 if (ar->dimen_type[i] == DIMEN_VECTOR)
3583 return true;
3584
3585 return false;
3586 }
3587
3588 /* If handed an expression of the form
3589
3590 TRANSPOSE(CONJG(A))
3591
3592 check if A can be handled by matmul and return if there is an uneven number
3593 of CONJG calls. Return a pointer to the array when everything is OK, NULL
3594 otherwise. The caller has to check for the correct rank. */
3595
3596 static gfc_expr*
3597 check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
3598 {
3599 *conjg = false;
3600 *transpose = false;
3601
3602 do
3603 {
3604 if (e->expr_type == EXPR_VARIABLE)
3605 {
3606 gcc_assert (e->rank == 1 || e->rank == 2);
3607 return e;
3608 }
3609 else if (e->expr_type == EXPR_FUNCTION)
3610 {
3611 if (e->value.function.isym == NULL)
3612 return NULL;
3613
3614 if (e->value.function.isym->id == GFC_ISYM_CONJG)
3615 *conjg = !*conjg;
3616 else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE)
3617 *transpose = !*transpose;
3618 else return NULL;
3619 }
3620 else
3621 return NULL;
3622
3623 e = e->value.function.actual->expr;
3624 }
3625 while(1);
3626
3627 return NULL;
3628 }
3629
3630 /* Inline assignments of the form c = matmul(a,b).
3631 Handle only the cases currently where b and c are rank-two arrays.
3632
3633 This basically translates the code to
3634
3635 BLOCK
3636 integer i,j,k
3637 c = 0
3638 do j=0, size(b,2)-1
3639 do k=0, size(a, 2)-1
3640 do i=0, size(a, 1)-1
3641 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
3642 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
3643 a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
3644 b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
3645 end do
3646 end do
3647 end do
3648 END BLOCK
3649
3650 */
3651
3652 static int
3653 inline_matmul_assign (gfc_code **c, int *walk_subtrees,
3654 void *data ATTRIBUTE_UNUSED)
3655 {
3656 gfc_code *co = *c;
3657 gfc_expr *expr1, *expr2;
3658 gfc_expr *matrix_a, *matrix_b;
3659 gfc_actual_arglist *a, *b;
3660 gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
3661 gfc_expr *zero_e;
3662 gfc_expr *u1, *u2, *u3;
3663 gfc_expr *list[2];
3664 gfc_expr *ascalar, *bscalar, *cscalar;
3665 gfc_expr *mult;
3666 gfc_expr *var_1, *var_2, *var_3;
3667 gfc_expr *zero;
3668 gfc_namespace *ns;
3669 gfc_intrinsic_op op_times, op_plus;
3670 enum matrix_case m_case;
3671 int i;
3672 gfc_code *if_limit = NULL;
3673 gfc_code **next_code_point;
3674 bool conjg_a, conjg_b, transpose_a, transpose_b;
3675
3676 if (co->op != EXEC_ASSIGN)
3677 return 0;
3678
3679 if (in_where)
3680 return 0;
3681
3682 /* The BLOCKS generated for the temporary variables and FORALL don't
3683 mix. */
3684 if (forall_level > 0)
3685 return 0;
3686
3687 /* For now don't do anything in OpenMP workshare, it confuses
3688 its translation, which expects only the allowed statements in there.
3689 We should figure out how to parallelize this eventually. */
3690 if (in_omp_workshare)
3691 return 0;
3692
3693 expr1 = co->expr1;
3694 expr2 = co->expr2;
3695 if (expr2->expr_type != EXPR_FUNCTION
3696 || expr2->value.function.isym == NULL
3697 || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
3698 return 0;
3699
3700 current_code = c;
3701 inserted_block = NULL;
3702 changed_statement = NULL;
3703
3704 a = expr2->value.function.actual;
3705 matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
3706 if (matrix_a == NULL)
3707 return 0;
3708
3709 b = a->next;
3710 matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
3711 if (matrix_b == NULL)
3712 return 0;
3713
3714 if (has_dimen_vector_ref (expr1) || has_dimen_vector_ref (matrix_a)
3715 || has_dimen_vector_ref (matrix_b))
3716 return 0;
3717
3718 /* We do not handle data dependencies yet. */
3719 if (gfc_check_dependency (expr1, matrix_a, true)
3720 || gfc_check_dependency (expr1, matrix_b, true))
3721 return 0;
3722
3723 m_case = none;
3724 if (matrix_a->rank == 2)
3725 {
3726 if (transpose_a)
3727 {
3728 if (matrix_b->rank == 2 && !transpose_b)
3729 m_case = A2TB2;
3730 }
3731 else
3732 {
3733 if (matrix_b->rank == 1)
3734 m_case = A2B1;
3735 else /* matrix_b->rank == 2 */
3736 {
3737 if (transpose_b)
3738 m_case = A2B2T;
3739 else
3740 m_case = A2B2;
3741 }
3742 }
3743 }
3744 else /* matrix_a->rank == 1 */
3745 {
3746 if (matrix_b->rank == 2)
3747 {
3748 if (!transpose_b)
3749 m_case = A1B2;
3750 }
3751 }
3752
3753 if (m_case == none)
3754 return 0;
3755
3756 ns = insert_block ();
3757
3758 /* Assign the type of the zero expression for initializing the resulting
3759 array, and the expression (+ and * for real, integer and complex;
3760 .and. and .or for logical. */
3761
3762 switch(expr1->ts.type)
3763 {
3764 case BT_INTEGER:
3765 zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
3766 op_times = INTRINSIC_TIMES;
3767 op_plus = INTRINSIC_PLUS;
3768 break;
3769
3770 case BT_LOGICAL:
3771 op_times = INTRINSIC_AND;
3772 op_plus = INTRINSIC_OR;
3773 zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
3774 0);
3775 break;
3776 case BT_REAL:
3777 zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
3778 &expr1->where);
3779 mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
3780 op_times = INTRINSIC_TIMES;
3781 op_plus = INTRINSIC_PLUS;
3782 break;
3783
3784 case BT_COMPLEX:
3785 zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
3786 &expr1->where);
3787 mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
3788 op_times = INTRINSIC_TIMES;
3789 op_plus = INTRINSIC_PLUS;
3790
3791 break;
3792
3793 default:
3794 gcc_unreachable();
3795 }
3796
3797 current_code = &ns->code;
3798
3799 /* Freeze the references, keeping track of how many temporary variables were
3800 created. */
3801 n_vars = 0;
3802 freeze_references (matrix_a);
3803 freeze_references (matrix_b);
3804 freeze_references (expr1);
3805
3806 if (n_vars == 0)
3807 next_code_point = current_code;
3808 else
3809 {
3810 next_code_point = &ns->code;
3811 for (i=0; i<n_vars; i++)
3812 next_code_point = &(*next_code_point)->next;
3813 }
3814
3815 /* Take care of the inline flag. If the limit check evaluates to a
3816 constant, dead code elimination will eliminate the unneeded branch. */
3817
3818 if (m_case == A2B2 && flag_inline_matmul_limit > 0)
3819 {
3820 if_limit = inline_limit_check (matrix_a, matrix_b, m_case);
3821
3822 /* Insert the original statement into the else branch. */
3823 if_limit->block->block->next = co;
3824 co->next = NULL;
3825
3826 /* ... and the new ones go into the original one. */
3827 *next_code_point = if_limit;
3828 next_code_point = &if_limit->block->next;
3829 }
3830
3831 assign_zero = XCNEW (gfc_code);
3832 assign_zero->op = EXEC_ASSIGN;
3833 assign_zero->loc = co->loc;
3834 assign_zero->expr1 = gfc_copy_expr (expr1);
3835 assign_zero->expr2 = zero_e;
3836
3837 /* Handle the reallocation, if needed. */
3838 if (flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1))
3839 {
3840 gfc_code *lhs_alloc;
3841
3842 /* Only need to check a single dimension for the A2B2 case for
3843 bounds checking, the rest will be allocated. Also check this
3844 for A2B1. */
3845
3846 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && (m_case == A2B2 || m_case == A2B1))
3847 {
3848 gfc_code *test;
3849 gfc_expr *a2, *b1;
3850
3851 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3852 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3853 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3854 "in MATMUL intrinsic: Is %ld, should be %ld");
3855 *next_code_point = test;
3856 next_code_point = &test->next;
3857 }
3858
3859
3860 lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
3861
3862 *next_code_point = lhs_alloc;
3863 next_code_point = &lhs_alloc->next;
3864
3865 }
3866 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3867 {
3868 gfc_code *test;
3869 gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
3870
3871 if (m_case == A2B2 || m_case == A2B1)
3872 {
3873 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3874 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3875 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3876 "in MATMUL intrinsic: Is %ld, should be %ld");
3877 *next_code_point = test;
3878 next_code_point = &test->next;
3879
3880 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3881 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3882
3883 if (m_case == A2B2)
3884 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3885 "MATMUL intrinsic for dimension 1: "
3886 "is %ld, should be %ld");
3887 else if (m_case == A2B1)
3888 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3889 "MATMUL intrinsic: "
3890 "is %ld, should be %ld");
3891
3892
3893 *next_code_point = test;
3894 next_code_point = &test->next;
3895 }
3896 else if (m_case == A1B2)
3897 {
3898 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3899 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3900 test = runtime_error_ne (b1, a1, "Dimension of array B incorrect "
3901 "in MATMUL intrinsic: Is %ld, should be %ld");
3902 *next_code_point = test;
3903 next_code_point = &test->next;
3904
3905 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3906 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3907
3908 test = runtime_error_ne (c1, b2, "Incorrect extent in return array in "
3909 "MATMUL intrinsic: "
3910 "is %ld, should be %ld");
3911
3912 *next_code_point = test;
3913 next_code_point = &test->next;
3914 }
3915
3916 if (m_case == A2B2)
3917 {
3918 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3919 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3920 test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
3921 "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
3922
3923 *next_code_point = test;
3924 next_code_point = &test->next;
3925 }
3926
3927 if (m_case == A2B2T)
3928 {
3929 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3930 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3931 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3932 "MATMUL intrinsic for dimension 1: "
3933 "is %ld, should be %ld");
3934
3935 *next_code_point = test;
3936 next_code_point = &test->next;
3937
3938 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3939 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3940 test = runtime_error_ne (c2, b1, "Incorrect extent in return array in "
3941 "MATMUL intrinsic for dimension 2: "
3942 "is %ld, should be %ld");
3943 *next_code_point = test;
3944 next_code_point = &test->next;
3945
3946 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3947 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3948
3949 test = runtime_error_ne (b2, a2, "Incorrect extent in argument B in "
3950 "MATMUL intrnisic for dimension 2: "
3951 "is %ld, should be %ld");
3952 *next_code_point = test;
3953 next_code_point = &test->next;
3954
3955 }
3956
3957 if (m_case == A2TB2)
3958 {
3959 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3960 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3961
3962 test = runtime_error_ne (c1, a2, "Incorrect extent in return array in "
3963 "MATMUL intrinsic for dimension 1: "
3964 "is %ld, should be %ld");
3965
3966 *next_code_point = test;
3967 next_code_point = &test->next;
3968
3969 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3970 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3971 test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
3972 "MATMUL intrinsic for dimension 2: "
3973 "is %ld, should be %ld");
3974 *next_code_point = test;
3975 next_code_point = &test->next;
3976
3977 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3978 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3979
3980 test = runtime_error_ne (b1, a1, "Incorrect extent in argument B in "
3981 "MATMUL intrnisic for dimension 2: "
3982 "is %ld, should be %ld");
3983 *next_code_point = test;
3984 next_code_point = &test->next;
3985
3986 }
3987 }
3988
3989 *next_code_point = assign_zero;
3990
3991 zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
3992
3993 assign_matmul = XCNEW (gfc_code);
3994 assign_matmul->op = EXEC_ASSIGN;
3995 assign_matmul->loc = co->loc;
3996
3997 /* Get the bounds for the loops, create them and create the scalarized
3998 expressions. */
3999
4000 switch (m_case)
4001 {
4002 case A2B2:
4003 inline_limit_check (matrix_a, matrix_b, m_case);
4004
4005 u1 = get_size_m1 (matrix_b, 2);
4006 u2 = get_size_m1 (matrix_a, 2);
4007 u3 = get_size_m1 (matrix_a, 1);
4008
4009 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4010 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4011 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4012
4013 do_1->block->next = do_2;
4014 do_2->block->next = do_3;
4015 do_3->block->next = assign_matmul;
4016
4017 var_1 = do_1->ext.iterator->var;
4018 var_2 = do_2->ext.iterator->var;
4019 var_3 = do_3->ext.iterator->var;
4020
4021 list[0] = var_3;
4022 list[1] = var_1;
4023 cscalar = scalarized_expr (co->expr1, list, 2);
4024
4025 list[0] = var_3;
4026 list[1] = var_2;
4027 ascalar = scalarized_expr (matrix_a, list, 2);
4028
4029 list[0] = var_2;
4030 list[1] = var_1;
4031 bscalar = scalarized_expr (matrix_b, list, 2);
4032
4033 break;
4034
4035 case A2B2T:
4036 inline_limit_check (matrix_a, matrix_b, m_case);
4037
4038 u1 = get_size_m1 (matrix_b, 1);
4039 u2 = get_size_m1 (matrix_a, 2);
4040 u3 = get_size_m1 (matrix_a, 1);
4041
4042 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4043 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4044 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4045
4046 do_1->block->next = do_2;
4047 do_2->block->next = do_3;
4048 do_3->block->next = assign_matmul;
4049
4050 var_1 = do_1->ext.iterator->var;
4051 var_2 = do_2->ext.iterator->var;
4052 var_3 = do_3->ext.iterator->var;
4053
4054 list[0] = var_3;
4055 list[1] = var_1;
4056 cscalar = scalarized_expr (co->expr1, list, 2);
4057
4058 list[0] = var_3;
4059 list[1] = var_2;
4060 ascalar = scalarized_expr (matrix_a, list, 2);
4061
4062 list[0] = var_1;
4063 list[1] = var_2;
4064 bscalar = scalarized_expr (matrix_b, list, 2);
4065
4066 break;
4067
4068 case A2TB2:
4069 inline_limit_check (matrix_a, matrix_b, m_case);
4070
4071 u1 = get_size_m1 (matrix_a, 2);
4072 u2 = get_size_m1 (matrix_b, 2);
4073 u3 = get_size_m1 (matrix_a, 1);
4074
4075 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4076 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4077 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4078
4079 do_1->block->next = do_2;
4080 do_2->block->next = do_3;
4081 do_3->block->next = assign_matmul;
4082
4083 var_1 = do_1->ext.iterator->var;
4084 var_2 = do_2->ext.iterator->var;
4085 var_3 = do_3->ext.iterator->var;
4086
4087 list[0] = var_1;
4088 list[1] = var_2;
4089 cscalar = scalarized_expr (co->expr1, list, 2);
4090
4091 list[0] = var_3;
4092 list[1] = var_1;
4093 ascalar = scalarized_expr (matrix_a, list, 2);
4094
4095 list[0] = var_3;
4096 list[1] = var_2;
4097 bscalar = scalarized_expr (matrix_b, list, 2);
4098
4099 break;
4100
4101 case A2B1:
4102 u1 = get_size_m1 (matrix_b, 1);
4103 u2 = get_size_m1 (matrix_a, 1);
4104
4105 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4106 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4107
4108 do_1->block->next = do_2;
4109 do_2->block->next = assign_matmul;
4110
4111 var_1 = do_1->ext.iterator->var;
4112 var_2 = do_2->ext.iterator->var;
4113
4114 list[0] = var_2;
4115 cscalar = scalarized_expr (co->expr1, list, 1);
4116
4117 list[0] = var_2;
4118 list[1] = var_1;
4119 ascalar = scalarized_expr (matrix_a, list, 2);
4120
4121 list[0] = var_1;
4122 bscalar = scalarized_expr (matrix_b, list, 1);
4123
4124 break;
4125
4126 case A1B2:
4127 u1 = get_size_m1 (matrix_b, 2);
4128 u2 = get_size_m1 (matrix_a, 1);
4129
4130 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4131 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4132
4133 do_1->block->next = do_2;
4134 do_2->block->next = assign_matmul;
4135
4136 var_1 = do_1->ext.iterator->var;
4137 var_2 = do_2->ext.iterator->var;
4138
4139 list[0] = var_1;
4140 cscalar = scalarized_expr (co->expr1, list, 1);
4141
4142 list[0] = var_2;
4143 ascalar = scalarized_expr (matrix_a, list, 1);
4144
4145 list[0] = var_2;
4146 list[1] = var_1;
4147 bscalar = scalarized_expr (matrix_b, list, 2);
4148
4149 break;
4150
4151 default:
4152 gcc_unreachable();
4153 }
4154
4155 /* Build the conjg call around the variables. Set the typespec manually
4156 because gfc_build_intrinsic_call sometimes gets this wrong. */
4157 if (conjg_a)
4158 {
4159 gfc_typespec ts;
4160 ts = matrix_a->ts;
4161 ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4162 matrix_a->where, 1, ascalar);
4163 ascalar->ts = ts;
4164 }
4165
4166 if (conjg_b)
4167 {
4168 gfc_typespec ts;
4169 ts = matrix_b->ts;
4170 bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4171 matrix_b->where, 1, bscalar);
4172 bscalar->ts = ts;
4173 }
4174 /* First loop comes after the zero assignment. */
4175 assign_zero->next = do_1;
4176
4177 /* Build the assignment expression in the loop. */
4178 assign_matmul->expr1 = gfc_copy_expr (cscalar);
4179
4180 mult = get_operand (op_times, ascalar, bscalar);
4181 assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
4182
4183 /* If we don't want to keep the original statement around in
4184 the else branch, we can free it. */
4185
4186 if (if_limit == NULL)
4187 gfc_free_statements(co);
4188 else
4189 co->next = NULL;
4190
4191 gfc_free_expr (zero);
4192 *walk_subtrees = 0;
4193 return 0;
4194 }
4195
4196 #define WALK_SUBEXPR(NODE) \
4197 do \
4198 { \
4199 result = gfc_expr_walker (&(NODE), exprfn, data); \
4200 if (result) \
4201 return result; \
4202 } \
4203 while (0)
4204 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
4205
4206 /* Walk expression *E, calling EXPRFN on each expression in it. */
4207
4208 int
4209 gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
4210 {
4211 while (*e)
4212 {
4213 int walk_subtrees = 1;
4214 gfc_actual_arglist *a;
4215 gfc_ref *r;
4216 gfc_constructor *c;
4217
4218 int result = exprfn (e, &walk_subtrees, data);
4219 if (result)
4220 return result;
4221 if (walk_subtrees)
4222 switch ((*e)->expr_type)
4223 {
4224 case EXPR_OP:
4225 WALK_SUBEXPR ((*e)->value.op.op1);
4226 WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
4227 break;
4228 case EXPR_FUNCTION:
4229 for (a = (*e)->value.function.actual; a; a = a->next)
4230 WALK_SUBEXPR (a->expr);
4231 break;
4232 case EXPR_COMPCALL:
4233 case EXPR_PPC:
4234 WALK_SUBEXPR ((*e)->value.compcall.base_object);
4235 for (a = (*e)->value.compcall.actual; a; a = a->next)
4236 WALK_SUBEXPR (a->expr);
4237 break;
4238
4239 case EXPR_STRUCTURE:
4240 case EXPR_ARRAY:
4241 for (c = gfc_constructor_first ((*e)->value.constructor); c;
4242 c = gfc_constructor_next (c))
4243 {
4244 if (c->iterator == NULL)
4245 WALK_SUBEXPR (c->expr);
4246 else
4247 {
4248 iterator_level ++;
4249 WALK_SUBEXPR (c->expr);
4250 iterator_level --;
4251 WALK_SUBEXPR (c->iterator->var);
4252 WALK_SUBEXPR (c->iterator->start);
4253 WALK_SUBEXPR (c->iterator->end);
4254 WALK_SUBEXPR (c->iterator->step);
4255 }
4256 }
4257
4258 if ((*e)->expr_type != EXPR_ARRAY)
4259 break;
4260
4261 /* Fall through to the variable case in order to walk the
4262 reference. */
4263 gcc_fallthrough ();
4264
4265 case EXPR_SUBSTRING:
4266 case EXPR_VARIABLE:
4267 for (r = (*e)->ref; r; r = r->next)
4268 {
4269 gfc_array_ref *ar;
4270 int i;
4271
4272 switch (r->type)
4273 {
4274 case REF_ARRAY:
4275 ar = &r->u.ar;
4276 if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
4277 {
4278 for (i=0; i< ar->dimen; i++)
4279 {
4280 WALK_SUBEXPR (ar->start[i]);
4281 WALK_SUBEXPR (ar->end[i]);
4282 WALK_SUBEXPR (ar->stride[i]);
4283 }
4284 }
4285
4286 break;
4287
4288 case REF_SUBSTRING:
4289 WALK_SUBEXPR (r->u.ss.start);
4290 WALK_SUBEXPR (r->u.ss.end);
4291 break;
4292
4293 case REF_COMPONENT:
4294 break;
4295 }
4296 }
4297
4298 default:
4299 break;
4300 }
4301 return 0;
4302 }
4303 return 0;
4304 }
4305
4306 #define WALK_SUBCODE(NODE) \
4307 do \
4308 { \
4309 result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
4310 if (result) \
4311 return result; \
4312 } \
4313 while (0)
4314
4315 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
4316 on each expression in it. If any of the hooks returns non-zero, that
4317 value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
4318 no subcodes or subexpressions are traversed. */
4319
4320 int
4321 gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
4322 void *data)
4323 {
4324 for (; *c; c = &(*c)->next)
4325 {
4326 int walk_subtrees = 1;
4327 int result = codefn (c, &walk_subtrees, data);
4328 if (result)
4329 return result;
4330
4331 if (walk_subtrees)
4332 {
4333 gfc_code *b;
4334 gfc_actual_arglist *a;
4335 gfc_code *co;
4336 gfc_association_list *alist;
4337 bool saved_in_omp_workshare;
4338 bool saved_in_where;
4339
4340 /* There might be statement insertions before the current code,
4341 which must not affect the expression walker. */
4342
4343 co = *c;
4344 saved_in_omp_workshare = in_omp_workshare;
4345 saved_in_where = in_where;
4346
4347 switch (co->op)
4348 {
4349
4350 case EXEC_BLOCK:
4351 WALK_SUBCODE (co->ext.block.ns->code);
4352 if (co->ext.block.assoc)
4353 {
4354 bool saved_in_assoc_list = in_assoc_list;
4355
4356 in_assoc_list = true;
4357 for (alist = co->ext.block.assoc; alist; alist = alist->next)
4358 WALK_SUBEXPR (alist->target);
4359
4360 in_assoc_list = saved_in_assoc_list;
4361 }
4362
4363 break;
4364
4365 case EXEC_DO:
4366 doloop_level ++;
4367 WALK_SUBEXPR (co->ext.iterator->var);
4368 WALK_SUBEXPR (co->ext.iterator->start);
4369 WALK_SUBEXPR (co->ext.iterator->end);
4370 WALK_SUBEXPR (co->ext.iterator->step);
4371 break;
4372
4373 case EXEC_IF:
4374 if_level ++;
4375 break;
4376
4377 case EXEC_WHERE:
4378 in_where = true;
4379 break;
4380
4381 case EXEC_CALL:
4382 case EXEC_ASSIGN_CALL:
4383 for (a = co->ext.actual; a; a = a->next)
4384 WALK_SUBEXPR (a->expr);
4385 break;
4386
4387 case EXEC_CALL_PPC:
4388 WALK_SUBEXPR (co->expr1);
4389 for (a = co->ext.actual; a; a = a->next)
4390 WALK_SUBEXPR (a->expr);
4391 break;
4392
4393 case EXEC_SELECT:
4394 WALK_SUBEXPR (co->expr1);
4395 select_level ++;
4396 for (b = co->block; b; b = b->block)
4397 {
4398 gfc_case *cp;
4399 for (cp = b->ext.block.case_list; cp; cp = cp->next)
4400 {
4401 WALK_SUBEXPR (cp->low);
4402 WALK_SUBEXPR (cp->high);
4403 }
4404 WALK_SUBCODE (b->next);
4405 }
4406 continue;
4407
4408 case EXEC_ALLOCATE:
4409 case EXEC_DEALLOCATE:
4410 {
4411 gfc_alloc *a;
4412 for (a = co->ext.alloc.list; a; a = a->next)
4413 WALK_SUBEXPR (a->expr);
4414 break;
4415 }
4416
4417 case EXEC_FORALL:
4418 case EXEC_DO_CONCURRENT:
4419 {
4420 gfc_forall_iterator *fa;
4421 for (fa = co->ext.forall_iterator; fa; fa = fa->next)
4422 {
4423 WALK_SUBEXPR (fa->var);
4424 WALK_SUBEXPR (fa->start);
4425 WALK_SUBEXPR (fa->end);
4426 WALK_SUBEXPR (fa->stride);
4427 }
4428 if (co->op == EXEC_FORALL)
4429 forall_level ++;
4430 break;
4431 }
4432
4433 case EXEC_OPEN:
4434 WALK_SUBEXPR (co->ext.open->unit);
4435 WALK_SUBEXPR (co->ext.open->file);
4436 WALK_SUBEXPR (co->ext.open->status);
4437 WALK_SUBEXPR (co->ext.open->access);
4438 WALK_SUBEXPR (co->ext.open->form);
4439 WALK_SUBEXPR (co->ext.open->recl);
4440 WALK_SUBEXPR (co->ext.open->blank);
4441 WALK_SUBEXPR (co->ext.open->position);
4442 WALK_SUBEXPR (co->ext.open->action);
4443 WALK_SUBEXPR (co->ext.open->delim);
4444 WALK_SUBEXPR (co->ext.open->pad);
4445 WALK_SUBEXPR (co->ext.open->iostat);
4446 WALK_SUBEXPR (co->ext.open->iomsg);
4447 WALK_SUBEXPR (co->ext.open->convert);
4448 WALK_SUBEXPR (co->ext.open->decimal);
4449 WALK_SUBEXPR (co->ext.open->encoding);
4450 WALK_SUBEXPR (co->ext.open->round);
4451 WALK_SUBEXPR (co->ext.open->sign);
4452 WALK_SUBEXPR (co->ext.open->asynchronous);
4453 WALK_SUBEXPR (co->ext.open->id);
4454 WALK_SUBEXPR (co->ext.open->newunit);
4455 WALK_SUBEXPR (co->ext.open->share);
4456 WALK_SUBEXPR (co->ext.open->cc);
4457 break;
4458
4459 case EXEC_CLOSE:
4460 WALK_SUBEXPR (co->ext.close->unit);
4461 WALK_SUBEXPR (co->ext.close->status);
4462 WALK_SUBEXPR (co->ext.close->iostat);
4463 WALK_SUBEXPR (co->ext.close->iomsg);
4464 break;
4465
4466 case EXEC_BACKSPACE:
4467 case EXEC_ENDFILE:
4468 case EXEC_REWIND:
4469 case EXEC_FLUSH:
4470 WALK_SUBEXPR (co->ext.filepos->unit);
4471 WALK_SUBEXPR (co->ext.filepos->iostat);
4472 WALK_SUBEXPR (co->ext.filepos->iomsg);
4473 break;
4474
4475 case EXEC_INQUIRE:
4476 WALK_SUBEXPR (co->ext.inquire->unit);
4477 WALK_SUBEXPR (co->ext.inquire->file);
4478 WALK_SUBEXPR (co->ext.inquire->iomsg);
4479 WALK_SUBEXPR (co->ext.inquire->iostat);
4480 WALK_SUBEXPR (co->ext.inquire->exist);
4481 WALK_SUBEXPR (co->ext.inquire->opened);
4482 WALK_SUBEXPR (co->ext.inquire->number);
4483 WALK_SUBEXPR (co->ext.inquire->named);
4484 WALK_SUBEXPR (co->ext.inquire->name);
4485 WALK_SUBEXPR (co->ext.inquire->access);
4486 WALK_SUBEXPR (co->ext.inquire->sequential);
4487 WALK_SUBEXPR (co->ext.inquire->direct);
4488 WALK_SUBEXPR (co->ext.inquire->form);
4489 WALK_SUBEXPR (co->ext.inquire->formatted);
4490 WALK_SUBEXPR (co->ext.inquire->unformatted);
4491 WALK_SUBEXPR (co->ext.inquire->recl);
4492 WALK_SUBEXPR (co->ext.inquire->nextrec);
4493 WALK_SUBEXPR (co->ext.inquire->blank);
4494 WALK_SUBEXPR (co->ext.inquire->position);
4495 WALK_SUBEXPR (co->ext.inquire->action);
4496 WALK_SUBEXPR (co->ext.inquire->read);
4497 WALK_SUBEXPR (co->ext.inquire->write);
4498 WALK_SUBEXPR (co->ext.inquire->readwrite);
4499 WALK_SUBEXPR (co->ext.inquire->delim);
4500 WALK_SUBEXPR (co->ext.inquire->encoding);
4501 WALK_SUBEXPR (co->ext.inquire->pad);
4502 WALK_SUBEXPR (co->ext.inquire->iolength);
4503 WALK_SUBEXPR (co->ext.inquire->convert);
4504 WALK_SUBEXPR (co->ext.inquire->strm_pos);
4505 WALK_SUBEXPR (co->ext.inquire->asynchronous);
4506 WALK_SUBEXPR (co->ext.inquire->decimal);
4507 WALK_SUBEXPR (co->ext.inquire->pending);
4508 WALK_SUBEXPR (co->ext.inquire->id);
4509 WALK_SUBEXPR (co->ext.inquire->sign);
4510 WALK_SUBEXPR (co->ext.inquire->size);
4511 WALK_SUBEXPR (co->ext.inquire->round);
4512 break;
4513
4514 case EXEC_WAIT:
4515 WALK_SUBEXPR (co->ext.wait->unit);
4516 WALK_SUBEXPR (co->ext.wait->iostat);
4517 WALK_SUBEXPR (co->ext.wait->iomsg);
4518 WALK_SUBEXPR (co->ext.wait->id);
4519 break;
4520
4521 case EXEC_READ:
4522 case EXEC_WRITE:
4523 WALK_SUBEXPR (co->ext.dt->io_unit);
4524 WALK_SUBEXPR (co->ext.dt->format_expr);
4525 WALK_SUBEXPR (co->ext.dt->rec);
4526 WALK_SUBEXPR (co->ext.dt->advance);
4527 WALK_SUBEXPR (co->ext.dt->iostat);
4528 WALK_SUBEXPR (co->ext.dt->size);
4529 WALK_SUBEXPR (co->ext.dt->iomsg);
4530 WALK_SUBEXPR (co->ext.dt->id);
4531 WALK_SUBEXPR (co->ext.dt->pos);
4532 WALK_SUBEXPR (co->ext.dt->asynchronous);
4533 WALK_SUBEXPR (co->ext.dt->blank);
4534 WALK_SUBEXPR (co->ext.dt->decimal);
4535 WALK_SUBEXPR (co->ext.dt->delim);
4536 WALK_SUBEXPR (co->ext.dt->pad);
4537 WALK_SUBEXPR (co->ext.dt->round);
4538 WALK_SUBEXPR (co->ext.dt->sign);
4539 WALK_SUBEXPR (co->ext.dt->extra_comma);
4540 break;
4541
4542 case EXEC_OMP_PARALLEL:
4543 case EXEC_OMP_PARALLEL_DO:
4544 case EXEC_OMP_PARALLEL_DO_SIMD:
4545 case EXEC_OMP_PARALLEL_SECTIONS:
4546
4547 in_omp_workshare = false;
4548
4549 /* This goto serves as a shortcut to avoid code
4550 duplication or a larger if or switch statement. */
4551 goto check_omp_clauses;
4552
4553 case EXEC_OMP_WORKSHARE:
4554 case EXEC_OMP_PARALLEL_WORKSHARE:
4555
4556 in_omp_workshare = true;
4557
4558 /* Fall through */
4559
4560 case EXEC_OMP_CRITICAL:
4561 case EXEC_OMP_DISTRIBUTE:
4562 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4563 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4564 case EXEC_OMP_DISTRIBUTE_SIMD:
4565 case EXEC_OMP_DO:
4566 case EXEC_OMP_DO_SIMD:
4567 case EXEC_OMP_ORDERED:
4568 case EXEC_OMP_SECTIONS:
4569 case EXEC_OMP_SINGLE:
4570 case EXEC_OMP_END_SINGLE:
4571 case EXEC_OMP_SIMD:
4572 case EXEC_OMP_TASKLOOP:
4573 case EXEC_OMP_TASKLOOP_SIMD:
4574 case EXEC_OMP_TARGET:
4575 case EXEC_OMP_TARGET_DATA:
4576 case EXEC_OMP_TARGET_ENTER_DATA:
4577 case EXEC_OMP_TARGET_EXIT_DATA:
4578 case EXEC_OMP_TARGET_PARALLEL:
4579 case EXEC_OMP_TARGET_PARALLEL_DO:
4580 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
4581 case EXEC_OMP_TARGET_SIMD:
4582 case EXEC_OMP_TARGET_TEAMS:
4583 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4584 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4585 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4586 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4587 case EXEC_OMP_TARGET_UPDATE:
4588 case EXEC_OMP_TASK:
4589 case EXEC_OMP_TEAMS:
4590 case EXEC_OMP_TEAMS_DISTRIBUTE:
4591 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4592 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4593 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
4594
4595 /* Come to this label only from the
4596 EXEC_OMP_PARALLEL_* cases above. */
4597
4598 check_omp_clauses:
4599
4600 if (co->ext.omp_clauses)
4601 {
4602 gfc_omp_namelist *n;
4603 static int list_types[]
4604 = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
4605 OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
4606 size_t idx;
4607 WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
4608 WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
4609 WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
4610 WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
4611 WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
4612 WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
4613 WALK_SUBEXPR (co->ext.omp_clauses->num_teams);
4614 WALK_SUBEXPR (co->ext.omp_clauses->device);
4615 WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
4616 WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
4617 WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
4618 WALK_SUBEXPR (co->ext.omp_clauses->hint);
4619 WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
4620 WALK_SUBEXPR (co->ext.omp_clauses->priority);
4621 for (idx = 0; idx < OMP_IF_LAST; idx++)
4622 WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
4623 for (idx = 0;
4624 idx < sizeof (list_types) / sizeof (list_types[0]);
4625 idx++)
4626 for (n = co->ext.omp_clauses->lists[list_types[idx]];
4627 n; n = n->next)
4628 WALK_SUBEXPR (n->expr);
4629 }
4630 break;
4631 default:
4632 break;
4633 }
4634
4635 WALK_SUBEXPR (co->expr1);
4636 WALK_SUBEXPR (co->expr2);
4637 WALK_SUBEXPR (co->expr3);
4638 WALK_SUBEXPR (co->expr4);
4639 for (b = co->block; b; b = b->block)
4640 {
4641 WALK_SUBEXPR (b->expr1);
4642 WALK_SUBEXPR (b->expr2);
4643 WALK_SUBCODE (b->next);
4644 }
4645
4646 if (co->op == EXEC_FORALL)
4647 forall_level --;
4648
4649 if (co->op == EXEC_DO)
4650 doloop_level --;
4651
4652 if (co->op == EXEC_IF)
4653 if_level --;
4654
4655 if (co->op == EXEC_SELECT)
4656 select_level --;
4657
4658 in_omp_workshare = saved_in_omp_workshare;
4659 in_where = saved_in_where;
4660 }
4661 }
4662 return 0;
4663 }