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(-)
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