struct-equiv.c: Remove file.

2008-03-02  Andi Kleen  <ak@suse.de>
	Richard Guenther  <rguenther@suse.de>

	* struct-equiv.c: Remove file.
	* cfg_cleanup.c (condjump_equiv_p): Remove.
	* Makefile.in (OBJS-common): Remove struct-equiv.o.
	(struct-equiv.o): Remove rule.
	* basic-block.h (struct_equiv_checkpoint, STRUCT_EQUIV_*,
	insns_match_p, struct_equiv_block_eq, struct_equiv_init, 
	rtx_equiv_p, condjump_equiv_p): Remove prototypes.

Co-Authored-By: Richard Guenther <rguenther@suse.de>

From-SVN: r132814
This commit is contained in:
Andi Kleen 2008-03-02 12:09:08 +00:00 committed by Richard Biener
parent 363d536b17
commit f3130d75de
5 changed files with 11 additions and 1648 deletions

View File

@ -1,3 +1,14 @@
2008-03-02 Andi Kleen <ak@suse.de>
Richard Guenther <rguenther@suse.de>
* struct-equiv.c: Remove file.
* cfg_cleanup.c (condjump_equiv_p): Remove.
* Makefile.in (OBJS-common): Remove struct-equiv.o.
(struct-equiv.o): Remove rule.
* basic-block.h (struct_equiv_checkpoint, STRUCT_EQUIV_*,
insns_match_p, struct_equiv_block_eq, struct_equiv_init,
rtx_equiv_p, condjump_equiv_p): Remove prototypes.
2008-03-01 Alexandre Oliva <aoliva@redhat.com>
* ifcvt.c (noce_process_if_block): Try to handle only the then

View File

@ -1138,7 +1138,6 @@ OBJS-common = \
stmt.o \
stor-layout.o \
stringpool.o \
struct-equiv.o \
targhooks.o \
timevar.o \
toplev.o \
@ -2677,10 +2676,6 @@ cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(OBSTACK_H) output.h graphds.h
graphds.o : graphds.c graphds.h $(CONFIG_H) $(SYSTEM_H) bitmap.h $(OBSTACK_H) \
coretypes.h vec.h vecprim.h
struct-equiv.o : struct-equiv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) hard-reg-set.h output.h $(FLAGS_H) $(RECOG_H) \
insn-config.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \
$(REGS_H) $(EMIT_RTL_H) $(DF_H)
loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) \
output.h intl.h $(DF_H) $(HASHTAB_H)

View File

