};
/* A table of cse_reg_info indexed by register numbers. */
-struct cse_reg_info *cse_reg_info_table;
+static struct cse_reg_info *cse_reg_info_table;
/* The size of the above table. */
static unsigned int cse_reg_info_table_size;
if (REG_P (classp->exp)
&& GET_MODE (classp->exp) == GET_MODE (x))
{
- make_regs_eqv (regno, REGNO (classp->exp));
+ unsigned c_regno = REGNO (classp->exp);
+
+ gcc_assert (REGNO_QTY_VALID_P (c_regno));
+
+ /* Suppose that 5 is hard reg and 100 and 101 are
+ pseudos. Consider
+
+ (set (reg:si 100) (reg:si 5))
+ (set (reg:si 5) (reg:si 100))
+ (set (reg:di 101) (reg:di 5))
+
+ We would now set REG_QTY (101) = REG_QTY (5), but the
+ entry for 5 is in SImode. When we use this later in
+ copy propagation, we get the register in wrong mode. */
+ if (qty_table[REG_QTY (c_regno)].mode != GET_MODE (x))
+ continue;
+
+ make_regs_eqv (regno, c_regno);
return 1;
}
be valid and produce better code. */
if (!REG_P (addr))
{
- rtx folded = fold_rtx (addr, NULL_RTX);
+ rtx folded = canon_for_address (fold_rtx (addr, NULL_RTX));
+
if (folded != addr)
{
int addr_folded_cost = address_cost (folded, mode);
int new_cost;
/* Get the canonical version of the address so we can accept
- more. */
+ more. */
new = canon_for_address (new);
new_cost = address_cost (new, mode);
if (offset >= 0
&& (offset / GET_MODE_SIZE (GET_MODE (table))
< XVECLEN (table, 0)))
- return XVECEXP (table, 0,
- offset / GET_MODE_SIZE (GET_MODE (table)));
+ {
+ rtx label = XVECEXP
+ (table, 0, offset / GET_MODE_SIZE (GET_MODE (table)));
+ rtx set;
+
+ /* If we have an insn that loads the label from the
+ jumptable into a reg, we don't want to set the reg
+ to the label, because this may cause a reference to
+ the label to remain after the label is removed in
+ some very obscure cases (PR middle-end/18628). */
+ if (!insn)
+ return label;
+
+ set = single_set (insn);
+
+ if (! set || SET_SRC (set) != x)
+ return x;
+
+ /* If it's a jump, it's safe to reference the label. */
+ if (SET_DEST (set) == pc_rtx)
+ return label;
+
+ return x;
+ }
}
if (table_insn && JUMP_P (table_insn)
&& GET_CODE (PATTERN (table_insn)) == ADDR_DIFF_VEC)
/* It's not safe to substitute the operand of a conversion
operator with a constant, as the conversion's identity
- depends upon the mode of it's operand. This optimization
+ depends upon the mode of its operand. This optimization
is handled by the call to simplify_unary_operation. */
if (GET_RTX_CLASS (code) == RTX_UNARY
&& GET_MODE (replacements[j]) != mode_arg0
return 0;
}
\f
-/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point
- number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
- least-significant part of X.
- MODE specifies how big a part of X to return.
-
- If the requested operation cannot be done, 0 is returned.
-
- This is similar to gen_lowpart_general in emit-rtl.c. */
-
-rtx
-gen_lowpart_if_possible (enum machine_mode mode, rtx x)
-{
- rtx result = gen_lowpart_common (mode, x);
-
- if (result)
- return result;
- else if (MEM_P (x))
- {
- /* This is the only other case we handle. */
- int offset = 0;
- rtx new;
-
- if (WORDS_BIG_ENDIAN)
- offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
- if (BYTES_BIG_ENDIAN)
- /* Adjust the address so that the address-after-the-data is
- unchanged. */
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
-
- new = adjust_address_nv (x, mode, offset);
- if (! memory_address_p (mode, XEXP (new, 0)))
- return 0;
-
- return new;
- }
- else
- return 0;
-}
-\f
/* Given INSN, a jump insn, PATH_TAKEN indicates if we are following the "taken"
branch. It will be zero if not.