@@ -5084,6 +5084,7 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy)
&& REGNO (to) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (to),
GET_MODE (to),
+ SUBREG_BYTE (x),
GET_MODE (x)))
return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
#endif
@@ -6450,6 +6451,7 @@ simplify_set (rtx x)
&& ! (REG_P (dest) && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
GET_MODE (SUBREG_REG (src)),
+ SUBREG_BYTE (src),
GET_MODE (src)))
#endif
&& (REG_P (dest)
@@ -35057,13 +35057,6 @@ ix86_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
the vec_dupv4hi pattern. */
if (GET_MODE_SIZE (from) < 4)
return true;
-
- /* Vector registers do not support subreg with nonzero offsets, which
- are otherwise valid for integer registers. Since we can't see
- whether we have a nonzero offset from here, prohibit all
- nonparadoxical subregs changing size. */
- if (GET_MODE_SIZE (to) < GET_MODE_SIZE (from))
- return true;
}
return false;
@@ -1522,10 +1522,15 @@ enum reg_class
? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \
: MODE)
-/* Return a class of registers that cannot change FROM mode to TO mode. */
+/* Return true if the registers in CLASS cannot represent the change
+ from mode FROM to mode TO. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
ix86_cannot_change_mode_class (FROM, TO, CLASS)
+
+/* Return true if the register CLASS may be a vector class. */
+#define MAYBE_VECTOR_CLASS_P(CLASS) \
+ (MAYBE_SSE_CLASS_P (CLASS) || MAYBE_MMX_CLASS_P (CLASS))
/* Stack layout; function entry, exit and calling. */
@@ -1388,6 +1388,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define SWITCHABLE_TARGET 0
#endif
+#ifndef MAYBE_VECTOR_CLASS_P
+#define MAYBE_VECTOR_CLASS_P(CLASS) false
+#endif
+
#endif /* GCC_INSN_FLAGS_H */
#endif /* ! GCC_DEFAULTS_H */
@@ -2898,6 +2898,20 @@ as below:
@end smallexample
@end defmac
+@defmac MAYBE_VECTOR_CLASS_P (@var{class})
+A C expression that returns @code{true} for a @var{class} of registers
+which may be vector registers. Defaults to @code{false}.
+
+For the example, on x86 system, MMX and SSE registers are vector
+registers. Therefore, @file{i386.h} defines @code{MAYBE_VECTOR_CLASS_P}
+as below:
+
+@smallexample
+#define MAYBE_VECTOR_CLASS_P(CLASS) \
+ (MAYBE_SSE_CLASS_P (CLASS) || MAYBE_MMX_CLASS_P (CLASS))
+@end smallexample
+@end defmac
+
@deftypefn {Target Hook} bool TARGET_LRA_P (void)
A target hook which returns true if we use LRA instead of reload pass. It means that LRA was ported to the target. The default version of this target hook returns always false.
@end deftypefn
@@ -2539,6 +2539,20 @@ as below:
@end smallexample
@end defmac
+@defmac MAYBE_VECTOR_CLASS_P (@var{class})
+A C expression that returns @code{true} for a @var{class} of registers
+which may be vector registers. Defaults to @code{false}.
+
+For the example, on x86 system, MMX and SSE registers are vector
+registers. Therefore, @file{i386.h} defines @code{MAYBE_VECTOR_CLASS_P}
+as below:
+
+@smallexample
+#define MAYBE_VECTOR_CLASS_P(CLASS) \
+ (MAYBE_SSE_CLASS_P (CLASS) || MAYBE_MMX_CLASS_P (CLASS))
+@end smallexample
+@end defmac
+
@hook TARGET_LRA_P
@hook TARGET_REGISTER_PRIORITY
@@ -748,7 +748,7 @@ validate_subreg (enum machine_mode omode, enum machine_mode imode,
if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode))
&& GET_MODE_INNER (imode) == omode)
;
- else if (REG_CANNOT_CHANGE_MODE_P (regno, imode, omode))
+ else if (REG_CANNOT_CHANGE_MODE_P (regno, imode, offset, omode))
return false;
#endif
@@ -716,9 +716,17 @@ extern struct target_hard_regs *this_target_hard_regs;
extern const char * reg_class_names[];
-/* 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) \
- CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN))
+/* Return true if the registers in CLASS cannot represent the change
+ from mode FROM at offset SUBREG_BYTE to mode TO. */
+#define CANNOT_CHANGE_MODE_CLASS_P(FROM, SUBREG_BYTE, TO, CLASS) \
+ ((MAYBE_VECTOR_CLASS_P (CLASS) \
+ && (SUBREG_BYTE) != 0 \
+ && GET_MODE_SIZE (TO) < GET_MODE_SIZE (FROM)) \
+ || CANNOT_CHANGE_MODE_CLASS (FROM, TO, CLASS))
+
+/* Given a hard REGN a FROM mode at SUBREG_BYTE and a TO mode, return
+ true if REGN cannot change modes between the specified modes. */
+#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, SUBREG_BYTE, TO) \
+ CANNOT_CHANGE_MODE_CLASS_P (FROM, SUBREG_BYTE, TO, REGNO_REG_CLASS (REGN))
#endif /* ! GCC_HARD_REG_SET_H */
@@ -348,9 +348,11 @@ reload_cse_simplify_set (rtx set, rtx insn)
if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
&& extend_op != UNKNOWN
#ifdef CANNOT_CHANGE_MODE_CLASS
- && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
- word_mode,
- REGNO_REG_CLASS (REGNO (SET_DEST (set))))
+ && !CANNOT_CHANGE_MODE_CLASS_P (GET_MODE (SET_DEST (set)),
+ (GET_CODE (SET_DEST (set)) == SUBREG
+ ? SUBREG_BYTE (SET_DEST (set)) : 0),
+ word_mode,
+ REGNO_REG_CLASS (REGNO (SET_DEST (set))))
#endif
)
{
@@ -458,9 +460,11 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
/* If the register cannot change mode to word_mode, it follows that
it cannot have been used in word_mode. */
else if (REG_P (SET_DEST (set))
- && CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
- word_mode,
- REGNO_REG_CLASS (REGNO (SET_DEST (set)))))
+ && CANNOT_CHANGE_MODE_CLASS_P (GET_MODE (SET_DEST (set)),
+ (GET_CODE (SET_DEST (set)) == SUBREG
+ ? SUBREG_BYTE (SET_DEST (set)) : 0),
+ word_mode,
+ REGNO_REG_CLASS (REGNO (SET_DEST (set)))))
; /* Continue ordinary processing. */
#endif
/* If this is a straight load, make the extension explicit. */
@@ -1069,7 +1069,8 @@ register_operand (rtx op, enum machine_mode mode)
#ifdef CANNOT_CHANGE_MODE_CLASS
if (REG_P (sub)
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
- && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
+ && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub),
+ SUBREG_BYTE (op), mode)
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT
/* LRA can generate some invalid SUBREGS just for matched
@@ -389,7 +389,9 @@ mode_change_ok (enum machine_mode orig_mode, enum machine_mode new_mode,
return false;
#ifdef CANNOT_CHANGE_MODE_CLASS
- return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode);
+ return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode,
+ (MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT),
+ new_mode);
#endif
return true;
@@ -1221,8 +1221,9 @@ record_subregs_of_mode (rtx subreg, bitmap subregs_of_mode)
for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
if (!bitmap_bit_p (invalid_mode_changes,
regno * N_REG_CLASSES + rclass)
- && CANNOT_CHANGE_MODE_CLASS (PSEUDO_REGNO_MODE (regno),
- mode, (enum reg_class) rclass))
+ && CANNOT_CHANGE_MODE_CLASS_P (PSEUDO_REGNO_MODE (regno),
+ (MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT),
+ mode, (enum reg_class) rclass))
bitmap_set_bit (invalid_mode_changes,
regno * N_REG_CLASSES + rclass);
}
@@ -1064,7 +1064,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
if (in != 0 && GET_CODE (in) == SUBREG
&& (subreg_lowpart_p (in) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
- && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass)
+ && !CANNOT_CHANGE_MODE_CLASS_P (GET_MODE (SUBREG_REG (in)),
+ SUBREG_BYTE (in), inmode, rclass)
#endif
&& contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (in))]
&& (CONSTANT_P (SUBREG_REG (in))
@@ -1113,7 +1114,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|| (REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P
- (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
+ (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)),
+ SUBREG_BYTE (in), inmode))
#endif
))
{
@@ -1174,7 +1176,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
- && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass)
+ && !CANNOT_CHANGE_MODE_CLASS_P (GET_MODE (SUBREG_REG (out)),
+ SUBREG_BYTE (out), outmode, rclass)
#endif
&& contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (out))]
&& (CONSTANT_P (SUBREG_REG (out))
@@ -1209,6 +1212,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
+ SUBREG_BYTE (out),
outmode))
#endif
))
@@ -6609,7 +6609,7 @@ choose_reload_regs (struct insn_chain *chain)
mode MODE. */
&& !REG_CANNOT_CHANGE_MODE_P (REGNO (reg_last_reload_reg[regno]),
GET_MODE (reg_last_reload_reg[regno]),
- mode)
+ byte, mode)
#endif
)
{
@@ -8080,8 +8080,12 @@ inherit_piecemeal_p (int dest ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED)
{
#ifdef CANNOT_CHANGE_MODE_CLASS
- return (!REG_CANNOT_CHANGE_MODE_P (dest, mode, reg_raw_mode[dest])
- && !REG_CANNOT_CHANGE_MODE_P (src, mode, reg_raw_mode[src]));
+ return (!REG_CANNOT_CHANGE_MODE_P (dest, mode,
+ (MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT),
+ reg_raw_mode[dest])
+ && !REG_CANNOT_CHANGE_MODE_P (src, mode,
+ (MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT),
+ reg_raw_mode[src]));
#else
return true;
#endif
@@ -3533,7 +3533,7 @@ simplify_subreg_regno (unsigned int xregno, enum machine_mode xmode,
/* Give the backend a chance to disallow the mode change. */
if (GET_MODE_CLASS (xmode) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (xmode) != MODE_COMPLEX_FLOAT
- && REG_CANNOT_CHANGE_MODE_P (xregno, xmode, ymode)
+ && REG_CANNOT_CHANGE_MODE_P (xregno, xmode, offset, ymode)
/* We can use mode change in LRA for some transformations. */
&& ! lra_in_progress)
return -1;