Commit b53978a3 by Jeffrey Oldham Committed by Mark Mitchell

Makefile.in (OBJS): Added dce.o.

	* Makefile.in (OBJS): Added dce.o.
	(ssa.o): Updated target to include ssa.h.
	(flow.o): Likewise.
	(toplev.o): Likewise.
	(dce.o): Created target.
	* basic-block.h: Added comments.
	(INVALID_BLOCK): Added definition.
	(connect_infinite_loops_to_exit): Added declaration.
	Moved SSA declarations to ssa.h.
	* flow.c: Added inclusion of ssa.h.
	(struct depth_first_search_dsS, depth_first_search_ds):
	Added definitions.
	(compute_immediate_postdominators): Added definition.
	(connect_infinite_loops_to_exit): Likewise.
	(flow_dfs_compute_reverse_init): Likewise.
	(flow_dfs_compute_reverse_add_bb): Likewise.
	(flow_dfs_compute_reverse_execute): Likewise.
	(flow_dfs_compute_reverse_finish): Likewise.
	* rtl.h (rtx/in_struct): Added use to determine insn necessity.
	(LABEL_P): Added definition.
	(JUMP_P): Likewise.
	(NOTE_P): Likewise.
	(BARRIER_P): Likewise.
	(JUMP_TABLE_DATA_P): Likewise.
	(INSN_DEAD_CODE_P): Likewise.
	* ssa.c: Replaced inclusions with ssa.h inclusion.
	(CONVERT_HARD_REGISTER_TO_SSA_P): Moved to ssa.h.
	(rename_registers): Removed unnecessary variables.
	* ssa.h: Created by moving declarations from ssa.c and
	basic-block.h.
	* timevar.def: Defined TV_DEAD_CODE_ELIM.
	* toplev.c: Added ssa.h inclusion.
	(dump_file_index): Added DFI_dce.
	(dump_file): Added "dce" entry.
	Defined flag_ssa.
	(f_options): Added dce entry.
	* invoke.texi: Document -fdce.  Emphasize experimental status of
	-fssa.

Co-Authored-By: Mark Mitchell <mark@codesourcery.com>

