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 } 147