This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa] More efficient lowered COND_EXPR representation


Hello,

as noted previously, having the COND_EXPR in the lowered form contain
GOTO_EXPRs is not neccessary (given that we always consider the
whole thing as a single statement) and is a clear waste of memory.
This patch makes the branches contain just the label they jump to.

Bootstrapped & regtested on i686.

Zdenek

	* expr.c (expand_expr_1): Expand COND_EXPR with labels in branches.
	* gimple-low.c (lower_cond_expr): Create COND_EXPRs with labels in
	branches.
	* tree-cfg.c (make_cond_expr_edges, cfg_remove_useless_stmts_bb,
	cleanup_cond_expr_graph, tree_redirect_edge_and_branch_1): Handle a
	new form of COND_EXPRs.
	(tree_verify_flow_info): Check that COND_EXPRs have only labels in
	branches.
	* tree-eh.c (replace_goto_queue_cond_clause,
	maybe_record_in_goto_queue, do_goto_redirection,
	lower_eh_constructs_1): Handle a new form of COND_EXPRs.
	* tree-pretty-print.c (dump_generic_node): Ditto.
	* tree-ssa-dce.c (stmt_useful_p): Remove useless COND_EXPR handling.

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.64
diff -c -3 -p -r1.467.2.64 expr.c
*** expr.c	18 Nov 2003 08:49:32 -0000	1.467.2.64
--- expr.c	21 Nov 2003 21:23:49 -0000
*************** expand_expr_1 (tree exp, rtx target, enu
*** 8401,8406 ****
--- 8401,8431 ----
  	  tree pred = TREE_OPERAND (exp, 0);
  	  tree then_ = TREE_OPERAND (exp, 1);
  	  tree else_ = TREE_OPERAND (exp, 2);
+ 	  tree then_label, else_label;
+ 
+ 	  if (TREE_CODE (then_) == GOTO_EXPR)
+ 	    then_label = GOTO_DESTINATION (then_);
+ 	  else if (TREE_CODE (then_) == LABEL_DECL)
+ 	    then_label = then_;
+ 	  else
+ 	    then_label = NULL_TREE;
+ 	  if (!then_label)
+ 	    ;
+ 	  else if (TREE_CODE (then_label) != LABEL_DECL
+ 		   || NONLOCAL_LABEL (then_label))
+ 	    then_label = NULL_TREE;
+ 
+ 	  if (TREE_CODE (else_) == GOTO_EXPR)
+ 	    else_label = GOTO_DESTINATION (else_);
+ 	  else if (TREE_CODE (else_) == LABEL_DECL)
+ 	    else_label = else_;
+ 	  else
+ 	    else_label = NULL_TREE;
+ 	  if (!else_label)
+ 	    ;
+ 	  else if (TREE_CODE (else_label) != LABEL_DECL
+ 		   || NONLOCAL_LABEL (else_label))
+ 	    else_label = NULL_TREE;
  
  	  /* If we do not have any pending cleanups or stack_levels
  	     to restore, and at least one arm of the COND_EXPR is a
*************** expand_expr_1 (tree exp, rtx target, enu
*** 8409,8457 ****
  	  if (! optimize
  	      || containing_blocks_have_cleanups_or_stack_level ())
  	    ;
! 	  else if (TREE_CODE (then_) == GOTO_EXPR
! 		   && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL
! 		   && ! NONLOCAL_LABEL (GOTO_DESTINATION (then_)))
  	    {
! 	      jumpif (pred, label_rtx (GOTO_DESTINATION (then_)));
! 	      return expand_expr (else_, const0_rtx, VOIDmode, 0);
  	    }
! 	  else if (TREE_CODE (else_) == GOTO_EXPR
! 		   && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL
! 		   && ! NONLOCAL_LABEL (GOTO_DESTINATION (else_)))
  	    {
! 	      jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_)));
  	      return expand_expr (then_, const0_rtx, VOIDmode, 0);
  	    }
  
  	  /* Just use the 'if' machinery.  */
  	  expand_start_cond (pred, 0);
  	  start_cleanup_deferral ();
! 	  expand_expr (then_, const0_rtx, VOIDmode, 0);
  
! 	  exp = else_;
! 
! 	  /* Iterate over 'else if's instead of recursing.  */
! 	  for (; TREE_CODE (exp) == COND_EXPR; exp = TREE_OPERAND (exp, 2))
  	    {
  	      expand_start_else ();
! 	      if (EXPR_LOCUS (exp))
! 		{
! 		  emit_line_note (*(EXPR_LOCUS (exp)));
! 		  if (cfun->dont_emit_block_notes)
! 		    record_block_change (TREE_BLOCK (exp));
! 		}
! 	      expand_elseif (TREE_OPERAND (exp, 0));
! 	      expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, 0);
  	    }
