1 /* Pass manager for Fortran front end.
2 Copyright (C) 2010-2017 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
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
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/>. */
23 #include "coretypes.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
*,
52 static void check_locus (gfc_namespace
*);
55 /* How deep we are inside an argument list. */
57 static int count_arglist
;
59 /* Vector of gfc_expr ** we operate on. */
61 static vec
<gfc_expr
**> expr_array
;
63 /* Pointer to the gfc_code we currently work on - to be able to insert
64 a block before the statement. */
66 static gfc_code
**current_code
;
68 /* Pointer to the block to be inserted, and the statement we are
69 changing within the block. */
71 static gfc_code
*inserted_block
, **changed_statement
;
73 /* The namespace we are currently dealing with. */
75 static gfc_namespace
*current_ns
;
77 /* If we are within any forall loop. */
79 static int forall_level
;
81 /* Keep track of whether we are within an OMP workshare. */
83 static bool in_omp_workshare
;
85 /* Keep track of whether we are within a WHERE statement. */
89 /* Keep track of iterators for array constructors. */
91 static int iterator_level
;
93 /* Keep track of DO loop levels. */
95 static vec
<gfc_code
*> doloop_list
;
97 static int doloop_level
;
99 /* Vector of gfc_expr * to keep track of DO loops. */
101 struct my_struct
*evec
;
103 /* Keep track of association lists. */
105 static bool in_assoc_list
;
107 /* Counter for temporary variables. */
109 static int var_num
= 1;
111 /* What sort of matrix we are dealing with when inlining MATMUL. */
113 enum matrix_case
{ none
=0, A2B2
, A2B1
, A1B2
, A2B2T
};
115 /* Keep track of the number of expressions we have inserted so far
120 /* Entry point - run all passes for a namespace. */
123 gfc_run_passes (gfc_namespace
*ns
)
126 /* Warn about dubious DO loops where the index might
131 doloop_list
.release ();
138 if (flag_frontend_optimize
)
140 optimize_namespace (ns
);
141 optimize_reduction (ns
);
142 if (flag_dump_fortran_optimized
)
143 gfc_dump_parse_tree (ns
, stdout
);
145 expr_array
.release ();
148 gfc_get_errors (&w
, &e
);
152 if (flag_realloc_lhs
)
153 realloc_strings (ns
);
158 /* Callback function: Warn if there is no location information in a
162 check_locus_code (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
163 void *data ATTRIBUTE_UNUSED
)
166 if (c
&& *c
&& (((*c
)->loc
.nextc
== NULL
) || ((*c
)->loc
.lb
== NULL
)))
167 gfc_warning_internal (0, "No location in statement");
173 /* Callback function: Warn if there is no location information in an
177 check_locus_expr (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
178 void *data ATTRIBUTE_UNUSED
)
181 if (e
&& *e
&& (((*e
)->where
.nextc
== NULL
|| (*e
)->where
.lb
== NULL
)))
182 gfc_warning_internal (0, "No location in expression near %L",
183 &((*current_code
)->loc
));
187 /* Run check for missing location information. */
190 check_locus (gfc_namespace
*ns
)
192 gfc_code_walker (&ns
->code
, check_locus_code
, check_locus_expr
, NULL
);
194 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
196 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
203 /* Callback for each gfc_code node invoked from check_realloc_strings.
204 For an allocatable LHS string which also appears as a variable on
216 realloc_string_callback (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
217 void *data ATTRIBUTE_UNUSED
)
219 gfc_expr
*expr1
, *expr2
;
225 if (co
->op
!= EXEC_ASSIGN
)
229 if (expr1
->ts
.type
!= BT_CHARACTER
|| expr1
->rank
!= 0
230 || !gfc_expr_attr(expr1
).allocatable
231 || !expr1
->ts
.deferred
)
234 expr2
= gfc_discard_nops (co
->expr2
);
235 if (expr2
->expr_type
!= EXPR_VARIABLE
)
238 found_substr
= false;
239 for (ref
= expr2
->ref
; ref
; ref
= ref
->next
)
241 if (ref
->type
== REF_SUBSTRING
)
250 if (!gfc_check_dependency (expr1
, expr2
, true))
253 /* gfc_check_dependency doesn't always pick up identical expressions.
254 However, eliminating the above sends the compiler into an infinite
255 loop on valid expressions. Without this check, the gimplifier emits
256 an ICE for a = a, where a is deferred character length. */
257 if (!gfc_dep_compare_expr (expr1
, expr2
))
261 inserted_block
= NULL
;
262 changed_statement
= NULL
;
263 n
= create_var (expr2
, "realloc_string");
268 /* Callback for each gfc_code node invoked through gfc_code_walker
269 from optimize_namespace. */
272 optimize_code (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
273 void *data ATTRIBUTE_UNUSED
)
280 if (op
== EXEC_CALL
|| op
== EXEC_COMPCALL
|| op
== EXEC_ASSIGN_CALL
281 || op
== EXEC_CALL_PPC
)
287 inserted_block
= NULL
;
288 changed_statement
= NULL
;
290 if (op
== EXEC_ASSIGN
)
291 optimize_assignment (*c
);
295 /* Callback for each gfc_expr node invoked through gfc_code_walker
296 from optimize_namespace. */
299 optimize_expr (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
300 void *data ATTRIBUTE_UNUSED
)
304 if ((*e
)->expr_type
== EXPR_FUNCTION
)
307 function_expr
= true;
310 function_expr
= false;
312 if (optimize_trim (*e
))
313 gfc_simplify_expr (*e
, 0);
315 if (optimize_lexical_comparison (*e
))
316 gfc_simplify_expr (*e
, 0);
318 if ((*e
)->expr_type
== EXPR_OP
&& optimize_op (*e
))
319 gfc_simplify_expr (*e
, 0);
321 if ((*e
)->expr_type
== EXPR_FUNCTION
&& (*e
)->value
.function
.isym
)
322 switch ((*e
)->value
.function
.isym
->id
)
324 case GFC_ISYM_MINLOC
:
325 case GFC_ISYM_MAXLOC
:
326 optimize_minmaxloc (e
);
338 /* Auxiliary function to handle the arguments to reduction intrnisics. If the
339 function is a scalar, just copy it; otherwise returns the new element, the
340 old one can be freed. */
343 copy_walk_reduction_arg (gfc_constructor
*c
, gfc_expr
*fn
)
345 gfc_expr
*fcn
, *e
= c
->expr
;
347 fcn
= gfc_copy_expr (e
);
350 gfc_constructor_base newbase
;
352 gfc_constructor
*new_c
;
355 new_expr
= gfc_get_expr ();
356 new_expr
->expr_type
= EXPR_ARRAY
;
357 new_expr
->ts
= e
->ts
;
358 new_expr
->where
= e
->where
;
360 new_c
= gfc_constructor_append_expr (&newbase
, fcn
, &(e
->where
));
361 new_c
->iterator
= c
->iterator
;
362 new_expr
->value
.constructor
= newbase
;
370 gfc_isym_id id
= fn
->value
.function
.isym
->id
;
372 if (id
== GFC_ISYM_SUM
|| id
== GFC_ISYM_PRODUCT
)
373 fcn
= gfc_build_intrinsic_call (current_ns
, id
,
374 fn
->value
.function
.isym
->name
,
375 fn
->where
, 3, fcn
, NULL
, NULL
);
376 else if (id
== GFC_ISYM_ANY
|| id
== GFC_ISYM_ALL
)
377 fcn
= gfc_build_intrinsic_call (current_ns
, id
,
378 fn
->value
.function
.isym
->name
,
379 fn
->where
, 2, fcn
, NULL
);
381 gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
383 fcn
->symtree
->n
.sym
->attr
.access
= ACCESS_PRIVATE
;
389 /* Callback function for optimzation of reductions to scalars. Transform ANY
390 ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
391 correspondingly. Handly only the simple cases without MASK and DIM. */
394 callback_reduction (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
395 void *data ATTRIBUTE_UNUSED
)
400 gfc_actual_arglist
*a
;
401 gfc_actual_arglist
*dim
;
403 gfc_expr
*res
, *new_expr
;
404 gfc_actual_arglist
*mask
;
408 if (fn
->rank
!= 0 || fn
->expr_type
!= EXPR_FUNCTION
409 || fn
->value
.function
.isym
== NULL
)
412 id
= fn
->value
.function
.isym
->id
;
414 if (id
!= GFC_ISYM_SUM
&& id
!= GFC_ISYM_PRODUCT
415 && id
!= GFC_ISYM_ANY
&& id
!= GFC_ISYM_ALL
)
418 a
= fn
->value
.function
.actual
;
420 /* Don't handle MASK or DIM. */
424 if (dim
->expr
!= NULL
)
427 if (id
== GFC_ISYM_SUM
|| id
== GFC_ISYM_PRODUCT
)
430 if ( mask
->expr
!= NULL
)
436 if (arg
->expr_type
!= EXPR_ARRAY
)
445 case GFC_ISYM_PRODUCT
:
446 op
= INTRINSIC_TIMES
;
461 c
= gfc_constructor_first (arg
->value
.constructor
);
463 /* Don't do any simplififcation if we have
464 - no element in the constructor or
465 - only have a single element in the array which contains an
471 res
= copy_walk_reduction_arg (c
, fn
);
473 c
= gfc_constructor_next (c
);
476 new_expr
= gfc_get_expr ();
477 new_expr
->ts
= fn
->ts
;
478 new_expr
->expr_type
= EXPR_OP
;
479 new_expr
->rank
= fn
->rank
;
480 new_expr
->where
= fn
->where
;
481 new_expr
->value
.op
.op
= op
;
482 new_expr
->value
.op
.op1
= res
;
483 new_expr
->value
.op
.op2
= copy_walk_reduction_arg (c
, fn
);
485 c
= gfc_constructor_next (c
);
488 gfc_simplify_expr (res
, 0);
495 /* Callback function for common function elimination, called from cfe_expr_0.
496 Put all eligible function expressions into expr_array. */
499 cfe_register_funcs (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
500 void *data ATTRIBUTE_UNUSED
)
503 if ((*e
)->expr_type
!= EXPR_FUNCTION
)
506 /* We don't do character functions with unknown charlens. */
507 if ((*e
)->ts
.type
== BT_CHARACTER
508 && ((*e
)->ts
.u
.cl
== NULL
|| (*e
)->ts
.u
.cl
->length
== NULL
509 || (*e
)->ts
.u
.cl
->length
->expr_type
!= EXPR_CONSTANT
))
512 /* We don't do function elimination within FORALL statements, it can
513 lead to wrong-code in certain circumstances. */
515 if (forall_level
> 0)
518 /* Function elimination inside an iterator could lead to functions which
519 depend on iterator variables being moved outside. FIXME: We should check
520 if the functions do indeed depend on the iterator variable. */
522 if (iterator_level
> 0)
525 /* If we don't know the shape at compile time, we create an allocatable
526 temporary variable to hold the intermediate result, but only if
527 allocation on assignment is active. */
529 if ((*e
)->rank
> 0 && (*e
)->shape
== NULL
&& !flag_realloc_lhs
)
532 /* Skip the test for pure functions if -faggressive-function-elimination
534 if ((*e
)->value
.function
.esym
)
536 /* Don't create an array temporary for elemental functions. */
537 if ((*e
)->value
.function
.esym
->attr
.elemental
&& (*e
)->rank
> 0)
540 /* Only eliminate potentially impure functions if the
541 user specifically requested it. */
542 if (!flag_aggressive_function_elimination
543 && !(*e
)->value
.function
.esym
->attr
.pure
544 && !(*e
)->value
.function
.esym
->attr
.implicit_pure
)
548 if ((*e
)->value
.function
.isym
)
550 /* Conversions are handled on the fly by the middle end,
551 transpose during trans-* stages and TRANSFER by the middle end. */
552 if ((*e
)->value
.function
.isym
->id
== GFC_ISYM_CONVERSION
553 || (*e
)->value
.function
.isym
->id
== GFC_ISYM_TRANSFER
554 || gfc_inline_intrinsic_function_p (*e
))
557 /* Don't create an array temporary for elemental functions,
558 as this would be wasteful of memory.
559 FIXME: Create a scalar temporary during scalarization. */
560 if ((*e
)->value
.function
.isym
->elemental
&& (*e
)->rank
> 0)
563 if (!(*e
)->value
.function
.isym
->pure
)
567 expr_array
.safe_push (e
);
571 /* Auxiliary function to check if an expression is a temporary created by
575 is_fe_temp (gfc_expr
*e
)
577 if (e
->expr_type
!= EXPR_VARIABLE
)
580 return e
->symtree
->n
.sym
->attr
.fe_temp
;
583 /* Determine the length of a string, if it can be evaluated as a constant
584 expression. Return a newly allocated gfc_expr or NULL on failure.
585 If the user specified a substring which is potentially longer than
586 the string itself, the string will be padded with spaces, which
590 constant_string_length (gfc_expr
*e
)
600 length
= e
->ts
.u
.cl
->length
;
601 if (length
&& length
->expr_type
== EXPR_CONSTANT
)
602 return gfc_copy_expr(length
);
605 /* Return length of substring, if constant. */
606 for (ref
= e
->ref
; ref
; ref
= ref
->next
)
608 if (ref
->type
== REF_SUBSTRING
609 && gfc_dep_difference (ref
->u
.ss
.end
, ref
->u
.ss
.start
, &value
))
611 res
= gfc_get_constant_expr (BT_INTEGER
, gfc_charlen_int_kind
,
614 mpz_add_ui (res
->value
.integer
, value
, 1);
620 /* Return length of char symbol, if constant. */
622 if (e
->symtree
->n
.sym
->ts
.u
.cl
&& e
->symtree
->n
.sym
->ts
.u
.cl
->length
623 && e
->symtree
->n
.sym
->ts
.u
.cl
->length
->expr_type
== EXPR_CONSTANT
)
624 return gfc_copy_expr (e
->symtree
->n
.sym
->ts
.u
.cl
->length
);
630 /* Insert a block at the current position unless it has already
631 been inserted; in this case use the one already there. */
633 static gfc_namespace
*
638 /* If the block hasn't already been created, do so. */
639 if (inserted_block
== NULL
)
641 inserted_block
= XCNEW (gfc_code
);
642 inserted_block
->op
= EXEC_BLOCK
;
643 inserted_block
->loc
= (*current_code
)->loc
;
644 ns
= gfc_build_block_ns (current_ns
);
645 inserted_block
->ext
.block
.ns
= ns
;
646 inserted_block
->ext
.block
.assoc
= NULL
;
648 ns
->code
= *current_code
;
650 /* If the statement has a label, make sure it is transferred to
651 the newly created block. */
653 if ((*current_code
)->here
)
655 inserted_block
->here
= (*current_code
)->here
;
656 (*current_code
)->here
= NULL
;
659 inserted_block
->next
= (*current_code
)->next
;
660 changed_statement
= &(inserted_block
->ext
.block
.ns
->code
);
661 (*current_code
)->next
= NULL
;
662 /* Insert the BLOCK at the right position. */
663 *current_code
= inserted_block
;
664 ns
->parent
= current_ns
;
667 ns
= inserted_block
->ext
.block
.ns
;
672 /* Returns a new expression (a variable) to be used in place of the old one,
673 with an optional assignment statement before the current statement to set
674 the value of the variable. Creates a new BLOCK for the statement if that
675 hasn't already been done and puts the statement, plus the newly created
676 variables, in that block. Special cases: If the expression is constant or
677 a temporary which has already been created, just copy it. */
680 create_var (gfc_expr
* e
, const char *vname
)
682 char name
[GFC_MAX_SYMBOL_LEN
+1];
683 gfc_symtree
*symtree
;
691 if (e
->expr_type
== EXPR_CONSTANT
|| is_fe_temp (e
))
692 return gfc_copy_expr (e
);
694 ns
= insert_block ();
697 snprintf (name
, GFC_MAX_SYMBOL_LEN
, "__var_%d_%s", var_num
++, vname
);
699 snprintf (name
, GFC_MAX_SYMBOL_LEN
, "__var_%d", var_num
++);
701 if (gfc_get_sym_tree (name
, ns
, &symtree
, false) != 0)
704 symbol
= symtree
->n
.sym
;
709 symbol
->as
= gfc_get_array_spec ();
710 symbol
->as
->rank
= e
->rank
;
712 if (e
->shape
== NULL
)
714 /* We don't know the shape at compile time, so we use an
716 symbol
->as
->type
= AS_DEFERRED
;
717 symbol
->attr
.allocatable
= 1;
721 symbol
->as
->type
= AS_EXPLICIT
;
722 /* Copy the shape. */
723 for (i
=0; i
<e
->rank
; i
++)
727 p
= gfc_get_constant_expr (BT_INTEGER
, gfc_default_integer_kind
,
729 mpz_set_si (p
->value
.integer
, 1);
730 symbol
->as
->lower
[i
] = p
;
732 q
= gfc_get_constant_expr (BT_INTEGER
, gfc_index_integer_kind
,
734 mpz_set (q
->value
.integer
, e
->shape
[i
]);
735 symbol
->as
->upper
[i
] = q
;
741 if (e
->ts
.type
== BT_CHARACTER
&& e
->rank
== 0)
745 symbol
->ts
.u
.cl
= gfc_new_charlen (ns
, NULL
);
746 length
= constant_string_length (e
);
748 symbol
->ts
.u
.cl
->length
= length
;
751 symbol
->attr
.allocatable
= 1;
756 symbol
->attr
.flavor
= FL_VARIABLE
;
757 symbol
->attr
.referenced
= 1;
758 symbol
->attr
.dimension
= e
->rank
> 0;
759 symbol
->attr
.fe_temp
= 1;
760 gfc_commit_symbol (symbol
);
762 result
= gfc_get_expr ();
763 result
->expr_type
= EXPR_VARIABLE
;
765 result
->ts
.deferred
= deferred
;
766 result
->rank
= e
->rank
;
767 result
->shape
= gfc_copy_shape (e
->shape
, e
->rank
);
768 result
->symtree
= symtree
;
769 result
->where
= e
->where
;
772 result
->ref
= gfc_get_ref ();
773 result
->ref
->type
= REF_ARRAY
;
774 result
->ref
->u
.ar
.type
= AR_FULL
;
775 result
->ref
->u
.ar
.where
= e
->where
;
776 result
->ref
->u
.ar
.dimen
= e
->rank
;
777 result
->ref
->u
.ar
.as
= symbol
->ts
.type
== BT_CLASS
778 ? CLASS_DATA (symbol
)->as
: symbol
->as
;
779 if (warn_array_temporaries
)
780 gfc_warning (OPT_Warray_temporaries
,
781 "Creating array temporary at %L", &(e
->where
));
784 /* Generate the new assignment. */
785 n
= XCNEW (gfc_code
);
787 n
->loc
= (*current_code
)->loc
;
788 n
->next
= *changed_statement
;
789 n
->expr1
= gfc_copy_expr (result
);
791 *changed_statement
= n
;
797 /* Warn about function elimination. */
800 do_warn_function_elimination (gfc_expr
*e
)
802 if (e
->expr_type
!= EXPR_FUNCTION
)
804 if (e
->value
.function
.esym
)
805 gfc_warning (OPT_Wfunction_elimination
,
806 "Removing call to function %qs at %L",
807 e
->value
.function
.esym
->name
, &(e
->where
));
808 else if (e
->value
.function
.isym
)
809 gfc_warning (OPT_Wfunction_elimination
,
810 "Removing call to function %qs at %L",
811 e
->value
.function
.isym
->name
, &(e
->where
));
813 /* Callback function for the code walker for doing common function
814 elimination. This builds up the list of functions in the expression
815 and goes through them to detect duplicates, which it then replaces
819 cfe_expr_0 (gfc_expr
**e
, int *walk_subtrees
,
820 void *data ATTRIBUTE_UNUSED
)
826 /* Don't do this optimization within OMP workshare or ASSOC lists. */
828 if (in_omp_workshare
|| in_assoc_list
)
834 expr_array
.release ();
836 gfc_expr_walker (e
, cfe_register_funcs
, NULL
);
838 /* Walk through all the functions. */
840 FOR_EACH_VEC_ELT_FROM (expr_array
, i
, ei
, 1)
842 /* Skip if the function has been replaced by a variable already. */
843 if ((*ei
)->expr_type
== EXPR_VARIABLE
)
850 if (gfc_dep_compare_functions (*ei
, *ej
, true) == 0)
853 newvar
= create_var (*ei
, "fcn");
855 if (warn_function_elimination
)
856 do_warn_function_elimination (*ej
);
859 *ej
= gfc_copy_expr (newvar
);
866 /* We did all the necessary walking in this function. */
871 /* Callback function for common function elimination, called from
872 gfc_code_walker. This keeps track of the current code, in order
873 to insert statements as needed. */
876 cfe_code (gfc_code
**c
, int *walk_subtrees
, void *data ATTRIBUTE_UNUSED
)
879 inserted_block
= NULL
;
880 changed_statement
= NULL
;
882 /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
883 and allocation on assigment are prohibited inside WHERE, and finally
884 masking an expression would lead to wrong-code when replacing
887 b = sum(foo(a) + foo(a))
898 if ((*c
)->op
== EXEC_WHERE
)
908 /* Dummy function for expression call back, for use when we
909 really don't want to do any walking. */
912 dummy_expr_callback (gfc_expr
**e ATTRIBUTE_UNUSED
, int *walk_subtrees
,
913 void *data ATTRIBUTE_UNUSED
)
919 /* Dummy function for code callback, for use when we really
920 don't want to do anything. */
922 gfc_dummy_code_callback (gfc_code
**e ATTRIBUTE_UNUSED
,
923 int *walk_subtrees ATTRIBUTE_UNUSED
,
924 void *data ATTRIBUTE_UNUSED
)
929 /* Code callback function for converting
936 This is because common function elimination would otherwise place the
937 temporary variables outside the loop. */
940 convert_do_while (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
941 void *data ATTRIBUTE_UNUSED
)
944 gfc_code
*c_if1
, *c_if2
, *c_exit
;
946 gfc_expr
*e_not
, *e_cond
;
948 if (co
->op
!= EXEC_DO_WHILE
)
951 if (co
->expr1
== NULL
|| co
->expr1
->expr_type
== EXPR_CONSTANT
)
956 /* Generate the condition of the if statement, which is .not. the original
958 e_not
= gfc_get_expr ();
959 e_not
->ts
= e_cond
->ts
;
960 e_not
->where
= e_cond
->where
;
961 e_not
->expr_type
= EXPR_OP
;
962 e_not
->value
.op
.op
= INTRINSIC_NOT
;
963 e_not
->value
.op
.op1
= e_cond
;
965 /* Generate the EXIT statement. */
966 c_exit
= XCNEW (gfc_code
);
967 c_exit
->op
= EXEC_EXIT
;
968 c_exit
->ext
.which_construct
= co
;
969 c_exit
->loc
= co
->loc
;
971 /* Generate the IF statement. */
972 c_if2
= XCNEW (gfc_code
);
974 c_if2
->expr1
= e_not
;
975 c_if2
->next
= c_exit
;
976 c_if2
->loc
= co
->loc
;
978 /* ... plus the one to chain it to. */
979 c_if1
= XCNEW (gfc_code
);
981 c_if1
->block
= c_if2
;
982 c_if1
->loc
= co
->loc
;
984 /* Make the DO WHILE loop into a DO block by replacing the condition
985 with a true constant. */
986 co
->expr1
= gfc_get_logical_expr (gfc_default_integer_kind
, &co
->loc
, true);
988 /* Hang the generated if statement into the loop body. */
990 loopblock
= co
->block
->next
;
991 co
->block
->next
= c_if1
;
992 c_if1
->next
= loopblock
;
997 /* Code callback function for converting
1010 because otherwise common function elimination would place the BLOCKs
1011 into the wrong place. */
1014 convert_elseif (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
1015 void *data ATTRIBUTE_UNUSED
)
1018 gfc_code
*c_if1
, *c_if2
, *else_stmt
;
1020 if (co
->op
!= EXEC_IF
)
1023 /* This loop starts out with the first ELSE statement. */
1024 else_stmt
= co
->block
->block
;
1026 while (else_stmt
!= NULL
)
1028 gfc_code
*next_else
;
1030 /* If there is no condition, we're done. */
1031 if (else_stmt
->expr1
== NULL
)
1034 next_else
= else_stmt
->block
;
1036 /* Generate the new IF statement. */
1037 c_if2
= XCNEW (gfc_code
);
1038 c_if2
->op
= EXEC_IF
;
1039 c_if2
->expr1
= else_stmt
->expr1
;
1040 c_if2
->next
= else_stmt
->next
;
1041 c_if2
->loc
= else_stmt
->loc
;
1042 c_if2
->block
= next_else
;
1044 /* ... plus the one to chain it to. */
1045 c_if1
= XCNEW (gfc_code
);
1046 c_if1
->op
= EXEC_IF
;
1047 c_if1
->block
= c_if2
;
1048 c_if1
->loc
= else_stmt
->loc
;
1050 /* Insert the new IF after the ELSE. */
1051 else_stmt
->expr1
= NULL
;
1052 else_stmt
->next
= c_if1
;
1053 else_stmt
->block
= NULL
;
1055 else_stmt
= next_else
;
1057 /* Don't walk subtrees. */
1061 /* Optimize a namespace, including all contained namespaces. */
1064 optimize_namespace (gfc_namespace
*ns
)
1066 gfc_namespace
*saved_ns
= gfc_current_ns
;
1068 gfc_current_ns
= ns
;
1071 in_assoc_list
= false;
1072 in_omp_workshare
= false;
1074 gfc_code_walker (&ns
->code
, convert_do_while
, dummy_expr_callback
, NULL
);
1075 gfc_code_walker (&ns
->code
, convert_elseif
, dummy_expr_callback
, NULL
);
1076 gfc_code_walker (&ns
->code
, cfe_code
, cfe_expr_0
, NULL
);
1077 gfc_code_walker (&ns
->code
, optimize_code
, optimize_expr
, NULL
);
1078 if (flag_inline_matmul_limit
!= 0)
1079 gfc_code_walker (&ns
->code
, inline_matmul_assign
, dummy_expr_callback
,
1082 /* BLOCKs are handled in the expression walker below. */
1083 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
1085 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
1086 optimize_namespace (ns
);
1088 gfc_current_ns
= saved_ns
;
1091 /* Handle dependencies for allocatable strings which potentially redefine
1092 themselves in an assignment. */
1095 realloc_strings (gfc_namespace
*ns
)
1098 gfc_code_walker (&ns
->code
, realloc_string_callback
, dummy_expr_callback
, NULL
);
1100 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
1102 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
1103 realloc_strings (ns
);
1109 optimize_reduction (gfc_namespace
*ns
)
1112 gfc_code_walker (&ns
->code
, gfc_dummy_code_callback
,
1113 callback_reduction
, NULL
);
1115 /* BLOCKs are handled in the expression walker below. */
1116 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
1118 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
1119 optimize_reduction (ns
);
1123 /* Replace code like
1126 a = matmul(b,c) ; a = a + d
1127 where the array function is not elemental and not allocatable
1128 and does not depend on the left-hand side.
1132 optimize_binop_array_assignment (gfc_code
*c
, gfc_expr
**rhs
, bool seen_op
)
1140 if (e
->expr_type
== EXPR_OP
)
1142 switch (e
->value
.op
.op
)
1144 /* Unary operators and exponentiation: Only look at a single
1147 case INTRINSIC_UPLUS
:
1148 case INTRINSIC_UMINUS
:
1149 case INTRINSIC_PARENTHESES
:
1150 case INTRINSIC_POWER
:
1151 if (optimize_binop_array_assignment (c
, &e
->value
.op
.op1
, seen_op
))
1155 case INTRINSIC_CONCAT
:
1156 /* Do not do string concatenations. */
1160 /* Binary operators. */
1161 if (optimize_binop_array_assignment (c
, &e
->value
.op
.op1
, true))
1164 if (optimize_binop_array_assignment (c
, &e
->value
.op
.op2
, true))
1170 else if (seen_op
&& e
->expr_type
== EXPR_FUNCTION
&& e
->rank
> 0
1171 && ! (e
->value
.function
.esym
1172 && (e
->value
.function
.esym
->attr
.elemental
1173 || e
->value
.function
.esym
->attr
.allocatable
1174 || e
->value
.function
.esym
->ts
.type
!= c
->expr1
->ts
.type
1175 || e
->value
.function
.esym
->ts
.kind
!= c
->expr1
->ts
.kind
))
1176 && ! (e
->value
.function
.isym
1177 && (e
->value
.function
.isym
->elemental
1178 || e
->ts
.type
!= c
->expr1
->ts
.type
1179 || e
->ts
.kind
!= c
->expr1
->ts
.kind
))
1180 && ! gfc_inline_intrinsic_function_p (e
))
1186 /* Insert a new assignment statement after the current one. */
1187 n
= XCNEW (gfc_code
);
1188 n
->op
= EXEC_ASSIGN
;
1193 n
->expr1
= gfc_copy_expr (c
->expr1
);
1194 n
->expr2
= c
->expr2
;
1195 new_expr
= gfc_copy_expr (c
->expr1
);
1203 /* Nothing to optimize. */
1207 /* Remove unneeded TRIMs at the end of expressions. */
1210 remove_trim (gfc_expr
*rhs
)
1218 /* Check for a // b // trim(c). Looping is probably not
1219 necessary because the parser usually generates
1220 (// (// a b ) trim(c) ) , but better safe than sorry. */
1222 while (rhs
->expr_type
== EXPR_OP
1223 && rhs
->value
.op
.op
== INTRINSIC_CONCAT
)
1224 rhs
= rhs
->value
.op
.op2
;
1226 while (rhs
->expr_type
== EXPR_FUNCTION
&& rhs
->value
.function
.isym
1227 && rhs
->value
.function
.isym
->id
== GFC_ISYM_TRIM
)
1229 strip_function_call (rhs
);
1230 /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1238 /* Optimizations for an assignment. */
1241 optimize_assignment (gfc_code
* c
)
1243 gfc_expr
*lhs
, *rhs
;
1248 if (lhs
->ts
.type
== BT_CHARACTER
&& !lhs
->ts
.deferred
)
1250 /* Optimize a = trim(b) to a = b. */
1253 /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1254 if (is_empty_string (rhs
))
1255 rhs
->value
.character
.length
= 0;
1258 if (lhs
->rank
> 0 && gfc_check_dependency (lhs
, rhs
, true) == 0)
1259 optimize_binop_array_assignment (c
, &rhs
, false);
1263 /* Remove an unneeded function call, modifying the expression.
1264 This replaces the function call with the value of its
1265 first argument. The rest of the argument list is freed. */
1268 strip_function_call (gfc_expr
*e
)
1271 gfc_actual_arglist
*a
;
1273 a
= e
->value
.function
.actual
;
1275 /* We should have at least one argument. */
1276 gcc_assert (a
->expr
!= NULL
);
1280 /* Free the remaining arglist, if any. */
1282 gfc_free_actual_arglist (a
->next
);
1284 /* Graft the argument expression onto the original function. */
1290 /* Optimization of lexical comparison functions. */
1293 optimize_lexical_comparison (gfc_expr
*e
)
1295 if (e
->expr_type
!= EXPR_FUNCTION
|| e
->value
.function
.isym
== NULL
)
1298 switch (e
->value
.function
.isym
->id
)
1301 return optimize_comparison (e
, INTRINSIC_LE
);
1304 return optimize_comparison (e
, INTRINSIC_GE
);
1307 return optimize_comparison (e
, INTRINSIC_GT
);
1310 return optimize_comparison (e
, INTRINSIC_LT
);
1318 /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1319 do CHARACTER because of possible pessimization involving character
1323 combine_array_constructor (gfc_expr
*e
)
1326 gfc_expr
*op1
, *op2
;
1329 gfc_constructor
*c
, *new_c
;
1330 gfc_constructor_base oldbase
, newbase
;
1333 /* Array constructors have rank one. */
1337 /* Don't try to combine association lists, this makes no sense
1338 and leads to an ICE. */
1342 /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1343 if (forall_level
> 0)
1346 /* Inside an iterator, things can get hairy; we are likely to create
1347 an invalid temporary variable. */
1348 if (iterator_level
> 0)
1351 op1
= e
->value
.op
.op1
;
1352 op2
= e
->value
.op
.op2
;
1357 if (op1
->expr_type
== EXPR_ARRAY
&& op2
->rank
== 0)
1358 scalar_first
= false;
1359 else if (op2
->expr_type
== EXPR_ARRAY
&& op1
->rank
== 0)
1361 scalar_first
= true;
1362 op1
= e
->value
.op
.op2
;
1363 op2
= e
->value
.op
.op1
;
1368 if (op2
->ts
.type
== BT_CHARACTER
)
1371 scalar
= create_var (gfc_copy_expr (op2
), "constr");
1373 oldbase
= op1
->value
.constructor
;
1375 e
->expr_type
= EXPR_ARRAY
;
1377 for (c
= gfc_constructor_first (oldbase
); c
;
1378 c
= gfc_constructor_next (c
))
1380 new_expr
= gfc_get_expr ();
1381 new_expr
->ts
= e
->ts
;
1382 new_expr
->expr_type
= EXPR_OP
;
1383 new_expr
->rank
= c
->expr
->rank
;
1384 new_expr
->where
= c
->where
;
1385 new_expr
->value
.op
.op
= e
->value
.op
.op
;
1389 new_expr
->value
.op
.op1
= gfc_copy_expr (scalar
);
1390 new_expr
->value
.op
.op2
= gfc_copy_expr (c
->expr
);
1394 new_expr
->value
.op
.op1
= gfc_copy_expr (c
->expr
);
1395 new_expr
->value
.op
.op2
= gfc_copy_expr (scalar
);
1398 new_c
= gfc_constructor_append_expr (&newbase
, new_expr
, &(e
->where
));
1399 new_c
->iterator
= c
->iterator
;
1403 gfc_free_expr (op1
);
1404 gfc_free_expr (op2
);
1405 gfc_free_expr (scalar
);
1407 e
->value
.constructor
= newbase
;
1411 /* Change (-1)**k into 1-ishift(iand(k,1),1) and
1412 2**k into ishift(1,k) */
1415 optimize_power (gfc_expr
*e
)
1417 gfc_expr
*op1
, *op2
;
1418 gfc_expr
*iand
, *ishft
;
1420 if (e
->ts
.type
!= BT_INTEGER
)
1423 op1
= e
->value
.op
.op1
;
1425 if (op1
== NULL
|| op1
->expr_type
!= EXPR_CONSTANT
)
1428 if (mpz_cmp_si (op1
->value
.integer
, -1L) == 0)
1430 gfc_free_expr (op1
);
1432 op2
= e
->value
.op
.op2
;
1437 iand
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_IAND
,
1438 "_internal_iand", e
->where
, 2, op2
,
1439 gfc_get_int_expr (e
->ts
.kind
,
1442 ishft
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_ISHFT
,
1443 "_internal_ishft", e
->where
, 2, iand
,
1444 gfc_get_int_expr (e
->ts
.kind
,
1447 e
->value
.op
.op
= INTRINSIC_MINUS
;
1448 e
->value
.op
.op1
= gfc_get_int_expr (e
->ts
.kind
, &e
->where
, 1);
1449 e
->value
.op
.op2
= ishft
;
1452 else if (mpz_cmp_si (op1
->value
.integer
, 2L) == 0)
1454 gfc_free_expr (op1
);
1456 op2
= e
->value
.op
.op2
;
1460 ishft
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_ISHFT
,
1461 "_internal_ishft", e
->where
, 2,
1462 gfc_get_int_expr (e
->ts
.kind
,
1469 else if (mpz_cmp_si (op1
->value
.integer
, 1L) == 0)
1471 op2
= e
->value
.op
.op2
;
1475 gfc_free_expr (op1
);
1476 gfc_free_expr (op2
);
1478 e
->expr_type
= EXPR_CONSTANT
;
1479 e
->value
.op
.op1
= NULL
;
1480 e
->value
.op
.op2
= NULL
;
1481 mpz_init_set_si (e
->value
.integer
, 1);
1482 /* Typespec and location are still OK. */
1489 /* Recursive optimization of operators. */
1492 optimize_op (gfc_expr
*e
)
1496 gfc_intrinsic_op op
= e
->value
.op
.op
;
1500 /* Only use new-style comparisons. */
1503 case INTRINSIC_EQ_OS
:
1507 case INTRINSIC_GE_OS
:
1511 case INTRINSIC_LE_OS
:
1515 case INTRINSIC_NE_OS
:
1519 case INTRINSIC_GT_OS
:
1523 case INTRINSIC_LT_OS
:
1539 changed
= optimize_comparison (e
, op
);
1542 /* Look at array constructors. */
1543 case INTRINSIC_PLUS
:
1544 case INTRINSIC_MINUS
:
1545 case INTRINSIC_TIMES
:
1546 case INTRINSIC_DIVIDE
:
1547 return combine_array_constructor (e
) || changed
;
1549 case INTRINSIC_POWER
:
1550 return optimize_power (e
);
1560 /* Return true if a constant string contains only blanks. */
1563 is_empty_string (gfc_expr
*e
)
1567 if (e
->ts
.type
!= BT_CHARACTER
|| e
->expr_type
!= EXPR_CONSTANT
)
1570 for (i
=0; i
< e
->value
.character
.length
; i
++)
1572 if (e
->value
.character
.string
[i
] != ' ')
1580 /* Insert a call to the intrinsic len_trim. Use a different name for
1581 the symbol tree so we don't run into trouble when the user has
1582 renamed len_trim for some reason. */
1585 get_len_trim_call (gfc_expr
*str
, int kind
)
1588 gfc_actual_arglist
*actual_arglist
, *next
;
1590 fcn
= gfc_get_expr ();
1591 fcn
->expr_type
= EXPR_FUNCTION
;
1592 fcn
->value
.function
.isym
= gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM
);
1593 actual_arglist
= gfc_get_actual_arglist ();
1594 actual_arglist
->expr
= str
;
1595 next
= gfc_get_actual_arglist ();
1596 next
->expr
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
, kind
);
1597 actual_arglist
->next
= next
;
1599 fcn
->value
.function
.actual
= actual_arglist
;
1600 fcn
->where
= str
->where
;
1601 fcn
->ts
.type
= BT_INTEGER
;
1602 fcn
->ts
.kind
= gfc_charlen_int_kind
;
1604 gfc_get_sym_tree ("__internal_len_trim", current_ns
, &fcn
->symtree
, false);
1605 fcn
->symtree
->n
.sym
->ts
= fcn
->ts
;
1606 fcn
->symtree
->n
.sym
->attr
.flavor
= FL_PROCEDURE
;
1607 fcn
->symtree
->n
.sym
->attr
.function
= 1;
1608 fcn
->symtree
->n
.sym
->attr
.elemental
= 1;
1609 fcn
->symtree
->n
.sym
->attr
.referenced
= 1;
1610 fcn
->symtree
->n
.sym
->attr
.access
= ACCESS_PRIVATE
;
1611 gfc_commit_symbol (fcn
->symtree
->n
.sym
);
1616 /* Optimize expressions for equality. */
1619 optimize_comparison (gfc_expr
*e
, gfc_intrinsic_op op
)
1621 gfc_expr
*op1
, *op2
;
1625 gfc_actual_arglist
*firstarg
, *secondarg
;
1627 if (e
->expr_type
== EXPR_OP
)
1631 op1
= e
->value
.op
.op1
;
1632 op2
= e
->value
.op
.op2
;
1634 else if (e
->expr_type
== EXPR_FUNCTION
)
1636 /* One of the lexical comparison functions. */
1637 firstarg
= e
->value
.function
.actual
;
1638 secondarg
= firstarg
->next
;
1639 op1
= firstarg
->expr
;
1640 op2
= secondarg
->expr
;
1645 /* Strip off unneeded TRIM calls from string comparisons. */
1647 change
= remove_trim (op1
);
1649 if (remove_trim (op2
))
1652 /* An expression of type EXPR_CONSTANT is only valid for scalars. */
1653 /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
1654 handles them well). However, there are also cases that need a non-scalar
1655 argument. For example the any intrinsic. See PR 45380. */
1659 /* Replace a == '' with len_trim(a) == 0 and a /= '' with
1661 if (op1
->ts
.type
== BT_CHARACTER
&& op2
->ts
.type
== BT_CHARACTER
1662 && (op
== INTRINSIC_EQ
|| op
== INTRINSIC_NE
))
1664 bool empty_op1
, empty_op2
;
1665 empty_op1
= is_empty_string (op1
);
1666 empty_op2
= is_empty_string (op2
);
1668 if (empty_op1
|| empty_op2
)
1674 /* This can only happen when an error for comparing
1675 characters of different kinds has already been issued. */
1676 if (empty_op1
&& empty_op2
)
1679 zero
= gfc_get_int_expr (gfc_charlen_int_kind
, &e
->where
, 0);
1680 str
= empty_op1
? op2
: op1
;
1682 fcn
= get_len_trim_call (str
, gfc_charlen_int_kind
);
1686 gfc_free_expr (op1
);
1688 gfc_free_expr (op2
);
1692 e
->value
.op
.op1
= fcn
;
1693 e
->value
.op
.op2
= zero
;
1698 /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
1700 if (flag_finite_math_only
1701 || (op1
->ts
.type
!= BT_REAL
&& op2
->ts
.type
!= BT_REAL
1702 && op1
->ts
.type
!= BT_COMPLEX
&& op2
->ts
.type
!= BT_COMPLEX
))
1704 eq
= gfc_dep_compare_expr (op1
, op2
);
1707 /* Replace A // B < A // C with B < C, and A // B < C // B
1709 if (op1
->ts
.type
== BT_CHARACTER
&& op2
->ts
.type
== BT_CHARACTER
1710 && op1
->expr_type
== EXPR_OP
1711 && op1
->value
.op
.op
== INTRINSIC_CONCAT
1712 && op2
->expr_type
== EXPR_OP
1713 && op2
->value
.op
.op
== INTRINSIC_CONCAT
)
1715 gfc_expr
*op1_left
= op1
->value
.op
.op1
;
1716 gfc_expr
*op2_left
= op2
->value
.op
.op1
;
1717 gfc_expr
*op1_right
= op1
->value
.op
.op2
;
1718 gfc_expr
*op2_right
= op2
->value
.op
.op2
;
1720 if (gfc_dep_compare_expr (op1_left
, op2_left
) == 0)
1722 /* Watch out for 'A ' // x vs. 'A' // x. */
1724 if (op1_left
->expr_type
== EXPR_CONSTANT
1725 && op2_left
->expr_type
== EXPR_CONSTANT
1726 && op1_left
->value
.character
.length
1727 != op2_left
->value
.character
.length
)
1735 firstarg
->expr
= op1_right
;
1736 secondarg
->expr
= op2_right
;
1740 e
->value
.op
.op1
= op1_right
;
1741 e
->value
.op
.op2
= op2_right
;
1743 optimize_comparison (e
, op
);
1747 if (gfc_dep_compare_expr (op1_right
, op2_right
) == 0)
1753 firstarg
->expr
= op1_left
;
1754 secondarg
->expr
= op2_left
;
1758 e
->value
.op
.op1
= op1_left
;
1759 e
->value
.op
.op2
= op2_left
;
1762 optimize_comparison (e
, op
);
1769 /* eq can only be -1, 0 or 1 at this point. */
1797 gfc_internal_error ("illegal OP in optimize_comparison");
1801 /* Replace the expression by a constant expression. The typespec
1802 and where remains the way it is. */
1805 e
->expr_type
= EXPR_CONSTANT
;
1806 e
->value
.logical
= result
;
1814 /* Optimize a trim function by replacing it with an equivalent substring
1815 involving a call to len_trim. This only works for expressions where
1816 variables are trimmed. Return true if anything was modified. */
1819 optimize_trim (gfc_expr
*e
)
1824 gfc_ref
**rr
= NULL
;
1826 /* Don't do this optimization within an argument list, because
1827 otherwise aliasing issues may occur. */
1829 if (count_arglist
!= 1)
1832 if (e
->ts
.type
!= BT_CHARACTER
|| e
->expr_type
!= EXPR_FUNCTION
1833 || e
->value
.function
.isym
== NULL
1834 || e
->value
.function
.isym
->id
!= GFC_ISYM_TRIM
)
1837 a
= e
->value
.function
.actual
->expr
;
1839 if (a
->expr_type
!= EXPR_VARIABLE
)
1842 /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
1844 if (a
->symtree
->n
.sym
->attr
.allocatable
)
1847 /* Follow all references to find the correct place to put the newly
1848 created reference. FIXME: Also handle substring references and
1849 array references. Array references cause strange regressions at
1854 for (rr
= &(a
->ref
); *rr
; rr
= &((*rr
)->next
))
1856 if ((*rr
)->type
== REF_SUBSTRING
|| (*rr
)->type
== REF_ARRAY
)
1861 strip_function_call (e
);
1866 /* Create the reference. */
1868 ref
= gfc_get_ref ();
1869 ref
->type
= REF_SUBSTRING
;
1871 /* Set the start of the reference. */
1873 ref
->u
.ss
.start
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
, 1);
1875 /* Build the function call to len_trim(x, gfc_default_integer_kind). */
1877 fcn
= get_len_trim_call (gfc_copy_expr (e
), gfc_default_integer_kind
);
1879 /* Set the end of the reference to the call to len_trim. */
1881 ref
->u
.ss
.end
= fcn
;
1882 gcc_assert (rr
!= NULL
&& *rr
== NULL
);
1887 /* Optimize minloc(b), where b is rank 1 array, into
1888 (/ minloc(b, dim=1) /), and similarly for maxloc,
1889 as the latter forms are expanded inline. */
1892 optimize_minmaxloc (gfc_expr
**e
)
1895 gfc_actual_arglist
*a
;
1899 || fn
->value
.function
.actual
== NULL
1900 || fn
->value
.function
.actual
->expr
== NULL
1901 || fn
->value
.function
.actual
->expr
->rank
!= 1)
1904 *e
= gfc_get_array_expr (fn
->ts
.type
, fn
->ts
.kind
, &fn
->where
);
1905 (*e
)->shape
= fn
->shape
;
1908 gfc_constructor_append_expr (&(*e
)->value
.constructor
, fn
, &fn
->where
);
1910 name
= XALLOCAVEC (char, strlen (fn
->value
.function
.name
) + 1);
1911 strcpy (name
, fn
->value
.function
.name
);
1912 p
= strstr (name
, "loc0");
1914 fn
->value
.function
.name
= gfc_get_string ("%s", name
);
1915 if (fn
->value
.function
.actual
->next
)
1917 a
= fn
->value
.function
.actual
->next
;
1918 gcc_assert (a
->expr
== NULL
);
1922 a
= gfc_get_actual_arglist ();
1923 fn
->value
.function
.actual
->next
= a
;
1925 a
->expr
= gfc_get_constant_expr (BT_INTEGER
, gfc_default_integer_kind
,
1927 mpz_set_ui (a
->expr
->value
.integer
, 1);
1930 /* Callback function for code checking that we do not pass a DO variable to an
1931 INTENT(OUT) or INTENT(INOUT) dummy variable. */
1934 doloop_code (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
1935 void *data ATTRIBUTE_UNUSED
)
1939 gfc_formal_arglist
*f
;
1940 gfc_actual_arglist
*a
;
1945 /* If the doloop_list grew, we have to truncate it here. */
1947 if ((unsigned) doloop_level
< doloop_list
.length())
1948 doloop_list
.truncate (doloop_level
);
1954 if (co
->ext
.iterator
&& co
->ext
.iterator
->var
)
1955 doloop_list
.safe_push (co
);
1957 doloop_list
.safe_push ((gfc_code
*) NULL
);
1962 if (co
->resolved_sym
== NULL
)
1965 f
= gfc_sym_get_dummy_args (co
->resolved_sym
);
1967 /* Withot a formal arglist, there is only unknown INTENT,
1968 which we don't check for. */
1976 FOR_EACH_VEC_ELT (doloop_list
, i
, cl
)
1983 do_sym
= cl
->ext
.iterator
->var
->symtree
->n
.sym
;
1985 if (a
->expr
&& a
->expr
->symtree
1986 && a
->expr
->symtree
->n
.sym
== do_sym
)
1988 if (f
->sym
->attr
.intent
== INTENT_OUT
)
1989 gfc_error_now ("Variable %qs at %L set to undefined "
1990 "value inside loop beginning at %L as "
1991 "INTENT(OUT) argument to subroutine %qs",
1992 do_sym
->name
, &a
->expr
->where
,
1993 &doloop_list
[i
]->loc
,
1994 co
->symtree
->n
.sym
->name
);
1995 else if (f
->sym
->attr
.intent
== INTENT_INOUT
)
1996 gfc_error_now ("Variable %qs at %L not definable inside "
1997 "loop beginning at %L as INTENT(INOUT) "
1998 "argument to subroutine %qs",
1999 do_sym
->name
, &a
->expr
->where
,
2000 &doloop_list
[i
]->loc
,
2001 co
->symtree
->n
.sym
->name
);
2015 /* Callback function for functions checking that we do not pass a DO variable
2016 to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
2019 do_function (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2020 void *data ATTRIBUTE_UNUSED
)
2022 gfc_formal_arglist
*f
;
2023 gfc_actual_arglist
*a
;
2029 if (expr
->expr_type
!= EXPR_FUNCTION
)
2032 /* Intrinsic functions don't modify their arguments. */
2034 if (expr
->value
.function
.isym
)
2037 f
= gfc_sym_get_dummy_args (expr
->symtree
->n
.sym
);
2039 /* Without a formal arglist, there is only unknown INTENT,
2040 which we don't check for. */
2044 a
= expr
->value
.function
.actual
;
2048 FOR_EACH_VEC_ELT (doloop_list
, i
, dl
)
2055 do_sym
= dl
->ext
.iterator
->var
->symtree
->n
.sym
;
2057 if (a
->expr
&& a
->expr
->symtree
2058 && a
->expr
->symtree
->n
.sym
== do_sym
)
2060 if (f
->sym
->attr
.intent
== INTENT_OUT
)
2061 gfc_error_now ("Variable %qs at %L set to undefined value "
2062 "inside loop beginning at %L as INTENT(OUT) "
2063 "argument to function %qs", do_sym
->name
,
2064 &a
->expr
->where
, &doloop_list
[i
]->loc
,
2065 expr
->symtree
->n
.sym
->name
);
2066 else if (f
->sym
->attr
.intent
== INTENT_INOUT
)
2067 gfc_error_now ("Variable %qs at %L not definable inside loop"
2068 " beginning at %L as INTENT(INOUT) argument to"
2069 " function %qs", do_sym
->name
,
2070 &a
->expr
->where
, &doloop_list
[i
]->loc
,
2071 expr
->symtree
->n
.sym
->name
);
2082 doloop_warn (gfc_namespace
*ns
)
2084 gfc_code_walker (&ns
->code
, doloop_code
, do_function
, NULL
);
2087 /* This selction deals with inlining calls to MATMUL. */
2089 /* Auxiliary function to build and simplify an array inquiry function.
2090 dim is zero-based. */
2093 get_array_inq_function (gfc_isym_id id
, gfc_expr
*e
, int dim
)
2096 gfc_expr
*dim_arg
, *kind
;
2102 case GFC_ISYM_LBOUND
:
2103 name
= "_gfortran_lbound";
2106 case GFC_ISYM_UBOUND
:
2107 name
= "_gfortran_ubound";
2111 name
= "_gfortran_size";
2118 dim_arg
= gfc_get_int_expr (gfc_default_integer_kind
, &e
->where
, dim
);
2119 kind
= gfc_get_int_expr (gfc_default_integer_kind
, &e
->where
,
2120 gfc_index_integer_kind
);
2122 ec
= gfc_copy_expr (e
);
2123 fcn
= gfc_build_intrinsic_call (current_ns
, id
, name
, e
->where
, 3,
2125 gfc_simplify_expr (fcn
, 0);
2129 /* Builds a logical expression. */
2132 build_logical_expr (gfc_intrinsic_op op
, gfc_expr
*e1
, gfc_expr
*e2
)
2137 ts
.type
= BT_LOGICAL
;
2138 ts
.kind
= gfc_default_logical_kind
;
2139 res
= gfc_get_expr ();
2140 res
->where
= e1
->where
;
2141 res
->expr_type
= EXPR_OP
;
2142 res
->value
.op
.op
= op
;
2143 res
->value
.op
.op1
= e1
;
2144 res
->value
.op
.op2
= e2
;
2151 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
2152 compatible typespecs. */
2155 get_operand (gfc_intrinsic_op op
, gfc_expr
*e1
, gfc_expr
*e2
)
2159 res
= gfc_get_expr ();
2161 res
->where
= e1
->where
;
2162 res
->expr_type
= EXPR_OP
;
2163 res
->value
.op
.op
= op
;
2164 res
->value
.op
.op1
= e1
;
2165 res
->value
.op
.op2
= e2
;
2166 gfc_simplify_expr (res
, 0);
2170 /* Generate the IF statement for a runtime check if we want to do inlining or
2171 not - putting in the code for both branches and putting it into the syntax
2172 tree is the caller's responsibility. For fixed array sizes, this should be
2173 removed by DCE. Only called for rank-two matrices A and B. */
2176 inline_limit_check (gfc_expr
*a
, gfc_expr
*b
, enum matrix_case m_case
)
2178 gfc_expr
*inline_limit
;
2179 gfc_code
*if_1
, *if_2
, *else_2
;
2180 gfc_expr
*b2
, *a2
, *a1
, *m1
, *m2
;
2184 gcc_assert (m_case
== A2B2
|| m_case
== A2B2T
);
2186 /* Calculation is done in real to avoid integer overflow. */
2188 inline_limit
= gfc_get_constant_expr (BT_REAL
, gfc_default_real_kind
,
2190 mpfr_set_si (inline_limit
->value
.real
, flag_inline_matmul_limit
,
2192 mpfr_pow_ui (inline_limit
->value
.real
, inline_limit
->value
.real
, 3,
2195 a1
= get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2196 a2
= get_array_inq_function (GFC_ISYM_SIZE
, a
, 2);
2197 b2
= get_array_inq_function (GFC_ISYM_SIZE
, b
, 2);
2201 ts
.kind
= gfc_default_real_kind
;
2202 gfc_convert_type_warn (a1
, &ts
, 2, 0);
2203 gfc_convert_type_warn (a2
, &ts
, 2, 0);
2204 gfc_convert_type_warn (b2
, &ts
, 2, 0);
2206 m1
= get_operand (INTRINSIC_TIMES
, a1
, a2
);
2207 m2
= get_operand (INTRINSIC_TIMES
, m1
, b2
);
2209 cond
= build_logical_expr (INTRINSIC_LE
, m2
, inline_limit
);
2210 gfc_simplify_expr (cond
, 0);
2212 else_2
= XCNEW (gfc_code
);
2213 else_2
->op
= EXEC_IF
;
2214 else_2
->loc
= a
->where
;
2216 if_2
= XCNEW (gfc_code
);
2219 if_2
->loc
= a
->where
;
2220 if_2
->block
= else_2
;
2222 if_1
= XCNEW (gfc_code
);
2225 if_1
->loc
= a
->where
;
2231 /* Insert code to issue a runtime error if the expressions are not equal. */
2234 runtime_error_ne (gfc_expr
*e1
, gfc_expr
*e2
, const char *msg
)
2237 gfc_code
*if_1
, *if_2
;
2239 gfc_actual_arglist
*a1
, *a2
, *a3
;
2241 gcc_assert (e1
->where
.lb
);
2242 /* Build the call to runtime_error. */
2243 c
= XCNEW (gfc_code
);
2247 /* Get a null-terminated message string. */
2249 a1
= gfc_get_actual_arglist ();
2250 a1
->expr
= gfc_get_character_expr (gfc_default_character_kind
, &e1
->where
,
2251 msg
, strlen(msg
)+1);
2254 /* Pass the value of the first expression. */
2255 a2
= gfc_get_actual_arglist ();
2256 a2
->expr
= gfc_copy_expr (e1
);
2259 /* Pass the value of the second expression. */
2260 a3
= gfc_get_actual_arglist ();
2261 a3
->expr
= gfc_copy_expr (e2
);
2264 gfc_check_fe_runtime_error (c
->ext
.actual
);
2265 gfc_resolve_fe_runtime_error (c
);
2267 if_2
= XCNEW (gfc_code
);
2269 if_2
->loc
= e1
->where
;
2272 if_1
= XCNEW (gfc_code
);
2275 if_1
->loc
= e1
->where
;
2277 cond
= build_logical_expr (INTRINSIC_NE
, e1
, e2
);
2278 gfc_simplify_expr (cond
, 0);
2284 /* Handle matrix reallocation. Caller is responsible to insert into
2287 For the two-dimensional case, build
2289 if (allocated(c)) then
2290 if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
2292 allocate (c(size(a,1), size(b,2)))
2295 allocate (c(size(a,1),size(b,2)))
2298 and for the other cases correspondingly.
2302 matmul_lhs_realloc (gfc_expr
*c
, gfc_expr
*a
, gfc_expr
*b
,
2303 enum matrix_case m_case
)
2306 gfc_expr
*allocated
, *alloc_expr
;
2307 gfc_code
*if_alloc_1
, *if_alloc_2
, *if_size_1
, *if_size_2
;
2308 gfc_code
*else_alloc
;
2309 gfc_code
*deallocate
, *allocate1
, *allocate_else
;
2311 gfc_expr
*cond
, *ne1
, *ne2
;
2313 if (warn_realloc_lhs
)
2314 gfc_warning (OPT_Wrealloc_lhs
,
2315 "Code for reallocating the allocatable array at %L will "
2316 "be added", &c
->where
);
2318 alloc_expr
= gfc_copy_expr (c
);
2320 ar
= gfc_find_array_ref (alloc_expr
);
2321 gcc_assert (ar
&& ar
->type
== AR_FULL
);
2323 /* c comes in as a full ref. Change it into a copy and make it into an
2324 element ref so it has the right form for for ALLOCATE. In the same
2325 switch statement, also generate the size comparison for the secod IF
2328 ar
->type
= AR_ELEMENT
;
2333 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2334 ar
->start
[1] = get_array_inq_function (GFC_ISYM_SIZE
, b
, 2);
2335 ne1
= build_logical_expr (INTRINSIC_NE
,
2336 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2337 get_array_inq_function (GFC_ISYM_SIZE
, a
, 1));
2338 ne2
= build_logical_expr (INTRINSIC_NE
,
2339 get_array_inq_function (GFC_ISYM_SIZE
, c
, 2),
2340 get_array_inq_function (GFC_ISYM_SIZE
, b
, 2));
2341 cond
= build_logical_expr (INTRINSIC_OR
, ne1
, ne2
);
2345 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2346 ar
->start
[1] = get_array_inq_function (GFC_ISYM_SIZE
, b
, 1);
2348 ne1
= build_logical_expr (INTRINSIC_NE
,
2349 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2350 get_array_inq_function (GFC_ISYM_SIZE
, a
, 1));
2351 ne2
= build_logical_expr (INTRINSIC_NE
,
2352 get_array_inq_function (GFC_ISYM_SIZE
, c
, 2),
2353 get_array_inq_function (GFC_ISYM_SIZE
, b
, 1));
2354 cond
= build_logical_expr (INTRINSIC_OR
, ne1
, ne2
);
2358 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2359 cond
= build_logical_expr (INTRINSIC_NE
,
2360 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2361 get_array_inq_function (GFC_ISYM_SIZE
, a
, 2));
2365 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, b
, 1);
2366 cond
= build_logical_expr (INTRINSIC_NE
,
2367 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2368 get_array_inq_function (GFC_ISYM_SIZE
, b
, 2));
2376 gfc_simplify_expr (cond
, 0);
2378 /* We need two identical allocate statements in two
2379 branches of the IF statement. */
2381 allocate1
= XCNEW (gfc_code
);
2382 allocate1
->op
= EXEC_ALLOCATE
;
2383 allocate1
->ext
.alloc
.list
= gfc_get_alloc ();
2384 allocate1
->loc
= c
->where
;
2385 allocate1
->ext
.alloc
.list
->expr
= gfc_copy_expr (alloc_expr
);
2387 allocate_else
= XCNEW (gfc_code
);
2388 allocate_else
->op
= EXEC_ALLOCATE
;
2389 allocate_else
->ext
.alloc
.list
= gfc_get_alloc ();
2390 allocate_else
->loc
= c
->where
;
2391 allocate_else
->ext
.alloc
.list
->expr
= alloc_expr
;
2393 allocated
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_ALLOCATED
,
2394 "_gfortran_allocated", c
->where
,
2395 1, gfc_copy_expr (c
));
2397 deallocate
= XCNEW (gfc_code
);
2398 deallocate
->op
= EXEC_DEALLOCATE
;
2399 deallocate
->ext
.alloc
.list
= gfc_get_alloc ();
2400 deallocate
->ext
.alloc
.list
->expr
= gfc_copy_expr (c
);
2401 deallocate
->next
= allocate1
;
2402 deallocate
->loc
= c
->where
;
2404 if_size_2
= XCNEW (gfc_code
);
2405 if_size_2
->op
= EXEC_IF
;
2406 if_size_2
->expr1
= cond
;
2407 if_size_2
->loc
= c
->where
;
2408 if_size_2
->next
= deallocate
;
2410 if_size_1
= XCNEW (gfc_code
);
2411 if_size_1
->op
= EXEC_IF
;
2412 if_size_1
->block
= if_size_2
;
2413 if_size_1
->loc
= c
->where
;
2415 else_alloc
= XCNEW (gfc_code
);
2416 else_alloc
->op
= EXEC_IF
;
2417 else_alloc
->loc
= c
->where
;
2418 else_alloc
->next
= allocate_else
;
2420 if_alloc_2
= XCNEW (gfc_code
);
2421 if_alloc_2
->op
= EXEC_IF
;
2422 if_alloc_2
->expr1
= allocated
;
2423 if_alloc_2
->loc
= c
->where
;
2424 if_alloc_2
->next
= if_size_1
;
2425 if_alloc_2
->block
= else_alloc
;
2427 if_alloc_1
= XCNEW (gfc_code
);
2428 if_alloc_1
->op
= EXEC_IF
;
2429 if_alloc_1
->block
= if_alloc_2
;
2430 if_alloc_1
->loc
= c
->where
;
2435 /* Callback function for has_function_or_op. */
2438 is_function_or_op (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2439 void *data ATTRIBUTE_UNUSED
)
2444 return (*e
)->expr_type
== EXPR_FUNCTION
2445 || (*e
)->expr_type
== EXPR_OP
;
2448 /* Returns true if the expression contains a function. */
2451 has_function_or_op (gfc_expr
**e
)
2456 return gfc_expr_walker (e
, is_function_or_op
, NULL
);
2459 /* Freeze (assign to a temporary variable) a single expression. */
2462 freeze_expr (gfc_expr
**ep
)
2465 if (has_function_or_op (ep
))
2467 ne
= create_var (*ep
, "freeze");
2472 /* Go through an expression's references and assign them to temporary
2473 variables if they contain functions. This is usually done prior to
2474 front-end scalarization to avoid multiple invocations of functions. */
2477 freeze_references (gfc_expr
*e
)
2483 for (r
=e
->ref
; r
; r
=r
->next
)
2485 if (r
->type
== REF_SUBSTRING
)
2487 if (r
->u
.ss
.start
!= NULL
)
2488 freeze_expr (&r
->u
.ss
.start
);
2490 if (r
->u
.ss
.end
!= NULL
)
2491 freeze_expr (&r
->u
.ss
.end
);
2493 else if (r
->type
== REF_ARRAY
)
2502 for (i
=0; i
<ar
->dimen
; i
++)
2504 if (ar
->dimen_type
[i
] == DIMEN_RANGE
)
2506 freeze_expr (&ar
->start
[i
]);
2507 freeze_expr (&ar
->end
[i
]);
2508 freeze_expr (&ar
->stride
[i
]);
2510 else if (ar
->dimen_type
[i
] == DIMEN_ELEMENT
)
2512 freeze_expr (&ar
->start
[i
]);
2518 for (i
=0; i
<ar
->dimen
; i
++)
2519 freeze_expr (&ar
->start
[i
]);
2529 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
2532 convert_to_index_kind (gfc_expr
*e
)
2536 gcc_assert (e
!= NULL
);
2538 res
= gfc_copy_expr (e
);
2540 gcc_assert (e
->ts
.type
== BT_INTEGER
);
2542 if (res
->ts
.kind
!= gfc_index_integer_kind
)
2546 ts
.type
= BT_INTEGER
;
2547 ts
.kind
= gfc_index_integer_kind
;
2549 gfc_convert_type_warn (e
, &ts
, 2, 0);
2555 /* Function to create a DO loop including creation of the
2556 iteration variable. gfc_expr are copied.*/
2559 create_do_loop (gfc_expr
*start
, gfc_expr
*end
, gfc_expr
*step
, locus
*where
,
2560 gfc_namespace
*ns
, char *vname
)
2563 char name
[GFC_MAX_SYMBOL_LEN
+1];
2564 gfc_symtree
*symtree
;
2569 /* Create an expression for the iteration variable. */
2571 sprintf (name
, "__var_%d_do_%s", var_num
++, vname
);
2573 sprintf (name
, "__var_%d_do", var_num
++);
2576 if (gfc_get_sym_tree (name
, ns
, &symtree
, false) != 0)
2579 /* Create the loop variable. */
2581 symbol
= symtree
->n
.sym
;
2582 symbol
->ts
.type
= BT_INTEGER
;
2583 symbol
->ts
.kind
= gfc_index_integer_kind
;
2584 symbol
->attr
.flavor
= FL_VARIABLE
;
2585 symbol
->attr
.referenced
= 1;
2586 symbol
->attr
.dimension
= 0;
2587 symbol
->attr
.fe_temp
= 1;
2588 gfc_commit_symbol (symbol
);
2590 i
= gfc_get_expr ();
2591 i
->expr_type
= EXPR_VARIABLE
;
2595 i
->symtree
= symtree
;
2597 /* ... and the nested DO statements. */
2598 n
= XCNEW (gfc_code
);
2601 n
->ext
.iterator
= gfc_get_iterator ();
2602 n
->ext
.iterator
->var
= i
;
2603 n
->ext
.iterator
->start
= convert_to_index_kind (start
);
2604 n
->ext
.iterator
->end
= convert_to_index_kind (end
);
2606 n
->ext
.iterator
->step
= convert_to_index_kind (step
);
2608 n
->ext
.iterator
->step
= gfc_get_int_expr (gfc_index_integer_kind
,
2611 n2
= XCNEW (gfc_code
);
2619 /* Get the upper bound of the DO loops for matmul along a dimension. This
2623 get_size_m1 (gfc_expr
*e
, int dimen
)
2628 if (gfc_array_dimen_size (e
, dimen
- 1, &size
))
2630 res
= gfc_get_constant_expr (BT_INTEGER
,
2631 gfc_index_integer_kind
, &e
->where
);
2632 mpz_sub_ui (res
->value
.integer
, size
, 1);
2637 res
= get_operand (INTRINSIC_MINUS
,
2638 get_array_inq_function (GFC_ISYM_SIZE
, e
, dimen
),
2639 gfc_get_int_expr (gfc_index_integer_kind
,
2641 gfc_simplify_expr (res
, 0);
2647 /* Function to return a scalarized expression. It is assumed that indices are
2648 zero based to make generation of DO loops easier. A zero as index will
2649 access the first element along a dimension. Single element references will
2650 be skipped. A NULL as an expression will be replaced by a full reference.
2651 This assumes that the index loops have gfc_index_integer_kind, and that all
2652 references have been frozen. */
2655 scalarized_expr (gfc_expr
*e_in
, gfc_expr
**index
, int count_index
)
2664 e
= gfc_copy_expr(e_in
);
2668 ar
= gfc_find_array_ref (e
);
2670 /* We scalarize count_index variables, reducing the rank by count_index. */
2672 e
->rank
= rank
- count_index
;
2674 was_fullref
= ar
->type
== AR_FULL
;
2677 ar
->type
= AR_ELEMENT
;
2679 ar
->type
= AR_SECTION
;
2681 /* Loop over the indices. For each index, create the expression
2682 index * stride + lbound(e, dim). */
2685 for (i
=0; i
< ar
->dimen
; i
++)
2687 if (was_fullref
|| ar
->dimen_type
[i
] == DIMEN_RANGE
)
2689 if (index
[i_index
] != NULL
)
2691 gfc_expr
*lbound
, *nindex
;
2694 loopvar
= gfc_copy_expr (index
[i_index
]);
2700 tmp
= gfc_copy_expr(ar
->stride
[i
]);
2701 if (tmp
->ts
.kind
!= gfc_index_integer_kind
)
2705 ts
.type
= BT_INTEGER
;
2706 ts
.kind
= gfc_index_integer_kind
;
2707 gfc_convert_type (tmp
, &ts
, 2);
2709 nindex
= get_operand (INTRINSIC_TIMES
, loopvar
, tmp
);
2714 /* Calculate the lower bound of the expression. */
2717 lbound
= gfc_copy_expr (ar
->start
[i
]);
2718 if (lbound
->ts
.kind
!= gfc_index_integer_kind
)
2722 ts
.type
= BT_INTEGER
;
2723 ts
.kind
= gfc_index_integer_kind
;
2724 gfc_convert_type (lbound
, &ts
, 2);
2733 lbound_e
= gfc_copy_expr (e_in
);
2735 for (ref
= lbound_e
->ref
; ref
; ref
= ref
->next
)
2736 if (ref
->type
== REF_ARRAY
2737 && (ref
->u
.ar
.type
== AR_FULL
2738 || ref
->u
.ar
.type
== AR_SECTION
))
2743 gfc_free_ref_list (ref
->next
);
2749 /* Look at full individual sections, like a(:). The first index
2750 is the lbound of a full ref. */
2756 for (j
= 0; j
< ar
->dimen
; j
++)
2758 gfc_free_expr (ar
->start
[j
]);
2759 ar
->start
[j
] = NULL
;
2760 gfc_free_expr (ar
->end
[j
]);
2762 gfc_free_expr (ar
->stride
[j
]);
2763 ar
->stride
[j
] = NULL
;
2766 /* We have to get rid of the shape, if there is one. Do
2767 so by freeing it and calling gfc_resolve to rebuild
2768 it, if necessary. */
2770 if (lbound_e
->shape
)
2771 gfc_free_shape (&(lbound_e
->shape
), lbound_e
->rank
);
2773 lbound_e
->rank
= ar
->dimen
;
2774 gfc_resolve_expr (lbound_e
);
2776 lbound
= get_array_inq_function (GFC_ISYM_LBOUND
, lbound_e
,
2778 gfc_free_expr (lbound_e
);
2781 ar
->dimen_type
[i
] = DIMEN_ELEMENT
;
2783 gfc_free_expr (ar
->start
[i
]);
2784 ar
->start
[i
] = get_operand (INTRINSIC_PLUS
, nindex
, lbound
);
2786 gfc_free_expr (ar
->end
[i
]);
2788 gfc_free_expr (ar
->stride
[i
]);
2789 ar
->stride
[i
] = NULL
;
2790 gfc_simplify_expr (ar
->start
[i
], 0);
2792 else if (was_fullref
)
2794 gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
2803 /* Helper function to check for a dimen vector as subscript. */
2806 has_dimen_vector_ref (gfc_expr
*e
)
2811 ar
= gfc_find_array_ref (e
);
2813 if (ar
->type
== AR_FULL
)
2816 for (i
=0; i
<ar
->dimen
; i
++)
2817 if (ar
->dimen_type
[i
] == DIMEN_VECTOR
)
2823 /* If handed an expression of the form
2827 check if A can be handled by matmul and return if there is an uneven number
2828 of CONJG calls. Return a pointer to the array when everything is OK, NULL
2829 otherwise. The caller has to check for the correct rank. */
2832 check_conjg_transpose_variable (gfc_expr
*e
, bool *conjg
, bool *transpose
)
2839 if (e
->expr_type
== EXPR_VARIABLE
)
2841 gcc_assert (e
->rank
== 1 || e
->rank
== 2);
2844 else if (e
->expr_type
== EXPR_FUNCTION
)
2846 if (e
->value
.function
.isym
== NULL
)
2849 if (e
->value
.function
.isym
->id
== GFC_ISYM_CONJG
)
2851 else if (e
->value
.function
.isym
->id
== GFC_ISYM_TRANSPOSE
)
2852 *transpose
= !*transpose
;
2858 e
= e
->value
.function
.actual
->expr
;
2865 /* Inline assignments of the form c = matmul(a,b).
2866 Handle only the cases currently where b and c are rank-two arrays.
2868 This basically translates the code to
2874 do k=0, size(a, 2)-1
2875 do i=0, size(a, 1)-1
2876 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
2877 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
2878 a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
2879 b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
2888 inline_matmul_assign (gfc_code
**c
, int *walk_subtrees
,
2889 void *data ATTRIBUTE_UNUSED
)
2892 gfc_expr
*expr1
, *expr2
;
2893 gfc_expr
*matrix_a
, *matrix_b
;
2894 gfc_actual_arglist
*a
, *b
;
2895 gfc_code
*do_1
, *do_2
, *do_3
, *assign_zero
, *assign_matmul
;
2897 gfc_expr
*u1
, *u2
, *u3
;
2899 gfc_expr
*ascalar
, *bscalar
, *cscalar
;
2901 gfc_expr
*var_1
, *var_2
, *var_3
;
2904 gfc_intrinsic_op op_times
, op_plus
;
2905 enum matrix_case m_case
;
2907 gfc_code
*if_limit
= NULL
;
2908 gfc_code
**next_code_point
;
2909 bool conjg_a
, conjg_b
, transpose_a
, transpose_b
;
2911 if (co
->op
!= EXEC_ASSIGN
)
2917 /* The BLOCKS generated for the temporary variables and FORALL don't
2919 if (forall_level
> 0)
2922 /* For now don't do anything in OpenMP workshare, it confuses
2923 its translation, which expects only the allowed statements in there.
2924 We should figure out how to parallelize this eventually. */
2925 if (in_omp_workshare
)
2930 if (expr2
->expr_type
!= EXPR_FUNCTION
2931 || expr2
->value
.function
.isym
== NULL
2932 || expr2
->value
.function
.isym
->id
!= GFC_ISYM_MATMUL
)
2936 inserted_block
= NULL
;
2937 changed_statement
= NULL
;
2939 a
= expr2
->value
.function
.actual
;
2940 matrix_a
= check_conjg_transpose_variable (a
->expr
, &conjg_a
, &transpose_a
);
2941 if (transpose_a
|| matrix_a
== NULL
)
2945 matrix_b
= check_conjg_transpose_variable (b
->expr
, &conjg_b
, &transpose_b
);
2946 if (matrix_b
== NULL
)
2949 if (has_dimen_vector_ref (expr1
) || has_dimen_vector_ref (matrix_a
)
2950 || has_dimen_vector_ref (matrix_b
))
2953 /* We do not handle data dependencies yet. */
2954 if (gfc_check_dependency (expr1
, matrix_a
, true)
2955 || gfc_check_dependency (expr1
, matrix_b
, true))
2958 if (matrix_a
->rank
== 2)
2960 if (matrix_b
->rank
== 1)
2972 /* Vector * Transpose(B) not handled yet. */
2982 ns
= insert_block ();
2984 /* Assign the type of the zero expression for initializing the resulting
2985 array, and the expression (+ and * for real, integer and complex;
2986 .and. and .or for logical. */
2988 switch(expr1
->ts
.type
)
2991 zero_e
= gfc_get_int_expr (expr1
->ts
.kind
, &expr1
->where
, 0);
2992 op_times
= INTRINSIC_TIMES
;
2993 op_plus
= INTRINSIC_PLUS
;
2997 op_times
= INTRINSIC_AND
;
2998 op_plus
= INTRINSIC_OR
;
2999 zero_e
= gfc_get_logical_expr (expr1
->ts
.kind
, &expr1
->where
,
3003 zero_e
= gfc_get_constant_expr (BT_REAL
, expr1
->ts
.kind
,
3005 mpfr_set_si (zero_e
->value
.real
, 0, GFC_RND_MODE
);
3006 op_times
= INTRINSIC_TIMES
;
3007 op_plus
= INTRINSIC_PLUS
;
3011 zero_e
= gfc_get_constant_expr (BT_COMPLEX
, expr1
->ts
.kind
,
3013 mpc_set_si_si (zero_e
->value
.complex, 0, 0, GFC_RND_MODE
);
3014 op_times
= INTRINSIC_TIMES
;
3015 op_plus
= INTRINSIC_PLUS
;
3023 current_code
= &ns
->code
;
3025 /* Freeze the references, keeping track of how many temporary variables were
3028 freeze_references (matrix_a
);
3029 freeze_references (matrix_b
);
3030 freeze_references (expr1
);
3033 next_code_point
= current_code
;
3036 next_code_point
= &ns
->code
;
3037 for (i
=0; i
<n_vars
; i
++)
3038 next_code_point
= &(*next_code_point
)->next
;
3041 /* Take care of the inline flag. If the limit check evaluates to a
3042 constant, dead code elimination will eliminate the unneeded branch. */
3044 if (m_case
== A2B2
&& flag_inline_matmul_limit
> 0)
3046 if_limit
= inline_limit_check (matrix_a
, matrix_b
, m_case
);
3048 /* Insert the original statement into the else branch. */
3049 if_limit
->block
->block
->next
= co
;
3052 /* ... and the new ones go into the original one. */
3053 *next_code_point
= if_limit
;
3054 next_code_point
= &if_limit
->block
->next
;
3057 assign_zero
= XCNEW (gfc_code
);
3058 assign_zero
->op
= EXEC_ASSIGN
;
3059 assign_zero
->loc
= co
->loc
;
3060 assign_zero
->expr1
= gfc_copy_expr (expr1
);
3061 assign_zero
->expr2
= zero_e
;
3063 /* Handle the reallocation, if needed. */
3064 if (flag_realloc_lhs
&& gfc_is_reallocatable_lhs (expr1
))
3066 gfc_code
*lhs_alloc
;
3068 /* Only need to check a single dimension for the A2B2 case for
3069 bounds checking, the rest will be allocated. */
3071 if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
&& m_case
== A2B2
)
3076 a2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 2);
3077 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3078 test
= runtime_error_ne (b1
, a2
, "Dimension of array B incorrect "
3079 "in MATMUL intrinsic: Is %ld, should be %ld");
3080 *next_code_point
= test
;
3081 next_code_point
= &test
->next
;
3085 lhs_alloc
= matmul_lhs_realloc (expr1
, matrix_a
, matrix_b
, m_case
);
3087 *next_code_point
= lhs_alloc
;
3088 next_code_point
= &lhs_alloc
->next
;
3091 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
3094 gfc_expr
*a2
, *b1
, *c1
, *c2
, *a1
, *b2
;
3096 if (m_case
== A2B2
|| m_case
== A2B1
)
3098 a2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 2);
3099 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3100 test
= runtime_error_ne (b1
, a2
, "Dimension of array B incorrect "
3101 "in MATMUL intrinsic: Is %ld, should be %ld");
3102 *next_code_point
= test
;
3103 next_code_point
= &test
->next
;
3105 c1
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 1);
3106 a1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 1);
3109 test
= runtime_error_ne (c1
, a1
, "Incorrect extent in return array in "
3110 "MATMUL intrinsic for dimension 1: "
3111 "is %ld, should be %ld");
3112 else if (m_case
== A2B1
)
3113 test
= runtime_error_ne (c1
, a1
, "Incorrect extent in return array in "
3114 "MATMUL intrinsic: "
3115 "is %ld, should be %ld");
3118 *next_code_point
= test
;
3119 next_code_point
= &test
->next
;
3121 else if (m_case
== A1B2
)
3123 a1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 1);
3124 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3125 test
= runtime_error_ne (b1
, a1
, "Dimension of array B incorrect "
3126 "in MATMUL intrinsic: Is %ld, should be %ld");
3127 *next_code_point
= test
;
3128 next_code_point
= &test
->next
;
3130 c1
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 1);
3131 b2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 2);
3133 test
= runtime_error_ne (c1
, b2
, "Incorrect extent in return array in "
3134 "MATMUL intrinsic: "
3135 "is %ld, should be %ld");
3137 *next_code_point
= test
;
3138 next_code_point
= &test
->next
;
3143 c2
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 2);
3144 b2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 2);
3145 test
= runtime_error_ne (c2
, b2
, "Incorrect extent in return array in "
3146 "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
3148 *next_code_point
= test
;
3149 next_code_point
= &test
->next
;
3152 if (m_case
== A2B2T
)
3154 c1
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 1);
3155 a1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 1);
3156 test
= runtime_error_ne (c1
, a1
, "Incorrect extent in return array in "
3157 "MATMUL intrinsic for dimension 1: "
3158 "is %ld, should be %ld");
3160 *next_code_point
= test
;
3161 next_code_point
= &test
->next
;
3163 c2
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 2);
3164 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3165 test
= runtime_error_ne (c2
, b1
, "Incorrect extent in return array in "
3166 "MATMUL intrinsic for dimension 2: "
3167 "is %ld, should be %ld");
3168 *next_code_point
= test
;
3169 next_code_point
= &test
->next
;
3171 a2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 2);
3172 b2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 2);
3174 test
= runtime_error_ne (b2
, a2
, "Incorrect extent in argument B in "
3175 "MATMUL intrnisic for dimension 2: "
3176 "is %ld, should be %ld");
3177 *next_code_point
= test
;
3178 next_code_point
= &test
->next
;
3183 *next_code_point
= assign_zero
;
3185 zero
= gfc_get_int_expr (gfc_index_integer_kind
, &co
->loc
, 0);
3187 assign_matmul
= XCNEW (gfc_code
);
3188 assign_matmul
->op
= EXEC_ASSIGN
;
3189 assign_matmul
->loc
= co
->loc
;
3191 /* Get the bounds for the loops, create them and create the scalarized
3197 inline_limit_check (matrix_a
, matrix_b
, m_case
);
3199 u1
= get_size_m1 (matrix_b
, 2);
3200 u2
= get_size_m1 (matrix_a
, 2);
3201 u3
= get_size_m1 (matrix_a
, 1);
3203 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3204 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3205 do_3
= create_do_loop (gfc_copy_expr (zero
), u3
, NULL
, &co
->loc
, ns
);
3207 do_1
->block
->next
= do_2
;
3208 do_2
->block
->next
= do_3
;
3209 do_3
->block
->next
= assign_matmul
;
3211 var_1
= do_1
->ext
.iterator
->var
;
3212 var_2
= do_2
->ext
.iterator
->var
;
3213 var_3
= do_3
->ext
.iterator
->var
;
3217 cscalar
= scalarized_expr (co
->expr1
, list
, 2);
3221 ascalar
= scalarized_expr (matrix_a
, list
, 2);
3225 bscalar
= scalarized_expr (matrix_b
, list
, 2);
3230 inline_limit_check (matrix_a
, matrix_b
, m_case
);
3232 u1
= get_size_m1 (matrix_b
, 1);
3233 u2
= get_size_m1 (matrix_a
, 2);
3234 u3
= get_size_m1 (matrix_a
, 1);
3236 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3237 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3238 do_3
= create_do_loop (gfc_copy_expr (zero
), u3
, NULL
, &co
->loc
, ns
);
3240 do_1
->block
->next
= do_2
;
3241 do_2
->block
->next
= do_3
;
3242 do_3
->block
->next
= assign_matmul
;
3244 var_1
= do_1
->ext
.iterator
->var
;
3245 var_2
= do_2
->ext
.iterator
->var
;
3246 var_3
= do_3
->ext
.iterator
->var
;
3250 cscalar
= scalarized_expr (co
->expr1
, list
, 2);
3254 ascalar
= scalarized_expr (matrix_a
, list
, 2);
3258 bscalar
= scalarized_expr (matrix_b
, list
, 2);
3263 u1
= get_size_m1 (matrix_b
, 1);
3264 u2
= get_size_m1 (matrix_a
, 1);
3266 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3267 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3269 do_1
->block
->next
= do_2
;
3270 do_2
->block
->next
= assign_matmul
;
3272 var_1
= do_1
->ext
.iterator
->var
;
3273 var_2
= do_2
->ext
.iterator
->var
;
3276 cscalar
= scalarized_expr (co
->expr1
, list
, 1);
3280 ascalar
= scalarized_expr (matrix_a
, list
, 2);
3283 bscalar
= scalarized_expr (matrix_b
, list
, 1);
3288 u1
= get_size_m1 (matrix_b
, 2);
3289 u2
= get_size_m1 (matrix_a
, 1);
3291 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3292 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3294 do_1
->block
->next
= do_2
;
3295 do_2
->block
->next
= assign_matmul
;
3297 var_1
= do_1
->ext
.iterator
->var
;
3298 var_2
= do_2
->ext
.iterator
->var
;
3301 cscalar
= scalarized_expr (co
->expr1
, list
, 1);
3304 ascalar
= scalarized_expr (matrix_a
, list
, 1);
3308 bscalar
= scalarized_expr (matrix_b
, list
, 2);
3317 ascalar
= gfc_build_intrinsic_call (ns
, GFC_ISYM_CONJG
, "conjg",
3318 matrix_a
->where
, 1, ascalar
);
3321 bscalar
= gfc_build_intrinsic_call (ns
, GFC_ISYM_CONJG
, "conjg",
3322 matrix_b
->where
, 1, bscalar
);
3324 /* First loop comes after the zero assignment. */
3325 assign_zero
->next
= do_1
;
3327 /* Build the assignment expression in the loop. */
3328 assign_matmul
->expr1
= gfc_copy_expr (cscalar
);
3330 mult
= get_operand (op_times
, ascalar
, bscalar
);
3331 assign_matmul
->expr2
= get_operand (op_plus
, cscalar
, mult
);
3333 /* If we don't want to keep the original statement around in
3334 the else branch, we can free it. */
3336 if (if_limit
== NULL
)
3337 gfc_free_statements(co
);
3341 gfc_free_expr (zero
);
3346 #define WALK_SUBEXPR(NODE) \
3349 result = gfc_expr_walker (&(NODE), exprfn, data); \
3354 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
3356 /* Walk expression *E, calling EXPRFN on each expression in it. */
3359 gfc_expr_walker (gfc_expr
**e
, walk_expr_fn_t exprfn
, void *data
)
3363 int walk_subtrees
= 1;
3364 gfc_actual_arglist
*a
;
3368 int result
= exprfn (e
, &walk_subtrees
, data
);
3372 switch ((*e
)->expr_type
)
3375 WALK_SUBEXPR ((*e
)->value
.op
.op1
);
3376 WALK_SUBEXPR_TAIL ((*e
)->value
.op
.op2
);
3379 for (a
= (*e
)->value
.function
.actual
; a
; a
= a
->next
)
3380 WALK_SUBEXPR (a
->expr
);
3384 WALK_SUBEXPR ((*e
)->value
.compcall
.base_object
);
3385 for (a
= (*e
)->value
.compcall
.actual
; a
; a
= a
->next
)
3386 WALK_SUBEXPR (a
->expr
);
3389 case EXPR_STRUCTURE
:
3391 for (c
= gfc_constructor_first ((*e
)->value
.constructor
); c
;
3392 c
= gfc_constructor_next (c
))
3394 if (c
->iterator
== NULL
)
3395 WALK_SUBEXPR (c
->expr
);
3399 WALK_SUBEXPR (c
->expr
);
3401 WALK_SUBEXPR (c
->iterator
->var
);
3402 WALK_SUBEXPR (c
->iterator
->start
);
3403 WALK_SUBEXPR (c
->iterator
->end
);
3404 WALK_SUBEXPR (c
->iterator
->step
);
3408 if ((*e
)->expr_type
!= EXPR_ARRAY
)
3411 /* Fall through to the variable case in order to walk the
3415 case EXPR_SUBSTRING
:
3417 for (r
= (*e
)->ref
; r
; r
= r
->next
)
3426 if (ar
->type
== AR_SECTION
|| ar
->type
== AR_ELEMENT
)
3428 for (i
=0; i
< ar
->dimen
; i
++)
3430 WALK_SUBEXPR (ar
->start
[i
]);
3431 WALK_SUBEXPR (ar
->end
[i
]);
3432 WALK_SUBEXPR (ar
->stride
[i
]);
3439 WALK_SUBEXPR (r
->u
.ss
.start
);
3440 WALK_SUBEXPR (r
->u
.ss
.end
);
3456 #define WALK_SUBCODE(NODE) \
3459 result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
3465 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
3466 on each expression in it. If any of the hooks returns non-zero, that
3467 value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
3468 no subcodes or subexpressions are traversed. */
3471 gfc_code_walker (gfc_code
**c
, walk_code_fn_t codefn
, walk_expr_fn_t exprfn
,
3474 for (; *c
; c
= &(*c
)->next
)
3476 int walk_subtrees
= 1;
3477 int result
= codefn (c
, &walk_subtrees
, data
);
3484 gfc_actual_arglist
*a
;
3486 gfc_association_list
*alist
;
3487 bool saved_in_omp_workshare
;
3488 bool saved_in_where
;
3490 /* There might be statement insertions before the current code,
3491 which must not affect the expression walker. */
3494 saved_in_omp_workshare
= in_omp_workshare
;
3495 saved_in_where
= in_where
;
3501 WALK_SUBCODE (co
->ext
.block
.ns
->code
);
3502 if (co
->ext
.block
.assoc
)
3504 bool saved_in_assoc_list
= in_assoc_list
;
3506 in_assoc_list
= true;
3507 for (alist
= co
->ext
.block
.assoc
; alist
; alist
= alist
->next
)
3508 WALK_SUBEXPR (alist
->target
);
3510 in_assoc_list
= saved_in_assoc_list
;
3517 WALK_SUBEXPR (co
->ext
.iterator
->var
);
3518 WALK_SUBEXPR (co
->ext
.iterator
->start
);
3519 WALK_SUBEXPR (co
->ext
.iterator
->end
);
3520 WALK_SUBEXPR (co
->ext
.iterator
->step
);
3528 case EXEC_ASSIGN_CALL
:
3529 for (a
= co
->ext
.actual
; a
; a
= a
->next
)
3530 WALK_SUBEXPR (a
->expr
);
3534 WALK_SUBEXPR (co
->expr1
);
3535 for (a
= co
->ext
.actual
; a
; a
= a
->next
)
3536 WALK_SUBEXPR (a
->expr
);
3540 WALK_SUBEXPR (co
->expr1
);
3541 for (b
= co
->block
; b
; b
= b
->block
)
3544 for (cp
= b
->ext
.block
.case_list
; cp
; cp
= cp
->next
)
3546 WALK_SUBEXPR (cp
->low
);
3547 WALK_SUBEXPR (cp
->high
);
3549 WALK_SUBCODE (b
->next
);
3554 case EXEC_DEALLOCATE
:
3557 for (a
= co
->ext
.alloc
.list
; a
; a
= a
->next
)
3558 WALK_SUBEXPR (a
->expr
);
3563 case EXEC_DO_CONCURRENT
:
3565 gfc_forall_iterator
*fa
;
3566 for (fa
= co
->ext
.forall_iterator
; fa
; fa
= fa
->next
)
3568 WALK_SUBEXPR (fa
->var
);
3569 WALK_SUBEXPR (fa
->start
);
3570 WALK_SUBEXPR (fa
->end
);
3571 WALK_SUBEXPR (fa
->stride
);
3573 if (co
->op
== EXEC_FORALL
)
3579 WALK_SUBEXPR (co
->ext
.open
->unit
);
3580 WALK_SUBEXPR (co
->ext
.open
->file
);
3581 WALK_SUBEXPR (co
->ext
.open
->status
);
3582 WALK_SUBEXPR (co
->ext
.open
->access
);
3583 WALK_SUBEXPR (co
->ext
.open
->form
);
3584 WALK_SUBEXPR (co
->ext
.open
->recl
);
3585 WALK_SUBEXPR (co
->ext
.open
->blank
);
3586 WALK_SUBEXPR (co
->ext
.open
->position
);
3587 WALK_SUBEXPR (co
->ext
.open
->action
);
3588 WALK_SUBEXPR (co
->ext
.open
->delim
);
3589 WALK_SUBEXPR (co
->ext
.open
->pad
);
3590 WALK_SUBEXPR (co
->ext
.open
->iostat
);
3591 WALK_SUBEXPR (co
->ext
.open
->iomsg
);
3592 WALK_SUBEXPR (co
->ext
.open
->convert
);
3593 WALK_SUBEXPR (co
->ext
.open
->decimal
);
3594 WALK_SUBEXPR (co
->ext
.open
->encoding
);
3595 WALK_SUBEXPR (co
->ext
.open
->round
);
3596 WALK_SUBEXPR (co
->ext
.open
->sign
);
3597 WALK_SUBEXPR (co
->ext
.open
->asynchronous
);
3598 WALK_SUBEXPR (co
->ext
.open
->id
);
3599 WALK_SUBEXPR (co
->ext
.open
->newunit
);
3600 WALK_SUBEXPR (co
->ext
.open
->share
);
3601 WALK_SUBEXPR (co
->ext
.open
->cc
);
3605 WALK_SUBEXPR (co
->ext
.close
->unit
);
3606 WALK_SUBEXPR (co
->ext
.close
->status
);
3607 WALK_SUBEXPR (co
->ext
.close
->iostat
);
3608 WALK_SUBEXPR (co
->ext
.close
->iomsg
);
3611 case EXEC_BACKSPACE
:
3615 WALK_SUBEXPR (co
->ext
.filepos
->unit
);
3616 WALK_SUBEXPR (co
->ext
.filepos
->iostat
);
3617 WALK_SUBEXPR (co
->ext
.filepos
->iomsg
);
3621 WALK_SUBEXPR (co
->ext
.inquire
->unit
);
3622 WALK_SUBEXPR (co
->ext
.inquire
->file
);
3623 WALK_SUBEXPR (co
->ext
.inquire
->iomsg
);
3624 WALK_SUBEXPR (co
->ext
.inquire
->iostat
);
3625 WALK_SUBEXPR (co
->ext
.inquire
->exist
);
3626 WALK_SUBEXPR (co
->ext
.inquire
->opened
);
3627 WALK_SUBEXPR (co
->ext
.inquire
->number
);
3628 WALK_SUBEXPR (co
->ext
.inquire
->named
);
3629 WALK_SUBEXPR (co
->ext
.inquire
->name
);
3630 WALK_SUBEXPR (co
->ext
.inquire
->access
);
3631 WALK_SUBEXPR (co
->ext
.inquire
->sequential
);
3632 WALK_SUBEXPR (co
->ext
.inquire
->direct
);
3633 WALK_SUBEXPR (co
->ext
.inquire
->form
);
3634 WALK_SUBEXPR (co
->ext
.inquire
->formatted
);
3635 WALK_SUBEXPR (co
->ext
.inquire
->unformatted
);
3636 WALK_SUBEXPR (co
->ext
.inquire
->recl
);
3637 WALK_SUBEXPR (co
->ext
.inquire
->nextrec
);
3638 WALK_SUBEXPR (co
->ext
.inquire
->blank
);
3639 WALK_SUBEXPR (co
->ext
.inquire
->position
);
3640 WALK_SUBEXPR (co
->ext
.inquire
->action
);
3641 WALK_SUBEXPR (co
->ext
.inquire
->read
);
3642 WALK_SUBEXPR (co
->ext
.inquire
->write
);
3643 WALK_SUBEXPR (co
->ext
.inquire
->readwrite
);
3644 WALK_SUBEXPR (co
->ext
.inquire
->delim
);
3645 WALK_SUBEXPR (co
->ext
.inquire
->encoding
);
3646 WALK_SUBEXPR (co
->ext
.inquire
->pad
);
3647 WALK_SUBEXPR (co
->ext
.inquire
->iolength
);
3648 WALK_SUBEXPR (co
->ext
.inquire
->convert
);
3649 WALK_SUBEXPR (co
->ext
.inquire
->strm_pos
);
3650 WALK_SUBEXPR (co
->ext
.inquire
->asynchronous
);
3651 WALK_SUBEXPR (co
->ext
.inquire
->decimal
);
3652 WALK_SUBEXPR (co
->ext
.inquire
->pending
);
3653 WALK_SUBEXPR (co
->ext
.inquire
->id
);
3654 WALK_SUBEXPR (co
->ext
.inquire
->sign
);
3655 WALK_SUBEXPR (co
->ext
.inquire
->size
);
3656 WALK_SUBEXPR (co
->ext
.inquire
->round
);
3660 WALK_SUBEXPR (co
->ext
.wait
->unit
);
3661 WALK_SUBEXPR (co
->ext
.wait
->iostat
);
3662 WALK_SUBEXPR (co
->ext
.wait
->iomsg
);
3663 WALK_SUBEXPR (co
->ext
.wait
->id
);
3668 WALK_SUBEXPR (co
->ext
.dt
->io_unit
);
3669 WALK_SUBEXPR (co
->ext
.dt
->format_expr
);
3670 WALK_SUBEXPR (co
->ext
.dt
->rec
);
3671 WALK_SUBEXPR (co
->ext
.dt
->advance
);
3672 WALK_SUBEXPR (co
->ext
.dt
->iostat
);
3673 WALK_SUBEXPR (co
->ext
.dt
->size
);
3674 WALK_SUBEXPR (co
->ext
.dt
->iomsg
);
3675 WALK_SUBEXPR (co
->ext
.dt
->id
);
3676 WALK_SUBEXPR (co
->ext
.dt
->pos
);
3677 WALK_SUBEXPR (co
->ext
.dt
->asynchronous
);
3678 WALK_SUBEXPR (co
->ext
.dt
->blank
);
3679 WALK_SUBEXPR (co
->ext
.dt
->decimal
);
3680 WALK_SUBEXPR (co
->ext
.dt
->delim
);
3681 WALK_SUBEXPR (co
->ext
.dt
->pad
);
3682 WALK_SUBEXPR (co
->ext
.dt
->round
);
3683 WALK_SUBEXPR (co
->ext
.dt
->sign
);
3684 WALK_SUBEXPR (co
->ext
.dt
->extra_comma
);
3687 case EXEC_OMP_PARALLEL
:
3688 case EXEC_OMP_PARALLEL_DO
:
3689 case EXEC_OMP_PARALLEL_DO_SIMD
:
3690 case EXEC_OMP_PARALLEL_SECTIONS
:
3692 in_omp_workshare
= false;
3694 /* This goto serves as a shortcut to avoid code
3695 duplication or a larger if or switch statement. */
3696 goto check_omp_clauses
;
3698 case EXEC_OMP_WORKSHARE
:
3699 case EXEC_OMP_PARALLEL_WORKSHARE
:
3701 in_omp_workshare
= true;
3705 case EXEC_OMP_CRITICAL
:
3706 case EXEC_OMP_DISTRIBUTE
:
3707 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO
:
3708 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD
:
3709 case EXEC_OMP_DISTRIBUTE_SIMD
:
3711 case EXEC_OMP_DO_SIMD
:
3712 case EXEC_OMP_ORDERED
:
3713 case EXEC_OMP_SECTIONS
:
3714 case EXEC_OMP_SINGLE
:
3715 case EXEC_OMP_END_SINGLE
:
3717 case EXEC_OMP_TASKLOOP
:
3718 case EXEC_OMP_TASKLOOP_SIMD
:
3719 case EXEC_OMP_TARGET
:
3720 case EXEC_OMP_TARGET_DATA
:
3721 case EXEC_OMP_TARGET_ENTER_DATA
:
3722 case EXEC_OMP_TARGET_EXIT_DATA
:
3723 case EXEC_OMP_TARGET_PARALLEL
:
3724 case EXEC_OMP_TARGET_PARALLEL_DO
:
3725 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD
:
3726 case EXEC_OMP_TARGET_SIMD
:
3727 case EXEC_OMP_TARGET_TEAMS
:
3728 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
:
3729 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
:
3730 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD
:
3731 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
:
3732 case EXEC_OMP_TARGET_UPDATE
:
3734 case EXEC_OMP_TEAMS
:
3735 case EXEC_OMP_TEAMS_DISTRIBUTE
:
3736 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO
:
3737 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD
:
3738 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD
:
3740 /* Come to this label only from the
3741 EXEC_OMP_PARALLEL_* cases above. */
3745 if (co
->ext
.omp_clauses
)
3747 gfc_omp_namelist
*n
;
3748 static int list_types
[]
3749 = { OMP_LIST_ALIGNED
, OMP_LIST_LINEAR
, OMP_LIST_DEPEND
,
3750 OMP_LIST_MAP
, OMP_LIST_TO
, OMP_LIST_FROM
};
3752 WALK_SUBEXPR (co
->ext
.omp_clauses
->if_expr
);
3753 WALK_SUBEXPR (co
->ext
.omp_clauses
->final_expr
);
3754 WALK_SUBEXPR (co
->ext
.omp_clauses
->num_threads
);
3755 WALK_SUBEXPR (co
->ext
.omp_clauses
->chunk_size
);
3756 WALK_SUBEXPR (co
->ext
.omp_clauses
->safelen_expr
);
3757 WALK_SUBEXPR (co
->ext
.omp_clauses
->simdlen_expr
);
3758 WALK_SUBEXPR (co
->ext
.omp_clauses
->num_teams
);
3759 WALK_SUBEXPR (co
->ext
.omp_clauses
->device
);
3760 WALK_SUBEXPR (co
->ext
.omp_clauses
->thread_limit
);
3761 WALK_SUBEXPR (co
->ext
.omp_clauses
->dist_chunk_size
);
3762 WALK_SUBEXPR (co
->ext
.omp_clauses
->grainsize
);
3763 WALK_SUBEXPR (co
->ext
.omp_clauses
->hint
);
3764 WALK_SUBEXPR (co
->ext
.omp_clauses
->num_tasks
);
3765 WALK_SUBEXPR (co
->ext
.omp_clauses
->priority
);
3766 for (idx
= 0; idx
< OMP_IF_LAST
; idx
++)
3767 WALK_SUBEXPR (co
->ext
.omp_clauses
->if_exprs
[idx
]);
3769 idx
< sizeof (list_types
) / sizeof (list_types
[0]);
3771 for (n
= co
->ext
.omp_clauses
->lists
[list_types
[idx
]];
3773 WALK_SUBEXPR (n
->expr
);
3780 WALK_SUBEXPR (co
->expr1
);
3781 WALK_SUBEXPR (co
->expr2
);
3782 WALK_SUBEXPR (co
->expr3
);
3783 WALK_SUBEXPR (co
->expr4
);
3784 for (b
= co
->block
; b
; b
= b
->block
)
3786 WALK_SUBEXPR (b
->expr1
);
3787 WALK_SUBEXPR (b
->expr2
);
3788 WALK_SUBCODE (b
->next
);
3791 if (co
->op
== EXEC_FORALL
)
3794 if (co
->op
== EXEC_DO
)
3797 in_omp_workshare
= saved_in_omp_workshare
;
3798 in_where
= saved_in_where
;