xref: /dflybsd-src/contrib/gcc-8.0/gcc/tree-vector-builder.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* A class for building vector tree constants.
2*38fd1498Szrj    Copyright (C) 2017-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #include "config.h"
21*38fd1498Szrj #include "system.h"
22*38fd1498Szrj #include "coretypes.h"
23*38fd1498Szrj #include "tree.h"
24*38fd1498Szrj #include "fold-const.h"
25*38fd1498Szrj #include "tree-vector-builder.h"
26*38fd1498Szrj 
27*38fd1498Szrj /* Try to start building a new vector of type TYPE that holds the result of
28*38fd1498Szrj    a unary operation on VECTOR_CST T.  ALLOW_STEPPED_P is true if the
29*38fd1498Szrj    operation can handle stepped encodings directly, without having to
30*38fd1498Szrj    expand the full sequence.
31*38fd1498Szrj 
32*38fd1498Szrj    Return true if the operation is possible, which it always is when
33*38fd1498Szrj    ALLOW_STEPPED_P is true.  Leave the builder unchanged otherwise.  */
34*38fd1498Szrj 
35*38fd1498Szrj bool
new_unary_operation(tree type,tree t,bool allow_stepped_p)36*38fd1498Szrj tree_vector_builder::new_unary_operation (tree type, tree t,
37*38fd1498Szrj 					  bool allow_stepped_p)
38*38fd1498Szrj {
39*38fd1498Szrj   poly_uint64 full_nelts = TYPE_VECTOR_SUBPARTS (type);
40*38fd1498Szrj   gcc_assert (known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t))));
41*38fd1498Szrj   unsigned int npatterns = VECTOR_CST_NPATTERNS (t);
42*38fd1498Szrj   unsigned int nelts_per_pattern = VECTOR_CST_NELTS_PER_PATTERN (t);
43*38fd1498Szrj   if (!allow_stepped_p && nelts_per_pattern > 2)
44*38fd1498Szrj     {
45*38fd1498Szrj       if (!full_nelts.is_constant ())
46*38fd1498Szrj 	return false;
47*38fd1498Szrj       npatterns = full_nelts.to_constant ();
48*38fd1498Szrj       nelts_per_pattern = 1;
49*38fd1498Szrj     }
50*38fd1498Szrj   new_vector (type, npatterns, nelts_per_pattern);
51*38fd1498Szrj   return true;
52*38fd1498Szrj }
53*38fd1498Szrj 
54*38fd1498Szrj /* Try to start building a new vector of type TYPE that holds the result of
55*38fd1498Szrj    a binary operation on VECTOR_CSTs T1 and T2.  ALLOW_STEPPED_P is true if
56*38fd1498Szrj    the operation can handle stepped encodings directly, without having to
57*38fd1498Szrj    expand the full sequence.
58*38fd1498Szrj 
59*38fd1498Szrj    Return true if the operation is possible.  Leave the builder unchanged
60*38fd1498Szrj    otherwise.  */
61*38fd1498Szrj 
62*38fd1498Szrj bool
new_binary_operation(tree type,tree t1,tree t2,bool allow_stepped_p)63*38fd1498Szrj tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2,
64*38fd1498Szrj 					   bool allow_stepped_p)
65*38fd1498Szrj {
66*38fd1498Szrj   poly_uint64 full_nelts = TYPE_VECTOR_SUBPARTS (type);
67*38fd1498Szrj   gcc_assert (known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1)))
68*38fd1498Szrj 	      && known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))));
69*38fd1498Szrj   /* Conceptually we split the patterns in T1 and T2 until we have
70*38fd1498Szrj      an equal number for both.  Each split pattern requires the same
71*38fd1498Szrj      number of elements per pattern as the original.  E.g. splitting:
72*38fd1498Szrj 
73*38fd1498Szrj        { 1, 2, 3, ... }
74*38fd1498Szrj 
75*38fd1498Szrj      into two gives:
76*38fd1498Szrj 
77*38fd1498Szrj        { 1, 3, 5, ... }
78*38fd1498Szrj        { 2, 4, 6, ... }
79*38fd1498Szrj 
80*38fd1498Szrj      while splitting:
81*38fd1498Szrj 
82*38fd1498Szrj        { 1, 0, ... }
83*38fd1498Szrj 
84*38fd1498Szrj      into two gives:
85*38fd1498Szrj 
86*38fd1498Szrj        { 1, 0, ... }
87*38fd1498Szrj        { 0, 0, ... }.  */
88*38fd1498Szrj   unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
89*38fd1498Szrj 						  VECTOR_CST_NPATTERNS (t2));
90*38fd1498Szrj   unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
91*38fd1498Szrj 					VECTOR_CST_NELTS_PER_PATTERN (t2));
92*38fd1498Szrj   if (!allow_stepped_p && nelts_per_pattern > 2)
93*38fd1498Szrj     {
94*38fd1498Szrj       if (!full_nelts.is_constant ())
95*38fd1498Szrj 	return false;
96*38fd1498Szrj       npatterns = full_nelts.to_constant ();
97*38fd1498Szrj       nelts_per_pattern = 1;
98*38fd1498Szrj     }
99*38fd1498Szrj   new_vector (type, npatterns, nelts_per_pattern);
100*38fd1498Szrj   return true;
101*38fd1498Szrj }
102*38fd1498Szrj 
103*38fd1498Szrj /* Return the number of elements that the caller needs to operate on in
104*38fd1498Szrj    order to handle a binary operation on VECTOR_CSTs T1 and T2.  This static
105*38fd1498Szrj    function is used instead of new_binary_operation if the result of the
106*38fd1498Szrj    operation is not a VECTOR_CST.  */
107*38fd1498Szrj 
108*38fd1498Szrj unsigned int
binary_encoded_nelts(tree t1,tree t2)109*38fd1498Szrj tree_vector_builder::binary_encoded_nelts (tree t1, tree t2)
110*38fd1498Szrj {
111*38fd1498Szrj   poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1));
112*38fd1498Szrj   gcc_assert (known_eq (nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))));
113*38fd1498Szrj   /* See new_binary_operation for details.  */
114*38fd1498Szrj   unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
115*38fd1498Szrj 						  VECTOR_CST_NPATTERNS (t2));
116*38fd1498Szrj   unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
117*38fd1498Szrj 					VECTOR_CST_NELTS_PER_PATTERN (t2));
118*38fd1498Szrj   unsigned HOST_WIDE_INT const_nelts;
119*38fd1498Szrj   if (nelts.is_constant (&const_nelts))
120*38fd1498Szrj     return MIN (npatterns * nelts_per_pattern, const_nelts);
121*38fd1498Szrj   return npatterns * nelts_per_pattern;
122*38fd1498Szrj }
123*38fd1498Szrj 
124*38fd1498Szrj /* Return a vector element with the value BASE + FACTOR * STEP.  */
125*38fd1498Szrj 
126*38fd1498Szrj tree
apply_step(tree base,unsigned int factor,const wide_int & step)127*38fd1498Szrj tree_vector_builder::apply_step (tree base, unsigned int factor,
128*38fd1498Szrj 				 const wide_int &step) const
129*38fd1498Szrj {
130*38fd1498Szrj   return wide_int_to_tree (TREE_TYPE (base),
131*38fd1498Szrj 			   wi::to_wide (base) + factor * step);
132*38fd1498Szrj }
133*38fd1498Szrj 
134*38fd1498Szrj /* Return a VECTOR_CST for the current constant.  */
135*38fd1498Szrj 
136*38fd1498Szrj tree
build()137*38fd1498Szrj tree_vector_builder::build ()
138*38fd1498Szrj {
139*38fd1498Szrj   finalize ();
140*38fd1498Szrj   gcc_assert (pow2p_hwi (npatterns ()));
141*38fd1498Szrj   tree v = make_vector (exact_log2 (npatterns ()), nelts_per_pattern ());
142*38fd1498Szrj   TREE_TYPE (v) = m_type;
143*38fd1498Szrj   memcpy (VECTOR_CST_ENCODED_ELTS (v), address (),
144*38fd1498Szrj 	  encoded_nelts () * sizeof (tree));
145*38fd1498Szrj   return v;
146*38fd1498Szrj }
147