This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[07/nn] Add unique CONSTs
- From: Richard Sandiford <richard dot sandiford at linaro dot org>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 23 Oct 2017 12:21:57 +0100
- Subject: [07/nn] Add unique CONSTs
- Authentication-results: sourceware.org; auth=none
- References: <87wp3mxgir.fsf@linaro.org>
This patch adds a way of treating certain kinds of CONST as unique,
so that pointer equality is equivalent to value equality. For now it
is restricted to VEC_DUPLICATE and VEC_SERIES, although the code to
generate them remains in the else arm of an "if (1)" until a later
patch.
This is needed so that (const (vec_duplicate xx)) can used as the
CONSTxx_RTX of a variable-length vector.
2017-10-23 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* rtl.h (unique_const_p): New function.
(gen_rtx_CONST): Declare.
* emit-rtl.c (const_hasher): New struct.
(const_htab): New variable.
(init_emit_once): Initialize it.
(const_hasher::hash, const_hasher::equal): New functions.
(gen_rtx_CONST): New function.
(spare_vec_duplicate, spare_vec_series): New variables.
(gen_const_vec_duplicate_1): Add code for use (const (vec_duplicate)),
but disable it for now.
(gen_const_vec_series): Likewise (const (vec_series)).
* gengenrtl.c (special_rtx): Return true for CONST.
* rtl.c (shared_const_p): Return true if unique_const_p.
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h 2017-10-23 11:41:41.549050496 +0100
+++ gcc/rtl.h 2017-10-23 11:42:47.297720974 +0100
@@ -2861,6 +2861,23 @@ vec_series_p (const_rtx x, rtx *base_out
return const_vec_series_p (x, base_out, step_out);
}
+/* Return true if there should only ever be one instance of (const X),
+ so that constants of this type can be compared using pointer equality. */
+
+inline bool
+unique_const_p (const_rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case VEC_DUPLICATE:
+ case VEC_SERIES:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/* Return the unpromoted (outer) mode of SUBREG_PROMOTED_VAR_P subreg X. */
inline scalar_int_mode
@@ -3542,6 +3559,7 @@ extern rtx_insn_list *gen_rtx_INSN_LIST
gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
basic_block bb, rtx pattern, int location, int code,
rtx reg_notes);
+extern rtx gen_rtx_CONST (machine_mode, rtx);
extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c 2017-10-23 11:41:41.548050496 +0100
+++ gcc/emit-rtl.c 2017-10-23 11:42:47.296720974 +0100
@@ -175,6 +175,15 @@ struct const_fixed_hasher : ggc_cache_pt
static GTY ((cache)) hash_table<const_fixed_hasher> *const_fixed_htab;
+/* A hash table storing unique CONSTs. */
+struct const_hasher : ggc_cache_ptr_hash<rtx_def>
+{
+ static hashval_t hash (rtx x);
+ static bool equal (rtx x, rtx y);
+};
+
+static GTY ((cache)) hash_table<const_hasher> *const_htab;
+
#define cur_insn_uid (crtl->emit.x_cur_insn_uid)
#define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid)
#define first_label_num (crtl->emit.x_first_label_num)
@@ -310,6 +319,28 @@ const_fixed_hasher::equal (rtx x, rtx y)
return fixed_identical (CONST_FIXED_VALUE (a), CONST_FIXED_VALUE (b));
}
+/* Returns a hash code for X (which is either an existing unique CONST
+ or an operand to gen_rtx_CONST). */
+
+hashval_t
+const_hasher::hash (rtx x)
+{
+ if (GET_CODE (x) == CONST)
+ x = XEXP (x, 0);
+
+ int do_not_record_p = 0;
+ return hash_rtx (x, GET_MODE (x), &do_not_record_p, NULL, false);
+}
+
+/* Returns true if the operand of unique CONST X is equal to Y. */
+
+bool
+const_hasher::equal (rtx x, rtx y)
+{
+ gcc_checking_assert (GET_CODE (x) == CONST);
+ return rtx_equal_p (XEXP (x, 0), y);
+}
+
/* Return true if the given memory attributes are equal. */
bool
@@ -5756,16 +5787,55 @@ init_emit (void)
#endif
}
+rtx
+gen_rtx_CONST (machine_mode mode, rtx val)
+{
+ if (unique_const_p (val))
+ {
+ /* Look up the CONST in the hash table. */
+ rtx *slot = const_htab->find_slot (val, INSERT);
+ if (*slot == 0)
+ *slot = gen_rtx_raw_CONST (mode, val);
+ return *slot;
+ }
+
+ return gen_rtx_raw_CONST (mode, val);
+}
+
+/* Temporary rtx used by gen_const_vec_duplicate_1. */
+static GTY((deletable)) rtx spare_vec_duplicate;
+
/* Like gen_const_vec_duplicate, but ignore const_tiny_rtx. */
static rtx
gen_const_vec_duplicate_1 (machine_mode mode, rtx el)
{
int nunits = GET_MODE_NUNITS (mode);
- rtvec v = rtvec_alloc (nunits);
- for (int i = 0; i < nunits; ++i)
- RTVEC_ELT (v, i) = el;
- return gen_rtx_raw_CONST_VECTOR (mode, v);
+ if (1)
+ {
+ rtvec v = rtvec_alloc (nunits);
+
+ for (int i = 0; i < nunits; ++i)
+ RTVEC_ELT (v, i) = el;
+
+ return gen_rtx_raw_CONST_VECTOR (mode, v);
+ }
+ else
+ {
+ if (spare_vec_duplicate)
+ {
+ PUT_MODE (spare_vec_duplicate, mode);
+ XEXP (spare_vec_duplicate, 0) = el;
+ }
+ else
+ spare_vec_duplicate = gen_rtx_VEC_DUPLICATE (mode, el);
+
+ rtx res = gen_rtx_CONST (mode, spare_vec_duplicate);
+ if (XEXP (res, 0) == spare_vec_duplicate)
+ spare_vec_duplicate = NULL_RTX;
+
+ return res;
+ }
}
/* Generate a vector constant of mode MODE in which every element has
@@ -5827,6 +5897,9 @@ const_vec_series_p_1 (const_rtx x, rtx *
return true;
}
+/* Temporary rtx used by gen_const_vec_series. */
+static GTY((deletable)) rtx spare_vec_series;
+
/* Generate a vector constant of mode MODE in which element I has
the value BASE + I * STEP. */
@@ -5836,13 +5909,33 @@ gen_const_vec_series (machine_mode mode,
gcc_assert (CONSTANT_P (base) && CONSTANT_P (step));
int nunits = GET_MODE_NUNITS (mode);
- rtvec v = rtvec_alloc (nunits);
- scalar_mode inner_mode = GET_MODE_INNER (mode);
- RTVEC_ELT (v, 0) = base;
- for (int i = 1; i < nunits; ++i)
- RTVEC_ELT (v, i) = simplify_gen_binary (PLUS, inner_mode,
- RTVEC_ELT (v, i - 1), step);
- return gen_rtx_raw_CONST_VECTOR (mode, v);
+ if (1)
+ {
+ rtvec v = rtvec_alloc (nunits);
+ scalar_mode inner_mode = GET_MODE_INNER (mode);
+ RTVEC_ELT (v, 0) = base;
+ for (int i = 1; i < nunits; ++i)
+ RTVEC_ELT (v, i) = simplify_gen_binary (PLUS, inner_mode,
+ RTVEC_ELT (v, i - 1), step);
+ return gen_rtx_raw_CONST_VECTOR (mode, v);
+ }
+ else
+ {
+ if (spare_vec_series)
+ {
+ PUT_MODE (spare_vec_series, mode);
+ XEXP (spare_vec_series, 0) = base;
+ XEXP (spare_vec_series, 1) = step;
+ }
+ else
+ spare_vec_series = gen_rtx_VEC_SERIES (mode, base, step);
+
+ rtx res = gen_rtx_CONST (mode, spare_vec_series);
+ if (XEXP (res, 0) == spare_vec_series)
+ spare_vec_series = NULL_RTX;
+
+ return res;
+ }
}
/* Generate a vector of mode MODE in which element I has the value
@@ -6000,6 +6093,8 @@ init_emit_once (void)
reg_attrs_htab = hash_table<reg_attr_hasher>::create_ggc (37);
+ const_htab = hash_table<const_hasher>::create_ggc (37);
+
#ifdef INIT_EXPANDERS
/* This is to initialize {init|mark|free}_machine_status before the first
call to push_function_context_to. This is needed by the Chill front
Index: gcc/gengenrtl.c
===================================================================
--- gcc/gengenrtl.c 2017-08-03 10:40:53.029491180 +0100
+++ gcc/gengenrtl.c 2017-10-23 11:42:47.297720974 +0100
@@ -143,7 +143,8 @@ special_rtx (int idx)
|| strcmp (defs[idx].enumname, "CC0") == 0
|| strcmp (defs[idx].enumname, "RETURN") == 0
|| strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
- || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
+ || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0
+ || strcmp (defs[idx].enumname, "CONST") == 0);
}
/* Return nonzero if the RTL code given by index IDX is one that we should
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c 2017-08-03 10:40:55.646123304 +0100
+++ gcc/rtl.c 2017-10-23 11:42:47.297720974 +0100
@@ -252,6 +252,9 @@ shared_const_p (const_rtx orig)
{
gcc_assert (GET_CODE (orig) == CONST);
+ if (unique_const_p (XEXP (orig, 0)))
+ return true;
+
/* CONST can be shared if it contains a SYMBOL_REF. If it contains
a LABEL_REF, it isn't sharable. */
return (GET_CODE (XEXP (orig, 0)) == PLUS