cfgcleanup.c (outgoing_edges_match): Compare the jump tables.

* cfgcleanup.c (outgoing_edges_match): Compare the jump tables.
	(try_crossjump_to_edge): Replace refereces to one jump table by
	references to identical jump table.
	* loop.c (load_mems): Moved setting the JUMP_LABEL to replace_label.
	(replace_label): Moved to rtlanal.c.
	(struct rtx_pair): Moved to rtl.h.
	* rtl.h (struct rtx_pair): Moved from loop.c.
	(replace_label): New extern function.
	(subrtx_p): New extern function.
	(tablejump_p): New extern function.
	* rtlanal.c (replace_label): Moved from loop.c.
	(subrtx_p_1): New static function.
	(subrtx_p): New function.
	(tablejump_p): New function.

From-SVN: r64096
This commit is contained in:
Josef Zlomek 2003-03-10 18:23:44 +01:00 committed by Josef Zlomek
parent 8f474219ec
commit 398111844b
5 changed files with 220 additions and 48 deletions

View File

@ -1,3 +1,20 @@
2003-03-10 Josef Zlomek <zlomekj@suse.cz>
* cfgcleanup.c (outgoing_edges_match): Compare the jump tables.
(try_crossjump_to_edge): Replace refereces to one jump table by
references to identical jump table.
* loop.c (load_mems): Moved setting the JUMP_LABEL to replace_label.
(replace_label): Moved to rtlanal.c.
(struct rtx_pair): Moved to rtl.h.
* rtl.h (struct rtx_pair): Moved from loop.c.
(replace_label): New extern function.
(subrtx_p): New extern function.
(tablejump_p): New extern function.
* rtlanal.c (replace_label): Moved from loop.c.
(subrtx_p_1): New static function.
(subrtx_p): New function.
(tablejump_p): New function.
Mon Mar 10 15:30:36 CET 2003 Jan Hubicka <jh@suse.cz>
* cfgcleanup.c (merge_blocks): Return where to iterate next.

View File

@ -1254,10 +1254,83 @@ outgoing_edges_match (mode, bb1, bb2)
/* Generic case - we are seeing a computed jump, table jump or trapping
instruction. */
#ifndef CASE_DROPS_THROUGH
/* Check whether there are tablejumps in the end of BB1 and BB2.
Return true if they are identical. */
{
rtx label1, label2;
rtx table1, table2;
if (tablejump_p (bb1->end, &label1, &table1)
&& tablejump_p (bb2->end, &label2, &table2)
&& GET_CODE (PATTERN (table1)) == GET_CODE (PATTERN (table2)))
{
/* The labels should never be the same rtx. If they really are same
the jump tables are same too. So disable crossjumping of blocks BB1
and BB2 because when deleting the common insns in the end of BB1
by flow_delete_block () the jump table would be deleted too. */
/* If LABEL2 is contained in BB1->END do not do anything
because we would loose information when replacing
LABEL1 by LABEL2 and then LABEL2 by LABEL1 in BB1->END. */
if (label1 != label2 && !subrtx_p (label2, bb1->end))
{
/* Set IDENTICAL to true when the tables are identical. */
bool identical = false;
rtx p1, p2;
p1 = PATTERN (table1);
p2 = PATTERN (table2);
if (GET_CODE (p1) == ADDR_VEC && rtx_equal_p (p1, p2))
{
identical = true;
}
else if (GET_CODE (p1) == ADDR_DIFF_VEC
&& (XVECLEN (p1, 1) == XVECLEN (p2, 1))
&& rtx_equal_p (XEXP (p1, 2), XEXP (p2, 2))
&& rtx_equal_p (XEXP (p1, 3), XEXP (p2, 3)))
{
int i;
identical = true;
for (i = XVECLEN (p1, 1) - 1; i >= 0 && identical; i--)
if (!rtx_equal_p (XVECEXP (p1, 1, i), XVECEXP (p2, 1, i)))
identical = false;
}
if (identical)
{
rtx_pair rr;
bool match;
/* Temporarily replace references to LABEL1 with LABEL2
in BB1->END so that we could compare the instructions. */
rr.r1 = label1;
rr.r2 = label2;
for_each_rtx (&bb1->end, replace_label, &rr);
match = insns_match_p (mode, bb1->end, bb2->end);
if (rtl_dump_file && match)
fprintf (rtl_dump_file,
"Tablejumps in bb %i and %i match.\n",
bb1->index, bb2->index);
/* Set the original label in BB1->END because when deleting
a block whose end is a tablejump, the tablejump referenced
from the instruction is deleted too. */
rr.r1 = label2;
rr.r2 = label1;
for_each_rtx (&bb1->end, replace_label, &rr);
return match;
}
}
return false;
}
}
#endif
/* First ensure that the instructions match. There may be many outgoing
edges so this test is generally cheaper.
??? Currently the tablejumps will never match, as they do have
different tables. */
edges so this test is generally cheaper. */
if (!insns_match_p (mode, bb1->end, bb2->end))
return false;
@ -1370,6 +1443,38 @@ try_crossjump_to_edge (mode, e1, e2)
if (!nmatch)
return false;
#ifndef CASE_DROPS_THROUGH
/* Here we know that the insns in the end of SRC1 which are common with SRC2
will be deleted.
If we have tablejumps in the end of SRC1 and SRC2
they have been already compared for equivalence in outgoing_edges_match ()
so replace the references to TABLE1 by references to TABLE2. */
{
rtx label1, label2;
rtx table1, table2;
if (tablejump_p (src1->end, &label1, &table1)
&& tablejump_p (src2->end, &label2, &table2)
&& label1 != label2)
{
rtx_pair rr;
rtx insn;
/* Replace references to LABEL1 with LABEL2. */
rr.r1 = label1;
rr.r2 = label2;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
/* Do not replace the label in SRC1->END because when deleting
a block whose end is a tablejump, the tablejump referenced
from the instruction is deleted too. */
if (insn != src1->end)
for_each_rtx (&insn, replace_label, &rr);
}
}
}
#endif
/* Avoid splitting if possible. */
if (newpos2 == src2->head)
redirect_to = src2;

