diff options
author | tkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-01 19:40:25 +0000 |
---|---|---|
committer | tkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-01 19:40:25 +0000 |
commit | ecce8d80d087429a803348721f03e5cf77f49412 (patch) | |
tree | 1c1de7aad1210ad2ec5aa0340fad68d471836ad3 /gcc/fortran/frontend-passes.c | |
parent | c66706ff62aab969f25b474f10e094b345aa6a3d (diff) | |
download | gcc-ecce8d80d087429a803348721f03e5cf77f49412.tar.gz |
2012-02-01 Thomas König <tkoenig@gcc.gnu.org>
PR fortran/51958
* frontend-passes.c (convert_elseif): New function.
(optimize_namespace): Call it.
2012-02-01 Thomas König <tkoenig@gcc.gnu.org>
PR fortran/51958
* gfortran.dg/function_optimize_10.f90: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183812 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/frontend-passes.c')
-rw-r--r-- | gcc/fortran/frontend-passes.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index 20f76ebfbe6..a86982fa3a7 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -510,6 +510,69 @@ convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, return 0; } +/* Code callback function for converting + if (a) then + ... + else if (b) then + end if + + into + if (a) then + else + if (b) then + end if + end if + + because otherwise common function elimination would place the BLOCKs + into the wrong place. */ + +static int +convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + gfc_code *co = *c; + gfc_code *c_if1, *c_if2, *else_stmt; + + if (co->op != EXEC_IF) + return 0; + + /* This loop starts out with the first ELSE statement. */ + else_stmt = co->block->block; + + while (else_stmt != NULL) + { + gfc_code *next_else; + + /* If there is no condition, we're done. */ + if (else_stmt->expr1 == NULL) + break; + + next_else = else_stmt->block; + + /* Generate the new IF statement. */ + c_if2 = XCNEW (gfc_code); + c_if2->op = EXEC_IF; + c_if2->expr1 = else_stmt->expr1; + c_if2->next = else_stmt->next; + c_if2->loc = else_stmt->loc; + c_if2->block = next_else; + + /* ... plus the one to chain it to. */ + c_if1 = XCNEW (gfc_code); + c_if1->op = EXEC_IF; + c_if1->block = c_if2; + c_if1->loc = else_stmt->loc; + + /* Insert the new IF after the ELSE. */ + else_stmt->expr1 = NULL; + else_stmt->next = c_if1; + else_stmt->block = NULL; + + else_stmt = next_else; + } + /* Don't walk subtrees. */ + return 0; +} /* Optimize a namespace, including all contained namespaces. */ static void @@ -521,6 +584,7 @@ optimize_namespace (gfc_namespace *ns) in_omp_workshare = false; gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL); + gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL); gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL); gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL); |