! 	  /* Don't emit the jump and label if there's no 'else' clause.  */
! 	  if (TREE_SIDE_EFFECTS (exp))
  	    {
! 	      expand_start_else ();
! 	      expand_expr (exp, const0_rtx, VOIDmode, 0);
  	    }
  	  end_cleanup_deferral ();
! 	  expand_end_cond ();
  	  return const0_rtx;
  	}
  
--- 8434,8495 ----
  	  if (! optimize
  	      || containing_blocks_have_cleanups_or_stack_level ())
  	    ;
! 	  else if (then_label)
  	    {
! 	      jumpif (pred, label_rtx (then_label));
! 	      if (else_label)
! 		{
! 		  expand_goto (else_label);
! 		  return const0_rtx;
! 		}
! 	      else
! 		return expand_expr (else_, const0_rtx, VOIDmode, 0);
  	    }
! 	  else if (else_label)
  	    {
! 	      jumpifnot (pred, label_rtx (else_label));
  	      return expand_expr (then_, const0_rtx, VOIDmode, 0);
  	    }
  
  	  /* Just use the 'if' machinery.  */
  	  expand_start_cond (pred, 0);
  	  start_cleanup_deferral ();
! 	  if (then_label)
! 	    expand_goto (then_label);
! 	  else
! 	    expand_expr (then_, const0_rtx, VOIDmode, 0);
  
! 	  if (else_label)
  	    {
  	      expand_start_else ();
! 	      expand_goto (else_label);
  	    }
! 	  else
  	    {
! 	      exp = else_;
! 
! 	      /* Iterate over 'else if's instead of recursing.  */
! 	      for (; TREE_CODE (exp) == COND_EXPR; exp = TREE_OPERAND (exp, 2))
! 		{
! 		  expand_start_else ();
! 		  if (EXPR_LOCUS (exp))
! 		    {
! 		      emit_line_note (*(EXPR_LOCUS (exp)));
! 		      if (cfun->dont_emit_block_notes)
! 			record_block_change (TREE_BLOCK (exp));
! 		    }
! 		  expand_elseif (TREE_OPERAND (exp, 0));
! 		  expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, 0);
! 		}
! 	      /* Don't emit the jump and label if there's no 'else' clause.  */
! 	      if (TREE_SIDE_EFFECTS (exp))
! 		{
! 		  expand_start_else ();
! 		  expand_expr (exp, const0_rtx, VOIDmode, 0);
! 		}
  	    }
  	  end_cleanup_deferral ();
