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