Patchwork shrink storage for target_expmed cost fields

login
register
mail settings
Submitter Nathan Froyd
Date July 30, 2012, 9:05 p.m.
Message ID <1343682326-6963-1-git-send-email-froydnj@mozilla.com>
Download mbox | patch
Permalink /patch/174094/
State New
Headers show

Comments

Nathan Froyd - July 30, 2012, 9:05 p.m.
Now that we can freely change the representation of the cost fields in
struct target_expmed, the patch below does so, by only requiring arrays
to hold enough storage for integer modes and/or vector integer modes,
as appropriate.

default_target_expmed shrinks from ~200KB to ~85KB on
x86_64-unknown-linux-gnu as a result of this patch (20+ (!) vector
integer modes).  As a comparison point, it shrinks from ~120KB to ~45KB
on alpha-linux-gnu (5 vector integer modes).  So it should be helpful no
matter what your target looks like.

Tested on x86_64-unknown-linux-gnu.  OK to commit?

-Nathan

	* expmed.h (NUM_MODE_VECTOR_INT): Define.
	(struct expmed_op_cheap, struct expmed_op_costs): New structures.
	(struct target_expmed): Convert x_mul_highpart_cost and
	x_mul_widen_cost fields to be indexed by integer modes.
	Convert x_sdiv_pow2_cheap and x_smod_pow2_cheap fields to be
	of type struct expmed_op_cheap.  Convert other cost fields to be
	of type struct_expmed_op_costs.
	(mul_widen_cost_ptr, mul_highpart_cost_ptr): Adjust for new
	indexing of respective fields.
	(expmed_op_cheap_ptr): New function.
	(sdiv_pow2_cheap_ptr, smod_pow2_cheap_ptr): Call it.
	(expmed_op_cost_ptr): New function.
	(add_cost_ptr, neg_cost_ptr, shift_cost_ptr, shiftadd_cost_ptr,
	shiftsub0_cost_ptr, shiftsub1_cost_ptr, mul_cost_ptr,
	sdiv_cost_ptr, udiv_cost_ptr): Call it.

---
 gcc/ChangeLog |   18 ++++++++
 gcc/expmed.h  |  124 +++++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 116 insertions(+), 26 deletions(-)
Richard Henderson - July 30, 2012, 10:36 p.m.
On 07/30/2012 02:05 PM, Nathan Froyd wrote:
> 	* expmed.h (NUM_MODE_VECTOR_INT): Define.
> 	(struct expmed_op_cheap, struct expmed_op_costs): New structures.
> 	(struct target_expmed): Convert x_mul_highpart_cost and
> 	x_mul_widen_cost fields to be indexed by integer modes.
> 	Convert x_sdiv_pow2_cheap and x_smod_pow2_cheap fields to be
> 	of type struct expmed_op_cheap.  Convert other cost fields to be
> 	of type struct_expmed_op_costs.
> 	(mul_widen_cost_ptr, mul_highpart_cost_ptr): Adjust for new
> 	indexing of respective fields.
> 	(expmed_op_cheap_ptr): New function.
> 	(sdiv_pow2_cheap_ptr, smod_pow2_cheap_ptr): Call it.
> 	(expmed_op_cost_ptr): New function.
> 	(add_cost_ptr, neg_cost_ptr, shift_cost_ptr, shiftadd_cost_ptr,
> 	shiftsub0_cost_ptr, shiftsub1_cost_ptr, mul_cost_ptr,
> 	sdiv_cost_ptr, udiv_cost_ptr): Call it.

Ok.


r~

Patch

