Commit 4e872036 by Alex Samuel

rtl.h (INSN_P): New macro.

	* rtl.h (INSN_P): New macro.
	(successor_phi_fn): New typedef.
	(for_each_successor_phi): New prototype.
	(in_ssa_form): New variable.
	(PHI_NODE_P): Likewise.
	* flow.c (calculate_global_regs_live): Add to new_live_at_end from
	phi nodes in successors.
	(mark_used_regs): Add PHI case.
	(set_phi_alternative_reg): New function.
	(life_analysis): Assert that dead code elimination is not selected
	when in SSA form.
	* toplev.c (to_ssa_time): New variable.
	(from_ssa_time): Likewise.
	(compile_file): Zero to_ssa_time and from_ssa_time.
	Print time to convert to and from SSA.
	(rest_of_compilation): Time convert_to_ssa and convert_from_ssa.
	(print_time): Compute percent fraction as integer.
	* ssa.c (PHI_NODE_P): Moved to rtl.h.
	(convert_to_ssa): Check if we're already in SSA.
	Don't eliminate dead code in life_analysis.
	Rerun flow and life analysis at bottom.
	(eliminate_phi): Use canonical regnos when adding nodes.
	(mark_reg_in_phi): New function.
	(mark_phi_and_copy_regs): Likewise.
	(convert_from_ssa): Rerun life analysis at top.
	Use coalesced partition.
	Check for removing a phi node at the end of the block.
	(compute_coalesced_reg_partition): New function.
	(coalesce_regs_in_copies): Likewise.
	(coalesce_reg_in_phi): Likewise.
	(coalesce_regs_in_sucessor_phi_nodes): Likewise.
	(for_each_successor_phi): Likewise.
	(rename_context): New struct.
	(rename_block): Use a rename_context with rename_insn_1.  When
	renaming sets of a subreg, emit a copy of the entire reg first.
	(rename_insn_1): Treat data as a rename_context *.  Save current
	insn in set_data.
	(rename_set_data): Add field set_insn.
	* Makefile.in (HASHTAB_H): Move up in file.
	(OBSTACK_H): New macro.
	(collect2.o): Use OBSTACK_H in dependencies.
	(sdbout.o): Likewise.
	(emit-rtl.o): Likewise.
	(simplify-rtx.o): Likewise.
	(fix-header.o): Likewise.
	(OBJS):	Add conflict.o.
	(conflict.o): New rule.
	* basic-block.h: Include partition.h.
	(conflict_graph): New typedef.
	(conflict_graph_enum_fn): Likewise.
	(conflict_graph_new): New prototype.
	(conflict_graph_delete): Likewise.
	(conflict_graph_add): Likewise.
	(conflict_graph_conflict_p): Likewise.
	(conflict_graph_enum): Likewise.
	(conflict_graph_merge_regs): Likewise.
	(conflict_graph_print): Likewise.
	(conflict_graph_compute): Likewise.
	* conflict.c: New file.

