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
This commit is contained in:
parent
9c49953c15
commit
bb51e27026
@ -1,3 +1,12 @@
|
|||||||
|
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
|
|||||||
|
|
||||||
/* 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,46 +3187,57 @@ loc_mentioned_in_p (rtx *loc, rtx in)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function for subreg_lsb. Given a subreg's OUTER_MODE, INNER_MODE,
|
||||||
|
and SUBREG_BYTE, return the bit offset where the subreg begins
|
||||||
|
(counting from the least significant bit of the operand). */
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
subreg_lsb_1 (enum machine_mode outer_mode,
|
||||||
|
enum machine_mode inner_mode,
|
||||||
|
unsigned int subreg_byte)
|
||||||
|
{
|
||||||
|
unsigned int bitpos;
|
||||||
|
unsigned int byte;
|
||||||
|
unsigned int word;
|
||||||
|
|
||||||
|
/* A paradoxical subreg begins at bit position 0. */
|
||||||
|
if (GET_MODE_BITSIZE (outer_mode) > GET_MODE_BITSIZE (inner_mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
|
||||||
|
/* If the subreg crosses a word boundary ensure that
|
||||||
|
it also begins and ends on a word boundary. */
|
||||||
|
if ((subreg_byte % UNITS_PER_WORD
|
||||||
|
+ GET_MODE_SIZE (outer_mode)) > UNITS_PER_WORD
|
||||||
|
&& (subreg_byte % UNITS_PER_WORD
|
||||||
|
|| GET_MODE_SIZE (outer_mode) % UNITS_PER_WORD))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (WORDS_BIG_ENDIAN)
|
||||||
|
word = (GET_MODE_SIZE (inner_mode)
|
||||||
|
- (subreg_byte + GET_MODE_SIZE (outer_mode))) / UNITS_PER_WORD;
|
||||||
|
else
|
||||||
|
word = subreg_byte / UNITS_PER_WORD;
|
||||||
|
bitpos = word * BITS_PER_WORD;
|
||||||
|
|
||||||
|
if (BYTES_BIG_ENDIAN)
|
||||||
|
byte = (GET_MODE_SIZE (inner_mode)
|
||||||
|
- (subreg_byte + GET_MODE_SIZE (outer_mode))) % UNITS_PER_WORD;
|
||||||
|
else
|
||||||
|
byte = subreg_byte % UNITS_PER_WORD;
|
||||||
|
bitpos += byte * BITS_PER_UNIT;
|
||||||
|
|
||||||
|
return bitpos;
|
||||||
|
}
|
||||||
|
|
||||||
/* Given a subreg X, return the bit offset where the subreg begins
|
/* Given a subreg X, return the bit offset where the subreg begins
|
||||||
(counting from the least significant bit of the reg). */
|
(counting from the least significant bit of the reg). */
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
subreg_lsb (rtx x)
|
subreg_lsb (rtx x)
|
||||||
{
|
{
|
||||||
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
|
return subreg_lsb_1 (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
|
||||||
enum machine_mode mode = GET_MODE (x);
|
SUBREG_BYTE (x));
|
||||||
unsigned int bitpos;
|
|
||||||
unsigned int byte;
|
|
||||||
unsigned int word;
|
|
||||||
|
|
||||||
/* A paradoxical subreg begins at bit position 0. */
|
|
||||||
if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (inner_mode))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
|
|
||||||
/* If the subreg crosses a word boundary ensure that
|
|
||||||
it also begins and ends on a word boundary. */
|
|
||||||
if ((SUBREG_BYTE (x) % UNITS_PER_WORD
|
|
||||||
+ GET_MODE_SIZE (mode)) > UNITS_PER_WORD
|
|
||||||
&& (SUBREG_BYTE (x) % UNITS_PER_WORD
|
|
||||||
|| GET_MODE_SIZE (mode) % UNITS_PER_WORD))
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
if (WORDS_BIG_ENDIAN)
|
|
||||||
word = (GET_MODE_SIZE (inner_mode)
|
|
||||||
- (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) / UNITS_PER_WORD;
|
|
||||||
else
|
|
||||||
word = SUBREG_BYTE (x) / UNITS_PER_WORD;
|
|
||||||
bitpos = word * BITS_PER_WORD;
|
|
||||||
|
|
||||||
if (BYTES_BIG_ENDIAN)
|
|
||||||
byte = (GET_MODE_SIZE (inner_mode)
|
|
||||||
- (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) % UNITS_PER_WORD;
|
|
||||||
else
|
|
||||||
byte = SUBREG_BYTE (x) % UNITS_PER_WORD;
|
|
||||||
bitpos += byte * BITS_PER_UNIT;
|
|
||||||
|
|
||||||
return bitpos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function returns the regno offset of a subreg expression.
|
/* This function returns the regno offset of a subreg expression.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user