131
|
1 /* A class for building vector tree constants.
|
|
2 Copyright (C) 2017-2018 Free Software Foundation, Inc.
|
|
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 #include "config.h"
|
|
21 #include "system.h"
|
|
22 #include "coretypes.h"
|
|
23 #include "tree.h"
|
|
24 #include "fold-const.h"
|
|
25 #include "tree-vector-builder.h"
|
|
26
|
|
27 /* Try to start building a new vector of type TYPE that holds the result of
|
|
28 a unary operation on VECTOR_CST T. ALLOW_STEPPED_P is true if the
|
|
29 operation can handle stepped encodings directly, without having to
|
|
30 expand the full sequence.
|
|
31
|
|
32 Return true if the operation is possible, which it always is when
|
|
33 ALLOW_STEPPED_P is true. Leave the builder unchanged otherwise. */
|
|
34
|
|
35 bool
|
|
36 tree_vector_builder::new_unary_operation (tree type, tree t,
|
|
37 bool allow_stepped_p)
|
|
38 {
|
|
39 poly_uint64 full_nelts = TYPE_VECTOR_SUBPARTS (type);
|
|
40 gcc_assert (known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t))));
|
|
41 unsigned int npatterns = VECTOR_CST_NPATTERNS (t);
|
|
42 unsigned int nelts_per_pattern = VECTOR_CST_NELTS_PER_PATTERN (t);
|
|
43 if (!allow_stepped_p && nelts_per_pattern > 2)
|
|
44 {
|
|
45 if (!full_nelts.is_constant ())
|
|
46 return false;
|
|
47 npatterns = full_nelts.to_constant ();
|
|
48 nelts_per_pattern = 1;
|
|
49 }
|
|
50 new_vector (type, npatterns, nelts_per_pattern);
|
|
51 return true;
|
|
52 }
|
|
53
|
|
54 /* Try to start building a new vector of type TYPE that holds the result of
|
|
55 a binary operation on VECTOR_CSTs T1 and T2. ALLOW_STEPPED_P is true if
|
|
56 the operation can handle stepped encodings directly, without having to
|
|
57 expand the full sequence.
|
|
58
|
|
59 Return true if the operation is possible. Leave the builder unchanged
|
|
60 otherwise. */
|
|
61
|
|
62 bool
|
|
63 tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2,
|
|
64 bool allow_stepped_p)
|
|
65 {
|
|
66 poly_uint64 full_nelts = TYPE_VECTOR_SUBPARTS (type);
|
|
67 gcc_assert (known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1)))
|
|
68 && known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))));
|
|
69 /* Conceptually we split the patterns in T1 and T2 until we have
|
|
70 an equal number for both. Each split pattern requires the same
|
|
71 number of elements per pattern as the original. E.g. splitting:
|
|
72
|
|
73 { 1, 2, 3, ... }
|
|
74
|
|
75 into two gives:
|
|
76
|
|
77 { 1, 3, 5, ... }
|
|
78 { 2, 4, 6, ... }
|
|
79
|
|
80 while splitting:
|
|
81
|
|
82 { 1, 0, ... }
|
|
83
|
|
84 into two gives:
|
|
85
|
|
86 { 1, 0, ... }
|
|
87 { 0, 0, ... }. */
|
|
88 unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
|
|
89 VECTOR_CST_NPATTERNS (t2));
|
|
90 unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
|
|
91 VECTOR_CST_NELTS_PER_PATTERN (t2));
|
|
92 if (!allow_stepped_p && nelts_per_pattern > 2)
|
|
93 {
|
|
94 if (!full_nelts.is_constant ())
|
|
95 return false;
|
|
96 npatterns = full_nelts.to_constant ();
|
|
97 nelts_per_pattern = 1;
|
|
98 }
|
|
99 new_vector (type, npatterns, nelts_per_pattern);
|
|
100 return true;
|
|
101 }
|
|
102
|
|
103 /* Return the number of elements that the caller needs to operate on in
|
|
104 order to handle a binary operation on VECTOR_CSTs T1 and T2. This static
|
|
105 function is used instead of new_binary_operation if the result of the
|
|
106 operation is not a VECTOR_CST. */
|
|
107
|
|
108 unsigned int
|
|
109 tree_vector_builder::binary_encoded_nelts (tree t1, tree t2)
|
|
110 {
|
|
111 poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1));
|
|
112 gcc_assert (known_eq (nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))));
|
|
113 /* See new_binary_operation for details. */
|
|
114 unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
|
|
115 VECTOR_CST_NPATTERNS (t2));
|
|
116 unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
|
|
117 VECTOR_CST_NELTS_PER_PATTERN (t2));
|
|
118 unsigned HOST_WIDE_INT const_nelts;
|
|
119 if (nelts.is_constant (&const_nelts))
|
|
120 return MIN (npatterns * nelts_per_pattern, const_nelts);
|
|
121 return npatterns * nelts_per_pattern;
|
|
122 }
|
|
123
|
|
124 /* Return a vector element with the value BASE + FACTOR * STEP. */
|
|
125
|
|
126 tree
|
|
127 tree_vector_builder::apply_step (tree base, unsigned int factor,
|
|
128 const wide_int &step) const
|
|
129 {
|
|
130 return wide_int_to_tree (TREE_TYPE (base),
|
|
131 wi::to_wide (base) + factor * step);
|
|
132 }
|
|
133
|
|
134 /* Return a VECTOR_CST for the current constant. */
|
|
135
|
|
136 tree
|
|
137 tree_vector_builder::build ()
|
|
138 {
|
|
139 finalize ();
|
|
140 gcc_assert (pow2p_hwi (npatterns ()));
|
|
141 tree v = make_vector (exact_log2 (npatterns ()), nelts_per_pattern ());
|
|
142 TREE_TYPE (v) = m_type;
|
|
143 memcpy (VECTOR_CST_ENCODED_ELTS (v), address (),
|
|
144 encoded_nelts () * sizeof (tree));
|
|
145 return v;
|
|
146 }
|