From-SVN: r32979
parent 2c561874
......@@ -218,6 +218,10 @@ RANLIB_TEST_FOR_TARGET = \
# Dir to search for system headers. Overridden by cross-make.
SYSTEM_HEADER_DIR = /usr/include
# Where to find some libiberty headers.
HASHTAB_H = $(srcdir)/../include/hashtab.h
OBSTACK_H = $(srcdir)/../include/obstack.h
# Default cross SYSTEM_HEADER_DIR, to be overridden by targets.
CROSS_SYSTEM_HEADER_DIR = $(tooldir)/sys-include
......@@ -680,7 +684,7 @@ OBJS = diagnostic.o \
profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \
mbchar.o dyn-string.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
sibcall.o conflict.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
......@@ -1387,7 +1391,7 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(COLLECT2_OBJS) $(LIBS)
collect2.o : collect2.c $(CONFIG_H) system.h gstab.h intl.h \
$(srcdir)/../include/obstack.h $(DEMANGLE_H) collect2.h version.h
$(OBSTACK_H) $(DEMANGLE_H) collect2.h version.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DTARGET_MACHINE=\"$(target_alias)\" $(MAYBE_USE_COLLECT2) \
-c `echo $(srcdir)/collect2.c | sed 's,^\./,,'`
......@@ -1548,7 +1552,7 @@ dbxout.o : dbxout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h $(REGS_H) \
toplev.h
sdbout.o : sdbout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h except.h \
function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) defaults.h real.h \
insn-config.h $(srcdir)/../include/obstack.h xcoffout.h c-pragma.h \
insn-config.h $(OBSTACK_H) xcoffout.h c-pragma.h \
sdbout.h toplev.h
dwarfout.o : dwarfout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) dwarf.h \
flags.h insn-config.h reload.h output.h defaults.h toplev.h dwarfout.h
......@@ -1572,7 +1576,7 @@ jump.o : jump.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
simplify-rtx.o : simplify-rtx.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h cselib.h $(GGC_H) $(srcdir)/../include/obstack.h
output.h function.h cselib.h ggc.h $(OBSTACK_H)
cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h $(GGC_H)
gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
......@@ -1587,6 +1591,8 @@ 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) $(REGS_H) $(BASIC_BLOCK_H) \
output.h insn-config.h
conflict.o : conflict.c $(CONFIG_H) $(OBSTACK_H) $(HASHTAB_H) \
rtl.h basic-block.h
profile.o : profile.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-flags.h \
gcov-io.h $(TREE_H) output.h $(REGS_H) toplev.h function.h insn-config.h \
$(GGC_H)
......@@ -2056,7 +2062,6 @@ LIBCPP_OBJS = cpplib.o cpphash.o cpperror.o cppexp.o cppfiles.o \
prefix.o version.o mbchar.o @extra_cpp_objs@
LIBCPP_DEPS = cpplib.h cpphash.h intl.h system.h
HASHTAB_H = $(srcdir)/../include/hashtab.h
# All the other archives built/used by this makefile are for targets. This
# one is strictly for the host.
......@@ -2287,7 +2292,7 @@ fix-header: fix-header.o scan-decls.o scan.o xsys-protos.h $(HOST_LIBDEPS) \
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ fix-header.o \
scan-decls.o scan.o libcpp.a $(HOST_LIBS) ../libiberty/libiberty.a
fix-header.o: fix-header.c $(srcdir)/../include/obstack.h scan.h \
fix-header.o: fix-header.c $(OBSTACK_H) scan.h \
xsys-protos.h $(build_xm_file) system.h cpplib.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/fix-header.c
......
......@@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */
#include "bitmap.h"
#include "sbitmap.h"
#include "varray.h"
#include "partition.h"
/* Head of register set linked list. */
typedef bitmap_head regset_head;
......@@ -146,7 +147,9 @@ typedef struct basic_block_def {
/* The edges into and out of the block. */
edge pred, succ;
/* Liveness info. */
/* Liveness info. Note that in SSA form, global_live_at_start does
not reflect the use of regs in phi functions, since the liveness
of these regs may depend on which edge was taken into the block. */
regset local_set;
regset global_live_at_start;
regset global_live_at_end;
......@@ -459,5 +462,31 @@ extern void debug_regset PARAMS ((regset));
extern void verify_flow_info PARAMS ((void));
extern int flow_loop_outside_edge_p PARAMS ((const struct loop *, edge));
typedef struct conflict_graph_def *conflict_graph;
/* Callback function when enumerating conflicts. The arguments are
the smaller and larger regno in the conflict. Returns zero if
enumeration is to continue, non-zero to halt enumeration. */
typedef int (*conflict_graph_enum_fn) (int, int, void *);
/* Prototypes of operations on conflict graphs. */
extern conflict_graph conflict_graph_new
PARAMS ((int));
extern void conflict_graph_delete PARAMS ((conflict_graph));
extern int conflict_graph_add PARAMS ((conflict_graph,
int, int));
extern int conflict_graph_conflict_p PARAMS ((conflict_graph,
int, int));
extern void conflict_graph_enum PARAMS ((conflict_graph, int,
conflict_graph_enum_fn,
void *));
extern void conflict_graph_merge_regs PARAMS ((conflict_graph, int,
int));
extern void conflict_graph_print PARAMS ((conflict_graph, FILE*));
extern conflict_graph conflict_graph_compute
PARAMS ((regset,
partition));
#endif /* _BASIC_BLOCK_H */
This diff is collapsed. Click to expand it.
......@@ -317,6 +317,7 @@ static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
static void notice_stack_pointer_modification PARAMS ((rtx));
static void mark_reg PARAMS ((rtx, void *));
static void mark_regs_live_at_end PARAMS ((regset));
static int set_phi_alternative_reg PARAMS ((rtx, int, int, void *));
static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
static void propagate_block PARAMS ((basic_block, regset,
regset, int));
......@@ -2486,6 +2487,15 @@ life_analysis (f, nregs, file, remove_dead_code)
#endif
int flags;
sbitmap all_blocks;
/* Dead code elimination changes basic block structure and therefore
breaks the SSA phi representation. Particularly, a phi node
can have an alternative value for each incoming block, referenced
by the block number. Removing dead code can bump entire blocks
and therefore cause blocks to be renumbered, invalidating the
numbering of phi alternatives. */
if (remove_dead_code && in_ssa_form)
abort ();
/* Record which registers will be eliminated. We use this in
mark_used_regs. */
......@@ -2960,6 +2970,22 @@ mark_regs_live_at_end (set)
diddle_return_value (mark_reg, set);
}
/* Callback function for for_each_successor_phi. DATA is a regset.
Sets the SRC_REGNO, the regno of the phi alternative for phi node
INSN, in the regset. */
static int
set_phi_alternative_reg (insn, dest_regno, src_regno, data)
rtx insn ATTRIBUTE_UNUSED;
int dest_regno ATTRIBUTE_UNUSED;
int src_regno;
void *data;
{
regset live = (regset) data;
SET_REGNO_REG_SET (live, src_regno);
return 0;
}
/* Propagate global life info around the graph of basic blocks. Begin
considering blocks with their corresponding bit set in BLOCKS_IN.
BLOCKS_OUT is set for every block that was changed. */
......@@ -3020,6 +3046,13 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
}
/* Regs used in phi nodes are not included in
global_live_at_start, since they are live only along a
particular edge. Set those regs that are live because of a
phi node alternative corresponding to this particular block. */
for_each_successor_phi (bb->index, &set_phi_alternative_reg,
new_live_at_end);
if (bb == ENTRY_BLOCK_PTR)
{
COPY_REG_SET (bb->global_live_at_end, new_live_at_end);
......@@ -4688,6 +4721,13 @@ mark_used_regs (needed, live, x, flags, insn)
break;
}
case PHI:
/* We _do_not_ want to scan operands of phi nodes. Operands of
a phi function are evaluated only when control reaches this
block along a particular edge. Therefore, regs that appear
as arguments to phi should not be added to the global live at
start. */
return;
default:
break;
......
......@@ -357,6 +357,9 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
/* ACCESS MACROS for particular fields of insns. */
/* Determines whether X is an insn. */
#define INSN_P(X) (GET_RTX_CLASS (GET_CODE(X)) == 'i')
/* Holds a unique number for each insn.
These are not necessarily sequentially increasing. */
#define INSN_UID(INSN) XINT(INSN, 0)
......@@ -981,6 +984,12 @@ extern const char * const note_insn_name[];
/* For a NOTE_INSN_LIVE note, the original basic block number. */
#define RANGE_LIVE_ORIG_BLOCK(INSN) (XINT (INSN, 1))
/* Determine if the insn is a PHI node. */
#define PHI_NODE_P(X) \
(X && GET_CODE (X) == INSN \
&& GET_CODE (PATTERN (X)) == SET \
&& GET_CODE (SET_SRC (PATTERN (X))) == PHI)
/* Nonzero if we need to distinguish between the return value of this function
and the return value of a function called by this function. This helps
......@@ -1793,6 +1802,11 @@ extern int stack_regs_mentioned PARAMS ((rtx insn));
/* 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 ((int bb,
successor_phi_fn,
void *));
extern int in_ssa_form;
/* In toplev.c */
......
......@@ -1426,6 +1426,8 @@ int reorder_blocks_time;
int rename_registers_time;
int shorten_branch_time;
int stack_reg_time;
int to_ssa_time;
int from_ssa_time;
int final_time;
int symout_time;
int dump_time;
......@@ -1510,9 +1512,9 @@ print_time (str, total)
int total;
{
fprintf (stderr,
"time in %s: %d.%06d (%.0f%%)\n",
"time in %s: %d.%06d (%d%%)\n",
str, total / 1000000, total % 1000000,
all_time == 0 ? 0.00 : (double) total / (double) all_time * 100.0);
all_time == 0 ? 0 : (100 * total) / all_time);
}
/* This is the default decl_printable_name function. */
......@@ -1890,6 +1892,26 @@ close_dump_file (index, func, insns)
});
}
/* Routine to empty a dump file. */
static void
clean_dump_file (suffix)
const char *suffix;
{
char * const dumpname = concat (dump_base_name, suffix, NULL);
rtl_dump_file = fopen (dumpname, "w");
if (rtl_dump_file == NULL)
pfatal_with_name (dumpname);
free (dumpname);
fclose (rtl_dump_file);
rtl_dump_file = NULL;
return;
}
/* Do any final processing required for the declarations in VEC, of
which there are LEN. We write out inline functions and variables
that have been deferred until this point, but which are required.
......@@ -2176,6 +2198,8 @@ compile_file (name)
rename_registers_time = 0;
shorten_branch_time = 0;
stack_reg_time = 0;
to_ssa_time = 0;
from_ssa_time = 0;
final_time = 0;
symout_time = 0;
dump_time = 0;
......@@ -2559,6 +2583,8 @@ compile_file (name)
print_time ("integration", integration_time);
print_time ("jump", jump_time);
print_time ("cse", cse_time);
print_time ("to ssa", to_ssa_time);
print_time ("from ssa", from_ssa_time);
print_time ("gcse", gcse_time);
print_time ("loop", loop_time);
print_time ("cse2", cse2_time);
......@@ -3032,11 +3058,11 @@ rest_of_compilation (decl)
if (flag_ssa)
{
open_dump_file (DFI_ssa, decl);
convert_to_ssa ();
TIMEVAR (to_ssa_time, convert_to_ssa ());
close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
open_dump_file (DFI_ussa, decl);
convert_from_ssa ();
TIMEVAR (from_ssa_time, convert_from_ssa ());
/* New registers have been created. Rescan their usage. */
reg_scan (insns, max_reg_num (), 1);
close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
......
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