summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2013-12-09 10:46:24 -0800
committerH.J. Lu <hjl.tools@gmail.com>2013-12-14 10:59:26 -0800
commit23023006b946e06b6fd93786585f2f8cd4837956 (patch)
tree2f093718fb3c81390a6e96c9506748c752463cc4
parent73ee5dca233a3f6c5de125f188620efb202576e7 (diff)
downloadgcc-hjl/subreg-class.tar.gz
Add subreg_byte to REG_CANNOT_CHANGE_MODE_Phjl/subreg-class
Add MAYBE_VECTOR_CLASS_P for a class of registers which may be vector registers. Add CANNOT_CHANGE_MODE_CLASS_P and replace usage of CANNOT_CHANGE_MODE_CLASS with CANNOT_CHANGE_MODE_CLASS_P, which takes subreg_byte and always returns true for vector mode and non-zero subreg_byte. Use MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT indicate unknown subreg_byte.
-rw-r--r--gcc/ChangeLog.subreg27
-rw-r--r--gcc/combine.c2
-rw-r--r--gcc/config/i386/i386.c7
-rw-r--r--gcc/config/i386/i386.h7
-rw-r--r--gcc/defaults.h4
-rw-r--r--gcc/doc/tm.texi14
-rw-r--r--gcc/doc/tm.texi.in14
-rw-r--r--gcc/emit-rtl.c2
-rw-r--r--gcc/hard-reg-set.h16
-rw-r--r--gcc/postreload.c16
-rw-r--r--gcc/recog.c3
-rw-r--r--gcc/regcprop.c4
-rw-r--r--gcc/reginfo.c5
-rw-r--r--gcc/reload.c10
-rw-r--r--gcc/reload1.c10
-rw-r--r--gcc/rtlanal.c2
16 files changed, 113 insertions, 30 deletions
diff --git a/gcc/ChangeLog.subreg b/gcc/ChangeLog.subreg
new file mode 100644
index 00000000000..36987ee5dd3
--- /dev/null
+++ b/gcc/ChangeLog.subreg
@@ -0,0 +1,27 @@
+2013-12-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * combine.c (subst): Pass subreg byte to REG_CANNOT_CHANGE_MODE_P.
+ (simplify_set): Likewise.
+ * emit-rtl.c (validate_subreg): Likewise.
+ * recog.c (register_operand): Likewise.
+ * rtlanal.c (simplify_subreg_regno): Likewise.
+ * defaults.h (MAYBE_VECTOR_CLASS_P): New macro.
+ * hard-reg-set.h (CANNOT_CHANGE_MODE_CLASS_P): New macro.
+ (REG_CANNOT_CHANGE_MODE_P): Add SUBREG_BYTE and pass it to
+ CANNOT_CHANGE_MODE_CLASS_P.
+ * postreload.c (reload_cse_simplify_set): Pass subreg byte to
+ CANNOT_CHANGE_MODE_CLASS_P.
+ (reload_cse_simplify_operands): Likewise.
+ * reload.c (push_reload): Likewise.
+ * regcprop.c (mode_change_ok): Pass unknown subreg byte to
+ REG_CANNOT_CHANGE_MODE_P.
+ * reginfo.c (record_subregs_of_mode): Likewise.
+ * reload1.c (choose_reload_regs): Pass subreg byte to
+ REG_CANNOT_CHANGE_MODE_P.
+ (inherit_piecemeal_p): Pass unknown subreg byte to
+ REG_CANNOT_CHANGE_MODE_P.
+ * config/i386/i386.c (ix86_cannot_change_mode_class): Don't
+ check mode size.
+ * config/i386/i386.h (MAYBE_VECTOR_CLASS_P): New macro.
+ * doc/tm.texi.in: Document MAYBE_VECTOR_CLASS_P.
+ * doc/tm.texi: Regenerated.
diff --git a/gcc/combine.c b/gcc/combine.c
index dea6c2818bb..8e3b9629ab0 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -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)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index ecf5e0b1bc0..8d71ffbe451 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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;
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 7efd1e01f4e..d6156d79735 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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. */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 1d12aef801d..e7fbf2775da 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -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 */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 8abb3effff4..94757c1d482 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index deedb41d3b2..6ca29f8b056 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -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
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index d7fa3a5e0dc..b8e3dfd1c2b 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -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
diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h
index ad987f9b354..d488a3368d3 100644
--- a/gcc/hard-reg-set.h
+++ b/gcc/hard-reg-set.h
@@ -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 */
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 37bd9ff6ae3..a3629c792a7 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -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. */
diff --git a/gcc/recog.c b/gcc/recog.c
index dbd9a8a5065..e30d81c814b 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -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
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index 3c9ef3d3380..2be57744809 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -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;
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 46288ebd181..1f81227f378 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -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);
}
diff --git a/gcc/reload.c b/gcc/reload.c
index 96619f67820..58a614326fd 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -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
))
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 47439ce6ec9..10d5a4e69c1 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -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
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 38f9e36593d..96871106d12 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -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;