131
|
1 /* A representation of vector permutation indices.
|
145
|
2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
|
131
|
3
|
|
4 This file is part of GCC.
|
|
5
|
|
6 GCC is free software; you can redistribute it and/or modify it under
|
|
7 the terms of the GNU General Public License as published by the Free
|
|
8 Software Foundation; either version 3, or (at your option) any later
|
|
9 version.
|
|
10
|
|
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with GCC; see the file COPYING3. If not see
|
|
18 <http://www.gnu.org/licenses/>. */
|
|
19
|
|
20 #ifndef GCC_VEC_PERN_INDICES_H
|
|
21 #define GCC_VEC_PERN_INDICES_H 1
|
|
22
|
|
23 #include "int-vector-builder.h"
|
|
24
|
|
25 /* A vector_builder for building constant permutation vectors.
|
|
26 The elements do not need to be clamped to a particular range
|
|
27 of input elements. */
|
|
28 typedef int_vector_builder<poly_int64> vec_perm_builder;
|
|
29
|
|
30 /* This class represents a constant permutation vector, such as that used
|
|
31 as the final operand to a VEC_PERM_EXPR.
|
|
32
|
|
33 Permutation vectors select indices modulo the number of input elements,
|
|
34 and the class canonicalizes each permutation vector for a particular
|
|
35 number of input vectors and for a particular number of elements per
|
|
36 input. For example, the gimple statements:
|
|
37
|
|
38 _1 = VEC_PERM_EXPR <a, a, { 0, 2, 4, 6, 0, 2, 4, 6 }>;
|
|
39 _2 = VEC_PERM_EXPR <a, a, { 0, 2, 4, 6, 8, 10, 12, 14 }>;
|
|
40 _3 = VEC_PERM_EXPR <a, a, { 0, 2, 20, 22, 24, 2, 4, 14 }>;
|
|
41
|
|
42 effectively have only a single vector input "a". If "a" has 8
|
|
43 elements, the indices select elements modulo 8, which makes all three
|
|
44 VEC_PERM_EXPRs equivalent. The canonical form is for the indices to be
|
|
45 in the range [0, number of input elements - 1], so the class treats the
|
|
46 second and third permutation vectors as though they had been the first.
|
|
47
|
|
48 The class copes with cases in which the input and output vectors have
|
|
49 different numbers of elements. */
|
|
50 class vec_perm_indices
|
|
51 {
|
|
52 typedef poly_int64 element_type;
|
|
53
|
|
54 public:
|
|
55 vec_perm_indices ();
|
|
56 vec_perm_indices (const vec_perm_builder &, unsigned int, poly_uint64);
|
|
57
|
|
58 void new_vector (const vec_perm_builder &, unsigned int, poly_uint64);
|
|
59 void new_expanded_vector (const vec_perm_indices &, unsigned int);
|
|
60 void rotate_inputs (int delta);
|
|
61
|
|
62 /* Return the underlying vector encoding. */
|
|
63 const vec_perm_builder &encoding () const { return m_encoding; }
|
|
64
|
|
65 /* Return the number of output elements. This is called length ()
|
|
66 so that we present a more vec-like interface. */
|
|
67 poly_uint64 length () const { return m_encoding.full_nelts (); }
|
|
68
|
|
69 /* Return the number of input vectors being permuted. */
|
|
70 unsigned int ninputs () const { return m_ninputs; }
|
|
71
|
|
72 /* Return the number of elements in each input vector. */
|
|
73 poly_uint64 nelts_per_input () const { return m_nelts_per_input; }
|
|
74
|
|
75 /* Return the total number of input elements. */
|
|
76 poly_uint64 input_nelts () const { return m_ninputs * m_nelts_per_input; }
|
|
77
|
|
78 element_type clamp (element_type) const;
|
|
79 element_type operator[] (unsigned int i) const;
|
|
80 bool series_p (unsigned int, unsigned int, element_type, element_type) const;
|
|
81 bool all_in_range_p (element_type, element_type) const;
|
|
82 bool all_from_input_p (unsigned int) const;
|
|
83
|
|
84 private:
|
|
85 vec_perm_indices (const vec_perm_indices &);
|
|
86
|
|
87 vec_perm_builder m_encoding;
|
|
88 unsigned int m_ninputs;
|
|
89 poly_uint64 m_nelts_per_input;
|
|
90 };
|
|
91
|
|
92 bool tree_to_vec_perm_builder (vec_perm_builder *, tree);
|
|
93 tree vec_perm_indices_to_tree (tree, const vec_perm_indices &);
|
|
94 rtx vec_perm_indices_to_rtx (machine_mode, const vec_perm_indices &);
|
|
95
|
|
96 inline
|
|
97 vec_perm_indices::vec_perm_indices ()
|
|
98 : m_ninputs (0),
|
|
99 m_nelts_per_input (0)
|
|
100 {
|
|
101 }
|
|
102
|
|
103 /* Construct a permutation vector that selects between NINPUTS vector
|
|
104 inputs that have NELTS_PER_INPUT elements each. Take the elements of
|
|
105 the new vector from ELEMENTS, clamping each one to be in range. */
|
|
106
|
|
107 inline
|
|
108 vec_perm_indices::vec_perm_indices (const vec_perm_builder &elements,
|
|
109 unsigned int ninputs,
|
|
110 poly_uint64 nelts_per_input)
|
|
111 {
|
|
112 new_vector (elements, ninputs, nelts_per_input);
|
|
113 }
|
|
114
|
|
115 /* Return the canonical value for permutation vector element ELT,
|
|
116 taking into account the current number of input elements. */
|
|
117
|
|
118 inline vec_perm_indices::element_type
|
|
119 vec_perm_indices::clamp (element_type elt) const
|
|
120 {
|
|
121 element_type limit = input_nelts (), elem_within_input;
|
|
122 HOST_WIDE_INT input;
|
|
123 if (!can_div_trunc_p (elt, limit, &input, &elem_within_input))
|
|
124 return elt;
|
|
125
|
|
126 /* Treat negative elements as counting from the end. This only matters
|
|
127 if the vector size is not a power of 2. */
|
|
128 if (known_lt (elem_within_input, 0))
|
|
129 return elem_within_input + limit;
|
|
130
|
|
131 return elem_within_input;
|
|
132 }
|
|
133
|
|
134 /* Return the value of vector element I, which might or might not be
|
|
135 explicitly encoded. */
|
|
136
|
|
137 inline vec_perm_indices::element_type
|
|
138 vec_perm_indices::operator[] (unsigned int i) const
|
|
139 {
|
|
140 return clamp (m_encoding.elt (i));
|
|
141 }
|
|
142
|
|
143 /* Return true if the permutation vector only selects elements from
|
|
144 input I. */
|
|
145
|
|
146 inline bool
|
|
147 vec_perm_indices::all_from_input_p (unsigned int i) const
|
|
148 {
|
|
149 return all_in_range_p (i * m_nelts_per_input, m_nelts_per_input);
|
|
150 }
|
|
151
|
|
152 #endif
|