This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Crossjumping of tablejumps
Hi,
this patch fixes breakage on s390 because of the labels in constant
pool introduced by my patch for crossjumping of tablejumps.
I apologize for the breakage.
This patch replaces references to one constant pool label (LCx) by
references to the second constant pool label.
Bootstrapped/regtested s390 and x86-64.
It fixes the testcase (from fortran compiler) sent by Ulrich Weigand,
gcc.dg/20030213-1.c and many fortran testcases (because the
miscompilation of part of fortran compiler is fixed).
OK for mainline?
Josef
2003-03-13 Josef Zlomek <zlomekj at suse dot cz>
* cfgcleanup.c (try_crossjump_to_edge): If the labels are in constant
pool replace one constant pool label (LCx) by another.
* rtlanal.c (replace_label): Replace label also in INSN_LIST (in
REG_LABEL note).
(subrtx_p): Renamed to rtx_referenced_p.
(subrtx_p_1): Renamed to rtx_referenced_p_1, compare the interior of
LABEL_REF with CODE_LABEL, traverse constants from pool.
* rtl.h (subrtx_p): Renamed to rtx_referenced_p.
(get_constant_pool_symbol_ref): New extern function.
* varasm.c (get_constant_pool_symbol_ref): New function.
Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v
retrieving revision 1.77
diff -c -3 -p -r1.77 cfgcleanup.c
*** cfgcleanup.c 10 Mar 2003 18:32:17 -0000 1.77
--- cfgcleanup.c 13 Mar 2003 12:39:26 -0000
*************** outgoing_edges_match (mode, bb1, bb2)
*** 1271,1280 ****
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;
--- 1271,1280 ----
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 referenced 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 && !rtx_referenced_p (label2, bb1->end))
{
/* Set IDENTICAL to true when the tables are identical. */
bool identical = false;
*************** try_crossjump_to_edge (mode, e1, e2)
*** 1461,1466 ****
--- 1461,1467 ----
{
rtx_pair rr;
rtx insn;
+ rtx sym1, sym2;
/* Replace references to LABEL1 with LABEL2. */
rr.r1 = label1;
*************** try_crossjump_to_edge (mode, e1, e2)
*** 1473,1478 ****
--- 1474,1491 ----
if (insn != src1->end)
for_each_rtx (&insn, replace_label, &rr);
}
+
+ /* If the labels are in constant pool
+ replace the SYMBOL_REF SYM1 by SYM2. */
+ sym1 = get_constant_pool_symbol_ref (label1);
+ sym2 = get_constant_pool_symbol_ref (label2);
+ if (sym1 && sym2)
+ {
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ replace_rtx (insn, sym1, copy_rtx (sym2));
+ }
+ else if (sym1 || sym2)
+ abort ();
}
}
#endif
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.387
diff -c -3 -p -r1.387 rtl.h
*** rtl.h 10 Mar 2003 17:23:44 -0000 1.387
--- rtl.h 13 Mar 2003 12:39:26 -0000
*************** extern rtx mem_for_const_double PARAMS
*** 1445,1450 ****
--- 1445,1451 ----
extern rtx force_const_mem PARAMS ((enum machine_mode, rtx));
/* In varasm.c */
+ extern rtx get_constant_pool_symbol_ref PARAMS ((rtx));
extern rtx get_pool_constant PARAMS ((rtx));
extern rtx get_pool_constant_mark PARAMS ((rtx, bool *));
extern enum machine_mode get_pool_mode PARAMS ((rtx));
*************** extern rtx replace_rtx PARAMS ((rtx, r
*** 1662,1668 ****
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 *));
--- 1663,1669 ----
extern rtx replace_regs PARAMS ((rtx, rtx *, unsigned int,
int));
extern int replace_label PARAMS ((rtx *, void *));
! extern int rtx_referenced_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 *));
Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.148
diff -c -3 -p -r1.148 rtlanal.c
*** rtlanal.c 10 Mar 2003 17:23:44 -0000 1.148
--- rtlanal.c 13 Mar 2003 12:39:26 -0000
*************** Software Foundation, 59 Temple Place - S
*** 38,44 ****
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));
--- 38,44 ----
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 rtx_referenced_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));
*************** replace_label (x, data)
*** 2813,2819 ****
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)
--- 2813,2820 ----
if (GET_CODE (l) == JUMP_INSN && JUMP_LABEL (l) == old_label)
JUMP_LABEL (l) = new_label;
! if (GET_CODE (l) != LABEL_REF
! && GET_CODE (l) != INSN_LIST)
return 0;
if (XEXP (l, 0) != old_label)
*************** replace_label (x, data)
*** 2826,2851 ****
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
--- 2827,2867 ----
return 0;
}
! /* When *BODY is equal to X or X is directly referenced by *BODY
! return nonzero, thus FOR_EACH_RTX stops traversing and returns nonzero
! too, otherwise FOR_EACH_RTX continues traversing *BODY. */
static int
! rtx_referenced_p_1 (body, x)
! rtx *body;
! void *x;
{
! rtx y = (rtx) x;
!
! if (*body == NULL_RTX)
! return y == NULL_RTX;
!
! /* Return true if a label_ref *BODY refers to label Y. */
! if (GET_CODE (*body) == LABEL_REF && GET_CODE (y) == CODE_LABEL)
! return XEXP (*body, 0) == y;
!
! /* If *BODY is a reference to pool constant traverse the constant. */
! if (GET_CODE (*body) == SYMBOL_REF
! && CONSTANT_POOL_ADDRESS_P (*body))
! return rtx_referenced_p (y, get_pool_constant (*body));
!
! /* By default, compare the RTL expressions. */
! return rtx_equal_p (*body, y);
}
! /* Return true if X is referenced in BODY. */
int
! rtx_referenced_p (x, body)
rtx x;
+ rtx body;
{
! return for_each_rtx (&body, rtx_referenced_p_1, x);
}
/* If INSN is a jump to jumptable insn rturn true and store the label (which
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.333
diff -c -3 -p -r1.333 varasm.c
*** varasm.c 9 Mar 2003 20:41:30 -0000 1.333
--- varasm.c 13 Mar 2003 12:39:27 -0000
*************** find_pool_constant (f, addr)
*** 3265,3270 ****
--- 3265,3285 ----
abort ();
}
+ /* Given a CONSTANT, return the corresponding constant pool reference. */
+
+ rtx
+ get_constant_pool_symbol_ref (constant)
+ rtx constant;
+ {
+ struct pool_constant *pool;
+
+ for (pool = cfun->varasm->x_first_pool; pool; pool = pool->next)
+ if (rtx_referenced_p (constant, pool->constant))
+ return XEXP (pool->desc->rtl, 0);
+
+ return NULL;
+ }
+
/* Given a constant pool SYMBOL_REF, return the corresponding constant. */
rtx