2016-08-25 Steven g. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / frontend-passes.c
blobc138f4d7c77beb071c1523d1eb62113e20be4287
1 /* Pass manager for Fortran front end.
2 Copyright (C) 2010-2016 Free Software Foundation, Inc.
3 Contributed by Thomas König.
5 This file is part of GCC.
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.
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.
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/>. */
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"
30 /* Forward declarations. */
32 static void strip_function_call (gfc_expr *);
33 static void optimize_namespace (gfc_namespace *);
34 static void optimize_assignment (gfc_code *);
35 static bool optimize_op (gfc_expr *);
36 static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op);
37 static bool optimize_trim (gfc_expr *);
38 static bool optimize_lexical_comparison (gfc_expr *);
39 static void optimize_minmaxloc (gfc_expr **);
40 static bool is_empty_string (gfc_expr *e);
41 static void doloop_warn (gfc_namespace *);
42 static void optimize_reduction (gfc_namespace *);
43 static int callback_reduction (gfc_expr **, int *, void *);
44 static void realloc_strings (gfc_namespace *);
45 static gfc_expr *create_var (gfc_expr *, const char *vname=NULL);
46 static int inline_matmul_assign (gfc_code **, int *, void *);
47 static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
48 locus *, gfc_namespace *,
49 char *vname=NULL);
51 /* How deep we are inside an argument list. */
53 static int count_arglist;
55 /* Vector of gfc_expr ** we operate on. */
57 static vec<gfc_expr **> expr_array;
59 /* Pointer to the gfc_code we currently work on - to be able to insert
60 a block before the statement. */
62 static gfc_code **current_code;
64 /* Pointer to the block to be inserted, and the statement we are
65 changing within the block. */
67 static gfc_code *inserted_block, **changed_statement;
69 /* The namespace we are currently dealing with. */
71 static gfc_namespace *current_ns;
73 /* If we are within any forall loop. */
75 static int forall_level;
77 /* Keep track of whether we are within an OMP workshare. */
79 static bool in_omp_workshare;
81 /* Keep track of whether we are within a WHERE statement. */
83 static bool in_where;
85 /* Keep track of iterators for array constructors. */
87 static int iterator_level;
89 /* Keep track of DO loop levels. */
91 static vec<gfc_code *> doloop_list;
93 static int doloop_level;
95 /* Vector of gfc_expr * to keep track of DO loops. */
97 struct my_struct *evec;
99 /* Keep track of association lists. */
101 static bool in_assoc_list;
103 /* Counter for temporary variables. */
105 static int var_num = 1;
107 /* What sort of matrix we are dealing with when inlining MATMUL. */
109 enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T };
111 /* Keep track of the number of expressions we have inserted so far
112 using create_var. */
114 int n_vars;
116 /* Entry point - run all passes for a namespace. */
118 void
119 gfc_run_passes (gfc_namespace *ns)
122 /* Warn about dubious DO loops where the index might
123 change. */
125 doloop_level = 0;
126 doloop_warn (ns);
127 doloop_list.release ();
128 int w, e;
130 if (flag_frontend_optimize)
132 optimize_namespace (ns);
133 optimize_reduction (ns);
134 if (flag_dump_fortran_optimized)
135 gfc_dump_parse_tree (ns, stdout);
137 expr_array.release ();
140 gfc_get_errors (&w, &e);
141 if (e > 0)
142 return;
144 if (flag_realloc_lhs)
145 realloc_strings (ns);
148 /* Callback for each gfc_code node invoked from check_realloc_strings.
149 For an allocatable LHS string which also appears as a variable on
150 the RHS, replace
152 a = a(x:y)
154 with
156 tmp = a(x:y)
157 a = tmp
160 static int
161 realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
162 void *data ATTRIBUTE_UNUSED)
164 gfc_expr *expr1, *expr2;
165 gfc_code *co = *c;
166 gfc_expr *n;
168 if (co->op != EXEC_ASSIGN)
169 return 0;
171 expr1 = co->expr1;
172 if (expr1->ts.type != BT_CHARACTER || expr1->rank != 0
173 || !expr1->symtree->n.sym->attr.allocatable)
174 return 0;
176 expr2 = gfc_discard_nops (co->expr2);
177 if (expr2->expr_type != EXPR_VARIABLE)
178 return 0;
180 if (!gfc_check_dependency (expr1, expr2, true))
181 return 0;
183 /* gfc_check_dependency doesn't always pick up identical expressions.
184 However, eliminating the above sends the compiler into an infinite
185 loop on valid expressions. Without this check, the gimplifier emits
186 an ICE for a = a, where a is deferred character length. */
187 if (!gfc_dep_compare_expr (expr1, expr2))
188 return 0;
190 current_code = c;
191 inserted_block = NULL;
192 changed_statement = NULL;
193 n = create_var (expr2, "trim");
194 co->expr2 = n;
195 return 0;
198 /* Callback for each gfc_code node invoked through gfc_code_walker
199 from optimize_namespace. */
201 static int
202 optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
203 void *data ATTRIBUTE_UNUSED)
206 gfc_exec_op op;
208 op = (*c)->op;
210 if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL
211 || op == EXEC_CALL_PPC)
212 count_arglist = 1;
213 else
214 count_arglist = 0;
216 current_code = c;
217 inserted_block = NULL;
218 changed_statement = NULL;
220 if (op == EXEC_ASSIGN)
221 optimize_assignment (*c);
222 return 0;
225 /* Callback for each gfc_expr node invoked through gfc_code_walker
226 from optimize_namespace. */
228 static int
229 optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
230 void *data ATTRIBUTE_UNUSED)
232 bool function_expr;
234 if ((*e)->expr_type == EXPR_FUNCTION)
236 count_arglist ++;
237 function_expr = true;
239 else
240 function_expr = false;
242 if (optimize_trim (*e))
243 gfc_simplify_expr (*e, 0);
245 if (optimize_lexical_comparison (*e))
246 gfc_simplify_expr (*e, 0);
248 if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
249 gfc_simplify_expr (*e, 0);
251 if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym)
252 switch ((*e)->value.function.isym->id)
254 case GFC_ISYM_MINLOC:
255 case GFC_ISYM_MAXLOC:
256 optimize_minmaxloc (e);
257 break;
258 default:
259 break;
262 if (function_expr)
263 count_arglist --;
265 return 0;
268 /* Auxiliary function to handle the arguments to reduction intrnisics. If the
269 function is a scalar, just copy it; otherwise returns the new element, the
270 old one can be freed. */
272 static gfc_expr *
273 copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn)
275 gfc_expr *fcn, *e = c->expr;
277 fcn = gfc_copy_expr (e);
278 if (c->iterator)
280 gfc_constructor_base newbase;
281 gfc_expr *new_expr;
282 gfc_constructor *new_c;
284 newbase = NULL;
285 new_expr = gfc_get_expr ();
286 new_expr->expr_type = EXPR_ARRAY;
287 new_expr->ts = e->ts;
288 new_expr->where = e->where;
289 new_expr->rank = 1;
290 new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where));
291 new_c->iterator = c->iterator;
292 new_expr->value.constructor = newbase;
293 c->iterator = NULL;
295 fcn = new_expr;
298 if (fcn->rank != 0)
300 gfc_isym_id id = fn->value.function.isym->id;
302 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
303 fcn = gfc_build_intrinsic_call (current_ns, id,
304 fn->value.function.isym->name,
305 fn->where, 3, fcn, NULL, NULL);
306 else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL)
307 fcn = gfc_build_intrinsic_call (current_ns, id,
308 fn->value.function.isym->name,
309 fn->where, 2, fcn, NULL);
310 else
311 gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
313 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
316 return fcn;
319 /* Callback function for optimzation of reductions to scalars. Transform ANY
320 ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
321 correspondingly. Handly only the simple cases without MASK and DIM. */
323 static int
324 callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
325 void *data ATTRIBUTE_UNUSED)
327 gfc_expr *fn, *arg;
328 gfc_intrinsic_op op;
329 gfc_isym_id id;
330 gfc_actual_arglist *a;
331 gfc_actual_arglist *dim;
332 gfc_constructor *c;
333 gfc_expr *res, *new_expr;
334 gfc_actual_arglist *mask;
336 fn = *e;
338 if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
339 || fn->value.function.isym == NULL)
340 return 0;
342 id = fn->value.function.isym->id;
344 if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
345 && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
346 return 0;
348 a = fn->value.function.actual;
350 /* Don't handle MASK or DIM. */
352 dim = a->next;
354 if (dim->expr != NULL)
355 return 0;
357 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
359 mask = dim->next;
360 if ( mask->expr != NULL)
361 return 0;
364 arg = a->expr;
366 if (arg->expr_type != EXPR_ARRAY)
367 return 0;
369 switch (id)
371 case GFC_ISYM_SUM:
372 op = INTRINSIC_PLUS;
373 break;
375 case GFC_ISYM_PRODUCT:
376 op = INTRINSIC_TIMES;
377 break;
379 case GFC_ISYM_ANY:
380 op = INTRINSIC_OR;
381 break;
383 case GFC_ISYM_ALL:
384 op = INTRINSIC_AND;
385 break;
387 default:
388 return 0;
391 c = gfc_constructor_first (arg->value.constructor);
393 /* Don't do any simplififcation if we have
394 - no element in the constructor or
395 - only have a single element in the array which contains an
396 iterator. */
398 if (c == NULL)
399 return 0;
401 res = copy_walk_reduction_arg (c, fn);
403 c = gfc_constructor_next (c);
404 while (c)
406 new_expr = gfc_get_expr ();
407 new_expr->ts = fn->ts;
408 new_expr->expr_type = EXPR_OP;
409 new_expr->rank = fn->rank;
410 new_expr->where = fn->where;
411 new_expr->value.op.op = op;
412 new_expr->value.op.op1 = res;
413 new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn);
414 res = new_expr;
415 c = gfc_constructor_next (c);
418 gfc_simplify_expr (res, 0);
419 *e = res;
420 gfc_free_expr (fn);
422 return 0;
425 /* Callback function for common function elimination, called from cfe_expr_0.
426 Put all eligible function expressions into expr_array. */
428 static int
429 cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
430 void *data ATTRIBUTE_UNUSED)
433 if ((*e)->expr_type != EXPR_FUNCTION)
434 return 0;
436 /* We don't do character functions with unknown charlens. */
437 if ((*e)->ts.type == BT_CHARACTER
438 && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
439 || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
440 return 0;
442 /* We don't do function elimination within FORALL statements, it can
443 lead to wrong-code in certain circumstances. */
445 if (forall_level > 0)
446 return 0;
448 /* Function elimination inside an iterator could lead to functions which
449 depend on iterator variables being moved outside. FIXME: We should check
450 if the functions do indeed depend on the iterator variable. */
452 if (iterator_level > 0)
453 return 0;
455 /* If we don't know the shape at compile time, we create an allocatable
456 temporary variable to hold the intermediate result, but only if
457 allocation on assignment is active. */
459 if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
460 return 0;
462 /* Skip the test for pure functions if -faggressive-function-elimination
463 is specified. */
464 if ((*e)->value.function.esym)
466 /* Don't create an array temporary for elemental functions. */
467 if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0)
468 return 0;
470 /* Only eliminate potentially impure functions if the
471 user specifically requested it. */
472 if (!flag_aggressive_function_elimination
473 && !(*e)->value.function.esym->attr.pure
474 && !(*e)->value.function.esym->attr.implicit_pure)
475 return 0;
478 if ((*e)->value.function.isym)
480 /* Conversions are handled on the fly by the middle end,
481 transpose during trans-* stages and TRANSFER by the middle end. */
482 if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION
483 || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER
484 || gfc_inline_intrinsic_function_p (*e))
485 return 0;
487 /* Don't create an array temporary for elemental functions,
488 as this would be wasteful of memory.
489 FIXME: Create a scalar temporary during scalarization. */
490 if ((*e)->value.function.isym->elemental && (*e)->rank > 0)
491 return 0;
493 if (!(*e)->value.function.isym->pure)
494 return 0;
497 expr_array.safe_push (e);
498 return 0;
501 /* Auxiliary function to check if an expression is a temporary created by
502 create var. */
504 static bool
505 is_fe_temp (gfc_expr *e)
507 if (e->expr_type != EXPR_VARIABLE)
508 return false;
510 return e->symtree->n.sym->attr.fe_temp;
513 /* Determine the length of a string, if it can be evaluated as a constant
514 expression. Return a newly allocated gfc_expr or NULL on failure.
515 If the user specified a substring which is potentially longer than
516 the string itself, the string will be padded with spaces, which
517 is harmless. */
519 static gfc_expr *
520 constant_string_length (gfc_expr *e)
523 gfc_expr *length;
524 gfc_ref *ref;
525 gfc_expr *res;
526 mpz_t value;
528 if (e->ts.u.cl)
530 length = e->ts.u.cl->length;
531 if (length && length->expr_type == EXPR_CONSTANT)
532 return gfc_copy_expr(length);
535 /* Return length of substring, if constant. */
536 for (ref = e->ref; ref; ref = ref->next)
538 if (ref->type == REF_SUBSTRING
539 && gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value))
541 res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
542 &e->where);
544 mpz_add_ui (res->value.integer, value, 1);
545 mpz_clear (value);
546 return res;
550 /* Return length of char symbol, if constant. */
552 if (e->symtree->n.sym->ts.u.cl && e->symtree->n.sym->ts.u.cl->length
553 && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
554 return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length);
556 return NULL;
560 /* Insert a block at the current position unless it has already
561 been inserted; in this case use the one already there. */
563 static gfc_namespace*
564 insert_block ()
566 gfc_namespace *ns;
568 /* If the block hasn't already been created, do so. */
569 if (inserted_block == NULL)
571 inserted_block = XCNEW (gfc_code);
572 inserted_block->op = EXEC_BLOCK;
573 inserted_block->loc = (*current_code)->loc;
574 ns = gfc_build_block_ns (current_ns);
575 inserted_block->ext.block.ns = ns;
576 inserted_block->ext.block.assoc = NULL;
578 ns->code = *current_code;
580 /* If the statement has a label, make sure it is transferred to
581 the newly created block. */
583 if ((*current_code)->here)
585 inserted_block->here = (*current_code)->here;
586 (*current_code)->here = NULL;
589 inserted_block->next = (*current_code)->next;
590 changed_statement = &(inserted_block->ext.block.ns->code);
591 (*current_code)->next = NULL;
592 /* Insert the BLOCK at the right position. */
593 *current_code = inserted_block;
594 ns->parent = current_ns;
596 else
597 ns = inserted_block->ext.block.ns;
599 return ns;
602 /* Returns a new expression (a variable) to be used in place of the old one,
603 with an optional assignment statement before the current statement to set
604 the value of the variable. Creates a new BLOCK for the statement if that
605 hasn't already been done and puts the statement, plus the newly created
606 variables, in that block. Special cases: If the expression is constant or
607 a temporary which has already been created, just copy it. */
609 static gfc_expr*
610 create_var (gfc_expr * e, const char *vname)
612 char name[GFC_MAX_SYMBOL_LEN +1];
613 gfc_symtree *symtree;
614 gfc_symbol *symbol;
615 gfc_expr *result;
616 gfc_code *n;
617 gfc_namespace *ns;
618 int i;
619 bool deferred;
621 if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
622 return gfc_copy_expr (e);
624 ns = insert_block ();
626 if (vname)
627 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname);
628 else
629 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++);
631 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
632 gcc_unreachable ();
634 symbol = symtree->n.sym;
635 symbol->ts = e->ts;
637 if (e->rank > 0)
639 symbol->as = gfc_get_array_spec ();
640 symbol->as->rank = e->rank;
642 if (e->shape == NULL)
644 /* We don't know the shape at compile time, so we use an
645 allocatable. */
646 symbol->as->type = AS_DEFERRED;
647 symbol->attr.allocatable = 1;
649 else
651 symbol->as->type = AS_EXPLICIT;
652 /* Copy the shape. */
653 for (i=0; i<e->rank; i++)
655 gfc_expr *p, *q;
657 p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
658 &(e->where));
659 mpz_set_si (p->value.integer, 1);
660 symbol->as->lower[i] = p;
662 q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
663 &(e->where));
664 mpz_set (q->value.integer, e->shape[i]);
665 symbol->as->upper[i] = q;
670 deferred = 0;
671 if (e->ts.type == BT_CHARACTER && e->rank == 0)
673 gfc_expr *length;
675 symbol->ts.u.cl = gfc_new_charlen (ns, NULL);
676 length = constant_string_length (e);
677 if (length)
678 symbol->ts.u.cl->length = length;
679 else
681 symbol->attr.allocatable = 1;
682 deferred = 1;
686 symbol->attr.flavor = FL_VARIABLE;
687 symbol->attr.referenced = 1;
688 symbol->attr.dimension = e->rank > 0;
689 symbol->attr.fe_temp = 1;
690 gfc_commit_symbol (symbol);
692 result = gfc_get_expr ();
693 result->expr_type = EXPR_VARIABLE;
694 result->ts = e->ts;
695 result->ts.deferred = deferred;
696 result->rank = e->rank;
697 result->shape = gfc_copy_shape (e->shape, e->rank);
698 result->symtree = symtree;
699 result->where = e->where;
700 if (e->rank > 0)
702 result->ref = gfc_get_ref ();
703 result->ref->type = REF_ARRAY;
704 result->ref->u.ar.type = AR_FULL;
705 result->ref->u.ar.where = e->where;
706 result->ref->u.ar.dimen = e->rank;
707 result->ref->u.ar.as = symbol->ts.type == BT_CLASS
708 ? CLASS_DATA (symbol)->as : symbol->as;
709 if (warn_array_temporaries)
710 gfc_warning (OPT_Warray_temporaries,
711 "Creating array temporary at %L", &(e->where));
714 /* Generate the new assignment. */
715 n = XCNEW (gfc_code);
716 n->op = EXEC_ASSIGN;
717 n->loc = (*current_code)->loc;
718 n->next = *changed_statement;
719 n->expr1 = gfc_copy_expr (result);
720 n->expr2 = e;
721 *changed_statement = n;
722 n_vars ++;
724 return result;
727 /* Warn about function elimination. */
729 static void
730 do_warn_function_elimination (gfc_expr *e)
732 if (e->expr_type != EXPR_FUNCTION)
733 return;
734 if (e->value.function.esym)
735 gfc_warning (0, "Removing call to function %qs at %L",
736 e->value.function.esym->name, &(e->where));
737 else if (e->value.function.isym)
738 gfc_warning (0, "Removing call to function %qs at %L",
739 e->value.function.isym->name, &(e->where));
741 /* Callback function for the code walker for doing common function
742 elimination. This builds up the list of functions in the expression
743 and goes through them to detect duplicates, which it then replaces
744 by variables. */
746 static int
747 cfe_expr_0 (gfc_expr **e, int *walk_subtrees,
748 void *data ATTRIBUTE_UNUSED)
750 int i,j;
751 gfc_expr *newvar;
752 gfc_expr **ei, **ej;
754 /* Don't do this optimization within OMP workshare or ASSOC lists. */
756 if (in_omp_workshare || in_assoc_list)
758 *walk_subtrees = 0;
759 return 0;
762 expr_array.release ();
764 gfc_expr_walker (e, cfe_register_funcs, NULL);
766 /* Walk through all the functions. */
768 FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1)
770 /* Skip if the function has been replaced by a variable already. */
771 if ((*ei)->expr_type == EXPR_VARIABLE)
772 continue;
774 newvar = NULL;
775 for (j=0; j<i; j++)
777 ej = expr_array[j];
778 if (gfc_dep_compare_functions (*ei, *ej, true) == 0)
780 if (newvar == NULL)
781 newvar = create_var (*ei, "fcn");
783 if (warn_function_elimination)
784 do_warn_function_elimination (*ej);
786 free (*ej);
787 *ej = gfc_copy_expr (newvar);
790 if (newvar)
791 *ei = newvar;
794 /* We did all the necessary walking in this function. */
795 *walk_subtrees = 0;
796 return 0;
799 /* Callback function for common function elimination, called from
800 gfc_code_walker. This keeps track of the current code, in order
801 to insert statements as needed. */
803 static int
804 cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
806 current_code = c;
807 inserted_block = NULL;
808 changed_statement = NULL;
810 /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
811 and allocation on assigment are prohibited inside WHERE, and finally
812 masking an expression would lead to wrong-code when replacing
814 WHERE (a>0)
815 b = sum(foo(a) + foo(a))
816 END WHERE
818 with
820 WHERE (a > 0)
821 tmp = foo(a)
822 b = sum(tmp + tmp)
823 END WHERE
826 if ((*c)->op == EXEC_WHERE)
828 *walk_subtrees = 0;
829 return 0;
833 return 0;
836 /* Dummy function for expression call back, for use when we
837 really don't want to do any walking. */
839 static int
840 dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
841 void *data ATTRIBUTE_UNUSED)
843 *walk_subtrees = 0;
844 return 0;
847 /* Dummy function for code callback, for use when we really
848 don't want to do anything. */
850 gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED,
851 int *walk_subtrees ATTRIBUTE_UNUSED,
852 void *data ATTRIBUTE_UNUSED)
854 return 0;
857 /* Code callback function for converting
858 do while(a)
859 end do
860 into the equivalent
862 if (.not. a) exit
863 end do
864 This is because common function elimination would otherwise place the
865 temporary variables outside the loop. */
867 static int
868 convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
869 void *data ATTRIBUTE_UNUSED)
871 gfc_code *co = *c;
872 gfc_code *c_if1, *c_if2, *c_exit;
873 gfc_code *loopblock;
874 gfc_expr *e_not, *e_cond;
876 if (co->op != EXEC_DO_WHILE)
877 return 0;
879 if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
880 return 0;
882 e_cond = co->expr1;
884 /* Generate the condition of the if statement, which is .not. the original
885 statement. */
886 e_not = gfc_get_expr ();
887 e_not->ts = e_cond->ts;
888 e_not->where = e_cond->where;
889 e_not->expr_type = EXPR_OP;
890 e_not->value.op.op = INTRINSIC_NOT;
891 e_not->value.op.op1 = e_cond;
893 /* Generate the EXIT statement. */
894 c_exit = XCNEW (gfc_code);
895 c_exit->op = EXEC_EXIT;
896 c_exit->ext.which_construct = co;
897 c_exit->loc = co->loc;
899 /* Generate the IF statement. */
900 c_if2 = XCNEW (gfc_code);
901 c_if2->op = EXEC_IF;
902 c_if2->expr1 = e_not;
903 c_if2->next = c_exit;
904 c_if2->loc = co->loc;
906 /* ... plus the one to chain it to. */
907 c_if1 = XCNEW (gfc_code);
908 c_if1->op = EXEC_IF;
909 c_if1->block = c_if2;
910 c_if1->loc = co->loc;
912 /* Make the DO WHILE loop into a DO block by replacing the condition
913 with a true constant. */
914 co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
916 /* Hang the generated if statement into the loop body. */
918 loopblock = co->block->next;
919 co->block->next = c_if1;
920 c_if1->next = loopblock;
922 return 0;
925 /* Code callback function for converting
926 if (a) then
928 else if (b) then
929 end if
931 into
932 if (a) then
933 else
934 if (b) then
935 end if
936 end if
938 because otherwise common function elimination would place the BLOCKs
939 into the wrong place. */
941 static int
942 convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
943 void *data ATTRIBUTE_UNUSED)
945 gfc_code *co = *c;
946 gfc_code *c_if1, *c_if2, *else_stmt;
948 if (co->op != EXEC_IF)
949 return 0;
951 /* This loop starts out with the first ELSE statement. */
952 else_stmt = co->block->block;
954 while (else_stmt != NULL)
956 gfc_code *next_else;
958 /* If there is no condition, we're done. */
959 if (else_stmt->expr1 == NULL)
960 break;
962 next_else = else_stmt->block;
964 /* Generate the new IF statement. */
965 c_if2 = XCNEW (gfc_code);
966 c_if2->op = EXEC_IF;
967 c_if2->expr1 = else_stmt->expr1;
968 c_if2->next = else_stmt->next;
969 c_if2->loc = else_stmt->loc;
970 c_if2->block = next_else;
972 /* ... plus the one to chain it to. */
973 c_if1 = XCNEW (gfc_code);
974 c_if1->op = EXEC_IF;
975 c_if1->block = c_if2;
976 c_if1->loc = else_stmt->loc;
978 /* Insert the new IF after the ELSE. */
979 else_stmt->expr1 = NULL;
980 else_stmt->next = c_if1;
981 else_stmt->block = NULL;
983 else_stmt = next_else;
985 /* Don't walk subtrees. */
986 return 0;
989 /* Optimize a namespace, including all contained namespaces. */
991 static void
992 optimize_namespace (gfc_namespace *ns)
994 gfc_namespace *saved_ns = gfc_current_ns;
995 current_ns = ns;
996 gfc_current_ns = ns;
997 forall_level = 0;
998 iterator_level = 0;
999 in_assoc_list = false;
1000 in_omp_workshare = false;
1002 gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
1003 gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL);
1004 gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
1005 gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
1006 if (flag_inline_matmul_limit != 0)
1007 gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
1008 NULL);
1010 /* BLOCKs are handled in the expression walker below. */
1011 for (ns = ns->contained; ns; ns = ns->sibling)
1013 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1014 optimize_namespace (ns);
1016 gfc_current_ns = saved_ns;
1019 /* Handle dependencies for allocatable strings which potentially redefine
1020 themselves in an assignment. */
1022 static void
1023 realloc_strings (gfc_namespace *ns)
1025 current_ns = ns;
1026 gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL);
1028 for (ns = ns->contained; ns; ns = ns->sibling)
1030 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1031 realloc_strings (ns);
1036 static void
1037 optimize_reduction (gfc_namespace *ns)
1039 current_ns = ns;
1040 gfc_code_walker (&ns->code, gfc_dummy_code_callback,
1041 callback_reduction, NULL);
1043 /* BLOCKs are handled in the expression walker below. */
1044 for (ns = ns->contained; ns; ns = ns->sibling)
1046 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1047 optimize_reduction (ns);
1051 /* Replace code like
1052 a = matmul(b,c) + d
1053 with
1054 a = matmul(b,c) ; a = a + d
1055 where the array function is not elemental and not allocatable
1056 and does not depend on the left-hand side.
1059 static bool
1060 optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
1062 gfc_expr *e;
1064 e = *rhs;
1065 if (e->expr_type == EXPR_OP)
1067 switch (e->value.op.op)
1069 /* Unary operators and exponentiation: Only look at a single
1070 operand. */
1071 case INTRINSIC_NOT:
1072 case INTRINSIC_UPLUS:
1073 case INTRINSIC_UMINUS:
1074 case INTRINSIC_PARENTHESES:
1075 case INTRINSIC_POWER:
1076 if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
1077 return true;
1078 break;
1080 case INTRINSIC_CONCAT:
1081 /* Do not do string concatenations. */
1082 break;
1084 default:
1085 /* Binary operators. */
1086 if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
1087 return true;
1089 if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
1090 return true;
1092 break;
1095 else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
1096 && ! (e->value.function.esym
1097 && (e->value.function.esym->attr.elemental
1098 || e->value.function.esym->attr.allocatable
1099 || e->value.function.esym->ts.type != c->expr1->ts.type
1100 || e->value.function.esym->ts.kind != c->expr1->ts.kind))
1101 && ! (e->value.function.isym
1102 && (e->value.function.isym->elemental
1103 || e->ts.type != c->expr1->ts.type
1104 || e->ts.kind != c->expr1->ts.kind))
1105 && ! gfc_inline_intrinsic_function_p (e))
1108 gfc_code *n;
1109 gfc_expr *new_expr;
1111 /* Insert a new assignment statement after the current one. */
1112 n = XCNEW (gfc_code);
1113 n->op = EXEC_ASSIGN;
1114 n->loc = c->loc;
1115 n->next = c->next;
1116 c->next = n;
1118 n->expr1 = gfc_copy_expr (c->expr1);
1119 n->expr2 = c->expr2;
1120 new_expr = gfc_copy_expr (c->expr1);
1121 c->expr2 = e;
1122 *rhs = new_expr;
1124 return true;
1128 /* Nothing to optimize. */
1129 return false;
1132 /* Remove unneeded TRIMs at the end of expressions. */
1134 static bool
1135 remove_trim (gfc_expr *rhs)
1137 bool ret;
1139 ret = false;
1140 if (!rhs)
1141 return ret;
1143 /* Check for a // b // trim(c). Looping is probably not
1144 necessary because the parser usually generates
1145 (// (// a b ) trim(c) ) , but better safe than sorry. */
1147 while (rhs->expr_type == EXPR_OP
1148 && rhs->value.op.op == INTRINSIC_CONCAT)
1149 rhs = rhs->value.op.op2;
1151 while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym
1152 && rhs->value.function.isym->id == GFC_ISYM_TRIM)
1154 strip_function_call (rhs);
1155 /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1156 remove_trim (rhs);
1157 ret = true;
1160 return ret;
1163 /* Optimizations for an assignment. */
1165 static void
1166 optimize_assignment (gfc_code * c)
1168 gfc_expr *lhs, *rhs;
1170 lhs = c->expr1;
1171 rhs = c->expr2;
1173 if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred)
1175 /* Optimize a = trim(b) to a = b. */
1176 remove_trim (rhs);
1178 /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1179 if (is_empty_string (rhs))
1180 rhs->value.character.length = 0;
1183 if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
1184 optimize_binop_array_assignment (c, &rhs, false);
1188 /* Remove an unneeded function call, modifying the expression.
1189 This replaces the function call with the value of its
1190 first argument. The rest of the argument list is freed. */
1192 static void
1193 strip_function_call (gfc_expr *e)
1195 gfc_expr *e1;
1196 gfc_actual_arglist *a;
1198 a = e->value.function.actual;
1200 /* We should have at least one argument. */
1201 gcc_assert (a->expr != NULL);
1203 e1 = a->expr;
1205 /* Free the remaining arglist, if any. */
1206 if (a->next)
1207 gfc_free_actual_arglist (a->next);
1209 /* Graft the argument expression onto the original function. */
1210 *e = *e1;
1211 free (e1);
1215 /* Optimization of lexical comparison functions. */
1217 static bool
1218 optimize_lexical_comparison (gfc_expr *e)
1220 if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL)
1221 return false;
1223 switch (e->value.function.isym->id)
1225 case GFC_ISYM_LLE:
1226 return optimize_comparison (e, INTRINSIC_LE);
1228 case GFC_ISYM_LGE:
1229 return optimize_comparison (e, INTRINSIC_GE);
1231 case GFC_ISYM_LGT:
1232 return optimize_comparison (e, INTRINSIC_GT);
1234 case GFC_ISYM_LLT:
1235 return optimize_comparison (e, INTRINSIC_LT);
1237 default:
1238 break;
1240 return false;
1243 /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1244 do CHARACTER because of possible pessimization involving character
1245 lengths. */
1247 static bool
1248 combine_array_constructor (gfc_expr *e)
1251 gfc_expr *op1, *op2;
1252 gfc_expr *scalar;
1253 gfc_expr *new_expr;
1254 gfc_constructor *c, *new_c;
1255 gfc_constructor_base oldbase, newbase;
1256 bool scalar_first;
1258 /* Array constructors have rank one. */
1259 if (e->rank != 1)
1260 return false;
1262 /* Don't try to combine association lists, this makes no sense
1263 and leads to an ICE. */
1264 if (in_assoc_list)
1265 return false;
1267 /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1268 if (forall_level > 0)
1269 return false;
1271 /* Inside an iterator, things can get hairy; we are likely to create
1272 an invalid temporary variable. */
1273 if (iterator_level > 0)
1274 return false;
1276 op1 = e->value.op.op1;
1277 op2 = e->value.op.op2;
1279 if (!op1 || !op2)
1280 return false;
1282 if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
1283 scalar_first = false;
1284 else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
1286 scalar_first = true;
1287 op1 = e->value.op.op2;
1288 op2 = e->value.op.op1;
1290 else
1291 return false;
1293 if (op2->ts.type == BT_CHARACTER)
1294 return false;
1296 scalar = create_var (gfc_copy_expr (op2), "constr");
1298 oldbase = op1->value.constructor;
1299 newbase = NULL;
1300 e->expr_type = EXPR_ARRAY;
1302 for (c = gfc_constructor_first (oldbase); c;
1303 c = gfc_constructor_next (c))
1305 new_expr = gfc_get_expr ();
1306 new_expr->ts = e->ts;
1307 new_expr->expr_type = EXPR_OP;
1308 new_expr->rank = c->expr->rank;
1309 new_expr->where = c->where;
1310 new_expr->value.op.op = e->value.op.op;
1312 if (scalar_first)
1314 new_expr->value.op.op1 = gfc_copy_expr (scalar);
1315 new_expr->value.op.op2 = gfc_copy_expr (c->expr);
1317 else
1319 new_expr->value.op.op1 = gfc_copy_expr (c->expr);
1320 new_expr->value.op.op2 = gfc_copy_expr (scalar);
1323 new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
1324 new_c->iterator = c->iterator;
1325 c->iterator = NULL;
1328 gfc_free_expr (op1);
1329 gfc_free_expr (op2);
1330 gfc_free_expr (scalar);
1332 e->value.constructor = newbase;
1333 return true;
1336 /* Change (-1)**k into 1-ishift(iand(k,1),1) and
1337 2**k into ishift(1,k) */
1339 static bool
1340 optimize_power (gfc_expr *e)
1342 gfc_expr *op1, *op2;
1343 gfc_expr *iand, *ishft;
1345 if (e->ts.type != BT_INTEGER)
1346 return false;
1348 op1 = e->value.op.op1;
1350 if (op1 == NULL || op1->expr_type != EXPR_CONSTANT)
1351 return false;
1353 if (mpz_cmp_si (op1->value.integer, -1L) == 0)
1355 gfc_free_expr (op1);
1357 op2 = e->value.op.op2;
1359 if (op2 == NULL)
1360 return false;
1362 iand = gfc_build_intrinsic_call (current_ns, GFC_ISYM_IAND,
1363 "_internal_iand", e->where, 2, op2,
1364 gfc_get_int_expr (e->ts.kind,
1365 &e->where, 1));
1367 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1368 "_internal_ishft", e->where, 2, iand,
1369 gfc_get_int_expr (e->ts.kind,
1370 &e->where, 1));
1372 e->value.op.op = INTRINSIC_MINUS;
1373 e->value.op.op1 = gfc_get_int_expr (e->ts.kind, &e->where, 1);
1374 e->value.op.op2 = ishft;
1375 return true;
1377 else if (mpz_cmp_si (op1->value.integer, 2L) == 0)
1379 gfc_free_expr (op1);
1381 op2 = e->value.op.op2;
1382 if (op2 == NULL)
1383 return false;
1385 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1386 "_internal_ishft", e->where, 2,
1387 gfc_get_int_expr (e->ts.kind,
1388 &e->where, 1),
1389 op2);
1390 *e = *ishft;
1391 return true;
1394 else if (mpz_cmp_si (op1->value.integer, 1L) == 0)
1396 op2 = e->value.op.op2;
1397 if (op2 == NULL)
1398 return false;
1400 gfc_free_expr (op1);
1401 gfc_free_expr (op2);
1403 e->expr_type = EXPR_CONSTANT;
1404 e->value.op.op1 = NULL;
1405 e->value.op.op2 = NULL;
1406 mpz_init_set_si (e->value.integer, 1);
1407 /* Typespec and location are still OK. */
1408 return true;
1411 return false;
1414 /* Recursive optimization of operators. */
1416 static bool
1417 optimize_op (gfc_expr *e)
1419 bool changed;
1421 gfc_intrinsic_op op = e->value.op.op;
1423 changed = false;
1425 /* Only use new-style comparisons. */
1426 switch(op)
1428 case INTRINSIC_EQ_OS:
1429 op = INTRINSIC_EQ;
1430 break;
1432 case INTRINSIC_GE_OS:
1433 op = INTRINSIC_GE;
1434 break;
1436 case INTRINSIC_LE_OS:
1437 op = INTRINSIC_LE;
1438 break;
1440 case INTRINSIC_NE_OS:
1441 op = INTRINSIC_NE;
1442 break;
1444 case INTRINSIC_GT_OS:
1445 op = INTRINSIC_GT;
1446 break;
1448 case INTRINSIC_LT_OS:
1449 op = INTRINSIC_LT;
1450 break;
1452 default:
1453 break;
1456 switch (op)
1458 case INTRINSIC_EQ:
1459 case INTRINSIC_GE:
1460 case INTRINSIC_LE:
1461 case INTRINSIC_NE:
1462 case INTRINSIC_GT:
1463 case INTRINSIC_LT:
1464 changed = optimize_comparison (e, op);
1466 /* Fall through */
1467 /* Look at array constructors. */
1468 case INTRINSIC_PLUS:
1469 case INTRINSIC_MINUS:
1470 case INTRINSIC_TIMES:
1471 case INTRINSIC_DIVIDE:
1472 return combine_array_constructor (e) || changed;
1474 case INTRINSIC_POWER:
1475 return optimize_power (e);
1476 break;
1478 default:
1479 break;
1482 return false;
1486 /* Return true if a constant string contains only blanks. */
1488 static bool
1489 is_empty_string (gfc_expr *e)
1491 int i;
1493 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1494 return false;
1496 for (i=0; i < e->value.character.length; i++)
1498 if (e->value.character.string[i] != ' ')
1499 return false;
1502 return true;
1506 /* Insert a call to the intrinsic len_trim. Use a different name for
1507 the symbol tree so we don't run into trouble when the user has
1508 renamed len_trim for some reason. */
1510 static gfc_expr*
1511 get_len_trim_call (gfc_expr *str, int kind)
1513 gfc_expr *fcn;
1514 gfc_actual_arglist *actual_arglist, *next;
1516 fcn = gfc_get_expr ();
1517 fcn->expr_type = EXPR_FUNCTION;
1518 fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM);
1519 actual_arglist = gfc_get_actual_arglist ();
1520 actual_arglist->expr = str;
1521 next = gfc_get_actual_arglist ();
1522 next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind);
1523 actual_arglist->next = next;
1525 fcn->value.function.actual = actual_arglist;
1526 fcn->where = str->where;
1527 fcn->ts.type = BT_INTEGER;
1528 fcn->ts.kind = gfc_charlen_int_kind;
1530 gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false);
1531 fcn->symtree->n.sym->ts = fcn->ts;
1532 fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
1533 fcn->symtree->n.sym->attr.function = 1;
1534 fcn->symtree->n.sym->attr.elemental = 1;
1535 fcn->symtree->n.sym->attr.referenced = 1;
1536 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
1537 gfc_commit_symbol (fcn->symtree->n.sym);
1539 return fcn;
1542 /* Optimize expressions for equality. */
1544 static bool
1545 optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
1547 gfc_expr *op1, *op2;
1548 bool change;
1549 int eq;
1550 bool result;
1551 gfc_actual_arglist *firstarg, *secondarg;
1553 if (e->expr_type == EXPR_OP)
1555 firstarg = NULL;
1556 secondarg = NULL;
1557 op1 = e->value.op.op1;
1558 op2 = e->value.op.op2;
1560 else if (e->expr_type == EXPR_FUNCTION)
1562 /* One of the lexical comparison functions. */
1563 firstarg = e->value.function.actual;
1564 secondarg = firstarg->next;
1565 op1 = firstarg->expr;
1566 op2 = secondarg->expr;
1568 else
1569 gcc_unreachable ();
1571 /* Strip off unneeded TRIM calls from string comparisons. */
1573 change = remove_trim (op1);
1575 if (remove_trim (op2))
1576 change = true;
1578 /* An expression of type EXPR_CONSTANT is only valid for scalars. */
1579 /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
1580 handles them well). However, there are also cases that need a non-scalar
1581 argument. For example the any intrinsic. See PR 45380. */
1582 if (e->rank > 0)
1583 return change;
1585 /* Replace a == '' with len_trim(a) == 0 and a /= '' with
1586 len_trim(a) != 0 */
1587 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
1588 && (op == INTRINSIC_EQ || op == INTRINSIC_NE))
1590 bool empty_op1, empty_op2;
1591 empty_op1 = is_empty_string (op1);
1592 empty_op2 = is_empty_string (op2);
1594 if (empty_op1 || empty_op2)
1596 gfc_expr *fcn;
1597 gfc_expr *zero;
1598 gfc_expr *str;
1600 /* This can only happen when an error for comparing
1601 characters of different kinds has already been issued. */
1602 if (empty_op1 && empty_op2)
1603 return false;
1605 zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0);
1606 str = empty_op1 ? op2 : op1;
1608 fcn = get_len_trim_call (str, gfc_charlen_int_kind);
1611 if (empty_op1)
1612 gfc_free_expr (op1);
1613 else
1614 gfc_free_expr (op2);
1616 op1 = fcn;
1617 op2 = zero;
1618 e->value.op.op1 = fcn;
1619 e->value.op.op2 = zero;
1624 /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
1626 if (flag_finite_math_only
1627 || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL
1628 && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
1630 eq = gfc_dep_compare_expr (op1, op2);
1631 if (eq <= -2)
1633 /* Replace A // B < A // C with B < C, and A // B < C // B
1634 with A < C. */
1635 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
1636 && op1->expr_type == EXPR_OP
1637 && op1->value.op.op == INTRINSIC_CONCAT
1638 && op2->expr_type == EXPR_OP
1639 && op2->value.op.op == INTRINSIC_CONCAT)
1641 gfc_expr *op1_left = op1->value.op.op1;
1642 gfc_expr *op2_left = op2->value.op.op1;
1643 gfc_expr *op1_right = op1->value.op.op2;
1644 gfc_expr *op2_right = op2->value.op.op2;
1646 if (gfc_dep_compare_expr (op1_left, op2_left) == 0)
1648 /* Watch out for 'A ' // x vs. 'A' // x. */
1650 if (op1_left->expr_type == EXPR_CONSTANT
1651 && op2_left->expr_type == EXPR_CONSTANT
1652 && op1_left->value.character.length
1653 != op2_left->value.character.length)
1654 return change;
1655 else
1657 free (op1_left);
1658 free (op2_left);
1659 if (firstarg)
1661 firstarg->expr = op1_right;
1662 secondarg->expr = op2_right;
1664 else
1666 e->value.op.op1 = op1_right;
1667 e->value.op.op2 = op2_right;
1669 optimize_comparison (e, op);
1670 return true;
1673 if (gfc_dep_compare_expr (op1_right, op2_right) == 0)
1675 free (op1_right);
1676 free (op2_right);
1677 if (firstarg)
1679 firstarg->expr = op1_left;
1680 secondarg->expr = op2_left;
1682 else
1684 e->value.op.op1 = op1_left;
1685 e->value.op.op2 = op2_left;
1688 optimize_comparison (e, op);
1689 return true;
1693 else
1695 /* eq can only be -1, 0 or 1 at this point. */
1696 switch (op)
1698 case INTRINSIC_EQ:
1699 result = eq == 0;
1700 break;
1702 case INTRINSIC_GE:
1703 result = eq >= 0;
1704 break;
1706 case INTRINSIC_LE:
1707 result = eq <= 0;
1708 break;
1710 case INTRINSIC_NE:
1711 result = eq != 0;
1712 break;
1714 case INTRINSIC_GT:
1715 result = eq > 0;
1716 break;
1718 case INTRINSIC_LT:
1719 result = eq < 0;
1720 break;
1722 default:
1723 gfc_internal_error ("illegal OP in optimize_comparison");
1724 break;
1727 /* Replace the expression by a constant expression. The typespec
1728 and where remains the way it is. */
1729 free (op1);
1730 free (op2);
1731 e->expr_type = EXPR_CONSTANT;
1732 e->value.logical = result;
1733 return true;
1737 return change;
1740 /* Optimize a trim function by replacing it with an equivalent substring
1741 involving a call to len_trim. This only works for expressions where
1742 variables are trimmed. Return true if anything was modified. */
1744 static bool
1745 optimize_trim (gfc_expr *e)
1747 gfc_expr *a;
1748 gfc_ref *ref;
1749 gfc_expr *fcn;
1750 gfc_ref **rr = NULL;
1752 /* Don't do this optimization within an argument list, because
1753 otherwise aliasing issues may occur. */
1755 if (count_arglist != 1)
1756 return false;
1758 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION
1759 || e->value.function.isym == NULL
1760 || e->value.function.isym->id != GFC_ISYM_TRIM)
1761 return false;
1763 a = e->value.function.actual->expr;
1765 if (a->expr_type != EXPR_VARIABLE)
1766 return false;
1768 /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
1770 if (a->symtree->n.sym->attr.allocatable)
1771 return false;
1773 /* Follow all references to find the correct place to put the newly
1774 created reference. FIXME: Also handle substring references and
1775 array references. Array references cause strange regressions at
1776 the moment. */
1778 if (a->ref)
1780 for (rr = &(a->ref); *rr; rr = &((*rr)->next))
1782 if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY)
1783 return false;
1787 strip_function_call (e);
1789 if (e->ref == NULL)
1790 rr = &(e->ref);
1792 /* Create the reference. */
1794 ref = gfc_get_ref ();
1795 ref->type = REF_SUBSTRING;
1797 /* Set the start of the reference. */
1799 ref->u.ss.start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
1801 /* Build the function call to len_trim(x, gfc_default_integer_kind). */
1803 fcn = get_len_trim_call (gfc_copy_expr (e), gfc_default_integer_kind);
1805 /* Set the end of the reference to the call to len_trim. */
1807 ref->u.ss.end = fcn;
1808 gcc_assert (rr != NULL && *rr == NULL);
1809 *rr = ref;
1810 return true;
1813 /* Optimize minloc(b), where b is rank 1 array, into
1814 (/ minloc(b, dim=1) /), and similarly for maxloc,
1815 as the latter forms are expanded inline. */
1817 static void
1818 optimize_minmaxloc (gfc_expr **e)
1820 gfc_expr *fn = *e;
1821 gfc_actual_arglist *a;
1822 char *name, *p;
1824 if (fn->rank != 1
1825 || fn->value.function.actual == NULL
1826 || fn->value.function.actual->expr == NULL
1827 || fn->value.function.actual->expr->rank != 1)
1828 return;
1830 *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
1831 (*e)->shape = fn->shape;
1832 fn->rank = 0;
1833 fn->shape = NULL;
1834 gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
1836 name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
1837 strcpy (name, fn->value.function.name);
1838 p = strstr (name, "loc0");
1839 p[3] = '1';
1840 fn->value.function.name = gfc_get_string (name);
1841 if (fn->value.function.actual->next)
1843 a = fn->value.function.actual->next;
1844 gcc_assert (a->expr == NULL);
1846 else
1848 a = gfc_get_actual_arglist ();
1849 fn->value.function.actual->next = a;
1851 a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
1852 &fn->where);
1853 mpz_set_ui (a->expr->value.integer, 1);
1856 /* Callback function for code checking that we do not pass a DO variable to an
1857 INTENT(OUT) or INTENT(INOUT) dummy variable. */
1859 static int
1860 doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1861 void *data ATTRIBUTE_UNUSED)
1863 gfc_code *co;
1864 int i;
1865 gfc_formal_arglist *f;
1866 gfc_actual_arglist *a;
1867 gfc_code *cl;
1869 co = *c;
1871 /* If the doloop_list grew, we have to truncate it here. */
1873 if ((unsigned) doloop_level < doloop_list.length())
1874 doloop_list.truncate (doloop_level);
1876 switch (co->op)
1878 case EXEC_DO:
1880 if (co->ext.iterator && co->ext.iterator->var)
1881 doloop_list.safe_push (co);
1882 else
1883 doloop_list.safe_push ((gfc_code *) NULL);
1884 break;
1886 case EXEC_CALL:
1888 if (co->resolved_sym == NULL)
1889 break;
1891 f = gfc_sym_get_dummy_args (co->resolved_sym);
1893 /* Withot a formal arglist, there is only unknown INTENT,
1894 which we don't check for. */
1895 if (f == NULL)
1896 break;
1898 a = co->ext.actual;
1900 while (a && f)
1902 FOR_EACH_VEC_ELT (doloop_list, i, cl)
1904 gfc_symbol *do_sym;
1906 if (cl == NULL)
1907 break;
1909 do_sym = cl->ext.iterator->var->symtree->n.sym;
1911 if (a->expr && a->expr->symtree
1912 && a->expr->symtree->n.sym == do_sym)
1914 if (f->sym->attr.intent == INTENT_OUT)
1915 gfc_error_now ("Variable %qs at %L set to undefined "
1916 "value inside loop beginning at %L as "
1917 "INTENT(OUT) argument to subroutine %qs",
1918 do_sym->name, &a->expr->where,
1919 &doloop_list[i]->loc,
1920 co->symtree->n.sym->name);
1921 else if (f->sym->attr.intent == INTENT_INOUT)
1922 gfc_error_now ("Variable %qs at %L not definable inside "
1923 "loop beginning at %L as INTENT(INOUT) "
1924 "argument to subroutine %qs",
1925 do_sym->name, &a->expr->where,
1926 &doloop_list[i]->loc,
1927 co->symtree->n.sym->name);
1930 a = a->next;
1931 f = f->next;
1933 break;
1935 default:
1936 break;
1938 return 0;
1941 /* Callback function for functions checking that we do not pass a DO variable
1942 to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
1944 static int
1945 do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1946 void *data ATTRIBUTE_UNUSED)
1948 gfc_formal_arglist *f;
1949 gfc_actual_arglist *a;
1950 gfc_expr *expr;
1951 gfc_code *dl;
1952 int i;
1954 expr = *e;
1955 if (expr->expr_type != EXPR_FUNCTION)
1956 return 0;
1958 /* Intrinsic functions don't modify their arguments. */
1960 if (expr->value.function.isym)
1961 return 0;
1963 f = gfc_sym_get_dummy_args (expr->symtree->n.sym);
1965 /* Without a formal arglist, there is only unknown INTENT,
1966 which we don't check for. */
1967 if (f == NULL)
1968 return 0;
1970 a = expr->value.function.actual;
1972 while (a && f)
1974 FOR_EACH_VEC_ELT (doloop_list, i, dl)
1976 gfc_symbol *do_sym;
1978 if (dl == NULL)
1979 break;
1981 do_sym = dl->ext.iterator->var->symtree->n.sym;
1983 if (a->expr && a->expr->symtree
1984 && a->expr->symtree->n.sym == do_sym)
1986 if (f->sym->attr.intent == INTENT_OUT)
1987 gfc_error_now ("Variable %qs at %L set to undefined value "
1988 "inside loop beginning at %L as INTENT(OUT) "
1989 "argument to function %qs", do_sym->name,
1990 &a->expr->where, &doloop_list[i]->loc,
1991 expr->symtree->n.sym->name);
1992 else if (f->sym->attr.intent == INTENT_INOUT)
1993 gfc_error_now ("Variable %qs at %L not definable inside loop"
1994 " beginning at %L as INTENT(INOUT) argument to"
1995 " function %qs", do_sym->name,
1996 &a->expr->where, &doloop_list[i]->loc,
1997 expr->symtree->n.sym->name);
2000 a = a->next;
2001 f = f->next;
2004 return 0;
2007 static void
2008 doloop_warn (gfc_namespace *ns)
2010 gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
2013 /* This selction deals with inlining calls to MATMUL. */
2015 /* Auxiliary function to build and simplify an array inquiry function.
2016 dim is zero-based. */
2018 static gfc_expr *
2019 get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim)
2021 gfc_expr *fcn;
2022 gfc_expr *dim_arg, *kind;
2023 const char *name;
2024 gfc_expr *ec;
2026 switch (id)
2028 case GFC_ISYM_LBOUND:
2029 name = "_gfortran_lbound";
2030 break;
2032 case GFC_ISYM_UBOUND:
2033 name = "_gfortran_ubound";
2034 break;
2036 case GFC_ISYM_SIZE:
2037 name = "_gfortran_size";
2038 break;
2040 default:
2041 gcc_unreachable ();
2044 dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
2045 kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
2046 gfc_index_integer_kind);
2048 ec = gfc_copy_expr (e);
2049 fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
2050 ec, dim_arg, kind);
2051 gfc_simplify_expr (fcn, 0);
2052 return fcn;
2055 /* Builds a logical expression. */
2057 static gfc_expr*
2058 build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2060 gfc_typespec ts;
2061 gfc_expr *res;
2063 ts.type = BT_LOGICAL;
2064 ts.kind = gfc_default_logical_kind;
2065 res = gfc_get_expr ();
2066 res->where = e1->where;
2067 res->expr_type = EXPR_OP;
2068 res->value.op.op = op;
2069 res->value.op.op1 = e1;
2070 res->value.op.op2 = e2;
2071 res->ts = ts;
2073 return res;
2077 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
2078 compatible typespecs. */
2080 static gfc_expr *
2081 get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2083 gfc_expr *res;
2085 res = gfc_get_expr ();
2086 res->ts = e1->ts;
2087 res->where = e1->where;
2088 res->expr_type = EXPR_OP;
2089 res->value.op.op = op;
2090 res->value.op.op1 = e1;
2091 res->value.op.op2 = e2;
2092 gfc_simplify_expr (res, 0);
2093 return res;
2096 /* Generate the IF statement for a runtime check if we want to do inlining or
2097 not - putting in the code for both branches and putting it into the syntax
2098 tree is the caller's responsibility. For fixed array sizes, this should be
2099 removed by DCE. Only called for rank-two matrices A and B. */
2101 static gfc_code *
2102 inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case)
2104 gfc_expr *inline_limit;
2105 gfc_code *if_1, *if_2, *else_2;
2106 gfc_expr *b2, *a2, *a1, *m1, *m2;
2107 gfc_typespec ts;
2108 gfc_expr *cond;
2110 gcc_assert (m_case == A2B2 || m_case == A2B2T);
2112 /* Calculation is done in real to avoid integer overflow. */
2114 inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
2115 &a->where);
2116 mpfr_set_si (inline_limit->value.real, flag_inline_matmul_limit,
2117 GFC_RND_MODE);
2118 mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, 3,
2119 GFC_RND_MODE);
2121 a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2122 a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
2123 b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
2125 gfc_clear_ts (&ts);
2126 ts.type = BT_REAL;
2127 ts.kind = gfc_default_real_kind;
2128 gfc_convert_type_warn (a1, &ts, 2, 0);
2129 gfc_convert_type_warn (a2, &ts, 2, 0);
2130 gfc_convert_type_warn (b2, &ts, 2, 0);
2132 m1 = get_operand (INTRINSIC_TIMES, a1, a2);
2133 m2 = get_operand (INTRINSIC_TIMES, m1, b2);
2135 cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
2136 gfc_simplify_expr (cond, 0);
2138 else_2 = XCNEW (gfc_code);
2139 else_2->op = EXEC_IF;
2140 else_2->loc = a->where;
2142 if_2 = XCNEW (gfc_code);
2143 if_2->op = EXEC_IF;
2144 if_2->expr1 = cond;
2145 if_2->loc = a->where;
2146 if_2->block = else_2;
2148 if_1 = XCNEW (gfc_code);
2149 if_1->op = EXEC_IF;
2150 if_1->block = if_2;
2151 if_1->loc = a->where;
2153 return if_1;
2157 /* Insert code to issue a runtime error if the expressions are not equal. */
2159 static gfc_code *
2160 runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
2162 gfc_expr *cond;
2163 gfc_code *if_1, *if_2;
2164 gfc_code *c;
2165 gfc_actual_arglist *a1, *a2, *a3;
2167 gcc_assert (e1->where.lb);
2168 /* Build the call to runtime_error. */
2169 c = XCNEW (gfc_code);
2170 c->op = EXEC_CALL;
2171 c->loc = e1->where;
2173 /* Get a null-terminated message string. */
2175 a1 = gfc_get_actual_arglist ();
2176 a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
2177 msg, strlen(msg)+1);
2178 c->ext.actual = a1;
2180 /* Pass the value of the first expression. */
2181 a2 = gfc_get_actual_arglist ();
2182 a2->expr = gfc_copy_expr (e1);
2183 a1->next = a2;
2185 /* Pass the value of the second expression. */
2186 a3 = gfc_get_actual_arglist ();
2187 a3->expr = gfc_copy_expr (e2);
2188 a2->next = a3;
2190 gfc_check_fe_runtime_error (c->ext.actual);
2191 gfc_resolve_fe_runtime_error (c);
2193 if_2 = XCNEW (gfc_code);
2194 if_2->op = EXEC_IF;
2195 if_2->loc = e1->where;
2196 if_2->next = c;
2198 if_1 = XCNEW (gfc_code);
2199 if_1->op = EXEC_IF;
2200 if_1->block = if_2;
2201 if_1->loc = e1->where;
2203 cond = build_logical_expr (INTRINSIC_NE, e1, e2);
2204 gfc_simplify_expr (cond, 0);
2205 if_2->expr1 = cond;
2207 return if_1;
2210 /* Handle matrix reallocation. Caller is responsible to insert into
2211 the code tree.
2213 For the two-dimensional case, build
2215 if (allocated(c)) then
2216 if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
2217 deallocate(c)
2218 allocate (c(size(a,1), size(b,2)))
2219 end if
2220 else
2221 allocate (c(size(a,1),size(b,2)))
2222 end if
2224 and for the other cases correspondingly.
2227 static gfc_code *
2228 matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
2229 enum matrix_case m_case)
2232 gfc_expr *allocated, *alloc_expr;
2233 gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
2234 gfc_code *else_alloc;
2235 gfc_code *deallocate, *allocate1, *allocate_else;
2236 gfc_array_ref *ar;
2237 gfc_expr *cond, *ne1, *ne2;
2239 if (warn_realloc_lhs)
2240 gfc_warning (OPT_Wrealloc_lhs,
2241 "Code for reallocating the allocatable array at %L will "
2242 "be added", &c->where);
2244 alloc_expr = gfc_copy_expr (c);
2246 ar = gfc_find_array_ref (alloc_expr);
2247 gcc_assert (ar && ar->type == AR_FULL);
2249 /* c comes in as a full ref. Change it into a copy and make it into an
2250 element ref so it has the right form for for ALLOCATE. In the same
2251 switch statement, also generate the size comparison for the secod IF
2252 statement. */
2254 ar->type = AR_ELEMENT;
2256 switch (m_case)
2258 case A2B2:
2259 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2260 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
2261 ne1 = build_logical_expr (INTRINSIC_NE,
2262 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2263 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
2264 ne2 = build_logical_expr (INTRINSIC_NE,
2265 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
2266 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
2267 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
2268 break;
2270 case A2B2T:
2271 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2272 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
2274 ne1 = build_logical_expr (INTRINSIC_NE,
2275 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2276 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
2277 ne2 = build_logical_expr (INTRINSIC_NE,
2278 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
2279 get_array_inq_function (GFC_ISYM_SIZE, b, 1));
2280 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
2281 break;
2283 case A2B1:
2284 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2285 cond = build_logical_expr (INTRINSIC_NE,
2286 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2287 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
2288 break;
2290 case A1B2:
2291 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
2292 cond = build_logical_expr (INTRINSIC_NE,
2293 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2294 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
2295 break;
2297 default:
2298 gcc_unreachable();
2302 gfc_simplify_expr (cond, 0);
2304 /* We need two identical allocate statements in two
2305 branches of the IF statement. */
2307 allocate1 = XCNEW (gfc_code);
2308 allocate1->op = EXEC_ALLOCATE;
2309 allocate1->ext.alloc.list = gfc_get_alloc ();
2310 allocate1->loc = c->where;
2311 allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
2313 allocate_else = XCNEW (gfc_code);
2314 allocate_else->op = EXEC_ALLOCATE;
2315 allocate_else->ext.alloc.list = gfc_get_alloc ();
2316 allocate_else->loc = c->where;
2317 allocate_else->ext.alloc.list->expr = alloc_expr;
2319 allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
2320 "_gfortran_allocated", c->where,
2321 1, gfc_copy_expr (c));
2323 deallocate = XCNEW (gfc_code);
2324 deallocate->op = EXEC_DEALLOCATE;
2325 deallocate->ext.alloc.list = gfc_get_alloc ();
2326 deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
2327 deallocate->next = allocate1;
2328 deallocate->loc = c->where;
2330 if_size_2 = XCNEW (gfc_code);
2331 if_size_2->op = EXEC_IF;
2332 if_size_2->expr1 = cond;
2333 if_size_2->loc = c->where;
2334 if_size_2->next = deallocate;
2336 if_size_1 = XCNEW (gfc_code);
2337 if_size_1->op = EXEC_IF;
2338 if_size_1->block = if_size_2;
2339 if_size_1->loc = c->where;
2341 else_alloc = XCNEW (gfc_code);
2342 else_alloc->op = EXEC_IF;
2343 else_alloc->loc = c->where;
2344 else_alloc->next = allocate_else;
2346 if_alloc_2 = XCNEW (gfc_code);
2347 if_alloc_2->op = EXEC_IF;
2348 if_alloc_2->expr1 = allocated;
2349 if_alloc_2->loc = c->where;
2350 if_alloc_2->next = if_size_1;
2351 if_alloc_2->block = else_alloc;
2353 if_alloc_1 = XCNEW (gfc_code);
2354 if_alloc_1->op = EXEC_IF;
2355 if_alloc_1->block = if_alloc_2;
2356 if_alloc_1->loc = c->where;
2358 return if_alloc_1;
2361 /* Callback function for has_function_or_op. */
2363 static int
2364 is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2365 void *data ATTRIBUTE_UNUSED)
2367 if ((*e) == 0)
2368 return 0;
2369 else
2370 return (*e)->expr_type == EXPR_FUNCTION
2371 || (*e)->expr_type == EXPR_OP;
2374 /* Returns true if the expression contains a function. */
2376 static bool
2377 has_function_or_op (gfc_expr **e)
2379 if (e == NULL)
2380 return false;
2381 else
2382 return gfc_expr_walker (e, is_function_or_op, NULL);
2385 /* Freeze (assign to a temporary variable) a single expression. */
2387 static void
2388 freeze_expr (gfc_expr **ep)
2390 gfc_expr *ne;
2391 if (has_function_or_op (ep))
2393 ne = create_var (*ep, "freeze");
2394 *ep = ne;
2398 /* Go through an expression's references and assign them to temporary
2399 variables if they contain functions. This is usually done prior to
2400 front-end scalarization to avoid multiple invocations of functions. */
2402 static void
2403 freeze_references (gfc_expr *e)
2405 gfc_ref *r;
2406 gfc_array_ref *ar;
2407 int i;
2409 for (r=e->ref; r; r=r->next)
2411 if (r->type == REF_SUBSTRING)
2413 if (r->u.ss.start != NULL)
2414 freeze_expr (&r->u.ss.start);
2416 if (r->u.ss.end != NULL)
2417 freeze_expr (&r->u.ss.end);
2419 else if (r->type == REF_ARRAY)
2421 ar = &r->u.ar;
2422 switch (ar->type)
2424 case AR_FULL:
2425 break;
2427 case AR_SECTION:
2428 for (i=0; i<ar->dimen; i++)
2430 if (ar->dimen_type[i] == DIMEN_RANGE)
2432 freeze_expr (&ar->start[i]);
2433 freeze_expr (&ar->end[i]);
2434 freeze_expr (&ar->stride[i]);
2436 else if (ar->dimen_type[i] == DIMEN_ELEMENT)
2438 freeze_expr (&ar->start[i]);
2441 break;
2443 case AR_ELEMENT:
2444 for (i=0; i<ar->dimen; i++)
2445 freeze_expr (&ar->start[i]);
2446 break;
2448 default:
2449 break;
2455 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
2457 static gfc_expr *
2458 convert_to_index_kind (gfc_expr *e)
2460 gfc_expr *res;
2462 gcc_assert (e != NULL);
2464 res = gfc_copy_expr (e);
2466 gcc_assert (e->ts.type == BT_INTEGER);
2468 if (res->ts.kind != gfc_index_integer_kind)
2470 gfc_typespec ts;
2471 gfc_clear_ts (&ts);
2472 ts.type = BT_INTEGER;
2473 ts.kind = gfc_index_integer_kind;
2475 gfc_convert_type_warn (e, &ts, 2, 0);
2478 return res;
2481 /* Function to create a DO loop including creation of the
2482 iteration variable. gfc_expr are copied.*/
2484 static gfc_code *
2485 create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
2486 gfc_namespace *ns, char *vname)
2489 char name[GFC_MAX_SYMBOL_LEN +1];
2490 gfc_symtree *symtree;
2491 gfc_symbol *symbol;
2492 gfc_expr *i;
2493 gfc_code *n, *n2;
2495 /* Create an expression for the iteration variable. */
2496 if (vname)
2497 sprintf (name, "__var_%d_do_%s", var_num++, vname);
2498 else
2499 sprintf (name, "__var_%d_do", var_num++);
2502 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
2503 gcc_unreachable ();
2505 /* Create the loop variable. */
2507 symbol = symtree->n.sym;
2508 symbol->ts.type = BT_INTEGER;
2509 symbol->ts.kind = gfc_index_integer_kind;
2510 symbol->attr.flavor = FL_VARIABLE;
2511 symbol->attr.referenced = 1;
2512 symbol->attr.dimension = 0;
2513 symbol->attr.fe_temp = 1;
2514 gfc_commit_symbol (symbol);
2516 i = gfc_get_expr ();
2517 i->expr_type = EXPR_VARIABLE;
2518 i->ts = symbol->ts;
2519 i->rank = 0;
2520 i->where = *where;
2521 i->symtree = symtree;
2523 /* ... and the nested DO statements. */
2524 n = XCNEW (gfc_code);
2525 n->op = EXEC_DO;
2526 n->loc = *where;
2527 n->ext.iterator = gfc_get_iterator ();
2528 n->ext.iterator->var = i;
2529 n->ext.iterator->start = convert_to_index_kind (start);
2530 n->ext.iterator->end = convert_to_index_kind (end);
2531 if (step)
2532 n->ext.iterator->step = convert_to_index_kind (step);
2533 else
2534 n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
2535 where, 1);
2537 n2 = XCNEW (gfc_code);
2538 n2->op = EXEC_DO;
2539 n2->loc = *where;
2540 n2->next = NULL;
2541 n->block = n2;
2542 return n;
2545 /* Get the upper bound of the DO loops for matmul along a dimension. This
2546 is one-based. */
2548 static gfc_expr*
2549 get_size_m1 (gfc_expr *e, int dimen)
2551 mpz_t size;
2552 gfc_expr *res;
2554 if (gfc_array_dimen_size (e, dimen - 1, &size))
2556 res = gfc_get_constant_expr (BT_INTEGER,
2557 gfc_index_integer_kind, &e->where);
2558 mpz_sub_ui (res->value.integer, size, 1);
2559 mpz_clear (size);
2561 else
2563 res = get_operand (INTRINSIC_MINUS,
2564 get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
2565 gfc_get_int_expr (gfc_index_integer_kind,
2566 &e->where, 1));
2567 gfc_simplify_expr (res, 0);
2570 return res;
2573 /* Function to return a scalarized expression. It is assumed that indices are
2574 zero based to make generation of DO loops easier. A zero as index will
2575 access the first element along a dimension. Single element references will
2576 be skipped. A NULL as an expression will be replaced by a full reference.
2577 This assumes that the index loops have gfc_index_integer_kind, and that all
2578 references have been frozen. */
2580 static gfc_expr*
2581 scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
2583 gfc_array_ref *ar;
2584 int i;
2585 int rank;
2586 gfc_expr *e;
2587 int i_index;
2588 bool was_fullref;
2590 e = gfc_copy_expr(e_in);
2592 rank = e->rank;
2594 ar = gfc_find_array_ref (e);
2596 /* We scalarize count_index variables, reducing the rank by count_index. */
2598 e->rank = rank - count_index;
2600 was_fullref = ar->type == AR_FULL;
2602 if (e->rank == 0)
2603 ar->type = AR_ELEMENT;
2604 else
2605 ar->type = AR_SECTION;
2607 /* Loop over the indices. For each index, create the expression
2608 index * stride + lbound(e, dim). */
2610 i_index = 0;
2611 for (i=0; i < ar->dimen; i++)
2613 if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
2615 if (index[i_index] != NULL)
2617 gfc_expr *lbound, *nindex;
2618 gfc_expr *loopvar;
2620 loopvar = gfc_copy_expr (index[i_index]);
2622 if (ar->stride[i])
2624 gfc_expr *tmp;
2626 tmp = gfc_copy_expr(ar->stride[i]);
2627 if (tmp->ts.kind != gfc_index_integer_kind)
2629 gfc_typespec ts;
2630 gfc_clear_ts (&ts);
2631 ts.type = BT_INTEGER;
2632 ts.kind = gfc_index_integer_kind;
2633 gfc_convert_type (tmp, &ts, 2);
2635 nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
2637 else
2638 nindex = loopvar;
2640 /* Calculate the lower bound of the expression. */
2641 if (ar->start[i])
2643 lbound = gfc_copy_expr (ar->start[i]);
2644 if (lbound->ts.kind != gfc_index_integer_kind)
2646 gfc_typespec ts;
2647 gfc_clear_ts (&ts);
2648 ts.type = BT_INTEGER;
2649 ts.kind = gfc_index_integer_kind;
2650 gfc_convert_type (lbound, &ts, 2);
2654 else
2656 gfc_expr *lbound_e;
2657 gfc_ref *ref;
2659 lbound_e = gfc_copy_expr (e_in);
2661 for (ref = lbound_e->ref; ref; ref = ref->next)
2662 if (ref->type == REF_ARRAY
2663 && (ref->u.ar.type == AR_FULL
2664 || ref->u.ar.type == AR_SECTION))
2665 break;
2667 if (ref->next)
2669 gfc_free_ref_list (ref->next);
2670 ref->next = NULL;
2673 if (!was_fullref)
2675 /* Look at full individual sections, like a(:). The first index
2676 is the lbound of a full ref. */
2677 int j;
2678 gfc_array_ref *ar;
2680 ar = &ref->u.ar;
2681 ar->type = AR_FULL;
2682 for (j = 0; j < ar->dimen; j++)
2684 gfc_free_expr (ar->start[j]);
2685 ar->start[j] = NULL;
2686 gfc_free_expr (ar->end[j]);
2687 ar->end[j] = NULL;
2688 gfc_free_expr (ar->stride[j]);
2689 ar->stride[j] = NULL;
2692 /* We have to get rid of the shape, if there is one. Do
2693 so by freeing it and calling gfc_resolve to rebuild
2694 it, if necessary. */
2696 if (lbound_e->shape)
2697 gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
2699 lbound_e->rank = ar->dimen;
2700 gfc_resolve_expr (lbound_e);
2702 lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
2703 i + 1);
2704 gfc_free_expr (lbound_e);
2707 ar->dimen_type[i] = DIMEN_ELEMENT;
2709 gfc_free_expr (ar->start[i]);
2710 ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
2712 gfc_free_expr (ar->end[i]);
2713 ar->end[i] = NULL;
2714 gfc_free_expr (ar->stride[i]);
2715 ar->stride[i] = NULL;
2716 gfc_simplify_expr (ar->start[i], 0);
2718 else if (was_fullref)
2720 gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
2722 i_index ++;
2726 return e;
2729 /* Helper function to check for a dimen vector as subscript. */
2731 static bool
2732 has_dimen_vector_ref (gfc_expr *e)
2734 gfc_array_ref *ar;
2735 int i;
2737 ar = gfc_find_array_ref (e);
2738 gcc_assert (ar);
2739 if (ar->type == AR_FULL)
2740 return false;
2742 for (i=0; i<ar->dimen; i++)
2743 if (ar->dimen_type[i] == DIMEN_VECTOR)
2744 return true;
2746 return false;
2749 /* If handed an expression of the form
2751 TRANSPOSE(CONJG(A))
2753 check if A can be handled by matmul and return if there is an uneven number
2754 of CONJG calls. Return a pointer to the array when everything is OK, NULL
2755 otherwise. The caller has to check for the correct rank. */
2757 static gfc_expr*
2758 check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
2760 *conjg = false;
2761 *transpose = false;
2765 if (e->expr_type == EXPR_VARIABLE)
2767 gcc_assert (e->rank == 1 || e->rank == 2);
2768 return e;
2770 else if (e->expr_type == EXPR_FUNCTION)
2772 if (e->value.function.isym == NULL)
2773 return NULL;
2775 if (e->value.function.isym->id == GFC_ISYM_CONJG)
2776 *conjg = !*conjg;
2777 else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE)
2778 *transpose = !*transpose;
2779 else return NULL;
2781 else
2782 return NULL;
2784 e = e->value.function.actual->expr;
2786 while(1);
2788 return NULL;
2791 /* Inline assignments of the form c = matmul(a,b).
2792 Handle only the cases currently where b and c are rank-two arrays.
2794 This basically translates the code to
2796 BLOCK
2797 integer i,j,k
2798 c = 0
2799 do j=0, size(b,2)-1
2800 do k=0, size(a, 2)-1
2801 do i=0, size(a, 1)-1
2802 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
2803 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
2804 a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
2805 b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
2806 end do
2807 end do
2808 end do
2809 END BLOCK
2813 static int
2814 inline_matmul_assign (gfc_code **c, int *walk_subtrees,
2815 void *data ATTRIBUTE_UNUSED)
2817 gfc_code *co = *c;
2818 gfc_expr *expr1, *expr2;
2819 gfc_expr *matrix_a, *matrix_b;
2820 gfc_actual_arglist *a, *b;
2821 gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
2822 gfc_expr *zero_e;
2823 gfc_expr *u1, *u2, *u3;
2824 gfc_expr *list[2];
2825 gfc_expr *ascalar, *bscalar, *cscalar;
2826 gfc_expr *mult;
2827 gfc_expr *var_1, *var_2, *var_3;
2828 gfc_expr *zero;
2829 gfc_namespace *ns;
2830 gfc_intrinsic_op op_times, op_plus;
2831 enum matrix_case m_case;
2832 int i;
2833 gfc_code *if_limit = NULL;
2834 gfc_code **next_code_point;
2835 bool conjg_a, conjg_b, transpose_a, transpose_b;
2837 if (co->op != EXEC_ASSIGN)
2838 return 0;
2840 if (in_where)
2841 return 0;
2843 /* For now don't do anything in OpenMP workshare, it confuses
2844 its translation, which expects only the allowed statements in there.
2845 We should figure out how to parallelize this eventually. */
2846 if (in_omp_workshare)
2847 return 0;
2849 expr1 = co->expr1;
2850 expr2 = co->expr2;
2851 if (expr2->expr_type != EXPR_FUNCTION
2852 || expr2->value.function.isym == NULL
2853 || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
2854 return 0;
2856 current_code = c;
2857 inserted_block = NULL;
2858 changed_statement = NULL;
2860 a = expr2->value.function.actual;
2861 matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
2862 if (transpose_a || matrix_a == NULL)
2863 return 0;
2865 b = a->next;
2866 matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
2867 if (matrix_b == NULL)
2868 return 0;
2870 if (has_dimen_vector_ref (expr1) || has_dimen_vector_ref (matrix_a)
2871 || has_dimen_vector_ref (matrix_b))
2872 return 0;
2874 /* We do not handle data dependencies yet. */
2875 if (gfc_check_dependency (expr1, matrix_a, true)
2876 || gfc_check_dependency (expr1, matrix_b, true))
2877 return 0;
2879 if (matrix_a->rank == 2)
2881 if (matrix_b->rank == 1)
2882 m_case = A2B1;
2883 else
2885 if (transpose_b)
2886 m_case = A2B2T;
2887 else
2888 m_case = A2B2;
2891 else
2893 /* Vector * Transpose(B) not handled yet. */
2894 if (transpose_b)
2895 m_case = none;
2896 else
2897 m_case = A1B2;
2900 if (m_case == none)
2901 return 0;
2903 ns = insert_block ();
2905 /* Assign the type of the zero expression for initializing the resulting
2906 array, and the expression (+ and * for real, integer and complex;
2907 .and. and .or for logical. */
2909 switch(expr1->ts.type)
2911 case BT_INTEGER:
2912 zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
2913 op_times = INTRINSIC_TIMES;
2914 op_plus = INTRINSIC_PLUS;
2915 break;
2917 case BT_LOGICAL:
2918 op_times = INTRINSIC_AND;
2919 op_plus = INTRINSIC_OR;
2920 zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
2922 break;
2923 case BT_REAL:
2924 zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
2925 &expr1->where);
2926 mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
2927 op_times = INTRINSIC_TIMES;
2928 op_plus = INTRINSIC_PLUS;
2929 break;
2931 case BT_COMPLEX:
2932 zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
2933 &expr1->where);
2934 mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
2935 op_times = INTRINSIC_TIMES;
2936 op_plus = INTRINSIC_PLUS;
2938 break;
2940 default:
2941 gcc_unreachable();
2944 current_code = &ns->code;
2946 /* Freeze the references, keeping track of how many temporary variables were
2947 created. */
2948 n_vars = 0;
2949 freeze_references (matrix_a);
2950 freeze_references (matrix_b);
2951 freeze_references (expr1);
2953 if (n_vars == 0)
2954 next_code_point = current_code;
2955 else
2957 next_code_point = &ns->code;
2958 for (i=0; i<n_vars; i++)
2959 next_code_point = &(*next_code_point)->next;
2962 /* Take care of the inline flag. If the limit check evaluates to a
2963 constant, dead code elimination will eliminate the unneeded branch. */
2965 if (m_case == A2B2 && flag_inline_matmul_limit > 0)
2967 if_limit = inline_limit_check (matrix_a, matrix_b, m_case);
2969 /* Insert the original statement into the else branch. */
2970 if_limit->block->block->next = co;
2971 co->next = NULL;
2973 /* ... and the new ones go into the original one. */
2974 *next_code_point = if_limit;
2975 next_code_point = &if_limit->block->next;
2978 assign_zero = XCNEW (gfc_code);
2979 assign_zero->op = EXEC_ASSIGN;
2980 assign_zero->loc = co->loc;
2981 assign_zero->expr1 = gfc_copy_expr (expr1);
2982 assign_zero->expr2 = zero_e;
2984 /* Handle the reallocation, if needed. */
2985 if (flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1))
2987 gfc_code *lhs_alloc;
2989 /* Only need to check a single dimension for the A2B2 case for
2990 bounds checking, the rest will be allocated. */
2992 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS && m_case == A2B2)
2994 gfc_code *test;
2995 gfc_expr *a2, *b1;
2997 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
2998 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
2999 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3000 "in MATMUL intrinsic: Is %ld, should be %ld");
3001 *next_code_point = test;
3002 next_code_point = &test->next;
3006 lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
3008 *next_code_point = lhs_alloc;
3009 next_code_point = &lhs_alloc->next;
3012 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3014 gfc_code *test;
3015 gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
3017 if (m_case == A2B2 || m_case == A2B1)
3019 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3020 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3021 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3022 "in MATMUL intrinsic: Is %ld, should be %ld");
3023 *next_code_point = test;
3024 next_code_point = &test->next;
3026 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3027 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3029 if (m_case == A2B2)
3030 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3031 "MATMUL intrinsic for dimension 1: "
3032 "is %ld, should be %ld");
3033 else if (m_case == A2B1)
3034 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3035 "MATMUL intrinsic: "
3036 "is %ld, should be %ld");
3039 *next_code_point = test;
3040 next_code_point = &test->next;
3042 else if (m_case == A1B2)
3044 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3045 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3046 test = runtime_error_ne (b1, a1, "Dimension of array B incorrect "
3047 "in MATMUL intrinsic: Is %ld, should be %ld");
3048 *next_code_point = test;
3049 next_code_point = &test->next;
3051 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3052 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3054 test = runtime_error_ne (c1, b2, "Incorrect extent in return array in "
3055 "MATMUL intrinsic: "
3056 "is %ld, should be %ld");
3058 *next_code_point = test;
3059 next_code_point = &test->next;
3062 if (m_case == A2B2)
3064 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3065 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3066 test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
3067 "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
3069 *next_code_point = test;
3070 next_code_point = &test->next;
3073 if (m_case == A2B2T)
3075 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3076 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3077 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3078 "MATMUL intrinsic for dimension 1: "
3079 "is %ld, should be %ld");
3081 *next_code_point = test;
3082 next_code_point = &test->next;
3084 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3085 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3086 test = runtime_error_ne (c2, b1, "Incorrect extent in return array in "
3087 "MATMUL intrinsic for dimension 2: "
3088 "is %ld, should be %ld");
3089 *next_code_point = test;
3090 next_code_point = &test->next;
3092 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3093 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3095 test = runtime_error_ne (b2, a2, "Incorrect extent in argument B in "
3096 "MATMUL intrnisic for dimension 2: "
3097 "is %ld, should be %ld");
3098 *next_code_point = test;
3099 next_code_point = &test->next;
3104 *next_code_point = assign_zero;
3106 zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
3108 assign_matmul = XCNEW (gfc_code);
3109 assign_matmul->op = EXEC_ASSIGN;
3110 assign_matmul->loc = co->loc;
3112 /* Get the bounds for the loops, create them and create the scalarized
3113 expressions. */
3115 switch (m_case)
3117 case A2B2:
3118 inline_limit_check (matrix_a, matrix_b, m_case);
3120 u1 = get_size_m1 (matrix_b, 2);
3121 u2 = get_size_m1 (matrix_a, 2);
3122 u3 = get_size_m1 (matrix_a, 1);
3124 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3125 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3126 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
3128 do_1->block->next = do_2;
3129 do_2->block->next = do_3;
3130 do_3->block->next = assign_matmul;
3132 var_1 = do_1->ext.iterator->var;
3133 var_2 = do_2->ext.iterator->var;
3134 var_3 = do_3->ext.iterator->var;
3136 list[0] = var_3;
3137 list[1] = var_1;
3138 cscalar = scalarized_expr (co->expr1, list, 2);
3140 list[0] = var_3;
3141 list[1] = var_2;
3142 ascalar = scalarized_expr (matrix_a, list, 2);
3144 list[0] = var_2;
3145 list[1] = var_1;
3146 bscalar = scalarized_expr (matrix_b, list, 2);
3148 break;
3150 case A2B2T:
3151 inline_limit_check (matrix_a, matrix_b, m_case);
3153 u1 = get_size_m1 (matrix_b, 1);
3154 u2 = get_size_m1 (matrix_a, 2);
3155 u3 = get_size_m1 (matrix_a, 1);
3157 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3158 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3159 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
3161 do_1->block->next = do_2;
3162 do_2->block->next = do_3;
3163 do_3->block->next = assign_matmul;
3165 var_1 = do_1->ext.iterator->var;
3166 var_2 = do_2->ext.iterator->var;
3167 var_3 = do_3->ext.iterator->var;
3169 list[0] = var_3;
3170 list[1] = var_1;
3171 cscalar = scalarized_expr (co->expr1, list, 2);
3173 list[0] = var_3;
3174 list[1] = var_2;
3175 ascalar = scalarized_expr (matrix_a, list, 2);
3177 list[0] = var_1;
3178 list[1] = var_2;
3179 bscalar = scalarized_expr (matrix_b, list, 2);
3181 break;
3183 case A2B1:
3184 u1 = get_size_m1 (matrix_b, 1);
3185 u2 = get_size_m1 (matrix_a, 1);
3187 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3188 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3190 do_1->block->next = do_2;
3191 do_2->block->next = assign_matmul;
3193 var_1 = do_1->ext.iterator->var;
3194 var_2 = do_2->ext.iterator->var;
3196 list[0] = var_2;
3197 cscalar = scalarized_expr (co->expr1, list, 1);
3199 list[0] = var_2;
3200 list[1] = var_1;
3201 ascalar = scalarized_expr (matrix_a, list, 2);
3203 list[0] = var_1;
3204 bscalar = scalarized_expr (matrix_b, list, 1);
3206 break;
3208 case A1B2:
3209 u1 = get_size_m1 (matrix_b, 2);
3210 u2 = get_size_m1 (matrix_a, 1);
3212 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3213 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3215 do_1->block->next = do_2;
3216 do_2->block->next = assign_matmul;
3218 var_1 = do_1->ext.iterator->var;
3219 var_2 = do_2->ext.iterator->var;
3221 list[0] = var_1;
3222 cscalar = scalarized_expr (co->expr1, list, 1);
3224 list[0] = var_2;
3225 ascalar = scalarized_expr (matrix_a, list, 1);
3227 list[0] = var_2;
3228 list[1] = var_1;
3229 bscalar = scalarized_expr (matrix_b, list, 2);
3231 break;
3233 default:
3234 gcc_unreachable();
3237 if (conjg_a)
3238 ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
3239 matrix_a->where, 1, ascalar);
3241 if (conjg_b)
3242 bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
3243 matrix_b->where, 1, bscalar);
3245 /* First loop comes after the zero assignment. */
3246 assign_zero->next = do_1;
3248 /* Build the assignment expression in the loop. */
3249 assign_matmul->expr1 = gfc_copy_expr (cscalar);
3251 mult = get_operand (op_times, ascalar, bscalar);
3252 assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
3254 /* If we don't want to keep the original statement around in
3255 the else branch, we can free it. */
3257 if (if_limit == NULL)
3258 gfc_free_statements(co);
3259 else
3260 co->next = NULL;
3262 gfc_free_expr (zero);
3263 *walk_subtrees = 0;
3264 return 0;
3267 #define WALK_SUBEXPR(NODE) \
3268 do \
3270 result = gfc_expr_walker (&(NODE), exprfn, data); \
3271 if (result) \
3272 return result; \
3274 while (0)
3275 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
3277 /* Walk expression *E, calling EXPRFN on each expression in it. */
3280 gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
3282 while (*e)
3284 int walk_subtrees = 1;
3285 gfc_actual_arglist *a;
3286 gfc_ref *r;
3287 gfc_constructor *c;
3289 int result = exprfn (e, &walk_subtrees, data);
3290 if (result)
3291 return result;
3292 if (walk_subtrees)
3293 switch ((*e)->expr_type)
3295 case EXPR_OP:
3296 WALK_SUBEXPR ((*e)->value.op.op1);
3297 WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
3298 break;
3299 case EXPR_FUNCTION:
3300 for (a = (*e)->value.function.actual; a; a = a->next)
3301 WALK_SUBEXPR (a->expr);
3302 break;
3303 case EXPR_COMPCALL:
3304 case EXPR_PPC:
3305 WALK_SUBEXPR ((*e)->value.compcall.base_object);
3306 for (a = (*e)->value.compcall.actual; a; a = a->next)
3307 WALK_SUBEXPR (a->expr);
3308 break;
3310 case EXPR_STRUCTURE:
3311 case EXPR_ARRAY:
3312 for (c = gfc_constructor_first ((*e)->value.constructor); c;
3313 c = gfc_constructor_next (c))
3315 if (c->iterator == NULL)
3316 WALK_SUBEXPR (c->expr);
3317 else
3319 iterator_level ++;
3320 WALK_SUBEXPR (c->expr);
3321 iterator_level --;
3322 WALK_SUBEXPR (c->iterator->var);
3323 WALK_SUBEXPR (c->iterator->start);
3324 WALK_SUBEXPR (c->iterator->end);
3325 WALK_SUBEXPR (c->iterator->step);
3329 if ((*e)->expr_type != EXPR_ARRAY)
3330 break;
3332 /* Fall through to the variable case in order to walk the
3333 reference. */
3335 case EXPR_SUBSTRING:
3336 case EXPR_VARIABLE:
3337 for (r = (*e)->ref; r; r = r->next)
3339 gfc_array_ref *ar;
3340 int i;
3342 switch (r->type)
3344 case REF_ARRAY:
3345 ar = &r->u.ar;
3346 if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
3348 for (i=0; i< ar->dimen; i++)
3350 WALK_SUBEXPR (ar->start[i]);
3351 WALK_SUBEXPR (ar->end[i]);
3352 WALK_SUBEXPR (ar->stride[i]);
3356 break;
3358 case REF_SUBSTRING:
3359 WALK_SUBEXPR (r->u.ss.start);
3360 WALK_SUBEXPR (r->u.ss.end);
3361 break;
3363 case REF_COMPONENT:
3364 break;
3368 default:
3369 break;
3371 return 0;
3373 return 0;
3376 #define WALK_SUBCODE(NODE) \
3377 do \
3379 result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
3380 if (result) \
3381 return result; \
3383 while (0)
3385 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
3386 on each expression in it. If any of the hooks returns non-zero, that
3387 value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
3388 no subcodes or subexpressions are traversed. */
3391 gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
3392 void *data)
3394 for (; *c; c = &(*c)->next)
3396 int walk_subtrees = 1;
3397 int result = codefn (c, &walk_subtrees, data);
3398 if (result)
3399 return result;
3401 if (walk_subtrees)
3403 gfc_code *b;
3404 gfc_actual_arglist *a;
3405 gfc_code *co;
3406 gfc_association_list *alist;
3407 bool saved_in_omp_workshare;
3408 bool saved_in_where;
3410 /* There might be statement insertions before the current code,
3411 which must not affect the expression walker. */
3413 co = *c;
3414 saved_in_omp_workshare = in_omp_workshare;
3415 saved_in_where = in_where;
3417 switch (co->op)
3420 case EXEC_BLOCK:
3421 WALK_SUBCODE (co->ext.block.ns->code);
3422 if (co->ext.block.assoc)
3424 bool saved_in_assoc_list = in_assoc_list;
3426 in_assoc_list = true;
3427 for (alist = co->ext.block.assoc; alist; alist = alist->next)
3428 WALK_SUBEXPR (alist->target);
3430 in_assoc_list = saved_in_assoc_list;
3433 break;
3435 case EXEC_DO:
3436 doloop_level ++;
3437 WALK_SUBEXPR (co->ext.iterator->var);
3438 WALK_SUBEXPR (co->ext.iterator->start);
3439 WALK_SUBEXPR (co->ext.iterator->end);
3440 WALK_SUBEXPR (co->ext.iterator->step);
3441 break;
3443 case EXEC_WHERE:
3444 in_where = true;
3445 break;
3447 case EXEC_CALL:
3448 case EXEC_ASSIGN_CALL:
3449 for (a = co->ext.actual; a; a = a->next)
3450 WALK_SUBEXPR (a->expr);
3451 break;
3453 case EXEC_CALL_PPC:
3454 WALK_SUBEXPR (co->expr1);
3455 for (a = co->ext.actual; a; a = a->next)
3456 WALK_SUBEXPR (a->expr);
3457 break;
3459 case EXEC_SELECT:
3460 WALK_SUBEXPR (co->expr1);
3461 for (b = co->block; b; b = b->block)
3463 gfc_case *cp;
3464 for (cp = b->ext.block.case_list; cp; cp = cp->next)
3466 WALK_SUBEXPR (cp->low);
3467 WALK_SUBEXPR (cp->high);
3469 WALK_SUBCODE (b->next);
3471 continue;
3473 case EXEC_ALLOCATE:
3474 case EXEC_DEALLOCATE:
3476 gfc_alloc *a;
3477 for (a = co->ext.alloc.list; a; a = a->next)
3478 WALK_SUBEXPR (a->expr);
3479 break;
3482 case EXEC_FORALL:
3483 case EXEC_DO_CONCURRENT:
3485 gfc_forall_iterator *fa;
3486 for (fa = co->ext.forall_iterator; fa; fa = fa->next)
3488 WALK_SUBEXPR (fa->var);
3489 WALK_SUBEXPR (fa->start);
3490 WALK_SUBEXPR (fa->end);
3491 WALK_SUBEXPR (fa->stride);
3493 if (co->op == EXEC_FORALL)
3494 forall_level ++;
3495 break;
3498 case EXEC_OPEN:
3499 WALK_SUBEXPR (co->ext.open->unit);
3500 WALK_SUBEXPR (co->ext.open->file);
3501 WALK_SUBEXPR (co->ext.open->status);
3502 WALK_SUBEXPR (co->ext.open->access);
3503 WALK_SUBEXPR (co->ext.open->form);
3504 WALK_SUBEXPR (co->ext.open->recl);
3505 WALK_SUBEXPR (co->ext.open->blank);
3506 WALK_SUBEXPR (co->ext.open->position);
3507 WALK_SUBEXPR (co->ext.open->action);
3508 WALK_SUBEXPR (co->ext.open->delim);
3509 WALK_SUBEXPR (co->ext.open->pad);
3510 WALK_SUBEXPR (co->ext.open->iostat);
3511 WALK_SUBEXPR (co->ext.open->iomsg);
3512 WALK_SUBEXPR (co->ext.open->convert);
3513 WALK_SUBEXPR (co->ext.open->decimal);
3514 WALK_SUBEXPR (co->ext.open->encoding);
3515 WALK_SUBEXPR (co->ext.open->round);
3516 WALK_SUBEXPR (co->ext.open->sign);
3517 WALK_SUBEXPR (co->ext.open->asynchronous);
3518 WALK_SUBEXPR (co->ext.open->id);
3519 WALK_SUBEXPR (co->ext.open->newunit);
3520 break;
3522 case EXEC_CLOSE:
3523 WALK_SUBEXPR (co->ext.close->unit);
3524 WALK_SUBEXPR (co->ext.close->status);
3525 WALK_SUBEXPR (co->ext.close->iostat);
3526 WALK_SUBEXPR (co->ext.close->iomsg);
3527 break;
3529 case EXEC_BACKSPACE:
3530 case EXEC_ENDFILE:
3531 case EXEC_REWIND:
3532 case EXEC_FLUSH:
3533 WALK_SUBEXPR (co->ext.filepos->unit);
3534 WALK_SUBEXPR (co->ext.filepos->iostat);
3535 WALK_SUBEXPR (co->ext.filepos->iomsg);
3536 break;
3538 case EXEC_INQUIRE:
3539 WALK_SUBEXPR (co->ext.inquire->unit);
3540 WALK_SUBEXPR (co->ext.inquire->file);
3541 WALK_SUBEXPR (co->ext.inquire->iomsg);
3542 WALK_SUBEXPR (co->ext.inquire->iostat);
3543 WALK_SUBEXPR (co->ext.inquire->exist);
3544 WALK_SUBEXPR (co->ext.inquire->opened);
3545 WALK_SUBEXPR (co->ext.inquire->number);
3546 WALK_SUBEXPR (co->ext.inquire->named);
3547 WALK_SUBEXPR (co->ext.inquire->name);
3548 WALK_SUBEXPR (co->ext.inquire->access);
3549 WALK_SUBEXPR (co->ext.inquire->sequential);
3550 WALK_SUBEXPR (co->ext.inquire->direct);
3551 WALK_SUBEXPR (co->ext.inquire->form);
3552 WALK_SUBEXPR (co->ext.inquire->formatted);
3553 WALK_SUBEXPR (co->ext.inquire->unformatted);
3554 WALK_SUBEXPR (co->ext.inquire->recl);
3555 WALK_SUBEXPR (co->ext.inquire->nextrec);
3556 WALK_SUBEXPR (co->ext.inquire->blank);
3557 WALK_SUBEXPR (co->ext.inquire->position);
3558 WALK_SUBEXPR (co->ext.inquire->action);
3559 WALK_SUBEXPR (co->ext.inquire->read);
3560 WALK_SUBEXPR (co->ext.inquire->write);
3561 WALK_SUBEXPR (co->ext.inquire->readwrite);
3562 WALK_SUBEXPR (co->ext.inquire->delim);
3563 WALK_SUBEXPR (co->ext.inquire->encoding);
3564 WALK_SUBEXPR (co->ext.inquire->pad);
3565 WALK_SUBEXPR (co->ext.inquire->iolength);
3566 WALK_SUBEXPR (co->ext.inquire->convert);
3567 WALK_SUBEXPR (co->ext.inquire->strm_pos);
3568 WALK_SUBEXPR (co->ext.inquire->asynchronous);
3569 WALK_SUBEXPR (co->ext.inquire->decimal);
3570 WALK_SUBEXPR (co->ext.inquire->pending);
3571 WALK_SUBEXPR (co->ext.inquire->id);
3572 WALK_SUBEXPR (co->ext.inquire->sign);
3573 WALK_SUBEXPR (co->ext.inquire->size);
3574 WALK_SUBEXPR (co->ext.inquire->round);
3575 break;
3577 case EXEC_WAIT:
3578 WALK_SUBEXPR (co->ext.wait->unit);
3579 WALK_SUBEXPR (co->ext.wait->iostat);
3580 WALK_SUBEXPR (co->ext.wait->iomsg);
3581 WALK_SUBEXPR (co->ext.wait->id);
3582 break;
3584 case EXEC_READ:
3585 case EXEC_WRITE:
3586 WALK_SUBEXPR (co->ext.dt->io_unit);
3587 WALK_SUBEXPR (co->ext.dt->format_expr);
3588 WALK_SUBEXPR (co->ext.dt->rec);
3589 WALK_SUBEXPR (co->ext.dt->advance);
3590 WALK_SUBEXPR (co->ext.dt->iostat);
3591 WALK_SUBEXPR (co->ext.dt->size);
3592 WALK_SUBEXPR (co->ext.dt->iomsg);
3593 WALK_SUBEXPR (co->ext.dt->id);
3594 WALK_SUBEXPR (co->ext.dt->pos);
3595 WALK_SUBEXPR (co->ext.dt->asynchronous);
3596 WALK_SUBEXPR (co->ext.dt->blank);
3597 WALK_SUBEXPR (co->ext.dt->decimal);
3598 WALK_SUBEXPR (co->ext.dt->delim);
3599 WALK_SUBEXPR (co->ext.dt->pad);
3600 WALK_SUBEXPR (co->ext.dt->round);
3601 WALK_SUBEXPR (co->ext.dt->sign);
3602 WALK_SUBEXPR (co->ext.dt->extra_comma);
3603 break;
3605 case EXEC_OMP_PARALLEL:
3606 case EXEC_OMP_PARALLEL_DO:
3607 case EXEC_OMP_PARALLEL_DO_SIMD:
3608 case EXEC_OMP_PARALLEL_SECTIONS:
3610 in_omp_workshare = false;
3612 /* This goto serves as a shortcut to avoid code
3613 duplication or a larger if or switch statement. */
3614 goto check_omp_clauses;
3616 case EXEC_OMP_WORKSHARE:
3617 case EXEC_OMP_PARALLEL_WORKSHARE:
3619 in_omp_workshare = true;
3621 /* Fall through */
3623 case EXEC_OMP_DISTRIBUTE:
3624 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
3625 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
3626 case EXEC_OMP_DISTRIBUTE_SIMD:
3627 case EXEC_OMP_DO:
3628 case EXEC_OMP_DO_SIMD:
3629 case EXEC_OMP_SECTIONS:
3630 case EXEC_OMP_SINGLE:
3631 case EXEC_OMP_END_SINGLE:
3632 case EXEC_OMP_SIMD:
3633 case EXEC_OMP_TARGET:
3634 case EXEC_OMP_TARGET_DATA:
3635 case EXEC_OMP_TARGET_TEAMS:
3636 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3637 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
3638 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3639 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
3640 case EXEC_OMP_TARGET_UPDATE:
3641 case EXEC_OMP_TASK:
3642 case EXEC_OMP_TEAMS:
3643 case EXEC_OMP_TEAMS_DISTRIBUTE:
3644 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
3645 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3646 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
3648 /* Come to this label only from the
3649 EXEC_OMP_PARALLEL_* cases above. */
3651 check_omp_clauses:
3653 if (co->ext.omp_clauses)
3655 gfc_omp_namelist *n;
3656 static int list_types[]
3657 = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
3658 OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
3659 size_t idx;
3660 WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
3661 WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
3662 WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
3663 WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
3664 WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
3665 WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
3666 WALK_SUBEXPR (co->ext.omp_clauses->num_teams);
3667 WALK_SUBEXPR (co->ext.omp_clauses->device);
3668 WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
3669 WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
3670 for (idx = 0;
3671 idx < sizeof (list_types) / sizeof (list_types[0]);
3672 idx++)
3673 for (n = co->ext.omp_clauses->lists[list_types[idx]];
3674 n; n = n->next)
3675 WALK_SUBEXPR (n->expr);
3677 break;
3678 default:
3679 break;
3682 WALK_SUBEXPR (co->expr1);
3683 WALK_SUBEXPR (co->expr2);
3684 WALK_SUBEXPR (co->expr3);
3685 WALK_SUBEXPR (co->expr4);
3686 for (b = co->block; b; b = b->block)
3688 WALK_SUBEXPR (b->expr1);
3689 WALK_SUBEXPR (b->expr2);
3690 WALK_SUBCODE (b->next);
3693 if (co->op == EXEC_FORALL)
3694 forall_level --;
3696 if (co->op == EXEC_DO)
3697 doloop_level --;
3699 in_omp_workshare = saved_in_omp_workshare;
3700 in_where = saved_in_where;
3703 return 0;