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