diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 95a314f..0032cb1 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5442,7 +5442,7 @@ split_double (rtx value, rtx *first, rtx *second)
    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)
@@ -5454,6 +5454,16 @@ 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 (GET_RTX_CLASS (code) == RTX_BITFIELD_OPS)
+	{
+	  /* Bitfield operations [SIGN|ZERO]_EXTRACT can be used too.  */
+	  enum machine_mode mode = GET_MODE(*loc);
+	  unsigned HOST_WIDE_INT len = INTVAL (XEXP (*loc, 1));
+	  HOST_WIDE_INT pos = INTVAL (XEXP (*loc, 2));
+
+	  if (pos == (BITS_BIG_ENDIAN ? GET_MODE_PRECISION (mode) - len : 0))
+	    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);
@@ -5470,6 +5480,18 @@ strip_address_mutations (rtx *loc, enum rtx_code *outer_code)
     }
 }
 
+/* Return true if X is a shifting operation.  */
+
+static bool
+shift_code_p (rtx x)
+{
+  return (GET_CODE (x) == ASHIFT
+          || GET_CODE (x) == ASHIFTRT
+          || GET_CODE (x) == LSHIFTRT
+          || GET_CODE (x) == ROTATE
+          || GET_CODE (x) == ROTATERT);
+}
+
 /* Return true if X must be a base rather than an index.  */
 
 static bool
@@ -5483,7 +5505,7 @@ 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 || shift_code_p (x);
 }
 
 /* Set the segment part of address INFO to LOC, given that INNER is the
@@ -5522,7 +5544,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)
+  if ((GET_CODE (*inner) == MULT || shift_code_p (*inner))
       && CONSTANT_P (XEXP (*inner, 1)))
     inner = strip_address_mutations (&XEXP (*inner, 0));
   gcc_checking_assert (REG_P (*inner)