From-SVN: r35419
parent 79c2c6da
2000-08-01 Jeffrey Oldham <oldham@codesourcery.com>
Mark Mitchell <mark@codesourcery.com>
* Makefile.in (OBJS): Added dce.o.
(ssa.o): Updated target to include ssa.h.
(flow.o): Likewise.
(toplev.o): Likewise.
(dce.o): Created target.
* basic-block.h: Added comments.
(INVALID_BLOCK): Added definition.
(connect_infinite_loops_to_exit): Added declaration.
Moved SSA declarations to ssa.h.
* flow.c: Added inclusion of ssa.h.
(struct depth_first_search_dsS, depth_first_search_ds):
Added definitions.
(compute_immediate_postdominators): Added definition.
(connect_infinite_loops_to_exit): Likewise.
(flow_dfs_compute_reverse_init): Likewise.
(flow_dfs_compute_reverse_add_bb): Likewise.
(flow_dfs_compute_reverse_execute): Likewise.
(flow_dfs_compute_reverse_finish): Likewise.
* rtl.h (rtx/in_struct): Added use to determine insn necessity.
(LABEL_P): Added definition.
(JUMP_P): Likewise.
(NOTE_P): Likewise.
(BARRIER_P): Likewise.
(JUMP_TABLE_DATA_P): Likewise.
(INSN_DEAD_CODE_P): Likewise.
* ssa.c: Replaced inclusions with ssa.h inclusion.
(CONVERT_HARD_REGISTER_TO_SSA_P): Moved to ssa.h.
(rename_registers): Removed unnecessary variables.
* ssa.h: Created by moving declarations from ssa.c and
basic-block.h.
* timevar.def: Defined TV_DEAD_CODE_ELIM.
* toplev.c: Added ssa.h inclusion.
(dump_file_index): Added DFI_dce.
(dump_file): Added "dce" entry.
Defined flag_ssa.
(f_options): Added dce entry.
* invoke.texi: Document -fdce. Emphasize experimental status of
-fssa.
2000-08-01 Zack Weinberg <zack@wolery.cumb.org>
* cpperror.c (v_message): Split into _cpp_begin_message and
......
......@@ -696,7 +696,7 @@ OBJS = diagnostic.o \
profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \
mbchar.o splay-tree.o graph.o sbitmap.o resource.o hash.o predict.o \
lists.o ggc-common.o $(GGC) simplify-rtx.o ssa.o bb-reorder.o \
sibcall.o conflict.o timevar.o ifcvt.o
sibcall.o conflict.o timevar.o ifcvt.o dce.o
# GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
......@@ -1242,7 +1242,7 @@ toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) function.h \
flags.h input.h $(INSN_ATTR_H) xcoffout.h defaults.h output.h diagnostic.h \
insn-codes.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h dwarfout.h \
dwarf2out.h sdbout.h dbxout.h $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \
graph.h loop.h except.h regs.h $(TIMEVAR_H) $(lang_options_files)
graph.h loop.h except.h regs.h $(TIMEVAR_H) $(lang_options_files) ssa.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(MAYBE_USE_COLLECT2) \
-DTARGET_NAME=\"$(target_alias)\" \
-c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
......@@ -1326,10 +1326,11 @@ resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h system.h \
$(INSN_ATTR_H) except.h
lcm.o : lcm.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
real.h insn-config.h $(INSN_ATTR_H) $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H)
ssa.o : ssa.c $(CONFIG_H) system.h $(RTL_H) varray.h sbitmap.h \
$(HASHTAB_H) $(REGS_H) hard-reg-set.h flags.h function.h real.h \
insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) \
output.h
ssa.o : ssa.c $(CONFIG_H) system.h $(REGS_H) varray.h \
hard-reg-set.h flags.h function.h real.h insn-config.h $(RECOG_H) \
$(BASIC_BLOCK_H) output.h ssa.h
dce.o : dce.c $(CONFIG_H) system.h $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H) \
ssa.h insn-config.h $(RECOG_H) output.h
conflict.o : conflict.c $(CONFIG_H) system.h $(OBSTACK_H) $(HASHTAB_H) \
$(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H)
profile.o : profile.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
......@@ -1345,7 +1346,7 @@ unroll.o : unroll.c $(CONFIG_H) system.h $(RTL_H) insn-config.h function.h \
hard-reg-set.h varray.h $(BASIC_BLOCK_H)
flow.o : flow.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h insn-config.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
insn-flags.h function.h except.h $(EXPR_H)
insn-flags.h function.h except.h $(EXPR_H) ssa.h
combine.o : combine.c $(CONFIG_H) system.h $(RTL_H) flags.h function.h \
insn-config.h insn-flags.h insn-codes.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
$(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h
......
......@@ -141,6 +141,18 @@ typedef struct edge_def {
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
/* Basic blocks need not start with a label nor end with a jump insn.
For example, a previous basic block may just "conditionally fall"
into the succeeding basic block, and the last basic block need not
end with a jump insn. Block 0 is a descendant of the entry block.
A basic block beginning with two labels cannot have notes between
the labels.
Data for jump tables are stored in jump_insns that occur in no
basic block even though these insns can follow or precede insns in
basic blocks. */
/* Basic block information indexed by block number. */
typedef struct basic_block_def {
/* The first and last insns of the block. */
......@@ -210,6 +222,9 @@ extern regset regs_live_at_setjmp;
#define ENTRY_BLOCK (-1)
#define EXIT_BLOCK (-2)
/* Special block number not valid for any block. */
#define INVALID_BLOCK (-3)
/* Similarly, block pointers for the edge list. */
extern struct basic_block_def entry_exit_blocks[2];
#define ENTRY_BLOCK_PTR (&entry_exit_blocks[0])
......@@ -230,6 +245,7 @@ extern void insert_insn_on_edge PARAMS ((rtx, edge));
extern void commit_edge_insertions PARAMS ((void));
extern void remove_fake_edges PARAMS ((void));
extern void add_noreturn_fake_exit_edges PARAMS ((void));
extern void connect_infinite_loops_to_exit PARAMS ((void));
extern rtx flow_delete_insn PARAMS ((rtx));
extern void flow_delete_insn_chain PARAMS ((rtx, rtx));
extern void make_edge PARAMS ((sbitmap *, basic_block,
......@@ -514,13 +530,4 @@ extern conflict_graph conflict_graph_compute
PARAMS ((regset,
partition));
/* In ssa.c */
extern void convert_to_ssa PARAMS ((void));
extern void convert_from_ssa PARAMS ((void));
typedef int (*successor_phi_fn) PARAMS ((rtx, int, int, void *));
extern int for_each_successor_phi PARAMS ((basic_block bb,
successor_phi_fn,
void *));
extern int in_ssa_form;
#endif /* _BASIC_BLOCK_H */
This diff is collapsed. Click to expand it.
......@@ -136,6 +136,7 @@ Boston, MA 02111-1307, USA. */
#include "recog.h"
#include "insn-flags.h"
#include "expr.h"
#include "ssa.h"
#include "obstack.h"
#include "splay-tree.h"
......@@ -308,6 +309,20 @@ struct propagate_block_info
int flags;
};
/* Store the data structures necessary for depth-first search. */
struct depth_first_search_dsS {
/* stack for backtracking during the algorithm */
basic_block *stack;
/* number of edges in the stack. That is, positions 0, ..., sp-1
have edges. */
unsigned int sp;
/* record of basic blocks already seen by depth-first search */
sbitmap visited_blocks;
};
typedef struct depth_first_search_dsS *depth_first_search_ds;
/* Forward declarations */
static int count_basic_blocks PARAMS ((rtx));
static void find_basic_blocks_1 PARAMS ((rtx));
......@@ -398,6 +413,14 @@ static int flow_loop_nested_p PARAMS ((struct loop *, struct loop *));
static int flow_loop_exits_find PARAMS ((const sbitmap, edge **));
static int flow_loop_nodes_find PARAMS ((basic_block, basic_block, sbitmap));
static int flow_depth_first_order_compute PARAMS ((int *, int *));
static void flow_dfs_compute_reverse_init
PARAMS ((depth_first_search_ds));
static void flow_dfs_compute_reverse_add_bb
PARAMS ((depth_first_search_ds, basic_block));
static basic_block flow_dfs_compute_reverse_execute
PARAMS ((depth_first_search_ds));
static void flow_dfs_compute_reverse_finish
PARAMS ((depth_first_search_ds));
static basic_block flow_loop_pre_header_find PARAMS ((basic_block, const sbitmap *));
static void flow_loop_tree_node_add PARAMS ((struct loop *, struct loop *));
static void flow_loops_tree_build PARAMS ((struct loops *));
......@@ -3741,7 +3764,7 @@ init_propagate_block_info (bb, live, local_set, flags)
&& GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
{
rtx mem = SET_DEST (PATTERN (insn));
if (XEXP (mem, 0) == frame_pointer_rtx
|| (GET_CODE (XEXP (mem, 0)) == PLUS
&& XEXP (XEXP (mem, 0), 0) == frame_pointer_rtx
......@@ -6254,7 +6277,6 @@ compute_immediate_postdominators (idom, postdominators)
sbitmap *postdominators;
{
compute_immediate_dominators (idom, postdominators);
return;
}
/* Recompute register set/reference counts immediately prior to register
......@@ -6888,7 +6910,6 @@ verify_edge_list (f, elist)
/* This routine will determine what, if any, edge there is between
a specified predecessor and successor. */
int
find_edge_index (edge_list, pred, succ)
struct edge_list *edge_list;
......@@ -6984,8 +7005,44 @@ add_noreturn_fake_exit_edges ()
make_edge (NULL, BASIC_BLOCK (x), EXIT_BLOCK_PTR, EDGE_FAKE);
}
/* Redirect an edge's successor from one block to another. */
/* This function adds a fake edge between any infinite loops to the
exit block. Some optimizations require a path from each node to
the exit node.
See also Morgan, Figure 3.10, pp. 82-83.
The current implementation is ugly, not attempting to minimize the
number of inserted fake edges. To reduce the number of fake edges
to insert, add fake edges from _innermost_ loops containing only
nodes not reachable from the exit block. */
void
connect_infinite_loops_to_exit ()
{
basic_block unvisited_block;
/* Perform depth-first search in the reverse graph to find nodes
reachable from the exit block. */
struct depth_first_search_dsS dfs_ds;
flow_dfs_compute_reverse_init (&dfs_ds);
flow_dfs_compute_reverse_add_bb (&dfs_ds, EXIT_BLOCK_PTR);
/* Repeatedly add fake edges, updating the unreachable nodes. */
while (1)
{
unvisited_block = flow_dfs_compute_reverse_execute (&dfs_ds);
if (!unvisited_block)
break;
make_edge (NULL, unvisited_block, EXIT_BLOCK_PTR, EDGE_FAKE);
flow_dfs_compute_reverse_add_bb (&dfs_ds, unvisited_block);
}
flow_dfs_compute_reverse_finish (&dfs_ds);
return;
}
/* Redirect an edge's successor from one block to another. */
void
redirect_edge_succ (e, new_succ)
edge e;
......@@ -7005,7 +7062,6 @@ redirect_edge_succ (e, new_succ)
}
/* Redirect an edge's predecessor from one block to another. */
void
redirect_edge_pred (e, new_pred)
edge e;
......@@ -7427,6 +7483,115 @@ flow_depth_first_order_compute (dfs_order, rc_order)
}
/* Compute the depth first search order on the _reverse_ graph and
store in the array DFS_ORDER, marking the nodes visited in VISITED.
Returns the number of nodes visited.
The computation is split into three pieces:
flow_dfs_compute_reverse_init () creates the necessary data
structures.
flow_dfs_compute_reverse_add_bb () adds a basic block to the data
structures. The block will start the search.
flow_dfs_compute_reverse_execute () continues (or starts) the
search using the block on the top of the stack, stopping when the
stack is empty.
flow_dfs_compute_reverse_finish () destroys the necessary data
structures.
Thus, the user will probably call ..._init(), call ..._add_bb() to
add a beginning basic block to the stack, call ..._execute(),
possibly add another bb to the stack and again call ..._execute(),
..., and finally call _finish(). */
/* Initialize the data structures used for depth-first search on the
reverse graph. If INITIALIZE_STACK is nonzero, the exit block is
added to the basic block stack. DATA is the current depth-first
search context. If INITIALIZE_STACK is non-zero, there is an
element on the stack. */
static void
flow_dfs_compute_reverse_init (data)
depth_first_search_ds data;
{
/* Allocate stack for back-tracking up CFG. */
data->stack =
(basic_block *) xmalloc ((n_basic_blocks - (INVALID_BLOCK+1))
* sizeof (basic_block));
data->sp = 0;
/* Allocate bitmap to track nodes that have been visited. */
data->visited_blocks
= sbitmap_alloc (n_basic_blocks - (INVALID_BLOCK + 1));
/* None of the nodes in the CFG have been visited yet. */
sbitmap_zero (data->visited_blocks);
return;
}
/* Add the specified basic block to the top of the dfs data
structures. When the search continues, it will start at the
block. */
static void
flow_dfs_compute_reverse_add_bb (data, bb)
depth_first_search_ds data;
basic_block bb;
{
data->stack[data->sp++] = bb;
return;
}
/* Continue the depth-first search through the reverse graph starting
with the block at the stack's top and ending when the stack is
empty. Visited nodes are marked. Returns an unvisited basic
block, or NULL if there is none available. */
static basic_block
flow_dfs_compute_reverse_execute (data)
depth_first_search_ds data;
{
basic_block bb;
edge e;
int i;
while (data->sp > 0)
{
bb = data->stack[--data->sp];
/* Mark that we have visited this node. */
if (!TEST_BIT (data->visited_blocks, bb->index - (INVALID_BLOCK+1)))
{
SET_BIT (data->visited_blocks, bb->index - (INVALID_BLOCK+1));
/* Perform depth-first search on adjacent vertices. */
for (e = bb->pred; e; e = e->pred_next)
flow_dfs_compute_reverse_add_bb (data, e->src);
}
}
/* Determine if there are unvisited basic blocks. */
for (i = n_basic_blocks - (INVALID_BLOCK+1); --i >= 0; )
if (!TEST_BIT (data->visited_blocks, i))
return BASIC_BLOCK (i + (INVALID_BLOCK+1));
return NULL;
}
/* Destroy the data structures needed for depth-first search on the
reverse graph. */
static void
flow_dfs_compute_reverse_finish (data)
depth_first_search_ds data;
{
free (data->stack);
sbitmap_free (data->visited_blocks);
return;
}
/* Return the block for the pre-header of the loop with header
HEADER where DOM specifies the dominator information. Return NULL if
there is no pre-header. */
......
......@@ -168,7 +168,7 @@ in the following sections.
-falign-functions=@var{n} -falign-labels=@var{n} -falign-loops=@var{n}
-falign-jumps=@var{n} -fbranch-probabilities
-fcaller-saves -fcse-follow-jumps -fcse-skip-blocks
-fdelayed-branch -fdelete-null-pointer-checks -fexpensive-optimizations
-fdce -fdelayed-branch -fdelete-null-pointer-checks -fexpensive-optimizations
-ffast-math -ffloat-store -fforce-addr -fforce-mem -fno-math-errno
-fdata-sections -ffunction-sections -fgcse
-finline-functions -finline-limit=@var{n} -fkeep-inline-functions
......@@ -2900,9 +2900,12 @@ If @var{n} is not specified, use a machine-dependent default.
@item -fssa
Perform optimizations in static single assignment form. Each function's
flow graph is translated into SSA form, optimizations are performed, and
the flow graph is translated back from SSA form. (Currently, no
SSA-based optimizations are implemented, but converting into and out of
SSA form is not an invariant operation, and generated code may differ.)
the flow graph is translated back from SSA form. User's should not
specify this option, since it is not yet ready for production use.
@item -fdce
Perform dead-code elimination in SSA form. Requires @samp{-fssa}. Like
@samp{-fssa}, this is an experimental feature.
@item -fsingle-precision-constant
Treat floating point constant as single precision constant instead of
......
......@@ -148,7 +148,9 @@ typedef struct rtx_def
together with the preceding insn. Valid only within sched.
1 in an INSN, JUMP_INSN, or CALL_INSN if insn is in a delay slot and
from the target of a branch. Valid from reorg until end of compilation;
cleared before used. */
cleared before used.
1 in an INSN if this insn is dead code. Valid only during
dead-code elimination phase; cleared before use. */
unsigned int in_struct : 1;
/* 1 if this rtx is used. This is used for copying shared structure.
See `unshare_all_rtl'.
......@@ -202,10 +204,26 @@ typedef struct rtvec_def{
#define GET_NUM_ELEM(RTVEC) ((RTVEC)->num_elem)
#define PUT_NUM_ELEM(RTVEC, NUM) ((RTVEC)->num_elem = (NUM))
/* 1 if X is a REG. */
/* Predicate yielding nonzero iff X is an rtl for a register. */
#define REG_P(X) (GET_CODE (X) == REG)
/* Predicate yielding nonzero iff X is a label insn. */
#define LABEL_P(X) (GET_CODE (X) == CODE_LABEL)
/* Predicate yielding nonzero iff X is a jump insn. */
#define JUMP_P(X) (GET_CODE (X) == JUMP_INSN)
/* Predicate yielding nonzero iff X is a note insn. */
#define NOTE_P(X) (GET_CODE (X) == NOTE)
/* Predicate yielding nonzero iff X is a barrier insn. */
#define BARRIER_P(X) (GET_CODE (X) == BARRIER)
/* Predicate yielding nonzero iff X is a data for a jump table. */
#define JUMP_TABLE_DATA_P(INSN) \
(JUMP_P (INSN) && (GET_CODE (PATTERN (INSN)) == ADDR_VEC || \
GET_CODE (PATTERN (INSN)) == ADDR_DIFF_VEC))
/* 1 if X is a constant value that is an integer. */
#define CONSTANT_P(X) \
......@@ -374,6 +392,9 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
delay slots, i.e., it is an annulled branch. */
#define INSN_ANNULLED_BRANCH_P(INSN) ((INSN)->unchanging)
/* 1 if insn is a dead code. Valid only for dead-code elimination phase. */
#define INSN_DEAD_CODE_P(INSN) ((INSN)->in_struct)
/* 1 if insn is in a delay slot and is from the target of the branch. If
the branch insn has INSN_ANNULLED_BRANCH_P set, this insn should only be
executed if the branch is taken. For annulled branches with this bit
......
......@@ -46,6 +46,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "recog.h"
#include "basic-block.h"
#include "output.h"
#include "ssa.h"
/* We cannot use <assert.h> in GCC source, since that would include
GCC's assert.h, which may not be compatible with the host compiler. */
......@@ -91,24 +92,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
left in for a limited time only, as a debugging tool until the
coalescing algorithm is validated. */
/* All pseudo-registers (having register number >=
FIRST_PSEUDO_REGISTER) and hard registers satisfying
CONVERT_HARD_REGISTER_TO_SSA_P are converted to SSA form. */
/* Given a hard register number REG_NO, return nonzero if and only if
the register should be converted to SSA. */
#ifndef CONVERT_HARD_REGISTER_TO_SSA_P
#define CONVERT_HARD_REGISTER_TO_SSA_P(REG_NO) (0) /* default of no hard registers */
#endif /* CONVERT_HARD_REGISTER_TO_SSA_P */
/* Given a register number REG_NO, return nonzero if and only if the
register should be converted to SSA. */
#define CONVERT_REGISTER_TO_SSA_P(REG_NO) \
((!HARD_REGISTER_NUM_P (REG_NO)) || \
(CONVERT_HARD_REGISTER_TO_SSA_P (REG_NO)))
static int conservative_reg_partition;
/* This flag is set when the CFG is in SSA form. */
......@@ -152,20 +135,20 @@ struct ssa_rename_from_hash_table_data {
partition reg_partition;
};
void ssa_rename_from_initialize
static void ssa_rename_from_initialize
PARAMS ((void));
rtx ssa_rename_from_lookup
static rtx ssa_rename_from_lookup
PARAMS ((int reg));
unsigned int original_register
static unsigned int original_register
PARAMS ((unsigned int regno));
void ssa_rename_from_insert
static void ssa_rename_from_insert
PARAMS ((unsigned int reg, rtx r));
void ssa_rename_from_free
static void ssa_rename_from_free
PARAMS ((void));
typedef int (*srf_trav) PARAMS ((int regno, rtx r, sbitmap canonical_elements, partition reg_partition));
static void ssa_rename_from_traverse
PARAMS ((htab_trav callback_function, sbitmap canonical_elements, partition reg_partition));
static void ssa_rename_from_print
/*static Avoid warnign message. */ void ssa_rename_from_print
PARAMS ((void));
static int ssa_rename_from_print_1
PARAMS ((void **slot, void *data));
......@@ -299,7 +282,7 @@ ssa_rename_to_insert(reg, r)
/* Prepare ssa_rename_from for use. */
void
static void
ssa_rename_from_initialize ()
{
/* We use an arbitrary initial hash table size of 64. */
......@@ -312,7 +295,7 @@ ssa_rename_from_initialize ()
/* Find the REG entry in ssa_rename_from. Return NULL_RTX if no entry is
found. */
rtx
static rtx
ssa_rename_from_lookup (reg)
int reg;
{
......@@ -329,7 +312,7 @@ ssa_rename_from_lookup (reg)
the register is a pseudo, return the original register's number.
Otherwise, return this register number REGNO. */
unsigned int
static unsigned int
original_register (regno)
unsigned int regno;
{
......@@ -339,7 +322,7 @@ original_register (regno)
/* Add mapping from R to REG to ssa_rename_from even if already present. */
void
static void
ssa_rename_from_insert (reg, r)
unsigned int reg;
rtx r;
......@@ -359,7 +342,7 @@ ssa_rename_from_insert (reg, r)
CANONICAL_ELEMENTS and REG_PARTITION pass data needed by the only
current use of this function. */
void
static void
ssa_rename_from_traverse (callback_function,
canonical_elements, reg_partition)
htab_trav callback_function;
......@@ -374,7 +357,7 @@ ssa_rename_from_traverse (callback_function,
/* Destroy ssa_rename_from. */
void
static void
ssa_rename_from_free ()
{
htab_delete (ssa_rename_from_ht);
......@@ -382,7 +365,8 @@ ssa_rename_from_free ()
/* Print the contents of ssa_rename_from. */
static void
/* static Avoid erroneous error message. */
void
ssa_rename_from_print ()
{
printf ("ssa_rename_from's hash table contents:\n");
......@@ -1146,9 +1130,6 @@ rename_registers (nregs, idom)
int nregs;
int *idom;
{
int reg;
int mach_mode;
VARRAY_RTX_INIT (ssa_definition, nregs * 3, "ssa_definition");
VARRAY_RTX_INIT (ssa_uses, nregs * 3, "ssa_uses");
ssa_rename_from_initialize ();
......
/* Static Single Assignment (SSA) definitions for GNU C-Compiler
Copyright (C) 2000 Free Software Foundation, Inc.
Written by Jeffrey D. Oldham <oldham@codesourcery.com>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Main SSA routines. */
extern void convert_to_ssa PARAMS ((void));
extern void convert_from_ssa PARAMS ((void));
typedef int (*successor_phi_fn) PARAMS ((rtx, int, int, void *));
extern int for_each_successor_phi PARAMS ((basic_block bb,
successor_phi_fn,
void *));
/* Optimizations. */
/* In dce.c */
extern void eliminate_dead_code PARAMS ((void));
/* SSA definitions and uses. */
/* This flag is set when the CFG is in SSA form. */
extern int in_ssa_form;
/* Element I is the single instruction that sets register I. */
extern varray_type ssa_definition;
/* Element I is an INSN_LIST of instructions that use register I. */
extern varray_type ssa_uses;
/* Specify which hard registers should be converted. */
/* All pseudo-registers (having register number >=
FIRST_PSEUDO_REGISTER) and hard registers satisfying
CONVERT_HARD_REGISTER_TO_SSA_P are converted to SSA form. */
/* Given a hard register number REG_NO, return nonzero if and only if
the register should be converted to SSA. */
#ifndef CONVERT_HARD_REGISTER_TO_SSA_P
#define CONVERT_HARD_REGISTER_TO_SSA_P(REG_NO) (0) /* default of no hard registers */
#endif /* CONVERT_HARD_REGISTER_TO_SSA_P */
/* Given a register number REG_NO, return nonzero if and only if the
register should be converted to SSA. */
#define CONVERT_REGISTER_TO_SSA_P(REG_NO) \
((!HARD_REGISTER_NUM_P (REG_NO)) || \
(CONVERT_HARD_REGISTER_TO_SSA_P (REG_NO)))
......@@ -68,6 +68,7 @@ DEFTIMEVAR (TV_REORDER_BLOCKS , "reorder blocks")
DEFTIMEVAR (TV_SHORTEN_BRANCH , "shorten branches")
DEFTIMEVAR (TV_REG_STACK , "reg stack")
DEFTIMEVAR (TV_TO_SSA , "convert to SSA")
DEFTIMEVAR (TV_DEAD_CODE_ELIM , "eliminate dead code")
DEFTIMEVAR (TV_FROM_SSA , "convert from SSA")
DEFTIMEVAR (TV_FINAL , "final")
DEFTIMEVAR (TV_SYMOUT , "symout")
......
......@@ -63,6 +63,7 @@ Boston, MA 02111-1307, USA. */
#include "regs.h"
#include "timevar.h"
#include "diagnostic.h"
#include "ssa.h"
#ifndef ACCUMULATE_OUTGOING_ARGS
#define ACCUMULATE_OUTGOING_ARGS 0
......@@ -259,6 +260,7 @@ enum dump_file_index
DFI_cse,
DFI_addressof,
DFI_ssa,
DFI_dce,
DFI_ussa,
DFI_gcse,
DFI_loop,
......@@ -291,7 +293,7 @@ enum dump_file_index
Remaining -d letters:
" h o q u "
" H K OPQ TUVWXYZ"
" H K OPQ TUVW YZ"
*/
struct dump_file_info dump_file[DFI_MAX] =
......@@ -302,6 +304,7 @@ struct dump_file_info dump_file[DFI_MAX] =
{ "cse", 's', 0, 0, 0 },
{ "addressof", 'F', 0, 0, 0 },
{ "ssa", 'e', 1, 0, 0 },
{ "dce", 'X', 1, 0, 0 },
{ "ussa", 'e', 1, 0, 0 }, /* Yes, duplicate enable switch. */
{ "gcse", 'G', 1, 0, 0 },
{ "loop", 'L', 1, 0, 0 },
......@@ -786,6 +789,9 @@ int flag_gnu_linker = 1;
/* Enable SSA. */
int flag_ssa = 0;
/* Enable dead code elimination. */
int flag_dce = 0;
/* Tag all structures with __attribute__(packed) */
int flag_pack_struct = 0;
......@@ -1094,6 +1100,8 @@ lang_independent_options f_options[] =
"Instrument function entry/exit with profiling calls"},
{"ssa", &flag_ssa, 1,
"Enable SSA optimizations" },
{"dce", &flag_dce, 1,
"Enable dead code elimination" },
{"leading-underscore", &flag_leading_underscore, 1,
"External symbols have a leading underscore" },
{"ident", &flag_no_ident, 0,
......@@ -2976,13 +2984,25 @@ rest_of_compilation (decl)
close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
timevar_pop (TV_TO_SSA);
/* Currently, there's nothing to do in SSA form. */
/* The SSA implementation uses basic block numbers in its phi
nodes. Thus, changing the control-flow graph or the basic
blocks, e.g., calling find_basic_blocks () or cleanup_cfg (),
may cause problems. */
if (flag_dce)
{
/* Remove dead code. */
timevar_push (TV_DEAD_CODE_ELIM);
open_dump_file (DFI_dce, decl);
insns = get_insns ();
eliminate_dead_code();
close_dump_file (DFI_dce, print_rtl_with_bb, insns);
timevar_pop (TV_DEAD_CODE_ELIM);
}
/* Convert from SSA form. */
timevar_push (TV_FROM_SSA);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment