c: Support C2x empty initializer braces
[platform/upstream/gcc.git] / gcc / tree-vectorizer.cc
1 /* Vectorizer
2    Copyright (C) 2003-2022 Free Software Foundation, Inc.
3    Contributed by Dorit Naishlos <dorit@il.ibm.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 /* Loop and basic block vectorizer.
22
23   This file contains drivers for the three vectorizers:
24   (1) loop vectorizer (inter-iteration parallelism),
25   (2) loop-aware SLP (intra-iteration parallelism) (invoked by the loop
26       vectorizer)
27   (3) BB vectorizer (out-of-loops), aka SLP
28
29   The rest of the vectorizer's code is organized as follows:
30   - tree-vect-loop.cc - loop specific parts such as reductions, etc. These are
31     used by drivers (1) and (2).
32   - tree-vect-loop-manip.cc - vectorizer's loop control-flow utilities, used by
33     drivers (1) and (2).
34   - tree-vect-slp.cc - BB vectorization specific analysis and transformation,
35     used by drivers (2) and (3).
36   - tree-vect-stmts.cc - statements analysis and transformation (used by all).
37   - tree-vect-data-refs.cc - vectorizer specific data-refs analysis and
38     manipulations (used by all).
39   - tree-vect-patterns.cc - vectorizable code patterns detector (used by all)
40
41   Here's a poor attempt at illustrating that:
42
43      tree-vectorizer.cc:
44      loop_vect()  loop_aware_slp()  slp_vect()
45           |        /           \          /
46           |       /             \        /
47           tree-vect-loop.cc  tree-vect-slp.cc
48                 | \      \  /      /   |
49                 |  \      \/      /    |
50                 |   \     /\     /     |
51                 |    \   /  \   /      |
52          tree-vect-stmts.cc  tree-vect-data-refs.cc
53                        \      /
54                     tree-vect-patterns.cc
55 */
56
57 #include "config.h"
58 #include "system.h"
59 #include "coretypes.h"
60 #include "backend.h"
61 #include "tree.h"
62 #include "gimple.h"
63 #include "predict.h"
64 #include "tree-pass.h"
65 #include "ssa.h"
66 #include "cgraph.h"
67 #include "fold-const.h"
68 #include "stor-layout.h"
69 #include "gimple-iterator.h"
70 #include "gimple-walk.h"
71 #include "tree-ssa-loop-manip.h"
72 #include "tree-ssa-loop-niter.h"
73 #include "tree-cfg.h"
74 #include "cfgloop.h"
75 #include "tree-vectorizer.h"
76 #include "tree-ssa-propagate.h"
77 #include "dbgcnt.h"
78 #include "tree-scalar-evolution.h"
79 #include "stringpool.h"
80 #include "attribs.h"
81 #include "gimple-pretty-print.h"
82 #include "opt-problem.h"
83 #include "internal-fn.h"
84 #include "tree-ssa-sccvn.h"
85 #include "tree-into-ssa.h"
86
87 /* Loop or bb location, with hotness information.  */
88 dump_user_location_t vect_location;
89
90 /* auto_purge_vect_location's dtor: reset the vect_location
91    global, to avoid stale location_t values that could reference
92    GC-ed blocks.  */
93
94 auto_purge_vect_location::~auto_purge_vect_location ()
95 {
96   vect_location = dump_user_location_t ();
97 }
98
99 /* Dump a cost entry according to args to F.  */
100
101 void
102 dump_stmt_cost (FILE *f, int count, enum vect_cost_for_stmt kind,
103                 stmt_vec_info stmt_info, slp_tree node, tree,
104                 int misalign, unsigned cost,
105                 enum vect_cost_model_location where)
106 {
107   if (stmt_info)
108     {
109       print_gimple_expr (f, STMT_VINFO_STMT (stmt_info), 0, TDF_SLIM);
110       fprintf (f, " ");
111     }
112   else if (node)
113     fprintf (f, "node %p ", (void *)node);
114   else
115     fprintf (f, "<unknown> ");
116   fprintf (f, "%d times ", count);
117   const char *ks = "unknown";
118   switch (kind)
119     {
120     case scalar_stmt:
121       ks = "scalar_stmt";
122       break;
123     case scalar_load:
124       ks = "scalar_load";
125       break;
126     case scalar_store:
127       ks = "scalar_store";
128       break;
129     case vector_stmt:
130       ks = "vector_stmt";
131       break;
132     case vector_load:
133       ks = "vector_load";
134       break;
135     case vector_gather_load:
136       ks = "vector_gather_load";
137       break;
138     case unaligned_load:
139       ks = "unaligned_load";
140       break;
141     case unaligned_store:
142       ks = "unaligned_store";
143       break;
144     case vector_store:
145       ks = "vector_store";
146       break;
147     case vector_scatter_store:
148       ks = "vector_scatter_store";
149       break;
150     case vec_to_scalar:
151       ks = "vec_to_scalar";
152       break;
153     case scalar_to_vec:
154       ks = "scalar_to_vec";
155       break;
156     case cond_branch_not_taken:
157       ks = "cond_branch_not_taken";
158       break;
159     case cond_branch_taken:
160       ks = "cond_branch_taken";
161       break;
162     case vec_perm:
163       ks = "vec_perm";
164       break;
165     case vec_promote_demote:
166       ks = "vec_promote_demote";
167       break;
168     case vec_construct:
169       ks = "vec_construct";
170       break;
171     }
172   fprintf (f, "%s ", ks);
173   if (kind == unaligned_load || kind == unaligned_store)
174     fprintf (f, "(misalign %d) ", misalign);
175   fprintf (f, "costs %u ", cost);
176   const char *ws = "unknown";
177   switch (where)
178     {
179     case vect_prologue:
180       ws = "prologue";
181       break;
182     case vect_body:
183       ws = "body";
184       break;
185     case vect_epilogue:
186       ws = "epilogue";
187       break;
188     }
189   fprintf (f, "in %s\n", ws);
190 }
191 \f
192 /* For mapping simduid to vectorization factor.  */
193
194 class simduid_to_vf : public free_ptr_hash<simduid_to_vf>
195 {
196 public:
197   unsigned int simduid;
198   poly_uint64 vf;
199
200   /* hash_table support.  */
201   static inline hashval_t hash (const simduid_to_vf *);
202   static inline int equal (const simduid_to_vf *, const simduid_to_vf *);
203 };
204
205 inline hashval_t
206 simduid_to_vf::hash (const simduid_to_vf *p)
207 {
208   return p->simduid;
209 }
210
211 inline int
212 simduid_to_vf::equal (const simduid_to_vf *p1, const simduid_to_vf *p2)
213 {
214   return p1->simduid == p2->simduid;
215 }
216
217 /* This hash maps the OMP simd array to the corresponding simduid used
218    to index into it.  Like thus,
219
220         _7 = GOMP_SIMD_LANE (simduid.0)
221         ...
222         ...
223         D.1737[_7] = stuff;
224
225
226    This hash maps from the OMP simd array (D.1737[]) to DECL_UID of
227    simduid.0.  */
228
229 struct simd_array_to_simduid : free_ptr_hash<simd_array_to_simduid>
230 {
231   tree decl;
232   unsigned int simduid;
233
234   /* hash_table support.  */
235   static inline hashval_t hash (const simd_array_to_simduid *);
236   static inline int equal (const simd_array_to_simduid *,
237                            const simd_array_to_simduid *);
238 };
239
240 inline hashval_t
241 simd_array_to_simduid::hash (const simd_array_to_simduid *p)
242 {
243   return DECL_UID (p->decl);
244 }
245
246 inline int
247 simd_array_to_simduid::equal (const simd_array_to_simduid *p1,
248                               const simd_array_to_simduid *p2)
249 {
250   return p1->decl == p2->decl;
251 }
252
253 /* Fold IFN_GOMP_SIMD_LANE, IFN_GOMP_SIMD_VF, IFN_GOMP_SIMD_LAST_LANE,
254    into their corresponding constants and remove
255    IFN_GOMP_SIMD_ORDERED_{START,END}.  */
256
257 static void
258 adjust_simduid_builtins (hash_table<simduid_to_vf> *htab, function *fun)
259 {
260   basic_block bb;
261
262   FOR_EACH_BB_FN (bb, fun)
263     {
264       gimple_stmt_iterator i;
265
266       for (i = gsi_start_bb (bb); !gsi_end_p (i); )
267         {
268           poly_uint64 vf = 1;
269           enum internal_fn ifn;
270           gimple *stmt = gsi_stmt (i);
271           tree t;
272           if (!is_gimple_call (stmt)
273               || !gimple_call_internal_p (stmt))
274             {
275               gsi_next (&i);
276               continue;
277             }
278           ifn = gimple_call_internal_fn (stmt);
279           switch (ifn)
280             {
281             case IFN_GOMP_SIMD_LANE:
282             case IFN_GOMP_SIMD_VF:
283             case IFN_GOMP_SIMD_LAST_LANE:
284               break;
285             case IFN_GOMP_SIMD_ORDERED_START:
286             case IFN_GOMP_SIMD_ORDERED_END:
287               if (integer_onep (gimple_call_arg (stmt, 0)))
288                 {
289                   enum built_in_function bcode
290                     = (ifn == IFN_GOMP_SIMD_ORDERED_START
291                        ? BUILT_IN_GOMP_ORDERED_START
292                        : BUILT_IN_GOMP_ORDERED_END);
293                   gimple *g
294                     = gimple_build_call (builtin_decl_explicit (bcode), 0);
295                   gimple_move_vops (g, stmt);
296                   gsi_replace (&i, g, true);
297                   continue;
298                 }
299               gsi_remove (&i, true);
300               unlink_stmt_vdef (stmt);
301               continue;
302             default:
303               gsi_next (&i);
304               continue;
305             }
306           tree arg = gimple_call_arg (stmt, 0);
307           gcc_assert (arg != NULL_TREE);
308           gcc_assert (TREE_CODE (arg) == SSA_NAME);
309           simduid_to_vf *p = NULL, data;
310           data.simduid = DECL_UID (SSA_NAME_VAR (arg));
311           /* Need to nullify loop safelen field since it's value is not
312              valid after transformation.  */
313           if (bb->loop_father && bb->loop_father->safelen > 0)
314             bb->loop_father->safelen = 0;
315           if (htab)
316             {
317               p = htab->find (&data);
318               if (p)
319                 vf = p->vf;
320             }
321           switch (ifn)
322             {
323             case IFN_GOMP_SIMD_VF:
324               t = build_int_cst (unsigned_type_node, vf);
325               break;
326             case IFN_GOMP_SIMD_LANE:
327               t = build_int_cst (unsigned_type_node, 0);
328               break;
329             case IFN_GOMP_SIMD_LAST_LANE:
330               t = gimple_call_arg (stmt, 1);
331               break;
332             default:
333               gcc_unreachable ();
334             }
335           tree lhs = gimple_call_lhs (stmt);
336           if (lhs)
337             replace_uses_by (lhs, t);
338           release_defs (stmt);
339           gsi_remove (&i, true);
340         }
341     }
342 }
343
344 /* Helper structure for note_simd_array_uses.  */
345
346 struct note_simd_array_uses_struct
347 {
348   hash_table<simd_array_to_simduid> **htab;
349   unsigned int simduid;
350 };
351
352 /* Callback for note_simd_array_uses, called through walk_gimple_op.  */
353
354 static tree
355 note_simd_array_uses_cb (tree *tp, int *walk_subtrees, void *data)
356 {
357   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
358   struct note_simd_array_uses_struct *ns
359     = (struct note_simd_array_uses_struct *) wi->info;
360
361   if (TYPE_P (*tp))
362     *walk_subtrees = 0;
363   else if (VAR_P (*tp)
364            && lookup_attribute ("omp simd array", DECL_ATTRIBUTES (*tp))
365            && DECL_CONTEXT (*tp) == current_function_decl)
366     {
367       simd_array_to_simduid data;
368       if (!*ns->htab)
369         *ns->htab = new hash_table<simd_array_to_simduid> (15);
370       data.decl = *tp;
371       data.simduid = ns->simduid;
372       simd_array_to_simduid **slot = (*ns->htab)->find_slot (&data, INSERT);
373       if (*slot == NULL)
374         {
375           simd_array_to_simduid *p = XNEW (simd_array_to_simduid);
376           *p = data;
377           *slot = p;
378         }
379       else if ((*slot)->simduid != ns->simduid)
380         (*slot)->simduid = -1U;
381       *walk_subtrees = 0;
382     }
383   return NULL_TREE;
384 }
385
386 /* Find "omp simd array" temporaries and map them to corresponding
387    simduid.  */
388
389 static void
390 note_simd_array_uses (hash_table<simd_array_to_simduid> **htab, function *fun)
391 {
392   basic_block bb;
393   gimple_stmt_iterator gsi;
394   struct walk_stmt_info wi;
395   struct note_simd_array_uses_struct ns;
396
397   memset (&wi, 0, sizeof (wi));
398   wi.info = &ns;
399   ns.htab = htab;
400
401   FOR_EACH_BB_FN (bb, fun)
402     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
403       {
404         gimple *stmt = gsi_stmt (gsi);
405         if (!is_gimple_call (stmt) || !gimple_call_internal_p (stmt))
406           continue;
407         switch (gimple_call_internal_fn (stmt))
408           {
409           case IFN_GOMP_SIMD_LANE:
410           case IFN_GOMP_SIMD_VF:
411           case IFN_GOMP_SIMD_LAST_LANE:
412             break;
413           default:
414             continue;
415           }
416         tree lhs = gimple_call_lhs (stmt);
417         if (lhs == NULL_TREE)
418           continue;
419         imm_use_iterator use_iter;
420         gimple *use_stmt;
421         ns.simduid = DECL_UID (SSA_NAME_VAR (gimple_call_arg (stmt, 0)));
422         FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, lhs)
423           if (!is_gimple_debug (use_stmt))
424             walk_gimple_op (use_stmt, note_simd_array_uses_cb, &wi);
425       }
426 }
427
428 /* Shrink arrays with "omp simd array" attribute to the corresponding
429    vectorization factor.  */
430
431 static void
432 shrink_simd_arrays
433   (hash_table<simd_array_to_simduid> *simd_array_to_simduid_htab,
434    hash_table<simduid_to_vf> *simduid_to_vf_htab)
435 {
436   for (hash_table<simd_array_to_simduid>::iterator iter
437          = simd_array_to_simduid_htab->begin ();
438        iter != simd_array_to_simduid_htab->end (); ++iter)
439     if ((*iter)->simduid != -1U)
440       {
441         tree decl = (*iter)->decl;
442         poly_uint64 vf = 1;
443         if (simduid_to_vf_htab)
444           {
445             simduid_to_vf *p = NULL, data;
446             data.simduid = (*iter)->simduid;
447             p = simduid_to_vf_htab->find (&data);
448             if (p)
449               vf = p->vf;
450           }
451         tree atype
452           = build_array_type_nelts (TREE_TYPE (TREE_TYPE (decl)), vf);
453         TREE_TYPE (decl) = atype;
454         relayout_decl (decl);
455       }
456
457   delete simd_array_to_simduid_htab;
458 }
459 \f
460 /* Initialize the vec_info with kind KIND_IN and target cost data
461    TARGET_COST_DATA_IN.  */
462
463 vec_info::vec_info (vec_info::vec_kind kind_in, vec_info_shared *shared_)
464   : kind (kind_in),
465     shared (shared_),
466     stmt_vec_info_ro (false)
467 {
468   stmt_vec_infos.create (50);
469 }
470
471 vec_info::~vec_info ()
472 {
473   for (slp_instance &instance : slp_instances)
474     vect_free_slp_instance (instance);
475
476   free_stmt_vec_infos ();
477 }
478
479 vec_info_shared::vec_info_shared ()
480   : n_stmts (0),
481     datarefs (vNULL),
482     datarefs_copy (vNULL),
483     ddrs (vNULL)
484 {
485 }
486
487 vec_info_shared::~vec_info_shared ()
488 {
489   free_data_refs (datarefs);
490   free_dependence_relations (ddrs);
491   datarefs_copy.release ();
492 }
493
494 void
495 vec_info_shared::save_datarefs ()
496 {
497   if (!flag_checking)
498     return;
499   datarefs_copy.reserve_exact (datarefs.length ());
500   for (unsigned i = 0; i < datarefs.length (); ++i)
501     datarefs_copy.quick_push (*datarefs[i]);
502 }
503
504 void
505 vec_info_shared::check_datarefs ()
506 {
507   if (!flag_checking)
508     return;
509   gcc_assert (datarefs.length () == datarefs_copy.length ());
510   for (unsigned i = 0; i < datarefs.length (); ++i)
511     if (memcmp (&datarefs_copy[i], datarefs[i],
512                 offsetof (data_reference, alt_indices)) != 0)
513       gcc_unreachable ();
514 }
515
516 /* Record that STMT belongs to the vectorizable region.  Create and return
517    an associated stmt_vec_info.  */
518
519 stmt_vec_info
520 vec_info::add_stmt (gimple *stmt)
521 {
522   stmt_vec_info res = new_stmt_vec_info (stmt);
523   set_vinfo_for_stmt (stmt, res);
524   return res;
525 }
526
527 /* Record that STMT belongs to the vectorizable region.  Create a new
528    stmt_vec_info and mark VECINFO as being related and return the new
529    stmt_vec_info.  */
530
531 stmt_vec_info
532 vec_info::add_pattern_stmt (gimple *stmt, stmt_vec_info stmt_info)
533 {
534   stmt_vec_info res = new_stmt_vec_info (stmt);
535   set_vinfo_for_stmt (stmt, res, false);
536   STMT_VINFO_RELATED_STMT (res) = stmt_info;
537   return res;
538 }
539
540 /* If STMT has an associated stmt_vec_info, return that vec_info, otherwise
541    return null.  It is safe to call this function on any statement, even if
542    it might not be part of the vectorizable region.  */
543
544 stmt_vec_info
545 vec_info::lookup_stmt (gimple *stmt)
546 {
547   unsigned int uid = gimple_uid (stmt);
548   if (uid > 0 && uid - 1 < stmt_vec_infos.length ())
549     {
550       stmt_vec_info res = stmt_vec_infos[uid - 1];
551       if (res && res->stmt == stmt)
552         return res;
553     }
554   return NULL;
555 }
556
557 /* If NAME is an SSA_NAME and its definition has an associated stmt_vec_info,
558    return that stmt_vec_info, otherwise return null.  It is safe to call
559    this on arbitrary operands.  */
560
561 stmt_vec_info
562 vec_info::lookup_def (tree name)
563 {
564   if (TREE_CODE (name) == SSA_NAME
565       && !SSA_NAME_IS_DEFAULT_DEF (name))
566     return lookup_stmt (SSA_NAME_DEF_STMT (name));
567   return NULL;
568 }
569
570 /* See whether there is a single non-debug statement that uses LHS and
571    whether that statement has an associated stmt_vec_info.  Return the
572    stmt_vec_info if so, otherwise return null.  */
573
574 stmt_vec_info
575 vec_info::lookup_single_use (tree lhs)
576 {
577   use_operand_p dummy;
578   gimple *use_stmt;
579   if (single_imm_use (lhs, &dummy, &use_stmt))
580     return lookup_stmt (use_stmt);
581   return NULL;
582 }
583
584 /* Return vectorization information about DR.  */
585
586 dr_vec_info *
587 vec_info::lookup_dr (data_reference *dr)
588 {
589   stmt_vec_info stmt_info = lookup_stmt (DR_STMT (dr));
590   /* DR_STMT should never refer to a stmt in a pattern replacement.  */
591   gcc_checking_assert (!is_pattern_stmt_p (stmt_info));
592   return STMT_VINFO_DR_INFO (stmt_info->dr_aux.stmt);
593 }
594
595 /* Record that NEW_STMT_INFO now implements the same data reference
596    as OLD_STMT_INFO.  */
597
598 void
599 vec_info::move_dr (stmt_vec_info new_stmt_info, stmt_vec_info old_stmt_info)
600 {
601   gcc_assert (!is_pattern_stmt_p (old_stmt_info));
602   STMT_VINFO_DR_INFO (old_stmt_info)->stmt = new_stmt_info;
603   new_stmt_info->dr_aux = old_stmt_info->dr_aux;
604   STMT_VINFO_DR_WRT_VEC_LOOP (new_stmt_info)
605     = STMT_VINFO_DR_WRT_VEC_LOOP (old_stmt_info);
606   STMT_VINFO_GATHER_SCATTER_P (new_stmt_info)
607     = STMT_VINFO_GATHER_SCATTER_P (old_stmt_info);
608 }
609
610 /* Permanently remove the statement described by STMT_INFO from the
611    function.  */
612
613 void
614 vec_info::remove_stmt (stmt_vec_info stmt_info)
615 {
616   gcc_assert (!stmt_info->pattern_stmt_p);
617   set_vinfo_for_stmt (stmt_info->stmt, NULL);
618   unlink_stmt_vdef (stmt_info->stmt);
619   gimple_stmt_iterator si = gsi_for_stmt (stmt_info->stmt);
620   gsi_remove (&si, true);
621   release_defs (stmt_info->stmt);
622   free_stmt_vec_info (stmt_info);
623 }
624
625 /* Replace the statement at GSI by NEW_STMT, both the vectorization
626    information and the function itself.  STMT_INFO describes the statement
627    at GSI.  */
628
629 void
630 vec_info::replace_stmt (gimple_stmt_iterator *gsi, stmt_vec_info stmt_info,
631                         gimple *new_stmt)
632 {
633   gimple *old_stmt = stmt_info->stmt;
634   gcc_assert (!stmt_info->pattern_stmt_p && old_stmt == gsi_stmt (*gsi));
635   gimple_set_uid (new_stmt, gimple_uid (old_stmt));
636   stmt_info->stmt = new_stmt;
637   gsi_replace (gsi, new_stmt, true);
638 }
639
640 /* Insert stmts in SEQ on the VEC_INFO region entry.  If CONTEXT is
641    not NULL it specifies whether to use the sub-region entry
642    determined by it, currently used for loop vectorization to insert
643    on the inner loop entry vs. the outer loop entry.  */
644
645 void
646 vec_info::insert_seq_on_entry (stmt_vec_info context, gimple_seq seq)
647 {
648   if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (this))
649     {
650       class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
651       basic_block new_bb;
652       edge pe;
653
654       if (context && nested_in_vect_loop_p (loop, context))
655         loop = loop->inner;
656
657       pe = loop_preheader_edge (loop);
658       new_bb = gsi_insert_seq_on_edge_immediate (pe, seq);
659       gcc_assert (!new_bb);
660     }
661   else
662     {
663       bb_vec_info bb_vinfo = as_a <bb_vec_info> (this);
664       gimple_stmt_iterator gsi_region_begin
665         = gsi_after_labels (bb_vinfo->bbs[0]);
666       gsi_insert_seq_before (&gsi_region_begin, seq, GSI_SAME_STMT);
667     }
668 }
669
670 /* Like insert_seq_on_entry but just inserts the single stmt NEW_STMT.  */
671
672 void
673 vec_info::insert_on_entry (stmt_vec_info context, gimple *new_stmt)
674 {
675   gimple_seq seq = NULL;
676   gimple_stmt_iterator gsi = gsi_start (seq);
677   gsi_insert_before_without_update (&gsi, new_stmt, GSI_SAME_STMT);
678   insert_seq_on_entry (context, seq);
679 }
680
681 /* Create and initialize a new stmt_vec_info struct for STMT.  */
682
683 stmt_vec_info
684 vec_info::new_stmt_vec_info (gimple *stmt)
685 {
686   stmt_vec_info res = XCNEW (class _stmt_vec_info);
687   res->stmt = stmt;
688
689   STMT_VINFO_TYPE (res) = undef_vec_info_type;
690   STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
691   STMT_VINFO_VECTORIZABLE (res) = true;
692   STMT_VINFO_REDUC_TYPE (res) = TREE_CODE_REDUCTION;
693   STMT_VINFO_REDUC_CODE (res) = ERROR_MARK;
694   STMT_VINFO_REDUC_FN (res) = IFN_LAST;
695   STMT_VINFO_REDUC_IDX (res) = -1;
696   STMT_VINFO_SLP_VECT_ONLY (res) = false;
697   STMT_VINFO_SLP_VECT_ONLY_PATTERN (res) = false;
698   STMT_VINFO_VEC_STMTS (res) = vNULL;
699   res->reduc_initial_values = vNULL;
700   res->reduc_scalar_results = vNULL;
701
702   if (is_a <loop_vec_info> (this)
703       && gimple_code (stmt) == GIMPLE_PHI
704       && is_loop_header_bb_p (gimple_bb (stmt)))
705     STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
706   else
707     STMT_VINFO_DEF_TYPE (res) = vect_internal_def;
708
709   STMT_SLP_TYPE (res) = loop_vect;
710
711   /* This is really "uninitialized" until vect_compute_data_ref_alignment.  */
712   res->dr_aux.misalignment = DR_MISALIGNMENT_UNINITIALIZED;
713
714   return res;
715 }
716
717 /* Associate STMT with INFO.  */
718
719 void
720 vec_info::set_vinfo_for_stmt (gimple *stmt, stmt_vec_info info, bool check_ro)
721 {
722   unsigned int uid = gimple_uid (stmt);
723   if (uid == 0)
724     {
725       gcc_assert (!check_ro || !stmt_vec_info_ro);
726       gcc_checking_assert (info);
727       uid = stmt_vec_infos.length () + 1;
728       gimple_set_uid (stmt, uid);
729       stmt_vec_infos.safe_push (info);
730     }
731   else
732     {
733       gcc_checking_assert (info == NULL);
734       stmt_vec_infos[uid - 1] = info;
735     }
736 }
737
738 /* Free the contents of stmt_vec_infos.  */
739
740 void
741 vec_info::free_stmt_vec_infos (void)
742 {
743   for (stmt_vec_info &info : stmt_vec_infos)
744     if (info != NULL)
745       free_stmt_vec_info (info);
746   stmt_vec_infos.release ();
747 }
748
749 /* Free STMT_INFO.  */
750
751 void
752 vec_info::free_stmt_vec_info (stmt_vec_info stmt_info)
753 {
754   if (stmt_info->pattern_stmt_p)
755     {
756       gimple_set_bb (stmt_info->stmt, NULL);
757       tree lhs = gimple_get_lhs (stmt_info->stmt);
758       if (lhs && TREE_CODE (lhs) == SSA_NAME)
759         release_ssa_name (lhs);
760     }
761
762   stmt_info->reduc_initial_values.release ();
763   stmt_info->reduc_scalar_results.release ();
764   STMT_VINFO_SIMD_CLONE_INFO (stmt_info).release ();
765   STMT_VINFO_VEC_STMTS (stmt_info).release ();
766   free (stmt_info);
767 }
768
769 /* Returns true if S1 dominates S2.  */
770
771 bool
772 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
773 {
774   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
775
776   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
777      SSA_NAME.  Assume it lives at the beginning of function and
778      thus dominates everything.  */
779   if (!bb1 || s1 == s2)
780     return true;
781
782   /* If bb2 is NULL, it doesn't dominate any stmt with a bb.  */
783   if (!bb2)
784     return false;
785
786   if (bb1 != bb2)
787     return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
788
789   /* PHIs in the same basic block are assumed to be
790      executed all in parallel, if only one stmt is a PHI,
791      it dominates the other stmt in the same basic block.  */
792   if (gimple_code (s1) == GIMPLE_PHI)
793     return true;
794
795   if (gimple_code (s2) == GIMPLE_PHI)
796     return false;
797
798   /* Inserted vectorized stmts all have UID 0 while the original stmts
799      in the IL have UID increasing within a BB.  Walk from both sides
800      until we find the other stmt or a stmt with UID != 0.  */
801   gimple_stmt_iterator gsi1 = gsi_for_stmt (s1);
802   while (gimple_uid (gsi_stmt (gsi1)) == 0)
803     {
804       gsi_next (&gsi1);
805       if (gsi_end_p (gsi1))
806         return false;
807       if (gsi_stmt (gsi1) == s2)
808         return true;
809     }
810   if (gimple_uid (gsi_stmt (gsi1)) == -1u)
811     return false;
812
813   gimple_stmt_iterator gsi2 = gsi_for_stmt (s2);
814   while (gimple_uid (gsi_stmt (gsi2)) == 0)
815     {
816       gsi_prev (&gsi2);
817       if (gsi_end_p (gsi2))
818         return false;
819       if (gsi_stmt (gsi2) == s1)
820         return true;
821     }
822   if (gimple_uid (gsi_stmt (gsi2)) == -1u)
823     return false;
824
825   if (gimple_uid (gsi_stmt (gsi1)) <= gimple_uid (gsi_stmt (gsi2)))
826     return true;
827   return false;
828 }
829
830 /* A helper function to free scev and LOOP niter information, as well as
831    clear loop constraint LOOP_C_FINITE.  */
832
833 void
834 vect_free_loop_info_assumptions (class loop *loop)
835 {
836   scev_reset_htab ();
837   /* We need to explicitly reset upper bound information since they are
838      used even after free_numbers_of_iterations_estimates.  */
839   loop->any_upper_bound = false;
840   loop->any_likely_upper_bound = false;
841   free_numbers_of_iterations_estimates (loop);
842   loop_constraint_clear (loop, LOOP_C_FINITE);
843 }
844
845 /* If LOOP has been versioned during ifcvt, return the internal call
846    guarding it.  */
847
848 gimple *
849 vect_loop_vectorized_call (class loop *loop, gcond **cond)
850 {
851   basic_block bb = loop_preheader_edge (loop)->src;
852   gimple *g;
853   do
854     {
855       g = last_stmt (bb);
856       if ((g && gimple_code (g) == GIMPLE_COND)
857           || !single_succ_p (bb))
858         break;
859       if (!single_pred_p (bb))
860         break;
861       bb = single_pred (bb);
862     }
863   while (1);
864   if (g && gimple_code (g) == GIMPLE_COND)
865     {
866       if (cond)
867         *cond = as_a <gcond *> (g);
868       gimple_stmt_iterator gsi = gsi_for_stmt (g);
869       gsi_prev (&gsi);
870       if (!gsi_end_p (gsi))
871         {
872           g = gsi_stmt (gsi);
873           if (gimple_call_internal_p (g, IFN_LOOP_VECTORIZED)
874               && (tree_to_shwi (gimple_call_arg (g, 0)) == loop->num
875                   || tree_to_shwi (gimple_call_arg (g, 1)) == loop->num))
876             return g;
877         }
878     }
879   return NULL;
880 }
881
882 /* If LOOP has been versioned during loop distribution, return the gurading
883    internal call.  */
884
885 static gimple *
886 vect_loop_dist_alias_call (class loop *loop, function *fun)
887 {
888   basic_block bb;
889   basic_block entry;
890   class loop *outer, *orig;
891   gimple_stmt_iterator gsi;
892   gimple *g;
893
894   if (loop->orig_loop_num == 0)
895     return NULL;
896
897   orig = get_loop (fun, loop->orig_loop_num);
898   if (orig == NULL)
899     {
900       /* The original loop is somehow destroyed.  Clear the information.  */
901       loop->orig_loop_num = 0;
902       return NULL;
903     }
904
905   if (loop != orig)
906     bb = nearest_common_dominator (CDI_DOMINATORS, loop->header, orig->header);
907   else
908     bb = loop_preheader_edge (loop)->src;
909
910   outer = bb->loop_father;
911   entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
912
913   /* Look upward in dominance tree.  */
914   for (; bb != entry && flow_bb_inside_loop_p (outer, bb);
915        bb = get_immediate_dominator (CDI_DOMINATORS, bb))
916     {
917       g = last_stmt (bb);
918       if (g == NULL || gimple_code (g) != GIMPLE_COND)
919         continue;
920
921       gsi = gsi_for_stmt (g);
922       gsi_prev (&gsi);
923       if (gsi_end_p (gsi))
924         continue;
925
926       g = gsi_stmt (gsi);
927       /* The guarding internal function call must have the same distribution
928          alias id.  */
929       if (gimple_call_internal_p (g, IFN_LOOP_DIST_ALIAS)
930           && (tree_to_shwi (gimple_call_arg (g, 0)) == loop->orig_loop_num))
931         return g;
932     }
933   return NULL;
934 }
935
936 /* Set the uids of all the statements in basic blocks inside loop
937    represented by LOOP_VINFO. LOOP_VECTORIZED_CALL is the internal
938    call guarding the loop which has been if converted.  */
939 static void
940 set_uid_loop_bbs (loop_vec_info loop_vinfo, gimple *loop_vectorized_call,
941                   function *fun)
942 {
943   tree arg = gimple_call_arg (loop_vectorized_call, 1);
944   basic_block *bbs;
945   unsigned int i;
946   class loop *scalar_loop = get_loop (fun, tree_to_shwi (arg));
947
948   LOOP_VINFO_SCALAR_LOOP (loop_vinfo) = scalar_loop;
949   gcc_checking_assert (vect_loop_vectorized_call (scalar_loop)
950                        == loop_vectorized_call);
951   /* If we are going to vectorize outer loop, prevent vectorization
952      of the inner loop in the scalar loop - either the scalar loop is
953      thrown away, so it is a wasted work, or is used only for
954      a few iterations.  */
955   if (scalar_loop->inner)
956     {
957       gimple *g = vect_loop_vectorized_call (scalar_loop->inner);
958       if (g)
959         {
960           arg = gimple_call_arg (g, 0);
961           get_loop (fun, tree_to_shwi (arg))->dont_vectorize = true;
962           fold_loop_internal_call (g, boolean_false_node);
963         }
964     }
965   bbs = get_loop_body (scalar_loop);
966   for (i = 0; i < scalar_loop->num_nodes; i++)
967     {
968       basic_block bb = bbs[i];
969       gimple_stmt_iterator gsi;
970       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
971         {
972           gimple *phi = gsi_stmt (gsi);
973           gimple_set_uid (phi, 0);
974         }
975       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
976         {
977           gimple *stmt = gsi_stmt (gsi);
978           gimple_set_uid (stmt, 0);
979         }
980     }
981   free (bbs);
982 }
983
984 /* Generate vectorized code for LOOP and its epilogues.  */
985
986 static unsigned
987 vect_transform_loops (hash_table<simduid_to_vf> *&simduid_to_vf_htab,
988                       loop_p loop, gimple *loop_vectorized_call,
989                       function *fun)
990 {
991   loop_vec_info loop_vinfo = loop_vec_info_for_loop (loop);
992
993   if (loop_vectorized_call)
994     set_uid_loop_bbs (loop_vinfo, loop_vectorized_call, fun);
995
996   unsigned HOST_WIDE_INT bytes;
997   if (dump_enabled_p ())
998     {
999       if (GET_MODE_SIZE (loop_vinfo->vector_mode).is_constant (&bytes))
1000         dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
1001                          "loop vectorized using %wu byte vectors\n", bytes);
1002       else
1003         dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
1004                          "loop vectorized using variable length vectors\n");
1005     }
1006
1007   loop_p new_loop = vect_transform_loop (loop_vinfo,
1008                                          loop_vectorized_call);
1009   /* Now that the loop has been vectorized, allow it to be unrolled
1010      etc.  */
1011   loop->force_vectorize = false;
1012
1013   if (loop->simduid)
1014     {
1015       simduid_to_vf *simduid_to_vf_data = XNEW (simduid_to_vf);
1016       if (!simduid_to_vf_htab)
1017         simduid_to_vf_htab = new hash_table<simduid_to_vf> (15);
1018       simduid_to_vf_data->simduid = DECL_UID (loop->simduid);
1019       simduid_to_vf_data->vf = loop_vinfo->vectorization_factor;
1020       *simduid_to_vf_htab->find_slot (simduid_to_vf_data, INSERT)
1021           = simduid_to_vf_data;
1022     }
1023
1024   /* We should not have to update virtual SSA form here but some
1025      transforms involve creating new virtual definitions which makes
1026      updating difficult.
1027      We delay the actual update to the end of the pass but avoid
1028      confusing ourselves by forcing need_ssa_update_p () to false.  */
1029   unsigned todo = 0;
1030   if (need_ssa_update_p (cfun))
1031     {
1032       gcc_assert (loop_vinfo->any_known_not_updated_vssa);
1033       fun->gimple_df->ssa_renaming_needed = false;
1034       todo |= TODO_update_ssa_only_virtuals;
1035     }
1036   gcc_assert (!need_ssa_update_p (cfun));
1037
1038   /* Epilogue of vectorized loop must be vectorized too.  */
1039   if (new_loop)
1040     todo |= vect_transform_loops (simduid_to_vf_htab, new_loop, NULL, fun);
1041
1042   return todo;
1043 }
1044
1045 /* Try to vectorize LOOP.  */
1046
1047 static unsigned
1048 try_vectorize_loop_1 (hash_table<simduid_to_vf> *&simduid_to_vf_htab,
1049                       unsigned *num_vectorized_loops, loop_p loop,
1050                       gimple *loop_vectorized_call,
1051                       gimple *loop_dist_alias_call,
1052                       function *fun)
1053 {
1054   unsigned ret = 0;
1055   vec_info_shared shared;
1056   auto_purge_vect_location sentinel;
1057   vect_location = find_loop_location (loop);
1058
1059   if (LOCATION_LOCUS (vect_location.get_location_t ()) != UNKNOWN_LOCATION
1060       && dump_enabled_p ())
1061     dump_printf (MSG_NOTE | MSG_PRIORITY_INTERNALS,
1062                  "\nAnalyzing loop at %s:%d\n",
1063                  LOCATION_FILE (vect_location.get_location_t ()),
1064                  LOCATION_LINE (vect_location.get_location_t ()));
1065
1066   /* Try to analyze the loop, retaining an opt_problem if dump_enabled_p.  */
1067   opt_loop_vec_info loop_vinfo = vect_analyze_loop (loop, &shared);
1068   loop->aux = loop_vinfo;
1069
1070   if (!loop_vinfo)
1071     if (dump_enabled_p ())
1072       if (opt_problem *problem = loop_vinfo.get_problem ())
1073         {
1074           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
1075                            "couldn't vectorize loop\n");
1076           problem->emit_and_clear ();
1077         }
1078
1079   if (!loop_vinfo || !LOOP_VINFO_VECTORIZABLE_P (loop_vinfo))
1080     {
1081       /* Free existing information if loop is analyzed with some
1082          assumptions.  */
1083       if (loop_constraint_set_p (loop, LOOP_C_FINITE))
1084         vect_free_loop_info_assumptions (loop);
1085
1086       /* If we applied if-conversion then try to vectorize the
1087          BB of innermost loops.
1088          ???  Ideally BB vectorization would learn to vectorize
1089          control flow by applying if-conversion on-the-fly, the
1090          following retains the if-converted loop body even when
1091          only non-if-converted parts took part in BB vectorization.  */
1092       if (flag_tree_slp_vectorize != 0
1093           && loop_vectorized_call
1094           && ! loop->inner)
1095         {
1096           basic_block bb = loop->header;
1097           bool require_loop_vectorize = false;
1098           for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
1099                !gsi_end_p (gsi); gsi_next (&gsi))
1100             {
1101               gimple *stmt = gsi_stmt (gsi);
1102               gcall *call = dyn_cast <gcall *> (stmt);
1103               if (call && gimple_call_internal_p (call))
1104                 {
1105                   internal_fn ifn = gimple_call_internal_fn (call);
1106                   if (ifn == IFN_MASK_LOAD || ifn == IFN_MASK_STORE
1107                       /* Don't keep the if-converted parts when the ifn with
1108                          specifc type is not supported by the backend.  */
1109                       || (direct_internal_fn_p (ifn)
1110                           && !direct_internal_fn_supported_p
1111                           (call, OPTIMIZE_FOR_SPEED)))
1112                     {
1113                       require_loop_vectorize = true;
1114                       break;
1115                     }
1116                 }
1117               gimple_set_uid (stmt, -1);
1118               gimple_set_visited (stmt, false);
1119             }
1120           if (!require_loop_vectorize)
1121             {
1122               tree arg = gimple_call_arg (loop_vectorized_call, 1);
1123               class loop *scalar_loop = get_loop (fun, tree_to_shwi (arg));
1124               if (vect_slp_if_converted_bb (bb, scalar_loop))
1125                 {
1126                   fold_loop_internal_call (loop_vectorized_call,
1127                                            boolean_true_node);
1128                   loop_vectorized_call = NULL;
1129                   ret |= TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
1130                 }
1131             }
1132         }
1133       /* If outer loop vectorization fails for LOOP_VECTORIZED guarded
1134          loop, don't vectorize its inner loop; we'll attempt to
1135          vectorize LOOP_VECTORIZED guarded inner loop of the scalar
1136          loop version.  */
1137       if (loop_vectorized_call && loop->inner)
1138         loop->inner->dont_vectorize = true;
1139       return ret;
1140     }
1141
1142   if (!dbg_cnt (vect_loop))
1143     {
1144       /* Free existing information if loop is analyzed with some
1145          assumptions.  */
1146       if (loop_constraint_set_p (loop, LOOP_C_FINITE))
1147         vect_free_loop_info_assumptions (loop);
1148       return ret;
1149     }
1150
1151   (*num_vectorized_loops)++;
1152   /* Transform LOOP and its epilogues.  */
1153   ret |= vect_transform_loops (simduid_to_vf_htab, loop,
1154                                loop_vectorized_call, fun);
1155
1156   if (loop_vectorized_call)
1157     {
1158       fold_loop_internal_call (loop_vectorized_call, boolean_true_node);
1159       ret |= TODO_cleanup_cfg;
1160     }
1161   if (loop_dist_alias_call)
1162     {
1163       tree value = gimple_call_arg (loop_dist_alias_call, 1);
1164       fold_loop_internal_call (loop_dist_alias_call, value);
1165       ret |= TODO_cleanup_cfg;
1166     }
1167
1168   return ret;
1169 }
1170
1171 /* Try to vectorize LOOP.  */
1172
1173 static unsigned
1174 try_vectorize_loop (hash_table<simduid_to_vf> *&simduid_to_vf_htab,
1175                     unsigned *num_vectorized_loops, loop_p loop,
1176                     function *fun)
1177 {
1178   if (!((flag_tree_loop_vectorize
1179          && optimize_loop_nest_for_speed_p (loop))
1180         || loop->force_vectorize))
1181     return 0;
1182
1183   return try_vectorize_loop_1 (simduid_to_vf_htab, num_vectorized_loops, loop,
1184                                vect_loop_vectorized_call (loop),
1185                                vect_loop_dist_alias_call (loop, fun), fun);
1186 }
1187
1188
1189 /* Loop autovectorization.  */
1190
1191 namespace {
1192
1193 const pass_data pass_data_vectorize =
1194 {
1195   GIMPLE_PASS, /* type */
1196   "vect", /* name */
1197   OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
1198   TV_TREE_VECTORIZATION, /* tv_id */
1199   ( PROP_cfg | PROP_ssa ), /* properties_required */
1200   0, /* properties_provided */
1201   0, /* properties_destroyed */
1202   0, /* todo_flags_start */
1203   0, /* todo_flags_finish */
1204 };
1205
1206 class pass_vectorize : public gimple_opt_pass
1207 {
1208 public:
1209   pass_vectorize (gcc::context *ctxt)
1210     : gimple_opt_pass (pass_data_vectorize, ctxt)
1211   {}
1212
1213   /* opt_pass methods: */
1214   bool gate (function *fun) final override
1215     {
1216       return flag_tree_loop_vectorize || fun->has_force_vectorize_loops;
1217     }
1218
1219   unsigned int execute (function *) final override;
1220
1221 }; // class pass_vectorize
1222
1223 /* Function vectorize_loops.
1224
1225    Entry point to loop vectorization phase.  */
1226
1227 unsigned
1228 pass_vectorize::execute (function *fun)
1229 {
1230   unsigned int i;
1231   unsigned int num_vectorized_loops = 0;
1232   unsigned int vect_loops_num;
1233   hash_table<simduid_to_vf> *simduid_to_vf_htab = NULL;
1234   hash_table<simd_array_to_simduid> *simd_array_to_simduid_htab = NULL;
1235   bool any_ifcvt_loops = false;
1236   unsigned ret = 0;
1237
1238   vect_loops_num = number_of_loops (fun);
1239
1240   /* Bail out if there are no loops.  */
1241   if (vect_loops_num <= 1)
1242     return 0;
1243
1244   vect_slp_init ();
1245
1246   if (fun->has_simduid_loops)
1247     note_simd_array_uses (&simd_array_to_simduid_htab, fun);
1248
1249   /*  ----------- Analyze loops. -----------  */
1250
1251   /* If some loop was duplicated, it gets bigger number
1252      than all previously defined loops.  This fact allows us to run
1253      only over initial loops skipping newly generated ones.  */
1254   for (auto loop : loops_list (fun, 0))
1255     if (loop->dont_vectorize)
1256       {
1257         any_ifcvt_loops = true;
1258         /* If-conversion sometimes versions both the outer loop
1259            (for the case when outer loop vectorization might be
1260            desirable) as well as the inner loop in the scalar version
1261            of the loop.  So we have:
1262             if (LOOP_VECTORIZED (1, 3))
1263               {
1264                 loop1
1265                   loop2
1266               }
1267             else
1268               loop3 (copy of loop1)
1269                 if (LOOP_VECTORIZED (4, 5))
1270                   loop4 (copy of loop2)
1271                 else
1272                   loop5 (copy of loop4)
1273            If loops' iteration gives us loop3 first (which has
1274            dont_vectorize set), make sure to process loop1 before loop4;
1275            so that we can prevent vectorization of loop4 if loop1
1276            is successfully vectorized.  */
1277         if (loop->inner)
1278           {
1279             gimple *loop_vectorized_call
1280               = vect_loop_vectorized_call (loop);
1281             if (loop_vectorized_call
1282                 && vect_loop_vectorized_call (loop->inner))
1283               {
1284                 tree arg = gimple_call_arg (loop_vectorized_call, 0);
1285                 class loop *vector_loop
1286                   = get_loop (fun, tree_to_shwi (arg));
1287                 if (vector_loop && vector_loop != loop)
1288                   {
1289                     /* Make sure we don't vectorize it twice.  */
1290                     vector_loop->dont_vectorize = true;
1291                     ret |= try_vectorize_loop (simduid_to_vf_htab,
1292                                                &num_vectorized_loops,
1293                                                vector_loop, fun);
1294                   }
1295               }
1296           }
1297       }
1298     else
1299       ret |= try_vectorize_loop (simduid_to_vf_htab, &num_vectorized_loops,
1300                                  loop, fun);
1301
1302   vect_location = dump_user_location_t ();
1303
1304   statistics_counter_event (fun, "Vectorized loops", num_vectorized_loops);
1305   if (dump_enabled_p ()
1306       || (num_vectorized_loops > 0 && dump_enabled_p ()))
1307     dump_printf_loc (MSG_NOTE, vect_location,
1308                      "vectorized %u loops in function.\n",
1309                      num_vectorized_loops);
1310
1311   /*  ----------- Finalize. -----------  */
1312
1313   if (any_ifcvt_loops)
1314     for (i = 1; i < number_of_loops (fun); i++)
1315       {
1316         class loop *loop = get_loop (fun, i);
1317         if (loop && loop->dont_vectorize)
1318           {
1319             gimple *g = vect_loop_vectorized_call (loop);
1320             if (g)
1321               {
1322                 fold_loop_internal_call (g, boolean_false_node);
1323                 ret |= TODO_cleanup_cfg;
1324                 g = NULL;
1325               }
1326             else
1327               g = vect_loop_dist_alias_call (loop, fun);
1328
1329             if (g)
1330               {
1331                 fold_loop_internal_call (g, boolean_false_node);
1332                 ret |= TODO_cleanup_cfg;
1333               }
1334           }
1335       }
1336
1337   /* Fold IFN_GOMP_SIMD_{VF,LANE,LAST_LANE,ORDERED_{START,END}} builtins.  */
1338   if (fun->has_simduid_loops)
1339     {
1340       adjust_simduid_builtins (simduid_to_vf_htab, fun);
1341       /* Avoid stale SCEV cache entries for the SIMD_LANE defs.  */
1342       scev_reset ();
1343     }
1344   /* Shrink any "omp array simd" temporary arrays to the
1345      actual vectorization factors.  */
1346   if (simd_array_to_simduid_htab)
1347     shrink_simd_arrays (simd_array_to_simduid_htab, simduid_to_vf_htab);
1348   delete simduid_to_vf_htab;
1349   fun->has_simduid_loops = false;
1350
1351   if (num_vectorized_loops > 0)
1352     {
1353       /* We are collecting some corner cases where we need to update
1354          virtual SSA form via the TODO but delete the queued update-SSA
1355          state.  Force renaming if we think that might be necessary.  */
1356       if (ret & TODO_update_ssa_only_virtuals)
1357         mark_virtual_operands_for_renaming (cfun);
1358       /* If we vectorized any loop only virtual SSA form needs to be updated.
1359          ???  Also while we try hard to update loop-closed SSA form we fail
1360          to properly do this in some corner-cases (see PR56286).  */
1361       rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa_only_virtuals);
1362       ret |= TODO_cleanup_cfg;
1363     }
1364
1365   for (i = 1; i < number_of_loops (fun); i++)
1366     {
1367       loop_vec_info loop_vinfo;
1368       bool has_mask_store;
1369
1370       class loop *loop = get_loop (fun, i);
1371       if (!loop || !loop->aux)
1372         continue;
1373       loop_vinfo = (loop_vec_info) loop->aux;
1374       has_mask_store = LOOP_VINFO_HAS_MASK_STORE (loop_vinfo);
1375       delete loop_vinfo;
1376       if (has_mask_store
1377           && targetm.vectorize.empty_mask_is_expensive (IFN_MASK_STORE))
1378         optimize_mask_stores (loop);
1379
1380       auto_bitmap exit_bbs;
1381       /* Perform local CSE, this esp. helps because we emit code for
1382          predicates that need to be shared for optimal predicate usage.
1383          However reassoc will re-order them and prevent CSE from working
1384          as it should.  CSE only the loop body, not the entry.  */
1385       bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index);
1386
1387       edge entry = EDGE_PRED (loop_preheader_edge (loop)->src, 0);
1388       do_rpo_vn (fun, entry, exit_bbs);
1389
1390       loop->aux = NULL;
1391     }
1392
1393   vect_slp_fini ();
1394
1395   return ret;
1396 }
1397
1398 } // anon namespace
1399
1400 gimple_opt_pass *
1401 make_pass_vectorize (gcc::context *ctxt)
1402 {
1403   return new pass_vectorize (ctxt);
1404 }
1405
1406 /* Entry point to the simduid cleanup pass.  */
1407
1408 namespace {
1409
1410 const pass_data pass_data_simduid_cleanup =
1411 {
1412   GIMPLE_PASS, /* type */
1413   "simduid", /* name */
1414   OPTGROUP_NONE, /* optinfo_flags */
1415   TV_NONE, /* tv_id */
1416   ( PROP_ssa | PROP_cfg ), /* properties_required */
1417   0, /* properties_provided */
1418   0, /* properties_destroyed */
1419   0, /* todo_flags_start */
1420   0, /* todo_flags_finish */
1421 };
1422
1423 class pass_simduid_cleanup : public gimple_opt_pass
1424 {
1425 public:
1426   pass_simduid_cleanup (gcc::context *ctxt)
1427     : gimple_opt_pass (pass_data_simduid_cleanup, ctxt)
1428   {}
1429
1430   /* opt_pass methods: */
1431   opt_pass * clone () final override
1432   {
1433     return new pass_simduid_cleanup (m_ctxt);
1434   }
1435   bool gate (function *fun) final override { return fun->has_simduid_loops; }
1436   unsigned int execute (function *) final override;
1437
1438 }; // class pass_simduid_cleanup
1439
1440 unsigned int
1441 pass_simduid_cleanup::execute (function *fun)
1442 {
1443   hash_table<simd_array_to_simduid> *simd_array_to_simduid_htab = NULL;
1444
1445   note_simd_array_uses (&simd_array_to_simduid_htab, fun);
1446
1447   /* Fold IFN_GOMP_SIMD_{VF,LANE,LAST_LANE,ORDERED_{START,END}} builtins.  */
1448   adjust_simduid_builtins (NULL, fun);
1449
1450   /* Shrink any "omp array simd" temporary arrays to the
1451      actual vectorization factors.  */
1452   if (simd_array_to_simduid_htab)
1453     shrink_simd_arrays (simd_array_to_simduid_htab, NULL);
1454   fun->has_simduid_loops = false;
1455   return 0;
1456 }
1457
1458 }  // anon namespace
1459
1460 gimple_opt_pass *
1461 make_pass_simduid_cleanup (gcc::context *ctxt)
1462 {
1463   return new pass_simduid_cleanup (ctxt);
1464 }
1465
1466
1467 /*  Entry point to basic block SLP phase.  */
1468
1469 namespace {
1470
1471 const pass_data pass_data_slp_vectorize =
1472 {
1473   GIMPLE_PASS, /* type */
1474   "slp", /* name */
1475   OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
1476   TV_TREE_SLP_VECTORIZATION, /* tv_id */
1477   ( PROP_ssa | PROP_cfg ), /* properties_required */
1478   0, /* properties_provided */
1479   0, /* properties_destroyed */
1480   0, /* todo_flags_start */
1481   TODO_update_ssa, /* todo_flags_finish */
1482 };
1483
1484 class pass_slp_vectorize : public gimple_opt_pass
1485 {
1486 public:
1487   pass_slp_vectorize (gcc::context *ctxt)
1488     : gimple_opt_pass (pass_data_slp_vectorize, ctxt)
1489   {}
1490
1491   /* opt_pass methods: */
1492   opt_pass * clone () final override { return new pass_slp_vectorize (m_ctxt); }
1493   bool gate (function *) final override { return flag_tree_slp_vectorize != 0; }
1494   unsigned int execute (function *) final override;
1495
1496 }; // class pass_slp_vectorize
1497
1498 unsigned int
1499 pass_slp_vectorize::execute (function *fun)
1500 {
1501   auto_purge_vect_location sentinel;
1502   basic_block bb;
1503
1504   bool in_loop_pipeline = scev_initialized_p ();
1505   if (!in_loop_pipeline)
1506     {
1507       loop_optimizer_init (LOOPS_NORMAL);
1508       scev_initialize ();
1509     }
1510
1511   /* Mark all stmts as not belonging to the current region and unvisited.  */
1512   FOR_EACH_BB_FN (bb, fun)
1513     {
1514       for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
1515            gsi_next (&gsi))
1516         {
1517           gphi *stmt = gsi.phi ();
1518           gimple_set_uid (stmt, -1);
1519           gimple_set_visited (stmt, false);
1520         }
1521       for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
1522            gsi_next (&gsi))
1523         {
1524           gimple *stmt = gsi_stmt (gsi);
1525           gimple_set_uid (stmt, -1);
1526           gimple_set_visited (stmt, false);
1527         }
1528     }
1529
1530   vect_slp_init ();
1531
1532   vect_slp_function (fun);
1533
1534   vect_slp_fini ();
1535
1536   if (!in_loop_pipeline)
1537     {
1538       scev_finalize ();
1539       loop_optimizer_finalize ();
1540     }
1541
1542   return 0;
1543 }
1544
1545 } // anon namespace
1546
1547 gimple_opt_pass *
1548 make_pass_slp_vectorize (gcc::context *ctxt)
1549 {
1550   return new pass_slp_vectorize (ctxt);
1551 }
1552
1553
1554 /* Increase alignment of global arrays to improve vectorization potential.
1555    TODO:
1556    - Consider also structs that have an array field.
1557    - Use ipa analysis to prune arrays that can't be vectorized?
1558      This should involve global alignment analysis and in the future also
1559      array padding.  */
1560
1561 static unsigned get_vec_alignment_for_type (tree);
1562 static hash_map<tree, unsigned> *type_align_map;
1563
1564 /* Return alignment of array's vector type corresponding to scalar type.
1565    0 if no vector type exists.  */
1566 static unsigned
1567 get_vec_alignment_for_array_type (tree type) 
1568 {
1569   gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1570   poly_uint64 array_size, vector_size;
1571
1572   tree scalar_type = strip_array_types (type);
1573   tree vectype = get_related_vectype_for_scalar_type (VOIDmode, scalar_type);
1574   if (!vectype
1575       || !poly_int_tree_p (TYPE_SIZE (type), &array_size)
1576       || !poly_int_tree_p (TYPE_SIZE (vectype), &vector_size)
1577       || maybe_lt (array_size, vector_size))
1578     return 0;
1579
1580   return TYPE_ALIGN (vectype);
1581 }
1582
1583 /* Return alignment of field having maximum alignment of vector type
1584    corresponding to it's scalar type. For now, we only consider fields whose
1585    offset is a multiple of it's vector alignment.
1586    0 if no suitable field is found.  */
1587 static unsigned
1588 get_vec_alignment_for_record_type (tree type) 
1589 {
1590   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
1591
1592   unsigned max_align = 0, alignment;
1593   HOST_WIDE_INT offset;
1594   tree offset_tree;
1595
1596   if (TYPE_PACKED (type))
1597     return 0;
1598
1599   unsigned *slot = type_align_map->get (type);
1600   if (slot)
1601     return *slot;
1602
1603   for (tree field = first_field (type);
1604        field != NULL_TREE;
1605        field = DECL_CHAIN (field))
1606     {
1607       /* Skip if not FIELD_DECL or if alignment is set by user.  */ 
1608       if (TREE_CODE (field) != FIELD_DECL
1609           || DECL_USER_ALIGN (field)
1610           || DECL_ARTIFICIAL (field))
1611         continue;
1612
1613       /* We don't need to process the type further if offset is variable,
1614          since the offsets of remaining members will also be variable.  */
1615       if (TREE_CODE (DECL_FIELD_OFFSET (field)) != INTEGER_CST
1616           || TREE_CODE (DECL_FIELD_BIT_OFFSET (field)) != INTEGER_CST)
1617         break;
1618
1619       /* Similarly stop processing the type if offset_tree
1620          does not fit in unsigned HOST_WIDE_INT.  */
1621       offset_tree = bit_position (field);
1622       if (!tree_fits_uhwi_p (offset_tree))
1623         break;
1624
1625       offset = tree_to_uhwi (offset_tree); 
1626       alignment = get_vec_alignment_for_type (TREE_TYPE (field));
1627
1628       /* Get maximum alignment of vectorized field/array among those members
1629          whose offset is multiple of the vector alignment.  */ 
1630       if (alignment
1631           && (offset % alignment == 0)
1632           && (alignment > max_align))
1633         max_align = alignment;
1634     }
1635
1636   type_align_map->put (type, max_align);
1637   return max_align;
1638 }
1639
1640 /* Return alignment of vector type corresponding to decl's scalar type
1641    or 0 if it doesn't exist or the vector alignment is lesser than
1642    decl's alignment.  */
1643 static unsigned
1644 get_vec_alignment_for_type (tree type)
1645 {
1646   if (type == NULL_TREE)
1647     return 0;
1648
1649   gcc_assert (TYPE_P (type));
1650
1651   static unsigned alignment = 0;
1652   switch (TREE_CODE (type))
1653     {
1654       case ARRAY_TYPE:
1655         alignment = get_vec_alignment_for_array_type (type);
1656         break;
1657       case RECORD_TYPE:
1658         alignment = get_vec_alignment_for_record_type (type);
1659         break;
1660       default:
1661         alignment = 0;
1662         break;
1663     }
1664
1665   return (alignment > TYPE_ALIGN (type)) ? alignment : 0;
1666 }
1667
1668 /* Entry point to increase_alignment pass.  */
1669 static unsigned int
1670 increase_alignment (void)
1671 {
1672   varpool_node *vnode;
1673
1674   vect_location = dump_user_location_t ();
1675   type_align_map = new hash_map<tree, unsigned>;
1676
1677   /* Increase the alignment of all global arrays for vectorization.  */
1678   FOR_EACH_DEFINED_VARIABLE (vnode)
1679     {
1680       tree decl = vnode->decl;
1681       unsigned int alignment;
1682
1683       if ((decl_in_symtab_p (decl)
1684           && !symtab_node::get (decl)->can_increase_alignment_p ())
1685           || DECL_USER_ALIGN (decl) || DECL_ARTIFICIAL (decl))
1686         continue;
1687
1688       alignment = get_vec_alignment_for_type (TREE_TYPE (decl));
1689       if (alignment && vect_can_force_dr_alignment_p (decl, alignment))
1690         {
1691           vnode->increase_alignment (alignment);
1692           if (dump_enabled_p ())
1693             dump_printf (MSG_NOTE, "Increasing alignment of decl: %T\n", decl);
1694         }
1695     }
1696
1697   delete type_align_map;
1698   return 0;
1699 }
1700
1701
1702 namespace {
1703
1704 const pass_data pass_data_ipa_increase_alignment =
1705 {
1706   SIMPLE_IPA_PASS, /* type */
1707   "increase_alignment", /* name */
1708   OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
1709   TV_IPA_OPT, /* tv_id */
1710   0, /* properties_required */
1711   0, /* properties_provided */
1712   0, /* properties_destroyed */
1713   0, /* todo_flags_start */
1714   0, /* todo_flags_finish */
1715 };
1716
1717 class pass_ipa_increase_alignment : public simple_ipa_opt_pass
1718 {
1719 public:
1720   pass_ipa_increase_alignment (gcc::context *ctxt)
1721     : simple_ipa_opt_pass (pass_data_ipa_increase_alignment, ctxt)
1722   {}
1723
1724   /* opt_pass methods: */
1725   bool gate (function *) final override
1726     {
1727       return flag_section_anchors && flag_tree_loop_vectorize;
1728     }
1729
1730   unsigned int execute (function *) final override
1731   {
1732     return increase_alignment ();
1733   }
1734
1735 }; // class pass_ipa_increase_alignment
1736
1737 } // anon namespace
1738
1739 simple_ipa_opt_pass *
1740 make_pass_ipa_increase_alignment (gcc::context *ctxt)
1741 {
1742   return new pass_ipa_increase_alignment (ctxt);
1743 }
1744
1745 /* If the condition represented by T is a comparison or the SSA name
1746    result of a comparison, extract the comparison's operands.  Represent
1747    T as NE_EXPR <T, 0> otherwise.  */
1748
1749 void
1750 scalar_cond_masked_key::get_cond_ops_from_tree (tree t)
1751 {
1752   if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_comparison)
1753     {
1754       this->code = TREE_CODE (t);
1755       this->op0 = TREE_OPERAND (t, 0);
1756       this->op1 = TREE_OPERAND (t, 1);
1757       this->inverted_p = false;
1758       return;
1759     }
1760
1761   if (TREE_CODE (t) == SSA_NAME)
1762     if (gassign *stmt = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (t)))
1763       {
1764         tree_code code = gimple_assign_rhs_code (stmt);
1765         if (TREE_CODE_CLASS (code) == tcc_comparison)
1766           {
1767             this->code = code;
1768             this->op0 = gimple_assign_rhs1 (stmt);
1769             this->op1 = gimple_assign_rhs2 (stmt);
1770             this->inverted_p = false;
1771             return;
1772           }
1773         else if (code == BIT_NOT_EXPR)
1774           {
1775             tree n_op = gimple_assign_rhs1 (stmt);
1776             if ((stmt = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (n_op))))
1777               {
1778                 code = gimple_assign_rhs_code (stmt);
1779                 if (TREE_CODE_CLASS (code) == tcc_comparison)
1780                   {
1781                     this->code = code;
1782                     this->op0 = gimple_assign_rhs1 (stmt);
1783                     this->op1 = gimple_assign_rhs2 (stmt);
1784                     this->inverted_p = true;
1785                     return;
1786                   }
1787               }
1788           }
1789       }
1790
1791   this->code = NE_EXPR;
1792   this->op0 = t;
1793   this->op1 = build_zero_cst (TREE_TYPE (t));
1794   this->inverted_p = false;
1795 }
1796
1797 /* See the comment above the declaration for details.  */
1798
1799 unsigned int
1800 vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
1801                              stmt_vec_info stmt_info, slp_tree,
1802                              tree vectype, int misalign,
1803                              vect_cost_model_location where)
1804 {
1805   unsigned int cost
1806     = builtin_vectorization_cost (kind, vectype, misalign) * count;
1807   return record_stmt_cost (stmt_info, where, cost);
1808 }
1809
1810 /* See the comment above the declaration for details.  */
1811
1812 void
1813 vector_costs::finish_cost (const vector_costs *)
1814 {
1815   gcc_assert (!m_finished);
1816   m_finished = true;
1817 }
1818
1819 /* Record a base cost of COST units against WHERE.  If STMT_INFO is
1820    nonnull, use it to adjust the cost based on execution frequency
1821    (where appropriate).  */
1822
1823 unsigned int
1824 vector_costs::record_stmt_cost (stmt_vec_info stmt_info,
1825                                 vect_cost_model_location where,
1826                                 unsigned int cost)
1827 {
1828   cost = adjust_cost_for_freq (stmt_info, where, cost);
1829   m_costs[where] += cost;
1830   return cost;
1831 }
1832
1833 /* COST is the base cost we have calculated for an operation in location WHERE.
1834    If STMT_INFO is nonnull, use it to adjust the cost based on execution
1835    frequency (where appropriate).  Return the adjusted cost.  */
1836
1837 unsigned int
1838 vector_costs::adjust_cost_for_freq (stmt_vec_info stmt_info,
1839                                     vect_cost_model_location where,
1840                                     unsigned int cost)
1841 {
1842   /* Statements in an inner loop relative to the loop being
1843      vectorized are weighted more heavily.  The value here is
1844      arbitrary and could potentially be improved with analysis.  */
1845   if (where == vect_body
1846       && stmt_info
1847       && stmt_in_inner_loop_p (m_vinfo, stmt_info))
1848     {
1849       loop_vec_info loop_vinfo = as_a<loop_vec_info> (m_vinfo);
1850       cost *= LOOP_VINFO_INNER_LOOP_COST_FACTOR (loop_vinfo);
1851     }
1852   return cost;
1853 }
1854
1855 /* See the comment above the declaration for details.  */
1856
1857 bool
1858 vector_costs::better_main_loop_than_p (const vector_costs *other) const
1859 {
1860   int diff = compare_inside_loop_cost (other);
1861   if (diff != 0)
1862     return diff < 0;
1863
1864   /* If there's nothing to choose between the loop bodies, see whether
1865      there's a difference in the prologue and epilogue costs.  */
1866   diff = compare_outside_loop_cost (other);
1867   if (diff != 0)
1868     return diff < 0;
1869
1870   return false;
1871 }
1872
1873
1874 /* See the comment above the declaration for details.  */
1875
1876 bool
1877 vector_costs::better_epilogue_loop_than_p (const vector_costs *other,
1878                                            loop_vec_info main_loop) const
1879 {
1880   loop_vec_info this_loop_vinfo = as_a<loop_vec_info> (this->m_vinfo);
1881   loop_vec_info other_loop_vinfo = as_a<loop_vec_info> (other->m_vinfo);
1882
1883   poly_int64 this_vf = LOOP_VINFO_VECT_FACTOR (this_loop_vinfo);
1884   poly_int64 other_vf = LOOP_VINFO_VECT_FACTOR (other_loop_vinfo);
1885
1886   poly_uint64 main_poly_vf = LOOP_VINFO_VECT_FACTOR (main_loop);
1887   unsigned HOST_WIDE_INT main_vf;
1888   unsigned HOST_WIDE_INT other_factor, this_factor, other_cost, this_cost;
1889   /* If we can determine how many iterations are left for the epilogue
1890      loop, that is if both the main loop's vectorization factor and number
1891      of iterations are constant, then we use them to calculate the cost of
1892      the epilogue loop together with a 'likely value' for the epilogues
1893      vectorization factor.  Otherwise we use the main loop's vectorization
1894      factor and the maximum poly value for the epilogue's.  If the target
1895      has not provided with a sensible upper bound poly vectorization
1896      factors are likely to be favored over constant ones.  */
1897   if (main_poly_vf.is_constant (&main_vf)
1898       && LOOP_VINFO_NITERS_KNOWN_P (main_loop))
1899     {
1900       unsigned HOST_WIDE_INT niters
1901         = LOOP_VINFO_INT_NITERS (main_loop) % main_vf;
1902       HOST_WIDE_INT other_likely_vf
1903         = estimated_poly_value (other_vf, POLY_VALUE_LIKELY);
1904       HOST_WIDE_INT this_likely_vf
1905         = estimated_poly_value (this_vf, POLY_VALUE_LIKELY);
1906
1907       /* If the epilogue is using partial vectors we account for the
1908          partial iteration here too.  */
1909       other_factor = niters / other_likely_vf;
1910       if (LOOP_VINFO_USING_PARTIAL_VECTORS_P (other_loop_vinfo)
1911           && niters % other_likely_vf != 0)
1912         other_factor++;
1913
1914       this_factor = niters / this_likely_vf;
1915       if (LOOP_VINFO_USING_PARTIAL_VECTORS_P (this_loop_vinfo)
1916           && niters % this_likely_vf != 0)
1917         this_factor++;
1918     }
1919   else
1920     {
1921       unsigned HOST_WIDE_INT main_vf_max
1922         = estimated_poly_value (main_poly_vf, POLY_VALUE_MAX);
1923       unsigned HOST_WIDE_INT other_vf_max
1924         = estimated_poly_value (other_vf, POLY_VALUE_MAX);
1925       unsigned HOST_WIDE_INT this_vf_max
1926         = estimated_poly_value (this_vf, POLY_VALUE_MAX);
1927
1928       other_factor = CEIL (main_vf_max, other_vf_max);
1929       this_factor = CEIL (main_vf_max, this_vf_max);
1930
1931       /* If the loop is not using partial vectors then it will iterate one
1932          time less than one that does.  It is safe to subtract one here,
1933          because the main loop's vf is always at least 2x bigger than that
1934          of an epilogue.  */
1935       if (!LOOP_VINFO_USING_PARTIAL_VECTORS_P (other_loop_vinfo))
1936         other_factor -= 1;
1937       if (!LOOP_VINFO_USING_PARTIAL_VECTORS_P (this_loop_vinfo))
1938         this_factor -= 1;
1939     }
1940
1941   /* Compute the costs by multiplying the inside costs with the factor and
1942      add the outside costs for a more complete picture.  The factor is the
1943      amount of times we are expecting to iterate this epilogue.  */
1944   other_cost = other->body_cost () * other_factor;
1945   this_cost = this->body_cost () * this_factor;
1946   other_cost += other->outside_cost ();
1947   this_cost += this->outside_cost ();
1948   return this_cost < other_cost;
1949 }
1950
1951 /* A <=>-style subroutine of better_main_loop_than_p.  Check whether we can
1952    determine the return value of better_main_loop_than_p by comparing the
1953    inside (loop body) costs of THIS and OTHER.  Return:
1954
1955    * -1 if better_main_loop_than_p should return true.
1956    * 1 if better_main_loop_than_p should return false.
1957    * 0 if we can't decide.  */
1958
1959 int
1960 vector_costs::compare_inside_loop_cost (const vector_costs *other) const
1961 {
1962   loop_vec_info this_loop_vinfo = as_a<loop_vec_info> (this->m_vinfo);
1963   loop_vec_info other_loop_vinfo = as_a<loop_vec_info> (other->m_vinfo);
1964
1965   struct loop *loop = LOOP_VINFO_LOOP (this_loop_vinfo);
1966   gcc_assert (LOOP_VINFO_LOOP (other_loop_vinfo) == loop);
1967
1968   poly_int64 this_vf = LOOP_VINFO_VECT_FACTOR (this_loop_vinfo);
1969   poly_int64 other_vf = LOOP_VINFO_VECT_FACTOR (other_loop_vinfo);
1970
1971   /* Limit the VFs to what is likely to be the maximum number of iterations,
1972      to handle cases in which at least one loop_vinfo is fully-masked.  */
1973   HOST_WIDE_INT estimated_max_niter = likely_max_stmt_executions_int (loop);
1974   if (estimated_max_niter != -1)
1975     {
1976       if (known_le (estimated_max_niter, this_vf))
1977         this_vf = estimated_max_niter;
1978       if (known_le (estimated_max_niter, other_vf))
1979         other_vf = estimated_max_niter;
1980     }
1981
1982   /* Check whether the (fractional) cost per scalar iteration is lower or
1983      higher: this_inside_cost / this_vf vs. other_inside_cost / other_vf.  */
1984   poly_int64 rel_this = this_loop_vinfo->vector_costs->body_cost () * other_vf;
1985   poly_int64 rel_other
1986     = other_loop_vinfo->vector_costs->body_cost () * this_vf;
1987
1988   HOST_WIDE_INT est_rel_this_min
1989     = estimated_poly_value (rel_this, POLY_VALUE_MIN);
1990   HOST_WIDE_INT est_rel_this_max
1991     = estimated_poly_value (rel_this, POLY_VALUE_MAX);
1992
1993   HOST_WIDE_INT est_rel_other_min
1994     = estimated_poly_value (rel_other, POLY_VALUE_MIN);
1995   HOST_WIDE_INT est_rel_other_max
1996     = estimated_poly_value (rel_other, POLY_VALUE_MAX);
1997
1998   /* Check first if we can make out an unambigous total order from the minimum
1999      and maximum estimates.  */
2000   if (est_rel_this_min < est_rel_other_min
2001       && est_rel_this_max < est_rel_other_max)
2002     return -1;
2003
2004   if (est_rel_other_min < est_rel_this_min
2005       && est_rel_other_max < est_rel_this_max)
2006     return 1;
2007
2008   /* When other_loop_vinfo uses a variable vectorization factor,
2009      we know that it has a lower cost for at least one runtime VF.
2010      However, we don't know how likely that VF is.
2011
2012      One option would be to compare the costs for the estimated VFs.
2013      The problem is that that can put too much pressure on the cost
2014      model.  E.g. if the estimated VF is also the lowest possible VF,
2015      and if other_loop_vinfo is 1 unit worse than this_loop_vinfo
2016      for the estimated VF, we'd then choose this_loop_vinfo even
2017      though (a) this_loop_vinfo might not actually be better than
2018      other_loop_vinfo for that VF and (b) it would be significantly
2019      worse at larger VFs.
2020
2021      Here we go for a hacky compromise: pick this_loop_vinfo if it is
2022      no more expensive than other_loop_vinfo even after doubling the
2023      estimated other_loop_vinfo VF.  For all but trivial loops, this
2024      ensures that we only pick this_loop_vinfo if it is significantly
2025      better than other_loop_vinfo at the estimated VF.  */
2026   if (est_rel_other_min != est_rel_this_min
2027       || est_rel_other_max != est_rel_this_max)
2028     {
2029       HOST_WIDE_INT est_rel_this_likely
2030         = estimated_poly_value (rel_this, POLY_VALUE_LIKELY);
2031       HOST_WIDE_INT est_rel_other_likely
2032         = estimated_poly_value (rel_other, POLY_VALUE_LIKELY);
2033
2034       return est_rel_this_likely * 2 <= est_rel_other_likely ? -1 : 1;
2035     }
2036
2037   return 0;
2038 }
2039
2040 /* A <=>-style subroutine of better_main_loop_than_p, used when there is
2041    nothing to choose between the inside (loop body) costs of THIS and OTHER.
2042    Check whether we can determine the return value of better_main_loop_than_p
2043    by comparing the outside (prologue and epilogue) costs of THIS and OTHER.
2044    Return:
2045
2046    * -1 if better_main_loop_than_p should return true.
2047    * 1 if better_main_loop_than_p should return false.
2048    * 0 if we can't decide.  */
2049
2050 int
2051 vector_costs::compare_outside_loop_cost (const vector_costs *other) const
2052 {
2053   auto this_outside_cost = this->outside_cost ();
2054   auto other_outside_cost = other->outside_cost ();
2055   if (this_outside_cost != other_outside_cost)
2056     return this_outside_cost < other_outside_cost ? -1 : 1;
2057
2058   return 0;
2059 }