diff mbox

[ARM] Properly compute rtx costs of narrow mode shifter operands

Message ID 528B964D.70708@arm.com
State New
Headers show

Commit Message

Kyrylo Tkachov Nov. 19, 2013, 4:48 p.m. UTC
Hi all,

This patch improves the rtx costs computation for the add/sub + shift operations 
for modes narrower than SImode. There's a bit of refactoring going on, but 
essentially they are computed in the same way that SImode costs for these 
operations are computed, except that only left-shifts are considered for the 
narrow ones.

Regtested arm-non-eabi on qemu and bootstrapped on a Chromebook before trunk for 
arm became unstable recently.

Ok for trunk?

Thanks,
Kyrill

2013-11-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * config/arm/arm.c (arm_new_rtx_costs):
     Handle narrow mode add-shifts properly.
     * config/arm/arm-common.c (arm_rtx_shift_left_p): Remove static.
     * config/arm/arm-common-protos.h (arm_rtx_shift_left_p):
     Declare extern.

Comments

Richard Earnshaw Nov. 19, 2013, 5:02 p.m. UTC | #1
On 19/11/13 16:48, Kyrill Tkachov wrote:
> Hi all,
> 
> This patch improves the rtx costs computation for the add/sub + shift operations 
> for modes narrower than SImode. There's a bit of refactoring going on, but 
> essentially they are computed in the same way that SImode costs for these 
> operations are computed, except that only left-shifts are considered for the 
> narrow ones.
> 
> Regtested arm-non-eabi on qemu and bootstrapped on a Chromebook before trunk for 
> arm became unstable recently.
> 
> Ok for trunk?
> 
> Thanks,
> Kyrill
> 
> 2013-11-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>      * config/arm/arm.c (arm_new_rtx_costs):
>      Handle narrow mode add-shifts properly.
>      * config/arm/arm-common.c (arm_rtx_shift_left_p): Remove static.
>      * config/arm/arm-common-protos.h (arm_rtx_shift_left_p):
>      Declare extern.
> 
> 

Please move the ifdef/undef outside of the function definition.

OK with that change.

R.
diff mbox

Patch

diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index 841f544..c3652a7 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -31,6 +31,7 @@  extern int arm_no_early_alu_shift_dep (rtx, rtx);
 extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
 extern int arm_no_early_mul_dep (rtx, rtx);
 extern int arm_no_early_store_addr_dep (rtx, rtx);
+extern bool arm_rtx_shift_left_p (rtx);
 
 /* RTX cost table definitions.  These are used when tuning for speed rather
    than for size and should reflect the _additional_ cost over the cost
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
index 201e581..a46e675 100644
--- a/gcc/config/arm/aarch-common.c
+++ b/gcc/config/arm/aarch-common.c
@@ -40,7 +40,7 @@  typedef struct
 
 /* Return TRUE if X is either an arithmetic shift left, or
    is a multiplication by a power of two.  */
-static bool
+bool
 arm_rtx_shift_left_p (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f0f6c89..a7abdfe 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -9203,6 +9203,29 @@  arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
       *cost = LIBCALL_COST (2);
       return false;
 
+#define HANDLE_NARROW_SHIFT_ARITH(OP, IDX)				\
+	do								\
+	  {								\
+	    shift_op = shifter_op_p (XEXP (x, IDX), &shift_reg);	\
+	    if (shift_op != NULL					\
+	        && arm_rtx_shift_left_p (XEXP (x, IDX)))		\
+	      {								\
+	        if (shift_reg)						\
+		  {							\
+		    if (speed_p)					\
+		      *cost += extra_cost->alu.arith_shift_reg;	\
+		    *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);	\
+		  }							\
+	        else if (speed_p)					\
+		  *cost += extra_cost->alu.arith_shift;		\
+									\
+		  *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)	\
+			  + rtx_cost (XEXP (x, 1 - IDX),		\
+			              OP, 1, speed_p));		\
+	        return true;						\
+	      }								\
+	  }								\
+	while (0);
     case MINUS:
       if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
 	  && (mode == SFmode || !TARGET_VFP_SINGLE))
@@ -9309,6 +9332,15 @@  arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
       if (GET_MODE_CLASS (mode) == MODE_INT
 	  && GET_MODE_SIZE (mode) < 4)
 	{
+	  rtx shift_op, shift_reg;
+	  shift_reg = NULL;
+
+	  /* We check both sides of the MINUS for shifter operands since,
+	     unlike PLUS, it's not commutative.  */
+
+	  HANDLE_NARROW_SHIFT_ARITH (MINUS, 0)
+	  HANDLE_NARROW_SHIFT_ARITH (MINUS, 1)
+
 	  /* Slightly disparage, as we might need to widen the result.  */
 	  *cost = 1 + COSTS_N_INSNS (1);
 	  if (speed_p)
@@ -9408,11 +9440,20 @@  arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  return false;
 	}
 
+	/* Narrow modes can be synthesized in SImode, but the range
+	   of useful sub-operations is limited.  Check for shift operations
+	   on one of the operands.  Only left shifts can be used in the
+	   narrow modes.  */
       if (GET_MODE_CLASS (mode) == MODE_INT
 	  && GET_MODE_SIZE (mode) < 4)
 	{
-	  /* Narrow modes can be synthesized in SImode, but the range
-	     of useful sub-operations is limited.  */
+	  rtx shift_op, shift_reg;
+	  shift_reg = NULL;
+
+	  HANDLE_NARROW_SHIFT_ARITH (PLUS, 0)
+
+#undef HANDLE_NARROW_SHIFT_ARITH
+
 	  if (CONST_INT_P (XEXP (x, 1)))
 	    {
 	      int insns = arm_gen_constant (PLUS, SImode, NULL_RTX,