re PR fortran/50327 (Front-end optimization generates wrong code for BLAS's srotmg)
authorThomas Koenig <tkoenig@gcc.gnu.org>
Sun, 11 Sep 2011 20:48:26 +0000 (20:48 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Sun, 11 Sep 2011 20:48:26 +0000 (20:48 +0000)
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

gcc/fortran/ChangeLog
gcc/fortran/frontend-passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/do_while_1.f90 [new file with mode: 0644]

index 96af79e04f87dad829c1258ed499d664f9c902c5..836967d7a4bdc0a15df84858a9d48c3d60463418 100644 (file)
@@ -1,3 +1,10 @@
+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>
 
        PR fortran/35831
index ab8e9e0607b2b44a873d09f6be5fdcbe8f0f7134..16053e0742aef3658383884a01e7eb367cbb099f 100644 (file)
@@ -407,6 +407,85 @@ cfe_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
   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.  */
 
 static void
@@ -415,6 +494,7 @@ optimize_namespace (gfc_namespace *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, optimize_code, optimize_expr, NULL);
 
index 2a5096970bce9798a29e40592feadab77b98e54e..f3cb48705ac4a9ce7157d44692b66b9ad8540706 100644 (file)
@@ -1,3 +1,8 @@
+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>
 
        PR fortran/35831
diff --git a/gcc/testsuite/gfortran.dg/do_while_1.f90 b/gcc/testsuite/gfortran.dg/do_while_1.f90
new file mode 100644 (file)
index 0000000..0a22ff3
--- /dev/null
@@ -0,0 +1,10 @@
+! { 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