View File

@ -338,7 +338,6 @@ static void note_reg_stored PARAMS ((rtx, rtx, void *));
static void try_copy_prop PARAMS ((const struct loop *, rtx, unsigned int));
static void try_swap_copy_prop PARAMS ((const struct loop *, rtx,
unsigned int));
static int replace_label PARAMS ((rtx *, void *));
static rtx check_insn_for_givs PARAMS((struct loop *, rtx, int, int));
static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int));
static rtx gen_add_mult PARAMS ((rtx, rtx, rtx, rtx));
@ -363,12 +362,6 @@ void debug_giv PARAMS ((const struct induction *));
void debug_loop PARAMS ((const struct loop *));
void debug_loops PARAMS ((const struct loops *));
typedef struct rtx_pair
{
rtx r1;
rtx r2;
} rtx_pair;
typedef struct loop_replace_args
{
rtx match;
@ -10151,15 +10144,6 @@ load_mems (loop)
for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
{
for_each_rtx (&p, replace_label, &rr);
/* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
field. This is not handled by for_each_rtx because it doesn't
handle unprinted ('0') fields. We need to update JUMP_LABEL
because the immediately following unroll pass will use it.
replace_label would not work anyways, because that only handles
LABEL_REFs. */
if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == end_label)
JUMP_LABEL (p) = label;
}
}
@ -10489,35 +10473,6 @@ replace_loop_regs (insn, reg, replacement)
for_each_rtx (&insn, replace_loop_reg, &args);
}
/* Replace occurrences of the old exit label for the loop with the new
one. DATA is an rtx_pair containing the old and new labels,
respectively. */
static int
replace_label (x, data)
rtx *x;
void *data;
{
rtx l = *x;
rtx old_label = ((rtx_pair *) data)->r1;
rtx new_label = ((rtx_pair *) data)->r2;
if (l == NULL_RTX)
return 0;
if (GET_CODE (l) != LABEL_REF)
return 0;
if (XEXP (l, 0) != old_label)
return 0;
XEXP (l, 0) = new_label;
++LABEL_NUSES (new_label);
--LABEL_NUSES (old_label);
return 0;
}
/* Emit insn for PATTERN after WHERE_INSN in basic block WHERE_BB
(ignored in the interim). */