diff --git a/gcc/expmed.h b/gcc/expmed.h
index 97e17f3..bde5cae 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -125,6 +125,23 @@  struct alg_hash_entry {
 #endif
 
 #define NUM_MODE_INT (MAX_MODE_INT - MIN_MODE_INT + 1)
+#define NUM_MODE_VECTOR_INT (MAX_MODE_VECTOR_INT - MIN_MODE_VECTOR_INT + 1)
+
+struct expmed_op_cheap {
+  /* Whether an operation is cheap in a given integer mode.  */
+  bool cheap_int[2][NUM_MODE_INT];
+
+  /* Whether an operation is cheap in a given vector integer mode.  */
+  bool cheap_vector_int[2][NUM_MODE_VECTOR_INT];
+};
+
+struct expmed_op_costs {
+  /* The cost of an operation in a given integer mode.  */
+  int int_cost[2][NUM_MODE_INT];
+
+  /* The cost of an operation in a given vector integer mode.  */
+  int vector_int_cost[2][NUM_MODE_VECTOR_INT];
+};
 
 /* Target-dependent globals.  */
 struct target_expmed {
@@ -140,23 +157,23 @@  struct target_expmed {
      powers of two, so don't use branches; emit the operation instead.
      Usually, this will mean that the MD file will emit non-branch
      sequences.  */
-  bool x_sdiv_pow2_cheap[2][NUM_MACHINE_MODES];
-  bool x_smod_pow2_cheap[2][NUM_MACHINE_MODES];
+  struct expmed_op_cheap x_sdiv_pow2_cheap;
+  struct expmed_op_cheap x_smod_pow2_cheap;
 
   /* Cost of various pieces of RTL.  Note that some of these are indexed by
      shift count and some by mode.  */
   int x_zero_cost[2];
-  int x_add_cost[2][NUM_MACHINE_MODES];
-  int x_neg_cost[2][NUM_MACHINE_MODES];
-  int x_shift_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD];
-  int x_shiftadd_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD];
-  int x_shiftsub0_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD];
-  int x_shiftsub1_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD];
-  int x_mul_cost[2][NUM_MACHINE_MODES];
-  int x_sdiv_cost[2][NUM_MACHINE_MODES];
-  int x_udiv_cost[2][NUM_MACHINE_MODES];
-  int x_mul_widen_cost[2][NUM_MACHINE_MODES];
-  int x_mul_highpart_cost[2][NUM_MACHINE_MODES];
+  struct expmed_op_costs x_add_cost;
+  struct expmed_op_costs x_neg_cost;
+  struct expmed_op_costs x_shift_cost[MAX_BITS_PER_WORD];
+  struct expmed_op_costs x_shiftadd_cost[MAX_BITS_PER_WORD];
+  struct expmed_op_costs x_shiftsub0_cost[MAX_BITS_PER_WORD];
+  struct expmed_op_costs x_shiftsub1_cost[MAX_BITS_PER_WORD];
+  struct expmed_op_costs x_mul_cost;
+  struct expmed_op_costs x_sdiv_cost;
+  struct expmed_op_costs x_udiv_cost;
+  int x_mul_widen_cost[2][NUM_MODE_INT];
+  int x_mul_highpart_cost[2][NUM_MODE_INT];
 
   /* Conversion costs are only defined between two scalar integer modes
      of different sizes.  The first machine mode is the destination mode,
@@ -195,12 +212,58 @@  set_alg_hash_used_p (bool usedp)
   this_target_expmed->x_alg_hash_used_p = usedp;
 }
 
+/* Return a pointer to a boolean contained in EOC indicating whether
+   a particular operation performed in MODE is cheap when optimizing
+   for SPEED.  */
+
+static inline bool *
+expmed_op_cheap_ptr (struct expmed_op_cheap *eoc, bool speed,
+		     enum machine_mode mode)
+{
+  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
+	      || GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
+
+  if (GET_MODE_CLASS (mode) == MODE_INT)
+    {
+      int idx = mode - MIN_MODE_INT;
+      return &eoc->cheap_int[speed][idx];
+    }
+  else
+    {
+      int idx = mode - MIN_MODE_VECTOR_INT;
+      return &eoc->cheap_vector_int[speed][idx];
+    }
+}
+
+/* Return a pointer to a cost contained in COSTS when a particular
+   operation is performed in MODE when optimizing for SPEED.  */
+
+static inline int *
+expmed_op_cost_ptr (struct expmed_op_costs *costs, bool speed,
+		    enum machine_mode mode)
+{
+  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
+	      || GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
+
+  if (GET_MODE_CLASS (mode) == MODE_INT)
+    {
+      int idx = mode - MIN_MODE_INT;
+      return &costs->int_cost[speed][idx];
+    }
+  else
+    {
+      int idx = mode - MIN_MODE_VECTOR_INT;
+      return &costs->vector_int_cost[speed][idx];
+    }
+}
+
 /* Subroutine of {set_,}sdiv_pow2_cheap.  Not to be used otherwise.  */
 
 static inline bool *
 sdiv_pow2_cheap_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_sdiv_pow2_cheap[speed][mode];
+  return expmed_op_cheap_ptr (&this_target_expmed->x_sdiv_pow2_cheap,
+			      speed, mode);
 }
 
 /* Set whether a signed division by a power of 2 is cheap in MODE
@@ -226,7 +289,8 @@  sdiv_pow2_cheap (bool speed, enum machine_mode mode)
 static inline bool *
 smod_pow2_cheap_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_smod_pow2_cheap[speed][mode];
+  return expmed_op_cheap_ptr (&this_target_expmed->x_smod_pow2_cheap,
+			      speed, mode);
 }
 
 /* Set whether a signed modulo by a power of 2 is CHEAP in MODE when
@@ -276,7 +340,7 @@  zero_cost (bool speed)
 static inline int *
 add_cost_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_add_cost[speed][mode];
+  return expmed_op_cost_ptr (&this_target_expmed->x_add_cost, speed, mode);
 }
 
 /* Set the COST of computing an add in MODE when optimizing for SPEED.  */
