summaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1999-06-17 01:56:31 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1999-06-17 01:56:31 +0000
commitab0f6ce81f286df6d0a136abca62553bdeb69e6a (patch)
treea570b046814dba585fb23c24779f923df7ddb1ed /gcc/emit-rtl.c
parent371eccf30d95f441a12fef868164ba98886b8a6f (diff)
downloadgcc-ab0f6ce81f286df6d0a136abca62553bdeb69e6a.tar.gz
* emit-rtl.c (operand_subword): Tighten checks for when it is safe
to safe to extract a subword out of a REG. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@27564 138bc75d-0d04-0410-961f-82ee72b054a4
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 2aa51aca4da..f1caea7d60d 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)