Commit 3936bafc by Yvan Roux Committed by Yvan Roux

rtlanal.c (lsb_bitfield_op_p): New predicate for bitfield operations from the…

rtlanal.c (lsb_bitfield_op_p): New predicate for bitfield operations from the least significant bit.

2013-09-25  Yvan Roux  <yvan.roux@linaro.org>
	    Vladimir Makarov  <vmakarov@redhat.com>

	* rtlanal.c (lsb_bitfield_op_p): New predicate for bitfield operations
	from the least significant bit.
	(strip_address_mutations): Add bitfield operations handling.
	(must_be_index_p): Add shifting and rotate operations handling.
	(set_address_base): Use must_be_base_p predicate.
	(set_address_index):Use must_be_index_p predicate.


Co-Authored-By: Vladimir Makarov <vmakarov@redhat.com>

From-SVN: r202914
parent b86f6e9e
2013-09-25 Yvan Roux <yvan.roux@linaro.org>
Vladimir Makarov <vmakarov@redhat.com>
* rtlanal.c (lsb_bitfield_op_p): New predicate for bitfield operations
from the least significant bit.
(strip_address_mutations): Add bitfield operations handling.
(must_be_index_p): Add shifting and rotate operations handling.
(set_address_base): Use must_be_base_p predicate.
(set_address_index):Use must_be_index_p predicate.
2013-09-25 Alexander Ivchenko <alexander.ivchenko@intel.com> 2013-09-25 Alexander Ivchenko <alexander.ivchenko@intel.com>
Maxim Kuznetsov <maxim.kuznetsov@intel.com> Maxim Kuznetsov <maxim.kuznetsov@intel.com>
Sergey Lega <sergey.s.lega@intel.com> Sergey Lega <sergey.s.lega@intel.com>
......
...@@ -5467,12 +5467,29 @@ split_double (rtx value, rtx *first, rtx *second) ...@@ -5467,12 +5467,29 @@ split_double (rtx value, rtx *first, rtx *second)
} }
} }
/* Return true if X is a sign_extract or zero_extract from the least
significant bit. */
static bool
lsb_bitfield_op_p (rtx x)
{
if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
{
enum machine_mode mode = GET_MODE (XEXP (x, 0));
unsigned HOST_WIDE_INT len = INTVAL (XEXP (x, 1));
HOST_WIDE_INT pos = INTVAL (XEXP (x, 2));
return (pos == (BITS_BIG_ENDIAN ? GET_MODE_PRECISION (mode) - len : 0));
}
return false;
}
/* Strip outer address "mutations" from LOC and return a pointer to the /* Strip outer address "mutations" from LOC and return a pointer to the
inner value. If OUTER_CODE is nonnull, store the code of the innermost inner value. If OUTER_CODE is nonnull, store the code of the innermost
stripped expression there. stripped expression there.
"Mutations" either convert between modes or apply some kind of "Mutations" either convert between modes or apply some kind of
alignment. */ extension, truncation or alignment. */
rtx * rtx *
strip_address_mutations (rtx *loc, enum rtx_code *outer_code) strip_address_mutations (rtx *loc, enum rtx_code *outer_code)
...@@ -5484,6 +5501,10 @@ strip_address_mutations (rtx *loc, enum rtx_code *outer_code) ...@@ -5484,6 +5501,10 @@ strip_address_mutations (rtx *loc, enum rtx_code *outer_code)
/* Things like SIGN_EXTEND, ZERO_EXTEND and TRUNCATE can be /* Things like SIGN_EXTEND, ZERO_EXTEND and TRUNCATE can be
used to convert between pointer sizes. */ used to convert between pointer sizes. */
loc = &XEXP (*loc, 0); loc = &XEXP (*loc, 0);
else if (lsb_bitfield_op_p (*loc))
/* A [SIGN|ZERO]_EXTRACT from the least significant bit effectively
acts as a combined truncation and extension. */
loc = &XEXP (*loc, 0);
else if (code == AND && CONST_INT_P (XEXP (*loc, 1))) else if (code == AND && CONST_INT_P (XEXP (*loc, 1)))
/* (and ... (const_int -X)) is used to align to X bytes. */ /* (and ... (const_int -X)) is used to align to X bytes. */
loc = &XEXP (*loc, 0); loc = &XEXP (*loc, 0);
...@@ -5513,7 +5534,13 @@ must_be_base_p (rtx x) ...@@ -5513,7 +5534,13 @@ must_be_base_p (rtx x)
static bool static bool
must_be_index_p (rtx x) must_be_index_p (rtx x)
{ {
return GET_CODE (x) == MULT || GET_CODE (x) == ASHIFT; return (GET_CODE (x) == MULT
|| GET_CODE (x) == ASHIFT
/* Needed by ARM targets. */
|| GET_CODE (x) == ASHIFTRT
|| GET_CODE (x) == LSHIFTRT
|| GET_CODE (x) == ROTATE
|| GET_CODE (x) == ROTATERT);
} }
/* Set the segment part of address INFO to LOC, given that INNER is the /* Set the segment part of address INFO to LOC, given that INNER is the
...@@ -5535,7 +5562,7 @@ set_address_segment (struct address_info *info, rtx *loc, rtx *inner) ...@@ -5535,7 +5562,7 @@ set_address_segment (struct address_info *info, rtx *loc, rtx *inner)
static void static void
set_address_base (struct address_info *info, rtx *loc, rtx *inner) set_address_base (struct address_info *info, rtx *loc, rtx *inner)
{ {
if (GET_CODE (*inner) == LO_SUM) if (must_be_base_p (*inner))
inner = strip_address_mutations (&XEXP (*inner, 0)); inner = strip_address_mutations (&XEXP (*inner, 0));
gcc_checking_assert (REG_P (*inner) gcc_checking_assert (REG_P (*inner)
|| MEM_P (*inner) || MEM_P (*inner)
...@@ -5552,8 +5579,7 @@ set_address_base (struct address_info *info, rtx *loc, rtx *inner) ...@@ -5552,8 +5579,7 @@ set_address_base (struct address_info *info, rtx *loc, rtx *inner)
static void static void
set_address_index (struct address_info *info, rtx *loc, rtx *inner) set_address_index (struct address_info *info, rtx *loc, rtx *inner)
{ {
if ((GET_CODE (*inner) == MULT || GET_CODE (*inner) == ASHIFT) if (must_be_index_p (*inner) && CONSTANT_P (XEXP (*inner, 1)))
&& CONSTANT_P (XEXP (*inner, 1)))
inner = strip_address_mutations (&XEXP (*inner, 0)); inner = strip_address_mutations (&XEXP (*inner, 0));
gcc_checking_assert (REG_P (*inner) gcc_checking_assert (REG_P (*inner)
|| MEM_P (*inner) || MEM_P (*inner)
......
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