From 06ec586d2c384ba016c784de3279f3770d9f399d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 1 Nov 2017 10:37:03 +0000 Subject: [PATCH] Allow vector CONSTs This patch allows (const ...) wrappers to be used for rtx vector constants, as an alternative to const_vector. This is useful for SVE, where the number of elements isn't known until runtime. It could also be useful in future for fixed-length vectors, to reduce the amount of memory needed to represent simple constants with high element counts. However, one nice thing about keeping it restricted to variable-length vectors is that there is never any need to handle combinations of (const ...) and CONST_VECTOR. 2017-11-01 Richard Sandiford Alan Hayward David Sherwood gcc/ * doc/rtl.texi (const): Update description of address constants. Say that vector constants are allowed too. * common.md (E, F): Use CONSTANT_P instead of checking for CONST_VECTOR. * emit-rtl.c (gen_lowpart_common): Use const_vec_p instead of checking for CONST_VECTOR. * expmed.c (make_tree): Use build_vector_from_val for a CONST VEC_DUPLICATE. * expr.c (expand_expr_real_2): Check for vector modes instead of checking for CONST_VECTOR. * rtl.h (const_vec_p): New function. (const_vec_duplicate_p): Check for a CONST VEC_DUPLICATE. (unwrap_const_vec_duplicate): Handle them here too. Co-Authored-By: Alan Hayward Co-Authored-By: David Sherwood From-SVN: r254296 --- gcc/ChangeLog | 18 ++++++++++++++++++ gcc/common.md | 4 ++-- gcc/doc/rtl.texi | 19 +++++++++++-------- gcc/emit-rtl.c | 2 +- gcc/expmed.c | 10 +++++++++- gcc/expr.c | 2 +- gcc/rtl.h | 25 +++++++++++++++++++++---- 7 files changed, 63 insertions(+), 17 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0dde53b..0a30e38 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,22 @@ 2017-11-01 Richard Sandiford + Alan Hayward + David Sherwood + + * doc/rtl.texi (const): Update description of address constants. + Say that vector constants are allowed too. + * common.md (E, F): Use CONSTANT_P instead of checking for + CONST_VECTOR. + * emit-rtl.c (gen_lowpart_common): Use const_vec_p instead of + checking for CONST_VECTOR. + * expmed.c (make_tree): Use build_vector_from_val for a CONST + VEC_DUPLICATE. + * expr.c (expand_expr_real_2): Check for vector modes instead + of checking for CONST_VECTOR. + * rtl.h (const_vec_p): New function. + (const_vec_duplicate_p): Check for a CONST VEC_DUPLICATE. + (unwrap_const_vec_duplicate): Handle them here too. + +2017-11-01 Richard Sandiford David Malcolm Alan Hayward David Sherwood diff --git a/gcc/common.md b/gcc/common.md index dd28a7b..22c010f 100644 --- a/gcc/common.md +++ b/gcc/common.md @@ -80,14 +80,14 @@ (define_constraint "E" "Matches a floating-point constant." (ior (match_test "CONST_DOUBLE_AS_FLOAT_P (op)") - (match_test "GET_CODE (op) == CONST_VECTOR + (match_test "CONSTANT_P (op) && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT"))) ;; There is no longer a distinction between "E" and "F". (define_constraint "F" "Matches a floating-point constant." (ior (match_test "CONST_DOUBLE_AS_FLOAT_P (op)") - (match_test "GET_CODE (op) == CONST_VECTOR + (match_test "CONSTANT_P (op) && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT"))) (define_constraint "X" diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 7f67685..0a5623e 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -1667,14 +1667,17 @@ Usually that is the only mode for which a label is directly valid. @findex const @item (const:@var{m} @var{exp}) -Represents a constant that is the result of an assembly-time -arithmetic computation. The operand, @var{exp}, is an expression that -contains only constants (@code{const_int}, @code{symbol_ref} and -@code{label_ref} expressions) combined with @code{plus} and -@code{minus}. However, not all combinations are valid, since the -assembler cannot do arbitrary arithmetic on relocatable symbols. - -@var{m} should be @code{Pmode}. +Wraps an rtx computation @var{exp} whose inputs and result do not +change during the execution of a thread. There are two valid uses. +The first is to represent a global or thread-local address calculation. +In this case @var{exp} should contain @code{const_int}, +@code{symbol_ref}, @code{label_ref} or @code{unspec} expressions, +combined with @code{plus} and @code{minus}. Any such @code{unspec}s +are target-specific and typically represent some form of relocation +operator. @var{m} should be a valid address mode. + +The second use of @code{const} is to wrap a vector operation. +In this case @var{exp} must be a @code{vec_duplicate} expression. @findex high @item (high:@var{m} @var{exp}) diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 4df550f..10554ac 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -1470,7 +1470,7 @@ gen_lowpart_common (machine_mode mode, rtx x) return gen_rtx_fmt_e (GET_CODE (x), int_mode, XEXP (x, 0)); } else if (GET_CODE (x) == SUBREG || REG_P (x) - || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR + || GET_CODE (x) == CONCAT || const_vec_p (x) || CONST_DOUBLE_AS_FLOAT_P (x) || CONST_SCALAR_INT_P (x)) return lowpart_subreg (mode, x, innermode); diff --git a/gcc/expmed.c b/gcc/expmed.c index eeb25d3..da9a0a2 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -5244,7 +5244,15 @@ make_tree (tree type, rtx x) return fold_convert (type, make_tree (t, XEXP (x, 0))); case CONST: - return make_tree (type, XEXP (x, 0)); + { + rtx op = XEXP (x, 0); + if (GET_CODE (op) == VEC_DUPLICATE) + { + tree elt_tree = make_tree (TREE_TYPE (type), XEXP (op, 0)); + return build_vector_from_val (type, elt_tree); + } + return make_tree (type, op); + } case SYMBOL_REF: t = SYMBOL_REF_DECL (x); diff --git a/gcc/expr.c b/gcc/expr.c index 496d492..cb294bb 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -9429,7 +9429,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, /* Careful here: if the target doesn't support integral vector modes, a constant selection vector could wind up smooshed into a normal integral constant. */ - if (CONSTANT_P (op2) && GET_CODE (op2) != CONST_VECTOR) + if (CONSTANT_P (op2) && !VECTOR_MODE_P (GET_MODE (op2))) { tree sel_type = TREE_TYPE (treeop2); machine_mode vmode diff --git a/gcc/rtl.h b/gcc/rtl.h index b01e306..373f8a2 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2749,12 +2749,22 @@ extern rtx shallow_copy_rtx (const_rtx CXX_MEM_STAT_INFO); extern int rtx_equal_p (const_rtx, const_rtx); extern bool rtvec_all_equal_p (const_rtvec); +/* Return true if X is some form of vector constant. */ + +inline bool +const_vec_p (const_rtx x) +{ + return VECTOR_MODE_P (GET_MODE (x)) && CONSTANT_P (x); +} + /* Return true if X is a vector constant with a duplicated element value. */ inline bool const_vec_duplicate_p (const_rtx x) { - return GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)); + return ((GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0))) + || (GET_CODE (x) == CONST + && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)); } /* Return true if X is a vector constant with a duplicated element value. @@ -2764,11 +2774,16 @@ template inline bool const_vec_duplicate_p (T x, T *elt) { - if (const_vec_duplicate_p (x)) + if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0))) { *elt = CONST_VECTOR_ELT (x, 0); return true; } + if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE) + { + *elt = XEXP (XEXP (x, 0), 0); + return true; + } return false; } @@ -2794,8 +2809,10 @@ template inline T unwrap_const_vec_duplicate (T x) { - if (const_vec_duplicate_p (x)) - x = CONST_VECTOR_ELT (x, 0); + if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0))) + return CONST_VECTOR_ELT (x, 0); + if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE) + return XEXP (XEXP (x, 0), 0); return x; } -- 2.7.4