Import GCC-8 to a new vendor branch
[dragonfly.git] / contrib / gcc-8.0 / gcc / tree-vector-builder.c
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 }