Commit bb51e270 by Roger Sayle Committed by Roger Sayle

rtlanal.c (subreg_lsb_1): New function split out from subreg_lsb.


	* rtlanal.c (subreg_lsb_1): New function split out from subreg_lsb.
	(subreg_lsb): Change to call new subreg_lsb_1 helper function.
	* rtl.h (subreg_lsb_1): Prototype here.
	* simplify-rtx.c (simplify_subreg): Optimize subregs of zero and
	sign extensions.

Co-Authored-By: Paolo Bonzini <bonzini@gnu.org>

From-SVN: r76352
parent 9c49953c
2004-01-22 Roger Sayle <roger@eyesopen.com>
Paolo Bonzini <bonzini@gnu.org>
* rtlanal.c (subreg_lsb_1): New function split out from subreg_lsb.
(subreg_lsb): Change to call new subreg_lsb_1 helper function.
* rtl.h (subreg_lsb_1): Prototype here.
* simplify-rtx.c (simplify_subreg): Optimize subregs of zero and
sign extensions.
2004-01-22 Kazu Hirata <kazu@cs.umass.edu> 2004-01-22 Kazu Hirata <kazu@cs.umass.edu>
* doc/tm.texi (CASE_VECTOR_PC_RELATIVE): Mention that the * doc/tm.texi (CASE_VECTOR_PC_RELATIVE): Mention that the
......
...@@ -1065,6 +1065,8 @@ enum label_kind ...@@ -1065,6 +1065,8 @@ enum label_kind
/* in rtlanal.c */ /* in rtlanal.c */
extern unsigned int subreg_lsb (rtx); extern unsigned int subreg_lsb (rtx);
extern unsigned int subreg_lsb_1 (enum machine_mode, enum machine_mode,
unsigned int);
extern unsigned int subreg_regno_offset (unsigned int, enum machine_mode, extern unsigned int subreg_regno_offset (unsigned int, enum machine_mode,
unsigned int, enum machine_mode); unsigned int, enum machine_mode);
extern bool subreg_offset_representable_p (unsigned int, enum machine_mode, extern bool subreg_offset_representable_p (unsigned int, enum machine_mode,
......
...@@ -3187,48 +3187,59 @@ loc_mentioned_in_p (rtx *loc, rtx in) ...@@ -3187,48 +3187,59 @@ loc_mentioned_in_p (rtx *loc, rtx in)
return 0; return 0;
} }
/* Given a subreg X, return the bit offset where the subreg begins /* Helper function for subreg_lsb. Given a subreg's OUTER_MODE, INNER_MODE,
(counting from the least significant bit of the reg). */ and SUBREG_BYTE, return the bit offset where the subreg begins
(counting from the least significant bit of the operand). */
unsigned int unsigned int
subreg_lsb (rtx x) subreg_lsb_1 (enum machine_mode outer_mode,
enum machine_mode inner_mode,
unsigned int subreg_byte)
{ {
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
enum machine_mode mode = GET_MODE (x);
unsigned int bitpos; unsigned int bitpos;
unsigned int byte; unsigned int byte;
unsigned int word; unsigned int word;
/* A paradoxical subreg begins at bit position 0. */ /* A paradoxical subreg begins at bit position 0. */
if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (inner_mode)) if (GET_MODE_BITSIZE (outer_mode) > GET_MODE_BITSIZE (inner_mode))
return 0; return 0;
if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN) if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
/* If the subreg crosses a word boundary ensure that /* If the subreg crosses a word boundary ensure that
it also begins and ends on a word boundary. */ it also begins and ends on a word boundary. */
if ((SUBREG_BYTE (x) % UNITS_PER_WORD if ((subreg_byte % UNITS_PER_WORD
+ GET_MODE_SIZE (mode)) > UNITS_PER_WORD + GET_MODE_SIZE (outer_mode)) > UNITS_PER_WORD
&& (SUBREG_BYTE (x) % UNITS_PER_WORD && (subreg_byte % UNITS_PER_WORD
|| GET_MODE_SIZE (mode) % UNITS_PER_WORD)) || GET_MODE_SIZE (outer_mode) % UNITS_PER_WORD))
abort (); abort ();
if (WORDS_BIG_ENDIAN) if (WORDS_BIG_ENDIAN)
word = (GET_MODE_SIZE (inner_mode) word = (GET_MODE_SIZE (inner_mode)
- (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) / UNITS_PER_WORD; - (subreg_byte + GET_MODE_SIZE (outer_mode))) / UNITS_PER_WORD;
else else
word = SUBREG_BYTE (x) / UNITS_PER_WORD; word = subreg_byte / UNITS_PER_WORD;
bitpos = word * BITS_PER_WORD; bitpos = word * BITS_PER_WORD;
if (BYTES_BIG_ENDIAN) if (BYTES_BIG_ENDIAN)
byte = (GET_MODE_SIZE (inner_mode) byte = (GET_MODE_SIZE (inner_mode)
- (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) % UNITS_PER_WORD; - (subreg_byte + GET_MODE_SIZE (outer_mode))) % UNITS_PER_WORD;
else else
byte = SUBREG_BYTE (x) % UNITS_PER_WORD; byte = subreg_byte % UNITS_PER_WORD;
bitpos += byte * BITS_PER_UNIT; bitpos += byte * BITS_PER_UNIT;
return bitpos; return bitpos;
} }
/* Given a subreg X, return the bit offset where the subreg begins
(counting from the least significant bit of the reg). */
unsigned int
subreg_lsb (rtx x)
{
return subreg_lsb_1 (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
}
/* This function returns the regno offset of a subreg expression. /* This function returns the regno offset of a subreg expression.
xregno - A regno of an inner hard subreg_reg (or what will become one). xregno - A regno of an inner hard subreg_reg (or what will become one).
xmode - The mode of xregno. xmode - The mode of xregno.
......
...@@ -3379,10 +3379,45 @@ simplify_subreg (enum machine_mode outermode, rtx op, ...@@ -3379,10 +3379,45 @@ simplify_subreg (enum machine_mode outermode, rtx op,
res = simplify_subreg (outermode, part, GET_MODE (part), final_offset); res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
if (res) if (res)
return res; return res;
/* We can at least simplify it by referring directly to the relevant part. */ /* We can at least simplify it by referring directly to the
relevant part. */
return gen_rtx_SUBREG (outermode, part, final_offset); return gen_rtx_SUBREG (outermode, part, final_offset);
} }
/* Optimize SUBREG truncations of zero and sign extended values. */
if ((GET_CODE (op) == ZERO_EXTEND
|| GET_CODE (op) == SIGN_EXTEND)
&& GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode))
{
unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte);
/* If we're requesting the lowpart of a zero or sign extension,
there are three possibilities. If the outermode is the same
as the origmode, we can omit both the extension and the subreg.
If the outermode is not larger than the origmode, we can apply
the truncation without the extension. Finally, if the outermode
is larger than the origmode, but both are integer modes, we
can just extend to the appropriate mode. */
if (bitpos == 0)
{
enum machine_mode origmode = GET_MODE (XEXP (op, 0));
if (outermode == origmode)
return XEXP (op, 0);
if (GET_MODE_BITSIZE (outermode) <= GET_MODE_BITSIZE (origmode))
return simplify_gen_subreg (outermode, XEXP (op, 0),
origmode, byte);
if (SCALAR_INT_MODE_P (outermode))
return simplify_gen_unary (GET_CODE (op), outermode,
XEXP (op, 0), origmode);
}
/* A SUBREG resulting from a zero extension may fold to zero if
it extracts higher bits that the ZERO_EXTEND's source bits. */
if (GET_CODE (op) == ZERO_EXTEND
&& bitpos >= GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))))
return CONST0_RTX (outermode);
}
return NULL_RTX; return NULL_RTX;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment