[PATCH] Improved loop lowering for C++

Roger Sayle roger@eyesopen.com
Sun Dec 5 23:42:00 GMT 2004


This is the next installment towards resolving PR12454, by improving
the way we lower C++ loops to gimple, the same way we recently fixed
C loops: http://gcc.gnu.org/ml/gcc-patches/2004-12/msg00326.html
The improvements to the .generic dumps for C++ are identical to the
C improvements described in the above post.

This patch shuffles around the structure of gimplify_c_loop such
that it's similar to c-typeck.c's c_finish_loop.  The one thing worse
than duplication, is divergence that complicates fixing both copies.

I also took the opportunity to clean up a minor inefficiency in
append_to_statement_list; we end up calling the internal function
append_to_statement_list_1 with a Boolean flag indicating whether
it should return immediately.  As this function is only called in
two places, I tweaked both callers to only call it when required.
By removing the side_effects argument, these callers also become
terminal sibling calls.  This helps minimize performance differences
between C's use of c_finish_loop and C++'s use of gimplify_c_loop.

The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested with
a top-level "make -k check" with no new failures.

Ok for mainline?



2004-12-05  Roger Sayle  <roger@eyesopen.com>

	* c-gimplify.c (gimplify_c_loop): Improve initial implementations
	for loops whose conditions are known at compile-time.
	* gimplify.c (append_to_statement_list_1): Remove side_effects
	parameter, this function should never be called if its false.
	(append_to_statement_list): Only call append_to_statement_list_1
	if t is non-NULL tree with side-effects.
	(append_to_statement_list_force):  Likewise, if t is not NULL.


Index: c-gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-gimplify.c,v
retrieving revision 2.23
diff -c -3 -p -r2.23 c-gimplify.c
*** c-gimplify.c	7 Sep 2004 10:18:58 -0000	2.23
--- c-gimplify.c	5 Dec 2004 20:06:53 -0000
*************** gimplify_c_loop (tree cond, tree body, t
*** 338,347 ****
    location_t stmt_locus;

    stmt_locus = input_location;

!   /* Detect do { ... } while (0) and don't generate loop construct.  */
!   if (!cond_is_first && cond && integer_zerop (cond))
!     top = cond = NULL;
    else
      {
        /* If we use a LOOP_EXPR here, we have to feed the whole thing
--- 338,360 ----
    location_t stmt_locus;

    stmt_locus = input_location;
+   stmt_list = NULL_TREE;
+   entry = NULL_TREE;

!   break_block = begin_bc_block (bc_break);
!   cont_block = begin_bc_block (bc_continue);
!
!   /* If condition is zero don't generate a loop construct.  */
!   if (cond && integer_zerop (cond))
!     {
!       top = NULL_TREE;
!       exit = NULL_TREE;
!       if (cond_is_first)
! 	{
! 	  t = build_bc_goto (bc_break);
! 	  append_to_statement_list (t, &stmt_list);
! 	}
!     }
    else
      {
        /* If we use a LOOP_EXPR here, we have to feed the whole thing
*************** gimplify_c_loop (tree cond, tree body, t
*** 349,393 ****
  	 have to gimplify the loop body NOW so that we can resolve
  	 break/continue stmts, seems easier to just expand to gotos.  */
        top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-     }
-
-   break_block = begin_bc_block (bc_break);

-   if (top)
-     {
        /* If we have an exit condition, then we build an IF with gotos either
  	 out of the loop, or to the top of it.  If there's no exit condition,
  	 then we just build a jump back to the top.  */
        exit = build_and_jump (&LABEL_EXPR_LABEL (top));
!       if (cond)
  	{
  	  t = build_bc_goto (bc_break);
  	  exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
  	  exit = fold (exit);
  	  gimplify_stmt (&exit);
  	}
      }
-   else
-     exit = NULL_TREE;
-
-   cont_block = begin_bc_block (bc_continue);

    gimplify_stmt (&body);
    gimplify_stmt (&incr);

    body = finish_bc_block (cont_block, body);

-   stmt_list = NULL;
-
-   if (cond_is_first && cond)
-     {
-       entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-       t = build_and_jump (&LABEL_EXPR_LABEL (entry));
-       append_to_statement_list (t, &stmt_list);
-     }
-   else
-     entry = NULL_TREE;
-
    append_to_statement_list (top, &stmt_list);
    append_to_statement_list (body, &stmt_list);
    append_to_statement_list (incr, &stmt_list);
--- 362,398 ----
  	 have to gimplify the loop body NOW so that we can resolve
  	 break/continue stmts, seems easier to just expand to gotos.  */
        top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);

        /* If we have an exit condition, then we build an IF with gotos either
  	 out of the loop, or to the top of it.  If there's no exit condition,
  	 then we just build a jump back to the top.  */
        exit = build_and_jump (&LABEL_EXPR_LABEL (top));
!       if (cond && !integer_nonzerop (cond))
  	{
  	  t = build_bc_goto (bc_break);
  	  exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
  	  exit = fold (exit);
  	  gimplify_stmt (&exit);
+
+ 	  if (cond_is_first)
+ 	    {
+ 	      if (incr)
+ 		{
+ 		  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+ 		  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
+ 		}
+ 	      else
+ 		t = build_bc_goto (bc_continue);
+ 	      append_to_statement_list (t, &stmt_list);
+ 	    }
  	}
      }

    gimplify_stmt (&body);
    gimplify_stmt (&incr);

    body = finish_bc_block (cont_block, body);

    append_to_statement_list (top, &stmt_list);
    append_to_statement_list (body, &stmt_list);
    append_to_statement_list (incr, &stmt_list);
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.90
diff -c -3 -p -r2.90 gimplify.c
*** gimplify.c	4 Dec 2004 14:11:44 -0000	2.90
--- gimplify.c	5 Dec 2004 20:06:53 -0000
*************** gimple_pop_condition (tree *pre_p)
*** 214,230 ****
      }
  }

