+2015-12-16  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/aarch64/aarch64.c (aarch64_extend_bitfield_pattern_p):
+       New function.
+       (aarch64_rtx_costs, ZERO_EXTEND, SIGN_EXTEND cases): Use the above
+       to handle extend+shift rtxes.
+
 2015-12-16  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        PR target/68696
 
   return false;
 }
 
+/* Check whether X is a bitfield operation of the form shift + extend that
+   maps down to a UBFIZ/SBFIZ/UBFX/SBFX instruction.  If so, return the
+   operand to which the bitfield operation is applied.  Otherwise return
+   NULL_RTX.  */
+
+static rtx
+aarch64_extend_bitfield_pattern_p (rtx x)
+{
+  rtx_code outer_code = GET_CODE (x);
+  machine_mode outer_mode = GET_MODE (x);
+
+  if (outer_code != ZERO_EXTEND && outer_code != SIGN_EXTEND
+      && outer_mode != SImode && outer_mode != DImode)
+    return NULL_RTX;
+
+  rtx inner = XEXP (x, 0);
+  rtx_code inner_code = GET_CODE (inner);
+  machine_mode inner_mode = GET_MODE (inner);
+  rtx op = NULL_RTX;
+
+  switch (inner_code)
+    {
+      case ASHIFT:
+       if (CONST_INT_P (XEXP (inner, 1))
+           && (inner_mode == QImode || inner_mode == HImode))
+         op = XEXP (inner, 0);
+       break;
+      case LSHIFTRT:
+       if (outer_code == ZERO_EXTEND && CONST_INT_P (XEXP (inner, 1))
+           && (inner_mode == QImode || inner_mode == HImode))
+         op = XEXP (inner, 0);
+       break;
+      case ASHIFTRT:
+       if (outer_code == SIGN_EXTEND && CONST_INT_P (XEXP (inner, 1))
+           && (inner_mode == QImode || inner_mode == HImode))
+         op = XEXP (inner, 0);
+       break;
+      default:
+       break;
+    }
+
+  return op;
+}
+
 /* Calculate the cost of calculating X, storing it in *COST.  Result
    is true if the total cost of the operation has now been calculated.  */
 static bool
          return true;
        }
 
+      op0 = aarch64_extend_bitfield_pattern_p (x);
+      if (op0)
+       {
+         *cost += rtx_cost (op0, mode, ZERO_EXTEND, 0, speed);
+         if (speed)
+           *cost += extra_cost->alu.bfx;
+         return true;
+       }
+
       if (speed)
        {
          if (VECTOR_MODE_P (mode))
          return true;
        }
 
+      op0 = aarch64_extend_bitfield_pattern_p (x);
+      if (op0)
+       {
+         *cost += rtx_cost (op0, mode, SIGN_EXTEND, 0, speed);
+         if (speed)
+           *cost += extra_cost->alu.bfx;
+         return true;
+       }
+
       if (speed)
        {
          if (VECTOR_MODE_P (mode))