diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-12-20 12:51:36 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-12-20 12:51:36 +0000 |
commit | 0c12fc9b2d605cf323cfdab28a972d86398e71a1 (patch) | |
tree | ca58581589b8fa244d77652a9a9c06f5293a8bea /gcc/rtl.h | |
parent | abd3c800109b95f09af3b3f1a7a43d9b7631f21c (diff) | |
download | gcc-0c12fc9b2d605cf323cfdab28a972d86398e71a1.zip gcc-0c12fc9b2d605cf323cfdab28a972d86398e71a1.tar.gz gcc-0c12fc9b2d605cf323cfdab28a972d86398e71a1.tar.bz2 |
poly_int: rtx constants
This patch adds an rtl representation of poly_int values.
There were three possible ways of doing this:
(1) Add a new rtl code for the poly_ints themselves and store the
coefficients as trailing wide_ints. This would give constants like:
(const_poly_int [c0 c1 ... cn])
The runtime value would be:
c0 + c1 * x1 + ... + cn * xn
(2) Like (1), but use rtxes for the coefficients. This would give
constants like:
(const_poly_int [(const_int c0)
(const_int c1)
...
(const_int cn)])
although the coefficients could be const_wide_ints instead
of const_ints where appropriate.
(3) Add a new rtl code for the polynomial indeterminates,
then use them in const wrappers. A constant like c0 + c1 * x1
would then look like:
(const:M (plus:M (mult:M (const_param:M x1)
(const_int c1))
(const_int c0)))
There didn't seem to be that much to choose between them. The main
advantage of (1) is that it's a more efficient representation and
that we can refer to the cofficients directly as wide_int_storage.
2017-12-20 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* doc/rtl.texi (const_poly_int): Document. Also document the
rtl sharing behavior.
* gengenrtl.c (excluded_rtx): Return true for CONST_POLY_INT.
* rtl.h (const_poly_int_def): New struct.
(rtx_def::u): Add a cpi field.
(CASE_CONST_UNIQUE, CASE_CONST_ANY): Add CONST_POLY_INT.
(CONST_POLY_INT_P, CONST_POLY_INT_COEFFS): New macros.
(wi::rtx_to_poly_wide_ref): New typedef
(const_poly_int_value, wi::to_poly_wide, rtx_to_poly_int64)
(poly_int_rtx_p): New functions.
(trunc_int_for_mode): Declare a poly_int64 version.
(plus_constant): Take a poly_int64 instead of a HOST_WIDE_INT.
(immed_wide_int_const): Take a poly_wide_int_ref rather than
a wide_int_ref.
(strip_offset): Declare.
(strip_offset_and_add): New function.
* rtl.def (CONST_POLY_INT): New rtx code.
* rtl.c (rtx_size): Handle CONST_POLY_INT.
(shared_const_p): Use poly_int_rtx_p.
* emit-rtl.h (gen_int_mode): Take a poly_int64 instead of a
HOST_WIDE_INT.
(gen_int_shift_amount): Likewise.
* emit-rtl.c (const_poly_int_hasher): New class.
(const_poly_int_htab): New variable.
(init_emit_once): Initialize it when NUM_POLY_INT_COEFFS > 1.
(const_poly_int_hasher::hash): New function.
(const_poly_int_hasher::equal): Likewise.
(gen_int_mode): Take a poly_int64 instead of a HOST_WIDE_INT.
(immed_wide_int_const): Rename to...
(immed_wide_int_const_1): ...this and make static.
(immed_wide_int_const): New function, taking a poly_wide_int_ref
instead of a wide_int_ref.
(gen_int_shift_amount): Take a poly_int64 instead of a HOST_WIDE_INT.
(gen_lowpart_common): Handle CONST_POLY_INT.
* cse.c (hash_rtx_cb, equiv_constant): Likewise.
* cselib.c (cselib_hash_rtx): Likewise.
* dwarf2out.c (const_ok_for_output_1): Likewise.
* expr.c (convert_modes): Likewise.
* print-rtl.c (rtx_writer::print_rtx, print_value): Likewise.
* rtlhash.c (add_rtx): Likewise.
* explow.c (trunc_int_for_mode): Add a poly_int64 version.
(plus_constant): Take a poly_int64 instead of a HOST_WIDE_INT.
Handle existing CONST_POLY_INT rtxes.
* expmed.h (expand_shift): Take a poly_int64 instead of a
HOST_WIDE_INT.
* expmed.c (expand_shift): Likewise.
* rtlanal.c (strip_offset): New function.
(commutative_operand_precedence): Give CONST_POLY_INT the same
precedence as CONST_DOUBLE and put CONST_WIDE_INT between that
and CONST_INT.
* rtl-tests.c (const_poly_int_tests): New struct.
(rtl_tests_c_tests): Use it.
* simplify-rtx.c (simplify_const_unary_operation): Handle
CONST_POLY_INT.
(simplify_const_binary_operation): Likewise.
(simplify_binary_operation_1): Fold additions of symbolic constants
and CONST_POLY_INTs.
(simplify_subreg): Handle extensions and truncations of
CONST_POLY_INTs.
(simplify_const_poly_int_tests): New struct.
(simplify_rtx_c_tests): Use it.
* wide-int.h (storage_ref): Add default constructor.
(wide_int_ref_storage): Likewise.
(trailing_wide_ints): Use GTY((user)).
(trailing_wide_ints::operator[]): Add a const version.
(trailing_wide_ints::get_precision): New function.
(trailing_wide_ints::extra_size): Likewise.
Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r255862
Diffstat (limited to 'gcc/rtl.h')
-rw-r--r-- | gcc/rtl.h | 119 |
1 files changed, 115 insertions, 4 deletions
@@ -280,6 +280,10 @@ struct GTY((variable_size)) hwivec_def { #define CWI_PUT_NUM_ELEM(RTX, NUM) \ (RTL_FLAG_CHECK1("CWI_PUT_NUM_ELEM", (RTX), CONST_WIDE_INT)->u2.num_elem = (NUM)) +struct GTY((variable_size)) const_poly_int_def { + trailing_wide_ints<NUM_POLY_INT_COEFFS> coeffs; +}; + /* RTL expression ("rtx"). */ /* The GTY "desc" and "tag" options below are a kludge: we need a desc @@ -424,6 +428,7 @@ struct GTY((desc("0"), tag("0"), struct real_value rv; struct fixed_value fv; struct hwivec_def hwiv; + struct const_poly_int_def cpi; } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u; }; @@ -734,6 +739,7 @@ struct GTY(()) rtvec_def { #define CASE_CONST_UNIQUE \ case CONST_INT: \ case CONST_WIDE_INT: \ + case CONST_POLY_INT: \ case CONST_DOUBLE: \ case CONST_FIXED @@ -741,6 +747,7 @@ struct GTY(()) rtvec_def { #define CASE_CONST_ANY \ case CONST_INT: \ case CONST_WIDE_INT: \ + case CONST_POLY_INT: \ case CONST_DOUBLE: \ case CONST_FIXED: \ case CONST_VECTOR @@ -773,6 +780,11 @@ struct GTY(()) rtvec_def { /* Predicate yielding nonzero iff X is an rtx for a constant integer. */ #define CONST_WIDE_INT_P(X) (GET_CODE (X) == CONST_WIDE_INT) +/* Predicate yielding nonzero iff X is an rtx for a polynomial constant + integer. */ +#define CONST_POLY_INT_P(X) \ + (NUM_POLY_INT_COEFFS > 1 && GET_CODE (X) == CONST_POLY_INT) + /* Predicate yielding nonzero iff X is an rtx for a constant fixed-point. */ #define CONST_FIXED_P(X) (GET_CODE (X) == CONST_FIXED) @@ -1914,6 +1926,12 @@ set_regno_raw (rtx x, unsigned int regno, unsigned int nregs) #define CONST_WIDE_INT_NUNITS(RTX) CWI_GET_NUM_ELEM (RTX) #define CONST_WIDE_INT_ELT(RTX, N) CWI_ELT (RTX, N) +/* For a CONST_POLY_INT, CONST_POLY_INT_COEFFS gives access to the + individual coefficients, in the form of a trailing_wide_ints structure. */ +#define CONST_POLY_INT_COEFFS(RTX) \ + (RTL_FLAG_CHECK1("CONST_POLY_INT_COEFFS", (RTX), \ + CONST_POLY_INT)->u.cpi.coeffs) + /* For a CONST_DOUBLE: #if TARGET_SUPPORTS_WIDE_INT == 0 For a VOIDmode, there are two integers CONST_DOUBLE_LOW is the @@ -2227,6 +2245,84 @@ wi::max_value (machine_mode mode, signop sgn) return max_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn); } +namespace wi +{ + typedef poly_int<NUM_POLY_INT_COEFFS, + generic_wide_int <wide_int_ref_storage <false, false> > > + rtx_to_poly_wide_ref; + rtx_to_poly_wide_ref to_poly_wide (const_rtx, machine_mode); +} + +/* Return the value of a CONST_POLY_INT in its native precision. */ + +inline wi::rtx_to_poly_wide_ref +const_poly_int_value (const_rtx x) +{ + poly_int<NUM_POLY_INT_COEFFS, WIDE_INT_REF_FOR (wide_int)> res; + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + res.coeffs[i] = CONST_POLY_INT_COEFFS (x)[i]; + return res; +} + +/* Return true if X is a scalar integer or a CONST_POLY_INT. The value + can then be extracted using wi::to_poly_wide. */ + +inline bool +poly_int_rtx_p (const_rtx x) +{ + return CONST_SCALAR_INT_P (x) || CONST_POLY_INT_P (x); +} + +/* Access X (which satisfies poly_int_rtx_p) as a poly_wide_int. + MODE is the mode of X. */ + +inline wi::rtx_to_poly_wide_ref +wi::to_poly_wide (const_rtx x, machine_mode mode) +{ + if (CONST_POLY_INT_P (x)) + return const_poly_int_value (x); + return rtx_mode_t (const_cast<rtx> (x), mode); +} + +/* Return the value of X as a poly_int64. */ + +inline poly_int64 +rtx_to_poly_int64 (const_rtx x) +{ + if (CONST_POLY_INT_P (x)) + { + poly_int64 res; + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + res.coeffs[i] = CONST_POLY_INT_COEFFS (x)[i].to_shwi (); + return res; + } + return INTVAL (x); +} + +/* Return true if arbitrary value X is an integer constant that can + be represented as a poly_int64. Store the value in *RES if so, + otherwise leave it unmodified. */ + +inline bool +poly_int_rtx_p (const_rtx x, poly_int64_pod *res) +{ + if (CONST_INT_P (x)) + { + *res = INTVAL (x); + return true; + } + if (CONST_POLY_INT_P (x)) + { + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + if (!wi::fits_shwi_p (CONST_POLY_INT_COEFFS (x)[i])) + return false; + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + res->coeffs[i] = CONST_POLY_INT_COEFFS (x)[i].to_shwi (); + return true; + } + return false; +} + extern void init_rtlanal (void); extern int rtx_cost (rtx, machine_mode, enum rtx_code, int, bool); extern int address_cost (rtx, machine_mode, addr_space_t, bool); @@ -2764,7 +2860,8 @@ get_full_set_src_cost (rtx x, machine_mode mode, struct full_rtx_costs *c) /* In explow.c */ extern HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT, machine_mode); -extern rtx plus_constant (machine_mode, rtx, HOST_WIDE_INT, bool = false); +extern poly_int64 trunc_int_for_mode (poly_int64, machine_mode); +extern rtx plus_constant (machine_mode, rtx, poly_int64, bool = false); extern HOST_WIDE_INT get_stack_check_protect (void); /* In rtl.c */ @@ -3058,13 +3155,11 @@ extern void end_sequence (void); extern double_int rtx_to_double_int (const_rtx); #endif extern void cwi_output_hex (FILE *, const_rtx); -#ifndef GENERATOR_FILE -extern rtx immed_wide_int_const (const wide_int_ref &, machine_mode); -#endif #if TARGET_SUPPORTS_WIDE_INT == 0 extern rtx immed_double_const (HOST_WIDE_INT, HOST_WIDE_INT, machine_mode); #endif +extern rtx immed_wide_int_const (const poly_wide_int_ref &, machine_mode); /* In varasm.c */ extern rtx force_const_mem (machine_mode, rtx); @@ -3252,6 +3347,7 @@ extern HOST_WIDE_INT get_integer_term (const_rtx); extern rtx get_related_value (const_rtx); extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT); extern void split_const (rtx, rtx *, rtx *); +extern rtx strip_offset (rtx, poly_int64_pod *); extern bool unsigned_reg_p (rtx); extern int reg_mentioned_p (const_rtx, const_rtx); extern int count_occurrences (const_rtx, const_rtx, int); @@ -4185,6 +4281,21 @@ load_extend_op (machine_mode mode) return UNKNOWN; } +/* If X is a PLUS of a base and a constant offset, add the constant to *OFFSET + and return the base. Return X otherwise. */ + +inline rtx +strip_offset_and_add (rtx x, poly_int64_pod *offset) +{ + if (GET_CODE (x) == PLUS) + { + poly_int64 suboffset; + x = strip_offset (x, &suboffset); + *offset += suboffset; + } + return x; +} + /* gtype-desc.c. */ extern void gt_ggc_mx (rtx &); extern void gt_pch_nx (rtx &); |