View File

@ -1595,6 +1595,13 @@ extern rtx set_unique_reg_note PARAMS ((rtx, enum reg_note, rtx));
: NULL_RTX)
#define single_set_1(I) single_set_2 (I, PATTERN (I))
/* Structure used for passing data to REPLACE_LABEL. */
typedef struct rtx_pair
{
rtx r1;
rtx r2;
} rtx_pair;
extern int rtx_addr_can_trap_p PARAMS ((rtx));
extern bool nonzero_address_p PARAMS ((rtx));
extern int rtx_unstable_p PARAMS ((rtx));
@ -1654,6 +1661,9 @@ extern int inequality_comparisons_p PARAMS ((rtx));
extern rtx replace_rtx PARAMS ((rtx, rtx, rtx));
extern rtx replace_regs PARAMS ((rtx, rtx *, unsigned int,
int));
extern int replace_label PARAMS ((rtx *, void *));
extern int subrtx_p PARAMS ((rtx, rtx));
extern bool tablejump_p PARAMS ((rtx, rtx *, rtx *));
extern int computed_jump_p PARAMS ((rtx));
typedef int (*rtx_function) PARAMS ((rtx *, void *));
extern int for_each_rtx PARAMS ((rtx *, rtx_function, void *));

View File

@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
static void set_of_1 PARAMS ((rtx, rtx, void *));
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
static int subrtx_p_1 PARAMS ((rtx *, void *));
static int computed_jump_p_1 PARAMS ((rtx));
static void parms_set PARAMS ((rtx, rtx, void *));
static bool hoist_test_store PARAMS ((rtx, rtx, regset));
@ -2791,6 +2792,90 @@ replace_regs (x, reg_map, nregs, replace_dest)
return x;
}
/* Replace occurrences of the old label in *X with the new one.
DATA is an rtx_pair containing the old and new labels, respectively. */
int
replace_label (x, data)
rtx *x;
void *data;
{
rtx l = *x;
rtx old_label = ((rtx_pair *) data)->r1;
rtx new_label = ((rtx_pair *) data)->r2;
if (l == NULL_RTX)
return 0;
/* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
field. This is not handled by for_each_rtx because it doesn't
handle unprinted ('0') fields. */
if (GET_CODE (l) == JUMP_INSN && JUMP_LABEL (l) == old_label)
JUMP_LABEL (l) = new_label;
if (GET_CODE (l) != LABEL_REF)
return 0;
if (XEXP (l, 0) != old_label)
return 0;
XEXP (l, 0) = new_label;
++LABEL_NUSES (new_label);
--LABEL_NUSES (old_label);
return 0;
}
/* Return RTX_EQUAL_P (*PX, SUBX). If *PX and SUBX are not equal
FOR_EACH_RTX continues traversing, if they are equal FOR_EACH_RTX
stops traversing and returns the same value as this function. */
static int
subrtx_p_1 (px, subx)
rtx *px;
void *subx;
{
return rtx_equal_p (*px, (rtx) subx);
}
/* Return true if SUBX is equal to some subexpression of X. */
int
subrtx_p (subx, x)
rtx subx;
rtx x;
{
return for_each_rtx (&x, subrtx_p_1, subx);
}
/* If INSN is a jump to jumptable insn rturn true and store the label (which
INSN jumps to) to *LABEL and the tablejump insn to *TABLE.
LABEL and TABLE may be NULL. */
bool
tablejump_p (insn, label, table)
rtx insn;
rtx *label;
rtx *table;
{
rtx l, t;
if (onlyjump_p (insn)
&& (l = JUMP_LABEL (insn)) != NULL_RTX
&& (t = NEXT_INSN (l)) != NULL_RTX
&& GET_CODE (t) == JUMP_INSN
&& (GET_CODE (PATTERN (t)) == ADDR_VEC
|| GET_CODE (PATTERN (t)) == ADDR_DIFF_VEC))
{
if (label)
*label = l;
if (table)
*table = t;
return true;
}
return false;
}
/* A subroutine of computed_jump_p, return 1 if X contains a REG or MEM or
constant that is not in the constant pool and not in the condition
of an IF_THEN_ELSE. */