summaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-06-04 14:52:14 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-06-04 14:52:14 +0000
commit81802af67bf22f3decf31100628f236650275ddb (patch)
treed351d9b0c5c56ead3c8dc57fbda5329e9a5df46f /gcc/emit-rtl.c
parent1580af85fa12b48da3d5888ce74a8e689911958b (diff)
downloadgcc-81802af67bf22f3decf31100628f236650275ddb.tar.gz
* simplify_rtx.c (simplify_subreg): Keep subregs on return values,
check CLASS_CANNOT_CHANGE_MODE before avoiding subreg on hard reg, in case register wasn't OK previously, accept it now; allow subregs of frame pointer if reload completed and frame pointer is not needed. * combine.c (sombine_simplify_rtx): Fix comment; use subreg_lowpart_offset instead of subreg_lowpart_p (gen_lowpart_for_combine): Use subreg_lowpart_offset. * rtl.h (subreg_lowpart_parts_p): Kill. (subreg_lowpart_offset, subreg_highpart_offset): Declare. * simplify-rtx.c (simplify_subreg): Use subreg_lowpart_offset. * emit-rtl.c (gen_lowpart_SUBREG): Use subreg_lowpart_offset; (gen_lowpart_common): Likewise. (subreg_lowpart_p): Likewise. (subreg_lowpart_parts_p): Kill. (subreg_lowpart_offset, subreg_highpart_offset): New function. * emit-rtl.c (gen_lowpart_common): Use simplify_gen_subreg to simplify SUBREG and REG. (gen_highpart): Use simplify_gen_subreg for all simplifications. * emit-rtl.c (gen_realpart, gen_imagpart): Do not handle CONCAT specially. * rtlanal.c (replace_regs): Use simplify_gen_subreg git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@42850 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r--gcc/emit-rtl.c209
1 files changed, 43 insertions, 166 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 7a98f20f46b..6c72a99902b 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -381,22 +381,12 @@ gen_lowpart_SUBREG (mode, reg)
rtx reg;
{
enum machine_mode inmode;
- int offset;
inmode = GET_MODE (reg);
if (inmode == VOIDmode)
inmode = mode;
- offset = 0;
- if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (inmode)
- && (WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN))
- {
- offset = GET_MODE_SIZE (inmode) - GET_MODE_SIZE (mode);
- if (! BYTES_BIG_ENDIAN)
- offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
- else if (! WORDS_BIG_ENDIAN)
- offset %= UNITS_PER_WORD;
- }
- return gen_rtx_SUBREG (mode, reg, offset);
+ return gen_rtx_SUBREG (mode, reg,
+ subreg_lowpart_offset (mode, inmode));
}
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
@@ -761,16 +751,7 @@ gen_lowpart_common (mode, x)
> ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
return 0;
- if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
- && xsize > msize)
- {
- int difference = xsize - msize;
-
- if (WORDS_BIG_ENDIAN)
- offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset += difference % UNITS_PER_WORD;
- }
+ offset = subreg_lowpart_offset (mode, GET_MODE (x));
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
&& (GET_MODE_CLASS (mode) == MODE_INT
@@ -791,61 +772,8 @@ gen_lowpart_common (mode, x)
else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))
return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
}
- else if (GET_CODE (x) == SUBREG
- && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
- || GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
- {
- int final_offset;
-
- if (GET_MODE (SUBREG_REG (x)) == mode && subreg_lowpart_p (x))
- return SUBREG_REG (x);
-
- /* When working with SUBREGs the rule is that the byte
- offset must be a multiple of the SUBREG's mode. */
- final_offset = SUBREG_BYTE (x) + offset;
- final_offset = (final_offset / GET_MODE_SIZE (mode));
- final_offset = (final_offset * GET_MODE_SIZE (mode));
- return gen_rtx_SUBREG (mode, SUBREG_REG (x), final_offset);
- }
- else if (GET_CODE (x) == REG)
- {
- /* Hard registers are done specially in certain cases. */
- if (REGNO (x) < FIRST_PSEUDO_REGISTER)
- {
- int final_regno = REGNO (x) +
- subreg_regno_offset (REGNO (x), GET_MODE (x),
- offset, mode);
-
- /* If the final regno is not valid for MODE, punt. */
- /* ??? We do allow it if the current REG is not valid for
- ??? it's mode. It is a kludge to work around how float/complex
- ??? arguments are passed on 32-bit Sparc and should be fixed. */
- if (! HARD_REGNO_MODE_OK (final_regno, mode)
- && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))
- return 0;
-
- /* integrate.c can't handle parts of a return value register. */
- if ((! REG_FUNCTION_VALUE_P (x)
- || ! rtx_equal_function_value_matters)
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && ! (CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (x))
- && GET_MODE_CLASS (GET_MODE (x)) != MODE_COMPLEX_INT
- && GET_MODE_CLASS (GET_MODE (x)) != MODE_COMPLEX_FLOAT
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- REGNO (x))))
-#endif
- /* We want to keep the stack, frame, and arg pointers
- special. */
- && x != frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- && x != arg_pointer_rtx
-#endif
- && x != stack_pointer_rtx)
- return gen_rtx_REG (mode, final_regno);
- }
- return gen_rtx_SUBREG (mode, x, offset);
- }
+ else if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG || GET_CODE (x) == CONCAT)
+ return simplify_gen_subreg (mode, x, GET_MODE (x), offset);
/* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
from the low-order part of the constant. */
else if ((GET_MODE_CLASS (mode) == MODE_INT
@@ -1088,12 +1016,10 @@ gen_realpart (mode, x)
enum machine_mode mode;
register rtx x;
{
- if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode)
- return XEXP (x, 0);
- else if (WORDS_BIG_ENDIAN
- && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
- && REG_P (x)
- && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ if (WORDS_BIG_ENDIAN
+ && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
+ && REG_P (x)
+ && REGNO (x) < FIRST_PSEUDO_REGISTER)
internal_error
("Can't access real part of complex value in hard register");
else if (WORDS_BIG_ENDIAN)
@@ -1110,9 +1036,7 @@ gen_imagpart (mode, x)
enum machine_mode mode;
register rtx x;
{
- if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode)
- return XEXP (x, 1);
- else if (WORDS_BIG_ENDIAN)
+ if (WORDS_BIG_ENDIAN)
return gen_lowpart (mode, x);
else if (! WORDS_BIG_ENDIAN
&& GET_MODE_BITSIZE (mode) < BITS_PER_WORD
@@ -1195,109 +1119,62 @@ gen_highpart (mode, x)
register rtx x;
{
unsigned int msize = GET_MODE_SIZE (mode);
- unsigned int xsize = GET_MODE_SIZE (GET_MODE (x));
+ rtx result;
/* This case loses if X is a subreg. To catch bugs early,
complain if an invalid MODE is used even in other cases. */
if (msize > UNITS_PER_WORD
&& msize != GET_MODE_UNIT_SIZE (GET_MODE (x)))
abort ();
- if (GET_CODE (x) == CONST_DOUBLE
-#if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined (REAL_IS_NOT_DOUBLE))
- && GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT
-#endif
- )
- return GEN_INT (CONST_DOUBLE_HIGH (x) & GET_MODE_MASK (mode));
- else if (GET_CODE (x) == CONST_INT)
- {
- if (HOST_BITS_PER_WIDE_INT <= BITS_PER_WORD)
- return const0_rtx;
- return GEN_INT (INTVAL (x) >> (HOST_BITS_PER_WIDE_INT - BITS_PER_WORD));
- }
- else if (GET_CODE (x) == MEM)
- {
- register int offset = 0;
- if (! WORDS_BIG_ENDIAN)
- offset = (MAX (xsize, UNITS_PER_WORD)
- - MAX (msize, UNITS_PER_WORD));
+ result = simplify_gen_subreg (mode, x, GET_MODE (x),
+ subreg_highpart_offset (mode, GET_MODE (x)));
+ if (!result)
+ abort ();
+ return result;
+}
+/* Return offset in bytes to get OUTERMODE low part
+ of the value in mode INNERMODE stored in memory in target format. */
- if (! BYTES_BIG_ENDIAN
- && msize < UNITS_PER_WORD)
- offset -= (msize - MIN (UNITS_PER_WORD, xsize));
+unsigned int
+subreg_lowpart_offset (outermode, innermode)
+ enum machine_mode outermode, innermode;
+{
+ unsigned int offset = 0;
+ int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
- return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
- }
- else if (GET_CODE (x) == SUBREG)
+ if (difference > 0)
{
- /* The only time this should occur is when we are looking at a
- multi-word item with a SUBREG whose mode is the same as that of the
- item. It isn't clear what we would do if it wasn't. */
- if (SUBREG_BYTE (x) != 0)
- abort ();
- return gen_highpart (mode, SUBREG_REG (x));
+ if (WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
}
- else if (GET_CODE (x) == REG)
- {
- int offset = 0;
-
- if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
- abort ();
-
- if ((! WORDS_BIG_ENDIAN || ! BYTES_BIG_ENDIAN)
- && xsize > msize)
- {
- int difference = xsize - msize;
- if (! WORDS_BIG_ENDIAN)
- offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
- if (! BYTES_BIG_ENDIAN)
- offset += difference % UNITS_PER_WORD;
- }
- if (REGNO (x) < FIRST_PSEUDO_REGISTER)
- {
- int final_regno = REGNO (x) +
- subreg_regno_offset (REGNO (x), GET_MODE (x), offset, mode);
-
- /* integrate.c can't handle parts of a return value register.
- ??? Then integrate.c should be fixed!
- ??? What about CLASS_CANNOT_CHANGE_SIZE? */
- if ((! REG_FUNCTION_VALUE_P (x)
- || ! rtx_equal_function_value_matters)
- /* We want to keep the stack, frame, and arg pointers special. */
- && x != frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- && x != arg_pointer_rtx
-#endif
- && x != stack_pointer_rtx)
- return gen_rtx_REG (mode, final_regno);
- }
- /* Just generate a normal SUBREG. */
- return gen_rtx_SUBREG (mode, x, offset);
- }
- else
- abort ();
+ return offset;
}
-/* Return 1 iff (SUBREG:outermode (OP:innermode) byte)
- refers to the least significant part of its containing reg. */
-int
-subreg_lowpart_parts_p (outermode, innermode, byte)
+/* Return offset in bytes to get OUTERMODE high part
+ of the value in mode INNERMODE stored in memory in target format. */
+unsigned int
+subreg_highpart_offset (outermode, innermode)
enum machine_mode outermode, innermode;
- unsigned int byte;
{
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
+ if (GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode))
+ abort ();
+
if (difference > 0)
{
- if (WORDS_BIG_ENDIAN)
+ if (! WORDS_BIG_ENDIAN)
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
+ if (! BYTES_BIG_ENDIAN)
offset += difference % UNITS_PER_WORD;
}
- return byte == offset;
+ return offset;
}
/* Return 1 iff X, assumed to be a SUBREG,
@@ -1313,8 +1190,8 @@ subreg_lowpart_p (x)
else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
return 0;
- return subreg_lowpart_parts_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
- SUBREG_BYTE (x));
+ return (subreg_lowpart_offset (GET_MODE (x), GET_MODE (SUBREG_REG (x)))
+ == SUBREG_BYTE (x));
}