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>
|
||||
|
||||
* doc/tm.texi (CASE_VECTOR_PC_RELATIVE): Mention that the
|
||||
|
@ -1065,6 +1065,8 @@ enum label_kind
|
||||
|
||||
/* in rtlanal.c */
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
(counting from the least significant bit of the reg). */
|
||||
|
||||
unsigned int
|
||||
subreg_lsb (rtx x)
|
||||
{
|
||||
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
|
||||
enum machine_mode mode = GET_MODE (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;
|
||||
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.
|
||||
|
@ -3379,10 +3379,45 @@ simplify_subreg (enum machine_mode outermode, rtx op,
|
||||
res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
|
||||
if (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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user