Make more use of VECTOR_CST_ENCODED_ELT
[official-gcc.git] / gcc / tree-vector-builder.c
blob88b9d1a94808b904b50af9533d2df7a7660f5b8e
1 /* A class for building vector tree constants.
2 Copyright (C) 2017 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
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.
32 Return true if the operation is possible, which it always is when
33 ALLOW_STEPPED_P is true. Leave the builder unchanged otherwise. */
35 bool
36 tree_vector_builder::new_unary_operation (tree type, tree t,
37 bool allow_stepped_p)
39 unsigned int full_nelts = TYPE_VECTOR_SUBPARTS (type);
40 gcc_assert (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)
45 npatterns = full_nelts;
46 nelts_per_pattern = 1;
48 new_vector (type, npatterns, nelts_per_pattern);
49 return true;
52 /* Try to start building a new vector of type TYPE that holds the result of
53 a binary operation on VECTOR_CSTs T1 and T2. ALLOW_STEPPED_P is true if
54 the operation can handle stepped encodings directly, without having to
55 expand the full sequence.
57 Return true if the operation is possible. Leave the builder unchanged
58 otherwise. */
60 bool
61 tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2,
62 bool allow_stepped_p)
64 unsigned int full_nelts = TYPE_VECTOR_SUBPARTS (type);
65 gcc_assert (full_nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1))
66 && full_nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2)));
67 /* Conceptually we split the patterns in T1 and T2 until we have
68 an equal number for both. Each split pattern requires the same
69 number of elements per pattern as the original. E.g. splitting:
71 { 1, 2, 3, ... }
73 into two gives:
75 { 1, 3, 5, ... }
76 { 2, 4, 6, ... }
78 while splitting:
80 { 1, 0, ... }
82 into two gives:
84 { 1, 0, ... }
85 { 0, 0, ... }. */
86 unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
87 VECTOR_CST_NPATTERNS (t2));
88 unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
89 VECTOR_CST_NELTS_PER_PATTERN (t2));
90 if (!allow_stepped_p && nelts_per_pattern > 2)
92 npatterns = full_nelts;
93 nelts_per_pattern = 1;
95 new_vector (type, npatterns, nelts_per_pattern);
96 return true;
99 /* Return the number of elements that the caller needs to operate on in
100 order to handle a binary operation on VECTOR_CSTs T1 and T2. This static
101 function is used instead of new_binary_operation if the result of the
102 operation is not a VECTOR_CST. */
104 unsigned int
105 tree_vector_builder::binary_encoded_nelts (tree t1, tree t2)
107 unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1));
108 gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2)));
109 /* See new_binary_operation for details. */
110 unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
111 VECTOR_CST_NPATTERNS (t2));
112 unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
113 VECTOR_CST_NELTS_PER_PATTERN (t2));
114 return MIN (npatterns * nelts_per_pattern, nelts);
117 /* Return a vector element with the value BASE + FACTOR * STEP. */
119 tree
120 tree_vector_builder::apply_step (tree base, unsigned int factor,
121 const wide_int &step) const
123 return wide_int_to_tree (TREE_TYPE (base),
124 wi::to_wide (base) + factor * step);
127 /* Return a VECTOR_CST for the current constant. */
129 tree
130 tree_vector_builder::build ()
132 finalize ();
133 gcc_assert (pow2p_hwi (npatterns ()));
134 tree v = make_vector (exact_log2 (npatterns ()), nelts_per_pattern ());
135 TREE_TYPE (v) = m_type;
136 memcpy (VECTOR_CST_ENCODED_ELTS (v), address (),
137 encoded_nelts () * sizeof (tree));
138 return v;