This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [tree-ssa] Re: COND_EXPR lowering patch
- From: law at redhat dot com
- To: Andrew MacLeod <amacleod at redhat dot com>
- Cc: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>, gcc mailing list <gcc at gcc dot gnu dot org>
- Date: Mon, 25 Aug 2003 09:50:19 -0600
- Subject: Re: [tree-ssa] Re: COND_EXPR lowering patch
- Reply-to: law at redhat dot com
In message <1061819890.2413.39.camel@p4>, Andrew MacLeod writes:
>> It was discussed before, but afair there was not any definitive
>> conclusion. To me the following scheme seems to be the best:
>> The control structures removal part will only be activated with -O3
>> and will be done using regular control dependency analysis.
>>
>I think it better to simply handle the DCE issue under flag control so
>we can choose to call light or heavyweight DCE at our whim.
Or have it trigger based on whether or not we have valid
post-dominator information. Again, I'm starting to think about how
DSE is going to play into this.
I expect DSE will probably be a separate pass -- the DSE's I've worked
with have a pretty different structure than our DCE, trying to integrate
them would be nontrivial.
DSE benefits from having the post-dominators, since we effectively
want to eliminate dead stores in post-dominator tree ie
BBx BBy
store X store Y
\ /
\ /
BBx
store X
store Y
If you do DSE using the post-dominators to build the post-dominator
tree, then you get to remove the store to X in BBx and the store Y
in BBy. Conceptually its the same thing as the dominator tree,
except its on the reverse flow graph.
Anyway, given that DSE will need the post-dominators and it does not
modify the CFG, it _may_ make sense to have DCE follow DSE and thus
share the cost of building the post-doms. Of course the two passes
interact with each other in fun and interesting ways, so it's really
not clear at this time what ordering (if any) makes the most sense.
There may be more modern DSE implementations which run in parallel
with DCE at which point ordering is not an issue).
>a more convienient time. (I went digging but didnt find a copy of Jeffs
>control dependancy patch. Give me a copy and I'll work with it if you
>want)
Attached. I never posted it to the list. This is the code in the
last state I had it.
I think these diffs were set up to allow passing in a flag which
enabled removal of conditionals/control structures and thus
avoided the overhead of pdom calculation in that case.
I think the code still uses parents and marks them as necessary --
that was done to see if using that got us through the worklist
faster. I'm pretty sure it was a wash and you don't need to
muck around calling parent_stmt at all.
It cleaned up some of the code which cached cond_checked and
goto_checked as well. Basically we just need to know which
blocks were visited since any "magic" stuff happens once the first
time the block becomes executable.
Note there may be some debugging statements left in the code -- look
look for "Yow".
*** tree-ssa-dce.c 2003-08-05 10:41:10.000000000 -0600
--- tree-ssa-dce.c.SAVE 2003-08-04 17:03:17.000000000 -0600
*************** Software Foundation, 59 Temple Place - S
*** 40,47 ****
e.g., function calls, writing a value to memory, etc;
2. Propagating necessary instructions, e.g., the instructions
giving values to operands in necessary instructions; and
! 3. Removing dead instructions (except replacing dead conditionals
! with unconditional jumps). */
#include "config.h"
#include "system.h"
--- 40,46 ----
e.g., function calls, writing a value to memory, etc;
2. Propagating necessary instructions, e.g., the instructions
giving values to operands in necessary instructions; and
! 3. Removing dead instructions, including conditionals. */
#include "config.h"
#include "system.h"
*************** static FILE *dump_file;
*** 69,76 ****
static int dump_flags;
static varray_type worklist;
- static dominance_info dom_info = NULL;
- static dominance_info pdom_info = NULL;
static struct stmt_stats
{
--- 68,73 ----
*************** static struct stmt_stats
*** 82,101 ****
static htab_t needed_stmts;
/* Forward function prototypes. */
static bool necessary_p (tree);
static int mark_tree_necessary (tree);
static void mark_necessary (tree);
static void print_stats (void);
static bool need_to_preserve_store (tree);
! static void find_useful_stmts (void);
! static bool stmt_useful_p (tree);
! static void process_worklist (void);
! static void remove_dead_stmts (void);
! static void remove_dead_stmt (block_stmt_iterator *, basic_block);
static void remove_dead_phis (basic_block);
! static void remove_conditional (basic_block);
/* Is a tree necessary? */
--- 79,259 ----
static htab_t needed_stmts;
+ /* A map from blocks to the edges on which they are control dependent. */
+ typedef struct {
+ /* A dynamically allocated array. The Nth element corresponds to
+ the block with index N + 2. The Ith bit in the bitmap is set if
+ that block is dependent on the Ith edge. */
+ bitmap *data;
+ /* The number of elements in the array. */
+ int length;
+ } control_dependent_block_to_edge_map_s, *control_dependent_block_to_edge_map
;
+
/* Forward function prototypes. */
static bool necessary_p (tree);
static int mark_tree_necessary (tree);
static void mark_necessary (tree);
static void print_stats (void);
static bool need_to_preserve_store (tree);
! static void find_useful_stmts (int);
! static bool stmt_useful_p (tree, int);
! static void process_worklist (control_dependent_block_to_edge_map cdbte,
! struct edge_list *, int);
! static void remove_dead_stmts (dominance_info);
! static void remove_dead_stmt (block_stmt_iterator *, basic_block,
dominance_info);
static void remove_dead_phis (basic_block);
! static void remove_conditional (basic_block, dominance_info);
! static control_dependent_block_to_edge_map control_dependent_block_to_edge_ma
p_create
! (size_t num_basic_blocks);
! static void set_control_dependent_block_to_edge_map_bit
! (control_dependent_block_to_edge_map c, basic_block bb, int edge_index);
! static void control_dependent_block_to_edge_map_free
! (control_dependent_block_to_edge_map c);
! static void find_all_control_dependences
! (struct edge_list *el, dominance_info pdom,
! control_dependent_block_to_edge_map cdbte);
! static void find_control_dependence
! (struct edge_list *el, int edge_index, dominance_info pdom,
! control_dependent_block_to_edge_map cdbte);
! static basic_block find_pdom (dominance_info pdom, basic_block block);
!
! /* Recording which blocks are control dependent on which edges. We
! expect each block to be control dependent on very few edges so we
! use a bitmap for each block recording its edges. An array holds
! the bitmap. Its position 0 entry holds the bitmap for block
! INVALID_BLOCK+1 so that all blocks, including the entry and exit
! blocks can participate in the data structure. */
!
! /* Create a control_dependent_block_to_edge_map, given the number
! NUM_BASIC_BLOCKS of non-entry, non-exit basic blocks, e.g.,
! n_basic_blocks. This memory must be released using
! control_dependent_block_to_edge_map_free (). */
!
! static control_dependent_block_to_edge_map
! control_dependent_block_to_edge_map_create (size_t num_basic_blocks)
! {
! int i;
! control_dependent_block_to_edge_map c
! = xmalloc (sizeof (control_dependent_block_to_edge_map_s));
! c->length = num_basic_blocks - (INVALID_BLOCK+1);
! c->data = xmalloc ((size_t) c->length*sizeof (bitmap));
! for (i = 0; i < c->length; ++i)
! c->data[i] = BITMAP_XMALLOC ();
!
! return c;
! }
!
! /* Indicate block BB is control dependent on an edge with index
! EDGE_INDEX in the mapping C of blocks to edges on which they are
! control-dependent. */
!
! static void
! set_control_dependent_block_to_edge_map_bit (control_dependent_block_to_edge_
map c,
! basic_block bb, int edge_index)
! {
! #ifdef ENABLE_CHECKING
! if (bb->index - (INVALID_BLOCK+1) >= c->length)
! abort ();
! #endif
!
! bitmap_set_bit (c->data[bb->index - (INVALID_BLOCK+1)],
! edge_index);
! }
!
! /* Execute CODE for each edge (given number EDGE_NUMBER within the
! CODE) for which block BB is control dependent, returning no output.
! CDBTE is the mapping of blocks to edges on which they are
control-dependent. */
+ #define EXECUTE_IF_CONTROL_DEPENDENT(CDBTE, BB, EDGE_NUMBER, CODE) \
+ EXECUTE_IF_SET_IN_BITMAP \
+ (CDBTE->data[(BB)->index - (INVALID_BLOCK+1)], 0, EDGE_NUMBER, CODE)
+
+ /* Destroy a control_dependent_block_to_edge_map C. */
+
+ static void
+ control_dependent_block_to_edge_map_free (control_dependent_block_to_edge_map
c)
+ {
+ int i;
+ for (i = 0; i < c->length; ++i)
+ BITMAP_XFREE (c->data[i]);
+ free (c);
+ }
+
+ /* Record all blocks' control dependences on all edges in the edge
+ list EL, ala Morgan, Section 3.6. The mapping PDOM of blocks to
+ their postdominators are used, and results are stored in CDBTE,
+ which should be empty. */
+
+ static void
+ find_all_control_dependences (struct edge_list *el, dominance_info pdom,
+ control_dependent_block_to_edge_map cdbte)
+ {
+ int i;
+
+ for (i = 0; i < NUM_EDGES (el); ++i)
+ find_control_dependence (el, i, pdom, cdbte);
+ }
+
+ /* Determine all blocks' control dependences on the given edge with
+ edge_list EL index EDGE_INDEX, ala Morgan, Section 3.6. The
+ mapping PDOM of blocks to their postdominators are used, and
+ results are stored in CDBTE, which is assumed to be initialized
+ with zeros in each (block b', edge) position. */
+
+ static void
+ find_control_dependence (struct edge_list *el, int edge_index,
+ dominance_info pdom,
+ control_dependent_block_to_edge_map cdbte)
+ {
+ basic_block current_block;
+ basic_block ending_block;
+
+ #ifdef ENABLE_CHECKING
+ if (INDEX_EDGE_PRED_BB (el, edge_index) == EXIT_BLOCK_PTR)
+ abort ();
+ #endif
+
+ ending_block =
+ (INDEX_EDGE_PRED_BB (el, edge_index) == ENTRY_BLOCK_PTR)
+ ? ENTRY_BLOCK_PTR->next_bb
+ : find_pdom (pdom, INDEX_EDGE_PRED_BB (el, edge_index));
+
+ for (current_block = INDEX_EDGE_SUCC_BB (el, edge_index);
+ current_block != ending_block && current_block != EXIT_BLOCK_PTR;
+ current_block = find_pdom (pdom, current_block))
+ {
+ set_control_dependent_block_to_edge_map_bit (cdbte,
+ current_block,
+ edge_index);
+ }
+ }
+
+ /* Find the immediate postdominator PDOM of the specified basic block
+ BLOCK. This function is necessary because some blocks have
+ negative numbers. */
+
+ static basic_block
+ find_pdom (dominance_info pdom, basic_block block)
+ {
+ #ifdef ENABLE_CHECKING
+ if (!block)
+ abort ();
+ if (block->index == INVALID_BLOCK)
+ abort ();
+ #endif
+
+ if (block == ENTRY_BLOCK_PTR)
+ return ENTRY_BLOCK_PTR->next_bb;
+ else if (block == EXIT_BLOCK_PTR)
+ return EXIT_BLOCK_PTR;
+ else
+ {
+ basic_block bb = get_immediate_dominator (pdom, block);
+ if (!bb)
+ return EXIT_BLOCK_PTR;
+ return bb;
+ }
+ }
/* Is a tree necessary? */
*************** mark_necessary (tree t)
*** 144,151 ****
tree parent = parent_stmt (t);
while (parent)
{
! mark_tree_necessary (parent);
! parent = parent_stmt (parent);
}
}
}
--- 302,311 ----
tree parent = parent_stmt (t);
while (parent)
{
! if (mark_tree_necessary (parent))
! parent = parent_stmt (parent);
! else
! break;
}
}
}
*************** need_to_preserve_store (tree var)
*** 214,220 ****
calls and stores to file level variables. */
static void
! find_useful_stmts (void)
{
basic_block bb;
block_stmt_iterator i;
--- 374,380 ----
calls and stores to file level variables. */
static void
! find_useful_stmts (int remove_conditionals)
{
basic_block bb;
block_stmt_iterator i;
*************** find_useful_stmts (void)
*** 233,239 ****
{
tree stmt = bsi_stmt (i);
! if (stmt_useful_p (stmt))
mark_necessary (stmt);
}
}
--- 393,399 ----
{
tree stmt = bsi_stmt (i);
! if (stmt_useful_p (stmt, remove_conditionals))
mark_necessary (stmt);
}
}
*************** find_useful_stmts (void)
*** 243,287 ****
/* Return true if STMT is necessary. */
static bool
! stmt_useful_p (tree stmt)
{
varray_type ops;
size_t i;
/* Instructions that are implicitly live. Function calls, asm and return
statements are required. Labels and BIND_EXPR nodes are kept because
they are control flow, and we have no way of knowing whether they can
be removed. DCE can eliminate all the other statements in a block,
and CFG can then remove the block and labels. */
! if ((TREE_CODE (stmt) == ASM_EXPR)
! || (TREE_CODE (stmt) == RETURN_EXPR)
! || (TREE_CODE (stmt) == CASE_LABEL_EXPR)
! || (TREE_CODE (stmt) == LABEL_EXPR)
! || (TREE_CODE (stmt) == BIND_EXPR)
! || (TREE_CODE (stmt) == CALL_EXPR)
! || ((TREE_CODE (stmt) == MODIFY_EXPR)
! && (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR))
! || (TREE_CODE (stmt) == TRY_CATCH_EXPR)
! || (TREE_CODE (stmt) == TRY_FINALLY_EXPR)
! || (TREE_CODE (stmt) == EH_FILTER_EXPR)
! || (TREE_CODE (stmt) == CATCH_EXPR))
return true;
- /* GOTO_EXPR nodes to nonlocal labels need to be kept (This fixes
- gcc.c-torture/execute/920501-7.c and others that have nested functions
- with nonlocal gotos). FIXME: If we were doing IPA we could determine
- if the label is actually reachable. */
- if (TREE_CODE (stmt) == GOTO_EXPR)
- {
- edge e;
- basic_block bb = bb_for_stmt (stmt);
-
- if (bb)
- for (e = bb->succ; e; e = e->succ_next)
- if (e->dest == EXIT_BLOCK_PTR && e->flags & EDGE_ABNORMAL)
- return true;
- }
-
/* Examine all the stores in this statement. */
get_stmt_operands (stmt);
--- 403,435 ----
/* Return true if STMT is necessary. */
static bool
! stmt_useful_p (tree stmt, int remove_conditionals)
{
varray_type ops;
size_t i;
+ enum tree_code code = TREE_CODE (stmt);
/* Instructions that are implicitly live. Function calls, asm and return
statements are required. Labels and BIND_EXPR nodes are kept because
they are control flow, and we have no way of knowing whether they can
be removed. DCE can eliminate all the other statements in a block,
and CFG can then remove the block and labels. */
! if (code == ASM_EXPR
! || code == RETURN_EXPR
! || code == CASE_LABEL_EXPR
! || code == LABEL_EXPR
! || code == BIND_EXPR
! || code == CALL_EXPR
! || (code == MODIFY_EXPR
! && TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
! || code == TRY_CATCH_EXPR
! || code == TRY_FINALLY_EXPR
! || code == EH_FILTER_EXPR
! || code == CATCH_EXPR
! || (! remove_conditionals
! && (code == COND_EXPR || code == SWITCH_EXPR)))
return true;
/* Examine all the stores in this statement. */
get_stmt_operands (stmt);
*************** stmt_useful_p (tree stmt)
*** 308,322 ****
this value to the worklist. */
static void
! process_worklist (void)
{
basic_block bb;
- tree i, j;
edge e;
- bitmap cond_checked, goto_checked;
! cond_checked = BITMAP_XMALLOC ();
! goto_checked = BITMAP_XMALLOC ();
while (VARRAY_ACTIVE_SIZE (worklist) > 0)
{
--- 456,470 ----
this value to the worklist. */
static void
! process_worklist (control_dependent_block_to_edge_map cdbte, struct
edge_list *el, int remove_conditionals)
{
+ tree i;
+ bitmap blocks_visited;
+ int edge_number;
basic_block bb;
edge e;
! blocks_visited = BITMAP_XMALLOC ();
while (VARRAY_ACTIVE_SIZE (worklist) > 0)
{
*************** process_worklist (void)
*** 331,355 ****
fprintf (dump_file, "\n");
}
! /* Find any predecessor which 'goto's this block, and mark the goto
! as necessary since it is control flow. A block's predecessors only
! need to be checked once. */
bb = bb_for_stmt (i);
! if (bb && !bitmap_bit_p (goto_checked, bb->index))
! {
! bitmap_set_bit (goto_checked, bb->index);
for (e = bb->pred; e != NULL; e = e->pred_next)
{
basic_block p = e->src;
if (p == ENTRY_BLOCK_PTR)
continue;
! j = last_stmt (p);
! if ((e->flags & EDGE_ABNORMAL)
! || (j && TREE_CODE (j) == GOTO_EXPR))
! mark_necessary (j);
}
}
!
if (TREE_CODE (i) == PHI_NODE)
{
int k;
--- 479,519 ----
fprintf (dump_file, "\n");
}
! /* The first time we consider a block executable we need to mark
! jumps leading to the block as well as the block's parent control
! structure as necessary. */
bb = bb_for_stmt (i);
! if (bb && !bitmap_bit_p (blocks_visited, bb->index))
! {
! /* Mark this block as visited. */
! bitmap_set_bit (blocks_visited, bb->index);
!
! /* Mark GOTO_EXPRs which reach our block as necessary. */
for (e = bb->pred; e != NULL; e = e->pred_next)
{
+ tree last;
basic_block p = e->src;
+
if (p == ENTRY_BLOCK_PTR)
continue;
! last = last_stmt (p);
! if (last && TREE_CODE (last) == GOTO_EXPR)
! mark_necessary (last);
}
+
+ /* Mark the control dependent edges leading to this statement's
+ block as necessary. */
+ if (remove_conditionals)
+ EXECUTE_IF_CONTROL_DEPENDENT (cdbte, bb, edge_number,
+ {
+ basic_block dep_bb = INDEX_EDGE_PRED_BB (el, edge_number);
+
+ if (!bitmap_bit_p (blocks_visited, dep_bb->index))
+ mark_necessary (last_stmt (dep_bb));
+ });
+
}
!
if (TREE_CODE (i) == PHI_NODE)
{
int k;
*************** process_worklist (void)
*** 359,396 ****
for (k = 0; k < PHI_NUM_ARGS (i); k++)
{
tree arg = PHI_ARG_DEF (i, k);
! if (TREE_CODE (arg) == SSA_NAME)
! mark_necessary (SSA_NAME_DEF_STMT (PHI_ARG_DEF (i, k)));
! }
! /* Look at all the predecessors, and if this PHI is being fed
! from a conditional expression, mark that conditional
! as necessary. Copies may be needed on an edge later.
! This only needs to be done once per block. */
! k = bb_for_stmt (i)->index;
! if (!bitmap_bit_p (cond_checked, k))
! {
! bitmap_set_bit (cond_checked, k);
! for (e = bb->pred; e; e = e->pred_next)
! {
! basic_block pred, par;
! pred = e->src;
! if (pred != ENTRY_BLOCK_PTR)
! {
! par = parent_block (pred);
! if (par)
! {
! tree last;
! last = last_stmt (par);
! if (last && (TREE_CODE (last) == COND_EXPR
! || TREE_CODE (last) == SWITCH_EXPR))
! {
! mark_necessary (last);
! }
! }
! }
! }
}
}
else
--- 523,539 ----
for (k = 0; k < PHI_NUM_ARGS (i); k++)
{
tree arg = PHI_ARG_DEF (i, k);
! basic_block pred_bb = PHI_ARG_EDGE (i, k)->src;
! if (TREE_CODE (arg) == SSA_NAME)
! mark_necessary (SSA_NAME_DEF_STMT (arg));
! /* PHI nodes also have control dependencies for each of their
! arguments. */
! if (remove_conditionals && pred_bb != ENTRY_BLOCK_PTR)
! EXECUTE_IF_CONTROL_DEPENDENT (cdbte, pred_bb, edge_number,
! mark_necessary (last_stmt (INDEX_EDGE_PRED_BB (el,
! edge_number))));
}
}
else
*************** process_worklist (void)
*** 428,435 ****
}
}
}
! BITMAP_XFREE (cond_checked);
! BITMAP_XFREE (goto_checked);
}
--- 571,577 ----
}
}
}
! BITMAP_XFREE (blocks_visited);
}
*************** process_worklist (void)
*** 437,458 ****
contributes nothing to the program, and can be deleted. */
static void
! remove_dead_stmts (void)
{
basic_block bb;
tree t;
block_stmt_iterator i;
! dom_info = NULL;
! pdom_info = NULL;
!
FOR_EACH_BB_REVERSE (bb)
{
bsi_list_p stack;
/* Remove dead PHI nodes. */
remove_dead_phis (bb);
! /* Remove dead statements. */
FOR_EACH_BSI_IN_REVERSE (stack, bb, i)
{
t = bsi_stmt (i);
--- 579,602 ----
contributes nothing to the program, and can be deleted. */
static void
! remove_dead_stmts (dominance_info pdom_info)
{
basic_block bb;
tree t;
block_stmt_iterator i;
! /* Remove dead statements in each basic block. Running through the
! blocks in reverse order allows us to detect and delete more
! useless COMPOUND_EXPRs. */
FOR_EACH_BB_REVERSE (bb)
{
bsi_list_p stack;
+
/* Remove dead PHI nodes. */
remove_dead_phis (bb);
! /* Remove dead statements. Removing them in reverse order allows
! us to remove more useless COMPOUND_EXPRs within a basic block. */
FOR_EACH_BSI_IN_REVERSE (stack, bb, i)
{
t = bsi_stmt (i);
*************** remove_dead_stmts (void)
*** 460,475 ****
/* If `i' is not in `necessary' then remove from B. */
if (!necessary_p (t))
! remove_dead_stmt (&i, bb);
}
}
-
- /* If we needed the dominance info, free it now. */
- if (dom_info != NULL)
- free_dominance_info (dom_info);
-
- if (pdom_info != NULL)
- free_dominance_info (pdom_info);
}
--- 604,612 ----
/* If `i' is not in `necessary' then remove from B. */
if (!necessary_p (t))
! remove_dead_stmt (&i, bb, pdom_info);
}
}
}
*************** remove_dead_phis (basic_block bb)
*** 513,519 ****
/* Remove dead statement pointed by iterator I from block BB. */
static void
! remove_dead_stmt (block_stmt_iterator *i, basic_block bb)
{
tree t;
--- 650,656 ----
/* Remove dead statement pointed by iterator I from block BB. */
static void
! remove_dead_stmt (block_stmt_iterator *i, basic_block bb, dominance_info
pdom_info)
{
tree t;
*************** remove_dead_stmt (block_stmt_iterator *i
*** 544,550 ****
{
tree parent = parent_stmt (t);
if (parent == NULL_TREE || necessary_p (parent))
! remove_conditional (bb);
}
bsi_remove (i);
--- 681,687 ----
{
tree parent = parent_stmt (t);
if (parent == NULL_TREE || necessary_p (parent))
! remove_conditional (bb, pdom_info);
}
bsi_remove (i);
*************** remove_dead_stmt (block_stmt_iterator *i
*** 553,588 ****
/* Main routine to eliminate dead code. */
void
! tree_ssa_dce (tree fndecl)
{
tree fnbody;
timevar_push (TV_TREE_DCE);
memset ((void *) &stats, 0, sizeof (stats));
fnbody = DECL_SAVED_TREE (fndecl);
if (fnbody == NULL_TREE)
abort ();
VARRAY_TREE_INIT (worklist, 64, "work list");
needed_stmts = htab_create (64, htab_hash_pointer, htab_eq_pointer, NULL);
! /* Initialize dump_file for debugging dumps. */
! dump_file = dump_begin (TDI_dce, &dump_flags);
! find_useful_stmts ();
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nProcessing worklist:\n");
! process_worklist ();
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nEliminating unnecessary instructions:\n");
! remove_dead_stmts ();
cleanup_tree_cfg ();
/* Debugging dumps. */
--- 690,739 ----
/* Main routine to eliminate dead code. */
void
! tree_ssa_dce (tree fndecl, int remove_conditionals)
{
tree fnbody;
+ control_dependent_block_to_edge_map cdbte;
+ dominance_info pdom;
+ struct edge_list *el;
timevar_push (TV_TREE_DCE);
memset ((void *) &stats, 0, sizeof (stats));
+ /* Initialize dump_file for debugging dumps. */
+ dump_file = dump_begin (TDI_dce, &dump_flags);
+
fnbody = DECL_SAVED_TREE (fndecl);
+
+ #ifdef ENABLE_CHECKING
if (fnbody == NULL_TREE)
abort ();
+ #endif
VARRAY_TREE_INIT (worklist, 64, "work list");
needed_stmts = htab_create (64, htab_hash_pointer, htab_eq_pointer, NULL);
! if (remove_conditionals)
! {
! cdbte = control_dependent_block_to_edge_map_create (last_basic_block);
! pdom = calculate_dominance_info (CDI_POST_DOMINATORS);
! el = create_edge_list ();
! find_all_control_dependences (el, pdom, cdbte);
! }
! find_useful_stmts (remove_conditionals);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nProcessing worklist:\n");
! process_worklist (cdbte, el, remove_conditionals);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nEliminating unnecessary instructions:\n");
! remove_dead_stmts (pdom);
cleanup_tree_cfg ();
/* Debugging dumps. */
*************** tree_ssa_dce (tree fndecl)
*** 595,600 ****
--- 746,758 ----
htab_delete (needed_stmts);
+ if (remove_conditionals)
+ {
+ control_dependent_block_to_edge_map_free (cdbte);
+ free (pdom);
+ free_edge_list (el);
+ }
+
timevar_pop (TV_TREE_DCE);
}
*************** tree_ssa_dce (tree fndecl)
*** 602,619 ****
/* Remove the conditional statement starting at block BB. */
static void
! remove_conditional (basic_block bb)
{
basic_block pdom_bb;
edge e;
! /* Calculate dominance info, if it hasn't been computed yet. */
! if (pdom_info == NULL)
! pdom_info = calculate_dominance_info (CDI_POST_DOMINATORS);
!
! if (dom_info == NULL)
! dom_info = calculate_dominance_info (CDI_DOMINATORS);
!
pdom_bb = get_immediate_dominator (pdom_info, bb);
/* Remove all outgoing edges. */
--- 760,771 ----
/* Remove the conditional statement starting at block BB. */
static void
! remove_conditional (basic_block bb, dominance_info pdom_info)
{
basic_block pdom_bb;
edge e;
! printf("Yow\n");
pdom_bb = get_immediate_dominator (pdom_info, bb);
/* Remove all outgoing edges. */