aboutsummaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorJeffrey A Law <law@cygnus.com>1999-06-17 01:56:31 +0000
committerJeff Law <law@gcc.gnu.org>1999-06-16 19:56:31 -0600
commit227d6ce040d7ac43962ab3610f50cbda3dbed544 (patch)
treea570b046814dba585fb23c24779f923df7ddb1ed /gcc/emit-rtl.c
parentff77e80cf8aed5b75c76ac943c58e5cb9958b120 (diff)
downloadgcc-227d6ce040d7ac43962ab3610f50cbda3dbed544.zip
gcc-227d6ce040d7ac43962ab3610f50cbda3dbed544.tar.gz
gcc-227d6ce040d7ac43962ab3610f50cbda3dbed544.tar.bz2
emit-rtl.c (operand_subword): Tighten checks for when it is safe to safe to extract a subword out of a REG.
* emit-rtl.c (operand_subword): Tighten checks for when it is safe to safe to extract a subword out of a REG. From-SVN: r27564
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r--gcc/emit-rtl.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 2aa51ac..f1caea7 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1196,10 +1196,33 @@ operand_subword (op, i, validate_address, mode)
/* If OP is a REG or SUBREG, we can handle it very simply. */
if (GET_CODE (op) == REG)
{
- /* If the register is not valid for MODE, return 0. If we don't
- do this, there is no way to fix up the resulting REG later. */
+ /* ??? There is a potential problem with this code. It does not
+ properly handle extractions of a subword from a hard register
+ that is larger than word_mode. Presumably the check for
+ HARD_REGNO_MODE_OK catches these most of these cases. */
+
+ /* If OP is a hard register, but OP + I is not a hard register,
+ then extracting a subword is impossible.
+
+ For example, consider if OP is the last hard register and it is
+ larger than word_mode. If we wanted word N (for N > 0) because a
+ part of that hard register was known to contain a useful value,
+ then OP + I would refer to a pseudo, not the hard register we
+ actually wanted. */
+ if (REGNO (op) < FIRST_PSEUDO_REGISTER
+ && REGNO (op) + i >= FIRST_PSEUDO_REGISTER)
+ return 0;
+
+ /* If the register is not valid for MODE, return 0. Note we
+ have to check both OP and OP + I since they may refer to
+ different parts of the register file.
+
+ Consider if OP refers to the last 96bit FP register and we want
+ subword 3 because that subword is known to contain a value we
+ needed. */
if (REGNO (op) < FIRST_PSEUDO_REGISTER
- && ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode))
+ && (! HARD_REGNO_MODE_OK (REGNO (op), word_mode)
+ || ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)))
return 0;
else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| (REG_FUNCTION_VALUE_P (op)