This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Mainline merge as of 2003-04-06
- From: Diego Novillo <dnovillo at redhat dot com>
- To: gcc at gcc dot gnu dot org
- Date: Wed, 9 Apr 2003 15:36:34 -0400
- Subject: [tree-ssa] Mainline merge as of 2003-04-06
- Organization: Red Hat Canada
This merge exposed a few bugs in the flowgraph builder. Thanks
to Steven Bosscher for finding the hundreds of new C++
regressions. In cp/call.c:print_z_candidate, I had stupidly
changed the call to errfn to pass &TREE_LOCUS instead of
TREE_LOCUS.
There are a couple new regressions due to line number mismatch.
Also, we are failing g++.dg/eh/cond1.C. The gimplifier is trying
to put the call to __cxa_throw on the RHS of an assignment.
Since __cxa_throw is of type void, we go on to ICE in the RTL
expanders.
This patch to the gimplifier fixes the symptom, but I'm not sure
if it fixes the problem. It's odd that we have a void object in
an INIT_EXPR, but I'm not at all familiar with the C++ FE.
Jason, does this fix look right? (it's still not committed):
--- gimplify.c 20 Mar 2003 21:21:15 -0000 1.1.2.32
+++ gimplify.c 9 Apr 2003 19:17:29 -0000
@@ -2319,7 +2320,8 @@ simplify_target_expr (expr_p, pre_p, pos
gimple_add_tmp_var (temp);
/* Build up the initialization and add it to pre_p. */
- init = build (MODIFY_EXPR, void_type_node, temp, init);
+ if (!VOID_TYPE_P (TREE_TYPE (init)))
+ init = build (MODIFY_EXPR, void_type_node, temp, init);
simplify_expr (&init, pre_p, post_p, is_simple_stmt, fb_none);
add_tree (init, pre_p);
The fixes to the flowgraph code were needed to better handle the
presence of empty statements in the function. The inliner is now
inlining functions after they've been optimized by the tree
optimizers. This was confusing the flowgraph in various places.
Bootstrapped and tested on ppc, x86 and x86-64. treelang should
now bootstrap, but I still haven't looked at the problems with Ada.
Diego.
* gimplify.c (simplify_expr): Handle VECTOR_CST nodes.
* tree-cfg.c (make_blocks): Ignore empty statement containers.
Create a basic block before processing containers that only have
empty statements.
(make_loop_expr_blocks): Use the container instead of the statement
when setting NEXT_BLOCK_LINK.
(make_cond_expr_blocks): Likewise.
(make_switch_expr_blocks): Likewise.
(make_bind_expr_blocks): Likewise.
(successor_block): If the last statement of the block is the empty
statement, use its container to get NEXT_BLOCK_LINK.
(stmt_starts_bb_p): Return false if the statement is NULL.
* tree-pretty-print.c (dump_generic_node): Handle VECTOR_CST nodes.
* tree-simple.c (is_simple_const): Accept VECTOR_CST as constants.
* objc/objc-lang.c (LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P):
Define.
--- gimplify.c 2003/04/06 23:45:14 1.1
+++ gimplify.c 2003/04/06 23:45:27
@@ -457,6 +457,7 @@ simplify_expr (expr_p, pre_p, post_p, si
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
+ case VECTOR_CST:
break;
/* FIXME make this a decl. */
--- tree-cfg.c 2003/04/06 23:45:14 1.1
+++ tree-cfg.c 2003/04/08 03:24:25
@@ -278,14 +278,28 @@ make_blocks (first_p, next_block_link, p
tree prev_stmt;
tree *stmt_p = tsi_container (i);
+ /* Ignore empty containers. */
+ if (*stmt_p == empty_stmt_node || *stmt_p == error_mark_node)
+ continue;
+
prev_stmt = stmt;
stmt = tsi_stmt (i);
+ /* If the statement starts a new basic block or if we have determined
+ in a previous pass that we need to create a new block for STMT, do
+ so now. */
+ if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
+ {
+ bb = create_bb ();
+ start_new_block = false;
+ }
+
/* Set the block for the container of non-executable statements. */
if (stmt == NULL_TREE)
{
- if (bb && *stmt_p != empty_stmt_node)
+ if (bb)
append_stmt_to_bb (stmt_p, bb, parent_stmt);
+ last = *stmt_p;
continue;
}
@@ -293,15 +307,6 @@ make_blocks (first_p, next_block_link, p
NEXT_BLOCK_LINK (stmt) = NULL_TREE;
code = TREE_CODE (stmt);
- /* If the statement starts a new basic block or if we have determined
- in a previous pass that we need to create a new block for STMT, do
- so now. */
- if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
- {
- bb = create_bb ();
- start_new_block = false;
- }
-
/* Now add STMT to BB and create the subgraphs for special statement
codes. */
append_stmt_to_bb (stmt_p, bb, parent_stmt);
@@ -380,9 +385,8 @@ make_blocks (first_p, next_block_link, p
last = stmt;
}
- /* If LAST_STMT is set, link it to NEXT_BLOCK_LINK. This allows making
- edges from the last block inside a lexical scope (see
- successor_block). */
+ /* If LAST is set, link it to NEXT_BLOCK_LINK. This allows making edges
+ from the last block inside a lexical scope (see successor_block). */
if (last)
{
NEXT_BLOCK_LINK (last) = next_block_link;
@@ -421,17 +425,17 @@ make_loop_expr_blocks (loop_p, next_bloc
LOOP_EXPR body, will naturally loop back. */
STRIP_CONTAINERS (loop);
si = tsi_start (&LOOP_EXPR_BODY (loop));
- next_block_link = tsi_stmt (si);
+ next_block_link = *(tsi_container (si));
/* If the loop body is empty, point NEXT_BLOCK_LINK to the statement
following the LOOP_EXPR node, as we do with the other control
structures. */
- if (next_block_link == NULL_TREE)
+ if (body_is_empty (LOOP_EXPR_BODY (loop)))
{
si = tsi_start (loop_p);
tsi_next (&si);
if (!tsi_end_p (si))
- next_block_link = tsi_stmt (si);
+ next_block_link = *(tsi_container (si));
}
make_blocks (&LOOP_EXPR_BODY (loop), next_block_link, loop, NULL);
@@ -461,7 +465,7 @@ make_cond_expr_blocks (cond_p, next_bloc
si = tsi_start (cond_p);
tsi_next (&si);
if (!tsi_end_p (si))
- next_block_link = tsi_stmt (si);
+ next_block_link = *(tsi_container (si));
STRIP_CONTAINERS (cond);
make_blocks (&COND_EXPR_THEN (cond), next_block_link, cond, NULL);
@@ -492,7 +496,7 @@ make_switch_expr_blocks (switch_e_p, nex
si = tsi_start (switch_e_p);
tsi_next (&si);
if (!tsi_end_p (si))
- next_block_link = tsi_stmt (si);
+ next_block_link = *(tsi_container (si));
STRIP_CONTAINERS (switch_e);
make_blocks (&SWITCH_BODY (switch_e), next_block_link, switch_e, NULL);
@@ -531,7 +535,7 @@ make_bind_expr_blocks (bind_p, next_bloc
si = tsi_start (bind_p);
tsi_next (&si);
if (!tsi_end_p (si))
- next_block_link = tsi_stmt (si);
+ next_block_link = *(tsi_container (si));
/* By passing the current block ENTRY to make_blocks, we will keep adding
statements to ENTRY until we find a block terminating statement inside
@@ -1103,17 +1107,9 @@ remove_bb (bb, remove_stmts)
remove_edge (bb->pred);
}
+ /* Remove edges to BB's successors. */
while (bb->succ != NULL)
- {
- tree phi;
-
- /* PHI nodes in successors of this block now have one less
- alternative. */
- for (phi = phi_nodes (bb->succ->dest); phi; phi = TREE_CHAIN (phi))
- remove_phi_arg (phi, bb);
-
- remove_edge (bb->succ);
- }
+ ssa_remove_edge (bb->succ);
bb->pred = NULL;
bb->succ = NULL;
@@ -1384,15 +1380,7 @@ cleanup_cond_expr_graph (bb)
{
next = e->succ_next;
if (e != taken_edge)
- {
- tree phi;
-
- /* Remove the appropriate PHI alternative in the
- target block for each non executable edge. */
- for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
- remove_phi_arg (phi, e->dest);
- remove_edge (e);
- }
+ ssa_remove_edge (e);
}
}
}
@@ -1431,15 +1419,7 @@ cleanup_switch_expr_graph (switch_bb)
basic_block chain_bb = successor_block (switch_bb);
edge e = find_edge (switch_bb, chain_bb);
if (e)
- {
- tree phi;
-
- /* Remove the appropriate PHI alternative in the
- target block for each unexecutable edge. */
- for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
- remove_phi_arg (phi, e->src);
- remove_edge (e);
- }
+ ssa_remove_edge (e);
break;
}
}
@@ -1474,15 +1454,7 @@ disconnect_unreachable_case_labels (bb)
{
next = e->succ_next;
if (e != taken_edge)
- {
- tree phi;
-
- /* Remove the appropriate PHI alternative in the
- target block for each non executable edge. */
- for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
- remove_phi_arg (phi, e->src);
- remove_edge (e);
- }
+ ssa_remove_edge (e);
}
}
}
@@ -1749,6 +1721,7 @@ dump_tree_bb (outf, prefix, bb, indent)
char *s_indent;
basic_block loop_bb;
block_stmt_iterator si;
+ tree phi;
s_indent = (char *) alloca ((size_t) indent + 1);
memset ((void *) s_indent, ' ', (size_t) indent);
@@ -1792,6 +1765,14 @@ dump_tree_bb (outf, prefix, bb, indent)
else
fprintf (outf, "nil\n");
+ if (bb->aux)
+ for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+ {
+ fprintf (outf, "%s%s# ", s_indent, prefix);
+ print_generic_stmt (outf, phi, 0);
+ fprintf (outf, "\n");
+ }
+
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{
fprintf (outf, "%s%s%d ", s_indent, prefix, get_lineno (bsi_stmt (si)));
@@ -2062,7 +2043,10 @@ successor_block (bb)
NEXT_BLOCK_LINK for BB's last statement. If NEXT_BLOCK_LINK is still
NULL, then BB is the last basic block in the function. In which case
we have reached the end of the flowgraph and return EXIT_BLOCK_PTR. */
- if (last_stmt && NEXT_BLOCK_LINK (last_stmt))
+ if (last_stmt == NULL_TREE)
+ last_stmt = *bb->end_tree_p;
+
+ if (NEXT_BLOCK_LINK (last_stmt))
return bb_for_stmt (NEXT_BLOCK_LINK (last_stmt));
else
return EXIT_BLOCK_PTR;
@@ -2181,12 +2165,16 @@ stmt_starts_bb_p (t, prev_t)
tree t;
tree prev_t;
{
- enum tree_code code = TREE_CODE (t);
-
+ enum tree_code code;
+
+ if (t == NULL_TREE)
+ return false;
+
/* LABEL_EXPRs and CASE_LABEL_EXPRs start a new basic block only if the
preceding statement wasn't a label of the same type. This prevents
the creation of consecutive blocks that have nothing but a single
label. */
+ code = TREE_CODE (t);
if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
{
if (prev_t && TREE_CODE (prev_t) == code)
@@ -3126,6 +3114,60 @@ bsi_insert_on_edge (e, stmt)
}
+/* These 2 routines are used to process BSI's in reverse within a block.
+ When there is a decent implementation of bsi_prev, we can get rid of
+ these forever! */
+
+/* Push another block_stmt_iterator onto the stack. */
+void
+push_bsi (list, bsi)
+ bsi_list_p *list;
+ block_stmt_iterator bsi;
+{
+ bsi_list_p tmp;
+ if (*list == NULL)
+ {
+ *list = new_bsi_list ();
+ (*list)->bsi[0] = bsi;
+ }
+ else
+ {
+ if ((*list)->curr_index == (BSI_NUM_ELEMENTS - 1))
+ {
+ tmp = new_bsi_list ();
+ tmp->bsi[0] = bsi;
+ tmp->next = *list;
+ *list = tmp;
+ }
+ else
+ {
+ (*list)->bsi[++((*list)->curr_index)] = bsi;
+ }
+ }
+}
+
+/* Pop a block_stmt_iterator off the stack. */
+block_stmt_iterator
+pop_bsi (list)
+ bsi_list_p *list;
+{
+ block_stmt_iterator bsi;
+ bsi_list_p tmp;
+ if (!list)
+ abort ();
+
+ tmp = *list;
+ bsi = tmp->bsi[(tmp->curr_index)--];
+ if (tmp->curr_index< 0)
+ {
+ tmp = *list;
+ *list = (*list)->next;
+ free (tmp);
+ }
+ return bsi;
+}
+
+
/* Replace the statement pointed by TP1 with the statement pointed by TP2.
Note that this function will not replace COMPOUND_EXPR nodes, only
individual statements.
@@ -3216,13 +3258,29 @@ merge_tree_blocks (basic_block bb1, basi
/* BB2's successors are now BB1's. */
while (bb1->succ)
- remove_edge (bb1->succ);
+ ssa_remove_edge (bb1->succ);
while (bb2->succ)
{
- edge e = bb2->succ;
- make_edge (bb1, e->dest, e->flags);
- remove_edge (e);
+ tree phi;
+ edge new_edge, old_edge;
+
+ old_edge = bb2->succ;
+ new_edge = make_edge (bb1, old_edge->dest, old_edge->flags);
+
+ /* Update PHI nodes at BB2's successor. The arguments that used to
+ come from BB2 now come from BB1. */
+ for (phi = phi_nodes (old_edge->dest); phi; phi = TREE_CHAIN (phi))
+ {
+ int i;
+ for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+ if (PHI_ARG_EDGE (phi, i) == old_edge)
+ PHI_ARG_EDGE (phi, i) = new_edge;
+ }
+
+ /* Note that we shouldn't call ssa_remove_edge here because we've
+ already dealt with PHI nodes. */
+ remove_edge (old_edge);
}
/* BB2's dominator children are now BB1's. Also, remove BB2 as a
--- tree-pretty-print.c 2003/04/06 23:45:14 1.1
+++ tree-pretty-print.c 2003/04/07 01:37:51
@@ -37,7 +37,7 @@ static const char *op_symbol PARAMS ((t
static void pretty_print_string PARAMS ((output_buffer *, const char*));
static void print_call_name PARAMS ((output_buffer *, tree));
static void newline_and_indent PARAMS ((output_buffer *, int));
-static inline void maybe_init_pretty_print PARAMS ((void));
+static void maybe_init_pretty_print PARAMS ((void));
static void print_declaration PARAMS ((output_buffer *, tree, int,
int));
static void print_struct_decl PARAMS ((output_buffer *, tree, int));
@@ -477,6 +477,20 @@ dump_generic_node (buffer, node, spc, fl
output_add_string (buffer, "\"");
break;
+ case VECTOR_CST:
+ {
+ tree elt;
+ output_add_string (buffer, "{ ");
+ for (elt = TREE_VECTOR_CST_ELTS (node); elt; elt = TREE_CHAIN (elt))
+ {
+ dump_generic_node (buffer, TREE_VALUE (elt), spc, flags);
+ if (TREE_CHAIN (elt))
+ output_add_string (buffer, ", ");
+ }
+ output_add_string (buffer, " }");
+ }
+ break;
+
case FUNCTION_TYPE:
break;
@@ -1335,6 +1349,9 @@ dump_generic_node (buffer, node, spc, fl
for (i = 0; i < PHI_NUM_ARGS (node); i++)
{
dump_generic_node (buffer, PHI_ARG_DEF (node, i), spc, flags);
+ output_add_string (buffer, "(");
+ output_decimal (buffer, PHI_ARG_EDGE (node, i)->src->index);
+ output_add_string (buffer, ")");
if (i < PHI_NUM_ARGS (node) - 1)
output_add_string (buffer, ", ");
}
--- tree-simple.c 2003/04/06 23:45:14 1.1
+++ tree-simple.c 2003/04/06 23:45:27
@@ -649,7 +649,8 @@ is_simple_const (t)
|| TREE_CODE (t) == STRING_CST
|| TREE_CODE (t) == LABEL_DECL
|| TREE_CODE (t) == RESULT_DECL
- || TREE_CODE (t) == COMPLEX_CST);
+ || TREE_CODE (t) == COMPLEX_CST
+ || TREE_CODE (t) == VECTOR_CST);
}
int
--- objc/objc-lang.c 2 Mar 2003 19:59:14 -0000 1.24.2.5
+++ objc/objc-lang.c 8 Apr 2003 18:12:40 -0000
@@ -100,6 +100,9 @@ static void objc_init_options
#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
c_convert_parm_for_inlining
+#undef LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P
+#define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \
+ c_tree_chain_matters_p
#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION c_expand_body