aboutsummaryrefslogtreecommitdiff
path: root/gcc/cse.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1992-06-28 06:10:54 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1992-06-28 06:10:54 -0400
commit4b980e20ad0778782fdf76e58a71d4a88b5a3df0 (patch)
treeb215796c829e5f18a18e35ba251206bb77efe9af /gcc/cse.c
parentca3c6eae463a45719741d379a9c52fec613fd2fd (diff)
downloadgcc-4b980e20ad0778782fdf76e58a71d4a88b5a3df0.zip
gcc-4b980e20ad0778782fdf76e58a71d4a88b5a3df0.tar.gz
gcc-4b980e20ad0778782fdf76e58a71d4a88b5a3df0.tar.bz2
*** empty log message ***
From-SVN: r1318
Diffstat (limited to 'gcc/cse.c')
-rw-r--r--gcc/cse.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/gcc/cse.c b/gcc/cse.c
index 6476549..334d899 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4327,10 +4327,32 @@ fold_rtx (x, insn)
|| (new = lookup_as_function (x, CONST_DOUBLE)) != 0)
return new;
- /* If this is a paradoxical SUBREG, we can't do anything with
- it because we have no idea what value the extra bits would have. */
+ /* If this is a paradoxical SUBREG, we have no idea what value the
+ extra bits would have. However, if the operand is equivalent
+ to a SUBREG whose operand is the same as our mode, and all the
+ modes are within a word, we can just use the inner operand
+ because these SUBREGs just say how to treat the register. */
+
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- return x;
+ {
+ enum machine_mode imode = GET_MODE (SUBREG_REG (x));
+ struct table_elt *elt;
+
+ if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ && GET_MODE_SIZE (imode) <= UNITS_PER_WORD
+ && (elt = lookup (SUBREG_REG (x), HASH (SUBREG_REG (x), imode),
+ imode)) != 0)
+ {
+ for (elt = elt->first_same_value;
+ elt; elt = elt->next_same_value)
+ if (GET_CODE (elt->exp) == SUBREG
+ && GET_MODE (SUBREG_REG (elt->exp)) == mode
+ && exp_equiv_p (elt->exp, elt->exp, 1))
+ return copy_rtx (SUBREG_REG (elt->exp));
+ }
+
+ return x;
+ }
/* Fold SUBREG_REG. If it changed, see if we can simplify the SUBREG.
We might be able to if the SUBREG is extracting a single word in an
@@ -4364,7 +4386,12 @@ fold_rtx (x, insn)
extra bits will be. But we can find an equivalence for this SUBREG
by folding that operation is the narrow mode. This allows us to
fold arithmetic in narrow modes when the machine only supports
- word-sized arithmetic. */
+ word-sized arithmetic.
+
+ Also look for a case where we have a SUBREG whose operand is the
+ same as our result. If both modes are smaller than a word, we
+ are simply interpreting a register in different modes and we
+ can use the inner value. */
if (GET_CODE (folded_arg0) == REG
&& GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (folded_arg0)))
@@ -4430,6 +4457,13 @@ fold_rtx (x, insn)
op0, op1);
}
+ else if (GET_CODE (elt->exp) == SUBREG
+ && GET_MODE (SUBREG_REG (elt->exp)) == mode
+ && (GET_MODE_SIZE (GET_MODE (folded_arg0))
+ <= UNITS_PER_WORD)
+ && exp_equiv_p (elt->exp, elt->exp, 1))
+ new = copy_rtx (SUBREG_REG (elt->exp));
+
if (new)
return new;
}