@@ -300,7 +364,7 @@  add_cost (bool speed, enum machine_mode mode)
 static inline int *
 neg_cost_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_neg_cost[speed][mode];
+  return expmed_op_cost_ptr (&this_target_expmed->x_neg_cost, speed, mode);
 }
 
 /* Set the COST of computing a negation in MODE when optimizing for SPEED.  */
@@ -325,7 +389,8 @@  neg_cost (bool speed, enum machine_mode mode)
 static inline int *
 shift_cost_ptr (bool speed, enum machine_mode mode, int bits)
 {
-  return &this_target_expmed->x_shift_cost[speed][mode][bits];
+  return expmed_op_cost_ptr (&this_target_expmed->x_shift_cost[bits],
+			     speed, mode);
 }
 
 /* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED.  */
@@ -350,7 +415,8 @@  shift_cost (bool speed, enum machine_mode mode, int bits)
 static inline int *
 shiftadd_cost_ptr (bool speed, enum machine_mode mode, int bits)
 {
-  return &this_target_expmed->x_shiftadd_cost[speed][mode][bits];
+  return expmed_op_cost_ptr (&this_target_expmed->x_shiftadd_cost[bits],
+			     speed, mode);
 }
 
 /* Set the COST of doing a shift in MODE by BITS followed by an add when
@@ -376,7 +442,8 @@  shiftadd_cost (bool speed, enum machine_mode mode, int bits)
 static inline int *
 shiftsub0_cost_ptr (bool speed, enum machine_mode mode, int bits)
 {
-  return &this_target_expmed->x_shiftsub0_cost[speed][mode][bits];
+  return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub0_cost[bits],
+			     speed, mode);
 }
 
 /* Set the COST of doing a shift in MODE by BITS and then subtracting a
@@ -402,7 +469,8 @@  shiftsub0_cost (bool speed, enum machine_mode mode, int bits)
 static inline int *
 shiftsub1_cost_ptr (bool speed, enum machine_mode mode, int bits)
 {
-  return &this_target_expmed->x_shiftsub1_cost[speed][mode][bits];
+  return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub1_cost[bits],
+			     speed, mode);
 }
 
 /* Set the COST of subtracting a shift in MODE by BITS from a value when
@@ -428,7 +496,7 @@  shiftsub1_cost (bool speed, enum machine_mode mode, int bits)
 static inline int *
 mul_cost_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_mul_cost[speed][mode];
+  return expmed_op_cost_ptr (&this_target_expmed->x_mul_cost, speed, mode);
 }
 
 /* Set the COST of doing a multiplication in MODE when optimizing for
@@ -454,7 +522,7 @@  mul_cost (bool speed, enum machine_mode mode)
 static inline int *
 sdiv_cost_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_sdiv_cost[speed][mode];
+  return expmed_op_cost_ptr (&this_target_expmed->x_sdiv_cost, speed, mode);
 }
 
 /* Set the COST of doing a signed division in MODE when optimizing
@@ -480,7 +548,7 @@  sdiv_cost (bool speed, enum machine_mode mode)
 static inline int *
 udiv_cost_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_udiv_cost[speed][mode];
+  return expmed_op_cost_ptr (&this_target_expmed->x_udiv_cost, speed, mode);
 }
 
 /* Set the COST of doing an unsigned division in MODE when optimizing
@@ -506,7 +574,9 @@  udiv_cost (bool speed, enum machine_mode mode)
 static inline int *
 mul_widen_cost_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_mul_widen_cost[speed][mode];
+  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+
+  return &this_target_expmed->x_mul_widen_cost[speed][mode - MIN_MODE_INT];
 }
 
 /* Set the COST for computing a widening multiplication in MODE when
@@ -532,7 +602,9 @@  mul_widen_cost (bool speed, enum machine_mode mode)
 static inline int *
 mul_highpart_cost_ptr (bool speed, enum machine_mode mode)
 {
-  return &this_target_expmed->x_mul_highpart_cost[speed][mode];
+  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+
+  return &this_target_expmed->x_mul_highpart_cost[speed][mode - MIN_MODE_INT];
 }
 
 /* Set the COST for computing the high part of a multiplication in MODE