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