@ -805,17 +805,6 @@ edge find_edge (basic_block, basic_block);
insns. */
#define CLEANUP_CFGLAYOUT 32 /* Do cleanup in cfglayout mode. */
/* The following are ORed in on top of the CLEANUP* flags in calls to
struct_equiv_block_eq. */
#define STRUCT_EQUIV_START 64 /* Initializes the search range. */
#define STRUCT_EQUIV_RERUN 128 /* Rerun to find register use in
found equivalence. */
#define STRUCT_EQUIV_FINAL 256 /* Make any changes necessary to get
actual equivalence. */
#define STRUCT_EQUIV_NEED_FULL_BLOCK 512 /* struct_equiv_block_eq is required
to match only full blocks */
#define STRUCT_EQUIV_MATCH_JUMPS 1024 /* Also include the jumps at the end of the block in the comparison. */
/* In lcm.c */
extern struct edge_list *pre_edge_lcm (int, sbitmap *, sbitmap *,
sbitmap *, sbitmap *, sbitmap **,
@ -955,171 +944,6 @@ extern rtx insert_insn_end_bb_new (rtx, basic_block);
#include "cfghooks.h"
/* In struct-equiv.c */
/* Constants used to size arrays in struct equiv_info (currently only one).
When these limits are exceeded, struct_equiv returns zero.
The maximum number of pseudo registers that are different in the two blocks,
but appear in equivalent places and are dead at the end (or where one of
a pair is dead at the end). */
#define STRUCT_EQUIV_MAX_LOCAL 16
/* The maximum number of references to an input register that struct_equiv
can handle. */
/* Structure used to track state during struct_equiv that can be rolled
back when we find we can't match an insn, or if we want to match part
of it in a different way.
This information pertains to the pair of partial blocks that has been
matched so far. Since this pair is structurally equivalent, this is
conceptually just one partial block expressed in two potentially
different ways. */
struct struct_equiv_checkpoint
{
int ninsns; /* Insns are matched so far. */
int local_count; /* Number of block-local registers. */
int input_count; /* Number of inputs to the block. */
/* X_START and Y_START are the first insns (in insn stream order)
of the partial blocks that have been considered for matching so far.
Since we are scanning backwards, they are also the instructions that
are currently considered - or the last ones that have been considered -
for matching (Unless we tracked back to these because a preceding
instruction failed to match). */
rtx x_start, y_start;
/* INPUT_VALID indicates if we have actually set up X_INPUT / Y_INPUT
during the current pass; we keep X_INPUT / Y_INPUT around between passes
so that we can match REG_EQUAL / REG_EQUIV notes referring to these. */
bool input_valid;
/* Some information would be expensive to exactly checkpoint, so we
merely increment VERSION any time information about local
registers, inputs and/or register liveness changes. When backtracking,
it is decremented for changes that can be undone, and if a discrepancy
remains, NEED_RERUN in the relevant struct equiv_info is set to indicate
that a new pass should be made over the entire block match to get
accurate register information. */
int version;
};
/* A struct equiv_info is used to pass information to struct_equiv and
to gather state while two basic blocks are checked for structural
equivalence. */
struct equiv_info
{
/* Fields set up by the caller to struct_equiv_block_eq */
basic_block x_block, y_block; /* The two blocks being matched. */
/* MODE carries the mode bits from cleanup_cfg if we are called from
try_crossjump_to_edge, and additionally it carries the
STRUCT_EQUIV_* bits described above. */
int mode;
/* INPUT_COST is the cost that adding an extra input to the matched blocks
is supposed to have, and is taken into account when considering if the
matched sequence should be extended backwards. input_cost < 0 means
don't accept any inputs at all. */
int input_cost;
/* Fields to track state inside of struct_equiv_block_eq. Some of these
are also outputs. */
/* X_INPUT and Y_INPUT are used by struct_equiv to record a register that
is used as an input parameter, i.e. where different registers are used
as sources. This is only used for a register that is live at the end
of the blocks, or in some identical code at the end of the blocks;
Inputs that are dead at the end go into X_LOCAL / Y_LOCAL. */
rtx x_input, y_input;
/* When a previous pass has identified a valid input, INPUT_REG is set
by struct_equiv_block_eq, and it is henceforth replaced in X_BLOCK
for the input. */
rtx input_reg;
/* COMMON_LIVE keeps track of the registers which are currently live
(as we scan backwards from the end) and have the same numbers in both
blocks. N.B. a register that is in common_live is unsuitable to become
a local reg. */
regset common_live;
/* Likewise, X_LOCAL_LIVE / Y_LOCAL_LIVE keep track of registers that are
local to one of the blocks; these registers must not be accepted as
identical when encountered in both blocks. */
regset x_local_live, y_local_live;
/* EQUIV_USED indicates for which insns a REG_EQUAL or REG_EQUIV note is
being used, to avoid having to backtrack in the next pass, so that we
get accurate life info for this insn then. For each such insn,
the bit with the number corresponding to the CUR.NINSNS value at the
time of scanning is set. */
bitmap equiv_used;
/* Current state that can be saved & restored easily. */
struct struct_equiv_checkpoint cur;
/* BEST_MATCH is used to store the best match so far, weighing the
cost of matched insns COSTS_N_INSNS (CUR.NINSNS) against the cost
CUR.INPUT_COUNT * INPUT_COST of setting up the inputs. */
struct struct_equiv_checkpoint best_match;
/* If a checkpoint restore failed, or an input conflict newly arises,
NEED_RERUN is set. This has to be tested by the caller to re-run
the comparison if the match appears otherwise sound. The state kept in
x_start, y_start, equiv_used and check_input_conflict ensures that
we won't loop indefinitely. */
bool need_rerun;
/* If there is indication of an input conflict at the end,
CHECK_INPUT_CONFLICT is set so that we'll check for input conflicts
for each insn in the next pass. This is needed so that we won't discard
a partial match if there is a longer match that has to be abandoned due
to an input conflict. */
bool check_input_conflict;
/* HAD_INPUT_CONFLICT is set if CHECK_INPUT_CONFLICT was already set and we
have passed a point where there were multiple dying inputs. This helps
us decide if we should set check_input_conflict for the next pass. */
bool had_input_conflict;
/* LIVE_UPDATE controls if we want to change any life info at all. We
set it to false during REG_EQUAL / REG_EUQIV note comparison of the final
pass so that we don't introduce new registers just for the note; if we
can't match the notes without the current register information, we drop
them. */
bool live_update;
/* X_LOCAL and Y_LOCAL are used to gather register numbers of register pairs
that are local to X_BLOCK and Y_BLOCK, with CUR.LOCAL_COUNT being the index
to the next free entry. */
rtx x_local[STRUCT_EQUIV_MAX_LOCAL], y_local[STRUCT_EQUIV_MAX_LOCAL];
/* LOCAL_RVALUE is nonzero if the corresponding X_LOCAL / Y_LOCAL entry
was a source operand (including STRICT_LOW_PART) for the last invocation
of struct_equiv mentioning it, zero if it was a destination-only operand.
Since we are scanning backwards, this means the register is input/local
for the (partial) block scanned so far. */
bool local_rvalue[STRUCT_EQUIV_MAX_LOCAL];
/* Additional fields that are computed for the convenience of the caller. */
/* DYING_INPUTS is set to the number of local registers that turn out
to be inputs to the (possibly partial) block. */
int dying_inputs;
/* X_END and Y_END are the last insns in X_BLOCK and Y_BLOCK, respectively,
that are being compared. A final jump insn will not be included. */
rtx x_end, y_end;
/* If we are matching tablejumps, X_LABEL in X_BLOCK corresponds to
Y_LABEL in Y_BLOCK. */
rtx x_label, y_label;
};
extern bool insns_match_p (rtx, rtx, struct equiv_info *);
extern int struct_equiv_block_eq (int, struct equiv_info *);
extern bool struct_equiv_init (int, struct equiv_info *);
extern bool rtx_equiv_p (rtx *, rtx, int, struct equiv_info *);
/* In cfgcleanup.c */
extern bool condjump_equiv_p (struct equiv_info *, bool);
/* Return true when one of the predecessor edges of BB is marked with EDGE_EH. */
static inline bool
bb_has_eh_pred (basic_block bb)

View File

@ -1134,134 +1134,6 @@ flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1,
return ninsns;
}
/* Return true iff the condbranches at the end of BB1 and BB2 match. */
bool
condjump_equiv_p (struct equiv_info *info, bool call_init)
{
basic_block bb1 = info->x_block;
basic_block bb2 = info->y_block;
edge b1 = BRANCH_EDGE (bb1);
edge b2 = BRANCH_EDGE (bb2);
edge f1 = FALLTHRU_EDGE (bb1);
edge f2 = FALLTHRU_EDGE (bb2);
bool reverse, match;
rtx set1, set2, cond1, cond2;
rtx src1, src2;
enum rtx_code code1, code2;
/* Get around possible forwarders on fallthru edges. Other cases
should be optimized out already. */
if (FORWARDER_BLOCK_P (f1->dest))
f1 = single_succ_edge (f1->dest);
if (FORWARDER_BLOCK_P (f2->dest))
f2 = single_succ_edge (f2->dest);
/* To simplify use of this function, return false if there are
unneeded forwarder blocks. These will get eliminated later
during cleanup_cfg. */
if (FORWARDER_BLOCK_P (f1->dest)
|| FORWARDER_BLOCK_P (f2->dest)
|| FORWARDER_BLOCK_P (b1->dest)
|| FORWARDER_BLOCK_P (b2->dest))
return false;
if (f1->dest == f2->dest && b1->dest == b2->dest)
reverse = false;
else if (f1->dest == b2->dest && b1->dest == f2->dest)
reverse = true;
else
return false;
set1 = pc_set (BB_END (bb1));
set2 = pc_set (BB_END (bb2));
if ((XEXP (SET_SRC (set1), 1) == pc_rtx)
!= (XEXP (SET_SRC (set2), 1) == pc_rtx))
reverse = !reverse;
src1 = SET_SRC (set1);
src2 = SET_SRC (set2);
cond1 = XEXP (src1, 0);
cond2 = XEXP (src2, 0);
code1 = GET_CODE (cond1);
if (reverse)
code2 = reversed_comparison_code (cond2, BB_END (bb2));
else
code2 = GET_CODE (cond2);
if (code2 == UNKNOWN)
return false;
if (call_init && !struct_equiv_init (STRUCT_EQUIV_START | info->mode, info))
gcc_unreachable ();
/* Make the sources of the pc sets unreadable so that when we call
insns_match_p it won't process them.
The death_notes_match_p from insns_match_p won't see the local registers
used for the pc set, but that could only cause missed optimizations when
there are actually condjumps that use stack registers. */
SET_SRC (set1) = pc_rtx;
SET_SRC (set2) = pc_rtx;
/* Verify codes and operands match. */
if (code1 == code2)
{
match = (insns_match_p (BB_END (bb1), BB_END (bb2), info)
&& rtx_equiv_p (&XEXP (cond1, 0), XEXP (cond2, 0), 1, info)
&& rtx_equiv_p (&XEXP (cond1, 1), XEXP (cond2, 1), 1, info));
}
else if (code1 == swap_condition (code2))
{
match = (insns_match_p (BB_END (bb1), BB_END (bb2), info)
&& rtx_equiv_p (&XEXP (cond1, 1), XEXP (cond2, 0), 1, info)
&& rtx_equiv_p (&XEXP (cond1, 0), XEXP (cond2, 1), 1, info));
}
else
match = false;
SET_SRC (set1) = src1;
SET_SRC (set2) = src2;
match &= verify_changes (0);
/* If we return true, we will join the blocks. Which means that
we will only have one branch prediction bit to work with. Thus
we require the existing branches to have probabilities that are
roughly similar. */
if (match
&& !optimize_size
&& maybe_hot_bb_p (bb1)
&& maybe_hot_bb_p (bb2))
{
int prob2;
if (b1->dest == b2->dest)
prob2 = b2->probability;
else
/* Do not use f2 probability as f2 may be forwarded. */
prob2 = REG_BR_PROB_BASE - b2->probability;
/* Fail if the difference in probabilities is greater than 50%.
This rules out two well-predicted branches with opposite
outcomes. */
if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2)
{
if (dump_file)
fprintf (dump_file,
"Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
bb1->index, bb2->index, b1->probability, prob2);
match = false;
}
}
if (dump_file && match)
fprintf (dump_file, "Conditionals in bb %i and %i match.\n",
bb1->index, bb2->index);
if (!match)
cancel_changes (0);
return match;
}
/* Return true iff outgoing edges of BB1 and BB2 match, together with
the branch instruction. This means that if we commonize the control
flow before end of the basic block, the semantic remains unchanged.

File diff suppressed because it is too large Load Diff