]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtlanal.c (lsb_bitfield_op_p): New predicate for bitfield operations from the least...
authorYvan Roux <yvan.roux@linaro.org>
Wed, 25 Sep 2013 18:31:13 +0000 (18:31 +0000)
committerYvan Roux <yroux@gcc.gnu.org>
Wed, 25 Sep 2013 18:31:13 +0000 (18:31 +0000)
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

gcc/ChangeLog
gcc/rtlanal.c

index 828da1e9ff0e394ab9d4b2b8ad75d230d6000708..360a8f12e8c37cbd1204532d43725b3e0586affc 100644 (file)
@@ -1,3 +1,13 @@
+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>
            Maxim Kuznetsov  <maxim.kuznetsov@intel.com>
            Sergey Lega  <sergey.s.lega@intel.com>
index 554a44c4d9c0be7c08bfc54853773d57d22d0738..24cbcd2fcf2dc0a64a3051cecd77460d6fda0214 100644 (file)
@@ -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
    inner value.  If OUTER_CODE is nonnull, store the code of the innermost
    stripped expression there.
 
    "Mutations" either convert between modes or apply some kind of
-   alignment.  */
+   extension, truncation or alignment.  */
 
 rtx *
 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
           used to convert between pointer sizes.  */
        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)))
        /* (and ... (const_int -X)) is used to align to X bytes.  */
        loc = &XEXP (*loc, 0);
@@ -5513,7 +5534,13 @@ must_be_base_p (rtx x)
 static bool
 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
@@ -5535,7 +5562,7 @@ set_address_segment (struct address_info *info, rtx *loc, rtx *inner)
 static void
 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));
   gcc_checking_assert (REG_P (*inner)
                       || MEM_P (*inner)
@@ -5552,8 +5579,7 @@ set_address_base (struct address_info *info, rtx *loc, rtx *inner)
 static void
 set_address_index (struct address_info *info, rtx *loc, rtx *inner)
 {
-  if ((GET_CODE (*inner) == MULT || GET_CODE (*inner) == ASHIFT)
-      && CONSTANT_P (XEXP (*inner, 1)))
+  if (must_be_index_p (*inner) && CONSTANT_P (XEXP (*inner, 1)))
     inner = strip_address_mutations (&XEXP (*inner, 0));
   gcc_checking_assert (REG_P (*inner)
                       || MEM_P (*inner)