This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Overlapping live range patch.
On Tue, 2003-06-03 at 17:36, Diego Novillo wrote:
> On Tue, 2003-06-03 at 17:26, Toon Moene wrote:
> ^^^^
> > Ah, yes - that's because g95 is not yet part of the tree-ssa branch :-)
> >
> It's part of my secret plan to detect when you guys finally include g95
> :)
>
>
> > stage1/xgcc .... f95/array.c -o f95/array.o
> > ../../gcc/gcc/f95/array.c: In function `spec_size':
> > ../../gcc/gcc/f95/array.c:1565: internal compiler error: in assign_vars,
> > at tree-ssa.c:1553
> >
> Should be fixed by Andrew's overlapping LRs patch which should be ready
> anytime now. It works on amd64 and ia64, but Andrew found a corner case
> on x86. It should be ready RSN (says he who's not actually working on
> the fix).
RSN for sure. no, now. just about. now. no, not quite... Thats been my
last week or so :-)
So, It now bootstraps and appears to do everything fine, with one minor
exception. The stage 1 compiler miscompiles the fortran file f/intrin.c,
and this results in a bootstrapped fortran compiler which fails a lot of
the fortran tests. If you dont bootstrap, it works great :-|
The problem is that the into SSA pass is generating a structure copy
which has a VDEF as a real use. This is a no-no. The out of SSA pass
creates a new temporary which is undefined on entry since there is no
defintion present. This of course causes problem :-)
Diego is looking at is today.
I will not check this in until he has resolved that problem on the
outside chance something else comes up, but until then, here is the
patch which I intend to commit when everything is worked out.
Andrew
* toplev.c (parse_options_and_default_flags): Turn tree_copyprop on by
default.
* tree-cfg.c (linearize_control_structures, linearize_cond_expr,
replace_stmt, merge_tree_blocks, remap_stmts): Fix PROTOS.
(find_insert_location): Add additional basic block parameter. Handle
switch stmts.
(handle_switch_split): New. Split edges to switch labels.
(bsi_commit_first_edge_insert): Add extra parameter to
find_insert_location call. Fix split block chaining in THEN & ELSE.
* tree-ssa-live.c (calculate_live_on_entry): Process all PHI def's after
all the arguments have been processed.
* tree-ssa.c (struct ssa_stats_d, struct loops *loops, var_is_live,
rewrite_into_ssa): Remove old UNSSA code.
(rewrite_block): Remove stmt is rewrite_stmt returns 1.
(assign_vars): Remove abort and enable overlapping live ranges.
(replace_variable): New. Replace SSA name with the partition variable.
(rewrite_out_of_ssa): Use replace_variable().
(dump_tree_ssa_stats): Remove old UNSSA code.
(rewrite_stmt): Return 1 if stmt should be deleted. Remove old UNSSA
code.
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.53
diff -c -p -r1.654.2.53 toplev.c
*** toplev.c 3 Jun 2003 16:50:51 -0000 1.654.2.53
--- toplev.c 3 Jun 2003 23:10:53 -0000
*************** parse_options_and_default_flags (argc, a
*** 5107,5112 ****
--- 5107,5113 ----
flag_if_conversion2 = 1;
flag_tree_ccp = 1;
flag_tree_dce = 1;
+ flag_tree_copyprop = 1;
}
if (optimize >= 2)
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.98
diff -c -p -r1.1.4.98 tree-cfg.c
*** tree-cfg.c 2 Jun 2003 18:49:53 -0000 1.1.4.98
--- tree-cfg.c 3 Jun 2003 23:10:55 -0000
*************** static void disconnect_unreachable_case_
*** 127,137 ****
static edge find_taken_edge_cond_expr PARAMS ((basic_block, tree));
static edge find_taken_edge_switch_expr PARAMS ((basic_block, tree));
static bool value_matches_some_label PARAMS ((edge, tree, edge *));
! static void linearize_control_structures (void);
! static bool linearize_cond_expr (tree *, basic_block);
! static void replace_stmt (tree *, tree *);
! static void merge_tree_blocks (basic_block, basic_block);
! static bool remap_stmts (basic_block, basic_block, tree *);
/* Block iterator helpers. */
--- 127,138 ----
static edge find_taken_edge_cond_expr PARAMS ((basic_block, tree));
static edge find_taken_edge_switch_expr PARAMS ((basic_block, tree));
static bool value_matches_some_label PARAMS ((edge, tree, edge *));
! static void linearize_control_structures PARAMS ((void));
! static bool linearize_cond_expr PARAMS ((tree *, basic_block));
! static void replace_stmt PARAMS ((tree *, tree *));
! static void merge_tree_blocks PARAMS ((basic_block, basic_block));
! static bool remap_stmts PARAMS ((basic_block, basic_block, tree *));
! static tree *handle_switch_split PARAMS ((basic_block, basic_block));
/* Block iterator helpers. */
*************** enum find_location_action {
*** 149,155 ****
EDGE_INSERT_LOCATION_ELSE,
EDGE_INSERT_LOCATION_NEW_ELSE };
! static tree_stmt_iterator find_insert_location PARAMS ((basic_block, basic_block, enum find_location_action *));
/* Location to track pending stmt for edge insertion. */
#define PENDING_STMT(e) ((tree)(e->insns))
--- 150,156 ----
EDGE_INSERT_LOCATION_ELSE,
EDGE_INSERT_LOCATION_NEW_ELSE };
! static tree_stmt_iterator find_insert_location PARAMS ((basic_block, basic_block, basic_block, enum find_location_action *));
/* Location to track pending stmt for edge insertion. */
#define PENDING_STMT(e) ((tree)(e->insns))
*************** bsi_insert_before (curr_bsi, t, mode)
*** 3622,3636 ****
return;
}
/* Given an edge between src and dest, return a TSI representing the location
that any instructions on this edge should be inserted.
The location parameter returns a value indicating how this iterator is
to be used. */
static tree_stmt_iterator
! find_insert_location (src, dest, location)
basic_block src;
basic_block dest;
enum find_location_action *location;
{
block_stmt_iterator bsi;
--- 3623,3788 ----
return;
}
+
+ /* Arrange for a place to insert a stmt when we are splitting a block which is
+ targetting by a switch stmt. Return the container which is used to build
+ a TSI where the edge stmt should be inserted after.
+
+ Fallthrough code must be directed around the target label, and a target
+ label must be inserted on the other side of the code we are inserting.
+ ie:
+ case X:
+ // fallthrough
+ BB_a
+ case Y:
+ code;
+
+ will be turned into:
+
+ case X:
+ BB_b
+ goto newlab;
+ BB_c
+ case Y:
+ inserted_code;
+ BB_a
+ newlab:
+ code;
+
+ This will cause the creation of 2 new basic blocks, and require some
+ edges to be redirected.
+
+ Note that upon entry to this function, src is *not* the switch stmt's block
+ any more. commit_one_edge_insertion() has already split the edge from
+ src->dest, so we have original_src -> src -> dest. This new src block
+ is currently empty.
+
+ This routine will create BB_b. BB_c will be the SRC block passed in.
+ BB_a will remain the DEST block. */
+
+ static tree *
+ handle_switch_split (src, dest)
+ basic_block src;
+ basic_block dest;
+ {
+ block_stmt_iterator bsi, tmp;
+ tree_stmt_iterator tsi;
+ tree stmt, label, parent;
+ basic_block new_bb;
+ edge e;
+ bb_ann_t bb_ann;
+
+
+ /* 1. Insert the goto immediately preceeding the labels that are targeted.
+ This should place the goto in the correct location in the tree. */
+
+ tsi = tsi_start (dest->head_tree_p);
+ parent = parent_stmt (tsi_stmt (tsi));
+
+ label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ TREE_USED (label) = 1;
+ stmt = build1 (GOTO_EXPR, void_type_node, label);
+
+ tsi_link_before (&tsi, stmt, TSI_NEW_STMT);
+ modify_stmt (stmt);
+
+ /* 2. Make a new basic block of which this stmt is the sole member. */
+
+ new_bb = create_bb ();
+ alloc_aux_for_block (new_bb, sizeof (struct bb_ann_d));
+ bb_ann = (bb_ann_t) xmalloc (sizeof (struct bb_ann_d));
+ new_bb->aux = bb_ann;
+ bb_ann->phi_nodes = NULL_TREE;
+ bb_ann->ephi_nodes = NULL_TREE;
+ bb_ann->dom_children = (bitmap) NULL;
+ append_stmt_to_bb (tsi_container (tsi), new_bb, parent);
+
+ /* Reset the head of dest since the container might be different now. */
+ tsi_next (&tsi);
+ dest->head_tree_p = tsi_container (tsi);
+
+ /* 3. Redirect all the edges except the one from src to point to this
+ block. */
+
+ for (e = dest->pred; e ; e = e->pred_next)
+ {
+ if (e->src == src)
+ continue;
+ redirect_edge_succ (e, new_bb);
+ }
+
+ /* 4. Now make dest the target of the new block. */
+
+ make_edge (new_bb, dest, 0);
+
+ /* 5. Find the last case label. That will be where the code seperation
+ between bb_c and bb_a will be formed. Upon exit of the loop, bsi will
+ point to the first stmt in BB_a. */
+
+ bsi = bsi_start (dest);
+ for (tmp = bsi; !bsi_end_p (bsi); bsi_next (&bsi))
+ {
+ stmt = bsi_stmt (bsi);
+ if (is_label_stmt (bsi_stmt (bsi)))
+ {
+ /* FIXME. This block may also be the target of a GOTO. Hopefully
+ there are no case stmts after the label. ick. */
+ if (TREE_CODE (stmt) != CASE_LABEL_EXPR)
+ break;
+ }
+ else
+ break;
+ tmp = bsi;
+ }
+
+ /* 6. Now the stmts delinieating the new block are known. Change the basic
+ block for those stmts. It cannot be done in the above loop, for
+ changing the basic block of a stmt pointed to by an iterator will cause
+ the iterator to think its reached the end of a block. (It is now
+ pointing to BB_c, the next stmt is in BB_a, so it terminates. */
+
+ for (tsi = tsi_start (dest->head_tree_p);
+ !tsi_end_p (tsi) && (tsi_container (tsi) != bsi_container (bsi));
+ tsi_next (&tsi))
+ append_stmt_to_bb (tsi_container (tsi), src, parent_stmt (tsi_stmt (tsi)));
+
+
+ /* 7. Issue the label at the beginning of DEST, and update DEST's head
+ and end pointers. */
+
+ stmt = build1 (LABEL_EXPR, void_type_node, label);
+ if (bsi_end_p (bsi))
+ {
+ /* There are no stmts left, so we need to link an empty_stmt node
+ after the last stmt in BB_c (which is pointed to by 'tmp'), and make
+ it the only element of BB_a. */
+ tsi = tsi_from_bsi (tmp);
+ tsi_link_after (&tsi, stmt, TSI_NEW_STMT);
+ dest->head_tree_p = (tree *) NULL;
+ dest->end_tree_p = (tree *) NULL;
+ append_stmt_to_bb (tsi_container (tsi),
+ dest,
+ parent_stmt (bsi_stmt (tmp)));
+ }
+ else
+ {
+ dest->head_tree_p = bsi_container (bsi);
+ bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+ }
+
+ return bsi_container (tmp);
+ }
+
/* Given an edge between src and dest, return a TSI representing the location
that any instructions on this edge should be inserted.
The location parameter returns a value indicating how this iterator is
to be used. */
static tree_stmt_iterator
! find_insert_location (src, dest, new_block, location)
basic_block src;
basic_block dest;
+ basic_block new_block;
enum find_location_action *location;
{
block_stmt_iterator bsi;
*************** find_insert_location (src, dest, locatio
*** 3676,3682 ****
ret = src->end_tree_p;
*location = EDGE_INSERT_LOCATION_AFTER;
break;
!
default:
ret = dest->head_tree_p;
break;
--- 3828,3839 ----
ret = src->end_tree_p;
*location = EDGE_INSERT_LOCATION_AFTER;
break;
!
! case SWITCH_EXPR:
! ret = handle_switch_split (new_block, dest);
! *location = EDGE_INSERT_LOCATION_AFTER;
! break;
!
default:
ret = dest->head_tree_p;
break;
*************** bsi_commit_first_edge_insert (e, stmt)
*** 3797,3803 ****
bb_ann->ephi_nodes = NULL_TREE;
bb_ann->dom_children = (bitmap) NULL;
! tsi = find_insert_location (src, dest, &location);
parent = parent_stmt (tsi_stmt (tsi));
switch (location)
--- 3954,3960 ----
bb_ann->ephi_nodes = NULL_TREE;
bb_ann->dom_children = (bitmap) NULL;
! tsi = find_insert_location (src, dest, new_bb, &location);
parent = parent_stmt (tsi_stmt (tsi));
switch (location)
*************** bsi_commit_first_edge_insert (e, stmt)
*** 3824,3832 ****
case EDGE_INSERT_LOCATION_ELSE:
stmt = last_stmt (src);
if (location == EDGE_INSERT_LOCATION_THEN)
! COND_EXPR_THEN (stmt) = inserted_stmt;
else
! COND_EXPR_ELSE (stmt) = inserted_stmt;
/* Fallthru. */
case EDGE_INSERT_LOCATION_BEFORE:
--- 3981,3989 ----
case EDGE_INSERT_LOCATION_ELSE:
stmt = last_stmt (src);
if (location == EDGE_INSERT_LOCATION_THEN)
! COND_EXPR_THEN (stmt) = *tsi_container (tsi);
else
! COND_EXPR_ELSE (stmt) = *tsi_container (tsi);
/* Fallthru. */
case EDGE_INSERT_LOCATION_BEFORE:
Index: tree-ssa-live.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-live.c,v
retrieving revision 1.1.2.5
diff -c -p -r1.1.2.5 tree-ssa-live.c
*** tree-ssa-live.c 24 May 2003 13:08:51 -0000 1.1.2.5
--- tree-ssa-live.c 3 Jun 2003 23:10:56 -0000
*************** calculate_live_on_entry (map)
*** 490,496 ****
for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
{
var = PHI_RESULT (phi);
- set_if_valid (map, saw_def, var);
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
{
var = PHI_ARG_DEF (phi, i);
--- 490,495 ----
*************** calculate_live_on_entry (map)
*** 503,508 ****
--- 502,520 ----
add_livein_if_notdef (live, saw_def, var, e->src);
}
}
+
+ /* Don't mark PHI results as defined until all the PHI nodes have
+ been processed. If the PHI sequence is:
+ a_3 = PHI <a_1, a_2>
+ b_3 = PHI <b_1, a_3>
+ The a_3 referred to in b_3's PHI node is the one incoming on the
+ edge, *not* the PHI node just seen. */
+
+ for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+ {
+ var = PHI_RESULT (phi);
+ set_if_valid (map, saw_def, var);
+ }
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.85
diff -c -p -r1.1.4.85 tree-ssa.c
*** tree-ssa.c 2 Jun 2003 18:49:54 -0000 1.1.4.85
--- tree-ssa.c 3 Jun 2003 23:10:57 -0000
*************** struct ssa_stats_d
*** 150,169 ****
long num_const_prop;
long num_copy_prop;
long num_re;
- /* FIXME. [UNSSA] Not needed after SSA->normal pass is working. */
- #if 1
- long blocked_optimizations;
- long blocked_by_life_crossing;
- #endif
};
static struct ssa_stats_d ssa_stats;
- #if 1
- /* FIXME: [UNSSA] Remove this once overlapping live ranges are allowed. */
- static struct loops *loops = NULL;
- #endif
-
/* Local functions. */
static void init_tree_ssa PARAMS ((void));
static void delete_tree_ssa PARAMS ((tree));
--- 150,159 ----
*************** static void set_livein_block PARAMS ((t
*** 174,180 ****
static void insert_phi_nodes PARAMS ((bitmap *, sbitmap));
static void insert_phis_for_deferred_variables PARAMS ((varray_type));
static void rewrite_block PARAMS ((basic_block, tree));
! static void rewrite_stmt PARAMS ((block_stmt_iterator,
varray_type *,
varray_type *));
static inline void rewrite_operand PARAMS ((tree *));
--- 164,170 ----
static void insert_phi_nodes PARAMS ((bitmap *, sbitmap));
static void insert_phis_for_deferred_variables PARAMS ((varray_type));
static void rewrite_block PARAMS ((basic_block, tree));
! static int rewrite_stmt PARAMS ((block_stmt_iterator,
varray_type *,
varray_type *));
static inline void rewrite_operand PARAMS ((tree *));
*************** static void coalesce_ssa_name PARAMS ((
*** 213,224 ****
static void assign_vars PARAMS ((var_map));
static inline void set_if_valid PARAMS ((var_map, sbitmap, tree));
static inline void add_conflicts_if_valid PARAMS ((root_var_p, conflict_graph, var_map, sbitmap, tree));
!
! /* FIXME: [UNSSA] Remove once the real unSSA pass is implemented. */
! #if 1
! static bool var_is_live PARAMS ((tree, basic_block));
! #endif
!
/* Main entry point to the SSA builder. FNDECL is the gimplified function
to convert.
--- 203,209 ----
static void assign_vars PARAMS ((var_map));
static inline void set_if_valid PARAMS ((var_map, sbitmap, tree));
static inline void add_conflicts_if_valid PARAMS ((root_var_p, conflict_graph, var_map, sbitmap, tree));
! static void replace_variable PARAMS ((var_map, tree *));
/* Main entry point to the SSA builder. FNDECL is the gimplified function
to convert.
*************** rewrite_into_ssa (fndecl)
*** 312,323 ****
timevar_push (TV_TREE_SSA_OTHER);
- #if 1
- /* FIXME: [UNSSA] Remove once overlapping live ranges are allowed. */
- if (loops == NULL)
- loops = loop_optimizer_init (NULL);
- #endif
-
/* Initialize common SSA structures. */
init_tree_ssa ();
--- 297,302 ----
*************** rewrite_into_ssa (fndecl)
*** 360,374 ****
htab_delete (avail_exprs);
htab_delete (const_and_copies);
- #if 1
- /* FIXME: [UNSSA] Remove this once overlapping live ranges are allowed. */
- if (loops)
- {
- loop_optimizer_finalize (loops, NULL);
- loops = NULL;
- }
- #endif
-
/* Debugging dumps. */
if (tree_ssa_dump_file)
{
--- 339,344 ----
*************** rewrite_block (bb, eq_expr_value)
*** 784,791 ****
/* Step 2. Rewrite every variable used in each statement the block with
its immediate reaching definitions. Update the current definition of
a variable when a new real or virtual definition is found. */
! for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
! rewrite_stmt (si, &block_defs, &block_avail_exprs);
/* Step 3. Visit all the successor blocks of BB looking for PHI nodes.
For every PHI node found, add a new argument containing the current
--- 754,764 ----
/* Step 2. Rewrite every variable used in each statement the block with
its immediate reaching definitions. Update the current definition of
a variable when a new real or virtual definition is found. */
! for (si = bsi_start (bb); !bsi_end_p (si); )
! if (!rewrite_stmt (si, &block_defs, &block_avail_exprs))
! bsi_next (&si);
! else
! bsi_remove (&si);
/* Step 3. Visit all the successor blocks of BB looking for PHI nodes.
For every PHI node found, add a new argument containing the current
*************** assign_vars (map)
*** 1547,1557 ****
print_generic_expr (tree_ssa_dump_file, var, TDF_SLIM);
}
- /* FIXME. Since we still don't have passes that create overlapping
- live ranges, the code above should've coalesced all the versions of
- the variable together. */
- abort ();
-
var = create_temp (t);
change_partition_var (map, var, i);
ann = var_ann (var);
--- 1520,1525 ----
*************** assign_vars (map)
*** 1568,1583 ****
delete_root_var (rv);
}
! /* Take function FNDECL out of SSA form.
! FIXME: Need to support overlapping live ranges for different versions of
! the same variable. At the moment, we will silently generate
! wrong code if an optimizer pass moves code so that two versions
! of the same variable have overlapping live ranges.
! NOTE: Look for the string '[UNSSA]' to re-enable code that
! depends on a properly working unSSA pass. */
void
rewrite_out_of_ssa (fndecl)
--- 1536,1573 ----
delete_root_var (rv);
}
+ /* Replace *p with whatever variable it has been rewritten to. */
! static void
! replace_variable (map, p)
! var_map map;
! tree *p;
! {
! tree new_var;
! tree var = *p;
! tree copy;
! new_var = var_to_partition_to_var (map, var);
! if (new_var)
! *p = new_var;
! else
! {
! /* Replace (*var)_version with just (*var). */
! if (TREE_CODE (SSA_NAME_VAR (var)) == INDIRECT_REF)
! {
! tree var2 = TREE_OPERAND (SSA_NAME_VAR (var), 0);
! new_var = var_to_partition_to_var (map, var2);
! copy = copy_node (SSA_NAME_VAR (var));
! if (new_var)
! TREE_OPERAND (copy, 0) = new_var;
! else
! TREE_OPERAND (copy, 0) = var2;
! *p = copy;
! }
! }
! }
! /* Take function FNDECL out of SSA form. */
void
rewrite_out_of_ssa (fndecl)
*************** rewrite_out_of_ssa (fndecl)
*** 1648,1662 ****
for (i = 0; i < num_ops; i++)
{
use_p = VARRAY_GENERIC_PTR (ops, i);
! *use_p = var_to_partition_to_var (map, *use_p);
}
if (def_op (stmt))
{
tree *def_p = def_op (stmt);
*def_p = var_to_partition_to_var (map, *def_p);
! if (is_copy && num_ops == 1 && use_p && (*def_p == *use_p))
remove = 1;
}
--- 1638,1653 ----
for (i = 0; i < num_ops; i++)
{
use_p = VARRAY_GENERIC_PTR (ops, i);
! replace_variable (map, use_p);
}
if (def_op (stmt))
{
tree *def_p = def_op (stmt);
*def_p = var_to_partition_to_var (map, *def_p);
+ replace_variable (map, def_p);
! if (is_copy && num_ops == 1 && use_p && def_p && (*def_p == *use_p))
remove = 1;
}
*************** void
*** 1761,1767 ****
dump_tree_ssa_stats (file)
FILE *file;
{
! long tmp, n_exprs;
fprintf (file, "Total number of statements: %6ld\n\n",
ssa_stats.num_stmts);
--- 1752,1758 ----
dump_tree_ssa_stats (file)
FILE *file;
{
! long n_exprs;
fprintf (file, "Total number of statements: %6ld\n\n",
ssa_stats.num_stmts);
*************** dump_tree_ssa_stats (file)
*** 1782,1798 ****
ssa_stats.num_re, PERCENT (ssa_stats.num_re,
n_exprs));
- /* FIXME. [UNSSA] Not needed after SSA->normal pass is working. */
- #if 1
- fprintf (file, " Optimizations blocked by lack of unSSA: %6ld (%.0f%%)\n",
- ssa_stats.blocked_optimizations,
- PERCENT (ssa_stats.blocked_optimizations, n_exprs));
-
- tmp = ssa_stats.blocked_optimizations - ssa_stats.blocked_by_life_crossing;
- fprintf (file, " Optimizations blocked due to pruned SSA: %6ld (%.0f%%)\n",
- tmp, PERCENT (tmp, n_exprs));
- #endif
-
fprintf (file, "\nHash table statistics:\n");
fprintf (file, " def_blocks: ");
--- 1773,1778 ----
*************** insert_phi_nodes_for (var, dfs, def_maps
*** 1979,1985 ****
}
! /* Rewrite the statement pointed by iterator SI into SSA form.
BLOCK_DEFS_P points to a stack with all the definitions found in the
block. This is used by rewrite_block to restore the current reaching
--- 1959,1966 ----
}
! /* Rewrite the statement pointed by iterator SI into SSA form. Return 1 if
! the stmt is to be deleted.
BLOCK_DEFS_P points to a stack with all the definitions found in the
block. This is used by rewrite_block to restore the current reaching
*************** insert_phi_nodes_for (var, dfs, def_maps
*** 2025,2031 ****
replace the constant and copy propagation passes. It only does very
simplistic propagation while renaming. */
! static void
rewrite_stmt (si, block_defs_p, block_avail_exprs_p)
block_stmt_iterator si;
varray_type *block_defs_p;
--- 2006,2012 ----
replace the constant and copy propagation passes. It only does very
simplistic propagation while renaming. */
! static int
rewrite_stmt (si, block_defs_p, block_avail_exprs_p)
block_stmt_iterator si;
varray_type *block_defs_p;
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2039,2045 ****
stmt = bsi_stmt (si);
if (IS_EMPTY_STMT (stmt))
! return;
ann = stmt_ann (stmt);
ssa_stats.num_stmts++;
--- 2020,2026 ----
stmt = bsi_stmt (si);
if (IS_EMPTY_STMT (stmt))
! return 0;
ann = stmt_ann (stmt);
ssa_stats.num_stmts++;
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2086,2103 ****
val = get_value_for (*op_p, const_and_copies);
if (val)
{
- #if 1
- /* FIXME: [UNSSA] Remove the following check after implementing
- SSA->normal. For the time being, avoid doing copy propagation
- if that would make two versions of VAL to be live at the same
- time. */
- if (TREE_CODE (val) == SSA_NAME && !var_is_live (val, ann->bb))
- {
- ssa_stats.blocked_optimizations++;
- continue;
- }
- #endif
-
/* Gather statistics. */
if (TREE_CONSTANT (val))
ssa_stats.num_const_prop++;
--- 2067,2072 ----
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2156,2195 ****
fprintf (tree_ssa_dump_file, "'\n");
}
! /* FIXME: [UNSSA] Re-enable this once the SSA->normal pass is
! implemented. Otherwise, this leads to cases where a PHI node
! contains arguments from different variables, which is
! something we can't handle with the current unSSA pass. It may
! also lead to cases where we re-use the LHS of a computation at
! a point where more than one version of the LHS is live at the
! same time. */
! #if 0
! ssa_stats.num_re++;
! TREE_OPERAND (stmt, 1) = cached_lhs;
! ann->modified = 1;
! #else
! if (cached_lhs
! && get_value_for (*def_p, currdefs) == cached_lhs
! && var_is_live (cached_lhs, ann->bb))
{
/* A redundant assignment to the same lhs, perhaps a new
evaluation of an expression temporary that is still live.
Just discard it. */
ssa_stats.num_re++;
! bsi_remove (&si);
! return;
}
! if (var_is_live (cached_lhs, ann->bb))
! {
! register_new_def (*def_p, cached_lhs, block_defs_p);
! TREE_OPERAND (stmt, 1) = cached_lhs;
! ann->modified = 1;
! ssa_stats.num_re++;
! }
! else
! ssa_stats.blocked_optimizations++;
! #endif
}
}
--- 2125,2142 ----
fprintf (tree_ssa_dump_file, "'\n");
}
! if (cached_lhs && get_value_for (*def_p, currdefs) == cached_lhs)
{
/* A redundant assignment to the same lhs, perhaps a new
evaluation of an expression temporary that is still live.
Just discard it. */
ssa_stats.num_re++;
! return 1;
}
! ssa_stats.num_re++;
! TREE_OPERAND (stmt, 1) = cached_lhs;
! ann->modified = 1;
}
}
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2222,2227 ****
--- 2169,2176 ----
register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdef)),
VDEF_RESULT (vdef), block_defs_p);
}
+
+ return 0;
}
*************** get_def_blocks_for (var)
*** 2692,2767 ****
dm.var = var;
return (struct def_blocks_d *) htab_find (def_blocks, (void *) &dm);
}
-
- #if 1
- /* Return true if the variable VAR is live at this point of the
- dominator tree walk. This means that the current reaching definition
- for VAR is itself and that VAR is livein at basic block BB.
-
- FIXME: [UNSSA] This will not be necessary when the unSSA pass is
- implemented. */
-
- static bool
- var_is_live (var, bb)
- tree var;
- basic_block bb;
- {
- int i;
- basic_block def_bb;
- struct def_blocks_d *def_map;
- tree real_var = SSA_NAME_VAR (var);
-
- if (get_value_for (real_var, currdefs) != var)
- {
- ssa_stats.blocked_by_life_crossing++;
- return false;
- }
-
- /* This is gross, but since it's temporary, close your eyes. It's needed
- to avoid miscompiling java/jcf-write.c:generate_classfile, where the
- fully pruned SSA form is not inserting PHI nodes in the main loop of
- the function for variable 'ptr'. This makes two versions of 'ptr'
- live at the same time.
-
- If there are any blocks between VAR's definition block and BB where
- VAR is defined again, then two versions of VAR are live at the same
- time. Notice that this heuristic assumes that blocks in the path from
- DEF_BB to BB will be numbered in ascending order. This is only true
- when the CFG is initially built. But since we only use this in the
- SSA renaming pass, it should still be safe to assume. Another
- limitation is that if there exists another overlapping definition for
- VAR in block BB, this code will not realize that. */
- def_map = get_def_blocks_for (real_var);
- def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (var));
- if (def_bb && bitmap_first_set_bit (def_map->def_blocks) >= 0)
- EXECUTE_IF_SET_IN_BITMAP (def_map->def_blocks, def_bb->index + 1, i,
- { if (i < bb->index) return false; });
-
- /* VAR doesn't have definitions between DEF_BB and BB. If BB is inside a
- loop but DEF_BB is outside BB's loop, we may still have definitions
- below BB wrapping around in cases where the pruned SSA form has
- removed a PHI function for VAR at the header block for the loop. */
- {
- if (def_bb
- && loops
- && bb->loop_depth > 0
- && (def_bb->loop_depth == 0
- || !flow_bb_inside_loop_p (bb->loop_father, def_bb)))
- EXECUTE_IF_SET_IN_BITMAP (def_map->def_blocks, bb->index + 1, i,
- {
- basic_block other_def_bb = BASIC_BLOCK (i);
-
- /* If BB is inside the same loop L as the other definition block
- (OTHER_DEF_BB), definition at OTHER_DEF_BB wraps around and
- reaches VAR at BB. Meaning that the other definition at
- OTHER_DEF_BB overlaps with VAR at DEF_BB. */
- if (flow_bb_inside_loop_p (other_def_bb->loop_father, bb)
- || flow_bb_inside_loop_p (bb->loop_father, other_def_bb))
- return false;
- });
- }
-
-
- return true;
- }
- #endif
--- 2641,2643 ----