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
+ /* 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 && !subrtx_p (label2, bb1->end))
+ if (label1 != label2 && !rtx_referenced_p (label2, bb1->end))
{
/* Set IDENTICAL to true when the tables are identical. */
bool identical = false;
if (identical)
{
- rtx_pair rr;
+ replace_label_data 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;
+ rr.update_label_nuses = false;
for_each_rtx (&bb1->end, replace_label, &rr);
match = insns_match_p (mode, bb1->end, bb2->end);
&& tablejump_p (src2->end, &label2, &table2)
&& label1 != label2)
{
- rtx_pair rr;
+ replace_label_data rr;
rtx insn;
/* Replace references to LABEL1 with LABEL2. */
rr.r1 = label1;
rr.r2 = label2;
+ rr.update_label_nuses = true;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
/* Do not replace the label in SRC1->END because when deleting
#define single_set_1(I) single_set_2 (I, PATTERN (I))
/* Structure used for passing data to REPLACE_LABEL. */
-typedef struct rtx_pair
+typedef struct replace_label_data
{
rtx r1;
rtx r2;
-} rtx_pair;
+ bool update_label_nuses;
+} replace_label_data;
extern int rtx_addr_can_trap_p PARAMS ((rtx));
extern bool nonzero_address_p PARAMS ((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 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 *));
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 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 occurrences of the old label in *X with the new one.
- DATA is an rtx_pair containing the old and new labels, respectively. */
+ DATA is a REPLACE_LABEL_DATA containing the old and new labels. */
int
replace_label (x, data)
void *data;
{
rtx l = *x;
- rtx old_label = ((rtx_pair *) data)->r1;
- rtx new_label = ((rtx_pair *) data)->r2;
+ rtx tmp;
+ rtx old_label = ((replace_label_data *) data)->r1;
+ rtx new_label = ((replace_label_data *) data)->r2;
+ bool update_label_nuses = ((replace_label_data *) data)->update_label_nuses;
if (l == NULL_RTX)
return 0;
+ if (GET_CODE (l) == MEM
+ && (tmp = XEXP (l, 0)) != NULL_RTX
+ && GET_CODE (tmp) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (tmp))
+ {
+ rtx c = get_pool_constant (tmp);
+ if (rtx_referenced_p (old_label, c))
+ {
+ rtx new_c, new_l;
+ replace_label_data *d = (replace_label_data *) data;
+
+ /* Create a copy of constant C; replace the label inside
+ but do not update LABEL_NUSES because uses in constant pool
+ are not counted. */
+ new_c = copy_rtx (c);
+ d->update_label_nuses = false;
+ for_each_rtx (&new_c, replace_label, data);
+ d->update_label_nuses = update_label_nuses;
+
+ /* Add the new constant NEW_C to constant pool and replace
+ the old reference to constant by new reference. */
+ new_l = force_const_mem (get_pool_mode (tmp), new_c);
+ *x = replace_rtx (l, l, new_l);
+ }
+ 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);
+ if ((GET_CODE (l) == LABEL_REF
+ || GET_CODE (l) == INSN_LIST)
+ && XEXP (l, 0) == old_label)
+ {
+ XEXP (l, 0) = new_label;
+ if (update_label_nuses)
+ {
+ ++LABEL_NUSES (new_label);
+ --LABEL_NUSES (old_label);
+ }
+ return 0;
+ }
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. */
+/* 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
-subrtx_p_1 (px, subx)
- rtx *px;
- void *subx;
+rtx_referenced_p_1 (body, x)
+ rtx *body;
+ void *x;
{
- return rtx_equal_p (*px, (rtx) subx);
+ 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 SUBX is equal to some subexpression of X. */
+/* Return true if X is referenced in BODY. */
int
-subrtx_p (subx, x)
- rtx subx;
+rtx_referenced_p (x, body)
rtx x;
+ rtx body;
{
- return for_each_rtx (&x, subrtx_p_1, subx);
+ 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