!      	  expand_end_cond ();
  	  return const0_rtx;
  	}
  
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimple-low.c,v
retrieving revision 1.1.4.13
diff -c -3 -p -r1.1.4.13 gimple-low.c
*** gimple-low.c	16 Nov 2003 23:00:59 -0000	1.1.4.13
--- gimple-low.c	21 Nov 2003 21:23:50 -0000
*************** lower_cond_expr (tree_stmt_iterator *tsi
*** 265,273 ****
--- 265,277 ----
  
    then_goto = expr_only (then_branch);
    then_is_goto = then_goto && simple_goto_p (then_goto);
+   if (then_is_goto)
+     then_goto = GOTO_DESTINATION (then_goto);
  
    else_goto = expr_only (else_branch);
    else_is_goto = else_goto && simple_goto_p (else_goto);
+   if (else_is_goto)
+     else_goto = GOTO_DESTINATION (else_goto);
  
    if (!then_is_goto || !else_is_goto)
      {
*************** lower_cond_expr (tree_stmt_iterator *tsi
*** 280,296 ****
        /* Replace the cond_expr with explicit gotos.  */
        if (!then_is_goto)
  	{
! 	  t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
  	  if (TREE_SIDE_EFFECTS (then_branch))
  	    then_label = t;
  	  else
  	    end_label = t;
! 	  then_goto = build_and_jump (&LABEL_EXPR_LABEL (t));
  	}
  
        if (!else_is_goto)
  	{
! 	  t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
  	  if (TREE_SIDE_EFFECTS (else_branch))
  	    else_label = t;
  	  else
--- 284,300 ----
        /* Replace the cond_expr with explicit gotos.  */
        if (!then_is_goto)
  	{
! 	  t = build1 (LABEL_EXPR, void_type_node, create_artificial_label ());
  	  if (TREE_SIDE_EFFECTS (then_branch))
  	    then_label = t;
  	  else
  	    end_label = t;
! 	  then_goto = LABEL_EXPR_LABEL (t);
  	}
  
        if (!else_is_goto)
  	{
! 	  t = build1 (LABEL_EXPR, void_type_node, create_artificial_label ());
  	  if (TREE_SIDE_EFFECTS (else_branch))
  	    else_label = t;
  	  else
*************** lower_cond_expr (tree_stmt_iterator *tsi
*** 308,314 ****
  	      else
  		end_label = t;
  	    }
! 	  else_goto = build_and_jump (&LABEL_EXPR_LABEL (t));
  	}
  
        if (then_label)
--- 312,318 ----
  	      else
  		end_label = t;
  	    }
! 	  else_goto = LABEL_EXPR_LABEL (t);
  	}
  
        if (then_label)
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.221
diff -c -3 -p -r1.1.4.221 tree-cfg.c
*** tree-cfg.c	20 Nov 2003 20:54:39 -0000	1.1.4.221
--- tree-cfg.c	21 Nov 2003 21:23:53 -0000
*************** make_cond_expr_edges (basic_block bb)
*** 613,620 ****
  #endif
  
    /* Entry basic blocks for each component.  */
!   then_label = GOTO_DESTINATION (COND_EXPR_THEN (entry));
!   else_label = GOTO_DESTINATION (COND_EXPR_ELSE (entry));
    then_bb = label_to_block (then_label);
    else_bb = label_to_block (else_label);
  
--- 613,620 ----
  #endif
  
    /* Entry basic blocks for each component.  */
!   then_label = COND_EXPR_THEN (entry);
!   else_label = COND_EXPR_ELSE (entry);
    then_bb = label_to_block (then_label);
    else_bb = label_to_block (else_label);
  
*************** cfg_remove_useless_stmts_bb (basic_block
*** 1403,1412 ****
        pstmt = gotos[n_gotos];
        stmt = *pstmt;
  
!       if (TREE_CODE (GOTO_DESTINATION (stmt)) != LABEL_DECL)
  	continue;
  
!       if (label_to_block (GOTO_DESTINATION (stmt)) != bb->next_bb)
  	continue;
  
        *pstmt = build_empty_stmt ();
--- 1403,1415 ----
        pstmt = gotos[n_gotos];
        stmt = *pstmt;
  
!       if (TREE_CODE (stmt) == GOTO_EXPR)
! 	stmt = GOTO_DESTINATION (stmt);
! 
!       if (TREE_CODE (stmt) != LABEL_DECL)
  	continue;
  
!       if (label_to_block (stmt) != bb->next_bb)
  	continue;
  
        *pstmt = build_empty_stmt ();
*************** cleanup_cond_expr_graph (basic_block bb,
*** 1694,1702 ****
      taken_edge = bb->succ;
  
    if (taken_edge->flags & EDGE_TRUE_VALUE)
!     bsi_replace (&bsi, COND_EXPR_THEN (cond_expr), false);
    else if (taken_edge->flags & EDGE_FALSE_VALUE)
!     bsi_replace (&bsi, COND_EXPR_ELSE (cond_expr), false);
    else
      abort ();
  
--- 1697,1709 ----
      taken_edge = bb->succ;
  
    if (taken_edge->flags & EDGE_TRUE_VALUE)
!     bsi_replace (&bsi,
! 		 build1 (GOTO_EXPR, void_type_node,
! 			 COND_EXPR_THEN (cond_expr)), false);
    else if (taken_edge->flags & EDGE_FALSE_VALUE)
!     bsi_replace (&bsi,
! 		 build1 (GOTO_EXPR, void_type_node,
! 			 COND_EXPR_ELSE (cond_expr)), false);
    else
      abort ();
  
*************** tree_verify_flow_info (void)
*** 2881,2888 ****
  	  {
  	    edge true_edge;
  	    edge false_edge;
! 	    if (TREE_CODE (COND_EXPR_THEN (stmt)) != GOTO_EXPR
! 		|| TREE_CODE (COND_EXPR_ELSE (stmt)) != GOTO_EXPR)
  	      {
  		error ("Structured COND_EXPR at end of bb %d\n", bb->index);
  		err = 1;
--- 2888,2895 ----
  	  {
  	    edge true_edge;
  	    edge false_edge;
! 	    if (TREE_CODE (COND_EXPR_THEN (stmt)) != LABEL_DECL
! 		|| TREE_CODE (COND_EXPR_ELSE (stmt)) != LABEL_DECL)
  	      {
  		error ("Structured COND_EXPR at end of bb %d\n", bb->index);
  		err = 1;
*************** tree_verify_flow_info (void)
*** 2902,2910 ****
  		err = 1;
  	      }
  	    if (!has_label_p (true_edge->dest,
! 			      GOTO_DESTINATION (COND_EXPR_THEN (stmt)))
  		|| !has_label_p (false_edge->dest,
! 				 GOTO_DESTINATION (COND_EXPR_ELSE (stmt))))
  	      {
  		error ("Label %s does not match edge at end of bb %d\n",
  		       IDENTIFIER_POINTER (DECL_NAME (stmt)),
--- 2909,2917 ----
  		err = 1;
  	      }
  	    if (!has_label_p (true_edge->dest,
! 			      COND_EXPR_THEN (stmt))
  		|| !has_label_p (false_edge->dest,
! 				 COND_EXPR_ELSE (stmt)))
  	      {
  		error ("Label %s does not match edge at end of bb %d\n",
  		       IDENTIFIER_POINTER (DECL_NAME (stmt)),
*************** tree_redirect_edge_and_branch_1 (edge e,
*** 3459,3469 ****
    switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
      {
      case COND_EXPR:
!       stmt = (e->flags & EDGE_TRUE_VALUE
! 	      ? COND_EXPR_THEN (stmt)
! 	      : COND_EXPR_ELSE (stmt));
        flags = e->flags;
!       /* FALLTHRU */
  
      case GOTO_EXPR:
        GOTO_DESTINATION (stmt) = label;
--- 3466,3477 ----
    switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
      {
      case COND_EXPR:
!       if (e->flags & EDGE_TRUE_VALUE)
! 	COND_EXPR_THEN (stmt) = label;
!       else
! 	COND_EXPR_ELSE (stmt) = label;
        flags = e->flags;
!       break;
  
      case GOTO_EXPR:
        GOTO_DESTINATION (stmt) = label;
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-pretty-print.c,v
retrieving revision 1.1.2.61
diff -c -3 -p -r1.1.2.61 tree-pretty-print.c
*** tree-pretty-print.c	17 Nov 2003 12:08:26 -0000	1.1.2.61
--- tree-pretty-print.c	21 Nov 2003 21:23:55 -0000
*************** dump_generic_node (pretty_printer *buffe
*** 758,783 ****
      case COND_EXPR:
        if (TREE_TYPE (node) == void_type_node)
  	{
  	  pp_string (buffer, "if (");
  	  dump_generic_node (buffer, COND_EXPR_COND (node), spc, flags, false);
  	  pp_character (buffer, ')');
! 	  /* The lowered cond_exprs should always be printed in full.  */
! 	  if (COND_EXPR_THEN (node)
! 	      && TREE_CODE (COND_EXPR_THEN (node)) == GOTO_EXPR
! 	      && COND_EXPR_ELSE (node)
! 	      && TREE_CODE (COND_EXPR_ELSE (node)) == GOTO_EXPR)
! 	    {
! 	      pp_space (buffer);
! 	      dump_generic_node (buffer, COND_EXPR_THEN (node), 0, flags, true);
! 	      pp_string (buffer, " else ");
! 	      dump_generic_node (buffer, COND_EXPR_ELSE (node), 0, flags, true);
! 	    }
! 	  else if (!(flags & TDF_SLIM))
  	    {
! 	      /* Output COND_EXPR_THEN.  */
! 	      if (COND_EXPR_THEN (node))
  		{
- 		  newline_and_indent (buffer, spc+2);
  		  pp_character (buffer, '{');
  		  newline_and_indent (buffer, spc+4);
  		  dump_generic_node (buffer, COND_EXPR_THEN (node), spc+4,
--- 758,786 ----
      case COND_EXPR:
        if (TREE_TYPE (node) == void_type_node)
  	{
+ 	  is_expr = false;
  	  pp_string (buffer, "if (");
  	  dump_generic_node (buffer, COND_EXPR_COND (node), spc, flags, false);
  	  pp_character (buffer, ')');
! 
! 	  if (flags & TDF_SLIM)
! 	    break;
! 
! 	  /* Output COND_EXPR_THEN.  */
!       	  if (COND_EXPR_THEN (node))
  	    {
! 	      newline_and_indent (buffer, spc+2);
! 	      if (TREE_CODE (COND_EXPR_THEN (node)) == LABEL_DECL)
! 		{
! 		  /* Lowered gimple cond_expr has just a label_decl
! 		     here.  Show it as a goto.  */
! 		  pp_string (buffer, "goto ");
! 		  dump_generic_node (buffer, COND_EXPR_THEN (node), spc + 2,
! 				     flags, false);
! 		  pp_semicolon (buffer);
! 		}
! 	      else
  		{
  		  pp_character (buffer, '{');
  		  newline_and_indent (buffer, spc+4);
  		  dump_generic_node (buffer, COND_EXPR_THEN (node), spc+4,
*************** dump_generic_node (pretty_printer *buffe
*** 785,806 ****
  		  newline_and_indent (buffer, spc+2);
  		  pp_character (buffer, '}');
  		}
  
! 	      /* Output COND_EXPR_ELSE.  */
! 	      if (COND_EXPR_ELSE (node))
  		{
- 		  newline_and_indent (buffer, spc);
- 		  pp_string (buffer, "else");
- 		  newline_and_indent (buffer, spc+2);
  		  pp_character (buffer, '{');
  		  newline_and_indent (buffer, spc+4);
  		  dump_generic_node (buffer, COND_EXPR_ELSE (node), spc+4,
! 			             flags, true);
  		  newline_and_indent (buffer, spc+2);
  		  pp_character (buffer, '}');
  		}
  	    }
- 	  is_expr = false;
  	}
        else
  	{
--- 788,820 ----
  		  newline_and_indent (buffer, spc+2);
  		  pp_character (buffer, '}');
  		}
+ 	    }
  
! 	  /* Output COND_EXPR_ELSE.  */
! 	  if (COND_EXPR_ELSE (node))
! 	    {
! 	      newline_and_indent (buffer, spc);
! 	      pp_string (buffer, "else");
! 	      newline_and_indent (buffer, spc+2);
! 	      if (TREE_CODE (COND_EXPR_ELSE (node)) == LABEL_DECL)
! 		{
! 		  /* Lowered gimple cond_expr has just a label_decl
! 		     here.  Show it as a goto.  */
! 		  pp_string (buffer, "goto ");
! 		  dump_generic_node (buffer, COND_EXPR_ELSE (node), spc + 2,
! 				     flags, false);
! 		  pp_semicolon (buffer);
! 		}
! 	      else
  		{
  		  pp_character (buffer, '{');
  		  newline_and_indent (buffer, spc+4);
  		  dump_generic_node (buffer, COND_EXPR_ELSE (node), spc+4,
! 				     flags, true);
  		  newline_and_indent (buffer, spc+2);
  		  pp_character (buffer, '}');
  		}
  	    }
  	}
        else
  	{
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.69
diff -c -3 -p -r1.1.2.69 tree-ssa-dce.c
*** tree-ssa-dce.c	19 Nov 2003 20:10:01 -0000	1.1.2.69
--- tree-ssa-dce.c	21 Nov 2003 21:23:55 -0000
*************** stmt_useful_p (tree stmt)
*** 276,288 ****
  	return true;
        break;
  
-     case COND_EXPR:
-       /* Check if the dest labels are the same. If they are, the condition
- 	 is useless.  */
-       if (GOTO_DESTINATION (COND_EXPR_THEN (stmt))
- 	  == GOTO_DESTINATION (COND_EXPR_ELSE (stmt)))
- 	return false;
- 
      default:
        break;
      }
--- 276,281 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]