[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:
Razya Ladelsky 2006-05-04 09:19:02 +00:00
parent 23ba9627f4
commit 8cd37d0b6c
16 changed files with 4030 additions and 37 deletions

View File

@ -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>
PR tree-optimization/26447

View File

@ -995,7 +995,7 @@ OBJS-common = \
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 \
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 \
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 \
@ -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) \
hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.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) \
$(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 \

View File

@ -1001,6 +1001,8 @@ extern basic_block get_bb_original (basic_block);
extern void set_bb_copy (basic_block, basic_block);
extern basic_block get_bb_copy (basic_block);
extern rtx insert_insn_end_bb_new (rtx, basic_block);
#include "cfghooks.h"
/* In struct-equiv.c */

View File

@ -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. */
struct cfg_hooks rtl_cfg_hooks = {
"rtl",
@ -2973,4 +3060,3 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
rtl_extract_cond_bb_edges, /* extract_cond_bb_edges */
NULL /* flush_pending_stmts */
};

View File

@ -809,6 +809,10 @@ frtl-abstract-sequences
Common Report Var(flag_rtl_seqabstr)
Perform sequence abstraction optimization on RTL
fsee
Common Report Var(flag_see) Init(0)
Eliminate redundant sign extensions using LCM.
fshow-column
Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(1)
Show column numbers in diagnostics, when available. Default on

View File

@ -2992,7 +2992,9 @@ df_chains_dump (struct dataflow *dflow, FILE *file)
{
fprintf (file, "d%d bb %d luid %d insn %d reg %d ",
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_REGNO (def));
if (def->flags & DF_REF_READ_WRITE)

View File

@ -593,4 +593,23 @@ extern void df_hard_reg_init (void);
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 */

View File

@ -334,7 +334,7 @@ Objective-C and Objective-C++ Dialects}.
-fsched-spec-load-dangerous @gol
-fsched-stalled-insns=@var{n} -fsched-stalled-insns-dep=@var{n} @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
-fstack-protector -fstack-protector-all @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
@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
@opindex fscheduling-in-modulo-scheduled-loops
The modulo scheduling comes before the traditional scheduling, if a loop was modulo scheduled

View File

@ -592,6 +592,7 @@ decode_options (unsigned int argc, const char **argv)
flag_inline_functions = 1;
flag_unswitch_loops = 1;
flag_gcse_after_reload = 1;
flag_see = 1;
}
if (optimize < 2 || optimize_size)

View File

@ -652,6 +652,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_regmove);
NEXT_PASS (pass_split_all_insns);
NEXT_PASS (pass_mode_switching);
NEXT_PASS (pass_see);
NEXT_PASS (pass_recompute_reg_usage);
NEXT_PASS (pass_sms);
NEXT_PASS (pass_sched);

View File

@ -698,6 +698,46 @@ validate_replace_src_group (rtx from, rtx to, rtx insn)
d.insn = insn;
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
/* Return 1 if the insn using CC0 set by INSN does not contain

View File

@ -87,6 +87,7 @@ extern int strict_memory_address_p (enum machine_mode, rtx);
extern int validate_replace_rtx (rtx, rtx, rtx);
extern void validate_replace_rtx_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);
#ifdef HAVE_cc0
extern int next_insn_tests_no_inequality (rtx);

3782
gcc/see.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -145,6 +145,7 @@ DEFTIMEVAR (TV_VPT , "value profile opts")
DEFTIMEVAR (TV_FLOW , "flow analysis")
DEFTIMEVAR (TV_COMBINE , "combiner")
DEFTIMEVAR (TV_IFCVT , "if-conversion")
DEFTIMEVAR (TV_SEE , "see")
DEFTIMEVAR (TV_REGMOVE , "regmove")
DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
DEFTIMEVAR (TV_SMS , "sms modulo scheduling")

View File

@ -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_split_all_insns;
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_sms;
extern struct tree_opt_pass pass_sched;

View File

@ -61,25 +61,12 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#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 void replace_ref (struct df_ref *, rtx);
/* Find the root of unionfind tree (the representative of set). */
static struct web_entry *
struct web_entry *
unionfind_root (struct web_entry *element)
{
struct web_entry *element1 = element, *element2;
@ -95,30 +82,48 @@ unionfind_root (struct web_entry *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)
{
first = unionfind_root (first);
second = unionfind_root (second);
if (first == second)
return;
return true;
second->pred = first;
return false;
}
/* 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,
struct web_entry *use_entry)
struct web_entry *use_entry,
bool (*fun) (struct web_entry *, struct web_entry *))
{
rtx insn = DF_REF_INSN (use);
struct df_link *link = DF_REF_CHAIN (use);
struct df_ref *use_link = DF_INSN_USES (df, insn);
struct df_ref *def_link = DF_INSN_DEFS (df, insn);
rtx set = single_set (insn);
struct df_ref *use_link;
struct df_ref *def_link;
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
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
&& DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link))
unionfind_union (use_entry + DF_REF_ID (use),
use_entry + DF_REF_ID (use_link));
(*fun) (use_entry + DF_REF_ID (use),
use_entry + DF_REF_ID (use_link));
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)
{
if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link))
unionfind_union (use_entry + DF_REF_ID (use),
def_entry + DF_REF_ID (def_link));
(*fun) (use_entry + DF_REF_ID (use),
def_entry + DF_REF_ID (def_link));
def_link = def_link->next_ref;
}
}
while (link)
{
unionfind_union (use_entry + DF_REF_ID (use),
def_entry + DF_REF_ID (link->ref));
(*fun) (use_entry + DF_REF_ID (use),
def_entry + DF_REF_ID (link->ref));
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. */
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)
{
if (DF_REF_REAL_REG (link) == DF_REF_REAL_REG (use))
unionfind_union (use_entry + DF_REF_ID (use),
def_entry + DF_REF_ID (link));
(*fun) (use_entry + DF_REF_ID (use),
def_entry + DF_REF_ID (link));
link = link->next_ref;
}
}
@ -258,7 +268,7 @@ web_main (void)
/* Produce the web. */
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
in progress. */