LCOV - code coverage report
Current view: top level - gcc - tree-vectorizer.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 80.9 % 931 753
Test Date: 2024-12-21 13:15:12 Functions: 82.8 % 64 53
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.