PR tree-optimization/84740
[official-gcc.git] / gcc / tree-vector-builder.c
blob08652a20f497fc5a592f9aca0778e035b11d8b25
1 /* A class for building vector tree constants.
2 Copyright (C) 2017-2018 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 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)
45 if (!full_nelts.is_constant ())
46 return false;
47 npatterns = full_nelts.to_constant ();
48 nelts_per_pattern = 1;
50 new_vector (type, npatterns, nelts_per_pattern);
51 return true;
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.
59 Return true if the operation is possible. Leave the builder unchanged
60 otherwise. */
62 bool
63 tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2,
64 bool allow_stepped_p)
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:
73 { 1, 2, 3, ... }
75 into two gives:
77 { 1, 3, 5, ... }
78 { 2, 4, 6, ... }
80 while splitting:
82 { 1, 0, ... }
84 into two gives:
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)
94 if (!full_nelts.is_constant ())
95 return false;
96 npatterns = full_nelts.to_constant ();
97 nelts_per_pattern = 1;
99 new_vector (type, npatterns, nelts_per_pattern);
100 return true;
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. */
108 unsigned int
109 tree_vector_builder::binary_encoded_nelts (tree t1, tree t2)
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;
124 /* Return a vector element with the value BASE + FACTOR * STEP. */
126 tree
127 tree_vector_builder::apply_step (tree base, unsigned int factor,
128 const wide_int &step) const
130 return wide_int_to_tree (TREE_TYPE (base),
131 wi::to_wide (base) + factor * step);
134 /* Return a VECTOR_CST for the current constant. */
136 tree
137 tree_vector_builder::build ()
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;