[multiple changes]
2006-05-04 Leehod Baruch <leehod@il.ibm.com> * see.c: New file. * Makefile.in (OBJS-common): Add see.o. (see.o): Add dependencies. * common.opt (fsee): New flag for the see optimization was added. * opts.c (flag_see): Initialized. * passes.c (init_optimization_passes, pass_see): New pass. * rtl.h (see_main): Declaration as extern. * timevar.def (TV_SEE): New. * tree-pass.h (pass_see): Declaration as extern. * invoke.texi (-fsee): Document. * recog.c (validate_simplify_insn): New function. * recog.h (validate_simplify_insn): Declaration as extern. * df-problems.c (df_chain_dump): Check for NULL. 2006-05-04 Kenneth Zadeck <zadeck@naturalbridge.com> Daniel Berlin <dberlin@dberlin.org> * cfgrtl.c (insert_insn_bb_end_new): New function. * basic-block.h (insert_insn_bb_end_new): Declaration as extern. 2006-05-04 Leehod Baruch <leehod.baruch@weizmann.ac.il> * df.h (struct web_entry): Moved from web.c. (union_defs): Declaration as extern. (unionfind_root): Likewise. (unionfind_union): Likewise. * web.c (struct web_entry): Moved to df.h. (unionfind_root): Remove static declaration. (unionfind_union): Likewise. (union_defs): Likewise and generalize to use callback function. (web_main): Update arguments for union_defs function call. From-SVN: r113518
This commit is contained in:
parent
23ba9627f4
commit
8cd37d0b6c
|
@ -1,3 +1,37 @@
|
||||||
|
2006-05-04 Leehod Baruch <leehod@il.ibm.com>
|
||||||
|
|
||||||
|
* see.c: New file.
|
||||||
|
* Makefile.in (OBJS-common): Add see.o.
|
||||||
|
(see.o): Add dependencies.
|
||||||
|
* common.opt (fsee): New flag for the see optimization was added.
|
||||||
|
* opts.c (flag_see): Initialized.
|
||||||
|
* passes.c (init_optimization_passes, pass_see): New pass.
|
||||||
|
* rtl.h (see_main): Declaration as extern.
|
||||||
|
* timevar.def (TV_SEE): New.
|
||||||
|
* tree-pass.h (pass_see): Declaration as extern.
|
||||||
|
* invoke.texi (-fsee): Document.
|
||||||
|
* recog.c (validate_simplify_insn): New function.
|
||||||
|
* recog.h (validate_simplify_insn): Declaration as extern.
|
||||||
|
* df-problems.c (df_chain_dump): Check for NULL.
|
||||||
|
|
||||||
|
2006-05-04 Kenneth Zadeck <zadeck@naturalbridge.com>
|
||||||
|
Daniel Berlin <dberlin@dberlin.org>
|
||||||
|
|
||||||
|
* cfgrtl.c (insert_insn_bb_end_new): New function.
|
||||||
|
* basic-block.h (insert_insn_bb_end_new): Declaration as extern.
|
||||||
|
|
||||||
|
2006-05-04 Leehod Baruch <leehod.baruch@weizmann.ac.il>
|
||||||
|
|
||||||
|
* df.h (struct web_entry): Moved from web.c.
|
||||||
|
(union_defs): Declaration as extern.
|
||||||
|
(unionfind_root): Likewise.
|
||||||
|
(unionfind_union): Likewise.
|
||||||
|
* web.c (struct web_entry): Moved to df.h.
|
||||||
|
(unionfind_root): Remove static declaration.
|
||||||
|
(unionfind_union): Likewise.
|
||||||
|
(union_defs): Likewise and generalize to use callback function.
|
||||||
|
(web_main): Update arguments for union_defs function call.
|
||||||
|
|
||||||
2006-05-04 Richard Guenther <rguenther@suse.de>
|
2006-05-04 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
PR tree-optimization/26447
|
PR tree-optimization/26447
|
||||||
|
|
|
@ -995,7 +995,7 @@ OBJS-common = \
|
||||||
real.o recog.o reg-stack.o regclass.o regmove.o regrename.o \
|
real.o recog.o reg-stack.o regclass.o regmove.o regrename.o \
|
||||||
reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o \
|
reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o \
|
||||||
sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o \
|
sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o \
|
||||||
simplify-rtx.o sreal.o stmt.o stor-layout.o stringpool.o \
|
see.o simplify-rtx.o sreal.o stmt.o stor-layout.o stringpool.o \
|
||||||
struct-equiv.o targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
|
struct-equiv.o targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
|
||||||
varasm.o varray.o vec.o version.o vmsdbgout.o xcoffout.o alloc-pool.o \
|
varasm.o varray.o vec.o version.o vmsdbgout.o xcoffout.o alloc-pool.o \
|
||||||
et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o passes.o \
|
et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o passes.o \
|
||||||
|
@ -2314,6 +2314,9 @@ cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
|
||||||
web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||||
hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
|
hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
|
||||||
$(DF_H) $(OBSTACK_H) timevar.h tree-pass.h
|
$(DF_H) $(OBSTACK_H) timevar.h tree-pass.h
|
||||||
|
see.o : see.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||||
|
hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) function.h output.h toplev.h \
|
||||||
|
$(DF_H) $(OBSTACK_H) timevar.h tree-pass.h
|
||||||
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||||
$(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \
|
$(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \
|
||||||
$(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
|
$(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
|
||||||
|
|
|
@ -1001,6 +1001,8 @@ extern basic_block get_bb_original (basic_block);
|
||||||
extern void set_bb_copy (basic_block, basic_block);
|
extern void set_bb_copy (basic_block, basic_block);
|
||||||
extern basic_block get_bb_copy (basic_block);
|
extern basic_block get_bb_copy (basic_block);
|
||||||
|
|
||||||
|
extern rtx insert_insn_end_bb_new (rtx, basic_block);
|
||||||
|
|
||||||
#include "cfghooks.h"
|
#include "cfghooks.h"
|
||||||
|
|
||||||
/* In struct-equiv.c */
|
/* In struct-equiv.c */
|
||||||
|
|
88
gcc/cfgrtl.c
88
gcc/cfgrtl.c
|
@ -2899,6 +2899,93 @@ init_rtl_bb_info (basic_block bb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Add EXPR to the end of basic block BB. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
insert_insn_end_bb_new (rtx pat, basic_block bb)
|
||||||
|
{
|
||||||
|
rtx insn = BB_END (bb);
|
||||||
|
rtx new_insn;
|
||||||
|
rtx pat_end = pat;
|
||||||
|
|
||||||
|
while (NEXT_INSN (pat_end) != NULL_RTX)
|
||||||
|
pat_end = NEXT_INSN (pat_end);
|
||||||
|
|
||||||
|
/* If the last insn is a jump, insert EXPR in front [taking care to
|
||||||
|
handle cc0, etc. properly]. Similarly we need to care trapping
|
||||||
|
instructions in presence of non-call exceptions. */
|
||||||
|
|
||||||
|
if (JUMP_P (insn)
|
||||||
|
|| (NONJUMP_INSN_P (insn)
|
||||||
|
&& (!single_succ_p (bb)
|
||||||
|
|| single_succ_edge (bb)->flags & EDGE_ABNORMAL)))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_cc0
|
||||||
|
rtx note;
|
||||||
|
#endif
|
||||||
|
/* If this is a jump table, then we can't insert stuff here. Since
|
||||||
|
we know the previous real insn must be the tablejump, we insert
|
||||||
|
the new instruction just before the tablejump. */
|
||||||
|
if (GET_CODE (PATTERN (insn)) == ADDR_VEC
|
||||||
|
|| GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
|
||||||
|
insn = prev_real_insn (insn);
|
||||||
|
|
||||||
|
#ifdef HAVE_cc0
|
||||||
|
/* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts
|
||||||
|
if cc0 isn't set. */
|
||||||
|
note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
|
||||||
|
if (note)
|
||||||
|
insn = XEXP (note, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rtx maybe_cc0_setter = prev_nonnote_insn (insn);
|
||||||
|
if (maybe_cc0_setter
|
||||||
|
&& INSN_P (maybe_cc0_setter)
|
||||||
|
&& sets_cc0_p (PATTERN (maybe_cc0_setter)))
|
||||||
|
insn = maybe_cc0_setter;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* FIXME: What if something in cc0/jump uses value set in new
|
||||||
|
insn? */
|
||||||
|
new_insn = emit_insn_before_noloc (pat, insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Likewise if the last insn is a call, as will happen in the presence
|
||||||
|
of exception handling. */
|
||||||
|
else if (CALL_P (insn)
|
||||||
|
&& (!single_succ_p (bb)
|
||||||
|
|| single_succ_edge (bb)->flags & EDGE_ABNORMAL))
|
||||||
|
{
|
||||||
|
/* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
|
||||||
|
we search backward and place the instructions before the first
|
||||||
|
parameter is loaded. Do this for everyone for consistency and a
|
||||||
|
presumption that we'll get better code elsewhere as well. */
|
||||||
|
|
||||||
|
/* Since different machines initialize their parameter registers
|
||||||
|
in different orders, assume nothing. Collect the set of all
|
||||||
|
parameter registers. */
|
||||||
|
insn = find_first_parameter_load (insn, BB_HEAD (bb));
|
||||||
|
|
||||||
|
/* If we found all the parameter loads, then we want to insert
|
||||||
|
before the first parameter load.
|
||||||
|
|
||||||
|
If we did not find all the parameter loads, then we might have
|
||||||
|
stopped on the head of the block, which could be a CODE_LABEL.
|
||||||
|
If we inserted before the CODE_LABEL, then we would be putting
|
||||||
|
the insn in the wrong basic block. In that case, put the insn
|
||||||
|
after the CODE_LABEL. Also, respect NOTE_INSN_BASIC_BLOCK. */
|
||||||
|
while (LABEL_P (insn)
|
||||||
|
|| NOTE_INSN_BASIC_BLOCK_P (insn))
|
||||||
|
insn = NEXT_INSN (insn);
|
||||||
|
|
||||||
|
new_insn = emit_insn_before_noloc (pat, insn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
new_insn = emit_insn_after_noloc (pat, insn);
|
||||||
|
|
||||||
|
return new_insn;
|
||||||
|
}
|
||||||
|
|
||||||
/* Implementation of CFG manipulation for linearized RTL. */
|
/* Implementation of CFG manipulation for linearized RTL. */
|
||||||
struct cfg_hooks rtl_cfg_hooks = {
|
struct cfg_hooks rtl_cfg_hooks = {
|
||||||
"rtl",
|
"rtl",
|
||||||
|
@ -2973,4 +3060,3 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
|
||||||
rtl_extract_cond_bb_edges, /* extract_cond_bb_edges */
|
rtl_extract_cond_bb_edges, /* extract_cond_bb_edges */
|
||||||
NULL /* flush_pending_stmts */
|
NULL /* flush_pending_stmts */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -809,6 +809,10 @@ frtl-abstract-sequences
|
||||||
Common Report Var(flag_rtl_seqabstr)
|
Common Report Var(flag_rtl_seqabstr)
|
||||||
Perform sequence abstraction optimization on RTL
|
Perform sequence abstraction optimization on RTL
|
||||||
|
|
||||||
|
fsee
|
||||||
|
Common Report Var(flag_see) Init(0)
|
||||||
|
Eliminate redundant sign extensions using LCM.
|
||||||
|
|
||||||
fshow-column
|
fshow-column
|
||||||
Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(1)
|
Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(1)
|
||||||
Show column numbers in diagnostics, when available. Default on
|
Show column numbers in diagnostics, when available. Default on
|
||||||
|
|
|
@ -2992,7 +2992,9 @@ df_chains_dump (struct dataflow *dflow, FILE *file)
|
||||||
{
|
{
|
||||||
fprintf (file, "d%d bb %d luid %d insn %d reg %d ",
|
fprintf (file, "d%d bb %d luid %d insn %d reg %d ",
|
||||||
j, DF_REF_BBNO (def),
|
j, DF_REF_BBNO (def),
|
||||||
DF_INSN_LUID (df, DF_REF_INSN (def)),
|
DF_REF_INSN (def) ?
|
||||||
|
DF_INSN_LUID (df, DF_REF_INSN (def)):
|
||||||
|
-1,
|
||||||
DF_REF_INSN (def) ? DF_REF_INSN_UID (def) : -1,
|
DF_REF_INSN (def) ? DF_REF_INSN_UID (def) : -1,
|
||||||
DF_REF_REGNO (def));
|
DF_REF_REGNO (def));
|
||||||
if (def->flags & DF_REF_READ_WRITE)
|
if (def->flags & DF_REF_READ_WRITE)
|
||||||
|
|
19
gcc/df.h
19
gcc/df.h
|
@ -593,4 +593,23 @@ extern void df_hard_reg_init (void);
|
||||||
extern bool df_read_modify_subreg_p (rtx);
|
extern bool df_read_modify_subreg_p (rtx);
|
||||||
|
|
||||||
|
|
||||||
|
/* web */
|
||||||
|
|
||||||
|
/* This entry is allocated for each reference in the insn stream. */
|
||||||
|
struct web_entry
|
||||||
|
{
|
||||||
|
/* Pointer to the parent in the union/find tree. */
|
||||||
|
struct web_entry *pred;
|
||||||
|
/* Newly assigned register to the entry. Set only for roots. */
|
||||||
|
rtx reg;
|
||||||
|
void* extra_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct web_entry *unionfind_root (struct web_entry *);
|
||||||
|
extern bool unionfind_union (struct web_entry *, struct web_entry *);
|
||||||
|
extern void union_defs (struct df *, struct df_ref *,
|
||||||
|
struct web_entry *, struct web_entry *,
|
||||||
|
bool (*fun) (struct web_entry *, struct web_entry *));
|
||||||
|
|
||||||
|
|
||||||
#endif /* GCC_DF_H */
|
#endif /* GCC_DF_H */
|
||||||
|
|
|
@ -334,7 +334,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||||
-fsched-spec-load-dangerous @gol
|
-fsched-spec-load-dangerous @gol
|
||||||
-fsched-stalled-insns=@var{n} -fsched-stalled-insns-dep=@var{n} @gol
|
-fsched-stalled-insns=@var{n} -fsched-stalled-insns-dep=@var{n} @gol
|
||||||
-fsched2-use-superblocks @gol
|
-fsched2-use-superblocks @gol
|
||||||
-fsched2-use-traces -freschedule-modulo-scheduled-loops @gol
|
-fsched2-use-traces -fsee -freschedule-modulo-scheduled-loops @gol
|
||||||
-fsection-anchors -fsignaling-nans -fsingle-precision-constant @gol
|
-fsection-anchors -fsignaling-nans -fsingle-precision-constant @gol
|
||||||
-fstack-protector -fstack-protector-all @gol
|
-fstack-protector -fstack-protector-all @gol
|
||||||
-fstrict-aliasing -ftracer -fthread-jumps @gol
|
-fstrict-aliasing -ftracer -fthread-jumps @gol
|
||||||
|
@ -5008,6 +5008,12 @@ match the reality and hurt the performance. This only makes
|
||||||
sense when scheduling after register allocation, i.e.@: with
|
sense when scheduling after register allocation, i.e.@: with
|
||||||
@option{-fschedule-insns2} or at @option{-O2} or higher.
|
@option{-fschedule-insns2} or at @option{-O2} or higher.
|
||||||
|
|
||||||
|
@item -fsee
|
||||||
|
@opindex fsee
|
||||||
|
Eliminates redundant extension instructions and move the non redundant
|
||||||
|
ones to optimal placement using LCM.
|
||||||
|
Enabled at level @option{-O3}.
|
||||||
|
|
||||||
@item -freschedule-modulo-scheduled-loops
|
@item -freschedule-modulo-scheduled-loops
|
||||||
@opindex fscheduling-in-modulo-scheduled-loops
|
@opindex fscheduling-in-modulo-scheduled-loops
|
||||||
The modulo scheduling comes before the traditional scheduling, if a loop was modulo scheduled
|
The modulo scheduling comes before the traditional scheduling, if a loop was modulo scheduled
|
||||||
|
|
|
@ -592,6 +592,7 @@ decode_options (unsigned int argc, const char **argv)
|
||||||
flag_inline_functions = 1;
|
flag_inline_functions = 1;
|
||||||
flag_unswitch_loops = 1;
|
flag_unswitch_loops = 1;
|
||||||
flag_gcse_after_reload = 1;
|
flag_gcse_after_reload = 1;
|
||||||
|
flag_see = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optimize < 2 || optimize_size)
|
if (optimize < 2 || optimize_size)
|
||||||
|
|
|
@ -652,6 +652,7 @@ init_optimization_passes (void)
|
||||||
NEXT_PASS (pass_regmove);
|
NEXT_PASS (pass_regmove);
|
||||||
NEXT_PASS (pass_split_all_insns);
|
NEXT_PASS (pass_split_all_insns);
|
||||||
NEXT_PASS (pass_mode_switching);
|
NEXT_PASS (pass_mode_switching);
|
||||||
|
NEXT_PASS (pass_see);
|
||||||
NEXT_PASS (pass_recompute_reg_usage);
|
NEXT_PASS (pass_recompute_reg_usage);
|
||||||
NEXT_PASS (pass_sms);
|
NEXT_PASS (pass_sms);
|
||||||
NEXT_PASS (pass_sched);
|
NEXT_PASS (pass_sched);
|
||||||
|
|
40
gcc/recog.c
40
gcc/recog.c
|
@ -698,6 +698,46 @@ validate_replace_src_group (rtx from, rtx to, rtx insn)
|
||||||
d.insn = insn;
|
d.insn = insn;
|
||||||
note_uses (&PATTERN (insn), validate_replace_src_1, &d);
|
note_uses (&PATTERN (insn), validate_replace_src_1, &d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try simplify INSN.
|
||||||
|
Invoke simplify_rtx () on every SET_SRC and SET_DEST inside the INSN's
|
||||||
|
pattern and return true if something was simplified. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
validate_simplify_insn (rtx insn)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
rtx pat = NULL;
|
||||||
|
rtx newpat = NULL;
|
||||||
|
|
||||||
|
pat = PATTERN (insn);
|
||||||
|
|
||||||
|
if (GET_CODE (pat) == SET)
|
||||||
|
{
|
||||||
|
newpat = simplify_rtx (SET_SRC (pat));
|
||||||
|
if (newpat && !rtx_equal_p (SET_SRC (pat), newpat))
|
||||||
|
validate_change (insn, &SET_SRC (pat), newpat, 1);
|
||||||
|
newpat = simplify_rtx (SET_DEST (pat));
|
||||||
|
if (newpat && !rtx_equal_p (SET_DEST (pat), newpat))
|
||||||
|
validate_change (insn, &SET_DEST (pat), newpat, 1);
|
||||||
|
}
|
||||||
|
else if (GET_CODE (pat) == PARALLEL)
|
||||||
|
for (i = 0; i < XVECLEN (pat, 0); i++)
|
||||||
|
{
|
||||||
|
rtx s = XVECEXP (pat, 0, i);
|
||||||
|
|
||||||
|
if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
|
||||||
|
{
|
||||||
|
newpat = simplify_rtx (SET_SRC (s));
|
||||||
|
if (newpat && !rtx_equal_p (SET_SRC (s), newpat))
|
||||||
|
validate_change (insn, &SET_SRC (s), newpat, 1);
|
||||||
|
newpat = simplify_rtx (SET_DEST (s));
|
||||||
|
if (newpat && !rtx_equal_p (SET_DEST (s), newpat))
|
||||||
|
validate_change (insn, &SET_DEST (s), newpat, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ((num_changes_pending () > 0) && (apply_change_group () > 0));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_cc0
|
#ifdef HAVE_cc0
|
||||||
/* Return 1 if the insn using CC0 set by INSN does not contain
|
/* Return 1 if the insn using CC0 set by INSN does not contain
|
||||||
|
|
|
@ -87,6 +87,7 @@ extern int strict_memory_address_p (enum machine_mode, rtx);
|
||||||
extern int validate_replace_rtx (rtx, rtx, rtx);
|
extern int validate_replace_rtx (rtx, rtx, rtx);
|
||||||
extern void validate_replace_rtx_group (rtx, rtx, rtx);
|
extern void validate_replace_rtx_group (rtx, rtx, rtx);
|
||||||
extern void validate_replace_src_group (rtx, rtx, rtx);
|
extern void validate_replace_src_group (rtx, rtx, rtx);
|
||||||
|
extern bool validate_simplify_insn (rtx insn);
|
||||||
extern int num_changes_pending (void);
|
extern int num_changes_pending (void);
|
||||||
#ifdef HAVE_cc0
|
#ifdef HAVE_cc0
|
||||||
extern int next_insn_tests_no_inequality (rtx);
|
extern int next_insn_tests_no_inequality (rtx);
|
||||||
|
|
|
@ -145,6 +145,7 @@ DEFTIMEVAR (TV_VPT , "value profile opts")
|
||||||
DEFTIMEVAR (TV_FLOW , "flow analysis")
|
DEFTIMEVAR (TV_FLOW , "flow analysis")
|
||||||
DEFTIMEVAR (TV_COMBINE , "combiner")
|
DEFTIMEVAR (TV_COMBINE , "combiner")
|
||||||
DEFTIMEVAR (TV_IFCVT , "if-conversion")
|
DEFTIMEVAR (TV_IFCVT , "if-conversion")
|
||||||
|
DEFTIMEVAR (TV_SEE , "see")
|
||||||
DEFTIMEVAR (TV_REGMOVE , "regmove")
|
DEFTIMEVAR (TV_REGMOVE , "regmove")
|
||||||
DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
|
DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
|
||||||
DEFTIMEVAR (TV_SMS , "sms modulo scheduling")
|
DEFTIMEVAR (TV_SMS , "sms modulo scheduling")
|
||||||
|
|
|
@ -356,6 +356,7 @@ extern struct tree_opt_pass pass_partition_blocks;
|
||||||
extern struct tree_opt_pass pass_regmove;
|
extern struct tree_opt_pass pass_regmove;
|
||||||
extern struct tree_opt_pass pass_split_all_insns;
|
extern struct tree_opt_pass pass_split_all_insns;
|
||||||
extern struct tree_opt_pass pass_mode_switching;
|
extern struct tree_opt_pass pass_mode_switching;
|
||||||
|
extern struct tree_opt_pass pass_see;
|
||||||
extern struct tree_opt_pass pass_recompute_reg_usage;
|
extern struct tree_opt_pass pass_recompute_reg_usage;
|
||||||
extern struct tree_opt_pass pass_sms;
|
extern struct tree_opt_pass pass_sms;
|
||||||
extern struct tree_opt_pass pass_sched;
|
extern struct tree_opt_pass pass_sched;
|
||||||
|
|
76
gcc/web.c
76
gcc/web.c
|
@ -61,25 +61,12 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
#include "tree-pass.h"
|
#include "tree-pass.h"
|
||||||
|
|
||||||
|
|
||||||
/* This entry is allocated for each reference in the insn stream. */
|
|
||||||
struct web_entry
|
|
||||||
{
|
|
||||||
/* Pointer to the parent in the union/find tree. */
|
|
||||||
struct web_entry *pred;
|
|
||||||
/* Newly assigned register to the entry. Set only for roots. */
|
|
||||||
rtx reg;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct web_entry *unionfind_root (struct web_entry *);
|
|
||||||
static void unionfind_union (struct web_entry *, struct web_entry *);
|
|
||||||
static void union_defs (struct df *, struct df_ref *, struct web_entry *,
|
|
||||||
struct web_entry *);
|
|
||||||
static rtx entry_register (struct web_entry *, struct df_ref *, char *);
|
static rtx entry_register (struct web_entry *, struct df_ref *, char *);
|
||||||
static void replace_ref (struct df_ref *, rtx);
|
static void replace_ref (struct df_ref *, rtx);
|
||||||
|
|
||||||
/* Find the root of unionfind tree (the representative of set). */
|
/* Find the root of unionfind tree (the representative of set). */
|
||||||
|
|
||||||
static struct web_entry *
|
struct web_entry *
|
||||||
unionfind_root (struct web_entry *element)
|
unionfind_root (struct web_entry *element)
|
||||||
{
|
{
|
||||||
struct web_entry *element1 = element, *element2;
|
struct web_entry *element1 = element, *element2;
|
||||||
|
@ -95,30 +82,48 @@ unionfind_root (struct web_entry *element)
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Union sets. */
|
/* Union sets.
|
||||||
|
Return true if FIRST and SECOND points to the same web entry structure and
|
||||||
|
nothing is done. Otherwise, return false. */
|
||||||
|
|
||||||
static void
|
bool
|
||||||
unionfind_union (struct web_entry *first, struct web_entry *second)
|
unionfind_union (struct web_entry *first, struct web_entry *second)
|
||||||
{
|
{
|
||||||
first = unionfind_root (first);
|
first = unionfind_root (first);
|
||||||
second = unionfind_root (second);
|
second = unionfind_root (second);
|
||||||
if (first == second)
|
if (first == second)
|
||||||
return;
|
return true;
|
||||||
second->pred = first;
|
second->pred = first;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For each use, all possible defs reaching it must come in the same
|
/* For each use, all possible defs reaching it must come in the same
|
||||||
register, union them. */
|
register, union them.
|
||||||
|
FUN is the function that does the union. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
union_defs (struct df *df, struct df_ref *use, struct web_entry *def_entry,
|
union_defs (struct df *df, struct df_ref *use, struct web_entry *def_entry,
|
||||||
struct web_entry *use_entry)
|
struct web_entry *use_entry,
|
||||||
|
bool (*fun) (struct web_entry *, struct web_entry *))
|
||||||
{
|
{
|
||||||
rtx insn = DF_REF_INSN (use);
|
rtx insn = DF_REF_INSN (use);
|
||||||
struct df_link *link = DF_REF_CHAIN (use);
|
struct df_link *link = DF_REF_CHAIN (use);
|
||||||
struct df_ref *use_link = DF_INSN_USES (df, insn);
|
struct df_ref *use_link;
|
||||||
struct df_ref *def_link = DF_INSN_DEFS (df, insn);
|
struct df_ref *def_link;
|
||||||
rtx set = single_set (insn);
|
rtx set;
|
||||||
|
|
||||||
|
if (insn)
|
||||||
|
{
|
||||||
|
use_link = DF_INSN_USES (df, insn);
|
||||||
|
def_link = DF_INSN_DEFS (df, insn);
|
||||||
|
set = single_set (insn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
use_link = NULL;
|
||||||
|
def_link = NULL;
|
||||||
|
set = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Some instructions may use match_dup for their operands. In case the
|
/* Some instructions may use match_dup for their operands. In case the
|
||||||
operands are dead, we will assign them different pseudos, creating
|
operands are dead, we will assign them different pseudos, creating
|
||||||
|
@ -129,8 +134,8 @@ union_defs (struct df *df, struct df_ref *use, struct web_entry *def_entry,
|
||||||
{
|
{
|
||||||
if (use != use_link
|
if (use != use_link
|
||||||
&& DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link))
|
&& DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link))
|
||||||
unionfind_union (use_entry + DF_REF_ID (use),
|
(*fun) (use_entry + DF_REF_ID (use),
|
||||||
use_entry + DF_REF_ID (use_link));
|
use_entry + DF_REF_ID (use_link));
|
||||||
use_link = use_link->next_ref;
|
use_link = use_link->next_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,15 +150,15 @@ union_defs (struct df *df, struct df_ref *use, struct web_entry *def_entry,
|
||||||
while (def_link)
|
while (def_link)
|
||||||
{
|
{
|
||||||
if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link))
|
if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link))
|
||||||
unionfind_union (use_entry + DF_REF_ID (use),
|
(*fun) (use_entry + DF_REF_ID (use),
|
||||||
def_entry + DF_REF_ID (def_link));
|
def_entry + DF_REF_ID (def_link));
|
||||||
def_link = def_link->next_ref;
|
def_link = def_link->next_ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (link)
|
while (link)
|
||||||
{
|
{
|
||||||
unionfind_union (use_entry + DF_REF_ID (use),
|
(*fun) (use_entry + DF_REF_ID (use),
|
||||||
def_entry + DF_REF_ID (link->ref));
|
def_entry + DF_REF_ID (link->ref));
|
||||||
link = link->next;
|
link = link->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,13 +166,18 @@ union_defs (struct df *df, struct df_ref *use, struct web_entry *def_entry,
|
||||||
register. Find it and union. */
|
register. Find it and union. */
|
||||||
if (use->flags & DF_REF_READ_WRITE)
|
if (use->flags & DF_REF_READ_WRITE)
|
||||||
{
|
{
|
||||||
struct df_ref *link = DF_INSN_DEFS (df, DF_REF_INSN (use));
|
struct df_ref *link;
|
||||||
|
|
||||||
|
if (DF_REF_INSN (use))
|
||||||
|
link = DF_INSN_DEFS (df, DF_REF_INSN (use));
|
||||||
|
else
|
||||||
|
link = NULL;
|
||||||
|
|
||||||
while (link)
|
while (link)
|
||||||
{
|
{
|
||||||
if (DF_REF_REAL_REG (link) == DF_REF_REAL_REG (use))
|
if (DF_REF_REAL_REG (link) == DF_REF_REAL_REG (use))
|
||||||
unionfind_union (use_entry + DF_REF_ID (use),
|
(*fun) (use_entry + DF_REF_ID (use),
|
||||||
def_entry + DF_REF_ID (link));
|
def_entry + DF_REF_ID (link));
|
||||||
link = link->next_ref;
|
link = link->next_ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,7 +268,7 @@ web_main (void)
|
||||||
|
|
||||||
/* Produce the web. */
|
/* Produce the web. */
|
||||||
for (i = 0; i < DF_USES_SIZE (df); i++)
|
for (i = 0; i < DF_USES_SIZE (df); i++)
|
||||||
union_defs (df, DF_USES_GET (df, i), def_entry, use_entry);
|
union_defs (df, DF_USES_GET (df, i), def_entry, use_entry, unionfind_union);
|
||||||
|
|
||||||
/* Update the instruction stream, allocating new registers for split pseudos
|
/* Update the instruction stream, allocating new registers for split pseudos
|
||||||
in progress. */
|
in progress. */
|
||||||
|
|
Loading…
Reference in New Issue