===================================================================
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
static void strip_function_call (gfc_expr *);
static void optimize_namespace (gfc_namespace *);
static void optimize_assignment (gfc_code *);
+static void optimize_forall_header (gfc_code *);
static bool optimize_op (gfc_expr *);
static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op);
static bool optimize_trim (gfc_expr *);
@@ -145,6 +146,10 @@ optimize_code (gfc_code **c, int *walk_subtrees AT
if (op == EXEC_ASSIGN)
optimize_assignment (*c);
+
+ if (op == EXEC_DO_CONCURRENT || op == EXEC_FORALL)
+ optimize_forall_header (*c);
+
return 0;
}
@@ -980,6 +985,70 @@ remove_trim (gfc_expr *rhs)
return ret;
}
+/* Callback function to check if there is a reference
+ to one of the concurrent iterators in the expression. */
+
+static int
+concurrent_iterator_check (gfc_expr **e,
+ int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
+{
+ gfc_symtree *se;
+ gfc_forall_iterator *fa;
+
+ if ((*e)->expr_type != EXPR_VARIABLE)
+ return 0;
+
+ se = (*e)->symtree;
+
+ if (se == NULL)
+ return 0;
+
+ for (fa = (*current_code)->ext.forall_iterator; fa;
+ fa = fa->next)
+ {
+ if (se == fa->var->symtree)
+ return 1;
+ }
+ return 0;
+}
+
+/* Callback helper function for optimizing the header of
+ FORALL and DO CONCURRENT. */
+
+static int
+forall_header_varmove (gfc_expr **e,
+ int *walk_subtrees,
+ void *data ATTRIBUTE_UNUSED)
+{
+ if ((*e)->expr_type == EXPR_VARIABLE && (*e)->ref == NULL)
+ return 0;
+
+ if ((*e)->expr_type == EXPR_CONSTANT)
+ return 0;
+
+ if (gfc_expr_walker (e, concurrent_iterator_check, NULL) == 0)
+ {
+ gfc_expr *ex;
+
+ ex = create_var (*e);
+ (*e) = ex;
+ *walk_subtrees = 1;
+ }
+ return 0;
+}
+
+/* Optimization for FORALL and DO CONCURRENT masks. */
+
+static void
+optimize_forall_header (gfc_code *c)
+{
+ if (c->expr1 == NULL)
+ return;
+
+ gfc_expr_walker (&(c->expr1), forall_header_varmove, NULL);
+}
+
/* Optimizations for an assignment. */
static void