! /* A subroutine of append_to_statement_list{,_force}.  */

  static void
! append_to_statement_list_1 (tree t, tree *list_p, bool side_effects)
  {
    tree list = *list_p;
    tree_stmt_iterator i;

-   if (!side_effects)
-     return;
-
    if (!list)
      {
        if (t && TREE_CODE (t) == STATEMENT_LIST)
--- 214,227 ----
      }
  }

! /* A subroutine of append_to_statement_list{,_force}.  T is not NULL.  */

  static void
! append_to_statement_list_1 (tree t, tree *list_p)
  {
    tree list = *list_p;
    tree_stmt_iterator i;

    if (!list)
      {
        if (t && TREE_CODE (t) == STATEMENT_LIST)
*************** append_to_statement_list_1 (tree t, tree
*** 245,251 ****
  void
  append_to_statement_list (tree t, tree *list_p)
  {
!   append_to_statement_list_1 (t, list_p, t ? TREE_SIDE_EFFECTS (t) : false);
  }

  /* Similar, but the statement is always added, regardless of side effects.  */
--- 242,249 ----
  void
  append_to_statement_list (tree t, tree *list_p)
  {
!   if (t && TREE_SIDE_EFFECTS (t))
!     append_to_statement_list_1 (t, list_p);
  }

  /* Similar, but the statement is always added, regardless of side effects.  */
*************** append_to_statement_list (tree t, tree *
*** 253,259 ****
  void
  append_to_statement_list_force (tree t, tree *list_p)
  {
!   append_to_statement_list_1 (t, list_p, t != NULL);
  }

  /* Both gimplify the statement T and append it to LIST_P.  */
--- 251,258 ----
  void
  append_to_statement_list_force (tree t, tree *list_p)
  {
!   if (t != NULL_TREE)
!     append_to_statement_list_1 (t, list_p);
  }

  /* Both gimplify the statement T and append it to LIST_P.  */


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833



More information about the Gcc-patches mailing list