+Sat Feb 1 00:28:30 CET 2003 Jan Hubicka <jh@suse.cz>
+
+ * loop.c (emit_prefetch_instructions): Do conversion at right place in
+ RTL chain.
+
+ * combine.c (simplify_set): Reverse order of ragumetns to
+ REG_CANNOT_CHANGE_MODE_P
+ * df.c (df_def_record_1): Likewise.
+ * recog.c (register_operand): Likewise.
+ * simplify-rtx.c (simplify_subreg): Likewise.
+ * hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): Update use of
+ CANNOT_CHANGE_MODE_CLASS.
+ * regclass.c (cannot_change_mode_set_regs, invalid_mode_change_p):
+ Likewise.
+ * reload.c (push_reload): Likewise.
+ * alpha.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * ia64.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * mips.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * mips-protos.h (mips_cannot_change_mode_class): Update prototype.
+ * mips.c (mips_cannot_change_mode_class): Update.
+ * pa64-regs.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * rs6000.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * s390.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * sh.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * sh-protos.h (sh_cannot_change_mode_class): Update prototype.
+ * sh.c (sh_cannot_change_mode_class): Update.
+ * i386.h (CANNOT_CHANGE_MODE_CLASS): New.
+ * tm.texi (CANNOT_CHANGE_MODE_CLASS): Update documentation.
+
2003-01-31 Geoffrey Keating <geoffk@apple.com>
* config/darwin.h (LINK_COMMAND_SPEC): Update for Nathan's recent
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
- GET_MODE (src),
- GET_MODE (SUBREG_REG (src))))
+ GET_MODE (SUBREG_REG (src)),
+ GET_MODE (src)))
#endif
&& (GET_CODE (dest) == REG
|| (GET_CODE (dest) == SUBREG
/* Return the class of registers that cannot change mode from FROM to TO. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, CLASS) : 0)
/* Define the cost of moving between registers of various classes. Moving
between FLOAT_REGS and anything else except float regs is expensive.
rtx compare_op;
rtx val = const0_rtx;
bool fpcmp = false;
- rtx pat, clob;
enum machine_mode mode = GET_MODE (operands[0]);
if (operands[3] != const1_rtx
|| ((CLASS) == SIREG) \
|| ((CLASS) == DIREG))
+/* Return a class of registers that cannot change FROM mode to TO mode.
+
+ x87 registers can't do subreg as all values are reformated to extended
+ precision. XMM registers does not support with nonzero offsets equal
+ to 4, 8 and 12 otherwise valid for integer registers. Since we can't
+ determine these, prohibit all nonparadoxical subregs changing size. */
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (TO) < GET_MODE_SIZE (FROM) \
+ ? reg_classes_intersect_p (FLOAT_SSE_REGS, (CLASS)) \
+ || MAYBE_MMX_CLASS_P (CLASS) \
+ : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
+
/* A C statement that adds to CLOBBERS any hard regs the port wishes
to automatically clobber for all asms.
/* In FP regs, we can't change FP values to integer values and vice
versa, but we can change e.g. DImode to SImode. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
- (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) ? FR_REGS : NO_REGS)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) \
+ ? reg_classes_intersect_p (CLASS, FR_REGS) : 0)
/* A C expression that defines the machine-dependent operand constraint
letters (`I', `J', `K', .. 'P') that specify particular ranges of
extern enum reg_class mips_secondary_reload_class PARAMS ((enum reg_class,
enum machine_mode,
rtx, int));
-extern enum reg_class mips_cannot_change_mode_class
- PARAMS ((enum machine_mode, enum machine_mode));
+extern bool mips_cannot_change_mode_class
+ PARAMS ((enum machine_mode, enum machine_mode,
+ enum reg_class));
extern int mips_class_max_nregs PARAMS ((enum reg_class,
enum machine_mode));
extern int mips_register_move_cost PARAMS ((enum machine_mode,
We can't allow 64-bit float registers to change from a 32-bit
mode to a 64-bit mode. */
-enum reg_class
-mips_cannot_change_mode_class (from, to)
+bool
+mips_cannot_change_mode_class (from, to, class)
enum machine_mode from, to;
+ enum reg_class class;
{
if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
{
if (TARGET_BIG_ENDIAN)
- return FP_REGS;
+ return reg_classes_intersect_p (FP_REGS, class);
if (TARGET_FLOAT64)
- return HI_AND_FP_REGS;
- return HI_REG;
+ return reg_classes_intersect_p (HI_AND_FP_REGS, class);
+ return reg_classes_intersect_p (HI_REG, class);
}
- return NO_REGS;
+ return false;
}
/* This function returns the register class required for a secondary
#define CLASS_MAX_NREGS(CLASS, MODE) mips_class_max_nregs (CLASS, MODE)
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
- mips_cannot_change_mode_class (FROM, TO)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ mips_cannot_change_mode_class (FROM, TO, CLASS)
\f
/* Stack layout; function entry, exit and calling. */
we inhibit changes from SImode unless they are to a mode that is
identical in size. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
- ? FP_REGS : NO_REGS)
+ ? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
/* Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
/* Return a class of registers that cannot change FROM mode to TO mode. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS \
- : (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1 ? GENERAL_REGS \
- : NO_REGS)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
+ : (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1 \
+ ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
+ : 0)
/* Stack layout; function entry, exit and calling. */
/* If a 4-byte value is loaded into a FPR, it is placed into the
*upper* half of the register, not the lower. Therefore, we
cannot use SUBREGs to switch between modes in FP registers. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FP_REGS : NO_REGS)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FP_REGS, CLASS) : 0)
/* Register classes. */
extern int sh_hard_regno_rename_ok PARAMS ((unsigned int, unsigned int));
extern int sh_cfun_interrupt_handler_p PARAMS ((void));
extern void sh_initialize_trampoline PARAMS ((rtx, rtx, rtx));
-extern enum reg_class sh_cannot_change_mode_class
- PARAMS ((enum machine_mode, enum machine_mode));
+extern bool sh_cannot_change_mode_class
+ PARAMS ((enum machine_mode, enum machine_mode, enum reg_class));
extern void sh_mark_label PARAMS ((rtx, int));
extern int sh_register_move_cost
PARAMS ((enum machine_mode mode, enum reg_class, enum reg_class));
/* Return the class of registers for which a mode change from FROM to TO
is invalid. */
-enum reg_class
-sh_cannot_change_mode_class (from, to)
+bool
+sh_cannot_change_mode_class (from, to, class)
enum machine_mode from, to;
+ enum reg_class class;
{
if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
{
if (TARGET_LITTLE_ENDIAN)
{
if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8)
- return DF_REGS;
+ return reg_classes_intersect_p (DF_REGS, class);
}
else
{
if (GET_MODE_SIZE (from) < 8)
- return DF_HI_REGS;
+ return reg_classes_intersect_p (DF_HI_REGS, class);
}
}
- return NO_REGS;
+ return 0;
}
/* ??? We need to renumber the internal numbers for the frnn registers
when in little endian in order to allow mode size changes. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
- sh_cannot_change_mode_class (FROM, TO)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ sh_cannot_change_mode_class (FROM, TO, CLASS)
\f
/* Stack layout; function entry, exit and calling. */
#ifdef CLASS_CANNOT_CHANGE_MODE
if (GET_CODE (dst) == SUBREG
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
- GET_MODE (SUBREG_REG (dst))))
+ && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
+ GET_MODE (dst)))
flags |= DF_REF_MODE_CHANGE;
#endif
}
#ifdef CLASS_CANNOT_CHANGE_MODE
if (GET_CODE (dst) == SUBREG
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
- GET_MODE (SUBREG_REG (dst))))
+ && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
+ GET_MODE (dst)))
flags |= DF_REF_MODE_CHANGE;
#endif
loc = &XEXP (dst, 0);
This macro helps control the handling of multiple-word values
in the reload pass.
-@item CANNOT_CHANGE_MODE_CLASS(@var{from}, @var{to})
-If defined, a C expression that returns a register class for which
-a change from mode @var{from} to mode @var{to} is invalid, otherwise the
-macro returns @code{NO_REGS}.
+@item CANNOT_CHANGE_MODE_CLASS(@var{from}, @var{to}, @var{class})
+If defined, a C expression that returns nonzero for a @var{class} for which
+a change from mode @var{from} to mode @var{to} is invalid.
For the example, loading 32-bit integer or floating-point objects into
floating-point registers on the Alpha extends them to 64 bits.
as below:
@example
-#define CANNOT_CHANGE_MODE_CLASS \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
@end example
@end table
/* Given a hard REGN a FROM mode and a TO mode, return nonzero if
REGN cannot change modes between the specified modes. */
#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO) \
- (TEST_HARD_REG_BIT \
- (reg_class_contents[(int) CANNOT_CHANGE_MODE_CLASS (FROM, TO)], \
- REGN))
+ CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN))
#endif /* ! GCC_HARD_REG_SET_H */
non-constant INIT_VAL to have the same mode as REG, which
in this case we know to be Pmode. */
if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val))
- init_val = convert_to_mode (Pmode, init_val, 0);
+ {
+ rtx seq;
+
+ start_sequence ();
+ init_val = convert_to_mode (Pmode, init_val, 0);
+ seq = get_insns ();
+ end_sequence ();
+ loop_insn_emit_before (loop, 0, loop_start, seq);
+ }
loop_iv_add_mult_emit_before (loop, init_val,
info[i].giv->mult_val,
add_val, reg, 0, loop_start);
#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (sub) == REG
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
- && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), mode, GET_MODE (sub))
+ && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
return 0;
unsigned int regno;
{
enum machine_mode to;
- enum reg_class class;
for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
{
- class = CANNOT_CHANGE_MODE_CLASS (from, to);
- if (class != NO_REGS)
- IOR_HARD_REG_SET (*used, reg_class_contents [(int) class]);
+ int i;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (! TEST_HARD_REG_BIT (*used, i)
+ && REG_CANNOT_CHANGE_MODE_P (from, to, i))
+ SET_HARD_REG_BIT (*used, i);
}
}
for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
- && reg_classes_intersect_p
- (class, CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode)))
+ && CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class))
return 1;
return 0;
}
if (in != 0 && GET_CODE (in) == SUBREG
&& (subreg_lowpart_p (in) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
- && !reg_classes_intersect_p
- (class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)),
- inmode))
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class)
#endif
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
- && !reg_classes_intersect_p
- (class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)),
- outmode))
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class)
#endif
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
|| ! rtx_equal_function_value_matters)
&& REGNO (op) < FIRST_PSEUDO_REGISTER
#ifdef CANNOT_CHANGE_MODE_CLASS
- && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), outermode, innermode)
+ && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode)
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
#endif