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