[AArch64] Properly cost zero_extend+ashift forms of ubfi[xz]
authorktkachov <ktkachov@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Dec 2015 15:49:42 +0000 (15:49 +0000)
committerktkachov <ktkachov@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Dec 2015 15:49:42 +0000 (15:49 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231698 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/aarch64/aarch64.c

index 75da80b..ef9db37 100644 (file)
@@ -1,5 +1,12 @@
 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
        * config/aarch64/aarch64-simd.md (*aarch64_simd_bsl<mode>_alt):
        New pattern.
index 1e1b864..e3e5b6b 100644 (file)
@@ -6146,6 +6146,50 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx op2, int *cost, bool speed)
   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
@@ -6837,6 +6881,15 @@ cost_plus:
          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))
@@ -6868,6 +6921,15 @@ cost_plus:
          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))