Commit fa11ae6c by Thomas Koenig

re PR fortran/50327 (Front-end optimization generates wrong code for BLAS's srotmg)

2011-09-11  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/50327
	* frontend-passes.c (dummy_expr_callback):  New function.
	(convert_do_while):  New function.
	(optimize_namespace):  Call code walker to convert do while loops.

2011-09-11  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/50327
	* gfortran.dg/do_while_1.f90:  New test.

From-SVN: r178768
parent 9795c594
2011-09-11 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/50327
* frontend-passes.c (dummy_expr_callback): New function.
(convert_do_while): New function.
(optimize_namespace): Call code walker to convert do while loops.
2011-09-11 Janus Weil <janus@gcc.gnu.org> 2011-09-11 Janus Weil <janus@gcc.gnu.org>
PR fortran/35831 PR fortran/35831
......
...@@ -407,6 +407,85 @@ cfe_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, ...@@ -407,6 +407,85 @@ cfe_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
return 0; return 0;
} }
/* Dummy function for expression call back, for use when we
really don't want to do any walking. */
static int
dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
void *data ATTRIBUTE_UNUSED)
{
*walk_subtrees = 0;
return 0;
}
/* Code callback function for converting
do while(a)
end do
into the equivalent
do
if (.not. a) exit
end do
This is because common function elimination would otherwise place the
temporary variables outside the loop. */
static int
convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
gfc_code *co = *c;
gfc_code *c_if1, *c_if2, *c_exit;
gfc_code *loopblock;
gfc_expr *e_not, *e_cond;
if (co->op != EXEC_DO_WHILE)
return 0;
if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
return 0;
e_cond = co->expr1;
/* Generate the condition of the if statement, which is .not. the original
statement. */
e_not = gfc_get_expr ();
e_not->ts = e_cond->ts;
e_not->where = e_cond->where;
e_not->expr_type = EXPR_OP;
e_not->value.op.op = INTRINSIC_NOT;
e_not->value.op.op1 = e_cond;
/* Generate the EXIT statement. */
c_exit = XCNEW (gfc_code);
c_exit->op = EXEC_EXIT;
c_exit->ext.which_construct = co;
c_exit->loc = co->loc;
/* Generate the IF statement. */
c_if2 = XCNEW (gfc_code);
c_if2->op = EXEC_IF;
c_if2->expr1 = e_not;
c_if2->next = c_exit;
c_if2->loc = co->loc;
/* ... 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 = co->loc;
/* Make the DO WHILE loop into a DO block by replacing the condition
with a true constant. */
co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
/* Hang the generated if statement into the loop body. */
loopblock = co->block->next;
co->block->next = c_if1;
c_if1->next = loopblock;
return 0;
}
/* Optimize a namespace, including all contained namespaces. */ /* Optimize a namespace, including all contained namespaces. */
static void static void
...@@ -415,6 +494,7 @@ optimize_namespace (gfc_namespace *ns) ...@@ -415,6 +494,7 @@ optimize_namespace (gfc_namespace *ns)
current_ns = ns; current_ns = ns;
gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL); gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL); gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
......
2011-09-11 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/50327
* gfortran.dg/do_while_1.f90: New test.
2011-09-11 Janus Weil <janus@gcc.gnu.org> 2011-09-11 Janus Weil <janus@gcc.gnu.org>
PR fortran/35831 PR fortran/35831
......
! { dg-do run }
! PR 50327 - this used to cause an endless loop because
! of wrong fron-end optimization.
program main
real :: tmp
tmp = 0.
do while (abs(tmp) < 10. .and. abs(tmp) < 20.)
tmp = tmp + 1.
end do
end program main
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment