1 1.1 mrg /* Lower vector operations to scalar operations. 2 1.1 mrg Copyright (C) 2004-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify it 7 1.1 mrg under the terms of the GNU General Public License as published by the 8 1.1 mrg Free Software Foundation; either version 3, or (at your option) any 9 1.1 mrg later version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT 12 1.1 mrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 1.1 mrg for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License 17 1.1 mrg along with GCC; see the file COPYING3. If not see 18 1.1 mrg <http://www.gnu.org/licenses/>. */ 19 1.1 mrg 20 1.1 mrg #include "config.h" 21 1.1 mrg #include "system.h" 22 1.1 mrg #include "coretypes.h" 23 1.1 mrg #include "backend.h" 24 1.1 mrg #include "rtl.h" 25 1.1 mrg #include "tree.h" 26 1.1 mrg #include "gimple.h" 27 1.1 mrg #include "tree-pass.h" 28 1.1 mrg #include "ssa.h" 29 1.1 mrg #include "expmed.h" 30 1.1 mrg #include "optabs-tree.h" 31 1.1 mrg #include "diagnostic.h" 32 1.1 mrg #include "fold-const.h" 33 1.1 mrg #include "stor-layout.h" 34 1.1 mrg #include "langhooks.h" 35 1.1 mrg #include "tree-eh.h" 36 1.1 mrg #include "gimple-iterator.h" 37 1.1 mrg #include "gimplify-me.h" 38 1.1 mrg #include "gimplify.h" 39 1.1 mrg #include "tree-cfg.h" 40 1.1 mrg #include "tree-vector-builder.h" 41 1.1 mrg #include "vec-perm-indices.h" 42 1.1 mrg #include "insn-config.h" 43 1.1 mrg #include "tree-ssa-dce.h" 44 1.1 mrg #include "gimple-fold.h" 45 1.1 mrg #include "gimple-match.h" 46 1.1 mrg #include "recog.h" /* FIXME: for insn_data */ 47 1.1 mrg 48 1.1 mrg 49 1.1 mrg /* Build a ternary operation and gimplify it. Emit code before GSI. 50 1.1 mrg Return the gimple_val holding the result. */ 51 1.1 mrg 52 1.1 mrg static tree 53 1.1 mrg gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code, 54 1.1 mrg tree type, tree a, tree b, tree c) 55 1.1 mrg { 56 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 57 1.1 mrg gimple_seq stmts = NULL; 58 1.1 mrg tree ret = gimple_build (&stmts, loc, code, type, a, b, c); 59 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); 60 1.1 mrg return ret; 61 1.1 mrg } 62 1.1 mrg 63 1.1 mrg /* Build a binary operation and gimplify it. Emit code before GSI. 64 1.1 mrg Return the gimple_val holding the result. */ 65 1.1 mrg 66 1.1 mrg static tree 67 1.1 mrg gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code, 68 1.1 mrg tree type, tree a, tree b) 69 1.1 mrg { 70 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 71 1.1 mrg gimple_seq stmts = NULL; 72 1.1 mrg tree ret = gimple_build (&stmts, loc, code, type, a, b); 73 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); 74 1.1 mrg return ret; 75 1.1 mrg } 76 1.1 mrg 77 1.1 mrg /* Build a unary operation and gimplify it. Emit code before GSI. 78 1.1 mrg Return the gimple_val holding the result. */ 79 1.1 mrg 80 1.1 mrg static tree 81 1.1 mrg gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type, 82 1.1 mrg tree a) 83 1.1 mrg { 84 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 85 1.1 mrg gimple_seq stmts = NULL; 86 1.1 mrg tree ret = gimple_build (&stmts, loc, code, type, a); 87 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); 88 1.1 mrg return ret; 89 1.1 mrg } 90 1.1 mrg 91 1.1 mrg 92 1.1 mrg static void expand_vector_operations_1 (gimple_stmt_iterator *, bitmap); 93 1.1 mrg 94 1.1 mrg /* Return the number of elements in a vector type TYPE that we have 95 1.1 mrg already decided needs to be expanded piecewise. We don't support 96 1.1 mrg this kind of expansion for variable-length vectors, since we should 97 1.1 mrg always check for target support before introducing uses of those. */ 98 1.1 mrg static unsigned int 99 1.1 mrg nunits_for_known_piecewise_op (const_tree type) 100 1.1 mrg { 101 1.1 mrg return TYPE_VECTOR_SUBPARTS (type).to_constant (); 102 1.1 mrg } 103 1.1 mrg 104 1.1 mrg /* Return true if TYPE1 has more elements than TYPE2, where either 105 1.1 mrg type may be a vector or a scalar. */ 106 1.1 mrg 107 1.1 mrg static inline bool 108 1.1 mrg subparts_gt (tree type1, tree type2) 109 1.1 mrg { 110 1.1 mrg poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1; 111 1.1 mrg poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1; 112 1.1 mrg return known_gt (n1, n2); 113 1.1 mrg } 114 1.1 mrg 115 1.1 mrg /* Build a constant of type TYPE, made of VALUE's bits replicated 116 1.1 mrg every WIDTH bits to fit TYPE's precision. */ 117 1.1 mrg static tree 118 1.1 mrg build_replicated_const (tree type, unsigned int width, HOST_WIDE_INT value) 119 1.1 mrg { 120 1.1 mrg int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1) 121 1.1 mrg / HOST_BITS_PER_WIDE_INT; 122 1.1 mrg unsigned HOST_WIDE_INT low, mask; 123 1.1 mrg HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; 124 1.1 mrg int i; 125 1.1 mrg 126 1.1 mrg gcc_assert (n && n <= WIDE_INT_MAX_ELTS); 127 1.1 mrg 128 1.1 mrg if (width == HOST_BITS_PER_WIDE_INT) 129 1.1 mrg low = value; 130 1.1 mrg else 131 1.1 mrg { 132 1.1 mrg mask = ((HOST_WIDE_INT)1 << width) - 1; 133 1.1 mrg low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask); 134 1.1 mrg } 135 1.1 mrg 136 1.1 mrg for (i = 0; i < n; i++) 137 1.1 mrg a[i] = low; 138 1.1 mrg 139 1.1 mrg gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT); 140 1.1 mrg return wide_int_to_tree 141 1.1 mrg (type, wide_int::from_array (a, n, TYPE_PRECISION (type))); 142 1.1 mrg } 143 1.1 mrg 144 1.1 mrg static GTY(()) tree vector_inner_type; 145 1.1 mrg static GTY(()) tree vector_last_type; 146 1.1 mrg static GTY(()) int vector_last_nunits; 147 1.1 mrg 148 1.1 mrg /* Return a suitable vector types made of SUBPARTS units each of mode 149 1.1 mrg "word_mode" (the global variable). */ 150 1.1 mrg static tree 151 1.1 mrg build_word_mode_vector_type (int nunits) 152 1.1 mrg { 153 1.1 mrg if (!vector_inner_type) 154 1.1 mrg vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1); 155 1.1 mrg else if (vector_last_nunits == nunits) 156 1.1 mrg { 157 1.1 mrg gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE); 158 1.1 mrg return vector_last_type; 159 1.1 mrg } 160 1.1 mrg 161 1.1 mrg vector_last_nunits = nunits; 162 1.1 mrg vector_last_type = build_vector_type (vector_inner_type, nunits); 163 1.1 mrg return vector_last_type; 164 1.1 mrg } 165 1.1 mrg 166 1.1 mrg typedef tree (*elem_op_func) (gimple_stmt_iterator *, 167 1.1 mrg tree, tree, tree, tree, tree, enum tree_code, 168 1.1 mrg tree); 169 1.1 mrg 170 1.1 mrg /* Extract the vector element of type TYPE at BITPOS with BITSIZE from T 171 1.1 mrg and return it. */ 172 1.1 mrg 173 1.1 mrg tree 174 1.1 mrg tree_vec_extract (gimple_stmt_iterator *gsi, tree type, 175 1.1 mrg tree t, tree bitsize, tree bitpos) 176 1.1 mrg { 177 1.1 mrg /* We're using the resimplify API and maybe_push_res_to_seq to 178 1.1 mrg simplify the BIT_FIELD_REF but restrict the simplification to 179 1.1 mrg a single stmt while at the same time following SSA edges for 180 1.1 mrg simplification with already emitted CTORs. */ 181 1.1 mrg gimple_match_op opr; 182 1.1 mrg opr.set_op (BIT_FIELD_REF, type, t, bitsize, bitpos); 183 1.1 mrg opr.resimplify (NULL, follow_all_ssa_edges); 184 1.1 mrg gimple_seq stmts = NULL; 185 1.1 mrg tree res = maybe_push_res_to_seq (&opr, &stmts); 186 1.1 mrg if (!res) 187 1.1 mrg { 188 1.1 mrg /* This can happen if SSA_NAME_OCCURS_IN_ABNORMAL_PHI are 189 1.1 mrg used. Build BIT_FIELD_REF manually otherwise. */ 190 1.1 mrg t = build3 (BIT_FIELD_REF, type, t, bitsize, bitpos); 191 1.1 mrg res = make_ssa_name (type); 192 1.1 mrg gimple *g = gimple_build_assign (res, t); 193 1.1 mrg gsi_insert_before (gsi, g, GSI_SAME_STMT); 194 1.1 mrg return res; 195 1.1 mrg } 196 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); 197 1.1 mrg return res; 198 1.1 mrg } 199 1.1 mrg 200 1.1 mrg static tree 201 1.1 mrg do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a, 202 1.1 mrg tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize, 203 1.1 mrg enum tree_code code, tree type ATTRIBUTE_UNUSED) 204 1.1 mrg { 205 1.1 mrg tree rhs_type = inner_type; 206 1.1 mrg 207 1.1 mrg /* For ABSU_EXPR, use the signed type for the rhs if the rhs was signed. */ 208 1.1 mrg if (code == ABSU_EXPR 209 1.1 mrg && ANY_INTEGRAL_TYPE_P (TREE_TYPE (a)) 210 1.1 mrg && !TYPE_UNSIGNED (TREE_TYPE (a))) 211 1.1 mrg rhs_type = signed_type_for (rhs_type); 212 1.1 mrg 213 1.1 mrg a = tree_vec_extract (gsi, rhs_type, a, bitsize, bitpos); 214 1.1 mrg return gimplify_build1 (gsi, code, inner_type, a); 215 1.1 mrg } 216 1.1 mrg 217 1.1 mrg static tree 218 1.1 mrg do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b, 219 1.1 mrg tree bitpos, tree bitsize, enum tree_code code, 220 1.1 mrg tree type ATTRIBUTE_UNUSED) 221 1.1 mrg { 222 1.1 mrg if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE) 223 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos); 224 1.1 mrg if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE) 225 1.1 mrg b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos); 226 1.1 mrg return gimplify_build2 (gsi, code, inner_type, a, b); 227 1.1 mrg } 228 1.1 mrg 229 1.1 mrg /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0 230 1.1 mrg 231 1.1 mrg INNER_TYPE is the type of A and B elements 232 1.1 mrg 233 1.1 mrg returned expression is of signed integer type with the 234 1.1 mrg size equal to the size of INNER_TYPE. */ 235 1.1 mrg static tree 236 1.1 mrg do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b, 237 1.1 mrg tree bitpos, tree bitsize, enum tree_code code, tree type) 238 1.1 mrg { 239 1.1 mrg tree stype = TREE_TYPE (type); 240 1.1 mrg tree cst_false = build_zero_cst (stype); 241 1.1 mrg tree cst_true = build_all_ones_cst (stype); 242 1.1 mrg tree cmp; 243 1.1 mrg 244 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos); 245 1.1 mrg b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos); 246 1.1 mrg 247 1.1 mrg cmp = build2 (code, boolean_type_node, a, b); 248 1.1 mrg return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false); 249 1.1 mrg } 250 1.1 mrg 251 1.1 mrg /* Expand vector addition to scalars. This does bit twiddling 252 1.1 mrg in order to increase parallelism: 253 1.1 mrg 254 1.1 mrg a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^ 255 1.1 mrg (a ^ b) & 0x80808080 256 1.1 mrg 257 1.1 mrg a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^ 258 1.1 mrg (a ^ ~b) & 0x80808080 259 1.1 mrg 260 1.1 mrg -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080) 261 1.1 mrg 262 1.1 mrg This optimization should be done only if 4 vector items or more 263 1.1 mrg fit into a word. */ 264 1.1 mrg static tree 265 1.1 mrg do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b, 266 1.1 mrg tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED, 267 1.1 mrg enum tree_code code, tree type ATTRIBUTE_UNUSED) 268 1.1 mrg { 269 1.1 mrg unsigned int width = vector_element_bits (TREE_TYPE (a)); 270 1.1 mrg tree inner_type = TREE_TYPE (TREE_TYPE (a)); 271 1.1 mrg unsigned HOST_WIDE_INT max; 272 1.1 mrg tree low_bits, high_bits, a_low, b_low, result_low, signs; 273 1.1 mrg 274 1.1 mrg max = GET_MODE_MASK (TYPE_MODE (inner_type)); 275 1.1 mrg low_bits = build_replicated_const (word_type, width, max >> 1); 276 1.1 mrg high_bits = build_replicated_const (word_type, width, max & ~(max >> 1)); 277 1.1 mrg 278 1.1 mrg a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos); 279 1.1 mrg b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos); 280 1.1 mrg 281 1.1 mrg signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b); 282 1.1 mrg b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits); 283 1.1 mrg if (code == PLUS_EXPR) 284 1.1 mrg a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits); 285 1.1 mrg else 286 1.1 mrg { 287 1.1 mrg a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits); 288 1.1 mrg signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs); 289 1.1 mrg } 290 1.1 mrg 291 1.1 mrg signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits); 292 1.1 mrg result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low); 293 1.1 mrg return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs); 294 1.1 mrg } 295 1.1 mrg 296 1.1 mrg static tree 297 1.1 mrg do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b, 298 1.1 mrg tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED, 299 1.1 mrg tree bitsize ATTRIBUTE_UNUSED, 300 1.1 mrg enum tree_code code ATTRIBUTE_UNUSED, 301 1.1 mrg tree type ATTRIBUTE_UNUSED) 302 1.1 mrg { 303 1.1 mrg unsigned int width = vector_element_bits (TREE_TYPE (b)); 304 1.1 mrg tree inner_type = TREE_TYPE (TREE_TYPE (b)); 305 1.1 mrg HOST_WIDE_INT max; 306 1.1 mrg tree low_bits, high_bits, b_low, result_low, signs; 307 1.1 mrg 308 1.1 mrg max = GET_MODE_MASK (TYPE_MODE (inner_type)); 309 1.1 mrg low_bits = build_replicated_const (word_type, width, max >> 1); 310 1.1 mrg high_bits = build_replicated_const (word_type, width, max & ~(max >> 1)); 311 1.1 mrg 312 1.1 mrg b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos); 313 1.1 mrg 314 1.1 mrg b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits); 315 1.1 mrg signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b); 316 1.1 mrg signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits); 317 1.1 mrg result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low); 318 1.1 mrg return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs); 319 1.1 mrg } 320 1.1 mrg 321 1.1 mrg /* Expand a vector operation to scalars, by using many operations 322 1.1 mrg whose type is the vector type's inner type. */ 323 1.1 mrg static tree 324 1.1 mrg expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f, 325 1.1 mrg tree type, tree inner_type, 326 1.1 mrg tree a, tree b, enum tree_code code, 327 1.1 mrg bool parallel_p, tree ret_type = NULL_TREE) 328 1.1 mrg { 329 1.1 mrg vec<constructor_elt, va_gc> *v; 330 1.1 mrg tree part_width = TYPE_SIZE (inner_type); 331 1.1 mrg tree index = bitsize_int (0); 332 1.1 mrg int nunits = nunits_for_known_piecewise_op (type); 333 1.1 mrg int delta = tree_to_uhwi (part_width) / vector_element_bits (type); 334 1.1 mrg int i; 335 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 336 1.1 mrg 337 1.1 mrg if (nunits == 1 338 1.1 mrg || warning_suppressed_p (gsi_stmt (*gsi), 339 1.1 mrg OPT_Wvector_operation_performance)) 340 1.1 mrg /* Do not diagnose decomposing single element vectors or when 341 1.1 mrg decomposing vectorizer produced operations. */ 342 1.1 mrg ; 343 1.1 mrg else if (ret_type || !parallel_p) 344 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance, 345 1.1 mrg "vector operation will be expanded piecewise"); 346 1.1 mrg else 347 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance, 348 1.1 mrg "vector operation will be expanded in parallel"); 349 1.1 mrg 350 1.1 mrg if (!ret_type) 351 1.1 mrg ret_type = type; 352 1.1 mrg vec_alloc (v, (nunits + delta - 1) / delta); 353 1.1 mrg bool constant_p = true; 354 1.1 mrg for (i = 0; i < nunits; 355 1.1 mrg i += delta, index = int_const_binop (PLUS_EXPR, index, part_width)) 356 1.1 mrg { 357 1.1 mrg tree result = f (gsi, inner_type, a, b, index, part_width, code, 358 1.1 mrg ret_type); 359 1.1 mrg if (!CONSTANT_CLASS_P (result)) 360 1.1 mrg constant_p = false; 361 1.1 mrg constructor_elt ce = {NULL_TREE, result}; 362 1.1 mrg v->quick_push (ce); 363 1.1 mrg } 364 1.1 mrg 365 1.1 mrg if (constant_p) 366 1.1 mrg return build_vector_from_ctor (ret_type, v); 367 1.1 mrg else 368 1.1 mrg return build_constructor (ret_type, v); 369 1.1 mrg } 370 1.1 mrg 371 1.1 mrg /* Expand a vector operation to scalars with the freedom to use 372 1.1 mrg a scalar integer type, or to use a different size for the items 373 1.1 mrg in the vector type. */ 374 1.1 mrg static tree 375 1.1 mrg expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type, 376 1.1 mrg tree a, tree b, enum tree_code code) 377 1.1 mrg { 378 1.1 mrg tree result, compute_type; 379 1.1 mrg int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD; 380 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 381 1.1 mrg 382 1.1 mrg /* We have three strategies. If the type is already correct, just do 383 1.1 mrg the operation an element at a time. Else, if the vector is wider than 384 1.1 mrg one word, do it a word at a time; finally, if the vector is smaller 385 1.1 mrg than one word, do it as a scalar. */ 386 1.1 mrg if (TYPE_MODE (TREE_TYPE (type)) == word_mode) 387 1.1 mrg return expand_vector_piecewise (gsi, f, 388 1.1 mrg type, TREE_TYPE (type), 389 1.1 mrg a, b, code, true); 390 1.1 mrg else if (n_words > 1) 391 1.1 mrg { 392 1.1 mrg tree word_type = build_word_mode_vector_type (n_words); 393 1.1 mrg result = expand_vector_piecewise (gsi, f, 394 1.1 mrg word_type, TREE_TYPE (word_type), 395 1.1 mrg a, b, code, true); 396 1.1 mrg result = force_gimple_operand_gsi (gsi, result, true, NULL, true, 397 1.1 mrg GSI_SAME_STMT); 398 1.1 mrg } 399 1.1 mrg else 400 1.1 mrg { 401 1.1 mrg /* Use a single scalar operation with a mode no wider than word_mode. */ 402 1.1 mrg if (!warning_suppressed_p (gsi_stmt (*gsi), 403 1.1 mrg OPT_Wvector_operation_performance)) 404 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance, 405 1.1 mrg "vector operation will be expanded with a " 406 1.1 mrg "single scalar operation"); 407 1.1 mrg scalar_int_mode mode 408 1.1 mrg = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require (); 409 1.1 mrg compute_type = lang_hooks.types.type_for_mode (mode, 1); 410 1.1 mrg result = f (gsi, compute_type, a, b, bitsize_zero_node, 411 1.1 mrg TYPE_SIZE (compute_type), code, type); 412 1.1 mrg } 413 1.1 mrg 414 1.1 mrg return result; 415 1.1 mrg } 416 1.1 mrg 417 1.1 mrg /* Expand a vector operation to scalars; for integer types we can use 418 1.1 mrg special bit twiddling tricks to do the sums a word at a time, using 419 1.1 mrg function F_PARALLEL instead of F. These tricks are done only if 420 1.1 mrg they can process at least four items, that is, only if the vector 421 1.1 mrg holds at least four items and if a word can hold four items. */ 422 1.1 mrg static tree 423 1.1 mrg expand_vector_addition (gimple_stmt_iterator *gsi, 424 1.1 mrg elem_op_func f, elem_op_func f_parallel, 425 1.1 mrg tree type, tree a, tree b, enum tree_code code) 426 1.1 mrg { 427 1.1 mrg int parts_per_word = BITS_PER_WORD / vector_element_bits (type); 428 1.1 mrg 429 1.1 mrg if (INTEGRAL_TYPE_P (TREE_TYPE (type)) 430 1.1 mrg && parts_per_word >= 4 431 1.1 mrg && nunits_for_known_piecewise_op (type) >= 4) 432 1.1 mrg return expand_vector_parallel (gsi, f_parallel, 433 1.1 mrg type, a, b, code); 434 1.1 mrg else 435 1.1 mrg return expand_vector_piecewise (gsi, f, 436 1.1 mrg type, TREE_TYPE (type), 437 1.1 mrg a, b, code, false); 438 1.1 mrg } 439 1.1 mrg 440 1.1 mrg static bool 441 1.1 mrg expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names); 442 1.1 mrg 443 1.1 mrg /* Try to expand vector comparison expression OP0 CODE OP1 by 444 1.1 mrg querying optab if the following expression: 445 1.1 mrg VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}> 446 1.1 mrg can be expanded. */ 447 1.1 mrg static tree 448 1.1 mrg expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0, 449 1.1 mrg tree op1, enum tree_code code, 450 1.1 mrg bitmap dce_ssa_names) 451 1.1 mrg { 452 1.1 mrg tree lhs = gimple_assign_lhs (gsi_stmt (*gsi)); 453 1.1 mrg use_operand_p use_p; 454 1.1 mrg imm_use_iterator iterator; 455 1.1 mrg bool vec_cond_expr_only = true; 456 1.1 mrg 457 1.1 mrg /* As seen in PR95830, we should not expand comparisons that are only 458 1.1 mrg feeding a VEC_COND_EXPR statement. */ 459 1.1 mrg auto_vec<gimple *> uses; 460 1.1 mrg FOR_EACH_IMM_USE_FAST (use_p, iterator, lhs) 461 1.1 mrg { 462 1.1 mrg gimple *use = USE_STMT (use_p); 463 1.1 mrg if (is_gimple_debug (use)) 464 1.1 mrg continue; 465 1.1 mrg if (is_gimple_assign (use) 466 1.1 mrg && gimple_assign_rhs_code (use) == VEC_COND_EXPR 467 1.1 mrg && gimple_assign_rhs1 (use) == lhs 468 1.1 mrg && gimple_assign_rhs2 (use) != lhs 469 1.1 mrg && gimple_assign_rhs3 (use) != lhs) 470 1.1 mrg uses.safe_push (use); 471 1.1 mrg else 472 1.1 mrg vec_cond_expr_only = false; 473 1.1 mrg } 474 1.1 mrg 475 1.1 mrg if (vec_cond_expr_only) 476 1.1 mrg for (gimple *use : uses) 477 1.1 mrg { 478 1.1 mrg gimple_stmt_iterator it = gsi_for_stmt (use); 479 1.1 mrg if (!expand_vector_condition (&it, dce_ssa_names)) 480 1.1 mrg { 481 1.1 mrg vec_cond_expr_only = false; 482 1.1 mrg break; 483 1.1 mrg } 484 1.1 mrg } 485 1.1 mrg 486 1.1 mrg if (!uses.is_empty () && vec_cond_expr_only) 487 1.1 mrg return NULL_TREE; 488 1.1 mrg 489 1.1 mrg tree t; 490 1.1 mrg if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)) 491 1.1 mrg { 492 1.1 mrg if (VECTOR_BOOLEAN_TYPE_P (type) 493 1.1 mrg && SCALAR_INT_MODE_P (TYPE_MODE (type)) 494 1.1 mrg && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)), 495 1.1 mrg TYPE_VECTOR_SUBPARTS (type) 496 1.1 mrg * GET_MODE_BITSIZE (SCALAR_TYPE_MODE 497 1.1 mrg (TREE_TYPE (type))))) 498 1.1 mrg { 499 1.1 mrg tree inner_type = TREE_TYPE (TREE_TYPE (op0)); 500 1.1 mrg tree part_width = vector_element_bits_tree (TREE_TYPE (op0)); 501 1.1 mrg tree index = bitsize_int (0); 502 1.1 mrg int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0)); 503 1.1 mrg int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type)); 504 1.1 mrg tree ret_type = build_nonstandard_integer_type (prec, 1); 505 1.1 mrg tree ret_inner_type = boolean_type_node; 506 1.1 mrg int i; 507 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 508 1.1 mrg t = build_zero_cst (ret_type); 509 1.1 mrg 510 1.1 mrg if (TYPE_PRECISION (ret_inner_type) != 1) 511 1.1 mrg ret_inner_type = build_nonstandard_integer_type (1, 1); 512 1.1 mrg if (!warning_suppressed_p (gsi_stmt (*gsi), 513 1.1 mrg OPT_Wvector_operation_performance)) 514 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance, 515 1.1 mrg "vector operation will be expanded piecewise"); 516 1.1 mrg for (i = 0; i < nunits; 517 1.1 mrg i++, index = int_const_binop (PLUS_EXPR, index, part_width)) 518 1.1 mrg { 519 1.1 mrg tree a = tree_vec_extract (gsi, inner_type, op0, part_width, 520 1.1 mrg index); 521 1.1 mrg tree b = tree_vec_extract (gsi, inner_type, op1, part_width, 522 1.1 mrg index); 523 1.1 mrg tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b); 524 1.1 mrg t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result, 525 1.1 mrg bitsize_int (i)); 526 1.1 mrg } 527 1.1 mrg t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t); 528 1.1 mrg } 529 1.1 mrg else 530 1.1 mrg t = expand_vector_piecewise (gsi, do_compare, type, 531 1.1 mrg TREE_TYPE (TREE_TYPE (op0)), op0, op1, 532 1.1 mrg code, false); 533 1.1 mrg } 534 1.1 mrg else 535 1.1 mrg t = NULL_TREE; 536 1.1 mrg 537 1.1 mrg return t; 538 1.1 mrg } 539 1.1 mrg 540 1.1 mrg /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type 541 1.1 mrg of OP0 with shift counts in SHIFTCNTS array and return the temporary holding 542 1.1 mrg the result if successful, otherwise return NULL_TREE. */ 543 1.1 mrg static tree 544 1.1 mrg add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts) 545 1.1 mrg { 546 1.1 mrg optab op; 547 1.1 mrg unsigned int i, nunits = nunits_for_known_piecewise_op (type); 548 1.1 mrg bool scalar_shift = true; 549 1.1 mrg 550 1.1 mrg for (i = 1; i < nunits; i++) 551 1.1 mrg { 552 1.1 mrg if (shiftcnts[i] != shiftcnts[0]) 553 1.1 mrg scalar_shift = false; 554 1.1 mrg } 555 1.1 mrg 556 1.1 mrg if (scalar_shift && shiftcnts[0] == 0) 557 1.1 mrg return op0; 558 1.1 mrg 559 1.1 mrg if (scalar_shift) 560 1.1 mrg { 561 1.1 mrg op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar); 562 1.1 mrg if (op != unknown_optab 563 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing) 564 1.1 mrg return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, 565 1.1 mrg build_int_cst (NULL_TREE, shiftcnts[0])); 566 1.1 mrg } 567 1.1 mrg 568 1.1 mrg op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector); 569 1.1 mrg if (op != unknown_optab 570 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing) 571 1.1 mrg { 572 1.1 mrg tree_vector_builder vec (type, nunits, 1); 573 1.1 mrg for (i = 0; i < nunits; i++) 574 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i])); 575 1.1 mrg return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ()); 576 1.1 mrg } 577 1.1 mrg 578 1.1 mrg return NULL_TREE; 579 1.1 mrg } 580 1.1 mrg 581 1.1 mrg /* Try to expand integer vector division by constant using 582 1.1 mrg widening multiply, shifts and additions. */ 583 1.1 mrg static tree 584 1.1 mrg expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, 585 1.1 mrg tree op1, enum tree_code code) 586 1.1 mrg { 587 1.1 mrg bool use_pow2 = true; 588 1.1 mrg bool has_vector_shift = true; 589 1.1 mrg bool use_abs_op1 = false; 590 1.1 mrg int mode = -1, this_mode; 591 1.1 mrg int pre_shift = -1, post_shift; 592 1.1 mrg unsigned int nunits = nunits_for_known_piecewise_op (type); 593 1.1 mrg int *shifts = XALLOCAVEC (int, nunits * 4); 594 1.1 mrg int *pre_shifts = shifts + nunits; 595 1.1 mrg int *post_shifts = pre_shifts + nunits; 596 1.1 mrg int *shift_temps = post_shifts + nunits; 597 1.1 mrg unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits); 598 1.1 mrg int prec = TYPE_PRECISION (TREE_TYPE (type)); 599 1.1 mrg int dummy_int; 600 1.1 mrg unsigned int i; 601 1.1 mrg signop sign_p = TYPE_SIGN (TREE_TYPE (type)); 602 1.1 mrg unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type))); 603 1.1 mrg tree cur_op, mulcst, tem; 604 1.1 mrg optab op; 605 1.1 mrg 606 1.1 mrg if (prec > HOST_BITS_PER_WIDE_INT) 607 1.1 mrg return NULL_TREE; 608 1.1 mrg 609 1.1 mrg op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector); 610 1.1 mrg if (op == unknown_optab 611 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 612 1.1 mrg has_vector_shift = false; 613 1.1 mrg 614 1.1 mrg /* Analysis phase. Determine if all op1 elements are either power 615 1.1 mrg of two and it is possible to expand it using shifts (or for remainder 616 1.1 mrg using masking). Additionally compute the multiplicative constants 617 1.1 mrg and pre and post shifts if the division is to be expanded using 618 1.1 mrg widening or high part multiplication plus shifts. */ 619 1.1 mrg for (i = 0; i < nunits; i++) 620 1.1 mrg { 621 1.1 mrg tree cst = VECTOR_CST_ELT (op1, i); 622 1.1 mrg unsigned HOST_WIDE_INT ml; 623 1.1 mrg 624 1.1 mrg if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst)) 625 1.1 mrg return NULL_TREE; 626 1.1 mrg pre_shifts[i] = 0; 627 1.1 mrg post_shifts[i] = 0; 628 1.1 mrg mulc[i] = 0; 629 1.1 mrg if (use_pow2 630 1.1 mrg && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1)) 631 1.1 mrg use_pow2 = false; 632 1.1 mrg if (use_pow2) 633 1.1 mrg { 634 1.1 mrg shifts[i] = tree_log2 (cst); 635 1.1 mrg if (shifts[i] != shifts[0] 636 1.1 mrg && code == TRUNC_DIV_EXPR 637 1.1 mrg && !has_vector_shift) 638 1.1 mrg use_pow2 = false; 639 1.1 mrg } 640 1.1 mrg if (mode == -2) 641 1.1 mrg continue; 642 1.1 mrg if (sign_p == UNSIGNED) 643 1.1 mrg { 644 1.1 mrg unsigned HOST_WIDE_INT mh; 645 1.1 mrg unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask; 646 1.1 mrg 647 1.1 mrg if (d >= (HOST_WIDE_INT_1U << (prec - 1))) 648 1.1 mrg /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */ 649 1.1 mrg return NULL_TREE; 650 1.1 mrg 651 1.1 mrg if (d <= 1) 652 1.1 mrg { 653 1.1 mrg mode = -2; 654 1.1 mrg continue; 655 1.1 mrg } 656 1.1 mrg 657 1.1 mrg /* Find a suitable multiplier and right shift count 658 1.1 mrg instead of multiplying with D. */ 659 1.1 mrg mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int); 660 1.1 mrg 661 1.1 mrg /* If the suggested multiplier is more than SIZE bits, we can 662 1.1 mrg do better for even divisors, using an initial right shift. */ 663 1.1 mrg if ((mh != 0 && (d & 1) == 0) 664 1.1 mrg || (!has_vector_shift && pre_shift != -1)) 665 1.1 mrg { 666 1.1 mrg if (has_vector_shift) 667 1.1 mrg pre_shift = ctz_or_zero (d); 668 1.1 mrg else if (pre_shift == -1) 669 1.1 mrg { 670 1.1 mrg unsigned int j; 671 1.1 mrg for (j = 0; j < nunits; j++) 672 1.1 mrg { 673 1.1 mrg tree cst2 = VECTOR_CST_ELT (op1, j); 674 1.1 mrg unsigned HOST_WIDE_INT d2; 675 1.1 mrg int this_pre_shift; 676 1.1 mrg 677 1.1 mrg if (!tree_fits_uhwi_p (cst2)) 678 1.1 mrg return NULL_TREE; 679 1.1 mrg d2 = tree_to_uhwi (cst2) & mask; 680 1.1 mrg if (d2 == 0) 681 1.1 mrg return NULL_TREE; 682 1.1 mrg this_pre_shift = floor_log2 (d2 & -d2); 683 1.1 mrg if (pre_shift == -1 || this_pre_shift < pre_shift) 684 1.1 mrg pre_shift = this_pre_shift; 685 1.1 mrg } 686 1.1 mrg if (i != 0 && pre_shift != 0) 687 1.1 mrg { 688 1.1 mrg /* Restart. */ 689 1.1 mrg i = -1U; 690 1.1 mrg mode = -1; 691 1.1 mrg continue; 692 1.1 mrg } 693 1.1 mrg } 694 1.1 mrg if (pre_shift != 0) 695 1.1 mrg { 696 1.1 mrg if ((d >> pre_shift) <= 1) 697 1.1 mrg { 698 1.1 mrg mode = -2; 699 1.1 mrg continue; 700 1.1 mrg } 701 1.1 mrg mh = choose_multiplier (d >> pre_shift, prec, 702 1.1 mrg prec - pre_shift, 703 1.1 mrg &ml, &post_shift, &dummy_int); 704 1.1 mrg gcc_assert (!mh); 705 1.1 mrg pre_shifts[i] = pre_shift; 706 1.1 mrg } 707 1.1 mrg } 708 1.1 mrg if (!mh) 709 1.1 mrg this_mode = 0; 710 1.1 mrg else 711 1.1 mrg this_mode = 1; 712 1.1 mrg } 713 1.1 mrg else 714 1.1 mrg { 715 1.1 mrg HOST_WIDE_INT d = TREE_INT_CST_LOW (cst); 716 1.1 mrg unsigned HOST_WIDE_INT abs_d; 717 1.1 mrg 718 1.1 mrg if (d == -1) 719 1.1 mrg return NULL_TREE; 720 1.1 mrg 721 1.1 mrg /* Since d might be INT_MIN, we have to cast to 722 1.1 mrg unsigned HOST_WIDE_INT before negating to avoid 723 1.1 mrg undefined signed overflow. */ 724 1.1 mrg abs_d = (d >= 0 725 1.1 mrg ? (unsigned HOST_WIDE_INT) d 726 1.1 mrg : - (unsigned HOST_WIDE_INT) d); 727 1.1 mrg 728 1.1 mrg /* n rem d = n rem -d */ 729 1.1 mrg if (code == TRUNC_MOD_EXPR && d < 0) 730 1.1 mrg { 731 1.1 mrg d = abs_d; 732 1.1 mrg use_abs_op1 = true; 733 1.1 mrg } 734 1.1 mrg if (abs_d == HOST_WIDE_INT_1U << (prec - 1)) 735 1.1 mrg { 736 1.1 mrg /* This case is not handled correctly below. */ 737 1.1 mrg mode = -2; 738 1.1 mrg continue; 739 1.1 mrg } 740 1.1 mrg if (abs_d <= 1) 741 1.1 mrg { 742 1.1 mrg mode = -2; 743 1.1 mrg continue; 744 1.1 mrg } 745 1.1 mrg 746 1.1 mrg choose_multiplier (abs_d, prec, prec - 1, &ml, 747 1.1 mrg &post_shift, &dummy_int); 748 1.1 mrg if (ml >= HOST_WIDE_INT_1U << (prec - 1)) 749 1.1 mrg { 750 1.1 mrg this_mode = 4 + (d < 0); 751 1.1 mrg ml |= HOST_WIDE_INT_M1U << (prec - 1); 752 1.1 mrg } 753 1.1 mrg else 754 1.1 mrg this_mode = 2 + (d < 0); 755 1.1 mrg } 756 1.1 mrg mulc[i] = ml; 757 1.1 mrg post_shifts[i] = post_shift; 758 1.1 mrg if ((i && !has_vector_shift && post_shifts[0] != post_shift) 759 1.1 mrg || post_shift >= prec 760 1.1 mrg || pre_shifts[i] >= prec) 761 1.1 mrg this_mode = -2; 762 1.1 mrg 763 1.1 mrg if (i == 0) 764 1.1 mrg mode = this_mode; 765 1.1 mrg else if (mode != this_mode) 766 1.1 mrg mode = -2; 767 1.1 mrg } 768 1.1 mrg 769 1.1 mrg if (use_pow2) 770 1.1 mrg { 771 1.1 mrg tree addend = NULL_TREE; 772 1.1 mrg if (sign_p == SIGNED) 773 1.1 mrg { 774 1.1 mrg tree uns_type; 775 1.1 mrg 776 1.1 mrg /* Both division and remainder sequences need 777 1.1 mrg op0 < 0 ? mask : 0 computed. It can be either computed as 778 1.1 mrg (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i])) 779 1.1 mrg if none of the shifts is 0, or as the conditional. */ 780 1.1 mrg for (i = 0; i < nunits; i++) 781 1.1 mrg if (shifts[i] == 0) 782 1.1 mrg break; 783 1.1 mrg uns_type 784 1.1 mrg = build_vector_type (build_nonstandard_integer_type (prec, 1), 785 1.1 mrg nunits); 786 1.1 mrg if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type)) 787 1.1 mrg { 788 1.1 mrg for (i = 0; i < nunits; i++) 789 1.1 mrg shift_temps[i] = prec - 1; 790 1.1 mrg cur_op = add_rshift (gsi, type, op0, shift_temps); 791 1.1 mrg if (cur_op != NULL_TREE) 792 1.1 mrg { 793 1.1 mrg cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, 794 1.1 mrg uns_type, cur_op); 795 1.1 mrg for (i = 0; i < nunits; i++) 796 1.1 mrg shift_temps[i] = prec - shifts[i]; 797 1.1 mrg cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps); 798 1.1 mrg if (cur_op != NULL_TREE) 799 1.1 mrg addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, 800 1.1 mrg type, cur_op); 801 1.1 mrg } 802 1.1 mrg } 803 1.1 mrg if (addend == NULL_TREE 804 1.1 mrg && expand_vec_cond_expr_p (type, type, LT_EXPR)) 805 1.1 mrg { 806 1.1 mrg tree zero, cst, mask_type, mask; 807 1.1 mrg gimple *stmt, *cond; 808 1.1 mrg 809 1.1 mrg mask_type = truth_type_for (type); 810 1.1 mrg zero = build_zero_cst (type); 811 1.1 mrg mask = make_ssa_name (mask_type); 812 1.1 mrg cond = gimple_build_assign (mask, LT_EXPR, op0, zero); 813 1.1 mrg gsi_insert_before (gsi, cond, GSI_SAME_STMT); 814 1.1 mrg tree_vector_builder vec (type, nunits, 1); 815 1.1 mrg for (i = 0; i < nunits; i++) 816 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type), 817 1.1 mrg (HOST_WIDE_INT_1U 818 1.1 mrg << shifts[i]) - 1)); 819 1.1 mrg cst = vec.build (); 820 1.1 mrg addend = make_ssa_name (type); 821 1.1 mrg stmt 822 1.1 mrg = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero); 823 1.1 mrg gsi_insert_before (gsi, stmt, GSI_SAME_STMT); 824 1.1 mrg } 825 1.1 mrg } 826 1.1 mrg if (code == TRUNC_DIV_EXPR) 827 1.1 mrg { 828 1.1 mrg if (sign_p == UNSIGNED) 829 1.1 mrg { 830 1.1 mrg /* q = op0 >> shift; */ 831 1.1 mrg cur_op = add_rshift (gsi, type, op0, shifts); 832 1.1 mrg if (cur_op != NULL_TREE) 833 1.1 mrg return cur_op; 834 1.1 mrg } 835 1.1 mrg else if (addend != NULL_TREE) 836 1.1 mrg { 837 1.1 mrg /* t1 = op0 + addend; 838 1.1 mrg q = t1 >> shift; */ 839 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default); 840 1.1 mrg if (op != unknown_optab 841 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing) 842 1.1 mrg { 843 1.1 mrg cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend); 844 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, shifts); 845 1.1 mrg if (cur_op != NULL_TREE) 846 1.1 mrg return cur_op; 847 1.1 mrg } 848 1.1 mrg } 849 1.1 mrg } 850 1.1 mrg else 851 1.1 mrg { 852 1.1 mrg tree mask; 853 1.1 mrg tree_vector_builder vec (type, nunits, 1); 854 1.1 mrg for (i = 0; i < nunits; i++) 855 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type), 856 1.1 mrg (HOST_WIDE_INT_1U 857 1.1 mrg << shifts[i]) - 1)); 858 1.1 mrg mask = vec.build (); 859 1.1 mrg op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default); 860 1.1 mrg if (op != unknown_optab 861 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing) 862 1.1 mrg { 863 1.1 mrg if (sign_p == UNSIGNED) 864 1.1 mrg /* r = op0 & mask; */ 865 1.1 mrg return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask); 866 1.1 mrg else if (addend != NULL_TREE) 867 1.1 mrg { 868 1.1 mrg /* t1 = op0 + addend; 869 1.1 mrg t2 = t1 & mask; 870 1.1 mrg r = t2 - addend; */ 871 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default); 872 1.1 mrg if (op != unknown_optab 873 1.1 mrg && optab_handler (op, TYPE_MODE (type)) 874 1.1 mrg != CODE_FOR_nothing) 875 1.1 mrg { 876 1.1 mrg cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, 877 1.1 mrg addend); 878 1.1 mrg cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type, 879 1.1 mrg cur_op, mask); 880 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, 881 1.1 mrg optab_default); 882 1.1 mrg if (op != unknown_optab 883 1.1 mrg && optab_handler (op, TYPE_MODE (type)) 884 1.1 mrg != CODE_FOR_nothing) 885 1.1 mrg return gimplify_build2 (gsi, MINUS_EXPR, type, 886 1.1 mrg cur_op, addend); 887 1.1 mrg } 888 1.1 mrg } 889 1.1 mrg } 890 1.1 mrg } 891 1.1 mrg } 892 1.1 mrg 893 1.1 mrg if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) 894 1.1 mrg return NULL_TREE; 895 1.1 mrg 896 1.1 mrg if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type))) 897 1.1 mrg return NULL_TREE; 898 1.1 mrg 899 1.1 mrg cur_op = op0; 900 1.1 mrg 901 1.1 mrg switch (mode) 902 1.1 mrg { 903 1.1 mrg case 0: 904 1.1 mrg gcc_assert (sign_p == UNSIGNED); 905 1.1 mrg /* t1 = oprnd0 >> pre_shift; 906 1.1 mrg t2 = t1 h* ml; 907 1.1 mrg q = t2 >> post_shift; */ 908 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, pre_shifts); 909 1.1 mrg if (cur_op == NULL_TREE) 910 1.1 mrg return NULL_TREE; 911 1.1 mrg break; 912 1.1 mrg case 1: 913 1.1 mrg gcc_assert (sign_p == UNSIGNED); 914 1.1 mrg for (i = 0; i < nunits; i++) 915 1.1 mrg { 916 1.1 mrg shift_temps[i] = 1; 917 1.1 mrg post_shifts[i]--; 918 1.1 mrg } 919 1.1 mrg break; 920 1.1 mrg case 2: 921 1.1 mrg case 3: 922 1.1 mrg case 4: 923 1.1 mrg case 5: 924 1.1 mrg gcc_assert (sign_p == SIGNED); 925 1.1 mrg for (i = 0; i < nunits; i++) 926 1.1 mrg shift_temps[i] = prec - 1; 927 1.1 mrg break; 928 1.1 mrg default: 929 1.1 mrg return NULL_TREE; 930 1.1 mrg } 931 1.1 mrg 932 1.1 mrg tree_vector_builder vec (type, nunits, 1); 933 1.1 mrg for (i = 0; i < nunits; i++) 934 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i])); 935 1.1 mrg mulcst = vec.build (); 936 1.1 mrg 937 1.1 mrg cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst); 938 1.1 mrg 939 1.1 mrg switch (mode) 940 1.1 mrg { 941 1.1 mrg case 0: 942 1.1 mrg /* t1 = oprnd0 >> pre_shift; 943 1.1 mrg t2 = t1 h* ml; 944 1.1 mrg q = t2 >> post_shift; */ 945 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, post_shifts); 946 1.1 mrg break; 947 1.1 mrg case 1: 948 1.1 mrg /* t1 = oprnd0 h* ml; 949 1.1 mrg t2 = oprnd0 - t1; 950 1.1 mrg t3 = t2 >> 1; 951 1.1 mrg t4 = t1 + t3; 952 1.1 mrg q = t4 >> (post_shift - 1); */ 953 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default); 954 1.1 mrg if (op == unknown_optab 955 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 956 1.1 mrg return NULL_TREE; 957 1.1 mrg tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op); 958 1.1 mrg tem = add_rshift (gsi, type, tem, shift_temps); 959 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default); 960 1.1 mrg if (op == unknown_optab 961 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 962 1.1 mrg return NULL_TREE; 963 1.1 mrg tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem); 964 1.1 mrg cur_op = add_rshift (gsi, type, tem, post_shifts); 965 1.1 mrg if (cur_op == NULL_TREE) 966 1.1 mrg return NULL_TREE; 967 1.1 mrg break; 968 1.1 mrg case 2: 969 1.1 mrg case 3: 970 1.1 mrg case 4: 971 1.1 mrg case 5: 972 1.1 mrg /* t1 = oprnd0 h* ml; 973 1.1 mrg t2 = t1; [ iff (mode & 2) != 0 ] 974 1.1 mrg t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ] 975 1.1 mrg t3 = t2 >> post_shift; 976 1.1 mrg t4 = oprnd0 >> (prec - 1); 977 1.1 mrg q = t3 - t4; [ iff (mode & 1) == 0 ] 978 1.1 mrg q = t4 - t3; [ iff (mode & 1) != 0 ] */ 979 1.1 mrg if ((mode & 2) == 0) 980 1.1 mrg { 981 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default); 982 1.1 mrg if (op == unknown_optab 983 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 984 1.1 mrg return NULL_TREE; 985 1.1 mrg cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0); 986 1.1 mrg } 987 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, post_shifts); 988 1.1 mrg if (cur_op == NULL_TREE) 989 1.1 mrg return NULL_TREE; 990 1.1 mrg tem = add_rshift (gsi, type, op0, shift_temps); 991 1.1 mrg if (tem == NULL_TREE) 992 1.1 mrg return NULL_TREE; 993 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default); 994 1.1 mrg if (op == unknown_optab 995 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 996 1.1 mrg return NULL_TREE; 997 1.1 mrg if ((mode & 1) == 0) 998 1.1 mrg cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem); 999 1.1 mrg else 1000 1.1 mrg cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op); 1001 1.1 mrg break; 1002 1.1 mrg default: 1003 1.1 mrg gcc_unreachable (); 1004 1.1 mrg } 1005 1.1 mrg 1006 1.1 mrg if (code == TRUNC_DIV_EXPR) 1007 1.1 mrg return cur_op; 1008 1.1 mrg 1009 1.1 mrg /* We divided. Now finish by: 1010 1.1 mrg t1 = q * oprnd1; 1011 1.1 mrg r = oprnd0 - t1; */ 1012 1.1 mrg op = optab_for_tree_code (MULT_EXPR, type, optab_default); 1013 1.1 mrg if (op == unknown_optab 1014 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 1015 1.1 mrg return NULL_TREE; 1016 1.1 mrg if (use_abs_op1) 1017 1.1 mrg { 1018 1.1 mrg tree_vector_builder elts; 1019 1.1 mrg if (!elts.new_unary_operation (type, op1, false)) 1020 1.1 mrg return NULL_TREE; 1021 1.1 mrg unsigned int count = elts.encoded_nelts (); 1022 1.1 mrg for (unsigned int i = 0; i < count; ++i) 1023 1.1 mrg { 1024 1.1 mrg tree elem1 = VECTOR_CST_ELT (op1, i); 1025 1.1 mrg 1026 1.1 mrg tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1); 1027 1.1 mrg if (elt == NULL_TREE) 1028 1.1 mrg return NULL_TREE; 1029 1.1 mrg elts.quick_push (elt); 1030 1.1 mrg } 1031 1.1 mrg op1 = elts.build (); 1032 1.1 mrg } 1033 1.1 mrg tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1); 1034 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default); 1035 1.1 mrg if (op == unknown_optab 1036 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 1037 1.1 mrg return NULL_TREE; 1038 1.1 mrg return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem); 1039 1.1 mrg } 1040 1.1 mrg 1041 1.1 mrg /* Expand a vector condition to scalars, by using many conditions 1042 1.1 mrg on the vector's elements. */ 1043 1.1 mrg 1044 1.1 mrg static bool 1045 1.1 mrg expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names) 1046 1.1 mrg { 1047 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi)); 1048 1.1 mrg tree type = TREE_TYPE (gimple_assign_lhs (stmt)); 1049 1.1 mrg tree a = gimple_assign_rhs1 (stmt); 1050 1.1 mrg tree a1 = a; 1051 1.1 mrg tree a2 = NULL_TREE; 1052 1.1 mrg bool a_is_comparison = false; 1053 1.1 mrg bool a_is_scalar_bitmask = false; 1054 1.1 mrg tree b = gimple_assign_rhs2 (stmt); 1055 1.1 mrg tree c = gimple_assign_rhs3 (stmt); 1056 1.1 mrg vec<constructor_elt, va_gc> *v; 1057 1.1 mrg tree constr; 1058 1.1 mrg tree inner_type = TREE_TYPE (type); 1059 1.1 mrg tree width = vector_element_bits_tree (type); 1060 1.1 mrg tree cond_type = TREE_TYPE (TREE_TYPE (a)); 1061 1.1 mrg tree comp_inner_type = cond_type; 1062 1.1 mrg tree index = bitsize_int (0); 1063 1.1 mrg tree comp_width = width; 1064 1.1 mrg tree comp_index = index; 1065 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 1066 1.1 mrg tree_code code = TREE_CODE (a); 1067 1.1 mrg gassign *assign = NULL; 1068 1.1 mrg 1069 1.1 mrg if (code == SSA_NAME) 1070 1.1 mrg { 1071 1.1 mrg assign = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (a)); 1072 1.1 mrg if (assign != NULL 1073 1.1 mrg && TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison) 1074 1.1 mrg { 1075 1.1 mrg a_is_comparison = true; 1076 1.1 mrg a1 = gimple_assign_rhs1 (assign); 1077 1.1 mrg a2 = gimple_assign_rhs2 (assign); 1078 1.1 mrg code = gimple_assign_rhs_code (assign); 1079 1.1 mrg comp_inner_type = TREE_TYPE (TREE_TYPE (a1)); 1080 1.1 mrg comp_width = vector_element_bits_tree (TREE_TYPE (a1)); 1081 1.1 mrg } 1082 1.1 mrg } 1083 1.1 mrg 1084 1.1 mrg if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), code) 1085 1.1 mrg || (integer_all_onesp (b) && integer_zerop (c) 1086 1.1 mrg && expand_vec_cmp_expr_p (type, TREE_TYPE (a1), code))) 1087 1.1 mrg { 1088 1.1 mrg gcc_assert (TREE_CODE (a) == SSA_NAME || TREE_CODE (a) == VECTOR_CST); 1089 1.1 mrg return true; 1090 1.1 mrg } 1091 1.1 mrg 1092 1.1 mrg /* If a has vector boolean type and is a comparison, above 1093 1.1 mrg expand_vec_cond_expr_p might fail, even if both the comparison and 1094 1.1 mrg VEC_COND_EXPR could be supported individually. See PR109176. */ 1095 1.1 mrg if (a_is_comparison 1096 1.1 mrg && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)) 1097 1.1 mrg && expand_vec_cond_expr_p (type, TREE_TYPE (a), SSA_NAME) 1098 1.1 mrg && expand_vec_cmp_expr_p (TREE_TYPE (a1), TREE_TYPE (a), code)) 1099 1.1 mrg return true; 1100 1.1 mrg 1101 1.1 mrg /* Handle vector boolean types with bitmasks. If there is a comparison 1102 1.1 mrg and we can expand the comparison into the vector boolean bitmask, 1103 1.1 mrg or otherwise if it is compatible with type, we can transform 1104 1.1 mrg vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5; 1105 1.1 mrg into 1106 1.1 mrg tmp_6 = x_2 < y_3; 1107 1.1 mrg tmp_7 = tmp_6 & vbfld_4; 1108 1.1 mrg tmp_8 = ~tmp_6; 1109 1.1 mrg tmp_9 = tmp_8 & vbfld_5; 1110 1.1 mrg vbfld_1 = tmp_7 | tmp_9; 1111 1.1 mrg Similarly for vbfld_10 instead of x_2 < y_3. */ 1112 1.1 mrg if (VECTOR_BOOLEAN_TYPE_P (type) 1113 1.1 mrg && SCALAR_INT_MODE_P (TYPE_MODE (type)) 1114 1.1 mrg && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)), 1115 1.1 mrg TYPE_VECTOR_SUBPARTS (type) 1116 1.1 mrg * GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type)))) 1117 1.1 mrg && (a_is_comparison 1118 1.1 mrg ? useless_type_conversion_p (type, TREE_TYPE (a)) 1119 1.1 mrg : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a)))) 1120 1.1 mrg { 1121 1.1 mrg if (a_is_comparison) 1122 1.1 mrg a = gimplify_build2 (gsi, code, type, a1, a2); 1123 1.1 mrg a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b); 1124 1.1 mrg a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a); 1125 1.1 mrg a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c); 1126 1.1 mrg a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2); 1127 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, a); 1128 1.1 mrg update_stmt (gsi_stmt (*gsi)); 1129 1.1 mrg return true; 1130 1.1 mrg } 1131 1.1 mrg 1132 1.1 mrg /* TODO: try and find a smaller vector type. */ 1133 1.1 mrg 1134 1.1 mrg if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance)) 1135 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance, 1136 1.1 mrg "vector condition will be expanded piecewise"); 1137 1.1 mrg 1138 1.1 mrg if (!a_is_comparison 1139 1.1 mrg && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)) 1140 1.1 mrg && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a))) 1141 1.1 mrg && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))), 1142 1.1 mrg TYPE_VECTOR_SUBPARTS (TREE_TYPE (a)) 1143 1.1 mrg * GET_MODE_BITSIZE (SCALAR_TYPE_MODE 1144 1.1 mrg (TREE_TYPE (TREE_TYPE (a)))))) 1145 1.1 mrg { 1146 1.1 mrg a_is_scalar_bitmask = true; 1147 1.1 mrg int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a))); 1148 1.1 mrg tree atype = build_nonstandard_integer_type (prec, 1); 1149 1.1 mrg a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a); 1150 1.1 mrg } 1151 1.1 mrg else if (!a_is_comparison 1152 1.1 mrg && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))) 1153 1.1 mrg comp_width = vector_element_bits_tree (TREE_TYPE (a)); 1154 1.1 mrg 1155 1.1 mrg int nunits = nunits_for_known_piecewise_op (type); 1156 1.1 mrg vec_alloc (v, nunits); 1157 1.1 mrg bool constant_p = true; 1158 1.1 mrg for (int i = 0; i < nunits; i++) 1159 1.1 mrg { 1160 1.1 mrg tree aa, result; 1161 1.1 mrg tree bb = tree_vec_extract (gsi, inner_type, b, width, index); 1162 1.1 mrg tree cc = tree_vec_extract (gsi, inner_type, c, width, index); 1163 1.1 mrg if (a_is_comparison) 1164 1.1 mrg { 1165 1.1 mrg tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, 1166 1.1 mrg comp_width, comp_index); 1167 1.1 mrg tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, 1168 1.1 mrg comp_width, comp_index); 1169 1.1 mrg aa = build2 (code, cond_type, aa1, aa2); 1170 1.1 mrg } 1171 1.1 mrg else if (a_is_scalar_bitmask) 1172 1.1 mrg { 1173 1.1 mrg wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a))); 1174 1.1 mrg result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a), 1175 1.1 mrg a, wide_int_to_tree (TREE_TYPE (a), w)); 1176 1.1 mrg aa = build2 (NE_EXPR, boolean_type_node, result, 1177 1.1 mrg build_zero_cst (TREE_TYPE (a))); 1178 1.1 mrg } 1179 1.1 mrg else 1180 1.1 mrg aa = tree_vec_extract (gsi, cond_type, a, comp_width, comp_index); 1181 1.1 mrg result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc); 1182 1.1 mrg if (!CONSTANT_CLASS_P (result)) 1183 1.1 mrg constant_p = false; 1184 1.1 mrg constructor_elt ce = {NULL_TREE, result}; 1185 1.1 mrg v->quick_push (ce); 1186 1.1 mrg index = int_const_binop (PLUS_EXPR, index, width); 1187 1.1 mrg if (width == comp_width) 1188 1.1 mrg comp_index = index; 1189 1.1 mrg else 1190 1.1 mrg comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width); 1191 1.1 mrg } 1192 1.1 mrg 1193 1.1 mrg if (constant_p) 1194 1.1 mrg constr = build_vector_from_ctor (type, v); 1195 1.1 mrg else 1196 1.1 mrg constr = build_constructor (type, v); 1197 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, constr); 1198 1.1 mrg update_stmt (gsi_stmt (*gsi)); 1199 1.1 mrg 1200 1.1 mrg if (a_is_comparison) 1201 1.1 mrg bitmap_set_bit (dce_ssa_names, 1202 1.1 mrg SSA_NAME_VERSION (gimple_assign_lhs (assign))); 1203 1.1 mrg 1204 1.1 mrg return false; 1205 1.1 mrg } 1206 1.1 mrg 1207 1.1 mrg static tree 1208 1.1 mrg expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type, 1209 1.1 mrg gassign *assign, enum tree_code code, 1210 1.1 mrg bitmap dce_ssa_names) 1211 1.1 mrg { 1212 1.1 mrg machine_mode compute_mode = TYPE_MODE (compute_type); 1213 1.1 mrg 1214 1.1 mrg /* If the compute mode is not a vector mode (hence we are not decomposing 1215 1.1 mrg a BLKmode vector to smaller, hardware-supported vectors), we may want 1216 1.1 mrg to expand the operations in parallel. */ 1217 1.1 mrg if (!VECTOR_MODE_P (compute_mode)) 1218 1.1 mrg switch (code) 1219 1.1 mrg { 1220 1.1 mrg case PLUS_EXPR: 1221 1.1 mrg case MINUS_EXPR: 1222 1.1 mrg if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)) 1223 1.1 mrg return expand_vector_addition (gsi, do_binop, do_plus_minus, type, 1224 1.1 mrg gimple_assign_rhs1 (assign), 1225 1.1 mrg gimple_assign_rhs2 (assign), code); 1226 1.1 mrg break; 1227 1.1 mrg 1228 1.1 mrg case NEGATE_EXPR: 1229 1.1 mrg if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)) 1230 1.1 mrg return expand_vector_addition (gsi, do_unop, do_negate, type, 1231 1.1 mrg gimple_assign_rhs1 (assign), 1232 1.1 mrg NULL_TREE, code); 1233 1.1 mrg break; 1234 1.1 mrg 1235 1.1 mrg case BIT_AND_EXPR: 1236 1.1 mrg case BIT_IOR_EXPR: 1237 1.1 mrg case BIT_XOR_EXPR: 1238 1.1 mrg return expand_vector_parallel (gsi, do_binop, type, 1239 1.1 mrg gimple_assign_rhs1 (assign), 1240 1.1 mrg gimple_assign_rhs2 (assign), code); 1241 1.1 mrg 1242 1.1 mrg case BIT_NOT_EXPR: 1243 1.1 mrg return expand_vector_parallel (gsi, do_unop, type, 1244 1.1 mrg gimple_assign_rhs1 (assign), 1245 1.1 mrg NULL_TREE, code); 1246 1.1 mrg case EQ_EXPR: 1247 1.1 mrg case NE_EXPR: 1248 1.1 mrg case GT_EXPR: 1249 1.1 mrg case LT_EXPR: 1250 1.1 mrg case GE_EXPR: 1251 1.1 mrg case LE_EXPR: 1252 1.1 mrg case UNEQ_EXPR: 1253 1.1 mrg case UNGT_EXPR: 1254 1.1 mrg case UNLT_EXPR: 1255 1.1 mrg case UNGE_EXPR: 1256 1.1 mrg case UNLE_EXPR: 1257 1.1 mrg case LTGT_EXPR: 1258 1.1 mrg case ORDERED_EXPR: 1259 1.1 mrg case UNORDERED_EXPR: 1260 1.1 mrg { 1261 1.1 mrg tree rhs1 = gimple_assign_rhs1 (assign); 1262 1.1 mrg tree rhs2 = gimple_assign_rhs2 (assign); 1263 1.1 mrg 1264 1.1 mrg return expand_vector_comparison (gsi, type, rhs1, rhs2, code, 1265 1.1 mrg dce_ssa_names); 1266 1.1 mrg } 1267 1.1 mrg 1268 1.1 mrg case TRUNC_DIV_EXPR: 1269 1.1 mrg case TRUNC_MOD_EXPR: 1270 1.1 mrg { 1271 1.1 mrg tree rhs1 = gimple_assign_rhs1 (assign); 1272 1.1 mrg tree rhs2 = gimple_assign_rhs2 (assign); 1273 1.1 mrg tree ret; 1274 1.1 mrg 1275 1.1 mrg if (!optimize 1276 1.1 mrg || !VECTOR_INTEGER_TYPE_P (type) 1277 1.1 mrg || TREE_CODE (rhs2) != VECTOR_CST 1278 1.1 mrg || !VECTOR_MODE_P (TYPE_MODE (type))) 1279 1.1 mrg break; 1280 1.1 mrg 1281 1.1 mrg ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code); 1282 1.1 mrg if (ret != NULL_TREE) 1283 1.1 mrg return ret; 1284 1.1 mrg break; 1285 1.1 mrg } 1286 1.1 mrg 1287 1.1 mrg default: 1288 1.1 mrg break; 1289 1.1 mrg } 1290 1.1 mrg 1291 1.1 mrg if (TREE_CODE_CLASS (code) == tcc_unary) 1292 1.1 mrg return expand_vector_piecewise (gsi, do_unop, type, compute_type, 1293 1.1 mrg gimple_assign_rhs1 (assign), 1294 1.1 mrg NULL_TREE, code, false); 1295 1.1 mrg else 1296 1.1 mrg return expand_vector_piecewise (gsi, do_binop, type, compute_type, 1297 1.1 mrg gimple_assign_rhs1 (assign), 1298 1.1 mrg gimple_assign_rhs2 (assign), code, false); 1299 1.1 mrg } 1300 1.1 mrg 1301 1.1 mrg /* Try to optimize 1302 1.1 mrg a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 }; 1303 1.1 mrg style stmts into: 1304 1.1 mrg _9 = { b_7, b_7, b_7, b_7 }; 1305 1.1 mrg a_5 = _9 + { 0, 3, 6, 9 }; 1306 1.1 mrg because vector splat operation is usually more efficient 1307 1.1 mrg than piecewise initialization of the vector. */ 1308 1.1 mrg 1309 1.1 mrg static void 1310 1.1 mrg optimize_vector_constructor (gimple_stmt_iterator *gsi) 1311 1.1 mrg { 1312 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi)); 1313 1.1 mrg tree lhs = gimple_assign_lhs (stmt); 1314 1.1 mrg tree rhs = gimple_assign_rhs1 (stmt); 1315 1.1 mrg tree type = TREE_TYPE (rhs); 1316 1.1 mrg unsigned int i, j; 1317 1.1 mrg unsigned HOST_WIDE_INT nelts; 1318 1.1 mrg bool all_same = true; 1319 1.1 mrg constructor_elt *elt; 1320 1.1 mrg gimple *g; 1321 1.1 mrg tree base = NULL_TREE; 1322 1.1 mrg optab op; 1323 1.1 mrg 1324 1.1 mrg if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts) 1325 1.1 mrg || nelts <= 2 1326 1.1 mrg || CONSTRUCTOR_NELTS (rhs) != nelts) 1327 1.1 mrg return; 1328 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default); 1329 1.1 mrg if (op == unknown_optab 1330 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) 1331 1.1 mrg return; 1332 1.1 mrg FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt) 1333 1.1 mrg if (TREE_CODE (elt->value) != SSA_NAME 1334 1.1 mrg || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE) 1335 1.1 mrg return; 1336 1.1 mrg else 1337 1.1 mrg { 1338 1.1 mrg tree this_base = elt->value; 1339 1.1 mrg if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value) 1340 1.1 mrg all_same = false; 1341 1.1 mrg for (j = 0; j < nelts + 1; j++) 1342 1.1 mrg { 1343 1.1 mrg g = SSA_NAME_DEF_STMT (this_base); 1344 1.1 mrg if (is_gimple_assign (g) 1345 1.1 mrg && gimple_assign_rhs_code (g) == PLUS_EXPR 1346 1.1 mrg && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST 1347 1.1 mrg && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME 1348 1.1 mrg && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g))) 1349 1.1 mrg this_base = gimple_assign_rhs1 (g); 1350 1.1 mrg else 1351 1.1 mrg break; 1352 1.1 mrg } 1353 1.1 mrg if (i == 0) 1354 1.1 mrg base = this_base; 1355 1.1 mrg else if (this_base != base) 1356 1.1 mrg return; 1357 1.1 mrg } 1358 1.1 mrg if (all_same) 1359 1.1 mrg return; 1360 1.1 mrg tree_vector_builder cst (type, nelts, 1); 1361 1.1 mrg for (i = 0; i < nelts; i++) 1362 1.1 mrg { 1363 1.1 mrg tree this_base = CONSTRUCTOR_ELT (rhs, i)->value; 1364 1.1 mrg tree elt = build_zero_cst (TREE_TYPE (base)); 1365 1.1 mrg while (this_base != base) 1366 1.1 mrg { 1367 1.1 mrg g = SSA_NAME_DEF_STMT (this_base); 1368 1.1 mrg elt = fold_binary (PLUS_EXPR, TREE_TYPE (base), 1369 1.1 mrg elt, gimple_assign_rhs2 (g)); 1370 1.1 mrg if (elt == NULL_TREE 1371 1.1 mrg || TREE_CODE (elt) != INTEGER_CST 1372 1.1 mrg || TREE_OVERFLOW (elt)) 1373 1.1 mrg return; 1374 1.1 mrg this_base = gimple_assign_rhs1 (g); 1375 1.1 mrg } 1376 1.1 mrg cst.quick_push (elt); 1377 1.1 mrg } 1378 1.1 mrg for (i = 0; i < nelts; i++) 1379 1.1 mrg CONSTRUCTOR_ELT (rhs, i)->value = base; 1380 1.1 mrg g = gimple_build_assign (make_ssa_name (type), rhs); 1381 1.1 mrg gsi_insert_before (gsi, g, GSI_SAME_STMT); 1382 1.1 mrg g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g), 1383 1.1 mrg cst.build ()); 1384 1.1 mrg gsi_replace (gsi, g, false); 1385 1.1 mrg } 1386 1.1 mrg 1387 1.1 mrg /* Return a type for the widest vector mode with the same element type as 1389 1.1 mrg type ORIGINAL_VECTOR_TYPE, with at most the same number of elements as type 1390 1.1 mrg ORIGINAL_VECTOR_TYPE and that is supported by the target for an operation 1391 1.1 mrg with optab OP, or return NULL_TREE if none is found. */ 1392 1.1 mrg 1393 1.1 mrg static tree 1394 1.1 mrg type_for_widest_vector_mode (tree original_vector_type, optab op) 1395 1.1 mrg { 1396 1.1 mrg gcc_assert (VECTOR_TYPE_P (original_vector_type)); 1397 1.1 mrg tree type = TREE_TYPE (original_vector_type); 1398 1.1 mrg machine_mode inner_mode = TYPE_MODE (type); 1399 1.1 mrg machine_mode best_mode = VOIDmode, mode; 1400 1.1 mrg poly_int64 best_nunits = 0; 1401 1.1 mrg 1402 1.1 mrg if (SCALAR_FLOAT_MODE_P (inner_mode)) 1403 1.1 mrg mode = MIN_MODE_VECTOR_FLOAT; 1404 1.1 mrg else if (SCALAR_FRACT_MODE_P (inner_mode)) 1405 1.1 mrg mode = MIN_MODE_VECTOR_FRACT; 1406 1.1 mrg else if (SCALAR_UFRACT_MODE_P (inner_mode)) 1407 1.1 mrg mode = MIN_MODE_VECTOR_UFRACT; 1408 1.1 mrg else if (SCALAR_ACCUM_MODE_P (inner_mode)) 1409 1.1 mrg mode = MIN_MODE_VECTOR_ACCUM; 1410 1.1 mrg else if (SCALAR_UACCUM_MODE_P (inner_mode)) 1411 1.1 mrg mode = MIN_MODE_VECTOR_UACCUM; 1412 1.1 mrg else if (inner_mode == BImode) 1413 1.1 mrg mode = MIN_MODE_VECTOR_BOOL; 1414 1.1 mrg else 1415 1.1 mrg mode = MIN_MODE_VECTOR_INT; 1416 1.1 mrg 1417 1.1 mrg FOR_EACH_MODE_FROM (mode, mode) 1418 1.1 mrg if (GET_MODE_INNER (mode) == inner_mode 1419 1.1 mrg && maybe_gt (GET_MODE_NUNITS (mode), best_nunits) 1420 1.1 mrg && optab_handler (op, mode) != CODE_FOR_nothing 1421 1.1 mrg && known_le (GET_MODE_NUNITS (mode), 1422 1.1 mrg TYPE_VECTOR_SUBPARTS (original_vector_type))) 1423 1.1 mrg best_mode = mode, best_nunits = GET_MODE_NUNITS (mode); 1424 1.1 mrg 1425 1.1 mrg if (best_mode == VOIDmode) 1426 1.1 mrg return NULL_TREE; 1427 1.1 mrg else 1428 1.1 mrg return build_vector_type_for_mode (type, best_mode); 1429 1.1 mrg } 1430 1.1 mrg 1431 1.1 mrg 1432 1.1 mrg /* Build a reference to the element of the vector VECT. Function 1433 1.1 mrg returns either the element itself, either BIT_FIELD_REF, or an 1434 1.1 mrg ARRAY_REF expression. 1435 1.1 mrg 1436 1.1 mrg GSI is required to insert temporary variables while building a 1437 1.1 mrg refernece to the element of the vector VECT. 1438 1.1 mrg 1439 1.1 mrg PTMPVEC is a pointer to the temporary variable for caching 1440 1.1 mrg purposes. In case when PTMPVEC is NULL new temporary variable 1441 1.1 mrg will be created. */ 1442 1.1 mrg static tree 1443 1.1 mrg vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec) 1444 1.1 mrg { 1445 1.1 mrg tree vect_type, vect_elt_type; 1446 1.1 mrg gimple *asgn; 1447 1.1 mrg tree tmpvec; 1448 1.1 mrg tree arraytype; 1449 1.1 mrg bool need_asgn = true; 1450 1.1 mrg unsigned int elements; 1451 1.1 mrg 1452 1.1 mrg vect_type = TREE_TYPE (vect); 1453 1.1 mrg vect_elt_type = TREE_TYPE (vect_type); 1454 1.1 mrg elements = nunits_for_known_piecewise_op (vect_type); 1455 1.1 mrg 1456 1.1 mrg if (TREE_CODE (idx) == INTEGER_CST) 1457 1.1 mrg { 1458 1.1 mrg unsigned HOST_WIDE_INT index; 1459 1.1 mrg 1460 1.1 mrg /* Given that we're about to compute a binary modulus, 1461 1.1 mrg we don't care about the high bits of the value. */ 1462 1.1 mrg index = TREE_INT_CST_LOW (idx); 1463 1.1 mrg if (!tree_fits_uhwi_p (idx) || index >= elements) 1464 1.1 mrg { 1465 1.1 mrg index &= elements - 1; 1466 1.1 mrg idx = build_int_cst (TREE_TYPE (idx), index); 1467 1.1 mrg } 1468 1.1 mrg 1469 1.1 mrg /* When lowering a vector statement sequence do some easy 1470 1.1 mrg simplification by looking through intermediate vector results. */ 1471 1.1 mrg if (TREE_CODE (vect) == SSA_NAME) 1472 1.1 mrg { 1473 1.1 mrg gimple *def_stmt = SSA_NAME_DEF_STMT (vect); 1474 1.1 mrg if (is_gimple_assign (def_stmt) 1475 1.1 mrg && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST 1476 1.1 mrg || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR)) 1477 1.1 mrg vect = gimple_assign_rhs1 (def_stmt); 1478 1.1 mrg } 1479 1.1 mrg 1480 1.1 mrg if (TREE_CODE (vect) == VECTOR_CST) 1481 1.1 mrg return VECTOR_CST_ELT (vect, index); 1482 1.1 mrg else if (TREE_CODE (vect) == CONSTRUCTOR 1483 1.1 mrg && (CONSTRUCTOR_NELTS (vect) == 0 1484 1.1 mrg || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value)) 1485 1.1 mrg != VECTOR_TYPE)) 1486 1.1 mrg { 1487 1.1 mrg if (index < CONSTRUCTOR_NELTS (vect)) 1488 1.1 mrg return CONSTRUCTOR_ELT (vect, index)->value; 1489 1.1 mrg return build_zero_cst (vect_elt_type); 1490 1.1 mrg } 1491 1.1 mrg else 1492 1.1 mrg { 1493 1.1 mrg tree size = vector_element_bits_tree (vect_type); 1494 1.1 mrg tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index), 1495 1.1 mrg size); 1496 1.1 mrg return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos); 1497 1.1 mrg } 1498 1.1 mrg } 1499 1.1 mrg 1500 1.1 mrg if (!ptmpvec) 1501 1.1 mrg tmpvec = create_tmp_var (vect_type, "vectmp"); 1502 1.1 mrg else if (!*ptmpvec) 1503 1.1 mrg tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp"); 1504 1.1 mrg else 1505 1.1 mrg { 1506 1.1 mrg tmpvec = *ptmpvec; 1507 1.1 mrg need_asgn = false; 1508 1.1 mrg } 1509 1.1 mrg 1510 1.1 mrg if (need_asgn) 1511 1.1 mrg { 1512 1.1 mrg TREE_ADDRESSABLE (tmpvec) = 1; 1513 1.1 mrg asgn = gimple_build_assign (tmpvec, vect); 1514 1.1 mrg gsi_insert_before (gsi, asgn, GSI_SAME_STMT); 1515 1.1 mrg } 1516 1.1 mrg 1517 1.1 mrg arraytype = build_array_type_nelts (vect_elt_type, elements); 1518 1.1 mrg return build4 (ARRAY_REF, vect_elt_type, 1519 1.1 mrg build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec), 1520 1.1 mrg idx, NULL_TREE, NULL_TREE); 1521 1.1 mrg } 1522 1.1 mrg 1523 1.1 mrg /* Check if VEC_PERM_EXPR within the given setting is supported 1524 1.1 mrg by hardware, or lower it piecewise. 1525 1.1 mrg 1526 1.1 mrg When VEC_PERM_EXPR has the same first and second operands: 1527 1.1 mrg VEC_PERM_EXPR <v0, v0, mask> the lowered version would be 1528 1.1 mrg {v0[mask[0]], v0[mask[1]], ...} 1529 1.1 mrg MASK and V0 must have the same number of elements. 1530 1.1 mrg 1531 1.1 mrg Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to 1532 1.1 mrg {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...} 1533 1.1 mrg V0 and V1 must have the same type. MASK, V0, V1 must have the 1534 1.1 mrg same number of arguments. */ 1535 1.1 mrg 1536 1.1 mrg static void 1537 1.1 mrg lower_vec_perm (gimple_stmt_iterator *gsi) 1538 1.1 mrg { 1539 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi)); 1540 1.1 mrg tree mask = gimple_assign_rhs3 (stmt); 1541 1.1 mrg tree vec0 = gimple_assign_rhs1 (stmt); 1542 1.1 mrg tree vec1 = gimple_assign_rhs2 (stmt); 1543 1.1 mrg tree vect_type = TREE_TYPE (vec0); 1544 1.1 mrg tree mask_type = TREE_TYPE (mask); 1545 1.1 mrg tree vect_elt_type = TREE_TYPE (vect_type); 1546 1.1 mrg tree mask_elt_type = TREE_TYPE (mask_type); 1547 1.1 mrg unsigned HOST_WIDE_INT elements; 1548 1.1 mrg vec<constructor_elt, va_gc> *v; 1549 1.1 mrg tree constr, t, si, i_val; 1550 1.1 mrg tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE; 1551 1.1 mrg bool two_operand_p = !operand_equal_p (vec0, vec1, 0); 1552 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 1553 1.1 mrg unsigned i; 1554 1.1 mrg 1555 1.1 mrg if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements)) 1556 1.1 mrg return; 1557 1.1 mrg 1558 1.1 mrg if (TREE_CODE (mask) == SSA_NAME) 1559 1.1 mrg { 1560 1.1 mrg gimple *def_stmt = SSA_NAME_DEF_STMT (mask); 1561 1.1 mrg if (is_gimple_assign (def_stmt) 1562 1.1 mrg && gimple_assign_rhs_code (def_stmt) == VECTOR_CST) 1563 1.1 mrg mask = gimple_assign_rhs1 (def_stmt); 1564 1.1 mrg } 1565 1.1 mrg 1566 1.1 mrg vec_perm_builder sel_int; 1567 1.1 mrg 1568 1.1 mrg if (TREE_CODE (mask) == VECTOR_CST 1569 1.1 mrg && tree_to_vec_perm_builder (&sel_int, mask)) 1570 1.1 mrg { 1571 1.1 mrg vec_perm_indices indices (sel_int, 2, elements); 1572 1.1 mrg if (can_vec_perm_const_p (TYPE_MODE (vect_type), indices)) 1573 1.1 mrg { 1574 1.1 mrg gimple_assign_set_rhs3 (stmt, mask); 1575 1.1 mrg update_stmt (stmt); 1576 1.1 mrg return; 1577 1.1 mrg } 1578 1.1 mrg /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero 1579 1.1 mrg vector as VEC1 and a right element shift MASK. */ 1580 1.1 mrg if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type)) 1581 1.1 mrg != CODE_FOR_nothing 1582 1.1 mrg && TREE_CODE (vec1) == VECTOR_CST 1583 1.1 mrg && initializer_zerop (vec1) 1584 1.1 mrg && maybe_ne (indices[0], 0) 1585 1.1 mrg && known_lt (poly_uint64 (indices[0]), elements)) 1586 1.1 mrg { 1587 1.1 mrg bool ok_p = indices.series_p (0, 1, indices[0], 1); 1588 1.1 mrg if (!ok_p) 1589 1.1 mrg { 1590 1.1 mrg for (i = 1; i < elements; ++i) 1591 1.1 mrg { 1592 1.1 mrg poly_uint64 actual = indices[i]; 1593 1.1 mrg poly_uint64 expected = i + indices[0]; 1594 1.1 mrg /* Indices into the second vector are all equivalent. */ 1595 1.1 mrg if (maybe_lt (actual, elements) 1596 1.1 mrg ? maybe_ne (actual, expected) 1597 1.1 mrg : maybe_lt (expected, elements)) 1598 1.1 mrg break; 1599 1.1 mrg } 1600 1.1 mrg ok_p = i == elements; 1601 1.1 mrg } 1602 1.1 mrg if (ok_p) 1603 1.1 mrg { 1604 1.1 mrg gimple_assign_set_rhs3 (stmt, mask); 1605 1.1 mrg update_stmt (stmt); 1606 1.1 mrg return; 1607 1.1 mrg } 1608 1.1 mrg } 1609 1.1 mrg /* And similarly vec_shl pattern. */ 1610 1.1 mrg if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type)) 1611 1.1 mrg != CODE_FOR_nothing 1612 1.1 mrg && TREE_CODE (vec0) == VECTOR_CST 1613 1.1 mrg && initializer_zerop (vec0)) 1614 1.1 mrg { 1615 1.1 mrg unsigned int first = 0; 1616 1.1 mrg for (i = 0; i < elements; ++i) 1617 1.1 mrg if (known_eq (poly_uint64 (indices[i]), elements)) 1618 1.1 mrg { 1619 1.1 mrg if (i == 0 || first) 1620 1.1 mrg break; 1621 1.1 mrg first = i; 1622 1.1 mrg } 1623 1.1 mrg else if (first 1624 1.1 mrg ? maybe_ne (poly_uint64 (indices[i]), 1625 1.1 mrg elements + i - first) 1626 1.1 mrg : maybe_ge (poly_uint64 (indices[i]), elements)) 1627 1.1 mrg break; 1628 1.1 mrg if (first && i == elements) 1629 1.1 mrg { 1630 1.1 mrg gimple_assign_set_rhs3 (stmt, mask); 1631 1.1 mrg update_stmt (stmt); 1632 1.1 mrg return; 1633 1.1 mrg } 1634 1.1 mrg } 1635 1.1 mrg } 1636 1.1 mrg else if (can_vec_perm_var_p (TYPE_MODE (vect_type))) 1637 1.1 mrg return; 1638 1.1 mrg 1639 1.1 mrg if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance)) 1640 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance, 1641 1.1 mrg "vector shuffling operation will be expanded piecewise"); 1642 1.1 mrg 1643 1.1 mrg vec_alloc (v, elements); 1644 1.1 mrg bool constant_p = true; 1645 1.1 mrg for (i = 0; i < elements; i++) 1646 1.1 mrg { 1647 1.1 mrg si = size_int (i); 1648 1.1 mrg i_val = vector_element (gsi, mask, si, &masktmp); 1649 1.1 mrg 1650 1.1 mrg if (TREE_CODE (i_val) == INTEGER_CST) 1651 1.1 mrg { 1652 1.1 mrg unsigned HOST_WIDE_INT index; 1653 1.1 mrg 1654 1.1 mrg index = TREE_INT_CST_LOW (i_val); 1655 1.1 mrg if (!tree_fits_uhwi_p (i_val) || index >= elements) 1656 1.1 mrg i_val = build_int_cst (mask_elt_type, index & (elements - 1)); 1657 1.1 mrg 1658 1.1 mrg if (two_operand_p && (index & elements) != 0) 1659 1.1 mrg t = vector_element (gsi, vec1, i_val, &vec1tmp); 1660 1.1 mrg else 1661 1.1 mrg t = vector_element (gsi, vec0, i_val, &vec0tmp); 1662 1.1 mrg 1663 1.1 mrg t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, 1664 1.1 mrg true, GSI_SAME_STMT); 1665 1.1 mrg } 1666 1.1 mrg else 1667 1.1 mrg { 1668 1.1 mrg tree cond = NULL_TREE, v0_val; 1669 1.1 mrg 1670 1.1 mrg if (two_operand_p) 1671 1.1 mrg { 1672 1.1 mrg cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val, 1673 1.1 mrg build_int_cst (mask_elt_type, elements)); 1674 1.1 mrg cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, 1675 1.1 mrg true, GSI_SAME_STMT); 1676 1.1 mrg } 1677 1.1 mrg 1678 1.1 mrg i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val, 1679 1.1 mrg build_int_cst (mask_elt_type, elements - 1)); 1680 1.1 mrg i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE, 1681 1.1 mrg true, GSI_SAME_STMT); 1682 1.1 mrg 1683 1.1 mrg v0_val = vector_element (gsi, vec0, i_val, &vec0tmp); 1684 1.1 mrg v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE, 1685 1.1 mrg true, GSI_SAME_STMT); 1686 1.1 mrg 1687 1.1 mrg if (two_operand_p) 1688 1.1 mrg { 1689 1.1 mrg tree v1_val; 1690 1.1 mrg 1691 1.1 mrg v1_val = vector_element (gsi, vec1, i_val, &vec1tmp); 1692 1.1 mrg v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE, 1693 1.1 mrg true, GSI_SAME_STMT); 1694 1.1 mrg 1695 1.1 mrg cond = fold_build2 (EQ_EXPR, boolean_type_node, 1696 1.1 mrg cond, build_zero_cst (mask_elt_type)); 1697 1.1 mrg cond = fold_build3 (COND_EXPR, vect_elt_type, 1698 1.1 mrg cond, v0_val, v1_val); 1699 1.1 mrg t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, 1700 1.1 mrg true, GSI_SAME_STMT); 1701 1.1 mrg } 1702 1.1 mrg else 1703 1.1 mrg t = v0_val; 1704 1.1 mrg } 1705 1.1 mrg 1706 1.1 mrg if (!CONSTANT_CLASS_P (t)) 1707 1.1 mrg constant_p = false; 1708 1.1 mrg CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t); 1709 1.1 mrg } 1710 1.1 mrg 1711 1.1 mrg if (constant_p) 1712 1.1 mrg constr = build_vector_from_ctor (vect_type, v); 1713 1.1 mrg else 1714 1.1 mrg constr = build_constructor (vect_type, v); 1715 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, constr); 1716 1.1 mrg update_stmt (gsi_stmt (*gsi)); 1717 1.1 mrg } 1718 1.1 mrg 1719 1.1 mrg /* If OP is a uniform vector return the element it is a splat from. */ 1720 1.1 mrg 1721 1.1 mrg static tree 1722 1.1 mrg ssa_uniform_vector_p (tree op) 1723 1.1 mrg { 1724 1.1 mrg if (TREE_CODE (op) == VECTOR_CST 1725 1.1 mrg || TREE_CODE (op) == VEC_DUPLICATE_EXPR 1726 1.1 mrg || TREE_CODE (op) == CONSTRUCTOR) 1727 1.1 mrg return uniform_vector_p (op); 1728 1.1 mrg if (TREE_CODE (op) == SSA_NAME) 1729 1.1 mrg { 1730 1.1 mrg gimple *def_stmt = SSA_NAME_DEF_STMT (op); 1731 1.1 mrg if (gimple_assign_single_p (def_stmt)) 1732 1.1 mrg return uniform_vector_p (gimple_assign_rhs1 (def_stmt)); 1733 1.1 mrg } 1734 1.1 mrg return NULL_TREE; 1735 1.1 mrg } 1736 1.1 mrg 1737 1.1 mrg /* Return type in which CODE operation with optab OP can be 1738 1.1 mrg computed. */ 1739 1.1 mrg 1740 1.1 mrg static tree 1741 1.1 mrg get_compute_type (enum tree_code code, optab op, tree type) 1742 1.1 mrg { 1743 1.1 mrg /* For very wide vectors, try using a smaller vector mode. */ 1744 1.1 mrg tree compute_type = type; 1745 1.1 mrg if (op 1746 1.1 mrg && (!VECTOR_MODE_P (TYPE_MODE (type)) 1747 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)) 1748 1.1 mrg { 1749 1.1 mrg tree vector_compute_type 1750 1.1 mrg = type_for_widest_vector_mode (type, op); 1751 1.1 mrg if (vector_compute_type != NULL_TREE 1752 1.1 mrg && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U) 1753 1.1 mrg && (optab_handler (op, TYPE_MODE (vector_compute_type)) 1754 1.1 mrg != CODE_FOR_nothing)) 1755 1.1 mrg compute_type = vector_compute_type; 1756 1.1 mrg } 1757 1.1 mrg 1758 1.1 mrg /* If we are breaking a BLKmode vector into smaller pieces, 1759 1.1 mrg type_for_widest_vector_mode has already looked into the optab, 1760 1.1 mrg so skip these checks. */ 1761 1.1 mrg if (compute_type == type) 1762 1.1 mrg { 1763 1.1 mrg machine_mode compute_mode = TYPE_MODE (compute_type); 1764 1.1 mrg if (VECTOR_MODE_P (compute_mode)) 1765 1.1 mrg { 1766 1.1 mrg if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing) 1767 1.1 mrg return compute_type; 1768 1.1 mrg if (code == MULT_HIGHPART_EXPR 1769 1.1 mrg && can_mult_highpart_p (compute_mode, 1770 1.1 mrg TYPE_UNSIGNED (compute_type))) 1771 1.1 mrg return compute_type; 1772 1.1 mrg } 1773 1.1 mrg /* There is no operation in hardware, so fall back to scalars. */ 1774 1.1 mrg compute_type = TREE_TYPE (type); 1775 1.1 mrg } 1776 1.1 mrg 1777 1.1 mrg return compute_type; 1778 1.1 mrg } 1779 1.1 mrg 1780 1.1 mrg static tree 1781 1.1 mrg do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b, 1782 1.1 mrg tree bitpos, tree bitsize, enum tree_code code, 1783 1.1 mrg tree type ATTRIBUTE_UNUSED) 1784 1.1 mrg { 1785 1.1 mrg if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE) 1786 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos); 1787 1.1 mrg if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE) 1788 1.1 mrg b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos); 1789 1.1 mrg tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi)); 1790 1.1 mrg return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b); 1791 1.1 mrg } 1792 1.1 mrg 1793 1.1 mrg /* Expand a vector COND_EXPR to scalars, piecewise. */ 1794 1.1 mrg static void 1795 1.1 mrg expand_vector_scalar_condition (gimple_stmt_iterator *gsi) 1796 1.1 mrg { 1797 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi)); 1798 1.1 mrg tree lhs = gimple_assign_lhs (stmt); 1799 1.1 mrg tree type = TREE_TYPE (lhs); 1800 1.1 mrg tree compute_type = get_compute_type (COND_EXPR, mov_optab, type); 1801 1.1 mrg machine_mode compute_mode = TYPE_MODE (compute_type); 1802 1.1 mrg gcc_assert (compute_mode != BLKmode); 1803 1.1 mrg tree rhs2 = gimple_assign_rhs2 (stmt); 1804 1.1 mrg tree rhs3 = gimple_assign_rhs3 (stmt); 1805 1.1 mrg tree new_rhs; 1806 1.1 mrg 1807 1.1 mrg /* If the compute mode is not a vector mode (hence we are not decomposing 1808 1.1 mrg a BLKmode vector to smaller, hardware-supported vectors), we may want 1809 1.1 mrg to expand the operations in parallel. */ 1810 1.1 mrg if (!VECTOR_MODE_P (compute_mode)) 1811 1.1 mrg new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3, 1812 1.1 mrg COND_EXPR); 1813 1.1 mrg else 1814 1.1 mrg new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type, 1815 1.1 mrg rhs2, rhs3, COND_EXPR, false); 1816 1.1 mrg if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs))) 1817 1.1 mrg new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), 1818 1.1 mrg new_rhs); 1819 1.1 mrg 1820 1.1 mrg /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One 1821 1.1 mrg way to do it is change expand_vector_operation and its callees to 1822 1.1 mrg return a tree_code, RHS1 and RHS2 instead of a tree. */ 1823 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, new_rhs); 1824 1.1 mrg update_stmt (gsi_stmt (*gsi)); 1825 1.1 mrg } 1826 1.1 mrg 1827 1.1 mrg /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call 1828 1.1 mrg lowering. If INNER_TYPE is not a vector type, this is a scalar 1829 1.1 mrg fallback. */ 1830 1.1 mrg 1831 1.1 mrg static tree 1832 1.1 mrg do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a, 1833 1.1 mrg tree decl, tree bitpos, tree bitsize, 1834 1.1 mrg enum tree_code code, tree type) 1835 1.1 mrg { 1836 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos); 1837 1.1 mrg if (!VECTOR_TYPE_P (inner_type)) 1838 1.1 mrg return gimplify_build1 (gsi, code, TREE_TYPE (type), a); 1839 1.1 mrg if (code == CALL_EXPR) 1840 1.1 mrg { 1841 1.1 mrg gimple *g = gimple_build_call (decl, 1, a); 1842 1.1 mrg tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl))); 1843 1.1 mrg gimple_call_set_lhs (g, lhs); 1844 1.1 mrg gsi_insert_before (gsi, g, GSI_SAME_STMT); 1845 1.1 mrg return lhs; 1846 1.1 mrg } 1847 1.1 mrg else 1848 1.1 mrg { 1849 1.1 mrg tree outer_type = build_vector_type (TREE_TYPE (type), 1850 1.1 mrg TYPE_VECTOR_SUBPARTS (inner_type)); 1851 1.1 mrg return gimplify_build1 (gsi, code, outer_type, a); 1852 1.1 mrg } 1853 1.1 mrg } 1854 1.1 mrg 1855 1.1 mrg /* Similarly, but for narrowing conversion. */ 1856 1.1 mrg 1857 1.1 mrg static tree 1858 1.1 mrg do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a, 1859 1.1 mrg tree, tree bitpos, tree, enum tree_code code, 1860 1.1 mrg tree type) 1861 1.1 mrg { 1862 1.1 mrg tree itype = build_vector_type (TREE_TYPE (inner_type), 1863 1.1 mrg exact_div (TYPE_VECTOR_SUBPARTS (inner_type), 1864 1.1 mrg 2)); 1865 1.1 mrg tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos); 1866 1.1 mrg tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), 1867 1.1 mrg int_const_binop (PLUS_EXPR, bitpos, 1868 1.1 mrg TYPE_SIZE (itype))); 1869 1.1 mrg tree outer_type = build_vector_type (TREE_TYPE (type), 1870 1.1 mrg TYPE_VECTOR_SUBPARTS (inner_type)); 1871 1.1 mrg return gimplify_build2 (gsi, code, outer_type, b, c); 1872 1.1 mrg } 1873 1.1 mrg 1874 1.1 mrg /* Expand VEC_CONVERT ifn call. */ 1875 1.1 mrg 1876 1.1 mrg static void 1877 1.1 mrg expand_vector_conversion (gimple_stmt_iterator *gsi) 1878 1.1 mrg { 1879 1.1 mrg gimple *stmt = gsi_stmt (*gsi); 1880 1.1 mrg gimple *g; 1881 1.1 mrg tree lhs = gimple_call_lhs (stmt); 1882 1.1 mrg if (lhs == NULL_TREE) 1883 1.1 mrg { 1884 1.1 mrg g = gimple_build_nop (); 1885 1.1 mrg gsi_replace (gsi, g, false); 1886 1.1 mrg return; 1887 1.1 mrg } 1888 1.1 mrg tree arg = gimple_call_arg (stmt, 0); 1889 1.1 mrg tree ret_type = TREE_TYPE (lhs); 1890 1.1 mrg tree arg_type = TREE_TYPE (arg); 1891 1.1 mrg tree new_rhs, compute_type = TREE_TYPE (arg_type); 1892 1.1 mrg enum tree_code code = NOP_EXPR; 1893 1.1 mrg enum tree_code code1 = ERROR_MARK; 1894 1.1 mrg enum { NARROW, NONE, WIDEN } modifier = NONE; 1895 1.1 mrg optab optab1 = unknown_optab; 1896 1.1 mrg 1897 1.1 mrg gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type)); 1898 1.1 mrg if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type)) 1899 1.1 mrg && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type))) 1900 1.1 mrg code = FIX_TRUNC_EXPR; 1901 1.1 mrg else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type)) 1902 1.1 mrg && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type))) 1903 1.1 mrg code = FLOAT_EXPR; 1904 1.1 mrg unsigned int ret_elt_bits = vector_element_bits (ret_type); 1905 1.1 mrg unsigned int arg_elt_bits = vector_element_bits (arg_type); 1906 1.1 mrg if (ret_elt_bits < arg_elt_bits) 1907 1.1 mrg modifier = NARROW; 1908 1.1 mrg else if (ret_elt_bits > arg_elt_bits) 1909 1.1 mrg modifier = WIDEN; 1910 1.1 mrg 1911 1.1 mrg if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR)) 1912 1.1 mrg { 1913 1.1 mrg if (supportable_convert_operation (code, ret_type, arg_type, &code1)) 1914 1.1 mrg { 1915 1.1 mrg g = gimple_build_assign (lhs, code1, arg); 1916 1.1 mrg gsi_replace (gsi, g, false); 1917 1.1 mrg return; 1918 1.1 mrg } 1919 1.1 mrg /* Can't use get_compute_type here, as supportable_convert_operation 1920 1.1 mrg doesn't necessarily use an optab and needs two arguments. */ 1921 1.1 mrg tree vec_compute_type 1922 1.1 mrg = type_for_widest_vector_mode (arg_type, mov_optab); 1923 1.1 mrg if (vec_compute_type 1924 1.1 mrg && VECTOR_MODE_P (TYPE_MODE (vec_compute_type))) 1925 1.1 mrg { 1926 1.1 mrg unsigned HOST_WIDE_INT nelts 1927 1.1 mrg = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type)); 1928 1.1 mrg while (nelts > 1) 1929 1.1 mrg { 1930 1.1 mrg tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts); 1931 1.1 mrg tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts); 1932 1.1 mrg if (supportable_convert_operation (code, ret1_type, arg1_type, 1933 1.1 mrg &code1)) 1934 1.1 mrg { 1935 1.1 mrg new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, 1936 1.1 mrg ret_type, arg1_type, arg, 1937 1.1 mrg NULL_TREE, code1, false); 1938 1.1 mrg g = gimple_build_assign (lhs, new_rhs); 1939 1.1 mrg gsi_replace (gsi, g, false); 1940 1.1 mrg return; 1941 1.1 mrg } 1942 1.1 mrg nelts = nelts / 2; 1943 1.1 mrg } 1944 1.1 mrg } 1945 1.1 mrg } 1946 1.1 mrg else if (modifier == NARROW) 1947 1.1 mrg { 1948 1.1 mrg switch (code) 1949 1.1 mrg { 1950 1.1 mrg CASE_CONVERT: 1951 1.1 mrg code1 = VEC_PACK_TRUNC_EXPR; 1952 1.1 mrg optab1 = optab_for_tree_code (code1, arg_type, optab_default); 1953 1.1 mrg break; 1954 1.1 mrg case FIX_TRUNC_EXPR: 1955 1.1 mrg code1 = VEC_PACK_FIX_TRUNC_EXPR; 1956 1.1 mrg /* The signedness is determined from output operand. */ 1957 1.1 mrg optab1 = optab_for_tree_code (code1, ret_type, optab_default); 1958 1.1 mrg break; 1959 1.1 mrg case FLOAT_EXPR: 1960 1.1 mrg code1 = VEC_PACK_FLOAT_EXPR; 1961 1.1 mrg optab1 = optab_for_tree_code (code1, arg_type, optab_default); 1962 1.1 mrg break; 1963 1.1 mrg default: 1964 1.1 mrg gcc_unreachable (); 1965 1.1 mrg } 1966 1.1 mrg 1967 1.1 mrg if (optab1) 1968 1.1 mrg compute_type = get_compute_type (code1, optab1, arg_type); 1969 1.1 mrg enum insn_code icode1; 1970 1.1 mrg if (VECTOR_TYPE_P (compute_type) 1971 1.1 mrg && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type))) 1972 1.1 mrg != CODE_FOR_nothing) 1973 1.1 mrg && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)) 1974 1.1 mrg { 1975 1.1 mrg tree cretd_type 1976 1.1 mrg = build_vector_type (TREE_TYPE (ret_type), 1977 1.1 mrg TYPE_VECTOR_SUBPARTS (compute_type) * 2); 1978 1.1 mrg if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type)) 1979 1.1 mrg { 1980 1.1 mrg if (compute_type == arg_type) 1981 1.1 mrg { 1982 1.1 mrg new_rhs = gimplify_build2 (gsi, code1, cretd_type, 1983 1.1 mrg arg, build_zero_cst (arg_type)); 1984 1.1 mrg new_rhs = tree_vec_extract (gsi, ret_type, new_rhs, 1985 1.1 mrg TYPE_SIZE (ret_type), 1986 1.1 mrg bitsize_int (0)); 1987 1.1 mrg g = gimple_build_assign (lhs, new_rhs); 1988 1.1 mrg gsi_replace (gsi, g, false); 1989 1.1 mrg return; 1990 1.1 mrg } 1991 1.1 mrg tree dcompute_type 1992 1.1 mrg = build_vector_type (TREE_TYPE (compute_type), 1993 1.1 mrg TYPE_VECTOR_SUBPARTS (compute_type) * 2); 1994 1.1 mrg if (TYPE_MAIN_VARIANT (dcompute_type) 1995 1.1 mrg == TYPE_MAIN_VARIANT (arg_type)) 1996 1.1 mrg new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg, 1997 1.1 mrg NULL_TREE, bitsize_int (0), 1998 1.1 mrg NULL_TREE, code1, 1999 1.1 mrg ret_type); 2000 1.1 mrg else 2001 1.1 mrg new_rhs = expand_vector_piecewise (gsi, 2002 1.1 mrg do_vec_narrow_conversion, 2003 1.1 mrg arg_type, dcompute_type, 2004 1.1 mrg arg, NULL_TREE, code1, 2005 1.1 mrg false, ret_type); 2006 1.1 mrg g = gimple_build_assign (lhs, new_rhs); 2007 1.1 mrg gsi_replace (gsi, g, false); 2008 1.1 mrg return; 2009 1.1 mrg } 2010 1.1 mrg } 2011 1.1 mrg } 2012 1.1 mrg else if (modifier == WIDEN) 2013 1.1 mrg { 2014 1.1 mrg enum tree_code code2 = ERROR_MARK; 2015 1.1 mrg optab optab2 = unknown_optab; 2016 1.1 mrg switch (code) 2017 1.1 mrg { 2018 1.1 mrg CASE_CONVERT: 2019 1.1 mrg code1 = VEC_UNPACK_LO_EXPR; 2020 1.1 mrg code2 = VEC_UNPACK_HI_EXPR; 2021 1.1 mrg break; 2022 1.1 mrg case FIX_TRUNC_EXPR: 2023 1.1 mrg code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR; 2024 1.1 mrg code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR; 2025 1.1 mrg break; 2026 1.1 mrg case FLOAT_EXPR: 2027 1.1 mrg code1 = VEC_UNPACK_FLOAT_LO_EXPR; 2028 1.1 mrg code2 = VEC_UNPACK_FLOAT_HI_EXPR; 2029 1.1 mrg break; 2030 1.1 mrg default: 2031 1.1 mrg gcc_unreachable (); 2032 1.1 mrg } 2033 1.1 mrg if (BYTES_BIG_ENDIAN) 2034 1.1 mrg std::swap (code1, code2); 2035 1.1 mrg 2036 1.1 mrg if (code == FIX_TRUNC_EXPR) 2037 1.1 mrg { 2038 1.1 mrg /* The signedness is determined from output operand. */ 2039 1.1 mrg optab1 = optab_for_tree_code (code1, ret_type, optab_default); 2040 1.1 mrg optab2 = optab_for_tree_code (code2, ret_type, optab_default); 2041 1.1 mrg } 2042 1.1 mrg else 2043 1.1 mrg { 2044 1.1 mrg optab1 = optab_for_tree_code (code1, arg_type, optab_default); 2045 1.1 mrg optab2 = optab_for_tree_code (code2, arg_type, optab_default); 2046 1.1 mrg } 2047 1.1 mrg 2048 1.1 mrg if (optab1 && optab2) 2049 1.1 mrg compute_type = get_compute_type (code1, optab1, arg_type); 2050 1.1 mrg 2051 1.1 mrg enum insn_code icode1, icode2; 2052 1.1 mrg if (VECTOR_TYPE_P (compute_type) 2053 1.1 mrg && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type))) 2054 1.1 mrg != CODE_FOR_nothing) 2055 1.1 mrg && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type))) 2056 1.1 mrg != CODE_FOR_nothing) 2057 1.1 mrg && VECTOR_MODE_P (insn_data[icode1].operand[0].mode) 2058 1.1 mrg && (insn_data[icode1].operand[0].mode 2059 1.1 mrg == insn_data[icode2].operand[0].mode)) 2060 1.1 mrg { 2061 1.1 mrg poly_uint64 nunits 2062 1.1 mrg = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2); 2063 1.1 mrg tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits); 2064 1.1 mrg if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type)) 2065 1.1 mrg { 2066 1.1 mrg vec<constructor_elt, va_gc> *v; 2067 1.1 mrg tree part_width = TYPE_SIZE (compute_type); 2068 1.1 mrg tree index = bitsize_int (0); 2069 1.1 mrg int nunits = nunits_for_known_piecewise_op (arg_type); 2070 1.1 mrg int delta = tree_to_uhwi (part_width) / arg_elt_bits; 2071 1.1 mrg int i; 2072 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi)); 2073 1.1 mrg 2074 1.1 mrg if (compute_type != arg_type) 2075 1.1 mrg { 2076 1.1 mrg if (!warning_suppressed_p (gsi_stmt (*gsi), 2077 1.1 mrg OPT_Wvector_operation_performance)) 2078 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance, 2079 1.1 mrg "vector operation will be expanded piecewise"); 2080 1.1 mrg } 2081 1.1 mrg else 2082 1.1 mrg { 2083 1.1 mrg nunits = 1; 2084 1.1 mrg delta = 1; 2085 1.1 mrg } 2086 1.1 mrg 2087 1.1 mrg vec_alloc (v, (nunits + delta - 1) / delta * 2); 2088 1.1 mrg bool constant_p = true; 2089 1.1 mrg for (i = 0; i < nunits; 2090 1.1 mrg i += delta, index = int_const_binop (PLUS_EXPR, index, 2091 1.1 mrg part_width)) 2092 1.1 mrg { 2093 1.1 mrg tree a = arg; 2094 1.1 mrg if (compute_type != arg_type) 2095 1.1 mrg a = tree_vec_extract (gsi, compute_type, a, part_width, 2096 1.1 mrg index); 2097 1.1 mrg tree result = gimplify_build1 (gsi, code1, cretd_type, a); 2098 1.1 mrg constructor_elt ce = { NULL_TREE, result }; 2099 1.1 mrg if (!CONSTANT_CLASS_P (ce.value)) 2100 1.1 mrg constant_p = false; 2101 1.1 mrg v->quick_push (ce); 2102 1.1 mrg ce.value = gimplify_build1 (gsi, code2, cretd_type, a); 2103 1.1 mrg if (!CONSTANT_CLASS_P (ce.value)) 2104 1.1 mrg constant_p = false; 2105 1.1 mrg v->quick_push (ce); 2106 1.1 mrg } 2107 1.1 mrg 2108 1.1 mrg if (constant_p) 2109 1.1 mrg new_rhs = build_vector_from_ctor (ret_type, v); 2110 1.1 mrg else 2111 1.1 mrg new_rhs = build_constructor (ret_type, v); 2112 1.1 mrg g = gimple_build_assign (lhs, new_rhs); 2113 1.1 mrg gsi_replace (gsi, g, false); 2114 1.1 mrg return; 2115 1.1 mrg } 2116 1.1 mrg } 2117 1.1 mrg } 2118 1.1 mrg 2119 1.1 mrg new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type, 2120 1.1 mrg TREE_TYPE (arg_type), arg, 2121 1.1 mrg NULL_TREE, code, false, ret_type); 2122 1.1 mrg g = gimple_build_assign (lhs, new_rhs); 2123 1.1 mrg gsi_replace (gsi, g, false); 2124 1.1 mrg } 2125 1.1 mrg 2126 1.1 mrg /* Process one statement. If we identify a vector operation, expand it. */ 2127 1.1 mrg 2128 1.1 mrg static void 2129 1.1 mrg expand_vector_operations_1 (gimple_stmt_iterator *gsi, 2130 1.1 mrg bitmap dce_ssa_names) 2131 1.1 mrg { 2132 1.1 mrg tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE; 2133 1.1 mrg enum tree_code code; 2134 1.1 mrg optab op = unknown_optab; 2135 1.1 mrg enum gimple_rhs_class rhs_class; 2136 1.1 mrg tree new_rhs; 2137 1.1 mrg 2138 1.1 mrg /* Only consider code == GIMPLE_ASSIGN. */ 2139 1.1 mrg gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi)); 2140 1.1 mrg if (!stmt) 2141 1.1 mrg { 2142 1.1 mrg if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT)) 2143 1.1 mrg expand_vector_conversion (gsi); 2144 1.1 mrg return; 2145 1.1 mrg } 2146 1.1 mrg 2147 1.1 mrg code = gimple_assign_rhs_code (stmt); 2148 1.1 mrg rhs_class = get_gimple_rhs_class (code); 2149 1.1 mrg lhs = gimple_assign_lhs (stmt); 2150 1.1 mrg 2151 1.1 mrg if (code == VEC_PERM_EXPR) 2152 1.1 mrg { 2153 1.1 mrg lower_vec_perm (gsi); 2154 1.1 mrg return; 2155 1.1 mrg } 2156 1.1 mrg 2157 1.1 mrg if (code == VEC_COND_EXPR) 2158 1.1 mrg { 2159 1.1 mrg expand_vector_condition (gsi, dce_ssa_names); 2160 1.1 mrg return; 2161 1.1 mrg } 2162 1.1 mrg 2163 1.1 mrg if (code == COND_EXPR 2164 1.1 mrg && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE 2165 1.1 mrg && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode) 2166 1.1 mrg { 2167 1.1 mrg expand_vector_scalar_condition (gsi); 2168 1.1 mrg return; 2169 1.1 mrg } 2170 1.1 mrg 2171 1.1 mrg if (code == CONSTRUCTOR 2172 1.1 mrg && TREE_CODE (lhs) == SSA_NAME 2173 1.1 mrg && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs))) 2174 1.1 mrg && !gimple_clobber_p (stmt) 2175 1.1 mrg && optimize) 2176 1.1 mrg { 2177 1.1 mrg optimize_vector_constructor (gsi); 2178 1.1 mrg return; 2179 1.1 mrg } 2180 1.1 mrg 2181 1.1 mrg if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS) 2182 1.1 mrg return; 2183 1.1 mrg 2184 1.1 mrg rhs1 = gimple_assign_rhs1 (stmt); 2185 1.1 mrg if (rhs_class == GIMPLE_BINARY_RHS) 2186 1.1 mrg rhs2 = gimple_assign_rhs2 (stmt); 2187 1.1 mrg 2188 1.1 mrg type = TREE_TYPE (lhs); 2189 1.1 mrg if (!VECTOR_TYPE_P (type) 2190 1.1 mrg || !VECTOR_TYPE_P (TREE_TYPE (rhs1))) 2191 1.1 mrg return; 2192 1.1 mrg 2193 1.1 mrg /* A scalar operation pretending to be a vector one. */ 2194 1.1 mrg if (VECTOR_BOOLEAN_TYPE_P (type) 2195 1.1 mrg && !VECTOR_MODE_P (TYPE_MODE (type)) 2196 1.1 mrg && TYPE_MODE (type) != BLKmode 2197 1.1 mrg && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison 2198 1.1 mrg || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)) 2199 1.1 mrg && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1))) 2200 1.1 mrg && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode))) 2201 1.1 mrg return; 2202 1.1 mrg 2203 1.1 mrg /* If the vector operation is operating on all same vector elements 2204 1.1 mrg implement it with a scalar operation and a splat if the target 2205 1.1 mrg supports the scalar operation. */ 2206 1.1 mrg tree srhs1, srhs2 = NULL_TREE; 2207 1.1 mrg if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE 2208 1.1 mrg && (rhs2 == NULL_TREE 2209 1.1 mrg || (! VECTOR_TYPE_P (TREE_TYPE (rhs2)) 2210 1.1 mrg && (srhs2 = rhs2)) 2211 1.1 mrg || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE) 2212 1.1 mrg /* As we query direct optabs restrict to non-convert operations. */ 2213 1.1 mrg && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1))) 2214 1.1 mrg { 2215 1.1 mrg op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar); 2216 1.1 mrg if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB 2217 1.1 mrg && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing) 2218 1.1 mrg { 2219 1.1 mrg tree stype = TREE_TYPE (TREE_TYPE (lhs)); 2220 1.1 mrg tree slhs = (rhs2 != NULL_TREE) 2221 1.1 mrg ? gimplify_build2 (gsi, code, stype, srhs1, srhs2) 2222 1.1 mrg : gimplify_build1 (gsi, code, stype, srhs1); 2223 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, 2224 1.1 mrg build_vector_from_val (type, slhs)); 2225 1.1 mrg update_stmt (stmt); 2226 1.1 mrg return; 2227 1.1 mrg } 2228 1.1 mrg } 2229 1.1 mrg 2230 1.1 mrg if (CONVERT_EXPR_CODE_P (code) 2231 1.1 mrg || code == FLOAT_EXPR 2232 1.1 mrg || code == FIX_TRUNC_EXPR 2233 1.1 mrg || code == VIEW_CONVERT_EXPR) 2234 1.1 mrg return; 2235 1.1 mrg 2236 1.1 mrg /* The signedness is determined from input argument. */ 2237 1.1 mrg if (code == VEC_UNPACK_FLOAT_HI_EXPR 2238 1.1 mrg || code == VEC_UNPACK_FLOAT_LO_EXPR 2239 1.1 mrg || code == VEC_PACK_FLOAT_EXPR) 2240 1.1 mrg { 2241 1.1 mrg /* We do not know how to scalarize those. */ 2242 1.1 mrg return; 2243 1.1 mrg } 2244 1.1 mrg 2245 1.1 mrg /* For widening/narrowing vector operations, the relevant type is of the 2246 1.1 mrg arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is 2247 1.1 mrg calculated in the same way above. */ 2248 1.1 mrg if (code == WIDEN_SUM_EXPR 2249 1.1 mrg || code == VEC_WIDEN_PLUS_HI_EXPR 2250 1.1 mrg || code == VEC_WIDEN_PLUS_LO_EXPR 2251 1.1 mrg || code == VEC_WIDEN_MINUS_HI_EXPR 2252 1.1 mrg || code == VEC_WIDEN_MINUS_LO_EXPR 2253 1.1 mrg || code == VEC_WIDEN_MULT_HI_EXPR 2254 1.1 mrg || code == VEC_WIDEN_MULT_LO_EXPR 2255 1.1 mrg || code == VEC_WIDEN_MULT_EVEN_EXPR 2256 1.1 mrg || code == VEC_WIDEN_MULT_ODD_EXPR 2257 1.1 mrg || code == VEC_UNPACK_HI_EXPR 2258 1.1 mrg || code == VEC_UNPACK_LO_EXPR 2259 1.1 mrg || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR 2260 1.1 mrg || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR 2261 1.1 mrg || code == VEC_PACK_TRUNC_EXPR 2262 1.1 mrg || code == VEC_PACK_SAT_EXPR 2263 1.1 mrg || code == VEC_PACK_FIX_TRUNC_EXPR 2264 1.1 mrg || code == VEC_WIDEN_LSHIFT_HI_EXPR 2265 1.1 mrg || code == VEC_WIDEN_LSHIFT_LO_EXPR) 2266 1.1 mrg { 2267 1.1 mrg /* We do not know how to scalarize those. */ 2268 1.1 mrg return; 2269 1.1 mrg } 2270 1.1 mrg 2271 1.1 mrg /* Choose between vector shift/rotate by vector and vector shift/rotate by 2272 1.1 mrg scalar */ 2273 1.1 mrg if (code == LSHIFT_EXPR 2274 1.1 mrg || code == RSHIFT_EXPR 2275 1.1 mrg || code == LROTATE_EXPR 2276 1.1 mrg || code == RROTATE_EXPR) 2277 1.1 mrg { 2278 1.1 mrg optab opv; 2279 1.1 mrg 2280 1.1 mrg /* Check whether we have vector <op> {x,x,x,x} where x 2281 1.1 mrg could be a scalar variable or a constant. Transform 2282 1.1 mrg vector <op> {x,x,x,x} ==> vector <op> scalar. */ 2283 1.1 mrg if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2))) 2284 1.1 mrg { 2285 1.1 mrg tree first; 2286 1.1 mrg 2287 1.1 mrg if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE) 2288 1.1 mrg { 2289 1.1 mrg gimple_assign_set_rhs2 (stmt, first); 2290 1.1 mrg update_stmt (stmt); 2291 1.1 mrg rhs2 = first; 2292 1.1 mrg } 2293 1.1 mrg } 2294 1.1 mrg 2295 1.1 mrg opv = optab_for_tree_code (code, type, optab_vector); 2296 1.1 mrg if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2))) 2297 1.1 mrg op = opv; 2298 1.1 mrg else 2299 1.1 mrg { 2300 1.1 mrg op = optab_for_tree_code (code, type, optab_scalar); 2301 1.1 mrg 2302 1.1 mrg compute_type = get_compute_type (code, op, type); 2303 1.1 mrg if (compute_type == type) 2304 1.1 mrg return; 2305 1.1 mrg /* The rtl expander will expand vector/scalar as vector/vector 2306 1.1 mrg if necessary. Pick one with wider vector type. */ 2307 1.1 mrg tree compute_vtype = get_compute_type (code, opv, type); 2308 1.1 mrg if (subparts_gt (compute_vtype, compute_type)) 2309 1.1 mrg { 2310 1.1 mrg compute_type = compute_vtype; 2311 1.1 mrg op = opv; 2312 1.1 mrg } 2313 1.1 mrg } 2314 1.1 mrg 2315 1.1 mrg if (code == LROTATE_EXPR || code == RROTATE_EXPR) 2316 1.1 mrg { 2317 1.1 mrg if (compute_type == NULL_TREE) 2318 1.1 mrg compute_type = get_compute_type (code, op, type); 2319 1.1 mrg if (compute_type == type) 2320 1.1 mrg return; 2321 1.1 mrg /* Before splitting vector rotates into scalar rotates, 2322 1.1 mrg see if we can't use vector shifts and BIT_IOR_EXPR 2323 1.1 mrg instead. For vector by vector rotates we'd also 2324 1.1 mrg need to check BIT_AND_EXPR and NEGATE_EXPR, punt there 2325 1.1 mrg for now, fold doesn't seem to create such rotates anyway. */ 2326 1.1 mrg if (compute_type == TREE_TYPE (type) 2327 1.1 mrg && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2))) 2328 1.1 mrg { 2329 1.1 mrg optab oplv = vashl_optab, opl = ashl_optab; 2330 1.1 mrg optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab; 2331 1.1 mrg tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type); 2332 1.1 mrg tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type); 2333 1.1 mrg tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type); 2334 1.1 mrg tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type); 2335 1.1 mrg tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type); 2336 1.1 mrg /* The rtl expander will expand vector/scalar as vector/vector 2337 1.1 mrg if necessary. Pick one with wider vector type. */ 2338 1.1 mrg if (subparts_gt (compute_lvtype, compute_ltype)) 2339 1.1 mrg { 2340 1.1 mrg compute_ltype = compute_lvtype; 2341 1.1 mrg opl = oplv; 2342 1.1 mrg } 2343 1.1 mrg if (subparts_gt (compute_rvtype, compute_rtype)) 2344 1.1 mrg { 2345 1.1 mrg compute_rtype = compute_rvtype; 2346 1.1 mrg opr = oprv; 2347 1.1 mrg } 2348 1.1 mrg /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and 2349 1.1 mrg BIT_IOR_EXPR. */ 2350 1.1 mrg compute_type = compute_ltype; 2351 1.1 mrg if (subparts_gt (compute_type, compute_rtype)) 2352 1.1 mrg compute_type = compute_rtype; 2353 1.1 mrg if (subparts_gt (compute_type, compute_otype)) 2354 1.1 mrg compute_type = compute_otype; 2355 1.1 mrg /* Verify all 3 operations can be performed in that type. */ 2356 1.1 mrg if (compute_type != TREE_TYPE (type)) 2357 1.1 mrg { 2358 1.1 mrg if (optab_handler (opl, TYPE_MODE (compute_type)) 2359 1.1 mrg == CODE_FOR_nothing 2360 1.1 mrg || optab_handler (opr, TYPE_MODE (compute_type)) 2361 1.1 mrg == CODE_FOR_nothing 2362 1.1 mrg || optab_handler (opo, TYPE_MODE (compute_type)) 2363 1.1 mrg == CODE_FOR_nothing) 2364 1.1 mrg compute_type = TREE_TYPE (type); 2365 1.1 mrg } 2366 1.1 mrg } 2367 1.1 mrg } 2368 1.1 mrg } 2369 1.1 mrg else 2370 1.1 mrg op = optab_for_tree_code (code, type, optab_default); 2371 1.1 mrg 2372 1.1 mrg /* Optabs will try converting a negation into a subtraction, so 2373 1.1 mrg look for it as well. TODO: negation of floating-point vectors 2374 1.1 mrg might be turned into an exclusive OR toggling the sign bit. */ 2375 1.1 mrg if (op == unknown_optab 2376 1.1 mrg && code == NEGATE_EXPR 2377 1.1 mrg && INTEGRAL_TYPE_P (TREE_TYPE (type))) 2378 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default); 2379 1.1 mrg 2380 1.1 mrg if (compute_type == NULL_TREE) 2381 1.1 mrg compute_type = get_compute_type (code, op, type); 2382 1.1 mrg if (compute_type == type) 2383 1.1 mrg return; 2384 1.1 mrg 2385 1.1 mrg new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code, 2386 1.1 mrg dce_ssa_names); 2387 1.1 mrg 2388 1.1 mrg /* Leave expression untouched for later expansion. */ 2389 1.1 mrg if (new_rhs == NULL_TREE) 2390 1.1 mrg return; 2391 1.1 mrg 2392 1.1 mrg if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs))) 2393 1.1 mrg new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), 2394 1.1 mrg new_rhs); 2395 1.1 mrg 2396 1.1 mrg /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One 2397 1.1 mrg way to do it is change expand_vector_operation and its callees to 2398 1.1 mrg return a tree_code, RHS1 and RHS2 instead of a tree. */ 2399 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, new_rhs); 2400 1.1 mrg update_stmt (gsi_stmt (*gsi)); 2401 1.1 mrg } 2402 1.1 mrg 2403 1.1 mrg /* Use this to lower vector operations introduced by the vectorizer, 2405 1.1 mrg if it may need the bit-twiddling tricks implemented in this file. */ 2406 1.1 mrg 2407 1.1 mrg static unsigned int 2408 1.1 mrg expand_vector_operations (void) 2409 1.1 mrg { 2410 1.1 mrg gimple_stmt_iterator gsi; 2411 1.1 mrg basic_block bb; 2412 1.1 mrg bool cfg_changed = false; 2413 1.1 mrg 2414 1.1 mrg auto_bitmap dce_ssa_names; 2415 1.1 mrg 2416 1.1 mrg FOR_EACH_BB_FN (bb, cfun) 2417 1.1 mrg { 2418 1.1 mrg for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 2419 1.1 mrg { 2420 1.1 mrg expand_vector_operations_1 (&gsi, dce_ssa_names); 2421 1.1 mrg /* ??? If we do not cleanup EH then we will ICE in 2422 1.1 mrg verification. But in reality we have created wrong-code 2423 1.1 mrg as we did not properly transition EH info and edges to 2424 1.1 mrg the piecewise computations. */ 2425 1.1 mrg if (maybe_clean_eh_stmt (gsi_stmt (gsi)) 2426 1.1 mrg && gimple_purge_dead_eh_edges (bb)) 2427 1.1 mrg cfg_changed = true; 2428 1.1 mrg } 2429 1.1 mrg } 2430 1.1 mrg 2431 1.1 mrg simple_dce_from_worklist (dce_ssa_names); 2432 1.1 mrg 2433 1.1 mrg return cfg_changed ? TODO_cleanup_cfg : 0; 2434 1.1 mrg } 2435 1.1 mrg 2436 1.1 mrg namespace { 2437 1.1 mrg 2438 1.1 mrg const pass_data pass_data_lower_vector = 2439 1.1 mrg { 2440 1.1 mrg GIMPLE_PASS, /* type */ 2441 1.1 mrg "veclower", /* name */ 2442 1.1 mrg OPTGROUP_VEC, /* optinfo_flags */ 2443 1.1 mrg TV_NONE, /* tv_id */ 2444 1.1 mrg PROP_cfg, /* properties_required */ 2445 1.1 mrg PROP_gimple_lvec, /* properties_provided */ 2446 1.1 mrg 0, /* properties_destroyed */ 2447 1.1 mrg 0, /* todo_flags_start */ 2448 1.1 mrg TODO_update_ssa, /* todo_flags_finish */ 2449 1.1 mrg }; 2450 1.1 mrg 2451 1.1 mrg class pass_lower_vector : public gimple_opt_pass 2452 1.1 mrg { 2453 1.1 mrg public: 2454 1.1 mrg pass_lower_vector (gcc::context *ctxt) 2455 1.1 mrg : gimple_opt_pass (pass_data_lower_vector, ctxt) 2456 1.1 mrg {} 2457 1.1 mrg 2458 1.1 mrg /* opt_pass methods: */ 2459 1.1 mrg virtual bool gate (function *fun) 2460 1.1 mrg { 2461 1.1 mrg return !(fun->curr_properties & PROP_gimple_lvec); 2462 1.1 mrg } 2463 1.1 mrg 2464 1.1 mrg virtual unsigned int execute (function *) 2465 1.1 mrg { 2466 1.1 mrg return expand_vector_operations (); 2467 1.1 mrg } 2468 1.1 mrg 2469 1.1 mrg }; // class pass_lower_vector 2470 1.1 mrg 2471 1.1 mrg } // anon namespace 2472 1.1 mrg 2473 1.1 mrg gimple_opt_pass * 2474 1.1 mrg make_pass_lower_vector (gcc::context *ctxt) 2475 1.1 mrg { 2476 1.1 mrg return new pass_lower_vector (ctxt); 2477 1.1 mrg } 2478 1.1 mrg 2479 1.1 mrg namespace { 2480 1.1 mrg 2481 1.1 mrg const pass_data pass_data_lower_vector_ssa = 2482 1.1 mrg { 2483 1.1 mrg GIMPLE_PASS, /* type */ 2484 1.1 mrg "veclower2", /* name */ 2485 1.1 mrg OPTGROUP_VEC, /* optinfo_flags */ 2486 1.1 mrg TV_NONE, /* tv_id */ 2487 1.1 mrg PROP_cfg, /* properties_required */ 2488 1.1 mrg PROP_gimple_lvec, /* properties_provided */ 2489 1.1 mrg 0, /* properties_destroyed */ 2490 1.1 mrg 0, /* todo_flags_start */ 2491 1.1 mrg ( TODO_update_ssa 2492 1.1 mrg | TODO_cleanup_cfg ), /* todo_flags_finish */ 2493 1.1 mrg }; 2494 1.1 mrg 2495 1.1 mrg class pass_lower_vector_ssa : public gimple_opt_pass 2496 1.1 mrg { 2497 1.1 mrg public: 2498 1.1 mrg pass_lower_vector_ssa (gcc::context *ctxt) 2499 1.1 mrg : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt) 2500 1.1 mrg {} 2501 1.1 mrg 2502 1.1 mrg /* opt_pass methods: */ 2503 1.1 mrg opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); } 2504 1.1 mrg virtual unsigned int execute (function *) 2505 1.1 mrg { 2506 1.1 mrg return expand_vector_operations (); 2507 1.1 mrg } 2508 1.1 mrg 2509 1.1 mrg }; // class pass_lower_vector_ssa 2510 1.1 mrg 2511 1.1 mrg } // anon namespace 2512 1.1 mrg 2513 1.1 mrg gimple_opt_pass * 2514 1.1 mrg make_pass_lower_vector_ssa (gcc::context *ctxt) 2515 1.1 mrg { 2516 1.1 mrg return new pass_lower_vector_ssa (ctxt); 2517 1.1 mrg } 2518 2519 #include "gt-tree-vect-generic.h" 2520