This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] More efficient lowered COND_EXPR representation
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 23 Nov 2003 20:21:27 +0100
- Subject: [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 ----