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:
parent
8f474219ec
commit
398111844b
5 changed files with 220 additions and 48 deletions
|
@ -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.
|
||||
|
|
111
gcc/cfgcleanup.c
111
gcc/cfgcleanup.c
|
@ -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;
|
||||
|
|
45
gcc/loop.c
45
gcc/loop.c
|
@ -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). */
|
||||
|
|
10
gcc/rtl.h
10
gcc/rtl.h
|
@ -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 *));
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue