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