===================================================================
@@ -25,19 +25,35 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "dependency.h"
+
+/* A struct for holding the pass-specific functions. */
+typedef struct process_functions
+{
+ void (*process_assignment) (gfc_code *);
+ void (*process_expr) (gfc_expr *);
+ void (*process_actual_arglist) (gfc_actual_arglist *);
+ void (*process_pointer_assign) (gfc_code *);
+} process_functions;
+
/* Forward declarations. */
static void strip_function_call (gfc_expr *);
-static void optimize_namespace (gfc_namespace *);
+static void process_namespace (gfc_namespace *, process_functions *);
static void optimize_assignment (gfc_code *);
static void optimize_expr_0 (gfc_expr *);
static bool optimize_expr (gfc_expr *);
static bool optimize_op (gfc_expr *);
static bool optimize_equality (gfc_expr *, bool);
-static void optimize_code (gfc_code *);
-static void optimize_code_node (gfc_code *);
+static void process_code (gfc_code *, process_functions *);
+static void process_code_node (gfc_code *, process_functions *);
static void optimize_actual_arglist (gfc_actual_arglist *);
+struct process_functions optimize_pass =
+ { optimize_assignment,
+ optimize_expr_0,
+ optimize_actual_arglist,
+ NULL };
+
/* Entry point - run all passes for a namespace. So far, only an
optimization pass is run. */
@@ -45,32 +61,32 @@ void
gfc_run_passes (gfc_namespace *ns)
{
if (optimize)
- optimize_namespace (ns);
+ process_namespace (ns, &optimize_pass);
}
/* Optimize a namespace, including all contained namespaces. */
static void
-optimize_namespace (gfc_namespace *ns)
+process_namespace (gfc_namespace *ns, process_functions *pass)
{
- optimize_code (ns->code);
+ process_code (ns->code, pass);
for (ns = ns->contained; ns; ns = ns->sibling)
- optimize_namespace (ns);
+ process_namespace (ns, pass);
}
static void
-optimize_code (gfc_code *c)
+process_code (gfc_code *c, process_functions *pass)
{
for (; c; c = c->next)
- optimize_code_node (c);
+ process_code_node (c, pass);
}
-/* Do the optimizations for a code node. */
+/* Handle a code node. */
static void
-optimize_code_node (gfc_code *c)
+process_code_node (gfc_code *c, process_functions *pass)
{
gfc_forall_iterator *fa;
@@ -80,17 +96,17 @@ static void
switch (c->op)
{
case EXEC_ASSIGN:
- optimize_assignment (c);
+ pass->process_assignment (c);
break;
case EXEC_CALL:
case EXEC_ASSIGN_CALL:
case EXEC_CALL_PPC:
- optimize_actual_arglist (c->ext.actual);
+ pass->process_actual_arglist (c->ext.actual);
break;
case EXEC_ARITHMETIC_IF:
- optimize_expr_0 (c->expr1);
+ pass->process_expr (c->expr1);
break;
case EXEC_PAUSE:
@@ -98,50 +114,48 @@ static void
case EXEC_ERROR_STOP:
case EXEC_STOP:
case EXEC_COMPCALL:
- optimize_expr_0 (c->expr1);
+ pass->process_expr (c->expr1);
break;
case EXEC_SYNC_ALL:
case EXEC_SYNC_MEMORY:
case EXEC_SYNC_IMAGES:
- optimize_expr_0 (c->expr2);
+ pass->process_expr (c->expr2);
break;
case EXEC_IF:
d = c->block;
- optimize_expr_0 (d->expr1);
- optimize_code (d->next);
+ pass->process_expr (d->expr1);
+ process_code (d->next, pass);
for (d = d->block; d; d = d->block)
{
- optimize_expr_0 (d->expr1);
-
- optimize_code (d->next);
+ pass->process_expr (d->expr1);
+ process_code (d->next, pass);
}
-
break;
case EXEC_SELECT:
case EXEC_SELECT_TYPE:
d = c->block;
- optimize_expr_0 (c->expr1);
+ pass->process_expr (c->expr1);
for (; d; d = d->block)
- optimize_code (d->next);
+ process_code (d->next, pass);
break;
case EXEC_WHERE:
d = c->block;
- optimize_expr_0 (d->expr1);
- optimize_code (d->next);
+ pass->process_expr (d->expr1);
+ process_code (d->next, pass);
for (d = d->block; d; d = d->block)
{
- optimize_expr_0 (d->expr1);
- optimize_code (d->next);
+ pass->process_expr (d->expr1);
+ process_code (d->next, pass);
}
break;
@@ -149,51 +163,138 @@ static void
for (fa = c->ext.forall_iterator; fa; fa = fa->next)
{
- optimize_expr_0 (fa->start);
- optimize_expr_0 (fa->end);
- optimize_expr_0 (fa->stride);
+ pass->process_expr (fa->start);
+ pass->process_expr (fa->end);
+ pass->process_expr (fa->stride);
}
- if (c->expr1 != NULL)
- optimize_expr_0 (c->expr1);
+ pass->process_expr (c->expr1);
+ process_code (c->block->next, pass);
- optimize_code (c->block->next);
-
break;
case EXEC_CRITICAL:
- optimize_code (c->block->next);
+ process_code (c->block->next, pass);
break;
case EXEC_DO:
- optimize_expr_0 (c->ext.iterator->start);
- optimize_expr_0 (c->ext.iterator->end);
- optimize_expr_0 (c->ext.iterator->step);
- optimize_code (c->block->next);
-
+ pass->process_expr (c->ext.iterator->start);
+ pass->process_expr (c->ext.iterator->end);
+ pass->process_expr (c->ext.iterator->step);
+ process_code (c->block->next, pass);
break;
case EXEC_DO_WHILE:
- optimize_expr_0 (c->expr1);
- optimize_code (c->block->next);
+ pass->process_expr (c->expr1);
+ process_code (c->block->next, pass);
break;
case EXEC_ALLOCATE:
for (a = c->ext.alloc.list; a; a = a->next)
- optimize_expr_0 (a->expr);
+ pass->process_expr (a->expr);
break;
- /* Todo: Some of these may need to be optimized, as well. */
case EXEC_WRITE:
case EXEC_READ:
+ pass->process_expr (c->ext.dt->io_unit);
+ pass->process_expr (c->ext.dt->format_expr);
+ pass->process_expr (c->ext.dt->rec);
+ pass->process_expr (c->ext.dt->advance);
+ pass->process_expr (c->ext.dt->iostat);
+ pass->process_expr (c->ext.dt->size);
+ pass->process_expr (c->ext.dt->iomsg);
+ pass->process_expr (c->ext.dt->id);
+ pass->process_expr (c->ext.dt->pos);
+ pass->process_expr (c->ext.dt->asynchronous);
+ pass->process_expr (c->ext.dt->blank);
+ pass->process_expr (c->ext.dt->decimal);
+ pass->process_expr (c->ext.dt->delim);
+ pass->process_expr (c->ext.dt->pad);
+ pass->process_expr (c->ext.dt->round);
+ pass->process_expr (c->ext.dt->sign);
+ pass->process_expr (c->ext.dt->extra_comma);
+ break;
+
case EXEC_OPEN:
+ pass->process_expr (c->ext.open->unit);
+ pass->process_expr (c->ext.open->file);
+ pass->process_expr (c->ext.open->status);
+ pass->process_expr (c->ext.open->access);
+ pass->process_expr (c->ext.open->form);
+ pass->process_expr (c->ext.open->recl);
+ pass->process_expr (c->ext.open->blank);
+ pass->process_expr (c->ext.open->position);
+ pass->process_expr (c->ext.open->action);
+ pass->process_expr (c->ext.open->delim);
+ pass->process_expr (c->ext.open->pad);
+ pass->process_expr (c->ext.open->iostat);
+ pass->process_expr (c->ext.open->iomsg);
+ pass->process_expr (c->ext.open->convert);
+ pass->process_expr (c->ext.open->decimal);
+ pass->process_expr (c->ext.open->encoding);
+ pass->process_expr (c->ext.open->round);
+ pass->process_expr (c->ext.open->sign);
+ pass->process_expr (c->ext.open->asynchronous);
+ pass->process_expr (c->ext.open->id);
+ pass->process_expr (c->ext.open->newunit);
+ break;
+
case EXEC_INQUIRE:
+ pass->process_expr (c->ext.inquire->unit);
+ pass->process_expr (c->ext.inquire->file);
+ pass->process_expr (c->ext.inquire->iomsg);
+ pass->process_expr (c->ext.inquire->iostat);
+ pass->process_expr (c->ext.inquire->exist);
+ pass->process_expr (c->ext.inquire->opened);
+ pass->process_expr (c->ext.inquire->number);
+ pass->process_expr (c->ext.inquire->named);
+ pass->process_expr (c->ext.inquire->name);
+ pass->process_expr (c->ext.inquire->access);
+ pass->process_expr (c->ext.inquire->sequential);
+ pass->process_expr (c->ext.inquire->direct);
+ pass->process_expr (c->ext.inquire->form);
+ pass->process_expr (c->ext.inquire->formatted);
+ pass->process_expr (c->ext.inquire->unformatted);
+ pass->process_expr (c->ext.inquire->recl);
+ pass->process_expr (c->ext.inquire->nextrec);
+ pass->process_expr (c->ext.inquire->blank);
+ pass->process_expr (c->ext.inquire->position);
+ pass->process_expr (c->ext.inquire->action);
+ pass->process_expr (c->ext.inquire->read);
+ pass->process_expr (c->ext.inquire->write);
+ pass->process_expr (c->ext.inquire->readwrite);
+ pass->process_expr (c->ext.inquire->delim);
+ pass->process_expr (c->ext.inquire->encoding);
+ pass->process_expr (c->ext.inquire->pad);
+ pass->process_expr (c->ext.inquire->iolength);
+ pass->process_expr (c->ext.inquire->convert);
+ pass->process_expr (c->ext.inquire->strm_pos);
+ pass->process_expr (c->ext.inquire->asynchronous);
+ pass->process_expr (c->ext.inquire->decimal);
+ pass->process_expr (c->ext.inquire->pending);
+ pass->process_expr (c->ext.inquire->id);
+ pass->process_expr (c->ext.inquire->sign);
+ pass->process_expr (c->ext.inquire->size);
+ pass->process_expr (c->ext.inquire->round);
+ break;
+
case EXEC_REWIND:
case EXEC_ENDFILE:
case EXEC_BACKSPACE:
case EXEC_CLOSE:
case EXEC_WAIT:
+ pass->process_expr (c->ext.wait->unit);
+ pass->process_expr (c->ext.wait->iostat);
+ pass->process_expr (c->ext.wait->iomsg);
+ pass->process_expr (c->ext.wait->id);
+ break;
+
+ case EXEC_POINTER_ASSIGN:
+ if (pass->process_pointer_assign)
+ pass->process_pointer_assign (c);
+ break;
+
case EXEC_TRANSFER:
case EXEC_FLUSH:
case EXEC_IOLENGTH:
@@ -203,7 +304,6 @@ static void
case EXEC_ENTRY:
case EXEC_INIT_ASSIGN:
case EXEC_LABEL_ASSIGN:
- case EXEC_POINTER_ASSIGN:
case EXEC_GOTO:
case EXEC_CYCLE:
case EXEC_EXIT:
@@ -228,9 +328,11 @@ static void
case EXEC_OMP_END_NOWAIT:
case EXEC_OMP_END_SINGLE:
case EXEC_DEALLOCATE:
+ break;
+
case EXEC_DT_END:
for (d = c->block; d; d = d->block)
- optimize_code (d->next);
+ process_code (d->next, pass);
break;
default:
@@ -338,7 +440,7 @@ optimize_assignment (gfc_code * c)
optimize_binop_array_assignment (c, &rhs, false);
/* If we insert a statement after the current one, the surrounding loop in
- optimize_code will call optimize_assignment on the inserted statement
+ process_code will call optimize_assignment on the inserted statement
anyway, so there is no need to call optimize_assignment again. */
/* All direct optimizations have been done. Now it's time
@@ -382,6 +484,9 @@ strip_function_call (gfc_expr *e)
static void
optimize_expr_0 (gfc_expr * e)
{
+ if (e == NULL)
+ return;
+
if (optimize_expr (e))
gfc_simplify_expr (e, 0);
@@ -389,7 +494,7 @@ optimize_expr_0 (gfc_expr * e)
}
/* Recursive optimization of expressions.
- TODO: Make this handle many more things. */
+ TODO: Make this handle many more things. */
static bool
optimize_expr (gfc_expr *e)