Line data Source code
1 : /* SLP - Basic Block Vectorization
2 : Copyright (C) 2007-2026 Free Software Foundation, Inc.
3 : Contributed by Dorit Naishlos <dorit@il.ibm.com>
4 : and Ira Rosen <irar@il.ibm.com>
5 :
6 : This file is part of GCC.
7 :
8 : GCC is free software; you can redistribute it and/or modify it under
9 : the terms of the GNU General Public License as published by the Free
10 : Software Foundation; either version 3, or (at your option) any later
11 : version.
12 :
13 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with GCC; see the file COPYING3. If not see
20 : <http://www.gnu.org/licenses/>. */
21 :
22 : #include "config.h"
23 : #define INCLUDE_ALGORITHM
24 : #include "system.h"
25 : #include "coretypes.h"
26 : #include "backend.h"
27 : #include "target.h"
28 : #include "rtl.h"
29 : #include "tree.h"
30 : #include "gimple.h"
31 : #include "tree-pass.h"
32 : #include "ssa.h"
33 : #include "optabs-tree.h"
34 : #include "insn-config.h"
35 : #include "recog.h" /* FIXME: for insn_data */
36 : #include "fold-const.h"
37 : #include "stor-layout.h"
38 : #include "gimple-iterator.h"
39 : #include "cfgloop.h"
40 : #include "tree-vectorizer.h"
41 : #include "langhooks.h"
42 : #include "gimple-walk.h"
43 : #include "dbgcnt.h"
44 : #include "tree-vector-builder.h"
45 : #include "vec-perm-indices.h"
46 : #include "gimple-fold.h"
47 : #include "internal-fn.h"
48 : #include "dump-context.h"
49 : #include "cfganal.h"
50 : #include "tree-eh.h"
51 : #include "tree-cfg.h"
52 : #include "alloc-pool.h"
53 : #include "sreal.h"
54 : #include "predict.h"
55 :
56 : #define REDUC_GROUP_FIRST_ELEMENT(S) \
57 : (gcc_checking_assert (!(S)->dr_aux.dr), (S)->first_element)
58 :
59 : static bool vect_transform_slp_perm_load_1 (vec_info *, slp_tree,
60 : load_permutation_t &,
61 : const vec<tree> &,
62 : gimple_stmt_iterator *,
63 : poly_uint64, bool, bool,
64 : unsigned *,
65 : unsigned * = nullptr,
66 : bool = false);
67 : static int vectorizable_slp_permutation_1 (vec_info *, gimple_stmt_iterator *,
68 : slp_tree, lane_permutation_t &,
69 : vec<slp_tree> &, bool);
70 : static void vect_print_slp_tree (dump_flags_t, dump_location_t, slp_tree);
71 : static bool vect_slp_can_convert_to_external (const vec<stmt_vec_info> &);
72 :
73 : static object_allocator<_slp_tree> *slp_tree_pool;
74 : static slp_tree slp_first_node;
75 :
76 : void
77 1136857 : vect_slp_init (void)
78 : {
79 1136857 : slp_tree_pool = new object_allocator<_slp_tree> ("SLP nodes");
80 1136857 : }
81 :
82 : void
83 1136857 : vect_slp_fini (void)
84 : {
85 1829189 : while (slp_first_node)
86 692332 : delete slp_first_node;
87 2273714 : delete slp_tree_pool;
88 1136857 : slp_tree_pool = NULL;
89 1136857 : }
90 :
91 : void *
92 8273609 : _slp_tree::operator new (size_t n)
93 : {
94 8273609 : gcc_assert (n == sizeof (_slp_tree));
95 8273609 : return slp_tree_pool->allocate_raw ();
96 : }
97 :
98 : void
99 8273609 : _slp_tree::operator delete (void *node, size_t n)
100 : {
101 8273609 : gcc_assert (n == sizeof (_slp_tree));
102 8273609 : slp_tree_pool->remove_raw (node);
103 8273609 : }
104 :
105 :
106 : /* Initialize a SLP node. */
107 :
108 8273609 : _slp_tree::_slp_tree ()
109 : {
110 8273609 : this->prev_node = NULL;
111 8273609 : if (slp_first_node)
112 7240792 : slp_first_node->prev_node = this;
113 8273609 : this->next_node = slp_first_node;
114 8273609 : slp_first_node = this;
115 8273609 : SLP_TREE_SCALAR_STMTS (this) = vNULL;
116 8273609 : SLP_TREE_SCALAR_OPS (this) = vNULL;
117 8273609 : SLP_TREE_LIVE_LANES (this) = vNULL;
118 8273609 : SLP_TREE_VEC_DEFS (this) = vNULL;
119 8273609 : SLP_TREE_CHILDREN (this) = vNULL;
120 8273609 : SLP_TREE_LOAD_PERMUTATION (this) = vNULL;
121 8273609 : SLP_TREE_LANE_PERMUTATION (this) = vNULL;
122 8273609 : SLP_TREE_DEF_TYPE (this) = vect_uninitialized_def;
123 8273609 : SLP_TREE_CODE (this) = ERROR_MARK;
124 8273609 : SLP_TREE_GS_SCALE (this) = 0;
125 8273609 : SLP_TREE_GS_BASE (this) = NULL_TREE;
126 8273609 : this->ldst_lanes = false;
127 8273609 : this->avoid_stlf_fail = false;
128 8273609 : SLP_TREE_VECTYPE (this) = NULL_TREE;
129 8273609 : SLP_TREE_REPRESENTATIVE (this) = NULL;
130 8273609 : this->cycle_info.id = -1;
131 8273609 : this->cycle_info.reduc_idx = -1;
132 8273609 : SLP_TREE_REF_COUNT (this) = 1;
133 8273609 : this->failed = NULL;
134 8273609 : this->lanes = 0;
135 8273609 : SLP_TREE_TYPE (this) = undef_vec_info_type;
136 8273609 : this->data = NULL;
137 8273609 : this->si = NULL;
138 8273609 : }
139 :
140 : /* Tear down a SLP node. */
141 :
142 8273609 : _slp_tree::~_slp_tree ()
143 : {
144 8273609 : if (this->prev_node)
145 5055085 : this->prev_node->next_node = this->next_node;
146 : else
147 3218524 : slp_first_node = this->next_node;
148 8273609 : if (this->next_node)
149 6245989 : this->next_node->prev_node = this->prev_node;
150 8273609 : SLP_TREE_CHILDREN (this).release ();
151 8273609 : SLP_TREE_SCALAR_STMTS (this).release ();
152 8273609 : SLP_TREE_SCALAR_OPS (this).release ();
153 8273609 : SLP_TREE_LIVE_LANES (this).release ();
154 8273609 : SLP_TREE_VEC_DEFS (this).release ();
155 8273609 : SLP_TREE_LOAD_PERMUTATION (this).release ();
156 8273609 : SLP_TREE_LANE_PERMUTATION (this).release ();
157 8273609 : if (this->failed)
158 2217294 : free (failed);
159 8273609 : if (this->data)
160 1278600 : delete this->data;
161 8273609 : }
162 :
163 : /* Push the single SSA definition in DEF to the vector of vector defs. */
164 :
165 : void
166 531726 : _slp_tree::push_vec_def (gimple *def)
167 : {
168 531726 : if (gphi *phi = dyn_cast <gphi *> (def))
169 59484 : vec_defs.quick_push (gimple_phi_result (phi));
170 : else
171 : {
172 472242 : def_operand_p defop = single_ssa_def_operand (def, SSA_OP_ALL_DEFS);
173 472242 : vec_defs.quick_push (get_def_from_ptr (defop));
174 : }
175 531726 : }
176 :
177 : /* Recursively free the memory allocated for the SLP tree rooted at NODE. */
178 :
179 : void
180 15601262 : vect_free_slp_tree (slp_tree node)
181 : {
182 15601262 : int i;
183 15601262 : slp_tree child;
184 :
185 15601262 : if (--SLP_TREE_REF_COUNT (node) != 0)
186 15601262 : return;
187 :
188 11752740 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
189 4171463 : if (child)
190 3789942 : vect_free_slp_tree (child);
191 :
192 7581277 : delete node;
193 : }
194 :
195 : /* Return a location suitable for dumpings related to the SLP instance. */
196 :
197 : dump_user_location_t
198 3551793 : _slp_instance::location () const
199 : {
200 3551793 : if (!root_stmts.is_empty ())
201 411346 : return root_stmts[0]->stmt;
202 : else
203 3140447 : return SLP_TREE_SCALAR_STMTS (root)[0]->stmt;
204 : }
205 :
206 :
207 : /* Free the memory allocated for the SLP instance. */
208 :
209 : void
210 1628477 : vect_free_slp_instance (slp_instance instance)
211 : {
212 1628477 : vect_free_slp_tree (SLP_INSTANCE_TREE (instance));
213 1628477 : SLP_INSTANCE_LOADS (instance).release ();
214 1628477 : SLP_INSTANCE_ROOT_STMTS (instance).release ();
215 1628477 : SLP_INSTANCE_REMAIN_DEFS (instance).release ();
216 1628477 : instance->subgraph_entries.release ();
217 1628477 : instance->cost_vec.release ();
218 1628477 : free (instance);
219 1628477 : }
220 :
221 :
222 : /* Create a SLP node with NOPS children with CODE, either VEC_PERM_EXPR
223 : for a permute node or else ERROR_MARK. */
224 :
225 : slp_tree
226 97583 : vect_create_new_slp_node (unsigned nops, tree_code code)
227 : {
228 97583 : gcc_assert (code == ERROR_MARK || code == VEC_PERM_EXPR);
229 97583 : slp_tree node = new _slp_tree;
230 97583 : SLP_TREE_SCALAR_STMTS (node) = vNULL;
231 97583 : SLP_TREE_CHILDREN (node).create (nops);
232 97583 : SLP_TREE_DEF_TYPE (node) = vect_internal_def;
233 97583 : SLP_TREE_CODE (node) = code;
234 97583 : return node;
235 : }
236 :
237 : /* Create a SLP node inplace at NODE for SCALAR_STMTS and NOPS children. */
238 :
239 : static slp_tree
240 3979938 : vect_create_new_slp_node (slp_tree node,
241 : vec<stmt_vec_info> scalar_stmts, unsigned nops)
242 : {
243 3979938 : SLP_TREE_SCALAR_STMTS (node) = scalar_stmts;
244 3979938 : SLP_TREE_CHILDREN (node).create (nops);
245 3979938 : SLP_TREE_DEF_TYPE (node) = vect_internal_def;
246 3979938 : SLP_TREE_REPRESENTATIVE (node) = scalar_stmts[0];
247 3979938 : SLP_TREE_LANES (node) = scalar_stmts.length ();
248 3979938 : return node;
249 : }
250 :
251 : /* Create an SLP node for SCALAR_STMTS and NOPS children. */
252 :
253 : static slp_tree
254 8392 : vect_create_new_slp_node (vec<stmt_vec_info> scalar_stmts, unsigned nops)
255 : {
256 8392 : return vect_create_new_slp_node (new _slp_tree, scalar_stmts, nops);
257 : }
258 :
259 : /* Create a vect_external_def SLP node inplace at NODE for scalar
260 : operands OPS. */
261 :
262 : static slp_tree
263 1966664 : vect_create_new_slp_node (slp_tree node, vec<tree> ops)
264 : {
265 1966664 : SLP_TREE_SCALAR_OPS (node) = ops;
266 1966664 : SLP_TREE_DEF_TYPE (node) = vect_external_def;
267 0 : SLP_TREE_LANES (node) = ops.length ();
268 1966664 : return node;
269 : }
270 :
271 : /* Create a vect_external_def SLP node for scalar operands OPS. */
272 :
273 : static slp_tree
274 1966664 : vect_create_new_slp_node (vec<tree> ops)
275 : {
276 1966664 : return vect_create_new_slp_node (new _slp_tree, ops);
277 : }
278 :
279 :
280 : /* This structure is used in creation of an SLP tree. Each instance
281 : corresponds to the same operand in a group of scalar stmts in an SLP
282 : node. */
283 : typedef struct _slp_oprnd_info
284 : {
285 : /* Def-stmts for the operands. */
286 : vec<stmt_vec_info> def_stmts;
287 : /* Operands. */
288 : vec<tree> ops;
289 : /* Information about the first statement, its vector def-type, type, the
290 : operand itself in case it's constant, and an indication if it's a pattern
291 : stmt and gather/scatter info. */
292 : tree first_op_type;
293 : enum vect_def_type first_dt;
294 : bool any_pattern;
295 : bool first_gs_p;
296 : gather_scatter_info first_gs_info;
297 : } *slp_oprnd_info;
298 :
299 :
300 : /* Allocate operands info for NOPS operands, and GROUP_SIZE def-stmts for each
301 : operand. */
302 : static vec<slp_oprnd_info>
303 3536849 : vect_create_oprnd_info (int nops, int group_size)
304 : {
305 3536849 : int i;
306 3536849 : slp_oprnd_info oprnd_info;
307 3536849 : vec<slp_oprnd_info> oprnds_info;
308 :
309 3536849 : oprnds_info.create (nops);
310 12720352 : for (i = 0; i < nops; i++)
311 : {
312 5646654 : oprnd_info = XNEW (struct _slp_oprnd_info);
313 5646654 : oprnd_info->def_stmts.create (group_size);
314 5646654 : oprnd_info->ops.create (group_size);
315 5646654 : oprnd_info->first_dt = vect_uninitialized_def;
316 5646654 : oprnd_info->first_op_type = NULL_TREE;
317 5646654 : oprnd_info->any_pattern = false;
318 5646654 : oprnd_info->first_gs_p = false;
319 5646654 : oprnds_info.quick_push (oprnd_info);
320 : }
321 :
322 3536849 : return oprnds_info;
323 : }
324 :
325 :
326 : /* Free operands info. */
327 :
328 : static void
329 3536849 : vect_free_oprnd_info (vec<slp_oprnd_info> &oprnds_info)
330 : {
331 3536849 : int i;
332 3536849 : slp_oprnd_info oprnd_info;
333 :
334 9183503 : FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
335 : {
336 5646654 : oprnd_info->def_stmts.release ();
337 5646654 : oprnd_info->ops.release ();
338 5646654 : XDELETE (oprnd_info);
339 : }
340 :
341 3536849 : oprnds_info.release ();
342 3536849 : }
343 :
344 : /* Return the execution frequency of NODE (so that a higher value indicates
345 : a "more important" node when optimizing for speed). */
346 :
347 : static sreal
348 3671415 : vect_slp_node_weight (vec_info *vinfo, slp_tree node)
349 : {
350 3671415 : stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
351 3671415 : basic_block bb;
352 : /* ??? This is imprecise, VEC_PERM nodes do not have a representative
353 : but are laid out close to their children. */
354 3671415 : if (!stmt_info)
355 143093 : bb = vinfo->bbs[0];
356 : else
357 3998528 : bb = gimple_bb (vect_orig_stmt (stmt_info)->stmt);
358 3671415 : return bb->count.to_sreal_scale (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count);
359 : }
360 :
361 : /* Return true if STMTS contains a pattern statement. */
362 :
363 : static bool
364 30550 : vect_contains_pattern_stmt_p (vec<stmt_vec_info> stmts)
365 : {
366 30550 : stmt_vec_info stmt_info;
367 30550 : unsigned int i;
368 89106 : FOR_EACH_VEC_ELT (stmts, i, stmt_info)
369 66080 : if (stmt_info && is_pattern_stmt_p (stmt_info))
370 : return true;
371 : return false;
372 : }
373 :
374 : /* Return true when all lanes in the external or constant NODE have
375 : the same value. */
376 :
377 : static bool
378 645985 : vect_slp_tree_uniform_p (slp_tree node)
379 : {
380 645985 : gcc_assert (SLP_TREE_DEF_TYPE (node) == vect_constant_def
381 : || SLP_TREE_DEF_TYPE (node) == vect_external_def);
382 :
383 : /* Pre-existing vectors. */
384 645985 : if (SLP_TREE_SCALAR_OPS (node).is_empty ())
385 : return false;
386 :
387 : unsigned i;
388 : tree op, first = NULL_TREE;
389 1482408 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_OPS (node), i, op)
390 1323883 : if (!first)
391 : first = op;
392 677898 : else if (!operand_equal_p (first, op, 0))
393 : return false;
394 :
395 : return true;
396 : }
397 :
398 : /* Find the place of the data-ref in STMT_INFO in the interleaving chain
399 : that starts from FIRST_STMT_INFO. Return -1 if the data-ref is not a part
400 : of the chain. */
401 :
402 : int
403 746670 : vect_get_place_in_interleaving_chain (stmt_vec_info stmt_info,
404 : stmt_vec_info first_stmt_info)
405 : {
406 746670 : stmt_vec_info next_stmt_info = first_stmt_info;
407 746670 : int result = 0;
408 :
409 746670 : if (first_stmt_info != DR_GROUP_FIRST_ELEMENT (stmt_info))
410 : return -1;
411 :
412 2114957 : do
413 : {
414 2114957 : if (next_stmt_info == stmt_info)
415 : return result;
416 1368287 : next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
417 1368287 : if (next_stmt_info)
418 1368287 : result += DR_GROUP_GAP (next_stmt_info);
419 : }
420 1368287 : while (next_stmt_info);
421 :
422 : return -1;
423 : }
424 :
425 : /* Check whether it is possible to load COUNT elements of type ELT_TYPE
426 : using the method implemented by duplicate_and_interleave. Return true
427 : if so, returning the number of intermediate vectors in *NVECTORS_OUT
428 : (if nonnull) and the type of each intermediate vector in *VECTOR_TYPE_OUT
429 : (if nonnull). */
430 :
431 : bool
432 0 : can_duplicate_and_interleave_p (vec_info *vinfo, unsigned int count,
433 : tree elt_type, unsigned int *nvectors_out,
434 : tree *vector_type_out,
435 : tree *permutes)
436 : {
437 0 : tree base_vector_type = get_vectype_for_scalar_type (vinfo, elt_type, count);
438 0 : if (!base_vector_type || !VECTOR_MODE_P (TYPE_MODE (base_vector_type)))
439 : return false;
440 :
441 0 : machine_mode base_vector_mode = TYPE_MODE (base_vector_type);
442 0 : poly_int64 elt_bytes = count * GET_MODE_UNIT_SIZE (base_vector_mode);
443 0 : unsigned int nvectors = 1;
444 0 : for (;;)
445 : {
446 0 : scalar_int_mode int_mode;
447 0 : poly_int64 elt_bits = elt_bytes * BITS_PER_UNIT;
448 0 : if (int_mode_for_size (elt_bits, 1).exists (&int_mode))
449 : {
450 : /* Get the natural vector type for this SLP group size. */
451 0 : tree int_type = build_nonstandard_integer_type
452 0 : (GET_MODE_BITSIZE (int_mode), 1);
453 0 : tree vector_type
454 0 : = get_vectype_for_scalar_type (vinfo, int_type, count);
455 0 : poly_int64 half_nelts;
456 0 : if (vector_type
457 0 : && VECTOR_MODE_P (TYPE_MODE (vector_type))
458 0 : && known_eq (GET_MODE_SIZE (TYPE_MODE (vector_type)),
459 : GET_MODE_SIZE (base_vector_mode))
460 0 : && multiple_p (GET_MODE_NUNITS (TYPE_MODE (vector_type)),
461 : 2, &half_nelts))
462 : {
463 : /* Try fusing consecutive sequences of COUNT / NVECTORS elements
464 : together into elements of type INT_TYPE and using the result
465 : to build NVECTORS vectors. */
466 0 : poly_uint64 nelts = GET_MODE_NUNITS (TYPE_MODE (vector_type));
467 0 : vec_perm_builder sel1 (nelts, 2, 3);
468 0 : vec_perm_builder sel2 (nelts, 2, 3);
469 :
470 0 : for (unsigned int i = 0; i < 3; ++i)
471 : {
472 0 : sel1.quick_push (i);
473 0 : sel1.quick_push (i + nelts);
474 0 : sel2.quick_push (half_nelts + i);
475 0 : sel2.quick_push (half_nelts + i + nelts);
476 : }
477 0 : vec_perm_indices indices1 (sel1, 2, nelts);
478 0 : vec_perm_indices indices2 (sel2, 2, nelts);
479 0 : machine_mode vmode = TYPE_MODE (vector_type);
480 0 : if (can_vec_perm_const_p (vmode, vmode, indices1)
481 0 : && can_vec_perm_const_p (vmode, vmode, indices2))
482 : {
483 0 : if (nvectors_out)
484 0 : *nvectors_out = nvectors;
485 0 : if (vector_type_out)
486 0 : *vector_type_out = vector_type;
487 0 : if (permutes)
488 : {
489 0 : permutes[0] = vect_gen_perm_mask_checked (vector_type,
490 : indices1);
491 0 : permutes[1] = vect_gen_perm_mask_checked (vector_type,
492 : indices2);
493 : }
494 0 : return true;
495 : }
496 0 : }
497 : }
498 0 : if (!multiple_p (elt_bytes, 2, &elt_bytes))
499 : return false;
500 0 : nvectors *= 2;
501 : /* We need to be able to fuse COUNT / NVECTORS elements together. */
502 0 : if (!multiple_p (count, nvectors))
503 : return false;
504 : }
505 : }
506 :
507 : /* Return true if DTA and DTB match. */
508 :
509 : static bool
510 17179586 : vect_def_types_match (enum vect_def_type dta, enum vect_def_type dtb)
511 : {
512 17179586 : return (dta == dtb
513 366747 : || ((dta == vect_external_def || dta == vect_constant_def)
514 227094 : && (dtb == vect_external_def || dtb == vect_constant_def)));
515 : }
516 :
517 : #define GATHER_SCATTER_OFFSET (-3)
518 :
519 : /* For most SLP statements, there is a one-to-one mapping between
520 : gimple arguments and child nodes. If that is not true for STMT,
521 : return an array that contains:
522 :
523 : - the number of child nodes, followed by
524 : - for each child node, the index of the argument associated with that node.
525 : The special index -1 is the first operand of an embedded comparison and
526 : the special index -2 is the second operand of an embedded comparison.
527 : The special index -3 is the offset of a gather as analyzed by
528 : vect_check_gather_scatter.
529 :
530 : SWAP is as for vect_get_and_check_slp_defs. */
531 :
532 : static const int *
533 25275422 : vect_get_operand_map (const gimple *stmt, bool gather_scatter_p,
534 : unsigned char swap)
535 : {
536 25275422 : static const int no_arg_map[] = { 0 };
537 25275422 : static const int arg0_map[] = { 1, 0 };
538 25275422 : static const int arg2_map[] = { 1, 2 };
539 25275422 : static const int arg2_arg3_map[] = { 2, 2, 3 };
540 25275422 : static const int arg2_arg4_map[] = { 2, 2, 4 };
541 25275422 : static const int arg2_arg5_arg6_map[] = { 3, 2, 5, 6 };
542 25275422 : static const int arg2_arg4_arg5_map[] = { 3, 2, 4, 5 };
543 25275422 : static const int arg3_arg2_map[] = { 2, 3, 2 };
544 25275422 : static const int op00_map[] = { 1, -1 };
545 25275422 : static const int op1_op0_map[] = { 2, 1, 0 };
546 25275422 : static const int off_map[] = { 1, GATHER_SCATTER_OFFSET };
547 25275422 : static const int off_op0_map[] = { 2, GATHER_SCATTER_OFFSET, 0 };
548 25275422 : static const int off_arg2_arg3_map[] = { 3, GATHER_SCATTER_OFFSET, 2, 3 };
549 25275422 : static const int off_arg3_arg2_map[] = { 3, GATHER_SCATTER_OFFSET, 3, 2 };
550 25275422 : static const int mask_call_maps[6][7] = {
551 : { 1, 1, },
552 : { 2, 1, 2, },
553 : { 3, 1, 2, 3, },
554 : { 4, 1, 2, 3, 4, },
555 : { 5, 1, 2, 3, 4, 5, },
556 : { 6, 1, 2, 3, 4, 5, 6 },
557 : };
558 :
559 25275422 : gcc_checking_assert (!swap
560 : || !is_gimple_assign (stmt)
561 : || TREE_CODE_CLASS
562 : (gimple_assign_rhs_code (stmt)) == tcc_comparison
563 : || commutative_tree_code
564 : (gimple_assign_rhs_code (stmt)));
565 :
566 25275422 : if (auto assign = dyn_cast<const gassign *> (stmt))
567 : {
568 23717989 : tree_code code = gimple_assign_rhs_code (assign);
569 23717989 : if (code == COND_EXPR
570 23717989 : && COMPARISON_CLASS_P (gimple_assign_rhs1 (assign)))
571 0 : gcc_unreachable ();
572 23717989 : else if ((TREE_CODE_CLASS (code) == tcc_comparison
573 22205212 : || commutative_tree_code (code))
574 32807569 : && swap)
575 : return op1_op0_map;
576 23674957 : else if (code == VIEW_CONVERT_EXPR)
577 : return op00_map;
578 23665780 : else if (gather_scatter_p)
579 46084 : return (TREE_CODE (gimple_assign_lhs (assign)) != SSA_NAME
580 46084 : ? off_op0_map : off_map);
581 : }
582 1557433 : else if (auto call = dyn_cast<const gcall *> (stmt))
583 : {
584 176916 : if (gimple_call_internal_p (call))
585 93596 : switch (gimple_call_internal_fn (call))
586 : {
587 16137 : case IFN_MASK_LOAD:
588 16137 : return gather_scatter_p ? off_arg2_arg3_map : arg2_arg3_map;
589 :
590 0 : case IFN_GATHER_LOAD:
591 0 : return arg2_map;
592 :
593 0 : case IFN_MASK_GATHER_LOAD:
594 0 : case IFN_MASK_LEN_GATHER_LOAD:
595 0 : return arg2_arg5_arg6_map;
596 :
597 0 : case IFN_SCATTER_STORE:
598 0 : return arg2_arg4_map;
599 :
600 0 : case IFN_MASK_SCATTER_STORE:
601 0 : case IFN_MASK_LEN_SCATTER_STORE:
602 0 : return arg2_arg4_arg5_map;
603 :
604 9125 : case IFN_MASK_STORE:
605 9125 : return gather_scatter_p ? off_arg3_arg2_map : arg3_arg2_map;
606 :
607 996 : case IFN_MASK_CALL:
608 996 : {
609 996 : unsigned nargs = gimple_call_num_args (call);
610 996 : if (nargs >= 2 && nargs <= 7)
611 996 : return mask_call_maps[nargs-2];
612 : else
613 : return nullptr;
614 : }
615 :
616 278 : case IFN_CLZ:
617 278 : case IFN_CTZ:
618 278 : return arg0_map;
619 :
620 7302 : case IFN_GOMP_SIMD_LANE:
621 7302 : return no_arg_map;
622 :
623 : default:
624 : break;
625 : }
626 : }
627 : return nullptr;
628 : }
629 :
630 : static const int *
631 25254088 : vect_get_operand_map (const stmt_vec_info stmt, unsigned char swap = 0)
632 : {
633 0 : return vect_get_operand_map (stmt->stmt, STMT_VINFO_GATHER_SCATTER_P (stmt),
634 0 : swap);
635 : }
636 :
637 : /* Return the SLP node child index for operand OP of STMT. */
638 :
639 : int
640 1398261 : vect_slp_child_index_for_operand (const stmt_vec_info stmt, int op)
641 : {
642 1398261 : const int *opmap = vect_get_operand_map (stmt);
643 1398261 : if (!opmap)
644 : return op;
645 21835 : for (int i = 1; i < 1 + opmap[0]; ++i)
646 21835 : if (opmap[i] == op)
647 12192 : return i - 1;
648 0 : gcc_unreachable ();
649 : }
650 :
651 : /* Helper class for mapping of GIMPLE operands to SLP children. */
652 : /* ??? Add vect_slp_child_index_for_operand here and amend opmaps
653 : with the full reverse mapping and indicating the position of the
654 : first commutative operand index, eliding the swap_p argument from
655 : vect_get_operand_map. Adjust all consumers. */
656 :
657 : struct slp_oprnds {
658 : slp_oprnds (stmt_vec_info);
659 : tree get_op_for_slp_child (stmt_vec_info, unsigned);
660 : const int *opmap;
661 : const unsigned int num_slp_children;
662 : };
663 :
664 4617072 : slp_oprnds::slp_oprnds (stmt_vec_info stmt_info)
665 4617072 : : opmap (vect_get_operand_map (stmt_info)),
666 4617072 : num_slp_children (opmap ? opmap[0] : gimple_num_args (stmt_info->stmt))
667 : {
668 4617072 : }
669 :
670 : /* For SLP child number N get the corresponding tree operand from GIMPLE
671 : statement described by STMT_INFO. */
672 :
673 : tree
674 5153940 : slp_oprnds::get_op_for_slp_child (stmt_vec_info stmt_info, unsigned n)
675 : {
676 5153940 : gcc_assert (n < num_slp_children);
677 5153940 : int opno = opmap ? opmap[n + 1] : (int) n;
678 5153940 : if (opno == GATHER_SCATTER_OFFSET)
679 0 : gcc_unreachable (); // TODO
680 5153940 : else if (opno < 0)
681 2530 : return TREE_OPERAND (gimple_arg (stmt_info->stmt, 0), -1 - opno);
682 : else
683 5151410 : return gimple_arg (stmt_info->stmt, opno);
684 : }
685 :
686 : /* Get the defs for the rhs of STMT (collect them in OPRNDS_INFO), check that
687 : they are of a valid type and that they match the defs of the first stmt of
688 : the SLP group (stored in OPRNDS_INFO). This function tries to match stmts
689 : by swapping operands of STMTS[STMT_NUM] when possible. Non-zero SWAP
690 : indicates swap is required for cond_expr stmts. Specifically, SWAP
691 : is 1 if STMT is cond and operands of comparison need to be swapped;
692 : SWAP is 2 if STMT is cond and code of comparison needs to be inverted.
693 :
694 : If there was a fatal error return -1; if the error could be corrected by
695 : swapping operands of father node of this one, return 1; if everything is
696 : ok return 0. */
697 : static int
698 13053497 : vect_get_and_check_slp_defs (vec_info *vinfo, tree vectype, unsigned char swap,
699 : bool *skip_args,
700 : vec<stmt_vec_info> stmts, unsigned stmt_num,
701 : vec<slp_oprnd_info> *oprnds_info)
702 : {
703 13053497 : stmt_vec_info stmt_info = stmts[stmt_num];
704 13053497 : tree oprnd;
705 13053497 : unsigned int i, number_of_oprnds;
706 13053497 : enum vect_def_type dt = vect_uninitialized_def;
707 13053497 : slp_oprnd_info oprnd_info;
708 13053497 : gather_scatter_info gs_info;
709 13053497 : unsigned int gs_op = -1u;
710 13053497 : unsigned int commutative_op = -1U;
711 13053497 : bool first = stmt_num == 0;
712 :
713 13053497 : if (!stmt_info)
714 : {
715 0 : for (auto oi : *oprnds_info)
716 : {
717 0 : oi->def_stmts.quick_push (NULL);
718 0 : oi->ops.quick_push (NULL_TREE);
719 : }
720 : return 0;
721 : }
722 :
723 13053497 : if (!is_a<gcall *> (stmt_info->stmt)
724 : && !is_a<gassign *> (stmt_info->stmt)
725 : && !is_a<gphi *> (stmt_info->stmt))
726 : return -1;
727 :
728 13053497 : number_of_oprnds = gimple_num_args (stmt_info->stmt);
729 13053497 : const int *map = vect_get_operand_map (stmt_info, swap);
730 13053497 : if (map)
731 80279 : number_of_oprnds = *map++;
732 13053497 : if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
733 : {
734 54578 : if (gimple_call_internal_p (stmt))
735 : {
736 33290 : internal_fn ifn = gimple_call_internal_fn (stmt);
737 33290 : commutative_op = first_commutative_argument (ifn);
738 33290 : if (internal_gather_scatter_fn_p (ifn))
739 : {
740 0 : vect_describe_gather_scatter_call
741 0 : (stmt_info,
742 0 : first ? &(*oprnds_info)[0]->first_gs_info : &gs_info);
743 0 : if (first)
744 0 : (*oprnds_info)[0]->first_gs_p = true;
745 : gs_op = 0;
746 : }
747 : }
748 : }
749 12998919 : else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt))
750 : {
751 15147316 : if (commutative_tree_code (gimple_assign_rhs_code (stmt)))
752 8495663 : commutative_op = 0;
753 : }
754 :
755 13053497 : bool swapped = (swap != 0);
756 13053497 : bool backedge = false;
757 13053497 : enum vect_def_type *dts = XALLOCAVEC (enum vect_def_type, number_of_oprnds);
758 36072729 : for (i = 0; i < number_of_oprnds; i++)
759 : {
760 23020537 : oprnd_info = (*oprnds_info)[i];
761 23020537 : int opno = map ? map[i] : int (i);
762 23020537 : if (opno == GATHER_SCATTER_OFFSET)
763 : {
764 24109 : gcc_assert (STMT_VINFO_GATHER_SCATTER_P (stmt_info));
765 24109 : if (!is_a <loop_vec_info> (vinfo)
766 24109 : || !vect_check_gather_scatter (stmt_info, vectype,
767 : as_a <loop_vec_info> (vinfo),
768 : first ? &oprnd_info->first_gs_info
769 : : &gs_info))
770 1305 : return -1;
771 :
772 24109 : if (first)
773 : {
774 23835 : oprnd_info->first_gs_p = true;
775 23835 : oprnd = oprnd_info->first_gs_info.offset;
776 : }
777 : else
778 : {
779 274 : gs_op = i;
780 274 : oprnd = gs_info.offset;
781 : }
782 : }
783 22996428 : else if (opno < 0)
784 3083 : oprnd = TREE_OPERAND (gimple_arg (stmt_info->stmt, 0), -1 - opno);
785 : else
786 : {
787 22993345 : oprnd = gimple_arg (stmt_info->stmt, opno);
788 22993345 : if (gphi *stmt = dyn_cast <gphi *> (stmt_info->stmt))
789 : {
790 1265347 : edge e = gimple_phi_arg_edge (stmt, opno);
791 2530694 : backedge = (is_a <bb_vec_info> (vinfo)
792 1960712 : ? e->flags & EDGE_DFS_BACK
793 695365 : : dominated_by_p (CDI_DOMINATORS, e->src,
794 695365 : gimple_bb (stmt_info->stmt)));
795 : }
796 : }
797 :
798 23020537 : stmt_vec_info def_stmt_info;
799 23020537 : if (!vect_is_simple_use (oprnd, vinfo, &dts[i], &def_stmt_info))
800 : {
801 1029 : if (dump_enabled_p ())
802 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
803 : "Build SLP failed: can't analyze def for %T\n",
804 : oprnd);
805 :
806 : return -1;
807 : }
808 :
809 23019508 : if (skip_args[i])
810 : {
811 558374 : oprnd_info->def_stmts.quick_push (NULL);
812 558374 : oprnd_info->ops.quick_push (NULL_TREE);
813 558374 : oprnd_info->first_dt = vect_uninitialized_def;
814 558374 : continue;
815 : }
816 :
817 22461134 : oprnd_info->def_stmts.quick_push (def_stmt_info);
818 22461134 : oprnd_info->ops.quick_push (oprnd);
819 :
820 22461134 : if (def_stmt_info
821 22461134 : && is_pattern_stmt_p (def_stmt_info))
822 : {
823 441851 : if (STMT_VINFO_RELATED_STMT (vect_orig_stmt (def_stmt_info))
824 : != def_stmt_info)
825 316667 : oprnd_info->any_pattern = true;
826 : else
827 : /* If we promote this to external use the original stmt def. */
828 125184 : oprnd_info->ops.last ()
829 250368 : = gimple_get_lhs (vect_orig_stmt (def_stmt_info)->stmt);
830 : }
831 :
832 : /* If there's a extern def on a backedge make sure we can
833 : code-generate at the region start.
834 : ??? This is another case that could be fixed by adjusting
835 : how we split the function but at the moment we'd have conflicting
836 : goals there. */
837 22461134 : if (backedge
838 173520 : && dts[i] == vect_external_def
839 297 : && is_a <bb_vec_info> (vinfo)
840 297 : && TREE_CODE (oprnd) == SSA_NAME
841 276 : && !SSA_NAME_IS_DEFAULT_DEF (oprnd)
842 22461410 : && !dominated_by_p (CDI_DOMINATORS, vinfo->bbs[0],
843 276 : gimple_bb (SSA_NAME_DEF_STMT (oprnd))))
844 : {
845 276 : if (dump_enabled_p ())
846 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
847 : "Build SLP failed: extern def %T only defined "
848 : "on backedge\n", oprnd);
849 : return -1;
850 : }
851 :
852 22460858 : if (first)
853 : {
854 5127016 : tree type = TREE_TYPE (oprnd);
855 5127016 : dt = dts[i];
856 :
857 : /* For the swapping logic below force vect_reduction_def
858 : for the reduction op in a SLP reduction group. */
859 5127016 : if (!STMT_VINFO_DATA_REF (stmt_info)
860 3931784 : && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
861 5242 : && (int)i == STMT_VINFO_REDUC_IDX (stmt_info)
862 5129597 : && def_stmt_info)
863 2581 : dts[i] = dt = vect_reduction_def;
864 :
865 : /* Check the types of the definition. */
866 5127016 : switch (dt)
867 : {
868 5127016 : case vect_external_def:
869 5127016 : case vect_constant_def:
870 5127016 : case vect_internal_def:
871 5127016 : case vect_reduction_def:
872 5127016 : case vect_double_reduction_def:
873 5127016 : case vect_induction_def:
874 5127016 : case vect_nested_cycle:
875 5127016 : case vect_first_order_recurrence:
876 5127016 : break;
877 :
878 0 : default:
879 : /* FORNOW: Not supported. */
880 0 : if (dump_enabled_p ())
881 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
882 : "Build SLP failed: illegal type of def %T\n",
883 : oprnd);
884 : return -1;
885 : }
886 :
887 5127016 : oprnd_info->first_dt = dt;
888 5127016 : oprnd_info->first_op_type = type;
889 : }
890 : }
891 13052192 : if (first)
892 : return 0;
893 :
894 : /* Now match the operand definition types to that of the first stmt. */
895 26544557 : for (i = 0; i < number_of_oprnds;)
896 : {
897 17327268 : if (skip_args[i])
898 : {
899 44458 : ++i;
900 44458 : continue;
901 : }
902 :
903 17282810 : oprnd_info = (*oprnds_info)[i];
904 17282810 : dt = dts[i];
905 17282810 : stmt_vec_info def_stmt_info = oprnd_info->def_stmts[stmt_num];
906 17282810 : oprnd = oprnd_info->ops[stmt_num];
907 17282810 : tree type = TREE_TYPE (oprnd);
908 :
909 17282810 : if (!types_compatible_p (oprnd_info->first_op_type, type))
910 : {
911 109757 : if (dump_enabled_p ())
912 93 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
913 : "Build SLP failed: different operand types\n");
914 : return 1;
915 : }
916 :
917 17173053 : if ((gs_op == i) != oprnd_info->first_gs_p)
918 : {
919 0 : if (dump_enabled_p ())
920 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
921 : "Build SLP failed: mixed gather and non-gather\n");
922 : return 1;
923 : }
924 17173053 : else if (gs_op == i)
925 : {
926 242 : if (!operand_equal_p (oprnd_info->first_gs_info.base,
927 242 : gs_info.base))
928 : {
929 16 : if (dump_enabled_p ())
930 6 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
931 : "Build SLP failed: different gather base\n");
932 : return 1;
933 : }
934 226 : if (oprnd_info->first_gs_info.scale != gs_info.scale)
935 : {
936 8 : if (dump_enabled_p ())
937 2 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
938 : "Build SLP failed: different gather scale\n");
939 : return 1;
940 : }
941 : }
942 :
943 : /* Not first stmt of the group, check that the def-stmt/s match
944 : the def-stmt/s of the first stmt. Allow different definition
945 : types for reduction chains: the first stmt must be a
946 : vect_reduction_def (a phi node), and the rest
947 : end in the reduction chain. */
948 17173029 : if ((!vect_def_types_match (oprnd_info->first_dt, dt)
949 307496 : && !(oprnd_info->first_dt == vect_reduction_def
950 4806 : && !STMT_VINFO_DATA_REF (stmt_info)
951 4806 : && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
952 4780 : && def_stmt_info
953 4778 : && !STMT_VINFO_DATA_REF (def_stmt_info)
954 4778 : && (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info)
955 : == REDUC_GROUP_FIRST_ELEMENT (stmt_info))))
956 16870311 : || (!STMT_VINFO_DATA_REF (stmt_info)
957 15535169 : && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
958 9961 : && ((!def_stmt_info
959 9765 : || STMT_VINFO_DATA_REF (def_stmt_info)
960 17987 : || (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info)
961 : != REDUC_GROUP_FIRST_ELEMENT (stmt_info)))
962 9961 : != (oprnd_info->first_dt != vect_reduction_def))))
963 : {
964 : /* Try swapping operands if we got a mismatch. For BB
965 : vectorization only in case it will clearly improve things. */
966 305248 : if (i == commutative_op && !swapped
967 302718 : && (!is_a <bb_vec_info> (vinfo)
968 5038 : || (!vect_def_types_match ((*oprnds_info)[i+1]->first_dt,
969 5038 : dts[i+1])
970 1294 : && (vect_def_types_match (oprnd_info->first_dt, dts[i+1])
971 : || vect_def_types_match
972 225 : ((*oprnds_info)[i+1]->first_dt, dts[i])))))
973 : {
974 2530 : if (dump_enabled_p ())
975 153 : dump_printf_loc (MSG_NOTE, vect_location,
976 : "trying swapped operands\n");
977 2530 : std::swap (dts[i], dts[i+1]);
978 2530 : std::swap ((*oprnds_info)[i]->def_stmts[stmt_num],
979 2530 : (*oprnds_info)[i+1]->def_stmts[stmt_num]);
980 2530 : std::swap ((*oprnds_info)[i]->ops[stmt_num],
981 2530 : (*oprnds_info)[i+1]->ops[stmt_num]);
982 : /* After swapping some operands we lost track whether an
983 : operand has any pattern defs so be conservative here. */
984 2530 : if ((*oprnds_info)[i]->any_pattern
985 2530 : || (*oprnds_info)[i+1]->any_pattern)
986 36 : (*oprnds_info)[i]->any_pattern
987 18 : = (*oprnds_info)[i+1]->any_pattern = true;
988 2530 : swapped = true;
989 2530 : continue;
990 : }
991 :
992 300188 : if (is_a <bb_vec_info> (vinfo)
993 284640 : && !oprnd_info->any_pattern
994 584572 : && number_of_oprnds > 1)
995 : {
996 : /* Now for commutative ops we should see whether we can
997 : make the other operand matching. */
998 106614 : if (dump_enabled_p ())
999 261 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1000 : "treating operand as external\n");
1001 : oprnd_info->first_dt = dt = vect_external_def;
1002 : }
1003 : else
1004 : {
1005 193574 : if (dump_enabled_p ())
1006 411 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1007 : "Build SLP failed: different types\n");
1008 : return 1;
1009 : }
1010 : }
1011 :
1012 : /* Make sure to demote the overall operand to external. */
1013 16870311 : if (dt == vect_external_def)
1014 352042 : oprnd_info->first_dt = vect_external_def;
1015 : /* For a SLP reduction chain we want to duplicate the reduction to
1016 : each of the chain members. That gets us a sane SLP graph (still
1017 : the stmts are not 100% correct wrt the initial values). */
1018 16624883 : else if ((dt == vect_internal_def
1019 16624883 : || dt == vect_reduction_def)
1020 15658083 : && oprnd_info->first_dt == vect_reduction_def
1021 101252 : && !STMT_VINFO_DATA_REF (stmt_info)
1022 101252 : && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
1023 4778 : && !STMT_VINFO_DATA_REF (def_stmt_info)
1024 16629661 : && (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info)
1025 : == REDUC_GROUP_FIRST_ELEMENT (stmt_info)))
1026 : {
1027 4778 : oprnd_info->def_stmts[stmt_num] = oprnd_info->def_stmts[0];
1028 4778 : oprnd_info->ops[stmt_num] = oprnd_info->ops[0];
1029 : }
1030 :
1031 16976925 : ++i;
1032 : }
1033 :
1034 : /* Swap operands. */
1035 9217289 : if (swapped)
1036 : {
1037 43039 : if (dump_enabled_p ())
1038 457 : dump_printf_loc (MSG_NOTE, vect_location,
1039 : "swapped operands to match def types in %G",
1040 : stmt_info->stmt);
1041 : }
1042 :
1043 : return 0;
1044 : }
1045 :
1046 : /* Return true if call statements CALL1 and CALL2 are similar enough
1047 : to be combined into the same SLP group. */
1048 :
1049 : bool
1050 70780 : compatible_calls_p (gcall *call1, gcall *call2, bool allow_two_operators)
1051 : {
1052 70780 : unsigned int nargs = gimple_call_num_args (call1);
1053 70780 : if (nargs != gimple_call_num_args (call2))
1054 : return false;
1055 :
1056 64419 : auto cfn1 = gimple_call_combined_fn (call1);
1057 64419 : auto cfn2 = gimple_call_combined_fn (call2);
1058 64419 : if (cfn1 != cfn2
1059 2 : && (!allow_two_operators
1060 2 : || !((cfn1 == CFN_FMA || cfn1 == CFN_FMS)
1061 2 : && (cfn2 == CFN_FMA || cfn2 == CFN_FMS))))
1062 : return false;
1063 :
1064 64419 : if (gimple_call_internal_p (call1))
1065 : {
1066 7241 : if (!types_compatible_p (TREE_TYPE (gimple_call_lhs (call1)),
1067 7241 : TREE_TYPE (gimple_call_lhs (call2))))
1068 : return false;
1069 14878 : for (unsigned int i = 0; i < nargs; ++i)
1070 7637 : if (!types_compatible_p (TREE_TYPE (gimple_call_arg (call1, i)),
1071 7637 : TREE_TYPE (gimple_call_arg (call2, i))))
1072 : return false;
1073 : }
1074 : else
1075 : {
1076 57178 : if (!operand_equal_p (gimple_call_fn (call1),
1077 57178 : gimple_call_fn (call2), 0))
1078 : return false;
1079 :
1080 42279 : if (gimple_call_fntype (call1) != gimple_call_fntype (call2))
1081 : return false;
1082 : }
1083 :
1084 : /* Check that any unvectorized arguments are equal. */
1085 21334 : if (const int *map = vect_get_operand_map (call1, false, false))
1086 : {
1087 15 : unsigned int nkept = *map++;
1088 15 : unsigned int mapi = 0;
1089 57 : for (unsigned int i = 0; i < nargs; ++i)
1090 42 : if (mapi < nkept && map[mapi] == int (i))
1091 27 : mapi += 1;
1092 15 : else if (!operand_equal_p (gimple_call_arg (call1, i),
1093 15 : gimple_call_arg (call2, i)))
1094 : return false;
1095 : }
1096 :
1097 : return true;
1098 : }
1099 :
1100 : /* A subroutine of vect_build_slp_tree for checking VECTYPE, which is the
1101 : caller's attempt to find the vector type in STMT_INFO with the narrowest
1102 : element type. Return true if VECTYPE is nonnull and if it is valid
1103 : for STMT_INFO. GROUP_SIZE is as for vect_build_slp_tree. */
1104 :
1105 : static bool
1106 5902381 : vect_record_vectype (vec_info *vinfo, stmt_vec_info stmt_info,
1107 : unsigned int group_size, tree vectype)
1108 : {
1109 5902381 : if (!vectype)
1110 : {
1111 4241 : if (dump_enabled_p ())
1112 7 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1113 : "Build SLP failed: unsupported data-type in %G\n",
1114 : stmt_info->stmt);
1115 : /* Fatal mismatch. */
1116 : return false;
1117 : }
1118 :
1119 : /* If populating the vector type requires unrolling then fail
1120 : for basic-block vectorization. */
1121 5898140 : if (is_a <bb_vec_info> (vinfo)
1122 5898140 : && !multiple_p (group_size, TYPE_VECTOR_SUBPARTS (vectype)))
1123 : {
1124 216055 : if (dump_enabled_p ())
1125 155 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1126 : "Build SLP failed: unrolling required "
1127 : "in basic block SLP\n");
1128 : /* Fatal mismatch. */
1129 : return false;
1130 : }
1131 :
1132 : return true;
1133 : }
1134 :
1135 : /* Verify if the scalar stmts STMTS are isomorphic, require data
1136 : permutation or are of unsupported types of operation. Return
1137 : true if they are, otherwise return false and indicate in *MATCHES
1138 : which stmts are not isomorphic to the first one. If MATCHES[0]
1139 : is false then this indicates the comparison could not be
1140 : carried out or the stmts will never be vectorized by SLP.
1141 :
1142 : Note COND_EXPR is possibly isomorphic to another one after swapping its
1143 : operands. Set SWAP[i] to 1 if stmt I is COND_EXPR and isomorphic to
1144 : the first stmt by swapping the two operands of comparison; set SWAP[i]
1145 : to 2 if stmt I is isormorphic to the first stmt by inverting the code
1146 : of comparison. Take A1 >= B1 ? X1 : Y1 as an example, it can be swapped
1147 : to (B1 <= A1 ? X1 : Y1); or be inverted to (A1 < B1) ? Y1 : X1. */
1148 :
1149 : static bool
1150 6181011 : vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
1151 : vec<stmt_vec_info> stmts, bool *matches,
1152 : bool *two_operators, tree *node_vectype)
1153 : {
1154 6181011 : unsigned int group_size = stmts.length ();
1155 6181011 : unsigned int i;
1156 6181011 : stmt_vec_info first_stmt_info = stmts[0];
1157 6181011 : code_helper first_stmt_code = ERROR_MARK;
1158 6181011 : code_helper alt_stmt_code = ERROR_MARK;
1159 6181011 : code_helper first_cond_code = ERROR_MARK;
1160 6181011 : bool need_same_oprnds = false;
1161 6181011 : tree first_lhs = NULL_TREE;
1162 6181011 : tree first_op1 = NULL_TREE;
1163 6181011 : stmt_vec_info first_load = NULL, prev_first_load = NULL;
1164 6181011 : bool first_stmt_ldst_p = false, first_stmt_ldst_masklen_p = false;
1165 6181011 : bool first_stmt_phi_p = false;
1166 6181011 : int first_reduc_idx = -1;
1167 6181011 : bool maybe_soft_fail = false;
1168 6181011 : tree soft_fail_nunits_vectype = NULL_TREE;
1169 :
1170 6181011 : tree vectype, nunits_vectype;
1171 6181011 : if (!vect_get_vector_types_for_stmt (vinfo, first_stmt_info, &vectype,
1172 : &nunits_vectype, group_size))
1173 : {
1174 : /* Fatal mismatch. */
1175 237129 : matches[0] = false;
1176 237129 : return false;
1177 : }
1178 5943882 : if (is_a <bb_vec_info> (vinfo)
1179 5943882 : && known_le (TYPE_VECTOR_SUBPARTS (vectype), 1U))
1180 : {
1181 358406 : if (dump_enabled_p ())
1182 301 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1183 : "Build SLP failed: not using single lane "
1184 : "vector type %T\n", vectype);
1185 358406 : matches[0] = false;
1186 358406 : return false;
1187 : }
1188 : /* Record nunits required but continue analysis, producing matches[]
1189 : as if nunits was not an issue. This allows splitting of groups
1190 : to happen. */
1191 5585476 : if (nunits_vectype
1192 5585476 : && !vect_record_vectype (vinfo, first_stmt_info, group_size,
1193 : nunits_vectype))
1194 : {
1195 216055 : gcc_assert (is_a <bb_vec_info> (vinfo));
1196 216055 : maybe_soft_fail = true;
1197 216055 : soft_fail_nunits_vectype = nunits_vectype;
1198 : }
1199 :
1200 5585476 : gcc_assert (vectype || !gimple_get_lhs (first_stmt_info->stmt));
1201 5585476 : *node_vectype = vectype;
1202 :
1203 5585476 : basic_block common_bb = gimple_bb (first_stmt_info->stmt);
1204 5585476 : gimple *trapping_stmt = NULL;
1205 :
1206 : /* For every stmt in NODE find its def stmt/s. */
1207 5585476 : stmt_vec_info stmt_info;
1208 23453710 : FOR_EACH_VEC_ELT (stmts, i, stmt_info)
1209 : {
1210 18046221 : bool ldst_p = false;
1211 18046221 : bool ldst_masklen_p = false;
1212 18046221 : bool phi_p = false;
1213 18046221 : code_helper rhs_code = ERROR_MARK;
1214 :
1215 18046221 : swap[i] = 0;
1216 18046221 : matches[i] = false;
1217 18046221 : if (!stmt_info)
1218 : {
1219 40999 : matches[i] = true;
1220 17868234 : continue;
1221 : }
1222 :
1223 18005222 : gimple *stmt = stmt_info->stmt;
1224 18005222 : if (dump_enabled_p ())
1225 227349 : dump_printf_loc (MSG_NOTE, vect_location, "Build SLP for %G", stmt);
1226 :
1227 : /* Fail to vectorize statements marked as unvectorizable, throw
1228 : or are volatile. */
1229 18005222 : if (!STMT_VINFO_VECTORIZABLE (stmt_info)
1230 17753106 : || stmt_can_throw_internal (cfun, stmt)
1231 34893038 : || gimple_has_volatile_ops (stmt))
1232 : {
1233 259088 : if (dump_enabled_p ())
1234 248 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1235 : "Build SLP failed: unvectorizable statement %G",
1236 : stmt);
1237 : /* ??? For BB vectorization we want to commutate operands in a way
1238 : to shuffle all unvectorizable defs into one operand and have
1239 : the other still vectorized. The following doesn't reliably
1240 : work for this though but it's the easiest we can do here. */
1241 259088 : if (is_a <bb_vec_info> (vinfo) && i != 0)
1242 106481 : continue;
1243 : /* Fatal mismatch. */
1244 152607 : matches[0] = false;
1245 152607 : return false;
1246 : }
1247 :
1248 17746134 : gcall *call_stmt = dyn_cast <gcall *> (stmt);
1249 17746134 : tree lhs = gimple_get_lhs (stmt);
1250 17746134 : if (lhs == NULL_TREE && !call_stmt)
1251 : {
1252 34 : if (dump_enabled_p ())
1253 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1254 : "Build SLP failed: not GIMPLE_ASSIGN nor "
1255 : "GIMPLE_CALL %G", stmt);
1256 34 : if (is_a <bb_vec_info> (vinfo) && i != 0)
1257 34 : continue;
1258 : /* Fatal mismatch. */
1259 0 : matches[0] = false;
1260 0 : return false;
1261 : }
1262 :
1263 17746100 : if (call_stmt)
1264 : {
1265 174643 : combined_fn cfn = gimple_call_combined_fn (call_stmt);
1266 174643 : if (cfn != CFN_LAST && cfn != CFN_MASK_CALL)
1267 59980 : rhs_code = cfn;
1268 : else
1269 : rhs_code = CALL_EXPR;
1270 :
1271 174643 : if (cfn == CFN_GATHER_LOAD
1272 174643 : || cfn == CFN_SCATTER_STORE)
1273 : ldst_p = true;
1274 : else if (cfn == CFN_MASK_LOAD
1275 : || cfn == CFN_MASK_GATHER_LOAD
1276 : || cfn == CFN_MASK_LEN_GATHER_LOAD
1277 : || cfn == CFN_MASK_SCATTER_STORE
1278 : || cfn == CFN_MASK_LEN_SCATTER_STORE)
1279 : {
1280 : ldst_p = true;
1281 : ldst_masklen_p = true;
1282 : }
1283 : else if (cfn == CFN_MASK_STORE)
1284 : {
1285 : ldst_p = true;
1286 : ldst_masklen_p = true;
1287 : rhs_code = CFN_MASK_STORE;
1288 : }
1289 : else if (cfn == CFN_GOMP_SIMD_LANE)
1290 : ;
1291 162763 : else if ((cfn != CFN_LAST
1292 : && cfn != CFN_MASK_CALL
1293 48100 : && internal_fn_p (cfn)
1294 37571 : && !vectorizable_internal_fn_p (as_internal_fn (cfn)))
1295 162680 : || gimple_call_tail_p (call_stmt)
1296 162680 : || gimple_call_noreturn_p (call_stmt)
1297 325443 : || gimple_call_chain (call_stmt))
1298 : {
1299 443 : if (dump_enabled_p ())
1300 13 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1301 : "Build SLP failed: unsupported call type %G",
1302 : (gimple *) call_stmt);
1303 443 : if (is_a <bb_vec_info> (vinfo) && i != 0)
1304 72 : continue;
1305 : /* Fatal mismatch. */
1306 371 : matches[0] = false;
1307 371 : return false;
1308 : }
1309 : }
1310 17571457 : else if (gimple_code (stmt) == GIMPLE_PHI)
1311 : {
1312 17745657 : rhs_code = ERROR_MARK;
1313 17745657 : phi_p = true;
1314 : }
1315 : else
1316 : {
1317 16706167 : rhs_code = gimple_assign_rhs_code (stmt);
1318 16706167 : ldst_p = STMT_VINFO_DATA_REF (stmt_info) != nullptr;
1319 : }
1320 :
1321 : /* Check the operation. */
1322 17745657 : if (i == 0)
1323 : {
1324 5432498 : first_lhs = lhs;
1325 5432498 : first_stmt_code = rhs_code;
1326 5432498 : first_stmt_ldst_p = ldst_p;
1327 5432498 : first_stmt_ldst_masklen_p = ldst_masklen_p;
1328 5432498 : first_stmt_phi_p = phi_p;
1329 5432498 : first_reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info);
1330 :
1331 : /* Shift arguments should be equal in all the packed stmts for a
1332 : vector shift with scalar shift operand. */
1333 5432498 : if (rhs_code == LSHIFT_EXPR
1334 5360918 : || rhs_code == RSHIFT_EXPR
1335 5289814 : || rhs_code == LROTATE_EXPR
1336 10722198 : || rhs_code == RROTATE_EXPR)
1337 : {
1338 : /* First see if we have a vector/vector shift. */
1339 143276 : if (!directly_supported_p (rhs_code, vectype, optab_vector))
1340 : {
1341 : /* No vector/vector shift, arrange for a vector/scalar
1342 : SLP layout. */
1343 131085 : need_same_oprnds = true;
1344 131085 : first_op1 = gimple_assign_rhs2 (stmt);
1345 : }
1346 : }
1347 5289222 : else if (rhs_code == WIDEN_LSHIFT_EXPR)
1348 : {
1349 0 : need_same_oprnds = true;
1350 0 : first_op1 = gimple_assign_rhs2 (stmt);
1351 : }
1352 5289222 : else if (!ldst_p
1353 5289222 : && rhs_code == BIT_FIELD_REF)
1354 : {
1355 8914 : tree vec = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
1356 8914 : if (!is_a <bb_vec_info> (vinfo)
1357 8788 : || TREE_CODE (vec) != SSA_NAME
1358 : /* When the element types are not compatible we pun the
1359 : source to the target vectype which requires equal size. */
1360 17690 : || ((!VECTOR_TYPE_P (TREE_TYPE (vec))
1361 7979 : || !types_compatible_p (TREE_TYPE (vectype),
1362 7979 : TREE_TYPE (TREE_TYPE (vec))))
1363 1116 : && !operand_equal_p (TYPE_SIZE (vectype),
1364 1116 : TYPE_SIZE (TREE_TYPE (vec)))))
1365 : {
1366 853 : if (dump_enabled_p ())
1367 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1368 : "Build SLP failed: "
1369 : "BIT_FIELD_REF not supported\n");
1370 : /* Fatal mismatch. */
1371 853 : matches[0] = false;
1372 853 : return false;
1373 : }
1374 : }
1375 5280308 : else if (rhs_code == CFN_DIV_POW2)
1376 : {
1377 0 : need_same_oprnds = true;
1378 0 : first_op1 = gimple_call_arg (call_stmt, 1);
1379 : }
1380 5280308 : else if (rhs_code == CFN_GOMP_SIMD_LANE)
1381 : {
1382 3651 : need_same_oprnds = true;
1383 3651 : first_op1 = gimple_call_arg (call_stmt, 1);
1384 : }
1385 : }
1386 : else
1387 : {
1388 12313159 : int comm_arg;
1389 12313537 : if (first_reduc_idx != STMT_VINFO_REDUC_IDX (stmt_info)
1390 : /* For SLP reduction groups the index isn't necessarily
1391 : uniform but only that of the first stmt matters. */
1392 2382 : && !(first_reduc_idx != -1
1393 2382 : && STMT_VINFO_REDUC_IDX (stmt_info) != -1
1394 2382 : && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
1395 12313159 : && !(first_reduc_idx != -1
1396 1085 : && STMT_VINFO_REDUC_IDX (stmt_info) != -1
1397 1085 : && (comm_arg = first_commutative_argument
1398 1085 : (rhs_code, TREE_TYPE (lhs))) >= 0
1399 : && (first_reduc_idx
1400 851 : == 2 * comm_arg + 1 - STMT_VINFO_REDUC_IDX (stmt_info))))
1401 : {
1402 378 : if (dump_enabled_p ())
1403 : {
1404 12 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1405 : "Build SLP failed: different reduc_idx "
1406 : "%d instead of %d in %G",
1407 : STMT_VINFO_REDUC_IDX (stmt_info),
1408 : first_reduc_idx, stmt);
1409 : }
1410 : /* Mismatch. */
1411 378 : continue;
1412 : }
1413 12312781 : if (!ldst_p
1414 9670548 : && first_stmt_code != rhs_code
1415 13826456 : && alt_stmt_code == ERROR_MARK)
1416 : alt_stmt_code = rhs_code;
1417 13804046 : if ((!ldst_p
1418 9670548 : && first_stmt_code != rhs_code
1419 1513675 : && (first_stmt_code != IMAGPART_EXPR
1420 218 : || rhs_code != REALPART_EXPR)
1421 1513654 : && (first_stmt_code != REALPART_EXPR
1422 734 : || rhs_code != IMAGPART_EXPR)
1423 : /* Handle mismatches in plus/minus by computing both
1424 : and merging the results. */
1425 1513651 : && !((((first_stmt_code == PLUS_EXPR
1426 1404666 : || first_stmt_code == MINUS_EXPR)
1427 139324 : && (alt_stmt_code == PLUS_EXPR
1428 129459 : || alt_stmt_code == MINUS_EXPR))
1429 1482255 : || ((first_stmt_code == CFN_FMA
1430 1482253 : || first_stmt_code == CFN_FMS)
1431 2 : && (alt_stmt_code == CFN_FMA
1432 2 : || alt_stmt_code == CFN_FMS)))
1433 31398 : && rhs_code == alt_stmt_code)
1434 1526039 : && !(first_stmt_code.is_tree_code ()
1435 1384038 : && rhs_code.is_tree_code ()
1436 1267731 : && (TREE_CODE_CLASS (tree_code (first_stmt_code))
1437 : == tcc_comparison)
1438 140841 : && (swap_tree_comparison (tree_code (first_stmt_code))
1439 140841 : == tree_code (rhs_code))
1440 : && (first_reduc_idx == -1
1441 0 : || REDUC_GROUP_FIRST_ELEMENT (stmt_info))))
1442 : || (ldst_p
1443 5284466 : && (STMT_VINFO_GROUPED_ACCESS (stmt_info)
1444 2642233 : != STMT_VINFO_GROUPED_ACCESS (first_stmt_info)))
1445 : || (ldst_p
1446 2590392 : && (STMT_VINFO_GATHER_SCATTER_P (stmt_info)
1447 2590392 : != STMT_VINFO_GATHER_SCATTER_P (first_stmt_info)))
1448 10821688 : || first_stmt_ldst_p != ldst_p
1449 10821524 : || (ldst_p && first_stmt_ldst_masklen_p != ldst_masklen_p)
1450 23134297 : || first_stmt_phi_p != phi_p)
1451 : {
1452 1491265 : if (dump_enabled_p ())
1453 : {
1454 3375 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1455 : "Build SLP failed: different operation "
1456 : "in stmt %G", stmt);
1457 3375 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1458 : "original stmt %G", first_stmt_info->stmt);
1459 : }
1460 : /* Mismatch. */
1461 1491265 : continue;
1462 : }
1463 :
1464 10838351 : if (!ldst_p
1465 8231275 : && first_stmt_code == BIT_FIELD_REF
1466 10848129 : && (TREE_OPERAND (gimple_assign_rhs1 (first_stmt_info->stmt), 0)
1467 26613 : != TREE_OPERAND (gimple_assign_rhs1 (stmt_info->stmt), 0)))
1468 : {
1469 16835 : if (dump_enabled_p ())
1470 76 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1471 : "Build SLP failed: different BIT_FIELD_REF "
1472 : "arguments in %G", stmt);
1473 : /* Mismatch. */
1474 16835 : continue;
1475 : }
1476 :
1477 10804681 : if (call_stmt
1478 71493 : && first_stmt_code != CFN_MASK_LOAD
1479 10875772 : && first_stmt_code != CFN_MASK_STORE)
1480 : {
1481 70780 : if (!is_a <gcall *> (stmts[0]->stmt)
1482 70780 : || !compatible_calls_p (as_a <gcall *> (stmts[0]->stmt),
1483 : call_stmt, true))
1484 : {
1485 49446 : if (dump_enabled_p ())
1486 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1487 : "Build SLP failed: different calls in %G",
1488 : stmt);
1489 : /* Mismatch. */
1490 49446 : continue;
1491 : }
1492 : }
1493 :
1494 10796636 : if (phi_p
1495 10755235 : && (gimple_bb (first_stmt_info->stmt)
1496 208044 : != gimple_bb (stmt_info->stmt)))
1497 : {
1498 41401 : if (dump_enabled_p ())
1499 6 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1500 : "Build SLP failed: different BB for PHI %G",
1501 : stmt);
1502 : /* Mismatch. */
1503 41401 : continue;
1504 : }
1505 :
1506 10713834 : if (need_same_oprnds)
1507 : {
1508 55367 : tree other_op1 = gimple_arg (stmt, 1);
1509 55367 : if (!operand_equal_p (first_op1, other_op1, 0))
1510 : {
1511 7002 : if (dump_enabled_p ())
1512 133 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1513 : "Build SLP failed: different shift "
1514 : "arguments in %G", stmt);
1515 : /* Mismatch. */
1516 7002 : continue;
1517 : }
1518 : }
1519 :
1520 10707569 : if (first_lhs
1521 10706832 : && lhs
1522 10706832 : && !types_compatible_p (TREE_TYPE (lhs), TREE_TYPE (first_lhs)))
1523 : {
1524 737 : if (dump_enabled_p ())
1525 6 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1526 : "Build SLP failed: different vector type "
1527 : "in %G", stmt);
1528 : /* Mismatch. */
1529 737 : continue;
1530 : }
1531 : }
1532 :
1533 : /* Grouped store or load. */
1534 16137740 : if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
1535 : {
1536 4009059 : gcc_assert (ldst_p);
1537 4009059 : if (DR_IS_WRITE (STMT_VINFO_DATA_REF (stmt_info)))
1538 : {
1539 : /* Store. */
1540 3103737 : gcc_assert (rhs_code == CFN_MASK_STORE
1541 : || REFERENCE_CLASS_P (lhs)
1542 : || DECL_P (lhs));
1543 : }
1544 : else
1545 : {
1546 : /* Load. */
1547 905322 : first_load = DR_GROUP_FIRST_ELEMENT (stmt_info);
1548 905322 : if (prev_first_load)
1549 : {
1550 : /* Check that there are no loads from different interleaving
1551 : chains in the same node. */
1552 418766 : if (prev_first_load != first_load)
1553 : {
1554 62875 : if (dump_enabled_p ())
1555 2217 : dump_printf_loc (MSG_MISSED_OPTIMIZATION,
1556 : vect_location,
1557 : "Build SLP failed: different "
1558 : "interleaving chains in one node %G",
1559 : stmt);
1560 : /* Mismatch. */
1561 62875 : continue;
1562 : }
1563 : }
1564 : else
1565 : prev_first_load = first_load;
1566 : }
1567 : }
1568 : /* Non-grouped store or load. */
1569 12128681 : else if (ldst_p)
1570 : {
1571 923103 : if (DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info))
1572 646140 : && rhs_code != CFN_GATHER_LOAD
1573 : && rhs_code != CFN_MASK_GATHER_LOAD
1574 : && rhs_code != CFN_MASK_LEN_GATHER_LOAD
1575 : && rhs_code != CFN_SCATTER_STORE
1576 : && rhs_code != CFN_MASK_SCATTER_STORE
1577 : && rhs_code != CFN_MASK_LEN_SCATTER_STORE
1578 646140 : && !STMT_VINFO_GATHER_SCATTER_P (stmt_info)
1579 : /* Not grouped loads are handled as externals for BB
1580 : vectorization. For loop vectorization we can handle
1581 : splats the same we handle single element interleaving.
1582 : Likewise we can handle a collection of invariant refs. */
1583 1549371 : && (is_a <bb_vec_info> (vinfo)
1584 626268 : || (stmt_info != first_stmt_info
1585 68115 : && !(integer_zerop (DR_STEP (STMT_VINFO_DATA_REF (stmt_info)))
1586 241 : && integer_zerop (DR_STEP (STMT_VINFO_DATA_REF
1587 : (first_stmt_info)))))))
1588 : {
1589 : /* Not grouped load. */
1590 67633 : if (dump_enabled_p ())
1591 145 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1592 : "Build SLP failed: not grouped load %G", stmt);
1593 :
1594 67633 : if (i != 0)
1595 67633 : continue;
1596 : /* Fatal mismatch. */
1597 0 : matches[0] = false;
1598 0 : return false;
1599 : }
1600 : }
1601 : /* Not memory operation. */
1602 : else
1603 : {
1604 11205578 : if (!phi_p
1605 10501144 : && rhs_code.is_tree_code ()
1606 10451486 : && TREE_CODE_CLASS (tree_code (rhs_code)) != tcc_binary
1607 1823434 : && TREE_CODE_CLASS (tree_code (rhs_code)) != tcc_unary
1608 1130279 : && TREE_CODE_CLASS (tree_code (rhs_code)) != tcc_expression
1609 1060618 : && TREE_CODE_CLASS (tree_code (rhs_code)) != tcc_comparison
1610 89685 : && rhs_code != VIEW_CONVERT_EXPR
1611 : && rhs_code != CALL_EXPR
1612 : && rhs_code != BIT_FIELD_REF
1613 11205578 : && rhs_code != SSA_NAME)
1614 : {
1615 24156 : if (dump_enabled_p ())
1616 17 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1617 : "Build SLP failed: operation unsupported %G",
1618 : stmt);
1619 24156 : if (is_a <bb_vec_info> (vinfo) && i != 0)
1620 0 : continue;
1621 : /* Fatal mismatch. */
1622 24156 : matches[0] = false;
1623 24156 : return false;
1624 : }
1625 :
1626 11181422 : if (rhs_code == COND_EXPR)
1627 : {
1628 66734 : tree cond_expr = gimple_assign_rhs1 (stmt);
1629 66734 : enum tree_code cond_code = TREE_CODE (cond_expr);
1630 66734 : enum tree_code swap_code = ERROR_MARK;
1631 66734 : enum tree_code invert_code = ERROR_MARK;
1632 :
1633 66734 : if (i == 0)
1634 54600 : first_cond_code = TREE_CODE (cond_expr);
1635 12134 : else if (TREE_CODE_CLASS (cond_code) == tcc_comparison)
1636 : {
1637 0 : bool honor_nans = HONOR_NANS (TREE_OPERAND (cond_expr, 0));
1638 0 : swap_code = swap_tree_comparison (cond_code);
1639 0 : invert_code = invert_tree_comparison (cond_code, honor_nans);
1640 : }
1641 :
1642 66734 : if (first_cond_code == cond_code)
1643 : ;
1644 : /* Isomorphic can be achieved by swapping. */
1645 0 : else if (first_cond_code == swap_code)
1646 0 : swap[i] = 1;
1647 : /* Isomorphic can be achieved by inverting. */
1648 0 : else if (first_cond_code == invert_code)
1649 0 : swap[i] = 2;
1650 : else
1651 : {
1652 0 : if (dump_enabled_p ())
1653 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1654 : "Build SLP failed: different"
1655 : " operation %G", stmt);
1656 : /* Mismatch. */
1657 0 : continue;
1658 : }
1659 : }
1660 :
1661 11181422 : if (i != 0
1662 8116221 : && first_stmt_code != rhs_code
1663 74418 : && first_stmt_code.is_tree_code ()
1664 74416 : && rhs_code.is_tree_code ()
1665 74416 : && TREE_CODE_CLASS ((tree_code)first_stmt_code) == tcc_comparison
1666 11224825 : && (swap_tree_comparison ((tree_code)first_stmt_code)
1667 43403 : == (tree_code)rhs_code))
1668 43403 : swap[i] = 1;
1669 :
1670 11181422 : if (i != 0
1671 8116221 : && first_reduc_idx != STMT_VINFO_REDUC_IDX (stmt_info)
1672 1716 : && first_reduc_idx != -1
1673 1716 : && STMT_VINFO_REDUC_IDX (stmt_info) != -1
1674 1716 : && rhs_code.is_tree_code ()
1675 1708 : && commutative_tree_code (tree_code (rhs_code))
1676 11183128 : && first_reduc_idx == 1 - STMT_VINFO_REDUC_IDX (stmt_info))
1677 1706 : swap[i] = 1;
1678 : }
1679 :
1680 : /* We need to ensure all stmts are in the same BB when one stmt could
1681 : trap. Not matching stmts are not relevant, so exclude those. */
1682 15983076 : if (!trapping_stmt && gimple_could_trap_p (stmt))
1683 : trapping_stmt = stmt;
1684 15983076 : if (common_bb != gimple_bb (stmt))
1685 62327 : common_bb = NULL;
1686 :
1687 15983076 : matches[i] = true;
1688 : }
1689 :
1690 5407489 : if (trapping_stmt && common_bb == NULL)
1691 : {
1692 824 : if (dump_enabled_p ())
1693 4 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1694 : "Build SLP failed: not all stmts in same BB but "
1695 : "possibly trapping operation in %G", trapping_stmt);
1696 : /* Fatal mismatch. */
1697 824 : matches[0] = false;
1698 824 : return false;
1699 : }
1700 :
1701 21381919 : for (i = 0; i < group_size; ++i)
1702 16756435 : if (!matches[i])
1703 : return false;
1704 :
1705 : /* If we allowed a two-operation SLP node verify the target can cope
1706 : with the permute we are going to use. */
1707 4625484 : if (alt_stmt_code != ERROR_MARK
1708 4625484 : && (!alt_stmt_code.is_tree_code ()
1709 57597 : || (TREE_CODE_CLASS (tree_code (alt_stmt_code)) != tcc_reference
1710 57597 : && TREE_CODE_CLASS (tree_code (alt_stmt_code)) != tcc_comparison)))
1711 : {
1712 16401 : *two_operators = true;
1713 : }
1714 :
1715 4625484 : if (maybe_soft_fail)
1716 : {
1717 162841 : unsigned HOST_WIDE_INT const_nunits;
1718 162841 : if (!TYPE_VECTOR_SUBPARTS
1719 162841 : (soft_fail_nunits_vectype).is_constant (&const_nunits)
1720 162841 : || const_nunits > group_size)
1721 0 : matches[0] = false;
1722 : else
1723 : {
1724 : /* With constant vector elements simulate a mismatch at the
1725 : point we need to split. */
1726 162841 : unsigned tail = group_size & (const_nunits - 1);
1727 162841 : memset (&matches[group_size - tail], 0, sizeof (bool) * tail);
1728 : }
1729 : return false;
1730 : }
1731 :
1732 : return true;
1733 : }
1734 :
1735 : /* Traits for the hash_set to record failed SLP builds for a stmt set.
1736 : Note we never remove apart from at destruction time so we do not
1737 : need a special value for deleted that differs from empty. */
1738 : struct bst_traits
1739 : {
1740 : typedef vec <stmt_vec_info> value_type;
1741 : typedef vec <stmt_vec_info> compare_type;
1742 : static inline hashval_t hash (value_type);
1743 : static inline bool equal (value_type existing, value_type candidate);
1744 510115586 : static inline bool is_empty (value_type x) { return !x.exists (); }
1745 114579579 : static inline bool is_deleted (value_type x) { return !x.exists (); }
1746 : static const bool empty_zero_p = true;
1747 0 : static inline void mark_empty (value_type &x) { x.release (); }
1748 : static inline void mark_deleted (value_type &x) { x.release (); }
1749 9823221 : static inline void remove (value_type &x) { x.release (); }
1750 : };
1751 : inline hashval_t
1752 99722115 : bst_traits::hash (value_type x)
1753 : {
1754 99722115 : inchash::hash h;
1755 442660500 : for (unsigned i = 0; i < x.length (); ++i)
1756 342938385 : h.add_int (x[i] ? gimple_uid (x[i]->stmt) : -1);
1757 99722115 : return h.end ();
1758 : }
1759 : inline bool
1760 87360022 : bst_traits::equal (value_type existing, value_type candidate)
1761 : {
1762 262080066 : if (existing.length () != candidate.length ())
1763 : return false;
1764 87657007 : for (unsigned i = 0; i < existing.length (); ++i)
1765 83098272 : if (existing[i] != candidate[i])
1766 : return false;
1767 : return true;
1768 : }
1769 :
1770 : typedef hash_map <vec <stmt_vec_info>, slp_tree,
1771 : simple_hashmap_traits <bst_traits, slp_tree> >
1772 : scalar_stmts_to_slp_tree_map_t;
1773 :
1774 : /* Release BST_MAP. */
1775 :
1776 : static void
1777 1901275 : release_scalar_stmts_to_slp_tree_map (scalar_stmts_to_slp_tree_map_t *bst_map)
1778 : {
1779 : /* The map keeps a reference on SLP nodes built, release that. */
1780 11724496 : for (scalar_stmts_to_slp_tree_map_t::iterator it = bst_map->begin ();
1781 11724496 : it != bst_map->end (); ++it)
1782 9823221 : if ((*it).second)
1783 9823221 : vect_free_slp_tree ((*it).second);
1784 3802550 : delete bst_map;
1785 1901275 : }
1786 :
1787 : /* ??? This was std::pair<std::pair<tree_code, vect_def_type>, tree>
1788 : but then vec::insert does memmove and that's not compatible with
1789 : std::pair. */
1790 : struct chain_op_t
1791 : {
1792 4293748 : chain_op_t (tree_code code_, vect_def_type dt_, tree op_)
1793 4293748 : : code (code_), dt (dt_), op (op_) {}
1794 : tree_code code;
1795 : vect_def_type dt;
1796 : tree op;
1797 : };
1798 :
1799 : /* Comparator for sorting associatable chains. */
1800 :
1801 : static int
1802 12570305 : dt_sort_cmp (const void *op1_, const void *op2_, void *)
1803 : {
1804 12570305 : auto *op1 = (const chain_op_t *) op1_;
1805 12570305 : auto *op2 = (const chain_op_t *) op2_;
1806 12570305 : if (op1->dt != op2->dt)
1807 1843818 : return (int)op1->dt - (int)op2->dt;
1808 10726487 : return (int)op1->code - (int)op2->code;
1809 : }
1810 :
1811 : /* Linearize the associatable expression chain at START with the
1812 : associatable operation CODE (where PLUS_EXPR also allows MINUS_EXPR),
1813 : filling CHAIN with the result and using WORKLIST as intermediate storage.
1814 : CODE_STMT and ALT_CODE_STMT are filled with the first stmt using CODE
1815 : or MINUS_EXPR. *CHAIN_STMTS if not NULL is filled with all computation
1816 : stmts, starting with START. When ALLOW_ALT_CODE is false, do not
1817 : follow into MINUS_EXPR when building a PLUS chain (treat MINUS as leaf). */
1818 :
1819 : static void
1820 1851645 : vect_slp_linearize_chain (vec_info *vinfo,
1821 : vec<std::pair<tree_code, gimple *> > &worklist,
1822 : vec<chain_op_t> &chain,
1823 : enum tree_code code, gimple *start,
1824 : gimple *&code_stmt, gimple *&alt_code_stmt,
1825 : vec<gimple *> *chain_stmts,
1826 : bool allow_alt_code = true)
1827 : {
1828 : /* For each lane linearize the addition/subtraction (or other
1829 : uniform associatable operation) expression tree. */
1830 1851645 : worklist.safe_push (std::make_pair (code, start));
1831 4293748 : while (!worklist.is_empty ())
1832 : {
1833 2442103 : auto entry = worklist.pop ();
1834 2442103 : gassign *stmt = as_a <gassign *> (entry.second);
1835 2442103 : enum tree_code in_code = entry.first;
1836 4884206 : enum tree_code this_code = gimple_assign_rhs_code (stmt);
1837 : /* Pick some stmts suitable for SLP_TREE_REPRESENTATIVE. */
1838 2442103 : if (!code_stmt
1839 2442103 : && gimple_assign_rhs_code (stmt) == code)
1840 1544979 : code_stmt = stmt;
1841 897124 : else if (!alt_code_stmt
1842 897124 : && gimple_assign_rhs_code (stmt) == MINUS_EXPR)
1843 363478 : alt_code_stmt = stmt;
1844 2442103 : if (chain_stmts)
1845 2360873 : chain_stmts->safe_push (stmt);
1846 7326309 : for (unsigned opnum = 1; opnum <= 2; ++opnum)
1847 : {
1848 4884206 : tree op = gimple_op (stmt, opnum);
1849 4884206 : vect_def_type dt;
1850 4884206 : stmt_vec_info def_stmt_info;
1851 4884206 : bool res = vect_is_simple_use (op, vinfo, &dt, &def_stmt_info);
1852 4884206 : gcc_assert (res);
1853 4884206 : if (dt == vect_internal_def
1854 4884206 : && is_pattern_stmt_p (def_stmt_info))
1855 9280 : op = gimple_get_lhs (def_stmt_info->stmt);
1856 4884206 : gimple *use_stmt;
1857 4884206 : use_operand_p use_p;
1858 4884206 : if (dt == vect_internal_def
1859 4449189 : && single_imm_use (op, &use_p, &use_stmt)
1860 2870770 : && is_gimple_assign (def_stmt_info->stmt)
1861 7560460 : && (gimple_assign_rhs_code (def_stmt_info->stmt) == code
1862 2086111 : || (allow_alt_code
1863 57362 : && code == PLUS_EXPR
1864 36310 : && (gimple_assign_rhs_code (def_stmt_info->stmt)
1865 : == MINUS_EXPR))))
1866 : {
1867 590458 : tree_code op_def_code = this_code;
1868 590458 : if (op_def_code == MINUS_EXPR && opnum == 1)
1869 55050 : op_def_code = PLUS_EXPR;
1870 590458 : if (in_code == MINUS_EXPR)
1871 222 : op_def_code = op_def_code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR;
1872 590458 : worklist.safe_push (std::make_pair (op_def_code,
1873 590458 : def_stmt_info->stmt));
1874 : }
1875 : else
1876 : {
1877 4293748 : tree_code op_def_code = this_code;
1878 4293748 : if (op_def_code == MINUS_EXPR && opnum == 1)
1879 308545 : op_def_code = PLUS_EXPR;
1880 4293748 : if (in_code == MINUS_EXPR)
1881 4230 : op_def_code = op_def_code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR;
1882 4293748 : chain.safe_push (chain_op_t (op_def_code, dt, op));
1883 : }
1884 : }
1885 : }
1886 1851645 : }
1887 :
1888 : /* Distance from the node currently being discovered to the closest upthread
1889 : commutative operation whose operand-zero discovery may still be fixed by
1890 : retrying with swapped operands, or -1U if there is none. */
1891 :
1892 : static unsigned least_upthread_swappable_op_distance = -1U;
1893 :
1894 : static slp_tree
1895 : vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node,
1896 : vec<stmt_vec_info> stmts,
1897 : bool *matches, unsigned *limit, unsigned *tree_size,
1898 : scalar_stmts_to_slp_tree_map_t *bst_map);
1899 :
1900 : static slp_tree
1901 6684862 : vect_build_slp_tree (vec_info *vinfo,
1902 : vec<stmt_vec_info> stmts,
1903 : bool *matches, unsigned *limit, unsigned *tree_size,
1904 : scalar_stmts_to_slp_tree_map_t *bst_map)
1905 : {
1906 6684862 : unsigned int group_size = stmts.length ();
1907 6684862 : if (slp_tree *leader = bst_map->get (stmts))
1908 : {
1909 498205 : if (dump_enabled_p ())
1910 17399 : dump_printf_loc (MSG_NOTE, vect_location, "re-using %sSLP tree %p\n",
1911 17399 : !(*leader)->failed ? "" : "failed ",
1912 : (void *) *leader);
1913 498205 : if (!(*leader)->failed)
1914 : {
1915 452230 : SLP_TREE_REF_COUNT (*leader)++;
1916 452230 : stmts.release ();
1917 452230 : return *leader;
1918 : }
1919 45975 : memcpy (matches, (*leader)->failed, sizeof (bool) * group_size);
1920 45975 : return NULL;
1921 : }
1922 :
1923 : /* Single-lane SLP doesn't have the chance of run-away, do not account
1924 : it to the limit. */
1925 6186657 : if (stmts.length () > 1)
1926 : {
1927 3481478 : if (*limit == 0)
1928 : {
1929 1301 : if (dump_enabled_p ())
1930 15 : dump_printf_loc (MSG_NOTE, vect_location,
1931 : "SLP discovery limit exceeded\n");
1932 1301 : memset (matches, 0, sizeof (bool) * group_size);
1933 1301 : return NULL;
1934 : }
1935 3480177 : --*limit;
1936 : }
1937 :
1938 : /* Seed the bst_map with a stub node to be filled by vect_build_slp_tree_2
1939 : so we can pick up backedge destinations during discovery. */
1940 6185356 : slp_tree res = new _slp_tree;
1941 6185356 : SLP_TREE_DEF_TYPE (res) = vect_internal_def;
1942 6185356 : SLP_TREE_SCALAR_STMTS (res) = stmts;
1943 6185356 : bst_map->put (stmts.copy (), res);
1944 :
1945 6185356 : if (dump_enabled_p ())
1946 150679 : dump_printf_loc (MSG_NOTE, vect_location,
1947 : "starting SLP discovery for node %p\n", (void *) res);
1948 :
1949 6185356 : slp_tree res_ = vect_build_slp_tree_2 (vinfo, res, stmts,
1950 : matches, limit, tree_size, bst_map);
1951 6185356 : if (!res_)
1952 : {
1953 2217294 : if (dump_enabled_p ())
1954 8001 : dump_printf_loc (MSG_NOTE, vect_location,
1955 : "SLP discovery for node %p failed\n", (void *) res);
1956 : /* Mark the node invalid so we can detect those when still in use
1957 : as backedge destinations. */
1958 2217294 : SLP_TREE_SCALAR_STMTS (res) = vNULL;
1959 2217294 : SLP_TREE_DEF_TYPE (res) = vect_uninitialized_def;
1960 2217294 : res->failed = XNEWVEC (bool, group_size);
1961 2217294 : if (flag_checking)
1962 : {
1963 : unsigned i;
1964 4017156 : for (i = 0; i < group_size; ++i)
1965 4017156 : if (!matches[i])
1966 : break;
1967 2217294 : gcc_assert (i < group_size);
1968 : }
1969 2217294 : memcpy (res->failed, matches, sizeof (bool) * group_size);
1970 : }
1971 : else
1972 : {
1973 3968062 : if (dump_enabled_p ())
1974 142678 : dump_printf_loc (MSG_NOTE, vect_location,
1975 : "SLP discovery for node %p succeeded\n",
1976 : (void *) res);
1977 3968062 : gcc_assert (res_ == res);
1978 : /* Keep a reference for the bst_map use. */
1979 3968062 : SLP_TREE_REF_COUNT (res)++;
1980 : }
1981 : return res_;
1982 : }
1983 :
1984 : /* Helper for building an associated SLP node chain. */
1985 :
1986 : static void
1987 158 : vect_slp_build_two_operator_nodes (slp_tree perm, tree vectype,
1988 : slp_tree op0, slp_tree op1,
1989 : stmt_vec_info oper1, stmt_vec_info oper2,
1990 : vec<std::pair<unsigned, unsigned> > lperm)
1991 : {
1992 158 : unsigned group_size = SLP_TREE_LANES (op1);
1993 :
1994 158 : slp_tree child1 = new _slp_tree;
1995 158 : SLP_TREE_DEF_TYPE (child1) = vect_internal_def;
1996 158 : SLP_TREE_VECTYPE (child1) = vectype;
1997 158 : SLP_TREE_LANES (child1) = group_size;
1998 158 : SLP_TREE_CHILDREN (child1).create (2);
1999 158 : SLP_TREE_CHILDREN (child1).quick_push (op0);
2000 158 : SLP_TREE_CHILDREN (child1).quick_push (op1);
2001 158 : SLP_TREE_REPRESENTATIVE (child1) = oper1;
2002 :
2003 158 : slp_tree child2 = new _slp_tree;
2004 158 : SLP_TREE_DEF_TYPE (child2) = vect_internal_def;
2005 158 : SLP_TREE_VECTYPE (child2) = vectype;
2006 158 : SLP_TREE_LANES (child2) = group_size;
2007 158 : SLP_TREE_CHILDREN (child2).create (2);
2008 158 : SLP_TREE_CHILDREN (child2).quick_push (op0);
2009 158 : SLP_TREE_REF_COUNT (op0)++;
2010 158 : SLP_TREE_CHILDREN (child2).quick_push (op1);
2011 158 : SLP_TREE_REF_COUNT (op1)++;
2012 158 : SLP_TREE_REPRESENTATIVE (child2) = oper2;
2013 :
2014 158 : SLP_TREE_DEF_TYPE (perm) = vect_internal_def;
2015 158 : SLP_TREE_CODE (perm) = VEC_PERM_EXPR;
2016 158 : SLP_TREE_VECTYPE (perm) = vectype;
2017 158 : SLP_TREE_LANES (perm) = group_size;
2018 158 : SLP_TREE_REPRESENTATIVE (perm) = NULL;
2019 158 : SLP_TREE_LANE_PERMUTATION (perm) = lperm;
2020 158 : SLP_TREE_CHILDREN (perm).quick_push (child1);
2021 158 : SLP_TREE_CHILDREN (perm).quick_push (child2);
2022 158 : }
2023 :
2024 : /* Recursively build an SLP tree starting from NODE.
2025 : Fail (and return a value not equal to zero) if def-stmts are not
2026 : isomorphic, require data permutation or are of unsupported types of
2027 : operation. Otherwise, return 0.
2028 : The value returned is the depth in the SLP tree where a mismatch
2029 : was found. */
2030 :
2031 : static slp_tree
2032 6185356 : vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node,
2033 : vec<stmt_vec_info> stmts,
2034 : bool *matches, unsigned *limit, unsigned *tree_size,
2035 : scalar_stmts_to_slp_tree_map_t *bst_map)
2036 : {
2037 6185356 : unsigned int group_size = stmts.length ();
2038 6185356 : unsigned nops, i, this_tree_size = 0;
2039 :
2040 6185356 : matches[0] = false;
2041 :
2042 6185356 : stmt_vec_info stmt_info = stmts[0];
2043 6185356 : if (!is_a<gcall *> (stmt_info->stmt)
2044 : && !is_a<gassign *> (stmt_info->stmt)
2045 : && !is_a<gphi *> (stmt_info->stmt))
2046 : return NULL;
2047 :
2048 6185258 : nops = gimple_num_args (stmt_info->stmt);
2049 6185258 : if (const int *map = vect_get_operand_map (stmt_info))
2050 37099 : nops = map[0];
2051 :
2052 : /* If the SLP node is a PHI (induction or reduction), terminate
2053 : the recursion. */
2054 6185258 : bool *skip_args = XALLOCAVEC (bool, nops);
2055 6185258 : memset (skip_args, 0, sizeof (bool) * nops);
2056 6185258 : if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
2057 2903600 : if (gphi *stmt = dyn_cast <gphi *> (stmt_info->stmt))
2058 : {
2059 316925 : tree scalar_type = TREE_TYPE (PHI_RESULT (stmt));
2060 316925 : tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
2061 : group_size);
2062 316925 : if (!vect_record_vectype (vinfo, stmt_info, group_size, vectype))
2063 : return NULL;
2064 :
2065 312684 : vect_def_type def_type = STMT_VINFO_DEF_TYPE (stmt_info);
2066 312684 : if (def_type == vect_induction_def)
2067 : {
2068 : /* Induction PHIs are not cycles but walk the initial
2069 : value. Only for inner loops through, for outer loops
2070 : we need to pick up the value from the actual PHIs
2071 : to more easily support peeling and epilogue vectorization. */
2072 204288 : class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2073 204288 : if (!nested_in_vect_loop_p (loop, stmt_info))
2074 203432 : skip_args[loop_preheader_edge (loop)->dest_idx] = true;
2075 : else
2076 : loop = loop->inner;
2077 204288 : skip_args[loop_latch_edge (loop)->dest_idx] = true;
2078 : }
2079 108396 : else if (def_type == vect_reduction_def
2080 : || def_type == vect_double_reduction_def
2081 : || def_type == vect_nested_cycle
2082 108396 : || def_type == vect_first_order_recurrence)
2083 : {
2084 : /* Else def types have to match. */
2085 : stmt_vec_info other_info;
2086 : bool all_same = true;
2087 245015 : FOR_EACH_VEC_ELT (stmts, i, other_info)
2088 : {
2089 137942 : if (STMT_VINFO_DEF_TYPE (other_info) != def_type)
2090 6185356 : return NULL;
2091 137936 : if (other_info != stmt_info)
2092 26235 : all_same = false;
2093 : }
2094 107073 : class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2095 : /* Reduction initial values are not explicitly represented. */
2096 107073 : if (def_type != vect_first_order_recurrence
2097 107073 : && gimple_bb (stmt_info->stmt) == loop->header)
2098 103826 : skip_args[loop_preheader_edge (loop)->dest_idx] = true;
2099 : /* Reduction chain backedge defs are filled manually.
2100 : ??? Need a better way to identify a SLP reduction chain PHI.
2101 : Or a better overall way to SLP match those. */
2102 107073 : if (stmts.length () > 1
2103 107073 : && all_same && def_type == vect_reduction_def)
2104 2370 : skip_args[loop_latch_edge (loop)->dest_idx] = true;
2105 : }
2106 1317 : else if (def_type != vect_internal_def)
2107 : return NULL;
2108 : }
2109 :
2110 :
2111 6181011 : bool two_operators = false;
2112 6181011 : unsigned char *swap = XALLOCAVEC (unsigned char, group_size);
2113 6181011 : tree vectype = NULL_TREE;
2114 6181011 : if (!vect_build_slp_tree_1 (vinfo, swap, stmts, matches, &two_operators,
2115 : &vectype))
2116 : return NULL;
2117 :
2118 : /* If the SLP node is a load, terminate the recursion unless masked. */
2119 4462643 : if (STMT_VINFO_DATA_REF (stmt_info)
2120 2108299 : && DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)))
2121 : {
2122 949036 : if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
2123 : gcc_assert (DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)));
2124 : else
2125 : {
2126 929438 : (*tree_size)++;
2127 929438 : node = vect_create_new_slp_node (node, stmts, 0);
2128 929438 : SLP_TREE_VECTYPE (node) = vectype;
2129 : /* And compute the load permutation. Whether it is actually
2130 : a permutation depends on the unrolling factor which is
2131 : decided later. */
2132 929438 : vec<unsigned> load_permutation;
2133 929438 : int j;
2134 929438 : stmt_vec_info load_info;
2135 929438 : load_permutation.create (group_size);
2136 929438 : stmt_vec_info first_stmt_info
2137 929438 : = STMT_VINFO_GROUPED_ACCESS (stmt_info)
2138 929438 : ? DR_GROUP_FIRST_ELEMENT (stmt_info) : stmt_info;
2139 929438 : bool any_permute = false;
2140 2247363 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), j, load_info)
2141 : {
2142 1317925 : int load_place;
2143 1317925 : if (! load_info)
2144 : {
2145 40759 : if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
2146 : load_place = j;
2147 : else
2148 : load_place = 0;
2149 : }
2150 1277166 : else if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
2151 746670 : load_place = vect_get_place_in_interleaving_chain
2152 746670 : (load_info, first_stmt_info);
2153 : else
2154 : /* Recognize the splat case as { 0, 0, ... } but make
2155 : sure to use the appropriate refs for collections
2156 : of invariant refs. */
2157 530496 : load_place = (load_info == stmt_info) ? 0 : j;
2158 787670 : gcc_assert (load_place != -1);
2159 1317925 : any_permute |= load_place != j;
2160 1317925 : load_permutation.quick_push (load_place);
2161 : }
2162 :
2163 929438 : if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
2164 : {
2165 3500 : gcc_assert (gimple_call_internal_p (stmt, IFN_MASK_LOAD));
2166 3500 : bool has_gaps = false;
2167 3500 : if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
2168 189 : for (stmt_vec_info si = DR_GROUP_NEXT_ELEMENT (first_stmt_info);
2169 846 : si; si = DR_GROUP_NEXT_ELEMENT (si))
2170 657 : if (DR_GROUP_GAP (si) != 1)
2171 80 : has_gaps = true;
2172 : /* We cannot handle permuted masked loads directly, see
2173 : PR114375. We cannot handle strided masked loads or masked
2174 : loads with gaps unless the mask is uniform. */
2175 3500 : if ((STMT_VINFO_GROUPED_ACCESS (stmt_info)
2176 189 : && (DR_GROUP_GAP (first_stmt_info) != 0
2177 129 : || (has_gaps
2178 35 : && STMT_VINFO_SLP_VECT_ONLY (first_stmt_info))))
2179 6920 : || STMT_VINFO_STRIDED_P (stmt_info))
2180 : {
2181 93 : load_permutation.release ();
2182 93 : matches[0] = false;
2183 926070 : return NULL;
2184 : }
2185 :
2186 : /* For permuted masked loads do an unpermuted masked load of
2187 : the whole group followed by a SLP permute node. */
2188 3407 : if (any_permute
2189 3407 : || (STMT_VINFO_GROUPED_ACCESS (stmt_info)
2190 83 : && DR_GROUP_SIZE (first_stmt_info) != group_size))
2191 : {
2192 : /* Discover the whole unpermuted load. */
2193 39 : vec<stmt_vec_info> stmts2;
2194 39 : unsigned dr_group_size = STMT_VINFO_GROUPED_ACCESS (stmt_info)
2195 68 : ? DR_GROUP_SIZE (first_stmt_info) : 1;
2196 39 : stmts2.create (dr_group_size);
2197 39 : stmts2.quick_grow_cleared (dr_group_size);
2198 39 : unsigned i = 0;
2199 39 : for (stmt_vec_info si = first_stmt_info;
2200 464 : si; si = DR_GROUP_NEXT_ELEMENT (si))
2201 : {
2202 425 : if (si != first_stmt_info)
2203 1586 : for (unsigned k = 1; k < DR_GROUP_GAP (si); ++k)
2204 1200 : stmts2[i++] = NULL;
2205 425 : stmts2[i++] = si;
2206 : }
2207 39 : bool *matches2 = XALLOCAVEC (bool, dr_group_size);
2208 39 : slp_tree unperm_load
2209 39 : = vect_build_slp_tree (vinfo, stmts2, matches2, limit,
2210 39 : &this_tree_size, bst_map);
2211 : /* When we are able to do the full masked load emit that
2212 : followed by 'node' being the desired final permutation. */
2213 39 : if (unperm_load)
2214 : {
2215 16 : gcc_assert
2216 : (!SLP_TREE_LOAD_PERMUTATION (unperm_load).exists ());
2217 16 : lane_permutation_t lperm;
2218 16 : lperm.create (group_size);
2219 72 : for (unsigned j = 0; j < load_permutation.length (); ++j)
2220 40 : lperm.quick_push
2221 40 : (std::make_pair (0, load_permutation[j]));
2222 16 : SLP_TREE_CODE (node) = VEC_PERM_EXPR;
2223 16 : SLP_TREE_CHILDREN (node).safe_push (unperm_load);
2224 16 : SLP_TREE_LANE_PERMUTATION (node) = lperm;
2225 16 : SLP_TREE_REPRESENTATIVE (node) = NULL;
2226 16 : load_permutation.release ();
2227 16 : return node;
2228 : }
2229 23 : stmts2.release ();
2230 23 : load_permutation.release ();
2231 23 : matches[0] = false;
2232 23 : return NULL;
2233 : }
2234 3368 : load_permutation.release ();
2235 : }
2236 : else
2237 : {
2238 925938 : if (!any_permute
2239 797098 : && STMT_VINFO_GROUPED_ACCESS (stmt_info)
2240 1218872 : && group_size == DR_GROUP_SIZE (first_stmt_info))
2241 128934 : load_permutation.release ();
2242 925938 : SLP_TREE_LOAD_PERMUTATION (node) = load_permutation;
2243 925938 : return node;
2244 : }
2245 : }
2246 : }
2247 3513607 : else if (gimple_assign_single_p (stmt_info->stmt)
2248 2325462 : && !gimple_vuse (stmt_info->stmt)
2249 3522519 : && gimple_assign_rhs_code (stmt_info->stmt) == BIT_FIELD_REF)
2250 : {
2251 : /* vect_build_slp_tree_2 determined all BIT_FIELD_REFs reference
2252 : the same SSA name vector of a compatible type to vectype. */
2253 3397 : vec<std::pair<unsigned, unsigned> > lperm = vNULL;
2254 3397 : tree vec = TREE_OPERAND (gimple_assign_rhs1 (stmt_info->stmt), 0);
2255 3397 : stmt_vec_info estmt_info;
2256 12015 : FOR_EACH_VEC_ELT (stmts, i, estmt_info)
2257 : {
2258 8765 : gassign *estmt = as_a <gassign *> (estmt_info->stmt);
2259 8765 : tree bfref = gimple_assign_rhs1 (estmt);
2260 8765 : HOST_WIDE_INT lane;
2261 8765 : if (!known_eq (bit_field_size (bfref),
2262 : tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (vectype))))
2263 17383 : || !constant_multiple_p (bit_field_offset (bfref),
2264 8765 : bit_field_size (bfref), &lane))
2265 : {
2266 147 : lperm.release ();
2267 147 : matches[0] = false;
2268 147 : return NULL;
2269 : }
2270 8618 : lperm.safe_push (std::make_pair (0, (unsigned)lane));
2271 : }
2272 3250 : slp_tree vnode = vect_create_new_slp_node (vNULL);
2273 3250 : if (operand_equal_p (TYPE_SIZE (vectype), TYPE_SIZE (TREE_TYPE (vec))))
2274 : /* ??? We record vectype here but we hide eventually necessary
2275 : punning and instead rely on code generation to materialize
2276 : VIEW_CONVERT_EXPRs as necessary. We instead should make
2277 : this explicit somehow. */
2278 1456 : SLP_TREE_VECTYPE (vnode) = vectype;
2279 : else
2280 : {
2281 : /* For different size but compatible elements we can still
2282 : use VEC_PERM_EXPR without punning. */
2283 1794 : gcc_assert (VECTOR_TYPE_P (TREE_TYPE (vec))
2284 : && types_compatible_p (TREE_TYPE (vectype),
2285 : TREE_TYPE (TREE_TYPE (vec))));
2286 1794 : SLP_TREE_VECTYPE (vnode) = TREE_TYPE (vec);
2287 : }
2288 3250 : auto nunits = TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (vnode));
2289 3250 : unsigned HOST_WIDE_INT const_nunits;
2290 3250 : if (nunits.is_constant (&const_nunits))
2291 3250 : SLP_TREE_LANES (vnode) = const_nunits;
2292 3250 : SLP_TREE_VEC_DEFS (vnode).safe_push (vec);
2293 : /* We are always building a permutation node even if it is an identity
2294 : permute to shield the rest of the vectorizer from the odd node
2295 : representing an actual vector without any scalar ops.
2296 : ??? We could hide it completely with making the permute node
2297 : external? */
2298 3250 : node = vect_create_new_slp_node (node, stmts, 1);
2299 3250 : SLP_TREE_CODE (node) = VEC_PERM_EXPR;
2300 3250 : SLP_TREE_LANE_PERMUTATION (node) = lperm;
2301 3250 : SLP_TREE_VECTYPE (node) = vectype;
2302 3250 : SLP_TREE_CHILDREN (node).quick_push (vnode);
2303 3250 : SLP_TREE_REPRESENTATIVE (node) = NULL;
2304 3250 : return node;
2305 : }
2306 : /* When discovery reaches an associatable operation see whether we can
2307 : improve that to match up lanes in a way superior to the operand
2308 : swapping code which at most looks at two defs.
2309 : ??? For BB vectorization we cannot do the brute-force search
2310 : for matching as we can succeed by means of builds from scalars
2311 : and have no good way to "cost" one build against another. */
2312 3510210 : else if (is_a <loop_vec_info> (vinfo)
2313 : /* Do not bother for single-lane SLP. */
2314 2063047 : && group_size > 1
2315 : /* ??? We don't handle !vect_internal_def defs below. */
2316 113692 : && STMT_VINFO_DEF_TYPE (stmt_info) == vect_internal_def
2317 : /* ??? Do not associate a reduction, this will wreck REDUC_IDX
2318 : mapping as long as that exists on the stmt_info level. */
2319 88114 : && STMT_VINFO_REDUC_IDX (stmt_info) == -1
2320 79559 : && is_gimple_assign (stmt_info->stmt)
2321 79240 : && (associative_tree_code (gimple_assign_rhs_code (stmt_info->stmt))
2322 52360 : || gimple_assign_rhs_code (stmt_info->stmt) == MINUS_EXPR)
2323 3539042 : && ((FLOAT_TYPE_P (vectype) && flag_associative_math)
2324 16577 : || (INTEGRAL_TYPE_P (TREE_TYPE (vectype))
2325 14039 : && TYPE_OVERFLOW_WRAPS (TREE_TYPE (vectype)))))
2326 : {
2327 : /* See if we have a chain of (mixed) adds or subtracts or other
2328 : associatable ops. */
2329 21770 : enum tree_code code = gimple_assign_rhs_code (stmt_info->stmt);
2330 21770 : if (code == MINUS_EXPR)
2331 848 : code = PLUS_EXPR;
2332 21770 : stmt_vec_info other_op_stmt_info = NULL;
2333 21770 : stmt_vec_info op_stmt_info = NULL;
2334 21770 : unsigned chain_len = 0;
2335 21770 : auto_vec<chain_op_t> chain;
2336 21770 : auto_vec<std::pair<tree_code, gimple *> > worklist;
2337 21770 : auto_vec<vec<chain_op_t> > chains (group_size);
2338 21770 : auto_vec<slp_tree, 4> children;
2339 21770 : bool hard_fail = true;
2340 22797 : for (unsigned lane = 0; lane < group_size; ++lane)
2341 : {
2342 22461 : if (!stmts[lane])
2343 : {
2344 : /* ??? Below we require lane zero is present. */
2345 0 : if (lane == 0)
2346 : {
2347 : hard_fail = false;
2348 21434 : break;
2349 : }
2350 0 : chains.quick_push (vNULL);
2351 0 : continue;
2352 : }
2353 : /* For each lane linearize the addition/subtraction (or other
2354 : uniform associatable operation) expression tree. */
2355 22461 : gimple *op_stmt = NULL, *other_op_stmt = NULL;
2356 22461 : vect_slp_linearize_chain (vinfo, worklist, chain, code,
2357 22461 : stmts[lane]->stmt, op_stmt, other_op_stmt,
2358 : NULL);
2359 22461 : if (!op_stmt_info && op_stmt)
2360 21119 : op_stmt_info = vinfo->lookup_stmt (op_stmt);
2361 22461 : if (!other_op_stmt_info && other_op_stmt)
2362 884 : other_op_stmt_info = vinfo->lookup_stmt (other_op_stmt);
2363 22461 : if (chain.length () == 2)
2364 : {
2365 : /* In a chain of just two elements resort to the regular
2366 : operand swapping scheme. Likewise if we run into a
2367 : length mismatch process regularly as well as we did not
2368 : process the other lanes we cannot report a good hint what
2369 : lanes to try swapping in the parent. */
2370 : hard_fail = false;
2371 : break;
2372 : }
2373 1030 : else if (chain_len == 0)
2374 376 : chain_len = chain.length ();
2375 1308 : else if (chain.length () != chain_len)
2376 : {
2377 : /* ??? Here we could slip in magic to compensate with
2378 : neutral operands. */
2379 3 : matches[lane] = false;
2380 3 : if (lane != group_size - 1)
2381 3 : matches[0] = false;
2382 : break;
2383 : }
2384 1027 : chains.quick_push (chain.copy ());
2385 1027 : chain.truncate (0);
2386 : }
2387 43540 : if (chains.length () == group_size)
2388 : {
2389 : /* We cannot yet use SLP_TREE_CODE to communicate the operation. */
2390 336 : if (!op_stmt_info)
2391 : {
2392 3 : hard_fail = false;
2393 3 : goto out;
2394 : }
2395 : /* Now we have a set of chains with the same length. */
2396 : /* 1. pre-sort according to def_type and operation. */
2397 1248 : for (unsigned lane = 0; lane < group_size; ++lane)
2398 1830 : chains[lane].stablesort (dt_sort_cmp, vinfo);
2399 333 : if (dump_enabled_p ())
2400 : {
2401 157 : dump_printf_loc (MSG_NOTE, vect_location,
2402 : "pre-sorted chains of %s\n",
2403 : get_tree_code_name (code));
2404 685 : for (unsigned lane = 0; lane < group_size; ++lane)
2405 : {
2406 528 : if (!stmts[lane])
2407 0 : dump_printf (MSG_NOTE, "--");
2408 : else
2409 2422 : for (unsigned opnum = 0; opnum < chain_len; ++opnum)
2410 3788 : dump_printf (MSG_NOTE, "%s %T ",
2411 1894 : get_tree_code_name (chains[lane][opnum].code),
2412 1894 : chains[lane][opnum].op);
2413 528 : dump_printf (MSG_NOTE, "\n");
2414 : }
2415 : }
2416 : /* 2. try to build children nodes, associating as necessary. */
2417 : /* 2a. prepare and perform early checks to avoid eating into
2418 : discovery limit unnecessarily. */
2419 333 : vect_def_type *dts = XALLOCAVEC (vect_def_type, chain_len);
2420 1407 : for (unsigned n = 0; n < chain_len; ++n)
2421 : {
2422 1074 : vect_def_type dt = chains[0][n].dt;
2423 1074 : unsigned lane;
2424 4177 : for (lane = 0; lane < group_size; ++lane)
2425 6206 : if (stmts[lane] && chains[lane][n].dt != dt)
2426 : {
2427 0 : if (dt == vect_constant_def
2428 0 : && chains[lane][n].dt == vect_external_def)
2429 : dt = vect_external_def;
2430 0 : else if (dt == vect_external_def
2431 0 : && chains[lane][n].dt == vect_constant_def)
2432 : ;
2433 : else
2434 : break;
2435 : }
2436 1074 : if (lane != group_size)
2437 : {
2438 0 : if (dump_enabled_p ())
2439 0 : dump_printf_loc (MSG_NOTE, vect_location,
2440 : "giving up on chain due to mismatched "
2441 : "def types\n");
2442 0 : matches[lane] = false;
2443 0 : if (lane != group_size - 1)
2444 0 : matches[0] = false;
2445 0 : goto out;
2446 : }
2447 1074 : dts[n] = dt;
2448 1074 : if (dt == vect_constant_def
2449 1074 : || dt == vect_external_def)
2450 : {
2451 : /* Check whether we can build the invariant. If we can't
2452 : we never will be able to. */
2453 93 : tree type = TREE_TYPE (chains[0][n].op);
2454 1074 : if (!GET_MODE_SIZE (vinfo->vector_mode).is_constant ()
2455 : && (TREE_CODE (type) == BOOLEAN_TYPE
2456 : || !can_duplicate_and_interleave_p (vinfo, group_size,
2457 : type)))
2458 : {
2459 : matches[0] = false;
2460 : goto out;
2461 : }
2462 : }
2463 981 : else if (dt != vect_internal_def)
2464 : {
2465 : /* Not sure, we might need sth special.
2466 : gcc.dg/vect/pr96854.c,
2467 : gfortran.dg/vect/fast-math-pr37021.f90
2468 : and gfortran.dg/vect/pr61171.f trigger. */
2469 : /* Soft-fail for now. */
2470 0 : hard_fail = false;
2471 0 : goto out;
2472 : }
2473 : }
2474 : /* 2b. do the actual build. */
2475 1353 : for (unsigned n = 0; n < chain_len; ++n)
2476 : {
2477 1039 : vect_def_type dt = dts[n];
2478 1039 : unsigned lane;
2479 1039 : if (dt == vect_constant_def
2480 1039 : || dt == vect_external_def)
2481 : {
2482 93 : vec<tree> ops;
2483 93 : ops.create (group_size);
2484 461 : for (lane = 0; lane < group_size; ++lane)
2485 275 : if (stmts[lane])
2486 275 : ops.quick_push (chains[lane][n].op);
2487 : else
2488 0 : ops.quick_push (NULL_TREE);
2489 93 : slp_tree child = vect_create_new_slp_node (ops);
2490 93 : SLP_TREE_DEF_TYPE (child) = dt;
2491 93 : children.safe_push (child);
2492 : }
2493 : else
2494 : {
2495 946 : vec<stmt_vec_info> op_stmts;
2496 946 : op_stmts.create (group_size);
2497 946 : slp_tree child = NULL;
2498 : /* Brute-force our way. We have to consider a lane
2499 : failing after fixing an earlier fail up in the
2500 : SLP discovery recursion. So track the current
2501 : permute per lane. */
2502 946 : unsigned *perms = XALLOCAVEC (unsigned, group_size);
2503 946 : memset (perms, 0, sizeof (unsigned) * group_size);
2504 1040 : do
2505 : {
2506 1040 : op_stmts.truncate (0);
2507 5092 : for (lane = 0; lane < group_size; ++lane)
2508 3012 : if (stmts[lane])
2509 3012 : op_stmts.quick_push
2510 3012 : (vinfo->lookup_def (chains[lane][n].op));
2511 : else
2512 0 : op_stmts.quick_push (NULL);
2513 1040 : child = vect_build_slp_tree (vinfo, op_stmts,
2514 : matches, limit,
2515 : &this_tree_size, bst_map);
2516 : /* ??? We're likely getting too many fatal mismatches
2517 : here so maybe we want to ignore them (but then we
2518 : have no idea which lanes fatally mismatched). */
2519 1040 : if (child || !matches[0])
2520 : break;
2521 : /* Swap another lane we have not yet matched up into
2522 : lanes that did not match. If we run out of
2523 : permute possibilities for a lane terminate the
2524 : search. */
2525 287 : bool term = false;
2526 287 : for (lane = 1; lane < group_size; ++lane)
2527 193 : if (!matches[lane])
2528 : {
2529 165 : if (n + perms[lane] + 1 == chain_len)
2530 : {
2531 : term = true;
2532 : break;
2533 : }
2534 146 : if (dump_enabled_p ())
2535 113 : dump_printf_loc (MSG_NOTE, vect_location,
2536 : "swapping operand %d and %d "
2537 : "of lane %d\n",
2538 : n, n + perms[lane] + 1, lane);
2539 292 : std::swap (chains[lane][n],
2540 146 : chains[lane][n + perms[lane] + 1]);
2541 146 : perms[lane]++;
2542 : }
2543 113 : if (term)
2544 : break;
2545 : }
2546 : while (1);
2547 946 : if (!child)
2548 : {
2549 19 : if (dump_enabled_p ())
2550 18 : dump_printf_loc (MSG_NOTE, vect_location,
2551 : "failed to match up op %d\n", n);
2552 19 : op_stmts.release ();
2553 19 : if (lane != group_size - 1)
2554 9 : matches[0] = false;
2555 : else
2556 10 : matches[lane] = false;
2557 19 : goto out;
2558 : }
2559 927 : if (dump_enabled_p ())
2560 : {
2561 421 : dump_printf_loc (MSG_NOTE, vect_location,
2562 : "matched up op %d to\n", n);
2563 421 : vect_print_slp_tree (MSG_NOTE, vect_location, child);
2564 : }
2565 927 : children.safe_push (child);
2566 : }
2567 : }
2568 : /* 3. build SLP nodes to combine the chain. */
2569 1156 : for (unsigned lane = 0; lane < group_size; ++lane)
2570 1696 : if (stmts[lane] && chains[lane][0].code != code)
2571 : {
2572 : /* See if there's any alternate all-PLUS entry. */
2573 : unsigned n;
2574 6 : for (n = 1; n < chain_len; ++n)
2575 : {
2576 30 : for (lane = 0; lane < group_size; ++lane)
2577 48 : if (stmts[lane] && chains[lane][n].code != code)
2578 : break;
2579 6 : if (lane == group_size)
2580 : break;
2581 : }
2582 6 : if (n != chain_len)
2583 : {
2584 : /* Swap that in at first position. */
2585 6 : std::swap (children[0], children[n]);
2586 30 : for (lane = 0; lane < group_size; ++lane)
2587 24 : if (stmts[lane])
2588 24 : std::swap (chains[lane][0], chains[lane][n]);
2589 : }
2590 : else
2591 : {
2592 : /* ??? When this triggers and we end up with two
2593 : vect_constant/external_def up-front things break (ICE)
2594 : spectacularly finding an insertion place for the
2595 : all-constant op. We should have a fully
2596 : vect_internal_def operand though(?) so we can swap
2597 : that into first place and then prepend the all-zero
2598 : constant. */
2599 0 : if (dump_enabled_p ())
2600 0 : dump_printf_loc (MSG_NOTE, vect_location,
2601 : "inserting constant zero to compensate "
2602 : "for (partially) negated first "
2603 : "operand\n");
2604 0 : chain_len++;
2605 0 : for (lane = 0; lane < group_size; ++lane)
2606 0 : if (stmts[lane])
2607 0 : chains[lane].safe_insert
2608 0 : (0, chain_op_t (code, vect_constant_def, NULL_TREE));
2609 0 : vec<tree> zero_ops;
2610 0 : zero_ops.create (group_size);
2611 0 : zero_ops.quick_push (build_zero_cst (TREE_TYPE (vectype)));
2612 0 : for (lane = 1; lane < group_size; ++lane)
2613 0 : if (stmts[lane])
2614 0 : zero_ops.quick_push (zero_ops[0]);
2615 : else
2616 0 : zero_ops.quick_push (NULL_TREE);
2617 0 : slp_tree zero = vect_create_new_slp_node (zero_ops);
2618 0 : SLP_TREE_DEF_TYPE (zero) = vect_constant_def;
2619 0 : children.safe_insert (0, zero);
2620 : }
2621 : break;
2622 : }
2623 1015 : for (unsigned i = 1; i < children.length (); ++i)
2624 : {
2625 701 : slp_tree op0 = children[i - 1];
2626 701 : slp_tree op1 = children[i];
2627 701 : bool this_two_op = false;
2628 2569 : for (unsigned lane = 0; lane < group_size; ++lane)
2629 4052 : if (stmts[lane] && chains[lane][i].code != chains[0][i].code)
2630 : {
2631 : this_two_op = true;
2632 : break;
2633 : }
2634 701 : slp_tree child;
2635 701 : if (i == children.length () - 1)
2636 314 : child = vect_create_new_slp_node (node, stmts, 2);
2637 : else
2638 387 : child = vect_create_new_slp_node (2, ERROR_MARK);
2639 701 : if (this_two_op)
2640 : {
2641 158 : vec<std::pair<unsigned, unsigned> > lperm;
2642 158 : lperm.create (group_size);
2643 728 : for (unsigned lane = 0; lane < group_size; ++lane)
2644 824 : lperm.quick_push (std::make_pair
2645 412 : (chains[lane][i].code != chains[0][i].code, lane));
2646 316 : vect_slp_build_two_operator_nodes (child, vectype, op0, op1,
2647 158 : (chains[0][i].code == code
2648 : ? op_stmt_info
2649 : : other_op_stmt_info),
2650 158 : (chains[0][i].code == code
2651 : ? other_op_stmt_info
2652 : : op_stmt_info),
2653 : lperm);
2654 : }
2655 : else
2656 : {
2657 543 : SLP_TREE_DEF_TYPE (child) = vect_internal_def;
2658 543 : SLP_TREE_VECTYPE (child) = vectype;
2659 543 : SLP_TREE_LANES (child) = group_size;
2660 543 : SLP_TREE_CHILDREN (child).quick_push (op0);
2661 543 : SLP_TREE_CHILDREN (child).quick_push (op1);
2662 543 : SLP_TREE_REPRESENTATIVE (child)
2663 1086 : = (chains[0][i].code == code
2664 543 : ? op_stmt_info : other_op_stmt_info);
2665 : }
2666 701 : children[i] = child;
2667 : }
2668 314 : *tree_size += this_tree_size + 1;
2669 1516 : while (!chains.is_empty ())
2670 866 : chains.pop ().release ();
2671 : return node;
2672 : }
2673 21434 : out:
2674 21456 : if (dump_enabled_p ())
2675 2817 : dump_printf_loc (MSG_NOTE, vect_location,
2676 : "failed to line up SLP graph by re-associating "
2677 : "operations in lanes%s\n",
2678 : !hard_fail ? " trying regular discovery" : "");
2679 21461 : while (!children.is_empty ())
2680 5 : vect_free_slp_tree (children.pop ());
2681 21617 : while (!chains.is_empty ())
2682 161 : chains.pop ().release ();
2683 : /* Hard-fail, otherwise we might run into quadratic processing of the
2684 : chains starting one stmt into the chain again. */
2685 21456 : if (hard_fail)
2686 : return NULL;
2687 : /* Fall thru to normal processing. */
2688 21770 : }
2689 :
2690 : /* Get at the operands, verifying they are compatible. */
2691 3532840 : vec<slp_oprnd_info> oprnds_info = vect_create_oprnd_info (nops, group_size);
2692 3532840 : slp_oprnd_info oprnd_info;
2693 20117872 : FOR_EACH_VEC_ELT (stmts, i, stmt_info)
2694 : {
2695 26106994 : int res = vect_get_and_check_slp_defs (vinfo, vectype,
2696 13053497 : swap[i], skip_args,
2697 : stmts, i, &oprnds_info);
2698 13053497 : if (res != 0)
2699 608015 : matches[(res == -1) ? 0 : i] = false;
2700 13053497 : if (!matches[0])
2701 : break;
2702 : }
2703 16239251 : for (i = 0; i < group_size; ++i)
2704 12947677 : if (!matches[i])
2705 : {
2706 241266 : vect_free_oprnd_info (oprnds_info);
2707 241266 : return NULL;
2708 : }
2709 3291574 : swap = NULL;
2710 :
2711 3291574 : bool has_two_operators_perm = false;
2712 16457870 : auto_vec<unsigned> two_op_perm_indices[2];
2713 3291574 : vec<stmt_vec_info> two_op_scalar_stmts[2] = {vNULL, vNULL};
2714 :
2715 3307761 : if (two_operators && oprnds_info.length () == 2 && group_size > 2)
2716 : {
2717 4009 : unsigned idx = 0;
2718 4009 : hash_map<gimple *, unsigned> seen;
2719 4009 : vec<slp_oprnd_info> new_oprnds_info
2720 4009 : = vect_create_oprnd_info (1, group_size);
2721 4009 : bool success = true;
2722 :
2723 4009 : enum tree_code code = ERROR_MARK;
2724 4009 : if (oprnds_info[0]->def_stmts[0]
2725 4009 : && is_a<gassign *> (oprnds_info[0]->def_stmts[0]->stmt))
2726 3948 : code = gimple_assign_rhs_code (oprnds_info[0]->def_stmts[0]->stmt);
2727 4009 : basic_block bb = nullptr;
2728 :
2729 7707 : for (unsigned j = 0; j < group_size; ++j)
2730 : {
2731 17989 : FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
2732 : {
2733 14291 : stmt_vec_info stmt_info = oprnd_info->def_stmts[j];
2734 14291 : if (!stmt_info
2735 14125 : || !is_a<gassign *> (stmt_info->stmt)
2736 14122 : || gimple_assign_rhs_code (stmt_info->stmt) != code
2737 25055 : || skip_args[i])
2738 : {
2739 : success = false;
2740 3531 : break;
2741 : }
2742 : /* Avoid mixing lanes with defs in different basic-blocks. */
2743 10764 : if (!bb)
2744 4144 : bb = gimple_bb (vect_orig_stmt (stmt_info)->stmt);
2745 8554 : else if (gimple_bb (vect_orig_stmt (stmt_info)->stmt) != bb)
2746 : {
2747 : success = false;
2748 : break;
2749 : }
2750 :
2751 10760 : bool exists;
2752 10760 : unsigned &stmt_idx
2753 10760 : = seen.get_or_insert (stmt_info->stmt, &exists);
2754 :
2755 10760 : if (!exists)
2756 : {
2757 9383 : new_oprnds_info[0]->def_stmts.safe_push (stmt_info);
2758 9383 : new_oprnds_info[0]->ops.safe_push (oprnd_info->ops[j]);
2759 9383 : stmt_idx = idx;
2760 9383 : idx++;
2761 : }
2762 :
2763 10760 : two_op_perm_indices[i].safe_push (stmt_idx);
2764 : }
2765 :
2766 7229 : if (!success)
2767 : break;
2768 : }
2769 :
2770 4009 : if (success && idx == group_size)
2771 : {
2772 97 : if (dump_enabled_p ())
2773 : {
2774 0 : dump_printf_loc (MSG_NOTE, vect_location,
2775 : "Replace two_operators operands:\n");
2776 :
2777 0 : FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
2778 : {
2779 0 : dump_printf_loc (MSG_NOTE, vect_location,
2780 : "Operand %u:\n", i);
2781 0 : for (unsigned j = 0; j < group_size; j++)
2782 0 : dump_printf_loc (MSG_NOTE, vect_location, "\tstmt %u %G",
2783 0 : j, oprnd_info->def_stmts[j]->stmt);
2784 : }
2785 :
2786 0 : dump_printf_loc (MSG_NOTE, vect_location,
2787 : "With a single operand:\n");
2788 0 : for (unsigned j = 0; j < group_size; j++)
2789 0 : dump_printf_loc (MSG_NOTE, vect_location, "\tstmt %u %G",
2790 0 : j, new_oprnds_info[0]->def_stmts[j]->stmt);
2791 : }
2792 :
2793 97 : two_op_scalar_stmts[0].safe_splice (oprnds_info[0]->def_stmts);
2794 97 : two_op_scalar_stmts[1].safe_splice (oprnds_info[1]->def_stmts);
2795 :
2796 97 : new_oprnds_info[0]->first_op_type = oprnds_info[0]->first_op_type;
2797 97 : new_oprnds_info[0]->first_dt = oprnds_info[0]->first_dt;
2798 97 : new_oprnds_info[0]->any_pattern = oprnds_info[0]->any_pattern;
2799 97 : new_oprnds_info[0]->first_gs_p = oprnds_info[0]->first_gs_p;
2800 97 : new_oprnds_info[0]->first_gs_info = oprnds_info[0]->first_gs_info;
2801 :
2802 97 : vect_free_oprnd_info (oprnds_info);
2803 97 : oprnds_info = new_oprnds_info;
2804 97 : nops = 1;
2805 97 : has_two_operators_perm = true;
2806 : }
2807 : else
2808 3912 : vect_free_oprnd_info (new_oprnds_info);
2809 4009 : }
2810 :
2811 6583148 : auto_vec<slp_tree, 4> children;
2812 :
2813 3291574 : stmt_info = stmts[0];
2814 :
2815 3291574 : int reduc_idx = -1;
2816 3291574 : int gs_scale = 0;
2817 3291574 : tree gs_base = NULL_TREE;
2818 :
2819 : /* Create SLP_TREE nodes for the definition node/s. */
2820 8464707 : FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
2821 : {
2822 5286533 : slp_tree child = nullptr;
2823 5286533 : unsigned int j;
2824 5286533 : unsigned old_swap_distance;
2825 5286533 : bool can_swap;
2826 5286533 : bool can_swap_nonmatching;
2827 5286533 : bool *stmt_can_swap;
2828 :
2829 : /* We're skipping certain operands from processing, for example
2830 : outer loop reduction initial defs. */
2831 5286533 : if (skip_args[i])
2832 : {
2833 513916 : children.safe_push (NULL);
2834 5173133 : continue;
2835 : }
2836 :
2837 4772617 : if (oprnd_info->first_dt == vect_uninitialized_def)
2838 : {
2839 : /* COND_EXPR have one too many eventually if the condition
2840 : is a SSA name. */
2841 0 : gcc_assert (i == 3 && nops == 4);
2842 0 : continue;
2843 : }
2844 :
2845 4772617 : if (oprnd_info->first_gs_p)
2846 : {
2847 23785 : gs_scale = oprnd_info->first_gs_info.scale;
2848 23785 : gs_base = oprnd_info->first_gs_info.base;
2849 : }
2850 :
2851 4772617 : if (is_a <bb_vec_info> (vinfo)
2852 1699629 : && oprnd_info->first_dt == vect_internal_def
2853 5680604 : && !oprnd_info->any_pattern)
2854 : {
2855 : /* For BB vectorization, if all defs are the same do not
2856 : bother to continue the build along the single-lane
2857 : graph but use a splat of the scalar value. */
2858 854818 : stmt_vec_info first_def = oprnd_info->def_stmts[0];
2859 922648 : for (j = 1; j < group_size; ++j)
2860 872194 : if (oprnd_info->def_stmts[j] != first_def)
2861 : break;
2862 854818 : if (j == group_size
2863 : /* But avoid doing this for loads where we may be
2864 : able to CSE things, unless the stmt is not
2865 : vectorizable. */
2866 854818 : && (!STMT_VINFO_VECTORIZABLE (first_def)
2867 60542 : || !gimple_vuse (first_def->stmt)))
2868 : {
2869 40854 : if (dump_enabled_p ())
2870 119 : dump_printf_loc (MSG_NOTE, vect_location,
2871 : "Using a splat of the uniform operand %G",
2872 : first_def->stmt);
2873 40854 : oprnd_info->first_dt = vect_external_def;
2874 : }
2875 : }
2876 :
2877 4772617 : if (oprnd_info->first_dt == vect_external_def
2878 4772617 : || oprnd_info->first_dt == vect_constant_def)
2879 : {
2880 1572390 : if (!GET_MODE_SIZE (vinfo->vector_mode).is_constant ())
2881 : {
2882 : tree op0;
2883 : tree uniform_val = op0 = oprnd_info->ops[0];
2884 : for (j = 1; j < oprnd_info->ops.length (); ++j)
2885 : if (oprnd_info->ops[j]
2886 : && !operand_equal_p (uniform_val, oprnd_info->ops[j]))
2887 : {
2888 : uniform_val = NULL_TREE;
2889 : break;
2890 : }
2891 : if (!uniform_val
2892 : && !can_duplicate_and_interleave_p (vinfo,
2893 : oprnd_info->ops.length (),
2894 : TREE_TYPE (op0)))
2895 : {
2896 : matches[j] = false;
2897 : if (dump_enabled_p ())
2898 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
2899 : "Build SLP failed: invalid type of def "
2900 : "for variable-length SLP %T\n", op0);
2901 : goto fail;
2902 : }
2903 : }
2904 1572390 : slp_tree invnode = vect_create_new_slp_node (oprnd_info->ops);
2905 1572390 : SLP_TREE_DEF_TYPE (invnode) = oprnd_info->first_dt;
2906 1572390 : oprnd_info->ops = vNULL;
2907 1572390 : children.safe_push (invnode);
2908 1572390 : continue;
2909 1572390 : }
2910 :
2911 : /* See which SLP operand a reduction chain continues on. We want
2912 : to chain even PHIs but not backedges. */
2913 3200227 : if (STMT_VINFO_REDUC_DEF (oprnd_info->def_stmts[0])
2914 3200227 : || STMT_VINFO_REDUC_IDX (oprnd_info->def_stmts[0]) != -1)
2915 : {
2916 237923 : if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle)
2917 : {
2918 776 : if (oprnd_info->first_dt == vect_double_reduction_def)
2919 388 : reduc_idx = i;
2920 : }
2921 237147 : else if (is_a <gphi *> (stmt_info->stmt)
2922 237147 : && gimple_phi_num_args
2923 101849 : (as_a <gphi *> (stmt_info->stmt)) != 1)
2924 : ;
2925 135691 : else if (STMT_VINFO_REDUC_IDX (stmt_info) == -1
2926 393 : && STMT_VINFO_DEF_TYPE (stmt_info) != vect_double_reduction_def)
2927 : ;
2928 135691 : else if (reduc_idx == -1)
2929 127200 : reduc_idx = i;
2930 : else
2931 : /* For .COND_* reduction operations the else value can be the
2932 : same as one of the operation operands. The other def
2933 : stmts have been moved, so we can't check easily. Check
2934 : it's a call at least. */
2935 8491 : gcc_assert (is_a <gcall *> (stmt_info->stmt));
2936 : }
2937 :
2938 : /* When we have a masked load with uniform mask discover this
2939 : as a single-lane mask with a splat permute. This way we can
2940 : recognize this as a masked load-lane by stripping the splat. */
2941 3200227 : if (is_a <gcall *> (STMT_VINFO_STMT (stmt_info))
2942 58311 : && gimple_call_internal_p (STMT_VINFO_STMT (stmt_info),
2943 : IFN_MASK_LOAD)
2944 6193 : && STMT_VINFO_GROUPED_ACCESS (stmt_info)
2945 3200304 : && ! STMT_VINFO_SLP_VECT_ONLY (DR_GROUP_FIRST_ELEMENT (stmt_info)))
2946 : {
2947 35 : vec<stmt_vec_info> def_stmts2;
2948 35 : def_stmts2.create (1);
2949 35 : def_stmts2.quick_push (oprnd_info->def_stmts[0]);
2950 35 : child = vect_build_slp_tree (vinfo, def_stmts2,
2951 : matches, limit,
2952 : &this_tree_size, bst_map);
2953 35 : if (child)
2954 : {
2955 35 : slp_tree pnode = vect_create_new_slp_node (1, VEC_PERM_EXPR);
2956 35 : SLP_TREE_VECTYPE (pnode) = SLP_TREE_VECTYPE (child);
2957 35 : SLP_TREE_LANES (pnode) = group_size;
2958 35 : SLP_TREE_SCALAR_STMTS (pnode).create (group_size);
2959 35 : SLP_TREE_LANE_PERMUTATION (pnode).create (group_size);
2960 245 : for (unsigned k = 0; k < group_size; ++k)
2961 : {
2962 175 : SLP_TREE_SCALAR_STMTS (pnode)
2963 175 : .quick_push (oprnd_info->def_stmts[0]);
2964 175 : SLP_TREE_LANE_PERMUTATION (pnode)
2965 175 : .quick_push (std::make_pair (0u, 0u));
2966 : }
2967 35 : SLP_TREE_CHILDREN (pnode).quick_push (child);
2968 35 : children.safe_push (pnode);
2969 35 : oprnd_info->def_stmts = vNULL;
2970 35 : continue;
2971 35 : }
2972 : else
2973 0 : def_stmts2.release ();
2974 : }
2975 :
2976 6400384 : can_swap = (i == 0
2977 2363226 : && (nops == 2 || nops == 3)
2978 1528388 : && oprnds_info.length () > 1
2979 1528388 : && oprnds_info[1]->first_dt == vect_internal_def
2980 624229 : && (is_gimple_assign (stmt_info->stmt)
2981 51244 : || is_gimple_call (stmt_info->stmt))
2982 : /* Swapping operands for reductions breaks assumptions
2983 : later on. */
2984 3778328 : && STMT_VINFO_REDUC_IDX (stmt_info) == -1);
2985 3200192 : can_swap_nonmatching = can_swap;
2986 3200192 : stmt_can_swap = NULL;
2987 3200192 : if (can_swap)
2988 : {
2989 522492 : stmt_can_swap = XALLOCAVEC (bool, group_size);
2990 8197673 : for (j = 0; j < group_size; ++j)
2991 : {
2992 7675181 : stmt_can_swap[j] = false;
2993 7675181 : if (!stmts[j])
2994 : /* NULL lanes are gaps and have no stmt to swap. */
2995 0 : stmt_can_swap[j] = true;
2996 7675181 : else if (gassign *stmt = dyn_cast <gassign *> (stmts[j]->stmt))
2997 : {
2998 7669593 : tree_code code = gimple_assign_rhs_code (stmt);
2999 15339186 : stmt_can_swap[j] = (commutative_tree_code (code)
3000 7669593 : || commutative_ternary_tree_code (code));
3001 : }
3002 5588 : else if (gcall *call = dyn_cast <gcall *> (stmts[j]->stmt))
3003 : {
3004 5588 : internal_fn fn = (gimple_call_internal_p (call)
3005 5588 : ? gimple_call_internal_fn (call) : IFN_LAST);
3006 11176 : stmt_can_swap[j] = ((commutative_binary_fn_p (fn)
3007 5272 : || commutative_ternary_fn_p (fn))
3008 5624 : && first_commutative_argument (fn) == 0);
3009 : }
3010 :
3011 7675181 : if (j != 0 && !stmt_can_swap[j])
3012 7675181 : can_swap_nonmatching = false;
3013 : }
3014 : }
3015 :
3016 3200192 : old_swap_distance = least_upthread_swappable_op_distance;
3017 3200192 : if (can_swap_nonmatching)
3018 480187 : least_upthread_swappable_op_distance = 1;
3019 2720005 : else if (least_upthread_swappable_op_distance != -1U)
3020 351457 : least_upthread_swappable_op_distance++;
3021 3200192 : child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts,
3022 : matches, limit,
3023 : &this_tree_size, bst_map);
3024 3200192 : least_upthread_swappable_op_distance = old_swap_distance;
3025 3200192 : if (child != NULL)
3026 : {
3027 2691582 : oprnd_info->def_stmts = vNULL;
3028 2691582 : children.safe_push (child);
3029 2691582 : continue;
3030 : }
3031 :
3032 : /* If the SLP build for operand zero failed and operand zero
3033 : and one can be commuted try that for the scalar stmts
3034 : that failed the match. */
3035 508610 : if (/* A first scalar stmt mismatch signals a fatal mismatch. */
3036 508610 : matches[0]
3037 285934 : && can_swap)
3038 : {
3039 : /* See whether we can swap the matching or the non-matching
3040 : stmt operands. */
3041 : bool swap_not_matching = true;
3042 73995 : do
3043 : {
3044 7111931 : for (j = 0; j < group_size; ++j)
3045 : {
3046 7055805 : if (matches[j] != !swap_not_matching)
3047 87377 : continue;
3048 : /* Verify if we can swap operands of this stmt. */
3049 6968428 : if (!stmt_can_swap[j])
3050 : {
3051 17869 : if (!swap_not_matching)
3052 7875 : goto fail;
3053 : swap_not_matching = false;
3054 : break;
3055 : }
3056 : }
3057 : }
3058 66120 : while (j != group_size);
3059 :
3060 : /* Swap mismatched definition stmts. */
3061 56126 : if (dump_enabled_p ())
3062 401 : dump_printf_loc (MSG_NOTE, vect_location,
3063 : "Re-trying with swapped operands of stmts ");
3064 7083005 : for (j = 0; j < group_size; ++j)
3065 7026879 : if (matches[j] == !swap_not_matching)
3066 : {
3067 13900710 : std::swap (oprnds_info[0]->def_stmts[j],
3068 6950355 : oprnds_info[1]->def_stmts[j]);
3069 13900710 : std::swap (oprnds_info[0]->ops[j],
3070 6950355 : oprnds_info[1]->ops[j]);
3071 6950355 : if (dump_enabled_p ())
3072 1096 : dump_printf (MSG_NOTE, "%d ", j);
3073 : }
3074 56126 : if (dump_enabled_p ())
3075 401 : dump_printf (MSG_NOTE, "\n");
3076 : /* After swapping some operands we lost track whether an
3077 : operand has any pattern defs so be conservative here. */
3078 109087 : if (oprnds_info[0]->any_pattern || oprnds_info[1]->any_pattern)
3079 4240 : oprnds_info[0]->any_pattern = oprnds_info[1]->any_pattern = true;
3080 : /* And try again with scratch 'matches' ... */
3081 56126 : bool *tem = XALLOCAVEC (bool, group_size);
3082 56126 : if ((child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts,
3083 : tem, limit,
3084 : &this_tree_size, bst_map)) != NULL)
3085 : {
3086 7831 : oprnd_info->def_stmts = vNULL;
3087 7831 : children.safe_push (child);
3088 7831 : continue;
3089 : }
3090 : }
3091 444609 : fail:
3092 :
3093 : /* If the SLP build failed and we analyze a basic-block
3094 : simply treat nodes we fail to build as externally defined
3095 : (and thus build vectors from the scalar defs).
3096 : The cost model will reject outright expensive cases.
3097 : ??? This doesn't treat cases where permutation ultimatively
3098 : fails (or we don't try permutation below). Ideally we'd
3099 : even compute a permutation that will end up with the maximum
3100 : SLP tree size... */
3101 500779 : if (is_a <bb_vec_info> (vinfo)
3102 : /* ??? Rejecting patterns this way doesn't work. We'd have to
3103 : do extra work to cancel the pattern so the uses see the
3104 : scalar version. */
3105 : /* Skip building vector operands from scalars while operand
3106 : discovery may still be fixed by retrying with swapped operands. */
3107 441957 : && (least_upthread_swappable_op_distance != 1
3108 : /* A first scalar stmt mismatch signals a fatal mismatch
3109 : that the parent commutative retry cannot recover. */
3110 27479 : || !matches[0])
3111 423013 : && !is_pattern_stmt_p (stmt_info)
3112 895260 : && !oprnd_info->any_pattern)
3113 : {
3114 : /* But if there's a leading vector sized set of matching stmts
3115 : fail here so we can split the group. This matches the condition
3116 : vect_analyze_slp_instance uses. */
3117 : /* ??? We might want to split here and combine the results to support
3118 : multiple vector sizes better. */
3119 612673 : for (j = 0; j < group_size; ++j)
3120 612673 : if (!matches[j])
3121 : break;
3122 394160 : if (!known_ge (j, TYPE_VECTOR_SUBPARTS (vectype))
3123 394129 : && vect_slp_can_convert_to_external (oprnd_info->def_stmts))
3124 : {
3125 387379 : if (dump_enabled_p ())
3126 706 : dump_printf_loc (MSG_NOTE, vect_location,
3127 : "Building vector operands from scalars\n");
3128 387379 : this_tree_size++;
3129 387379 : child = vect_create_new_slp_node (oprnd_info->ops);
3130 387379 : children.safe_push (child);
3131 387379 : oprnd_info->ops = vNULL;
3132 387379 : continue;
3133 : }
3134 : }
3135 :
3136 113400 : gcc_assert (child == NULL);
3137 247144 : FOR_EACH_VEC_ELT (children, j, child)
3138 20344 : if (child)
3139 20344 : vect_free_slp_tree (child);
3140 113400 : vect_free_oprnd_info (oprnds_info);
3141 113400 : return NULL;
3142 : }
3143 :
3144 3178174 : vect_free_oprnd_info (oprnds_info);
3145 :
3146 : /* If we have all children of a child built up from uniform scalars
3147 : or does more than one possibly expensive vector construction then
3148 : just throw that away, causing it built up from scalars.
3149 : The exception is the SLP node for the vector store. */
3150 3178174 : if (is_a <bb_vec_info> (vinfo)
3151 1157202 : && !STMT_VINFO_GROUPED_ACCESS (stmt_info)
3152 : /* ??? Rejecting patterns this way doesn't work. We'd have to
3153 : do extra work to cancel the pattern so the uses see the
3154 : scalar version. */
3155 3660032 : && !is_pattern_stmt_p (stmt_info))
3156 : {
3157 : slp_tree child;
3158 : unsigned j;
3159 : bool all_uniform_p = true;
3160 : unsigned n_vector_builds = 0;
3161 1344082 : FOR_EACH_VEC_ELT (children, j, child)
3162 : {
3163 896059 : if (!child)
3164 : ;
3165 896059 : else if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
3166 : all_uniform_p = false;
3167 639813 : else if (!vect_slp_tree_uniform_p (child))
3168 : {
3169 483908 : all_uniform_p = false;
3170 483908 : if (SLP_TREE_DEF_TYPE (child) == vect_external_def)
3171 443391 : n_vector_builds++;
3172 : }
3173 : }
3174 448023 : if (all_uniform_p
3175 448023 : || n_vector_builds > 1
3176 761304 : || (n_vector_builds == children.length ()
3177 35433 : && is_a <gphi *> (stmt_info->stmt)))
3178 : {
3179 : /* Roll back. */
3180 139630 : matches[0] = false;
3181 442254 : FOR_EACH_VEC_ELT (children, j, child)
3182 302624 : if (child)
3183 302624 : vect_free_slp_tree (child);
3184 :
3185 139630 : if (dump_enabled_p ())
3186 234 : dump_printf_loc (MSG_NOTE, vect_location,
3187 : "Building parent vector operands from "
3188 : "scalars instead\n");
3189 3291574 : return NULL;
3190 : }
3191 : }
3192 :
3193 3038544 : *tree_size += this_tree_size + 1;
3194 :
3195 3038544 : if (two_operators)
3196 : {
3197 : /* ??? We'd likely want to either cache in bst_map sth like
3198 : { a+b, NULL, a+b, NULL } and { NULL, a-b, NULL, a-b } or
3199 : the true { a+b, a+b, a+b, a+b } ... but there we don't have
3200 : explicit stmts to put in so the keying on 'stmts' doesn't
3201 : work (but we have the same issue with nodes that use 'ops'). */
3202 :
3203 7649 : if (has_two_operators_perm)
3204 : {
3205 45 : slp_tree child = children[0];
3206 45 : children.truncate (0);
3207 180 : for (i = 0; i < 2; i++)
3208 : {
3209 90 : slp_tree pnode
3210 90 : = vect_create_new_slp_node (two_op_scalar_stmts[i], 2);
3211 90 : SLP_TREE_CODE (pnode) = VEC_PERM_EXPR;
3212 90 : SLP_TREE_VECTYPE (pnode) = vectype;
3213 90 : SLP_TREE_CHILDREN (pnode).quick_push (child);
3214 90 : SLP_TREE_CHILDREN (pnode).quick_push (child);
3215 90 : SLP_TREE_REPRESENTATIVE (pnode) = NULL;
3216 90 : lane_permutation_t& perm = SLP_TREE_LANE_PERMUTATION (pnode);
3217 90 : children.safe_push (pnode);
3218 :
3219 796 : for (unsigned j = 0; j < stmts.length (); j++)
3220 616 : perm.safe_push (std::make_pair (0, two_op_perm_indices[i][j]));
3221 : }
3222 :
3223 45 : SLP_TREE_REF_COUNT (child) += 4;
3224 : }
3225 :
3226 7649 : slp_tree one = new _slp_tree;
3227 7649 : slp_tree two = new _slp_tree;
3228 7649 : SLP_TREE_DEF_TYPE (one) = vect_internal_def;
3229 7649 : SLP_TREE_DEF_TYPE (two) = vect_internal_def;
3230 7649 : SLP_TREE_VECTYPE (one) = vectype;
3231 7649 : SLP_TREE_VECTYPE (two) = vectype;
3232 7649 : SLP_TREE_CHILDREN (one).safe_splice (children);
3233 7649 : SLP_TREE_CHILDREN (two).safe_splice (children);
3234 7649 : slp_tree child;
3235 30598 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (two), i, child)
3236 15300 : SLP_TREE_REF_COUNT (child)++;
3237 :
3238 : /* Here we record the original defs since this
3239 : node represents the final lane configuration. */
3240 7649 : node = vect_create_new_slp_node (node, stmts, 2);
3241 7649 : SLP_TREE_VECTYPE (node) = vectype;
3242 7649 : SLP_TREE_CODE (node) = VEC_PERM_EXPR;
3243 7649 : SLP_TREE_CHILDREN (node).quick_push (one);
3244 7649 : SLP_TREE_CHILDREN (node).quick_push (two);
3245 7649 : SLP_TREE_REPRESENTATIVE (node) = NULL;
3246 7649 : enum tree_code code0 = ERROR_MARK;
3247 7649 : enum tree_code ocode = ERROR_MARK;
3248 7649 : if (gassign *stmt = dyn_cast <gassign *> (stmts[0]->stmt))
3249 7647 : code0 = gimple_assign_rhs_code (stmt);
3250 7649 : stmt_vec_info ostmt_info;
3251 7649 : unsigned j = 0;
3252 27338 : FOR_EACH_VEC_ELT (stmts, i, ostmt_info)
3253 : {
3254 19689 : int op = 0;
3255 19689 : if (gassign *ostmt = dyn_cast <gassign *> (ostmt_info->stmt))
3256 : {
3257 19685 : if (gimple_assign_rhs_code (ostmt) != code0)
3258 : {
3259 9863 : ocode = gimple_assign_rhs_code (ostmt);
3260 : op = 1;
3261 : j = i;
3262 : }
3263 : }
3264 : else
3265 : {
3266 8 : if (gimple_call_combined_fn (stmts[0]->stmt)
3267 4 : != gimple_call_combined_fn (ostmt_info->stmt))
3268 : {
3269 2 : op = 1;
3270 2 : j = i;
3271 : }
3272 : }
3273 19689 : SLP_TREE_LANE_PERMUTATION (node).safe_push (std::make_pair (op, i));
3274 : }
3275 7649 : SLP_TREE_CODE (one) = code0;
3276 7649 : SLP_TREE_CODE (two) = ocode;
3277 7649 : SLP_TREE_LANES (one) = stmts.length ();
3278 7649 : SLP_TREE_LANES (two) = stmts.length ();
3279 7649 : SLP_TREE_REPRESENTATIVE (one) = stmts[0];
3280 7649 : SLP_TREE_REPRESENTATIVE (two) = stmts[j];
3281 :
3282 7649 : return node;
3283 : }
3284 :
3285 3030895 : node = vect_create_new_slp_node (node, stmts, nops);
3286 3030895 : SLP_TREE_VECTYPE (node) = vectype;
3287 3030895 : SLP_TREE_CHILDREN (node).splice (children);
3288 3030895 : SLP_TREE_GS_SCALE (node) = gs_scale;
3289 3030895 : SLP_TREE_GS_BASE (node) = gs_base;
3290 3030895 : if (reduc_idx != -1)
3291 : {
3292 119065 : gcc_assert (STMT_VINFO_REDUC_IDX (stmt_info) != -1
3293 : || STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle
3294 : || STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def);
3295 119065 : SLP_TREE_REDUC_IDX (node) = reduc_idx;
3296 119065 : node->cycle_info.id = SLP_TREE_CHILDREN (node)[reduc_idx]->cycle_info.id;
3297 : }
3298 : /* When reaching the reduction PHI, create a vect_reduc_info. */
3299 2911830 : else if ((STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def
3300 2911830 : || STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
3301 2911830 : && is_a <gphi *> (STMT_VINFO_STMT (stmt_info)))
3302 : {
3303 103826 : loop_vec_info loop_vinfo = as_a <loop_vec_info> (vinfo);
3304 103826 : gcc_assert (STMT_VINFO_REDUC_IDX (stmt_info) == -1);
3305 103826 : node->cycle_info.id = loop_vinfo->reduc_infos.length ();
3306 103826 : vect_reduc_info reduc_info = new vect_reduc_info_s ();
3307 103826 : loop_vinfo->reduc_infos.safe_push (reduc_info);
3308 103826 : stmt_vec_info reduc_phi = stmt_info;
3309 : /* ??? For double reductions vect_is_simple_reduction stores the
3310 : reduction type and code on the inner loop header PHI. */
3311 103826 : if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
3312 : {
3313 388 : use_operand_p use_p;
3314 388 : gimple *use_stmt;
3315 388 : bool res = single_imm_use (gimple_phi_result (stmt_info->stmt),
3316 : &use_p, &use_stmt);
3317 388 : gcc_assert (res);
3318 388 : reduc_phi = loop_vinfo->lookup_stmt (use_stmt);
3319 : }
3320 103826 : VECT_REDUC_INFO_DEF_TYPE (reduc_info) = STMT_VINFO_DEF_TYPE (stmt_info);
3321 103826 : VECT_REDUC_INFO_TYPE (reduc_info) = STMT_VINFO_REDUC_TYPE (reduc_phi);
3322 103826 : VECT_REDUC_INFO_CODE (reduc_info) = STMT_VINFO_REDUC_CODE (reduc_phi);
3323 103826 : VECT_REDUC_INFO_FN (reduc_info) = IFN_LAST;
3324 : }
3325 : return node;
3326 9874722 : }
3327 :
3328 : /* Dump a single SLP tree NODE. */
3329 :
3330 : static void
3331 461940 : vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc,
3332 : slp_tree node)
3333 : {
3334 461940 : unsigned i, j;
3335 461940 : slp_tree child;
3336 461940 : stmt_vec_info stmt_info;
3337 461940 : tree op;
3338 :
3339 461940 : dump_metadata_t metadata (dump_kind, loc.get_impl_location ());
3340 461940 : dump_user_location_t user_loc = loc.get_user_location ();
3341 461940 : dump_printf_loc (metadata, user_loc,
3342 : "node%s %p (refcnt=%u)",
3343 461940 : SLP_TREE_DEF_TYPE (node) == vect_external_def
3344 : ? " (external)"
3345 : : (SLP_TREE_DEF_TYPE (node) == vect_constant_def
3346 445571 : ? " (constant)"
3347 : : ""), (void *) node,
3348 : SLP_TREE_REF_COUNT (node));
3349 461940 : if (SLP_TREE_VECTYPE (node))
3350 391429 : dump_printf (metadata, " %T", SLP_TREE_VECTYPE (node));
3351 461940 : dump_printf (metadata, "%s",
3352 461940 : node->avoid_stlf_fail ? " (avoid-stlf-fail)" : "");
3353 461940 : if (node->cycle_info.id != -1 || node->cycle_info.reduc_idx != -1)
3354 24270 : dump_printf (metadata, " cycle %d, link %d", node->cycle_info.id,
3355 : node->cycle_info.reduc_idx);
3356 461940 : if (node->si)
3357 4896 : dump_printf (metadata, " @%G", node->si);
3358 : else
3359 457044 : dump_printf (metadata, "\n");
3360 461940 : if (SLP_TREE_DEF_TYPE (node) == vect_internal_def)
3361 : {
3362 376133 : if (SLP_TREE_PERMUTE_P (node))
3363 17295 : dump_printf_loc (metadata, user_loc, "op: VEC_PERM_EXPR\n");
3364 : else
3365 358838 : dump_printf_loc (metadata, user_loc, "op template: %G",
3366 358838 : SLP_TREE_REPRESENTATIVE (node)->stmt);
3367 : }
3368 461940 : if (SLP_TREE_SCALAR_STMTS (node).exists ())
3369 904172 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
3370 537075 : if (stmt_info)
3371 530953 : dump_printf_loc (metadata, user_loc, "\t%sstmt %u %G",
3372 530953 : SLP_TREE_LIVE_LANES (node).contains (i)
3373 527260 : ? "[l*]" : (STMT_VINFO_LIVE_P (stmt_info)
3374 527260 : ? "[l] " : ""),
3375 : i, stmt_info->stmt);
3376 : else
3377 6122 : dump_printf_loc (metadata, user_loc, "\tstmt %u ---\n", i);
3378 : else
3379 : {
3380 94843 : dump_printf_loc (metadata, user_loc, "\t{ ");
3381 208575 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_OPS (node), i, op)
3382 113732 : dump_printf (metadata, "%T%s ", op,
3383 113732 : i < SLP_TREE_SCALAR_OPS (node).length () - 1 ? "," : "");
3384 94843 : dump_printf (metadata, "}\n");
3385 : }
3386 461940 : if (SLP_TREE_LOAD_PERMUTATION (node).exists ())
3387 : {
3388 66569 : dump_printf_loc (metadata, user_loc, "\tload permutation {");
3389 152290 : FOR_EACH_VEC_ELT (SLP_TREE_LOAD_PERMUTATION (node), i, j)
3390 85721 : dump_printf (dump_kind, " %u", j);
3391 66569 : dump_printf (dump_kind, " }\n");
3392 : }
3393 461940 : if (SLP_TREE_LANE_PERMUTATION (node).exists ())
3394 : {
3395 17303 : dump_printf_loc (metadata, user_loc, "\tlane permutation {");
3396 64798 : for (i = 0; i < SLP_TREE_LANE_PERMUTATION (node).length (); ++i)
3397 47495 : dump_printf (dump_kind, " %u[%u]",
3398 47495 : SLP_TREE_LANE_PERMUTATION (node)[i].first,
3399 47495 : SLP_TREE_LANE_PERMUTATION (node)[i].second);
3400 17303 : dump_printf (dump_kind, " }%s\n",
3401 17303 : node->ldst_lanes ? " (load-lanes)" : "");
3402 : }
3403 461940 : if (SLP_TREE_CHILDREN (node).is_empty ())
3404 174749 : return;
3405 287191 : dump_printf_loc (metadata, user_loc, "\tchildren");
3406 756526 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
3407 469335 : dump_printf (dump_kind, " %p", (void *)child);
3408 287191 : dump_printf (dump_kind, "%s\n",
3409 287191 : node->ldst_lanes && !SLP_TREE_LANE_PERMUTATION (node).exists ()
3410 : ? " (store-lanes)" : "");
3411 : }
3412 :
3413 : DEBUG_FUNCTION void
3414 0 : debug (slp_tree node)
3415 : {
3416 0 : debug_dump_context ctx;
3417 0 : vect_print_slp_tree (MSG_NOTE,
3418 0 : dump_location_t::from_location_t (UNKNOWN_LOCATION),
3419 : node);
3420 0 : }
3421 :
3422 : /* Recursive helper for the dot producer below. */
3423 :
3424 : static void
3425 0 : dot_slp_tree (FILE *f, slp_tree node, hash_set<slp_tree> &visited)
3426 : {
3427 0 : if (visited.add (node))
3428 : return;
3429 :
3430 0 : fprintf (f, "\"%p\" [label=\"", (void *)node);
3431 0 : vect_print_slp_tree (MSG_NOTE,
3432 0 : dump_location_t::from_location_t (UNKNOWN_LOCATION),
3433 : node);
3434 0 : fprintf (f, "\"];\n");
3435 :
3436 :
3437 0 : for (slp_tree child : SLP_TREE_CHILDREN (node))
3438 0 : fprintf (f, "\"%p\" -> \"%p\";", (void *)node, (void *)child);
3439 :
3440 0 : for (slp_tree child : SLP_TREE_CHILDREN (node))
3441 0 : if (child)
3442 0 : dot_slp_tree (f, child, visited);
3443 : }
3444 :
3445 : DEBUG_FUNCTION void
3446 0 : dot_slp_tree (const char *fname, slp_tree node)
3447 : {
3448 0 : FILE *f = fopen (fname, "w");
3449 0 : fprintf (f, "digraph {\n");
3450 0 : fflush (f);
3451 0 : {
3452 0 : debug_dump_context ctx (f);
3453 0 : hash_set<slp_tree> visited;
3454 0 : dot_slp_tree (f, node, visited);
3455 0 : }
3456 0 : fflush (f);
3457 0 : fprintf (f, "}\n");
3458 0 : fclose (f);
3459 0 : }
3460 :
3461 : DEBUG_FUNCTION void
3462 0 : dot_slp_tree (const char *fname, const vec<slp_instance> &slp_instances)
3463 : {
3464 0 : FILE *f = fopen (fname, "w");
3465 0 : fprintf (f, "digraph {\n");
3466 0 : fflush (f);
3467 0 : {
3468 0 : debug_dump_context ctx (f);
3469 0 : hash_set<slp_tree> visited;
3470 0 : for (auto inst : slp_instances)
3471 0 : dot_slp_tree (f, SLP_INSTANCE_TREE (inst), visited);
3472 0 : }
3473 0 : fflush (f);
3474 0 : fprintf (f, "}\n");
3475 0 : fclose (f);
3476 0 : }
3477 :
3478 : /* Dump a slp tree NODE using flags specified in DUMP_KIND. */
3479 :
3480 : static void
3481 498023 : vect_print_slp_graph (dump_flags_t dump_kind, dump_location_t loc,
3482 : slp_tree node, hash_set<slp_tree> &visited)
3483 : {
3484 498023 : unsigned i;
3485 498023 : slp_tree child;
3486 :
3487 498023 : if (visited.add (node))
3488 498023 : return;
3489 :
3490 458108 : vect_print_slp_tree (dump_kind, loc, node);
3491 :
3492 1380435 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
3493 464219 : if (child)
3494 420438 : vect_print_slp_graph (dump_kind, loc, child, visited);
3495 : }
3496 :
3497 : static void
3498 47523 : vect_print_slp_graph (dump_flags_t dump_kind, dump_location_t loc,
3499 : slp_tree entry)
3500 : {
3501 47523 : hash_set<slp_tree> visited;
3502 47523 : vect_print_slp_graph (dump_kind, loc, entry, visited);
3503 47523 : }
3504 :
3505 : DEBUG_FUNCTION void
3506 0 : debug (slp_instance instance)
3507 : {
3508 0 : debug_dump_context ctx;
3509 0 : vect_print_slp_graph (MSG_NOTE,
3510 0 : dump_location_t::from_location_t (UNKNOWN_LOCATION),
3511 : SLP_INSTANCE_TREE (instance));
3512 0 : }
3513 :
3514 :
3515 : /* Compute the set of scalar stmts participating in external nodes. */
3516 :
3517 : static void
3518 1701178 : vect_slp_gather_extern_scalar_stmts (vec_info *vinfo, slp_tree node,
3519 : hash_set<slp_tree> &visited,
3520 : hash_set<stmt_vec_info> &estmts)
3521 : {
3522 1701178 : if (visited.add (node))
3523 : return;
3524 :
3525 1640142 : if (SLP_TREE_DEF_TYPE (node) == vect_internal_def)
3526 : {
3527 : slp_tree child;
3528 : int i;
3529 1924156 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
3530 984232 : if (child)
3531 984232 : vect_slp_gather_extern_scalar_stmts (vinfo, child, visited, estmts);
3532 : }
3533 : else
3534 3919008 : for (tree def : SLP_TREE_SCALAR_OPS (node))
3535 : {
3536 1820376 : stmt_vec_info def_stmt = vinfo->lookup_def (def);
3537 1820376 : if (def_stmt)
3538 390009 : estmts.add (def_stmt);
3539 : }
3540 : }
3541 :
3542 : /* Mark the original scalar stmt coverage of the vector SLP graph of VINFO
3543 : with STMT_SLP_TYPE == pure_slp. */
3544 :
3545 : static void
3546 246835 : vect_bb_slp_mark_stmts_vectorized (bb_vec_info vinfo)
3547 : {
3548 : /* Gather the scalar stmt leafs of the SLP graph to stop the below DFS
3549 : walk on. */
3550 246835 : hash_set<stmt_vec_info> scalar_stmts_in_externs;
3551 246835 : hash_set<slp_tree> visited;
3552 1457451 : for (auto instance : BB_VINFO_SLP_INSTANCES (vinfo))
3553 716946 : vect_slp_gather_extern_scalar_stmts (vinfo, SLP_INSTANCE_TREE (instance),
3554 : visited, scalar_stmts_in_externs);
3555 :
3556 : /* DFS walk scalar stmts to compute the vectorized coverage indicated
3557 : by STMT_SLP_TYPE (stmt) == pure_slp on the original scalar (non-pattern)
3558 : stmts. */
3559 1457451 : for (auto instance : BB_VINFO_SLP_INSTANCES (vinfo))
3560 : {
3561 903708 : for (auto stmt : SLP_INSTANCE_ROOT_STMTS (instance))
3562 84844 : if (!scalar_stmts_in_externs.contains (stmt))
3563 83590 : STMT_SLP_TYPE (stmt) = pure_slp;
3564 716946 : auto_vec<stmt_vec_info> worklist;
3565 4039368 : for (auto stmt : SLP_TREE_SCALAR_STMTS (SLP_INSTANCE_TREE (instance)))
3566 : {
3567 1888530 : stmt = vect_orig_stmt (stmt);
3568 1888530 : if (!scalar_stmts_in_externs.contains (stmt)
3569 1888530 : && STMT_SLP_TYPE (stmt) != pure_slp)
3570 : {
3571 1871641 : STMT_SLP_TYPE (stmt) = pure_slp;
3572 1871641 : worklist.safe_push (stmt);
3573 : }
3574 : }
3575 3769642 : while (!worklist.is_empty ())
3576 : {
3577 2340561 : stmt_vec_info stmt = worklist.pop ();
3578 :
3579 : /* Now walk relevant parts of the SSA use-def graph. */
3580 2340561 : slp_oprnds child_ops (stmt);
3581 7300904 : for (unsigned i = 0; i < child_ops.num_slp_children; ++i)
3582 : {
3583 2619782 : tree op = child_ops.get_op_for_slp_child (stmt, i);
3584 2619782 : stmt_vec_info def = vinfo->lookup_def (op);
3585 2619782 : if (def
3586 941845 : && !scalar_stmts_in_externs.contains (def)
3587 3183766 : && STMT_SLP_TYPE (def) != pure_slp)
3588 : {
3589 468920 : STMT_SLP_TYPE (def) = pure_slp;
3590 468920 : worklist.safe_push (def);
3591 : }
3592 : }
3593 : }
3594 716946 : }
3595 246835 : }
3596 :
3597 : /* Mark the statements of the tree rooted at NODE as relevant (vect_used). */
3598 :
3599 : static void
3600 2607641 : vect_mark_slp_stmts_relevant (slp_tree node, hash_set<slp_tree> &visited)
3601 : {
3602 2607641 : if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
3603 : return;
3604 :
3605 1566865 : if (visited.add (node))
3606 : return;
3607 :
3608 7306031 : for (auto stmt_info : SLP_TREE_SCALAR_STMTS (node))
3609 3261488 : if (stmt_info)
3610 : {
3611 3261488 : gcc_assert (!STMT_VINFO_RELEVANT (stmt_info)
3612 : || STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_scope);
3613 3261488 : STMT_VINFO_RELEVANT (stmt_info) = vect_used_in_scope;
3614 : }
3615 :
3616 5676979 : for (auto child: SLP_TREE_CHILDREN (node))
3617 1786476 : if (child)
3618 1786476 : vect_mark_slp_stmts_relevant (child, visited);
3619 : }
3620 :
3621 : static void
3622 821165 : vect_mark_slp_stmts_relevant (slp_tree node)
3623 : {
3624 821165 : hash_set<slp_tree> visited;
3625 821165 : vect_mark_slp_stmts_relevant (node, visited);
3626 821165 : }
3627 :
3628 :
3629 : /* Gather loads in the SLP graph NODE and populate the INST loads array. */
3630 :
3631 : static void
3632 11163541 : vect_gather_slp_loads (vec<slp_tree> &loads, slp_tree node,
3633 : hash_set<slp_tree> &visited)
3634 : {
3635 11163541 : if (!node || visited.add (node))
3636 : return;
3637 :
3638 9333850 : if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
3639 : return;
3640 :
3641 6902527 : if (!SLP_TREE_PERMUTE_P (node))
3642 : {
3643 6688086 : stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
3644 6688086 : if (STMT_VINFO_DATA_REF (stmt_info)
3645 2867681 : && DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)))
3646 1633851 : loads.safe_push (node);
3647 : }
3648 :
3649 6902527 : unsigned i;
3650 6902527 : slp_tree child;
3651 15736456 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
3652 8833929 : vect_gather_slp_loads (loads, child, visited);
3653 : }
3654 :
3655 :
3656 : /* Find the last store in SLP INSTANCE. */
3657 :
3658 : stmt_vec_info
3659 2565180 : vect_find_last_scalar_stmt_in_slp (slp_tree node)
3660 : {
3661 2565180 : stmt_vec_info last = NULL;
3662 14510627 : for (auto stmt_vinfo : SLP_TREE_SCALAR_STMTS (node))
3663 6815087 : if (stmt_vinfo)
3664 : {
3665 6815087 : stmt_vinfo = vect_orig_stmt (stmt_vinfo);
3666 6815087 : last = last ? get_later_stmt (stmt_vinfo, last) : stmt_vinfo;
3667 : }
3668 :
3669 2565180 : return last;
3670 : }
3671 :
3672 : /* Find the first stmt in NODE. */
3673 :
3674 : stmt_vec_info
3675 678102 : vect_find_first_scalar_stmt_in_slp (slp_tree node)
3676 : {
3677 678102 : stmt_vec_info first = NULL;
3678 :
3679 3667093 : for (auto stmt_vinfo : SLP_TREE_SCALAR_STMTS (node))
3680 1632787 : if (stmt_vinfo)
3681 : {
3682 1630099 : stmt_vinfo = vect_orig_stmt (stmt_vinfo);
3683 1630099 : if (!first
3684 1630099 : || get_later_stmt (stmt_vinfo, first) == first)
3685 : first = stmt_vinfo;
3686 : }
3687 :
3688 678102 : return first;
3689 : }
3690 :
3691 : /* Splits a group of stores, currently beginning at FIRST_VINFO, into
3692 : two groups: one (still beginning at FIRST_VINFO) of size GROUP1_SIZE
3693 : (also containing the first GROUP1_SIZE stmts, since stores are
3694 : consecutive), the second containing the remainder.
3695 : Return the first stmt in the second group. */
3696 :
3697 : static stmt_vec_info
3698 163457 : vect_split_slp_store_group (stmt_vec_info first_vinfo, unsigned group1_size)
3699 : {
3700 163457 : gcc_assert (DR_GROUP_FIRST_ELEMENT (first_vinfo) == first_vinfo);
3701 163457 : gcc_assert (group1_size > 0);
3702 163457 : int group2_size = DR_GROUP_SIZE (first_vinfo) - group1_size;
3703 163457 : gcc_assert (group2_size > 0);
3704 163457 : DR_GROUP_SIZE (first_vinfo) = group1_size;
3705 :
3706 163457 : stmt_vec_info stmt_info = first_vinfo;
3707 545818 : for (unsigned i = group1_size; i > 1; i--)
3708 : {
3709 382361 : stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info);
3710 382361 : gcc_assert (DR_GROUP_GAP (stmt_info) == 1);
3711 : }
3712 : /* STMT is now the last element of the first group. */
3713 163457 : stmt_vec_info group2 = DR_GROUP_NEXT_ELEMENT (stmt_info);
3714 163457 : DR_GROUP_NEXT_ELEMENT (stmt_info) = 0;
3715 :
3716 163457 : DR_GROUP_SIZE (group2) = group2_size;
3717 456470 : for (stmt_info = group2; stmt_info;
3718 293013 : stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info))
3719 : {
3720 293013 : DR_GROUP_FIRST_ELEMENT (stmt_info) = group2;
3721 293013 : gcc_assert (DR_GROUP_GAP (stmt_info) == 1);
3722 : }
3723 :
3724 : /* For the second group, the DR_GROUP_GAP is that before the original group,
3725 : plus skipping over the first vector. */
3726 163457 : DR_GROUP_GAP (group2) = DR_GROUP_GAP (first_vinfo) + group1_size;
3727 :
3728 : /* DR_GROUP_GAP of the first group now has to skip over the second group too. */
3729 163457 : DR_GROUP_GAP (first_vinfo) += group2_size;
3730 :
3731 163457 : if (dump_enabled_p ())
3732 74 : dump_printf_loc (MSG_NOTE, vect_location, "Split group into %d and %d\n",
3733 : group1_size, group2_size);
3734 :
3735 163457 : return group2;
3736 : }
3737 :
3738 : /* Calculate the unrolling factor for an SLP instance with GROUP_SIZE
3739 : statements and a vector of NUNITS elements. */
3740 :
3741 : static poly_uint64
3742 2866496 : calculate_unrolling_factor (poly_uint64 nunits, unsigned int group_size)
3743 : {
3744 2866496 : return exact_div (common_multiple (nunits, group_size), group_size);
3745 : }
3746 :
3747 : /* Helper that checks to see if a node is a load node. */
3748 :
3749 : static inline bool
3750 103 : vect_is_slp_load_node (slp_tree root)
3751 : {
3752 103 : return (!SLP_TREE_PERMUTE_P (root)
3753 103 : && SLP_TREE_DEF_TYPE (root) == vect_internal_def
3754 97 : && STMT_VINFO_GROUPED_ACCESS (SLP_TREE_REPRESENTATIVE (root))
3755 167 : && DR_IS_READ (STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (root))));
3756 : }
3757 :
3758 :
3759 : /* Helper function of optimize_load_redistribution that performs the operation
3760 : recursively. */
3761 :
3762 : static slp_tree
3763 21799 : optimize_load_redistribution_1 (scalar_stmts_to_slp_tree_map_t *bst_map,
3764 : vec_info *vinfo, unsigned int group_size,
3765 : hash_map<slp_tree, slp_tree> *load_map,
3766 : slp_tree root)
3767 : {
3768 21799 : if (slp_tree *leader = load_map->get (root))
3769 4549 : return *leader;
3770 :
3771 17250 : slp_tree node;
3772 17250 : unsigned i;
3773 :
3774 : /* For now, we don't know anything about externals so do not do anything. */
3775 17250 : if (!root || SLP_TREE_DEF_TYPE (root) != vect_internal_def)
3776 : return NULL;
3777 12115 : else if (SLP_TREE_PERMUTE_P (root))
3778 : {
3779 : /* First convert this node into a load node and add it to the leaves
3780 : list and flatten the permute from a lane to a load one. If it's
3781 : unneeded it will be elided later. */
3782 71 : vec<stmt_vec_info> stmts;
3783 71 : stmts.create (SLP_TREE_LANES (root));
3784 71 : lane_permutation_t lane_perm = SLP_TREE_LANE_PERMUTATION (root);
3785 135 : for (unsigned j = 0; j < lane_perm.length (); j++)
3786 : {
3787 103 : std::pair<unsigned, unsigned> perm = lane_perm[j];
3788 103 : node = SLP_TREE_CHILDREN (root)[perm.first];
3789 :
3790 103 : if (!vect_is_slp_load_node (node)
3791 103 : || SLP_TREE_CHILDREN (node).exists ())
3792 : {
3793 39 : stmts.release ();
3794 39 : goto next;
3795 : }
3796 :
3797 64 : stmts.quick_push (SLP_TREE_SCALAR_STMTS (node)[perm.second]);
3798 : }
3799 :
3800 32 : if (dump_enabled_p ())
3801 0 : dump_printf_loc (MSG_NOTE, vect_location,
3802 : "converting stmts on permute node %p\n",
3803 : (void *) root);
3804 :
3805 32 : bool *matches = XALLOCAVEC (bool, group_size);
3806 32 : unsigned tree_size = 0, limit = 1;
3807 32 : node = vect_build_slp_tree (vinfo, stmts,
3808 : matches, &limit, &tree_size, bst_map);
3809 32 : if (!node)
3810 0 : stmts.release ();
3811 :
3812 32 : load_map->put (root, node);
3813 32 : return node;
3814 : }
3815 :
3816 12044 : next:
3817 12083 : load_map->put (root, NULL);
3818 :
3819 27521 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (root), i , node)
3820 : {
3821 15438 : slp_tree value
3822 15438 : = optimize_load_redistribution_1 (bst_map, vinfo, group_size, load_map,
3823 : node);
3824 15438 : if (value)
3825 : {
3826 32 : SLP_TREE_REF_COUNT (value)++;
3827 32 : SLP_TREE_CHILDREN (root)[i] = value;
3828 : /* ??? We know the original leafs of the replaced nodes will
3829 : be referenced by bst_map, only the permutes created by
3830 : pattern matching are not. */
3831 32 : if (SLP_TREE_REF_COUNT (node) == 1)
3832 32 : load_map->remove (node);
3833 32 : vect_free_slp_tree (node);
3834 : }
3835 : }
3836 :
3837 : return NULL;
3838 : }
3839 :
3840 : /* Temporary workaround for loads not being CSEd during SLP build. This
3841 : function will traverse the SLP tree rooted in ROOT for INSTANCE and find
3842 : VEC_PERM nodes that blend vectors from multiple nodes that all read from the
3843 : same DR such that the final operation is equal to a permuted load. Such
3844 : NODES are then directly converted into LOADS themselves. The nodes are
3845 : CSEd using BST_MAP. */
3846 :
3847 : static void
3848 4179 : optimize_load_redistribution (scalar_stmts_to_slp_tree_map_t *bst_map,
3849 : vec_info *vinfo, unsigned int group_size,
3850 : hash_map<slp_tree, slp_tree> *load_map,
3851 : slp_tree root)
3852 : {
3853 4179 : slp_tree node;
3854 4179 : unsigned i;
3855 :
3856 10540 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (root), i , node)
3857 : {
3858 6361 : slp_tree value
3859 6361 : = optimize_load_redistribution_1 (bst_map, vinfo, group_size, load_map,
3860 : node);
3861 6361 : if (value)
3862 : {
3863 0 : SLP_TREE_REF_COUNT (value)++;
3864 0 : SLP_TREE_CHILDREN (root)[i] = value;
3865 : /* ??? We know the original leafs of the replaced nodes will
3866 : be referenced by bst_map, only the permutes created by
3867 : pattern matching are not. */
3868 0 : if (SLP_TREE_REF_COUNT (node) == 1)
3869 0 : load_map->remove (node);
3870 0 : vect_free_slp_tree (node);
3871 : }
3872 : }
3873 4179 : }
3874 :
3875 : /* Helper function of vect_match_slp_patterns.
3876 :
3877 : Attempts to match patterns against the slp tree rooted in REF_NODE using
3878 : VINFO. Patterns are matched in post-order traversal.
3879 :
3880 : If matching is successful the value in REF_NODE is updated and returned, if
3881 : not then it is returned unchanged. */
3882 :
3883 : static bool
3884 6483939 : vect_match_slp_patterns_2 (slp_tree *ref_node, vec_info *vinfo,
3885 : slp_tree_to_load_perm_map_t *perm_cache,
3886 : slp_compat_nodes_map_t *compat_cache,
3887 : hash_set<slp_tree> *visited)
3888 : {
3889 6483939 : unsigned i;
3890 6483939 : slp_tree node = *ref_node;
3891 6483939 : bool found_p = false;
3892 6483939 : if (!node || visited->add (node))
3893 : return false;
3894 :
3895 : slp_tree child;
3896 10415450 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
3897 4857616 : found_p |= vect_match_slp_patterns_2 (&SLP_TREE_CHILDREN (node)[i],
3898 : vinfo, perm_cache, compat_cache,
3899 : visited);
3900 :
3901 16673502 : for (unsigned x = 0; x < num__slp_patterns; x++)
3902 : {
3903 11115668 : vect_pattern *pattern
3904 11115668 : = slp_patterns[x] (perm_cache, compat_cache, ref_node);
3905 11115668 : if (pattern)
3906 : {
3907 1114 : pattern->build (vinfo);
3908 1114 : delete pattern;
3909 : found_p = true;
3910 : }
3911 : }
3912 :
3913 : return found_p;
3914 : }
3915 :
3916 : /* Applies pattern matching to the given SLP tree rooted in REF_NODE using
3917 : vec_info VINFO.
3918 :
3919 : The modified tree is returned. Patterns are tried in order and multiple
3920 : patterns may match. */
3921 :
3922 : static bool
3923 1626323 : vect_match_slp_patterns (slp_instance instance, vec_info *vinfo,
3924 : hash_set<slp_tree> *visited,
3925 : slp_tree_to_load_perm_map_t *perm_cache,
3926 : slp_compat_nodes_map_t *compat_cache)
3927 : {
3928 1626323 : DUMP_VECT_SCOPE ("vect_match_slp_patterns");
3929 1626323 : slp_tree *ref_node = &SLP_INSTANCE_TREE (instance);
3930 :
3931 1626323 : if (dump_enabled_p ())
3932 31329 : dump_printf_loc (MSG_NOTE, vect_location,
3933 : "Analyzing SLP tree %p for patterns\n",
3934 31329 : (void *) SLP_INSTANCE_TREE (instance));
3935 :
3936 1626323 : return vect_match_slp_patterns_2 (ref_node, vinfo, perm_cache, compat_cache,
3937 1626323 : visited);
3938 : }
3939 :
3940 : /* STMT_INFO is a store group of size GROUP_SIZE that we are considering
3941 : vectorizing with VECTYPE that might be NULL. MASKED_P indicates whether
3942 : the stores are masked.
3943 : Return true if we could use IFN_STORE_LANES instead and if that appears
3944 : to be the better approach. */
3945 :
3946 : static bool
3947 6156 : vect_slp_prefer_store_lanes_p (vec_info *vinfo, stmt_vec_info stmt_info,
3948 : tree vectype, bool masked_p,
3949 : unsigned int group_size,
3950 : unsigned int new_group_size)
3951 : {
3952 6156 : if (!vectype)
3953 : {
3954 6156 : tree scalar_type = TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));
3955 6156 : vectype = get_vectype_for_scalar_type (vinfo, scalar_type);
3956 : }
3957 6156 : if (!vectype)
3958 : return false;
3959 : /* Allow the split if one of the two new groups would operate on full
3960 : vectors *within* rather than across one scalar loop iteration.
3961 : This is purely a heuristic, but it should work well for group
3962 : sizes of 3 and 4, where the possible splits are:
3963 :
3964 : 3->2+1: OK if the vector has exactly two elements
3965 : 4->2+2: Likewise
3966 : 4->3+1: Less clear-cut. */
3967 6156 : if (multiple_p (group_size - new_group_size, TYPE_VECTOR_SUBPARTS (vectype))
3968 6156 : || multiple_p (new_group_size, TYPE_VECTOR_SUBPARTS (vectype)))
3969 : return false;
3970 3480 : return vect_store_lanes_supported (vectype, group_size, masked_p) != IFN_LAST;
3971 : }
3972 :
3973 : /* Analyze an SLP instance starting from a group of grouped stores. Call
3974 : vect_build_slp_tree to build a tree of packed stmts if possible.
3975 : Return FALSE if it's impossible to SLP any stmt in the loop. */
3976 :
3977 : static bool
3978 : vect_analyze_slp_instance (vec_info *vinfo,
3979 : scalar_stmts_to_slp_tree_map_t *bst_map,
3980 : stmt_vec_info stmt_info, slp_instance_kind kind,
3981 : unsigned max_tree_size, unsigned *limit,
3982 : bool force_single_lane);
3983 :
3984 : /* Build an interleaving scheme for the store sources RHS_NODES from
3985 : SCALAR_STMTS. */
3986 :
3987 : static slp_tree
3988 8259 : vect_build_slp_store_interleaving (vec<slp_tree> &rhs_nodes,
3989 : vec<stmt_vec_info> &scalar_stmts)
3990 : {
3991 8259 : unsigned int group_size = scalar_stmts.length ();
3992 16518 : slp_tree node = vect_create_new_slp_node (scalar_stmts,
3993 8259 : SLP_TREE_CHILDREN
3994 : (rhs_nodes[0]).length ());
3995 8259 : SLP_TREE_VECTYPE (node) = SLP_TREE_VECTYPE (rhs_nodes[0]);
3996 8259 : for (unsigned l = 0;
3997 16545 : l < SLP_TREE_CHILDREN (rhs_nodes[0]).length (); ++l)
3998 : {
3999 : /* And a permute merging all RHS SLP trees. */
4000 8286 : slp_tree perm = vect_create_new_slp_node (rhs_nodes.length (),
4001 8286 : VEC_PERM_EXPR);
4002 8286 : SLP_TREE_CHILDREN (node).quick_push (perm);
4003 8286 : SLP_TREE_LANE_PERMUTATION (perm).create (group_size);
4004 8286 : SLP_TREE_VECTYPE (perm) = SLP_TREE_VECTYPE (node);
4005 8286 : SLP_TREE_LANES (perm) = group_size;
4006 8286 : SLP_TREE_REPRESENTATIVE (perm) = NULL;
4007 64412 : for (unsigned j = 0; j < rhs_nodes.length (); ++j)
4008 : {
4009 23920 : SLP_TREE_CHILDREN (perm)
4010 23920 : .quick_push (SLP_TREE_CHILDREN (rhs_nodes[j])[l]);
4011 23920 : SLP_TREE_CHILDREN (rhs_nodes[j])[l]->refcnt++;
4012 23920 : for (unsigned k = 0;
4013 50213 : k < SLP_TREE_LANES (rhs_nodes[j]); ++k)
4014 : {
4015 : /* ??? We should populate SLP_TREE_SCALAR_STMTS
4016 : or SLP_TREE_SCALAR_OPS but then we might have
4017 : a mix of both in our children. */
4018 26293 : SLP_TREE_LANE_PERMUTATION (perm)
4019 26293 : .quick_push (std::make_pair (j, k));
4020 : }
4021 : }
4022 :
4023 : /* Now we have a single permute node but we cannot code-generate
4024 : the case with more than two inputs.
4025 : Perform pairwise reduction, reducing the two inputs
4026 : with the least number of lanes to one and then repeat until
4027 : we end up with two inputs. That scheme makes sure we end
4028 : up with permutes satisfying the restriction of requiring at
4029 : most two vector inputs to produce a single vector output
4030 : when the number of lanes is even. */
4031 15634 : while (SLP_TREE_CHILDREN (perm).length () > 2)
4032 : {
4033 : /* When we have three equal sized groups left the pairwise
4034 : reduction does not result in a scheme that avoids using
4035 : three vectors. Instead merge the first two groups
4036 : to the final size with do-not-care elements (chosen
4037 : from the first group) and then merge with the third.
4038 : { A0, B0, x, A1, B1, x, ... }
4039 : -> { A0, B0, C0, A1, B1, C1, ... }
4040 : This handles group size of three (and at least
4041 : power-of-two multiples of that). */
4042 7348 : if (SLP_TREE_CHILDREN (perm).length () == 3
4043 3390 : && (SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[0])
4044 3390 : == SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[1]))
4045 7348 : && (SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[0])
4046 2515 : == SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[2])))
4047 : {
4048 2209 : int ai = 0;
4049 2209 : int bi = 1;
4050 2209 : slp_tree a = SLP_TREE_CHILDREN (perm)[ai];
4051 2209 : slp_tree b = SLP_TREE_CHILDREN (perm)[bi];
4052 2209 : unsigned n = SLP_TREE_LANES (perm);
4053 :
4054 2209 : slp_tree permab = vect_create_new_slp_node (2, VEC_PERM_EXPR);
4055 2209 : SLP_TREE_LANES (permab) = n;
4056 2209 : SLP_TREE_LANE_PERMUTATION (permab).create (n);
4057 2209 : SLP_TREE_VECTYPE (permab) = SLP_TREE_VECTYPE (perm);
4058 : /* ??? Should be NULL but that's not expected. */
4059 2209 : SLP_TREE_REPRESENTATIVE (permab) = SLP_TREE_REPRESENTATIVE (perm);
4060 2209 : SLP_TREE_CHILDREN (permab).quick_push (a);
4061 6641 : for (unsigned k = 0; k < SLP_TREE_LANES (a); ++k)
4062 2223 : SLP_TREE_LANE_PERMUTATION (permab)
4063 2223 : .quick_push (std::make_pair (0, k));
4064 2209 : SLP_TREE_CHILDREN (permab).quick_push (b);
4065 6641 : for (unsigned k = 0; k < SLP_TREE_LANES (b); ++k)
4066 2223 : SLP_TREE_LANE_PERMUTATION (permab)
4067 2223 : .quick_push (std::make_pair (1, k));
4068 : /* Push the do-not-care lanes. */
4069 4432 : for (unsigned k = 0; k < SLP_TREE_LANES (a); ++k)
4070 2223 : SLP_TREE_LANE_PERMUTATION (permab)
4071 2223 : .quick_push (std::make_pair (0, k));
4072 :
4073 : /* Put the merged node into 'perm', in place of a. */
4074 2209 : SLP_TREE_CHILDREN (perm)[ai] = permab;
4075 : /* Adjust the references to b in the permutation
4076 : of perm and to the later children which we'll
4077 : remove. */
4078 8878 : for (unsigned k = 0; k < SLP_TREE_LANES (perm); ++k)
4079 : {
4080 6669 : std::pair<unsigned, unsigned> &p
4081 6669 : = SLP_TREE_LANE_PERMUTATION (perm)[k];
4082 6669 : if (p.first == (unsigned) bi)
4083 : {
4084 2223 : p.first = ai;
4085 2223 : p.second += SLP_TREE_LANES (a);
4086 : }
4087 4446 : else if (p.first > (unsigned) bi)
4088 2223 : p.first--;
4089 : }
4090 2209 : SLP_TREE_CHILDREN (perm).ordered_remove (bi);
4091 2209 : break;
4092 : }
4093 :
4094 : /* Pick the two nodes with the least number of lanes,
4095 : prefer the earliest candidate and maintain ai < bi. */
4096 : int ai = -1;
4097 : int bi = -1;
4098 46264 : for (unsigned ci = 0; ci < SLP_TREE_CHILDREN (perm).length (); ++ci)
4099 : {
4100 41125 : if (ai == -1)
4101 5139 : ai = ci;
4102 35986 : else if (bi == -1)
4103 5139 : bi = ci;
4104 30847 : else if ((SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[ci])
4105 30847 : < SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[ai]))
4106 30847 : || (SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[ci])
4107 25359 : < SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[bi])))
4108 : {
4109 11866 : if (SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[ai])
4110 5933 : <= SLP_TREE_LANES (SLP_TREE_CHILDREN (perm)[bi]))
4111 2730 : bi = ci;
4112 : else
4113 : {
4114 3203 : ai = bi;
4115 3203 : bi = ci;
4116 : }
4117 : }
4118 : }
4119 :
4120 : /* Produce a merge of nodes ai and bi. */
4121 5139 : slp_tree a = SLP_TREE_CHILDREN (perm)[ai];
4122 5139 : slp_tree b = SLP_TREE_CHILDREN (perm)[bi];
4123 5139 : unsigned n = SLP_TREE_LANES (a) + SLP_TREE_LANES (b);
4124 5139 : slp_tree permab = vect_create_new_slp_node (2, VEC_PERM_EXPR);
4125 5139 : SLP_TREE_LANES (permab) = n;
4126 5139 : SLP_TREE_LANE_PERMUTATION (permab).create (n);
4127 5139 : SLP_TREE_VECTYPE (permab) = SLP_TREE_VECTYPE (perm);
4128 : /* ??? Should be NULL but that's not expected. */
4129 5139 : SLP_TREE_REPRESENTATIVE (permab) = SLP_TREE_REPRESENTATIVE (perm);
4130 5139 : SLP_TREE_CHILDREN (permab).quick_push (a);
4131 18665 : for (unsigned k = 0; k < SLP_TREE_LANES (a); ++k)
4132 8387 : SLP_TREE_LANE_PERMUTATION (permab)
4133 8387 : .quick_push (std::make_pair (0, k));
4134 5139 : SLP_TREE_CHILDREN (permab).quick_push (b);
4135 17989 : for (unsigned k = 0; k < SLP_TREE_LANES (b); ++k)
4136 7711 : SLP_TREE_LANE_PERMUTATION (permab)
4137 7711 : .quick_push (std::make_pair (1, k));
4138 :
4139 : /* Put the merged node into 'perm', in place of a. */
4140 5139 : SLP_TREE_CHILDREN (perm)[ai] = permab;
4141 : /* Adjust the references to b in the permutation
4142 : of perm and to the later children which we'll
4143 : remove. */
4144 73717 : for (unsigned k = 0; k < SLP_TREE_LANES (perm); ++k)
4145 : {
4146 68578 : std::pair<unsigned, unsigned> &p
4147 68578 : = SLP_TREE_LANE_PERMUTATION (perm)[k];
4148 68578 : if (p.first == (unsigned) bi)
4149 : {
4150 7711 : p.first = ai;
4151 7711 : p.second += SLP_TREE_LANES (a);
4152 : }
4153 60867 : else if (p.first > (unsigned) bi)
4154 25554 : p.first--;
4155 : }
4156 5139 : SLP_TREE_CHILDREN (perm).ordered_remove (bi);
4157 : }
4158 : }
4159 :
4160 8259 : return node;
4161 : }
4162 :
4163 : /* Analyze an SLP instance starting from SCALAR_STMTS which are a group
4164 : of KIND. Return true if successful. SCALAR_STMTS is owned by this
4165 : function, REMAIN and ROOT_STMT_INFOS ownership is transferred back to
4166 : the caller upon failure. */
4167 :
4168 : static bool
4169 2096777 : vect_build_slp_instance (vec_info *vinfo,
4170 : slp_instance_kind kind,
4171 : vec<stmt_vec_info> &scalar_stmts,
4172 : vec<stmt_vec_info> &root_stmt_infos,
4173 : vec<tree> &remain,
4174 : unsigned max_tree_size, unsigned *limit,
4175 : scalar_stmts_to_slp_tree_map_t *bst_map,
4176 : bool force_single_lane)
4177 : {
4178 : /* If there's no budget left bail out early. */
4179 2096777 : if (*limit == 0)
4180 : {
4181 16191 : scalar_stmts.release ();
4182 16191 : return false;
4183 : }
4184 :
4185 2080586 : if (kind == slp_inst_kind_ctor)
4186 : {
4187 14422 : if (dump_enabled_p ())
4188 98 : dump_printf_loc (MSG_NOTE, vect_location,
4189 : "Analyzing vectorizable constructor: %G\n",
4190 49 : root_stmt_infos[0]->stmt);
4191 : }
4192 2066164 : else if (kind == slp_inst_kind_gcond)
4193 : {
4194 292109 : if (dump_enabled_p ())
4195 5830 : dump_printf_loc (MSG_NOTE, vect_location,
4196 : "Analyzing vectorizable control flow: %G",
4197 2915 : root_stmt_infos[0]->stmt);
4198 : }
4199 1774055 : else if (kind == slp_inst_kind_bb_reduc)
4200 : {
4201 1384420 : if (dump_enabled_p ())
4202 7178 : dump_printf_loc (MSG_NOTE, vect_location,
4203 : "Analyzing vectorizable BB reduction: %G",
4204 3589 : root_stmt_infos[0]->stmt);
4205 : }
4206 :
4207 2080586 : if (dump_enabled_p ())
4208 : {
4209 26351 : dump_printf_loc (MSG_NOTE, vect_location,
4210 : "Starting SLP discovery for\n");
4211 56925 : for (unsigned i = 0; i < scalar_stmts.length (); ++i)
4212 61148 : dump_printf_loc (MSG_NOTE, vect_location,
4213 30574 : " %G", scalar_stmts[i]->stmt);
4214 : }
4215 :
4216 : /* Build the tree for the SLP instance. */
4217 2080586 : unsigned int group_size = scalar_stmts.length ();
4218 2080586 : bool *matches = XALLOCAVEC (bool, group_size);
4219 2080586 : unsigned tree_size = 0;
4220 :
4221 2080586 : slp_tree node = NULL;
4222 2080586 : if (group_size > 1 && force_single_lane)
4223 : {
4224 0 : matches[0] = true;
4225 0 : matches[1] = false;
4226 : }
4227 : else
4228 2080586 : node = vect_build_slp_tree (vinfo, scalar_stmts, matches, limit,
4229 : &tree_size, bst_map);
4230 2080586 : if (node != NULL)
4231 : {
4232 : /* Create a new SLP instance. */
4233 821916 : slp_instance new_instance = XNEW (class _slp_instance);
4234 821916 : SLP_INSTANCE_TREE (new_instance) = node;
4235 821916 : SLP_INSTANCE_LOADS (new_instance) = vNULL;
4236 821916 : SLP_INSTANCE_ROOT_STMTS (new_instance) = root_stmt_infos;
4237 821916 : SLP_INSTANCE_REMAIN_DEFS (new_instance) = remain;
4238 821916 : SLP_INSTANCE_KIND (new_instance) = kind;
4239 821916 : new_instance->reduc_phis = NULL;
4240 821916 : new_instance->cost_vec = vNULL;
4241 821916 : new_instance->subgraph_entries = vNULL;
4242 :
4243 821916 : if (dump_enabled_p ())
4244 23144 : dump_printf_loc (MSG_NOTE, vect_location,
4245 : "SLP size %u vs. limit %u.\n",
4246 : tree_size, max_tree_size);
4247 :
4248 821916 : vinfo->slp_instances.safe_push (new_instance);
4249 :
4250 : /* ??? We've replaced the old SLP_INSTANCE_GROUP_SIZE with
4251 : the number of SLP lanes of the root in a few places.
4252 : Verify that assumption holds. */
4253 821916 : gcc_assert (SLP_TREE_LANES (SLP_INSTANCE_TREE (new_instance))
4254 : == group_size);
4255 :
4256 821916 : if (dump_enabled_p ())
4257 : {
4258 23144 : if (kind == slp_inst_kind_reduc_group)
4259 1470 : dump_printf_loc (MSG_NOTE, vect_location,
4260 : "SLP discovery of size %d reduction group "
4261 : "succeeded\n", group_size);
4262 23144 : dump_printf_loc (MSG_NOTE, vect_location,
4263 : "Final SLP tree for instance %p:\n",
4264 : (void *) new_instance);
4265 23144 : vect_print_slp_graph (MSG_NOTE, vect_location,
4266 : SLP_INSTANCE_TREE (new_instance));
4267 : }
4268 :
4269 821916 : return true;
4270 : }
4271 : /* Failed to SLP. */
4272 :
4273 : /* While we arrive here even with slp_inst_kind_store we should only
4274 : for group_size == 1. The code to split store groups is only in
4275 : vect_analyze_slp_instance now. */
4276 1258670 : gcc_assert (kind != slp_inst_kind_store || group_size == 1);
4277 :
4278 : /* For BB vectorization we get failures only in case of the need of
4279 : unrolling, as otherwise we'll simply get operands built from scalars.
4280 : Iff there is any mismatches in the toplevel stmts those will prevail,
4281 : otherwise we get the non-power-of-two tail of the lanes failed.
4282 : For BB reductions we mainly want to catch the first case so we pick
4283 : a more useful subset of lanes to reduce. */
4284 1258670 : if (kind == slp_inst_kind_bb_reduc && matches[0])
4285 : {
4286 : unsigned n_matching = 0;
4287 2197228 : for (unsigned i = 0; i < group_size; ++i)
4288 1553037 : if (matches[i])
4289 745123 : n_matching++;
4290 644191 : vec<stmt_vec_info> scalar_stmts2 = vNULL;
4291 : /* Try matched parts and put the rest to remain. */
4292 644191 : if (n_matching >= 2 && n_matching >= group_size / 2)
4293 : {
4294 : /* As we know the matches[] stmts match up, recursing for
4295 : non-power-of-two sizes will just force-fail the tail
4296 : for us at hopefully optimal vector size and succesfully
4297 : finish discovery. */
4298 45105 : scalar_stmts2.create (n_matching);
4299 282597 : for (unsigned i = 0; i < group_size; ++i)
4300 192387 : if (matches[i])
4301 138343 : scalar_stmts2.quick_push (scalar_stmts[i]);
4302 : else
4303 54044 : remain.safe_push
4304 57759 : (gimple_get_lhs (vect_orig_stmt (scalar_stmts[i])->stmt));
4305 : }
4306 : /* Try the non-matching part. */
4307 599086 : else if (group_size - n_matching >= 2)
4308 : {
4309 : /* We do not know whether the !matches[] part matches, so avoid
4310 : cutting to a multiple of the vector size too early. We should
4311 : make progress by means of remain only growing and most of the
4312 : time prefering the matching[] part. */
4313 30105 : scalar_stmts2.create (scalar_stmts.length () - n_matching);
4314 282898 : for (unsigned i = 0; i < group_size; ++i)
4315 222688 : if (!matches[i])
4316 184889 : scalar_stmts2.quick_push (scalar_stmts[i]);
4317 : else
4318 37799 : remain.safe_push
4319 38794 : (gimple_get_lhs (vect_orig_stmt (scalar_stmts[i])->stmt));
4320 : }
4321 644191 : if (scalar_stmts2.exists ())
4322 : {
4323 75210 : if (dump_enabled_p ())
4324 240 : dump_printf_loc (MSG_NOTE, vect_location, "Splitting %d "
4325 : "non-matching lanes to scalar remains\n",
4326 120 : scalar_stmts.length () - scalar_stmts2.length ());
4327 75210 : scalar_stmts.release ();
4328 75210 : return vect_build_slp_instance (vinfo, kind, scalar_stmts2,
4329 : root_stmt_infos, remain,
4330 : max_tree_size, limit, bst_map,
4331 75210 : force_single_lane);
4332 : }
4333 : }
4334 :
4335 : /* Free the allocated memory. */
4336 1183460 : scalar_stmts.release ();
4337 :
4338 : /* Failed to SLP. */
4339 1183460 : if (dump_enabled_p ())
4340 3087 : dump_printf_loc (MSG_NOTE, vect_location, "SLP discovery failed\n");
4341 : return false;
4342 : }
4343 :
4344 : /* Analyze an SLP instance starting from a the start of a reduction chain.
4345 : Call vect_build_slp_tree to build a tree of packed stmts if possible.
4346 : Return FALSE if SLP build fails. */
4347 :
4348 : static bool
4349 73412 : vect_analyze_slp_reduc_chain (loop_vec_info vinfo,
4350 : scalar_stmts_to_slp_tree_map_t *bst_map,
4351 : stmt_vec_info scalar_stmt,
4352 : unsigned max_tree_size, unsigned *limit)
4353 : {
4354 73412 : vec<stmt_vec_info> scalar_stmts = vNULL;
4355 :
4356 73412 : bool fail = false;
4357 : /* ??? We could leave operation code checking to SLP discovery. */
4358 73412 : code_helper code = STMT_VINFO_REDUC_CODE (STMT_VINFO_REDUC_DEF
4359 : (vect_orig_stmt (scalar_stmt)));
4360 73412 : bool first = true;
4361 73412 : stmt_vec_info next_stmt = scalar_stmt;
4362 83402 : do
4363 : {
4364 83402 : stmt_vec_info stmt = next_stmt;
4365 83402 : gimple_match_op op, orig_op;
4366 83402 : if (!gimple_extract_op (STMT_VINFO_STMT (stmt), &op))
4367 0 : gcc_unreachable ();
4368 166804 : tree reduc_def = gimple_arg (STMT_VINFO_STMT (stmt),
4369 83402 : STMT_VINFO_REDUC_IDX (stmt));
4370 83402 : next_stmt = vect_stmt_to_vectorize (vinfo->lookup_def (reduc_def));
4371 83402 : gcc_assert (is_a <gphi *> (STMT_VINFO_STMT (next_stmt))
4372 : || STMT_VINFO_REDUC_IDX (next_stmt) != -1);
4373 89310 : if (!gimple_extract_op (STMT_VINFO_STMT (vect_orig_stmt (stmt)),
4374 : &orig_op))
4375 0 : gcc_unreachable ();
4376 83402 : if (CONVERT_EXPR_CODE_P (op.code)
4377 4989 : && tree_nop_conversion_p (op.type, TREE_TYPE (op.ops[0]))
4378 88379 : && (first
4379 2496 : || is_a <gphi *> (STMT_VINFO_STMT (next_stmt))))
4380 : ;
4381 78485 : else if (code != orig_op.code)
4382 : {
4383 2728 : fail = true;
4384 2728 : break;
4385 : }
4386 : else
4387 75757 : scalar_stmts.safe_push (stmt);
4388 80674 : first = false;
4389 : }
4390 80674 : while (!is_a <gphi *> (STMT_VINFO_STMT (next_stmt)));
4391 73412 : if (fail)
4392 2728 : return false;
4393 :
4394 : /* Remember a stmt with the actual reduction operation. */
4395 70684 : stmt_vec_info reduc_scalar_stmt = scalar_stmts[0];
4396 :
4397 : /* When the SSA def chain through reduc-idx does not form a natural
4398 : reduction chain try to linearize an associative operation manually. */
4399 70684 : if (scalar_stmts.length () == 1
4400 68061 : && code.is_tree_code ()
4401 61990 : && associative_tree_code ((tree_code)code)
4402 : /* We may not associate if a fold-left reduction is required. */
4403 131256 : && !needs_fold_left_reduction_p (TREE_TYPE (gimple_get_lhs
4404 : (reduc_scalar_stmt->stmt)),
4405 : code))
4406 : {
4407 57313 : auto_vec<chain_op_t> chain;
4408 57313 : auto_vec<std::pair<tree_code, gimple *> > worklist;
4409 57313 : gimple *op_stmt = NULL, *other_op_stmt = NULL;
4410 57313 : if (is_a <gassign *> (scalar_stmts[0]->stmt)
4411 : /* We cannot linearize an operation that vect_slp_linearize_chain
4412 : would not put on its worklist. */
4413 57313 : && gimple_assign_rhs_code (scalar_stmts[0]->stmt) == (tree_code)code)
4414 : {
4415 56660 : vect_slp_linearize_chain (vinfo, worklist, chain, (tree_code)code,
4416 56660 : scalar_stmts[0]->stmt, op_stmt,
4417 : other_op_stmt,
4418 : NULL);
4419 :
4420 56660 : scalar_stmts.truncate (0);
4421 56660 : stmt_vec_info tail = NULL;
4422 283601 : for (auto el : chain)
4423 : {
4424 113915 : if (el.dt == vect_external_def
4425 113915 : || el.dt == vect_constant_def
4426 113915 : || el.code != (tree_code) code)
4427 : {
4428 294 : scalar_stmts.release ();
4429 294 : return false;
4430 : }
4431 113621 : stmt_vec_info stmt = vinfo->lookup_def (el.op);
4432 113621 : if (STMT_VINFO_REDUC_IDX (stmt) != -1
4433 111337 : || STMT_VINFO_REDUC_DEF (stmt))
4434 : {
4435 56577 : gcc_assert (tail == NULL);
4436 56577 : tail = stmt;
4437 56577 : continue;
4438 : }
4439 57044 : scalar_stmts.safe_push (stmt);
4440 : }
4441 56366 : gcc_assert (tail);
4442 : }
4443 :
4444 : /* When this linearization didn't produce a chain see if stripping
4445 : a wrapping sign conversion produces one. */
4446 57019 : if (scalar_stmts.length () == 1
4447 57019 : && (code == PLUS_EXPR || code == MULT_EXPR || code == BIT_IOR_EXPR
4448 : || code == BIT_AND_EXPR || code == BIT_XOR_EXPR))
4449 : {
4450 55208 : gimple *stmt = scalar_stmts[0]->stmt;
4451 55208 : if (!is_gimple_assign (stmt)
4452 54041 : || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
4453 4724 : || TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME
4454 59932 : || !tree_nop_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)),
4455 4724 : TREE_TYPE (gimple_assign_rhs1 (stmt))))
4456 : {
4457 53429 : scalar_stmts.release ();
4458 53429 : return false;
4459 : }
4460 1779 : stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
4461 1779 : if (!is_gimple_assign (stmt)
4462 1779 : || gimple_assign_rhs_code (stmt) != (tree_code)code)
4463 : {
4464 1760 : scalar_stmts.release ();
4465 1760 : return false;
4466 : }
4467 19 : chain.truncate (0);
4468 19 : vect_slp_linearize_chain (vinfo, worklist, chain, (tree_code)code,
4469 : stmt, op_stmt, other_op_stmt, NULL);
4470 :
4471 19 : scalar_stmts.truncate (0);
4472 19 : stmt_vec_info tail = NULL;
4473 93 : for (auto el : chain)
4474 : {
4475 44 : if (el.dt == vect_external_def
4476 44 : || el.dt == vect_constant_def
4477 44 : || el.code != (tree_code) code)
4478 : {
4479 8 : scalar_stmts.release ();
4480 8 : return false;
4481 : }
4482 36 : stmt_vec_info stmt = vinfo->lookup_def (el.op);
4483 36 : if (STMT_VINFO_REDUC_IDX (stmt) != -1
4484 36 : || STMT_VINFO_REDUC_DEF (stmt))
4485 : {
4486 0 : gcc_assert (tail == NULL);
4487 0 : tail = stmt;
4488 0 : continue;
4489 : }
4490 36 : scalar_stmts.safe_push (stmt);
4491 : }
4492 : /* Unlike the above this does not include the reduction SSA
4493 : cycle. */
4494 11 : gcc_assert (!tail);
4495 : }
4496 :
4497 1822 : if (scalar_stmts.length () < 2)
4498 : {
4499 1697 : scalar_stmts.release ();
4500 1697 : return false;
4501 : }
4502 :
4503 125 : if (dump_enabled_p ())
4504 : {
4505 34 : dump_printf_loc (MSG_NOTE, vect_location,
4506 : "Starting SLP discovery of reduction chain for\n");
4507 140 : for (unsigned i = 0; i < scalar_stmts.length (); ++i)
4508 212 : dump_printf_loc (MSG_NOTE, vect_location,
4509 106 : " %G", scalar_stmts[i]->stmt);
4510 : }
4511 :
4512 125 : unsigned int group_size = scalar_stmts.length ();
4513 125 : bool *matches = XALLOCAVEC (bool, group_size);
4514 125 : unsigned tree_size = 0;
4515 125 : slp_tree node = vect_build_slp_tree (vinfo, scalar_stmts, matches, limit,
4516 125 : &tree_size, bst_map);
4517 125 : if (!node)
4518 : {
4519 47 : scalar_stmts.release ();
4520 47 : return false;
4521 : }
4522 :
4523 78 : unsigned cycle_id = vinfo->reduc_infos.length ();
4524 78 : vect_reduc_info reduc_info = new vect_reduc_info_s ();
4525 78 : vinfo->reduc_infos.safe_push (reduc_info);
4526 78 : VECT_REDUC_INFO_DEF_TYPE (reduc_info) = STMT_VINFO_DEF_TYPE (next_stmt);
4527 78 : VECT_REDUC_INFO_TYPE (reduc_info) = STMT_VINFO_REDUC_TYPE (next_stmt);
4528 78 : VECT_REDUC_INFO_CODE (reduc_info) = STMT_VINFO_REDUC_CODE (next_stmt);
4529 78 : VECT_REDUC_INFO_FN (reduc_info) = IFN_LAST;
4530 78 : reduc_info->is_reduc_chain = true;
4531 :
4532 : /* Build the node for the PHI and possibly the conversions. */
4533 78 : slp_tree phis = vect_create_new_slp_node (2, ERROR_MARK);
4534 78 : SLP_TREE_REPRESENTATIVE (phis) = next_stmt;
4535 78 : phis->cycle_info.id = cycle_id;
4536 78 : SLP_TREE_LANES (phis) = group_size;
4537 78 : if (reduc_scalar_stmt == scalar_stmt)
4538 74 : SLP_TREE_VECTYPE (phis) = SLP_TREE_VECTYPE (node);
4539 : else
4540 4 : SLP_TREE_VECTYPE (phis)
4541 4 : = signed_or_unsigned_type_for (TYPE_UNSIGNED
4542 : (TREE_TYPE (gimple_get_lhs
4543 : (scalar_stmt->stmt))),
4544 : SLP_TREE_VECTYPE (node));
4545 : /* ??? vect_cse_slp_nodes cannot cope with cycles without any
4546 : SLP_TREE_SCALAR_STMTS. */
4547 78 : SLP_TREE_SCALAR_STMTS (phis).create (group_size);
4548 471 : for (unsigned i = 0; i < group_size; ++i)
4549 315 : SLP_TREE_SCALAR_STMTS (phis).quick_push (next_stmt);
4550 :
4551 78 : slp_tree op_input = phis;
4552 78 : if (reduc_scalar_stmt != scalar_stmt)
4553 : {
4554 4 : slp_tree conv = vect_create_new_slp_node (1, ERROR_MARK);
4555 4 : SLP_TREE_REPRESENTATIVE (conv)
4556 4 : = vinfo->lookup_def (gimple_arg (reduc_scalar_stmt->stmt,
4557 4 : STMT_VINFO_REDUC_IDX
4558 : (reduc_scalar_stmt)));
4559 4 : SLP_TREE_CHILDREN (conv).quick_push (phis);
4560 4 : conv->cycle_info.id = cycle_id;
4561 4 : SLP_TREE_REDUC_IDX (conv) = 0;
4562 4 : SLP_TREE_LANES (conv) = group_size;
4563 4 : SLP_TREE_VECTYPE (conv) = SLP_TREE_VECTYPE (node);
4564 4 : SLP_TREE_SCALAR_STMTS (conv) = vNULL;
4565 4 : op_input = conv;
4566 : }
4567 :
4568 78 : slp_tree reduc = vect_create_new_slp_node (2, ERROR_MARK);
4569 78 : SLP_TREE_REPRESENTATIVE (reduc) = reduc_scalar_stmt;
4570 78 : SLP_TREE_CHILDREN (reduc).quick_push (op_input);
4571 78 : SLP_TREE_CHILDREN (reduc).quick_push (node);
4572 78 : reduc->cycle_info.id = cycle_id;
4573 78 : SLP_TREE_REDUC_IDX (reduc) = 0;
4574 78 : SLP_TREE_LANES (reduc) = group_size;
4575 78 : SLP_TREE_VECTYPE (reduc) = SLP_TREE_VECTYPE (node);
4576 : /* ??? For the reduction epilogue we need a live lane. */
4577 78 : SLP_TREE_SCALAR_STMTS (reduc).create (group_size);
4578 78 : SLP_TREE_SCALAR_STMTS (reduc).quick_push (reduc_scalar_stmt);
4579 393 : for (unsigned i = 1; i < group_size; ++i)
4580 237 : SLP_TREE_SCALAR_STMTS (reduc).quick_push (NULL);
4581 :
4582 78 : if (reduc_scalar_stmt != scalar_stmt)
4583 : {
4584 4 : slp_tree conv = vect_create_new_slp_node (1, ERROR_MARK);
4585 4 : SLP_TREE_REPRESENTATIVE (conv) = scalar_stmt;
4586 4 : SLP_TREE_CHILDREN (conv).quick_push (reduc);
4587 4 : conv->cycle_info.id = cycle_id;
4588 4 : SLP_TREE_REDUC_IDX (conv) = 0;
4589 4 : SLP_TREE_LANES (conv) = group_size;
4590 4 : SLP_TREE_VECTYPE (conv) = SLP_TREE_VECTYPE (phis);
4591 : /* ??? For the reduction epilogue we need a live lane. */
4592 4 : SLP_TREE_SCALAR_STMTS (conv).create (group_size);
4593 4 : SLP_TREE_SCALAR_STMTS (conv).quick_push (scalar_stmt);
4594 12 : for (unsigned i = 1; i < group_size; ++i)
4595 4 : SLP_TREE_SCALAR_STMTS (conv).quick_push (NULL);
4596 4 : reduc = conv;
4597 : }
4598 :
4599 78 : edge le = loop_latch_edge (LOOP_VINFO_LOOP (vinfo));
4600 78 : SLP_TREE_CHILDREN (phis).quick_push (NULL);
4601 78 : SLP_TREE_CHILDREN (phis).quick_push (NULL);
4602 78 : SLP_TREE_CHILDREN (phis)[le->dest_idx] = reduc;
4603 78 : SLP_TREE_REF_COUNT (reduc)++;
4604 :
4605 : /* Create a new SLP instance. */
4606 78 : slp_instance new_instance = XNEW (class _slp_instance);
4607 78 : SLP_INSTANCE_TREE (new_instance) = reduc;
4608 78 : SLP_INSTANCE_LOADS (new_instance) = vNULL;
4609 78 : SLP_INSTANCE_ROOT_STMTS (new_instance) = vNULL;
4610 78 : SLP_INSTANCE_REMAIN_DEFS (new_instance) = vNULL;
4611 78 : SLP_INSTANCE_KIND (new_instance) = slp_inst_kind_reduc_chain;
4612 78 : new_instance->reduc_phis = NULL;
4613 78 : new_instance->cost_vec = vNULL;
4614 78 : new_instance->subgraph_entries = vNULL;
4615 :
4616 78 : vinfo->slp_instances.safe_push (new_instance);
4617 :
4618 78 : if (dump_enabled_p ())
4619 : {
4620 24 : dump_printf_loc (MSG_NOTE, vect_location,
4621 : "Final SLP tree for instance %p:\n",
4622 : (void *) new_instance);
4623 24 : vect_print_slp_graph (MSG_NOTE, vect_location,
4624 : SLP_INSTANCE_TREE (new_instance));
4625 : }
4626 :
4627 : return true;
4628 57313 : }
4629 :
4630 13371 : if (scalar_stmts.length () <= 1)
4631 : {
4632 10748 : scalar_stmts.release ();
4633 10748 : return false;
4634 : }
4635 :
4636 2623 : scalar_stmts.reverse ();
4637 2623 : stmt_vec_info reduc_phi_info = next_stmt;
4638 :
4639 : /* Build the tree for the SLP instance. */
4640 2623 : vec<stmt_vec_info> root_stmt_infos = vNULL;
4641 2623 : vec<tree> remain = vNULL;
4642 :
4643 2623 : if (dump_enabled_p ())
4644 : {
4645 196 : dump_printf_loc (MSG_NOTE, vect_location,
4646 : "Starting SLP discovery of reduction chain for\n");
4647 1038 : for (unsigned i = 0; i < scalar_stmts.length (); ++i)
4648 1684 : dump_printf_loc (MSG_NOTE, vect_location,
4649 842 : " %G", scalar_stmts[i]->stmt);
4650 : }
4651 :
4652 : /* Build the tree for the SLP instance. */
4653 2623 : unsigned int group_size = scalar_stmts.length ();
4654 2623 : bool *matches = XALLOCAVEC (bool, group_size);
4655 2623 : unsigned tree_size = 0;
4656 :
4657 : /* ??? We need this only for SLP discovery. */
4658 10237 : for (unsigned i = 0; i < scalar_stmts.length (); ++i)
4659 7614 : REDUC_GROUP_FIRST_ELEMENT (scalar_stmts[i]) = scalar_stmts[0];
4660 :
4661 2623 : slp_tree node = vect_build_slp_tree (vinfo, scalar_stmts, matches, limit,
4662 2623 : &tree_size, bst_map);
4663 :
4664 10237 : for (unsigned i = 0; i < scalar_stmts.length (); ++i)
4665 7614 : REDUC_GROUP_FIRST_ELEMENT (scalar_stmts[i]) = NULL;
4666 :
4667 2623 : if (node != NULL)
4668 : {
4669 : /* Create a new SLP instance. */
4670 2339 : slp_instance new_instance = XNEW (class _slp_instance);
4671 2339 : SLP_INSTANCE_TREE (new_instance) = node;
4672 2339 : SLP_INSTANCE_LOADS (new_instance) = vNULL;
4673 2339 : SLP_INSTANCE_ROOT_STMTS (new_instance) = root_stmt_infos;
4674 2339 : SLP_INSTANCE_REMAIN_DEFS (new_instance) = remain;
4675 2339 : SLP_INSTANCE_KIND (new_instance) = slp_inst_kind_reduc_chain;
4676 2339 : new_instance->reduc_phis = NULL;
4677 2339 : new_instance->cost_vec = vNULL;
4678 2339 : new_instance->subgraph_entries = vNULL;
4679 :
4680 2339 : vect_reduc_info reduc_info = info_for_reduction (vinfo, node);
4681 2339 : reduc_info->is_reduc_chain = true;
4682 :
4683 2339 : if (dump_enabled_p ())
4684 147 : dump_printf_loc (MSG_NOTE, vect_location,
4685 : "SLP size %u vs. limit %u.\n",
4686 : tree_size, max_tree_size);
4687 :
4688 : /* Fixup SLP reduction chains. If this is a reduction chain with
4689 : a conversion in front amend the SLP tree with a node for that. */
4690 2339 : gimple *scalar_def = STMT_VINFO_REDUC_DEF (reduc_phi_info)->stmt;
4691 2339 : if (is_gimple_assign (scalar_def)
4692 2339 : && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (scalar_def)))
4693 : {
4694 43 : stmt_vec_info conv_info = vect_stmt_to_vectorize
4695 43 : (STMT_VINFO_REDUC_DEF (reduc_phi_info));
4696 43 : scalar_stmts = vNULL;
4697 43 : scalar_stmts.create (group_size);
4698 178 : for (unsigned i = 0; i < group_size; ++i)
4699 92 : scalar_stmts.quick_push (conv_info);
4700 43 : slp_tree conv = vect_create_new_slp_node (scalar_stmts, 1);
4701 43 : SLP_TREE_VECTYPE (conv)
4702 43 : = get_vectype_for_scalar_type (vinfo,
4703 43 : TREE_TYPE
4704 : (gimple_assign_lhs (scalar_def)),
4705 : group_size);
4706 43 : SLP_TREE_REDUC_IDX (conv) = 0;
4707 43 : conv->cycle_info.id = node->cycle_info.id;
4708 43 : SLP_TREE_CHILDREN (conv).quick_push (node);
4709 43 : SLP_INSTANCE_TREE (new_instance) = conv;
4710 : }
4711 : /* Fill the backedge child of the PHI SLP node. The
4712 : general matching code cannot find it because the
4713 : scalar code does not reflect how we vectorize the
4714 : reduction. */
4715 2339 : use_operand_p use_p;
4716 2339 : imm_use_iterator imm_iter;
4717 2339 : class loop *loop = LOOP_VINFO_LOOP (vinfo);
4718 8896 : FOR_EACH_IMM_USE_FAST (use_p, imm_iter,
4719 : gimple_get_lhs (scalar_def))
4720 : /* There are exactly two non-debug uses, the reduction
4721 : PHI and the loop-closed PHI node. */
4722 6557 : if (!is_gimple_debug (USE_STMT (use_p))
4723 6557 : && gimple_bb (USE_STMT (use_p)) == loop->header)
4724 : {
4725 2339 : auto_vec<stmt_vec_info, 64> phis (group_size);
4726 2339 : stmt_vec_info phi_info = vinfo->lookup_stmt (USE_STMT (use_p));
4727 9223 : for (unsigned i = 0; i < group_size; ++i)
4728 6884 : phis.quick_push (phi_info);
4729 2339 : slp_tree *phi_node = bst_map->get (phis);
4730 2339 : unsigned dest_idx = loop_latch_edge (loop)->dest_idx;
4731 4678 : SLP_TREE_CHILDREN (*phi_node)[dest_idx]
4732 2339 : = SLP_INSTANCE_TREE (new_instance);
4733 2339 : SLP_INSTANCE_TREE (new_instance)->refcnt++;
4734 2339 : }
4735 :
4736 2339 : vinfo->slp_instances.safe_push (new_instance);
4737 :
4738 : /* ??? We've replaced the old SLP_INSTANCE_GROUP_SIZE with
4739 : the number of SLP lanes of the root in a few places.
4740 : Verify that assumption holds. */
4741 2339 : gcc_assert (SLP_TREE_LANES (SLP_INSTANCE_TREE (new_instance))
4742 : == group_size);
4743 :
4744 2339 : if (dump_enabled_p ())
4745 : {
4746 147 : dump_printf_loc (MSG_NOTE, vect_location,
4747 : "Final SLP tree for instance %p:\n",
4748 : (void *) new_instance);
4749 147 : vect_print_slp_graph (MSG_NOTE, vect_location,
4750 : SLP_INSTANCE_TREE (new_instance));
4751 : }
4752 :
4753 2339 : return true;
4754 : }
4755 :
4756 : /* Failed to SLP. */
4757 284 : scalar_stmts.release ();
4758 284 : if (dump_enabled_p ())
4759 49 : dump_printf_loc (MSG_NOTE, vect_location,
4760 : "SLP discovery of reduction chain failed\n");
4761 : return false;
4762 : }
4763 :
4764 : /* Analyze an SLP instance starting from SCALAR_STMTS which are a group
4765 : of KIND. Return true if successful. */
4766 :
4767 : static bool
4768 100306 : vect_analyze_slp_reduction (loop_vec_info vinfo,
4769 : stmt_vec_info scalar_stmt,
4770 : unsigned max_tree_size, unsigned *limit,
4771 : scalar_stmts_to_slp_tree_map_t *bst_map,
4772 : bool force_single_lane)
4773 : {
4774 100306 : slp_instance_kind kind = slp_inst_kind_reduc_group;
4775 :
4776 : /* Try to gather a reduction chain. Only attempt if there's budget left
4777 : since chain analysis may build multi-lane trees that consume limit. */
4778 100306 : if (! force_single_lane
4779 73697 : && *limit != 0
4780 73697 : && STMT_VINFO_DEF_TYPE (scalar_stmt) == vect_reduction_def
4781 173718 : && vect_analyze_slp_reduc_chain (vinfo, bst_map, scalar_stmt,
4782 : max_tree_size, limit))
4783 : return true;
4784 :
4785 97889 : vec<stmt_vec_info> scalar_stmts;
4786 97889 : scalar_stmts.create (1);
4787 97889 : scalar_stmts.quick_push (scalar_stmt);
4788 :
4789 97889 : if (dump_enabled_p ())
4790 : {
4791 3904 : dump_printf_loc (MSG_NOTE, vect_location,
4792 : "Starting SLP discovery for\n");
4793 7808 : for (unsigned i = 0; i < scalar_stmts.length (); ++i)
4794 7808 : dump_printf_loc (MSG_NOTE, vect_location,
4795 3904 : " %G", scalar_stmts[i]->stmt);
4796 : }
4797 :
4798 : /* Build the tree for the SLP instance. */
4799 97889 : unsigned int group_size = scalar_stmts.length ();
4800 97889 : bool *matches = XALLOCAVEC (bool, group_size);
4801 97889 : unsigned tree_size = 0;
4802 :
4803 97889 : slp_tree node = vect_build_slp_tree (vinfo, scalar_stmts, matches, limit,
4804 : &tree_size, bst_map);
4805 97889 : if (node != NULL)
4806 : {
4807 : /* Create a new SLP instance. */
4808 95989 : slp_instance new_instance = XNEW (class _slp_instance);
4809 95989 : SLP_INSTANCE_TREE (new_instance) = node;
4810 95989 : SLP_INSTANCE_LOADS (new_instance) = vNULL;
4811 95989 : SLP_INSTANCE_ROOT_STMTS (new_instance) = vNULL;
4812 95989 : SLP_INSTANCE_REMAIN_DEFS (new_instance) = vNULL;
4813 95989 : SLP_INSTANCE_KIND (new_instance) = kind;
4814 95989 : new_instance->reduc_phis = NULL;
4815 95989 : new_instance->cost_vec = vNULL;
4816 95989 : new_instance->subgraph_entries = vNULL;
4817 :
4818 95989 : if (dump_enabled_p ())
4819 3823 : dump_printf_loc (MSG_NOTE, vect_location,
4820 : "SLP size %u vs. limit %u.\n",
4821 : tree_size, max_tree_size);
4822 :
4823 95989 : vinfo->slp_instances.safe_push (new_instance);
4824 :
4825 : /* ??? We've replaced the old SLP_INSTANCE_GROUP_SIZE with
4826 : the number of SLP lanes of the root in a few places.
4827 : Verify that assumption holds. */
4828 95989 : gcc_assert (SLP_TREE_LANES (SLP_INSTANCE_TREE (new_instance))
4829 : == group_size);
4830 :
4831 95989 : if (dump_enabled_p ())
4832 : {
4833 3823 : dump_printf_loc (MSG_NOTE, vect_location,
4834 : "Final SLP tree for instance %p:\n",
4835 : (void *) new_instance);
4836 3823 : vect_print_slp_graph (MSG_NOTE, vect_location,
4837 : SLP_INSTANCE_TREE (new_instance));
4838 : }
4839 :
4840 95989 : return true;
4841 : }
4842 : /* Failed to SLP. */
4843 :
4844 : /* Free the allocated memory. */
4845 1900 : scalar_stmts.release ();
4846 :
4847 : /* Failed to SLP. */
4848 1900 : if (dump_enabled_p ())
4849 81 : dump_printf_loc (MSG_NOTE, vect_location, "SLP discovery failed\n");
4850 : return false;
4851 : }
4852 :
4853 : /* Analyze a single SLP reduction group. If successful add a SLP instance
4854 : for it and return true, otherwise return false and have *MATCHES
4855 : populated. */
4856 :
4857 : static bool
4858 24238 : vect_analyze_slp_reduction_group (loop_vec_info loop_vinfo,
4859 : vec<stmt_vec_info> scalar_stmts,
4860 : scalar_stmts_to_slp_tree_map_t *bst_map,
4861 : unsigned max_tree_size, unsigned *limit,
4862 : bool *matches)
4863 : {
4864 : /* Try to form a reduction group. Size-1 groups are not suitable
4865 : for SLP reduction and should fall back to single-lane reduction. */
4866 24238 : unsigned int group_size = scalar_stmts.length ();
4867 24238 : if (group_size <= 1)
4868 : return false;
4869 17511 : if (!matches)
4870 4550 : matches = XALLOCAVEC (bool, group_size);
4871 17511 : unsigned tree_size = 0;
4872 17511 : slp_tree node = vect_build_slp_tree (loop_vinfo, scalar_stmts, matches, limit,
4873 : &tree_size, bst_map);
4874 17511 : if (!node)
4875 : return false;
4876 :
4877 : /* Create a new SLP instance. */
4878 2756 : slp_instance new_instance = XNEW (class _slp_instance);
4879 2756 : SLP_INSTANCE_TREE (new_instance) = node;
4880 2756 : SLP_INSTANCE_LOADS (new_instance) = vNULL;
4881 2756 : SLP_INSTANCE_ROOT_STMTS (new_instance) = vNULL;
4882 2756 : SLP_INSTANCE_REMAIN_DEFS (new_instance) = vNULL;
4883 2756 : SLP_INSTANCE_KIND (new_instance) = slp_inst_kind_reduc_group;
4884 2756 : new_instance->reduc_phis = NULL;
4885 2756 : new_instance->cost_vec = vNULL;
4886 2756 : new_instance->subgraph_entries = vNULL;
4887 :
4888 2756 : if (dump_enabled_p ())
4889 203 : dump_printf_loc (MSG_NOTE, vect_location,
4890 : "SLP size %u vs. limit %u.\n",
4891 : tree_size, max_tree_size);
4892 :
4893 2756 : loop_vinfo->slp_instances.safe_push (new_instance);
4894 :
4895 : /* ??? We've replaced the old SLP_INSTANCE_GROUP_SIZE with
4896 : the number of SLP lanes of the root in a few places.
4897 : Verify that assumption holds. */
4898 2756 : gcc_assert (SLP_TREE_LANES (SLP_INSTANCE_TREE (new_instance))
4899 : == group_size);
4900 :
4901 2756 : if (dump_enabled_p ())
4902 : {
4903 203 : dump_printf_loc (MSG_NOTE, vect_location,
4904 : "SLP discovery of size %d reduction group "
4905 : "succeeded\n", group_size);
4906 203 : dump_printf_loc (MSG_NOTE, vect_location,
4907 : "Final SLP tree for instance %p:\n",
4908 : (void *) new_instance);
4909 203 : vect_print_slp_graph (MSG_NOTE, vect_location,
4910 : SLP_INSTANCE_TREE (new_instance));
4911 : }
4912 :
4913 : return true;
4914 : }
4915 :
4916 : /* Analyze reductions in LOOP_VINFO and populate SLP instances
4917 : accordingly. Returns false if something fails. */
4918 :
4919 : static bool
4920 514644 : vect_analyze_slp_reductions (loop_vec_info loop_vinfo,
4921 : unsigned max_tree_size, unsigned *limit,
4922 : scalar_stmts_to_slp_tree_map_t *bst_map,
4923 : bool force_single_lane)
4924 : {
4925 514644 : if (loop_vinfo->reductions.is_empty ())
4926 : return true;
4927 :
4928 : /* Collect reduction statements we can combine into
4929 : a SLP reduction. */
4930 74456 : vec<stmt_vec_info> scalar_stmts;
4931 74456 : scalar_stmts.create (loop_vinfo->reductions.length ());
4932 330054 : for (auto next_info : loop_vinfo->reductions)
4933 : {
4934 106686 : next_info = vect_stmt_to_vectorize (next_info);
4935 106686 : if ((STMT_VINFO_RELEVANT_P (next_info)
4936 14 : || STMT_VINFO_LIVE_P (next_info))
4937 : /* ??? Make sure we didn't skip a conversion around a
4938 : reduction path. In that case we'd have to reverse
4939 : engineer that conversion stmt following the chain using
4940 : reduc_idx and from the PHI using reduc_def. */
4941 106672 : && (STMT_VINFO_DEF_TYPE (next_info) == vect_reduction_def
4942 106672 : || (STMT_VINFO_DEF_TYPE (next_info)
4943 : == vect_double_reduction_def)))
4944 : {
4945 : /* Do not discover SLP reductions combining lane-reducing
4946 : ops, that will fail later. */
4947 106672 : if (!force_single_lane
4948 106672 : && !lane_reducing_stmt_p (STMT_VINFO_STMT (next_info)))
4949 79366 : scalar_stmts.quick_push (next_info);
4950 : /* Do SLP discovery for single-lane reductions. */
4951 27306 : else if (! vect_analyze_slp_reduction (loop_vinfo, next_info,
4952 : max_tree_size, limit,
4953 : bst_map,
4954 : force_single_lane))
4955 : {
4956 0 : scalar_stmts.release ();
4957 0 : return false;
4958 : }
4959 : }
4960 : }
4961 :
4962 74456 : if (scalar_stmts.length () > 1)
4963 : {
4964 : /* Try to form a reduction group. */
4965 4660 : unsigned int group_size = scalar_stmts.length ();
4966 4660 : bool *matches = XALLOCAVEC (bool, group_size);
4967 4660 : if (vect_analyze_slp_reduction_group (loop_vinfo, scalar_stmts, bst_map,
4968 : max_tree_size, limit, matches))
4969 1571 : return true;
4970 :
4971 : /* When analysis as a single SLP reduction group failed try to
4972 : form sub-groups by collecting matching lanes. Do not recurse
4973 : that on failure (to limit compile-time costs), but recurse
4974 : for the initial non-matching parts. Everything not covered
4975 : by a sub-group gets single-reduction treatment. */
4976 3541 : vec<stmt_vec_info> cands = vNULL;
4977 11412 : while (matches[0])
4978 : {
4979 11277 : cands.truncate (0);
4980 11277 : cands.reserve (group_size, true);
4981 99784 : for (unsigned i = 0; i < group_size; ++i)
4982 77230 : if (matches[i])
4983 19610 : cands.quick_push (scalar_stmts[i]);
4984 :
4985 : /* Try to form a reduction group. */
4986 11277 : if (vect_analyze_slp_reduction_group (loop_vinfo, cands, bst_map,
4987 : max_tree_size, limit, NULL))
4988 1207 : cands = vNULL;
4989 : else
4990 : {
4991 : /* Do SLP discovery for single-lane reductions. */
4992 47356 : for (auto stmt_info : cands)
4993 17168 : if (! vect_analyze_slp_reduction (loop_vinfo,
4994 : vect_stmt_to_vectorize
4995 : (stmt_info),
4996 : max_tree_size, limit,
4997 : bst_map, force_single_lane))
4998 : {
4999 22 : scalar_stmts.release ();
5000 22 : cands.release ();
5001 22 : return false;
5002 : }
5003 : }
5004 : /* Remove the handled stmts from scalar_stmts and try again,
5005 : possibly repeating the above with updated matches[]. */
5006 11255 : unsigned j = 0;
5007 88423 : for (unsigned i = 0; i < group_size; ++i)
5008 77168 : if (!matches[i])
5009 : {
5010 57593 : scalar_stmts[j] = scalar_stmts[i];
5011 57593 : ++j;
5012 : }
5013 11255 : scalar_stmts.truncate (j);
5014 11390 : group_size = scalar_stmts.length ();
5015 11255 : if (group_size <= 1)
5016 : break;
5017 8301 : if (vect_analyze_slp_reduction_group (loop_vinfo, scalar_stmts,
5018 : bst_map, max_tree_size, limit,
5019 : matches))
5020 : return true;
5021 : }
5022 : }
5023 : /* Do SLP discovery for single-lane reductions. */
5024 272609 : for (auto stmt_info : scalar_stmts)
5025 55832 : if (! vect_analyze_slp_reduction (loop_vinfo,
5026 : vect_stmt_to_vectorize (stmt_info),
5027 : max_tree_size, limit,
5028 : bst_map, force_single_lane))
5029 : {
5030 1878 : scalar_stmts.release ();
5031 1878 : return false;
5032 : }
5033 :
5034 71007 : scalar_stmts.release ();
5035 71007 : return true;
5036 : }
5037 :
5038 : /* Analyze an SLP instance starting from a group of grouped stores. Call
5039 : vect_build_slp_tree to build a tree of packed stmts if possible.
5040 : Return FALSE if it's impossible to SLP any stmt in the group. */
5041 :
5042 : static bool
5043 1125000 : vect_analyze_slp_instance (vec_info *vinfo,
5044 : scalar_stmts_to_slp_tree_map_t *bst_map,
5045 : stmt_vec_info stmt_info,
5046 : slp_instance_kind kind,
5047 : unsigned max_tree_size, unsigned *limit,
5048 : bool force_single_lane)
5049 : {
5050 1125000 : vec<stmt_vec_info> scalar_stmts;
5051 :
5052 1125000 : if (is_a <bb_vec_info> (vinfo))
5053 1094816 : vect_location = stmt_info->stmt;
5054 :
5055 1125000 : gcc_assert (kind == slp_inst_kind_store);
5056 :
5057 : /* Collect the stores and store them in scalar_stmts. */
5058 1125000 : scalar_stmts.create (DR_GROUP_SIZE (stmt_info));
5059 1125000 : stmt_vec_info next_info = stmt_info;
5060 5595552 : while (next_info)
5061 : {
5062 3345552 : scalar_stmts.quick_push (vect_stmt_to_vectorize (next_info));
5063 3345552 : next_info = DR_GROUP_NEXT_ELEMENT (next_info);
5064 : }
5065 :
5066 1125000 : vec<stmt_vec_info> root_stmt_infos = vNULL;
5067 1125000 : vec<tree> remain = vNULL;
5068 :
5069 : /* Build the tree for the SLP instance. */
5070 :
5071 : /* If there's no budget left bail out early. */
5072 1125000 : if (*limit == 0)
5073 : return false;
5074 :
5075 1124980 : if (dump_enabled_p ())
5076 : {
5077 4183 : dump_printf_loc (MSG_NOTE, vect_location,
5078 : "Starting SLP discovery for\n");
5079 24392 : for (unsigned i = 0; i < scalar_stmts.length (); ++i)
5080 40418 : dump_printf_loc (MSG_NOTE, vect_location,
5081 20209 : " %G", scalar_stmts[i]->stmt);
5082 : }
5083 :
5084 : /* Build the tree for the SLP instance. */
5085 1124980 : unsigned int group_size = scalar_stmts.length ();
5086 1124980 : bool *matches = XALLOCAVEC (bool, group_size);
5087 1124980 : unsigned tree_size = 0;
5088 1124980 : unsigned i;
5089 :
5090 1124980 : slp_tree node = NULL;
5091 1124980 : if (group_size > 1 && force_single_lane)
5092 : {
5093 1774 : matches[0] = true;
5094 1774 : matches[1] = false;
5095 : }
5096 : else
5097 1123206 : node = vect_build_slp_tree (vinfo, scalar_stmts, matches, limit,
5098 : &tree_size, bst_map);
5099 1124980 : if (node != NULL)
5100 : {
5101 : /* Create a new SLP instance. */
5102 697140 : slp_instance new_instance = XNEW (class _slp_instance);
5103 697140 : SLP_INSTANCE_TREE (new_instance) = node;
5104 697140 : SLP_INSTANCE_LOADS (new_instance) = vNULL;
5105 697140 : SLP_INSTANCE_ROOT_STMTS (new_instance) = root_stmt_infos;
5106 697140 : SLP_INSTANCE_REMAIN_DEFS (new_instance) = remain;
5107 697140 : SLP_INSTANCE_KIND (new_instance) = kind;
5108 697140 : new_instance->reduc_phis = NULL;
5109 697140 : new_instance->cost_vec = vNULL;
5110 697140 : new_instance->subgraph_entries = vNULL;
5111 :
5112 697140 : if (dump_enabled_p ())
5113 3166 : dump_printf_loc (MSG_NOTE, vect_location,
5114 : "SLP size %u vs. limit %u.\n",
5115 : tree_size, max_tree_size);
5116 :
5117 697140 : vinfo->slp_instances.safe_push (new_instance);
5118 :
5119 : /* ??? We've replaced the old SLP_INSTANCE_GROUP_SIZE with
5120 : the number of SLP lanes of the root in a few places.
5121 : Verify that assumption holds. */
5122 697140 : gcc_assert (SLP_TREE_LANES (SLP_INSTANCE_TREE (new_instance))
5123 : == group_size);
5124 :
5125 697140 : if (dump_enabled_p ())
5126 : {
5127 3166 : dump_printf_loc (MSG_NOTE, vect_location,
5128 : "Final SLP tree for instance %p:\n",
5129 : (void *) new_instance);
5130 3166 : vect_print_slp_graph (MSG_NOTE, vect_location,
5131 : SLP_INSTANCE_TREE (new_instance));
5132 : }
5133 697140 : return true;
5134 : }
5135 : /* Failed to SLP. */
5136 :
5137 : /* Try to break the group up into pieces. */
5138 427840 : if (*limit > 0 && kind == slp_inst_kind_store)
5139 : {
5140 : /* ??? We could delay all the actual splitting of store-groups
5141 : until after SLP discovery of the original group completed.
5142 : Then we can recurse to vect_build_slp_instance directly. */
5143 1119999 : for (i = 0; i < group_size; i++)
5144 1119999 : if (!matches[i])
5145 : break;
5146 :
5147 : /* For basic block SLP, try to break the group up into multiples of
5148 : a vector size. */
5149 427839 : if (is_a <bb_vec_info> (vinfo)
5150 427839 : && (i > 1 && i < group_size))
5151 : {
5152 : /* Free the allocated memory. */
5153 160826 : scalar_stmts.release ();
5154 :
5155 160826 : tree scalar_type
5156 160826 : = TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));
5157 321652 : tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
5158 160826 : 1 << floor_log2 (i));
5159 160826 : unsigned HOST_WIDE_INT const_nunits;
5160 160826 : if (vectype
5161 160826 : && TYPE_VECTOR_SUBPARTS (vectype).is_constant (&const_nunits))
5162 : {
5163 : /* Split into two groups at the first vector boundary. */
5164 160826 : gcc_assert ((const_nunits & (const_nunits - 1)) == 0);
5165 160826 : unsigned group1_size = i & ~(const_nunits - 1);
5166 :
5167 160826 : if (dump_enabled_p ())
5168 70 : dump_printf_loc (MSG_NOTE, vect_location,
5169 : "Splitting SLP group at stmt %u\n", i);
5170 160826 : stmt_vec_info rest = vect_split_slp_store_group (stmt_info,
5171 : group1_size);
5172 160826 : bool res = vect_analyze_slp_instance (vinfo, bst_map, stmt_info,
5173 : kind, max_tree_size,
5174 : limit, false);
5175 : /* Split the rest at the failure point and possibly
5176 : re-analyze the remaining matching part if it has
5177 : at least two lanes. */
5178 160826 : if (group1_size < i
5179 5715 : && (i + 1 < group_size
5180 3112 : || i - group1_size > 1))
5181 : {
5182 2631 : stmt_vec_info rest2 = rest;
5183 2631 : rest = vect_split_slp_store_group (rest, i - group1_size);
5184 2631 : if (i - group1_size > 1)
5185 57 : res |= vect_analyze_slp_instance (vinfo, bst_map, rest2,
5186 : kind, max_tree_size,
5187 : limit, false);
5188 : }
5189 : /* Re-analyze the non-matching tail if it has at least
5190 : two lanes. */
5191 160826 : if (i + 1 < group_size)
5192 22872 : res |= vect_analyze_slp_instance (vinfo, bst_map,
5193 : rest, kind, max_tree_size,
5194 : limit, false);
5195 1125000 : return res;
5196 : }
5197 : }
5198 :
5199 : /* For loop vectorization split the RHS into arbitrary pieces of
5200 : size >= 1. */
5201 267013 : else if (is_a <loop_vec_info> (vinfo)
5202 267013 : && (group_size != 1 && i < group_size))
5203 : {
5204 8377 : gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
5205 28 : bool masked_p = call
5206 28 : && gimple_call_internal_p (call)
5207 28 : && internal_fn_mask_index (gimple_call_internal_fn (call)) != -1;
5208 : /* There are targets that cannot do even/odd interleaving schemes
5209 : so they absolutely need to use load/store-lanes. For now
5210 : force single-lane SLP for them - they would be happy with
5211 : uniform power-of-two lanes (but depending on element size),
5212 : but even if we can use 'i' as indicator we would need to
5213 : backtrack when later lanes fail to discover with the same
5214 : granularity. We cannot turn any of strided or scatter store
5215 : into store-lanes. */
5216 : /* ??? If this is not in sync with what get_load_store_type
5217 : later decides the SLP representation is not good for other
5218 : store vectorization methods. */
5219 8377 : bool want_store_lanes
5220 8377 : = (! STMT_VINFO_GATHER_SCATTER_P (stmt_info)
5221 8377 : && ! STMT_VINFO_STRIDED_P (stmt_info)
5222 6265 : && ! STMT_VINFO_SLP_VECT_ONLY (stmt_info)
5223 6261 : && compare_step_with_zero (vinfo, stmt_info) > 0
5224 14533 : && vect_slp_prefer_store_lanes_p (vinfo, stmt_info, NULL_TREE,
5225 16754 : masked_p, group_size, i));
5226 8377 : if (want_store_lanes || force_single_lane)
5227 : i = 1;
5228 :
5229 : /* A fatal discovery fail doesn't always mean single-lane SLP
5230 : isn't a possibility, so try. */
5231 6603 : if (i == 0)
5232 : i = 1;
5233 :
5234 8377 : if (dump_enabled_p ())
5235 891 : dump_printf_loc (MSG_NOTE, vect_location,
5236 : "Splitting SLP group at stmt %u\n", i);
5237 :
5238 : /* Analyze the stored values and pinch them together with
5239 : a permute node so we can preserve the whole store group. */
5240 8377 : auto_vec<slp_tree> rhs_nodes;
5241 :
5242 8377 : unsigned int rhs_common_nlanes = 0;
5243 8377 : unsigned int start = 0, end = i;
5244 37923 : while (start < group_size)
5245 : {
5246 29664 : gcc_assert (end - start >= 1);
5247 29664 : vec<stmt_vec_info> substmts;
5248 29664 : substmts.create (end - start);
5249 121529 : for (unsigned j = start; j < end; ++j)
5250 62201 : substmts.quick_push (scalar_stmts[j]);
5251 29664 : node = vect_build_slp_tree (vinfo, substmts,
5252 : matches, limit, &tree_size, bst_map);
5253 29664 : if (node)
5254 : {
5255 23857 : rhs_nodes.safe_push (node);
5256 23857 : if (start == 0)
5257 8259 : rhs_common_nlanes = SLP_TREE_LANES (node);
5258 15598 : else if (rhs_common_nlanes != SLP_TREE_LANES (node))
5259 1413 : rhs_common_nlanes = 0;
5260 23857 : start = end;
5261 23857 : if (want_store_lanes || force_single_lane)
5262 5327 : end = start + 1;
5263 : else
5264 : end = group_size;
5265 : }
5266 : else
5267 : {
5268 5807 : substmts.release ();
5269 5807 : if (end - start == 1)
5270 : {
5271 : /* Single-lane discovery failed. Free resources. */
5272 118 : for (auto node : rhs_nodes)
5273 0 : vect_free_slp_tree (node);
5274 118 : scalar_stmts.release ();
5275 118 : if (dump_enabled_p ())
5276 17 : dump_printf_loc (MSG_NOTE, vect_location,
5277 : "SLP discovery failed\n");
5278 118 : return false;
5279 : }
5280 :
5281 : /* ??? It really happens that we soft-fail SLP
5282 : build at a mismatch but the matching part hard-fails
5283 : later. As we know we arrived here with a group
5284 : larger than one try a group of size one! */
5285 5689 : if (!matches[0])
5286 12 : end = start + 1;
5287 : else
5288 12459 : for (unsigned j = start; j < end; j++)
5289 12459 : if (!matches[j - start])
5290 : {
5291 : end = j;
5292 : break;
5293 : }
5294 : }
5295 : }
5296 :
5297 : /* Now re-assess whether we want store lanes in case the
5298 : discovery ended up producing all single-lane RHSs. */
5299 8259 : if (! want_store_lanes
5300 8259 : && rhs_common_nlanes == 1
5301 7179 : && ! STMT_VINFO_GATHER_SCATTER_P (stmt_info)
5302 7179 : && ! STMT_VINFO_STRIDED_P (stmt_info)
5303 5441 : && ! STMT_VINFO_SLP_VECT_ONLY (stmt_info)
5304 5438 : && compare_step_with_zero (vinfo, stmt_info) > 0
5305 13610 : && (vect_store_lanes_supported (SLP_TREE_VECTYPE (rhs_nodes[0]),
5306 : group_size, masked_p)
5307 : != IFN_LAST))
5308 : want_store_lanes = true;
5309 :
5310 : /* Now we assume we can build the root SLP node from all stores. */
5311 8259 : if (want_store_lanes)
5312 : {
5313 : /* For store-lanes feed the store node with all RHS nodes
5314 : in order. */
5315 0 : node = vect_create_new_slp_node (scalar_stmts,
5316 0 : SLP_TREE_CHILDREN
5317 : (rhs_nodes[0]).length ());
5318 0 : SLP_TREE_VECTYPE (node) = SLP_TREE_VECTYPE (rhs_nodes[0]);
5319 0 : node->ldst_lanes = true;
5320 0 : SLP_TREE_CHILDREN (node)
5321 0 : .reserve_exact (SLP_TREE_CHILDREN (rhs_nodes[0]).length ()
5322 0 : + rhs_nodes.length () - 1);
5323 : /* First store value and possibly mask. */
5324 0 : SLP_TREE_CHILDREN (node)
5325 0 : .splice (SLP_TREE_CHILDREN (rhs_nodes[0]));
5326 : /* Rest of the store values. All mask nodes are the same,
5327 : this should be guaranteed by dataref group discovery. */
5328 0 : for (unsigned j = 1; j < rhs_nodes.length (); ++j)
5329 0 : SLP_TREE_CHILDREN (node)
5330 0 : .quick_push (SLP_TREE_CHILDREN (rhs_nodes[j])[0]);
5331 0 : for (slp_tree child : SLP_TREE_CHILDREN (node))
5332 0 : child->refcnt++;
5333 : }
5334 : else
5335 8259 : node = vect_build_slp_store_interleaving (rhs_nodes, scalar_stmts);
5336 :
5337 32116 : while (!rhs_nodes.is_empty ())
5338 23857 : vect_free_slp_tree (rhs_nodes.pop ());
5339 :
5340 : /* Create a new SLP instance. */
5341 8259 : slp_instance new_instance = XNEW (class _slp_instance);
5342 8259 : SLP_INSTANCE_TREE (new_instance) = node;
5343 8259 : SLP_INSTANCE_LOADS (new_instance) = vNULL;
5344 8259 : SLP_INSTANCE_ROOT_STMTS (new_instance) = root_stmt_infos;
5345 8259 : SLP_INSTANCE_REMAIN_DEFS (new_instance) = remain;
5346 8259 : SLP_INSTANCE_KIND (new_instance) = kind;
5347 8259 : new_instance->reduc_phis = NULL;
5348 8259 : new_instance->cost_vec = vNULL;
5349 8259 : new_instance->subgraph_entries = vNULL;
5350 :
5351 8259 : if (dump_enabled_p ())
5352 874 : dump_printf_loc (MSG_NOTE, vect_location,
5353 : "SLP size %u vs. limit %u.\n",
5354 : tree_size, max_tree_size);
5355 :
5356 8259 : vinfo->slp_instances.safe_push (new_instance);
5357 :
5358 : /* ??? We've replaced the old SLP_INSTANCE_GROUP_SIZE with
5359 : the number of SLP lanes of the root in a few places.
5360 : Verify that assumption holds. */
5361 8259 : gcc_assert (SLP_TREE_LANES (SLP_INSTANCE_TREE (new_instance))
5362 : == group_size);
5363 :
5364 8259 : if (dump_enabled_p ())
5365 : {
5366 874 : dump_printf_loc (MSG_NOTE, vect_location,
5367 : "Final SLP tree for instance %p:\n",
5368 : (void *) new_instance);
5369 874 : vect_print_slp_graph (MSG_NOTE, vect_location,
5370 : SLP_INSTANCE_TREE (new_instance));
5371 : }
5372 : return true;
5373 8377 : }
5374 : else
5375 : /* Free the allocated memory. */
5376 258636 : scalar_stmts.release ();
5377 :
5378 : /* Even though the first vector did not all match, we might be able to SLP
5379 : (some) of the remainder. FORNOW ignore this possibility. */
5380 : }
5381 : else
5382 : /* Free the allocated memory. */
5383 1 : scalar_stmts.release ();
5384 :
5385 : /* Failed to SLP. */
5386 258637 : if (dump_enabled_p ())
5387 56 : dump_printf_loc (MSG_NOTE, vect_location, "SLP discovery failed\n");
5388 : return false;
5389 : }
5390 :
5391 : /* qsort comparator ordering SLP load nodes. */
5392 :
5393 : static int
5394 2691208 : vllp_cmp (const void *a_, const void *b_)
5395 : {
5396 2691208 : const slp_tree a = *(const slp_tree *)a_;
5397 2691208 : const slp_tree b = *(const slp_tree *)b_;
5398 2691208 : stmt_vec_info a0 = SLP_TREE_SCALAR_STMTS (a)[0];
5399 2691208 : stmt_vec_info b0 = SLP_TREE_SCALAR_STMTS (b)[0];
5400 2691208 : if (STMT_VINFO_GROUPED_ACCESS (a0)
5401 1545919 : && STMT_VINFO_GROUPED_ACCESS (b0)
5402 4175059 : && DR_GROUP_FIRST_ELEMENT (a0) == DR_GROUP_FIRST_ELEMENT (b0))
5403 : {
5404 : /* Same group, order after lanes used. */
5405 348323 : if (SLP_TREE_LANES (a) < SLP_TREE_LANES (b))
5406 : return 1;
5407 339350 : else if (SLP_TREE_LANES (a) > SLP_TREE_LANES (b))
5408 : return -1;
5409 : else
5410 : {
5411 : /* Try to order loads using the same lanes together, breaking
5412 : the tie with the lane number that first differs. */
5413 329613 : if (!SLP_TREE_LOAD_PERMUTATION (a).exists ()
5414 329613 : && !SLP_TREE_LOAD_PERMUTATION (b).exists ())
5415 : return 0;
5416 329613 : else if (SLP_TREE_LOAD_PERMUTATION (a).exists ()
5417 329613 : && !SLP_TREE_LOAD_PERMUTATION (b).exists ())
5418 : return 1;
5419 325550 : else if (!SLP_TREE_LOAD_PERMUTATION (a).exists ()
5420 325550 : && SLP_TREE_LOAD_PERMUTATION (b).exists ())
5421 : return -1;
5422 : else
5423 : {
5424 318064 : for (unsigned i = 0; i < SLP_TREE_LANES (a); ++i)
5425 318064 : if (SLP_TREE_LOAD_PERMUTATION (a)[i]
5426 318064 : != SLP_TREE_LOAD_PERMUTATION (b)[i])
5427 : {
5428 : /* In-order lane first, that's what the above case for
5429 : no permutation does. */
5430 316752 : if (SLP_TREE_LOAD_PERMUTATION (a)[i] == i)
5431 : return -1;
5432 194195 : else if (SLP_TREE_LOAD_PERMUTATION (b)[i] == i)
5433 : return 1;
5434 102102 : else if (SLP_TREE_LOAD_PERMUTATION (a)[i]
5435 102102 : < SLP_TREE_LOAD_PERMUTATION (b)[i])
5436 : return -1;
5437 : else
5438 38096 : return 1;
5439 : }
5440 : return 0;
5441 : }
5442 : }
5443 : }
5444 : else /* Different groups or non-groups. */
5445 : {
5446 : /* Order groups as their first element to keep them together. */
5447 2342885 : if (STMT_VINFO_GROUPED_ACCESS (a0))
5448 2342885 : a0 = DR_GROUP_FIRST_ELEMENT (a0);
5449 2342885 : if (STMT_VINFO_GROUPED_ACCESS (b0))
5450 2342885 : b0 = DR_GROUP_FIRST_ELEMENT (b0);
5451 2342885 : if (a0 == b0)
5452 : return 0;
5453 : /* Tie using UID. */
5454 2342765 : else if (gimple_uid (STMT_VINFO_STMT (a0))
5455 2342765 : < gimple_uid (STMT_VINFO_STMT (b0)))
5456 : return -1;
5457 : else
5458 : {
5459 1041744 : gcc_assert (gimple_uid (STMT_VINFO_STMT (a0))
5460 : != gimple_uid (STMT_VINFO_STMT (b0)));
5461 : return 1;
5462 : }
5463 : }
5464 : }
5465 :
5466 : /* Return whether if the load permutation of NODE is consecutive starting
5467 : with value START_VAL in the first element. If START_VAL is not given
5468 : the first element's value is used. */
5469 :
5470 : bool
5471 647890 : vect_load_perm_consecutive_p (slp_tree node, unsigned start_val)
5472 : {
5473 647890 : load_permutation_t perm = SLP_TREE_LOAD_PERMUTATION (node);
5474 :
5475 647890 : if (!perm.exists () || !perm.length ())
5476 : return false;
5477 :
5478 647890 : if (start_val == UINT_MAX)
5479 79797 : start_val = perm[0];
5480 :
5481 1279628 : for (unsigned int i = 0; i < perm.length (); i++)
5482 655226 : if (perm[i] != start_val + (unsigned int) i)
5483 : return false;
5484 :
5485 : return true;
5486 : }
5487 :
5488 : /* Process the set of LOADS that are all from the same dataref group. */
5489 :
5490 : static void
5491 161954 : vect_lower_load_permutations (loop_vec_info loop_vinfo,
5492 : scalar_stmts_to_slp_tree_map_t *bst_map,
5493 : const array_slice<slp_tree> &loads,
5494 : bool force_single_lane)
5495 : {
5496 : /* We at this point want to lower without a fixed VF or vector
5497 : size in mind which means we cannot actually compute whether we
5498 : need three or more vectors for a load permutation yet. So always
5499 : lower. */
5500 161954 : stmt_vec_info first
5501 161954 : = DR_GROUP_FIRST_ELEMENT (SLP_TREE_SCALAR_STMTS (loads[0])[0]);
5502 161954 : unsigned group_lanes = DR_GROUP_SIZE (first);
5503 :
5504 : /* Verify if all load permutations can be implemented with a suitably
5505 : large element load-lanes operation. */
5506 161954 : unsigned ld_lanes_lanes = SLP_TREE_LANES (loads[0]);
5507 161954 : if (STMT_VINFO_STRIDED_P (first)
5508 159501 : || compare_step_with_zero (loop_vinfo, first) <= 0
5509 156813 : || exact_log2 (ld_lanes_lanes) == -1
5510 : /* ??? For now only support the single-lane case as there is
5511 : missing support on the store-lane side and code generation
5512 : isn't up to the task yet. */
5513 154002 : || ld_lanes_lanes != 1
5514 304926 : || vect_load_lanes_supported (SLP_TREE_VECTYPE (loads[0]),
5515 : group_lanes / ld_lanes_lanes,
5516 : false) == IFN_LAST)
5517 : ld_lanes_lanes = 0;
5518 : else
5519 : /* Verify the loads access the same number of lanes aligned to
5520 : ld_lanes_lanes. */
5521 0 : for (slp_tree load : loads)
5522 : {
5523 0 : if (SLP_TREE_LANES (load) != ld_lanes_lanes)
5524 : {
5525 : ld_lanes_lanes = 0;
5526 : break;
5527 : }
5528 0 : unsigned first = SLP_TREE_LOAD_PERMUTATION (load)[0];
5529 0 : if (first % ld_lanes_lanes != 0)
5530 : {
5531 : ld_lanes_lanes = 0;
5532 : break;
5533 : }
5534 0 : if (!vect_load_perm_consecutive_p (load))
5535 : {
5536 : ld_lanes_lanes = 0;
5537 : break;
5538 : }
5539 : }
5540 :
5541 : /* Only a power-of-two number of lanes matches interleaving with N levels.
5542 : ??? An even number of lanes could be reduced to 1<<ceil_log2(N)-1 lanes
5543 : at each step. */
5544 262659 : if (ld_lanes_lanes == 0 && exact_log2 (group_lanes) == -1 && group_lanes != 3)
5545 : return;
5546 :
5547 266630 : for (slp_tree load : loads)
5548 : {
5549 : /* Leave masked or gather loads alone for now. */
5550 188168 : if (!SLP_TREE_CHILDREN (load).is_empty ())
5551 61040 : continue;
5552 :
5553 : /* For single-element interleaving spanning multiple vectors avoid
5554 : lowering, we want to use VMAT_ELEMENTWISE later. */
5555 188162 : if (ld_lanes_lanes == 0
5556 188162 : && SLP_TREE_LANES (load) == 1
5557 168676 : && !DR_GROUP_NEXT_ELEMENT (first)
5558 267949 : && maybe_gt (group_lanes,
5559 : TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (load))))
5560 51334 : return;
5561 :
5562 : /* We want to pattern-match special cases here and keep those
5563 : alone. Candidates are splats and load-lane. */
5564 :
5565 : /* We need to lower only loads of less than half of the groups
5566 : lanes, including duplicate lanes. Note this leaves nodes
5567 : with a non-1:1 load permutation around instead of canonicalizing
5568 : those into a load and a permute node. Removing this early
5569 : check would do such canonicalization. */
5570 136828 : if (SLP_TREE_LANES (load) >= (group_lanes + 1) / 2
5571 57464 : && ld_lanes_lanes == 0)
5572 57464 : continue;
5573 :
5574 : /* Build the permute to get the original load permutation order. */
5575 79364 : bool contiguous = vect_load_perm_consecutive_p (load);
5576 79364 : lane_permutation_t final_perm;
5577 79364 : final_perm.create (SLP_TREE_LANES (load));
5578 239036 : for (unsigned i = 0; i < SLP_TREE_LANES (load); ++i)
5579 160616 : final_perm.quick_push (
5580 80308 : std::make_pair (0, SLP_TREE_LOAD_PERMUTATION (load)[i]));
5581 :
5582 : /* When the load permutation accesses a contiguous unpermuted,
5583 : power-of-two aligned and sized chunk leave the load alone.
5584 : We can likely (re-)load it more efficiently rather than
5585 : extracting it from the larger load.
5586 : ??? Long-term some of the lowering should move to where
5587 : the vector types involved are fixed. */
5588 82934 : if (!force_single_lane
5589 79364 : && ld_lanes_lanes == 0
5590 53518 : && contiguous
5591 53258 : && (SLP_TREE_LANES (load) > 1 || loads.size () == 1)
5592 6566 : && pow2p_hwi (SLP_TREE_LANES (load))
5593 6530 : && pow2p_hwi (group_lanes)
5594 3570 : && SLP_TREE_LOAD_PERMUTATION (load)[0] % SLP_TREE_LANES (load) == 0
5595 82934 : && group_lanes % SLP_TREE_LANES (load) == 0)
5596 : {
5597 3570 : final_perm.release ();
5598 3570 : continue;
5599 : }
5600 :
5601 : /* First build (and possibly re-use) a load node for the
5602 : unpermuted group. Gaps in the middle and on the end are
5603 : represented with NULL stmts. */
5604 75794 : vec<stmt_vec_info> stmts;
5605 75794 : stmts.create (group_lanes);
5606 270615 : for (stmt_vec_info s = first; s; s = DR_GROUP_NEXT_ELEMENT (s))
5607 : {
5608 194821 : if (s != first)
5609 124074 : for (unsigned i = 1; i < DR_GROUP_GAP (s); ++i)
5610 5047 : stmts.quick_push (NULL);
5611 194821 : stmts.quick_push (s);
5612 : }
5613 139685 : for (unsigned i = 0; i < DR_GROUP_GAP (first); ++i)
5614 63891 : stmts.quick_push (NULL);
5615 75794 : bool *matches = XALLOCAVEC (bool, group_lanes);
5616 75794 : unsigned limit = 1;
5617 75794 : unsigned tree_size = 0;
5618 75794 : slp_tree l0 = vect_build_slp_tree (loop_vinfo, stmts, matches, &limit,
5619 75794 : &tree_size, bst_map);
5620 75794 : gcc_assert (!SLP_TREE_LOAD_PERMUTATION (l0).exists ());
5621 :
5622 75794 : if (ld_lanes_lanes != 0)
5623 : {
5624 : /* ??? If this is not in sync with what get_load_store_type
5625 : later decides the SLP representation is not good for other
5626 : store vectorization methods. */
5627 0 : l0->ldst_lanes = true;
5628 0 : load->ldst_lanes = true;
5629 : }
5630 :
5631 236080 : while (1)
5632 : {
5633 155937 : unsigned group_lanes = SLP_TREE_LANES (l0);
5634 155937 : if (ld_lanes_lanes != 0
5635 155937 : || SLP_TREE_LANES (load) >= (group_lanes + 1) / 2)
5636 : break;
5637 :
5638 : /* Try to lower by reducing the group to half its size using an
5639 : interleaving scheme. For this try to compute whether all
5640 : elements needed for this load are in even or odd elements of
5641 : an even/odd decomposition with N consecutive elements.
5642 : Thus { e, e, o, o, e, e, o, o } would be an even/odd decomposition
5643 : with N == 2. */
5644 : /* ??? Only an even number of lanes can be handed this way, but the
5645 : fallback below could work for any number. We have to make sure
5646 : to round up in that case. */
5647 80143 : gcc_assert ((group_lanes & 1) == 0 || group_lanes == 3);
5648 12134 : unsigned even = 0, odd = 0;
5649 12134 : if ((group_lanes & 1) == 0)
5650 : {
5651 12134 : even = (1 << ceil_log2 (group_lanes)) - 1;
5652 12134 : odd = even;
5653 49285 : for (auto l : final_perm)
5654 : {
5655 12883 : even &= ~l.second;
5656 12883 : odd &= l.second;
5657 : }
5658 : }
5659 :
5660 : /* Now build an even or odd extraction from the unpermuted load. */
5661 80143 : lane_permutation_t perm;
5662 80143 : perm.create ((group_lanes + 1) / 2);
5663 80143 : unsigned even_level = even ? 1 << ctz_hwi (even) : 0;
5664 80143 : unsigned odd_level = odd ? 1 << ctz_hwi (odd) : 0;
5665 80143 : if (even_level
5666 11152 : && group_lanes % (2 * even_level) == 0
5667 : /* ??? When code generating permutes we do not try to pun
5668 : to larger component modes so level != 1 isn't a natural
5669 : even/odd extract. Prefer one if possible. */
5670 11152 : && (even_level == 1 || !odd_level || odd_level != 1))
5671 : {
5672 : /* { 0, 1, ... 4, 5 ..., } */
5673 39526 : for (unsigned i = 0; i < group_lanes / 2 / even_level; ++i)
5674 62401 : for (unsigned j = 0; j < even_level; ++j)
5675 31396 : perm.quick_push (std::make_pair (0, 2 * i * even_level + j));
5676 : }
5677 68991 : else if (odd_level)
5678 : {
5679 : /* { ..., 2, 3, ... 6, 7 } */
5680 3583 : gcc_assert (group_lanes % (2 * odd_level) == 0);
5681 15451 : for (unsigned i = 0; i < group_lanes / 2 / odd_level; ++i)
5682 23790 : for (unsigned j = 0; j < odd_level; ++j)
5683 11922 : perm.quick_push
5684 11922 : (std::make_pair (0, (2 * i + 1) * odd_level + j));
5685 : }
5686 : else
5687 : {
5688 : /* As fallback extract all used lanes and fill to half the
5689 : group size by repeating the last element.
5690 : ??? This is quite a bad strathegy for re-use - we could
5691 : brute force our way to find more optimal filling lanes to
5692 : maximize re-use when looking at all loads from the group. */
5693 68039 : auto_bitmap l;
5694 272212 : for (auto p : final_perm)
5695 68095 : bitmap_set_bit (l, p.second);
5696 68039 : unsigned i = 0;
5697 68039 : bitmap_iterator bi;
5698 136134 : EXECUTE_IF_SET_IN_BITMAP (l, 0, i, bi)
5699 68095 : perm.quick_push (std::make_pair (0, i));
5700 272308 : while (perm.length () < (group_lanes + 1) / 2)
5701 68115 : perm.quick_push (perm.last ());
5702 68039 : }
5703 :
5704 : /* Update final_perm with the intermediate permute. */
5705 161035 : for (unsigned i = 0; i < final_perm.length (); ++i)
5706 : {
5707 80892 : unsigned l = final_perm[i].second;
5708 80892 : unsigned j;
5709 90457 : for (j = 0; j < perm.length (); ++j)
5710 90457 : if (perm[j].second == l)
5711 : {
5712 80892 : final_perm[i].second = j;
5713 80892 : break;
5714 : }
5715 80892 : gcc_assert (j < perm.length ());
5716 : }
5717 :
5718 : /* And create scalar stmts. */
5719 80143 : vec<stmt_vec_info> perm_stmts;
5720 80143 : perm_stmts.create (perm.length ());
5721 339814 : for (unsigned i = 0; i < perm.length (); ++i)
5722 179528 : perm_stmts.quick_push (SLP_TREE_SCALAR_STMTS (l0)[perm[i].second]);
5723 :
5724 80143 : slp_tree p = vect_create_new_slp_node (1, VEC_PERM_EXPR);
5725 80143 : SLP_TREE_CHILDREN (p).quick_push (l0);
5726 80143 : SLP_TREE_LANE_PERMUTATION (p) = perm;
5727 80143 : SLP_TREE_VECTYPE (p) = SLP_TREE_VECTYPE (load);
5728 80143 : SLP_TREE_LANES (p) = perm.length ();
5729 : /* ??? As we have scalar stmts for this intermediate permute we
5730 : could CSE it via bst_map but we do not want to pick up
5731 : another SLP node with a load permutation. We instead should
5732 : have a "local" CSE map here. */
5733 80143 : SLP_TREE_SCALAR_STMTS (p) = perm_stmts;
5734 :
5735 : /* We now have a node for (group_lanes + 1) / 2 lanes. */
5736 80143 : l0 = p;
5737 80143 : }
5738 :
5739 : /* And finally from the ordered reduction node create the
5740 : permute to shuffle the lanes into the original load-permutation
5741 : order. We replace the original load node with this. */
5742 75794 : SLP_TREE_CODE (load) = VEC_PERM_EXPR;
5743 75794 : SLP_TREE_LOAD_PERMUTATION (load).release ();
5744 75794 : SLP_TREE_LANE_PERMUTATION (load) = final_perm;
5745 75794 : SLP_TREE_CHILDREN (load).create (1);
5746 75794 : SLP_TREE_CHILDREN (load).quick_push (l0);
5747 75794 : SLP_TREE_REPRESENTATIVE (load) = NULL;
5748 : }
5749 : }
5750 :
5751 : /* Transform SLP loads in the SLP graph created by SLP discovery to
5752 : group loads from the same group and lower load permutations that
5753 : are unlikely to be supported into a series of permutes.
5754 : In the degenerate case of having only single-lane SLP instances
5755 : this should result in a series of permute nodes emulating an
5756 : interleaving scheme. */
5757 :
5758 : static void
5759 500241 : vect_lower_load_permutations (loop_vec_info loop_vinfo,
5760 : scalar_stmts_to_slp_tree_map_t *bst_map,
5761 : bool force_single_lane)
5762 : {
5763 : /* Gather and sort loads across all instances. */
5764 500241 : hash_set<slp_tree> visited;
5765 500241 : auto_vec<slp_tree> loads;
5766 2295214 : for (auto inst : loop_vinfo->slp_instances)
5767 796441 : vect_gather_slp_loads (loads, SLP_INSTANCE_TREE (inst), visited);
5768 500241 : if (loads.is_empty ())
5769 93287 : return;
5770 406954 : loads.qsort (vllp_cmp);
5771 :
5772 : /* Now process each dataref group separately. */
5773 406954 : unsigned firsti = 0;
5774 1158384 : for (unsigned i = 1; i < loads.length (); ++i)
5775 : {
5776 344476 : slp_tree first = loads[firsti];
5777 344476 : slp_tree next = loads[i];
5778 344476 : stmt_vec_info a0 = SLP_TREE_SCALAR_STMTS (first)[0];
5779 344476 : stmt_vec_info b0 = SLP_TREE_SCALAR_STMTS (next)[0];
5780 344476 : if (STMT_VINFO_GROUPED_ACCESS (a0)
5781 158687 : && STMT_VINFO_GROUPED_ACCESS (b0)
5782 489981 : && DR_GROUP_FIRST_ELEMENT (a0) == DR_GROUP_FIRST_ELEMENT (b0))
5783 63447 : continue;
5784 : /* Now we have one or multiple SLP loads of the same group from
5785 : firsti to i - 1. */
5786 281029 : if (STMT_VINFO_GROUPED_ACCESS (a0))
5787 95240 : vect_lower_load_permutations (loop_vinfo, bst_map,
5788 95240 : make_array_slice (&loads[firsti],
5789 : i - firsti),
5790 : force_single_lane);
5791 : firsti = i;
5792 : }
5793 813908 : if (firsti < loads.length ()
5794 813908 : && STMT_VINFO_GROUPED_ACCESS (SLP_TREE_SCALAR_STMTS (loads[firsti])[0]))
5795 66714 : vect_lower_load_permutations (loop_vinfo, bst_map,
5796 66714 : make_array_slice (&loads[firsti],
5797 66714 : loads.length () - firsti),
5798 : force_single_lane);
5799 500241 : }
5800 :
5801 : /* Check if there are stmts in the loop can be vectorized using SLP. Build SLP
5802 : trees of packed scalar stmts if SLP is possible. */
5803 :
5804 : opt_result
5805 1186844 : vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
5806 : bool force_single_lane)
5807 : {
5808 1186844 : loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
5809 1186844 : unsigned int i;
5810 1186844 : stmt_vec_info first_element;
5811 1186844 : slp_instance instance;
5812 :
5813 1186844 : DUMP_VECT_SCOPE ("vect_analyze_slp");
5814 :
5815 1186844 : unsigned limit = max_tree_size;
5816 :
5817 1186844 : scalar_stmts_to_slp_tree_map_t *bst_map
5818 1186844 : = new scalar_stmts_to_slp_tree_map_t ();
5819 :
5820 : /* Find SLP sequences starting from groups of grouped stores. */
5821 3314807 : FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
5822 941245 : if (! vect_analyze_slp_instance (vinfo, bst_map, first_element,
5823 : slp_inst_kind_store, max_tree_size, &limit,
5824 : force_single_lane)
5825 941245 : && loop_vinfo)
5826 : {
5827 126 : release_scalar_stmts_to_slp_tree_map (bst_map);
5828 126 : return opt_result::failure_at (vect_location, "SLP build failed.\n");
5829 : }
5830 :
5831 : /* For loops also start SLP discovery from non-grouped stores. */
5832 1186718 : if (loop_vinfo)
5833 : {
5834 : data_reference_p dr;
5835 1687316 : FOR_EACH_VEC_ELT (vinfo->shared->datarefs, i, dr)
5836 1172672 : if (DR_IS_WRITE (dr))
5837 : {
5838 379777 : stmt_vec_info stmt_info = vinfo->lookup_dr (dr)->stmt;
5839 : /* Grouped stores are already handled above. */
5840 379777 : if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
5841 102814 : continue;
5842 276963 : vec<stmt_vec_info> stmts;
5843 276963 : vec<stmt_vec_info> roots = vNULL;
5844 276963 : vec<tree> remain = vNULL;
5845 276963 : stmts.create (1);
5846 276963 : stmts.quick_push (stmt_info);
5847 276963 : if (! vect_build_slp_instance (vinfo, slp_inst_kind_store,
5848 : stmts, roots, remain, max_tree_size,
5849 : &limit, bst_map, force_single_lane))
5850 : {
5851 3577 : release_scalar_stmts_to_slp_tree_map (bst_map);
5852 3577 : return opt_result::failure_at (vect_location,
5853 : "SLP build failed.\n");
5854 : }
5855 : }
5856 :
5857 : stmt_vec_info stmt_info;
5858 514684 : FOR_EACH_VEC_ELT (LOOP_VINFO_ALTERNATE_DEFS (loop_vinfo), i, stmt_info)
5859 : {
5860 20 : vec<stmt_vec_info> stmts;
5861 20 : vec<stmt_vec_info> roots = vNULL;
5862 20 : vec<tree> remain = vNULL;
5863 20 : stmts.create (1);
5864 20 : stmts.quick_push (stmt_info);
5865 20 : if (! vect_build_slp_instance (vinfo, slp_inst_kind_store,
5866 : stmts, roots, remain, max_tree_size,
5867 : &limit, bst_map, force_single_lane))
5868 : {
5869 0 : release_scalar_stmts_to_slp_tree_map (bst_map);
5870 0 : return opt_result::failure_at (vect_location,
5871 : "SLP build failed.\n");
5872 : }
5873 : }
5874 : }
5875 :
5876 1183141 : if (bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo))
5877 : {
5878 2008320 : for (unsigned i = 0; i < bb_vinfo->roots.length (); ++i)
5879 : {
5880 1339823 : vect_location = bb_vinfo->roots[i].roots[0]->stmt;
5881 : /* Apply patterns. */
5882 4389819 : for (unsigned j = 0; j < bb_vinfo->roots[i].stmts.length (); ++j)
5883 6099992 : bb_vinfo->roots[i].stmts[j]
5884 3144280 : = vect_stmt_to_vectorize (bb_vinfo->roots[i].stmts[j]);
5885 1339823 : if (vect_build_slp_instance (bb_vinfo, bb_vinfo->roots[i].kind,
5886 1339823 : bb_vinfo->roots[i].stmts,
5887 1339823 : bb_vinfo->roots[i].roots,
5888 1339823 : bb_vinfo->roots[i].remain,
5889 : max_tree_size, &limit, bst_map, false))
5890 : {
5891 154541 : bb_vinfo->roots[i].roots = vNULL;
5892 154541 : bb_vinfo->roots[i].remain = vNULL;
5893 : }
5894 1339823 : bb_vinfo->roots[i].stmts = vNULL;
5895 : }
5896 : }
5897 :
5898 1183141 : if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
5899 : {
5900 : /* Find SLP sequences starting from groups of reductions. */
5901 514644 : if (!vect_analyze_slp_reductions (loop_vinfo, max_tree_size, &limit,
5902 : bst_map, force_single_lane))
5903 : {
5904 1900 : release_scalar_stmts_to_slp_tree_map (bst_map);
5905 1900 : return opt_result::failure_at (vect_location, "SLP build failed.\n");
5906 : }
5907 :
5908 : /* Make sure to vectorize only-live stmts, usually inductions. */
5909 2309646 : for (edge e : get_loop_exit_edges (LOOP_VINFO_LOOP (loop_vinfo)))
5910 1492391 : for (auto gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
5911 711090 : gsi_next (&gsi))
5912 : {
5913 720977 : gphi *lc_phi = *gsi;
5914 720977 : tree def = gimple_phi_arg_def_from_edge (lc_phi, e);
5915 720977 : stmt_vec_info stmt_info;
5916 720977 : if (TREE_CODE (def) == SSA_NAME
5917 604760 : && !virtual_operand_p (def)
5918 310225 : && (stmt_info = loop_vinfo->lookup_def (def))
5919 278010 : && ((stmt_info = vect_stmt_to_vectorize (stmt_info)), true)
5920 278010 : && STMT_VINFO_RELEVANT (stmt_info) == vect_used_only_live
5921 216842 : && STMT_VINFO_LIVE_P (stmt_info)
5922 216842 : && !VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))
5923 833717 : && STMT_VINFO_REDUC_IDX (stmt_info) == -1)
5924 : {
5925 112652 : vec<stmt_vec_info> stmts;
5926 112652 : vec<stmt_vec_info> roots = vNULL;
5927 112652 : vec<tree> remain = vNULL;
5928 112652 : stmts.create (1);
5929 112652 : stmts.quick_push (vect_stmt_to_vectorize (stmt_info));
5930 112652 : if (! vect_build_slp_instance (vinfo,
5931 : slp_inst_kind_reduc_group,
5932 : stmts, roots, remain,
5933 : max_tree_size, &limit,
5934 : bst_map, force_single_lane))
5935 : {
5936 9887 : release_scalar_stmts_to_slp_tree_map (bst_map);
5937 9887 : return opt_result::failure_at (vect_location,
5938 : "SLP build failed.\n");
5939 : }
5940 : }
5941 9887 : }
5942 :
5943 : /* Find SLP sequences starting from gconds. */
5944 1259383 : for (auto cond : LOOP_VINFO_LOOP_CONDS (loop_vinfo))
5945 : {
5946 293820 : auto cond_info = loop_vinfo->lookup_stmt (cond);
5947 :
5948 293820 : cond_info = vect_stmt_to_vectorize (cond_info);
5949 293820 : vec<stmt_vec_info> roots = vNULL;
5950 293820 : roots.safe_push (cond_info);
5951 293820 : gimple *stmt = STMT_VINFO_STMT (cond_info);
5952 293820 : tree args0 = gimple_cond_lhs (stmt);
5953 293820 : tree args1 = gimple_cond_rhs (stmt);
5954 :
5955 : /* These should be enforced by cond lowering, but if it failed
5956 : bail. */
5957 293820 : if (gimple_cond_code (stmt) != NE_EXPR
5958 292689 : || TREE_TYPE (args0) != boolean_type_node
5959 585929 : || !integer_zerop (args1))
5960 : {
5961 1711 : roots.release ();
5962 1711 : release_scalar_stmts_to_slp_tree_map (bst_map);
5963 1711 : return opt_result::failure_at (vect_location,
5964 : "SLP build failed.\n");
5965 : }
5966 :
5967 : /* An argument without a loop def will be codegened from vectorizing the
5968 : root gcond itself. As such we don't need to try to build an SLP tree
5969 : from them. It's highly likely that the resulting SLP tree here if both
5970 : arguments have a def will be incompatible, but we rely on it being split
5971 : later on. */
5972 292109 : auto varg = loop_vinfo->lookup_def (args0);
5973 292109 : vec<stmt_vec_info> stmts;
5974 292109 : vec<tree> remain = vNULL;
5975 292109 : stmts.create (1);
5976 292109 : stmts.quick_push (vect_stmt_to_vectorize (varg));
5977 :
5978 292109 : if (! vect_build_slp_instance (vinfo, slp_inst_kind_gcond,
5979 : stmts, roots, remain,
5980 : max_tree_size, &limit,
5981 : bst_map, force_single_lane))
5982 : {
5983 905 : roots.release ();
5984 905 : release_scalar_stmts_to_slp_tree_map (bst_map);
5985 905 : return opt_result::failure_at (vect_location,
5986 : "SLP build failed.\n");
5987 : }
5988 : }
5989 : }
5990 :
5991 1168738 : hash_set<slp_tree> visited_patterns;
5992 1168738 : slp_tree_to_load_perm_map_t perm_cache;
5993 1168738 : slp_compat_nodes_map_t compat_cache;
5994 :
5995 : /* See if any patterns can be found in the SLP tree. */
5996 1168738 : bool pattern_found = false;
5997 3963799 : FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (vinfo), i, instance)
5998 1626323 : pattern_found |= vect_match_slp_patterns (instance, vinfo,
5999 : &visited_patterns, &perm_cache,
6000 : &compat_cache);
6001 :
6002 : /* If any were found optimize permutations of loads. */
6003 1168738 : if (pattern_found)
6004 : {
6005 267 : hash_map<slp_tree, slp_tree> load_map;
6006 4980 : FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (vinfo), i, instance)
6007 : {
6008 4179 : slp_tree root = SLP_INSTANCE_TREE (instance);
6009 4179 : optimize_load_redistribution (bst_map, vinfo, SLP_TREE_LANES (root),
6010 : &load_map, root);
6011 : }
6012 267 : }
6013 :
6014 : /* Check whether we should force some SLP instances to use load/store-lanes
6015 : and do so by forcing SLP re-discovery with single lanes. We used
6016 : to cancel SLP when this applied to all instances in a loop but now
6017 : we decide this per SLP instance. It's important to do this only
6018 : after SLP pattern recognition. */
6019 1168738 : if (is_a <loop_vec_info> (vinfo))
6020 1296682 : FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (vinfo), i, instance)
6021 796441 : if (SLP_INSTANCE_KIND (instance) == slp_inst_kind_store
6022 301976 : && !SLP_INSTANCE_TREE (instance)->ldst_lanes)
6023 : {
6024 301976 : slp_tree slp_root = SLP_INSTANCE_TREE (instance);
6025 301976 : unsigned int group_size = SLP_TREE_LANES (slp_root);
6026 301976 : tree vectype = SLP_TREE_VECTYPE (slp_root);
6027 :
6028 301976 : stmt_vec_info rep_info = SLP_TREE_REPRESENTATIVE (slp_root);
6029 301976 : gimple *rep = STMT_VINFO_STMT (rep_info);
6030 301976 : bool masked = (is_gimple_call (rep)
6031 2446 : && gimple_call_internal_p (rep)
6032 304402 : && internal_fn_mask_index
6033 2426 : (gimple_call_internal_fn (rep)) != -1);
6034 301956 : if (!STMT_VINFO_GROUPED_ACCESS (rep_info)
6035 30023 : || slp_root->ldst_lanes
6036 331999 : || (vect_store_lanes_supported (vectype, group_size, masked)
6037 : == IFN_LAST))
6038 301976 : continue;
6039 :
6040 0 : auto_vec<slp_tree> loads;
6041 0 : hash_set<slp_tree> visited;
6042 0 : vect_gather_slp_loads (loads, slp_root, visited);
6043 :
6044 : /* Check whether any load in the SLP instance is possibly
6045 : permuted. */
6046 0 : bool loads_permuted = false;
6047 0 : slp_tree load_node;
6048 0 : unsigned j;
6049 0 : FOR_EACH_VEC_ELT (loads, j, load_node)
6050 : {
6051 0 : if (!SLP_TREE_LOAD_PERMUTATION (load_node).exists ())
6052 0 : continue;
6053 0 : for (unsigned k = 0; k < SLP_TREE_LANES (load_node); k++)
6054 0 : if (SLP_TREE_LOAD_PERMUTATION (load_node)[k] != k)
6055 : {
6056 : loads_permuted = true;
6057 : break;
6058 : }
6059 : }
6060 :
6061 : /* If the loads and stores can use load/store-lanes force re-discovery
6062 : with single lanes. */
6063 0 : if (loads_permuted)
6064 : {
6065 0 : bool can_use_lanes = true;
6066 : bool prefer_load_lanes = false;
6067 0 : FOR_EACH_VEC_ELT (loads, j, load_node)
6068 0 : if (STMT_VINFO_GROUPED_ACCESS
6069 : (SLP_TREE_REPRESENTATIVE (load_node)))
6070 : {
6071 0 : stmt_vec_info stmt_vinfo = DR_GROUP_FIRST_ELEMENT
6072 : (SLP_TREE_REPRESENTATIVE (load_node));
6073 0 : rep = STMT_VINFO_STMT (stmt_vinfo);
6074 0 : masked = (is_gimple_call (rep)
6075 0 : && gimple_call_internal_p (rep)
6076 0 : && internal_fn_mask_index
6077 0 : (gimple_call_internal_fn (rep)));
6078 : /* Use SLP for strided accesses (or if we can't
6079 : load-lanes). */
6080 0 : if (STMT_VINFO_STRIDED_P (stmt_vinfo)
6081 0 : || compare_step_with_zero (vinfo, stmt_vinfo) <= 0
6082 0 : || vect_load_lanes_supported
6083 0 : (SLP_TREE_VECTYPE (load_node),
6084 0 : DR_GROUP_SIZE (stmt_vinfo), masked) == IFN_LAST
6085 : /* ??? During SLP re-discovery with a single lane
6086 : a masked grouped load will appear permuted and
6087 : discovery will fail. We have to rework this
6088 : on the discovery side - for now avoid ICEing. */
6089 0 : || masked)
6090 : {
6091 : can_use_lanes = false;
6092 : break;
6093 : }
6094 : /* Make sure that the target would prefer store-lanes
6095 : for at least one of the loads.
6096 :
6097 : ??? Perhaps we should instead require this for
6098 : all loads? */
6099 0 : prefer_load_lanes
6100 : = (prefer_load_lanes
6101 0 : || SLP_TREE_LANES (load_node) == group_size
6102 0 : || (vect_slp_prefer_store_lanes_p
6103 0 : (vinfo, stmt_vinfo,
6104 : SLP_TREE_VECTYPE (load_node), masked,
6105 : group_size, SLP_TREE_LANES (load_node))));
6106 : }
6107 :
6108 0 : if (can_use_lanes && prefer_load_lanes)
6109 : {
6110 0 : if (dump_enabled_p ())
6111 0 : dump_printf_loc (MSG_NOTE, vect_location,
6112 : "SLP instance %p can use load/store-lanes,"
6113 : " re-discovering with single-lanes\n",
6114 : (void *) instance);
6115 :
6116 0 : stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (slp_root);
6117 :
6118 0 : vect_free_slp_instance (instance);
6119 0 : limit = max_tree_size;
6120 0 : bool res = vect_analyze_slp_instance (vinfo, bst_map,
6121 : stmt_info,
6122 : slp_inst_kind_store,
6123 : max_tree_size, &limit,
6124 : true);
6125 0 : gcc_assert (res);
6126 0 : auto new_inst = LOOP_VINFO_SLP_INSTANCES (vinfo).pop ();
6127 0 : LOOP_VINFO_SLP_INSTANCES (vinfo)[i] = new_inst;
6128 : }
6129 : }
6130 0 : }
6131 :
6132 : /* When we end up with load permutations that we cannot possibly handle,
6133 : like those requiring three vector inputs, lower them using interleaving
6134 : like schemes. */
6135 1168738 : if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
6136 : {
6137 500241 : vect_lower_load_permutations (loop_vinfo, bst_map, force_single_lane);
6138 500241 : if (dump_enabled_p ())
6139 : {
6140 20606 : dump_printf_loc (MSG_NOTE, vect_location,
6141 : "SLP graph after lowering permutations:\n");
6142 20606 : hash_set<slp_tree> visited;
6143 91680 : FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (vinfo), i, instance)
6144 29887 : vect_print_slp_graph (MSG_NOTE, vect_location,
6145 : SLP_INSTANCE_TREE (instance), visited);
6146 20606 : }
6147 : }
6148 :
6149 1168738 : release_scalar_stmts_to_slp_tree_map (bst_map);
6150 :
6151 1168738 : if (pattern_found && dump_enabled_p ())
6152 : {
6153 20 : dump_printf_loc (MSG_NOTE, vect_location,
6154 : "Pattern matched SLP tree\n");
6155 20 : hash_set<slp_tree> visited;
6156 101 : FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (vinfo), i, instance)
6157 41 : vect_print_slp_graph (MSG_NOTE, vect_location,
6158 : SLP_INSTANCE_TREE (instance), visited);
6159 20 : }
6160 :
6161 1168738 : return opt_result::success ();
6162 1168738 : }
6163 :
6164 : /* Estimates the cost of inserting layout changes into the SLP graph.
6165 : It can also say that the insertion is impossible. */
6166 :
6167 : struct slpg_layout_cost
6168 : {
6169 11211502 : slpg_layout_cost () = default;
6170 : slpg_layout_cost (sreal, bool);
6171 :
6172 530514 : static slpg_layout_cost impossible () { return { sreal::max (), 0 }; }
6173 5625312 : bool is_possible () const { return depth != sreal::max (); }
6174 :
6175 : bool operator== (const slpg_layout_cost &) const;
6176 : bool operator!= (const slpg_layout_cost &) const;
6177 :
6178 : bool is_better_than (const slpg_layout_cost &, bool) const;
6179 :
6180 : void add_parallel_cost (const slpg_layout_cost &);
6181 : void add_serial_cost (const slpg_layout_cost &);
6182 : void split (unsigned int);
6183 :
6184 : /* The longest sequence of layout changes needed during any traversal
6185 : of the partition dag, weighted by execution frequency.
6186 :
6187 : This is the most important metric when optimizing for speed, since
6188 : it helps to ensure that we keep the number of operations on
6189 : critical paths to a minimum. */
6190 : sreal depth = 0;
6191 :
6192 : /* An estimate of the total number of operations needed. It is weighted by
6193 : execution frequency when optimizing for speed but not when optimizing for
6194 : size. In order to avoid double-counting, a node with a fanout of N will
6195 : distribute 1/N of its total cost to each successor.
6196 :
6197 : This is the most important metric when optimizing for size, since
6198 : it helps to keep the total number of operations to a minimum, */
6199 : sreal total = 0;
6200 : };
6201 :
6202 : /* Construct costs for a node with weight WEIGHT. A higher weight
6203 : indicates more frequent execution. IS_FOR_SIZE is true if we are
6204 : optimizing for size rather than speed. */
6205 :
6206 1329255 : slpg_layout_cost::slpg_layout_cost (sreal weight, bool is_for_size)
6207 1337772 : : depth (weight), total (is_for_size && weight > 0 ? 1 : weight)
6208 : {
6209 1329255 : }
6210 :
6211 : bool
6212 0 : slpg_layout_cost::operator== (const slpg_layout_cost &other) const
6213 : {
6214 0 : return depth == other.depth && total == other.total;
6215 : }
6216 :
6217 : bool
6218 0 : slpg_layout_cost::operator!= (const slpg_layout_cost &other) const
6219 : {
6220 0 : return !operator== (other);
6221 : }
6222 :
6223 : /* Return true if these costs are better than OTHER. IS_FOR_SIZE is
6224 : true if we are optimizing for size rather than speed. */
6225 :
6226 : bool
6227 320436 : slpg_layout_cost::is_better_than (const slpg_layout_cost &other,
6228 : bool is_for_size) const
6229 : {
6230 320436 : if (is_for_size)
6231 : {
6232 3642 : if (total != other.total)
6233 1879 : return total < other.total;
6234 1763 : return depth < other.depth;
6235 : }
6236 : else
6237 : {
6238 316794 : if (depth != other.depth)
6239 129487 : return depth < other.depth;
6240 187307 : return total < other.total;
6241 : }
6242 : }
6243 :
6244 : /* Increase the costs to account for something with cost INPUT_COST
6245 : happening in parallel with the current costs. */
6246 :
6247 : void
6248 384176 : slpg_layout_cost::add_parallel_cost (const slpg_layout_cost &input_cost)
6249 : {
6250 384176 : depth = std::max (depth, input_cost.depth);
6251 384176 : total += input_cost.total;
6252 384176 : }
6253 :
6254 : /* Increase the costs to account for something with cost INPUT_COST
6255 : happening in series with the current costs. */
6256 :
6257 : void
6258 1577465 : slpg_layout_cost::add_serial_cost (const slpg_layout_cost &other)
6259 : {
6260 1577465 : depth += other.depth;
6261 1577465 : total += other.total;
6262 1577465 : }
6263 :
6264 : /* Split the total cost among TIMES successors or predecessors. */
6265 :
6266 : void
6267 1259003 : slpg_layout_cost::split (unsigned int times)
6268 : {
6269 1259003 : if (times > 1)
6270 605609 : total /= times;
6271 1259003 : }
6272 :
6273 : /* Information about one node in the SLP graph, for use during
6274 : vect_optimize_slp_pass. */
6275 :
6276 : struct slpg_vertex
6277 : {
6278 10470951 : slpg_vertex (slp_tree node_) : node (node_) {}
6279 :
6280 : /* The node itself. */
6281 : slp_tree node;
6282 :
6283 : /* Which partition the node belongs to, or -1 if none. Nodes outside of
6284 : partitions are flexible; they can have whichever layout consumers
6285 : want them to have. */
6286 : int partition = -1;
6287 :
6288 : /* The number of nodes that directly use the result of this one
6289 : (i.e. the number of nodes that count this one as a child). */
6290 : unsigned int out_degree = 0;
6291 :
6292 : /* The execution frequency of the node. */
6293 : sreal weight = 0;
6294 :
6295 : /* The total execution frequency of all nodes that directly use the
6296 : result of this one. */
6297 : sreal out_weight = 0;
6298 : };
6299 :
6300 : /* Information about one partition of the SLP graph, for use during
6301 : vect_optimize_slp_pass. */
6302 :
6303 : struct slpg_partition_info
6304 : {
6305 : /* The nodes in the partition occupy indices [NODE_BEGIN, NODE_END)
6306 : of m_partitioned_nodes. */
6307 : unsigned int node_begin = 0;
6308 : unsigned int node_end = 0;
6309 :
6310 : /* Which layout we've chosen to use for this partition, or -1 if
6311 : we haven't picked one yet. */
6312 : int layout = -1;
6313 :
6314 : /* The number of predecessors and successors in the partition dag.
6315 : The predecessors always have lower partition numbers and the
6316 : successors always have higher partition numbers.
6317 :
6318 : Note that the directions of these edges are not necessarily the
6319 : same as in the data flow graph. For example, if an SCC has separate
6320 : partitions for an inner loop and an outer loop, the inner loop's
6321 : partition will have at least two incoming edges from the outer loop's
6322 : partition: one for a live-in value and one for a live-out value.
6323 : In data flow terms, one of these edges would also be from the outer loop
6324 : to the inner loop, but the other would be in the opposite direction. */
6325 : unsigned int in_degree = 0;
6326 : unsigned int out_degree = 0;
6327 : };
6328 :
6329 : /* Information about the costs of using a particular layout for a
6330 : particular partition. It can also say that the combination is
6331 : impossible. */
6332 :
6333 : struct slpg_partition_layout_costs
6334 : {
6335 1652083 : bool is_possible () const { return internal_cost.is_possible (); }
6336 68313 : void mark_impossible () { internal_cost = slpg_layout_cost::impossible (); }
6337 :
6338 : /* The costs inherited from predecessor partitions. */
6339 : slpg_layout_cost in_cost;
6340 :
6341 : /* The inherent cost of the layout within the node itself. For example,
6342 : this is nonzero for a load if choosing a particular layout would require
6343 : the load to permute the loaded elements. It is nonzero for a
6344 : VEC_PERM_EXPR if the permutation cannot be eliminated or converted
6345 : to full-vector moves. */
6346 : slpg_layout_cost internal_cost;
6347 :
6348 : /* The costs inherited from successor partitions. */
6349 : slpg_layout_cost out_cost;
6350 : };
6351 :
6352 : /* This class tries to optimize the layout of vectors in order to avoid
6353 : unnecessary shuffling. At the moment, the set of possible layouts are
6354 : restricted to bijective permutations.
6355 :
6356 : The goal of the pass depends on whether we're optimizing for size or
6357 : for speed. When optimizing for size, the goal is to reduce the overall
6358 : number of layout changes (including layout changes implied by things
6359 : like load permutations). When optimizing for speed, the goal is to
6360 : reduce the maximum latency attributable to layout changes on any
6361 : non-cyclical path through the data flow graph.
6362 :
6363 : For example, when optimizing a loop nest for speed, we will prefer
6364 : to make layout changes outside of a loop rather than inside of a loop,
6365 : and will prefer to make layout changes in parallel rather than serially,
6366 : even if that increases the overall number of layout changes.
6367 :
6368 : The high-level procedure is:
6369 :
6370 : (1) Build a graph in which edges go from uses (parents) to definitions
6371 : (children).
6372 :
6373 : (2) Divide the graph into a dag of strongly-connected components (SCCs).
6374 :
6375 : (3) When optimizing for speed, partition the nodes in each SCC based
6376 : on their containing cfg loop. When optimizing for size, treat
6377 : each SCC as a single partition.
6378 :
6379 : This gives us a dag of partitions. The goal is now to assign a
6380 : layout to each partition.
6381 :
6382 : (4) Construct a set of vector layouts that are worth considering.
6383 : Record which nodes must keep their current layout.
6384 :
6385 : (5) Perform a forward walk over the partition dag (from loads to stores)
6386 : accumulating the "forward" cost of using each layout. When visiting
6387 : each partition, assign a tentative choice of layout to the partition
6388 : and use that choice when calculating the cost of using a different
6389 : layout in successor partitions.
6390 :
6391 : (6) Perform a backward walk over the partition dag (from stores to loads),
6392 : accumulating the "backward" cost of using each layout. When visiting
6393 : each partition, make a final choice of layout for that partition based
6394 : on the accumulated forward costs (from (5)) and backward costs
6395 : (from (6)).
6396 :
6397 : (7) Apply the chosen layouts to the SLP graph.
6398 :
6399 : For example, consider the SLP statements:
6400 :
6401 : S1: a_1 = load
6402 : loop:
6403 : S2: a_2 = PHI<a_1, a_3>
6404 : S3: b_1 = load
6405 : S4: a_3 = a_2 + b_1
6406 : exit:
6407 : S5: a_4 = PHI<a_3>
6408 : S6: store a_4
6409 :
6410 : S2 and S4 form an SCC and are part of the same loop. Every other
6411 : statement is in a singleton SCC. In this example there is a one-to-one
6412 : mapping between SCCs and partitions and the partition dag looks like this;
6413 :
6414 : S1 S3
6415 : \ /
6416 : S2+S4
6417 : |
6418 : S5
6419 : |
6420 : S6
6421 :
6422 : S2, S3 and S4 will have a higher execution frequency than the other
6423 : statements, so when optimizing for speed, the goal is to avoid any
6424 : layout changes:
6425 :
6426 : - within S3
6427 : - within S2+S4
6428 : - on the S3->S2+S4 edge
6429 :
6430 : For example, if S3 was originally a reversing load, the goal of the
6431 : pass is to make it an unreversed load and change the layout on the
6432 : S1->S2+S4 and S2+S4->S5 edges to compensate. (Changing the layout
6433 : on S1->S2+S4 and S5->S6 would also be acceptable.)
6434 :
6435 : The difference between SCCs and partitions becomes important if we
6436 : add an outer loop:
6437 :
6438 : S1: a_1 = ...
6439 : loop1:
6440 : S2: a_2 = PHI<a_1, a_6>
6441 : S3: b_1 = load
6442 : S4: a_3 = a_2 + b_1
6443 : loop2:
6444 : S5: a_4 = PHI<a_3, a_5>
6445 : S6: c_1 = load
6446 : S7: a_5 = a_4 + c_1
6447 : exit2:
6448 : S8: a_6 = PHI<a_5>
6449 : S9: store a_6
6450 : exit1:
6451 :
6452 : Here, S2, S4, S5, S7 and S8 form a single SCC. However, when optimizing
6453 : for speed, we usually do not want restrictions in the outer loop to "infect"
6454 : the decision for the inner loop. For example, if an outer-loop node
6455 : in the SCC contains a statement with a fixed layout, that should not
6456 : prevent the inner loop from using a different layout. Conversely,
6457 : the inner loop should not dictate a layout to the outer loop: if the
6458 : outer loop does a lot of computation, then it may not be efficient to
6459 : do all of that computation in the inner loop's preferred layout.
6460 :
6461 : So when optimizing for speed, we partition the SCC into S2+S4+S8 (outer)
6462 : and S5+S7 (inner). We also try to arrange partitions so that:
6463 :
6464 : - the partition for an outer loop comes before the partition for
6465 : an inner loop
6466 :
6467 : - if a sibling loop A dominates a sibling loop B, A's partition
6468 : comes before B's
6469 :
6470 : This gives the following partition dag for the example above:
6471 :
6472 : S1 S3
6473 : \ /
6474 : S2+S4+S8 S6
6475 : | \\ /
6476 : | S5+S7
6477 : |
6478 : S9
6479 :
6480 : There are two edges from S2+S4+S8 to S5+S7: one for the edge S4->S5 and
6481 : one for a reversal of the edge S7->S8.
6482 :
6483 : The backward walk picks a layout for S5+S7 before S2+S4+S8. The choice
6484 : for S2+S4+S8 therefore has to balance the cost of using the outer loop's
6485 : preferred layout against the cost of changing the layout on entry to the
6486 : inner loop (S4->S5) and on exit from the inner loop (S7->S8 reversed).
6487 :
6488 : Although this works well when optimizing for speed, it has the downside
6489 : when optimizing for size that the choice of layout for S5+S7 is completely
6490 : independent of S9, which lessens the chance of reducing the overall number
6491 : of permutations. We therefore do not partition SCCs when optimizing
6492 : for size.
6493 :
6494 : To give a concrete example of the difference between optimizing
6495 : for size and speed, consider:
6496 :
6497 : a[0] = (b[1] << c[3]) - d[1];
6498 : a[1] = (b[0] << c[2]) - d[0];
6499 : a[2] = (b[3] << c[1]) - d[3];
6500 : a[3] = (b[2] << c[0]) - d[2];
6501 :
6502 : There are three different layouts here: one for a, one for b and d,
6503 : and one for c. When optimizing for speed it is better to permute each
6504 : of b, c and d into the order required by a, since those permutations
6505 : happen in parallel. But when optimizing for size, it is better to:
6506 :
6507 : - permute c into the same order as b
6508 : - do the arithmetic
6509 : - permute the result into the order required by a
6510 :
6511 : This gives 2 permutations rather than 3. */
6512 :
6513 : class vect_optimize_slp_pass
6514 : {
6515 : public:
6516 714431 : vect_optimize_slp_pass (vec_info *vinfo) : m_vinfo (vinfo) {}
6517 : void run ();
6518 :
6519 : private:
6520 : /* Graph building. */
6521 : struct loop *containing_loop (slp_tree);
6522 : bool is_cfg_latch_edge (graph_edge *);
6523 : void build_vertices (hash_set<slp_tree> &, slp_tree);
6524 : void build_vertices ();
6525 : void build_graph ();
6526 :
6527 : /* Partitioning. */
6528 : void create_partitions ();
6529 : template<typename T> void for_each_partition_edge (unsigned int, T);
6530 :
6531 : /* Layout selection. */
6532 : bool is_compatible_layout (slp_tree, unsigned int);
6533 : bool is_compatible_layout (const slpg_partition_info &, unsigned int);
6534 : int change_layout_cost (slp_tree, unsigned int, unsigned int);
6535 : slpg_partition_layout_costs &partition_layout_costs (unsigned int,
6536 : unsigned int);
6537 : void change_vec_perm_layout (slp_tree, lane_permutation_t &,
6538 : int, unsigned int);
6539 : int internal_node_cost (slp_tree, int, unsigned int);
6540 : void start_choosing_layouts ();
6541 : bool legitimize ();
6542 :
6543 : /* Cost propagation. */
6544 : slpg_layout_cost edge_layout_cost (graph_edge *, unsigned int,
6545 : unsigned int, unsigned int);
6546 : slpg_layout_cost total_in_cost (unsigned int);
6547 : slpg_layout_cost forward_cost (graph_edge *, unsigned int, unsigned int);
6548 : slpg_layout_cost backward_cost (graph_edge *, unsigned int, unsigned int);
6549 : void forward_pass ();
6550 : void backward_pass ();
6551 :
6552 : /* Rematerialization. */
6553 : slp_tree get_result_with_layout (slp_tree, unsigned int);
6554 : void materialize ();
6555 :
6556 : /* Clean-up. */
6557 : void remove_redundant_permutations ();
6558 :
6559 : /* Masked load lanes discovery. */
6560 : void decide_masked_load_lanes ();
6561 :
6562 : void dump ();
6563 :
6564 : vec_info *m_vinfo;
6565 :
6566 : /* True if we should optimize the graph for size, false if we should
6567 : optimize it for speed. (It wouldn't be easy to make this decision
6568 : more locally.) */
6569 : bool m_optimize_size;
6570 :
6571 : /* A graph of all SLP nodes, with edges leading from uses to definitions.
6572 : In other words, a node's predecessors are its slp_tree parents and
6573 : a node's successors are its slp_tree children. */
6574 : graph *m_slpg = nullptr;
6575 :
6576 : /* The vertices of M_SLPG, indexed by slp_tree::vertex. */
6577 : auto_vec<slpg_vertex> m_vertices;
6578 :
6579 : /* The list of all leaves of M_SLPG. such as external definitions, constants,
6580 : and loads. */
6581 : auto_vec<int> m_leafs;
6582 :
6583 : /* This array has one entry for every vector layout that we're considering.
6584 : Element 0 is null and indicates "no change". Other entries describe
6585 : permutations that are inherent in the current graph and that we would
6586 : like to reverse if possible.
6587 :
6588 : For example, a permutation { 1, 2, 3, 0 } means that something has
6589 : effectively been permuted in that way, such as a load group
6590 : { a[1], a[2], a[3], a[0] } (viewed as a permutation of a[0:3]).
6591 : We'd then like to apply the reverse permutation { 3, 0, 1, 2 }
6592 : in order to put things "back" in order. */
6593 : auto_vec<vec<unsigned> > m_perms;
6594 :
6595 : /* A partitioning of the nodes for which a layout must be chosen.
6596 : Each partition represents an <SCC, cfg loop> pair; that is,
6597 : nodes in different SCCs belong to different partitions, and nodes
6598 : within an SCC can be further partitioned according to a containing
6599 : cfg loop. Partition <SCC1, L1> comes before <SCC2, L2> if:
6600 :
6601 : - SCC1 != SCC2 and SCC1 is a predecessor of SCC2 in a forward walk
6602 : from leaves (such as loads) to roots (such as stores).
6603 :
6604 : - SCC1 == SCC2 and L1's header strictly dominates L2's header. */
6605 : auto_vec<slpg_partition_info> m_partitions;
6606 :
6607 : /* The list of all nodes for which a layout must be chosen. Nodes for
6608 : partition P come before the nodes for partition P+1. Nodes within a
6609 : partition are in reverse postorder. */
6610 : auto_vec<unsigned int> m_partitioned_nodes;
6611 :
6612 : /* Index P * num-layouts + L contains the cost of using layout L
6613 : for partition P. */
6614 : auto_vec<slpg_partition_layout_costs> m_partition_layout_costs;
6615 :
6616 : /* Index N * num-layouts + L, if nonnull, is a node that provides the
6617 : original output of node N adjusted to have layout L. */
6618 : auto_vec<slp_tree> m_node_layouts;
6619 : };
6620 :
6621 : /* Fill the vertices and leafs vector with all nodes in the SLP graph.
6622 : Also record whether we should optimize anything for speed rather
6623 : than size. */
6624 :
6625 : void
6626 11313585 : vect_optimize_slp_pass::build_vertices (hash_set<slp_tree> &visited,
6627 : slp_tree node)
6628 : {
6629 11313585 : unsigned i;
6630 11313585 : slp_tree child;
6631 :
6632 11313585 : if (visited.add (node))
6633 11313585 : return;
6634 :
6635 10470951 : if (stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node))
6636 : {
6637 7997056 : basic_block bb = gimple_bb (vect_orig_stmt (rep)->stmt);
6638 7056644 : if (optimize_bb_for_speed_p (bb))
6639 6927472 : m_optimize_size = false;
6640 : }
6641 :
6642 10470951 : node->vertex = m_vertices.length ();
6643 10470951 : m_vertices.safe_push (slpg_vertex (node));
6644 :
6645 10470951 : bool leaf = true;
6646 10470951 : bool force_leaf = false;
6647 19632804 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
6648 9161853 : if (child)
6649 : {
6650 8247243 : leaf = false;
6651 8247243 : build_vertices (visited, child);
6652 : }
6653 : else
6654 : force_leaf = true;
6655 : /* Since SLP discovery works along use-def edges all cycles have an
6656 : entry - but there's the exception of cycles where we do not handle
6657 : the entry explicitly (but with a NULL SLP node), like some reductions
6658 : and inductions. Force those SLP PHIs to act as leafs to make them
6659 : backwards reachable. */
6660 10470951 : if (leaf || force_leaf)
6661 5185362 : m_leafs.safe_push (node->vertex);
6662 : }
6663 :
6664 : /* Fill the vertices and leafs vector with all nodes in the SLP graph. */
6665 :
6666 : void
6667 1428862 : vect_optimize_slp_pass::build_vertices ()
6668 : {
6669 1428862 : hash_set<slp_tree> visited;
6670 1428862 : unsigned i;
6671 1428862 : slp_instance instance;
6672 1428862 : m_vertices.truncate (0);
6673 1428862 : m_leafs.truncate (0);
6674 7352928 : FOR_EACH_VEC_ELT (m_vinfo->slp_instances, i, instance)
6675 3066342 : build_vertices (visited, SLP_INSTANCE_TREE (instance));
6676 1428862 : }
6677 :
6678 : /* Apply (reverse) bijectite PERM to VEC. */
6679 :
6680 : template <class T>
6681 : static void
6682 229615 : vect_slp_permute (vec<unsigned> perm,
6683 : vec<T> &vec, bool reverse)
6684 : {
6685 229615 : auto_vec<T, 64> saved;
6686 229615 : saved.create (vec.length ());
6687 761177 : for (unsigned i = 0; i < vec.length (); ++i)
6688 531562 : saved.quick_push (vec[i]);
6689 :
6690 229615 : if (reverse)
6691 : {
6692 1503891 : for (unsigned i = 0; i < vec.length (); ++i)
6693 529470 : vec[perm[i]] = saved[i];
6694 758119 : for (unsigned i = 0; i < vec.length (); ++i)
6695 905195 : gcc_assert (vec[perm[i]] == saved[i]);
6696 : }
6697 : else
6698 : {
6699 6116 : for (unsigned i = 0; i < vec.length (); ++i)
6700 2092 : vec[i] = saved[perm[i]];
6701 231707 : for (unsigned i = 0; i < vec.length (); ++i)
6702 3138 : gcc_assert (vec[i] == saved[perm[i]]);
6703 : }
6704 229615 : }
6705 :
6706 : /* Return the cfg loop that contains NODE. */
6707 :
6708 : struct loop *
6709 4076519 : vect_optimize_slp_pass::containing_loop (slp_tree node)
6710 : {
6711 4076519 : stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node);
6712 : /* ??? This is imprecise, VEC_PERM nodes do not have a representative
6713 : but are laid out close to their children. */
6714 4076519 : if (!rep)
6715 144760 : return m_vinfo->bbs[0]->loop_father;
6716 4415117 : return gimple_bb (vect_orig_stmt (rep)->stmt)->loop_father;
6717 : }
6718 :
6719 : /* Return true if UD (an edge from a use to a definition) is associated
6720 : with a loop latch edge in the cfg. */
6721 :
6722 : bool
6723 8247243 : vect_optimize_slp_pass::is_cfg_latch_edge (graph_edge *ud)
6724 : {
6725 8247243 : slp_tree use = m_vertices[ud->src].node;
6726 8247243 : slp_tree def = m_vertices[ud->dest].node;
6727 8247243 : if ((SLP_TREE_DEF_TYPE (use) != vect_internal_def
6728 8247243 : || SLP_TREE_PERMUTE_P (use))
6729 7927058 : || SLP_TREE_DEF_TYPE (def) != vect_internal_def)
6730 : return false;
6731 :
6732 4802234 : stmt_vec_info use_rep = vect_orig_stmt (SLP_TREE_REPRESENTATIVE (use));
6733 4802234 : return (is_a<gphi *> (use_rep->stmt)
6734 385802 : && bb_loop_header_p (gimple_bb (use_rep->stmt))
6735 5020168 : && containing_loop (def) == containing_loop (use));
6736 : }
6737 :
6738 : /* Build the graph. Mark edges that correspond to cfg loop latch edges with
6739 : a nonnull data field. */
6740 :
6741 : void
6742 1428862 : vect_optimize_slp_pass::build_graph ()
6743 : {
6744 1428862 : m_optimize_size = true;
6745 1428862 : build_vertices ();
6746 :
6747 2857724 : m_slpg = new_graph (m_vertices.length ());
6748 14757537 : for (slpg_vertex &v : m_vertices)
6749 31303302 : for (slp_tree child : SLP_TREE_CHILDREN (v.node))
6750 9161853 : if (child)
6751 : {
6752 8247243 : graph_edge *ud = add_edge (m_slpg, v.node->vertex, child->vertex);
6753 8247243 : if (is_cfg_latch_edge (ud))
6754 208010 : ud->data = this;
6755 : }
6756 1428862 : }
6757 :
6758 : /* Return true if E corresponds to a loop latch edge in the cfg. */
6759 :
6760 : static bool
6761 4227072 : skip_cfg_latch_edges (graph_edge *e)
6762 : {
6763 4227072 : return e->data;
6764 : }
6765 :
6766 : /* Create the node partitions. */
6767 :
6768 : void
6769 714431 : vect_optimize_slp_pass::create_partitions ()
6770 : {
6771 : /* Calculate a postorder of the graph, ignoring edges that correspond
6772 : to natural latch edges in the cfg. Reading the vector from the end
6773 : to the beginning gives the reverse postorder. */
6774 714431 : auto_vec<int> initial_rpo;
6775 1428862 : graphds_dfs (m_slpg, &m_leafs[0], m_leafs.length (), &initial_rpo,
6776 : false, NULL, skip_cfg_latch_edges);
6777 2143293 : gcc_assert (initial_rpo.length () == m_vertices.length ());
6778 :
6779 : /* Calculate the strongly connected components of the graph. */
6780 714431 : auto_vec<int> scc_grouping;
6781 714431 : unsigned int num_sccs = graphds_scc (m_slpg, NULL, NULL, &scc_grouping);
6782 :
6783 : /* Create a new index order in which all nodes from the same SCC are
6784 : consecutive. Use scc_pos to record the index of the first node in
6785 : each SCC. */
6786 714431 : auto_vec<unsigned int> scc_pos (num_sccs);
6787 714431 : int last_component = -1;
6788 714431 : unsigned int node_count = 0;
6789 7378220 : for (unsigned int node_i : scc_grouping)
6790 : {
6791 5234927 : if (last_component != m_slpg->vertices[node_i].component)
6792 : {
6793 5104303 : last_component = m_slpg->vertices[node_i].component;
6794 10208606 : gcc_assert (last_component == int (scc_pos.length ()));
6795 5104303 : scc_pos.quick_push (node_count);
6796 : }
6797 5234927 : node_count += 1;
6798 : }
6799 1428862 : gcc_assert (node_count == initial_rpo.length ()
6800 : && last_component + 1 == int (num_sccs));
6801 :
6802 : /* Use m_partitioned_nodes to group nodes into SCC order, with the nodes
6803 : inside each SCC following the RPO we calculated above. The fact that
6804 : we ignored natural latch edges when calculating the RPO should ensure
6805 : that, for natural loop nests:
6806 :
6807 : - the first node that we encounter in a cfg loop is the loop header phi
6808 : - the loop header phis are in dominance order
6809 :
6810 : Arranging for this is an optimization (see below) rather than a
6811 : correctness issue. Unnatural loops with a tangled mess of backedges
6812 : will still work correctly, but might give poorer results.
6813 :
6814 : Also update scc_pos so that it gives 1 + the index of the last node
6815 : in the SCC. */
6816 714431 : m_partitioned_nodes.safe_grow (node_count);
6817 6663789 : for (unsigned int old_i = initial_rpo.length (); old_i-- > 0;)
6818 : {
6819 5234927 : unsigned int node_i = initial_rpo[old_i];
6820 5234927 : unsigned int new_i = scc_pos[m_slpg->vertices[node_i].component]++;
6821 5234927 : m_partitioned_nodes[new_i] = node_i;
6822 : }
6823 :
6824 : /* When optimizing for speed, partition each SCC based on the containing
6825 : cfg loop. The order we constructed above should ensure that, for natural
6826 : cfg loops, we'll create sub-SCC partitions for outer loops before
6827 : the corresponding sub-SCC partitions for inner loops. Similarly,
6828 : when one sibling loop A dominates another sibling loop B, we should
6829 : create a sub-SCC partition for A before a sub-SCC partition for B.
6830 :
6831 : As above, nothing depends for correctness on whether this achieves
6832 : a natural nesting, but we should get better results when it does. */
6833 1428862 : m_partitions.reserve (m_vertices.length ());
6834 714431 : unsigned int next_partition_i = 0;
6835 714431 : hash_map<struct loop *, int> loop_partitions;
6836 714431 : unsigned int rpo_begin = 0;
6837 714431 : unsigned int num_partitioned_nodes = 0;
6838 7247596 : for (unsigned int rpo_end : scc_pos)
6839 : {
6840 5104303 : loop_partitions.empty ();
6841 5104303 : unsigned int partition_i = next_partition_i;
6842 10339230 : for (unsigned int rpo_i = rpo_begin; rpo_i < rpo_end; ++rpo_i)
6843 : {
6844 : /* Handle externals and constants optimistically throughout.
6845 : But treat existing vectors as fixed since we do not handle
6846 : permuting them. */
6847 5234927 : unsigned int node_i = m_partitioned_nodes[rpo_i];
6848 5234927 : auto &vertex = m_vertices[node_i];
6849 5234927 : if ((SLP_TREE_DEF_TYPE (vertex.node) == vect_external_def
6850 529895 : && !SLP_TREE_VEC_DEFS (vertex.node).exists ())
6851 5238149 : || SLP_TREE_DEF_TYPE (vertex.node) == vect_constant_def)
6852 1563512 : vertex.partition = -1;
6853 : else
6854 : {
6855 3671415 : bool existed;
6856 3671415 : if (m_optimize_size)
6857 30764 : existed = next_partition_i > partition_i;
6858 : else
6859 : {
6860 3640651 : struct loop *loop = containing_loop (vertex.node);
6861 3640651 : auto &entry = loop_partitions.get_or_insert (loop, &existed);
6862 3640651 : if (!existed)
6863 3511254 : entry = next_partition_i;
6864 3640651 : partition_i = entry;
6865 : }
6866 3671415 : if (!existed)
6867 : {
6868 3541926 : m_partitions.quick_push (slpg_partition_info ());
6869 3541926 : next_partition_i += 1;
6870 : }
6871 3671415 : vertex.partition = partition_i;
6872 3671415 : num_partitioned_nodes += 1;
6873 3671415 : m_partitions[partition_i].node_end += 1;
6874 : }
6875 : }
6876 5104303 : rpo_begin = rpo_end;
6877 : }
6878 :
6879 : /* Assign ranges of consecutive node indices to each partition,
6880 : in partition order. Start with node_end being the same as
6881 : node_begin so that the next loop can use it as a counter. */
6882 714431 : unsigned int node_begin = 0;
6883 5685219 : for (auto &partition : m_partitions)
6884 : {
6885 3541926 : partition.node_begin = node_begin;
6886 3541926 : node_begin += partition.node_end;
6887 3541926 : partition.node_end = partition.node_begin;
6888 : }
6889 714431 : gcc_assert (node_begin == num_partitioned_nodes);
6890 :
6891 : /* Finally build the list of nodes in partition order. */
6892 714431 : m_partitioned_nodes.truncate (num_partitioned_nodes);
6893 6663789 : for (unsigned int node_i = 0; node_i < m_vertices.length (); ++node_i)
6894 : {
6895 5234927 : int partition_i = m_vertices[node_i].partition;
6896 5234927 : if (partition_i >= 0)
6897 : {
6898 3671415 : unsigned int order_i = m_partitions[partition_i].node_end++;
6899 3671415 : m_partitioned_nodes[order_i] = node_i;
6900 : }
6901 : }
6902 714431 : }
6903 :
6904 : /* Look for edges from earlier partitions into node NODE_I and edges from
6905 : node NODE_I into later partitions. Call:
6906 :
6907 : FN (ud, other_node_i)
6908 :
6909 : for each such use-to-def edge ud, where other_node_i is the node at the
6910 : other end of the edge. */
6911 :
6912 : template<typename T>
6913 : void
6914 4134220 : vect_optimize_slp_pass::for_each_partition_edge (unsigned int node_i, T fn)
6915 : {
6916 4134220 : int partition_i = m_vertices[node_i].partition;
6917 4134220 : for (graph_edge *pred = m_slpg->vertices[node_i].pred;
6918 7149007 : pred; pred = pred->pred_next)
6919 : {
6920 3014787 : int src_partition_i = m_vertices[pred->src].partition;
6921 3014787 : if (src_partition_i >= 0 && src_partition_i != partition_i)
6922 2685496 : fn (pred, pred->src);
6923 : }
6924 4134220 : for (graph_edge *succ = m_slpg->vertices[node_i].succ;
6925 8882095 : succ; succ = succ->succ_next)
6926 : {
6927 4747875 : int dest_partition_i = m_vertices[succ->dest].partition;
6928 4747875 : if (dest_partition_i >= 0 && dest_partition_i != partition_i)
6929 2722202 : fn (succ, succ->dest);
6930 : }
6931 4134220 : }
6932 :
6933 : /* Return true if layout LAYOUT_I is compatible with the number of SLP lanes
6934 : that NODE would operate on. This test is independent of NODE's actual
6935 : operation. */
6936 :
6937 : bool
6938 1779168 : vect_optimize_slp_pass::is_compatible_layout (slp_tree node,
6939 : unsigned int layout_i)
6940 : {
6941 1779168 : if (layout_i == 0)
6942 : return true;
6943 :
6944 1044882 : if (SLP_TREE_LANES (node) != m_perms[layout_i].length ())
6945 18826 : return false;
6946 :
6947 : return true;
6948 : }
6949 :
6950 : /* Return true if layout LAYOUT_I is compatible with the number of SLP lanes
6951 : that NODE would operate on for each NODE in PARTITION.
6952 : This test is independent of NODE's actual operations. */
6953 :
6954 : bool
6955 24007 : vect_optimize_slp_pass::is_compatible_layout (const slpg_partition_info
6956 : &partition,
6957 : unsigned int layout_i)
6958 : {
6959 48446 : for (unsigned int order_i = partition.node_begin;
6960 48446 : order_i < partition.node_end; ++order_i)
6961 : {
6962 24541 : unsigned int node_i = m_partitioned_nodes[order_i];
6963 24541 : auto &vertex = m_vertices[node_i];
6964 :
6965 : /* The layout is incompatible if it is individually incompatible
6966 : with any node in the partition. */
6967 24541 : if (!is_compatible_layout (vertex.node, layout_i))
6968 : return false;
6969 : }
6970 : return true;
6971 : }
6972 :
6973 : /* Return the cost (in arbitrary units) of going from layout FROM_LAYOUT_I
6974 : to layout TO_LAYOUT_I for a node like NODE. Return -1 if either of the
6975 : layouts is incompatible with NODE or if the change is not possible for
6976 : some other reason.
6977 :
6978 : The properties taken from NODE include the number of lanes and the
6979 : vector type. The actual operation doesn't matter. */
6980 :
6981 : int
6982 750877 : vect_optimize_slp_pass::change_layout_cost (slp_tree node,
6983 : unsigned int from_layout_i,
6984 : unsigned int to_layout_i)
6985 : {
6986 750877 : if (!is_compatible_layout (node, from_layout_i)
6987 750877 : || !is_compatible_layout (node, to_layout_i))
6988 : return -1;
6989 :
6990 750232 : if (from_layout_i == to_layout_i)
6991 : return 0;
6992 :
6993 311195 : auto_vec<slp_tree, 1> children (1);
6994 311195 : children.quick_push (node);
6995 311195 : auto_lane_permutation_t perm (SLP_TREE_LANES (node));
6996 311195 : if (from_layout_i > 0)
6997 876124 : for (unsigned int i : m_perms[from_layout_i])
6998 389161 : perm.quick_push ({ 0, i });
6999 : else
7000 488889 : for (unsigned int i = 0; i < SLP_TREE_LANES (node); ++i)
7001 340015 : perm.quick_push ({ 0, i });
7002 311195 : if (to_layout_i > 0)
7003 149611 : vect_slp_permute (m_perms[to_layout_i], perm, true);
7004 311195 : auto count = vectorizable_slp_permutation_1 (m_vinfo, nullptr, node, perm,
7005 : children, false);
7006 311195 : if (count >= 0)
7007 305365 : return MAX (count, 1);
7008 :
7009 : /* ??? In principle we could try changing via layout 0, giving two
7010 : layout changes rather than 1. Doing that would require
7011 : corresponding support in get_result_with_layout. */
7012 : return -1;
7013 311195 : }
7014 :
7015 : /* Return the costs of assigning layout LAYOUT_I to partition PARTITION_I. */
7016 :
7017 : inline slpg_partition_layout_costs &
7018 1123633 : vect_optimize_slp_pass::partition_layout_costs (unsigned int partition_i,
7019 : unsigned int layout_i)
7020 : {
7021 2247266 : return m_partition_layout_costs[partition_i * m_perms.length () + layout_i];
7022 : }
7023 :
7024 : /* Change PERM in one of two ways:
7025 :
7026 : - if IN_LAYOUT_I < 0, accept input operand I in the layout that has been
7027 : chosen for child I of NODE.
7028 :
7029 : - if IN_LAYOUT >= 0, accept all inputs operands with that layout.
7030 :
7031 : In both cases, arrange for the output to have layout OUT_LAYOUT_I */
7032 :
7033 : void
7034 39214 : vect_optimize_slp_pass::
7035 : change_vec_perm_layout (slp_tree node, lane_permutation_t &perm,
7036 : int in_layout_i, unsigned int out_layout_i)
7037 : {
7038 230420 : for (auto &entry : perm)
7039 : {
7040 112778 : int this_in_layout_i = in_layout_i;
7041 112778 : if (this_in_layout_i < 0)
7042 : {
7043 76859 : slp_tree in_node = SLP_TREE_CHILDREN (node)[entry.first];
7044 76859 : unsigned int in_partition_i = m_vertices[in_node->vertex].partition;
7045 76859 : if (in_partition_i == -1u)
7046 329 : continue;
7047 76530 : this_in_layout_i = m_partitions[in_partition_i].layout;
7048 : }
7049 112449 : if (this_in_layout_i > 0)
7050 25601 : entry.second = m_perms[this_in_layout_i][entry.second];
7051 : }
7052 39214 : if (out_layout_i > 0)
7053 11094 : vect_slp_permute (m_perms[out_layout_i], perm, true);
7054 39214 : }
7055 :
7056 : /* Check whether the target allows NODE to be rearranged so that the node's
7057 : output has layout OUT_LAYOUT_I. Return the cost of the change if so,
7058 : in the same arbitrary units as for change_layout_cost. Return -1 otherwise.
7059 :
7060 : If NODE is a VEC_PERM_EXPR and IN_LAYOUT_I < 0, also check whether
7061 : NODE can adapt to the layout changes that have (perhaps provisionally)
7062 : been chosen for NODE's children, so that no extra permutations are
7063 : needed on either the input or the output of NODE.
7064 :
7065 : If NODE is a VEC_PERM_EXPR and IN_LAYOUT_I >= 0, instead assume
7066 : that all inputs will be forced into layout IN_LAYOUT_I beforehand.
7067 :
7068 : IN_LAYOUT_I has no meaning for other types of node.
7069 :
7070 : Keeping the node as-is is always valid. If the target doesn't appear
7071 : to support the node as-is, but might realistically support other layouts,
7072 : then layout 0 instead has the cost of a worst-case permutation. On the
7073 : one hand, this ensures that every node has at least one valid layout,
7074 : avoiding what would otherwise be an awkward special case. On the other,
7075 : it still encourages the pass to change an invalid pre-existing layout
7076 : choice into a valid one. */
7077 :
7078 : int
7079 248357 : vect_optimize_slp_pass::internal_node_cost (slp_tree node, int in_layout_i,
7080 : unsigned int out_layout_i)
7081 : {
7082 248357 : const int fallback_cost = 1;
7083 :
7084 248357 : if (SLP_TREE_PERMUTE_P (node))
7085 : {
7086 32553 : auto_lane_permutation_t tmp_perm;
7087 32553 : tmp_perm.safe_splice (SLP_TREE_LANE_PERMUTATION (node));
7088 :
7089 : /* Check that the child nodes support the chosen layout. Checking
7090 : the first child is enough, since any second child would have the
7091 : same shape. */
7092 32553 : auto first_child = SLP_TREE_CHILDREN (node)[0];
7093 32553 : if (in_layout_i > 0
7094 32553 : && !is_compatible_layout (first_child, in_layout_i))
7095 : return -1;
7096 :
7097 31913 : change_vec_perm_layout (node, tmp_perm, in_layout_i, out_layout_i);
7098 63826 : int count = vectorizable_slp_permutation_1 (m_vinfo, nullptr,
7099 : node, tmp_perm,
7100 31913 : SLP_TREE_CHILDREN (node),
7101 : false);
7102 31913 : if (count < 0)
7103 : {
7104 2609 : if (in_layout_i == 0 && out_layout_i == 0)
7105 : {
7106 : /* Use the fallback cost if the node could in principle support
7107 : some nonzero layout for both the inputs and the outputs.
7108 : Otherwise assume that the node will be rejected later
7109 : and rebuilt from scalars. */
7110 641 : if (SLP_TREE_LANES (node) == SLP_TREE_LANES (first_child))
7111 : return fallback_cost;
7112 319 : return 0;
7113 : }
7114 : return -1;
7115 : }
7116 :
7117 : /* We currently have no way of telling whether the new layout is cheaper
7118 : or more expensive than the old one. But at least in principle,
7119 : it should be worth making zero permutations (whole-vector shuffles)
7120 : cheaper than real permutations, in case the pass is able to remove
7121 : the latter. */
7122 29304 : return count == 0 ? 0 : 1;
7123 32553 : }
7124 :
7125 215804 : stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node);
7126 215804 : if (rep
7127 213845 : && STMT_VINFO_DATA_REF (rep)
7128 71861 : && DR_IS_READ (STMT_VINFO_DATA_REF (rep))
7129 263744 : && SLP_TREE_LOAD_PERMUTATION (node).exists ())
7130 : {
7131 39616 : auto_load_permutation_t tmp_perm;
7132 39616 : tmp_perm.safe_splice (SLP_TREE_LOAD_PERMUTATION (node));
7133 39616 : if (out_layout_i > 0)
7134 15202 : vect_slp_permute (m_perms[out_layout_i], tmp_perm, true);
7135 :
7136 39616 : poly_uint64 vf = 1;
7137 39616 : if (auto loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo))
7138 12152 : vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
7139 39616 : unsigned int n_perms;
7140 39616 : if (!vect_transform_slp_perm_load_1 (m_vinfo, node, tmp_perm, vNULL,
7141 : nullptr, vf, true, false, &n_perms))
7142 : {
7143 2366 : auto rep = SLP_TREE_REPRESENTATIVE (node);
7144 2366 : if (out_layout_i == 0)
7145 : {
7146 : /* Use the fallback cost if the load is an N-to-N permutation.
7147 : Otherwise assume that the node will be rejected later
7148 : and rebuilt from scalars. */
7149 1733 : if (STMT_VINFO_GROUPED_ACCESS (rep)
7150 3466 : && (DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (rep))
7151 1733 : == SLP_TREE_LANES (node)))
7152 685 : return fallback_cost;
7153 : return 0;
7154 : }
7155 : return -1;
7156 : }
7157 :
7158 : /* See the comment above the corresponding VEC_PERM_EXPR handling. */
7159 37250 : return n_perms == 0 ? 0 : 1;
7160 39616 : }
7161 :
7162 : return 0;
7163 : }
7164 :
7165 : /* Decide which element layouts we should consider using. Calculate the
7166 : weights associated with inserting layout changes on partition edges.
7167 : Also mark partitions that cannot change layout, by setting their
7168 : layout to zero. */
7169 :
7170 : void
7171 714431 : vect_optimize_slp_pass::start_choosing_layouts ()
7172 : {
7173 : /* Used to assign unique permutation indices. */
7174 714431 : using perm_hash = unbounded_hashmap_traits<
7175 : vec_free_hash_base<int_hash_base<unsigned>>,
7176 : int_hash<int, -1, -2>
7177 : >;
7178 714431 : hash_map<vec<unsigned>, int, perm_hash> layout_ids;
7179 :
7180 : /* Layout 0 is "no change". */
7181 714431 : m_perms.safe_push (vNULL);
7182 :
7183 : /* Create layouts from existing permutations. */
7184 714431 : auto_load_permutation_t tmp_perm;
7185 5814708 : for (unsigned int node_i : m_partitioned_nodes)
7186 : {
7187 : /* Leafs also double as entries to the reverse graph. Allow the
7188 : layout of those to be changed. */
7189 3671415 : auto &vertex = m_vertices[node_i];
7190 3671415 : auto &partition = m_partitions[vertex.partition];
7191 3671415 : if (!m_slpg->vertices[node_i].succ)
7192 936814 : partition.layout = 0;
7193 :
7194 : /* Loads and VEC_PERM_EXPRs are the only things generating permutes. */
7195 3671415 : slp_tree node = vertex.node;
7196 3671415 : stmt_vec_info dr_stmt = SLP_TREE_REPRESENTATIVE (node);
7197 3671415 : slp_tree child;
7198 3671415 : unsigned HOST_WIDE_INT imin, imax = 0;
7199 3671415 : bool any_permute = false;
7200 3671415 : tmp_perm.truncate (0);
7201 3671415 : if (SLP_TREE_LOAD_PERMUTATION (node).exists ())
7202 : {
7203 : /* If splitting out a SLP_TREE_LANE_PERMUTATION can make the node
7204 : unpermuted, record a layout that reverses this permutation.
7205 :
7206 : We would need more work to cope with loads that are internally
7207 : permuted and also have inputs (such as masks for
7208 : IFN_MASK_LOADs). */
7209 630990 : gcc_assert (partition.layout == 0 && !m_slpg->vertices[node_i].succ);
7210 630990 : if (!STMT_VINFO_GROUPED_ACCESS (dr_stmt))
7211 : {
7212 446659 : partition.layout = -1;
7213 3650183 : continue;
7214 : }
7215 184331 : dr_stmt = DR_GROUP_FIRST_ELEMENT (dr_stmt);
7216 184331 : imin = DR_GROUP_SIZE (dr_stmt) + 1;
7217 184331 : tmp_perm.safe_splice (SLP_TREE_LOAD_PERMUTATION (node));
7218 : }
7219 5960656 : else if (SLP_TREE_PERMUTE_P (node)
7220 139866 : && SLP_TREE_CHILDREN (node).length () == 1
7221 120194 : && (child = SLP_TREE_CHILDREN (node)[0])
7222 3180291 : && (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (child))
7223 120194 : .is_constant (&imin)))
7224 : {
7225 : /* If the child has the same vector size as this node,
7226 : reversing the permutation can make the permutation a no-op.
7227 : In other cases it can change a true permutation into a
7228 : full-vector extract. */
7229 120194 : tmp_perm.reserve (SLP_TREE_LANES (node));
7230 445327 : for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j)
7231 204939 : tmp_perm.quick_push (SLP_TREE_LANE_PERMUTATION (node)[j].second);
7232 : }
7233 : else
7234 2920231 : continue;
7235 :
7236 813765 : for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j)
7237 : {
7238 509240 : unsigned idx = tmp_perm[j];
7239 509240 : imin = MIN (imin, idx);
7240 509240 : imax = MAX (imax, idx);
7241 509240 : if (idx - tmp_perm[0] != j)
7242 160812 : any_permute = true;
7243 : }
7244 : /* If the span doesn't match we'd disrupt VF computation, avoid
7245 : that for now. */
7246 304525 : if (imax - imin + 1 != SLP_TREE_LANES (node))
7247 91328 : continue;
7248 : /* If there's no permute no need to split one out. In this case
7249 : we can consider turning a load into a permuted load, if that
7250 : turns out to be cheaper than alternatives. */
7251 213197 : if (!any_permute)
7252 : {
7253 191810 : partition.layout = -1;
7254 191810 : continue;
7255 : }
7256 :
7257 : /* For now only handle true permutes, like
7258 : vect_attempt_slp_rearrange_stmts did. This allows us to be lazy
7259 : when permuting constants and invariants keeping the permute
7260 : bijective. */
7261 21387 : auto_sbitmap load_index (SLP_TREE_LANES (node));
7262 21387 : bitmap_clear (load_index);
7263 106668 : for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j)
7264 63894 : bitmap_set_bit (load_index, tmp_perm[j] - imin);
7265 : unsigned j;
7266 84438 : for (j = 0; j < SLP_TREE_LANES (node); ++j)
7267 63206 : if (!bitmap_bit_p (load_index, j))
7268 : break;
7269 21387 : if (j != SLP_TREE_LANES (node))
7270 155 : continue;
7271 :
7272 21232 : vec<unsigned> perm = vNULL;
7273 21232 : perm.safe_grow (SLP_TREE_LANES (node), true);
7274 105391 : for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j)
7275 62927 : perm[j] = tmp_perm[j] - imin;
7276 :
7277 42464 : if (int (m_perms.length ()) >= param_vect_max_layout_candidates)
7278 : {
7279 : /* Continue to use existing layouts, but don't add any more. */
7280 0 : int *entry = layout_ids.get (perm);
7281 0 : partition.layout = entry ? *entry : 0;
7282 0 : perm.release ();
7283 : }
7284 : else
7285 : {
7286 21232 : bool existed;
7287 21232 : int &layout_i = layout_ids.get_or_insert (perm, &existed);
7288 21232 : if (existed)
7289 7971 : perm.release ();
7290 : else
7291 : {
7292 13261 : layout_i = m_perms.length ();
7293 13261 : m_perms.safe_push (perm);
7294 : }
7295 21232 : partition.layout = layout_i;
7296 : }
7297 21387 : }
7298 :
7299 : /* Initially assume that every layout is possible and has zero cost
7300 : in every partition. */
7301 714431 : m_partition_layout_costs.safe_grow_cleared (m_partitions.length ()
7302 1428862 : * m_perms.length ());
7303 :
7304 : /* We have to mark outgoing permutations facing non-associating-reduction
7305 : graph entries that are not represented as to be materialized.
7306 : slp_inst_kind_bb_reduc currently only covers associatable reductions. */
7307 3676464 : for (slp_instance instance : m_vinfo->slp_instances)
7308 1533171 : if (SLP_INSTANCE_KIND (instance) == slp_inst_kind_ctor)
7309 : {
7310 7054 : unsigned int node_i = SLP_INSTANCE_TREE (instance)->vertex;
7311 7054 : m_partitions[m_vertices[node_i].partition].layout = 0;
7312 : }
7313 1526117 : else if (SLP_INSTANCE_KIND (instance) == slp_inst_kind_reduc_chain)
7314 : {
7315 2306 : stmt_vec_info stmt_info
7316 2306 : = SLP_TREE_REPRESENTATIVE (SLP_INSTANCE_TREE (instance));
7317 2306 : vect_reduc_info reduc_info
7318 2306 : = info_for_reduction (as_a <loop_vec_info> (m_vinfo),
7319 : SLP_INSTANCE_TREE (instance));
7320 2306 : if (needs_fold_left_reduction_p (TREE_TYPE
7321 : (gimple_get_lhs (stmt_info->stmt)),
7322 : VECT_REDUC_INFO_CODE (reduc_info)))
7323 : {
7324 100 : unsigned int node_i = SLP_INSTANCE_TREE (instance)->vertex;
7325 100 : m_partitions[m_vertices[node_i].partition].layout = 0;
7326 : }
7327 : }
7328 :
7329 : /* Check which layouts each node and partition can handle. Calculate the
7330 : weights associated with inserting layout changes on edges. */
7331 5814708 : for (unsigned int node_i : m_partitioned_nodes)
7332 : {
7333 3671415 : auto &vertex = m_vertices[node_i];
7334 3671415 : auto &partition = m_partitions[vertex.partition];
7335 3671415 : slp_tree node = vertex.node;
7336 :
7337 3671415 : vertex.weight = vect_slp_node_weight (m_vinfo, node);
7338 :
7339 3671415 : if (stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node))
7340 : {
7341 : /* We do not handle stores with a permutation, so all
7342 : incoming permutations must have been materialized.
7343 :
7344 : We also don't handle masked grouped loads, which lack a
7345 : permutation vector. In this case the memory locations
7346 : form an implicit second input to the loads, on top of the
7347 : explicit mask input, and the memory input's layout cannot
7348 : be changed.
7349 :
7350 : On the other hand, we do support permuting gather loads and
7351 : masked gather loads, where each scalar load is independent
7352 : of the others. This can be useful if the address/index input
7353 : benefits from permutation. */
7354 3528322 : if (STMT_VINFO_DATA_REF (rep)
7355 1700275 : && STMT_VINFO_GROUPED_ACCESS (rep)
7356 4529941 : && !SLP_TREE_LOAD_PERMUTATION (node).exists ())
7357 817288 : partition.layout = 0;
7358 :
7359 : /* We cannot change the layout of an operation that is
7360 : not independent on lanes. Note this is an explicit
7361 : negative list since that's much shorter than the respective
7362 : positive one but it's critical to keep maintaining it. */
7363 3528322 : if (is_gimple_call (STMT_VINFO_STMT (rep)))
7364 33412 : switch (gimple_call_combined_fn (STMT_VINFO_STMT (rep)))
7365 : {
7366 1098 : case CFN_COMPLEX_ADD_ROT90:
7367 1098 : case CFN_COMPLEX_ADD_ROT270:
7368 1098 : case CFN_COMPLEX_MUL:
7369 1098 : case CFN_COMPLEX_MUL_CONJ:
7370 1098 : case CFN_VEC_ADDSUB:
7371 1098 : case CFN_VEC_FMADDSUB:
7372 1098 : case CFN_VEC_FMSUBADD:
7373 1098 : partition.layout = 0;
7374 : default:;
7375 : }
7376 : }
7377 :
7378 8296583 : auto process_edge = [&](graph_edge *ud, unsigned int other_node_i)
7379 : {
7380 4625168 : auto &other_vertex = m_vertices[other_node_i];
7381 :
7382 : /* Count the number of edges from earlier partitions and the number
7383 : of edges to later partitions. */
7384 4625168 : if (other_vertex.partition < vertex.partition)
7385 2312584 : partition.in_degree += 1;
7386 : else
7387 2312584 : partition.out_degree += 1;
7388 :
7389 : /* If the current node uses the result of OTHER_NODE_I, accumulate
7390 : the effects of that. */
7391 4625168 : if (ud->src == int (node_i))
7392 : {
7393 2312584 : other_vertex.out_weight += vertex.weight;
7394 2312584 : other_vertex.out_degree += 1;
7395 : }
7396 8296583 : };
7397 3671415 : for_each_partition_edge (node_i, process_edge);
7398 : }
7399 714431 : }
7400 :
7401 : /* Return the incoming costs for node NODE_I, assuming that each input keeps
7402 : its current (provisional) choice of layout. The inputs do not necessarily
7403 : have the same layout as each other. */
7404 :
7405 : slpg_layout_cost
7406 4461 : vect_optimize_slp_pass::total_in_cost (unsigned int node_i)
7407 : {
7408 4461 : auto &vertex = m_vertices[node_i];
7409 4461 : slpg_layout_cost cost;
7410 14732 : auto add_cost = [&](graph_edge *, unsigned int other_node_i)
7411 : {
7412 10271 : auto &other_vertex = m_vertices[other_node_i];
7413 10271 : if (other_vertex.partition < vertex.partition)
7414 : {
7415 6894 : auto &other_partition = m_partitions[other_vertex.partition];
7416 13788 : auto &other_costs = partition_layout_costs (other_vertex.partition,
7417 6894 : other_partition.layout);
7418 6894 : slpg_layout_cost this_cost = other_costs.in_cost;
7419 6894 : this_cost.add_serial_cost (other_costs.internal_cost);
7420 6894 : this_cost.split (other_partition.out_degree);
7421 6894 : cost.add_parallel_cost (this_cost);
7422 : }
7423 14732 : };
7424 4461 : for_each_partition_edge (node_i, add_cost);
7425 4461 : return cost;
7426 : }
7427 :
7428 : /* Return the cost of switching between layout LAYOUT1_I (at node NODE1_I)
7429 : and layout LAYOUT2_I on cross-partition use-to-def edge UD. Return
7430 : slpg_layout_cost::impossible () if the change isn't possible. */
7431 :
7432 : slpg_layout_cost
7433 750877 : vect_optimize_slp_pass::
7434 : edge_layout_cost (graph_edge *ud, unsigned int node1_i, unsigned int layout1_i,
7435 : unsigned int layout2_i)
7436 : {
7437 750877 : auto &def_vertex = m_vertices[ud->dest];
7438 750877 : auto &use_vertex = m_vertices[ud->src];
7439 750877 : auto def_layout_i = ud->dest == int (node1_i) ? layout1_i : layout2_i;
7440 750877 : auto use_layout_i = ud->dest == int (node1_i) ? layout2_i : layout1_i;
7441 750877 : auto factor = change_layout_cost (def_vertex.node, def_layout_i,
7442 : use_layout_i);
7443 750877 : if (factor < 0)
7444 6475 : return slpg_layout_cost::impossible ();
7445 :
7446 : /* We have a choice of putting the layout change at the site of the
7447 : definition or at the site of the use. Prefer the former when
7448 : optimizing for size or when the execution frequency of the
7449 : definition is no greater than the combined execution frequencies of
7450 : the uses. When putting the layout change at the site of the definition,
7451 : divvy up the cost among all consumers. */
7452 744402 : if (m_optimize_size || def_vertex.weight <= def_vertex.out_weight)
7453 : {
7454 701658 : slpg_layout_cost cost = { def_vertex.weight * factor, m_optimize_size };
7455 701658 : cost.split (def_vertex.out_degree);
7456 701658 : return cost;
7457 : }
7458 42744 : return { use_vertex.weight * factor, m_optimize_size };
7459 : }
7460 :
7461 : /* UD represents a use-def link between FROM_NODE_I and a node in a later
7462 : partition; FROM_NODE_I could be the definition node or the use node.
7463 : The node at the other end of the link wants to use layout TO_LAYOUT_I.
7464 : Return the cost of any necessary fix-ups on edge UD, or return
7465 : slpg_layout_cost::impossible () if the change isn't possible.
7466 :
7467 : At this point, FROM_NODE_I's partition has chosen the cheapest
7468 : layout based on the information available so far, but this choice
7469 : is only provisional. */
7470 :
7471 : slpg_layout_cost
7472 200652 : vect_optimize_slp_pass::forward_cost (graph_edge *ud, unsigned int from_node_i,
7473 : unsigned int to_layout_i)
7474 : {
7475 200652 : auto &from_vertex = m_vertices[from_node_i];
7476 200652 : unsigned int from_partition_i = from_vertex.partition;
7477 200652 : slpg_partition_info &from_partition = m_partitions[from_partition_i];
7478 200652 : gcc_assert (from_partition.layout >= 0);
7479 :
7480 : /* First calculate the cost on the assumption that FROM_PARTITION sticks
7481 : with its current layout preference. */
7482 200652 : slpg_layout_cost cost = slpg_layout_cost::impossible ();
7483 200652 : auto edge_cost = edge_layout_cost (ud, from_node_i,
7484 200652 : from_partition.layout, to_layout_i);
7485 200652 : if (edge_cost.is_possible ())
7486 : {
7487 394460 : auto &from_costs = partition_layout_costs (from_partition_i,
7488 197230 : from_partition.layout);
7489 197230 : cost = from_costs.in_cost;
7490 197230 : cost.add_serial_cost (from_costs.internal_cost);
7491 197230 : cost.split (from_partition.out_degree);
7492 197230 : cost.add_serial_cost (edge_cost);
7493 : }
7494 3422 : else if (from_partition.layout == 0)
7495 : /* We must allow the source partition to have layout 0 as a fallback,
7496 : in case all other options turn out to be impossible. */
7497 3422 : return cost;
7498 :
7499 : /* Take the minimum of that cost and the cost that applies if
7500 : FROM_PARTITION instead switches to TO_LAYOUT_I. */
7501 197230 : auto &direct_layout_costs = partition_layout_costs (from_partition_i,
7502 : to_layout_i);
7503 197230 : if (direct_layout_costs.is_possible ())
7504 : {
7505 173169 : slpg_layout_cost direct_cost = direct_layout_costs.in_cost;
7506 173169 : direct_cost.add_serial_cost (direct_layout_costs.internal_cost);
7507 173169 : direct_cost.split (from_partition.out_degree);
7508 173169 : if (!cost.is_possible ()
7509 173169 : || direct_cost.is_better_than (cost, m_optimize_size))
7510 34721 : cost = direct_cost;
7511 : }
7512 :
7513 197230 : return cost;
7514 : }
7515 :
7516 : /* UD represents a use-def link between TO_NODE_I and a node in an earlier
7517 : partition; TO_NODE_I could be the definition node or the use node.
7518 : The node at the other end of the link wants to use layout FROM_LAYOUT_I;
7519 : return the cost of any necessary fix-ups on edge UD, or
7520 : slpg_layout_cost::impossible () if the choice cannot be made.
7521 :
7522 : At this point, TO_NODE_I's partition has a fixed choice of layout. */
7523 :
7524 : slpg_layout_cost
7525 180052 : vect_optimize_slp_pass::backward_cost (graph_edge *ud, unsigned int to_node_i,
7526 : unsigned int from_layout_i)
7527 : {
7528 180052 : auto &to_vertex = m_vertices[to_node_i];
7529 180052 : unsigned int to_partition_i = to_vertex.partition;
7530 180052 : slpg_partition_info &to_partition = m_partitions[to_partition_i];
7531 180052 : gcc_assert (to_partition.layout >= 0);
7532 :
7533 : /* If TO_NODE_I is a VEC_PERM_EXPR consumer, see whether it can be
7534 : adjusted for this input having layout FROM_LAYOUT_I. Assume that
7535 : any other inputs keep their current choice of layout. */
7536 180052 : auto &to_costs = partition_layout_costs (to_partition_i,
7537 : to_partition.layout);
7538 180052 : if (ud->src == int (to_node_i)
7539 179770 : && SLP_TREE_PERMUTE_P (to_vertex.node))
7540 : {
7541 11642 : auto &from_partition = m_partitions[m_vertices[ud->dest].partition];
7542 11642 : auto old_layout = from_partition.layout;
7543 11642 : from_partition.layout = from_layout_i;
7544 23284 : int factor = internal_node_cost (to_vertex.node, -1,
7545 11642 : to_partition.layout);
7546 11642 : from_partition.layout = old_layout;
7547 11642 : if (factor >= 0)
7548 : {
7549 10738 : slpg_layout_cost cost = to_costs.out_cost;
7550 10738 : cost.add_serial_cost ({ to_vertex.weight * factor,
7551 : m_optimize_size });
7552 10738 : cost.split (to_partition.in_degree);
7553 10738 : return cost;
7554 : }
7555 : }
7556 :
7557 : /* Compute the cost if we insert any necessary layout change on edge UD. */
7558 169314 : auto edge_cost = edge_layout_cost (ud, to_node_i,
7559 169314 : to_partition.layout, from_layout_i);
7560 169314 : if (edge_cost.is_possible ())
7561 : {
7562 169314 : slpg_layout_cost cost = to_costs.out_cost;
7563 169314 : cost.add_serial_cost (to_costs.internal_cost);
7564 169314 : cost.split (to_partition.in_degree);
7565 169314 : cost.add_serial_cost (edge_cost);
7566 169314 : return cost;
7567 : }
7568 :
7569 0 : return slpg_layout_cost::impossible ();
7570 : }
7571 :
7572 : /* Make a forward pass through the partitions, accumulating input costs.
7573 : Make a tentative (provisional) choice of layout for each partition,
7574 : ensuring that this choice still allows later partitions to keep
7575 : their original layout. */
7576 :
7577 : void
7578 6621 : vect_optimize_slp_pass::forward_pass ()
7579 : {
7580 134158 : for (unsigned int partition_i = 0; partition_i < m_partitions.length ();
7581 : ++partition_i)
7582 : {
7583 127537 : auto &partition = m_partitions[partition_i];
7584 :
7585 : /* If the partition consists of a single VEC_PERM_EXPR, precompute
7586 : the incoming cost that would apply if every predecessor partition
7587 : keeps its current layout. This is used within the loop below. */
7588 127537 : slpg_layout_cost in_cost;
7589 127537 : slp_tree single_node = nullptr;
7590 127537 : if (partition.node_end == partition.node_begin + 1)
7591 : {
7592 121146 : unsigned int node_i = m_partitioned_nodes[partition.node_begin];
7593 121146 : single_node = m_vertices[node_i].node;
7594 121146 : if (SLP_TREE_PERMUTE_P (single_node))
7595 4461 : in_cost = total_in_cost (node_i);
7596 : }
7597 :
7598 : /* Go through the possible layouts. Decide which ones are valid
7599 : for this partition and record which of the valid layouts has
7600 : the lowest cost. */
7601 127537 : unsigned int min_layout_i = 0;
7602 127537 : slpg_layout_cost min_layout_cost = slpg_layout_cost::impossible ();
7603 393499 : for (unsigned int layout_i = 0; layout_i < m_perms.length (); ++layout_i)
7604 : {
7605 265962 : auto &layout_costs = partition_layout_costs (partition_i, layout_i);
7606 265962 : if (!layout_costs.is_possible ())
7607 68313 : continue;
7608 :
7609 : /* If the recorded layout is already 0 then the layout cannot
7610 : change. */
7611 265962 : if (partition.layout == 0 && layout_i != 0)
7612 : {
7613 46065 : layout_costs.mark_impossible ();
7614 46065 : continue;
7615 : }
7616 :
7617 219897 : bool is_possible = true;
7618 447232 : for (unsigned int order_i = partition.node_begin;
7619 447232 : order_i < partition.node_end; ++order_i)
7620 : {
7621 246388 : unsigned int node_i = m_partitioned_nodes[order_i];
7622 246388 : auto &vertex = m_vertices[node_i];
7623 :
7624 : /* Reject the layout if it is individually incompatible
7625 : with any node in the partition. */
7626 246388 : if (!is_compatible_layout (vertex.node, layout_i))
7627 : {
7628 17439 : is_possible = false;
7629 19053 : break;
7630 : }
7631 :
7632 613754 : auto add_cost = [&](graph_edge *ud, unsigned int other_node_i)
7633 : {
7634 384805 : auto &other_vertex = m_vertices[other_node_i];
7635 384805 : if (other_vertex.partition < vertex.partition)
7636 : {
7637 : /* Accumulate the incoming costs from earlier
7638 : partitions, plus the cost of any layout changes
7639 : on UD itself. */
7640 200652 : auto cost = forward_cost (ud, other_node_i, layout_i);
7641 200652 : if (!cost.is_possible ())
7642 3422 : is_possible = false;
7643 : else
7644 197230 : layout_costs.in_cost.add_parallel_cost (cost);
7645 : }
7646 : else
7647 : /* Reject the layout if it would make layout 0 impossible
7648 : for later partitions. This amounts to testing that the
7649 : target supports reversing the layout change on edges
7650 : to later partitions.
7651 :
7652 : In principle, it might be possible to push a layout
7653 : change all the way down a graph, so that it never
7654 : needs to be reversed and so that the target doesn't
7655 : need to support the reverse operation. But it would
7656 : be awkward to bail out if we hit a partition that
7657 : does not support the new layout, especially since
7658 : we are not dealing with a lattice. */
7659 184153 : is_possible &= edge_layout_cost (ud, other_node_i, 0,
7660 184153 : layout_i).is_possible ();
7661 613754 : };
7662 228949 : for_each_partition_edge (node_i, add_cost);
7663 :
7664 : /* Accumulate the cost of using LAYOUT_I within NODE,
7665 : both for the inputs and the outputs. */
7666 228949 : int factor = internal_node_cost (vertex.node, layout_i,
7667 : layout_i);
7668 228949 : if (factor < 0)
7669 : {
7670 1614 : is_possible = false;
7671 1614 : break;
7672 : }
7673 227335 : else if (factor)
7674 36558 : layout_costs.internal_cost.add_serial_cost
7675 36558 : ({ vertex.weight * factor, m_optimize_size });
7676 : }
7677 219897 : if (!is_possible)
7678 : {
7679 22248 : layout_costs.mark_impossible ();
7680 22248 : continue;
7681 : }
7682 :
7683 : /* Combine the incoming and partition-internal costs. */
7684 197649 : slpg_layout_cost combined_cost = layout_costs.in_cost;
7685 197649 : combined_cost.add_serial_cost (layout_costs.internal_cost);
7686 :
7687 : /* If this partition consists of a single VEC_PERM_EXPR, see
7688 : if the VEC_PERM_EXPR can be changed to support output layout
7689 : LAYOUT_I while keeping all the provisional choices of input
7690 : layout. */
7691 197649 : if (single_node && SLP_TREE_PERMUTE_P (single_node))
7692 : {
7693 7766 : int factor = internal_node_cost (single_node, -1, layout_i);
7694 7766 : if (factor >= 0)
7695 : {
7696 7043 : auto weight = m_vertices[single_node->vertex].weight;
7697 7043 : slpg_layout_cost internal_cost
7698 7043 : = { weight * factor, m_optimize_size };
7699 :
7700 7043 : slpg_layout_cost alt_cost = in_cost;
7701 7043 : alt_cost.add_serial_cost (internal_cost);
7702 7043 : if (alt_cost.is_better_than (combined_cost, m_optimize_size))
7703 : {
7704 1732 : combined_cost = alt_cost;
7705 1732 : layout_costs.in_cost = in_cost;
7706 1732 : layout_costs.internal_cost = internal_cost;
7707 : }
7708 : }
7709 : }
7710 :
7711 : /* Record the layout with the lowest cost. Prefer layout 0 in
7712 : the event of a tie between it and another layout. */
7713 197649 : if (!min_layout_cost.is_possible ()
7714 70112 : || combined_cost.is_better_than (min_layout_cost,
7715 : m_optimize_size))
7716 : {
7717 144822 : min_layout_i = layout_i;
7718 144822 : min_layout_cost = combined_cost;
7719 : }
7720 : }
7721 :
7722 : /* This loop's handling of earlier partitions should ensure that
7723 : choosing the original layout for the current partition is no
7724 : less valid than it was in the original graph, even with the
7725 : provisional layout choices for those earlier partitions. */
7726 127537 : gcc_assert (min_layout_cost.is_possible ());
7727 127537 : partition.layout = min_layout_i;
7728 : }
7729 6621 : }
7730 :
7731 : /* Make a backward pass through the partitions, accumulating output costs.
7732 : Make a final choice of layout for each partition. */
7733 :
7734 : void
7735 6621 : vect_optimize_slp_pass::backward_pass ()
7736 : {
7737 140779 : for (unsigned int partition_i = m_partitions.length (); partition_i-- > 0;)
7738 : {
7739 127537 : auto &partition = m_partitions[partition_i];
7740 :
7741 127537 : unsigned int min_layout_i = 0;
7742 127537 : slpg_layout_cost min_layout_cost = slpg_layout_cost::impossible ();
7743 393499 : for (unsigned int layout_i = 0; layout_i < m_perms.length (); ++layout_i)
7744 : {
7745 265962 : auto &layout_costs = partition_layout_costs (partition_i, layout_i);
7746 265962 : if (!layout_costs.is_possible ())
7747 68313 : continue;
7748 :
7749 : /* Accumulate the costs from successor partitions. */
7750 197649 : bool is_possible = true;
7751 421758 : for (unsigned int order_i = partition.node_begin;
7752 421758 : order_i < partition.node_end; ++order_i)
7753 : {
7754 224109 : unsigned int node_i = m_partitioned_nodes[order_i];
7755 224109 : auto &vertex = m_vertices[node_i];
7756 600919 : auto add_cost = [&](graph_edge *ud, unsigned int other_node_i)
7757 : {
7758 376810 : auto &other_vertex = m_vertices[other_node_i];
7759 376810 : auto &other_partition = m_partitions[other_vertex.partition];
7760 376810 : if (other_vertex.partition > vertex.partition)
7761 : {
7762 : /* Accumulate the incoming costs from later
7763 : partitions, plus the cost of any layout changes
7764 : on UD itself. */
7765 180052 : auto cost = backward_cost (ud, other_node_i, layout_i);
7766 180052 : if (!cost.is_possible ())
7767 0 : is_possible = false;
7768 : else
7769 180052 : layout_costs.out_cost.add_parallel_cost (cost);
7770 : }
7771 : else
7772 : /* Make sure that earlier partitions can (if necessary
7773 : or beneficial) keep the layout that they chose in
7774 : the forward pass. This ensures that there is at
7775 : least one valid choice of layout. */
7776 196758 : is_possible &= edge_layout_cost (ud, other_node_i,
7777 196758 : other_partition.layout,
7778 196758 : layout_i).is_possible ();
7779 600919 : };
7780 224109 : for_each_partition_edge (node_i, add_cost);
7781 : }
7782 197649 : if (!is_possible)
7783 : {
7784 0 : layout_costs.mark_impossible ();
7785 0 : continue;
7786 : }
7787 :
7788 : /* Locally combine the costs from the forward and backward passes.
7789 : (This combined cost is not passed on, since that would lead
7790 : to double counting.) */
7791 197649 : slpg_layout_cost combined_cost = layout_costs.in_cost;
7792 197649 : combined_cost.add_serial_cost (layout_costs.internal_cost);
7793 197649 : combined_cost.add_serial_cost (layout_costs.out_cost);
7794 :
7795 : /* Record the layout with the lowest cost. Prefer layout 0 in
7796 : the event of a tie between it and another layout. */
7797 197649 : if (!min_layout_cost.is_possible ()
7798 70112 : || combined_cost.is_better_than (min_layout_cost,
7799 : m_optimize_size))
7800 : {
7801 138516 : min_layout_i = layout_i;
7802 138516 : min_layout_cost = combined_cost;
7803 : }
7804 : }
7805 :
7806 127537 : gcc_assert (min_layout_cost.is_possible ());
7807 127537 : partition.layout = min_layout_i;
7808 : }
7809 6621 : }
7810 :
7811 : /* Return a node that applies layout TO_LAYOUT_I to the original form of NODE.
7812 : NODE already has the layout that was selected for its partition. */
7813 :
7814 : slp_tree
7815 177819 : vect_optimize_slp_pass::get_result_with_layout (slp_tree node,
7816 : unsigned int to_layout_i)
7817 : {
7818 177819 : unsigned int result_i = node->vertex * m_perms.length () + to_layout_i;
7819 177819 : slp_tree result = m_node_layouts[result_i];
7820 177819 : if (result)
7821 : return result;
7822 :
7823 176947 : if (SLP_TREE_DEF_TYPE (node) == vect_constant_def
7824 176947 : || (SLP_TREE_DEF_TYPE (node) == vect_external_def
7825 : /* We can't permute vector defs in place. */
7826 21552 : && SLP_TREE_VEC_DEFS (node).is_empty ()))
7827 : {
7828 : /* If the vector is uniform or unchanged, there's nothing to do. */
7829 44913 : if (to_layout_i == 0 || vect_slp_tree_uniform_p (node))
7830 : result = node;
7831 : else
7832 : {
7833 3552 : auto scalar_ops = SLP_TREE_SCALAR_OPS (node).copy ();
7834 3552 : result = vect_create_new_slp_node (scalar_ops);
7835 3552 : vect_slp_permute (m_perms[to_layout_i], scalar_ops, true);
7836 : }
7837 : }
7838 : else
7839 : {
7840 132034 : unsigned int partition_i = m_vertices[node->vertex].partition;
7841 132034 : unsigned int from_layout_i = m_partitions[partition_i].layout;
7842 132034 : if (from_layout_i == to_layout_i)
7843 130846 : return node;
7844 :
7845 : /* If NODE is itself a VEC_PERM_EXPR, try to create a parallel
7846 : permutation instead of a serial one. Leave the new permutation
7847 : in TMP_PERM on success. */
7848 1188 : auto_lane_permutation_t tmp_perm;
7849 1188 : unsigned int num_inputs = 1;
7850 1188 : if (SLP_TREE_PERMUTE_P (node))
7851 : {
7852 104 : tmp_perm.safe_splice (SLP_TREE_LANE_PERMUTATION (node));
7853 104 : if (from_layout_i != 0)
7854 44 : vect_slp_permute (m_perms[from_layout_i], tmp_perm, false);
7855 104 : if (to_layout_i != 0)
7856 64 : vect_slp_permute (m_perms[to_layout_i], tmp_perm, true);
7857 104 : if (vectorizable_slp_permutation_1 (m_vinfo, nullptr, node,
7858 : tmp_perm,
7859 104 : SLP_TREE_CHILDREN (node),
7860 : false) >= 0)
7861 104 : num_inputs = SLP_TREE_CHILDREN (node).length ();
7862 : else
7863 0 : tmp_perm.truncate (0);
7864 : }
7865 :
7866 1188 : if (dump_enabled_p ())
7867 : {
7868 70 : if (tmp_perm.length () > 0)
7869 6 : dump_printf_loc (MSG_NOTE, vect_location,
7870 : "duplicating permutation node %p with"
7871 : " layout %d\n",
7872 : (void *) node, to_layout_i);
7873 : else
7874 64 : dump_printf_loc (MSG_NOTE, vect_location,
7875 : "inserting permutation node in place of %p\n",
7876 : (void *) node);
7877 : }
7878 :
7879 1188 : unsigned int num_lanes = SLP_TREE_LANES (node);
7880 1188 : result = vect_create_new_slp_node (num_inputs, VEC_PERM_EXPR);
7881 1188 : if (SLP_TREE_SCALAR_STMTS (node).exists ())
7882 : {
7883 1188 : auto &stmts = SLP_TREE_SCALAR_STMTS (result);
7884 1188 : stmts.safe_splice (SLP_TREE_SCALAR_STMTS (node));
7885 1188 : if (from_layout_i != 0)
7886 483 : vect_slp_permute (m_perms[from_layout_i], stmts, false);
7887 1188 : if (to_layout_i != 0)
7888 715 : vect_slp_permute (m_perms[to_layout_i], stmts, true);
7889 : }
7890 1188 : SLP_TREE_LANES (result) = num_lanes;
7891 1188 : SLP_TREE_VECTYPE (result) = SLP_TREE_VECTYPE (node);
7892 1188 : result->vertex = -1;
7893 :
7894 1188 : auto &lane_perm = SLP_TREE_LANE_PERMUTATION (result);
7895 1188 : if (tmp_perm.length ())
7896 : {
7897 104 : lane_perm.safe_splice (tmp_perm);
7898 104 : SLP_TREE_CHILDREN (result).safe_splice (SLP_TREE_CHILDREN (node));
7899 : }
7900 : else
7901 : {
7902 1084 : lane_perm.create (num_lanes);
7903 4428 : for (unsigned j = 0; j < num_lanes; ++j)
7904 2260 : lane_perm.quick_push ({ 0, j });
7905 1084 : if (from_layout_i != 0)
7906 439 : vect_slp_permute (m_perms[from_layout_i], lane_perm, false);
7907 1084 : if (to_layout_i != 0)
7908 651 : vect_slp_permute (m_perms[to_layout_i], lane_perm, true);
7909 1084 : SLP_TREE_CHILDREN (result).safe_push (node);
7910 : }
7911 4824 : for (slp_tree child : SLP_TREE_CHILDREN (result))
7912 1260 : child->refcnt++;
7913 1188 : }
7914 46101 : m_node_layouts[result_i] = result;
7915 46101 : return result;
7916 : }
7917 :
7918 : /* Apply the chosen vector layouts to the SLP graph. */
7919 :
7920 : void
7921 12669 : vect_optimize_slp_pass::materialize ()
7922 : {
7923 : /* We no longer need the costs, so avoid having two O(N * P) arrays
7924 : live at the same time. */
7925 12669 : m_partition_layout_costs.release ();
7926 38007 : m_node_layouts.safe_grow_cleared (m_vertices.length () * m_perms.length ());
7927 :
7928 25338 : auto_sbitmap fully_folded (m_vertices.length ());
7929 12669 : bitmap_clear (fully_folded);
7930 193807 : for (unsigned int node_i : m_partitioned_nodes)
7931 : {
7932 155800 : auto &vertex = m_vertices[node_i];
7933 155800 : slp_tree node = vertex.node;
7934 155800 : int layout_i = m_partitions[vertex.partition].layout;
7935 155800 : gcc_assert (layout_i >= 0);
7936 :
7937 : /* Rearrange the scalar statements to match the chosen layout. */
7938 155800 : if (layout_i > 0)
7939 24337 : vect_slp_permute (m_perms[layout_i],
7940 24337 : SLP_TREE_SCALAR_STMTS (node), true);
7941 :
7942 : /* Update load and lane permutations. */
7943 155800 : if (SLP_TREE_PERMUTE_P (node))
7944 : {
7945 : /* First try to absorb the input vector layouts. If that fails,
7946 : force the inputs to have layout LAYOUT_I too. We checked that
7947 : that was possible before deciding to use nonzero output layouts.
7948 : (Note that at this stage we don't really have any guarantee that
7949 : the target supports the original VEC_PERM_EXPR.) */
7950 6660 : auto &perm = SLP_TREE_LANE_PERMUTATION (node);
7951 6660 : auto_lane_permutation_t tmp_perm;
7952 6660 : tmp_perm.safe_splice (perm);
7953 6660 : change_vec_perm_layout (node, tmp_perm, -1, layout_i);
7954 6660 : if (vectorizable_slp_permutation_1 (m_vinfo, nullptr, node,
7955 : tmp_perm,
7956 6660 : SLP_TREE_CHILDREN (node),
7957 : false) >= 0)
7958 : {
7959 6019 : if (dump_enabled_p ()
7960 6939 : && !std::equal (tmp_perm.begin (), tmp_perm.end (),
7961 : perm.begin ()))
7962 58 : dump_printf_loc (MSG_NOTE, vect_location,
7963 : "absorbing input layouts into %p\n",
7964 : (void *) node);
7965 34116 : std::copy (tmp_perm.begin (), tmp_perm.end (), perm.begin ());
7966 6019 : bitmap_set_bit (fully_folded, node_i);
7967 : }
7968 : else
7969 : {
7970 : /* Not MSG_MISSED because it would make no sense to users. */
7971 641 : if (dump_enabled_p ())
7972 46 : dump_printf_loc (MSG_NOTE, vect_location,
7973 : "failed to absorb input layouts into %p\n",
7974 : (void *) node);
7975 641 : change_vec_perm_layout (nullptr, perm, layout_i, layout_i);
7976 : }
7977 6660 : }
7978 : else
7979 : {
7980 149140 : gcc_assert (!SLP_TREE_LANE_PERMUTATION (node).exists ());
7981 149140 : auto &load_perm = SLP_TREE_LOAD_PERMUTATION (node);
7982 149140 : if (layout_i > 0)
7983 : /* ??? When we handle non-bijective permutes the idea
7984 : is that we can force the load-permutation to be
7985 : { min, min + 1, min + 2, ... max }. But then the
7986 : scalar defs might no longer match the lane content
7987 : which means wrong-code with live lane vectorization.
7988 : So we possibly have to have NULL entries for those. */
7989 23423 : vect_slp_permute (m_perms[layout_i], load_perm, true);
7990 : }
7991 : }
7992 :
7993 : /* Do this before any nodes disappear, since it involves a walk
7994 : over the leaves. */
7995 12669 : remove_redundant_permutations ();
7996 :
7997 : /* Replace each child with a correctly laid-out version. */
7998 193807 : for (unsigned int node_i : m_partitioned_nodes)
7999 : {
8000 : /* Skip nodes that have already been handled above. */
8001 155800 : if (bitmap_bit_p (fully_folded, node_i))
8002 6019 : continue;
8003 :
8004 149781 : auto &vertex = m_vertices[node_i];
8005 149781 : int in_layout_i = m_partitions[vertex.partition].layout;
8006 149781 : gcc_assert (in_layout_i >= 0);
8007 :
8008 : unsigned j;
8009 : slp_tree child;
8010 447763 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (vertex.node), j, child)
8011 : {
8012 183836 : if (!child)
8013 6017 : continue;
8014 :
8015 177819 : slp_tree new_child = get_result_with_layout (child, in_layout_i);
8016 177819 : if (new_child != child)
8017 : {
8018 5321 : vect_free_slp_tree (child);
8019 5321 : SLP_TREE_CHILDREN (vertex.node)[j] = new_child;
8020 5321 : new_child->refcnt += 1;
8021 : }
8022 : }
8023 : }
8024 12669 : }
8025 :
8026 : /* Elide load permutations that are not necessary. Such permutations might
8027 : be pre-existing, rather than created by the layout optimizations. */
8028 :
8029 : void
8030 714431 : vect_optimize_slp_pass::remove_redundant_permutations ()
8031 : {
8032 4735974 : for (unsigned int node_i : m_leafs)
8033 : {
8034 2592681 : slp_tree node = m_vertices[node_i].node;
8035 2592681 : if (!SLP_TREE_LOAD_PERMUTATION (node).exists ())
8036 1961691 : continue;
8037 :
8038 : /* In basic block vectorization we allow any subchain of an interleaving
8039 : chain.
8040 : FORNOW: not in loop SLP because of realignment complications. */
8041 630990 : if (is_a <bb_vec_info> (m_vinfo))
8042 : {
8043 184018 : bool subchain_p = true;
8044 : stmt_vec_info next_load_info = NULL;
8045 : stmt_vec_info load_info;
8046 : unsigned j;
8047 184018 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), j, load_info)
8048 : {
8049 152219 : if (j != 0
8050 152219 : && (next_load_info != load_info
8051 66339 : || ! load_info
8052 66339 : || DR_GROUP_GAP (load_info) != 1))
8053 : {
8054 : subchain_p = false;
8055 : break;
8056 : }
8057 121121 : next_load_info = DR_GROUP_NEXT_ELEMENT (load_info);
8058 : }
8059 62897 : if (subchain_p)
8060 : {
8061 31799 : SLP_TREE_LOAD_PERMUTATION (node).release ();
8062 31799 : continue;
8063 : }
8064 : }
8065 : else
8066 : {
8067 568093 : loop_vec_info loop_vinfo = as_a<loop_vec_info> (m_vinfo);
8068 568093 : bool this_load_permuted = !vect_load_perm_consecutive_p (node, 0);
8069 : /* When this isn't a grouped access we know it's single element
8070 : and contiguous. */
8071 568093 : if (!STMT_VINFO_GROUPED_ACCESS (SLP_TREE_SCALAR_STMTS (node)[0]))
8072 : {
8073 446659 : if (!this_load_permuted
8074 446659 : && (known_eq (LOOP_VINFO_VECT_FACTOR (loop_vinfo), 1U)
8075 445898 : || SLP_TREE_LANES (node) == 1))
8076 445900 : SLP_TREE_LOAD_PERMUTATION (node).release ();
8077 446659 : continue;
8078 : }
8079 121434 : stmt_vec_info first_stmt_info
8080 121434 : = DR_GROUP_FIRST_ELEMENT (SLP_TREE_SCALAR_STMTS (node)[0]);
8081 121938 : if (!this_load_permuted
8082 : /* The load requires permutation when unrolling exposes
8083 : a gap either because the group is larger than the SLP
8084 : group-size or because there is a gap between the groups. */
8085 121434 : && (known_eq (LOOP_VINFO_VECT_FACTOR (loop_vinfo), 1U)
8086 98935 : || ((SLP_TREE_LANES (node) == DR_GROUP_SIZE (first_stmt_info))
8087 136 : && DR_GROUP_GAP (first_stmt_info) == 0)))
8088 : {
8089 504 : SLP_TREE_LOAD_PERMUTATION (node).release ();
8090 504 : continue;
8091 : }
8092 : }
8093 : }
8094 714431 : }
8095 :
8096 : /* Print the partition graph and layout information to the dump file. */
8097 :
8098 : void
8099 684 : vect_optimize_slp_pass::dump ()
8100 : {
8101 684 : dump_printf_loc (MSG_NOTE, vect_location,
8102 : "SLP optimize permutations:\n");
8103 1381 : for (unsigned int layout_i = 1; layout_i < m_perms.length (); ++layout_i)
8104 : {
8105 697 : dump_printf_loc (MSG_NOTE, vect_location, " %d: { ", layout_i);
8106 697 : const char *sep = "";
8107 5938 : for (unsigned int idx : m_perms[layout_i])
8108 : {
8109 3847 : dump_printf (MSG_NOTE, "%s%d", sep, idx);
8110 3847 : sep = ", ";
8111 : }
8112 697 : dump_printf (MSG_NOTE, " }\n");
8113 : }
8114 684 : dump_printf_loc (MSG_NOTE, vect_location,
8115 : "SLP optimize partitions:\n");
8116 5736 : for (unsigned int partition_i = 0; partition_i < m_partitions.length ();
8117 : ++partition_i)
8118 : {
8119 5052 : auto &partition = m_partitions[partition_i];
8120 5052 : dump_printf_loc (MSG_NOTE, vect_location, " -------------\n");
8121 5052 : dump_printf_loc (MSG_NOTE, vect_location,
8122 : " partition %d (layout %d):\n",
8123 : partition_i, partition.layout);
8124 5052 : dump_printf_loc (MSG_NOTE, vect_location, " nodes:\n");
8125 10338 : for (unsigned int order_i = partition.node_begin;
8126 10338 : order_i < partition.node_end; ++order_i)
8127 : {
8128 5286 : auto &vertex = m_vertices[m_partitioned_nodes[order_i]];
8129 10572 : dump_printf_loc (MSG_NOTE, vect_location, " - %p:\n",
8130 5286 : (void *) vertex.node);
8131 5286 : dump_printf_loc (MSG_NOTE, vect_location,
8132 : " weight: %f\n",
8133 : vertex.weight.to_double ());
8134 5286 : if (vertex.out_degree)
8135 4134 : dump_printf_loc (MSG_NOTE, vect_location,
8136 : " out weight: %f (degree %d)\n",
8137 : vertex.out_weight.to_double (),
8138 : vertex.out_degree);
8139 5286 : if (SLP_TREE_PERMUTE_P (vertex.node))
8140 506 : dump_printf_loc (MSG_NOTE, vect_location,
8141 : " op: VEC_PERM_EXPR\n");
8142 4780 : else if (auto rep = SLP_TREE_REPRESENTATIVE (vertex.node))
8143 4762 : dump_printf_loc (MSG_NOTE, vect_location,
8144 : " op template: %G", rep->stmt);
8145 : }
8146 5052 : dump_printf_loc (MSG_NOTE, vect_location, " edges:\n");
8147 10338 : for (unsigned int order_i = partition.node_begin;
8148 10338 : order_i < partition.node_end; ++order_i)
8149 : {
8150 5286 : unsigned int node_i = m_partitioned_nodes[order_i];
8151 5286 : auto &vertex = m_vertices[node_i];
8152 15930 : auto print_edge = [&](graph_edge *, unsigned int other_node_i)
8153 : {
8154 10644 : auto &other_vertex = m_vertices[other_node_i];
8155 10644 : if (other_vertex.partition < vertex.partition)
8156 5322 : dump_printf_loc (MSG_NOTE, vect_location,
8157 : " - %p [%d] --> %p\n",
8158 5322 : (void *) other_vertex.node,
8159 : other_vertex.partition,
8160 5322 : (void *) vertex.node);
8161 : else
8162 5322 : dump_printf_loc (MSG_NOTE, vect_location,
8163 : " - %p --> [%d] %p\n",
8164 5322 : (void *) vertex.node,
8165 : other_vertex.partition,
8166 5322 : (void *) other_vertex.node);
8167 15930 : };
8168 5286 : for_each_partition_edge (node_i, print_edge);
8169 : }
8170 :
8171 15355 : for (unsigned int layout_i = 0; layout_i < m_perms.length (); ++layout_i)
8172 : {
8173 10303 : auto &layout_costs = partition_layout_costs (partition_i, layout_i);
8174 10303 : if (layout_costs.is_possible ())
8175 : {
8176 8514 : dump_printf_loc (MSG_NOTE, vect_location,
8177 : " layout %d:%s\n", layout_i,
8178 8514 : partition.layout == int (layout_i)
8179 : ? " (*)" : "");
8180 8514 : slpg_layout_cost combined_cost = layout_costs.in_cost;
8181 8514 : combined_cost.add_serial_cost (layout_costs.internal_cost);
8182 8514 : combined_cost.add_serial_cost (layout_costs.out_cost);
8183 : #define TEMPLATE "{depth: %f, total: %f}"
8184 8514 : dump_printf_loc (MSG_NOTE, vect_location,
8185 : " " TEMPLATE "\n",
8186 : layout_costs.in_cost.depth.to_double (),
8187 : layout_costs.in_cost.total.to_double ());
8188 8514 : dump_printf_loc (MSG_NOTE, vect_location,
8189 : " + " TEMPLATE "\n",
8190 : layout_costs.internal_cost.depth.to_double (),
8191 : layout_costs.internal_cost.total.to_double ());
8192 8514 : dump_printf_loc (MSG_NOTE, vect_location,
8193 : " + " TEMPLATE "\n",
8194 : layout_costs.out_cost.depth.to_double (),
8195 : layout_costs.out_cost.total.to_double ());
8196 8514 : dump_printf_loc (MSG_NOTE, vect_location,
8197 : " = " TEMPLATE "\n",
8198 : combined_cost.depth.to_double (),
8199 : combined_cost.total.to_double ());
8200 : #undef TEMPLATE
8201 : }
8202 : else
8203 1789 : dump_printf_loc (MSG_NOTE, vect_location,
8204 : " layout %d: rejected\n", layout_i);
8205 : }
8206 : }
8207 684 : }
8208 :
8209 : /* Masked load lanes discovery. */
8210 :
8211 : void
8212 714431 : vect_optimize_slp_pass::decide_masked_load_lanes ()
8213 : {
8214 7379317 : for (auto v : m_vertices)
8215 : {
8216 5236024 : slp_tree node = v.node;
8217 5236024 : if (SLP_TREE_DEF_TYPE (node) != vect_internal_def
8218 3669285 : || SLP_TREE_PERMUTE_P (node))
8219 1707702 : continue;
8220 3528322 : stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
8221 1700275 : if (! STMT_VINFO_GROUPED_ACCESS (stmt_info)
8222 : /* The mask has to be uniform. */
8223 1001619 : || STMT_VINFO_SLP_VECT_ONLY (stmt_info)
8224 1001541 : || ! is_a <gcall *> (STMT_VINFO_STMT (stmt_info))
8225 3528407 : || ! gimple_call_internal_p (STMT_VINFO_STMT (stmt_info),
8226 : IFN_MASK_LOAD))
8227 3528289 : continue;
8228 33 : stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
8229 66 : if (STMT_VINFO_STRIDED_P (stmt_info)
8230 33 : || compare_step_with_zero (m_vinfo, stmt_info) <= 0
8231 63 : || vect_load_lanes_supported (SLP_TREE_VECTYPE (node),
8232 30 : DR_GROUP_SIZE (stmt_info),
8233 : true) == IFN_LAST)
8234 33 : continue;
8235 :
8236 : /* Uniform masks need to be suitably represented. */
8237 0 : slp_tree mask = SLP_TREE_CHILDREN (node)[0];
8238 0 : if (!SLP_TREE_PERMUTE_P (mask)
8239 0 : || SLP_TREE_CHILDREN (mask).length () != 1)
8240 0 : continue;
8241 0 : bool match = true;
8242 0 : for (auto perm : SLP_TREE_LANE_PERMUTATION (mask))
8243 0 : if (perm.first != 0 || perm.second != 0)
8244 : {
8245 : match = false;
8246 : break;
8247 : }
8248 0 : if (!match)
8249 0 : continue;
8250 :
8251 : /* Now see if the consumer side matches. */
8252 0 : for (graph_edge *pred = m_slpg->vertices[node->vertex].pred;
8253 0 : pred; pred = pred->pred_next)
8254 : {
8255 0 : slp_tree pred_node = m_vertices[pred->src].node;
8256 : /* All consumers should be a permute with a single outgoing lane. */
8257 0 : if (!SLP_TREE_PERMUTE_P (pred_node)
8258 0 : || SLP_TREE_LANES (pred_node) != 1)
8259 : {
8260 : match = false;
8261 : break;
8262 : }
8263 0 : gcc_assert (SLP_TREE_CHILDREN (pred_node).length () == 1);
8264 : }
8265 0 : if (!match)
8266 0 : continue;
8267 : /* Now we can mark the nodes as to use load lanes. */
8268 0 : node->ldst_lanes = true;
8269 0 : for (graph_edge *pred = m_slpg->vertices[node->vertex].pred;
8270 0 : pred; pred = pred->pred_next)
8271 0 : m_vertices[pred->src].node->ldst_lanes = true;
8272 : /* The catch is we have to massage the mask. We have arranged
8273 : analyzed uniform masks to be represented by a splat VEC_PERM
8274 : which we can now simply elide as we cannot easily re-do SLP
8275 : discovery here. */
8276 0 : slp_tree new_mask = SLP_TREE_CHILDREN (mask)[0];
8277 0 : SLP_TREE_REF_COUNT (new_mask)++;
8278 0 : SLP_TREE_CHILDREN (node)[0] = new_mask;
8279 0 : vect_free_slp_tree (mask);
8280 : }
8281 714431 : }
8282 :
8283 : /* Perform legitimizing attempts. This is intended to improve the
8284 : situation when layout 0 is not valid which is a situation the cost
8285 : based propagation does not handle well.
8286 : Return true if further layout optimization is possible, false if
8287 : the layout configuration should be considered final. */
8288 :
8289 : bool
8290 12669 : vect_optimize_slp_pass::legitimize ()
8291 : {
8292 : /* Perform a very simple legitimizing attempt by attempting to choose
8293 : a single layout for all partitions that will make all permutations
8294 : a noop. That should also be the optimal layout choice in case
8295 : layout zero is legitimate.
8296 : ??? Disconnected components of the SLP graph could have distinct
8297 : single layouts. */
8298 12669 : int single_layout_i = -1;
8299 12669 : unsigned deferred_up_to = -1U;
8300 40000 : for (unsigned partition_i = 0; partition_i < m_partitions.length ();
8301 : ++partition_i)
8302 : {
8303 33935 : auto &partition = m_partitions[partition_i];
8304 33935 : if (single_layout_i == -1)
8305 : {
8306 16675 : single_layout_i = partition.layout;
8307 16675 : deferred_up_to = partition_i;
8308 : }
8309 17260 : else if (partition.layout == single_layout_i || partition.layout == -1)
8310 : ;
8311 : else
8312 : single_layout_i = 0;
8313 30660 : if (single_layout_i == 0)
8314 : return true;
8315 :
8316 27416 : if (single_layout_i != -1
8317 27416 : && !is_compatible_layout (partition, single_layout_i))
8318 : return true;
8319 : }
8320 :
8321 6065 : if (single_layout_i <= 0)
8322 : return true;
8323 :
8324 6645 : for (unsigned partition_i = 0; partition_i < deferred_up_to; ++partition_i)
8325 597 : if (!is_compatible_layout (m_partitions[partition_i],
8326 : single_layout_i))
8327 : return true;
8328 :
8329 18865 : for (unsigned partition_i = 0; partition_i < m_partitions.length ();
8330 : ++partition_i)
8331 : {
8332 12817 : auto &partition = m_partitions[partition_i];
8333 12817 : partition.layout = single_layout_i;
8334 : }
8335 :
8336 : return false;
8337 : }
8338 :
8339 : /* Main entry point for the SLP graph optimization pass. */
8340 :
8341 : void
8342 714431 : vect_optimize_slp_pass::run ()
8343 : {
8344 714431 : build_graph ();
8345 714431 : create_partitions ();
8346 714431 : start_choosing_layouts ();
8347 714431 : if (m_perms.length () > 1)
8348 : {
8349 12669 : if (legitimize ())
8350 : {
8351 6621 : forward_pass ();
8352 6621 : backward_pass ();
8353 : }
8354 12669 : if (dump_enabled_p ())
8355 684 : dump ();
8356 12669 : materialize ();
8357 51268 : while (!m_perms.is_empty ())
8358 25930 : m_perms.pop ().release ();
8359 : }
8360 : else
8361 701762 : remove_redundant_permutations ();
8362 714431 : free_graph (m_slpg);
8363 714431 : build_graph ();
8364 714431 : decide_masked_load_lanes ();
8365 714431 : free_graph (m_slpg);
8366 714431 : }
8367 :
8368 : /* Apply CSE to NODE and its children using BST_MAP. */
8369 :
8370 : static void
8371 5653171 : vect_cse_slp_nodes (scalar_stmts_to_slp_tree_map_t *bst_map, slp_tree& node)
8372 : {
8373 5653171 : bool put_p = false;
8374 5653171 : if (SLP_TREE_DEF_TYPE (node) == vect_internal_def
8375 : /* Besides some VEC_PERM_EXPR, two-operator nodes also
8376 : lack scalar stmts and thus CSE doesn't work via bst_map. Ideally
8377 : we'd have sth that works for all internal and external nodes. */
8378 5653171 : && !SLP_TREE_SCALAR_STMTS (node).is_empty ())
8379 : {
8380 4058191 : slp_tree *leader = bst_map->get (SLP_TREE_SCALAR_STMTS (node));
8381 4058191 : if (leader)
8382 : {
8383 : /* We've visited this node already. */
8384 420326 : if (!*leader || *leader == node)
8385 : return;
8386 :
8387 4320 : if (dump_enabled_p ())
8388 912 : dump_printf_loc (MSG_NOTE, vect_location,
8389 : "re-using SLP tree %p for %p\n",
8390 : (void *)*leader, (void *)node);
8391 4320 : vect_free_slp_tree (node);
8392 4320 : (*leader)->refcnt += 1;
8393 4320 : node = *leader;
8394 4320 : return;
8395 : }
8396 :
8397 : /* Avoid creating a cycle by populating the map only after recursion. */
8398 3637865 : bst_map->put (SLP_TREE_SCALAR_STMTS (node).copy (), nullptr);
8399 3637865 : node->refcnt += 1;
8400 3637865 : put_p = true;
8401 : /* And recurse. */
8402 : }
8403 :
8404 15638322 : for (slp_tree &child : SLP_TREE_CHILDREN (node))
8405 4577299 : if (child)
8406 4120000 : vect_cse_slp_nodes (bst_map, child);
8407 :
8408 : /* Now record the node for CSE in other siblings. */
8409 5232845 : if (put_p)
8410 3637865 : *bst_map->get (SLP_TREE_SCALAR_STMTS (node)) = node;
8411 : }
8412 :
8413 : /* Associate stmts with possible starts of a subset of lanes of NODE
8414 : in PART_STARTS. */
8415 :
8416 : static void
8417 2151585 : vect_cse_gather_part_starts (hash_set<slp_tree> &visited,
8418 : vec<vec<slp_tree>> part_starts, slp_tree node)
8419 : {
8420 : /* CSEing external nodes complicates scheduling since we materialize
8421 : those at the latest position, so avoid that. */
8422 2151585 : if (SLP_TREE_DEF_TYPE (node) != vect_internal_def
8423 2151585 : || visited.add (node))
8424 : return;
8425 :
8426 : /* Besides some VEC_PERM_EXPR, two-operator nodes also lack scalar stmts
8427 : and thus CSE doesn't work. For now gather two-lane aligned starts
8428 : of nodes with a multiple of two number of lanes. */
8429 1155140 : if (!SLP_TREE_SCALAR_STMTS (node).is_empty ()
8430 1147570 : && SLP_TREE_LANES (node) > 2
8431 149595 : && (SLP_TREE_LANES (node) & 1) == 0)
8432 : {
8433 149595 : auto_vec<unsigned, 8> uids;
8434 622675 : for (unsigned i = 0; i < SLP_TREE_LANES (node); i += 2)
8435 : {
8436 473080 : stmt_vec_info s = SLP_TREE_SCALAR_STMTS (node)[i];
8437 473080 : if (!s)
8438 0 : continue;
8439 473080 : unsigned uid = gimple_uid (s->stmt);
8440 473080 : if (!uids.contains (uid))
8441 : {
8442 469079 : uids.safe_push (uid);
8443 469079 : part_starts[uid].safe_push (node);
8444 : }
8445 : }
8446 149595 : }
8447 :
8448 4501727 : for (slp_tree &child : SLP_TREE_CHILDREN (node))
8449 1321703 : if (child)
8450 1321703 : vect_cse_gather_part_starts (visited, part_starts, child);
8451 : }
8452 :
8453 : /* Apply CSE to NODE and its children using lowparts of nodes in BST_MAP. */
8454 :
8455 : static void
8456 2148020 : vect_cse_slp_node_parts (hash_set<slp_tree> &visited,
8457 : const vec<vec<slp_tree>> part_starts,
8458 : vec<slp_tree> &drops, slp_tree node)
8459 : {
8460 2148020 : if (SLP_TREE_DEF_TYPE (node) != vect_internal_def
8461 2148020 : || visited.add (node))
8462 : return;
8463 :
8464 : /* Besides some VEC_PERM_EXPR, two-operator nodes also
8465 : lack scalar stmts and thus CSE doesn't work. */
8466 1153498 : unsigned HOST_WIDE_INT c;
8467 1153498 : if (!SLP_TREE_SCALAR_STMTS (node).is_empty ()
8468 1145932 : && SLP_TREE_SCALAR_STMTS (node)[0]
8469 : /* Avoid touching loads which need care with load permutations
8470 : and specialities like load-lane representations. */
8471 1145932 : && (SLP_TREE_PERMUTE_P (node)
8472 1138248 : || !STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (node))))
8473 36828 : for (slp_tree cand
8474 431555 : : part_starts[gimple_uid (SLP_TREE_SCALAR_STMTS (node)[0]->stmt)])
8475 : /* ??? There is a possible ordering/optimality problem in that
8476 : the CSE then can keep a wider feeding live even though it itself
8477 : becomes dead by means of CSE. Which might be solvable by doing
8478 : the CSE in a wide-to-narrow order. */
8479 37290 : if (SLP_TREE_LANES (cand) > SLP_TREE_LANES (node)
8480 : /* We can do high/lo extracts and full vector copies. */
8481 : && constant_multiple_p
8482 4633 : (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (cand)),
8483 37780 : TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (node)), &c)
8484 41923 : && c <= 2)
8485 : {
8486 4143 : unsigned HOST_WIDE_INT s;
8487 4143 : bool const_p
8488 4143 : = TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (node)).is_constant (&s);
8489 4143 : unsigned i;
8490 14870 : for (i = 0; i <= SLP_TREE_LANES (cand) - SLP_TREE_LANES (node);)
8491 : {
8492 : unsigned j;
8493 15833 : for (j = 0; j < SLP_TREE_LANES (node); ++j)
8494 15371 : if (!SLP_TREE_SCALAR_STMTS (node)[j]
8495 15371 : || (SLP_TREE_SCALAR_STMTS (cand)[i+j]
8496 15371 : != SLP_TREE_SCALAR_STMTS (node)[j]))
8497 : break;
8498 11189 : if (j == SLP_TREE_LANES (node))
8499 : break;
8500 10727 : if (!const_p)
8501 : {
8502 : i = SLP_TREE_LANES (cand);
8503 : break;
8504 : }
8505 : /* We can extract only aligned on node vector type boundary. */
8506 10727 : i += s;
8507 : }
8508 4143 : if (i > SLP_TREE_LANES (cand) - SLP_TREE_LANES (node))
8509 3681 : continue;
8510 : /* Found node within cand at i. Put a permute in place
8511 : of it, selecting the subset from cand. */
8512 462 : if (dump_enabled_p ())
8513 26 : dump_printf (MSG_NOTE, "CSEd node %p as %spart of node %p\n",
8514 : (void *)node, i == 0 ? "low" : "high", (void *)cand);
8515 2277 : for (slp_tree child : SLP_TREE_CHILDREN (node))
8516 : /* Delay SLP tree release since we might still reference a node
8517 : from the part_starts map. */
8518 891 : drops.safe_push (child);
8519 462 : SLP_TREE_CHILDREN (node).truncate (1);
8520 462 : SLP_TREE_REF_COUNT (cand)++;
8521 462 : SLP_TREE_CHILDREN (node)[0] = cand;
8522 462 : SLP_TREE_CODE (node) = VEC_PERM_EXPR;
8523 462 : SLP_TREE_REPRESENTATIVE (node) = NULL;
8524 462 : SLP_TREE_LANE_PERMUTATION (node).create (SLP_TREE_LANES (node));
8525 1988 : for (unsigned j = i; j < i + SLP_TREE_LANES (node); ++j)
8526 1064 : SLP_TREE_LANE_PERMUTATION (node).quick_push (std::make_pair (0, j));
8527 2148020 : return;
8528 : }
8529 :
8530 4492428 : for (slp_tree &child : SLP_TREE_CHILDREN (node))
8531 1318138 : if (child)
8532 1318138 : vect_cse_slp_node_parts (visited, part_starts, drops, child);
8533 : }
8534 :
8535 : /* Optimize the SLP graph of VINFO. */
8536 :
8537 : void
8538 1102221 : vect_optimize_slp (vec_info *vinfo)
8539 : {
8540 1102221 : if (vinfo->slp_instances.is_empty ())
8541 821514 : return;
8542 714431 : vect_optimize_slp_pass (vinfo).run ();
8543 :
8544 : /* Apply CSE again to nodes after permute optimization. */
8545 714431 : scalar_stmts_to_slp_tree_map_t *bst_map
8546 714431 : = new scalar_stmts_to_slp_tree_map_t ();
8547 :
8548 3676464 : for (auto inst : vinfo->slp_instances)
8549 1533171 : vect_cse_slp_nodes (bst_map, SLP_INSTANCE_TREE (inst));
8550 :
8551 714431 : release_scalar_stmts_to_slp_tree_map (bst_map);
8552 :
8553 714431 : if (!is_a <bb_vec_info> (vinfo))
8554 : return;
8555 :
8556 : /* Attempt to merge SLP sub-graphs that intersect in low or highparts of
8557 : each other. Build the reverse mapping from stmt to SLP node for
8558 : lanes starting at the low or high part.
8559 : ??? In the future we can extend this to do a two-step permute
8560 : and extract or extract and permute to put the high/low part in
8561 : place on the original vector or permute the hogh/low part to
8562 : match up the target lane order. */
8563 280707 : hash_set<slp_tree> visited;
8564 280707 : vec<vec<slp_tree>> start_for_part;
8565 561414 : start_for_part.create (vinfo->stmt_vec_infos.length () + 1);
8566 561414 : start_for_part.quick_grow_cleared (vinfo->stmt_vec_infos.length () + 1);
8567 1672003 : for (auto inst : vinfo->slp_instances)
8568 829882 : vect_cse_gather_part_starts (visited,
8569 : start_for_part, SLP_INSTANCE_TREE (inst));
8570 :
8571 : /* Now replace low/highpart copies with extracting permutes. */
8572 280707 : auto_vec<slp_tree> drops;
8573 280707 : visited.empty ();
8574 1672003 : for (auto inst : vinfo->slp_instances)
8575 829882 : vect_cse_slp_node_parts (visited, start_for_part, drops,
8576 : SLP_INSTANCE_TREE (inst));
8577 :
8578 : /* Now perform delayed releases of nodes. */
8579 282088 : for (slp_tree node : drops)
8580 891 : vect_free_slp_tree (node);
8581 :
8582 24202980 : for (auto v : start_for_part)
8583 23360859 : v.release ();
8584 280707 : start_for_part.release ();
8585 280707 : }
8586 :
8587 : /* Gather loads reachable from the individual SLP graph entries. */
8588 :
8589 : void
8590 1102221 : vect_gather_slp_loads (vec_info *vinfo)
8591 : {
8592 1102221 : unsigned i;
8593 1102221 : slp_instance instance;
8594 2635392 : FOR_EACH_VEC_ELT (vinfo->slp_instances, i, instance)
8595 : {
8596 1533171 : hash_set<slp_tree> visited;
8597 1533171 : vect_gather_slp_loads (SLP_INSTANCE_LOADS (instance),
8598 : SLP_INSTANCE_TREE (instance), visited);
8599 1533171 : }
8600 1102221 : }
8601 :
8602 : /* For NODE update VF based on the number of lanes and the vector types
8603 : used. */
8604 :
8605 : static void
8606 4483906 : vect_update_slp_vf_for_node (slp_tree node, poly_uint64 &vf,
8607 : hash_set<slp_tree> &visited)
8608 : {
8609 4483906 : if (!node || SLP_TREE_DEF_TYPE (node) != vect_internal_def)
8610 1621017 : return;
8611 3237591 : if (visited.add (node))
8612 : return;
8613 :
8614 10893762 : for (slp_tree child : SLP_TREE_CHILDREN (node))
8615 3687465 : vect_update_slp_vf_for_node (child, vf, visited);
8616 :
8617 : /* We do not visit SLP nodes for constants or externals - those neither
8618 : have a vector type set yet (vectorizable_* does this).
8619 : Note that when we stop using fixed size vectors externs and constants
8620 : shouldn't influence the (minimum) vectorization factor, instead
8621 : vectorizable_* should honor the vectorization factor when trying to
8622 : assign vector types to constants and externals and cause iteration
8623 : to a higher vectorization factor when required. */
8624 2862909 : tree vectype = SLP_TREE_VECTYPE (node);
8625 2862909 : if (!vectype)
8626 : /* OMP SIMD calls w/o LHS have no SLP_TREE_VECTYPE set. */
8627 : return;
8628 2862889 : poly_uint64 node_vf
8629 2862889 : = calculate_unrolling_factor (TYPE_VECTOR_SUBPARTS (vectype),
8630 : SLP_TREE_LANES (node));
8631 2862889 : vf = force_common_multiple (vf, node_vf);
8632 :
8633 : /* For permute nodes that are fed from externs or constants we have to
8634 : consider their number of lanes as well. Likewise for store-lanes. */
8635 2862889 : if (SLP_TREE_PERMUTE_P (node) || node->ldst_lanes)
8636 716487 : for (slp_tree child : SLP_TREE_CHILDREN (node))
8637 193002 : if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
8638 : {
8639 3607 : poly_uint64 child_vf
8640 3607 : = calculate_unrolling_factor (TYPE_VECTOR_SUBPARTS (vectype),
8641 : SLP_TREE_LANES (child));
8642 3607 : vf = force_common_multiple (vf, child_vf);
8643 : }
8644 : }
8645 :
8646 : /* For each possible SLP instance decide whether to SLP it and calculate overall
8647 : unrolling factor needed to SLP the loop. Return TRUE if decided to SLP at
8648 : least one instance. */
8649 :
8650 : bool
8651 500241 : vect_make_slp_decision (loop_vec_info loop_vinfo)
8652 : {
8653 500241 : unsigned int i;
8654 500241 : poly_uint64 unrolling_factor = 1;
8655 500241 : const vec<slp_instance> &slp_instances
8656 : = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
8657 500241 : slp_instance instance;
8658 500241 : int decided_to_slp = 0;
8659 :
8660 500241 : DUMP_VECT_SCOPE ("vect_make_slp_decision");
8661 :
8662 500241 : hash_set<slp_tree> visited;
8663 1796923 : FOR_EACH_VEC_ELT (slp_instances, i, instance)
8664 : {
8665 796441 : slp_tree root = SLP_INSTANCE_TREE (instance);
8666 :
8667 : /* All unroll factors have the form:
8668 :
8669 : GET_MODE_SIZE (vinfo->vector_mode) * X
8670 :
8671 : for some rational X, so they must have a common multiple. */
8672 796441 : vect_update_slp_vf_for_node (root, unrolling_factor, visited);
8673 :
8674 : /* If all instances ended up with vector(1) T roots make sure to
8675 : not vectorize. RVV for example relies on loop vectorization
8676 : when some instances are essentially kept scalar. See PR121048. */
8677 796441 : if (SLP_TREE_VECTYPE (root)
8678 796441 : && known_gt (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (root)), 1U))
8679 646970 : decided_to_slp++;
8680 : }
8681 :
8682 500241 : LOOP_VINFO_VECT_FACTOR (loop_vinfo) = unrolling_factor;
8683 :
8684 500241 : if (decided_to_slp && dump_enabled_p ())
8685 : {
8686 19502 : dump_printf_loc (MSG_NOTE, vect_location,
8687 : "Decided to SLP %d instances. Unrolling factor ",
8688 : decided_to_slp);
8689 19502 : dump_dec (MSG_NOTE, unrolling_factor);
8690 19502 : dump_printf (MSG_NOTE, "\n");
8691 : }
8692 :
8693 500241 : return (decided_to_slp > 0);
8694 500241 : }
8695 :
8696 : /* Initialize a bb_vec_info struct for the statements in BBS basic blocks. */
8697 :
8698 2296064 : _bb_vec_info::_bb_vec_info (vec<basic_block> _bbs, vec_info_shared *shared)
8699 : : vec_info (vec_info::bb, shared),
8700 2296064 : roots (vNULL)
8701 : {
8702 : /* The region we are operating on. bbs[0] is the entry, excluding
8703 : its PHI nodes. In the future we might want to track an explicit
8704 : entry edge to cover bbs[0] PHI nodes and have a region entry
8705 : insert location. */
8706 2296064 : bbs = _bbs.address ();
8707 2296064 : nbbs = _bbs.length ();
8708 :
8709 18371992 : for (unsigned i = 0; i < nbbs; ++i)
8710 : {
8711 16075928 : if (i != 0)
8712 20878321 : for (gphi_iterator si = gsi_start_phis (bbs[i]); !gsi_end_p (si);
8713 7098457 : gsi_next (&si))
8714 : {
8715 7098457 : gphi *phi = si.phi ();
8716 7098457 : gimple_set_uid (phi, 0);
8717 7098457 : add_stmt (phi);
8718 : }
8719 32151856 : for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]);
8720 148199252 : !gsi_end_p (gsi); gsi_next (&gsi))
8721 : {
8722 132123324 : gimple *stmt = gsi_stmt (gsi);
8723 132123324 : gimple_set_uid (stmt, 0);
8724 132123324 : if (is_gimple_debug (stmt) || is_a <glabel *> (stmt))
8725 85669211 : continue;
8726 46454113 : add_stmt (stmt);
8727 : }
8728 : }
8729 2296064 : }
8730 :
8731 :
8732 : /* Free BB_VINFO struct, as well as all the stmt_vec_info structs of all the
8733 : stmts in the basic block. */
8734 :
8735 2296064 : _bb_vec_info::~_bb_vec_info ()
8736 : {
8737 : /* Reset region marker. */
8738 18371992 : for (unsigned i = 0; i < nbbs; ++i)
8739 : {
8740 16075928 : if (i != 0)
8741 20894498 : for (gphi_iterator si = gsi_start_phis (bbs[i]); !gsi_end_p (si);
8742 7114634 : gsi_next (&si))
8743 : {
8744 7114634 : gphi *phi = si.phi ();
8745 7114634 : gimple_set_uid (phi, -1);
8746 : }
8747 32151856 : for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]);
8748 148167506 : !gsi_end_p (gsi); gsi_next (&gsi))
8749 : {
8750 132091578 : gimple *stmt = gsi_stmt (gsi);
8751 132091578 : gimple_set_uid (stmt, -1);
8752 : }
8753 : }
8754 :
8755 3635887 : for (unsigned i = 0; i < roots.length (); ++i)
8756 : {
8757 1339823 : roots[i].stmts.release ();
8758 1339823 : roots[i].roots.release ();
8759 1339823 : roots[i].remain.release ();
8760 : }
8761 2296064 : roots.release ();
8762 2296064 : }
8763 :
8764 : /* Subroutine of vect_slp_analyze_node_operations. Handle the root of NODE,
8765 : given then that child nodes have already been processed, and that
8766 : their def types currently match their SLP node's def type. */
8767 :
8768 : static bool
8769 2720677 : vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
8770 : slp_instance node_instance,
8771 : stmt_vector_for_cost *cost_vec)
8772 : {
8773 : /* Handle purely internal nodes. */
8774 2720677 : if (SLP_TREE_PERMUTE_P (node))
8775 : {
8776 82888 : gcc_checking_assert (!SLP_TREE_REPRESENTATIVE (node));
8777 82888 : if (!vectorizable_slp_permutation (vinfo, NULL, node, cost_vec))
8778 : return false;
8779 :
8780 : stmt_vec_info slp_stmt_info;
8781 : unsigned int i;
8782 204526 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, slp_stmt_info)
8783 : {
8784 123267 : if (slp_stmt_info
8785 117597 : && STMT_VINFO_LIVE_P (slp_stmt_info)
8786 123267 : && !vectorizable_live_operation (vinfo, slp_stmt_info, node,
8787 : node_instance, i,
8788 : false, cost_vec))
8789 : return false;
8790 : }
8791 81259 : SLP_TREE_TYPE (node) = permute_info_type;
8792 81259 : return true;
8793 : }
8794 :
8795 2637789 : return vect_analyze_stmt (vinfo, node, node_instance, cost_vec);
8796 : }
8797 :
8798 : static int
8799 1930613 : sort_ints (const void *a_, const void *b_)
8800 : {
8801 1930613 : int a = *(const int *)a_;
8802 1930613 : int b = *(const int *)b_;
8803 1930613 : return a - b;
8804 : }
8805 :
8806 : /* Verify if we can externalize a set of internal defs. */
8807 :
8808 : static bool
8809 410199 : vect_slp_can_convert_to_external (const vec<stmt_vec_info> &stmts)
8810 : {
8811 : /* Constant generation uses get_later_stmt which can only handle
8812 : defs from the same BB or a set of defs that can be ordered
8813 : with a dominance query. */
8814 410199 : basic_block bb = NULL;
8815 410199 : bool all_same = true;
8816 410199 : auto_vec<int> bbs;
8817 820398 : bbs.reserve_exact (stmts.length ());
8818 2197217 : for (stmt_vec_info stmt : stmts)
8819 : {
8820 966620 : if (!stmt)
8821 : return false;
8822 966620 : else if (!bb)
8823 410199 : bb = gimple_bb (stmt->stmt);
8824 556421 : else if (gimple_bb (stmt->stmt) != bb)
8825 187555 : all_same = false;
8826 966620 : bbs.quick_push (gimple_bb (stmt->stmt)->index);
8827 : }
8828 410199 : if (all_same)
8829 : return true;
8830 :
8831 : /* Produce a vector of unique BB indexes for the defs. */
8832 140856 : bbs.qsort (sort_ints);
8833 140856 : unsigned i, j;
8834 340116 : for (i = 1, j = 1; i < bbs.length (); ++i)
8835 199260 : if (bbs[i] != bbs[j-1])
8836 150422 : bbs[j++] = bbs[i];
8837 140856 : gcc_assert (j >= 2);
8838 140856 : bbs.truncate (j);
8839 :
8840 281712 : if (bbs.length () == 2)
8841 137334 : return (dominated_by_p (CDI_DOMINATORS,
8842 137334 : BASIC_BLOCK_FOR_FN (cfun, bbs[0]),
8843 137334 : BASIC_BLOCK_FOR_FN (cfun, bbs[1]))
8844 268414 : || dominated_by_p (CDI_DOMINATORS,
8845 131080 : BASIC_BLOCK_FOR_FN (cfun, bbs[1]),
8846 131080 : BASIC_BLOCK_FOR_FN (cfun, bbs[0])));
8847 :
8848 : /* ??? For more than two BBs we can sort the vector and verify the
8849 : result is a total order. But we can't use vec::qsort with a
8850 : compare function using a dominance query since there's no way to
8851 : signal failure and any fallback for an unordered pair would
8852 : fail qsort_chk later.
8853 : For now simply hope that ordering after BB index provides the
8854 : best candidate total order. If required we can implement our
8855 : own mergesort or export an entry without checking. */
8856 426754 : for (unsigned i = 1; i < bbs.length (); ++i)
8857 13064 : if (!dominated_by_p (CDI_DOMINATORS,
8858 13064 : BASIC_BLOCK_FOR_FN (cfun, bbs[i]),
8859 13064 : BASIC_BLOCK_FOR_FN (cfun, bbs[i-1])))
8860 : return false;
8861 :
8862 : return true;
8863 410199 : }
8864 :
8865 : /* Try to build NODE from scalars, returning true on success.
8866 : NODE_INSTANCE is the SLP instance that contains NODE. */
8867 :
8868 : static bool
8869 639834 : vect_slp_convert_to_external (vec_info *vinfo, slp_tree node,
8870 : slp_instance node_instance)
8871 : {
8872 639834 : stmt_vec_info stmt_info;
8873 639834 : unsigned int i;
8874 :
8875 639834 : if (!is_a <bb_vec_info> (vinfo)
8876 90312 : || node == SLP_INSTANCE_TREE (node_instance)
8877 30591 : || !SLP_TREE_SCALAR_STMTS (node).exists ()
8878 30550 : || vect_contains_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (node))
8879 : /* Force the mask use to be built from scalars instead. */
8880 23026 : || VECTOR_BOOLEAN_TYPE_P (SLP_TREE_VECTYPE (node))
8881 662623 : || !vect_slp_can_convert_to_external (SLP_TREE_SCALAR_STMTS (node)))
8882 : return false;
8883 :
8884 22789 : if (dump_enabled_p ())
8885 82 : dump_printf_loc (MSG_NOTE, vect_location,
8886 : "Building vector operands of %p from scalars instead\n",
8887 : (void *) node);
8888 :
8889 : /* Don't remove and free the child nodes here, since they could be
8890 : referenced by other structures. The analysis and scheduling phases
8891 : (need to) ignore child nodes of anything that isn't vect_internal_def. */
8892 22789 : unsigned int group_size = SLP_TREE_LANES (node);
8893 22789 : SLP_TREE_DEF_TYPE (node) = vect_external_def;
8894 : /* Invariants get their vector type from the uses. */
8895 22789 : SLP_TREE_VECTYPE (node) = NULL_TREE;
8896 22789 : SLP_TREE_SCALAR_OPS (node).safe_grow (group_size, true);
8897 22789 : SLP_TREE_LOAD_PERMUTATION (node).release ();
8898 103418 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
8899 : {
8900 57840 : tree lhs = gimple_get_lhs (vect_orig_stmt (stmt_info)->stmt);
8901 57840 : SLP_TREE_SCALAR_OPS (node)[i] = lhs;
8902 : }
8903 : return true;
8904 : }
8905 :
8906 : /* Return true if all elements of the slice are the same. */
8907 : bool
8908 449109 : vect_scalar_ops_slice::all_same_p () const
8909 : {
8910 500892 : for (unsigned int i = 1; i < length; ++i)
8911 414141 : if (!operand_equal_p (op (0), op (i)))
8912 : return false;
8913 : return true;
8914 : }
8915 :
8916 : hashval_t
8917 423908 : vect_scalar_ops_slice_hash::hash (const value_type &s)
8918 : {
8919 423908 : hashval_t hash = 0;
8920 1625020 : for (unsigned i = 0; i < s.length; ++i)
8921 1201112 : hash = iterative_hash_expr (s.op (i), hash);
8922 423908 : return hash;
8923 : }
8924 :
8925 : bool
8926 232941 : vect_scalar_ops_slice_hash::equal (const value_type &s1,
8927 : const compare_type &s2)
8928 : {
8929 232941 : if (s1.length != s2.length)
8930 : return false;
8931 403665 : for (unsigned i = 0; i < s1.length; ++i)
8932 351985 : if (!operand_equal_p (s1.op (i), s2.op (i)))
8933 : return false;
8934 : return true;
8935 : }
8936 :
8937 : /* Like vect_get_num_copies but N copies of the vector might have
8938 : excess elements in the last vector. Returns false if *NVECTORS
8939 : cannot be computed. */
8940 :
8941 : static bool
8942 1595393 : vect_get_num_copies_for_invariant (vec_info *vinfo, slp_tree node,
8943 : unsigned *nvectors)
8944 : {
8945 1595393 : poly_uint64 vf;
8946 :
8947 1595393 : if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
8948 372508 : vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
8949 : else
8950 1222885 : vf = 1;
8951 1595393 : vf *= SLP_TREE_LANES (node);
8952 :
8953 1595393 : tree vectype = SLP_TREE_VECTYPE (node);
8954 1595393 : bool res = can_div_away_from_zero_p (vf, TYPE_VECTOR_SUBPARTS (vectype),
8955 : nvectors);
8956 1595393 : return res;
8957 : }
8958 :
8959 : /* Compute the prologue cost for invariant or constant operands represented
8960 : by NODE. */
8961 :
8962 : static void
8963 1093989 : vect_prologue_cost_for_slp (slp_tree node, unsigned nvectors,
8964 : stmt_vector_for_cost *cost_vec)
8965 : {
8966 : /* There's a special case of an existing vector, that costs nothing. */
8967 1093989 : if (SLP_TREE_SCALAR_OPS (node).length () == 0
8968 1093989 : && !SLP_TREE_VEC_DEFS (node).is_empty ())
8969 2277 : return;
8970 : /* Without looking at the actual initializer a vector of
8971 : constants can be implemented as load from the constant pool.
8972 : When all elements are the same we can use a splat. */
8973 1091712 : tree vectype = SLP_TREE_VECTYPE (node);
8974 1091712 : unsigned group_size = SLP_TREE_LANES (node);
8975 1091712 : unsigned HOST_WIDE_INT const_nunits;
8976 1091712 : unsigned nelt_limit;
8977 1091712 : auto ops = &SLP_TREE_SCALAR_OPS (node);
8978 1091712 : auto_vec<unsigned int> starts (nvectors);
8979 1091712 : if (TYPE_VECTOR_SUBPARTS (vectype).is_constant (&const_nunits)
8980 1091712 : && ! multiple_p (const_nunits, group_size))
8981 : {
8982 67361 : nelt_limit = const_nunits;
8983 67361 : hash_set<vect_scalar_ops_slice_hash> vector_ops;
8984 345603 : for (unsigned int i = 0; i < nvectors; ++i)
8985 210881 : if (!vector_ops.add ({ ops, i * nelt_limit, nelt_limit }))
8986 159201 : starts.quick_push (i * nelt_limit);
8987 67361 : }
8988 : else
8989 : {
8990 : /* If either the vector has variable length or the vectors
8991 : are composed of repeated whole groups we only need to
8992 : cost construction once. All vectors will be the same. */
8993 1024351 : nelt_limit = group_size;
8994 1024351 : starts.quick_push (0);
8995 : }
8996 : /* ??? We're just tracking whether vectors in a single node are the same.
8997 : Ideally we'd do something more global. */
8998 1091712 : bool passed = false;
8999 4458688 : for (unsigned int start : starts)
9000 : {
9001 1183552 : vect_cost_for_stmt kind;
9002 1183552 : if (SLP_TREE_DEF_TYPE (node) == vect_constant_def)
9003 : kind = vector_load;
9004 449109 : else if (vect_scalar_ops_slice { ops, start, nelt_limit }.all_same_p ())
9005 : kind = scalar_to_vec;
9006 : else
9007 362358 : kind = vec_construct;
9008 : /* The target cost hook has no idea which part of the SLP node
9009 : we are costing so avoid passing it down more than once. Pass
9010 : it to the first vec_construct or scalar_to_vec part since for those
9011 : the x86 backend tries to account for GPR to XMM register moves. */
9012 1183552 : record_stmt_cost (cost_vec, 1, kind, nullptr,
9013 1183552 : (kind != vector_load && !passed) ? node : nullptr,
9014 : vectype, 0, vect_prologue);
9015 1183552 : if (kind != vector_load)
9016 449109 : passed = true;
9017 : }
9018 1091712 : }
9019 :
9020 : /* Analyze statements contained in SLP tree NODE after recursively analyzing
9021 : the subtree. NODE_INSTANCE contains NODE and VINFO contains INSTANCE.
9022 :
9023 : Return true if the operations are supported. */
9024 :
9025 : static bool
9026 5050729 : vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
9027 : slp_instance node_instance,
9028 : hash_set<slp_tree> &visited_set,
9029 : vec<slp_tree> &visited_vec,
9030 : stmt_vector_for_cost *cost_vec)
9031 : {
9032 5050729 : int i, j;
9033 5050729 : slp_tree child;
9034 :
9035 : /* Costing and analysis of invariants is delayed. */
9036 5050729 : if (!node
9037 4657592 : || SLP_TREE_DEF_TYPE (node) == vect_constant_def
9038 3866256 : || SLP_TREE_DEF_TYPE (node) == vect_external_def)
9039 : return true;
9040 :
9041 3381038 : if (SLP_TREE_DEF_TYPE (node) == vect_uninitialized_def)
9042 : {
9043 5 : if (dump_enabled_p ())
9044 0 : dump_printf_loc (MSG_NOTE, vect_location,
9045 : "Failed cyclic SLP reference in %p\n", (void *) node);
9046 : return false;
9047 : }
9048 3381033 : gcc_assert (SLP_TREE_DEF_TYPE (node) == vect_internal_def);
9049 :
9050 : /* If we already analyzed the exact same set of scalar stmts we're done.
9051 : We share the generated vector stmts for those. */
9052 3381033 : if (visited_set.add (node))
9053 : return true;
9054 3082075 : visited_vec.safe_push (node);
9055 :
9056 3082075 : bool res = true;
9057 3082075 : unsigned visited_rec_start = visited_vec.length ();
9058 3082075 : unsigned cost_vec_rec_start = cost_vec->length ();
9059 3082075 : bool seen_non_constant_child = false;
9060 8925269 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
9061 : {
9062 3684578 : res = vect_slp_analyze_node_operations (vinfo, child, node_instance,
9063 : visited_set, visited_vec,
9064 : cost_vec);
9065 3684578 : if (!res)
9066 : break;
9067 3323394 : if (child && SLP_TREE_DEF_TYPE (child) != vect_constant_def)
9068 3323394 : seen_non_constant_child = true;
9069 : }
9070 : /* We're having difficulties scheduling nodes with just constant
9071 : operands and no scalar stmts since we then cannot compute a stmt
9072 : insertion place. */
9073 3082075 : if (res
9074 3082075 : && !seen_non_constant_child
9075 3082075 : && SLP_TREE_SCALAR_STMTS (node).is_empty ())
9076 : {
9077 214 : if (dump_enabled_p ())
9078 6 : dump_printf_loc (MSG_NOTE, vect_location,
9079 : "Cannot vectorize all-constant op node %p\n",
9080 : (void *) node);
9081 : res = false;
9082 : }
9083 :
9084 3081867 : if (res)
9085 2720677 : res = vect_slp_analyze_node_operations_1 (vinfo, node, node_instance,
9086 : cost_vec);
9087 : /* If analysis failed we have to pop all recursive visited nodes
9088 : plus ourselves. */
9089 3082075 : if (!res)
9090 : {
9091 3156782 : while (visited_vec.length () >= visited_rec_start)
9092 938557 : visited_set.remove (visited_vec.pop ());
9093 639834 : cost_vec->truncate (cost_vec_rec_start);
9094 : }
9095 :
9096 : /* When the node can be vectorized cost invariant nodes it references.
9097 : This is not done in DFS order to allow the referring node
9098 : vectorizable_* calls to nail down the invariant nodes vector type
9099 : and possibly unshare it if it needs a different vector type than
9100 : other referrers. */
9101 3082075 : if (res)
9102 9389088 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
9103 2968187 : if (child
9104 2647440 : && (SLP_TREE_DEF_TYPE (child) == vect_constant_def
9105 2647440 : || SLP_TREE_DEF_TYPE (child) == vect_external_def)
9106 : /* Perform usual caching, note code-generation still
9107 : code-gens these nodes multiple times but we expect
9108 : to CSE them later. */
9109 4102878 : && !visited_set.add (child))
9110 : {
9111 1131442 : visited_vec.safe_push (child);
9112 : /* ??? After auditing more code paths make a "default"
9113 : and push the vector type from NODE to all children
9114 : if it is not already set. */
9115 : /* Compute the number of vectors to be generated. */
9116 1131442 : tree vector_type = SLP_TREE_VECTYPE (child);
9117 1131442 : if (!vector_type)
9118 : {
9119 : /* Masked loads can have an undefined (default SSA definition)
9120 : else operand. We do not need to cost it. */
9121 37453 : vec<tree> ops = SLP_TREE_SCALAR_OPS (child);
9122 38884 : if (SLP_TREE_TYPE (node) == load_vec_info_type
9123 38884 : && ((ops.length ()
9124 1431 : && TREE_CODE (ops[0]) == SSA_NAME
9125 0 : && SSA_NAME_IS_DEFAULT_DEF (ops[0])
9126 0 : && VAR_P (SSA_NAME_VAR (ops[0])))
9127 1431 : || SLP_TREE_DEF_TYPE (child) == vect_constant_def))
9128 1431 : continue;
9129 :
9130 : /* For shifts with a scalar argument we don't need
9131 : to cost or code-generate anything.
9132 : ??? Represent this more explicitly. */
9133 36022 : gcc_assert (SLP_TREE_TYPE (node) == shift_vec_info_type
9134 : && j == 1);
9135 36022 : continue;
9136 36022 : }
9137 :
9138 : /* Make sure we can generate them and then cost them. */
9139 1093989 : unsigned nvectors;
9140 1093989 : if (!vect_get_num_copies_for_invariant (vinfo, node, &nvectors))
9141 : return false;
9142 1093989 : vect_prologue_cost_for_slp (child, nvectors, cost_vec);
9143 : }
9144 :
9145 : /* If this node or any of its children can't be vectorized, try pruning
9146 : the tree here rather than felling the whole thing. */
9147 639834 : if (!res && vect_slp_convert_to_external (vinfo, node, node_instance))
9148 : {
9149 : /* We'll need to revisit this for invariant costing and number
9150 : of vectorized stmt setting. */
9151 : res = true;
9152 : }
9153 :
9154 : return res;
9155 : }
9156 :
9157 : /* Mark lanes of NODE that are live outside of the basic-block vectorized
9158 : region and that can be vectorized using vectorizable_live_operation
9159 : with STMT_VINFO_LIVE_P. Not handled live operations will cause the
9160 : scalar code computing it to be retained. */
9161 :
9162 : static void
9163 998275 : vect_bb_slp_mark_live_stmts (bb_vec_info bb_vinfo, slp_tree node,
9164 : slp_instance instance,
9165 : stmt_vector_for_cost *cost_vec,
9166 : hash_set<stmt_vec_info> &svisited,
9167 : hash_set<slp_tree> &visited)
9168 : {
9169 998275 : if (visited.add (node))
9170 58328 : return;
9171 :
9172 : unsigned i;
9173 : stmt_vec_info stmt_info;
9174 : gimple *last_stmt = NULL;
9175 3371521 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
9176 : {
9177 2431574 : if (!stmt_info || svisited.contains (stmt_info))
9178 94739 : continue;
9179 2396034 : stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info);
9180 2396034 : if (STMT_VINFO_IN_PATTERN_P (orig_stmt_info)
9181 35609 : && STMT_VINFO_RELATED_STMT (orig_stmt_info) != stmt_info)
9182 : /* Only the pattern root stmt computes the original scalar value. */
9183 29649 : continue;
9184 2366385 : if (!PURE_SLP_STMT (orig_stmt_info))
9185 : /* Iff the stmt is not part of the vector coverage because it or
9186 : uses of it are used by SLP graph leafs as extern input there is
9187 : no point in trying to live code-generate from a vector stmt as
9188 : the scalar stmt will survive anyway. */
9189 29550 : continue;
9190 2336835 : bool mark_visited = true;
9191 2336835 : gimple *orig_stmt = orig_stmt_info->stmt;
9192 2336835 : ssa_op_iter op_iter;
9193 2336835 : def_operand_p def_p;
9194 5236927 : FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_stmt, op_iter, SSA_OP_DEF)
9195 : {
9196 : /* We have to verify whether we can insert the lane extract
9197 : before all uses. The following is a conservative approximation.
9198 : We cannot put this into vectorizable_live_operation because
9199 : iterating over all use stmts from inside a FOR_EACH_IMM_USE_STMT
9200 : doesn't work.
9201 : Note that while the fact that we emit code for loads at the
9202 : first load should make this a non-problem leafs we construct
9203 : from scalars are vectorized after the last scalar def.
9204 : ??? If we'd actually compute the insert location during
9205 : analysis we could use sth less conservative than the last
9206 : scalar stmt in the node for the dominance check. */
9207 : /* ??? What remains is "live" uses in vector CTORs in the same
9208 : SLP graph which is where those uses can end up code-generated
9209 : right after their definition instead of close to their original
9210 : use. But that would restrict us to code-generate lane-extracts
9211 : from the latest stmt in a node. So we compensate for this
9212 : during code-generation, simply not replacing uses for those
9213 : hopefully rare cases. */
9214 563257 : imm_use_iterator use_iter;
9215 :
9216 563257 : bool live_p = false;
9217 563257 : bool can_insert = true;
9218 563257 : use_operand_p use_p;
9219 1691009 : FOR_EACH_IMM_USE_FAST (use_p, use_iter, DEF_FROM_PTR (def_p))
9220 : {
9221 1135891 : gimple *use_stmt = USE_STMT (use_p);
9222 1135891 : stmt_vec_info use_stmt_info;
9223 1135891 : if (!(!is_gimple_debug (use_stmt)
9224 872314 : && (!(use_stmt_info = bb_vinfo->lookup_stmt (use_stmt))
9225 861816 : || !PURE_SLP_STMT (use_stmt_info))))
9226 929256 : continue;
9227 206635 : live_p = true;
9228 206635 : if (!last_stmt)
9229 64279 : last_stmt
9230 64529 : = (node->si ? node->si
9231 250 : : vect_find_last_scalar_stmt_in_slp (node)->stmt);
9232 206635 : if (is_a <gphi *> (use_stmt))
9233 : {
9234 72560 : if (!dominated_by_p (CDI_DOMINATORS,
9235 36280 : phi_arg_edge_from_use (use_p)->src,
9236 36280 : gimple_bb (last_stmt)))
9237 : can_insert = false;
9238 : }
9239 : /* As we instert after last_stmt it may not be the use_stmt
9240 : itself. */
9241 170355 : else if (last_stmt == use_stmt
9242 170355 : || !vect_stmt_dominates_stmt_p (last_stmt, use_stmt))
9243 : can_insert = false;
9244 : if (!can_insert)
9245 : {
9246 8139 : if (dump_enabled_p ())
9247 66 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
9248 : "Cannot determine insertion place for "
9249 : "lane extract of %T at node %p\n",
9250 : DEF_FROM_PTR (def_p), (void *)node);
9251 : can_insert = false;
9252 : break;
9253 : }
9254 563257 : }
9255 563257 : if (live_p && can_insert)
9256 : {
9257 : /* Only record a live stmt when we can replace all uses. We
9258 : record from which SLP tree we vectorize the uses, so we'll
9259 : cost once and can deal with the case that not all SLP nodes
9260 : may be suitable for code-generation of all live uses.
9261 : ??? But we never split up the work between multiple SLP
9262 : nodes. */
9263 101521 : STMT_VINFO_LIVE_P (stmt_info) = true;
9264 101521 : if (!vectorizable_live_operation (bb_vinfo, stmt_info, node,
9265 : instance, i, false, cost_vec))
9266 : {
9267 0 : STMT_VINFO_LIVE_P (stmt_info) = false;
9268 0 : mark_visited = false;
9269 : }
9270 : }
9271 : }
9272 2336835 : if (mark_visited)
9273 2336835 : svisited.add (stmt_info);
9274 : }
9275 :
9276 : slp_tree child;
9277 2751821 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
9278 984250 : if (child && SLP_TREE_DEF_TYPE (child) == vect_internal_def)
9279 281329 : vect_bb_slp_mark_live_stmts (bb_vinfo, child, instance, cost_vec,
9280 : svisited, visited);
9281 : }
9282 :
9283 : /* Traverse all slp instances of BB_VINFO, and mark lanes of every node that
9284 : are live outside of the basic-block vectorized region and that can be
9285 : vectorized using vectorizable_live_operation with STMT_VINFO_LIVE_P. */
9286 :
9287 : static void
9288 246835 : vect_bb_slp_mark_live_stmts (bb_vec_info bb_vinfo)
9289 : {
9290 246835 : if (bb_vinfo->slp_instances.is_empty ())
9291 0 : return;
9292 :
9293 246835 : hash_set<slp_tree> visited;
9294 246835 : hash_set<stmt_vec_info> svisited;
9295 1457451 : for (slp_instance instance : bb_vinfo->slp_instances)
9296 : {
9297 716946 : if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ())
9298 50959 : STMT_VINFO_LIVE_P (SLP_INSTANCE_ROOT_STMTS (instance)[0]) = true;
9299 716946 : vect_location = instance->location ();
9300 716946 : vect_bb_slp_mark_live_stmts (bb_vinfo, SLP_INSTANCE_TREE (instance),
9301 : instance, &instance->cost_vec,
9302 : svisited, visited);
9303 : }
9304 246835 : }
9305 :
9306 : /* Determine whether we can vectorize the reduction epilogue for INSTANCE. */
9307 :
9308 : static bool
9309 89164 : vectorizable_bb_reduc_epilogue (slp_instance instance,
9310 : stmt_vector_for_cost *cost_vec)
9311 : {
9312 89164 : gassign *stmt = as_a <gassign *> (instance->root_stmts[0]->stmt);
9313 89164 : enum tree_code reduc_code = gimple_assign_rhs_code (stmt);
9314 89164 : if (reduc_code == MINUS_EXPR)
9315 0 : reduc_code = PLUS_EXPR;
9316 89164 : internal_fn reduc_fn;
9317 89164 : tree vectype = SLP_TREE_VECTYPE (SLP_INSTANCE_TREE (instance));
9318 89164 : if (!vectype
9319 89152 : || !useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)),
9320 89152 : TREE_TYPE (vectype))
9321 52231 : || (maybe_ne (TYPE_VECTOR_SUBPARTS (vectype), 2u)
9322 1050 : && (!reduction_fn_for_scalar_code (reduc_code, &reduc_fn)
9323 1050 : || reduc_fn == IFN_LAST
9324 1050 : || !direct_internal_fn_supported_p (reduc_fn, vectype,
9325 : OPTIMIZE_FOR_BOTH)))
9326 : /* Two-element reductions do not need special-handling for fold-left,
9327 : other cases are not yet implemented. remain_defs also have to
9328 : be included here. */
9329 178364 : || (needs_fold_left_reduction_p (TREE_TYPE (vectype), reduc_code)
9330 5739 : && (!instance->remain_defs.is_empty ()
9331 1857 : || SLP_TREE_LANES (SLP_INSTANCE_TREE (instance)) != 2)))
9332 : {
9333 38924 : if (dump_enabled_p ())
9334 54 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
9335 : "not vectorized: basic block reduction epilogue "
9336 : "operation unsupported.\n");
9337 : return false;
9338 : }
9339 :
9340 : /* There's no way to cost a horizontal vector reduction via REDUC_FN so
9341 : cost log2 vector operations plus shuffles and one extraction. */
9342 50240 : unsigned steps = floor_log2 (vect_nunits_for_cost (vectype));
9343 50240 : record_stmt_cost (cost_vec, steps, vector_stmt, instance->root_stmts[0],
9344 : vectype, 0, vect_body);
9345 50240 : record_stmt_cost (cost_vec, steps, vec_perm, instance->root_stmts[0],
9346 : vectype, 0, vect_body);
9347 50240 : record_stmt_cost (cost_vec, 1, vec_to_scalar, instance->root_stmts[0],
9348 : vectype, 0, vect_body);
9349 :
9350 : /* Since we replace all stmts of a possibly longer scalar reduction
9351 : chain account for the extra scalar stmts for that. */
9352 50240 : if (!instance->remain_defs.is_empty ())
9353 30340 : record_stmt_cost (cost_vec, instance->remain_defs.length (), scalar_stmt,
9354 15170 : instance->root_stmts[0], 0, vect_body);
9355 : return true;
9356 : }
9357 :
9358 : /* Prune from ROOTS all stmts that are computed as part of lanes of NODE
9359 : and recurse to children. */
9360 :
9361 : static void
9362 361981 : vect_slp_prune_covered_roots (slp_tree node, hash_set<stmt_vec_info> &roots,
9363 : hash_set<slp_tree> &visited)
9364 : {
9365 361981 : if (SLP_TREE_DEF_TYPE (node) != vect_internal_def
9366 361981 : || visited.add (node))
9367 : return;
9368 :
9369 1008848 : for (auto stmt : SLP_TREE_SCALAR_STMTS (node))
9370 447119 : if (stmt)
9371 478571 : roots.remove (vect_orig_stmt (stmt));
9372 :
9373 767126 : for (auto child : SLP_TREE_CHILDREN (node))
9374 256781 : if (child)
9375 255275 : vect_slp_prune_covered_roots (child, roots, visited);
9376 : }
9377 :
9378 : /* Hand over COST_VEC to the target COSTS grouped by SLP node. */
9379 :
9380 : static void
9381 985416 : add_slp_costs (vector_costs *costs, stmt_vector_for_cost& cost_vec)
9382 : {
9383 3776353 : for (unsigned start = 0; start < cost_vec.length ();)
9384 : {
9385 2790937 : unsigned end = start + 1;
9386 3448866 : while (end < cost_vec.length ()
9387 5921000 : && cost_vec[start].node == cost_vec[end].node)
9388 657929 : end++;
9389 2790937 : costs->add_slp_cost (cost_vec[start].node,
9390 2790937 : array_slice<stmt_info_for_cost>
9391 2790937 : (cost_vec.begin () + start, end - start));
9392 2790937 : start = end;
9393 : }
9394 985416 : }
9395 :
9396 : /* Analyze statements in SLP instances of VINFO. Return true if the
9397 : operations are supported. */
9398 :
9399 : bool
9400 694578 : vect_slp_analyze_operations (vec_info *vinfo)
9401 : {
9402 694578 : slp_instance instance;
9403 694578 : int i;
9404 :
9405 694578 : DUMP_VECT_SCOPE ("vect_slp_analyze_operations");
9406 :
9407 694578 : hash_set<slp_tree> visited;
9408 2496079 : for (i = 0; vinfo->slp_instances.iterate (i, &instance); )
9409 : {
9410 1366151 : auto_vec<slp_tree> visited_vec;
9411 1366151 : stmt_vector_for_cost cost_vec;
9412 1366151 : cost_vec.create (2);
9413 1366151 : if (is_a <bb_vec_info> (vinfo))
9414 821165 : vect_location = instance->location ();
9415 1366151 : if (!vect_slp_analyze_node_operations (vinfo,
9416 : SLP_INSTANCE_TREE (instance),
9417 : instance, visited, visited_vec,
9418 : &cost_vec)
9419 : /* CTOR instances require vectorized defs for the SLP tree root. */
9420 1110285 : || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_ctor
9421 6291 : && (SLP_TREE_DEF_TYPE (SLP_INSTANCE_TREE (instance))
9422 : != vect_internal_def
9423 : /* Make sure we vectorized with the expected type. */
9424 6291 : || !useless_type_conversion_p
9425 6291 : (TREE_TYPE (TREE_TYPE (gimple_assign_rhs1
9426 : (instance->root_stmts[0]->stmt))),
9427 6291 : TREE_TYPE (SLP_TREE_VECTYPE
9428 : (SLP_INSTANCE_TREE (instance))))))
9429 : /* Check we can vectorize the reduction. */
9430 1110270 : || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_bb_reduc
9431 89164 : && !vectorizable_bb_reduc_epilogue (instance, &cost_vec))
9432 : /* Check we can vectorize the gcond. */
9433 2437497 : || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_gcond
9434 65744 : && !vectorizable_early_exit (as_a <loop_vec_info> (vinfo),
9435 65744 : SLP_INSTANCE_ROOT_STMTS (instance)[0],
9436 : NULL,
9437 : SLP_INSTANCE_TREE (instance),
9438 : &cost_vec)))
9439 : {
9440 357888 : cost_vec.release ();
9441 357888 : slp_tree node = SLP_INSTANCE_TREE (instance);
9442 357888 : stmt_vec_info stmt_info;
9443 357888 : if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ())
9444 267656 : stmt_info = SLP_INSTANCE_ROOT_STMTS (instance)[0];
9445 90232 : else if (!SLP_TREE_SCALAR_STMTS (node).is_empty ()
9446 90232 : && SLP_TREE_SCALAR_STMTS (node)[0])
9447 : stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
9448 : else
9449 0 : stmt_info = SLP_TREE_REPRESENTATIVE (node);
9450 357888 : if (is_a <loop_vec_info> (vinfo))
9451 : {
9452 259228 : if (dump_enabled_p ())
9453 6845 : dump_printf_loc (MSG_NOTE, vect_location,
9454 : "unsupported SLP instance starting from: %G",
9455 : stmt_info->stmt);
9456 259228 : return false;
9457 : }
9458 98660 : if (dump_enabled_p ())
9459 110 : dump_printf_loc (MSG_NOTE, vect_location,
9460 : "removing SLP instance operations starting from: %G",
9461 : stmt_info->stmt);
9462 235227 : while (!visited_vec.is_empty ())
9463 : {
9464 136567 : slp_tree node = visited_vec.pop ();
9465 136567 : SLP_TREE_TYPE (node) = undef_vec_info_type;
9466 136567 : if (node->data)
9467 : {
9468 8555 : delete node->data;
9469 8555 : node->data = nullptr;
9470 : }
9471 136567 : visited.remove (node);
9472 : }
9473 98660 : vect_free_slp_instance (instance);
9474 98660 : vinfo->slp_instances.ordered_remove (i);
9475 : }
9476 : else
9477 : {
9478 1008263 : i++;
9479 1008263 : if (loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (vinfo))
9480 : {
9481 285758 : add_slp_costs (loop_vinfo->vector_costs, cost_vec);
9482 285758 : cost_vec.release ();
9483 : }
9484 : else
9485 : /* For BB vectorization remember the SLP graph entry
9486 : cost for later. */
9487 722505 : instance->cost_vec = cost_vec;
9488 : }
9489 1366151 : }
9490 :
9491 : /* Now look for SLP instances with a root that are covered by other
9492 : instances and remove them. */
9493 435350 : hash_set<stmt_vec_info> roots;
9494 1807953 : for (i = 0; vinfo->slp_instances.iterate (i, &instance); ++i)
9495 996418 : if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ())
9496 59165 : roots.add (SLP_INSTANCE_ROOT_STMTS (instance)[0]);
9497 435350 : if (!roots.is_empty ())
9498 : {
9499 23418 : visited.empty ();
9500 130124 : for (i = 0; vinfo->slp_instances.iterate (i, &instance); ++i)
9501 106706 : vect_slp_prune_covered_roots (SLP_INSTANCE_TREE (instance), roots,
9502 : visited);
9503 130124 : for (i = 0; vinfo->slp_instances.iterate (i, &instance); )
9504 106706 : if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ()
9505 59165 : && !roots.contains (SLP_INSTANCE_ROOT_STMTS (instance)[0]))
9506 : {
9507 5537 : stmt_vec_info root = SLP_INSTANCE_ROOT_STMTS (instance)[0];
9508 5537 : if (dump_enabled_p ())
9509 283 : dump_printf_loc (MSG_NOTE, vect_location,
9510 : "removing SLP instance operations starting "
9511 : "from: %G", root->stmt);
9512 5537 : vect_free_slp_instance (instance);
9513 5537 : vinfo->slp_instances.ordered_remove (i);
9514 : }
9515 : else
9516 101169 : ++i;
9517 : }
9518 :
9519 870700 : return !vinfo->slp_instances.is_empty ();
9520 1129928 : }
9521 :
9522 : /* Get the SLP instance leader from INSTANCE_LEADER thereby transitively
9523 : closing the eventual chain. */
9524 :
9525 : static slp_instance
9526 807080 : get_ultimate_leader (slp_instance instance,
9527 : hash_map<slp_instance, slp_instance> &instance_leader)
9528 : {
9529 807080 : auto_vec<slp_instance *, 8> chain;
9530 807080 : slp_instance *tem;
9531 917085 : while (*(tem = instance_leader.get (instance)) != instance)
9532 : {
9533 110005 : chain.safe_push (tem);
9534 110005 : instance = *tem;
9535 : }
9536 917085 : while (!chain.is_empty ())
9537 110005 : *chain.pop () = instance;
9538 807080 : return instance;
9539 807080 : }
9540 :
9541 : namespace {
9542 : /* Subroutine of vect_bb_partition_graph_r. Map KEY to INSTANCE in
9543 : KEY_TO_INSTANCE, making INSTANCE the leader of any previous mapping
9544 : for KEY. Return true if KEY was already in KEY_TO_INSTANCE.
9545 :
9546 : INSTANCE_LEADER is as for get_ultimate_leader. */
9547 :
9548 : template<typename T>
9549 : bool
9550 3567197 : vect_map_to_instance (slp_instance instance, T key,
9551 : hash_map<T, slp_instance> &key_to_instance,
9552 : hash_map<slp_instance, slp_instance> &instance_leader)
9553 : {
9554 : bool existed_p;
9555 3567197 : slp_instance &key_instance = key_to_instance.get_or_insert (key, &existed_p);
9556 3567197 : if (!existed_p)
9557 : ;
9558 244262 : else if (key_instance != instance)
9559 : {
9560 : /* If we're running into a previously marked key make us the
9561 : leader of the current ultimate leader. This keeps the
9562 : leader chain acyclic and works even when the current instance
9563 : connects two previously independent graph parts. */
9564 90134 : slp_instance key_leader
9565 90134 : = get_ultimate_leader (key_instance, instance_leader);
9566 90134 : if (key_leader != instance)
9567 26949 : instance_leader.put (key_leader, instance);
9568 : }
9569 3567197 : key_instance = instance;
9570 3567197 : return existed_p;
9571 : }
9572 : }
9573 :
9574 : /* Worker of vect_bb_partition_graph, recurse on NODE. */
9575 :
9576 : static void
9577 998275 : vect_bb_partition_graph_r (bb_vec_info bb_vinfo,
9578 : slp_instance instance, slp_tree node,
9579 : hash_map<stmt_vec_info, slp_instance> &stmt_to_instance,
9580 : hash_map<slp_tree, slp_instance> &node_to_instance,
9581 : hash_map<slp_instance, slp_instance> &instance_leader)
9582 : {
9583 5552367 : for (auto stmt_info : SLP_TREE_SCALAR_STMTS (node))
9584 2568922 : if (stmt_info)
9585 2568922 : vect_map_to_instance (instance, stmt_info, stmt_to_instance,
9586 : instance_leader);
9587 :
9588 998275 : if (vect_map_to_instance (instance, node, node_to_instance,
9589 : instance_leader))
9590 : return;
9591 :
9592 3579445 : for (auto child : SLP_TREE_CHILDREN (node))
9593 984250 : if (child && SLP_TREE_DEF_TYPE (child) == vect_internal_def)
9594 281329 : vect_bb_partition_graph_r (bb_vinfo, instance, child, stmt_to_instance,
9595 : node_to_instance, instance_leader);
9596 : }
9597 :
9598 : /* Partition the SLP graph into pieces that can be costed independently. */
9599 :
9600 : static void
9601 246835 : vect_bb_partition_graph (bb_vec_info bb_vinfo)
9602 : {
9603 246835 : DUMP_VECT_SCOPE ("vect_bb_partition_graph");
9604 :
9605 : /* First walk the SLP graph assigning each involved scalar stmt a
9606 : corresponding SLP graph entry and upon visiting a previously
9607 : marked stmt, make the stmts leader the current SLP graph entry. */
9608 246835 : hash_map<stmt_vec_info, slp_instance> stmt_to_instance;
9609 246835 : hash_map<slp_tree, slp_instance> node_to_instance;
9610 246835 : hash_map<slp_instance, slp_instance> instance_leader;
9611 246835 : slp_instance instance;
9612 1210616 : for (unsigned i = 0; bb_vinfo->slp_instances.iterate (i, &instance); ++i)
9613 : {
9614 716946 : instance_leader.put (instance, instance);
9615 716946 : vect_bb_partition_graph_r (bb_vinfo,
9616 : instance, SLP_INSTANCE_TREE (instance),
9617 : stmt_to_instance, node_to_instance,
9618 : instance_leader);
9619 : }
9620 :
9621 : /* Then collect entries to each independent subgraph. */
9622 1210616 : for (unsigned i = 0; bb_vinfo->slp_instances.iterate (i, &instance); ++i)
9623 : {
9624 716946 : slp_instance leader = get_ultimate_leader (instance, instance_leader);
9625 716946 : leader->subgraph_entries.safe_push (instance);
9626 716946 : if (dump_enabled_p ()
9627 716946 : && leader != instance)
9628 83 : dump_printf_loc (MSG_NOTE, vect_location,
9629 : "instance %p is leader of %p\n",
9630 : (void *) leader, (void *) instance);
9631 : }
9632 246835 : }
9633 :
9634 : /* Compute the scalar cost of the SLP node NODE and its children
9635 : and return it. Do not account defs that are marked in LIFE and
9636 : update LIFE according to uses of NODE. */
9637 :
9638 : static void
9639 712945 : vect_bb_slp_scalar_cost (bb_vec_info vinfo,
9640 : vec<stmt_vec_info> &worklist,
9641 : stmt_vector_for_cost *cost_vec,
9642 : hash_set<stmt_vec_info> &visited)
9643 : {
9644 3322645 : while (!worklist.is_empty ())
9645 : {
9646 2609700 : stmt_vec_info stmt = worklist.pop ();
9647 2934378 : if (!PURE_SLP_STMT (stmt))
9648 333189 : continue;
9649 :
9650 : /* When the stmt is live but not actually vectorized we have
9651 : to keep the feeding scalar defs. */
9652 2290672 : if (!STMT_VINFO_LIVE_P (vect_stmt_to_vectorize (stmt)))
9653 : {
9654 2185772 : bool live_p = false;
9655 2185772 : ssa_op_iter op_iter;
9656 2185772 : def_operand_p def_p;
9657 4806666 : FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt->stmt, op_iter, SSA_OP_DEF)
9658 : {
9659 435122 : imm_use_iterator use_iter;
9660 435122 : gimple *use_stmt;
9661 1115455 : FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, DEF_FROM_PTR (def_p))
9662 680333 : if (!is_gimple_debug (use_stmt))
9663 : {
9664 511946 : stmt_vec_info use_stmt_info = vinfo->lookup_stmt (use_stmt);
9665 511946 : if (!use_stmt_info || !PURE_SLP_STMT (use_stmt_info))
9666 : {
9667 15736 : if (dump_enabled_p ())
9668 : {
9669 74 : dump_printf_loc (MSG_NOTE, vect_location,
9670 : "stmt considered live: %G",
9671 : stmt->stmt);
9672 74 : dump_printf_loc (MSG_NOTE, vect_location,
9673 : "because of use in: %G",
9674 : use_stmt);
9675 : }
9676 : live_p = true;
9677 : }
9678 435122 : }
9679 : }
9680 2185772 : if (live_p)
9681 8511 : continue;
9682 : }
9683 :
9684 : /* The following assert verifies that vect_bb_partition_graph
9685 : partitions the SLP graph in a way that each scalar stmt of
9686 : the coverage of the SLP graph belongs to exactly one subgraph.
9687 : ??? This is currently not guaranteed since the function
9688 : works purely on SLP_TREE_SCALAR_STMTS, resulting in the assert
9689 : tripping or scalar stmts costed multiple times, making vectorization
9690 : more profitable than it really is. */
9691 : /* gcc_checking_assert (!gimple_visited_p (stmt->stmt)); */
9692 :
9693 2276511 : if (vect_nop_conversion_p (stmt))
9694 : ;
9695 : /* For single-argument PHIs assume coalescing which means zero
9696 : cost for the scalar and the vector PHIs. This avoids
9697 : artificially favoring the vector path (but may pessimize it
9698 : in some cases). */
9699 2245747 : else if (is_a <gphi *> (stmt->stmt)
9700 2245747 : && gimple_phi_num_args (as_a <gphi *> (stmt->stmt)) == 1)
9701 : ;
9702 : else
9703 : {
9704 2235203 : vect_cost_for_stmt kind;
9705 2235203 : if (STMT_VINFO_DATA_REF (stmt))
9706 : {
9707 2009719 : data_reference_p dr = STMT_VINFO_DATA_REF (stmt);
9708 2009719 : tree base = get_base_address (DR_REF (dr));
9709 : /* When the scalar access is to a non-global not
9710 : address-taken decl that is not BLKmode assume we can
9711 : access it with a single non-load/store instruction. */
9712 2009719 : if (DECL_P (base)
9713 1546344 : && !is_global_var (base)
9714 1468955 : && !TREE_ADDRESSABLE (base)
9715 2566968 : && DECL_MODE (base) != BLKmode)
9716 : kind = scalar_stmt;
9717 1865411 : else if (DR_IS_READ (STMT_VINFO_DATA_REF (stmt)))
9718 : kind = scalar_load;
9719 : else
9720 1623262 : kind = scalar_store;
9721 : }
9722 : else
9723 : kind = scalar_stmt;
9724 : /* Cost each scalar stmt only once. */
9725 2235203 : gimple_set_visited (stmt->stmt, true);
9726 2235203 : record_stmt_cost (cost_vec, 1, kind, stmt, NULL_TREE, 0, vect_body);
9727 : }
9728 :
9729 : /* Now walk relevant parts of the SSA use-def graph. */
9730 2276511 : slp_oprnds child_ops (stmt);
9731 7087180 : for (unsigned i = 0; i < child_ops.num_slp_children; ++i)
9732 : {
9733 2534158 : tree op = child_ops.get_op_for_slp_child (stmt, i);
9734 2534158 : stmt_vec_info def = vinfo->lookup_def (op);
9735 2534158 : if (def && !visited.add (def))
9736 761658 : worklist.safe_push (def);
9737 : }
9738 : }
9739 712945 : }
9740 :
9741 :
9742 : /* Comparator for the loop-index sorted cost vectors. */
9743 :
9744 : static int
9745 19792589 : li_cost_vec_cmp (const void *a_, const void *b_, void *)
9746 : {
9747 19792589 : auto *a = (const std::pair<unsigned, stmt_info_for_cost *> *)a_;
9748 19792589 : auto *b = (const std::pair<unsigned, stmt_info_for_cost *> *)b_;
9749 19792589 : if (a->first < b->first)
9750 : return -1;
9751 18595505 : else if (a->first == b->first)
9752 17587928 : return 0;
9753 : return 1;
9754 : }
9755 :
9756 : /* Check if vectorization of the basic block is profitable for the
9757 : subgraph denoted by SLP_INSTANCES. */
9758 :
9759 : static bool
9760 686182 : vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
9761 : vec<slp_instance> slp_instances,
9762 : loop_p orig_loop)
9763 : {
9764 686182 : slp_instance instance;
9765 686182 : int i;
9766 686182 : unsigned int vec_inside_cost = 0, vec_outside_cost = 0, scalar_cost = 0;
9767 686182 : unsigned int vec_prologue_cost = 0, vec_epilogue_cost = 0;
9768 :
9769 686182 : if (dump_enabled_p ())
9770 : {
9771 125 : dump_printf_loc (MSG_NOTE, vect_location, "Costing subgraph:\n");
9772 259 : FOR_EACH_VEC_ELT (slp_instances, i, instance)
9773 134 : dump_printf_loc (MSG_NOTE, vect_location, " entry instance %p -> "
9774 : "node %p\n", (void *)instance,
9775 134 : (void *)SLP_INSTANCE_TREE (instance));
9776 125 : hash_set<slp_tree> visited;
9777 509 : FOR_EACH_VEC_ELT (slp_instances, i, instance)
9778 134 : vect_print_slp_graph (MSG_NOTE, vect_location,
9779 : SLP_INSTANCE_TREE (instance), visited);
9780 125 : }
9781 :
9782 : /* Then DFS walk scalar stmts, performing costing and handling
9783 : still live scalar stmts via the previously computed vector coverage. */
9784 686182 : stmt_vector_for_cost scalar_costs = vNULL;
9785 686182 : stmt_vector_for_cost vector_costs = vNULL;
9786 686182 : hash_set<slp_tree> visited;
9787 686182 : hash_set<stmt_vec_info> svisited;
9788 2085309 : FOR_EACH_VEC_ELT (slp_instances, i, instance)
9789 : {
9790 712945 : auto_vec<stmt_vec_info> worklist;
9791 712945 : if (SLP_INSTANCE_ROOT_STMTS (instance).exists ())
9792 100418 : record_stmt_cost (&scalar_costs,
9793 50209 : SLP_INSTANCE_ROOT_STMTS (instance).length (),
9794 : scalar_stmt,
9795 50209 : SLP_INSTANCE_ROOT_STMTS (instance)[0], 0, vect_body);
9796 4002121 : for (auto stmt : SLP_TREE_SCALAR_STMTS (SLP_INSTANCE_TREE (instance)))
9797 : {
9798 1863286 : stmt = vect_orig_stmt (stmt);
9799 1863286 : if (!svisited.add (stmt))
9800 1848042 : worklist.safe_push (stmt);
9801 : }
9802 712945 : vect_bb_slp_scalar_cost (bb_vinfo, worklist, &scalar_costs, svisited);
9803 712945 : vector_costs.safe_splice (instance->cost_vec);
9804 712945 : instance->cost_vec.release ();
9805 712945 : }
9806 :
9807 686182 : if (dump_enabled_p ())
9808 125 : dump_printf_loc (MSG_NOTE, vect_location, "Cost model analysis: \n");
9809 :
9810 : /* When costing non-loop vectorization we need to consider each covered
9811 : loop independently and make sure vectorization is profitable. For
9812 : now we assume a loop may be not entered or executed an arbitrary
9813 : number of iterations (??? static information can provide more
9814 : precise info here) which means we can simply cost each containing
9815 : loops stmts separately. */
9816 :
9817 : /* First produce cost vectors sorted by loop index. */
9818 686182 : auto_vec<std::pair<unsigned, stmt_info_for_cost *> >
9819 1372364 : li_scalar_costs (scalar_costs.length ());
9820 686182 : auto_vec<std::pair<unsigned, stmt_info_for_cost *> >
9821 1372351 : li_vector_costs (vector_costs.length ());
9822 686182 : stmt_info_for_cost *cost;
9823 3657776 : FOR_EACH_VEC_ELT (scalar_costs, i, cost)
9824 : {
9825 2285412 : unsigned l = gimple_bb (cost->stmt_info->stmt)->loop_father->num;
9826 2285412 : li_scalar_costs.quick_push (std::make_pair (l, cost));
9827 : }
9828 : /* Use a random used loop as fallback in case the first vector_costs
9829 : entry does not have a stmt_info associated with it. */
9830 686182 : unsigned l = li_scalar_costs[0].first;
9831 2630468 : FOR_EACH_VEC_ELT (vector_costs, i, cost)
9832 : {
9833 : /* We inherit from the previous COST, invariants, externals and
9834 : extracts immediately follow the cost for the related stmt. */
9835 1944286 : if (cost->stmt_info)
9836 1175882 : l = gimple_bb (cost->stmt_info->stmt)->loop_father->num;
9837 1944286 : li_vector_costs.quick_push (std::make_pair (l, cost));
9838 : }
9839 686182 : li_scalar_costs.stablesort (li_cost_vec_cmp, NULL);
9840 686182 : li_vector_costs.stablesort (li_cost_vec_cmp, NULL);
9841 :
9842 : /* Now cost the portions individually. */
9843 686182 : unsigned vi = 0;
9844 686182 : unsigned si = 0;
9845 686182 : bool profitable = true;
9846 1387673 : while (si < li_scalar_costs.length ()
9847 2089206 : && vi < li_vector_costs.length ())
9848 : {
9849 701491 : unsigned sl = li_scalar_costs[si].first;
9850 701491 : unsigned vl = li_vector_costs[vi].first;
9851 701491 : if (sl != vl)
9852 : {
9853 1833 : if (dump_enabled_p ())
9854 2 : dump_printf_loc (MSG_NOTE, vect_location,
9855 : "Scalar %d and vector %d loop part do not "
9856 : "match up, skipping scalar part\n", sl, vl);
9857 : /* Skip the scalar part, assuming zero cost on the vector side. */
9858 2763 : do
9859 : {
9860 2763 : si++;
9861 : }
9862 2763 : while (si < li_scalar_costs.length ()
9863 6135 : && li_scalar_costs[si].first == sl);
9864 1833 : continue;
9865 : }
9866 :
9867 699658 : if (dump_enabled_p ())
9868 143 : dump_printf_loc (MSG_NOTE, vect_location,
9869 : "Scalar cost for part in loop %d\n", sl);
9870 699658 : class vector_costs *scalar_target_cost_data = init_cost (bb_vinfo, true);
9871 2282516 : do
9872 : {
9873 2282516 : add_stmt_cost (scalar_target_cost_data, li_scalar_costs[si].second);
9874 2282516 : si++;
9875 : }
9876 2282516 : while (si < li_scalar_costs.length ()
9877 4578857 : && li_scalar_costs[si].first == sl);
9878 699658 : scalar_target_cost_data->finish_cost (nullptr);
9879 699658 : scalar_cost = scalar_target_cost_data->body_cost ();
9880 :
9881 : /* Complete the target-specific vector cost calculation. */
9882 699658 : if (dump_enabled_p ())
9883 143 : dump_printf_loc (MSG_NOTE, vect_location,
9884 : "Vector cost for part in loop %d\n", vl);
9885 699658 : class vector_costs *vect_target_cost_data = init_cost (bb_vinfo, false);
9886 699658 : auto_vec<stmt_info_for_cost> tem;
9887 1941915 : do
9888 : {
9889 1941915 : tem.safe_push (*li_vector_costs[vi].second);
9890 1941915 : vi++;
9891 : }
9892 1941915 : while (vi < li_vector_costs.length ()
9893 3897651 : && li_vector_costs[vi].first == vl);
9894 699658 : add_slp_costs (vect_target_cost_data, tem);
9895 699658 : vect_target_cost_data->finish_cost (scalar_target_cost_data);
9896 699658 : vec_prologue_cost = vect_target_cost_data->prologue_cost ();
9897 699658 : vec_inside_cost = vect_target_cost_data->body_cost ();
9898 699658 : vec_epilogue_cost = vect_target_cost_data->epilogue_cost ();
9899 699658 : delete scalar_target_cost_data;
9900 699658 : delete vect_target_cost_data;
9901 :
9902 699658 : vec_outside_cost = vec_prologue_cost + vec_epilogue_cost;
9903 :
9904 699658 : if (dump_enabled_p ())
9905 : {
9906 143 : dump_printf_loc (MSG_NOTE, vect_location,
9907 : "Cost model analysis for part in loop %d:\n", sl);
9908 143 : dump_printf (MSG_NOTE, " Vector cost: %d\n",
9909 : vec_inside_cost + vec_outside_cost);
9910 143 : dump_printf (MSG_NOTE, " Scalar cost: %d\n", scalar_cost);
9911 : }
9912 :
9913 : /* Vectorization is profitable if its cost is more than the cost of scalar
9914 : version. Note that we err on the vector side for equal cost because
9915 : the cost estimate is otherwise quite pessimistic (constant uses are
9916 : free on the scalar side but cost a load on the vector side for
9917 : example). */
9918 699658 : if (vec_outside_cost + vec_inside_cost > scalar_cost)
9919 203861 : profitable = false;
9920 699658 : }
9921 1175591 : if (profitable && vi < li_vector_costs.length ())
9922 : {
9923 325 : if (dump_enabled_p ())
9924 0 : dump_printf_loc (MSG_NOTE, vect_location,
9925 : "Excess vector cost for part in loop %d:\n",
9926 0 : li_vector_costs[vi].first);
9927 : profitable = false;
9928 : }
9929 :
9930 : /* Unset visited flag. This is delayed when the subgraph is profitable
9931 : and we process the loop for remaining unvectorized if-converted code. */
9932 686182 : if (!orig_loop || !profitable)
9933 2969359 : FOR_EACH_VEC_ELT (scalar_costs, i, cost)
9934 2283337 : gimple_set_visited (cost->stmt_info->stmt, false);
9935 :
9936 686182 : scalar_costs.release ();
9937 686182 : vector_costs.release ();
9938 :
9939 686182 : return profitable;
9940 686182 : }
9941 :
9942 : /* qsort comparator for lane defs. */
9943 :
9944 : static int
9945 128 : vld_cmp (const void *a_, const void *b_)
9946 : {
9947 128 : auto *a = (const std::pair<unsigned, tree> *)a_;
9948 128 : auto *b = (const std::pair<unsigned, tree> *)b_;
9949 128 : return a->first - b->first;
9950 : }
9951 :
9952 : /* Return true if USE_STMT is a vector lane insert into VEC and set
9953 : *THIS_LANE to the lane number that is set. */
9954 :
9955 : static bool
9956 303 : vect_slp_is_lane_insert (gimple *use_stmt, tree vec, unsigned *this_lane)
9957 : {
9958 303 : gassign *use_ass = dyn_cast <gassign *> (use_stmt);
9959 110 : if (!use_ass
9960 110 : || gimple_assign_rhs_code (use_ass) != BIT_INSERT_EXPR
9961 35 : || (vec
9962 35 : ? gimple_assign_rhs1 (use_ass) != vec
9963 26 : : ((vec = gimple_assign_rhs1 (use_ass)), false))
9964 61 : || !useless_type_conversion_p (TREE_TYPE (TREE_TYPE (vec)),
9965 61 : TREE_TYPE (gimple_assign_rhs2 (use_ass)))
9966 61 : || !constant_multiple_p
9967 61 : (tree_to_poly_uint64 (gimple_assign_rhs3 (use_ass)),
9968 364 : tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (TREE_TYPE (vec)))),
9969 : this_lane))
9970 : return false;
9971 : return true;
9972 : }
9973 :
9974 : /* Find any vectorizable constructors and add them to the grouped_store
9975 : array. */
9976 :
9977 : static void
9978 2296064 : vect_slp_check_for_roots (bb_vec_info bb_vinfo)
9979 : {
9980 18371992 : for (unsigned i = 0; i < bb_vinfo->nbbs; ++i)
9981 32151856 : for (gimple_stmt_iterator gsi = gsi_start_bb (bb_vinfo->bbs[i]);
9982 148199252 : !gsi_end_p (gsi); gsi_next (&gsi))
9983 : {
9984 132123324 : gassign *assign = dyn_cast<gassign *> (gsi_stmt (gsi));
9985 : /* This can be used to start SLP discovery for early breaks for BB early breaks
9986 : when we get that far. */
9987 132123324 : if (!assign)
9988 101500629 : continue;
9989 :
9990 32743016 : tree rhs = gimple_assign_rhs1 (assign);
9991 32743016 : enum tree_code code = gimple_assign_rhs_code (assign);
9992 32743016 : use_operand_p use_p;
9993 32743016 : gimple *use_stmt;
9994 32743016 : if (code == CONSTRUCTOR)
9995 : {
9996 1737610 : if (!VECTOR_TYPE_P (TREE_TYPE (rhs))
9997 1782740 : || maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)),
9998 98187 : CONSTRUCTOR_NELTS (rhs))
9999 45130 : || VECTOR_TYPE_P (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value))
10000 1782720 : || uniform_vector_p (rhs))
10001 1723196 : continue;
10002 :
10003 : unsigned j;
10004 : tree val;
10005 70955 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), j, val)
10006 56541 : if (TREE_CODE (val) != SSA_NAME
10007 56541 : || !bb_vinfo->lookup_def (val))
10008 : break;
10009 35478 : if (j != CONSTRUCTOR_NELTS (rhs))
10010 3325 : continue;
10011 :
10012 14414 : vec<stmt_vec_info> roots = vNULL;
10013 14414 : roots.safe_push (bb_vinfo->lookup_stmt (assign));
10014 14414 : vec<stmt_vec_info> stmts;
10015 14414 : stmts.create (CONSTRUCTOR_NELTS (rhs));
10016 80364 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), j, val)
10017 51536 : stmts.quick_push
10018 51536 : (vect_stmt_to_vectorize (bb_vinfo->lookup_def (val)));
10019 14414 : bb_vinfo->roots.safe_push (slp_root (slp_inst_kind_ctor,
10020 14414 : stmts, roots));
10021 : }
10022 31005406 : else if (code == BIT_INSERT_EXPR
10023 1045 : && VECTOR_TYPE_P (TREE_TYPE (rhs))
10024 719 : && TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)).is_constant ()
10025 719 : && TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)).to_constant () > 1
10026 716 : && integer_zerop (gimple_assign_rhs3 (assign))
10027 400 : && useless_type_conversion_p
10028 400 : (TREE_TYPE (TREE_TYPE (rhs)),
10029 400 : TREE_TYPE (gimple_assign_rhs2 (assign)))
10030 31006146 : && bb_vinfo->lookup_def (gimple_assign_rhs2 (assign)))
10031 : {
10032 : /* We start to match on insert to lane zero but since the
10033 : inserts need not be ordered we'd have to search both
10034 : the def and the use chains. */
10035 265 : tree vectype = TREE_TYPE (rhs);
10036 265 : unsigned nlanes = TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
10037 265 : auto_vec<std::pair<unsigned, tree> > lane_defs (nlanes);
10038 265 : auto_sbitmap lanes (nlanes);
10039 265 : bitmap_clear (lanes);
10040 265 : bitmap_set_bit (lanes, 0);
10041 265 : tree def = gimple_assign_lhs (assign);
10042 265 : lane_defs.quick_push
10043 265 : (std::make_pair (0, gimple_assign_rhs2 (assign)));
10044 265 : unsigned lanes_found = 1;
10045 : /* Start with the use chains, the last stmt will be the root. */
10046 265 : stmt_vec_info last = bb_vinfo->lookup_stmt (assign);
10047 265 : vec<stmt_vec_info> roots = vNULL;
10048 265 : roots.safe_push (last);
10049 276 : do
10050 : {
10051 276 : use_operand_p use_p;
10052 276 : gimple *use_stmt;
10053 276 : if (!single_imm_use (def, &use_p, &use_stmt))
10054 : break;
10055 264 : unsigned this_lane;
10056 264 : if (!bb_vinfo->lookup_stmt (use_stmt)
10057 264 : || !vect_slp_is_lane_insert (use_stmt, def, &this_lane)
10058 299 : || !bb_vinfo->lookup_def (gimple_assign_rhs2 (use_stmt)))
10059 : break;
10060 35 : if (bitmap_bit_p (lanes, this_lane))
10061 : break;
10062 15 : lanes_found++;
10063 15 : bitmap_set_bit (lanes, this_lane);
10064 15 : gassign *use_ass = as_a <gassign *> (use_stmt);
10065 15 : lane_defs.quick_push (std::make_pair
10066 15 : (this_lane, gimple_assign_rhs2 (use_ass)));
10067 15 : last = bb_vinfo->lookup_stmt (use_ass);
10068 15 : roots.safe_push (last);
10069 15 : def = gimple_assign_lhs (use_ass);
10070 : }
10071 15 : while (lanes_found < nlanes);
10072 265 : if (roots.length () > 1)
10073 7 : std::swap(roots[0], roots[roots.length () - 1]);
10074 265 : if (lanes_found < nlanes)
10075 : {
10076 : /* Now search the def chain. */
10077 261 : def = gimple_assign_rhs1 (assign);
10078 263 : do
10079 : {
10080 263 : if (TREE_CODE (def) != SSA_NAME
10081 263 : || !has_single_use (def))
10082 : break;
10083 59 : gimple *def_stmt = SSA_NAME_DEF_STMT (def);
10084 59 : unsigned this_lane;
10085 59 : if (!bb_vinfo->lookup_stmt (def_stmt)
10086 39 : || !vect_slp_is_lane_insert (def_stmt,
10087 : NULL_TREE, &this_lane)
10088 85 : || !bb_vinfo->lookup_def (gimple_assign_rhs2 (def_stmt)))
10089 : break;
10090 26 : if (bitmap_bit_p (lanes, this_lane))
10091 : break;
10092 6 : lanes_found++;
10093 6 : bitmap_set_bit (lanes, this_lane);
10094 12 : lane_defs.quick_push (std::make_pair
10095 6 : (this_lane,
10096 6 : gimple_assign_rhs2 (def_stmt)));
10097 6 : roots.safe_push (bb_vinfo->lookup_stmt (def_stmt));
10098 6 : def = gimple_assign_rhs1 (def_stmt);
10099 : }
10100 6 : while (lanes_found < nlanes);
10101 : }
10102 265 : if (lanes_found == nlanes)
10103 : {
10104 : /* Sort lane_defs after the lane index and register the root. */
10105 8 : lane_defs.qsort (vld_cmp);
10106 8 : vec<stmt_vec_info> stmts;
10107 8 : stmts.create (nlanes);
10108 44 : for (unsigned i = 0; i < nlanes; ++i)
10109 28 : stmts.quick_push (bb_vinfo->lookup_def (lane_defs[i].second));
10110 8 : bb_vinfo->roots.safe_push (slp_root (slp_inst_kind_ctor,
10111 8 : stmts, roots));
10112 : }
10113 : else
10114 257 : roots.release ();
10115 265 : }
10116 31005141 : else if (!VECTOR_TYPE_P (TREE_TYPE (rhs))
10117 29989323 : && (associative_tree_code (code) || code == MINUS_EXPR)
10118 : /* Ops with constants at the tail can be stripped here. */
10119 6596389 : && TREE_CODE (rhs) == SSA_NAME
10120 6522541 : && TREE_CODE (gimple_assign_rhs2 (assign)) == SSA_NAME
10121 : /* Should be the chain end. */
10122 33841683 : && (!single_imm_use (gimple_assign_lhs (assign),
10123 : &use_p, &use_stmt)
10124 2269418 : || !is_gimple_assign (use_stmt)
10125 1643608 : || (gimple_assign_rhs_code (use_stmt) != code
10126 1093278 : && ((code != PLUS_EXPR && code != MINUS_EXPR)
10127 615398 : || (gimple_assign_rhs_code (use_stmt)
10128 615398 : != (code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR))))))
10129 : {
10130 : /* We start the match at the end of a possible association
10131 : chain. */
10132 2169630 : auto_vec<chain_op_t> chain;
10133 2169630 : auto_vec<std::pair<tree_code, gimple *> > worklist;
10134 2169630 : auto_vec<gimple *> chain_stmts;
10135 2169630 : gimple *code_stmt = NULL, *alt_code_stmt = NULL;
10136 2169630 : if (code == MINUS_EXPR)
10137 362295 : code = PLUS_EXPR;
10138 2169630 : internal_fn reduc_fn;
10139 2566755 : if (!reduction_fn_for_scalar_code (code, &reduc_fn)
10140 2169630 : || reduc_fn == IFN_LAST)
10141 397125 : continue;
10142 1772505 : vect_slp_linearize_chain (bb_vinfo, worklist, chain, code, assign,
10143 : /* ??? */
10144 : code_stmt, alt_code_stmt, &chain_stmts,
10145 : false);
10146 3545010 : if (chain.length () > 1)
10147 : {
10148 : /* Sort the chain according to def_type and operation. */
10149 1772505 : chain.sort (dt_sort_cmp, bb_vinfo);
10150 : /* ??? Now we'd want to strip externals and constants
10151 : but record those to be handled in the epilogue. */
10152 : /* ??? For now do not allow mixing ops or externs/constants. */
10153 1772505 : bool invalid = false;
10154 1772505 : unsigned remain_cnt = 0;
10155 7302854 : for (unsigned i = 0; i < chain.length (); ++i)
10156 : {
10157 4120139 : if (chain[i].code != code)
10158 : {
10159 : invalid = true;
10160 : break;
10161 : }
10162 3757844 : if (chain[i].dt != vect_internal_def
10163 : /* Avoid stmts where the def is not the LHS, like
10164 : ASMs. */
10165 7161459 : || (gimple_get_lhs (bb_vinfo->lookup_def
10166 3403615 : (chain[i].op)->stmt)
10167 3403615 : != chain[i].op))
10168 357181 : remain_cnt++;
10169 : }
10170 1772505 : if (!invalid && chain.length () - remain_cnt > 1)
10171 : {
10172 1325401 : vec<stmt_vec_info> stmts;
10173 1325401 : vec<tree> remain = vNULL;
10174 1325401 : stmts.create (chain.length ());
10175 1325401 : if (remain_cnt > 0)
10176 47279 : remain.create (remain_cnt);
10177 4412152 : for (unsigned i = 0; i < chain.length (); ++i)
10178 : {
10179 3086751 : stmt_vec_info stmt_info;
10180 3086751 : if (chain[i].dt == vect_internal_def
10181 3086751 : && ((stmt_info = bb_vinfo->lookup_def (chain[i].op)),
10182 2998516 : gimple_get_lhs (stmt_info->stmt) == chain[i].op))
10183 2998432 : stmts.quick_push (stmt_info);
10184 : else
10185 88319 : remain.quick_push (chain[i].op);
10186 : }
10187 1325401 : vec<stmt_vec_info> roots;
10188 1325401 : roots.create (chain_stmts.length ());
10189 4412152 : for (unsigned i = 0; i < chain_stmts.length (); ++i)
10190 1761350 : roots.quick_push (bb_vinfo->lookup_stmt (chain_stmts[i]));
10191 1325401 : bb_vinfo->roots.safe_push (slp_root (slp_inst_kind_bb_reduc,
10192 1325401 : stmts, roots, remain));
10193 : }
10194 : }
10195 2169630 : }
10196 : }
10197 2296064 : }
10198 :
10199 : /* Walk the grouped store chains and replace entries with their
10200 : pattern variant if any. */
10201 :
10202 : static void
10203 668497 : vect_fixup_store_groups_with_patterns (vec_info *vinfo)
10204 : {
10205 668497 : stmt_vec_info first_element;
10206 668497 : unsigned i;
10207 :
10208 1579558 : FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
10209 : {
10210 : /* We also have CTORs in this array. */
10211 911061 : if (!STMT_VINFO_GROUPED_ACCESS (first_element))
10212 0 : continue;
10213 911061 : if (STMT_VINFO_IN_PATTERN_P (first_element))
10214 : {
10215 252 : stmt_vec_info orig = first_element;
10216 252 : first_element = STMT_VINFO_RELATED_STMT (first_element);
10217 252 : DR_GROUP_FIRST_ELEMENT (first_element) = first_element;
10218 252 : DR_GROUP_SIZE (first_element) = DR_GROUP_SIZE (orig);
10219 252 : DR_GROUP_GAP (first_element) = DR_GROUP_GAP (orig);
10220 252 : DR_GROUP_NEXT_ELEMENT (first_element) = DR_GROUP_NEXT_ELEMENT (orig);
10221 252 : vinfo->grouped_stores[i] = first_element;
10222 : }
10223 911061 : stmt_vec_info prev = first_element;
10224 2564093 : while (DR_GROUP_NEXT_ELEMENT (prev))
10225 : {
10226 1653032 : stmt_vec_info elt = DR_GROUP_NEXT_ELEMENT (prev);
10227 1653032 : if (STMT_VINFO_IN_PATTERN_P (elt))
10228 : {
10229 849 : stmt_vec_info orig = elt;
10230 849 : elt = STMT_VINFO_RELATED_STMT (elt);
10231 849 : DR_GROUP_NEXT_ELEMENT (prev) = elt;
10232 849 : DR_GROUP_GAP (elt) = DR_GROUP_GAP (orig);
10233 849 : DR_GROUP_NEXT_ELEMENT (elt) = DR_GROUP_NEXT_ELEMENT (orig);
10234 : }
10235 1653032 : DR_GROUP_FIRST_ELEMENT (elt) = first_element;
10236 1653032 : prev = elt;
10237 : }
10238 : }
10239 668497 : }
10240 :
10241 : /* Check if the region described by BB_VINFO can be vectorized, returning
10242 : true if so. When returning false, set FATAL to true if the same failure
10243 : would prevent vectorization at other vector sizes, false if it is still
10244 : worth trying other sizes. N_STMTS is the number of statements in the
10245 : region. */
10246 :
10247 : static bool
10248 2296064 : vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
10249 : vec<int> *dataref_groups)
10250 : {
10251 2296064 : DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
10252 :
10253 2296064 : slp_instance instance;
10254 2296064 : int i;
10255 :
10256 : /* The first group of checks is independent of the vector size. */
10257 2296064 : fatal = true;
10258 :
10259 : /* Analyze the data references. */
10260 :
10261 2296064 : if (!vect_analyze_data_refs (bb_vinfo, NULL))
10262 : {
10263 0 : if (dump_enabled_p ())
10264 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10265 : "not vectorized: unhandled data-ref in basic "
10266 : "block.\n");
10267 : return false;
10268 : }
10269 :
10270 2296064 : if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
10271 : {
10272 0 : if (dump_enabled_p ())
10273 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10274 : "not vectorized: unhandled data access in "
10275 : "basic block.\n");
10276 : return false;
10277 : }
10278 :
10279 2296064 : vect_slp_check_for_roots (bb_vinfo);
10280 :
10281 : /* If there are no grouped stores and no constructors in the region
10282 : there is no need to continue with pattern recog as vect_analyze_slp
10283 : will fail anyway. */
10284 2296064 : if (bb_vinfo->grouped_stores.is_empty ()
10285 1945053 : && bb_vinfo->roots.is_empty ())
10286 : {
10287 1627567 : if (dump_enabled_p ())
10288 1014 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10289 : "not vectorized: no grouped stores in "
10290 : "basic block.\n");
10291 : return false;
10292 : }
10293 :
10294 : /* While the rest of the analysis below depends on it in some way. */
10295 668497 : fatal = false;
10296 :
10297 668497 : vect_pattern_recog (bb_vinfo);
10298 :
10299 : /* Update store groups from pattern processing. */
10300 668497 : vect_fixup_store_groups_with_patterns (bb_vinfo);
10301 :
10302 : /* Check the SLP opportunities in the basic block, analyze and build SLP
10303 : trees. */
10304 668497 : if (!vect_analyze_slp (bb_vinfo, n_stmts, false))
10305 : {
10306 0 : if (dump_enabled_p ())
10307 : {
10308 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10309 : "Failed to SLP the basic block.\n");
10310 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10311 : "not vectorized: failed to find SLP opportunities "
10312 : "in basic block.\n");
10313 : }
10314 : return false;
10315 : }
10316 :
10317 : /* Optimize permutations. */
10318 668497 : vect_optimize_slp (bb_vinfo);
10319 :
10320 : /* Gather the loads reachable from the SLP graph entries. */
10321 668497 : vect_gather_slp_loads (bb_vinfo);
10322 :
10323 668497 : vect_record_base_alignments (bb_vinfo);
10324 :
10325 : /* Analyze and verify the alignment of data references and the
10326 : dependence in the SLP instances. */
10327 2166876 : for (i = 0; BB_VINFO_SLP_INSTANCES (bb_vinfo).iterate (i, &instance); )
10328 : {
10329 829882 : vect_location = instance->location ();
10330 829882 : if (! vect_slp_analyze_instance_alignment (bb_vinfo, instance)
10331 829882 : || ! vect_slp_analyze_instance_dependence (bb_vinfo, instance))
10332 : {
10333 8717 : slp_tree node = SLP_INSTANCE_TREE (instance);
10334 8717 : stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
10335 8717 : if (dump_enabled_p ())
10336 4 : dump_printf_loc (MSG_NOTE, vect_location,
10337 : "removing SLP instance operations starting from: %G",
10338 : stmt_info->stmt);
10339 8717 : vect_free_slp_instance (instance);
10340 8717 : BB_VINFO_SLP_INSTANCES (bb_vinfo).ordered_remove (i);
10341 8717 : continue;
10342 8717 : }
10343 :
10344 : /* Mark all the statements that we want to vectorize as relevant. */
10345 821165 : vect_mark_slp_stmts_relevant (SLP_INSTANCE_TREE (instance));
10346 :
10347 821165 : i++;
10348 : }
10349 2574850 : if (! BB_VINFO_SLP_INSTANCES (bb_vinfo).length ())
10350 : return false;
10351 :
10352 278786 : if (!vect_slp_analyze_operations (bb_vinfo))
10353 : {
10354 31951 : if (dump_enabled_p ())
10355 69 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10356 : "not vectorized: bad operation in basic block.\n");
10357 : return false;
10358 : }
10359 :
10360 : /* Compute vector stmt placement. */
10361 246835 : if (!vect_schedule_slp (bb_vinfo, BB_VINFO_SLP_INSTANCES (bb_vinfo), true))
10362 : {
10363 0 : if (dump_enabled_p ())
10364 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10365 : "not vectorized: cannot schedule SLP graph\n");
10366 : return false;
10367 : }
10368 :
10369 : /* Mark all the statements that we vectorize. */
10370 246835 : vect_bb_slp_mark_stmts_vectorized (bb_vinfo);
10371 :
10372 : /* Compute vectorizable live stmts. */
10373 246835 : vect_bb_slp_mark_live_stmts (bb_vinfo);
10374 :
10375 246835 : vect_bb_partition_graph (bb_vinfo);
10376 :
10377 246835 : return true;
10378 : }
10379 :
10380 : /* Subroutine of vect_slp_bb. Try to vectorize the statements for all
10381 : basic blocks in BBS, returning true on success.
10382 : The region has N_STMTS statements and has the datarefs given by DATAREFS. */
10383 :
10384 : static bool
10385 1939978 : vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs,
10386 : vec<int> *dataref_groups, unsigned int n_stmts,
10387 : loop_p orig_loop)
10388 : {
10389 1939978 : bb_vec_info bb_vinfo;
10390 1939978 : auto_vector_modes vector_modes;
10391 :
10392 : /* Autodetect first vector size we try. */
10393 1939978 : machine_mode next_vector_mode = VOIDmode;
10394 1939978 : targetm.vectorize.autovectorize_vector_modes (&vector_modes, false);
10395 1939978 : unsigned int mode_i = 0;
10396 :
10397 1939978 : vec_info_shared shared;
10398 :
10399 1939978 : machine_mode autodetected_vector_mode = VOIDmode;
10400 2652150 : while (1)
10401 : {
10402 2296064 : bool vectorized = false;
10403 2296064 : bool fatal = false;
10404 2296064 : bb_vinfo = new _bb_vec_info (bbs, &shared);
10405 :
10406 2296064 : bool first_time_p = shared.datarefs.is_empty ();
10407 2296064 : BB_VINFO_DATAREFS (bb_vinfo) = datarefs;
10408 2296064 : if (first_time_p)
10409 1964630 : bb_vinfo->shared->save_datarefs ();
10410 : else
10411 331434 : bb_vinfo->shared->check_datarefs ();
10412 2296064 : bb_vinfo->vector_mode = next_vector_mode;
10413 :
10414 2296064 : if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups))
10415 : {
10416 246835 : if (dump_enabled_p ())
10417 : {
10418 1632 : dump_printf_loc (MSG_NOTE, vect_location,
10419 : "***** Analysis succeeded with vector mode"
10420 816 : " %s\n", GET_MODE_NAME (bb_vinfo->vector_mode));
10421 816 : dump_printf_loc (MSG_NOTE, vect_location, "SLPing BB part\n");
10422 : }
10423 :
10424 246835 : bb_vinfo->shared->check_datarefs ();
10425 :
10426 246835 : bool force_clear = false;
10427 246835 : auto_vec<slp_instance> profitable_subgraphs;
10428 1457451 : for (slp_instance instance : BB_VINFO_SLP_INSTANCES (bb_vinfo))
10429 : {
10430 716946 : if (instance->subgraph_entries.is_empty ())
10431 224034 : continue;
10432 :
10433 689997 : dump_user_location_t saved_vect_location = vect_location;
10434 689997 : vect_location = instance->location ();
10435 689997 : if (!unlimited_cost_model (NULL)
10436 686191 : && !param_vect_allow_possibly_not_worthwhile_vectorizations
10437 1376179 : && !vect_bb_vectorization_profitable_p
10438 686182 : (bb_vinfo, instance->subgraph_entries, orig_loop))
10439 : {
10440 197085 : if (dump_enabled_p ())
10441 51 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10442 : "not vectorized: vectorization is not "
10443 : "profitable.\n");
10444 197085 : vect_location = saved_vect_location;
10445 197085 : continue;
10446 : }
10447 :
10448 492912 : vect_location = saved_vect_location;
10449 492912 : if (!dbg_cnt (vect_slp))
10450 : {
10451 0 : force_clear = true;
10452 0 : continue;
10453 : }
10454 :
10455 492912 : profitable_subgraphs.safe_push (instance);
10456 : }
10457 :
10458 : /* When we're vectorizing an if-converted loop body make sure
10459 : we vectorized all if-converted code. */
10460 410107 : if ((!profitable_subgraphs.is_empty () || force_clear) && orig_loop)
10461 : {
10462 159 : gcc_assert (bb_vinfo->nbbs == 1);
10463 318 : for (gimple_stmt_iterator gsi = gsi_start_bb (bb_vinfo->bbs[0]);
10464 6235 : !gsi_end_p (gsi); gsi_next (&gsi))
10465 : {
10466 : /* The costing above left us with DCEable vectorized scalar
10467 : stmts having the visited flag set on profitable
10468 : subgraphs. Do the delayed clearing of the flag here. */
10469 6076 : if (gimple_visited_p (gsi_stmt (gsi)))
10470 : {
10471 1936 : gimple_set_visited (gsi_stmt (gsi), false);
10472 1936 : continue;
10473 : }
10474 4140 : if (flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED)
10475 813 : continue;
10476 :
10477 9115 : if (gassign *ass = dyn_cast <gassign *> (gsi_stmt (gsi)))
10478 3773 : if (gimple_assign_rhs_code (ass) == COND_EXPR)
10479 : {
10480 175 : if (!profitable_subgraphs.is_empty ()
10481 74 : && dump_enabled_p ())
10482 0 : dump_printf_loc (MSG_NOTE, vect_location,
10483 : "not profitable because of "
10484 : "unprofitable if-converted scalar "
10485 : "code\n");
10486 101 : profitable_subgraphs.truncate (0);
10487 : }
10488 : }
10489 : }
10490 :
10491 : /* Finally schedule the profitable subgraphs. */
10492 1066198 : for (slp_instance instance : profitable_subgraphs)
10493 : {
10494 492819 : if (!vectorized && dump_enabled_p ())
10495 777 : dump_printf_loc (MSG_NOTE, vect_location,
10496 : "Basic block will be vectorized "
10497 : "using SLP\n");
10498 492819 : vectorized = true;
10499 :
10500 : /* Dump before scheduling as store vectorization will remove
10501 : the original stores and mess with the instance tree
10502 : so querying its location will eventually ICE. */
10503 492819 : if (flag_checking)
10504 1983292 : for (slp_instance sub : instance->subgraph_entries)
10505 504835 : gcc_assert (SLP_TREE_VECTYPE (SLP_INSTANCE_TREE (sub)));
10506 492819 : unsigned HOST_WIDE_INT bytes;
10507 492819 : if (dump_enabled_p ())
10508 3693 : for (slp_instance sub : instance->subgraph_entries)
10509 : {
10510 984 : tree vtype = SLP_TREE_VECTYPE (SLP_INSTANCE_TREE (sub));
10511 1968 : if (GET_MODE_SIZE (TYPE_MODE (vtype)).is_constant (&bytes))
10512 984 : dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
10513 984 : sub->location (),
10514 : "basic block part vectorized using %wu "
10515 : "byte vectors\n", bytes);
10516 : else
10517 : dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
10518 : sub->location (),
10519 : "basic block part vectorized using "
10520 : "variable length vectors\n");
10521 : }
10522 :
10523 492819 : dump_user_location_t saved_vect_location = vect_location;
10524 492819 : vect_location = instance->location ();
10525 :
10526 492819 : vect_schedule_slp (bb_vinfo, instance->subgraph_entries, false);
10527 :
10528 492819 : vect_location = saved_vect_location;
10529 : }
10530 :
10531 : /* Generate the invariant statements. */
10532 246835 : if (!gimple_seq_empty_p (bb_vinfo->inv_pattern_def_seq))
10533 : {
10534 27 : if (dump_enabled_p ())
10535 0 : dump_printf_loc (MSG_NOTE, vect_location,
10536 : "------>generating invariant statements\n");
10537 :
10538 27 : bb_vinfo->insert_seq_on_entry (NULL,
10539 : bb_vinfo->inv_pattern_def_seq);
10540 : }
10541 246835 : }
10542 : else
10543 : {
10544 2049229 : if (dump_enabled_p ())
10545 1317 : dump_printf_loc (MSG_NOTE, vect_location,
10546 : "***** Analysis failed with vector mode %s\n",
10547 1317 : GET_MODE_NAME (bb_vinfo->vector_mode));
10548 : }
10549 :
10550 2296064 : if (mode_i == 0)
10551 1939978 : autodetected_vector_mode = bb_vinfo->vector_mode;
10552 :
10553 2296064 : if (!fatal)
10554 3321846 : while (mode_i < vector_modes.length ()
10555 1902302 : && vect_chooses_same_modes_p (bb_vinfo, vector_modes[mode_i]))
10556 : {
10557 357285 : if (dump_enabled_p ())
10558 1772 : dump_printf_loc (MSG_NOTE, vect_location,
10559 : "***** The result for vector mode %s would"
10560 : " be the same\n",
10561 886 : GET_MODE_NAME (vector_modes[mode_i]));
10562 357285 : mode_i += 1;
10563 : }
10564 :
10565 2296064 : delete bb_vinfo;
10566 :
10567 2296064 : if (mode_i < vector_modes.length ()
10568 2100483 : && VECTOR_MODE_P (autodetected_vector_mode)
10569 2093758 : && (related_vector_mode (vector_modes[mode_i],
10570 : GET_MODE_INNER (autodetected_vector_mode))
10571 1046879 : == autodetected_vector_mode)
10572 4396547 : && (related_vector_mode (autodetected_vector_mode,
10573 527499 : GET_MODE_INNER (vector_modes[mode_i]))
10574 1054998 : == vector_modes[mode_i]))
10575 : {
10576 527499 : if (dump_enabled_p ())
10577 195 : dump_printf_loc (MSG_NOTE, vect_location,
10578 : "***** Skipping vector mode %s, which would"
10579 : " repeat the analysis for %s\n",
10580 195 : GET_MODE_NAME (vector_modes[mode_i]),
10581 195 : GET_MODE_NAME (autodetected_vector_mode));
10582 527499 : mode_i += 1;
10583 : }
10584 :
10585 2296064 : if (vectorized
10586 2132866 : || mode_i == vector_modes.length ()
10587 1937334 : || autodetected_vector_mode == VOIDmode
10588 : /* If vect_slp_analyze_bb_1 signaled that analysis for all
10589 : vector sizes will fail do not bother iterating. */
10590 3179794 : || fatal)
10591 3879956 : return vectorized;
10592 :
10593 : /* Try the next biggest vector size. */
10594 356086 : next_vector_mode = vector_modes[mode_i++];
10595 356086 : if (dump_enabled_p ())
10596 235 : dump_printf_loc (MSG_NOTE, vect_location,
10597 : "***** Re-trying analysis with vector mode %s\n",
10598 235 : GET_MODE_NAME (next_vector_mode));
10599 356086 : }
10600 1939978 : }
10601 :
10602 :
10603 : /* Main entry for the BB vectorizer. Analyze and transform BBS, returns
10604 : true if anything in the basic-block was vectorized. */
10605 :
10606 : static bool
10607 1939978 : vect_slp_bbs (const vec<basic_block> &bbs, loop_p orig_loop)
10608 : {
10609 1939978 : vec<data_reference_p> datarefs = vNULL;
10610 1939978 : auto_vec<int> dataref_groups;
10611 1939978 : int insns = 0;
10612 1939978 : int current_group = 0;
10613 :
10614 12845974 : for (unsigned i = 0; i < bbs.length (); i++)
10615 : {
10616 10905996 : basic_block bb = bbs[i];
10617 95562770 : for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
10618 84656774 : gsi_next (&gsi))
10619 : {
10620 84656774 : gimple *stmt = gsi_stmt (gsi);
10621 84656774 : if (is_gimple_debug (stmt))
10622 53909113 : continue;
10623 :
10624 30747661 : insns++;
10625 :
10626 30747661 : if (gimple_location (stmt) != UNKNOWN_LOCATION)
10627 27593989 : vect_location = stmt;
10628 :
10629 30747661 : if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
10630 : &dataref_groups, current_group))
10631 5245041 : ++current_group;
10632 : }
10633 : /* New BBs always start a new DR group. */
10634 10905996 : ++current_group;
10635 : }
10636 :
10637 1939978 : return vect_slp_region (bbs, datarefs, &dataref_groups, insns, orig_loop);
10638 1939978 : }
10639 :
10640 : /* Special entry for the BB vectorizer. Analyze and transform a single
10641 : if-converted BB with ORIG_LOOPs body being the not if-converted
10642 : representation. Returns true if anything in the basic-block was
10643 : vectorized. */
10644 :
10645 : bool
10646 19486 : vect_slp_if_converted_bb (basic_block bb, loop_p orig_loop)
10647 : {
10648 19486 : auto_vec<basic_block> bbs;
10649 19486 : bbs.safe_push (bb);
10650 19486 : return vect_slp_bbs (bbs, orig_loop);
10651 19486 : }
10652 :
10653 : /* Main entry for the BB vectorizer. Analyze and transform BB, returns
10654 : true if anything in the basic-block was vectorized. */
10655 :
10656 : bool
10657 925486 : vect_slp_function (function *fun)
10658 : {
10659 925486 : bool r = false;
10660 925486 : int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun));
10661 925486 : auto_bitmap exit_bbs;
10662 925486 : bitmap_set_bit (exit_bbs, EXIT_BLOCK);
10663 925486 : edge entry = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (fun));
10664 925486 : unsigned n = rev_post_order_and_mark_dfs_back_seme (fun, entry, exit_bbs,
10665 925486 : true, rpo, NULL);
10666 :
10667 : /* For the moment split the function into pieces to avoid making
10668 : the iteration on the vector mode moot. Split at points we know
10669 : to not handle well which is CFG merges (SLP discovery doesn't
10670 : handle non-loop-header PHIs) and loop exits. Since pattern
10671 : recog requires reverse iteration to visit uses before defs
10672 : simply chop RPO into pieces. */
10673 925486 : auto_vec<basic_block> bbs;
10674 11842947 : for (unsigned i = 0; i < n; i++)
10675 : {
10676 10917461 : basic_block bb = BASIC_BLOCK_FOR_FN (fun, rpo[i]);
10677 10917461 : bool split = false;
10678 :
10679 : /* Split when a BB is not dominated by the first block. */
10680 20594532 : if (!bbs.is_empty ()
10681 9677071 : && !dominated_by_p (CDI_DOMINATORS, bb, bbs[0]))
10682 : {
10683 699895 : if (dump_enabled_p ())
10684 146 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10685 : "splitting region at dominance boundary bb%d\n",
10686 : bb->index);
10687 : split = true;
10688 : }
10689 : /* Split when the loop determined by the first block
10690 : is exited. This is because we eventually insert
10691 : invariants at region begin. */
10692 19194742 : else if (!bbs.is_empty ()
10693 8977176 : && bbs[0]->loop_father != bb->loop_father
10694 2326370 : && !flow_loop_nested_p (bbs[0]->loop_father, bb->loop_father))
10695 : {
10696 3852 : if (dump_enabled_p ())
10697 3 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10698 : "splitting region at loop %d exit at bb%d\n",
10699 3 : bbs[0]->loop_father->num, bb->index);
10700 : split = true;
10701 : }
10702 10213714 : else if (!bbs.is_empty ()
10703 8973324 : && bb->loop_father->header == bb
10704 476235 : && bb->loop_father->dont_vectorize)
10705 : {
10706 7306 : if (dump_enabled_p ())
10707 72 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10708 : "splitting region at dont-vectorize loop %d "
10709 : "entry at bb%d\n",
10710 : bb->loop_father->num, bb->index);
10711 : split = true;
10712 : }
10713 :
10714 221 : if (split && !bbs.is_empty ())
10715 : {
10716 711053 : r |= vect_slp_bbs (bbs, NULL);
10717 711053 : bbs.truncate (0);
10718 : }
10719 :
10720 10917461 : if (bbs.is_empty ())
10721 : {
10722 : /* We need to be able to insert at the head of the region which
10723 : we cannot for region starting with a returns-twice call. */
10724 1951443 : if (gcall *first = safe_dyn_cast <gcall *> (first_stmt (bb)))
10725 412068 : if (gimple_call_flags (first) & ECF_RETURNS_TWICE)
10726 : {
10727 306 : if (dump_enabled_p ())
10728 2 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10729 : "skipping bb%d as start of region as it "
10730 : "starts with returns-twice call\n",
10731 : bb->index);
10732 30951 : continue;
10733 : }
10734 : /* If the loop this BB belongs to is marked as not to be vectorized
10735 : honor that also for BB vectorization. */
10736 1951137 : if (bb->loop_father->dont_vectorize)
10737 30645 : continue;
10738 : }
10739 :
10740 10886510 : bbs.safe_push (bb);
10741 :
10742 : /* When we have a stmt ending this block and defining a
10743 : value we have to insert on edges when inserting after it for
10744 : a vector containing its definition. Avoid this for now. */
10745 21773020 : if (gimple *last = *gsi_last_bb (bb))
10746 8865377 : if (gimple_get_lhs (last)
10747 8865377 : && is_ctrl_altering_stmt (last))
10748 : {
10749 283960 : if (dump_enabled_p ())
10750 2 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
10751 : "splitting region at control altering "
10752 : "definition %G", last);
10753 283960 : r |= vect_slp_bbs (bbs, NULL);
10754 283960 : bbs.truncate (0);
10755 : }
10756 : }
10757 :
10758 925486 : if (!bbs.is_empty ())
10759 925479 : r |= vect_slp_bbs (bbs, NULL);
10760 :
10761 925486 : free (rpo);
10762 :
10763 925486 : return r;
10764 925486 : }
10765 :
10766 : /* Build a variable-length vector in which the elements in ELTS are repeated
10767 : to a fill NRESULTS vectors of type VECTOR_TYPE. Store the vectors in
10768 : RESULTS and add any new instructions to SEQ.
10769 :
10770 : The approach we use is:
10771 :
10772 : (1) Find a vector mode VM with integer elements of mode IM.
10773 :
10774 : (2) Replace ELTS[0:NELTS] with ELTS'[0:NELTS'], where each element of
10775 : ELTS' has mode IM. This involves creating NELTS' VIEW_CONVERT_EXPRs
10776 : from small vectors to IM.
10777 :
10778 : (3) Duplicate each ELTS'[I] into a vector of mode VM.
10779 :
10780 : (4) Use a tree of interleaving VEC_PERM_EXPRs to create VMs with the
10781 : correct byte contents.
10782 :
10783 : (5) Use VIEW_CONVERT_EXPR to cast the final VMs to the required type.
10784 :
10785 : We try to find the largest IM for which this sequence works, in order
10786 : to cut down on the number of interleaves. */
10787 :
10788 : void
10789 0 : duplicate_and_interleave (vec_info *vinfo, gimple_seq *seq, tree vector_type,
10790 : const vec<tree> &elts, unsigned int nresults,
10791 : vec<tree> &results)
10792 : {
10793 0 : unsigned int nelts = elts.length ();
10794 0 : tree element_type = TREE_TYPE (vector_type);
10795 :
10796 : /* (1) Find a vector mode VM with integer elements of mode IM. */
10797 0 : unsigned int nvectors = 1;
10798 0 : tree new_vector_type;
10799 0 : tree permutes[2];
10800 0 : if (!can_duplicate_and_interleave_p (vinfo, nelts, element_type,
10801 : &nvectors, &new_vector_type,
10802 : permutes))
10803 0 : gcc_unreachable ();
10804 :
10805 : /* Get a vector type that holds ELTS[0:NELTS/NELTS']. */
10806 0 : unsigned int partial_nelts = nelts / nvectors;
10807 0 : tree partial_vector_type = build_vector_type (element_type, partial_nelts);
10808 :
10809 0 : tree_vector_builder partial_elts;
10810 0 : auto_vec<tree, 32> pieces (nvectors * 2);
10811 0 : pieces.quick_grow_cleared (nvectors * 2);
10812 0 : for (unsigned int i = 0; i < nvectors; ++i)
10813 : {
10814 : /* (2) Replace ELTS[0:NELTS] with ELTS'[0:NELTS'], where each element of
10815 : ELTS' has mode IM. */
10816 0 : partial_elts.new_vector (partial_vector_type, partial_nelts, 1);
10817 0 : for (unsigned int j = 0; j < partial_nelts; ++j)
10818 0 : partial_elts.quick_push (elts[i * partial_nelts + j]);
10819 0 : tree t = gimple_build_vector (seq, &partial_elts);
10820 0 : t = gimple_build (seq, VIEW_CONVERT_EXPR,
10821 0 : TREE_TYPE (new_vector_type), t);
10822 :
10823 : /* (3) Duplicate each ELTS'[I] into a vector of mode VM. */
10824 0 : pieces[i] = gimple_build_vector_from_val (seq, new_vector_type, t);
10825 : }
10826 :
10827 : /* (4) Use a tree of VEC_PERM_EXPRs to create a single VM with the
10828 : correct byte contents.
10829 :
10830 : Conceptually, we need to repeat the following operation log2(nvectors)
10831 : times, where hi_start = nvectors / 2:
10832 :
10833 : out[i * 2] = VEC_PERM_EXPR (in[i], in[i + hi_start], lo_permute);
10834 : out[i * 2 + 1] = VEC_PERM_EXPR (in[i], in[i + hi_start], hi_permute);
10835 :
10836 : However, if each input repeats every N elements and the VF is
10837 : a multiple of N * 2, the HI result is the same as the LO result.
10838 : This will be true for the first N1 iterations of the outer loop,
10839 : followed by N2 iterations for which both the LO and HI results
10840 : are needed. I.e.:
10841 :
10842 : N1 + N2 = log2(nvectors)
10843 :
10844 : Each "N1 iteration" doubles the number of redundant vectors and the
10845 : effect of the process as a whole is to have a sequence of nvectors/2**N1
10846 : vectors that repeats 2**N1 times. Rather than generate these redundant
10847 : vectors, we halve the number of vectors for each N1 iteration. */
10848 : unsigned int in_start = 0;
10849 : unsigned int out_start = nvectors;
10850 : unsigned int new_nvectors = nvectors;
10851 0 : for (unsigned int in_repeat = 1; in_repeat < nvectors; in_repeat *= 2)
10852 : {
10853 0 : unsigned int hi_start = new_nvectors / 2;
10854 0 : unsigned int out_i = 0;
10855 0 : for (unsigned int in_i = 0; in_i < new_nvectors; ++in_i)
10856 : {
10857 0 : if ((in_i & 1) != 0
10858 0 : && multiple_p (TYPE_VECTOR_SUBPARTS (new_vector_type),
10859 : 2 * in_repeat))
10860 0 : continue;
10861 :
10862 0 : tree output = make_ssa_name (new_vector_type);
10863 0 : tree input1 = pieces[in_start + (in_i / 2)];
10864 0 : tree input2 = pieces[in_start + (in_i / 2) + hi_start];
10865 0 : gassign *stmt = gimple_build_assign (output, VEC_PERM_EXPR,
10866 : input1, input2,
10867 : permutes[in_i & 1]);
10868 0 : gimple_seq_add_stmt (seq, stmt);
10869 0 : pieces[out_start + out_i] = output;
10870 0 : out_i += 1;
10871 : }
10872 0 : std::swap (in_start, out_start);
10873 0 : new_nvectors = out_i;
10874 : }
10875 :
10876 : /* (5) Use VIEW_CONVERT_EXPR to cast the final VM to the required type. */
10877 0 : results.reserve (nresults);
10878 0 : for (unsigned int i = 0; i < nresults; ++i)
10879 0 : if (i < new_nvectors)
10880 0 : results.quick_push (gimple_build (seq, VIEW_CONVERT_EXPR, vector_type,
10881 0 : pieces[in_start + i]));
10882 : else
10883 0 : results.quick_push (results[i - new_nvectors]);
10884 0 : }
10885 :
10886 :
10887 : /* For constant and loop invariant defs in OP_NODE this function creates
10888 : vector defs that will be used in the vectorized stmts and stores them
10889 : to SLP_TREE_VEC_DEFS of OP_NODE. */
10890 :
10891 : static void
10892 501404 : vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
10893 : {
10894 501404 : unsigned HOST_WIDE_INT nunits;
10895 501404 : tree vec_cst;
10896 501404 : unsigned j, number_of_places_left_in_vector;
10897 501404 : tree vector_type;
10898 501404 : tree vop;
10899 501404 : int group_size = op_node->ops.length ();
10900 501404 : unsigned int vec_num, i;
10901 501404 : unsigned number_of_copies = 1;
10902 501404 : bool constant_p;
10903 501404 : gimple_seq ctor_seq = NULL;
10904 501404 : auto_vec<tree, 16> permute_results;
10905 :
10906 : /* We always want SLP_TREE_VECTYPE (op_node) here correctly set. */
10907 501404 : vector_type = SLP_TREE_VECTYPE (op_node);
10908 :
10909 501404 : unsigned int number_of_vectors;
10910 501404 : bool res = vect_get_num_copies_for_invariant (vinfo, op_node,
10911 : &number_of_vectors);
10912 501404 : gcc_assert (res);
10913 501404 : SLP_TREE_VEC_DEFS (op_node).create (number_of_vectors);
10914 501404 : auto_vec<tree> voprnds (number_of_vectors);
10915 :
10916 : /* NUMBER_OF_COPIES is the number of times we need to use the same values in
10917 : created vectors. It is greater than 1 if unrolling is performed.
10918 :
10919 : For example, we have two scalar operands, s1 and s2 (e.g., group of
10920 : strided accesses of size two), while NUNITS is four (i.e., four scalars
10921 : of this type can be packed in a vector). The output vector will contain
10922 : two copies of each scalar operand: {s1, s2, s1, s2}. (NUMBER_OF_COPIES
10923 : will be 2).
10924 :
10925 : If GROUP_SIZE > NUNITS, the scalars will be split into several vectors
10926 : containing the operands.
10927 :
10928 : For example, NUNITS is four as before, and the group size is 8
10929 : (s1, s2, ..., s8). We will create two vectors {s1, s2, s3, s4} and
10930 : {s5, s6, s7, s8}. */
10931 :
10932 : /* When using duplicate_and_interleave, we just need one element for
10933 : each scalar statement. */
10934 501404 : if (!TYPE_VECTOR_SUBPARTS (vector_type).is_constant (&nunits))
10935 : nunits = group_size;
10936 :
10937 501404 : number_of_copies = nunits * number_of_vectors / group_size;
10938 :
10939 501404 : number_of_places_left_in_vector = nunits;
10940 501404 : constant_p = true;
10941 501404 : tree uniform_elt = NULL_TREE;
10942 501404 : tree_vector_builder elts (vector_type, nunits, 1);
10943 501404 : elts.quick_grow (nunits);
10944 501404 : stmt_vec_info insert_after = NULL;
10945 1988254 : for (j = 0; j < number_of_copies; j++)
10946 : {
10947 985446 : tree op;
10948 3786056 : for (i = group_size - 1; op_node->ops.iterate (i, &op); i--)
10949 : {
10950 : /* Create 'vect_ = {op0,op1,...,opn}'. */
10951 1815164 : tree orig_op = op;
10952 1815164 : if (number_of_places_left_in_vector == nunits)
10953 : uniform_elt = op;
10954 1181691 : else if (uniform_elt && operand_equal_p (uniform_elt, op))
10955 748073 : op = elts[number_of_places_left_in_vector];
10956 : else
10957 : uniform_elt = NULL_TREE;
10958 1815164 : number_of_places_left_in_vector--;
10959 1815164 : if (!types_compatible_p (TREE_TYPE (vector_type), TREE_TYPE (op)))
10960 : {
10961 281222 : if (CONSTANT_CLASS_P (op))
10962 : {
10963 102487 : if (VECTOR_BOOLEAN_TYPE_P (vector_type))
10964 : {
10965 : /* Can't use VIEW_CONVERT_EXPR for booleans because
10966 : of possibly different sizes of scalar value and
10967 : vector element. */
10968 66 : if (integer_zerop (op))
10969 66 : op = build_int_cst (TREE_TYPE (vector_type), 0);
10970 0 : else if (integer_onep (op))
10971 0 : op = build_all_ones_cst (TREE_TYPE (vector_type));
10972 : else
10973 0 : gcc_unreachable ();
10974 : }
10975 : else
10976 102421 : op = fold_unary (VIEW_CONVERT_EXPR,
10977 : TREE_TYPE (vector_type), op);
10978 102487 : gcc_assert (op && CONSTANT_CLASS_P (op));
10979 : }
10980 : else
10981 : {
10982 178735 : tree new_temp = make_ssa_name (TREE_TYPE (vector_type));
10983 178735 : gimple *init_stmt;
10984 178735 : if (VECTOR_BOOLEAN_TYPE_P (vector_type))
10985 : {
10986 427 : tree true_val
10987 427 : = build_all_ones_cst (TREE_TYPE (vector_type));
10988 427 : tree false_val
10989 427 : = build_zero_cst (TREE_TYPE (vector_type));
10990 427 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (op)));
10991 427 : init_stmt = gimple_build_assign (new_temp, COND_EXPR,
10992 : op, true_val,
10993 : false_val);
10994 : }
10995 : else
10996 : {
10997 178308 : op = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (vector_type),
10998 : op);
10999 178308 : init_stmt
11000 178308 : = gimple_build_assign (new_temp, VIEW_CONVERT_EXPR,
11001 : op);
11002 : }
11003 178735 : gimple_seq_add_stmt (&ctor_seq, init_stmt);
11004 178735 : op = new_temp;
11005 : }
11006 : }
11007 1815164 : elts[number_of_places_left_in_vector] = op;
11008 1815164 : if (!CONSTANT_CLASS_P (op))
11009 324102 : constant_p = false;
11010 : /* For BB vectorization we have to compute an insert location
11011 : when a def is inside the analyzed region since we cannot
11012 : simply insert at the BB start in this case. */
11013 1815164 : stmt_vec_info opdef;
11014 1815164 : if (TREE_CODE (orig_op) == SSA_NAME
11015 186530 : && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
11016 166258 : && is_a <bb_vec_info> (vinfo)
11017 1923821 : && (opdef = vinfo->lookup_def (orig_op)))
11018 : {
11019 88956 : if (!insert_after)
11020 : insert_after = opdef;
11021 : else
11022 48829 : insert_after = get_later_stmt (insert_after, opdef);
11023 : }
11024 :
11025 1815164 : if (number_of_places_left_in_vector == 0)
11026 : {
11027 633473 : auto type_nunits = TYPE_VECTOR_SUBPARTS (vector_type);
11028 633473 : if (uniform_elt)
11029 657624 : vec_cst = gimple_build_vector_from_val (&ctor_seq, vector_type,
11030 328812 : elts[0]);
11031 609322 : else if (constant_p
11032 609322 : ? multiple_p (type_nunits, nunits)
11033 112697 : : known_eq (type_nunits, nunits))
11034 304661 : vec_cst = gimple_build_vector (&ctor_seq, &elts);
11035 : else
11036 : {
11037 0 : if (permute_results.is_empty ())
11038 0 : duplicate_and_interleave (vinfo, &ctor_seq, vector_type,
11039 : elts, number_of_vectors,
11040 : permute_results);
11041 0 : vec_cst = permute_results[number_of_vectors - j - 1];
11042 : }
11043 633473 : if (!gimple_seq_empty_p (ctor_seq))
11044 : {
11045 140612 : if (insert_after)
11046 : {
11047 40127 : gimple_stmt_iterator gsi;
11048 40127 : if (gimple_code (insert_after->stmt) == GIMPLE_PHI)
11049 : {
11050 749 : gsi = gsi_after_labels (gimple_bb (insert_after->stmt));
11051 749 : gsi_insert_seq_before (&gsi, ctor_seq,
11052 : GSI_CONTINUE_LINKING);
11053 : }
11054 39378 : else if (!stmt_ends_bb_p (insert_after->stmt))
11055 : {
11056 39378 : gsi = gsi_for_stmt (insert_after->stmt);
11057 39378 : gsi_insert_seq_after (&gsi, ctor_seq,
11058 : GSI_CONTINUE_LINKING);
11059 : }
11060 : else
11061 : {
11062 : /* When we want to insert after a def where the
11063 : defining stmt throws then insert on the fallthru
11064 : edge. */
11065 0 : edge e = find_fallthru_edge
11066 0 : (gimple_bb (insert_after->stmt)->succs);
11067 0 : basic_block new_bb
11068 0 : = gsi_insert_seq_on_edge_immediate (e, ctor_seq);
11069 0 : gcc_assert (!new_bb);
11070 : }
11071 : }
11072 : else
11073 100485 : vinfo->insert_seq_on_entry (NULL, ctor_seq);
11074 140612 : ctor_seq = NULL;
11075 : }
11076 633473 : voprnds.quick_push (vec_cst);
11077 633473 : insert_after = NULL;
11078 633473 : number_of_places_left_in_vector = nunits;
11079 633473 : constant_p = true;
11080 633473 : elts.new_vector (vector_type, nunits, 1);
11081 633473 : elts.quick_grow (nunits);
11082 : }
11083 : }
11084 : }
11085 :
11086 : /* Since the vectors are created in the reverse order, we should invert
11087 : them. */
11088 501404 : vec_num = voprnds.length ();
11089 1134877 : for (j = vec_num; j != 0; j--)
11090 : {
11091 633473 : vop = voprnds[j - 1];
11092 633473 : SLP_TREE_VEC_DEFS (op_node).quick_push (vop);
11093 : }
11094 :
11095 : /* In case that VF is greater than the unrolling factor needed for the SLP
11096 : group of stmts, NUMBER_OF_VECTORS to be created is greater than
11097 : NUMBER_OF_SCALARS/NUNITS or NUNITS/NUMBER_OF_SCALARS, and hence we have
11098 : to replicate the vectors. */
11099 1002808 : while (number_of_vectors > SLP_TREE_VEC_DEFS (op_node).length ())
11100 0 : for (i = 0; SLP_TREE_VEC_DEFS (op_node).iterate (i, &vop) && i < vec_num;
11101 : i++)
11102 0 : SLP_TREE_VEC_DEFS (op_node).quick_push (vop);
11103 501404 : }
11104 :
11105 : /* Get the scalar definition of the Nth lane from SLP_NODE or NULL_TREE
11106 : if there is no definition for it in the scalar IL or it is not known. */
11107 :
11108 : tree
11109 2617 : vect_get_slp_scalar_def (slp_tree slp_node, unsigned n)
11110 : {
11111 2617 : if (SLP_TREE_DEF_TYPE (slp_node) == vect_internal_def)
11112 : {
11113 2605 : if (!SLP_TREE_SCALAR_STMTS (slp_node).exists ())
11114 : return NULL_TREE;
11115 2605 : stmt_vec_info def = SLP_TREE_SCALAR_STMTS (slp_node)[n];
11116 2605 : if (!def)
11117 : return NULL_TREE;
11118 2605 : return gimple_get_lhs (STMT_VINFO_STMT (def));
11119 : }
11120 : else
11121 12 : return SLP_TREE_SCALAR_OPS (slp_node)[n];
11122 : }
11123 :
11124 : /* Get the Ith vectorized definition from SLP_NODE. */
11125 :
11126 : tree
11127 145650 : vect_get_slp_vect_def (slp_tree slp_node, unsigned i)
11128 : {
11129 145650 : return SLP_TREE_VEC_DEFS (slp_node)[i];
11130 : }
11131 :
11132 : /* Get the vectorized definitions of SLP_NODE in *VEC_DEFS. */
11133 :
11134 : void
11135 951364 : vect_get_slp_defs (slp_tree slp_node, vec<tree> *vec_defs)
11136 : {
11137 1902728 : vec_defs->create (SLP_TREE_VEC_DEFS (slp_node).length ());
11138 951364 : vec_defs->splice (SLP_TREE_VEC_DEFS (slp_node));
11139 951364 : }
11140 :
11141 : /* Get N vectorized definitions for SLP_NODE. */
11142 :
11143 : void
11144 2953 : vect_get_slp_defs (vec_info *,
11145 : slp_tree slp_node, vec<vec<tree> > *vec_oprnds, unsigned n)
11146 : {
11147 2953 : if (n == -1U)
11148 2953 : n = SLP_TREE_CHILDREN (slp_node).length ();
11149 :
11150 10648 : for (unsigned i = 0; i < n; ++i)
11151 : {
11152 7695 : slp_tree child = SLP_TREE_CHILDREN (slp_node)[i];
11153 7695 : vec<tree> vec_defs = vNULL;
11154 7695 : vect_get_slp_defs (child, &vec_defs);
11155 7695 : vec_oprnds->quick_push (vec_defs);
11156 : }
11157 2953 : }
11158 :
11159 : /* A subroutine of vect_transform_slp_perm_load with two extra arguments:
11160 : - PERM gives the permutation that the caller wants to use for NODE,
11161 : which might be different from SLP_LOAD_PERMUTATION.
11162 : - DUMP_P controls whether the function dumps information. */
11163 :
11164 : static bool
11165 138456 : vect_transform_slp_perm_load_1 (vec_info *vinfo, slp_tree node,
11166 : load_permutation_t &perm,
11167 : const vec<tree> &dr_chain,
11168 : gimple_stmt_iterator *gsi, poly_uint64 vf,
11169 : bool analyze_only, bool dump_p,
11170 : unsigned *n_perms, unsigned int *n_loads,
11171 : bool dce_chain)
11172 : {
11173 138456 : stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
11174 138456 : int vec_index = 0;
11175 138456 : tree vectype = SLP_TREE_VECTYPE (node);
11176 138456 : unsigned int group_size = SLP_TREE_LANES (node);
11177 138456 : unsigned int mask_element;
11178 138456 : unsigned dr_group_size;
11179 138456 : machine_mode mode;
11180 :
11181 138456 : if (!STMT_VINFO_GROUPED_ACCESS (stmt_info))
11182 : {
11183 : /* We have both splats of the same non-grouped load and groups
11184 : of distinct invariant loads entering here. */
11185 1491 : unsigned max_idx = 0;
11186 8261 : for (auto idx : perm)
11187 3788 : max_idx = idx > max_idx ? idx : max_idx;
11188 1491 : dr_group_size = max_idx + 1;
11189 : }
11190 : else
11191 : {
11192 136965 : stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
11193 136965 : dr_group_size = DR_GROUP_SIZE (stmt_info);
11194 : }
11195 :
11196 138456 : mode = TYPE_MODE (vectype);
11197 138456 : poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
11198 138456 : unsigned int nstmts = vect_get_num_copies (vinfo, node);
11199 :
11200 : /* Initialize the vect stmts of NODE to properly insert the generated
11201 : stmts later. */
11202 138456 : if (! analyze_only)
11203 59522 : for (unsigned i = SLP_TREE_VEC_DEFS (node).length (); i < nstmts; i++)
11204 22874 : SLP_TREE_VEC_DEFS (node).quick_push (NULL_TREE);
11205 :
11206 : /* Generate permutation masks for every NODE. Number of masks for each NODE
11207 : is equal to GROUP_SIZE.
11208 : E.g., we have a group of three nodes with three loads from the same
11209 : location in each node, and the vector size is 4. I.e., we have a
11210 : a0b0c0a1b1c1... sequence and we need to create the following vectors:
11211 : for a's: a0a0a0a1 a1a1a2a2 a2a3a3a3
11212 : for b's: b0b0b0b1 b1b1b2b2 b2b3b3b3
11213 : ...
11214 :
11215 : The masks for a's should be: {0,0,0,3} {3,3,6,6} {6,9,9,9}.
11216 : The last mask is illegal since we assume two operands for permute
11217 : operation, and the mask element values can't be outside that range.
11218 : Hence, the last mask must be converted into {2,5,5,5}.
11219 : For the first two permutations we need the first and the second input
11220 : vectors: {a0,b0,c0,a1} and {b1,c1,a2,b2}, and for the last permutation
11221 : we need the second and the third vectors: {b1,c1,a2,b2} and
11222 : {c2,a3,b3,c3}. */
11223 :
11224 138456 : int vect_stmts_counter = 0;
11225 138456 : unsigned int index = 0;
11226 138456 : int first_vec_index = -1;
11227 138456 : int second_vec_index = -1;
11228 138456 : bool noop_p = true;
11229 138456 : *n_perms = 0;
11230 :
11231 138456 : vec_perm_builder mask;
11232 138456 : unsigned int nelts_to_build;
11233 138456 : unsigned int nvectors_per_build;
11234 138456 : unsigned int in_nlanes;
11235 138456 : bool repeating_p = (group_size == dr_group_size
11236 174311 : && multiple_p (nunits, group_size));
11237 138456 : if (repeating_p)
11238 : {
11239 : /* A single vector contains a whole number of copies of the node, so:
11240 : (a) all permutes can use the same mask; and
11241 : (b) the permutes only need a single vector input. */
11242 33447 : mask.new_vector (nunits, group_size, 3);
11243 33447 : nelts_to_build = mask.encoded_nelts ();
11244 : /* It's possible to obtain zero nstmts during analyze_only, so make
11245 : it at least one to ensure the later computation for n_perms
11246 : proceed. */
11247 33447 : nvectors_per_build = nstmts > 0 ? nstmts : 1;
11248 33447 : in_nlanes = dr_group_size * 3;
11249 : }
11250 : else
11251 : {
11252 : /* We need to construct a separate mask for each vector statement. */
11253 105009 : unsigned HOST_WIDE_INT const_nunits, const_vf;
11254 105009 : if (!nunits.is_constant (&const_nunits)
11255 105009 : || !vf.is_constant (&const_vf))
11256 : return false;
11257 105009 : mask.new_vector (const_nunits, const_nunits, 1);
11258 105009 : nelts_to_build = const_vf * group_size;
11259 105009 : nvectors_per_build = 1;
11260 105009 : in_nlanes = const_vf * dr_group_size;
11261 : }
11262 138456 : auto_sbitmap used_in_lanes (in_nlanes);
11263 138456 : bitmap_clear (used_in_lanes);
11264 138456 : auto_bitmap used_defs;
11265 :
11266 138456 : unsigned int count = mask.encoded_nelts ();
11267 138456 : mask.quick_grow (count);
11268 138456 : vec_perm_indices indices;
11269 :
11270 727241 : for (unsigned int j = 0; j < nelts_to_build; j++)
11271 : {
11272 600136 : unsigned int iter_num = j / group_size;
11273 600136 : unsigned int stmt_num = j % group_size;
11274 600136 : unsigned int i = (iter_num * dr_group_size + perm[stmt_num]);
11275 600136 : bitmap_set_bit (used_in_lanes, i);
11276 600136 : if (repeating_p)
11277 : {
11278 : first_vec_index = 0;
11279 : mask_element = i;
11280 : }
11281 : else
11282 : {
11283 : /* Enforced before the loop when !repeating_p. */
11284 382372 : unsigned int const_nunits = nunits.to_constant ();
11285 382372 : vec_index = i / const_nunits;
11286 382372 : mask_element = i % const_nunits;
11287 382372 : if (vec_index == first_vec_index
11288 382372 : || first_vec_index == -1)
11289 : {
11290 : first_vec_index = vec_index;
11291 : }
11292 153077 : else if (vec_index == second_vec_index
11293 153077 : || second_vec_index == -1)
11294 : {
11295 146799 : second_vec_index = vec_index;
11296 146799 : mask_element += const_nunits;
11297 : }
11298 : else
11299 : {
11300 6278 : if (dump_p)
11301 280 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
11302 : "permutation requires at "
11303 : "least three vectors %G",
11304 : stmt_info->stmt);
11305 6278 : gcc_assert (analyze_only);
11306 : return false;
11307 : }
11308 :
11309 376094 : gcc_assert (mask_element < 2 * const_nunits);
11310 : }
11311 :
11312 593858 : if (mask_element != index)
11313 381789 : noop_p = false;
11314 593858 : mask[index++] = mask_element;
11315 :
11316 593858 : if (index == count)
11317 : {
11318 163037 : if (!noop_p)
11319 : {
11320 132832 : indices.new_vector (mask, second_vec_index == -1 ? 1 : 2, nunits);
11321 132832 : if (!can_vec_perm_const_p (mode, mode, indices))
11322 : {
11323 5073 : if (dump_p)
11324 : {
11325 79 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
11326 : "unsupported vect permute { ");
11327 673 : for (i = 0; i < count; ++i)
11328 : {
11329 594 : dump_dec (MSG_MISSED_OPTIMIZATION, mask[i]);
11330 594 : dump_printf (MSG_MISSED_OPTIMIZATION, " ");
11331 : }
11332 79 : dump_printf (MSG_MISSED_OPTIMIZATION, "}\n");
11333 : }
11334 5073 : gcc_assert (analyze_only);
11335 : return false;
11336 : }
11337 :
11338 127759 : tree mask_vec = NULL_TREE;
11339 127759 : if (!analyze_only)
11340 21151 : mask_vec = vect_gen_perm_mask_checked (vectype, indices);
11341 :
11342 127759 : if (second_vec_index == -1)
11343 36882 : second_vec_index = first_vec_index;
11344 :
11345 258383 : for (unsigned int ri = 0; ri < nvectors_per_build; ++ri)
11346 : {
11347 130624 : ++*n_perms;
11348 130624 : if (analyze_only)
11349 109190 : continue;
11350 : /* Generate the permute statement if necessary. */
11351 21434 : tree first_vec = dr_chain[first_vec_index + ri];
11352 21434 : tree second_vec = dr_chain[second_vec_index + ri];
11353 21434 : gassign *stmt = as_a<gassign *> (stmt_info->stmt);
11354 21434 : tree perm_dest
11355 21434 : = vect_create_destination_var (gimple_assign_lhs (stmt),
11356 : vectype);
11357 21434 : perm_dest = make_ssa_name (perm_dest);
11358 21434 : gimple *perm_stmt
11359 21434 : = gimple_build_assign (perm_dest, VEC_PERM_EXPR, first_vec,
11360 : second_vec, mask_vec);
11361 21434 : vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt,
11362 : gsi);
11363 21434 : if (dce_chain)
11364 : {
11365 20511 : bitmap_set_bit (used_defs, first_vec_index + ri);
11366 20511 : bitmap_set_bit (used_defs, second_vec_index + ri);
11367 : }
11368 :
11369 : /* Store the vector statement in NODE. */
11370 21434 : SLP_TREE_VEC_DEFS (node)[vect_stmts_counter++] = perm_dest;
11371 : }
11372 : }
11373 30205 : else if (!analyze_only)
11374 : {
11375 2880 : for (unsigned int ri = 0; ri < nvectors_per_build; ++ri)
11376 : {
11377 1440 : tree first_vec = dr_chain[first_vec_index + ri];
11378 : /* If mask was NULL_TREE generate the requested
11379 : identity transform. */
11380 1440 : if (dce_chain)
11381 1433 : bitmap_set_bit (used_defs, first_vec_index + ri);
11382 :
11383 : /* Store the vector statement in NODE. */
11384 1440 : SLP_TREE_VEC_DEFS (node)[vect_stmts_counter++] = first_vec;
11385 : }
11386 : }
11387 :
11388 : index = 0;
11389 : first_vec_index = -1;
11390 : second_vec_index = -1;
11391 : noop_p = true;
11392 : }
11393 : }
11394 :
11395 127105 : if (n_loads)
11396 : {
11397 89062 : if (repeating_p)
11398 10860 : *n_loads = nstmts;
11399 : else
11400 : {
11401 : /* Enforced above when !repeating_p. */
11402 78202 : unsigned int const_nunits = nunits.to_constant ();
11403 78202 : *n_loads = 0;
11404 78202 : bool load_seen = false;
11405 1051385 : for (unsigned i = 0; i < in_nlanes; ++i)
11406 : {
11407 973183 : if (i % const_nunits == 0)
11408 : {
11409 415634 : if (load_seen)
11410 123702 : *n_loads += 1;
11411 : load_seen = false;
11412 : }
11413 973183 : if (bitmap_bit_p (used_in_lanes, i))
11414 270874 : load_seen = true;
11415 : }
11416 78202 : if (load_seen)
11417 52247 : *n_loads += 1;
11418 : }
11419 : }
11420 :
11421 127105 : if (dce_chain)
11422 213082 : for (unsigned i = 0; i < dr_chain.length (); ++i)
11423 74626 : if (!bitmap_bit_p (used_defs, i))
11424 : {
11425 40903 : tree def = dr_chain[i];
11426 41315 : do
11427 : {
11428 41315 : gimple *stmt = SSA_NAME_DEF_STMT (def);
11429 41315 : if (is_gimple_assign (stmt)
11430 41315 : && (gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR
11431 41315 : || gimple_assign_rhs_code (stmt) == CONSTRUCTOR))
11432 4981 : def = single_ssa_tree_operand (stmt, SSA_OP_USE);
11433 : else
11434 : def = NULL;
11435 41315 : gimple_stmt_iterator rgsi = gsi_for_stmt (stmt);
11436 41315 : gsi_remove (&rgsi, true);
11437 41315 : release_defs (stmt);
11438 : }
11439 41315 : while (def);
11440 : }
11441 :
11442 : return true;
11443 138456 : }
11444 :
11445 : /* Generate vector permute statements from a list of loads in DR_CHAIN.
11446 : If ANALYZE_ONLY is TRUE, only check that it is possible to create valid
11447 : permute statements for the SLP node NODE. Store the number of vector
11448 : permute instructions in *N_PERMS and the number of vector load
11449 : instructions in *N_LOADS. If DCE_CHAIN is true, remove all definitions
11450 : that were not needed. */
11451 :
11452 : bool
11453 98840 : vect_transform_slp_perm_load (vec_info *vinfo,
11454 : slp_tree node, const vec<tree> &dr_chain,
11455 : gimple_stmt_iterator *gsi, poly_uint64 vf,
11456 : bool analyze_only, unsigned *n_perms,
11457 : unsigned int *n_loads, bool dce_chain)
11458 : {
11459 98840 : return vect_transform_slp_perm_load_1 (vinfo, node,
11460 98840 : SLP_TREE_LOAD_PERMUTATION (node),
11461 : dr_chain, gsi, vf, analyze_only,
11462 : dump_enabled_p (), n_perms, n_loads,
11463 98840 : dce_chain);
11464 : }
11465 :
11466 : /* Produce the next vector result for SLP permutation NODE by adding a vector
11467 : statement at GSI. If MASK_VEC is nonnull, add:
11468 :
11469 : <new SSA name> = VEC_PERM_EXPR <FIRST_DEF, SECOND_DEF, MASK_VEC>
11470 :
11471 : otherwise add:
11472 :
11473 : <new SSA name> = VEC_PERM_EXPR <FIRST_DEF, SECOND_DEF,
11474 : { N, N+1, N+2, ... }>
11475 :
11476 : where N == IDENTITY_OFFSET which is either zero or equal to the
11477 : number of elements of the result. */
11478 :
11479 : static void
11480 31651 : vect_add_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi,
11481 : slp_tree node, tree first_def, tree second_def,
11482 : tree mask_vec, poly_uint64 identity_offset)
11483 : {
11484 31651 : tree vectype = SLP_TREE_VECTYPE (node);
11485 :
11486 : /* ??? We SLP match existing vector element extracts but
11487 : allow punning which we need to re-instantiate at uses
11488 : but have no good way of explicitly representing. */
11489 31651 : if (operand_equal_p (TYPE_SIZE (TREE_TYPE (first_def)), TYPE_SIZE (vectype))
11490 31651 : && !types_compatible_p (TREE_TYPE (first_def), vectype))
11491 : {
11492 20 : gassign *conv_stmt
11493 20 : = gimple_build_assign (make_ssa_name (vectype),
11494 : build1 (VIEW_CONVERT_EXPR, vectype, first_def));
11495 20 : vect_finish_stmt_generation (vinfo, NULL, conv_stmt, gsi);
11496 20 : first_def = gimple_assign_lhs (conv_stmt);
11497 : }
11498 31651 : gassign *perm_stmt;
11499 31651 : if (mask_vec)
11500 : {
11501 28129 : if (operand_equal_p (TYPE_SIZE (TREE_TYPE (first_def)),
11502 28129 : TYPE_SIZE (vectype))
11503 28129 : && !types_compatible_p (TREE_TYPE (second_def), vectype))
11504 : {
11505 8 : gassign *conv_stmt
11506 8 : = gimple_build_assign (make_ssa_name (vectype),
11507 : build1 (VIEW_CONVERT_EXPR,
11508 : vectype, second_def));
11509 8 : vect_finish_stmt_generation (vinfo, NULL, conv_stmt, gsi);
11510 8 : second_def = gimple_assign_lhs (conv_stmt);
11511 : }
11512 28129 : tree perm_dest = make_ssa_name (vectype);
11513 28129 : perm_stmt = gimple_build_assign (perm_dest, VEC_PERM_EXPR,
11514 : first_def, second_def,
11515 : mask_vec);
11516 : }
11517 : else
11518 : {
11519 3522 : auto def_nunits = TYPE_VECTOR_SUBPARTS (TREE_TYPE (first_def));
11520 3522 : unsigned HOST_WIDE_INT vecno;
11521 3522 : poly_uint64 eltno;
11522 3522 : if (!can_div_trunc_p (poly_uint64 (identity_offset), def_nunits,
11523 : &vecno, &eltno))
11524 : gcc_unreachable ();
11525 3522 : tree def = vecno & 1 ? second_def : first_def;
11526 3522 : if (!types_compatible_p (TREE_TYPE (def), vectype))
11527 : {
11528 : /* For identity permutes we still need to handle the case
11529 : of offsetted extracts or concats. */
11530 397 : tree perm_dest = make_ssa_name (vectype);
11531 397 : unsigned HOST_WIDE_INT c;
11532 397 : if (known_le (TYPE_VECTOR_SUBPARTS (vectype), def_nunits))
11533 : {
11534 393 : unsigned HOST_WIDE_INT elsz
11535 393 : = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (def))));
11536 786 : tree lowpart = build3 (BIT_FIELD_REF, vectype, def,
11537 393 : TYPE_SIZE (vectype),
11538 393 : bitsize_int (eltno * elsz));
11539 393 : perm_stmt = gimple_build_assign (perm_dest, lowpart);
11540 : }
11541 4 : else if (constant_multiple_p (TYPE_VECTOR_SUBPARTS (vectype),
11542 4 : def_nunits, &c) && c == 2)
11543 : {
11544 4 : gcc_assert (known_eq (identity_offset, 0U));
11545 4 : tree ctor = build_constructor_va (vectype, 2,
11546 : NULL_TREE, first_def,
11547 : NULL_TREE, second_def);
11548 4 : perm_stmt = gimple_build_assign (perm_dest, ctor);
11549 : }
11550 : else
11551 0 : gcc_unreachable ();
11552 : }
11553 : else
11554 : {
11555 3125 : gcc_assert (known_eq (eltno, 0U));
11556 3125 : node->push_vec_def (def);
11557 3125 : return;
11558 : }
11559 : }
11560 28526 : vect_finish_stmt_generation (vinfo, NULL, perm_stmt, gsi);
11561 : /* Store the vector statement in NODE. */
11562 28526 : node->push_vec_def (perm_stmt);
11563 : }
11564 :
11565 : /* Subroutine of vectorizable_slp_permutation. Check whether the target
11566 : can perform permutation PERM on the (1 or 2) input nodes in CHILDREN.
11567 : If GSI is nonnull, emit the permutation there.
11568 :
11569 : When GSI is null, the only purpose of NODE is to give properties
11570 : of the result, such as the vector type and number of SLP lanes.
11571 : The node does not need to be a VEC_PERM_EXPR.
11572 :
11573 : If the target supports the operation, return the number of individual
11574 : VEC_PERM_EXPRs needed, otherwise return -1. Print information to the
11575 : dump file if DUMP_P is true. */
11576 :
11577 : static int
11578 449560 : vectorizable_slp_permutation_1 (vec_info *vinfo, gimple_stmt_iterator *gsi,
11579 : slp_tree node, lane_permutation_t &perm,
11580 : vec<slp_tree> &children, bool dump_p)
11581 : {
11582 449560 : tree vectype = SLP_TREE_VECTYPE (node);
11583 :
11584 : /* ??? We currently only support all same vector input types
11585 : while the SLP IL should really do a concat + select and thus accept
11586 : arbitrary mismatches. */
11587 449560 : slp_tree child;
11588 449560 : unsigned i;
11589 449560 : poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
11590 449560 : bool repeating_p = multiple_p (nunits, SLP_TREE_LANES (node));
11591 : /* True if we're permuting a single input of 2N vectors down
11592 : to N vectors. This case doesn't generalize beyond 2 since
11593 : VEC_PERM_EXPR only takes 2 inputs. */
11594 449560 : bool pack_p = false;
11595 : /* If we're permuting inputs of N vectors each into X*N outputs,
11596 : this is the value of X, otherwise it is 1. */
11597 449560 : unsigned int unpack_factor = 1;
11598 449560 : tree op_vectype = NULL_TREE;
11599 451138 : FOR_EACH_VEC_ELT (children, i, child)
11600 451045 : if (SLP_TREE_VECTYPE (child))
11601 : {
11602 : op_vectype = SLP_TREE_VECTYPE (child);
11603 : break;
11604 : }
11605 449560 : if (!op_vectype)
11606 93 : op_vectype = vectype;
11607 944458 : FOR_EACH_VEC_ELT (children, i, child)
11608 : {
11609 494898 : if ((SLP_TREE_DEF_TYPE (child) != vect_internal_def
11610 19120 : && !vect_maybe_update_slp_op_vectype (child, op_vectype))
11611 494898 : || !types_compatible_p (SLP_TREE_VECTYPE (child), op_vectype)
11612 989796 : || !types_compatible_p (TREE_TYPE (vectype), TREE_TYPE (op_vectype)))
11613 : {
11614 0 : if (dump_p)
11615 0 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
11616 : "Unsupported vector types in lane permutation\n");
11617 449560 : return -1;
11618 : }
11619 494898 : auto op_nunits = TYPE_VECTOR_SUBPARTS (op_vectype);
11620 494898 : unsigned int this_unpack_factor;
11621 : /* Detect permutations of external, pre-existing vectors. The external
11622 : node's SLP_TREE_LANES stores the total number of units in the vector,
11623 : or zero if the vector has variable length.
11624 :
11625 : We are expected to keep the original VEC_PERM_EXPR for such cases.
11626 : There is no repetition to model. */
11627 494898 : if (SLP_TREE_DEF_TYPE (child) == vect_external_def
11628 494898 : && SLP_TREE_SCALAR_OPS (child).is_empty ())
11629 : repeating_p = false;
11630 : /* Check whether the input has twice as many lanes per vector. */
11631 478396 : else if (children.length () == 1
11632 478396 : && known_eq (SLP_TREE_LANES (child) * nunits,
11633 : SLP_TREE_LANES (node) * op_nunits * 2))
11634 : pack_p = true;
11635 : /* Check whether the output has N times as many lanes per vector. */
11636 494898 : else if (constant_multiple_p (SLP_TREE_LANES (node) * op_nunits,
11637 434332 : SLP_TREE_LANES (child) * nunits,
11638 : &this_unpack_factor)
11639 399457 : && (i == 0 || unpack_factor == this_unpack_factor))
11640 : unpack_factor = this_unpack_factor;
11641 : else
11642 : repeating_p = false;
11643 : }
11644 :
11645 899120 : gcc_assert (perm.length () == SLP_TREE_LANES (node));
11646 :
11647 : /* Load-lanes permute. This permute only acts as a forwarder to
11648 : select the correct vector def of the load-lanes load which
11649 : has the permuted vectors in its vector defs like
11650 : { v0, w0, r0, v1, w1, r1 ... } for a ld3. All costs are
11651 : accounted for in the costing for the actual load so we
11652 : return zero here. */
11653 449560 : if (node->ldst_lanes)
11654 : {
11655 0 : gcc_assert (children.length () == 1);
11656 0 : if (!gsi)
11657 : /* This is a trivial op always supported. */
11658 : return 0;
11659 0 : slp_tree child = children[0];
11660 0 : unsigned vec_idx = (SLP_TREE_LANE_PERMUTATION (node)[0].second
11661 0 : / SLP_TREE_LANES (node));
11662 0 : unsigned vec_num = SLP_TREE_LANES (child) / SLP_TREE_LANES (node);
11663 0 : unsigned nvectors = vect_get_num_copies (vinfo, node);
11664 0 : for (unsigned i = 0; i < nvectors; ++i)
11665 : {
11666 0 : tree def = SLP_TREE_VEC_DEFS (child)[i * vec_num + vec_idx];
11667 0 : node->push_vec_def (def);
11668 : }
11669 : return 0;
11670 : }
11671 :
11672 : /* Set REPEATING_P to true if the permutations are cyclical wrt UNPACK_FACTOR
11673 : and if we can generate the vectors in a vector-length agnostic way.
11674 : This requires UNPACK_STEP == NUNITS / UNPACK_FACTOR to be known at
11675 : compile time.
11676 :
11677 : The significance of UNPACK_STEP is that, when PACK_P is false,
11678 : output vector I operates on a window of UNPACK_STEP elements from each
11679 : input, starting at lane UNPACK_STEP * (I % UNPACK_FACTOR). For example,
11680 : when UNPACK_FACTOR is 2, the first output vector operates on lanes
11681 : [0, NUNITS / 2 - 1] of each input vector and the second output vector
11682 : operates on lanes [NUNITS / 2, NUNITS - 1] of each input vector.
11683 :
11684 : When REPEATING_P is true, NOUTPUTS holds the total number of outputs
11685 : that we actually need to generate. */
11686 449560 : uint64_t noutputs = 0;
11687 449560 : poly_uint64 unpack_step = 0;
11688 449560 : loop_vec_info linfo = dyn_cast <loop_vec_info> (vinfo);
11689 182839 : if (!linfo
11690 488542 : || !multiple_p (nunits, unpack_factor, &unpack_step)
11691 181896 : || !constant_multiple_p (LOOP_VINFO_VECT_FACTOR (linfo)
11692 181896 : * SLP_TREE_LANES (node), nunits, &noutputs))
11693 : repeating_p = false;
11694 :
11695 : /* We can handle the conditions described for REPEATING_P above for
11696 : both variable- and constant-length vectors. The fallback requires
11697 : us to generate every element of every permute vector explicitly,
11698 : which is only possible for constant-length permute vectors.
11699 :
11700 : Set:
11701 :
11702 : - NPATTERNS and NELTS_PER_PATTERN to the encoding of the permute
11703 : mask vectors that we want to build.
11704 :
11705 : - NCOPIES to the number of copies of PERM that we need in order
11706 : to build the necessary permute mask vectors. */
11707 181896 : uint64_t npatterns;
11708 181896 : unsigned nelts_per_pattern;
11709 181896 : uint64_t ncopies;
11710 181896 : if (repeating_p)
11711 : {
11712 : /* We need permute mask vectors that have the form:
11713 :
11714 : { X1, ..., Xn, X1 + n, ..., Xn + n, X1 + 2n, ..., Xn + 2n, ... }
11715 :
11716 : In other words, the original n-element permute in PERM is
11717 : "unrolled" to fill a full vector. The stepped vector encoding
11718 : that we use for permutes requires 3n elements. */
11719 142914 : npatterns = SLP_TREE_LANES (node);
11720 142914 : nelts_per_pattern = ncopies = 3;
11721 : }
11722 : else
11723 : {
11724 : /* Calculate every element of every permute mask vector explicitly,
11725 : instead of relying on the pattern described above. */
11726 306646 : if (!nunits.is_constant (&npatterns)
11727 306646 : || !TYPE_VECTOR_SUBPARTS (op_vectype).is_constant ())
11728 : {
11729 : if (dump_p)
11730 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
11731 : "unsupported permutation %p on variable-length"
11732 : " vectors\n", (void *) node);
11733 : return -1;
11734 : }
11735 306646 : nelts_per_pattern = ncopies = 1;
11736 306646 : if (linfo && !LOOP_VINFO_VECT_FACTOR (linfo).is_constant (&ncopies))
11737 : {
11738 : if (dump_p)
11739 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
11740 : "unsupported permutation %p for variable VF\n",
11741 : (void *) node);
11742 : return -1;
11743 : }
11744 : pack_p = false;
11745 : unpack_factor = 1;
11746 : }
11747 449560 : unsigned olanes = unpack_factor * ncopies * SLP_TREE_LANES (node);
11748 449560 : gcc_assert (repeating_p || multiple_p (olanes, nunits));
11749 :
11750 : /* Compute the { { SLP operand, vector index}, lane } permutation sequence
11751 : from the { SLP operand, scalar lane } permutation as recorded in the
11752 : SLP node as intermediate step. This part should already work
11753 : with SLP children with arbitrary number of lanes. */
11754 449560 : auto_vec<std::pair<std::pair<unsigned, unsigned>, poly_uint64>> vperm;
11755 449560 : auto_vec<poly_uint64> active_lane;
11756 449560 : vperm.create (olanes);
11757 449560 : active_lane.safe_grow_cleared (children.length (), true);
11758 1356968 : for (unsigned int ui = 0; ui < unpack_factor; ++ui)
11759 : {
11760 1938596 : for (unsigned j = 0; j < children.length (); ++j)
11761 511450 : active_lane[j] = ui * unpack_step;
11762 1315902 : for (unsigned i = 0; i < ncopies; ++i)
11763 : {
11764 5411944 : for (unsigned pi = 0; pi < perm.length (); ++pi)
11765 : {
11766 1847918 : std::pair<unsigned, unsigned> p = perm[pi];
11767 1847918 : tree vtype = SLP_TREE_VECTYPE (children[p.first]);
11768 1847918 : if (repeating_p)
11769 834096 : vperm.quick_push ({{p.first, 0},
11770 834096 : p.second + active_lane[p.first]});
11771 : else
11772 : {
11773 : /* We checked above that the vectors are constant-length. */
11774 1013822 : unsigned vnunits = TYPE_VECTOR_SUBPARTS (vtype)
11775 1013822 : .to_constant ();
11776 1013822 : unsigned lane = active_lane[p.first].to_constant ();
11777 1013822 : unsigned vi = (lane + p.second) / vnunits;
11778 1013822 : unsigned vl = (lane + p.second) % vnunits;
11779 1013822 : vperm.quick_push ({{p.first, vi}, vl});
11780 : }
11781 : }
11782 : /* Advance to the next group. */
11783 1834161 : for (unsigned j = 0; j < children.length (); ++j)
11784 976107 : active_lane[j] += SLP_TREE_LANES (children[j]);
11785 : }
11786 : }
11787 :
11788 449560 : if (dump_p)
11789 : {
11790 9003 : dump_printf_loc (MSG_NOTE, vect_location,
11791 : "vectorizing permutation %p", (void *)node);
11792 32594 : for (unsigned i = 0; i < perm.length (); ++i)
11793 23591 : dump_printf (MSG_NOTE, " op%u[%u]", perm[i].first, perm[i].second);
11794 9003 : if (repeating_p)
11795 7566 : dump_printf (MSG_NOTE, " (repeat %d)", SLP_TREE_LANES (node));
11796 9003 : dump_printf (MSG_NOTE, "\n");
11797 9003 : dump_printf_loc (MSG_NOTE, vect_location, "as");
11798 90582 : for (unsigned i = 0; i < vperm.length (); ++i)
11799 : {
11800 81579 : if (i != 0
11801 81579 : && (repeating_p
11802 55311 : ? multiple_p (i, npatterns)
11803 81579 : : multiple_p (i, TYPE_VECTOR_SUBPARTS (vectype))))
11804 24361 : dump_printf (MSG_NOTE, ",");
11805 81579 : dump_printf (MSG_NOTE, " vops%u[%u][",
11806 81579 : vperm[i].first.first, vperm[i].first.second);
11807 81579 : dump_dec (MSG_NOTE, vperm[i].second);
11808 81579 : dump_printf (MSG_NOTE, "]");
11809 : }
11810 9003 : dump_printf (MSG_NOTE, "\n");
11811 : }
11812 :
11813 : /* We can only handle two-vector permutes, everything else should
11814 : be lowered on the SLP level. The following is closely inspired
11815 : by vect_transform_slp_perm_load and is supposed to eventually
11816 : replace it.
11817 : ??? As intermediate step do code-gen in the SLP tree representation
11818 : somehow? */
11819 449560 : std::pair<unsigned, unsigned> first_vec = std::make_pair (-1U, -1U);
11820 449560 : std::pair<unsigned, unsigned> second_vec = std::make_pair (-1U, -1U);
11821 449560 : unsigned int index = 0;
11822 449560 : poly_uint64 mask_element;
11823 449560 : vec_perm_builder mask;
11824 449560 : mask.new_vector (nunits, npatterns, nelts_per_pattern);
11825 449560 : unsigned int count = mask.encoded_nelts ();
11826 449560 : mask.quick_grow (count);
11827 449560 : vec_perm_indices indices;
11828 449560 : unsigned nperms = 0;
11829 : /* When REPEATING_P is true, we only have UNPACK_FACTOR unique permute
11830 : vectors to check during analysis, but we need to generate NOUTPUTS
11831 : vectors during transformation. */
11832 449560 : unsigned total_nelts = olanes;
11833 449560 : unsigned process_nelts = olanes;
11834 449560 : if (repeating_p)
11835 : {
11836 142914 : total_nelts = (total_nelts / unpack_factor) * noutputs;
11837 142914 : if (gsi)
11838 9799 : process_nelts = total_nelts;
11839 : }
11840 449560 : unsigned last_ei = (total_nelts - 1) % process_nelts;
11841 2299940 : for (unsigned i = 0; i < process_nelts; ++i)
11842 : {
11843 : /* VI is the input vector index when generating code for REPEATING_P. */
11844 1861089 : unsigned vi = i / olanes * (pack_p ? 2 : 1);
11845 1861089 : unsigned ei = i % olanes;
11846 1861089 : mask_element = vperm[ei].second;
11847 1861089 : if (pack_p)
11848 : {
11849 : /* In this case, we have N outputs and the single child provides 2N
11850 : inputs. Output X permutes inputs 2X and 2X+1.
11851 :
11852 : The mask indices are taken directly from the SLP permutation node.
11853 : Index X selects from the first vector if (X / NUNITS) % 2 == 0;
11854 : X selects from the second vector otherwise. These conditions
11855 : are only known at compile time for constant-length vectors. */
11856 : first_vec = std::make_pair (0, 0);
11857 : second_vec = std::make_pair (0, 1);
11858 : }
11859 1691934 : else if (first_vec.first == -1U
11860 1691934 : || first_vec == vperm[ei].first)
11861 1496113 : first_vec = vperm[ei].first;
11862 195821 : else if (second_vec.first == -1U
11863 195821 : || second_vec == vperm[ei].first)
11864 : {
11865 195417 : second_vec = vperm[ei].first;
11866 195417 : mask_element += nunits;
11867 : }
11868 : else
11869 : {
11870 404 : if (dump_p)
11871 7 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
11872 : "permutation requires at "
11873 : "least three vectors\n");
11874 404 : gcc_assert (!gsi);
11875 : return -1;
11876 : }
11877 :
11878 1860685 : mask[index++] = mask_element;
11879 :
11880 1860685 : if (index == count)
11881 : {
11882 593193 : indices.new_vector (mask, second_vec.first == -1U ? 1 : 2,
11883 : TYPE_VECTOR_SUBPARTS (op_vectype));
11884 593193 : bool identity_p = (indices.series_p (0, 1, mask[0], 1)
11885 923896 : && constant_multiple_p (mask[0], nunits));
11886 593193 : machine_mode vmode = TYPE_MODE (vectype);
11887 593193 : machine_mode op_vmode = TYPE_MODE (op_vectype);
11888 593193 : unsigned HOST_WIDE_INT c;
11889 593193 : if ((!identity_p
11890 544747 : && !can_vec_perm_const_p (vmode, op_vmode, indices))
11891 593193 : || (identity_p
11892 48446 : && !known_le (nunits,
11893 : TYPE_VECTOR_SUBPARTS (op_vectype))
11894 8 : && (!constant_multiple_p (nunits,
11895 10313 : TYPE_VECTOR_SUBPARTS (op_vectype),
11896 8 : &c) || c != 2)))
11897 : {
11898 10305 : if (dump_p)
11899 : {
11900 154 : dump_printf_loc (MSG_MISSED_OPTIMIZATION,
11901 : vect_location,
11902 : "unsupported vect permute { ");
11903 1596 : for (i = 0; i < count; ++i)
11904 : {
11905 1442 : dump_dec (MSG_MISSED_OPTIMIZATION, mask[i]);
11906 1442 : dump_printf (MSG_MISSED_OPTIMIZATION, " ");
11907 : }
11908 154 : dump_printf (MSG_MISSED_OPTIMIZATION, "}\n");
11909 : }
11910 10305 : gcc_assert (!gsi);
11911 449560 : return -1;
11912 : }
11913 :
11914 582888 : if (!identity_p)
11915 534442 : nperms += CEIL (total_nelts, process_nelts) - (ei > last_ei);
11916 582888 : if (gsi)
11917 : {
11918 31651 : if (second_vec.first == -1U)
11919 7391 : second_vec = first_vec;
11920 :
11921 31651 : slp_tree
11922 31651 : first_node = children[first_vec.first],
11923 31651 : second_node = children[second_vec.first];
11924 :
11925 31651 : tree mask_vec = NULL_TREE;
11926 31651 : if (!identity_p)
11927 28129 : mask_vec = vect_gen_perm_mask_checked (vectype, indices);
11928 :
11929 31651 : tree first_def
11930 31651 : = vect_get_slp_vect_def (first_node, first_vec.second + vi);
11931 31651 : tree second_def
11932 31651 : = vect_get_slp_vect_def (second_node, second_vec.second + vi);
11933 31651 : vect_add_slp_permutation (vinfo, gsi, node, first_def,
11934 31651 : second_def, mask_vec, mask[0]);
11935 : }
11936 :
11937 : index = 0;
11938 : first_vec = std::make_pair (-1U, -1U);
11939 : second_vec = std::make_pair (-1U, -1U);
11940 : }
11941 : }
11942 :
11943 438851 : return nperms;
11944 449560 : }
11945 :
11946 : /* Vectorize the SLP permutations in NODE as specified
11947 : in SLP_TREE_LANE_PERMUTATION which is a vector of pairs of SLP
11948 : child number and lane number.
11949 : Interleaving of two two-lane two-child SLP subtrees (not supported):
11950 : [ { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } ]
11951 : A blend of two four-lane two-child SLP subtrees:
11952 : [ { 0, 0 }, { 1, 1 }, { 0, 2 }, { 1, 3 } ]
11953 : Highpart of a four-lane one-child SLP subtree (not supported):
11954 : [ { 0, 2 }, { 0, 3 } ]
11955 : Where currently only a subset is supported by code generating below. */
11956 :
11957 : bool
11958 99688 : vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi,
11959 : slp_tree node, stmt_vector_for_cost *cost_vec)
11960 : {
11961 99688 : tree vectype = SLP_TREE_VECTYPE (node);
11962 99688 : lane_permutation_t &perm = SLP_TREE_LANE_PERMUTATION (node);
11963 99688 : int nperms = vectorizable_slp_permutation_1 (vinfo, gsi, node, perm,
11964 99688 : SLP_TREE_CHILDREN (node),
11965 : dump_enabled_p ());
11966 99688 : if (nperms < 0)
11967 : return false;
11968 :
11969 98059 : if (!gsi && nperms != 0)
11970 74424 : record_stmt_cost (cost_vec, nperms, vec_perm, node, vectype, 0, vect_body);
11971 :
11972 : return true;
11973 : }
11974 :
11975 : /* Vectorize SLP NODE. Only compute the vector insertion places when
11976 : PLACE_ONLY is true. When placing, return false if there is no possible
11977 : schedule. */
11978 :
11979 : static bool
11980 3142029 : vect_schedule_slp_node (vec_info *vinfo,
11981 : slp_tree node, slp_instance instance, bool place_only)
11982 : {
11983 3142029 : int i;
11984 3142029 : slp_tree child;
11985 :
11986 : /* Vectorize externals and constants. */
11987 3142029 : if (SLP_TREE_DEF_TYPE (node) == vect_constant_def
11988 3142029 : || SLP_TREE_DEF_TYPE (node) == vect_external_def)
11989 : {
11990 1209796 : if (place_only)
11991 : {
11992 700218 : if (SLP_TREE_DEF_TYPE (node) == vect_constant_def)
11993 : return true;
11994 319773 : gimple *last_stmt = NULL;
11995 319773 : vec<tree> &defs = (!SLP_TREE_SCALAR_OPS (node).is_empty ()
11996 : ? SLP_TREE_SCALAR_OPS (node)
11997 319773 : : SLP_TREE_VEC_DEFS (node));
11998 1712044 : for (tree def : defs)
11999 : /* If the stmt is not inside the region do not
12000 : use it as possible insertion point. */
12001 752725 : if (auto stmt_info = vinfo->lookup_def (def))
12002 : {
12003 390885 : gimple *stmt = stmt_info->stmt;
12004 390885 : if (!last_stmt)
12005 : last_stmt = stmt;
12006 220342 : else if (vect_stmt_dominates_stmt_p (last_stmt, stmt))
12007 : last_stmt = stmt;
12008 67523 : else if (vect_stmt_dominates_stmt_p (stmt, last_stmt))
12009 : ;
12010 : else
12011 0 : gcc_unreachable ();
12012 : }
12013 319773 : node->si = last_stmt;
12014 319773 : return true;
12015 : }
12016 :
12017 : /* ??? vectorizable_shift can end up using a scalar operand which is
12018 : currently denoted as !SLP_TREE_VECTYPE. No need to vectorize the
12019 : node in this case. */
12020 509578 : if (!SLP_TREE_VECTYPE (node))
12021 : return true;
12022 :
12023 : /* There are two reasons vector defs might already exist. The first
12024 : is that we are vectorizing an existing vector def. The second is
12025 : when performing BB vectorization shared constant/external nodes
12026 : are not split apart during partitioning so during the code-gen
12027 : DFS walk we can end up visiting them twice. */
12028 502344 : if (! SLP_TREE_VEC_DEFS (node).exists ())
12029 501404 : vect_create_constant_vectors (vinfo, node);
12030 : return true;
12031 : }
12032 :
12033 1932233 : stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
12034 :
12035 1932233 : gcc_assert (SLP_TREE_VEC_DEFS (node).is_empty ());
12036 1932233 : if (!place_only && SLP_TREE_VECTYPE (node))
12037 992277 : SLP_TREE_VEC_DEFS (node).create (vect_get_num_copies (vinfo, node));
12038 :
12039 1932233 : gimple *last_stmt;
12040 1932233 : gimple_stmt_iterator si;
12041 : /* ??? When !place_only we'd like to re-use place_only computed info,
12042 : but this is a bit awkward due to using gsi_insert_before and the
12043 : requirement to insert after vector defs. So we compute last_stmt
12044 : during pre-scheduling and si during scheduling. */
12045 1932233 : if (!SLP_TREE_PERMUTE_P (node) && STMT_VINFO_DATA_REF (stmt_info))
12046 : {
12047 : /* Vectorized loads go before the first scalar load to make it
12048 : ready early, vectorized stores go before the last scalar
12049 : stmt which is where all uses are ready.
12050 : In theory, if we delay dependence checking until after
12051 : placing, we can schedule at other points, but then
12052 : dependence checking would need to honor that. On the
12053 : other hand dependence checking could request a different
12054 : scheduling point as well, if dependences require that. */
12055 1504081 : stmt_vec_info last_stmt_info = NULL;
12056 1504081 : if (DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)))
12057 282096 : last_stmt_info = vect_find_first_scalar_stmt_in_slp (node);
12058 : else /* DR_IS_WRITE */
12059 : {
12060 1221985 : last_stmt_info = vect_find_last_scalar_stmt_in_slp (node);
12061 1221985 : if (place_only)
12062 1331976 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
12063 : {
12064 665989 : if (child->si
12065 665989 : && !vect_stmt_dominates_stmt_p (child->si,
12066 : last_stmt_info->stmt))
12067 : return false;
12068 : }
12069 : }
12070 1504079 : last_stmt = last_stmt_info->stmt;
12071 1504079 : si = gsi_for_stmt (last_stmt);
12072 1504079 : }
12073 428152 : else if (!SLP_TREE_PERMUTE_P (node)
12074 406606 : && (SLP_TREE_TYPE (node) == cycle_phi_info_type
12075 : || SLP_TREE_TYPE (node) == induc_vec_info_type
12076 : || SLP_TREE_TYPE (node) == phi_info_type))
12077 : {
12078 : /* For PHI node vectorization we do not use the insertion iterator. */
12079 108163 : last_stmt = SLP_TREE_SCALAR_STMTS (node)[0]->stmt;
12080 108163 : if (place_only)
12081 182197 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
12082 : {
12083 128900 : if (child->si
12084 224726 : && !dominated_by_p (CDI_DOMINATORS,
12085 : gimple_phi_arg_edge
12086 95826 : (as_a <gphi *> (last_stmt), i)->src,
12087 95826 : gimple_bb (child->si)))
12088 : return false;
12089 : }
12090 108161 : si = gsi_none ();
12091 : }
12092 : else
12093 : {
12094 : /* Emit other stmts after the children vectorized defs which is
12095 : earliest possible. */
12096 : last_stmt = NULL;
12097 885955 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
12098 565966 : if (place_only)
12099 : {
12100 189369 : gimple *vstmt = child->si;
12101 189369 : if (!vstmt)
12102 : {
12103 : /* vect_constant_def and defs at region boundary do not
12104 : constrain placement. */
12105 : gcc_assert (SLP_TREE_DEF_TYPE (child) == vect_constant_def
12106 : /* ??? Region boundary is not representated
12107 : by a NULL stmt. */
12108 : || true);
12109 : }
12110 148215 : else if (!last_stmt)
12111 : last_stmt = vstmt;
12112 42996 : else if (vect_stmt_dominates_stmt_p (last_stmt, vstmt))
12113 : last_stmt = vstmt;
12114 10950 : else if (vect_stmt_dominates_stmt_p (vstmt, last_stmt))
12115 : ;
12116 : else
12117 : /* Non-trapping stmts from different BBs might be combined,
12118 : and if we later CSE a low/high part we can run into this. */
12119 : return false;
12120 : }
12121 376597 : else if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
12122 : {
12123 : /* For fold-left reductions we are retaining the scalar
12124 : reduction PHI but we still have SLP_TREE_NUM_VEC_STMTS
12125 : set so the representation isn't perfect. Resort to the
12126 : last scalar def here. */
12127 300654 : if (SLP_TREE_VEC_DEFS (child).is_empty ())
12128 : {
12129 942 : gcc_assert (SLP_TREE_TYPE (child) == cycle_phi_info_type);
12130 942 : gphi *phi = as_a <gphi *>
12131 942 : (vect_find_last_scalar_stmt_in_slp (child)->stmt);
12132 942 : if (!last_stmt)
12133 : last_stmt = phi;
12134 722 : else if (vect_stmt_dominates_stmt_p (last_stmt, phi))
12135 : last_stmt = phi;
12136 711 : else if (vect_stmt_dominates_stmt_p (phi, last_stmt))
12137 : ;
12138 : else
12139 0 : gcc_unreachable ();
12140 : }
12141 : /* We are emitting all vectorized stmts in the same place and
12142 : the last one is the last.
12143 : ??? Unless we have a load permutation applied and that
12144 : figures to re-use an earlier generated load. */
12145 300654 : unsigned j;
12146 300654 : tree vdef;
12147 709663 : FOR_EACH_VEC_ELT (SLP_TREE_VEC_DEFS (child), j, vdef)
12148 409009 : if (TREE_CODE (vdef) == SSA_NAME
12149 409009 : && !SSA_NAME_IS_DEFAULT_DEF (vdef))
12150 : {
12151 408957 : gimple *vstmt = SSA_NAME_DEF_STMT (vdef);
12152 408957 : if (!last_stmt)
12153 : last_stmt = vstmt;
12154 209127 : else if (vect_stmt_dominates_stmt_p (last_stmt, vstmt))
12155 : last_stmt = vstmt;
12156 46719 : else if (vect_stmt_dominates_stmt_p (vstmt, last_stmt))
12157 : ;
12158 : else
12159 0 : gcc_unreachable ();
12160 : }
12161 : }
12162 75943 : else if (!SLP_TREE_VECTYPE (child))
12163 : {
12164 : /* For externals we use unvectorized at all scalar defs. */
12165 : unsigned j;
12166 : tree def;
12167 15857 : FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_OPS (child), j, def)
12168 : /* If the stmt is not inside the region do not
12169 : use it as possible insertion point. */
12170 9251 : if (auto stmt_info = vinfo->lookup_def (def))
12171 : {
12172 250 : gimple *stmt = stmt_info->stmt;
12173 250 : if (!last_stmt)
12174 : last_stmt = stmt;
12175 230 : else if (vect_stmt_dominates_stmt_p (last_stmt, stmt))
12176 : last_stmt = stmt;
12177 26 : else if (vect_stmt_dominates_stmt_p (stmt, last_stmt))
12178 : ;
12179 : else
12180 0 : gcc_unreachable ();
12181 : }
12182 : }
12183 : else
12184 : {
12185 : /* For externals we have to look at all defs since their
12186 : insertion place is decided per vector. But beware
12187 : of pre-existing vectors where we need to make sure
12188 : we do not insert before the region boundary. */
12189 138543 : if (SLP_TREE_SCALAR_OPS (child).is_empty ()
12190 708 : && !vinfo->lookup_def (SLP_TREE_VEC_DEFS (child)[0]))
12191 : ;
12192 : else
12193 : {
12194 : unsigned j;
12195 : tree vdef;
12196 732534 : FOR_EACH_VEC_ELT (SLP_TREE_VEC_DEFS (child), j, vdef)
12197 97362 : if (TREE_CODE (vdef) == SSA_NAME
12198 97362 : && !SSA_NAME_IS_DEFAULT_DEF (vdef))
12199 : {
12200 21452 : gimple *vstmt = SSA_NAME_DEF_STMT (vdef);
12201 21452 : if (!last_stmt)
12202 : last_stmt = vstmt;
12203 11652 : else if (vect_stmt_dominates_stmt_p (last_stmt, vstmt))
12204 : last_stmt = vstmt;
12205 9089 : else if (vect_stmt_dominates_stmt_p (vstmt, last_stmt))
12206 : ;
12207 : else
12208 0 : gcc_unreachable ();
12209 : }
12210 : }
12211 : }
12212 :
12213 : /* We split regions to vectorize at control altering stmts
12214 : with a definition so this can only be an external. */
12215 319989 : gcc_checking_assert (!last_stmt
12216 : || !is_ctrl_altering_stmt (last_stmt));
12217 :
12218 319989 : if (is_a <bb_vec_info> (vinfo)
12219 129748 : && !SLP_TREE_PERMUTE_P (node)
12220 123171 : && (!last_stmt
12221 120155 : || gimple_bb (last_stmt) != gimple_bb (stmt_info->stmt))
12222 353887 : && gimple_could_trap_p (stmt_info->stmt))
12223 : {
12224 : /* We've constrained possibly trapping operations to all come
12225 : from the same basic-block, if vectorized defs would allow earlier
12226 : scheduling still force vectorized stmts to the original block.
12227 : This is only necessary for BB vectorization since for loop vect
12228 : all operations are in a single BB and scalar stmt based
12229 : placement doesn't play well with epilogue vectorization. */
12230 659 : gcc_assert (!last_stmt
12231 : || dominated_by_p (CDI_DOMINATORS,
12232 : gimple_bb (stmt_info->stmt),
12233 : gimple_bb (last_stmt)));
12234 659 : si = gsi_after_labels (gimple_bb (stmt_info->stmt));
12235 659 : last_stmt = gsi_stmt (si);
12236 : }
12237 : /* When there is no in-region child def to guide placement, insert
12238 : at region boundary. */
12239 319330 : else if (!last_stmt)
12240 : {
12241 4806 : si = gsi_after_labels (vinfo->bbs[0]);
12242 : /* last_stmt NULL marks the region start. */
12243 : }
12244 314524 : else if (is_a <gphi *> (last_stmt))
12245 31189 : si = gsi_after_labels (gimple_bb (last_stmt));
12246 : else
12247 : {
12248 283335 : si = gsi_for_stmt (last_stmt);
12249 : /* We use gsi_insert_before, so when last_stmt is a vector
12250 : def we have to advance (or use gsi_insert_after). */
12251 283335 : gsi_next (&si);
12252 :
12253 283335 : if (auto loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
12254 : {
12255 : /* We'll have to fix this up for loop vect. */
12256 174336 : gcc_assert (!place_only);
12257 : /* Avoid scheduling stmts to random places in the CFG, any
12258 : stmt dominance check we performed is possibly wrong as UIDs
12259 : are not initialized for all of the function for loop
12260 : vectorization. Instead append to the loop preheader. */
12261 174336 : if ((LOOP_VINFO_LOOP (loop_vinfo)->header
12262 174336 : != gimple_bb (last_stmt))
12263 177498 : && dominated_by_p (CDI_DOMINATORS,
12264 : LOOP_VINFO_LOOP (loop_vinfo)->header,
12265 3162 : gimple_bb (last_stmt)))
12266 1278 : si = gsi_end_bb (loop_preheader_edge
12267 639 : (LOOP_VINFO_LOOP (loop_vinfo))->src);
12268 : /* Avoid scheduling internal defs outside of the loop when
12269 : we might have only implicitly tracked loop mask/len defs. */
12270 76 : if (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
12271 174336 : || LOOP_VINFO_FULLY_WITH_LENGTH_P (loop_vinfo))
12272 : {
12273 76 : gimple_stmt_iterator si2
12274 76 : = gsi_after_labels (LOOP_VINFO_LOOP (loop_vinfo)->header);
12275 76 : if ((gsi_end_p (si2)
12276 0 : && (LOOP_VINFO_LOOP (loop_vinfo)->header
12277 0 : != gimple_bb (last_stmt))
12278 0 : && dominated_by_p (CDI_DOMINATORS,
12279 : LOOP_VINFO_LOOP (loop_vinfo)->header,
12280 0 : gimple_bb (last_stmt)))
12281 76 : || (!gsi_end_p (si2)
12282 76 : && last_stmt != *si2
12283 73 : && vect_stmt_dominates_stmt_p (last_stmt, *si2)))
12284 3 : si = si2;
12285 : }
12286 : }
12287 : }
12288 : }
12289 :
12290 1932229 : if (place_only)
12291 : {
12292 939946 : if (dump_enabled_p () && last_stmt)
12293 3713 : dump_printf_loc (MSG_NOTE, vect_location,
12294 : "placing node %p at %G:", (void *)node, last_stmt);
12295 : /* Verify we either get a stmt anchor or region start. */
12296 939946 : gcc_assert ((last_stmt && gimple_bb (last_stmt))
12297 : || (!last_stmt && gsi_bb (si)));
12298 939946 : node->si = last_stmt;
12299 939946 : return true;
12300 : }
12301 :
12302 : /* ??? Asserting vect_stmt_dominates_stmt_p (gsi_stmt (si), node->si)
12303 : does not work because in some cases we advance si from last_stmt (as
12304 : we want to insert after vector stmts) and because vector stmts of
12305 : children have been inserted possibly at the same location constraint,
12306 : moving si even further. */
12307 992283 : if (flag_checking && node->si && gimple_bb (node->si) && !gsi_end_p (si))
12308 : {
12309 626859 : auto gsi2 = si;
12310 626859 : while (1)
12311 : {
12312 626859 : if (vect_stmt_dominates_stmt_p (gsi_stmt (gsi2), node->si))
12313 : break;
12314 : /* As we have possibly advanced si it might now point to the
12315 : scalar stmt immediately following node->si. That's OK. */
12316 25168 : if (gsi_stmt (gsi2) != gsi_stmt (si)
12317 25168 : && gimple_uid (gsi_stmt (gsi2)) != 0)
12318 0 : gcc_unreachable ();
12319 25168 : gsi_prev (&gsi2);
12320 25168 : if (gsi_end_p (gsi2))
12321 : {
12322 540 : if (is_a <gphi *> (node->si)
12323 540 : && gimple_bb (node->si) == gsi_bb (si))
12324 : break;
12325 0 : gcc_unreachable ();
12326 : }
12327 : }
12328 : }
12329 :
12330 992283 : if (dump_enabled_p ())
12331 : {
12332 72022 : if (stmt_info)
12333 68611 : dump_printf_loc (MSG_NOTE, vect_location,
12334 : "------>vectorizing SLP node starting from: %G",
12335 : stmt_info->stmt);
12336 : else
12337 : {
12338 3411 : dump_printf_loc (MSG_NOTE, vect_location,
12339 : "------>vectorizing SLP node:\n");
12340 3411 : vect_print_slp_tree (MSG_NOTE, vect_location, node);
12341 : }
12342 : }
12343 992283 : vect_transform_stmt (vinfo, stmt_info, &si, node, instance);
12344 992283 : return true;
12345 : }
12346 :
12347 : /* Replace scalar calls from SLP node NODE with setting of their lhs to zero.
12348 : For loop vectorization this is done in vectorizable_call, but for SLP
12349 : it needs to be deferred until end of vect_schedule_slp, because multiple
12350 : SLP instances may refer to the same scalar stmt. */
12351 :
12352 : static void
12353 604450 : vect_remove_slp_scalar_calls (vec_info *vinfo,
12354 : slp_tree node, hash_set<slp_tree> &visited)
12355 : {
12356 604450 : gimple *new_stmt;
12357 604450 : gimple_stmt_iterator gsi;
12358 604450 : tree lhs;
12359 :
12360 604450 : if (!node || SLP_TREE_DEF_TYPE (node) != vect_internal_def)
12361 189138 : return;
12362 :
12363 458993 : if (visited.add (node))
12364 : return;
12365 :
12366 1547727 : for (auto child : SLP_TREE_CHILDREN (node))
12367 513979 : vect_remove_slp_scalar_calls (vinfo, child, visited);
12368 :
12369 1725755 : for (auto stmt_info : SLP_TREE_SCALAR_STMTS (node))
12370 : {
12371 488097 : if (!stmt_info)
12372 3962 : continue;
12373 484135 : stmt_info = vect_orig_stmt (stmt_info);
12374 484135 : gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt);
12375 5144 : if (!stmt || gimple_bb (stmt) == NULL)
12376 479033 : continue;
12377 5102 : lhs = gimple_call_lhs (stmt);
12378 5102 : if (lhs)
12379 4531 : new_stmt = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
12380 : else
12381 571 : new_stmt = gimple_build_nop ();
12382 5102 : unlink_stmt_vdef (stmt_info->stmt);
12383 5102 : gsi = gsi_for_stmt (stmt);
12384 5102 : vinfo->replace_stmt (&gsi, stmt_info, new_stmt);
12385 5102 : if (lhs)
12386 4531 : SSA_NAME_DEF_STMT (lhs) = new_stmt;
12387 : }
12388 : }
12389 :
12390 : static void
12391 90471 : vect_remove_slp_scalar_calls (vec_info *vinfo, slp_tree node)
12392 : {
12393 90471 : hash_set<slp_tree> visited;
12394 90471 : vect_remove_slp_scalar_calls (vinfo, node, visited);
12395 90471 : }
12396 :
12397 : /* Vectorize the instance root. */
12398 :
12399 : void
12400 13846 : vectorize_slp_instance_root_stmt (vec_info *vinfo, slp_tree node, slp_instance instance)
12401 : {
12402 13846 : if (instance->kind == slp_inst_kind_ctor)
12403 : {
12404 5637 : tree new_def;
12405 5637 : if (SLP_TREE_VEC_DEFS (node).length () == 1)
12406 : {
12407 5592 : new_def = SLP_TREE_VEC_DEFS (node)[0];
12408 5592 : tree root_lhs = gimple_get_lhs (instance->root_stmts[0]->stmt);
12409 5592 : if (!useless_type_conversion_p (TREE_TYPE (root_lhs),
12410 5592 : TREE_TYPE (new_def)))
12411 0 : new_def = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (root_lhs),
12412 : new_def);
12413 : }
12414 : else
12415 : {
12416 45 : gcc_assert (SLP_TREE_VEC_DEFS (node).length () > 1);
12417 45 : tree child_def;
12418 45 : int j;
12419 45 : vec<constructor_elt, va_gc> *v;
12420 45 : vec_alloc (v, SLP_TREE_VEC_DEFS (node).length ());
12421 :
12422 : /* A CTOR can handle V16HI composition from VNx8HI so we
12423 : do not need to convert vector elements if the types
12424 : do not match. */
12425 180 : FOR_EACH_VEC_ELT (SLP_TREE_VEC_DEFS (node), j, child_def)
12426 90 : CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, child_def);
12427 45 : tree rtype
12428 45 : = TREE_TYPE (gimple_assign_rhs1 (instance->root_stmts[0]->stmt));
12429 45 : new_def = build_constructor (rtype, v);
12430 : }
12431 :
12432 5637 : gimple_stmt_iterator rgsi = gsi_for_stmt (instance->root_stmts[0]->stmt);
12433 5637 : gimple_assign_set_rhs_from_tree (&rgsi, new_def);
12434 5637 : update_stmt (gsi_stmt (rgsi));
12435 5637 : return;
12436 : }
12437 8209 : else if (instance->kind == slp_inst_kind_bb_reduc)
12438 : {
12439 : /* Largely inspired by reduction chain epilogue handling in
12440 : vect_create_epilog_for_reduction. */
12441 6590 : vec<tree> vec_defs = vNULL;
12442 6590 : vect_get_slp_defs (node, &vec_defs);
12443 6590 : enum tree_code reduc_code
12444 6590 : = gimple_assign_rhs_code (instance->root_stmts[0]->stmt);
12445 : /* ??? We actually have to reflect signs somewhere. */
12446 6590 : if (reduc_code == MINUS_EXPR)
12447 0 : reduc_code = PLUS_EXPR;
12448 6590 : gimple_seq epilogue = NULL;
12449 : /* We may end up with more than one vector result, reduce them
12450 : to one vector. */
12451 6590 : tree vec_def = vec_defs[0];
12452 6590 : tree vectype = TREE_TYPE (vec_def);
12453 6590 : tree compute_vectype = vectype;
12454 6590 : bool pun_for_overflow_p = (ANY_INTEGRAL_TYPE_P (vectype)
12455 5449 : && TYPE_OVERFLOW_UNDEFINED (vectype)
12456 10224 : && operation_can_overflow (reduc_code));
12457 3079 : if (pun_for_overflow_p)
12458 : {
12459 3079 : compute_vectype = unsigned_type_for (vectype);
12460 3079 : vec_def = gimple_build (&epilogue, VIEW_CONVERT_EXPR,
12461 : compute_vectype, vec_def);
12462 : }
12463 9089 : for (unsigned i = 1; i < vec_defs.length (); ++i)
12464 : {
12465 2499 : tree def = vec_defs[i];
12466 2499 : if (pun_for_overflow_p)
12467 2291 : def = gimple_build (&epilogue, VIEW_CONVERT_EXPR,
12468 : compute_vectype, def);
12469 2499 : vec_def = gimple_build (&epilogue, reduc_code, compute_vectype,
12470 : vec_def, def);
12471 : }
12472 6590 : vec_defs.release ();
12473 : /* ??? Support other schemes than direct internal fn or two
12474 : element vectors. */
12475 6590 : tree scalar_def;
12476 6590 : internal_fn reduc_fn;
12477 8239 : if (!reduction_fn_for_scalar_code (reduc_code, &reduc_fn)
12478 6590 : || reduc_fn == IFN_LAST
12479 13180 : || !direct_internal_fn_supported_p (reduc_fn, compute_vectype,
12480 : OPTIMIZE_FOR_BOTH))
12481 : {
12482 1649 : gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (compute_vectype), 2u));
12483 1649 : tree tem0 = gimple_build (&epilogue, BIT_FIELD_REF,
12484 1649 : TREE_TYPE (compute_vectype), vec_def,
12485 1649 : TYPE_SIZE (TREE_TYPE (compute_vectype)),
12486 1649 : bitsize_zero_node);
12487 1649 : tree tem1 = gimple_build (&epilogue, BIT_FIELD_REF,
12488 1649 : TREE_TYPE (compute_vectype), vec_def,
12489 1649 : TYPE_SIZE (TREE_TYPE (compute_vectype)),
12490 1649 : TYPE_SIZE (TREE_TYPE (compute_vectype)));
12491 1649 : scalar_def = gimple_build (&epilogue, reduc_code,
12492 1649 : TREE_TYPE (compute_vectype), tem0, tem1);
12493 : }
12494 : else
12495 4941 : scalar_def = gimple_build (&epilogue, as_combined_fn (reduc_fn),
12496 4941 : TREE_TYPE (compute_vectype), vec_def);
12497 6590 : if (!SLP_INSTANCE_REMAIN_DEFS (instance).is_empty ())
12498 : {
12499 3522 : tree rem_def = NULL_TREE;
12500 14510 : for (auto def : SLP_INSTANCE_REMAIN_DEFS (instance))
12501 : {
12502 10988 : def = gimple_convert (&epilogue, TREE_TYPE (scalar_def), def);
12503 10988 : if (!rem_def)
12504 : rem_def = def;
12505 : else
12506 7466 : rem_def = gimple_build (&epilogue, reduc_code,
12507 7466 : TREE_TYPE (scalar_def),
12508 : rem_def, def);
12509 : }
12510 3522 : scalar_def = gimple_build (&epilogue, reduc_code,
12511 3522 : TREE_TYPE (scalar_def),
12512 : scalar_def, rem_def);
12513 : }
12514 6590 : scalar_def = gimple_convert (&epilogue,
12515 6590 : TREE_TYPE (vectype), scalar_def);
12516 6590 : gimple_stmt_iterator rgsi = gsi_for_stmt (instance->root_stmts[0]->stmt);
12517 6590 : gsi_insert_seq_before (&rgsi, epilogue, GSI_SAME_STMT);
12518 6590 : gimple_assign_set_rhs_from_tree (&rgsi, scalar_def);
12519 6590 : update_stmt (gsi_stmt (rgsi));
12520 6590 : return;
12521 : }
12522 1619 : else if (instance->kind == slp_inst_kind_gcond)
12523 : {
12524 : /* Only support a single root for now as we can't codegen CFG yet and so we
12525 : can't support lane > 1 at this time. */
12526 1619 : gcc_assert (instance->root_stmts.length () == 1);
12527 1619 : auto root_stmt_info = instance->root_stmts[0];
12528 1619 : auto last_stmt = STMT_VINFO_STMT (vect_orig_stmt (root_stmt_info));
12529 1619 : gimple_stmt_iterator rgsi = gsi_for_stmt (last_stmt);
12530 1619 : gcc_assert (!SLP_TREE_VEC_DEFS (node).is_empty ());
12531 1619 : bool res = vectorizable_early_exit (as_a <loop_vec_info> (vinfo),
12532 : root_stmt_info, &rgsi, node, NULL);
12533 1619 : gcc_assert (res);
12534 1619 : return;
12535 : }
12536 : else
12537 0 : gcc_unreachable ();
12538 : }
12539 :
12540 : struct slp_scc_info
12541 : {
12542 : bool on_stack;
12543 : int dfs;
12544 : int lowlink;
12545 : };
12546 :
12547 : /* Schedule the SLP INSTANCE doing a DFS walk and collecting SCCs.
12548 : When PLACE_ONLY, return false if there is no possible schedule. */
12549 :
12550 : static bool
12551 3142029 : vect_schedule_scc (vec_info *vinfo, slp_tree node, slp_instance instance,
12552 : hash_map<slp_tree, slp_scc_info> &scc_info,
12553 : int &maxdfs, vec<slp_tree> &stack, bool place_only)
12554 : {
12555 3142029 : bool existed_p;
12556 3142029 : slp_scc_info *info = &scc_info.get_or_insert (node, &existed_p);
12557 3142029 : gcc_assert (!existed_p);
12558 3142029 : info->dfs = maxdfs;
12559 3142029 : info->lowlink = maxdfs;
12560 3142029 : maxdfs++;
12561 :
12562 : /* Leaf. */
12563 3142029 : if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
12564 : {
12565 1209796 : info->on_stack = false;
12566 1209796 : bool res = vect_schedule_slp_node (vinfo, node, instance, place_only);
12567 1209796 : gcc_assert (res);
12568 : return true;
12569 : }
12570 :
12571 1932233 : info->on_stack = true;
12572 1932233 : stack.safe_push (node);
12573 :
12574 1932233 : bool res = true;
12575 1932233 : unsigned i;
12576 1932233 : slp_tree child;
12577 : /* DFS recurse. */
12578 7552602 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
12579 : {
12580 2038328 : if (!child)
12581 55566 : continue;
12582 1982762 : slp_scc_info *child_info = scc_info.get (child);
12583 1982762 : if (!child_info)
12584 : {
12585 1833627 : res &= vect_schedule_scc (vinfo, child, instance, scc_info,
12586 : maxdfs, stack, place_only);
12587 : /* Recursion might have re-allocated the node. */
12588 1833627 : info = scc_info.get (node);
12589 1833627 : child_info = scc_info.get (child);
12590 1833627 : info->lowlink = MIN (info->lowlink, child_info->lowlink);
12591 : }
12592 149135 : else if (child_info->on_stack)
12593 35568 : info->lowlink = MIN (info->lowlink, child_info->dfs);
12594 : }
12595 1932233 : if (info->lowlink != info->dfs)
12596 : return res;
12597 :
12598 1892728 : auto_vec<slp_tree, 4> phis_to_fixup;
12599 :
12600 : /* Singleton. */
12601 1892728 : if (stack.last () == node)
12602 : {
12603 1863684 : stack.pop ();
12604 1863684 : info->on_stack = false;
12605 1863684 : res &= vect_schedule_slp_node (vinfo, node, instance, place_only);
12606 1863684 : if (!SLP_TREE_PERMUTE_P (node)
12607 1863684 : && is_a <gphi *> (SLP_TREE_REPRESENTATIVE (node)->stmt))
12608 73340 : phis_to_fixup.quick_push (node);
12609 : }
12610 : else
12611 : {
12612 : /* SCC. */
12613 29044 : int last_idx = stack.length () - 1;
12614 68549 : while (stack[last_idx] != node)
12615 39505 : last_idx--;
12616 : /* We can break the cycle at PHIs who have at least one child
12617 : code generated. Then we could re-start the DFS walk until
12618 : all nodes in the SCC are covered (we might have new entries
12619 : for only back-reachable nodes). But it's simpler to just
12620 : iterate and schedule those that are ready. */
12621 29044 : unsigned todo = stack.length () - last_idx;
12622 29912 : do
12623 : {
12624 132769 : for (int idx = stack.length () - 1; idx >= last_idx; --idx)
12625 : {
12626 72945 : slp_tree entry = stack[idx];
12627 72945 : if (!entry)
12628 2598 : continue;
12629 70347 : bool phi = (!SLP_TREE_PERMUTE_P (entry)
12630 70347 : && is_a <gphi *> (SLP_TREE_REPRESENTATIVE (entry)->stmt));
12631 70347 : bool ready = !phi;
12632 214003 : FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (entry), i, child)
12633 133367 : if (!child)
12634 : {
12635 23027 : gcc_assert (phi);
12636 : ready = true;
12637 : break;
12638 : }
12639 110340 : else if (scc_info.get (child)->on_stack)
12640 : {
12641 30978 : if (!phi)
12642 : {
12643 : ready = false;
12644 : break;
12645 : }
12646 : }
12647 : else
12648 : {
12649 79362 : if (phi)
12650 : {
12651 : ready = true;
12652 : break;
12653 : }
12654 : }
12655 47320 : if (ready)
12656 : {
12657 68549 : vect_schedule_slp_node (vinfo, entry, instance, place_only);
12658 68549 : scc_info.get (entry)->on_stack = false;
12659 68549 : stack[idx] = NULL;
12660 68549 : todo--;
12661 68549 : if (phi)
12662 35397 : phis_to_fixup.safe_push (entry);
12663 : }
12664 : }
12665 : }
12666 29912 : while (todo != 0);
12667 :
12668 : /* Pop the SCC. */
12669 29044 : stack.truncate (last_idx);
12670 : }
12671 :
12672 1892728 : if (place_only)
12673 : return res;
12674 :
12675 : /* Now fixup the backedge def of the vectorized PHIs in this SCC. */
12676 : slp_tree phi_node;
12677 1015832 : FOR_EACH_VEC_ELT (phis_to_fixup, i, phi_node)
12678 : {
12679 55438 : gphi *phi = as_a <gphi *> (SLP_TREE_REPRESENTATIVE (phi_node)->stmt);
12680 55438 : edge_iterator ei;
12681 55438 : edge e;
12682 174512 : FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds)
12683 : {
12684 119074 : unsigned dest_idx = e->dest_idx;
12685 119074 : child = SLP_TREE_CHILDREN (phi_node)[dest_idx];
12686 119074 : if (!child || SLP_TREE_DEF_TYPE (child) != vect_internal_def)
12687 66979 : continue;
12688 52095 : unsigned n = SLP_TREE_VEC_DEFS (phi_node).length ();
12689 : /* Simply fill all args. */
12690 52095 : if (STMT_VINFO_DEF_TYPE (SLP_TREE_REPRESENTATIVE (phi_node))
12691 : != vect_first_order_recurrence)
12692 110216 : for (unsigned i = 0; i < n; ++i)
12693 : {
12694 58166 : tree phidef = SLP_TREE_VEC_DEFS (phi_node)[i];
12695 58166 : gphi *phi = as_a <gphi *> (SSA_NAME_DEF_STMT (phidef));
12696 58166 : add_phi_arg (phi, vect_get_slp_vect_def (child, i),
12697 : e, gimple_phi_arg_location (phi, dest_idx));
12698 : }
12699 : else
12700 : {
12701 : /* Unless it is a first order recurrence which needs
12702 : args filled in for both the PHI node and the permutes. */
12703 45 : gimple *perm
12704 45 : = SSA_NAME_DEF_STMT (SLP_TREE_VEC_DEFS (phi_node)[0]);
12705 45 : gimple *rphi = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (perm));
12706 45 : add_phi_arg (as_a <gphi *> (rphi),
12707 : vect_get_slp_vect_def (child, n - 1),
12708 : e, gimple_phi_arg_location (phi, dest_idx));
12709 172 : for (unsigned i = 0; i < n; ++i)
12710 : {
12711 82 : gimple *perm
12712 82 : = SSA_NAME_DEF_STMT (SLP_TREE_VEC_DEFS (phi_node)[i]);
12713 82 : if (i > 0)
12714 37 : gimple_assign_set_rhs1 (perm,
12715 : vect_get_slp_vect_def (child, i - 1));
12716 82 : gimple_assign_set_rhs2 (perm,
12717 : vect_get_slp_vect_def (child, i));
12718 82 : update_stmt (perm);
12719 : }
12720 : }
12721 : }
12722 : }
12723 :
12724 960394 : gcc_assert (res);
12725 : return true;
12726 1892728 : }
12727 :
12728 : /* Generate vector code for SLP_INSTANCES in the loop/basic block. Perform
12729 : vector stmt placement only when PLACE_ONLY is true, removing SLP graph
12730 : entries that cannot be scheduled. If placing, return false if a schedule
12731 : cannot be computed for any entry. */
12732 :
12733 : bool
12734 801798 : vect_schedule_slp (vec_info *vinfo, vec<slp_instance> &slp_instances,
12735 : bool place_only)
12736 : {
12737 801798 : slp_instance instance;
12738 801798 : unsigned int i;
12739 :
12740 801798 : hash_map<slp_tree, slp_scc_info> scc_info;
12741 801798 : int maxdfs = 0;
12742 2114072 : for (i = 0; slp_instances.iterate (i, &instance); )
12743 : {
12744 1312274 : slp_tree node = SLP_INSTANCE_TREE (instance);
12745 1312274 : if (!place_only && dump_enabled_p ())
12746 : {
12747 16142 : dump_printf_loc (MSG_NOTE, vect_location,
12748 : "Vectorizing SLP tree:\n");
12749 : /* ??? Dump all? */
12750 16142 : if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ())
12751 510 : dump_printf_loc (MSG_NOTE, vect_location, "Root stmt: %G",
12752 510 : SLP_INSTANCE_ROOT_STMTS (instance)[0]->stmt);
12753 16142 : vect_print_slp_graph (MSG_NOTE, vect_location,
12754 : SLP_INSTANCE_TREE (instance));
12755 : }
12756 : /* Schedule the tree of INSTANCE, scheduling SCCs in a way to
12757 : have a PHI be the node breaking the cycle. */
12758 1312274 : bool res = true;
12759 1312274 : auto_vec<slp_tree> stack;
12760 1312274 : if (!scc_info.get (node))
12761 1308402 : res &= vect_schedule_scc (vinfo, node, instance, scc_info,
12762 : maxdfs, stack, place_only);
12763 :
12764 1312274 : if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ())
12765 : {
12766 64825 : if (place_only)
12767 : {
12768 50979 : gimple *root_stmt = instance->root_stmts[0]->stmt;
12769 50979 : res &= (!node->si
12770 : /* As we instert after node->si it may not be the
12771 : root_stmt itself. */
12772 50979 : || (node->si != root_stmt
12773 50134 : && vect_stmt_dominates_stmt_p (node->si, root_stmt)));
12774 : }
12775 : else
12776 13846 : vectorize_slp_instance_root_stmt (vinfo, node, instance);
12777 : }
12778 :
12779 1312274 : if (!place_only && dump_enabled_p ())
12780 16142 : dump_printf_loc (MSG_NOTE, vect_location,
12781 : "vectorizing stmts using SLP.\n");
12782 :
12783 1312274 : if (!res)
12784 : {
12785 22 : gcc_assert (place_only);
12786 22 : if (dump_enabled_p ())
12787 8 : dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
12788 : "not vectorized: cannot schedule SLP graph "
12789 : "entry %p\n", (void *)instance);
12790 22 : vect_free_slp_instance (instance);
12791 22 : slp_instances.ordered_remove (i);
12792 22 : continue;
12793 : }
12794 1312252 : ++i;
12795 1312274 : }
12796 :
12797 801798 : if (place_only)
12798 493670 : return !slp_instances.is_empty ();
12799 :
12800 1952067 : FOR_EACH_VEC_ELT (slp_instances, i, instance)
12801 : {
12802 595306 : slp_tree root = SLP_INSTANCE_TREE (instance);
12803 595306 : stmt_vec_info store_info;
12804 595306 : unsigned int j;
12805 :
12806 : /* Remove scalar call stmts. Do not do this for basic-block
12807 : vectorization as not all uses may be vectorized.
12808 : ??? Why should this be necessary? DCE should be able to
12809 : remove the stmts itself.
12810 : ??? For BB vectorization we can as well remove scalar
12811 : stmts starting from the SLP tree root if they have no
12812 : uses. */
12813 595306 : if (is_a <loop_vec_info> (vinfo))
12814 90471 : vect_remove_slp_scalar_calls (vinfo, root);
12815 :
12816 : /* Remove vectorized stores original scalar stmts. */
12817 2651479 : for (j = 0; SLP_TREE_SCALAR_STMTS (root).iterate (j, &store_info); j++)
12818 : {
12819 1500177 : if (!store_info
12820 1500163 : || !STMT_VINFO_DATA_REF (store_info)
12821 1470677 : || !DR_IS_WRITE (STMT_VINFO_DATA_REF (store_info)))
12822 : break;
12823 :
12824 1460867 : store_info = vect_orig_stmt (store_info);
12825 : /* Free the attached stmt_vec_info and remove the stmt. */
12826 1460867 : vinfo->remove_stmt (store_info);
12827 :
12828 : /* Invalidate SLP_TREE_REPRESENTATIVE in case we released it
12829 : to not crash in vect_free_slp_tree later. */
12830 1460867 : if (SLP_TREE_REPRESENTATIVE (root) == store_info)
12831 555658 : SLP_TREE_REPRESENTATIVE (root) = NULL;
12832 : }
12833 : }
12834 :
12835 : return true;
12836 801798 : }
|