|
|
4ac4fd |
2005-01-03 Jakub Jelinek <jakub@redhat.com>
|
|
|
4ac4fd |
|
|
|
4ac4fd |
* cfgrtl.c (try_redirect_by_replacing_jump): Add 2 arguments to
|
|
|
4ac4fd |
tablejump_p.
|
|
|
4ac4fd |
|
|
|
4ac4fd |
* gcc.c-torture/compile/20050103-1.c: New test.
|
|
|
4ac4fd |
|
|
|
4ac4fd |
2003-07-20 Josef Zlomek <zlomekj@suse.cz>
|
|
|
4ac4fd |
|
|
|
4ac4fd |
* cfgcleanup.c (merge_blocks_move_successor_nojumps): Use tablejump_p.
|
|
|
4ac4fd |
* ifcvt.c (find_if_block): Added 2 arguments to tablejump_p.
|
|
|
4ac4fd |
* jump.c (tablejump_p): Added 2 arguments.
|
|
|
4ac4fd |
* rtl.h (tablejump_p): Likewise.
|
|
|
4ac4fd |
|
|
|
4ac4fd |
--- gcc/rtl.h.jj 2003-06-11 14:58:17.000000000 +0200
|
|
|
4ac4fd |
+++ gcc/rtl.h 2005-01-03 17:32:46.113937897 +0100
|
|
|
4ac4fd |
@@ -1793,7 +1793,7 @@ extern rtx pc_set PARAMS ((rtx));
|
|
|
4ac4fd |
extern rtx condjump_label PARAMS ((rtx));
|
|
|
4ac4fd |
extern int simplejump_p PARAMS ((rtx));
|
|
|
4ac4fd |
extern int returnjump_p PARAMS ((rtx));
|
|
|
4ac4fd |
-extern int tablejump_p PARAMS ((rtx));
|
|
|
4ac4fd |
+extern int tablejump_p PARAMS ((rtx, rtx *, rtx *));
|
|
|
4ac4fd |
extern int onlyjump_p PARAMS ((rtx));
|
|
|
4ac4fd |
extern int only_sets_cc0_p PARAMS ((rtx));
|
|
|
4ac4fd |
extern int sets_cc0_p PARAMS ((rtx));
|
|
|
4ac4fd |
--- gcc/cfgrtl.c.jj 2003-04-08 15:50:58.000000000 +0200
|
|
|
4ac4fd |
+++ gcc/cfgrtl.c 2005-01-03 17:37:59.150837447 +0100
|
|
|
4ac4fd |
@@ -674,7 +674,7 @@ try_redirect_by_replacing_jump (e, targe
|
|
|
4ac4fd |
if (tmp || !onlyjump_p (insn))
|
|
|
4ac4fd |
return false;
|
|
|
4ac4fd |
|
|
|
4ac4fd |
- if ((!optimize || flow2_completed) && tablejump_p (insn))
|
|
|
4ac4fd |
+ if ((!optimize || flow2_completed) && tablejump_p (insn, NULL, NULL))
|
|
|
4ac4fd |
return false;
|
|
|
4ac4fd |
|
|
|
4ac4fd |
/* Avoid removing branch with side effects. */
|
|
|
4ac4fd |
--- gcc/cfgcleanup.c.jj 2003-08-02 01:18:22.000000000 +0200
|
|
|
4ac4fd |
+++ gcc/cfgcleanup.c 2005-01-03 17:32:10.010407336 +0100
|
|
|
4ac4fd |
@@ -691,25 +691,20 @@ merge_blocks_move_successor_nojumps (a,
|
|
|
4ac4fd |
basic_block a, b;
|
|
|
4ac4fd |
{
|
|
|
4ac4fd |
rtx barrier, real_b_end;
|
|
|
4ac4fd |
+ rtx label, table;
|
|
|
4ac4fd |
|
|
|
4ac4fd |
real_b_end = b->end;
|
|
|
4ac4fd |
- barrier = NEXT_INSN (b->end);
|
|
|
4ac4fd |
|
|
|
4ac4fd |
- /* Recognize a jump table following block B. */
|
|
|
4ac4fd |
- if (barrier
|
|
|
4ac4fd |
- && GET_CODE (barrier) == CODE_LABEL
|
|
|
4ac4fd |
- && NEXT_INSN (barrier)
|
|
|
4ac4fd |
- && GET_CODE (NEXT_INSN (barrier)) == JUMP_INSN
|
|
|
4ac4fd |
- && (GET_CODE (PATTERN (NEXT_INSN (barrier))) == ADDR_VEC
|
|
|
4ac4fd |
- || GET_CODE (PATTERN (NEXT_INSN (barrier))) == ADDR_DIFF_VEC))
|
|
|
4ac4fd |
+ /* If there is a jump table following block B temporarily add the jump table
|
|
|
4ac4fd |
+ to block B so that it will also be moved to the correct location. */
|
|
|
4ac4fd |
+ if (tablejump_p (b->end, &label, &table)
|
|
|
4ac4fd |
+ && prev_active_insn (label) == b->end)
|
|
|
4ac4fd |
{
|
|
|
4ac4fd |
- /* Temporarily add the table jump insn to b, so that it will also
|
|
|
4ac4fd |
- be moved to the correct location. */
|
|
|
4ac4fd |
- b->end = NEXT_INSN (barrier);
|
|
|
4ac4fd |
- barrier = NEXT_INSN (b->end);
|
|
|
4ac4fd |
+ b->end = table;
|
|
|
4ac4fd |
}
|
|
|
4ac4fd |
|
|
|
4ac4fd |
/* There had better have been a barrier there. Delete it. */
|
|
|
4ac4fd |
+ barrier = NEXT_INSN (b->end);
|
|
|
4ac4fd |
if (barrier && GET_CODE (barrier) == BARRIER)
|
|
|
4ac4fd |
delete_insn (barrier);
|
|
|
4ac4fd |
|
|
|
4ac4fd |
--- gcc/jump.c.jj 2003-08-01 22:38:45.000000000 +0200
|
|
|
4ac4fd |
+++ gcc/jump.c 2005-01-03 17:36:59.744484787 +0100
|
|
|
4ac4fd |
@@ -1099,20 +1099,32 @@ simplejump_p (insn)
|
|
|
4ac4fd |
&& GET_CODE (SET_DEST (PATTERN (insn))) == PC
|
|
|
4ac4fd |
&& GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
|
|
|
4ac4fd |
}
|
|
|
4ac4fd |
-/* Return 1 if INSN is an tablejump. */
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+/* If INSN is a tablejump return 1 and store the label (before jump table) to
|
|
|
4ac4fd |
+ *LABELP and the jump table to *TABLEP. LABELP and TABLEP may be NULL. */
|
|
|
4ac4fd |
|
|
|
4ac4fd |
int
|
|
|
4ac4fd |
-tablejump_p (insn)
|
|
|
4ac4fd |
+tablejump_p (insn, labelp, tablep)
|
|
|
4ac4fd |
rtx insn;
|
|
|
4ac4fd |
+ rtx *labelp;
|
|
|
4ac4fd |
+ rtx *tablep;
|
|
|
4ac4fd |
{
|
|
|
4ac4fd |
- rtx table;
|
|
|
4ac4fd |
- return (GET_CODE (insn) == JUMP_INSN
|
|
|
4ac4fd |
- && JUMP_LABEL (insn)
|
|
|
4ac4fd |
- && NEXT_INSN (JUMP_LABEL (insn))
|
|
|
4ac4fd |
- && (table = next_active_insn (JUMP_LABEL (insn)))
|
|
|
4ac4fd |
- && GET_CODE (table) == JUMP_INSN
|
|
|
4ac4fd |
- && (GET_CODE (PATTERN (table)) == ADDR_VEC
|
|
|
4ac4fd |
- || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC));
|
|
|
4ac4fd |
+ rtx label, table;
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ if (GET_CODE (insn) == JUMP_INSN
|
|
|
4ac4fd |
+ && (label = JUMP_LABEL (insn)) != NULL_RTX
|
|
|
4ac4fd |
+ && (table = next_active_insn (label)) != NULL_RTX
|
|
|
4ac4fd |
+ && GET_CODE (table) == JUMP_INSN
|
|
|
4ac4fd |
+ && (GET_CODE (PATTERN (table)) == ADDR_VEC
|
|
|
4ac4fd |
+ || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
|
|
|
4ac4fd |
+ {
|
|
|
4ac4fd |
+ if (labelp)
|
|
|
4ac4fd |
+ *labelp = label;
|
|
|
4ac4fd |
+ if (tablep)
|
|
|
4ac4fd |
+ *tablep = table;
|
|
|
4ac4fd |
+ return 1;
|
|
|
4ac4fd |
+ }
|
|
|
4ac4fd |
+ return 0;
|
|
|
4ac4fd |
}
|
|
|
4ac4fd |
|
|
|
4ac4fd |
/* Return nonzero if INSN is a (possibly) conditional jump
|
|
|
4ac4fd |
--- gcc/ifcvt.c.jj 2003-03-25 17:42:24.000000000 +0100
|
|
|
4ac4fd |
+++ gcc/ifcvt.c 2005-01-03 17:32:10.012406978 +0100
|
|
|
4ac4fd |
@@ -2046,7 +2046,7 @@ find_if_block (test_bb, then_edge, else_
|
|
|
4ac4fd |
if (then_succ != NULL_EDGE
|
|
|
4ac4fd |
&& (then_succ->succ_next != NULL_EDGE
|
|
|
4ac4fd |
|| (then_succ->flags & EDGE_COMPLEX)
|
|
|
4ac4fd |
- || (flow2_completed && tablejump_p (then_bb->end))))
|
|
|
4ac4fd |
+ || (flow2_completed && tablejump_p (then_bb->end, NULL, NULL))))
|
|
|
4ac4fd |
return FALSE;
|
|
|
4ac4fd |
|
|
|
4ac4fd |
/* If the THEN block has no successors, conditional execution can still
|
|
|
4ac4fd |
@@ -2094,7 +2094,7 @@ find_if_block (test_bb, then_edge, else_
|
|
|
4ac4fd |
&& else_bb->pred->pred_next == NULL_EDGE
|
|
|
4ac4fd |
&& else_succ->succ_next == NULL_EDGE
|
|
|
4ac4fd |
&& ! (else_succ->flags & EDGE_COMPLEX)
|
|
|
4ac4fd |
- && ! (flow2_completed && tablejump_p (else_bb->end)))
|
|
|
4ac4fd |
+ && ! (flow2_completed && tablejump_p (else_bb->end, NULL, NULL)))
|
|
|
4ac4fd |
join_bb = else_succ->dest;
|
|
|
4ac4fd |
|
|
|
4ac4fd |
/* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */
|
|
|
4ac4fd |
--- gcc/testsuite/gcc.c-torture/compile/20050103-1.c.jj 2004-12-09 13:34:01.422415552 +0100
|
|
|
4ac4fd |
+++ gcc/testsuite/gcc.c-torture/compile/20050103-1.c 2005-01-03 15:21:18.146431991 +0100
|
|
|
4ac4fd |
@@ -0,0 +1,83 @@
|
|
|
4ac4fd |
+extern void abort (void);
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+struct S
|
|
|
4ac4fd |
+{
|
|
|
4ac4fd |
+ char *s1;
|
|
|
4ac4fd |
+ int s2;
|
|
|
4ac4fd |
+};
|
|
|
4ac4fd |
+struct T
|
|
|
4ac4fd |
+{
|
|
|
4ac4fd |
+ int t1;
|
|
|
4ac4fd |
+ struct S *t2;
|
|
|
4ac4fd |
+} *s1;
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+extern int bar (const struct T *, unsigned int, unsigned int,
|
|
|
4ac4fd |
+ const struct T *, unsigned int, unsigned int);
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+extern inline void *
|
|
|
4ac4fd |
+baz (void *x, const void *y, unsigned int z)
|
|
|
4ac4fd |
+{
|
|
|
4ac4fd |
+ unsigned char *s1 = x;
|
|
|
4ac4fd |
+ const unsigned char *s2 = y;
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ if (z > 4 || __builtin_constant_p (z))
|
|
|
4ac4fd |
+ __builtin_memcpy (x, y, z);
|
|
|
4ac4fd |
+ else
|
|
|
4ac4fd |
+ switch (z)
|
|
|
4ac4fd |
+ {
|
|
|
4ac4fd |
+ case 4:
|
|
|
4ac4fd |
+ s1[3] = s2[3];
|
|
|
4ac4fd |
+ case 3:
|
|
|
4ac4fd |
+ s1[2] = s2[2];
|
|
|
4ac4fd |
+ case 2:
|
|
|
4ac4fd |
+ s1[1] = s2[1];
|
|
|
4ac4fd |
+ case 1:
|
|
|
4ac4fd |
+ s1[0] = s2[0];
|
|
|
4ac4fd |
+ case 0:
|
|
|
4ac4fd |
+ break;
|
|
|
4ac4fd |
+ }
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ return x;
|
|
|
4ac4fd |
+}
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+extern inline int
|
|
|
4ac4fd |
+foo (struct T *b, unsigned int x, const void *y, unsigned int z)
|
|
|
4ac4fd |
+{
|
|
|
4ac4fd |
+ if (!b || !z)
|
|
|
4ac4fd |
+ return 0;
|
|
|
4ac4fd |
+ if (x == b->t1)
|
|
|
4ac4fd |
+ {
|
|
|
4ac4fd |
+ struct S *r = b->t2;
|
|
|
4ac4fd |
+ baz (r->s1 + r->s2, y, z);
|
|
|
4ac4fd |
+ return 1;
|
|
|
4ac4fd |
+ }
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ return 0;
|
|
|
4ac4fd |
+}
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+int
|
|
|
4ac4fd |
+test (struct T *a, struct T *b, struct T *c, struct T *d)
|
|
|
4ac4fd |
+{
|
|
|
4ac4fd |
+ if (!a)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+ if (!b)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ if (bar (a, 1, a->t1, b, 1, b->t1) > 0)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+ if (bar (a, 41, a->t1 - 40, b, 1, b->t1) > 0)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ if (!c)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+ if (!d)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ if (bar (c, 1, c->t1, d, 1, d->t1) < 0)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+ if (bar (c, 41, c->t1 - 40, d, 1, d->t1) < 0)
|
|
|
4ac4fd |
+ abort ();
|
|
|
4ac4fd |
+
|
|
|
4ac4fd |
+ foo (s1, 0, "abcd", 4);
|
|
|
4ac4fd |
+ return 0;
|
|
|
4ac4fd |
+}
|