summaryrefslogtreecommitdiff
path: root/gcc/fortran/frontend-passes.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-05-02 14:43:35 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-05-02 14:43:35 +0000
commit34efdaf078b01a7387007c4e6bde6db86384c4b7 (patch)
treed503eaf41d085669d1481bb46ec038bc866fece6 /gcc/fortran/frontend-passes.c
parentf733cf303bcdc952c92b81dd62199a40a1f555ec (diff)
downloadgcc-tarball-master.tar.gz
gcc-7.1.0gcc-7.1.0
Diffstat (limited to 'gcc/fortran/frontend-passes.c')
-rw-r--r--gcc/fortran/frontend-passes.c185
1 files changed, 144 insertions, 41 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 1655de2c9f..459967d5c3 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -1,5 +1,5 @@
/* Pass manager for Fortran front end.
- Copyright (C) 2010-2016 Free Software Foundation, Inc.
+ Copyright (C) 2010-2017 Free Software Foundation, Inc.
Contributed by Thomas König.
This file is part of GCC.
@@ -45,9 +45,13 @@ static void realloc_strings (gfc_namespace *);
static gfc_expr *create_var (gfc_expr *, const char *vname=NULL);
static int inline_matmul_assign (gfc_code **, int *, void *);
static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
- locus *, gfc_namespace *,
+ locus *, gfc_namespace *,
char *vname=NULL);
+#ifdef CHECKING_P
+static void check_locus (gfc_namespace *);
+#endif
+
/* How deep we are inside an argument list. */
static int count_arglist;
@@ -108,7 +112,7 @@ static int var_num = 1;
enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T };
-/* Keep track of the number of expressions we have inserted so far
+/* Keep track of the number of expressions we have inserted so far
using create_var. */
int n_vars;
@@ -127,6 +131,10 @@ gfc_run_passes (gfc_namespace *ns)
doloop_list.release ();
int w, e;
+#ifdef CHECKING_P
+ check_locus (ns);
+#endif
+
if (flag_frontend_optimize)
{
optimize_namespace (ns);
@@ -145,9 +153,56 @@ gfc_run_passes (gfc_namespace *ns)
realloc_strings (ns);
}
+#ifdef CHECKING_P
+
+/* Callback function: Warn if there is no location information in a
+ statement. */
+
+static int
+check_locus_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
+{
+ current_code = c;
+ if (c && *c && (((*c)->loc.nextc == NULL) || ((*c)->loc.lb == NULL)))
+ gfc_warning_internal (0, "No location in statement");
+
+ return 0;
+}
+
+
+/* Callback function: Warn if there is no location information in an
+ expression. */
+
+static int
+check_locus_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
+{
+
+ if (e && *e && (((*e)->where.nextc == NULL || (*e)->where.lb == NULL)))
+ gfc_warning_internal (0, "No location in expression near %L",
+ &((*current_code)->loc));
+ return 0;
+}
+
+/* Run check for missing location information. */
+
+static void
+check_locus (gfc_namespace *ns)
+{
+ gfc_code_walker (&ns->code, check_locus_code, check_locus_expr, NULL);
+
+ for (ns = ns->contained; ns; ns = ns->sibling)
+ {
+ if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
+ check_locus (ns);
+ }
+}
+
+#endif
+
/* Callback for each gfc_code node invoked from check_realloc_strings.
For an allocatable LHS string which also appears as a variable on
- the RHS, replace
+ the RHS, replace
a = a(x:y)
@@ -164,19 +219,34 @@ realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
gfc_expr *expr1, *expr2;
gfc_code *co = *c;
gfc_expr *n;
+ gfc_ref *ref;
+ bool found_substr;
if (co->op != EXEC_ASSIGN)
return 0;
expr1 = co->expr1;
if (expr1->ts.type != BT_CHARACTER || expr1->rank != 0
- || !expr1->symtree->n.sym->attr.allocatable)
+ || !gfc_expr_attr(expr1).allocatable
+ || !expr1->ts.deferred)
return 0;
expr2 = gfc_discard_nops (co->expr2);
if (expr2->expr_type != EXPR_VARIABLE)
return 0;
+ found_substr = false;
+ for (ref = expr2->ref; ref; ref = ref->next)
+ {
+ if (ref->type == REF_SUBSTRING)
+ {
+ found_substr = true;
+ break;
+ }
+ }
+ if (!found_substr)
+ return 0;
+
if (!gfc_check_dependency (expr1, expr2, true))
return 0;
@@ -190,7 +260,7 @@ realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
current_code = c;
inserted_block = NULL;
changed_statement = NULL;
- n = create_var (expr2, "trim");
+ n = create_var (expr2, "realloc_string");
co->expr2 = n;
return 0;
}
@@ -434,7 +504,7 @@ cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
return 0;
/* We don't do character functions with unknown charlens. */
- if ((*e)->ts.type == BT_CHARACTER
+ if ((*e)->ts.type == BT_CHARACTER
&& ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
|| (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
return 0;
@@ -458,7 +528,7 @@ cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
return 0;
-
+
/* Skip the test for pure functions if -faggressive-function-elimination
is specified. */
if ((*e)->value.function.esym)
@@ -540,7 +610,7 @@ constant_string_length (gfc_expr *e)
{
res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
&e->where);
-
+
mpz_add_ui (res->value.integer, value, 1);
mpz_clear (value);
return res;
@@ -580,7 +650,7 @@ insert_block ()
/* If the statement has a label, make sure it is transferred to
the newly created block. */
- if ((*current_code)->here)
+ if ((*current_code)->here)
{
inserted_block->here = (*current_code)->here;
(*current_code)->here = NULL;
@@ -653,12 +723,12 @@ create_var (gfc_expr * e, const char *vname)
for (i=0; i<e->rank; i++)
{
gfc_expr *p, *q;
-
+
p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
&(e->where));
mpz_set_si (p->value.integer, 1);
symbol->as->lower[i] = p;
-
+
q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
&(e->where));
mpz_set (q->value.integer, e->shape[i]);
@@ -732,10 +802,12 @@ do_warn_function_elimination (gfc_expr *e)
if (e->expr_type != EXPR_FUNCTION)
return;
if (e->value.function.esym)
- gfc_warning (0, "Removing call to function %qs at %L",
+ gfc_warning (OPT_Wfunction_elimination,
+ "Removing call to function %qs at %L",
e->value.function.esym->name, &(e->where));
else if (e->value.function.isym)
- gfc_warning (0, "Removing call to function %qs at %L",
+ gfc_warning (OPT_Wfunction_elimination,
+ "Removing call to function %qs at %L",
e->value.function.isym->name, &(e->where));
}
/* Callback function for the code walker for doing common function
@@ -828,7 +900,7 @@ cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
*walk_subtrees = 0;
return 0;
}
-
+
return 0;
}
@@ -1061,6 +1133,9 @@ optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
{
gfc_expr *e;
+ if (!*rhs)
+ return false;
+
e = *rhs;
if (e->expr_type == EXPR_OP)
{
@@ -1093,8 +1168,8 @@ optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
}
}
else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
- && ! (e->value.function.esym
- && (e->value.function.esym->attr.elemental
+ && ! (e->value.function.esym
+ && (e->value.function.esym->attr.elemental
|| e->value.function.esym->attr.allocatable
|| e->value.function.esym->ts.type != c->expr1->ts.type
|| e->value.function.esym->ts.kind != c->expr1->ts.kind))
@@ -1120,7 +1195,7 @@ optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
new_expr = gfc_copy_expr (c->expr1);
c->expr2 = e;
*rhs = new_expr;
-
+
return true;
}
@@ -1137,6 +1212,8 @@ remove_trim (gfc_expr *rhs)
bool ret;
ret = false;
+ if (!rhs)
+ return ret;
/* Check for a // b // trim(c). Looping is probably not
necessary because the parser usually generates
@@ -1274,6 +1351,9 @@ combine_array_constructor (gfc_expr *e)
op1 = e->value.op.op1;
op2 = e->value.op.op2;
+ if (!op1 || !op2)
+ return false;
+
if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
scalar_first = false;
else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
@@ -1301,7 +1381,7 @@ combine_array_constructor (gfc_expr *e)
new_expr->ts = e->ts;
new_expr->expr_type = EXPR_OP;
new_expr->rank = c->expr->rank;
- new_expr->where = c->where;
+ new_expr->where = c->expr->where;
new_expr->value.op.op = e->value.op.op;
if (scalar_first)
@@ -1358,7 +1438,7 @@ optimize_power (gfc_expr *e)
"_internal_iand", e->where, 2, op2,
gfc_get_int_expr (e->ts.kind,
&e->where, 1));
-
+
ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
"_internal_ishft", e->where, 2, iand,
gfc_get_int_expr (e->ts.kind,
@@ -1458,7 +1538,7 @@ optimize_op (gfc_expr *e)
case INTRINSIC_LT:
changed = optimize_comparison (e, op);
- /* Fall through */
+ gcc_fallthrough ();
/* Look at array constructors. */
case INTRINSIC_PLUS:
case INTRINSIC_MINUS:
@@ -1468,7 +1548,6 @@ optimize_op (gfc_expr *e)
case INTRINSIC_POWER:
return optimize_power (e);
- break;
default:
break;
@@ -1693,7 +1772,7 @@ optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
case INTRINSIC_EQ:
result = eq == 0;
break;
-
+
case INTRINSIC_GE:
result = eq >= 0;
break;
@@ -1713,7 +1792,7 @@ optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
case INTRINSIC_LT:
result = eq < 0;
break;
-
+
default:
gfc_internal_error ("illegal OP in optimize_comparison");
break;
@@ -1832,7 +1911,7 @@ optimize_minmaxloc (gfc_expr **e)
strcpy (name, fn->value.function.name);
p = strstr (name, "loc0");
p[3] = '1';
- fn->value.function.name = gfc_get_string (name);
+ fn->value.function.name = gfc_get_string ("%s", name);
if (fn->value.function.actual->next)
{
a = fn->value.function.actual->next;
@@ -1897,12 +1976,12 @@ doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
FOR_EACH_VEC_ELT (doloop_list, i, cl)
{
gfc_symbol *do_sym;
-
+
if (cl == NULL)
break;
do_sym = cl->ext.iterator->var->symtree->n.sym;
-
+
if (a->expr && a->expr->symtree
&& a->expr->symtree->n.sym == do_sym)
{
@@ -1974,7 +2053,7 @@ do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
break;
do_sym = dl->ext.iterator->var->symtree->n.sym;
-
+
if (a->expr && a->expr->symtree
&& a->expr->symtree->n.sym == do_sym)
{
@@ -2205,7 +2284,7 @@ runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
/* Handle matrix reallocation. Caller is responsible to insert into
the code tree.
- For the two-dimensional case, build
+ For the two-dimensional case, build
if (allocated(c)) then
if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
@@ -2298,7 +2377,7 @@ matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
/* We need two identical allocate statements in two
branches of the IF statement. */
-
+
allocate1 = XCNEW (gfc_code);
allocate1->op = EXEC_ALLOCATE;
allocate1->ext.alloc.list = gfc_get_alloc ();
@@ -2321,7 +2400,7 @@ matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
deallocate->next = allocate1;
deallocate->loc = c->where;
-
+
if_size_2 = XCNEW (gfc_code);
if_size_2->op = EXEC_IF;
if_size_2->expr1 = cond;
@@ -2601,7 +2680,7 @@ scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
/* Loop over the indices. For each index, create the expression
index * stride + lbound(e, dim). */
-
+
i_index = 0;
for (i=0; i < ar->dimen; i++)
{
@@ -2611,9 +2690,9 @@ scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
{
gfc_expr *lbound, *nindex;
gfc_expr *loopvar;
-
- loopvar = gfc_copy_expr (index[i_index]);
-
+
+ loopvar = gfc_copy_expr (index[i_index]);
+
if (ar->stride[i])
{
gfc_expr *tmp;
@@ -2631,7 +2710,7 @@ scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
}
else
nindex = loopvar;
-
+
/* Calculate the lower bound of the expression. */
if (ar->start[i])
{
@@ -2698,12 +2777,12 @@ scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
i + 1);
gfc_free_expr (lbound_e);
}
-
+
ar->dimen_type[i] = DIMEN_ELEMENT;
gfc_free_expr (ar->start[i]);
ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
-
+
gfc_free_expr (ar->end[i]);
ar->end[i] = NULL;
gfc_free_expr (ar->stride[i]);
@@ -2802,7 +2881,7 @@ check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
end do
end do
END BLOCK
-
+
*/
static int
@@ -2835,6 +2914,11 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
if (in_where)
return 0;
+ /* The BLOCKS generated for the temporary variables and FORALL don't
+ mix. */
+ if (forall_level > 0)
+ return 0;
+
/* For now don't do anything in OpenMP workshare, it confuses
its translation, which expects only the allowed statements in there.
We should figure out how to parallelize this eventually. */
@@ -3234,7 +3318,7 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
matrix_a->where, 1, ascalar);
if (conjg_b)
- bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
+ bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
matrix_b->where, 1, bscalar);
/* First loop comes after the zero assignment. */
@@ -3326,6 +3410,7 @@ gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
/* Fall through to the variable case in order to walk the
reference. */
+ gcc_fallthrough ();
case EXPR_SUBSTRING:
case EXPR_VARIABLE:
@@ -3512,6 +3597,8 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
WALK_SUBEXPR (co->ext.open->asynchronous);
WALK_SUBEXPR (co->ext.open->id);
WALK_SUBEXPR (co->ext.open->newunit);
+ WALK_SUBEXPR (co->ext.open->share);
+ WALK_SUBEXPR (co->ext.open->cc);
break;
case EXEC_CLOSE:
@@ -3607,7 +3694,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
/* This goto serves as a shortcut to avoid code
duplication or a larger if or switch statement. */
goto check_omp_clauses;
-
+
case EXEC_OMP_WORKSHARE:
case EXEC_OMP_PARALLEL_WORKSHARE:
@@ -3615,18 +3702,28 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
/* Fall through */
+ case EXEC_OMP_CRITICAL:
case EXEC_OMP_DISTRIBUTE:
case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
case EXEC_OMP_DISTRIBUTE_SIMD:
case EXEC_OMP_DO:
case EXEC_OMP_DO_SIMD:
+ case EXEC_OMP_ORDERED:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
case EXEC_OMP_END_SINGLE:
case EXEC_OMP_SIMD:
+ case EXEC_OMP_TASKLOOP:
+ case EXEC_OMP_TASKLOOP_SIMD:
case EXEC_OMP_TARGET:
case EXEC_OMP_TARGET_DATA:
+ case EXEC_OMP_TARGET_ENTER_DATA:
+ case EXEC_OMP_TARGET_EXIT_DATA:
+ case EXEC_OMP_TARGET_PARALLEL:
+ case EXEC_OMP_TARGET_PARALLEL_DO:
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TARGET_SIMD:
case EXEC_OMP_TARGET_TEAMS:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
@@ -3662,6 +3759,12 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
WALK_SUBEXPR (co->ext.omp_clauses->device);
WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
+ WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
+ WALK_SUBEXPR (co->ext.omp_clauses->hint);
+ WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
+ WALK_SUBEXPR (co->ext.omp_clauses->priority);
+ for (idx = 0; idx < OMP_IF_LAST; idx++)
+ WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
for (idx = 0;
idx < sizeof (list_types) / sizeof (list_types[0]);
idx++)