Home | History | Annotate | Line # | Download | only in gcc
      1 /* Statement Analysis and Transformation for Vectorization
      2    Copyright (C) 2003-2022 Free Software Foundation, Inc.
      3    Contributed by Dorit Naishlos <dorit (at) il.ibm.com>
      4    and Ira Rosen <irar (at) il.ibm.com>
      5 
      6 This file is part of GCC.
      7 
      8 GCC is free software; you can redistribute it and/or modify it under
      9 the terms of the GNU General Public License as published by the Free
     10 Software Foundation; either version 3, or (at your option) any later
     11 version.
     12 
     13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16 for more details.
     17 
     18 You should have received a copy of the GNU General Public License
     19 along with GCC; see the file COPYING3.  If not see
     20 <http://www.gnu.org/licenses/>.  */
     21 
     22 #include "config.h"
     23 #include "system.h"
     24 #include "coretypes.h"
     25 #include "backend.h"
     26 #include "target.h"
     27 #include "rtl.h"
     28 #include "tree.h"
     29 #include "gimple.h"
     30 #include "ssa.h"
     31 #include "optabs-tree.h"
     32 #include "insn-config.h"
     33 #include "recog.h"		/* FIXME: for insn_data */
     34 #include "cgraph.h"
     35 #include "dumpfile.h"
     36 #include "alias.h"
     37 #include "fold-const.h"
     38 #include "stor-layout.h"
     39 #include "tree-eh.h"
     40 #include "gimplify.h"
     41 #include "gimple-iterator.h"
     42 #include "gimplify-me.h"
     43 #include "tree-cfg.h"
     44 #include "tree-ssa-loop-manip.h"
     45 #include "cfgloop.h"
     46 #include "explow.h"
     47 #include "tree-ssa-loop.h"
     48 #include "tree-scalar-evolution.h"
     49 #include "tree-vectorizer.h"
     50 #include "builtins.h"
     51 #include "internal-fn.h"
     52 #include "tree-vector-builder.h"
     53 #include "vec-perm-indices.h"
     54 #include "tree-ssa-loop-niter.h"
     55 #include "gimple-fold.h"
     56 #include "regs.h"
     57 #include "attribs.h"
     58 
     59 /* For lang_hooks.types.type_for_mode.  */
     60 #include "langhooks.h"
     61 
     62 /* Return the vectorized type for the given statement.  */
     63 
     64 tree
     65 stmt_vectype (class _stmt_vec_info *stmt_info)
     66 {
     67   return STMT_VINFO_VECTYPE (stmt_info);
     68 }
     69 
     70 /* Return TRUE iff the given statement is in an inner loop relative to
     71    the loop being vectorized.  */
     72 bool
     73 stmt_in_inner_loop_p (vec_info *vinfo, class _stmt_vec_info *stmt_info)
     74 {
     75   gimple *stmt = STMT_VINFO_STMT (stmt_info);
     76   basic_block bb = gimple_bb (stmt);
     77   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
     78   class loop* loop;
     79 
     80   if (!loop_vinfo)
     81     return false;
     82 
     83   loop = LOOP_VINFO_LOOP (loop_vinfo);
     84 
     85   return (bb->loop_father == loop->inner);
     86 }
     87 
     88 /* Record the cost of a statement, either by directly informing the
     89    target model or by saving it in a vector for later processing.
     90    Return a preliminary estimate of the statement's cost.  */
     91 
     92 static unsigned
     93 record_stmt_cost (stmt_vector_for_cost *body_cost_vec, int count,
     94 		  enum vect_cost_for_stmt kind,
     95 		  stmt_vec_info stmt_info, slp_tree node,
     96 		  tree vectype, int misalign,
     97 		  enum vect_cost_model_location where)
     98 {
     99   if ((kind == vector_load || kind == unaligned_load)
    100       && (stmt_info && STMT_VINFO_GATHER_SCATTER_P (stmt_info)))
    101     kind = vector_gather_load;
    102   if ((kind == vector_store || kind == unaligned_store)
    103       && (stmt_info && STMT_VINFO_GATHER_SCATTER_P (stmt_info)))
    104     kind = vector_scatter_store;
    105 
    106   stmt_info_for_cost si
    107     = { count, kind, where, stmt_info, node, vectype, misalign };
    108   body_cost_vec->safe_push (si);
    109 
    110   return (unsigned)
    111       (builtin_vectorization_cost (kind, vectype, misalign) * count);
    112 }
    113 
    114 unsigned
    115 record_stmt_cost (stmt_vector_for_cost *body_cost_vec, int count,
    116 		  enum vect_cost_for_stmt kind, stmt_vec_info stmt_info,
    117 		  tree vectype, int misalign,
    118 		  enum vect_cost_model_location where)
    119 {
    120   return record_stmt_cost (body_cost_vec, count, kind, stmt_info, NULL,
    121 			   vectype, misalign, where);
    122 }
    123 
    124 unsigned
    125 record_stmt_cost (stmt_vector_for_cost *body_cost_vec, int count,
    126 		  enum vect_cost_for_stmt kind, slp_tree node,
    127 		  tree vectype, int misalign,
    128 		  enum vect_cost_model_location where)
    129 {
    130   return record_stmt_cost (body_cost_vec, count, kind, NULL, node,
    131 			   vectype, misalign, where);
    132 }
    133 
    134 unsigned
    135 record_stmt_cost (stmt_vector_for_cost *body_cost_vec, int count,
    136 		  enum vect_cost_for_stmt kind,
    137 		  enum vect_cost_model_location where)
    138 {
    139   gcc_assert (kind == cond_branch_taken || kind == cond_branch_not_taken
    140 	      || kind == scalar_stmt);
    141   return record_stmt_cost (body_cost_vec, count, kind, NULL, NULL,
    142 			   NULL_TREE, 0, where);
    143 }
    144 
    145 /* Return a variable of type ELEM_TYPE[NELEMS].  */
    146 
    147 static tree
    148 create_vector_array (tree elem_type, unsigned HOST_WIDE_INT nelems)
    149 {
    150   return create_tmp_var (build_array_type_nelts (elem_type, nelems),
    151 			 "vect_array");
    152 }
    153 
    154 /* ARRAY is an array of vectors created by create_vector_array.
    155    Return an SSA_NAME for the vector in index N.  The reference
    156    is part of the vectorization of STMT_INFO and the vector is associated
    157    with scalar destination SCALAR_DEST.  */
    158 
    159 static tree
    160 read_vector_array (vec_info *vinfo,
    161 		   stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
    162 		   tree scalar_dest, tree array, unsigned HOST_WIDE_INT n)
    163 {
    164   tree vect_type, vect, vect_name, array_ref;
    165   gimple *new_stmt;
    166 
    167   gcc_assert (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE);
    168   vect_type = TREE_TYPE (TREE_TYPE (array));
    169   vect = vect_create_destination_var (scalar_dest, vect_type);
    170   array_ref = build4 (ARRAY_REF, vect_type, array,
    171 		      build_int_cst (size_type_node, n),
    172 		      NULL_TREE, NULL_TREE);
    173 
    174   new_stmt = gimple_build_assign (vect, array_ref);
    175   vect_name = make_ssa_name (vect, new_stmt);
    176   gimple_assign_set_lhs (new_stmt, vect_name);
    177   vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
    178 
    179   return vect_name;
    180 }
    181 
    182 /* ARRAY is an array of vectors created by create_vector_array.
    183    Emit code to store SSA_NAME VECT in index N of the array.
    184    The store is part of the vectorization of STMT_INFO.  */
    185 
    186 static void
    187 write_vector_array (vec_info *vinfo,
    188 		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
    189 		    tree vect, tree array, unsigned HOST_WIDE_INT n)
    190 {
    191   tree array_ref;
    192   gimple *new_stmt;
    193 
    194   array_ref = build4 (ARRAY_REF, TREE_TYPE (vect), array,
    195 		      build_int_cst (size_type_node, n),
    196 		      NULL_TREE, NULL_TREE);
    197 
    198   new_stmt = gimple_build_assign (array_ref, vect);
    199   vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
    200 }
    201 
    202 /* PTR is a pointer to an array of type TYPE.  Return a representation
    203    of *PTR.  The memory reference replaces those in FIRST_DR
    204    (and its group).  */
    205 
    206 static tree
    207 create_array_ref (tree type, tree ptr, tree alias_ptr_type)
    208 {
    209   tree mem_ref;
    210 
    211   mem_ref = build2 (MEM_REF, type, ptr, build_int_cst (alias_ptr_type, 0));
    212   /* Arrays have the same alignment as their type.  */
    213   set_ptr_info_alignment (get_ptr_info (ptr), TYPE_ALIGN_UNIT (type), 0);
    214   return mem_ref;
    215 }
    216 
    217 /* Add a clobber of variable VAR to the vectorization of STMT_INFO.
    218    Emit the clobber before *GSI.  */
    219 
    220 static void
    221 vect_clobber_variable (vec_info *vinfo, stmt_vec_info stmt_info,
    222 		       gimple_stmt_iterator *gsi, tree var)
    223 {
    224   tree clobber = build_clobber (TREE_TYPE (var));
    225   gimple *new_stmt = gimple_build_assign (var, clobber);
    226   vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
    227 }
    228 
    229 /* Utility functions used by vect_mark_stmts_to_be_vectorized.  */
    230 
    231 /* Function vect_mark_relevant.
    232 
    233    Mark STMT_INFO as "relevant for vectorization" and add it to WORKLIST.  */
    234 
    235 static void
    236 vect_mark_relevant (vec<stmt_vec_info> *worklist, stmt_vec_info stmt_info,
    237 		    enum vect_relevant relevant, bool live_p)
    238 {
    239   enum vect_relevant save_relevant = STMT_VINFO_RELEVANT (stmt_info);
    240   bool save_live_p = STMT_VINFO_LIVE_P (stmt_info);
    241 
    242   if (dump_enabled_p ())
    243     dump_printf_loc (MSG_NOTE, vect_location,
    244 		     "mark relevant %d, live %d: %G", relevant, live_p,
    245 		     stmt_info->stmt);
    246 
    247   /* If this stmt is an original stmt in a pattern, we might need to mark its
    248      related pattern stmt instead of the original stmt.  However, such stmts
    249      may have their own uses that are not in any pattern, in such cases the
    250      stmt itself should be marked.  */
    251   if (STMT_VINFO_IN_PATTERN_P (stmt_info))
    252     {
    253       /* This is the last stmt in a sequence that was detected as a
    254 	 pattern that can potentially be vectorized.  Don't mark the stmt
    255 	 as relevant/live because it's not going to be vectorized.
    256 	 Instead mark the pattern-stmt that replaces it.  */
    257 
    258       if (dump_enabled_p ())
    259 	dump_printf_loc (MSG_NOTE, vect_location,
    260 			 "last stmt in pattern. don't mark"
    261 			 " relevant/live.\n");
    262       stmt_vec_info old_stmt_info = stmt_info;
    263       stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
    264       gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == old_stmt_info);
    265       save_relevant = STMT_VINFO_RELEVANT (stmt_info);
    266       save_live_p = STMT_VINFO_LIVE_P (stmt_info);
    267     }
    268 
    269   STMT_VINFO_LIVE_P (stmt_info) |= live_p;
    270   if (relevant > STMT_VINFO_RELEVANT (stmt_info))
    271     STMT_VINFO_RELEVANT (stmt_info) = relevant;
    272 
    273   if (STMT_VINFO_RELEVANT (stmt_info) == save_relevant
    274       && STMT_VINFO_LIVE_P (stmt_info) == save_live_p)
    275     {
    276       if (dump_enabled_p ())
    277         dump_printf_loc (MSG_NOTE, vect_location,
    278                          "already marked relevant/live.\n");
    279       return;
    280     }
    281 
    282   worklist->safe_push (stmt_info);
    283 }
    284 
    285 
    286 /* Function is_simple_and_all_uses_invariant
    287 
    288    Return true if STMT_INFO is simple and all uses of it are invariant.  */
    289 
    290 bool
    291 is_simple_and_all_uses_invariant (stmt_vec_info stmt_info,
    292 				  loop_vec_info loop_vinfo)
    293 {
    294   tree op;
    295   ssa_op_iter iter;
    296 
    297   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
    298   if (!stmt)
    299     return false;
    300 
    301   FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
    302     {
    303       enum vect_def_type dt = vect_uninitialized_def;
    304 
    305       if (!vect_is_simple_use (op, loop_vinfo, &dt))
    306 	{
    307 	  if (dump_enabled_p ())
    308 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
    309 			     "use not simple.\n");
    310 	  return false;
    311 	}
    312 
    313       if (dt != vect_external_def && dt != vect_constant_def)
    314 	return false;
    315     }
    316   return true;
    317 }
    318 
    319 /* Function vect_stmt_relevant_p.
    320 
    321    Return true if STMT_INFO, in the loop that is represented by LOOP_VINFO,
    322    is "relevant for vectorization".
    323 
    324    A stmt is considered "relevant for vectorization" if:
    325    - it has uses outside the loop.
    326    - it has vdefs (it alters memory).
    327    - control stmts in the loop (except for the exit condition).
    328 
    329    CHECKME: what other side effects would the vectorizer allow?  */
    330 
    331 static bool
    332 vect_stmt_relevant_p (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
    333 		      enum vect_relevant *relevant, bool *live_p)
    334 {
    335   class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    336   ssa_op_iter op_iter;
    337   imm_use_iterator imm_iter;
    338   use_operand_p use_p;
    339   def_operand_p def_p;
    340 
    341   *relevant = vect_unused_in_scope;
    342   *live_p = false;
    343 
    344   /* cond stmt other than loop exit cond.  */
    345   if (is_ctrl_stmt (stmt_info->stmt)
    346       && STMT_VINFO_TYPE (stmt_info) != loop_exit_ctrl_vec_info_type)
    347     *relevant = vect_used_in_scope;
    348 
    349   /* changing memory.  */
    350   if (gimple_code (stmt_info->stmt) != GIMPLE_PHI)
    351     if (gimple_vdef (stmt_info->stmt)
    352 	&& !gimple_clobber_p (stmt_info->stmt))
    353       {
    354 	if (dump_enabled_p ())
    355 	  dump_printf_loc (MSG_NOTE, vect_location,
    356                            "vec_stmt_relevant_p: stmt has vdefs.\n");
    357 	*relevant = vect_used_in_scope;
    358       }
    359 
    360   /* uses outside the loop.  */
    361   FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt_info->stmt, op_iter, SSA_OP_DEF)
    362     {
    363       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
    364 	{
    365 	  basic_block bb = gimple_bb (USE_STMT (use_p));
    366 	  if (!flow_bb_inside_loop_p (loop, bb))
    367 	    {
    368 	      if (is_gimple_debug (USE_STMT (use_p)))
    369 		continue;
    370 
    371 	      if (dump_enabled_p ())
    372 		dump_printf_loc (MSG_NOTE, vect_location,
    373                                  "vec_stmt_relevant_p: used out of loop.\n");
    374 
    375 	      /* We expect all such uses to be in the loop exit phis
    376 		 (because of loop closed form)   */
    377 	      gcc_assert (gimple_code (USE_STMT (use_p)) == GIMPLE_PHI);
    378 	      gcc_assert (bb == single_exit (loop)->dest);
    379 
    380               *live_p = true;
    381 	    }
    382 	}
    383     }
    384 
    385   if (*live_p && *relevant == vect_unused_in_scope
    386       && !is_simple_and_all_uses_invariant (stmt_info, loop_vinfo))
    387     {
    388       if (dump_enabled_p ())
    389 	dump_printf_loc (MSG_NOTE, vect_location,
    390 			 "vec_stmt_relevant_p: stmt live but not relevant.\n");
    391       *relevant = vect_used_only_live;
    392     }
    393 
    394   return (*live_p || *relevant);
    395 }
    396 
    397 
    398 /* Function exist_non_indexing_operands_for_use_p
    399 
    400    USE is one of the uses attached to STMT_INFO.  Check if USE is
    401    used in STMT_INFO for anything other than indexing an array.  */
    402 
    403 static bool
    404 exist_non_indexing_operands_for_use_p (tree use, stmt_vec_info stmt_info)
    405 {
    406   tree operand;
    407 
    408   /* USE corresponds to some operand in STMT.  If there is no data
    409      reference in STMT, then any operand that corresponds to USE
    410      is not indexing an array.  */
    411   if (!STMT_VINFO_DATA_REF (stmt_info))
    412     return true;
    413 
    414   /* STMT has a data_ref. FORNOW this means that its of one of
    415      the following forms:
    416      -1- ARRAY_REF = var
    417      -2- var = ARRAY_REF
    418      (This should have been verified in analyze_data_refs).
    419 
    420      'var' in the second case corresponds to a def, not a use,
    421      so USE cannot correspond to any operands that are not used
    422      for array indexing.
    423 
    424      Therefore, all we need to check is if STMT falls into the
    425      first case, and whether var corresponds to USE.  */
    426 
    427   gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
    428   if (!assign || !gimple_assign_copy_p (assign))
    429     {
    430       gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
    431       if (call && gimple_call_internal_p (call))
    432 	{
    433 	  internal_fn ifn = gimple_call_internal_fn (call);
    434 	  int mask_index = internal_fn_mask_index (ifn);
    435 	  if (mask_index >= 0
    436 	      && use == gimple_call_arg (call, mask_index))
    437 	    return true;
    438 	  int stored_value_index = internal_fn_stored_value_index (ifn);
    439 	  if (stored_value_index >= 0
    440 	      && use == gimple_call_arg (call, stored_value_index))
    441 	    return true;
    442 	  if (internal_gather_scatter_fn_p (ifn)
    443 	      && use == gimple_call_arg (call, 1))
    444 	    return true;
    445 	}
    446       return false;
    447     }
    448 
    449   if (TREE_CODE (gimple_assign_lhs (assign)) == SSA_NAME)
    450     return false;
    451   operand = gimple_assign_rhs1 (assign);
    452   if (TREE_CODE (operand) != SSA_NAME)
    453     return false;
    454 
    455   if (operand == use)
    456     return true;
    457 
    458   return false;
    459 }
    460 
    461 
    462 /*
    463    Function process_use.
    464 
    465    Inputs:
    466    - a USE in STMT_VINFO in a loop represented by LOOP_VINFO
    467    - RELEVANT - enum value to be set in the STMT_VINFO of the stmt
    468      that defined USE.  This is done by calling mark_relevant and passing it
    469      the WORKLIST (to add DEF_STMT to the WORKLIST in case it is relevant).
    470    - FORCE is true if exist_non_indexing_operands_for_use_p check shouldn't
    471      be performed.
    472 
    473    Outputs:
    474    Generally, LIVE_P and RELEVANT are used to define the liveness and
    475    relevance info of the DEF_STMT of this USE:
    476        STMT_VINFO_LIVE_P (DEF_stmt_vinfo) <-- live_p
    477        STMT_VINFO_RELEVANT (DEF_stmt_vinfo) <-- relevant
    478    Exceptions:
    479    - case 1: If USE is used only for address computations (e.g. array indexing),
    480    which does not need to be directly vectorized, then the liveness/relevance
    481    of the respective DEF_STMT is left unchanged.
    482    - case 2: If STMT_VINFO is a reduction phi and DEF_STMT is a reduction stmt,
    483    we skip DEF_STMT cause it had already been processed.
    484    - case 3: If DEF_STMT and STMT_VINFO are in different nests, then
    485    "relevant" will be modified accordingly.
    486 
    487    Return true if everything is as expected. Return false otherwise.  */
    488 
    489 static opt_result
    490 process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo,
    491 	     enum vect_relevant relevant, vec<stmt_vec_info> *worklist,
    492 	     bool force)
    493 {
    494   stmt_vec_info dstmt_vinfo;
    495   enum vect_def_type dt;
    496 
    497   /* case 1: we are only interested in uses that need to be vectorized.  Uses
    498      that are used for address computation are not considered relevant.  */
    499   if (!force && !exist_non_indexing_operands_for_use_p (use, stmt_vinfo))
    500     return opt_result::success ();
    501 
    502   if (!vect_is_simple_use (use, loop_vinfo, &dt, &dstmt_vinfo))
    503     return opt_result::failure_at (stmt_vinfo->stmt,
    504 				   "not vectorized:"
    505 				   " unsupported use in stmt.\n");
    506 
    507   if (!dstmt_vinfo)
    508     return opt_result::success ();
    509 
    510   basic_block def_bb = gimple_bb (dstmt_vinfo->stmt);
    511   basic_block bb = gimple_bb (stmt_vinfo->stmt);
    512 
    513   /* case 2: A reduction phi (STMT) defined by a reduction stmt (DSTMT_VINFO).
    514      We have to force the stmt live since the epilogue loop needs it to
    515      continue computing the reduction.  */
    516   if (gimple_code (stmt_vinfo->stmt) == GIMPLE_PHI
    517       && STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
    518       && gimple_code (dstmt_vinfo->stmt) != GIMPLE_PHI
    519       && STMT_VINFO_DEF_TYPE (dstmt_vinfo) == vect_reduction_def
    520       && bb->loop_father == def_bb->loop_father)
    521     {
    522       if (dump_enabled_p ())
    523 	dump_printf_loc (MSG_NOTE, vect_location,
    524 			 "reduc-stmt defining reduc-phi in the same nest.\n");
    525       vect_mark_relevant (worklist, dstmt_vinfo, relevant, true);
    526       return opt_result::success ();
    527     }
    528 
    529   /* case 3a: outer-loop stmt defining an inner-loop stmt:
    530 	outer-loop-header-bb:
    531 		d = dstmt_vinfo
    532 	inner-loop:
    533 		stmt # use (d)
    534 	outer-loop-tail-bb:
    535 		...		  */
    536   if (flow_loop_nested_p (def_bb->loop_father, bb->loop_father))
    537     {
    538       if (dump_enabled_p ())
    539 	dump_printf_loc (MSG_NOTE, vect_location,
    540                          "outer-loop def-stmt defining inner-loop stmt.\n");
    541 
    542       switch (relevant)
    543 	{
    544 	case vect_unused_in_scope:
    545 	  relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_nested_cycle) ?
    546 		      vect_used_in_scope : vect_unused_in_scope;
    547 	  break;
    548 
    549 	case vect_used_in_outer_by_reduction:
    550           gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def);
    551 	  relevant = vect_used_by_reduction;
    552 	  break;
    553 
    554 	case vect_used_in_outer:
    555           gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def);
    556 	  relevant = vect_used_in_scope;
    557 	  break;
    558 
    559 	case vect_used_in_scope:
    560 	  break;
    561 
    562 	default:
    563 	  gcc_unreachable ();
    564 	}
    565     }
    566 
    567   /* case 3b: inner-loop stmt defining an outer-loop stmt:
    568 	outer-loop-header-bb:
    569 		...
    570 	inner-loop:
    571 		d = dstmt_vinfo
    572 	outer-loop-tail-bb (or outer-loop-exit-bb in double reduction):
    573 		stmt # use (d)		*/
    574   else if (flow_loop_nested_p (bb->loop_father, def_bb->loop_father))
    575     {
    576       if (dump_enabled_p ())
    577 	dump_printf_loc (MSG_NOTE, vect_location,
    578                          "inner-loop def-stmt defining outer-loop stmt.\n");
    579 
    580       switch (relevant)
    581         {
    582         case vect_unused_in_scope:
    583           relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
    584             || STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_double_reduction_def) ?
    585                       vect_used_in_outer_by_reduction : vect_unused_in_scope;
    586           break;
    587 
    588         case vect_used_by_reduction:
    589 	case vect_used_only_live:
    590           relevant = vect_used_in_outer_by_reduction;
    591           break;
    592 
    593         case vect_used_in_scope:
    594           relevant = vect_used_in_outer;
    595           break;
    596 
    597         default:
    598           gcc_unreachable ();
    599         }
    600     }
    601   /* We are also not interested in uses on loop PHI backedges that are
    602      inductions.  Otherwise we'll needlessly vectorize the IV increment
    603      and cause hybrid SLP for SLP inductions.  Unless the PHI is live
    604      of course.  */
    605   else if (gimple_code (stmt_vinfo->stmt) == GIMPLE_PHI
    606 	   && STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_induction_def
    607 	   && ! STMT_VINFO_LIVE_P (stmt_vinfo)
    608 	   && (PHI_ARG_DEF_FROM_EDGE (stmt_vinfo->stmt,
    609 				      loop_latch_edge (bb->loop_father))
    610 	       == use))
    611     {
    612       if (dump_enabled_p ())
    613 	dump_printf_loc (MSG_NOTE, vect_location,
    614                          "induction value on backedge.\n");
    615       return opt_result::success ();
    616     }
    617 
    618 
    619   vect_mark_relevant (worklist, dstmt_vinfo, relevant, false);
    620   return opt_result::success ();
    621 }
    622 
    623 
    624 /* Function vect_mark_stmts_to_be_vectorized.
    625 
    626    Not all stmts in the loop need to be vectorized. For example:
    627 
    628      for i...
    629        for j...
    630    1.    T0 = i + j
    631    2.	 T1 = a[T0]
    632 
    633    3.    j = j + 1
    634 
    635    Stmt 1 and 3 do not need to be vectorized, because loop control and
    636    addressing of vectorized data-refs are handled differently.
    637 
    638    This pass detects such stmts.  */
    639 
    640 opt_result
    641 vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo, bool *fatal)
    642 {
    643   class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    644   basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
    645   unsigned int nbbs = loop->num_nodes;
    646   gimple_stmt_iterator si;
    647   unsigned int i;
    648   basic_block bb;
    649   bool live_p;
    650   enum vect_relevant relevant;
    651 
    652   DUMP_VECT_SCOPE ("vect_mark_stmts_to_be_vectorized");
    653 
    654   auto_vec<stmt_vec_info, 64> worklist;
    655 
    656   /* 1. Init worklist.  */
    657   for (i = 0; i < nbbs; i++)
    658     {
    659       bb = bbs[i];
    660       for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
    661 	{
    662 	  stmt_vec_info phi_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
    663 	  if (dump_enabled_p ())
    664 	    dump_printf_loc (MSG_NOTE, vect_location, "init: phi relevant? %G",
    665 			     phi_info->stmt);
    666 
    667 	  if (vect_stmt_relevant_p (phi_info, loop_vinfo, &relevant, &live_p))
    668 	    vect_mark_relevant (&worklist, phi_info, relevant, live_p);
    669 	}
    670       for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
    671 	{
    672 	  if (is_gimple_debug (gsi_stmt (si)))
    673 	    continue;
    674 	  stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
    675 	  if (dump_enabled_p ())
    676 	      dump_printf_loc (MSG_NOTE, vect_location,
    677 			       "init: stmt relevant? %G", stmt_info->stmt);
    678 
    679 	  if (vect_stmt_relevant_p (stmt_info, loop_vinfo, &relevant, &live_p))
    680 	    vect_mark_relevant (&worklist, stmt_info, relevant, live_p);
    681 	}
    682     }
    683 
    684   /* 2. Process_worklist */
    685   while (worklist.length () > 0)
    686     {
    687       use_operand_p use_p;
    688       ssa_op_iter iter;
    689 
    690       stmt_vec_info stmt_vinfo = worklist.pop ();
    691       if (dump_enabled_p ())
    692 	dump_printf_loc (MSG_NOTE, vect_location,
    693 			 "worklist: examine stmt: %G", stmt_vinfo->stmt);
    694 
    695       /* Examine the USEs of STMT. For each USE, mark the stmt that defines it
    696 	 (DEF_STMT) as relevant/irrelevant according to the relevance property
    697 	 of STMT.  */
    698       relevant = STMT_VINFO_RELEVANT (stmt_vinfo);
    699 
    700       /* Generally, the relevance property of STMT (in STMT_VINFO_RELEVANT) is
    701 	 propagated as is to the DEF_STMTs of its USEs.
    702 
    703 	 One exception is when STMT has been identified as defining a reduction
    704 	 variable; in this case we set the relevance to vect_used_by_reduction.
    705 	 This is because we distinguish between two kinds of relevant stmts -
    706 	 those that are used by a reduction computation, and those that are
    707 	 (also) used by a regular computation.  This allows us later on to
    708 	 identify stmts that are used solely by a reduction, and therefore the
    709 	 order of the results that they produce does not have to be kept.  */
    710 
    711       switch (STMT_VINFO_DEF_TYPE (stmt_vinfo))
    712         {
    713           case vect_reduction_def:
    714 	    gcc_assert (relevant != vect_unused_in_scope);
    715 	    if (relevant != vect_unused_in_scope
    716 		&& relevant != vect_used_in_scope
    717 		&& relevant != vect_used_by_reduction
    718 		&& relevant != vect_used_only_live)
    719 	      return opt_result::failure_at
    720 		(stmt_vinfo->stmt, "unsupported use of reduction.\n");
    721 	    break;
    722 
    723           case vect_nested_cycle:
    724 	    if (relevant != vect_unused_in_scope
    725 		&& relevant != vect_used_in_outer_by_reduction
    726 		&& relevant != vect_used_in_outer)
    727 	      return opt_result::failure_at
    728 		(stmt_vinfo->stmt, "unsupported use of nested cycle.\n");
    729             break;
    730 
    731           case vect_double_reduction_def:
    732 	    if (relevant != vect_unused_in_scope
    733 		&& relevant != vect_used_by_reduction
    734 		&& relevant != vect_used_only_live)
    735 	      return opt_result::failure_at
    736 		(stmt_vinfo->stmt, "unsupported use of double reduction.\n");
    737             break;
    738 
    739           default:
    740             break;
    741         }
    742 
    743       if (is_pattern_stmt_p (stmt_vinfo))
    744         {
    745           /* Pattern statements are not inserted into the code, so
    746              FOR_EACH_PHI_OR_STMT_USE optimizes their operands out, and we
    747              have to scan the RHS or function arguments instead.  */
    748 	  if (gassign *assign = dyn_cast <gassign *> (stmt_vinfo->stmt))
    749 	    {
    750 	      enum tree_code rhs_code = gimple_assign_rhs_code (assign);
    751 	      tree op = gimple_assign_rhs1 (assign);
    752 
    753 	      i = 1;
    754 	      if (rhs_code == COND_EXPR && COMPARISON_CLASS_P (op))
    755 		{
    756 		  opt_result res
    757 		    = process_use (stmt_vinfo, TREE_OPERAND (op, 0),
    758 				   loop_vinfo, relevant, &worklist, false);
    759 		  if (!res)
    760 		    return res;
    761 		  res = process_use (stmt_vinfo, TREE_OPERAND (op, 1),
    762 				     loop_vinfo, relevant, &worklist, false);
    763 		  if (!res)
    764 		    return res;
    765 		  i = 2;
    766 		}
    767 	      for (; i < gimple_num_ops (assign); i++)
    768 		{
    769 		  op = gimple_op (assign, i);
    770                   if (TREE_CODE (op) == SSA_NAME)
    771 		    {
    772 		      opt_result res
    773 			= process_use (stmt_vinfo, op, loop_vinfo, relevant,
    774 				       &worklist, false);
    775 		      if (!res)
    776 			return res;
    777 		    }
    778                  }
    779             }
    780 	  else if (gcall *call = dyn_cast <gcall *> (stmt_vinfo->stmt))
    781 	    {
    782 	      for (i = 0; i < gimple_call_num_args (call); i++)
    783 		{
    784 		  tree arg = gimple_call_arg (call, i);
    785 		  opt_result res
    786 		    = process_use (stmt_vinfo, arg, loop_vinfo, relevant,
    787 				   &worklist, false);
    788 		  if (!res)
    789 		    return res;
    790 		}
    791 	    }
    792         }
    793       else
    794 	FOR_EACH_PHI_OR_STMT_USE (use_p, stmt_vinfo->stmt, iter, SSA_OP_USE)
    795           {
    796             tree op = USE_FROM_PTR (use_p);
    797 	    opt_result res
    798 	      = process_use (stmt_vinfo, op, loop_vinfo, relevant,
    799 			     &worklist, false);
    800 	    if (!res)
    801 	      return res;
    802           }
    803 
    804       if (STMT_VINFO_GATHER_SCATTER_P (stmt_vinfo))
    805 	{
    806 	  gather_scatter_info gs_info;
    807 	  if (!vect_check_gather_scatter (stmt_vinfo, loop_vinfo, &gs_info))
    808 	    gcc_unreachable ();
    809 	  opt_result res
    810 	    = process_use (stmt_vinfo, gs_info.offset, loop_vinfo, relevant,
    811 			   &worklist, true);
    812 	  if (!res)
    813 	    {
    814 	      if (fatal)
    815 		*fatal = false;
    816 	      return res;
    817 	    }
    818 	}
    819     } /* while worklist */
    820 
    821   return opt_result::success ();
    822 }
    823 
    824 /* Function vect_model_simple_cost.
    825 
    826    Models cost for simple operations, i.e. those that only emit ncopies of a
    827    single op.  Right now, this does not account for multiple insns that could
    828    be generated for the single vector op.  We will handle that shortly.  */
    829 
    830 static void
    831 vect_model_simple_cost (vec_info *,
    832 			stmt_vec_info stmt_info, int ncopies,
    833 			enum vect_def_type *dt,
    834 			int ndts,
    835 			slp_tree node,
    836 			stmt_vector_for_cost *cost_vec,
    837 			vect_cost_for_stmt kind = vector_stmt)
    838 {
    839   int inside_cost = 0, prologue_cost = 0;
    840 
    841   gcc_assert (cost_vec != NULL);
    842 
    843   /* ???  Somehow we need to fix this at the callers.  */
    844   if (node)
    845     ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (node);
    846 
    847   if (!node)
    848     /* Cost the "broadcast" of a scalar operand in to a vector operand.
    849        Use scalar_to_vec to cost the broadcast, as elsewhere in the vector
    850        cost model.  */
    851     for (int i = 0; i < ndts; i++)
    852       if (dt[i] == vect_constant_def || dt[i] == vect_external_def)
    853 	prologue_cost += record_stmt_cost (cost_vec, 1, scalar_to_vec,
    854 					   stmt_info, 0, vect_prologue);
    855 
    856   /* Pass the inside-of-loop statements to the target-specific cost model.  */
    857   inside_cost += record_stmt_cost (cost_vec, ncopies, kind,
    858 				   stmt_info, 0, vect_body);
    859 
    860   if (dump_enabled_p ())
    861     dump_printf_loc (MSG_NOTE, vect_location,
    862                      "vect_model_simple_cost: inside_cost = %d, "
    863                      "prologue_cost = %d .\n", inside_cost, prologue_cost);
    864 }
    865 
    866 
    867 /* Model cost for type demotion and promotion operations.  PWR is
    868    normally zero for single-step promotions and demotions.  It will be
    869    one if two-step promotion/demotion is required, and so on.  NCOPIES
    870    is the number of vector results (and thus number of instructions)
    871    for the narrowest end of the operation chain.  Each additional
    872    step doubles the number of instructions required.  If WIDEN_ARITH
    873    is true the stmt is doing widening arithmetic.  */
    874 
    875 static void
    876 vect_model_promotion_demotion_cost (stmt_vec_info stmt_info,
    877 				    enum vect_def_type *dt,
    878 				    unsigned int ncopies, int pwr,
    879 				    stmt_vector_for_cost *cost_vec,
    880 				    bool widen_arith)
    881 {
    882   int i;
    883   int inside_cost = 0, prologue_cost = 0;
    884 
    885   for (i = 0; i < pwr + 1; i++)
    886     {
    887       inside_cost += record_stmt_cost (cost_vec, ncopies,
    888 				       widen_arith
    889 				       ? vector_stmt : vec_promote_demote,
    890 				       stmt_info, 0, vect_body);
    891       ncopies *= 2;
    892     }
    893 
    894   /* FORNOW: Assuming maximum 2 args per stmts.  */
    895   for (i = 0; i < 2; i++)
    896     if (dt[i] == vect_constant_def || dt[i] == vect_external_def)
    897       prologue_cost += record_stmt_cost (cost_vec, 1, vector_stmt,
    898 					 stmt_info, 0, vect_prologue);
    899 
    900   if (dump_enabled_p ())
    901     dump_printf_loc (MSG_NOTE, vect_location,
    902                      "vect_model_promotion_demotion_cost: inside_cost = %d, "
    903                      "prologue_cost = %d .\n", inside_cost, prologue_cost);
    904 }
    905 
    906 /* Returns true if the current function returns DECL.  */
    907 
    908 static bool
    909 cfun_returns (tree decl)
    910 {
    911   edge_iterator ei;
    912   edge e;
    913   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
    914     {
    915       greturn *ret = safe_dyn_cast <greturn *> (last_stmt (e->src));
    916       if (!ret)
    917 	continue;
    918       if (gimple_return_retval (ret) == decl)
    919 	return true;
    920       /* We often end up with an aggregate copy to the result decl,
    921          handle that case as well.  First skip intermediate clobbers
    922 	 though.  */
    923       gimple *def = ret;
    924       do
    925 	{
    926 	  def = SSA_NAME_DEF_STMT (gimple_vuse (def));
    927 	}
    928       while (gimple_clobber_p (def));
    929       if (is_a <gassign *> (def)
    930 	  && gimple_assign_lhs (def) == gimple_return_retval (ret)
    931 	  && gimple_assign_rhs1 (def) == decl)
    932 	return true;
    933     }
    934   return false;
    935 }
    936 
    937 /* Function vect_model_store_cost
    938 
    939    Models cost for stores.  In the case of grouped accesses, one access
    940    has the overhead of the grouped access attributed to it.  */
    941 
    942 static void
    943 vect_model_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
    944 		       vect_memory_access_type memory_access_type,
    945 		       dr_alignment_support alignment_support_scheme,
    946 		       int misalignment,
    947 		       vec_load_store_type vls_type, slp_tree slp_node,
    948 		       stmt_vector_for_cost *cost_vec)
    949 {
    950   unsigned int inside_cost = 0, prologue_cost = 0;
    951   stmt_vec_info first_stmt_info = stmt_info;
    952   bool grouped_access_p = STMT_VINFO_GROUPED_ACCESS (stmt_info);
    953 
    954   /* ???  Somehow we need to fix this at the callers.  */
    955   if (slp_node)
    956     ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
    957 
    958   if (vls_type == VLS_STORE_INVARIANT)
    959     {
    960       if (!slp_node)
    961 	prologue_cost += record_stmt_cost (cost_vec, 1, scalar_to_vec,
    962 					   stmt_info, 0, vect_prologue);
    963     }
    964 
    965   /* Grouped stores update all elements in the group at once,
    966      so we want the DR for the first statement.  */
    967   if (!slp_node && grouped_access_p)
    968     first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
    969 
    970   /* True if we should include any once-per-group costs as well as
    971      the cost of the statement itself.  For SLP we only get called
    972      once per group anyhow.  */
    973   bool first_stmt_p = (first_stmt_info == stmt_info);
    974 
    975   /* We assume that the cost of a single store-lanes instruction is
    976      equivalent to the cost of DR_GROUP_SIZE separate stores.  If a grouped
    977      access is instead being provided by a permute-and-store operation,
    978      include the cost of the permutes.  */
    979   if (first_stmt_p
    980       && memory_access_type == VMAT_CONTIGUOUS_PERMUTE)
    981     {
    982       /* Uses a high and low interleave or shuffle operations for each
    983 	 needed permute.  */
    984       int group_size = DR_GROUP_SIZE (first_stmt_info);
    985       int nstmts = ncopies * ceil_log2 (group_size) * group_size;
    986       inside_cost = record_stmt_cost (cost_vec, nstmts, vec_perm,
    987 				      stmt_info, 0, vect_body);
    988 
    989       if (dump_enabled_p ())
    990         dump_printf_loc (MSG_NOTE, vect_location,
    991                          "vect_model_store_cost: strided group_size = %d .\n",
    992                          group_size);
    993     }
    994 
    995   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    996   /* Costs of the stores.  */
    997   if (memory_access_type == VMAT_ELEMENTWISE
    998       || memory_access_type == VMAT_GATHER_SCATTER)
    999     {
   1000       /* N scalar stores plus extracting the elements.  */
   1001       unsigned int assumed_nunits = vect_nunits_for_cost (vectype);
   1002       inside_cost += record_stmt_cost (cost_vec,
   1003 				       ncopies * assumed_nunits,
   1004 				       scalar_store, stmt_info, 0, vect_body);
   1005     }
   1006   else
   1007     vect_get_store_cost (vinfo, stmt_info, ncopies, alignment_support_scheme,
   1008 			 misalignment, &inside_cost, cost_vec);
   1009 
   1010   if (memory_access_type == VMAT_ELEMENTWISE
   1011       || memory_access_type == VMAT_STRIDED_SLP)
   1012     {
   1013       /* N scalar stores plus extracting the elements.  */
   1014       unsigned int assumed_nunits = vect_nunits_for_cost (vectype);
   1015       inside_cost += record_stmt_cost (cost_vec,
   1016 				       ncopies * assumed_nunits,
   1017 				       vec_to_scalar, stmt_info, 0, vect_body);
   1018     }
   1019 
   1020   /* When vectorizing a store into the function result assign
   1021      a penalty if the function returns in a multi-register location.
   1022      In this case we assume we'll end up with having to spill the
   1023      vector result and do piecewise loads as a conservative estimate.  */
   1024   tree base = get_base_address (STMT_VINFO_DATA_REF (stmt_info)->ref);
   1025   if (base
   1026       && (TREE_CODE (base) == RESULT_DECL
   1027 	  || (DECL_P (base) && cfun_returns (base)))
   1028       && !aggregate_value_p (base, cfun->decl))
   1029     {
   1030       rtx reg = hard_function_value (TREE_TYPE (base), cfun->decl, 0, 1);
   1031       /* ???  Handle PARALLEL in some way.  */
   1032       if (REG_P (reg))
   1033 	{
   1034 	  int nregs = hard_regno_nregs (REGNO (reg), GET_MODE (reg));
   1035 	  /* Assume that a single reg-reg move is possible and cheap,
   1036 	     do not account for vector to gp register move cost.  */
   1037 	  if (nregs > 1)
   1038 	    {
   1039 	      /* Spill.  */
   1040 	      prologue_cost += record_stmt_cost (cost_vec, ncopies,
   1041 						 vector_store,
   1042 						 stmt_info, 0, vect_epilogue);
   1043 	      /* Loads.  */
   1044 	      prologue_cost += record_stmt_cost (cost_vec, ncopies * nregs,
   1045 						 scalar_load,
   1046 						 stmt_info, 0, vect_epilogue);
   1047 	    }
   1048 	}
   1049     }
   1050 
   1051   if (dump_enabled_p ())
   1052     dump_printf_loc (MSG_NOTE, vect_location,
   1053                      "vect_model_store_cost: inside_cost = %d, "
   1054                      "prologue_cost = %d .\n", inside_cost, prologue_cost);
   1055 }
   1056 
   1057 
   1058 /* Calculate cost of DR's memory access.  */
   1059 void
   1060 vect_get_store_cost (vec_info *, stmt_vec_info stmt_info, int ncopies,
   1061 		     dr_alignment_support alignment_support_scheme,
   1062 		     int misalignment,
   1063 		     unsigned int *inside_cost,
   1064 		     stmt_vector_for_cost *body_cost_vec)
   1065 {
   1066   switch (alignment_support_scheme)
   1067     {
   1068     case dr_aligned:
   1069       {
   1070 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
   1071 					  vector_store, stmt_info, 0,
   1072 					  vect_body);
   1073 
   1074         if (dump_enabled_p ())
   1075           dump_printf_loc (MSG_NOTE, vect_location,
   1076                            "vect_model_store_cost: aligned.\n");
   1077         break;
   1078       }
   1079 
   1080     case dr_unaligned_supported:
   1081       {
   1082         /* Here, we assign an additional cost for the unaligned store.  */
   1083 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
   1084 					  unaligned_store, stmt_info,
   1085 					  misalignment, vect_body);
   1086         if (dump_enabled_p ())
   1087           dump_printf_loc (MSG_NOTE, vect_location,
   1088                            "vect_model_store_cost: unaligned supported by "
   1089                            "hardware.\n");
   1090         break;
   1091       }
   1092 
   1093     case dr_unaligned_unsupported:
   1094       {
   1095         *inside_cost = VECT_MAX_COST;
   1096 
   1097         if (dump_enabled_p ())
   1098           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   1099                            "vect_model_store_cost: unsupported access.\n");
   1100         break;
   1101       }
   1102 
   1103     default:
   1104       gcc_unreachable ();
   1105     }
   1106 }
   1107 
   1108 
   1109 /* Function vect_model_load_cost
   1110 
   1111    Models cost for loads.  In the case of grouped accesses, one access has
   1112    the overhead of the grouped access attributed to it.  Since unaligned
   1113    accesses are supported for loads, we also account for the costs of the
   1114    access scheme chosen.  */
   1115 
   1116 static void
   1117 vect_model_load_cost (vec_info *vinfo,
   1118 		      stmt_vec_info stmt_info, unsigned ncopies, poly_uint64 vf,
   1119 		      vect_memory_access_type memory_access_type,
   1120 		      dr_alignment_support alignment_support_scheme,
   1121 		      int misalignment,
   1122 		      gather_scatter_info *gs_info,
   1123 		      slp_tree slp_node,
   1124 		      stmt_vector_for_cost *cost_vec)
   1125 {
   1126   unsigned int inside_cost = 0, prologue_cost = 0;
   1127   bool grouped_access_p = STMT_VINFO_GROUPED_ACCESS (stmt_info);
   1128 
   1129   gcc_assert (cost_vec);
   1130 
   1131   /* ???  Somehow we need to fix this at the callers.  */
   1132   if (slp_node)
   1133     ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   1134 
   1135   if (slp_node && SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
   1136     {
   1137       /* If the load is permuted then the alignment is determined by
   1138 	 the first group element not by the first scalar stmt DR.  */
   1139       stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   1140       /* Record the cost for the permutation.  */
   1141       unsigned n_perms, n_loads;
   1142       vect_transform_slp_perm_load (vinfo, slp_node, vNULL, NULL,
   1143 				    vf, true, &n_perms, &n_loads);
   1144       inside_cost += record_stmt_cost (cost_vec, n_perms, vec_perm,
   1145 				       first_stmt_info, 0, vect_body);
   1146 
   1147       /* And adjust the number of loads performed.  This handles
   1148 	 redundancies as well as loads that are later dead.  */
   1149       ncopies = n_loads;
   1150     }
   1151 
   1152   /* Grouped loads read all elements in the group at once,
   1153      so we want the DR for the first statement.  */
   1154   stmt_vec_info first_stmt_info = stmt_info;
   1155   if (!slp_node && grouped_access_p)
   1156     first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   1157 
   1158   /* True if we should include any once-per-group costs as well as
   1159      the cost of the statement itself.  For SLP we only get called
   1160      once per group anyhow.  */
   1161   bool first_stmt_p = (first_stmt_info == stmt_info);
   1162 
   1163   /* An IFN_LOAD_LANES will load all its vector results, regardless of which
   1164      ones we actually need.  Account for the cost of unused results.  */
   1165   if (first_stmt_p && !slp_node && memory_access_type == VMAT_LOAD_STORE_LANES)
   1166     {
   1167       unsigned int gaps = DR_GROUP_SIZE (first_stmt_info);
   1168       stmt_vec_info next_stmt_info = first_stmt_info;
   1169       do
   1170 	{
   1171 	  gaps -= 1;
   1172 	  next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
   1173 	}
   1174       while (next_stmt_info);
   1175       if (gaps)
   1176 	{
   1177 	  if (dump_enabled_p ())
   1178 	    dump_printf_loc (MSG_NOTE, vect_location,
   1179 			     "vect_model_load_cost: %d unused vectors.\n",
   1180 			     gaps);
   1181 	  vect_get_load_cost (vinfo, stmt_info, ncopies * gaps,
   1182 			      alignment_support_scheme, misalignment, false,
   1183 			      &inside_cost, &prologue_cost,
   1184 			      cost_vec, cost_vec, true);
   1185 	}
   1186     }
   1187 
   1188   /* We assume that the cost of a single load-lanes instruction is
   1189      equivalent to the cost of DR_GROUP_SIZE separate loads.  If a grouped
   1190      access is instead being provided by a load-and-permute operation,
   1191      include the cost of the permutes.  */
   1192   if (first_stmt_p
   1193       && memory_access_type == VMAT_CONTIGUOUS_PERMUTE)
   1194     {
   1195       /* Uses an even and odd extract operations or shuffle operations
   1196 	 for each needed permute.  */
   1197       int group_size = DR_GROUP_SIZE (first_stmt_info);
   1198       int nstmts = ncopies * ceil_log2 (group_size) * group_size;
   1199       inside_cost += record_stmt_cost (cost_vec, nstmts, vec_perm,
   1200 				       stmt_info, 0, vect_body);
   1201 
   1202       if (dump_enabled_p ())
   1203         dump_printf_loc (MSG_NOTE, vect_location,
   1204                          "vect_model_load_cost: strided group_size = %d .\n",
   1205                          group_size);
   1206     }
   1207 
   1208   /* The loads themselves.  */
   1209   if (memory_access_type == VMAT_ELEMENTWISE
   1210       || memory_access_type == VMAT_GATHER_SCATTER)
   1211     {
   1212       tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   1213       unsigned int assumed_nunits = vect_nunits_for_cost (vectype);
   1214       if (memory_access_type == VMAT_GATHER_SCATTER
   1215 	  && gs_info->ifn == IFN_LAST && !gs_info->decl)
   1216 	/* For emulated gathers N offset vector element extracts
   1217 	   (we assume the scalar scaling and ptr + offset add is consumed by
   1218 	   the load).  */
   1219 	inside_cost += record_stmt_cost (cost_vec, ncopies * assumed_nunits,
   1220 					 vec_to_scalar, stmt_info, 0,
   1221 					 vect_body);
   1222       /* N scalar loads plus gathering them into a vector.  */
   1223       inside_cost += record_stmt_cost (cost_vec,
   1224 				       ncopies * assumed_nunits,
   1225 				       scalar_load, stmt_info, 0, vect_body);
   1226     }
   1227   else if (memory_access_type == VMAT_INVARIANT)
   1228     {
   1229       /* Invariant loads will ideally be hoisted and splat to a vector.  */
   1230       prologue_cost += record_stmt_cost (cost_vec, 1,
   1231 					 scalar_load, stmt_info, 0,
   1232 					 vect_prologue);
   1233       prologue_cost += record_stmt_cost (cost_vec, 1,
   1234 					 scalar_to_vec, stmt_info, 0,
   1235 					 vect_prologue);
   1236     }
   1237   else
   1238     vect_get_load_cost (vinfo, stmt_info, ncopies,
   1239 			alignment_support_scheme, misalignment, first_stmt_p,
   1240 			&inside_cost, &prologue_cost,
   1241 			cost_vec, cost_vec, true);
   1242   if (memory_access_type == VMAT_ELEMENTWISE
   1243       || memory_access_type == VMAT_STRIDED_SLP
   1244       || (memory_access_type == VMAT_GATHER_SCATTER
   1245 	  && gs_info->ifn == IFN_LAST && !gs_info->decl))
   1246     inside_cost += record_stmt_cost (cost_vec, ncopies, vec_construct,
   1247 				     stmt_info, 0, vect_body);
   1248 
   1249   if (dump_enabled_p ())
   1250     dump_printf_loc (MSG_NOTE, vect_location,
   1251                      "vect_model_load_cost: inside_cost = %d, "
   1252                      "prologue_cost = %d .\n", inside_cost, prologue_cost);
   1253 }
   1254 
   1255 
   1256 /* Calculate cost of DR's memory access.  */
   1257 void
   1258 vect_get_load_cost (vec_info *, stmt_vec_info stmt_info, int ncopies,
   1259 		    dr_alignment_support alignment_support_scheme,
   1260 		    int misalignment,
   1261 		    bool add_realign_cost, unsigned int *inside_cost,
   1262 		    unsigned int *prologue_cost,
   1263 		    stmt_vector_for_cost *prologue_cost_vec,
   1264 		    stmt_vector_for_cost *body_cost_vec,
   1265 		    bool record_prologue_costs)
   1266 {
   1267   switch (alignment_support_scheme)
   1268     {
   1269     case dr_aligned:
   1270       {
   1271 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies, vector_load,
   1272 					  stmt_info, 0, vect_body);
   1273 
   1274         if (dump_enabled_p ())
   1275           dump_printf_loc (MSG_NOTE, vect_location,
   1276                            "vect_model_load_cost: aligned.\n");
   1277 
   1278         break;
   1279       }
   1280     case dr_unaligned_supported:
   1281       {
   1282         /* Here, we assign an additional cost for the unaligned load.  */
   1283 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
   1284 					  unaligned_load, stmt_info,
   1285 					  misalignment, vect_body);
   1286 
   1287         if (dump_enabled_p ())
   1288           dump_printf_loc (MSG_NOTE, vect_location,
   1289                            "vect_model_load_cost: unaligned supported by "
   1290                            "hardware.\n");
   1291 
   1292         break;
   1293       }
   1294     case dr_explicit_realign:
   1295       {
   1296 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies * 2,
   1297 					  vector_load, stmt_info, 0, vect_body);
   1298 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
   1299 					  vec_perm, stmt_info, 0, vect_body);
   1300 
   1301         /* FIXME: If the misalignment remains fixed across the iterations of
   1302            the containing loop, the following cost should be added to the
   1303            prologue costs.  */
   1304         if (targetm.vectorize.builtin_mask_for_load)
   1305 	  *inside_cost += record_stmt_cost (body_cost_vec, 1, vector_stmt,
   1306 					    stmt_info, 0, vect_body);
   1307 
   1308         if (dump_enabled_p ())
   1309           dump_printf_loc (MSG_NOTE, vect_location,
   1310                            "vect_model_load_cost: explicit realign\n");
   1311 
   1312         break;
   1313       }
   1314     case dr_explicit_realign_optimized:
   1315       {
   1316         if (dump_enabled_p ())
   1317           dump_printf_loc (MSG_NOTE, vect_location,
   1318                            "vect_model_load_cost: unaligned software "
   1319                            "pipelined.\n");
   1320 
   1321         /* Unaligned software pipeline has a load of an address, an initial
   1322            load, and possibly a mask operation to "prime" the loop.  However,
   1323            if this is an access in a group of loads, which provide grouped
   1324            access, then the above cost should only be considered for one
   1325            access in the group.  Inside the loop, there is a load op
   1326            and a realignment op.  */
   1327 
   1328         if (add_realign_cost && record_prologue_costs)
   1329           {
   1330 	    *prologue_cost += record_stmt_cost (prologue_cost_vec, 2,
   1331 						vector_stmt, stmt_info,
   1332 						0, vect_prologue);
   1333             if (targetm.vectorize.builtin_mask_for_load)
   1334 	      *prologue_cost += record_stmt_cost (prologue_cost_vec, 1,
   1335 						  vector_stmt, stmt_info,
   1336 						  0, vect_prologue);
   1337           }
   1338 
   1339 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies, vector_load,
   1340 					  stmt_info, 0, vect_body);
   1341 	*inside_cost += record_stmt_cost (body_cost_vec, ncopies, vec_perm,
   1342 					  stmt_info, 0, vect_body);
   1343 
   1344         if (dump_enabled_p ())
   1345           dump_printf_loc (MSG_NOTE, vect_location,
   1346                            "vect_model_load_cost: explicit realign optimized"
   1347                            "\n");
   1348 
   1349         break;
   1350       }
   1351 
   1352     case dr_unaligned_unsupported:
   1353       {
   1354         *inside_cost = VECT_MAX_COST;
   1355 
   1356         if (dump_enabled_p ())
   1357           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   1358                            "vect_model_load_cost: unsupported access.\n");
   1359         break;
   1360       }
   1361 
   1362     default:
   1363       gcc_unreachable ();
   1364     }
   1365 }
   1366 
   1367 /* Insert the new stmt NEW_STMT at *GSI or at the appropriate place in
   1368    the loop preheader for the vectorized stmt STMT_VINFO.  */
   1369 
   1370 static void
   1371 vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
   1372 		    gimple_stmt_iterator *gsi)
   1373 {
   1374   if (gsi)
   1375     vect_finish_stmt_generation (vinfo, stmt_vinfo, new_stmt, gsi);
   1376   else
   1377     vinfo->insert_on_entry (stmt_vinfo, new_stmt);
   1378 
   1379   if (dump_enabled_p ())
   1380     dump_printf_loc (MSG_NOTE, vect_location,
   1381 		     "created new init_stmt: %G", new_stmt);
   1382 }
   1383 
   1384 /* Function vect_init_vector.
   1385 
   1386    Insert a new stmt (INIT_STMT) that initializes a new variable of type
   1387    TYPE with the value VAL.  If TYPE is a vector type and VAL does not have
   1388    vector type a vector with all elements equal to VAL is created first.
   1389    Place the initialization at GSI if it is not NULL.  Otherwise, place the
   1390    initialization at the loop preheader.
   1391    Return the DEF of INIT_STMT.
   1392    It will be used in the vectorization of STMT_INFO.  */
   1393 
   1394 tree
   1395 vect_init_vector (vec_info *vinfo, stmt_vec_info stmt_info, tree val, tree type,
   1396 		  gimple_stmt_iterator *gsi)
   1397 {
   1398   gimple *init_stmt;
   1399   tree new_temp;
   1400 
   1401   /* We abuse this function to push sth to a SSA name with initial 'val'.  */
   1402   if (! useless_type_conversion_p (type, TREE_TYPE (val)))
   1403     {
   1404       gcc_assert (TREE_CODE (type) == VECTOR_TYPE);
   1405       if (! types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
   1406 	{
   1407 	  /* Scalar boolean value should be transformed into
   1408 	     all zeros or all ones value before building a vector.  */
   1409 	  if (VECTOR_BOOLEAN_TYPE_P (type))
   1410 	    {
   1411 	      tree true_val = build_all_ones_cst (TREE_TYPE (type));
   1412 	      tree false_val = build_zero_cst (TREE_TYPE (type));
   1413 
   1414 	      if (CONSTANT_CLASS_P (val))
   1415 		val = integer_zerop (val) ? false_val : true_val;
   1416 	      else
   1417 		{
   1418 		  new_temp = make_ssa_name (TREE_TYPE (type));
   1419 		  init_stmt = gimple_build_assign (new_temp, COND_EXPR,
   1420 						   val, true_val, false_val);
   1421 		  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi);
   1422 		  val = new_temp;
   1423 		}
   1424 	    }
   1425 	  else
   1426 	    {
   1427 	      gimple_seq stmts = NULL;
   1428 	      if (! INTEGRAL_TYPE_P (TREE_TYPE (val)))
   1429 		val = gimple_build (&stmts, VIEW_CONVERT_EXPR,
   1430 				    TREE_TYPE (type), val);
   1431 	      else
   1432 		/* ???  Condition vectorization expects us to do
   1433 		   promotion of invariant/external defs.  */
   1434 		val = gimple_convert (&stmts, TREE_TYPE (type), val);
   1435 	      for (gimple_stmt_iterator gsi2 = gsi_start (stmts);
   1436 		   !gsi_end_p (gsi2); )
   1437 		{
   1438 		  init_stmt = gsi_stmt (gsi2);
   1439 		  gsi_remove (&gsi2, false);
   1440 		  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi);
   1441 		}
   1442 	    }
   1443 	}
   1444       val = build_vector_from_val (type, val);
   1445     }
   1446 
   1447   new_temp = vect_get_new_ssa_name (type, vect_simple_var, "cst_");
   1448   init_stmt = gimple_build_assign (new_temp, val);
   1449   vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi);
   1450   return new_temp;
   1451 }
   1452 
   1453 
   1454 /* Function vect_get_vec_defs_for_operand.
   1455 
   1456    OP is an operand in STMT_VINFO.  This function returns a vector of
   1457    NCOPIES defs that will be used in the vectorized stmts for STMT_VINFO.
   1458 
   1459    In the case that OP is an SSA_NAME which is defined in the loop, then
   1460    STMT_VINFO_VEC_STMTS of the defining stmt holds the relevant defs.
   1461 
   1462    In case OP is an invariant or constant, a new stmt that creates a vector def
   1463    needs to be introduced.  VECTYPE may be used to specify a required type for
   1464    vector invariant.  */
   1465 
   1466 void
   1467 vect_get_vec_defs_for_operand (vec_info *vinfo, stmt_vec_info stmt_vinfo,
   1468 			       unsigned ncopies,
   1469 			       tree op, vec<tree> *vec_oprnds, tree vectype)
   1470 {
   1471   gimple *def_stmt;
   1472   enum vect_def_type dt;
   1473   bool is_simple_use;
   1474   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   1475 
   1476   if (dump_enabled_p ())
   1477     dump_printf_loc (MSG_NOTE, vect_location,
   1478 		     "vect_get_vec_defs_for_operand: %T\n", op);
   1479 
   1480   stmt_vec_info def_stmt_info;
   1481   is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt,
   1482 				      &def_stmt_info, &def_stmt);
   1483   gcc_assert (is_simple_use);
   1484   if (def_stmt && dump_enabled_p ())
   1485     dump_printf_loc (MSG_NOTE, vect_location, "  def_stmt =  %G", def_stmt);
   1486 
   1487   vec_oprnds->create (ncopies);
   1488   if (dt == vect_constant_def || dt == vect_external_def)
   1489     {
   1490       tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
   1491       tree vector_type;
   1492 
   1493       if (vectype)
   1494 	vector_type = vectype;
   1495       else if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (op))
   1496 	       && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
   1497 	vector_type = truth_type_for (stmt_vectype);
   1498       else
   1499 	vector_type = get_vectype_for_scalar_type (loop_vinfo, TREE_TYPE (op));
   1500 
   1501       gcc_assert (vector_type);
   1502       tree vop = vect_init_vector (vinfo, stmt_vinfo, op, vector_type, NULL);
   1503       while (ncopies--)
   1504 	vec_oprnds->quick_push (vop);
   1505     }
   1506   else
   1507     {
   1508       def_stmt_info = vect_stmt_to_vectorize (def_stmt_info);
   1509       gcc_assert (STMT_VINFO_VEC_STMTS (def_stmt_info).length () == ncopies);
   1510       for (unsigned i = 0; i < ncopies; ++i)
   1511 	vec_oprnds->quick_push (gimple_get_lhs
   1512 				  (STMT_VINFO_VEC_STMTS (def_stmt_info)[i]));
   1513     }
   1514 }
   1515 
   1516 
   1517 /* Get vectorized definitions for OP0 and OP1.  */
   1518 
   1519 void
   1520 vect_get_vec_defs (vec_info *vinfo, stmt_vec_info stmt_info, slp_tree slp_node,
   1521 		   unsigned ncopies,
   1522 		   tree op0, vec<tree> *vec_oprnds0, tree vectype0,
   1523 		   tree op1, vec<tree> *vec_oprnds1, tree vectype1,
   1524 		   tree op2, vec<tree> *vec_oprnds2, tree vectype2,
   1525 		   tree op3, vec<tree> *vec_oprnds3, tree vectype3)
   1526 {
   1527   if (slp_node)
   1528     {
   1529       if (op0)
   1530 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[0], vec_oprnds0);
   1531       if (op1)
   1532 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[1], vec_oprnds1);
   1533       if (op2)
   1534 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[2], vec_oprnds2);
   1535       if (op3)
   1536 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[3], vec_oprnds3);
   1537     }
   1538   else
   1539     {
   1540       if (op0)
   1541 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
   1542 				       op0, vec_oprnds0, vectype0);
   1543       if (op1)
   1544 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
   1545 				       op1, vec_oprnds1, vectype1);
   1546       if (op2)
   1547 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
   1548 				       op2, vec_oprnds2, vectype2);
   1549       if (op3)
   1550 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
   1551 				       op3, vec_oprnds3, vectype3);
   1552     }
   1553 }
   1554 
   1555 void
   1556 vect_get_vec_defs (vec_info *vinfo, stmt_vec_info stmt_info, slp_tree slp_node,
   1557 		   unsigned ncopies,
   1558 		   tree op0, vec<tree> *vec_oprnds0,
   1559 		   tree op1, vec<tree> *vec_oprnds1,
   1560 		   tree op2, vec<tree> *vec_oprnds2,
   1561 		   tree op3, vec<tree> *vec_oprnds3)
   1562 {
   1563   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   1564 		     op0, vec_oprnds0, NULL_TREE,
   1565 		     op1, vec_oprnds1, NULL_TREE,
   1566 		     op2, vec_oprnds2, NULL_TREE,
   1567 		     op3, vec_oprnds3, NULL_TREE);
   1568 }
   1569 
   1570 /* Helper function called by vect_finish_replace_stmt and
   1571    vect_finish_stmt_generation.  Set the location of the new
   1572    statement and create and return a stmt_vec_info for it.  */
   1573 
   1574 static void
   1575 vect_finish_stmt_generation_1 (vec_info *,
   1576 			       stmt_vec_info stmt_info, gimple *vec_stmt)
   1577 {
   1578   if (dump_enabled_p ())
   1579     dump_printf_loc (MSG_NOTE, vect_location, "add new stmt: %G", vec_stmt);
   1580 
   1581   if (stmt_info)
   1582     {
   1583       gimple_set_location (vec_stmt, gimple_location (stmt_info->stmt));
   1584 
   1585       /* While EH edges will generally prevent vectorization, stmt might
   1586 	 e.g. be in a must-not-throw region.  Ensure newly created stmts
   1587 	 that could throw are part of the same region.  */
   1588       int lp_nr = lookup_stmt_eh_lp (stmt_info->stmt);
   1589       if (lp_nr != 0 && stmt_could_throw_p (cfun, vec_stmt))
   1590 	add_stmt_to_eh_lp (vec_stmt, lp_nr);
   1591     }
   1592   else
   1593     gcc_assert (!stmt_could_throw_p (cfun, vec_stmt));
   1594 }
   1595 
   1596 /* Replace the scalar statement STMT_INFO with a new vector statement VEC_STMT,
   1597    which sets the same scalar result as STMT_INFO did.  Create and return a
   1598    stmt_vec_info for VEC_STMT.  */
   1599 
   1600 void
   1601 vect_finish_replace_stmt (vec_info *vinfo,
   1602 			  stmt_vec_info stmt_info, gimple *vec_stmt)
   1603 {
   1604   gimple *scalar_stmt = vect_orig_stmt (stmt_info)->stmt;
   1605   gcc_assert (gimple_get_lhs (scalar_stmt) == gimple_get_lhs (vec_stmt));
   1606 
   1607   gimple_stmt_iterator gsi = gsi_for_stmt (scalar_stmt);
   1608   gsi_replace (&gsi, vec_stmt, true);
   1609 
   1610   vect_finish_stmt_generation_1 (vinfo, stmt_info, vec_stmt);
   1611 }
   1612 
   1613 /* Add VEC_STMT to the vectorized implementation of STMT_INFO and insert it
   1614    before *GSI.  Create and return a stmt_vec_info for VEC_STMT.  */
   1615 
   1616 void
   1617 vect_finish_stmt_generation (vec_info *vinfo,
   1618 			     stmt_vec_info stmt_info, gimple *vec_stmt,
   1619 			     gimple_stmt_iterator *gsi)
   1620 {
   1621   gcc_assert (!stmt_info || gimple_code (stmt_info->stmt) != GIMPLE_LABEL);
   1622 
   1623   if (!gsi_end_p (*gsi)
   1624       && gimple_has_mem_ops (vec_stmt))
   1625     {
   1626       gimple *at_stmt = gsi_stmt (*gsi);
   1627       tree vuse = gimple_vuse (at_stmt);
   1628       if (vuse && TREE_CODE (vuse) == SSA_NAME)
   1629 	{
   1630 	  tree vdef = gimple_vdef (at_stmt);
   1631 	  gimple_set_vuse (vec_stmt, gimple_vuse (at_stmt));
   1632 	  gimple_set_modified (vec_stmt, true);
   1633 	  /* If we have an SSA vuse and insert a store, update virtual
   1634 	     SSA form to avoid triggering the renamer.  Do so only
   1635 	     if we can easily see all uses - which is what almost always
   1636 	     happens with the way vectorized stmts are inserted.  */
   1637 	  if ((vdef && TREE_CODE (vdef) == SSA_NAME)
   1638 	      && ((is_gimple_assign (vec_stmt)
   1639 		   && !is_gimple_reg (gimple_assign_lhs (vec_stmt)))
   1640 		  || (is_gimple_call (vec_stmt)
   1641 		      && !(gimple_call_flags (vec_stmt)
   1642 			   & (ECF_CONST|ECF_PURE|ECF_NOVOPS)))))
   1643 	    {
   1644 	      tree new_vdef = copy_ssa_name (vuse, vec_stmt);
   1645 	      gimple_set_vdef (vec_stmt, new_vdef);
   1646 	      SET_USE (gimple_vuse_op (at_stmt), new_vdef);
   1647 	    }
   1648 	}
   1649     }
   1650   gsi_insert_before (gsi, vec_stmt, GSI_SAME_STMT);
   1651   vect_finish_stmt_generation_1 (vinfo, stmt_info, vec_stmt);
   1652 }
   1653 
   1654 /* We want to vectorize a call to combined function CFN with function
   1655    decl FNDECL, using VECTYPE_OUT as the type of the output and VECTYPE_IN
   1656    as the types of all inputs.  Check whether this is possible using
   1657    an internal function, returning its code if so or IFN_LAST if not.  */
   1658 
   1659 static internal_fn
   1660 vectorizable_internal_function (combined_fn cfn, tree fndecl,
   1661 				tree vectype_out, tree vectype_in)
   1662 {
   1663   internal_fn ifn;
   1664   if (internal_fn_p (cfn))
   1665     ifn = as_internal_fn (cfn);
   1666   else
   1667     ifn = associated_internal_fn (fndecl);
   1668   if (ifn != IFN_LAST && direct_internal_fn_p (ifn))
   1669     {
   1670       const direct_internal_fn_info &info = direct_internal_fn (ifn);
   1671       if (info.vectorizable)
   1672 	{
   1673 	  tree type0 = (info.type0 < 0 ? vectype_out : vectype_in);
   1674 	  tree type1 = (info.type1 < 0 ? vectype_out : vectype_in);
   1675 	  if (direct_internal_fn_supported_p (ifn, tree_pair (type0, type1),
   1676 					      OPTIMIZE_FOR_SPEED))
   1677 	    return ifn;
   1678 	}
   1679     }
   1680   return IFN_LAST;
   1681 }
   1682 
   1683 
   1684 static tree permute_vec_elements (vec_info *, tree, tree, tree, stmt_vec_info,
   1685 				  gimple_stmt_iterator *);
   1686 
   1687 /* Check whether a load or store statement in the loop described by
   1688    LOOP_VINFO is possible in a loop using partial vectors.  This is
   1689    testing whether the vectorizer pass has the appropriate support,
   1690    as well as whether the target does.
   1691 
   1692    VLS_TYPE says whether the statement is a load or store and VECTYPE
   1693    is the type of the vector being loaded or stored.  SLP_NODE is the SLP
   1694    node that contains the statement, or null if none.  MEMORY_ACCESS_TYPE
   1695    says how the load or store is going to be implemented and GROUP_SIZE
   1696    is the number of load or store statements in the containing group.
   1697    If the access is a gather load or scatter store, GS_INFO describes
   1698    its arguments.  If the load or store is conditional, SCALAR_MASK is the
   1699    condition under which it occurs.
   1700 
   1701    Clear LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P if a loop using partial
   1702    vectors is not supported, otherwise record the required rgroup control
   1703    types.  */
   1704 
   1705 static void
   1706 check_load_store_for_partial_vectors (loop_vec_info loop_vinfo, tree vectype,
   1707 				      slp_tree slp_node,
   1708 				      vec_load_store_type vls_type,
   1709 				      int group_size,
   1710 				      vect_memory_access_type
   1711 				      memory_access_type,
   1712 				      gather_scatter_info *gs_info,
   1713 				      tree scalar_mask)
   1714 {
   1715   /* Invariant loads need no special support.  */
   1716   if (memory_access_type == VMAT_INVARIANT)
   1717     return;
   1718 
   1719   unsigned int nvectors;
   1720   if (slp_node)
   1721     nvectors = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   1722   else
   1723     nvectors = vect_get_num_copies (loop_vinfo, vectype);
   1724 
   1725   vec_loop_masks *masks = &LOOP_VINFO_MASKS (loop_vinfo);
   1726   machine_mode vecmode = TYPE_MODE (vectype);
   1727   bool is_load = (vls_type == VLS_LOAD);
   1728   if (memory_access_type == VMAT_LOAD_STORE_LANES)
   1729     {
   1730       if (is_load
   1731 	  ? !vect_load_lanes_supported (vectype, group_size, true)
   1732 	  : !vect_store_lanes_supported (vectype, group_size, true))
   1733 	{
   1734 	  if (dump_enabled_p ())
   1735 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   1736 			     "can't operate on partial vectors because"
   1737 			     " the target doesn't have an appropriate"
   1738 			     " load/store-lanes instruction.\n");
   1739 	  LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   1740 	  return;
   1741 	}
   1742       vect_record_loop_mask (loop_vinfo, masks, nvectors, vectype,
   1743 			     scalar_mask);
   1744       return;
   1745     }
   1746 
   1747   if (memory_access_type == VMAT_GATHER_SCATTER)
   1748     {
   1749       internal_fn ifn = (is_load
   1750 			 ? IFN_MASK_GATHER_LOAD
   1751 			 : IFN_MASK_SCATTER_STORE);
   1752       if (!internal_gather_scatter_fn_supported_p (ifn, vectype,
   1753 						   gs_info->memory_type,
   1754 						   gs_info->offset_vectype,
   1755 						   gs_info->scale))
   1756 	{
   1757 	  if (dump_enabled_p ())
   1758 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   1759 			     "can't operate on partial vectors because"
   1760 			     " the target doesn't have an appropriate"
   1761 			     " gather load or scatter store instruction.\n");
   1762 	  LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   1763 	  return;
   1764 	}
   1765       vect_record_loop_mask (loop_vinfo, masks, nvectors, vectype,
   1766 			     scalar_mask);
   1767       return;
   1768     }
   1769 
   1770   if (memory_access_type != VMAT_CONTIGUOUS
   1771       && memory_access_type != VMAT_CONTIGUOUS_PERMUTE)
   1772     {
   1773       /* Element X of the data must come from iteration i * VF + X of the
   1774 	 scalar loop.  We need more work to support other mappings.  */
   1775       if (dump_enabled_p ())
   1776 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   1777 			 "can't operate on partial vectors because an"
   1778 			 " access isn't contiguous.\n");
   1779       LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   1780       return;
   1781     }
   1782 
   1783   if (!VECTOR_MODE_P (vecmode))
   1784     {
   1785       if (dump_enabled_p ())
   1786 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   1787 			 "can't operate on partial vectors when emulating"
   1788 			 " vector operations.\n");
   1789       LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   1790       return;
   1791     }
   1792 
   1793   /* We might load more scalars than we need for permuting SLP loads.
   1794      We checked in get_group_load_store_type that the extra elements
   1795      don't leak into a new vector.  */
   1796   auto group_memory_nvectors = [](poly_uint64 size, poly_uint64 nunits)
   1797   {
   1798     unsigned int nvectors;
   1799     if (can_div_away_from_zero_p (size, nunits, &nvectors))
   1800       return nvectors;
   1801     gcc_unreachable ();
   1802   };
   1803 
   1804   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   1805   poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
   1806   machine_mode mask_mode;
   1807   bool using_partial_vectors_p = false;
   1808   if (targetm.vectorize.get_mask_mode (vecmode).exists (&mask_mode)
   1809       && can_vec_mask_load_store_p (vecmode, mask_mode, is_load))
   1810     {
   1811       nvectors = group_memory_nvectors (group_size * vf, nunits);
   1812       vect_record_loop_mask (loop_vinfo, masks, nvectors, vectype, scalar_mask);
   1813       using_partial_vectors_p = true;
   1814     }
   1815 
   1816   machine_mode vmode;
   1817   if (get_len_load_store_mode (vecmode, is_load).exists (&vmode))
   1818     {
   1819       nvectors = group_memory_nvectors (group_size * vf, nunits);
   1820       vec_loop_lens *lens = &LOOP_VINFO_LENS (loop_vinfo);
   1821       unsigned factor = (vecmode == vmode) ? 1 : GET_MODE_UNIT_SIZE (vecmode);
   1822       vect_record_loop_len (loop_vinfo, lens, nvectors, vectype, factor);
   1823       using_partial_vectors_p = true;
   1824     }
   1825 
   1826   if (!using_partial_vectors_p)
   1827     {
   1828       if (dump_enabled_p ())
   1829 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   1830 			 "can't operate on partial vectors because the"
   1831 			 " target doesn't have the appropriate partial"
   1832 			 " vectorization load or store.\n");
   1833       LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   1834     }
   1835 }
   1836 
   1837 /* Return the mask input to a masked load or store.  VEC_MASK is the vectorized
   1838    form of the scalar mask condition and LOOP_MASK, if nonnull, is the mask
   1839    that needs to be applied to all loads and stores in a vectorized loop.
   1840    Return VEC_MASK if LOOP_MASK is null or if VEC_MASK is already masked,
   1841    otherwise return VEC_MASK & LOOP_MASK.
   1842 
   1843    MASK_TYPE is the type of both masks.  If new statements are needed,
   1844    insert them before GSI.  */
   1845 
   1846 static tree
   1847 prepare_vec_mask (loop_vec_info loop_vinfo, tree mask_type, tree loop_mask,
   1848 		  tree vec_mask, gimple_stmt_iterator *gsi)
   1849 {
   1850   gcc_assert (useless_type_conversion_p (mask_type, TREE_TYPE (vec_mask)));
   1851   if (!loop_mask)
   1852     return vec_mask;
   1853 
   1854   gcc_assert (TREE_TYPE (loop_mask) == mask_type);
   1855 
   1856   if (loop_vinfo->vec_cond_masked_set.contains ({ vec_mask, loop_mask }))
   1857     return vec_mask;
   1858 
   1859   tree and_res = make_temp_ssa_name (mask_type, NULL, "vec_mask_and");
   1860   gimple *and_stmt = gimple_build_assign (and_res, BIT_AND_EXPR,
   1861 					  vec_mask, loop_mask);
   1862 
   1863   gsi_insert_before (gsi, and_stmt, GSI_SAME_STMT);
   1864   return and_res;
   1865 }
   1866 
   1867 /* Determine whether we can use a gather load or scatter store to vectorize
   1868    strided load or store STMT_INFO by truncating the current offset to a
   1869    smaller width.  We need to be able to construct an offset vector:
   1870 
   1871      { 0, X, X*2, X*3, ... }
   1872 
   1873    without loss of precision, where X is STMT_INFO's DR_STEP.
   1874 
   1875    Return true if this is possible, describing the gather load or scatter
   1876    store in GS_INFO.  MASKED_P is true if the load or store is conditional.  */
   1877 
   1878 static bool
   1879 vect_truncate_gather_scatter_offset (stmt_vec_info stmt_info,
   1880 				     loop_vec_info loop_vinfo, bool masked_p,
   1881 				     gather_scatter_info *gs_info)
   1882 {
   1883   dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
   1884   data_reference *dr = dr_info->dr;
   1885   tree step = DR_STEP (dr);
   1886   if (TREE_CODE (step) != INTEGER_CST)
   1887     {
   1888       /* ??? Perhaps we could use range information here?  */
   1889       if (dump_enabled_p ())
   1890 	dump_printf_loc (MSG_NOTE, vect_location,
   1891 			 "cannot truncate variable step.\n");
   1892       return false;
   1893     }
   1894 
   1895   /* Get the number of bits in an element.  */
   1896   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   1897   scalar_mode element_mode = SCALAR_TYPE_MODE (TREE_TYPE (vectype));
   1898   unsigned int element_bits = GET_MODE_BITSIZE (element_mode);
   1899 
   1900   /* Set COUNT to the upper limit on the number of elements - 1.
   1901      Start with the maximum vectorization factor.  */
   1902   unsigned HOST_WIDE_INT count = vect_max_vf (loop_vinfo) - 1;
   1903 
   1904   /* Try lowering COUNT to the number of scalar latch iterations.  */
   1905   class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   1906   widest_int max_iters;
   1907   if (max_loop_iterations (loop, &max_iters)
   1908       && max_iters < count)
   1909     count = max_iters.to_shwi ();
   1910 
   1911   /* Try scales of 1 and the element size.  */
   1912   int scales[] = { 1, vect_get_scalar_dr_size (dr_info) };
   1913   wi::overflow_type overflow = wi::OVF_NONE;
   1914   for (int i = 0; i < 2; ++i)
   1915     {
   1916       int scale = scales[i];
   1917       widest_int factor;
   1918       if (!wi::multiple_of_p (wi::to_widest (step), scale, SIGNED, &factor))
   1919 	continue;
   1920 
   1921       /* Determine the minimum precision of (COUNT - 1) * STEP / SCALE.  */
   1922       widest_int range = wi::mul (count, factor, SIGNED, &overflow);
   1923       if (overflow)
   1924 	continue;
   1925       signop sign = range >= 0 ? UNSIGNED : SIGNED;
   1926       unsigned int min_offset_bits = wi::min_precision (range, sign);
   1927 
   1928       /* Find the narrowest viable offset type.  */
   1929       unsigned int offset_bits = 1U << ceil_log2 (min_offset_bits);
   1930       tree offset_type = build_nonstandard_integer_type (offset_bits,
   1931 							 sign == UNSIGNED);
   1932 
   1933       /* See whether the target supports the operation with an offset
   1934 	 no narrower than OFFSET_TYPE.  */
   1935       tree memory_type = TREE_TYPE (DR_REF (dr));
   1936       if (!vect_gather_scatter_fn_p (loop_vinfo, DR_IS_READ (dr), masked_p,
   1937 				     vectype, memory_type, offset_type, scale,
   1938 				     &gs_info->ifn, &gs_info->offset_vectype)
   1939 	  || gs_info->ifn == IFN_LAST)
   1940 	continue;
   1941 
   1942       gs_info->decl = NULL_TREE;
   1943       /* Logically the sum of DR_BASE_ADDRESS, DR_INIT and DR_OFFSET,
   1944 	 but we don't need to store that here.  */
   1945       gs_info->base = NULL_TREE;
   1946       gs_info->element_type = TREE_TYPE (vectype);
   1947       gs_info->offset = fold_convert (offset_type, step);
   1948       gs_info->offset_dt = vect_constant_def;
   1949       gs_info->scale = scale;
   1950       gs_info->memory_type = memory_type;
   1951       return true;
   1952     }
   1953 
   1954   if (overflow && dump_enabled_p ())
   1955     dump_printf_loc (MSG_NOTE, vect_location,
   1956 		     "truncating gather/scatter offset to %d bits"
   1957 		     " might change its value.\n", element_bits);
   1958 
   1959   return false;
   1960 }
   1961 
   1962 /* Return true if we can use gather/scatter internal functions to
   1963    vectorize STMT_INFO, which is a grouped or strided load or store.
   1964    MASKED_P is true if load or store is conditional.  When returning
   1965    true, fill in GS_INFO with the information required to perform the
   1966    operation.  */
   1967 
   1968 static bool
   1969 vect_use_strided_gather_scatters_p (stmt_vec_info stmt_info,
   1970 				    loop_vec_info loop_vinfo, bool masked_p,
   1971 				    gather_scatter_info *gs_info)
   1972 {
   1973   if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info)
   1974       || gs_info->ifn == IFN_LAST)
   1975     return vect_truncate_gather_scatter_offset (stmt_info, loop_vinfo,
   1976 						masked_p, gs_info);
   1977 
   1978   tree old_offset_type = TREE_TYPE (gs_info->offset);
   1979   tree new_offset_type = TREE_TYPE (gs_info->offset_vectype);
   1980 
   1981   gcc_assert (TYPE_PRECISION (new_offset_type)
   1982 	      >= TYPE_PRECISION (old_offset_type));
   1983   gs_info->offset = fold_convert (new_offset_type, gs_info->offset);
   1984 
   1985   if (dump_enabled_p ())
   1986     dump_printf_loc (MSG_NOTE, vect_location,
   1987 		     "using gather/scatter for strided/grouped access,"
   1988 		     " scale = %d\n", gs_info->scale);
   1989 
   1990   return true;
   1991 }
   1992 
   1993 /* STMT_INFO is a non-strided load or store, meaning that it accesses
   1994    elements with a known constant step.  Return -1 if that step
   1995    is negative, 0 if it is zero, and 1 if it is greater than zero.  */
   1996 
   1997 static int
   1998 compare_step_with_zero (vec_info *vinfo, stmt_vec_info stmt_info)
   1999 {
   2000   dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
   2001   return tree_int_cst_compare (vect_dr_behavior (vinfo, dr_info)->step,
   2002 			       size_zero_node);
   2003 }
   2004 
   2005 /* If the target supports a permute mask that reverses the elements in
   2006    a vector of type VECTYPE, return that mask, otherwise return null.  */
   2007 
   2008 static tree
   2009 perm_mask_for_reverse (tree vectype)
   2010 {
   2011   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   2012 
   2013   /* The encoding has a single stepped pattern.  */
   2014   vec_perm_builder sel (nunits, 1, 3);
   2015   for (int i = 0; i < 3; ++i)
   2016     sel.quick_push (nunits - 1 - i);
   2017 
   2018   vec_perm_indices indices (sel, 1, nunits);
   2019   if (!can_vec_perm_const_p (TYPE_MODE (vectype), indices))
   2020     return NULL_TREE;
   2021   return vect_gen_perm_mask_checked (vectype, indices);
   2022 }
   2023 
   2024 /* A subroutine of get_load_store_type, with a subset of the same
   2025    arguments.  Handle the case where STMT_INFO is a load or store that
   2026    accesses consecutive elements with a negative step.  Sets *POFFSET
   2027    to the offset to be applied to the DR for the first access.  */
   2028 
   2029 static vect_memory_access_type
   2030 get_negative_load_store_type (vec_info *vinfo,
   2031 			      stmt_vec_info stmt_info, tree vectype,
   2032 			      vec_load_store_type vls_type,
   2033 			      unsigned int ncopies, poly_int64 *poffset)
   2034 {
   2035   dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
   2036   dr_alignment_support alignment_support_scheme;
   2037 
   2038   if (ncopies > 1)
   2039     {
   2040       if (dump_enabled_p ())
   2041 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2042 			 "multiple types with negative step.\n");
   2043       return VMAT_ELEMENTWISE;
   2044     }
   2045 
   2046   /* For backward running DRs the first access in vectype actually is
   2047      N-1 elements before the address of the DR.  */
   2048   *poffset = ((-TYPE_VECTOR_SUBPARTS (vectype) + 1)
   2049 	      * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype))));
   2050 
   2051   int misalignment = dr_misalignment (dr_info, vectype, *poffset);
   2052   alignment_support_scheme
   2053     = vect_supportable_dr_alignment (vinfo, dr_info, vectype, misalignment);
   2054   if (alignment_support_scheme != dr_aligned
   2055       && alignment_support_scheme != dr_unaligned_supported)
   2056     {
   2057       if (dump_enabled_p ())
   2058 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2059 			 "negative step but alignment required.\n");
   2060       *poffset = 0;
   2061       return VMAT_ELEMENTWISE;
   2062     }
   2063 
   2064   if (vls_type == VLS_STORE_INVARIANT)
   2065     {
   2066       if (dump_enabled_p ())
   2067 	dump_printf_loc (MSG_NOTE, vect_location,
   2068 			 "negative step with invariant source;"
   2069 			 " no permute needed.\n");
   2070       return VMAT_CONTIGUOUS_DOWN;
   2071     }
   2072 
   2073   if (!perm_mask_for_reverse (vectype))
   2074     {
   2075       if (dump_enabled_p ())
   2076 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2077 			 "negative step and reversing not supported.\n");
   2078       *poffset = 0;
   2079       return VMAT_ELEMENTWISE;
   2080     }
   2081 
   2082   return VMAT_CONTIGUOUS_REVERSE;
   2083 }
   2084 
   2085 /* STMT_INFO is either a masked or unconditional store.  Return the value
   2086    being stored.  */
   2087 
   2088 tree
   2089 vect_get_store_rhs (stmt_vec_info stmt_info)
   2090 {
   2091   if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
   2092     {
   2093       gcc_assert (gimple_assign_single_p (assign));
   2094       return gimple_assign_rhs1 (assign);
   2095     }
   2096   if (gcall *call = dyn_cast <gcall *> (stmt_info->stmt))
   2097     {
   2098       internal_fn ifn = gimple_call_internal_fn (call);
   2099       int index = internal_fn_stored_value_index (ifn);
   2100       gcc_assert (index >= 0);
   2101       return gimple_call_arg (call, index);
   2102     }
   2103   gcc_unreachable ();
   2104 }
   2105 
   2106 /* Function VECTOR_VECTOR_COMPOSITION_TYPE
   2107 
   2108    This function returns a vector type which can be composed with NETLS pieces,
   2109    whose type is recorded in PTYPE.  VTYPE should be a vector type, and has the
   2110    same vector size as the return vector.  It checks target whether supports
   2111    pieces-size vector mode for construction firstly, if target fails to, check
   2112    pieces-size scalar mode for construction further.  It returns NULL_TREE if
   2113    fails to find the available composition.
   2114 
   2115    For example, for (vtype=V16QI, nelts=4), we can probably get:
   2116      - V16QI with PTYPE V4QI.
   2117      - V4SI with PTYPE SI.
   2118      - NULL_TREE.  */
   2119 
   2120 static tree
   2121 vector_vector_composition_type (tree vtype, poly_uint64 nelts, tree *ptype)
   2122 {
   2123   gcc_assert (VECTOR_TYPE_P (vtype));
   2124   gcc_assert (known_gt (nelts, 0U));
   2125 
   2126   machine_mode vmode = TYPE_MODE (vtype);
   2127   if (!VECTOR_MODE_P (vmode))
   2128     return NULL_TREE;
   2129 
   2130   poly_uint64 vbsize = GET_MODE_BITSIZE (vmode);
   2131   unsigned int pbsize;
   2132   if (constant_multiple_p (vbsize, nelts, &pbsize))
   2133     {
   2134       /* First check if vec_init optab supports construction from
   2135 	 vector pieces directly.  */
   2136       scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vtype));
   2137       poly_uint64 inelts = pbsize / GET_MODE_BITSIZE (elmode);
   2138       machine_mode rmode;
   2139       if (related_vector_mode (vmode, elmode, inelts).exists (&rmode)
   2140 	  && (convert_optab_handler (vec_init_optab, vmode, rmode)
   2141 	      != CODE_FOR_nothing))
   2142 	{
   2143 	  *ptype = build_vector_type (TREE_TYPE (vtype), inelts);
   2144 	  return vtype;
   2145 	}
   2146 
   2147       /* Otherwise check if exists an integer type of the same piece size and
   2148 	 if vec_init optab supports construction from it directly.  */
   2149       if (int_mode_for_size (pbsize, 0).exists (&elmode)
   2150 	  && related_vector_mode (vmode, elmode, nelts).exists (&rmode)
   2151 	  && (convert_optab_handler (vec_init_optab, rmode, elmode)
   2152 	      != CODE_FOR_nothing))
   2153 	{
   2154 	  *ptype = build_nonstandard_integer_type (pbsize, 1);
   2155 	  return build_vector_type (*ptype, nelts);
   2156 	}
   2157     }
   2158 
   2159   return NULL_TREE;
   2160 }
   2161 
   2162 /* A subroutine of get_load_store_type, with a subset of the same
   2163    arguments.  Handle the case where STMT_INFO is part of a grouped load
   2164    or store.
   2165 
   2166    For stores, the statements in the group are all consecutive
   2167    and there is no gap at the end.  For loads, the statements in the
   2168    group might not be consecutive; there can be gaps between statements
   2169    as well as at the end.  */
   2170 
   2171 static bool
   2172 get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
   2173 			   tree vectype, slp_tree slp_node,
   2174 			   bool masked_p, vec_load_store_type vls_type,
   2175 			   vect_memory_access_type *memory_access_type,
   2176 			   poly_int64 *poffset,
   2177 			   dr_alignment_support *alignment_support_scheme,
   2178 			   int *misalignment,
   2179 			   gather_scatter_info *gs_info)
   2180 {
   2181   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   2182   class loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
   2183   stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   2184   dr_vec_info *first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
   2185   unsigned int group_size = DR_GROUP_SIZE (first_stmt_info);
   2186   bool single_element_p = (stmt_info == first_stmt_info
   2187 			   && !DR_GROUP_NEXT_ELEMENT (stmt_info));
   2188   unsigned HOST_WIDE_INT gap = DR_GROUP_GAP (first_stmt_info);
   2189   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   2190 
   2191   /* True if the vectorized statements would access beyond the last
   2192      statement in the group.  */
   2193   bool overrun_p = false;
   2194 
   2195   /* True if we can cope with such overrun by peeling for gaps, so that
   2196      there is at least one final scalar iteration after the vector loop.  */
   2197   bool can_overrun_p = (!masked_p
   2198 			&& vls_type == VLS_LOAD
   2199 			&& loop_vinfo
   2200 			&& !loop->inner);
   2201 
   2202   /* There can only be a gap at the end of the group if the stride is
   2203      known at compile time.  */
   2204   gcc_assert (!STMT_VINFO_STRIDED_P (first_stmt_info) || gap == 0);
   2205 
   2206   /* Stores can't yet have gaps.  */
   2207   gcc_assert (slp_node || vls_type == VLS_LOAD || gap == 0);
   2208 
   2209   if (slp_node)
   2210     {
   2211       /* For SLP vectorization we directly vectorize a subchain
   2212 	 without permutation.  */
   2213       if (! SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
   2214 	first_dr_info
   2215 	  = STMT_VINFO_DR_INFO (SLP_TREE_SCALAR_STMTS (slp_node)[0]);
   2216       if (STMT_VINFO_STRIDED_P (first_stmt_info))
   2217 	{
   2218 	  /* Try to use consecutive accesses of DR_GROUP_SIZE elements,
   2219 	     separated by the stride, until we have a complete vector.
   2220 	     Fall back to scalar accesses if that isn't possible.  */
   2221 	  if (multiple_p (nunits, group_size))
   2222 	    *memory_access_type = VMAT_STRIDED_SLP;
   2223 	  else
   2224 	    *memory_access_type = VMAT_ELEMENTWISE;
   2225 	}
   2226       else
   2227 	{
   2228 	  overrun_p = loop_vinfo && gap != 0;
   2229 	  if (overrun_p && vls_type != VLS_LOAD)
   2230 	    {
   2231 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2232 			       "Grouped store with gaps requires"
   2233 			       " non-consecutive accesses\n");
   2234 	      return false;
   2235 	    }
   2236 	  /* An overrun is fine if the trailing elements are smaller
   2237 	     than the alignment boundary B.  Every vector access will
   2238 	     be a multiple of B and so we are guaranteed to access a
   2239 	     non-gap element in the same B-sized block.  */
   2240 	  if (overrun_p
   2241 	      && gap < (vect_known_alignment_in_bytes (first_dr_info,
   2242 						       vectype)
   2243 			/ vect_get_scalar_dr_size (first_dr_info)))
   2244 	    overrun_p = false;
   2245 
   2246 	  /* If the gap splits the vector in half and the target
   2247 	     can do half-vector operations avoid the epilogue peeling
   2248 	     by simply loading half of the vector only.  Usually
   2249 	     the construction with an upper zero half will be elided.  */
   2250 	  dr_alignment_support alss;
   2251 	  int misalign = dr_misalignment (first_dr_info, vectype);
   2252 	  tree half_vtype;
   2253 	  if (overrun_p
   2254 	      && !masked_p
   2255 	      && (((alss = vect_supportable_dr_alignment (vinfo, first_dr_info,
   2256 							  vectype, misalign)))
   2257 		   == dr_aligned
   2258 		  || alss == dr_unaligned_supported)
   2259 	      && known_eq (nunits, (group_size - gap) * 2)
   2260 	      && known_eq (nunits, group_size)
   2261 	      && (vector_vector_composition_type (vectype, 2, &half_vtype)
   2262 		  != NULL_TREE))
   2263 	    overrun_p = false;
   2264 
   2265 	  if (overrun_p && !can_overrun_p)
   2266 	    {
   2267 	      if (dump_enabled_p ())
   2268 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2269 				 "Peeling for outer loop is not supported\n");
   2270 	      return false;
   2271 	    }
   2272 	  int cmp = compare_step_with_zero (vinfo, stmt_info);
   2273 	  if (cmp < 0)
   2274 	    {
   2275 	      if (single_element_p)
   2276 		/* ???  The VMAT_CONTIGUOUS_REVERSE code generation is
   2277 		   only correct for single element "interleaving" SLP.  */
   2278 		*memory_access_type = get_negative_load_store_type
   2279 			     (vinfo, stmt_info, vectype, vls_type, 1, poffset);
   2280 	      else
   2281 		{
   2282 		  /* Try to use consecutive accesses of DR_GROUP_SIZE elements,
   2283 		     separated by the stride, until we have a complete vector.
   2284 		     Fall back to scalar accesses if that isn't possible.  */
   2285 		  if (multiple_p (nunits, group_size))
   2286 		    *memory_access_type = VMAT_STRIDED_SLP;
   2287 		  else
   2288 		    *memory_access_type = VMAT_ELEMENTWISE;
   2289 		}
   2290 	    }
   2291 	  else
   2292 	    {
   2293 	      gcc_assert (!loop_vinfo || cmp > 0);
   2294 	      *memory_access_type = VMAT_CONTIGUOUS;
   2295 	    }
   2296 
   2297 	  /* When we have a contiguous access across loop iterations
   2298 	     but the access in the loop doesn't cover the full vector
   2299 	     we can end up with no gap recorded but still excess
   2300 	     elements accessed, see PR103116.  Make sure we peel for
   2301 	     gaps if necessary and sufficient and give up if not.  */
   2302 	  if (loop_vinfo
   2303 	      && *memory_access_type == VMAT_CONTIGUOUS
   2304 	      && SLP_TREE_LOAD_PERMUTATION (slp_node).exists ()
   2305 	      && !multiple_p (group_size * LOOP_VINFO_VECT_FACTOR (loop_vinfo),
   2306 			      nunits))
   2307 	    {
   2308 	      unsigned HOST_WIDE_INT cnunits, cvf;
   2309 	      if (!can_overrun_p
   2310 		  || !nunits.is_constant (&cnunits)
   2311 		  || !LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant (&cvf)
   2312 		  /* Peeling for gaps assumes that a single scalar iteration
   2313 		     is enough to make sure the last vector iteration doesn't
   2314 		     access excess elements.
   2315 		     ???  Enhancements include peeling multiple iterations
   2316 		     or using masked loads with a static mask.  */
   2317 		  || (group_size * cvf) % cnunits + group_size < cnunits)
   2318 		{
   2319 		  if (dump_enabled_p ())
   2320 		    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2321 				     "peeling for gaps insufficient for "
   2322 				     "access\n");
   2323 		  return false;
   2324 		}
   2325 	      overrun_p = true;
   2326 	    }
   2327 	}
   2328     }
   2329   else
   2330     {
   2331       /* We can always handle this case using elementwise accesses,
   2332 	 but see if something more efficient is available.  */
   2333       *memory_access_type = VMAT_ELEMENTWISE;
   2334 
   2335       /* If there is a gap at the end of the group then these optimizations
   2336 	 would access excess elements in the last iteration.  */
   2337       bool would_overrun_p = (gap != 0);
   2338       /* An overrun is fine if the trailing elements are smaller than the
   2339 	 alignment boundary B.  Every vector access will be a multiple of B
   2340 	 and so we are guaranteed to access a non-gap element in the
   2341 	 same B-sized block.  */
   2342       if (would_overrun_p
   2343 	  && !masked_p
   2344 	  && gap < (vect_known_alignment_in_bytes (first_dr_info, vectype)
   2345 		    / vect_get_scalar_dr_size (first_dr_info)))
   2346 	would_overrun_p = false;
   2347 
   2348       if (!STMT_VINFO_STRIDED_P (first_stmt_info)
   2349 	  && (can_overrun_p || !would_overrun_p)
   2350 	  && compare_step_with_zero (vinfo, stmt_info) > 0)
   2351 	{
   2352 	  /* First cope with the degenerate case of a single-element
   2353 	     vector.  */
   2354 	  if (known_eq (TYPE_VECTOR_SUBPARTS (vectype), 1U))
   2355 	    ;
   2356 
   2357 	  /* Otherwise try using LOAD/STORE_LANES.  */
   2358 	  else if (vls_type == VLS_LOAD
   2359 		   ? vect_load_lanes_supported (vectype, group_size, masked_p)
   2360 		   : vect_store_lanes_supported (vectype, group_size,
   2361 						 masked_p))
   2362 	    {
   2363 	      *memory_access_type = VMAT_LOAD_STORE_LANES;
   2364 	      overrun_p = would_overrun_p;
   2365 	    }
   2366 
   2367 	  /* If that fails, try using permuting loads.  */
   2368 	  else if (vls_type == VLS_LOAD
   2369 		   ? vect_grouped_load_supported (vectype, single_element_p,
   2370 						  group_size)
   2371 		   : vect_grouped_store_supported (vectype, group_size))
   2372 	    {
   2373 	      *memory_access_type = VMAT_CONTIGUOUS_PERMUTE;
   2374 	      overrun_p = would_overrun_p;
   2375 	    }
   2376 	}
   2377 
   2378       /* As a last resort, trying using a gather load or scatter store.
   2379 
   2380 	 ??? Although the code can handle all group sizes correctly,
   2381 	 it probably isn't a win to use separate strided accesses based
   2382 	 on nearby locations.  Or, even if it's a win over scalar code,
   2383 	 it might not be a win over vectorizing at a lower VF, if that
   2384 	 allows us to use contiguous accesses.  */
   2385       if (*memory_access_type == VMAT_ELEMENTWISE
   2386 	  && single_element_p
   2387 	  && loop_vinfo
   2388 	  && vect_use_strided_gather_scatters_p (stmt_info, loop_vinfo,
   2389 						 masked_p, gs_info))
   2390 	*memory_access_type = VMAT_GATHER_SCATTER;
   2391     }
   2392 
   2393   if (*memory_access_type == VMAT_GATHER_SCATTER
   2394       || *memory_access_type == VMAT_ELEMENTWISE)
   2395     {
   2396       *alignment_support_scheme = dr_unaligned_supported;
   2397       *misalignment = DR_MISALIGNMENT_UNKNOWN;
   2398     }
   2399   else
   2400     {
   2401       *misalignment = dr_misalignment (first_dr_info, vectype, *poffset);
   2402       *alignment_support_scheme
   2403 	= vect_supportable_dr_alignment (vinfo, first_dr_info, vectype,
   2404 					 *misalignment);
   2405     }
   2406 
   2407   if (vls_type != VLS_LOAD && first_stmt_info == stmt_info)
   2408     {
   2409       /* STMT is the leader of the group. Check the operands of all the
   2410 	 stmts of the group.  */
   2411       stmt_vec_info next_stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info);
   2412       while (next_stmt_info)
   2413 	{
   2414 	  tree op = vect_get_store_rhs (next_stmt_info);
   2415 	  enum vect_def_type dt;
   2416 	  if (!vect_is_simple_use (op, vinfo, &dt))
   2417 	    {
   2418 	      if (dump_enabled_p ())
   2419 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2420 				 "use not simple.\n");
   2421 	      return false;
   2422 	    }
   2423 	  next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
   2424 	}
   2425     }
   2426 
   2427   if (overrun_p)
   2428     {
   2429       gcc_assert (can_overrun_p);
   2430       if (dump_enabled_p ())
   2431 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2432 			 "Data access with gaps requires scalar "
   2433 			 "epilogue loop\n");
   2434       LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo) = true;
   2435     }
   2436 
   2437   return true;
   2438 }
   2439 
   2440 /* Analyze load or store statement STMT_INFO of type VLS_TYPE.  Return true
   2441    if there is a memory access type that the vectorized form can use,
   2442    storing it in *MEMORY_ACCESS_TYPE if so.  If we decide to use gathers
   2443    or scatters, fill in GS_INFO accordingly.  In addition
   2444    *ALIGNMENT_SUPPORT_SCHEME is filled out and false is returned if
   2445    the target does not support the alignment scheme.  *MISALIGNMENT
   2446    is set according to the alignment of the access (including
   2447    DR_MISALIGNMENT_UNKNOWN when it is unknown).
   2448 
   2449    SLP says whether we're performing SLP rather than loop vectorization.
   2450    MASKED_P is true if the statement is conditional on a vectorized mask.
   2451    VECTYPE is the vector type that the vectorized statements will use.
   2452    NCOPIES is the number of vector statements that will be needed.  */
   2453 
   2454 static bool
   2455 get_load_store_type (vec_info  *vinfo, stmt_vec_info stmt_info,
   2456 		     tree vectype, slp_tree slp_node,
   2457 		     bool masked_p, vec_load_store_type vls_type,
   2458 		     unsigned int ncopies,
   2459 		     vect_memory_access_type *memory_access_type,
   2460 		     poly_int64 *poffset,
   2461 		     dr_alignment_support *alignment_support_scheme,
   2462 		     int *misalignment,
   2463 		     gather_scatter_info *gs_info)
   2464 {
   2465   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   2466   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   2467   *misalignment = DR_MISALIGNMENT_UNKNOWN;
   2468   *poffset = 0;
   2469   if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   2470     {
   2471       *memory_access_type = VMAT_GATHER_SCATTER;
   2472       if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info))
   2473 	gcc_unreachable ();
   2474       else if (!vect_is_simple_use (gs_info->offset, vinfo,
   2475 				    &gs_info->offset_dt,
   2476 				    &gs_info->offset_vectype))
   2477 	{
   2478 	  if (dump_enabled_p ())
   2479 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2480 			     "%s index use not simple.\n",
   2481 			     vls_type == VLS_LOAD ? "gather" : "scatter");
   2482 	  return false;
   2483 	}
   2484       else if (gs_info->ifn == IFN_LAST && !gs_info->decl)
   2485 	{
   2486 	  if (vls_type != VLS_LOAD)
   2487 	    {
   2488 	      if (dump_enabled_p ())
   2489 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2490 				 "unsupported emulated scatter.\n");
   2491 	      return false;
   2492 	    }
   2493 	  else if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant ()
   2494 		   || !TYPE_VECTOR_SUBPARTS
   2495 			 (gs_info->offset_vectype).is_constant ()
   2496 		   || VECTOR_BOOLEAN_TYPE_P (gs_info->offset_vectype)
   2497 		   || !constant_multiple_p (TYPE_VECTOR_SUBPARTS
   2498 					      (gs_info->offset_vectype),
   2499 					    TYPE_VECTOR_SUBPARTS (vectype)))
   2500 	    {
   2501 	      if (dump_enabled_p ())
   2502 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2503 				 "unsupported vector types for emulated "
   2504 				 "gather.\n");
   2505 	      return false;
   2506 	    }
   2507 	}
   2508       /* Gather-scatter accesses perform only component accesses, alignment
   2509 	 is irrelevant for them.  */
   2510       *alignment_support_scheme = dr_unaligned_supported;
   2511     }
   2512   else if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
   2513     {
   2514       if (!get_group_load_store_type (vinfo, stmt_info, vectype, slp_node,
   2515 				      masked_p,
   2516 				      vls_type, memory_access_type, poffset,
   2517 				      alignment_support_scheme,
   2518 				      misalignment, gs_info))
   2519 	return false;
   2520     }
   2521   else if (STMT_VINFO_STRIDED_P (stmt_info))
   2522     {
   2523       gcc_assert (!slp_node);
   2524       if (loop_vinfo
   2525 	  && vect_use_strided_gather_scatters_p (stmt_info, loop_vinfo,
   2526 						 masked_p, gs_info))
   2527 	*memory_access_type = VMAT_GATHER_SCATTER;
   2528       else
   2529 	*memory_access_type = VMAT_ELEMENTWISE;
   2530       /* Alignment is irrelevant here.  */
   2531       *alignment_support_scheme = dr_unaligned_supported;
   2532     }
   2533   else
   2534     {
   2535       int cmp = compare_step_with_zero (vinfo, stmt_info);
   2536       if (cmp == 0)
   2537 	{
   2538 	  gcc_assert (vls_type == VLS_LOAD);
   2539 	  *memory_access_type = VMAT_INVARIANT;
   2540 	  /* Invariant accesses perform only component accesses, alignment
   2541 	     is irrelevant for them.  */
   2542 	  *alignment_support_scheme = dr_unaligned_supported;
   2543 	}
   2544       else
   2545 	{
   2546 	  if (cmp < 0)
   2547 	    *memory_access_type = get_negative_load_store_type
   2548 	       (vinfo, stmt_info, vectype, vls_type, ncopies, poffset);
   2549 	  else
   2550 	    *memory_access_type = VMAT_CONTIGUOUS;
   2551 	  *misalignment = dr_misalignment (STMT_VINFO_DR_INFO (stmt_info),
   2552 					   vectype, *poffset);
   2553 	  *alignment_support_scheme
   2554 	    = vect_supportable_dr_alignment (vinfo,
   2555 					     STMT_VINFO_DR_INFO (stmt_info),
   2556 					     vectype, *misalignment);
   2557 	}
   2558     }
   2559 
   2560   if ((*memory_access_type == VMAT_ELEMENTWISE
   2561        || *memory_access_type == VMAT_STRIDED_SLP)
   2562       && !nunits.is_constant ())
   2563     {
   2564       if (dump_enabled_p ())
   2565 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2566 			 "Not using elementwise accesses due to variable "
   2567 			 "vectorization factor.\n");
   2568       return false;
   2569     }
   2570 
   2571   if (*alignment_support_scheme == dr_unaligned_unsupported)
   2572     {
   2573       if (dump_enabled_p ())
   2574 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2575 			 "unsupported unaligned access\n");
   2576       return false;
   2577     }
   2578 
   2579   /* FIXME: At the moment the cost model seems to underestimate the
   2580      cost of using elementwise accesses.  This check preserves the
   2581      traditional behavior until that can be fixed.  */
   2582   stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   2583   if (!first_stmt_info)
   2584     first_stmt_info = stmt_info;
   2585   if (*memory_access_type == VMAT_ELEMENTWISE
   2586       && !STMT_VINFO_STRIDED_P (first_stmt_info)
   2587       && !(stmt_info == DR_GROUP_FIRST_ELEMENT (stmt_info)
   2588 	   && !DR_GROUP_NEXT_ELEMENT (stmt_info)
   2589 	   && !pow2p_hwi (DR_GROUP_SIZE (stmt_info))))
   2590     {
   2591       if (dump_enabled_p ())
   2592 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2593 			 "not falling back to elementwise accesses\n");
   2594       return false;
   2595     }
   2596   return true;
   2597 }
   2598 
   2599 /* Return true if boolean argument at MASK_INDEX is suitable for vectorizing
   2600    conditional operation STMT_INFO.  When returning true, store the mask
   2601    in *MASK, the type of its definition in *MASK_DT_OUT, the type of the
   2602    vectorized mask in *MASK_VECTYPE_OUT and the SLP node corresponding
   2603    to the mask in *MASK_NODE if MASK_NODE is not NULL.  */
   2604 
   2605 static bool
   2606 vect_check_scalar_mask (vec_info *vinfo, stmt_vec_info stmt_info,
   2607 			slp_tree slp_node, unsigned mask_index,
   2608 			tree *mask, slp_tree *mask_node,
   2609 			vect_def_type *mask_dt_out, tree *mask_vectype_out)
   2610 {
   2611   enum vect_def_type mask_dt;
   2612   tree mask_vectype;
   2613   slp_tree mask_node_1;
   2614   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, mask_index,
   2615 			   mask, &mask_node_1, &mask_dt, &mask_vectype))
   2616     {
   2617       if (dump_enabled_p ())
   2618 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2619 			 "mask use not simple.\n");
   2620       return false;
   2621     }
   2622 
   2623   if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (*mask)))
   2624     {
   2625       if (dump_enabled_p ())
   2626 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2627 			 "mask argument is not a boolean.\n");
   2628       return false;
   2629     }
   2630 
   2631   /* If the caller is not prepared for adjusting an external/constant
   2632      SLP mask vector type fail.  */
   2633   if (slp_node
   2634       && !mask_node
   2635       && SLP_TREE_DEF_TYPE (mask_node_1) != vect_internal_def)
   2636     {
   2637       if (dump_enabled_p ())
   2638 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2639 			 "SLP mask argument is not vectorized.\n");
   2640       return false;
   2641     }
   2642 
   2643   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   2644   if (!mask_vectype)
   2645     mask_vectype = get_mask_type_for_scalar_type (vinfo, TREE_TYPE (vectype));
   2646 
   2647   if (!mask_vectype || !VECTOR_BOOLEAN_TYPE_P (mask_vectype))
   2648     {
   2649       if (dump_enabled_p ())
   2650 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2651 			 "could not find an appropriate vector mask type.\n");
   2652       return false;
   2653     }
   2654 
   2655   if (maybe_ne (TYPE_VECTOR_SUBPARTS (mask_vectype),
   2656 		TYPE_VECTOR_SUBPARTS (vectype)))
   2657     {
   2658       if (dump_enabled_p ())
   2659 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2660 			 "vector mask type %T"
   2661 			 " does not match vector data type %T.\n",
   2662 			 mask_vectype, vectype);
   2663 
   2664       return false;
   2665     }
   2666 
   2667   *mask_dt_out = mask_dt;
   2668   *mask_vectype_out = mask_vectype;
   2669   if (mask_node)
   2670     *mask_node = mask_node_1;
   2671   return true;
   2672 }
   2673 
   2674 /* Return true if stored value RHS is suitable for vectorizing store
   2675    statement STMT_INFO.  When returning true, store the type of the
   2676    definition in *RHS_DT_OUT, the type of the vectorized store value in
   2677    *RHS_VECTYPE_OUT and the type of the store in *VLS_TYPE_OUT.  */
   2678 
   2679 static bool
   2680 vect_check_store_rhs (vec_info *vinfo, stmt_vec_info stmt_info,
   2681 		      slp_tree slp_node, tree rhs,
   2682 		      vect_def_type *rhs_dt_out, tree *rhs_vectype_out,
   2683 		      vec_load_store_type *vls_type_out)
   2684 {
   2685   /* In the case this is a store from a constant make sure
   2686      native_encode_expr can handle it.  */
   2687   if (CONSTANT_CLASS_P (rhs) && native_encode_expr (rhs, NULL, 64) == 0)
   2688     {
   2689       if (dump_enabled_p ())
   2690 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2691 			 "cannot encode constant as a byte sequence.\n");
   2692       return false;
   2693     }
   2694 
   2695   unsigned op_no = 0;
   2696   if (gcall *call = dyn_cast <gcall *> (stmt_info->stmt))
   2697     {
   2698       if (gimple_call_internal_p (call)
   2699 	  && internal_store_fn_p (gimple_call_internal_fn (call)))
   2700 	op_no = internal_fn_stored_value_index (gimple_call_internal_fn (call));
   2701     }
   2702 
   2703   enum vect_def_type rhs_dt;
   2704   tree rhs_vectype;
   2705   slp_tree slp_op;
   2706   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, op_no,
   2707 			   &rhs, &slp_op, &rhs_dt, &rhs_vectype))
   2708     {
   2709       if (dump_enabled_p ())
   2710 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2711 			 "use not simple.\n");
   2712       return false;
   2713     }
   2714 
   2715   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   2716   if (rhs_vectype && !useless_type_conversion_p (vectype, rhs_vectype))
   2717     {
   2718       if (dump_enabled_p ())
   2719 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   2720 			 "incompatible vector types.\n");
   2721       return false;
   2722     }
   2723 
   2724   *rhs_dt_out = rhs_dt;
   2725   *rhs_vectype_out = rhs_vectype;
   2726   if (rhs_dt == vect_constant_def || rhs_dt == vect_external_def)
   2727     *vls_type_out = VLS_STORE_INVARIANT;
   2728   else
   2729     *vls_type_out = VLS_STORE;
   2730   return true;
   2731 }
   2732 
   2733 /* Build an all-ones vector mask of type MASKTYPE while vectorizing STMT_INFO.
   2734    Note that we support masks with floating-point type, in which case the
   2735    floats are interpreted as a bitmask.  */
   2736 
   2737 static tree
   2738 vect_build_all_ones_mask (vec_info *vinfo,
   2739 			  stmt_vec_info stmt_info, tree masktype)
   2740 {
   2741   if (TREE_CODE (masktype) == INTEGER_TYPE)
   2742     return build_int_cst (masktype, -1);
   2743   else if (TREE_CODE (TREE_TYPE (masktype)) == INTEGER_TYPE)
   2744     {
   2745       tree mask = build_int_cst (TREE_TYPE (masktype), -1);
   2746       mask = build_vector_from_val (masktype, mask);
   2747       return vect_init_vector (vinfo, stmt_info, mask, masktype, NULL);
   2748     }
   2749   else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (masktype)))
   2750     {
   2751       REAL_VALUE_TYPE r;
   2752       long tmp[6];
   2753       for (int j = 0; j < 6; ++j)
   2754 	tmp[j] = -1;
   2755       real_from_target (&r, tmp, TYPE_MODE (TREE_TYPE (masktype)));
   2756       tree mask = build_real (TREE_TYPE (masktype), r);
   2757       mask = build_vector_from_val (masktype, mask);
   2758       return vect_init_vector (vinfo, stmt_info, mask, masktype, NULL);
   2759     }
   2760   gcc_unreachable ();
   2761 }
   2762 
   2763 /* Build an all-zero merge value of type VECTYPE while vectorizing
   2764    STMT_INFO as a gather load.  */
   2765 
   2766 static tree
   2767 vect_build_zero_merge_argument (vec_info *vinfo,
   2768 				stmt_vec_info stmt_info, tree vectype)
   2769 {
   2770   tree merge;
   2771   if (TREE_CODE (TREE_TYPE (vectype)) == INTEGER_TYPE)
   2772     merge = build_int_cst (TREE_TYPE (vectype), 0);
   2773   else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (vectype)))
   2774     {
   2775       REAL_VALUE_TYPE r;
   2776       long tmp[6];
   2777       for (int j = 0; j < 6; ++j)
   2778 	tmp[j] = 0;
   2779       real_from_target (&r, tmp, TYPE_MODE (TREE_TYPE (vectype)));
   2780       merge = build_real (TREE_TYPE (vectype), r);
   2781     }
   2782   else
   2783     gcc_unreachable ();
   2784   merge = build_vector_from_val (vectype, merge);
   2785   return vect_init_vector (vinfo, stmt_info, merge, vectype, NULL);
   2786 }
   2787 
   2788 /* Build a gather load call while vectorizing STMT_INFO.  Insert new
   2789    instructions before GSI and add them to VEC_STMT.  GS_INFO describes
   2790    the gather load operation.  If the load is conditional, MASK is the
   2791    unvectorized condition and MASK_DT is its definition type, otherwise
   2792    MASK is null.  */
   2793 
   2794 static void
   2795 vect_build_gather_load_calls (vec_info *vinfo, stmt_vec_info stmt_info,
   2796 			      gimple_stmt_iterator *gsi,
   2797 			      gimple **vec_stmt,
   2798 			      gather_scatter_info *gs_info,
   2799 			      tree mask)
   2800 {
   2801   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   2802   class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   2803   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   2804   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   2805   int ncopies = vect_get_num_copies (loop_vinfo, vectype);
   2806   edge pe = loop_preheader_edge (loop);
   2807   enum { NARROW, NONE, WIDEN } modifier;
   2808   poly_uint64 gather_off_nunits
   2809     = TYPE_VECTOR_SUBPARTS (gs_info->offset_vectype);
   2810 
   2811   tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gs_info->decl));
   2812   tree rettype = TREE_TYPE (TREE_TYPE (gs_info->decl));
   2813   tree srctype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   2814   tree ptrtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   2815   tree idxtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   2816   tree masktype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   2817   tree scaletype = TREE_VALUE (arglist);
   2818   tree real_masktype = masktype;
   2819   gcc_checking_assert (types_compatible_p (srctype, rettype)
   2820 		       && (!mask
   2821 			   || TREE_CODE (masktype) == INTEGER_TYPE
   2822 			   || types_compatible_p (srctype, masktype)));
   2823   if (mask)
   2824     masktype = truth_type_for (srctype);
   2825 
   2826   tree mask_halftype = masktype;
   2827   tree perm_mask = NULL_TREE;
   2828   tree mask_perm_mask = NULL_TREE;
   2829   if (known_eq (nunits, gather_off_nunits))
   2830     modifier = NONE;
   2831   else if (known_eq (nunits * 2, gather_off_nunits))
   2832     {
   2833       modifier = WIDEN;
   2834 
   2835       /* Currently widening gathers and scatters are only supported for
   2836 	 fixed-length vectors.  */
   2837       int count = gather_off_nunits.to_constant ();
   2838       vec_perm_builder sel (count, count, 1);
   2839       for (int i = 0; i < count; ++i)
   2840 	sel.quick_push (i | (count / 2));
   2841 
   2842       vec_perm_indices indices (sel, 1, count);
   2843       perm_mask = vect_gen_perm_mask_checked (gs_info->offset_vectype,
   2844 					      indices);
   2845     }
   2846   else if (known_eq (nunits, gather_off_nunits * 2))
   2847     {
   2848       modifier = NARROW;
   2849 
   2850       /* Currently narrowing gathers and scatters are only supported for
   2851 	 fixed-length vectors.  */
   2852       int count = nunits.to_constant ();
   2853       vec_perm_builder sel (count, count, 1);
   2854       sel.quick_grow (count);
   2855       for (int i = 0; i < count; ++i)
   2856 	sel[i] = i < count / 2 ? i : i + count / 2;
   2857       vec_perm_indices indices (sel, 2, count);
   2858       perm_mask = vect_gen_perm_mask_checked (vectype, indices);
   2859 
   2860       ncopies *= 2;
   2861 
   2862       if (mask && VECTOR_TYPE_P (real_masktype))
   2863 	{
   2864 	  for (int i = 0; i < count; ++i)
   2865 	    sel[i] = i | (count / 2);
   2866 	  indices.new_vector (sel, 2, count);
   2867 	  mask_perm_mask = vect_gen_perm_mask_checked (masktype, indices);
   2868 	}
   2869       else if (mask)
   2870 	mask_halftype = truth_type_for (gs_info->offset_vectype);
   2871     }
   2872   else
   2873     gcc_unreachable ();
   2874 
   2875   tree scalar_dest = gimple_get_lhs (stmt_info->stmt);
   2876   tree vec_dest = vect_create_destination_var (scalar_dest, vectype);
   2877 
   2878   tree ptr = fold_convert (ptrtype, gs_info->base);
   2879   if (!is_gimple_min_invariant (ptr))
   2880     {
   2881       gimple_seq seq;
   2882       ptr = force_gimple_operand (ptr, &seq, true, NULL_TREE);
   2883       basic_block new_bb = gsi_insert_seq_on_edge_immediate (pe, seq);
   2884       gcc_assert (!new_bb);
   2885     }
   2886 
   2887   tree scale = build_int_cst (scaletype, gs_info->scale);
   2888 
   2889   tree vec_oprnd0 = NULL_TREE;
   2890   tree vec_mask = NULL_TREE;
   2891   tree src_op = NULL_TREE;
   2892   tree mask_op = NULL_TREE;
   2893   tree prev_res = NULL_TREE;
   2894 
   2895   if (!mask)
   2896     {
   2897       src_op = vect_build_zero_merge_argument (vinfo, stmt_info, rettype);
   2898       mask_op = vect_build_all_ones_mask (vinfo, stmt_info, masktype);
   2899     }
   2900 
   2901   auto_vec<tree> vec_oprnds0;
   2902   auto_vec<tree> vec_masks;
   2903   vect_get_vec_defs_for_operand (vinfo, stmt_info,
   2904 				 modifier == WIDEN ? ncopies / 2 : ncopies,
   2905 				 gs_info->offset, &vec_oprnds0);
   2906   if (mask)
   2907     vect_get_vec_defs_for_operand (vinfo, stmt_info,
   2908 				   modifier == NARROW ? ncopies / 2 : ncopies,
   2909 				   mask, &vec_masks, masktype);
   2910   for (int j = 0; j < ncopies; ++j)
   2911     {
   2912       tree op, var;
   2913       if (modifier == WIDEN && (j & 1))
   2914 	op = permute_vec_elements (vinfo, vec_oprnd0, vec_oprnd0,
   2915 				   perm_mask, stmt_info, gsi);
   2916       else
   2917 	op = vec_oprnd0 = vec_oprnds0[modifier == WIDEN ? j / 2 : j];
   2918 
   2919       if (!useless_type_conversion_p (idxtype, TREE_TYPE (op)))
   2920 	{
   2921 	  gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (op)),
   2922 				TYPE_VECTOR_SUBPARTS (idxtype)));
   2923 	  var = vect_get_new_ssa_name (idxtype, vect_simple_var);
   2924 	  op = build1 (VIEW_CONVERT_EXPR, idxtype, op);
   2925 	  gassign *new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
   2926 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   2927 	  op = var;
   2928 	}
   2929 
   2930       if (mask)
   2931 	{
   2932 	  if (mask_perm_mask && (j & 1))
   2933 	    mask_op = permute_vec_elements (vinfo, mask_op, mask_op,
   2934 					    mask_perm_mask, stmt_info, gsi);
   2935 	  else
   2936 	    {
   2937 	      if (modifier == NARROW)
   2938 		{
   2939 		  if ((j & 1) == 0)
   2940 		    vec_mask = vec_masks[j / 2];
   2941 		}
   2942 	      else
   2943 		vec_mask = vec_masks[j];
   2944 
   2945 	      mask_op = vec_mask;
   2946 	      if (!useless_type_conversion_p (masktype, TREE_TYPE (vec_mask)))
   2947 		{
   2948 		  poly_uint64 sub1 = TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask_op));
   2949 		  poly_uint64 sub2 = TYPE_VECTOR_SUBPARTS (masktype);
   2950 		  gcc_assert (known_eq (sub1, sub2));
   2951 		  var = vect_get_new_ssa_name (masktype, vect_simple_var);
   2952 		  mask_op = build1 (VIEW_CONVERT_EXPR, masktype, mask_op);
   2953 		  gassign *new_stmt
   2954 		    = gimple_build_assign (var, VIEW_CONVERT_EXPR, mask_op);
   2955 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   2956 		  mask_op = var;
   2957 		}
   2958 	    }
   2959 	  if (modifier == NARROW && !VECTOR_TYPE_P (real_masktype))
   2960 	    {
   2961 	      var = vect_get_new_ssa_name (mask_halftype, vect_simple_var);
   2962 	      gassign *new_stmt
   2963 		= gimple_build_assign (var, (j & 1) ? VEC_UNPACK_HI_EXPR
   2964 						    : VEC_UNPACK_LO_EXPR,
   2965 				       mask_op);
   2966 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   2967 	      mask_op = var;
   2968 	    }
   2969 	  src_op = mask_op;
   2970 	}
   2971 
   2972       tree mask_arg = mask_op;
   2973       if (masktype != real_masktype)
   2974 	{
   2975 	  tree utype, optype = TREE_TYPE (mask_op);
   2976 	  if (VECTOR_TYPE_P (real_masktype)
   2977 	      || TYPE_MODE (real_masktype) == TYPE_MODE (optype))
   2978 	    utype = real_masktype;
   2979 	  else
   2980 	    utype = lang_hooks.types.type_for_mode (TYPE_MODE (optype), 1);
   2981 	  var = vect_get_new_ssa_name (utype, vect_scalar_var);
   2982 	  mask_arg = build1 (VIEW_CONVERT_EXPR, utype, mask_op);
   2983 	  gassign *new_stmt
   2984 	    = gimple_build_assign (var, VIEW_CONVERT_EXPR, mask_arg);
   2985 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   2986 	  mask_arg = var;
   2987 	  if (!useless_type_conversion_p (real_masktype, utype))
   2988 	    {
   2989 	      gcc_assert (TYPE_PRECISION (utype)
   2990 			  <= TYPE_PRECISION (real_masktype));
   2991 	      var = vect_get_new_ssa_name (real_masktype, vect_scalar_var);
   2992 	      new_stmt = gimple_build_assign (var, NOP_EXPR, mask_arg);
   2993 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   2994 	      mask_arg = var;
   2995 	    }
   2996 	  src_op = build_zero_cst (srctype);
   2997 	}
   2998       gimple *new_stmt = gimple_build_call (gs_info->decl, 5, src_op, ptr, op,
   2999 					    mask_arg, scale);
   3000 
   3001       if (!useless_type_conversion_p (vectype, rettype))
   3002 	{
   3003 	  gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (vectype),
   3004 				TYPE_VECTOR_SUBPARTS (rettype)));
   3005 	  op = vect_get_new_ssa_name (rettype, vect_simple_var);
   3006 	  gimple_call_set_lhs (new_stmt, op);
   3007 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3008 	  var = make_ssa_name (vec_dest);
   3009 	  op = build1 (VIEW_CONVERT_EXPR, vectype, op);
   3010 	  new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
   3011 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3012 	}
   3013       else
   3014 	{
   3015 	  var = make_ssa_name (vec_dest, new_stmt);
   3016 	  gimple_call_set_lhs (new_stmt, var);
   3017 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3018 	}
   3019 
   3020       if (modifier == NARROW)
   3021 	{
   3022 	  if ((j & 1) == 0)
   3023 	    {
   3024 	      prev_res = var;
   3025 	      continue;
   3026 	    }
   3027 	  var = permute_vec_elements (vinfo, prev_res, var, perm_mask,
   3028 				      stmt_info, gsi);
   3029 	  new_stmt = SSA_NAME_DEF_STMT (var);
   3030 	}
   3031 
   3032       STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   3033     }
   3034   *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   3035 }
   3036 
   3037 /* Prepare the base and offset in GS_INFO for vectorization.
   3038    Set *DATAREF_PTR to the loop-invariant base address and *VEC_OFFSET
   3039    to the vectorized offset argument for the first copy of STMT_INFO.
   3040    STMT_INFO is the statement described by GS_INFO and LOOP is the
   3041    containing loop.  */
   3042 
   3043 static void
   3044 vect_get_gather_scatter_ops (loop_vec_info loop_vinfo,
   3045 			     class loop *loop, stmt_vec_info stmt_info,
   3046 			     slp_tree slp_node, gather_scatter_info *gs_info,
   3047 			     tree *dataref_ptr, vec<tree> *vec_offset)
   3048 {
   3049   gimple_seq stmts = NULL;
   3050   *dataref_ptr = force_gimple_operand (gs_info->base, &stmts, true, NULL_TREE);
   3051   if (stmts != NULL)
   3052     {
   3053       basic_block new_bb;
   3054       edge pe = loop_preheader_edge (loop);
   3055       new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
   3056       gcc_assert (!new_bb);
   3057     }
   3058   if (slp_node)
   3059     vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[0], vec_offset);
   3060   else
   3061     {
   3062       unsigned ncopies
   3063 	= vect_get_num_copies (loop_vinfo, gs_info->offset_vectype);
   3064       vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, ncopies,
   3065 				     gs_info->offset, vec_offset,
   3066 				     gs_info->offset_vectype);
   3067     }
   3068 }
   3069 
   3070 /* Prepare to implement a grouped or strided load or store using
   3071    the gather load or scatter store operation described by GS_INFO.
   3072    STMT_INFO is the load or store statement.
   3073 
   3074    Set *DATAREF_BUMP to the amount that should be added to the base
   3075    address after each copy of the vectorized statement.  Set *VEC_OFFSET
   3076    to an invariant offset vector in which element I has the value
   3077    I * DR_STEP / SCALE.  */
   3078 
   3079 static void
   3080 vect_get_strided_load_store_ops (stmt_vec_info stmt_info,
   3081 				 loop_vec_info loop_vinfo,
   3082 				 gather_scatter_info *gs_info,
   3083 				 tree *dataref_bump, tree *vec_offset)
   3084 {
   3085   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
   3086   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   3087 
   3088   tree bump = size_binop (MULT_EXPR,
   3089 			  fold_convert (sizetype, unshare_expr (DR_STEP (dr))),
   3090 			  size_int (TYPE_VECTOR_SUBPARTS (vectype)));
   3091   *dataref_bump = cse_and_gimplify_to_preheader (loop_vinfo, bump);
   3092 
   3093   /* The offset given in GS_INFO can have pointer type, so use the element
   3094      type of the vector instead.  */
   3095   tree offset_type = TREE_TYPE (gs_info->offset_vectype);
   3096 
   3097   /* Calculate X = DR_STEP / SCALE and convert it to the appropriate type.  */
   3098   tree step = size_binop (EXACT_DIV_EXPR, unshare_expr (DR_STEP (dr)),
   3099 			  ssize_int (gs_info->scale));
   3100   step = fold_convert (offset_type, step);
   3101 
   3102   /* Create {0, X, X*2, X*3, ...}.  */
   3103   tree offset = fold_build2 (VEC_SERIES_EXPR, gs_info->offset_vectype,
   3104 			     build_zero_cst (offset_type), step);
   3105   *vec_offset = cse_and_gimplify_to_preheader (loop_vinfo, offset);
   3106 }
   3107 
   3108 /* Return the amount that should be added to a vector pointer to move
   3109    to the next or previous copy of AGGR_TYPE.  DR_INFO is the data reference
   3110    being vectorized and MEMORY_ACCESS_TYPE describes the type of
   3111    vectorization.  */
   3112 
   3113 static tree
   3114 vect_get_data_ptr_increment (vec_info *vinfo,
   3115 			     dr_vec_info *dr_info, tree aggr_type,
   3116 			     vect_memory_access_type memory_access_type)
   3117 {
   3118   if (memory_access_type == VMAT_INVARIANT)
   3119     return size_zero_node;
   3120 
   3121   tree iv_step = TYPE_SIZE_UNIT (aggr_type);
   3122   tree step = vect_dr_behavior (vinfo, dr_info)->step;
   3123   if (tree_int_cst_sgn (step) == -1)
   3124     iv_step = fold_build1 (NEGATE_EXPR, TREE_TYPE (iv_step), iv_step);
   3125   return iv_step;
   3126 }
   3127 
   3128 /* Check and perform vectorization of BUILT_IN_BSWAP{16,32,64,128}.  */
   3129 
   3130 static bool
   3131 vectorizable_bswap (vec_info *vinfo,
   3132 		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   3133 		    gimple **vec_stmt, slp_tree slp_node,
   3134 		    slp_tree *slp_op,
   3135 		    tree vectype_in, stmt_vector_for_cost *cost_vec)
   3136 {
   3137   tree op, vectype;
   3138   gcall *stmt = as_a <gcall *> (stmt_info->stmt);
   3139   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   3140   unsigned ncopies;
   3141 
   3142   op = gimple_call_arg (stmt, 0);
   3143   vectype = STMT_VINFO_VECTYPE (stmt_info);
   3144   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   3145 
   3146   /* Multiple types in SLP are handled by creating the appropriate number of
   3147      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
   3148      case of SLP.  */
   3149   if (slp_node)
   3150     ncopies = 1;
   3151   else
   3152     ncopies = vect_get_num_copies (loop_vinfo, vectype);
   3153 
   3154   gcc_assert (ncopies >= 1);
   3155 
   3156   tree char_vectype = get_same_sized_vectype (char_type_node, vectype_in);
   3157   if (! char_vectype)
   3158     return false;
   3159 
   3160   poly_uint64 num_bytes = TYPE_VECTOR_SUBPARTS (char_vectype);
   3161   unsigned word_bytes;
   3162   if (!constant_multiple_p (num_bytes, nunits, &word_bytes))
   3163     return false;
   3164 
   3165   /* The encoding uses one stepped pattern for each byte in the word.  */
   3166   vec_perm_builder elts (num_bytes, word_bytes, 3);
   3167   for (unsigned i = 0; i < 3; ++i)
   3168     for (unsigned j = 0; j < word_bytes; ++j)
   3169       elts.quick_push ((i + 1) * word_bytes - j - 1);
   3170 
   3171   vec_perm_indices indices (elts, 1, num_bytes);
   3172   if (!can_vec_perm_const_p (TYPE_MODE (char_vectype), indices))
   3173     return false;
   3174 
   3175   if (! vec_stmt)
   3176     {
   3177       if (slp_node
   3178 	  && !vect_maybe_update_slp_op_vectype (slp_op[0], vectype_in))
   3179 	{
   3180 	  if (dump_enabled_p ())
   3181 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3182 			     "incompatible vector types for invariants\n");
   3183 	  return false;
   3184 	}
   3185 
   3186       STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
   3187       DUMP_VECT_SCOPE ("vectorizable_bswap");
   3188       record_stmt_cost (cost_vec,
   3189 			1, vector_stmt, stmt_info, 0, vect_prologue);
   3190       record_stmt_cost (cost_vec,
   3191 			slp_node
   3192 			? SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) : ncopies,
   3193 			vec_perm, stmt_info, 0, vect_body);
   3194       return true;
   3195     }
   3196 
   3197   tree bswap_vconst = vec_perm_indices_to_tree (char_vectype, indices);
   3198 
   3199   /* Transform.  */
   3200   vec<tree> vec_oprnds = vNULL;
   3201   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   3202 		     op, &vec_oprnds);
   3203   /* Arguments are ready. create the new vector stmt.  */
   3204   unsigned i;
   3205   tree vop;
   3206   FOR_EACH_VEC_ELT (vec_oprnds, i, vop)
   3207     {
   3208       gimple *new_stmt;
   3209       tree tem = make_ssa_name (char_vectype);
   3210       new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
   3211 						   char_vectype, vop));
   3212       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3213       tree tem2 = make_ssa_name (char_vectype);
   3214       new_stmt = gimple_build_assign (tem2, VEC_PERM_EXPR,
   3215 				      tem, tem, bswap_vconst);
   3216       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3217       tem = make_ssa_name (vectype);
   3218       new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
   3219 						   vectype, tem2));
   3220       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3221       if (slp_node)
   3222 	SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   3223       else
   3224 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   3225     }
   3226 
   3227   if (!slp_node)
   3228     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   3229 
   3230   vec_oprnds.release ();
   3231   return true;
   3232 }
   3233 
   3234 /* Return true if vector types VECTYPE_IN and VECTYPE_OUT have
   3235    integer elements and if we can narrow VECTYPE_IN to VECTYPE_OUT
   3236    in a single step.  On success, store the binary pack code in
   3237    *CONVERT_CODE.  */
   3238 
   3239 static bool
   3240 simple_integer_narrowing (tree vectype_out, tree vectype_in,
   3241 			  tree_code *convert_code)
   3242 {
   3243   if (!INTEGRAL_TYPE_P (TREE_TYPE (vectype_out))
   3244       || !INTEGRAL_TYPE_P (TREE_TYPE (vectype_in)))
   3245     return false;
   3246 
   3247   tree_code code;
   3248   int multi_step_cvt = 0;
   3249   auto_vec <tree, 8> interm_types;
   3250   if (!supportable_narrowing_operation (NOP_EXPR, vectype_out, vectype_in,
   3251 					&code, &multi_step_cvt, &interm_types)
   3252       || multi_step_cvt)
   3253     return false;
   3254 
   3255   *convert_code = code;
   3256   return true;
   3257 }
   3258 
   3259 /* Function vectorizable_call.
   3260 
   3261    Check if STMT_INFO performs a function call that can be vectorized.
   3262    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   3263    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   3264    Return true if STMT_INFO is vectorizable in this way.  */
   3265 
   3266 static bool
   3267 vectorizable_call (vec_info *vinfo,
   3268 		   stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   3269 		   gimple **vec_stmt, slp_tree slp_node,
   3270 		   stmt_vector_for_cost *cost_vec)
   3271 {
   3272   gcall *stmt;
   3273   tree vec_dest;
   3274   tree scalar_dest;
   3275   tree op;
   3276   tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
   3277   tree vectype_out, vectype_in;
   3278   poly_uint64 nunits_in;
   3279   poly_uint64 nunits_out;
   3280   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   3281   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   3282   tree fndecl, new_temp, rhs_type;
   3283   enum vect_def_type dt[4]
   3284     = { vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type,
   3285 	vect_unknown_def_type };
   3286   tree vectypes[ARRAY_SIZE (dt)] = {};
   3287   slp_tree slp_op[ARRAY_SIZE (dt)] = {};
   3288   int ndts = ARRAY_SIZE (dt);
   3289   int ncopies, j;
   3290   auto_vec<tree, 8> vargs;
   3291   enum { NARROW, NONE, WIDEN } modifier;
   3292   size_t i, nargs;
   3293   tree lhs;
   3294 
   3295   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   3296     return false;
   3297 
   3298   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   3299       && ! vec_stmt)
   3300     return false;
   3301 
   3302   /* Is STMT_INFO a vectorizable call?   */
   3303   stmt = dyn_cast <gcall *> (stmt_info->stmt);
   3304   if (!stmt)
   3305     return false;
   3306 
   3307   if (gimple_call_internal_p (stmt)
   3308       && (internal_load_fn_p (gimple_call_internal_fn (stmt))
   3309 	  || internal_store_fn_p (gimple_call_internal_fn (stmt))))
   3310     /* Handled by vectorizable_load and vectorizable_store.  */
   3311     return false;
   3312 
   3313   if (gimple_call_lhs (stmt) == NULL_TREE
   3314       || TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
   3315     return false;
   3316 
   3317   gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
   3318 
   3319   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
   3320 
   3321   /* Process function arguments.  */
   3322   rhs_type = NULL_TREE;
   3323   vectype_in = NULL_TREE;
   3324   nargs = gimple_call_num_args (stmt);
   3325 
   3326   /* Bail out if the function has more than four arguments, we do not have
   3327      interesting builtin functions to vectorize with more than two arguments
   3328      except for fma.  No arguments is also not good.  */
   3329   if (nargs == 0 || nargs > 4)
   3330     return false;
   3331 
   3332   /* Ignore the arguments of IFN_GOMP_SIMD_LANE, they are magic.  */
   3333   combined_fn cfn = gimple_call_combined_fn (stmt);
   3334   if (cfn == CFN_GOMP_SIMD_LANE)
   3335     {
   3336       nargs = 0;
   3337       rhs_type = unsigned_type_node;
   3338     }
   3339 
   3340   int mask_opno = -1;
   3341   if (internal_fn_p (cfn))
   3342     mask_opno = internal_fn_mask_index (as_internal_fn (cfn));
   3343 
   3344   for (i = 0; i < nargs; i++)
   3345     {
   3346       if ((int) i == mask_opno)
   3347 	{
   3348 	  if (!vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_opno,
   3349 				       &op, &slp_op[i], &dt[i], &vectypes[i]))
   3350 	    return false;
   3351 	  continue;
   3352 	}
   3353 
   3354       if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   3355 			       i, &op, &slp_op[i], &dt[i], &vectypes[i]))
   3356 	{
   3357 	  if (dump_enabled_p ())
   3358 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3359 			     "use not simple.\n");
   3360 	  return false;
   3361 	}
   3362 
   3363       /* We can only handle calls with arguments of the same type.  */
   3364       if (rhs_type
   3365 	  && !types_compatible_p (rhs_type, TREE_TYPE (op)))
   3366 	{
   3367 	  if (dump_enabled_p ())
   3368 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3369                              "argument types differ.\n");
   3370 	  return false;
   3371 	}
   3372       if (!rhs_type)
   3373 	rhs_type = TREE_TYPE (op);
   3374 
   3375       if (!vectype_in)
   3376 	vectype_in = vectypes[i];
   3377       else if (vectypes[i]
   3378 	       && !types_compatible_p (vectypes[i], vectype_in))
   3379 	{
   3380 	  if (dump_enabled_p ())
   3381 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3382                              "argument vector types differ.\n");
   3383 	  return false;
   3384 	}
   3385     }
   3386   /* If all arguments are external or constant defs, infer the vector type
   3387      from the scalar type.  */
   3388   if (!vectype_in)
   3389     vectype_in = get_vectype_for_scalar_type (vinfo, rhs_type, slp_node);
   3390   if (vec_stmt)
   3391     gcc_assert (vectype_in);
   3392   if (!vectype_in)
   3393     {
   3394       if (dump_enabled_p ())
   3395 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3396 			 "no vectype for scalar type %T\n", rhs_type);
   3397 
   3398       return false;
   3399     }
   3400   /* FORNOW: we don't yet support mixtures of vector sizes for calls,
   3401      just mixtures of nunits.  E.g. DI->SI versions of __builtin_ctz*
   3402      are traditionally vectorized as two VnDI->VnDI IFN_CTZs followed
   3403      by a pack of the two vectors into an SI vector.  We would need
   3404      separate code to handle direct VnDI->VnSI IFN_CTZs.  */
   3405   if (TYPE_SIZE (vectype_in) != TYPE_SIZE (vectype_out))
   3406     {
   3407       if (dump_enabled_p ())
   3408 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3409 			 "mismatched vector sizes %T and %T\n",
   3410 			 vectype_in, vectype_out);
   3411       return false;
   3412     }
   3413 
   3414   if (VECTOR_BOOLEAN_TYPE_P (vectype_out)
   3415       != VECTOR_BOOLEAN_TYPE_P (vectype_in))
   3416     {
   3417       if (dump_enabled_p ())
   3418 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3419 			 "mixed mask and nonmask vector types\n");
   3420       return false;
   3421     }
   3422 
   3423   if (vect_emulated_vector_p (vectype_in) || vect_emulated_vector_p (vectype_out))
   3424   {
   3425       if (dump_enabled_p ())
   3426 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3427 			 "use emulated vector type for call\n");
   3428       return false;
   3429   }
   3430 
   3431   /* FORNOW */
   3432   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
   3433   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   3434   if (known_eq (nunits_in * 2, nunits_out))
   3435     modifier = NARROW;
   3436   else if (known_eq (nunits_out, nunits_in))
   3437     modifier = NONE;
   3438   else if (known_eq (nunits_out * 2, nunits_in))
   3439     modifier = WIDEN;
   3440   else
   3441     return false;
   3442 
   3443   /* We only handle functions that do not read or clobber memory.  */
   3444   if (gimple_vuse (stmt))
   3445     {
   3446       if (dump_enabled_p ())
   3447 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3448 			 "function reads from or writes to memory.\n");
   3449       return false;
   3450     }
   3451 
   3452   /* For now, we only vectorize functions if a target specific builtin
   3453      is available.  TODO -- in some cases, it might be profitable to
   3454      insert the calls for pieces of the vector, in order to be able
   3455      to vectorize other operations in the loop.  */
   3456   fndecl = NULL_TREE;
   3457   internal_fn ifn = IFN_LAST;
   3458   tree callee = gimple_call_fndecl (stmt);
   3459 
   3460   /* First try using an internal function.  */
   3461   tree_code convert_code = ERROR_MARK;
   3462   if (cfn != CFN_LAST
   3463       && (modifier == NONE
   3464 	  || (modifier == NARROW
   3465 	      && simple_integer_narrowing (vectype_out, vectype_in,
   3466 					   &convert_code))))
   3467     ifn = vectorizable_internal_function (cfn, callee, vectype_out,
   3468 					  vectype_in);
   3469 
   3470   /* If that fails, try asking for a target-specific built-in function.  */
   3471   if (ifn == IFN_LAST)
   3472     {
   3473       if (cfn != CFN_LAST)
   3474 	fndecl = targetm.vectorize.builtin_vectorized_function
   3475 	  (cfn, vectype_out, vectype_in);
   3476       else if (callee && fndecl_built_in_p (callee, BUILT_IN_MD))
   3477 	fndecl = targetm.vectorize.builtin_md_vectorized_function
   3478 	  (callee, vectype_out, vectype_in);
   3479     }
   3480 
   3481   if (ifn == IFN_LAST && !fndecl)
   3482     {
   3483       if (cfn == CFN_GOMP_SIMD_LANE
   3484 	  && !slp_node
   3485 	  && loop_vinfo
   3486 	  && LOOP_VINFO_LOOP (loop_vinfo)->simduid
   3487 	  && TREE_CODE (gimple_call_arg (stmt, 0)) == SSA_NAME
   3488 	  && LOOP_VINFO_LOOP (loop_vinfo)->simduid
   3489 	     == SSA_NAME_VAR (gimple_call_arg (stmt, 0)))
   3490 	{
   3491 	  /* We can handle IFN_GOMP_SIMD_LANE by returning a
   3492 	     { 0, 1, 2, ... vf - 1 } vector.  */
   3493 	  gcc_assert (nargs == 0);
   3494 	}
   3495       else if (modifier == NONE
   3496 	       && (gimple_call_builtin_p (stmt, BUILT_IN_BSWAP16)
   3497 		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP32)
   3498 		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)
   3499 		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP128)))
   3500 	return vectorizable_bswap (vinfo, stmt_info, gsi, vec_stmt, slp_node,
   3501 				   slp_op, vectype_in, cost_vec);
   3502       else
   3503 	{
   3504 	  if (dump_enabled_p ())
   3505 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3506 			     "function is not vectorizable.\n");
   3507 	  return false;
   3508 	}
   3509     }
   3510 
   3511   if (slp_node)
   3512     ncopies = 1;
   3513   else if (modifier == NARROW && ifn == IFN_LAST)
   3514     ncopies = vect_get_num_copies (loop_vinfo, vectype_out);
   3515   else
   3516     ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
   3517 
   3518   /* Sanity check: make sure that at least one copy of the vectorized stmt
   3519      needs to be generated.  */
   3520   gcc_assert (ncopies >= 1);
   3521 
   3522   int reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info);
   3523   internal_fn cond_fn = get_conditional_internal_fn (ifn);
   3524   vec_loop_masks *masks = (loop_vinfo ? &LOOP_VINFO_MASKS (loop_vinfo) : NULL);
   3525   if (!vec_stmt) /* transformation not required.  */
   3526     {
   3527       if (slp_node)
   3528 	for (i = 0; i < nargs; ++i)
   3529 	  if (!vect_maybe_update_slp_op_vectype (slp_op[i],
   3530 						 vectypes[i]
   3531 						 ? vectypes[i] : vectype_in))
   3532 	    {
   3533 	      if (dump_enabled_p ())
   3534 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3535 				 "incompatible vector types for invariants\n");
   3536 	      return false;
   3537 	    }
   3538       STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
   3539       DUMP_VECT_SCOPE ("vectorizable_call");
   3540       vect_model_simple_cost (vinfo, stmt_info,
   3541 			      ncopies, dt, ndts, slp_node, cost_vec);
   3542       if (ifn != IFN_LAST && modifier == NARROW && !slp_node)
   3543 	record_stmt_cost (cost_vec, ncopies / 2,
   3544 			  vec_promote_demote, stmt_info, 0, vect_body);
   3545 
   3546       if (loop_vinfo
   3547 	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
   3548 	  && (reduc_idx >= 0 || mask_opno >= 0))
   3549 	{
   3550 	  if (reduc_idx >= 0
   3551 	      && (cond_fn == IFN_LAST
   3552 		  || !direct_internal_fn_supported_p (cond_fn, vectype_out,
   3553 						      OPTIMIZE_FOR_SPEED)))
   3554 	    {
   3555 	      if (dump_enabled_p ())
   3556 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   3557 				 "can't use a fully-masked loop because no"
   3558 				 " conditional operation is available.\n");
   3559 	      LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   3560 	    }
   3561 	  else
   3562 	    {
   3563 	      unsigned int nvectors
   3564 		= (slp_node
   3565 		   ? SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node)
   3566 		   : ncopies);
   3567 	      tree scalar_mask = NULL_TREE;
   3568 	      if (mask_opno >= 0)
   3569 		scalar_mask = gimple_call_arg (stmt_info->stmt, mask_opno);
   3570 	      vect_record_loop_mask (loop_vinfo, masks, nvectors,
   3571 				     vectype_out, scalar_mask);
   3572 	    }
   3573 	}
   3574       return true;
   3575     }
   3576 
   3577   /* Transform.  */
   3578 
   3579   if (dump_enabled_p ())
   3580     dump_printf_loc (MSG_NOTE, vect_location, "transform call.\n");
   3581 
   3582   /* Handle def.  */
   3583   scalar_dest = gimple_call_lhs (stmt);
   3584   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
   3585 
   3586   bool masked_loop_p = loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo);
   3587   unsigned int vect_nargs = nargs;
   3588   if (masked_loop_p && reduc_idx >= 0)
   3589     {
   3590       ifn = cond_fn;
   3591       vect_nargs += 2;
   3592     }
   3593 
   3594   if (modifier == NONE || ifn != IFN_LAST)
   3595     {
   3596       tree prev_res = NULL_TREE;
   3597       vargs.safe_grow (vect_nargs, true);
   3598       auto_vec<vec<tree> > vec_defs (nargs);
   3599       for (j = 0; j < ncopies; ++j)
   3600 	{
   3601 	  /* Build argument list for the vectorized call.  */
   3602 	  if (slp_node)
   3603 	    {
   3604 	      vec<tree> vec_oprnds0;
   3605 
   3606 	      vect_get_slp_defs (vinfo, slp_node, &vec_defs);
   3607 	      vec_oprnds0 = vec_defs[0];
   3608 
   3609 	      /* Arguments are ready.  Create the new vector stmt.  */
   3610 	      FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_oprnd0)
   3611 		{
   3612 		  int varg = 0;
   3613 		  if (masked_loop_p && reduc_idx >= 0)
   3614 		    {
   3615 		      unsigned int vec_num = vec_oprnds0.length ();
   3616 		      /* Always true for SLP.  */
   3617 		      gcc_assert (ncopies == 1);
   3618 		      vargs[varg++] = vect_get_loop_mask (gsi, masks, vec_num,
   3619 							  vectype_out, i);
   3620 		    }
   3621 		  size_t k;
   3622 		  for (k = 0; k < nargs; k++)
   3623 		    {
   3624 		      vec<tree> vec_oprndsk = vec_defs[k];
   3625 		      vargs[varg++] = vec_oprndsk[i];
   3626 		    }
   3627 		  if (masked_loop_p && reduc_idx >= 0)
   3628 		    vargs[varg++] = vargs[reduc_idx + 1];
   3629 		  gimple *new_stmt;
   3630 		  if (modifier == NARROW)
   3631 		    {
   3632 		      /* We don't define any narrowing conditional functions
   3633 			 at present.  */
   3634 		      gcc_assert (mask_opno < 0);
   3635 		      tree half_res = make_ssa_name (vectype_in);
   3636 		      gcall *call
   3637 			= gimple_build_call_internal_vec (ifn, vargs);
   3638 		      gimple_call_set_lhs (call, half_res);
   3639 		      gimple_call_set_nothrow (call, true);
   3640 		      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   3641 		      if ((i & 1) == 0)
   3642 			{
   3643 			  prev_res = half_res;
   3644 			  continue;
   3645 			}
   3646 		      new_temp = make_ssa_name (vec_dest);
   3647 		      new_stmt = gimple_build_assign (new_temp, convert_code,
   3648 						      prev_res, half_res);
   3649 		      vect_finish_stmt_generation (vinfo, stmt_info,
   3650 						   new_stmt, gsi);
   3651 		    }
   3652 		  else
   3653 		    {
   3654 		      if (mask_opno >= 0 && masked_loop_p)
   3655 			{
   3656 			  unsigned int vec_num = vec_oprnds0.length ();
   3657 			  /* Always true for SLP.  */
   3658 			  gcc_assert (ncopies == 1);
   3659 			  tree mask = vect_get_loop_mask (gsi, masks, vec_num,
   3660 							  vectype_out, i);
   3661 			  vargs[mask_opno] = prepare_vec_mask
   3662 			    (loop_vinfo, TREE_TYPE (mask), mask,
   3663 			     vargs[mask_opno], gsi);
   3664 			}
   3665 
   3666 		      gcall *call;
   3667 		      if (ifn != IFN_LAST)
   3668 			call = gimple_build_call_internal_vec (ifn, vargs);
   3669 		      else
   3670 			call = gimple_build_call_vec (fndecl, vargs);
   3671 		      new_temp = make_ssa_name (vec_dest, call);
   3672 		      gimple_call_set_lhs (call, new_temp);
   3673 		      gimple_call_set_nothrow (call, true);
   3674 		      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   3675 		      new_stmt = call;
   3676 		    }
   3677 		  SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   3678 		}
   3679 	      continue;
   3680 	    }
   3681 
   3682 	  int varg = 0;
   3683 	  if (masked_loop_p && reduc_idx >= 0)
   3684 	    vargs[varg++] = vect_get_loop_mask (gsi, masks, ncopies,
   3685 						vectype_out, j);
   3686 	  for (i = 0; i < nargs; i++)
   3687 	    {
   3688 	      op = gimple_call_arg (stmt, i);
   3689 	      if (j == 0)
   3690 		{
   3691 		  vec_defs.quick_push (vNULL);
   3692 		  vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
   3693 						 op, &vec_defs[i],
   3694 						 vectypes[i]);
   3695 		}
   3696 	      vargs[varg++] = vec_defs[i][j];
   3697 	    }
   3698 	  if (masked_loop_p && reduc_idx >= 0)
   3699 	    vargs[varg++] = vargs[reduc_idx + 1];
   3700 
   3701 	  if (mask_opno >= 0 && masked_loop_p)
   3702 	    {
   3703 	      tree mask = vect_get_loop_mask (gsi, masks, ncopies,
   3704 					      vectype_out, j);
   3705 	      vargs[mask_opno]
   3706 		= prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
   3707 				    vargs[mask_opno], gsi);
   3708 	    }
   3709 
   3710 	  gimple *new_stmt;
   3711 	  if (cfn == CFN_GOMP_SIMD_LANE)
   3712 	    {
   3713 	      tree cst = build_index_vector (vectype_out, j * nunits_out, 1);
   3714 	      tree new_var
   3715 		= vect_get_new_ssa_name (vectype_out, vect_simple_var, "cst_");
   3716 	      gimple *init_stmt = gimple_build_assign (new_var, cst);
   3717 	      vect_init_vector_1 (vinfo, stmt_info, init_stmt, NULL);
   3718 	      new_temp = make_ssa_name (vec_dest);
   3719 	      new_stmt = gimple_build_assign (new_temp, new_var);
   3720 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3721 	    }
   3722 	  else if (modifier == NARROW)
   3723 	    {
   3724 	      /* We don't define any narrowing conditional functions at
   3725 		 present.  */
   3726 	      gcc_assert (mask_opno < 0);
   3727 	      tree half_res = make_ssa_name (vectype_in);
   3728 	      gcall *call = gimple_build_call_internal_vec (ifn, vargs);
   3729 	      gimple_call_set_lhs (call, half_res);
   3730 	      gimple_call_set_nothrow (call, true);
   3731 	      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   3732 	      if ((j & 1) == 0)
   3733 		{
   3734 		  prev_res = half_res;
   3735 		  continue;
   3736 		}
   3737 	      new_temp = make_ssa_name (vec_dest);
   3738 	      new_stmt = gimple_build_assign (new_temp, convert_code,
   3739 					      prev_res, half_res);
   3740 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3741 	    }
   3742 	  else
   3743 	    {
   3744 	      gcall *call;
   3745 	      if (ifn != IFN_LAST)
   3746 		call = gimple_build_call_internal_vec (ifn, vargs);
   3747 	      else
   3748 		call = gimple_build_call_vec (fndecl, vargs);
   3749 	      new_temp = make_ssa_name (vec_dest, call);
   3750 	      gimple_call_set_lhs (call, new_temp);
   3751 	      gimple_call_set_nothrow (call, true);
   3752 	      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   3753 	      new_stmt = call;
   3754 	    }
   3755 
   3756 	  if (j == (modifier == NARROW ? 1 : 0))
   3757 	    *vec_stmt = new_stmt;
   3758 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   3759 	}
   3760       for (i = 0; i < nargs; i++)
   3761 	{
   3762 	  vec<tree> vec_oprndsi = vec_defs[i];
   3763 	  vec_oprndsi.release ();
   3764 	}
   3765     }
   3766   else if (modifier == NARROW)
   3767     {
   3768       auto_vec<vec<tree> > vec_defs (nargs);
   3769       /* We don't define any narrowing conditional functions at present.  */
   3770       gcc_assert (mask_opno < 0);
   3771       for (j = 0; j < ncopies; ++j)
   3772 	{
   3773 	  /* Build argument list for the vectorized call.  */
   3774 	  if (j == 0)
   3775 	    vargs.create (nargs * 2);
   3776 	  else
   3777 	    vargs.truncate (0);
   3778 
   3779 	  if (slp_node)
   3780 	    {
   3781 	      vec<tree> vec_oprnds0;
   3782 
   3783 	      vect_get_slp_defs (vinfo, slp_node, &vec_defs);
   3784 	      vec_oprnds0 = vec_defs[0];
   3785 
   3786 	      /* Arguments are ready.  Create the new vector stmt.  */
   3787 	      for (i = 0; vec_oprnds0.iterate (i, &vec_oprnd0); i += 2)
   3788 		{
   3789 		  size_t k;
   3790 		  vargs.truncate (0);
   3791 		  for (k = 0; k < nargs; k++)
   3792 		    {
   3793 		      vec<tree> vec_oprndsk = vec_defs[k];
   3794 		      vargs.quick_push (vec_oprndsk[i]);
   3795 		      vargs.quick_push (vec_oprndsk[i + 1]);
   3796 		    }
   3797 		  gcall *call;
   3798 		  if (ifn != IFN_LAST)
   3799 		    call = gimple_build_call_internal_vec (ifn, vargs);
   3800 		  else
   3801 		    call = gimple_build_call_vec (fndecl, vargs);
   3802 		  new_temp = make_ssa_name (vec_dest, call);
   3803 		  gimple_call_set_lhs (call, new_temp);
   3804 		  gimple_call_set_nothrow (call, true);
   3805 		  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   3806 		  SLP_TREE_VEC_STMTS (slp_node).quick_push (call);
   3807 		}
   3808 	      continue;
   3809 	    }
   3810 
   3811 	  for (i = 0; i < nargs; i++)
   3812 	    {
   3813 	      op = gimple_call_arg (stmt, i);
   3814 	      if (j == 0)
   3815 		{
   3816 		  vec_defs.quick_push (vNULL);
   3817 		  vect_get_vec_defs_for_operand (vinfo, stmt_info, 2 * ncopies,
   3818 						 op, &vec_defs[i], vectypes[i]);
   3819 		}
   3820 	      vec_oprnd0 = vec_defs[i][2*j];
   3821 	      vec_oprnd1 = vec_defs[i][2*j+1];
   3822 
   3823 	      vargs.quick_push (vec_oprnd0);
   3824 	      vargs.quick_push (vec_oprnd1);
   3825 	    }
   3826 
   3827 	  gcall *new_stmt = gimple_build_call_vec (fndecl, vargs);
   3828 	  new_temp = make_ssa_name (vec_dest, new_stmt);
   3829 	  gimple_call_set_lhs (new_stmt, new_temp);
   3830 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   3831 
   3832 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   3833 	}
   3834 
   3835       if (!slp_node)
   3836 	*vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   3837 
   3838       for (i = 0; i < nargs; i++)
   3839 	{
   3840 	  vec<tree> vec_oprndsi = vec_defs[i];
   3841 	  vec_oprndsi.release ();
   3842 	}
   3843     }
   3844   else
   3845     /* No current target implements this case.  */
   3846     return false;
   3847 
   3848   vargs.release ();
   3849 
   3850   /* The call in STMT might prevent it from being removed in dce.
   3851      We however cannot remove it here, due to the way the ssa name
   3852      it defines is mapped to the new definition.  So just replace
   3853      rhs of the statement with something harmless.  */
   3854 
   3855   if (slp_node)
   3856     return true;
   3857 
   3858   stmt_info = vect_orig_stmt (stmt_info);
   3859   lhs = gimple_get_lhs (stmt_info->stmt);
   3860 
   3861   gassign *new_stmt
   3862     = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
   3863   vinfo->replace_stmt (gsi, stmt_info, new_stmt);
   3864 
   3865   return true;
   3866 }
   3867 
   3868 
   3869 struct simd_call_arg_info
   3870 {
   3871   tree vectype;
   3872   tree op;
   3873   HOST_WIDE_INT linear_step;
   3874   enum vect_def_type dt;
   3875   unsigned int align;
   3876   bool simd_lane_linear;
   3877 };
   3878 
   3879 /* Helper function of vectorizable_simd_clone_call.  If OP, an SSA_NAME,
   3880    is linear within simd lane (but not within whole loop), note it in
   3881    *ARGINFO.  */
   3882 
   3883 static void
   3884 vect_simd_lane_linear (tree op, class loop *loop,
   3885 		       struct simd_call_arg_info *arginfo)
   3886 {
   3887   gimple *def_stmt = SSA_NAME_DEF_STMT (op);
   3888 
   3889   if (!is_gimple_assign (def_stmt)
   3890       || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR
   3891       || !is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt)))
   3892     return;
   3893 
   3894   tree base = gimple_assign_rhs1 (def_stmt);
   3895   HOST_WIDE_INT linear_step = 0;
   3896   tree v = gimple_assign_rhs2 (def_stmt);
   3897   while (TREE_CODE (v) == SSA_NAME)
   3898     {
   3899       tree t;
   3900       def_stmt = SSA_NAME_DEF_STMT (v);
   3901       if (is_gimple_assign (def_stmt))
   3902 	switch (gimple_assign_rhs_code (def_stmt))
   3903 	  {
   3904 	  case PLUS_EXPR:
   3905 	    t = gimple_assign_rhs2 (def_stmt);
   3906 	    if (linear_step || TREE_CODE (t) != INTEGER_CST)
   3907 	      return;
   3908 	    base = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (base), base, t);
   3909 	    v = gimple_assign_rhs1 (def_stmt);
   3910 	    continue;
   3911 	  case MULT_EXPR:
   3912 	    t = gimple_assign_rhs2 (def_stmt);
   3913 	    if (linear_step || !tree_fits_shwi_p (t) || integer_zerop (t))
   3914 	      return;
   3915 	    linear_step = tree_to_shwi (t);
   3916 	    v = gimple_assign_rhs1 (def_stmt);
   3917 	    continue;
   3918 	  CASE_CONVERT:
   3919 	    t = gimple_assign_rhs1 (def_stmt);
   3920 	    if (TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE
   3921 		|| (TYPE_PRECISION (TREE_TYPE (v))
   3922 		    < TYPE_PRECISION (TREE_TYPE (t))))
   3923 	      return;
   3924 	    if (!linear_step)
   3925 	      linear_step = 1;
   3926 	    v = t;
   3927 	    continue;
   3928 	  default:
   3929 	    return;
   3930 	  }
   3931       else if (gimple_call_internal_p (def_stmt, IFN_GOMP_SIMD_LANE)
   3932 	       && loop->simduid
   3933 	       && TREE_CODE (gimple_call_arg (def_stmt, 0)) == SSA_NAME
   3934 	       && (SSA_NAME_VAR (gimple_call_arg (def_stmt, 0))
   3935 		   == loop->simduid))
   3936 	{
   3937 	  if (!linear_step)
   3938 	    linear_step = 1;
   3939 	  arginfo->linear_step = linear_step;
   3940 	  arginfo->op = base;
   3941 	  arginfo->simd_lane_linear = true;
   3942 	  return;
   3943 	}
   3944     }
   3945 }
   3946 
   3947 /* Return the number of elements in vector type VECTYPE, which is associated
   3948    with a SIMD clone.  At present these vectors always have a constant
   3949    length.  */
   3950 
   3951 static unsigned HOST_WIDE_INT
   3952 simd_clone_subparts (tree vectype)
   3953 {
   3954   return TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
   3955 }
   3956 
   3957 /* Function vectorizable_simd_clone_call.
   3958 
   3959    Check if STMT_INFO performs a function call that can be vectorized
   3960    by calling a simd clone of the function.
   3961    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   3962    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   3963    Return true if STMT_INFO is vectorizable in this way.  */
   3964 
   3965 static bool
   3966 vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
   3967 			      gimple_stmt_iterator *gsi,
   3968 			      gimple **vec_stmt, slp_tree slp_node,
   3969 			      stmt_vector_for_cost *)
   3970 {
   3971   tree vec_dest;
   3972   tree scalar_dest;
   3973   tree op, type;
   3974   tree vec_oprnd0 = NULL_TREE;
   3975   tree vectype;
   3976   poly_uint64 nunits;
   3977   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   3978   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   3979   class loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
   3980   tree fndecl, new_temp;
   3981   int ncopies, j;
   3982   auto_vec<simd_call_arg_info> arginfo;
   3983   vec<tree> vargs = vNULL;
   3984   size_t i, nargs;
   3985   tree lhs, rtype, ratype;
   3986   vec<constructor_elt, va_gc> *ret_ctor_elts = NULL;
   3987 
   3988   /* Is STMT a vectorizable call?   */
   3989   gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt);
   3990   if (!stmt)
   3991     return false;
   3992 
   3993   fndecl = gimple_call_fndecl (stmt);
   3994   if (fndecl == NULL_TREE)
   3995     return false;
   3996 
   3997   struct cgraph_node *node = cgraph_node::get (fndecl);
   3998   if (node == NULL || node->simd_clones == NULL)
   3999     return false;
   4000 
   4001   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   4002     return false;
   4003 
   4004   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   4005       && ! vec_stmt)
   4006     return false;
   4007 
   4008   if (gimple_call_lhs (stmt)
   4009       && TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
   4010     return false;
   4011 
   4012   gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
   4013 
   4014   vectype = STMT_VINFO_VECTYPE (stmt_info);
   4015 
   4016   if (loop_vinfo && nested_in_vect_loop_p (loop, stmt_info))
   4017     return false;
   4018 
   4019   /* FORNOW */
   4020   if (slp_node)
   4021     return false;
   4022 
   4023   /* Process function arguments.  */
   4024   nargs = gimple_call_num_args (stmt);
   4025 
   4026   /* Bail out if the function has zero arguments.  */
   4027   if (nargs == 0)
   4028     return false;
   4029 
   4030   arginfo.reserve (nargs, true);
   4031 
   4032   for (i = 0; i < nargs; i++)
   4033     {
   4034       simd_call_arg_info thisarginfo;
   4035       affine_iv iv;
   4036 
   4037       thisarginfo.linear_step = 0;
   4038       thisarginfo.align = 0;
   4039       thisarginfo.op = NULL_TREE;
   4040       thisarginfo.simd_lane_linear = false;
   4041 
   4042       op = gimple_call_arg (stmt, i);
   4043       if (!vect_is_simple_use (op, vinfo, &thisarginfo.dt,
   4044 			       &thisarginfo.vectype)
   4045 	  || thisarginfo.dt == vect_uninitialized_def)
   4046 	{
   4047 	  if (dump_enabled_p ())
   4048 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4049 			     "use not simple.\n");
   4050 	  return false;
   4051 	}
   4052 
   4053       if (thisarginfo.dt == vect_constant_def
   4054 	  || thisarginfo.dt == vect_external_def)
   4055 	gcc_assert (thisarginfo.vectype == NULL_TREE);
   4056       else
   4057 	{
   4058 	  gcc_assert (thisarginfo.vectype != NULL_TREE);
   4059 	  if (VECTOR_BOOLEAN_TYPE_P (thisarginfo.vectype))
   4060 	    {
   4061 	      if (dump_enabled_p ())
   4062 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4063 				 "vector mask arguments are not supported\n");
   4064 	      return false;
   4065 	    }
   4066 	}
   4067 
   4068       /* For linear arguments, the analyze phase should have saved
   4069 	 the base and step in STMT_VINFO_SIMD_CLONE_INFO.  */
   4070       if (i * 3 + 4 <= STMT_VINFO_SIMD_CLONE_INFO (stmt_info).length ()
   4071 	  && STMT_VINFO_SIMD_CLONE_INFO (stmt_info)[i * 3 + 2])
   4072 	{
   4073 	  gcc_assert (vec_stmt);
   4074 	  thisarginfo.linear_step
   4075 	    = tree_to_shwi (STMT_VINFO_SIMD_CLONE_INFO (stmt_info)[i * 3 + 2]);
   4076 	  thisarginfo.op
   4077 	    = STMT_VINFO_SIMD_CLONE_INFO (stmt_info)[i * 3 + 1];
   4078 	  thisarginfo.simd_lane_linear
   4079 	    = (STMT_VINFO_SIMD_CLONE_INFO (stmt_info)[i * 3 + 3]
   4080 	       == boolean_true_node);
   4081 	  /* If loop has been peeled for alignment, we need to adjust it.  */
   4082 	  tree n1 = LOOP_VINFO_NITERS_UNCHANGED (loop_vinfo);
   4083 	  tree n2 = LOOP_VINFO_NITERS (loop_vinfo);
   4084 	  if (n1 != n2 && !thisarginfo.simd_lane_linear)
   4085 	    {
   4086 	      tree bias = fold_build2 (MINUS_EXPR, TREE_TYPE (n1), n1, n2);
   4087 	      tree step = STMT_VINFO_SIMD_CLONE_INFO (stmt_info)[i * 3 + 2];
   4088 	      tree opt = TREE_TYPE (thisarginfo.op);
   4089 	      bias = fold_convert (TREE_TYPE (step), bias);
   4090 	      bias = fold_build2 (MULT_EXPR, TREE_TYPE (step), bias, step);
   4091 	      thisarginfo.op
   4092 		= fold_build2 (POINTER_TYPE_P (opt)
   4093 			       ? POINTER_PLUS_EXPR : PLUS_EXPR, opt,
   4094 			       thisarginfo.op, bias);
   4095 	    }
   4096 	}
   4097       else if (!vec_stmt
   4098 	       && thisarginfo.dt != vect_constant_def
   4099 	       && thisarginfo.dt != vect_external_def
   4100 	       && loop_vinfo
   4101 	       && TREE_CODE (op) == SSA_NAME
   4102 	       && simple_iv (loop, loop_containing_stmt (stmt), op,
   4103 			     &iv, false)
   4104 	       && tree_fits_shwi_p (iv.step))
   4105 	{
   4106 	  thisarginfo.linear_step = tree_to_shwi (iv.step);
   4107 	  thisarginfo.op = iv.base;
   4108 	}
   4109       else if ((thisarginfo.dt == vect_constant_def
   4110 		|| thisarginfo.dt == vect_external_def)
   4111 	       && POINTER_TYPE_P (TREE_TYPE (op)))
   4112 	thisarginfo.align = get_pointer_alignment (op) / BITS_PER_UNIT;
   4113       /* Addresses of array elements indexed by GOMP_SIMD_LANE are
   4114 	 linear too.  */
   4115       if (POINTER_TYPE_P (TREE_TYPE (op))
   4116 	  && !thisarginfo.linear_step
   4117 	  && !vec_stmt
   4118 	  && thisarginfo.dt != vect_constant_def
   4119 	  && thisarginfo.dt != vect_external_def
   4120 	  && loop_vinfo
   4121 	  && !slp_node
   4122 	  && TREE_CODE (op) == SSA_NAME)
   4123 	vect_simd_lane_linear (op, loop, &thisarginfo);
   4124 
   4125       arginfo.quick_push (thisarginfo);
   4126     }
   4127 
   4128   poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
   4129   if (!vf.is_constant ())
   4130     {
   4131       if (dump_enabled_p ())
   4132 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4133 			 "not considering SIMD clones; not yet supported"
   4134 			 " for variable-width vectors.\n");
   4135       return false;
   4136     }
   4137 
   4138   unsigned int badness = 0;
   4139   struct cgraph_node *bestn = NULL;
   4140   if (STMT_VINFO_SIMD_CLONE_INFO (stmt_info).exists ())
   4141     bestn = cgraph_node::get (STMT_VINFO_SIMD_CLONE_INFO (stmt_info)[0]);
   4142   else
   4143     for (struct cgraph_node *n = node->simd_clones; n != NULL;
   4144 	 n = n->simdclone->next_clone)
   4145       {
   4146 	unsigned int this_badness = 0;
   4147 	unsigned int num_calls;
   4148 	if (!constant_multiple_p (vf, n->simdclone->simdlen, &num_calls)
   4149 	    || n->simdclone->nargs != nargs)
   4150 	  continue;
   4151 	if (num_calls != 1)
   4152 	  this_badness += exact_log2 (num_calls) * 4096;
   4153 	if (n->simdclone->inbranch)
   4154 	  this_badness += 8192;
   4155 	int target_badness = targetm.simd_clone.usable (n);
   4156 	if (target_badness < 0)
   4157 	  continue;
   4158 	this_badness += target_badness * 512;
   4159 	/* FORNOW: Have to add code to add the mask argument.  */
   4160 	if (n->simdclone->inbranch)
   4161 	  continue;
   4162 	for (i = 0; i < nargs; i++)
   4163 	  {
   4164 	    switch (n->simdclone->args[i].arg_type)
   4165 	      {
   4166 	      case SIMD_CLONE_ARG_TYPE_VECTOR:
   4167 		if (!useless_type_conversion_p
   4168 			(n->simdclone->args[i].orig_type,
   4169 			 TREE_TYPE (gimple_call_arg (stmt, i))))
   4170 		  i = -1;
   4171 		else if (arginfo[i].dt == vect_constant_def
   4172 			 || arginfo[i].dt == vect_external_def
   4173 			 || arginfo[i].linear_step)
   4174 		  this_badness += 64;
   4175 		break;
   4176 	      case SIMD_CLONE_ARG_TYPE_UNIFORM:
   4177 		if (arginfo[i].dt != vect_constant_def
   4178 		    && arginfo[i].dt != vect_external_def)
   4179 		  i = -1;
   4180 		break;
   4181 	      case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
   4182 	      case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
   4183 		if (arginfo[i].dt == vect_constant_def
   4184 		    || arginfo[i].dt == vect_external_def
   4185 		    || (arginfo[i].linear_step
   4186 			!= n->simdclone->args[i].linear_step))
   4187 		  i = -1;
   4188 		break;
   4189 	      case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
   4190 	      case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
   4191 	      case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
   4192 	      case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
   4193 	      case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
   4194 	      case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
   4195 		/* FORNOW */
   4196 		i = -1;
   4197 		break;
   4198 	      case SIMD_CLONE_ARG_TYPE_MASK:
   4199 		gcc_unreachable ();
   4200 	      }
   4201 	    if (i == (size_t) -1)
   4202 	      break;
   4203 	    if (n->simdclone->args[i].alignment > arginfo[i].align)
   4204 	      {
   4205 		i = -1;
   4206 		break;
   4207 	      }
   4208 	    if (arginfo[i].align)
   4209 	      this_badness += (exact_log2 (arginfo[i].align)
   4210 			       - exact_log2 (n->simdclone->args[i].alignment));
   4211 	  }
   4212 	if (i == (size_t) -1)
   4213 	  continue;
   4214 	if (bestn == NULL || this_badness < badness)
   4215 	  {
   4216 	    bestn = n;
   4217 	    badness = this_badness;
   4218 	  }
   4219       }
   4220 
   4221   if (bestn == NULL)
   4222     return false;
   4223 
   4224   for (i = 0; i < nargs; i++)
   4225     if ((arginfo[i].dt == vect_constant_def
   4226 	 || arginfo[i].dt == vect_external_def)
   4227 	&& bestn->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
   4228       {
   4229 	tree arg_type = TREE_TYPE (gimple_call_arg (stmt, i));
   4230 	arginfo[i].vectype = get_vectype_for_scalar_type (vinfo, arg_type,
   4231 							  slp_node);
   4232 	if (arginfo[i].vectype == NULL
   4233 	    || !constant_multiple_p (bestn->simdclone->simdlen,
   4234 				     simd_clone_subparts (arginfo[i].vectype)))
   4235 	  return false;
   4236       }
   4237 
   4238   fndecl = bestn->decl;
   4239   nunits = bestn->simdclone->simdlen;
   4240   ncopies = vector_unroll_factor (vf, nunits);
   4241 
   4242   /* If the function isn't const, only allow it in simd loops where user
   4243      has asserted that at least nunits consecutive iterations can be
   4244      performed using SIMD instructions.  */
   4245   if ((loop == NULL || maybe_lt ((unsigned) loop->safelen, nunits))
   4246       && gimple_vuse (stmt))
   4247     return false;
   4248 
   4249   /* Sanity check: make sure that at least one copy of the vectorized stmt
   4250      needs to be generated.  */
   4251   gcc_assert (ncopies >= 1);
   4252 
   4253   if (!vec_stmt) /* transformation not required.  */
   4254     {
   4255       STMT_VINFO_SIMD_CLONE_INFO (stmt_info).safe_push (bestn->decl);
   4256       for (i = 0; i < nargs; i++)
   4257 	if ((bestn->simdclone->args[i].arg_type
   4258 	     == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
   4259 	    || (bestn->simdclone->args[i].arg_type
   4260 		== SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP))
   4261 	  {
   4262 	    STMT_VINFO_SIMD_CLONE_INFO (stmt_info).safe_grow_cleared (i * 3
   4263 									+ 1,
   4264 								      true);
   4265 	    STMT_VINFO_SIMD_CLONE_INFO (stmt_info).safe_push (arginfo[i].op);
   4266 	    tree lst = POINTER_TYPE_P (TREE_TYPE (arginfo[i].op))
   4267 		       ? size_type_node : TREE_TYPE (arginfo[i].op);
   4268 	    tree ls = build_int_cst (lst, arginfo[i].linear_step);
   4269 	    STMT_VINFO_SIMD_CLONE_INFO (stmt_info).safe_push (ls);
   4270 	    tree sll = arginfo[i].simd_lane_linear
   4271 		       ? boolean_true_node : boolean_false_node;
   4272 	    STMT_VINFO_SIMD_CLONE_INFO (stmt_info).safe_push (sll);
   4273 	  }
   4274       STMT_VINFO_TYPE (stmt_info) = call_simd_clone_vec_info_type;
   4275       DUMP_VECT_SCOPE ("vectorizable_simd_clone_call");
   4276 /*      vect_model_simple_cost (vinfo, stmt_info, ncopies,
   4277 				dt, slp_node, cost_vec); */
   4278       return true;
   4279     }
   4280 
   4281   /* Transform.  */
   4282 
   4283   if (dump_enabled_p ())
   4284     dump_printf_loc (MSG_NOTE, vect_location, "transform call.\n");
   4285 
   4286   /* Handle def.  */
   4287   scalar_dest = gimple_call_lhs (stmt);
   4288   vec_dest = NULL_TREE;
   4289   rtype = NULL_TREE;
   4290   ratype = NULL_TREE;
   4291   if (scalar_dest)
   4292     {
   4293       vec_dest = vect_create_destination_var (scalar_dest, vectype);
   4294       rtype = TREE_TYPE (TREE_TYPE (fndecl));
   4295       if (TREE_CODE (rtype) == ARRAY_TYPE)
   4296 	{
   4297 	  ratype = rtype;
   4298 	  rtype = TREE_TYPE (ratype);
   4299 	}
   4300     }
   4301 
   4302   auto_vec<vec<tree> > vec_oprnds;
   4303   auto_vec<unsigned> vec_oprnds_i;
   4304   vec_oprnds.safe_grow_cleared (nargs, true);
   4305   vec_oprnds_i.safe_grow_cleared (nargs, true);
   4306   for (j = 0; j < ncopies; ++j)
   4307     {
   4308       /* Build argument list for the vectorized call.  */
   4309       if (j == 0)
   4310 	vargs.create (nargs);
   4311       else
   4312 	vargs.truncate (0);
   4313 
   4314       for (i = 0; i < nargs; i++)
   4315 	{
   4316 	  unsigned int k, l, m, o;
   4317 	  tree atype;
   4318 	  op = gimple_call_arg (stmt, i);
   4319 	  switch (bestn->simdclone->args[i].arg_type)
   4320 	    {
   4321 	    case SIMD_CLONE_ARG_TYPE_VECTOR:
   4322 	      atype = bestn->simdclone->args[i].vector_type;
   4323 	      o = vector_unroll_factor (nunits,
   4324 					simd_clone_subparts (atype));
   4325 	      for (m = j * o; m < (j + 1) * o; m++)
   4326 		{
   4327 		  if (simd_clone_subparts (atype)
   4328 		      < simd_clone_subparts (arginfo[i].vectype))
   4329 		    {
   4330 		      poly_uint64 prec = GET_MODE_BITSIZE (TYPE_MODE (atype));
   4331 		      k = (simd_clone_subparts (arginfo[i].vectype)
   4332 			   / simd_clone_subparts (atype));
   4333 		      gcc_assert ((k & (k - 1)) == 0);
   4334 		      if (m == 0)
   4335 			{
   4336 			  vect_get_vec_defs_for_operand (vinfo, stmt_info,
   4337 							 ncopies * o / k, op,
   4338 							 &vec_oprnds[i]);
   4339 			  vec_oprnds_i[i] = 0;
   4340 			  vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
   4341 			}
   4342 		      else
   4343 			{
   4344 			  vec_oprnd0 = arginfo[i].op;
   4345 			  if ((m & (k - 1)) == 0)
   4346 			    vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
   4347 			}
   4348 		      arginfo[i].op = vec_oprnd0;
   4349 		      vec_oprnd0
   4350 			= build3 (BIT_FIELD_REF, atype, vec_oprnd0,
   4351 				  bitsize_int (prec),
   4352 				  bitsize_int ((m & (k - 1)) * prec));
   4353 		      gassign *new_stmt
   4354 			= gimple_build_assign (make_ssa_name (atype),
   4355 					       vec_oprnd0);
   4356 		      vect_finish_stmt_generation (vinfo, stmt_info,
   4357 						   new_stmt, gsi);
   4358 		      vargs.safe_push (gimple_assign_lhs (new_stmt));
   4359 		    }
   4360 		  else
   4361 		    {
   4362 		      k = (simd_clone_subparts (atype)
   4363 			   / simd_clone_subparts (arginfo[i].vectype));
   4364 		      gcc_assert ((k & (k - 1)) == 0);
   4365 		      vec<constructor_elt, va_gc> *ctor_elts;
   4366 		      if (k != 1)
   4367 			vec_alloc (ctor_elts, k);
   4368 		      else
   4369 			ctor_elts = NULL;
   4370 		      for (l = 0; l < k; l++)
   4371 			{
   4372 			  if (m == 0 && l == 0)
   4373 			    {
   4374 			      vect_get_vec_defs_for_operand (vinfo, stmt_info,
   4375 							     k * o * ncopies,
   4376 							     op,
   4377 							     &vec_oprnds[i]);
   4378 			      vec_oprnds_i[i] = 0;
   4379 			      vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
   4380 			    }
   4381 			  else
   4382 			    vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
   4383 			  arginfo[i].op = vec_oprnd0;
   4384 			  if (k == 1)
   4385 			    break;
   4386 			  CONSTRUCTOR_APPEND_ELT (ctor_elts, NULL_TREE,
   4387 						  vec_oprnd0);
   4388 			}
   4389 		      if (k == 1)
   4390 			if (!useless_type_conversion_p (TREE_TYPE (vec_oprnd0),
   4391 						       atype))
   4392 			  {
   4393 			    vec_oprnd0
   4394 			      = build1 (VIEW_CONVERT_EXPR, atype, vec_oprnd0);
   4395 			    gassign *new_stmt
   4396 			      = gimple_build_assign (make_ssa_name (atype),
   4397 						     vec_oprnd0);
   4398 			    vect_finish_stmt_generation (vinfo, stmt_info,
   4399 							 new_stmt, gsi);
   4400 			    vargs.safe_push (gimple_assign_lhs (new_stmt));
   4401 			  }
   4402 			else
   4403 			  vargs.safe_push (vec_oprnd0);
   4404 		      else
   4405 			{
   4406 			  vec_oprnd0 = build_constructor (atype, ctor_elts);
   4407 			  gassign *new_stmt
   4408 			    = gimple_build_assign (make_ssa_name (atype),
   4409 						   vec_oprnd0);
   4410 			  vect_finish_stmt_generation (vinfo, stmt_info,
   4411 						       new_stmt, gsi);
   4412 			  vargs.safe_push (gimple_assign_lhs (new_stmt));
   4413 			}
   4414 		    }
   4415 		}
   4416 	      break;
   4417 	    case SIMD_CLONE_ARG_TYPE_UNIFORM:
   4418 	      vargs.safe_push (op);
   4419 	      break;
   4420 	    case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
   4421 	    case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
   4422 	      if (j == 0)
   4423 		{
   4424 		  gimple_seq stmts;
   4425 		  arginfo[i].op
   4426 		    = force_gimple_operand (unshare_expr (arginfo[i].op),
   4427 					    &stmts, true, NULL_TREE);
   4428 		  if (stmts != NULL)
   4429 		    {
   4430 		      basic_block new_bb;
   4431 		      edge pe = loop_preheader_edge (loop);
   4432 		      new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
   4433 		      gcc_assert (!new_bb);
   4434 		    }
   4435 		  if (arginfo[i].simd_lane_linear)
   4436 		    {
   4437 		      vargs.safe_push (arginfo[i].op);
   4438 		      break;
   4439 		    }
   4440 		  tree phi_res = copy_ssa_name (op);
   4441 		  gphi *new_phi = create_phi_node (phi_res, loop->header);
   4442 		  add_phi_arg (new_phi, arginfo[i].op,
   4443 			       loop_preheader_edge (loop), UNKNOWN_LOCATION);
   4444 		  enum tree_code code
   4445 		    = POINTER_TYPE_P (TREE_TYPE (op))
   4446 		      ? POINTER_PLUS_EXPR : PLUS_EXPR;
   4447 		  tree type = POINTER_TYPE_P (TREE_TYPE (op))
   4448 			      ? sizetype : TREE_TYPE (op);
   4449 		  poly_widest_int cst
   4450 		    = wi::mul (bestn->simdclone->args[i].linear_step,
   4451 			       ncopies * nunits);
   4452 		  tree tcst = wide_int_to_tree (type, cst);
   4453 		  tree phi_arg = copy_ssa_name (op);
   4454 		  gassign *new_stmt
   4455 		    = gimple_build_assign (phi_arg, code, phi_res, tcst);
   4456 		  gimple_stmt_iterator si = gsi_after_labels (loop->header);
   4457 		  gsi_insert_after (&si, new_stmt, GSI_NEW_STMT);
   4458 		  add_phi_arg (new_phi, phi_arg, loop_latch_edge (loop),
   4459 			       UNKNOWN_LOCATION);
   4460 		  arginfo[i].op = phi_res;
   4461 		  vargs.safe_push (phi_res);
   4462 		}
   4463 	      else
   4464 		{
   4465 		  enum tree_code code
   4466 		    = POINTER_TYPE_P (TREE_TYPE (op))
   4467 		      ? POINTER_PLUS_EXPR : PLUS_EXPR;
   4468 		  tree type = POINTER_TYPE_P (TREE_TYPE (op))
   4469 			      ? sizetype : TREE_TYPE (op);
   4470 		  poly_widest_int cst
   4471 		    = wi::mul (bestn->simdclone->args[i].linear_step,
   4472 			       j * nunits);
   4473 		  tree tcst = wide_int_to_tree (type, cst);
   4474 		  new_temp = make_ssa_name (TREE_TYPE (op));
   4475 		  gassign *new_stmt
   4476 		    = gimple_build_assign (new_temp, code,
   4477 					   arginfo[i].op, tcst);
   4478 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   4479 		  vargs.safe_push (new_temp);
   4480 		}
   4481 	      break;
   4482 	    case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
   4483 	    case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
   4484 	    case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
   4485 	    case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
   4486 	    case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
   4487 	    case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
   4488 	    default:
   4489 	      gcc_unreachable ();
   4490 	    }
   4491 	}
   4492 
   4493       gcall *new_call = gimple_build_call_vec (fndecl, vargs);
   4494       if (vec_dest)
   4495 	{
   4496 	  gcc_assert (ratype
   4497 		      || known_eq (simd_clone_subparts (rtype), nunits));
   4498 	  if (ratype)
   4499 	    new_temp = create_tmp_var (ratype);
   4500 	  else if (useless_type_conversion_p (vectype, rtype))
   4501 	    new_temp = make_ssa_name (vec_dest, new_call);
   4502 	  else
   4503 	    new_temp = make_ssa_name (rtype, new_call);
   4504 	  gimple_call_set_lhs (new_call, new_temp);
   4505 	}
   4506       vect_finish_stmt_generation (vinfo, stmt_info, new_call, gsi);
   4507       gimple *new_stmt = new_call;
   4508 
   4509       if (vec_dest)
   4510 	{
   4511 	  if (!multiple_p (simd_clone_subparts (vectype), nunits))
   4512 	    {
   4513 	      unsigned int k, l;
   4514 	      poly_uint64 prec = GET_MODE_BITSIZE (TYPE_MODE (vectype));
   4515 	      poly_uint64 bytes = GET_MODE_SIZE (TYPE_MODE (vectype));
   4516 	      k = vector_unroll_factor (nunits,
   4517 					simd_clone_subparts (vectype));
   4518 	      gcc_assert ((k & (k - 1)) == 0);
   4519 	      for (l = 0; l < k; l++)
   4520 		{
   4521 		  tree t;
   4522 		  if (ratype)
   4523 		    {
   4524 		      t = build_fold_addr_expr (new_temp);
   4525 		      t = build2 (MEM_REF, vectype, t,
   4526 				  build_int_cst (TREE_TYPE (t), l * bytes));
   4527 		    }
   4528 		  else
   4529 		    t = build3 (BIT_FIELD_REF, vectype, new_temp,
   4530 				bitsize_int (prec), bitsize_int (l * prec));
   4531 		  new_stmt = gimple_build_assign (make_ssa_name (vectype), t);
   4532 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   4533 
   4534 		  if (j == 0 && l == 0)
   4535 		    *vec_stmt = new_stmt;
   4536 		  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   4537 		}
   4538 
   4539 	      if (ratype)
   4540 		vect_clobber_variable (vinfo, stmt_info, gsi, new_temp);
   4541 	      continue;
   4542 	    }
   4543 	  else if (!multiple_p (nunits, simd_clone_subparts (vectype)))
   4544 	    {
   4545 	      unsigned int k = (simd_clone_subparts (vectype)
   4546 				/ simd_clone_subparts (rtype));
   4547 	      gcc_assert ((k & (k - 1)) == 0);
   4548 	      if ((j & (k - 1)) == 0)
   4549 		vec_alloc (ret_ctor_elts, k);
   4550 	      if (ratype)
   4551 		{
   4552 		  unsigned int m, o;
   4553 		  o = vector_unroll_factor (nunits,
   4554 					    simd_clone_subparts (rtype));
   4555 		  for (m = 0; m < o; m++)
   4556 		    {
   4557 		      tree tem = build4 (ARRAY_REF, rtype, new_temp,
   4558 					 size_int (m), NULL_TREE, NULL_TREE);
   4559 		      new_stmt = gimple_build_assign (make_ssa_name (rtype),
   4560 						      tem);
   4561 		      vect_finish_stmt_generation (vinfo, stmt_info,
   4562 						   new_stmt, gsi);
   4563 		      CONSTRUCTOR_APPEND_ELT (ret_ctor_elts, NULL_TREE,
   4564 					      gimple_assign_lhs (new_stmt));
   4565 		    }
   4566 		  vect_clobber_variable (vinfo, stmt_info, gsi, new_temp);
   4567 		}
   4568 	      else
   4569 		CONSTRUCTOR_APPEND_ELT (ret_ctor_elts, NULL_TREE, new_temp);
   4570 	      if ((j & (k - 1)) != k - 1)
   4571 		continue;
   4572 	      vec_oprnd0 = build_constructor (vectype, ret_ctor_elts);
   4573 	      new_stmt
   4574 		= gimple_build_assign (make_ssa_name (vec_dest), vec_oprnd0);
   4575 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   4576 
   4577 	      if ((unsigned) j == k - 1)
   4578 		*vec_stmt = new_stmt;
   4579 	      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   4580 	      continue;
   4581 	    }
   4582 	  else if (ratype)
   4583 	    {
   4584 	      tree t = build_fold_addr_expr (new_temp);
   4585 	      t = build2 (MEM_REF, vectype, t,
   4586 			  build_int_cst (TREE_TYPE (t), 0));
   4587 	      new_stmt = gimple_build_assign (make_ssa_name (vec_dest), t);
   4588 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   4589 	      vect_clobber_variable (vinfo, stmt_info, gsi, new_temp);
   4590 	    }
   4591 	  else if (!useless_type_conversion_p (vectype, rtype))
   4592 	    {
   4593 	      vec_oprnd0 = build1 (VIEW_CONVERT_EXPR, vectype, new_temp);
   4594 	      new_stmt
   4595 		= gimple_build_assign (make_ssa_name (vec_dest), vec_oprnd0);
   4596 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   4597 	    }
   4598 	}
   4599 
   4600       if (j == 0)
   4601 	*vec_stmt = new_stmt;
   4602       STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   4603     }
   4604 
   4605   for (i = 0; i < nargs; ++i)
   4606     {
   4607       vec<tree> oprndsi = vec_oprnds[i];
   4608       oprndsi.release ();
   4609     }
   4610   vargs.release ();
   4611 
   4612   /* The call in STMT might prevent it from being removed in dce.
   4613      We however cannot remove it here, due to the way the ssa name
   4614      it defines is mapped to the new definition.  So just replace
   4615      rhs of the statement with something harmless.  */
   4616 
   4617   if (slp_node)
   4618     return true;
   4619 
   4620   gimple *new_stmt;
   4621   if (scalar_dest)
   4622     {
   4623       type = TREE_TYPE (scalar_dest);
   4624       lhs = gimple_call_lhs (vect_orig_stmt (stmt_info)->stmt);
   4625       new_stmt = gimple_build_assign (lhs, build_zero_cst (type));
   4626     }
   4627   else
   4628     new_stmt = gimple_build_nop ();
   4629   vinfo->replace_stmt (gsi, vect_orig_stmt (stmt_info), new_stmt);
   4630   unlink_stmt_vdef (stmt);
   4631 
   4632   return true;
   4633 }
   4634 
   4635 
   4636 /* Function vect_gen_widened_results_half
   4637 
   4638    Create a vector stmt whose code, type, number of arguments, and result
   4639    variable are CODE, OP_TYPE, and VEC_DEST, and its arguments are
   4640    VEC_OPRND0 and VEC_OPRND1.  The new vector stmt is to be inserted at GSI.
   4641    In the case that CODE is a CALL_EXPR, this means that a call to DECL
   4642    needs to be created (DECL is a function-decl of a target-builtin).
   4643    STMT_INFO is the original scalar stmt that we are vectorizing.  */
   4644 
   4645 static gimple *
   4646 vect_gen_widened_results_half (vec_info *vinfo, enum tree_code code,
   4647                                tree vec_oprnd0, tree vec_oprnd1, int op_type,
   4648 			       tree vec_dest, gimple_stmt_iterator *gsi,
   4649 			       stmt_vec_info stmt_info)
   4650 {
   4651   gimple *new_stmt;
   4652   tree new_temp;
   4653 
   4654   /* Generate half of the widened result:  */
   4655   gcc_assert (op_type == TREE_CODE_LENGTH (code));
   4656   if (op_type != binary_op)
   4657     vec_oprnd1 = NULL;
   4658   new_stmt = gimple_build_assign (vec_dest, code, vec_oprnd0, vec_oprnd1);
   4659   new_temp = make_ssa_name (vec_dest, new_stmt);
   4660   gimple_assign_set_lhs (new_stmt, new_temp);
   4661   vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   4662 
   4663   return new_stmt;
   4664 }
   4665 
   4666 
   4667 /* Create vectorized demotion statements for vector operands from VEC_OPRNDS.
   4668    For multi-step conversions store the resulting vectors and call the function
   4669    recursively.  */
   4670 
   4671 static void
   4672 vect_create_vectorized_demotion_stmts (vec_info *vinfo, vec<tree> *vec_oprnds,
   4673 				       int multi_step_cvt,
   4674 				       stmt_vec_info stmt_info,
   4675 				       vec<tree> &vec_dsts,
   4676 				       gimple_stmt_iterator *gsi,
   4677 				       slp_tree slp_node, enum tree_code code)
   4678 {
   4679   unsigned int i;
   4680   tree vop0, vop1, new_tmp, vec_dest;
   4681 
   4682   vec_dest = vec_dsts.pop ();
   4683 
   4684   for (i = 0; i < vec_oprnds->length (); i += 2)
   4685     {
   4686       /* Create demotion operation.  */
   4687       vop0 = (*vec_oprnds)[i];
   4688       vop1 = (*vec_oprnds)[i + 1];
   4689       gassign *new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1);
   4690       new_tmp = make_ssa_name (vec_dest, new_stmt);
   4691       gimple_assign_set_lhs (new_stmt, new_tmp);
   4692       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   4693 
   4694       if (multi_step_cvt)
   4695 	/* Store the resulting vector for next recursive call.  */
   4696 	(*vec_oprnds)[i/2] = new_tmp;
   4697       else
   4698 	{
   4699 	  /* This is the last step of the conversion sequence. Store the
   4700 	     vectors in SLP_NODE or in vector info of the scalar statement
   4701 	     (or in STMT_VINFO_RELATED_STMT chain).  */
   4702 	  if (slp_node)
   4703 	    SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   4704 	  else
   4705 	    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   4706 	}
   4707     }
   4708 
   4709   /* For multi-step demotion operations we first generate demotion operations
   4710      from the source type to the intermediate types, and then combine the
   4711      results (stored in VEC_OPRNDS) in demotion operation to the destination
   4712      type.  */
   4713   if (multi_step_cvt)
   4714     {
   4715       /* At each level of recursion we have half of the operands we had at the
   4716 	 previous level.  */
   4717       vec_oprnds->truncate ((i+1)/2);
   4718       vect_create_vectorized_demotion_stmts (vinfo, vec_oprnds,
   4719 					     multi_step_cvt - 1,
   4720 					     stmt_info, vec_dsts, gsi,
   4721 					     slp_node, VEC_PACK_TRUNC_EXPR);
   4722     }
   4723 
   4724   vec_dsts.quick_push (vec_dest);
   4725 }
   4726 
   4727 
   4728 /* Create vectorized promotion statements for vector operands from VEC_OPRNDS0
   4729    and VEC_OPRNDS1, for a binary operation associated with scalar statement
   4730    STMT_INFO.  For multi-step conversions store the resulting vectors and
   4731    call the function recursively.  */
   4732 
   4733 static void
   4734 vect_create_vectorized_promotion_stmts (vec_info *vinfo,
   4735 					vec<tree> *vec_oprnds0,
   4736 					vec<tree> *vec_oprnds1,
   4737 					stmt_vec_info stmt_info, tree vec_dest,
   4738 					gimple_stmt_iterator *gsi,
   4739 					enum tree_code code1,
   4740 					enum tree_code code2, int op_type)
   4741 {
   4742   int i;
   4743   tree vop0, vop1, new_tmp1, new_tmp2;
   4744   gimple *new_stmt1, *new_stmt2;
   4745   vec<tree> vec_tmp = vNULL;
   4746 
   4747   vec_tmp.create (vec_oprnds0->length () * 2);
   4748   FOR_EACH_VEC_ELT (*vec_oprnds0, i, vop0)
   4749     {
   4750       if (op_type == binary_op)
   4751 	vop1 = (*vec_oprnds1)[i];
   4752       else
   4753 	vop1 = NULL_TREE;
   4754 
   4755       /* Generate the two halves of promotion operation.  */
   4756       new_stmt1 = vect_gen_widened_results_half (vinfo, code1, vop0, vop1,
   4757 						 op_type, vec_dest, gsi,
   4758 						 stmt_info);
   4759       new_stmt2 = vect_gen_widened_results_half (vinfo, code2, vop0, vop1,
   4760 						 op_type, vec_dest, gsi,
   4761 						 stmt_info);
   4762       if (is_gimple_call (new_stmt1))
   4763 	{
   4764 	  new_tmp1 = gimple_call_lhs (new_stmt1);
   4765 	  new_tmp2 = gimple_call_lhs (new_stmt2);
   4766 	}
   4767       else
   4768 	{
   4769 	  new_tmp1 = gimple_assign_lhs (new_stmt1);
   4770 	  new_tmp2 = gimple_assign_lhs (new_stmt2);
   4771 	}
   4772 
   4773       /* Store the results for the next step.  */
   4774       vec_tmp.quick_push (new_tmp1);
   4775       vec_tmp.quick_push (new_tmp2);
   4776     }
   4777 
   4778   vec_oprnds0->release ();
   4779   *vec_oprnds0 = vec_tmp;
   4780 }
   4781 
   4782 /* Create vectorized promotion stmts for widening stmts using only half the
   4783    potential vector size for input.  */
   4784 static void
   4785 vect_create_half_widening_stmts (vec_info *vinfo,
   4786 					vec<tree> *vec_oprnds0,
   4787 					vec<tree> *vec_oprnds1,
   4788 					stmt_vec_info stmt_info, tree vec_dest,
   4789 					gimple_stmt_iterator *gsi,
   4790 					enum tree_code code1,
   4791 					int op_type)
   4792 {
   4793   int i;
   4794   tree vop0, vop1;
   4795   gimple *new_stmt1;
   4796   gimple *new_stmt2;
   4797   gimple *new_stmt3;
   4798   vec<tree> vec_tmp = vNULL;
   4799 
   4800   vec_tmp.create (vec_oprnds0->length ());
   4801   FOR_EACH_VEC_ELT (*vec_oprnds0, i, vop0)
   4802     {
   4803       tree new_tmp1, new_tmp2, new_tmp3, out_type;
   4804 
   4805       gcc_assert (op_type == binary_op);
   4806       vop1 = (*vec_oprnds1)[i];
   4807 
   4808       /* Widen the first vector input.  */
   4809       out_type = TREE_TYPE (vec_dest);
   4810       new_tmp1 = make_ssa_name (out_type);
   4811       new_stmt1 = gimple_build_assign (new_tmp1, NOP_EXPR, vop0);
   4812       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt1, gsi);
   4813       if (VECTOR_TYPE_P (TREE_TYPE (vop1)))
   4814 	{
   4815 	  /* Widen the second vector input.  */
   4816 	  new_tmp2 = make_ssa_name (out_type);
   4817 	  new_stmt2 = gimple_build_assign (new_tmp2, NOP_EXPR, vop1);
   4818 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt2, gsi);
   4819 	  /* Perform the operation.  With both vector inputs widened.  */
   4820 	  new_stmt3 = gimple_build_assign (vec_dest, code1, new_tmp1, new_tmp2);
   4821 	}
   4822       else
   4823 	{
   4824 	  /* Perform the operation.  With the single vector input widened.  */
   4825 	  new_stmt3 = gimple_build_assign (vec_dest, code1, new_tmp1, vop1);
   4826       }
   4827 
   4828       new_tmp3 = make_ssa_name (vec_dest, new_stmt3);
   4829       gimple_assign_set_lhs (new_stmt3, new_tmp3);
   4830       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt3, gsi);
   4831 
   4832       /* Store the results for the next step.  */
   4833       vec_tmp.quick_push (new_tmp3);
   4834     }
   4835 
   4836   vec_oprnds0->release ();
   4837   *vec_oprnds0 = vec_tmp;
   4838 }
   4839 
   4840 
   4841 /* Check if STMT_INFO performs a conversion operation that can be vectorized.
   4842    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   4843    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   4844    Return true if STMT_INFO is vectorizable in this way.  */
   4845 
   4846 static bool
   4847 vectorizable_conversion (vec_info *vinfo,
   4848 			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   4849 			 gimple **vec_stmt, slp_tree slp_node,
   4850 			 stmt_vector_for_cost *cost_vec)
   4851 {
   4852   tree vec_dest;
   4853   tree scalar_dest;
   4854   tree op0, op1 = NULL_TREE;
   4855   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   4856   enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
   4857   enum tree_code codecvt1 = ERROR_MARK, codecvt2 = ERROR_MARK;
   4858   tree new_temp;
   4859   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
   4860   int ndts = 2;
   4861   poly_uint64 nunits_in;
   4862   poly_uint64 nunits_out;
   4863   tree vectype_out, vectype_in;
   4864   int ncopies, i;
   4865   tree lhs_type, rhs_type;
   4866   enum { NARROW, NONE, WIDEN } modifier;
   4867   vec<tree> vec_oprnds0 = vNULL;
   4868   vec<tree> vec_oprnds1 = vNULL;
   4869   tree vop0;
   4870   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   4871   int multi_step_cvt = 0;
   4872   vec<tree> interm_types = vNULL;
   4873   tree intermediate_type, cvt_type = NULL_TREE;
   4874   int op_type;
   4875   unsigned short fltsz;
   4876 
   4877   /* Is STMT a vectorizable conversion?   */
   4878 
   4879   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   4880     return false;
   4881 
   4882   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   4883       && ! vec_stmt)
   4884     return false;
   4885 
   4886   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
   4887   if (!stmt)
   4888     return false;
   4889 
   4890   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
   4891     return false;
   4892 
   4893   code = gimple_assign_rhs_code (stmt);
   4894   if (!CONVERT_EXPR_CODE_P (code)
   4895       && code != FIX_TRUNC_EXPR
   4896       && code != FLOAT_EXPR
   4897       && code != WIDEN_PLUS_EXPR
   4898       && code != WIDEN_MINUS_EXPR
   4899       && code != WIDEN_MULT_EXPR
   4900       && code != WIDEN_LSHIFT_EXPR)
   4901     return false;
   4902 
   4903   bool widen_arith = (code == WIDEN_PLUS_EXPR
   4904 		      || code == WIDEN_MINUS_EXPR
   4905 		      || code == WIDEN_MULT_EXPR
   4906 		      || code == WIDEN_LSHIFT_EXPR);
   4907   op_type = TREE_CODE_LENGTH (code);
   4908 
   4909   /* Check types of lhs and rhs.  */
   4910   scalar_dest = gimple_assign_lhs (stmt);
   4911   lhs_type = TREE_TYPE (scalar_dest);
   4912   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
   4913 
   4914   /* Check the operands of the operation.  */
   4915   slp_tree slp_op0, slp_op1 = NULL;
   4916   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   4917 			   0, &op0, &slp_op0, &dt[0], &vectype_in))
   4918     {
   4919       if (dump_enabled_p ())
   4920 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4921 			 "use not simple.\n");
   4922       return false;
   4923     }
   4924 
   4925   rhs_type = TREE_TYPE (op0);
   4926   if ((code != FIX_TRUNC_EXPR && code != FLOAT_EXPR)
   4927       && !((INTEGRAL_TYPE_P (lhs_type)
   4928 	    && INTEGRAL_TYPE_P (rhs_type))
   4929 	   || (SCALAR_FLOAT_TYPE_P (lhs_type)
   4930 	       && SCALAR_FLOAT_TYPE_P (rhs_type))))
   4931     return false;
   4932 
   4933   if (!VECTOR_BOOLEAN_TYPE_P (vectype_out)
   4934       && ((INTEGRAL_TYPE_P (lhs_type)
   4935 	   && !type_has_mode_precision_p (lhs_type))
   4936 	  || (INTEGRAL_TYPE_P (rhs_type)
   4937 	      && !type_has_mode_precision_p (rhs_type))))
   4938     {
   4939       if (dump_enabled_p ())
   4940 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4941                          "type conversion to/from bit-precision unsupported."
   4942                          "\n");
   4943       return false;
   4944     }
   4945 
   4946   if (op_type == binary_op)
   4947     {
   4948       gcc_assert (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR
   4949 		  || code == WIDEN_PLUS_EXPR || code == WIDEN_MINUS_EXPR);
   4950 
   4951       op1 = gimple_assign_rhs2 (stmt);
   4952       tree vectype1_in;
   4953       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1,
   4954 			       &op1, &slp_op1, &dt[1], &vectype1_in))
   4955 	{
   4956           if (dump_enabled_p ())
   4957             dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4958                              "use not simple.\n");
   4959 	  return false;
   4960 	}
   4961       /* For WIDEN_MULT_EXPR, if OP0 is a constant, use the type of
   4962 	 OP1.  */
   4963       if (!vectype_in)
   4964 	vectype_in = vectype1_in;
   4965     }
   4966 
   4967   /* If op0 is an external or constant def, infer the vector type
   4968      from the scalar type.  */
   4969   if (!vectype_in)
   4970     vectype_in = get_vectype_for_scalar_type (vinfo, rhs_type, slp_node);
   4971   if (vec_stmt)
   4972     gcc_assert (vectype_in);
   4973   if (!vectype_in)
   4974     {
   4975       if (dump_enabled_p ())
   4976 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4977 			 "no vectype for scalar type %T\n", rhs_type);
   4978 
   4979       return false;
   4980     }
   4981 
   4982   if (VECTOR_BOOLEAN_TYPE_P (vectype_out)
   4983       && !VECTOR_BOOLEAN_TYPE_P (vectype_in))
   4984     {
   4985       if (dump_enabled_p ())
   4986 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   4987 			 "can't convert between boolean and non "
   4988 			 "boolean vectors %T\n", rhs_type);
   4989 
   4990       return false;
   4991     }
   4992 
   4993   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
   4994   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   4995   if (known_eq (nunits_out, nunits_in))
   4996     if (widen_arith)
   4997       modifier = WIDEN;
   4998     else
   4999       modifier = NONE;
   5000   else if (multiple_p (nunits_out, nunits_in))
   5001     modifier = NARROW;
   5002   else
   5003     {
   5004       gcc_checking_assert (multiple_p (nunits_in, nunits_out));
   5005       modifier = WIDEN;
   5006     }
   5007 
   5008   /* Multiple types in SLP are handled by creating the appropriate number of
   5009      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
   5010      case of SLP.  */
   5011   if (slp_node)
   5012     ncopies = 1;
   5013   else if (modifier == NARROW)
   5014     ncopies = vect_get_num_copies (loop_vinfo, vectype_out);
   5015   else
   5016     ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
   5017 
   5018   /* Sanity check: make sure that at least one copy of the vectorized stmt
   5019      needs to be generated.  */
   5020   gcc_assert (ncopies >= 1);
   5021 
   5022   bool found_mode = false;
   5023   scalar_mode lhs_mode = SCALAR_TYPE_MODE (lhs_type);
   5024   scalar_mode rhs_mode = SCALAR_TYPE_MODE (rhs_type);
   5025   opt_scalar_mode rhs_mode_iter;
   5026 
   5027   /* Supportable by target?  */
   5028   switch (modifier)
   5029     {
   5030     case NONE:
   5031       if (code != FIX_TRUNC_EXPR
   5032 	  && code != FLOAT_EXPR
   5033 	  && !CONVERT_EXPR_CODE_P (code))
   5034 	return false;
   5035       if (supportable_convert_operation (code, vectype_out, vectype_in, &code1))
   5036 	break;
   5037       /* FALLTHRU */
   5038     unsupported:
   5039       if (dump_enabled_p ())
   5040 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5041                          "conversion not supported by target.\n");
   5042       return false;
   5043 
   5044     case WIDEN:
   5045       if (known_eq (nunits_in, nunits_out))
   5046 	{
   5047 	  if (!supportable_half_widening_operation (code, vectype_out,
   5048 						   vectype_in, &code1))
   5049 	    goto unsupported;
   5050 	  gcc_assert (!(multi_step_cvt && op_type == binary_op));
   5051 	  break;
   5052 	}
   5053       if (supportable_widening_operation (vinfo, code, stmt_info,
   5054 					       vectype_out, vectype_in, &code1,
   5055 					       &code2, &multi_step_cvt,
   5056 					       &interm_types))
   5057 	{
   5058 	  /* Binary widening operation can only be supported directly by the
   5059 	     architecture.  */
   5060 	  gcc_assert (!(multi_step_cvt && op_type == binary_op));
   5061 	  break;
   5062 	}
   5063 
   5064       if (code != FLOAT_EXPR
   5065 	  || GET_MODE_SIZE (lhs_mode) <= GET_MODE_SIZE (rhs_mode))
   5066 	goto unsupported;
   5067 
   5068       fltsz = GET_MODE_SIZE (lhs_mode);
   5069       FOR_EACH_2XWIDER_MODE (rhs_mode_iter, rhs_mode)
   5070 	{
   5071 	  rhs_mode = rhs_mode_iter.require ();
   5072 	  if (GET_MODE_SIZE (rhs_mode) > fltsz)
   5073 	    break;
   5074 
   5075 	  cvt_type
   5076 	    = build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), 0);
   5077 	  cvt_type = get_same_sized_vectype (cvt_type, vectype_in);
   5078 	  if (cvt_type == NULL_TREE)
   5079 	    goto unsupported;
   5080 
   5081 	  if (GET_MODE_SIZE (rhs_mode) == fltsz)
   5082 	    {
   5083 	      if (!supportable_convert_operation (code, vectype_out,
   5084 						  cvt_type, &codecvt1))
   5085 		goto unsupported;
   5086 	    }
   5087 	  else if (!supportable_widening_operation (vinfo, code, stmt_info,
   5088 						    vectype_out, cvt_type,
   5089 						    &codecvt1, &codecvt2,
   5090 						    &multi_step_cvt,
   5091 						    &interm_types))
   5092 	    continue;
   5093 	  else
   5094 	    gcc_assert (multi_step_cvt == 0);
   5095 
   5096 	  if (supportable_widening_operation (vinfo, NOP_EXPR, stmt_info,
   5097 					      cvt_type,
   5098 					      vectype_in, &code1, &code2,
   5099 					      &multi_step_cvt, &interm_types))
   5100 	    {
   5101 	      found_mode = true;
   5102 	      break;
   5103 	    }
   5104 	}
   5105 
   5106       if (!found_mode)
   5107 	goto unsupported;
   5108 
   5109       if (GET_MODE_SIZE (rhs_mode) == fltsz)
   5110 	codecvt2 = ERROR_MARK;
   5111       else
   5112 	{
   5113 	  multi_step_cvt++;
   5114 	  interm_types.safe_push (cvt_type);
   5115 	  cvt_type = NULL_TREE;
   5116 	}
   5117       break;
   5118 
   5119     case NARROW:
   5120       gcc_assert (op_type == unary_op);
   5121       if (supportable_narrowing_operation (code, vectype_out, vectype_in,
   5122 					   &code1, &multi_step_cvt,
   5123 					   &interm_types))
   5124 	break;
   5125 
   5126       if (code != FIX_TRUNC_EXPR
   5127 	  || GET_MODE_SIZE (lhs_mode) >= GET_MODE_SIZE (rhs_mode))
   5128 	goto unsupported;
   5129 
   5130       cvt_type
   5131 	= build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), 0);
   5132       cvt_type = get_same_sized_vectype (cvt_type, vectype_in);
   5133       if (cvt_type == NULL_TREE)
   5134 	goto unsupported;
   5135       if (!supportable_convert_operation (code, cvt_type, vectype_in,
   5136 					  &codecvt1))
   5137 	goto unsupported;
   5138       if (supportable_narrowing_operation (NOP_EXPR, vectype_out, cvt_type,
   5139 					   &code1, &multi_step_cvt,
   5140 					   &interm_types))
   5141 	break;
   5142       goto unsupported;
   5143 
   5144     default:
   5145       gcc_unreachable ();
   5146     }
   5147 
   5148   if (!vec_stmt)		/* transformation not required.  */
   5149     {
   5150       if (slp_node
   5151 	  && (!vect_maybe_update_slp_op_vectype (slp_op0, vectype_in)
   5152 	      || !vect_maybe_update_slp_op_vectype (slp_op1, vectype_in)))
   5153 	{
   5154 	  if (dump_enabled_p ())
   5155 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5156 			     "incompatible vector types for invariants\n");
   5157 	  return false;
   5158 	}
   5159       DUMP_VECT_SCOPE ("vectorizable_conversion");
   5160       if (modifier == NONE)
   5161         {
   5162 	  STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
   5163 	  vect_model_simple_cost (vinfo, stmt_info, ncopies, dt, ndts, slp_node,
   5164 				  cost_vec);
   5165 	}
   5166       else if (modifier == NARROW)
   5167 	{
   5168 	  STMT_VINFO_TYPE (stmt_info) = type_demotion_vec_info_type;
   5169 	  /* The final packing step produces one vector result per copy.  */
   5170 	  unsigned int nvectors
   5171 	    = (slp_node ? SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) : ncopies);
   5172 	  vect_model_promotion_demotion_cost (stmt_info, dt, nvectors,
   5173 					      multi_step_cvt, cost_vec,
   5174 					      widen_arith);
   5175 	}
   5176       else
   5177 	{
   5178 	  STMT_VINFO_TYPE (stmt_info) = type_promotion_vec_info_type;
   5179 	  /* The initial unpacking step produces two vector results
   5180 	     per copy.  MULTI_STEP_CVT is 0 for a single conversion,
   5181 	     so >> MULTI_STEP_CVT divides by 2^(number of steps - 1).  */
   5182 	  unsigned int nvectors
   5183 	    = (slp_node
   5184 	       ? SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) >> multi_step_cvt
   5185 	       : ncopies * 2);
   5186 	  vect_model_promotion_demotion_cost (stmt_info, dt, nvectors,
   5187 					      multi_step_cvt, cost_vec,
   5188 					      widen_arith);
   5189 	}
   5190       interm_types.release ();
   5191       return true;
   5192     }
   5193 
   5194   /* Transform.  */
   5195   if (dump_enabled_p ())
   5196     dump_printf_loc (MSG_NOTE, vect_location,
   5197                      "transform conversion. ncopies = %d.\n", ncopies);
   5198 
   5199   if (op_type == binary_op)
   5200     {
   5201       if (CONSTANT_CLASS_P (op0))
   5202 	op0 = fold_convert (TREE_TYPE (op1), op0);
   5203       else if (CONSTANT_CLASS_P (op1))
   5204 	op1 = fold_convert (TREE_TYPE (op0), op1);
   5205     }
   5206 
   5207   /* In case of multi-step conversion, we first generate conversion operations
   5208      to the intermediate types, and then from that types to the final one.
   5209      We create vector destinations for the intermediate type (TYPES) received
   5210      from supportable_*_operation, and store them in the correct order
   5211      for future use in vect_create_vectorized_*_stmts ().  */
   5212   auto_vec<tree> vec_dsts (multi_step_cvt + 1);
   5213   vec_dest = vect_create_destination_var (scalar_dest,
   5214 					  (cvt_type && modifier == WIDEN)
   5215 					  ? cvt_type : vectype_out);
   5216   vec_dsts.quick_push (vec_dest);
   5217 
   5218   if (multi_step_cvt)
   5219     {
   5220       for (i = interm_types.length () - 1;
   5221 	   interm_types.iterate (i, &intermediate_type); i--)
   5222 	{
   5223 	  vec_dest = vect_create_destination_var (scalar_dest,
   5224 						  intermediate_type);
   5225 	  vec_dsts.quick_push (vec_dest);
   5226 	}
   5227     }
   5228 
   5229   if (cvt_type)
   5230     vec_dest = vect_create_destination_var (scalar_dest,
   5231 					    modifier == WIDEN
   5232 					    ? vectype_out : cvt_type);
   5233 
   5234   int ninputs = 1;
   5235   if (!slp_node)
   5236     {
   5237       if (modifier == WIDEN)
   5238 	;
   5239       else if (modifier == NARROW)
   5240 	{
   5241 	  if (multi_step_cvt)
   5242 	    ninputs = vect_pow2 (multi_step_cvt);
   5243 	  ninputs *= 2;
   5244 	}
   5245     }
   5246 
   5247   switch (modifier)
   5248     {
   5249     case NONE:
   5250       vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   5251 			 op0, &vec_oprnds0);
   5252       FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
   5253 	{
   5254 	  /* Arguments are ready, create the new vector stmt.  */
   5255 	  gcc_assert (TREE_CODE_LENGTH (code1) == unary_op);
   5256 	  gassign *new_stmt = gimple_build_assign (vec_dest, code1, vop0);
   5257 	  new_temp = make_ssa_name (vec_dest, new_stmt);
   5258 	  gimple_assign_set_lhs (new_stmt, new_temp);
   5259 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   5260 
   5261 	  if (slp_node)
   5262 	    SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   5263 	  else
   5264 	    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   5265 	}
   5266       break;
   5267 
   5268     case WIDEN:
   5269       /* In case the vectorization factor (VF) is bigger than the number
   5270 	 of elements that we can fit in a vectype (nunits), we have to
   5271 	 generate more than one vector stmt - i.e - we need to "unroll"
   5272 	 the vector stmt by a factor VF/nunits.  */
   5273       vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies * ninputs,
   5274 			 op0, &vec_oprnds0,
   5275 			 code == WIDEN_LSHIFT_EXPR ? NULL_TREE : op1,
   5276 			 &vec_oprnds1);
   5277       if (code == WIDEN_LSHIFT_EXPR)
   5278 	{
   5279 	  int oprnds_size = vec_oprnds0.length ();
   5280 	  vec_oprnds1.create (oprnds_size);
   5281 	  for (i = 0; i < oprnds_size; ++i)
   5282 	    vec_oprnds1.quick_push (op1);
   5283 	}
   5284       /* Arguments are ready.  Create the new vector stmts.  */
   5285       for (i = multi_step_cvt; i >= 0; i--)
   5286 	{
   5287 	  tree this_dest = vec_dsts[i];
   5288 	  enum tree_code c1 = code1, c2 = code2;
   5289 	  if (i == 0 && codecvt2 != ERROR_MARK)
   5290 	    {
   5291 	      c1 = codecvt1;
   5292 	      c2 = codecvt2;
   5293 	    }
   5294 	  if (known_eq (nunits_out, nunits_in))
   5295 	    vect_create_half_widening_stmts (vinfo, &vec_oprnds0,
   5296 						    &vec_oprnds1, stmt_info,
   5297 						    this_dest, gsi,
   5298 						    c1, op_type);
   5299 	  else
   5300 	    vect_create_vectorized_promotion_stmts (vinfo, &vec_oprnds0,
   5301 						    &vec_oprnds1, stmt_info,
   5302 						    this_dest, gsi,
   5303 						    c1, c2, op_type);
   5304 	}
   5305 
   5306       FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
   5307 	{
   5308 	  gimple *new_stmt;
   5309 	  if (cvt_type)
   5310 	    {
   5311 	      gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
   5312 	      new_temp = make_ssa_name (vec_dest);
   5313 	      new_stmt = gimple_build_assign (new_temp, codecvt1, vop0);
   5314 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   5315 	    }
   5316 	  else
   5317 	    new_stmt = SSA_NAME_DEF_STMT (vop0);
   5318 
   5319 	  if (slp_node)
   5320 	    SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   5321 	  else
   5322 	    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   5323 	}
   5324       break;
   5325 
   5326     case NARROW:
   5327       /* In case the vectorization factor (VF) is bigger than the number
   5328 	 of elements that we can fit in a vectype (nunits), we have to
   5329 	 generate more than one vector stmt - i.e - we need to "unroll"
   5330 	 the vector stmt by a factor VF/nunits.  */
   5331       vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies * ninputs,
   5332 			 op0, &vec_oprnds0);
   5333       /* Arguments are ready.  Create the new vector stmts.  */
   5334       if (cvt_type)
   5335 	FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
   5336 	  {
   5337 	    gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
   5338 	    new_temp = make_ssa_name (vec_dest);
   5339 	    gassign *new_stmt
   5340 	      = gimple_build_assign (new_temp, codecvt1, vop0);
   5341 	    vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   5342 	    vec_oprnds0[i] = new_temp;
   5343 	  }
   5344 
   5345       vect_create_vectorized_demotion_stmts (vinfo, &vec_oprnds0,
   5346 					     multi_step_cvt,
   5347 					     stmt_info, vec_dsts, gsi,
   5348 					     slp_node, code1);
   5349       break;
   5350     }
   5351   if (!slp_node)
   5352     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   5353 
   5354   vec_oprnds0.release ();
   5355   vec_oprnds1.release ();
   5356   interm_types.release ();
   5357 
   5358   return true;
   5359 }
   5360 
   5361 /* Return true if we can assume from the scalar form of STMT_INFO that
   5362    neither the scalar nor the vector forms will generate code.  STMT_INFO
   5363    is known not to involve a data reference.  */
   5364 
   5365 bool
   5366 vect_nop_conversion_p (stmt_vec_info stmt_info)
   5367 {
   5368   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
   5369   if (!stmt)
   5370     return false;
   5371 
   5372   tree lhs = gimple_assign_lhs (stmt);
   5373   tree_code code = gimple_assign_rhs_code (stmt);
   5374   tree rhs = gimple_assign_rhs1 (stmt);
   5375 
   5376   if (code == SSA_NAME || code == VIEW_CONVERT_EXPR)
   5377     return true;
   5378 
   5379   if (CONVERT_EXPR_CODE_P (code))
   5380     return tree_nop_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs));
   5381 
   5382   return false;
   5383 }
   5384 
   5385 /* Function vectorizable_assignment.
   5386 
   5387    Check if STMT_INFO performs an assignment (copy) that can be vectorized.
   5388    If VEC_STMT is also passed, vectorize the STMT_INFO: create a vectorized
   5389    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   5390    Return true if STMT_INFO is vectorizable in this way.  */
   5391 
   5392 static bool
   5393 vectorizable_assignment (vec_info *vinfo,
   5394 			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   5395 			 gimple **vec_stmt, slp_tree slp_node,
   5396 			 stmt_vector_for_cost *cost_vec)
   5397 {
   5398   tree vec_dest;
   5399   tree scalar_dest;
   5400   tree op;
   5401   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   5402   tree new_temp;
   5403   enum vect_def_type dt[1] = {vect_unknown_def_type};
   5404   int ndts = 1;
   5405   int ncopies;
   5406   int i;
   5407   vec<tree> vec_oprnds = vNULL;
   5408   tree vop;
   5409   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   5410   enum tree_code code;
   5411   tree vectype_in;
   5412 
   5413   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   5414     return false;
   5415 
   5416   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   5417       && ! vec_stmt)
   5418     return false;
   5419 
   5420   /* Is vectorizable assignment?  */
   5421   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
   5422   if (!stmt)
   5423     return false;
   5424 
   5425   scalar_dest = gimple_assign_lhs (stmt);
   5426   if (TREE_CODE (scalar_dest) != SSA_NAME)
   5427     return false;
   5428 
   5429   if (STMT_VINFO_DATA_REF (stmt_info))
   5430     return false;
   5431 
   5432   code = gimple_assign_rhs_code (stmt);
   5433   if (!(gimple_assign_single_p (stmt)
   5434 	|| code == PAREN_EXPR
   5435 	|| CONVERT_EXPR_CODE_P (code)))
   5436     return false;
   5437 
   5438   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   5439   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   5440 
   5441   /* Multiple types in SLP are handled by creating the appropriate number of
   5442      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
   5443      case of SLP.  */
   5444   if (slp_node)
   5445     ncopies = 1;
   5446   else
   5447     ncopies = vect_get_num_copies (loop_vinfo, vectype);
   5448 
   5449   gcc_assert (ncopies >= 1);
   5450 
   5451   slp_tree slp_op;
   5452   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0, &op, &slp_op,
   5453 			   &dt[0], &vectype_in))
   5454     {
   5455       if (dump_enabled_p ())
   5456         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5457                          "use not simple.\n");
   5458       return false;
   5459     }
   5460   if (!vectype_in)
   5461     vectype_in = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op), slp_node);
   5462 
   5463   /* We can handle NOP_EXPR conversions that do not change the number
   5464      of elements or the vector size.  */
   5465   if ((CONVERT_EXPR_CODE_P (code)
   5466        || code == VIEW_CONVERT_EXPR)
   5467       && (!vectype_in
   5468 	  || maybe_ne (TYPE_VECTOR_SUBPARTS (vectype_in), nunits)
   5469 	  || maybe_ne (GET_MODE_SIZE (TYPE_MODE (vectype)),
   5470 		       GET_MODE_SIZE (TYPE_MODE (vectype_in)))))
   5471     return false;
   5472 
   5473   if (VECTOR_BOOLEAN_TYPE_P (vectype) != VECTOR_BOOLEAN_TYPE_P (vectype_in))
   5474     {
   5475       if (dump_enabled_p ())
   5476 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5477 			 "can't convert between boolean and non "
   5478 			 "boolean vectors %T\n", TREE_TYPE (op));
   5479 
   5480       return false;
   5481     }
   5482 
   5483   /* We do not handle bit-precision changes.  */
   5484   if ((CONVERT_EXPR_CODE_P (code)
   5485        || code == VIEW_CONVERT_EXPR)
   5486       && INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
   5487       && (!type_has_mode_precision_p (TREE_TYPE (scalar_dest))
   5488 	  || !type_has_mode_precision_p (TREE_TYPE (op)))
   5489       /* But a conversion that does not change the bit-pattern is ok.  */
   5490       && !((TYPE_PRECISION (TREE_TYPE (scalar_dest))
   5491 	    > TYPE_PRECISION (TREE_TYPE (op)))
   5492 	   && TYPE_UNSIGNED (TREE_TYPE (op))))
   5493     {
   5494       if (dump_enabled_p ())
   5495         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5496                          "type conversion to/from bit-precision "
   5497                          "unsupported.\n");
   5498       return false;
   5499     }
   5500 
   5501   if (!vec_stmt) /* transformation not required.  */
   5502     {
   5503       if (slp_node
   5504 	  && !vect_maybe_update_slp_op_vectype (slp_op, vectype_in))
   5505 	{
   5506 	  if (dump_enabled_p ())
   5507 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5508 			     "incompatible vector types for invariants\n");
   5509 	  return false;
   5510 	}
   5511       STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
   5512       DUMP_VECT_SCOPE ("vectorizable_assignment");
   5513       if (!vect_nop_conversion_p (stmt_info))
   5514 	vect_model_simple_cost (vinfo, stmt_info, ncopies, dt, ndts, slp_node,
   5515 				cost_vec);
   5516       return true;
   5517     }
   5518 
   5519   /* Transform.  */
   5520   if (dump_enabled_p ())
   5521     dump_printf_loc (MSG_NOTE, vect_location, "transform assignment.\n");
   5522 
   5523   /* Handle def.  */
   5524   vec_dest = vect_create_destination_var (scalar_dest, vectype);
   5525 
   5526   /* Handle use.  */
   5527   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies, op, &vec_oprnds);
   5528 
   5529   /* Arguments are ready. create the new vector stmt.  */
   5530   FOR_EACH_VEC_ELT (vec_oprnds, i, vop)
   5531     {
   5532       if (CONVERT_EXPR_CODE_P (code)
   5533 	  || code == VIEW_CONVERT_EXPR)
   5534 	vop = build1 (VIEW_CONVERT_EXPR, vectype, vop);
   5535       gassign *new_stmt = gimple_build_assign (vec_dest, vop);
   5536       new_temp = make_ssa_name (vec_dest, new_stmt);
   5537       gimple_assign_set_lhs (new_stmt, new_temp);
   5538       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   5539       if (slp_node)
   5540 	SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   5541       else
   5542 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   5543     }
   5544   if (!slp_node)
   5545     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   5546 
   5547   vec_oprnds.release ();
   5548   return true;
   5549 }
   5550 
   5551 
   5552 /* Return TRUE if CODE (a shift operation) is supported for SCALAR_TYPE
   5553    either as shift by a scalar or by a vector.  */
   5554 
   5555 bool
   5556 vect_supportable_shift (vec_info *vinfo, enum tree_code code, tree scalar_type)
   5557 {
   5558 
   5559   machine_mode vec_mode;
   5560   optab optab;
   5561   int icode;
   5562   tree vectype;
   5563 
   5564   vectype = get_vectype_for_scalar_type (vinfo, scalar_type);
   5565   if (!vectype)
   5566     return false;
   5567 
   5568   optab = optab_for_tree_code (code, vectype, optab_scalar);
   5569   if (!optab
   5570       || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing)
   5571     {
   5572       optab = optab_for_tree_code (code, vectype, optab_vector);
   5573       if (!optab
   5574           || (optab_handler (optab, TYPE_MODE (vectype))
   5575                       == CODE_FOR_nothing))
   5576         return false;
   5577     }
   5578 
   5579   vec_mode = TYPE_MODE (vectype);
   5580   icode = (int) optab_handler (optab, vec_mode);
   5581   if (icode == CODE_FOR_nothing)
   5582     return false;
   5583 
   5584   return true;
   5585 }
   5586 
   5587 
   5588 /* Function vectorizable_shift.
   5589 
   5590    Check if STMT_INFO performs a shift operation that can be vectorized.
   5591    If VEC_STMT is also passed, vectorize the STMT_INFO: create a vectorized
   5592    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   5593    Return true if STMT_INFO is vectorizable in this way.  */
   5594 
   5595 static bool
   5596 vectorizable_shift (vec_info *vinfo,
   5597 		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   5598 		    gimple **vec_stmt, slp_tree slp_node,
   5599 		    stmt_vector_for_cost *cost_vec)
   5600 {
   5601   tree vec_dest;
   5602   tree scalar_dest;
   5603   tree op0, op1 = NULL;
   5604   tree vec_oprnd1 = NULL_TREE;
   5605   tree vectype;
   5606   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   5607   enum tree_code code;
   5608   machine_mode vec_mode;
   5609   tree new_temp;
   5610   optab optab;
   5611   int icode;
   5612   machine_mode optab_op2_mode;
   5613   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
   5614   int ndts = 2;
   5615   poly_uint64 nunits_in;
   5616   poly_uint64 nunits_out;
   5617   tree vectype_out;
   5618   tree op1_vectype;
   5619   int ncopies;
   5620   int i;
   5621   vec<tree> vec_oprnds0 = vNULL;
   5622   vec<tree> vec_oprnds1 = vNULL;
   5623   tree vop0, vop1;
   5624   unsigned int k;
   5625   bool scalar_shift_arg = true;
   5626   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   5627   bool incompatible_op1_vectype_p = false;
   5628 
   5629   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   5630     return false;
   5631 
   5632   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   5633       && STMT_VINFO_DEF_TYPE (stmt_info) != vect_nested_cycle
   5634       && ! vec_stmt)
   5635     return false;
   5636 
   5637   /* Is STMT a vectorizable binary/unary operation?   */
   5638   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
   5639   if (!stmt)
   5640     return false;
   5641 
   5642   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
   5643     return false;
   5644 
   5645   code = gimple_assign_rhs_code (stmt);
   5646 
   5647   if (!(code == LSHIFT_EXPR || code == RSHIFT_EXPR || code == LROTATE_EXPR
   5648       || code == RROTATE_EXPR))
   5649     return false;
   5650 
   5651   scalar_dest = gimple_assign_lhs (stmt);
   5652   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
   5653   if (!type_has_mode_precision_p (TREE_TYPE (scalar_dest)))
   5654     {
   5655       if (dump_enabled_p ())
   5656         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5657                          "bit-precision shifts not supported.\n");
   5658       return false;
   5659     }
   5660 
   5661   slp_tree slp_op0;
   5662   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   5663 			   0, &op0, &slp_op0, &dt[0], &vectype))
   5664     {
   5665       if (dump_enabled_p ())
   5666         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5667                          "use not simple.\n");
   5668       return false;
   5669     }
   5670   /* If op0 is an external or constant def, infer the vector type
   5671      from the scalar type.  */
   5672   if (!vectype)
   5673     vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op0), slp_node);
   5674   if (vec_stmt)
   5675     gcc_assert (vectype);
   5676   if (!vectype)
   5677     {
   5678       if (dump_enabled_p ())
   5679         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5680                          "no vectype for scalar type\n");
   5681       return false;
   5682     }
   5683 
   5684   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   5685   nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
   5686   if (maybe_ne (nunits_out, nunits_in))
   5687     return false;
   5688 
   5689   stmt_vec_info op1_def_stmt_info;
   5690   slp_tree slp_op1;
   5691   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1, &op1, &slp_op1,
   5692 			   &dt[1], &op1_vectype, &op1_def_stmt_info))
   5693     {
   5694       if (dump_enabled_p ())
   5695         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5696                          "use not simple.\n");
   5697       return false;
   5698     }
   5699 
   5700   /* Multiple types in SLP are handled by creating the appropriate number of
   5701      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
   5702      case of SLP.  */
   5703   if (slp_node)
   5704     ncopies = 1;
   5705   else
   5706     ncopies = vect_get_num_copies (loop_vinfo, vectype);
   5707 
   5708   gcc_assert (ncopies >= 1);
   5709 
   5710   /* Determine whether the shift amount is a vector, or scalar.  If the
   5711      shift/rotate amount is a vector, use the vector/vector shift optabs.  */
   5712 
   5713   if ((dt[1] == vect_internal_def
   5714        || dt[1] == vect_induction_def
   5715        || dt[1] == vect_nested_cycle)
   5716       && !slp_node)
   5717     scalar_shift_arg = false;
   5718   else if (dt[1] == vect_constant_def
   5719 	   || dt[1] == vect_external_def
   5720 	   || dt[1] == vect_internal_def)
   5721     {
   5722       /* In SLP, need to check whether the shift count is the same,
   5723 	 in loops if it is a constant or invariant, it is always
   5724 	 a scalar shift.  */
   5725       if (slp_node)
   5726 	{
   5727 	  vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
   5728 	  stmt_vec_info slpstmt_info;
   5729 
   5730 	  FOR_EACH_VEC_ELT (stmts, k, slpstmt_info)
   5731 	    {
   5732 	      gassign *slpstmt = as_a <gassign *> (slpstmt_info->stmt);
   5733 	      if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
   5734 		scalar_shift_arg = false;
   5735 	    }
   5736 
   5737 	  /* For internal SLP defs we have to make sure we see scalar stmts
   5738 	     for all vector elements.
   5739 	     ???  For different vectors we could resort to a different
   5740 	     scalar shift operand but code-generation below simply always
   5741 	     takes the first.  */
   5742 	  if (dt[1] == vect_internal_def
   5743 	      && maybe_ne (nunits_out * SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node),
   5744 			   stmts.length ()))
   5745 	    scalar_shift_arg = false;
   5746 	}
   5747 
   5748       /* If the shift amount is computed by a pattern stmt we cannot
   5749          use the scalar amount directly thus give up and use a vector
   5750 	 shift.  */
   5751       if (op1_def_stmt_info && is_pattern_stmt_p (op1_def_stmt_info))
   5752 	scalar_shift_arg = false;
   5753     }
   5754   else
   5755     {
   5756       if (dump_enabled_p ())
   5757         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5758                          "operand mode requires invariant argument.\n");
   5759       return false;
   5760     }
   5761 
   5762   /* Vector shifted by vector.  */
   5763   bool was_scalar_shift_arg = scalar_shift_arg;
   5764   if (!scalar_shift_arg)
   5765     {
   5766       optab = optab_for_tree_code (code, vectype, optab_vector);
   5767       if (dump_enabled_p ())
   5768         dump_printf_loc (MSG_NOTE, vect_location,
   5769                          "vector/vector shift/rotate found.\n");
   5770 
   5771       if (!op1_vectype)
   5772 	op1_vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op1),
   5773 						   slp_op1);
   5774       incompatible_op1_vectype_p
   5775 	= (op1_vectype == NULL_TREE
   5776 	   || maybe_ne (TYPE_VECTOR_SUBPARTS (op1_vectype),
   5777 			TYPE_VECTOR_SUBPARTS (vectype))
   5778 	   || TYPE_MODE (op1_vectype) != TYPE_MODE (vectype));
   5779       if (incompatible_op1_vectype_p
   5780 	  && (!slp_node
   5781 	      || SLP_TREE_DEF_TYPE (slp_op1) != vect_constant_def
   5782 	      || slp_op1->refcnt != 1))
   5783 	{
   5784 	  if (dump_enabled_p ())
   5785 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5786                              "unusable type for last operand in"
   5787                              " vector/vector shift/rotate.\n");
   5788 	  return false;
   5789 	}
   5790     }
   5791   /* See if the machine has a vector shifted by scalar insn and if not
   5792      then see if it has a vector shifted by vector insn.  */
   5793   else
   5794     {
   5795       optab = optab_for_tree_code (code, vectype, optab_scalar);
   5796       if (optab
   5797           && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing)
   5798         {
   5799           if (dump_enabled_p ())
   5800             dump_printf_loc (MSG_NOTE, vect_location,
   5801                              "vector/scalar shift/rotate found.\n");
   5802         }
   5803       else
   5804         {
   5805           optab = optab_for_tree_code (code, vectype, optab_vector);
   5806           if (optab
   5807                && (optab_handler (optab, TYPE_MODE (vectype))
   5808                       != CODE_FOR_nothing))
   5809             {
   5810 	      scalar_shift_arg = false;
   5811 
   5812               if (dump_enabled_p ())
   5813                 dump_printf_loc (MSG_NOTE, vect_location,
   5814                                  "vector/vector shift/rotate found.\n");
   5815 
   5816 	      if (!op1_vectype)
   5817 		op1_vectype = get_vectype_for_scalar_type (vinfo,
   5818 							   TREE_TYPE (op1),
   5819 							   slp_op1);
   5820 
   5821               /* Unlike the other binary operators, shifts/rotates have
   5822                  the rhs being int, instead of the same type as the lhs,
   5823                  so make sure the scalar is the right type if we are
   5824 		 dealing with vectors of long long/long/short/char.  */
   5825 	      incompatible_op1_vectype_p
   5826 		= (!op1_vectype
   5827 		   || !tree_nop_conversion_p (TREE_TYPE (vectype),
   5828 					      TREE_TYPE (op1)));
   5829 	      if (incompatible_op1_vectype_p
   5830 		  && dt[1] == vect_internal_def)
   5831 		{
   5832 		  if (dump_enabled_p ())
   5833 		    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5834 				     "unusable type for last operand in"
   5835 				     " vector/vector shift/rotate.\n");
   5836 		  return false;
   5837 		}
   5838             }
   5839         }
   5840     }
   5841 
   5842   /* Supportable by target?  */
   5843   if (!optab)
   5844     {
   5845       if (dump_enabled_p ())
   5846         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5847                          "no optab.\n");
   5848       return false;
   5849     }
   5850   vec_mode = TYPE_MODE (vectype);
   5851   icode = (int) optab_handler (optab, vec_mode);
   5852   if (icode == CODE_FOR_nothing)
   5853     {
   5854       if (dump_enabled_p ())
   5855         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5856                          "op not supported by target.\n");
   5857       return false;
   5858     }
   5859   /* vector lowering cannot optimize vector shifts using word arithmetic.  */
   5860   if (vect_emulated_vector_p (vectype))
   5861     return false;
   5862 
   5863   if (!vec_stmt) /* transformation not required.  */
   5864     {
   5865       if (slp_node
   5866 	  && (!vect_maybe_update_slp_op_vectype (slp_op0, vectype)
   5867 	      || ((!scalar_shift_arg || dt[1] == vect_internal_def)
   5868 		  && (!incompatible_op1_vectype_p
   5869 		      || dt[1] == vect_constant_def)
   5870 		  && !vect_maybe_update_slp_op_vectype
   5871 			(slp_op1,
   5872 			 incompatible_op1_vectype_p ? vectype : op1_vectype))))
   5873 	{
   5874 	  if (dump_enabled_p ())
   5875 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   5876 			     "incompatible vector types for invariants\n");
   5877 	  return false;
   5878 	}
   5879       /* Now adjust the constant shift amount in place.  */
   5880       if (slp_node
   5881 	  && incompatible_op1_vectype_p
   5882 	  && dt[1] == vect_constant_def)
   5883 	{
   5884 	  for (unsigned i = 0;
   5885 	       i < SLP_TREE_SCALAR_OPS (slp_op1).length (); ++i)
   5886 	    {
   5887 	      SLP_TREE_SCALAR_OPS (slp_op1)[i]
   5888 		= fold_convert (TREE_TYPE (vectype),
   5889 				SLP_TREE_SCALAR_OPS (slp_op1)[i]);
   5890 	      gcc_assert ((TREE_CODE (SLP_TREE_SCALAR_OPS (slp_op1)[i])
   5891 			   == INTEGER_CST));
   5892 	    }
   5893 	}
   5894       STMT_VINFO_TYPE (stmt_info) = shift_vec_info_type;
   5895       DUMP_VECT_SCOPE ("vectorizable_shift");
   5896       vect_model_simple_cost (vinfo, stmt_info, ncopies, dt,
   5897 			      scalar_shift_arg ? 1 : ndts, slp_node, cost_vec);
   5898       return true;
   5899     }
   5900 
   5901   /* Transform.  */
   5902 
   5903   if (dump_enabled_p ())
   5904     dump_printf_loc (MSG_NOTE, vect_location,
   5905                      "transform binary/unary operation.\n");
   5906 
   5907   if (incompatible_op1_vectype_p && !slp_node)
   5908     {
   5909       gcc_assert (!scalar_shift_arg && was_scalar_shift_arg);
   5910       op1 = fold_convert (TREE_TYPE (vectype), op1);
   5911       if (dt[1] != vect_constant_def)
   5912 	op1 = vect_init_vector (vinfo, stmt_info, op1,
   5913 				TREE_TYPE (vectype), NULL);
   5914     }
   5915 
   5916   /* Handle def.  */
   5917   vec_dest = vect_create_destination_var (scalar_dest, vectype);
   5918 
   5919   if (scalar_shift_arg && dt[1] != vect_internal_def)
   5920     {
   5921       /* Vector shl and shr insn patterns can be defined with scalar
   5922 	 operand 2 (shift operand).  In this case, use constant or loop
   5923 	 invariant op1 directly, without extending it to vector mode
   5924 	 first.  */
   5925       optab_op2_mode = insn_data[icode].operand[2].mode;
   5926       if (!VECTOR_MODE_P (optab_op2_mode))
   5927 	{
   5928 	  if (dump_enabled_p ())
   5929 	    dump_printf_loc (MSG_NOTE, vect_location,
   5930 			     "operand 1 using scalar mode.\n");
   5931 	  vec_oprnd1 = op1;
   5932 	  vec_oprnds1.create (slp_node ? slp_node->vec_stmts_size : ncopies);
   5933 	  vec_oprnds1.quick_push (vec_oprnd1);
   5934 	      /* Store vec_oprnd1 for every vector stmt to be created.
   5935 		 We check during the analysis that all the shift arguments
   5936 		 are the same.
   5937 		 TODO: Allow different constants for different vector
   5938 		 stmts generated for an SLP instance.  */
   5939 	  for (k = 0;
   5940 	       k < (slp_node ? slp_node->vec_stmts_size - 1 : ncopies - 1); k++)
   5941 	    vec_oprnds1.quick_push (vec_oprnd1);
   5942 	}
   5943     }
   5944   else if (!scalar_shift_arg && slp_node && incompatible_op1_vectype_p)
   5945     {
   5946       if (was_scalar_shift_arg)
   5947 	{
   5948 	  /* If the argument was the same in all lanes create
   5949 	     the correctly typed vector shift amount directly.  */
   5950 	  op1 = fold_convert (TREE_TYPE (vectype), op1);
   5951 	  op1 = vect_init_vector (vinfo, stmt_info, op1, TREE_TYPE (vectype),
   5952 				  !loop_vinfo ? gsi : NULL);
   5953 	  vec_oprnd1 = vect_init_vector (vinfo, stmt_info, op1, vectype,
   5954 					 !loop_vinfo ? gsi : NULL);
   5955 	  vec_oprnds1.create (slp_node->vec_stmts_size);
   5956 	  for (k = 0; k < slp_node->vec_stmts_size; k++)
   5957 	    vec_oprnds1.quick_push (vec_oprnd1);
   5958 	}
   5959       else if (dt[1] == vect_constant_def)
   5960 	/* The constant shift amount has been adjusted in place.  */
   5961 	;
   5962       else
   5963 	gcc_assert (TYPE_MODE (op1_vectype) == TYPE_MODE (vectype));
   5964     }
   5965 
   5966   /* vec_oprnd1 is available if operand 1 should be of a scalar-type
   5967      (a special case for certain kind of vector shifts); otherwise,
   5968      operand 1 should be of a vector type (the usual case).  */
   5969   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   5970 		     op0, &vec_oprnds0,
   5971 		     vec_oprnd1 ? NULL_TREE : op1, &vec_oprnds1);
   5972 
   5973   /* Arguments are ready.  Create the new vector stmt.  */
   5974   FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
   5975     {
   5976       /* For internal defs where we need to use a scalar shift arg
   5977 	 extract the first lane.  */
   5978       if (scalar_shift_arg && dt[1] == vect_internal_def)
   5979 	{
   5980 	  vop1 = vec_oprnds1[0];
   5981 	  new_temp = make_ssa_name (TREE_TYPE (TREE_TYPE (vop1)));
   5982 	  gassign *new_stmt
   5983 	    = gimple_build_assign (new_temp,
   5984 				   build3 (BIT_FIELD_REF, TREE_TYPE (new_temp),
   5985 					   vop1,
   5986 					   TYPE_SIZE (TREE_TYPE (new_temp)),
   5987 					   bitsize_zero_node));
   5988 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   5989 	  vop1 = new_temp;
   5990 	}
   5991       else
   5992 	vop1 = vec_oprnds1[i];
   5993       gassign *new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1);
   5994       new_temp = make_ssa_name (vec_dest, new_stmt);
   5995       gimple_assign_set_lhs (new_stmt, new_temp);
   5996       vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   5997       if (slp_node)
   5998 	SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   5999       else
   6000 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   6001     }
   6002 
   6003   if (!slp_node)
   6004     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   6005 
   6006   vec_oprnds0.release ();
   6007   vec_oprnds1.release ();
   6008 
   6009   return true;
   6010 }
   6011 
   6012 
   6013 /* Function vectorizable_operation.
   6014 
   6015    Check if STMT_INFO performs a binary, unary or ternary operation that can
   6016    be vectorized.
   6017    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   6018    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   6019    Return true if STMT_INFO is vectorizable in this way.  */
   6020 
   6021 static bool
   6022 vectorizable_operation (vec_info *vinfo,
   6023 			stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   6024 			gimple **vec_stmt, slp_tree slp_node,
   6025 			stmt_vector_for_cost *cost_vec)
   6026 {
   6027   tree vec_dest;
   6028   tree scalar_dest;
   6029   tree op0, op1 = NULL_TREE, op2 = NULL_TREE;
   6030   tree vectype;
   6031   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   6032   enum tree_code code, orig_code;
   6033   machine_mode vec_mode;
   6034   tree new_temp;
   6035   int op_type;
   6036   optab optab;
   6037   bool target_support_p;
   6038   enum vect_def_type dt[3]
   6039     = {vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type};
   6040   int ndts = 3;
   6041   poly_uint64 nunits_in;
   6042   poly_uint64 nunits_out;
   6043   tree vectype_out;
   6044   int ncopies, vec_num;
   6045   int i;
   6046   vec<tree> vec_oprnds0 = vNULL;
   6047   vec<tree> vec_oprnds1 = vNULL;
   6048   vec<tree> vec_oprnds2 = vNULL;
   6049   tree vop0, vop1, vop2;
   6050   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   6051 
   6052   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   6053     return false;
   6054 
   6055   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   6056       && ! vec_stmt)
   6057     return false;
   6058 
   6059   /* Is STMT a vectorizable binary/unary operation?   */
   6060   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
   6061   if (!stmt)
   6062     return false;
   6063 
   6064   /* Loads and stores are handled in vectorizable_{load,store}.  */
   6065   if (STMT_VINFO_DATA_REF (stmt_info))
   6066     return false;
   6067 
   6068   orig_code = code = gimple_assign_rhs_code (stmt);
   6069 
   6070   /* Shifts are handled in vectorizable_shift.  */
   6071   if (code == LSHIFT_EXPR
   6072       || code == RSHIFT_EXPR
   6073       || code == LROTATE_EXPR
   6074       || code == RROTATE_EXPR)
   6075    return false;
   6076 
   6077   /* Comparisons are handled in vectorizable_comparison.  */
   6078   if (TREE_CODE_CLASS (code) == tcc_comparison)
   6079     return false;
   6080 
   6081   /* Conditions are handled in vectorizable_condition.  */
   6082   if (code == COND_EXPR)
   6083     return false;
   6084 
   6085   /* For pointer addition and subtraction, we should use the normal
   6086      plus and minus for the vector operation.  */
   6087   if (code == POINTER_PLUS_EXPR)
   6088     code = PLUS_EXPR;
   6089   if (code == POINTER_DIFF_EXPR)
   6090     code = MINUS_EXPR;
   6091 
   6092   /* Support only unary or binary operations.  */
   6093   op_type = TREE_CODE_LENGTH (code);
   6094   if (op_type != unary_op && op_type != binary_op && op_type != ternary_op)
   6095     {
   6096       if (dump_enabled_p ())
   6097         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6098                          "num. args = %d (not unary/binary/ternary op).\n",
   6099                          op_type);
   6100       return false;
   6101     }
   6102 
   6103   scalar_dest = gimple_assign_lhs (stmt);
   6104   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
   6105 
   6106   /* Most operations cannot handle bit-precision types without extra
   6107      truncations.  */
   6108   bool mask_op_p = VECTOR_BOOLEAN_TYPE_P (vectype_out);
   6109   if (!mask_op_p
   6110       && !type_has_mode_precision_p (TREE_TYPE (scalar_dest))
   6111       /* Exception are bitwise binary operations.  */
   6112       && code != BIT_IOR_EXPR
   6113       && code != BIT_XOR_EXPR
   6114       && code != BIT_AND_EXPR)
   6115     {
   6116       if (dump_enabled_p ())
   6117         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6118                          "bit-precision arithmetic not supported.\n");
   6119       return false;
   6120     }
   6121 
   6122   slp_tree slp_op0;
   6123   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   6124 			   0, &op0, &slp_op0, &dt[0], &vectype))
   6125     {
   6126       if (dump_enabled_p ())
   6127         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6128                          "use not simple.\n");
   6129       return false;
   6130     }
   6131   bool is_invariant = (dt[0] == vect_external_def
   6132 		       || dt[0] == vect_constant_def);
   6133   /* If op0 is an external or constant def, infer the vector type
   6134      from the scalar type.  */
   6135   if (!vectype)
   6136     {
   6137       /* For boolean type we cannot determine vectype by
   6138 	 invariant value (don't know whether it is a vector
   6139 	 of booleans or vector of integers).  We use output
   6140 	 vectype because operations on boolean don't change
   6141 	 type.  */
   6142       if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (op0)))
   6143 	{
   6144 	  if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (scalar_dest)))
   6145 	    {
   6146 	      if (dump_enabled_p ())
   6147 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6148 				 "not supported operation on bool value.\n");
   6149 	      return false;
   6150 	    }
   6151 	  vectype = vectype_out;
   6152 	}
   6153       else
   6154 	vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op0),
   6155 					       slp_node);
   6156     }
   6157   if (vec_stmt)
   6158     gcc_assert (vectype);
   6159   if (!vectype)
   6160     {
   6161       if (dump_enabled_p ())
   6162 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6163 			 "no vectype for scalar type %T\n",
   6164 			 TREE_TYPE (op0));
   6165 
   6166       return false;
   6167     }
   6168 
   6169   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   6170   nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
   6171   if (maybe_ne (nunits_out, nunits_in))
   6172     return false;
   6173 
   6174   tree vectype2 = NULL_TREE, vectype3 = NULL_TREE;
   6175   slp_tree slp_op1 = NULL, slp_op2 = NULL;
   6176   if (op_type == binary_op || op_type == ternary_op)
   6177     {
   6178       if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   6179 			       1, &op1, &slp_op1, &dt[1], &vectype2))
   6180 	{
   6181 	  if (dump_enabled_p ())
   6182 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6183                              "use not simple.\n");
   6184 	  return false;
   6185 	}
   6186       is_invariant &= (dt[1] == vect_external_def
   6187 		       || dt[1] == vect_constant_def);
   6188       if (vectype2
   6189 	  && maybe_ne (nunits_out, TYPE_VECTOR_SUBPARTS (vectype2)))
   6190 	return false;
   6191     }
   6192   if (op_type == ternary_op)
   6193     {
   6194       if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   6195 			       2, &op2, &slp_op2, &dt[2], &vectype3))
   6196 	{
   6197 	  if (dump_enabled_p ())
   6198 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6199                              "use not simple.\n");
   6200 	  return false;
   6201 	}
   6202       is_invariant &= (dt[2] == vect_external_def
   6203 		       || dt[2] == vect_constant_def);
   6204       if (vectype3
   6205 	  && maybe_ne (nunits_out, TYPE_VECTOR_SUBPARTS (vectype3)))
   6206 	return false;
   6207     }
   6208 
   6209   /* Multiple types in SLP are handled by creating the appropriate number of
   6210      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
   6211      case of SLP.  */
   6212   if (slp_node)
   6213     {
   6214       ncopies = 1;
   6215       vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   6216     }
   6217   else
   6218     {
   6219       ncopies = vect_get_num_copies (loop_vinfo, vectype);
   6220       vec_num = 1;
   6221     }
   6222 
   6223   gcc_assert (ncopies >= 1);
   6224 
   6225   /* Reject attempts to combine mask types with nonmask types, e.g. if
   6226      we have an AND between a (nonmask) boolean loaded from memory and
   6227      a (mask) boolean result of a comparison.
   6228 
   6229      TODO: We could easily fix these cases up using pattern statements.  */
   6230   if (VECTOR_BOOLEAN_TYPE_P (vectype) != mask_op_p
   6231       || (vectype2 && VECTOR_BOOLEAN_TYPE_P (vectype2) != mask_op_p)
   6232       || (vectype3 && VECTOR_BOOLEAN_TYPE_P (vectype3) != mask_op_p))
   6233     {
   6234       if (dump_enabled_p ())
   6235 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6236 			 "mixed mask and nonmask vector types\n");
   6237       return false;
   6238     }
   6239 
   6240   /* Supportable by target?  */
   6241 
   6242   vec_mode = TYPE_MODE (vectype);
   6243   if (code == MULT_HIGHPART_EXPR)
   6244     target_support_p = can_mult_highpart_p (vec_mode, TYPE_UNSIGNED (vectype));
   6245   else
   6246     {
   6247       optab = optab_for_tree_code (code, vectype, optab_default);
   6248       if (!optab)
   6249 	{
   6250           if (dump_enabled_p ())
   6251             dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6252                              "no optab.\n");
   6253 	  return false;
   6254 	}
   6255       target_support_p = (optab_handler (optab, vec_mode)
   6256 			  != CODE_FOR_nothing);
   6257     }
   6258 
   6259   bool using_emulated_vectors_p = vect_emulated_vector_p (vectype);
   6260   if (!target_support_p)
   6261     {
   6262       if (dump_enabled_p ())
   6263 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6264                          "op not supported by target.\n");
   6265       /* Check only during analysis.  */
   6266       if (maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD)
   6267 	  || (!vec_stmt && !vect_can_vectorize_without_simd_p (code)))
   6268         return false;
   6269       if (dump_enabled_p ())
   6270 	dump_printf_loc (MSG_NOTE, vect_location,
   6271                          "proceeding using word mode.\n");
   6272       using_emulated_vectors_p = true;
   6273     }
   6274 
   6275   if (using_emulated_vectors_p
   6276       && !vect_can_vectorize_without_simd_p (code))
   6277     {
   6278       if (dump_enabled_p ())
   6279 	dump_printf (MSG_NOTE, "using word mode not possible.\n");
   6280       return false;
   6281     }
   6282 
   6283   /* ???  We should instead expand the operations here, instead of
   6284      relying on vector lowering which has this hard cap on the number
   6285      of vector elements below it performs elementwise operations.  */
   6286   if (using_emulated_vectors_p
   6287       && (code == PLUS_EXPR || code == MINUS_EXPR || code == NEGATE_EXPR)
   6288       && ((BITS_PER_WORD / vector_element_bits (vectype)) < 4
   6289 	  || maybe_lt (nunits_out, 4U)))
   6290     {
   6291       if (dump_enabled_p ())
   6292 	dump_printf (MSG_NOTE, "not using word mode for +- and less than "
   6293 		     "four vector elements\n");
   6294       return false;
   6295     }
   6296 
   6297   int reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info);
   6298   vec_loop_masks *masks = (loop_vinfo ? &LOOP_VINFO_MASKS (loop_vinfo) : NULL);
   6299   internal_fn cond_fn = get_conditional_internal_fn (code);
   6300 
   6301   /* If operating on inactive elements could generate spurious traps,
   6302      we need to restrict the operation to active lanes.  Note that this
   6303      specifically doesn't apply to unhoisted invariants, since they
   6304      operate on the same value for every lane.
   6305 
   6306      Similarly, if this operation is part of a reduction, a fully-masked
   6307      loop should only change the active lanes of the reduction chain,
   6308      keeping the inactive lanes as-is.  */
   6309   bool mask_out_inactive = ((!is_invariant && gimple_could_trap_p (stmt))
   6310 			    || reduc_idx >= 0);
   6311 
   6312   if (!vec_stmt) /* transformation not required.  */
   6313     {
   6314       if (loop_vinfo
   6315 	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
   6316 	  && mask_out_inactive)
   6317 	{
   6318 	  if (cond_fn == IFN_LAST
   6319 	      || !direct_internal_fn_supported_p (cond_fn, vectype,
   6320 						  OPTIMIZE_FOR_SPEED))
   6321 	    {
   6322 	      if (dump_enabled_p ())
   6323 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6324 				 "can't use a fully-masked loop because no"
   6325 				 " conditional operation is available.\n");
   6326 	      LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   6327 	    }
   6328 	  else
   6329 	    vect_record_loop_mask (loop_vinfo, masks, ncopies * vec_num,
   6330 				   vectype, NULL);
   6331 	}
   6332 
   6333       /* Put types on constant and invariant SLP children.  */
   6334       if (slp_node
   6335 	  && (!vect_maybe_update_slp_op_vectype (slp_op0, vectype)
   6336 	      || !vect_maybe_update_slp_op_vectype (slp_op1, vectype)
   6337 	      || !vect_maybe_update_slp_op_vectype (slp_op2, vectype)))
   6338 	{
   6339 	  if (dump_enabled_p ())
   6340 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6341 			     "incompatible vector types for invariants\n");
   6342 	  return false;
   6343 	}
   6344 
   6345       STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
   6346       DUMP_VECT_SCOPE ("vectorizable_operation");
   6347       vect_model_simple_cost (vinfo, stmt_info,
   6348 			      ncopies, dt, ndts, slp_node, cost_vec);
   6349       if (using_emulated_vectors_p)
   6350 	{
   6351 	  /* The above vect_model_simple_cost call handles constants
   6352 	     in the prologue and (mis-)costs one of the stmts as
   6353 	     vector stmt.  See tree-vect-generic.cc:do_plus_minus/do_negate
   6354 	     for the actual lowering that will be applied.  */
   6355 	  unsigned n
   6356 	    = slp_node ? SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) : ncopies;
   6357 	  switch (code)
   6358 	    {
   6359 	    case PLUS_EXPR:
   6360 	      n *= 5;
   6361 	      break;
   6362 	    case MINUS_EXPR:
   6363 	      n *= 6;
   6364 	      break;
   6365 	    case NEGATE_EXPR:
   6366 	      n *= 4;
   6367 	      break;
   6368 	    default:;
   6369 	    }
   6370 	  record_stmt_cost (cost_vec, n, scalar_stmt, stmt_info, 0, vect_body);
   6371 	}
   6372       return true;
   6373     }
   6374 
   6375   /* Transform.  */
   6376 
   6377   if (dump_enabled_p ())
   6378     dump_printf_loc (MSG_NOTE, vect_location,
   6379                      "transform binary/unary operation.\n");
   6380 
   6381   bool masked_loop_p = loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo);
   6382 
   6383   /* POINTER_DIFF_EXPR has pointer arguments which are vectorized as
   6384      vectors with unsigned elements, but the result is signed.  So, we
   6385      need to compute the MINUS_EXPR into vectype temporary and
   6386      VIEW_CONVERT_EXPR it into the final vectype_out result.  */
   6387   tree vec_cvt_dest = NULL_TREE;
   6388   if (orig_code == POINTER_DIFF_EXPR)
   6389     {
   6390       vec_dest = vect_create_destination_var (scalar_dest, vectype);
   6391       vec_cvt_dest = vect_create_destination_var (scalar_dest, vectype_out);
   6392     }
   6393   /* Handle def.  */
   6394   else
   6395     vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
   6396 
   6397   /* In case the vectorization factor (VF) is bigger than the number
   6398      of elements that we can fit in a vectype (nunits), we have to generate
   6399      more than one vector stmt - i.e - we need to "unroll" the
   6400      vector stmt by a factor VF/nunits.  In doing so, we record a pointer
   6401      from one copy of the vector stmt to the next, in the field
   6402      STMT_VINFO_RELATED_STMT.  This is necessary in order to allow following
   6403      stages to find the correct vector defs to be used when vectorizing
   6404      stmts that use the defs of the current stmt.  The example below
   6405      illustrates the vectorization process when VF=16 and nunits=4 (i.e.,
   6406      we need to create 4 vectorized stmts):
   6407 
   6408      before vectorization:
   6409                                 RELATED_STMT    VEC_STMT
   6410         S1:     x = memref      -               -
   6411         S2:     z = x + 1       -               -
   6412 
   6413      step 1: vectorize stmt S1 (done in vectorizable_load. See more details
   6414              there):
   6415                                 RELATED_STMT    VEC_STMT
   6416         VS1_0:  vx0 = memref0   VS1_1           -
   6417         VS1_1:  vx1 = memref1   VS1_2           -
   6418         VS1_2:  vx2 = memref2   VS1_3           -
   6419         VS1_3:  vx3 = memref3   -               -
   6420         S1:     x = load        -               VS1_0
   6421         S2:     z = x + 1       -               -
   6422 
   6423      step2: vectorize stmt S2 (done here):
   6424         To vectorize stmt S2 we first need to find the relevant vector
   6425         def for the first operand 'x'.  This is, as usual, obtained from
   6426         the vector stmt recorded in the STMT_VINFO_VEC_STMT of the stmt
   6427         that defines 'x' (S1).  This way we find the stmt VS1_0, and the
   6428         relevant vector def 'vx0'.  Having found 'vx0' we can generate
   6429         the vector stmt VS2_0, and as usual, record it in the
   6430         STMT_VINFO_VEC_STMT of stmt S2.
   6431         When creating the second copy (VS2_1), we obtain the relevant vector
   6432         def from the vector stmt recorded in the STMT_VINFO_RELATED_STMT of
   6433         stmt VS1_0.  This way we find the stmt VS1_1 and the relevant
   6434         vector def 'vx1'.  Using 'vx1' we create stmt VS2_1 and record a
   6435         pointer to it in the STMT_VINFO_RELATED_STMT of the vector stmt VS2_0.
   6436         Similarly when creating stmts VS2_2 and VS2_3.  This is the resulting
   6437         chain of stmts and pointers:
   6438                                 RELATED_STMT    VEC_STMT
   6439         VS1_0:  vx0 = memref0   VS1_1           -
   6440         VS1_1:  vx1 = memref1   VS1_2           -
   6441         VS1_2:  vx2 = memref2   VS1_3           -
   6442         VS1_3:  vx3 = memref3   -               -
   6443         S1:     x = load        -               VS1_0
   6444         VS2_0:  vz0 = vx0 + v1  VS2_1           -
   6445         VS2_1:  vz1 = vx1 + v1  VS2_2           -
   6446         VS2_2:  vz2 = vx2 + v1  VS2_3           -
   6447         VS2_3:  vz3 = vx3 + v1  -               -
   6448         S2:     z = x + 1       -               VS2_0  */
   6449 
   6450   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   6451 		     op0, &vec_oprnds0, op1, &vec_oprnds1, op2, &vec_oprnds2);
   6452   /* Arguments are ready.  Create the new vector stmt.  */
   6453   FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
   6454     {
   6455       gimple *new_stmt = NULL;
   6456       vop1 = ((op_type == binary_op || op_type == ternary_op)
   6457 	      ? vec_oprnds1[i] : NULL_TREE);
   6458       vop2 = ((op_type == ternary_op) ? vec_oprnds2[i] : NULL_TREE);
   6459       if (masked_loop_p && mask_out_inactive)
   6460 	{
   6461 	  tree mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
   6462 					  vectype, i);
   6463 	  auto_vec<tree> vops (5);
   6464 	  vops.quick_push (mask);
   6465 	  vops.quick_push (vop0);
   6466 	  if (vop1)
   6467 	    vops.quick_push (vop1);
   6468 	  if (vop2)
   6469 	    vops.quick_push (vop2);
   6470 	  if (reduc_idx >= 0)
   6471 	    {
   6472 	      /* Perform the operation on active elements only and take
   6473 		 inactive elements from the reduction chain input.  */
   6474 	      gcc_assert (!vop2);
   6475 	      vops.quick_push (reduc_idx == 1 ? vop1 : vop0);
   6476 	    }
   6477 	  else
   6478 	    {
   6479 	      auto else_value = targetm.preferred_else_value
   6480 		(cond_fn, vectype, vops.length () - 1, &vops[1]);
   6481 	      vops.quick_push (else_value);
   6482 	    }
   6483 	  gcall *call = gimple_build_call_internal_vec (cond_fn, vops);
   6484 	  new_temp = make_ssa_name (vec_dest, call);
   6485 	  gimple_call_set_lhs (call, new_temp);
   6486 	  gimple_call_set_nothrow (call, true);
   6487 	  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   6488 	  new_stmt = call;
   6489 	}
   6490       else
   6491 	{
   6492 	  tree mask = NULL_TREE;
   6493 	  /* When combining two masks check if either of them is elsewhere
   6494 	     combined with a loop mask, if that's the case we can mark that the
   6495 	     new combined mask doesn't need to be combined with a loop mask.  */
   6496 	  if (masked_loop_p
   6497 	      && code == BIT_AND_EXPR
   6498 	      && VECTOR_BOOLEAN_TYPE_P (vectype))
   6499 	    {
   6500 	      if (loop_vinfo->scalar_cond_masked_set.contains ({ op0,
   6501 								 ncopies}))
   6502 		{
   6503 		  mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
   6504 					     vectype, i);
   6505 
   6506 		  vop0 = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
   6507 					   vop0, gsi);
   6508 		}
   6509 
   6510 	      if (loop_vinfo->scalar_cond_masked_set.contains ({ op1,
   6511 								 ncopies }))
   6512 		{
   6513 		  mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
   6514 					     vectype, i);
   6515 
   6516 		  vop1 = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
   6517 					   vop1, gsi);
   6518 		}
   6519 	    }
   6520 
   6521 	  new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1, vop2);
   6522 	  new_temp = make_ssa_name (vec_dest, new_stmt);
   6523 	  gimple_assign_set_lhs (new_stmt, new_temp);
   6524 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   6525 	  if (using_emulated_vectors_p)
   6526 	    suppress_warning (new_stmt, OPT_Wvector_operation_performance);
   6527 
   6528 	  /* Enter the combined value into the vector cond hash so we don't
   6529 	     AND it with a loop mask again.  */
   6530 	  if (mask)
   6531 	    loop_vinfo->vec_cond_masked_set.add ({ new_temp, mask });
   6532 
   6533 	  if (vec_cvt_dest)
   6534 	    {
   6535 	      new_temp = build1 (VIEW_CONVERT_EXPR, vectype_out, new_temp);
   6536 	      new_stmt = gimple_build_assign (vec_cvt_dest, VIEW_CONVERT_EXPR,
   6537 					      new_temp);
   6538 	      new_temp = make_ssa_name (vec_cvt_dest, new_stmt);
   6539 	      gimple_assign_set_lhs (new_stmt, new_temp);
   6540 	      vect_finish_stmt_generation (vinfo, stmt_info,
   6541 					   new_stmt, gsi);
   6542 	    }
   6543 	}
   6544       if (slp_node)
   6545 	SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   6546       else
   6547 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   6548     }
   6549 
   6550   if (!slp_node)
   6551     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   6552 
   6553   vec_oprnds0.release ();
   6554   vec_oprnds1.release ();
   6555   vec_oprnds2.release ();
   6556 
   6557   return true;
   6558 }
   6559 
   6560 /* A helper function to ensure data reference DR_INFO's base alignment.  */
   6561 
   6562 static void
   6563 ensure_base_align (dr_vec_info *dr_info)
   6564 {
   6565   /* Alignment is only analyzed for the first element of a DR group,
   6566      use that to look at base alignment we need to enforce.  */
   6567   if (STMT_VINFO_GROUPED_ACCESS (dr_info->stmt))
   6568     dr_info = STMT_VINFO_DR_INFO (DR_GROUP_FIRST_ELEMENT (dr_info->stmt));
   6569 
   6570   gcc_assert (dr_info->misalignment != DR_MISALIGNMENT_UNINITIALIZED);
   6571 
   6572   if (dr_info->base_misaligned)
   6573     {
   6574       tree base_decl = dr_info->base_decl;
   6575 
   6576       // We should only be able to increase the alignment of a base object if
   6577       // we know what its new alignment should be at compile time.
   6578       unsigned HOST_WIDE_INT align_base_to =
   6579 	DR_TARGET_ALIGNMENT (dr_info).to_constant () * BITS_PER_UNIT;
   6580 
   6581       if (decl_in_symtab_p (base_decl))
   6582 	symtab_node::get (base_decl)->increase_alignment (align_base_to);
   6583       else if (DECL_ALIGN (base_decl) < align_base_to)
   6584 	{
   6585 	  SET_DECL_ALIGN (base_decl, align_base_to);
   6586           DECL_USER_ALIGN (base_decl) = 1;
   6587 	}
   6588       dr_info->base_misaligned = false;
   6589     }
   6590 }
   6591 
   6592 
   6593 /* Function get_group_alias_ptr_type.
   6594 
   6595    Return the alias type for the group starting at FIRST_STMT_INFO.  */
   6596 
   6597 static tree
   6598 get_group_alias_ptr_type (stmt_vec_info first_stmt_info)
   6599 {
   6600   struct data_reference *first_dr, *next_dr;
   6601 
   6602   first_dr = STMT_VINFO_DATA_REF (first_stmt_info);
   6603   stmt_vec_info next_stmt_info = DR_GROUP_NEXT_ELEMENT (first_stmt_info);
   6604   while (next_stmt_info)
   6605     {
   6606       next_dr = STMT_VINFO_DATA_REF (next_stmt_info);
   6607       if (get_alias_set (DR_REF (first_dr))
   6608 	  != get_alias_set (DR_REF (next_dr)))
   6609 	{
   6610 	  if (dump_enabled_p ())
   6611 	    dump_printf_loc (MSG_NOTE, vect_location,
   6612 			     "conflicting alias set types.\n");
   6613 	  return ptr_type_node;
   6614 	}
   6615       next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
   6616     }
   6617   return reference_alias_ptr_type (DR_REF (first_dr));
   6618 }
   6619 
   6620 
   6621 /* Function scan_operand_equal_p.
   6622 
   6623    Helper function for check_scan_store.  Compare two references
   6624    with .GOMP_SIMD_LANE bases.  */
   6625 
   6626 static bool
   6627 scan_operand_equal_p (tree ref1, tree ref2)
   6628 {
   6629   tree ref[2] = { ref1, ref2 };
   6630   poly_int64 bitsize[2], bitpos[2];
   6631   tree offset[2], base[2];
   6632   for (int i = 0; i < 2; ++i)
   6633     {
   6634       machine_mode mode;
   6635       int unsignedp, reversep, volatilep = 0;
   6636       base[i] = get_inner_reference (ref[i], &bitsize[i], &bitpos[i],
   6637       				     &offset[i], &mode, &unsignedp,
   6638       				     &reversep, &volatilep);
   6639       if (reversep || volatilep || maybe_ne (bitpos[i], 0))
   6640 	return false;
   6641       if (TREE_CODE (base[i]) == MEM_REF
   6642 	  && offset[i] == NULL_TREE
   6643 	  && TREE_CODE (TREE_OPERAND (base[i], 0)) == SSA_NAME)
   6644 	{
   6645 	  gimple *def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (base[i], 0));
   6646 	  if (is_gimple_assign (def_stmt)
   6647 	      && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR
   6648 	      && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == ADDR_EXPR
   6649 	      && TREE_CODE (gimple_assign_rhs2 (def_stmt)) == SSA_NAME)
   6650 	    {
   6651 	      if (maybe_ne (mem_ref_offset (base[i]), 0))
   6652 		return false;
   6653 	      base[i] = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0);
   6654 	      offset[i] = gimple_assign_rhs2 (def_stmt);
   6655 	    }
   6656 	}
   6657     }
   6658 
   6659   if (!operand_equal_p (base[0], base[1], 0))
   6660     return false;
   6661   if (maybe_ne (bitsize[0], bitsize[1]))
   6662     return false;
   6663   if (offset[0] != offset[1])
   6664     {
   6665       if (!offset[0] || !offset[1])
   6666 	return false;
   6667       if (!operand_equal_p (offset[0], offset[1], 0))
   6668 	{
   6669 	  tree step[2];
   6670 	  for (int i = 0; i < 2; ++i)
   6671 	    {
   6672 	      step[i] = integer_one_node;
   6673 	      if (TREE_CODE (offset[i]) == SSA_NAME)
   6674 		{
   6675 		  gimple *def_stmt = SSA_NAME_DEF_STMT (offset[i]);
   6676 		  if (is_gimple_assign (def_stmt)
   6677 		      && gimple_assign_rhs_code (def_stmt) == MULT_EXPR
   6678 		      && (TREE_CODE (gimple_assign_rhs2 (def_stmt))
   6679 			  == INTEGER_CST))
   6680 		    {
   6681 		      step[i] = gimple_assign_rhs2 (def_stmt);
   6682 		      offset[i] = gimple_assign_rhs1 (def_stmt);
   6683 		    }
   6684 		}
   6685 	      else if (TREE_CODE (offset[i]) == MULT_EXPR)
   6686 		{
   6687 		  step[i] = TREE_OPERAND (offset[i], 1);
   6688 		  offset[i] = TREE_OPERAND (offset[i], 0);
   6689 		}
   6690 	      tree rhs1 = NULL_TREE;
   6691 	      if (TREE_CODE (offset[i]) == SSA_NAME)
   6692 		{
   6693 		  gimple *def_stmt = SSA_NAME_DEF_STMT (offset[i]);
   6694 		  if (gimple_assign_cast_p (def_stmt))
   6695 		    rhs1 = gimple_assign_rhs1 (def_stmt);
   6696 		}
   6697 	      else if (CONVERT_EXPR_P (offset[i]))
   6698 		rhs1 = TREE_OPERAND (offset[i], 0);
   6699 	      if (rhs1
   6700 		  && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
   6701 		  && INTEGRAL_TYPE_P (TREE_TYPE (offset[i]))
   6702 		  && (TYPE_PRECISION (TREE_TYPE (offset[i]))
   6703 		      >= TYPE_PRECISION (TREE_TYPE (rhs1))))
   6704 		offset[i] = rhs1;
   6705 	    }
   6706 	  if (!operand_equal_p (offset[0], offset[1], 0)
   6707 	      || !operand_equal_p (step[0], step[1], 0))
   6708 	    return false;
   6709 	}
   6710     }
   6711   return true;
   6712 }
   6713 
   6714 
   6715 enum scan_store_kind {
   6716   /* Normal permutation.  */
   6717   scan_store_kind_perm,
   6718 
   6719   /* Whole vector left shift permutation with zero init.  */
   6720   scan_store_kind_lshift_zero,
   6721 
   6722   /* Whole vector left shift permutation and VEC_COND_EXPR.  */
   6723   scan_store_kind_lshift_cond
   6724 };
   6725 
   6726 /* Function check_scan_store.
   6727 
   6728    Verify if we can perform the needed permutations or whole vector shifts.
   6729    Return -1 on failure, otherwise exact log2 of vectype's nunits.
   6730    USE_WHOLE_VECTOR is a vector of enum scan_store_kind which operation
   6731    to do at each step.  */
   6732 
   6733 static int
   6734 scan_store_can_perm_p (tree vectype, tree init,
   6735 		       vec<enum scan_store_kind> *use_whole_vector = NULL)
   6736 {
   6737   enum machine_mode vec_mode = TYPE_MODE (vectype);
   6738   unsigned HOST_WIDE_INT nunits;
   6739   if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits))
   6740     return -1;
   6741   int units_log2 = exact_log2 (nunits);
   6742   if (units_log2 <= 0)
   6743     return -1;
   6744 
   6745   int i;
   6746   enum scan_store_kind whole_vector_shift_kind = scan_store_kind_perm;
   6747   for (i = 0; i <= units_log2; ++i)
   6748     {
   6749       unsigned HOST_WIDE_INT j, k;
   6750       enum scan_store_kind kind = scan_store_kind_perm;
   6751       vec_perm_builder sel (nunits, nunits, 1);
   6752       sel.quick_grow (nunits);
   6753       if (i == units_log2)
   6754 	{
   6755 	  for (j = 0; j < nunits; ++j)
   6756 	    sel[j] = nunits - 1;
   6757 	}
   6758       else
   6759 	{
   6760 	  for (j = 0; j < (HOST_WIDE_INT_1U << i); ++j)
   6761 	    sel[j] = j;
   6762 	  for (k = 0; j < nunits; ++j, ++k)
   6763 	    sel[j] = nunits + k;
   6764 	}
   6765       vec_perm_indices indices (sel, i == units_log2 ? 1 : 2, nunits);
   6766       if (!can_vec_perm_const_p (vec_mode, indices))
   6767 	{
   6768 	  if (i == units_log2)
   6769 	    return -1;
   6770 
   6771 	  if (whole_vector_shift_kind == scan_store_kind_perm)
   6772 	    {
   6773 	      if (optab_handler (vec_shl_optab, vec_mode) == CODE_FOR_nothing)
   6774 		return -1;
   6775 	      whole_vector_shift_kind = scan_store_kind_lshift_zero;
   6776 	      /* Whole vector shifts shift in zeros, so if init is all zero
   6777 		 constant, there is no need to do anything further.  */
   6778 	      if ((TREE_CODE (init) != INTEGER_CST
   6779 		   && TREE_CODE (init) != REAL_CST)
   6780 		  || !initializer_zerop (init))
   6781 		{
   6782 		  tree masktype = truth_type_for (vectype);
   6783 		  if (!expand_vec_cond_expr_p (vectype, masktype, VECTOR_CST))
   6784 		    return -1;
   6785 		  whole_vector_shift_kind = scan_store_kind_lshift_cond;
   6786 		}
   6787 	    }
   6788 	  kind = whole_vector_shift_kind;
   6789 	}
   6790       if (use_whole_vector)
   6791 	{
   6792 	  if (kind != scan_store_kind_perm && use_whole_vector->is_empty ())
   6793 	    use_whole_vector->safe_grow_cleared (i, true);
   6794 	  if (kind != scan_store_kind_perm || !use_whole_vector->is_empty ())
   6795 	    use_whole_vector->safe_push (kind);
   6796 	}
   6797     }
   6798 
   6799   return units_log2;
   6800 }
   6801 
   6802 
   6803 /* Function check_scan_store.
   6804 
   6805    Check magic stores for #pragma omp scan {in,ex}clusive reductions.  */
   6806 
   6807 static bool
   6808 check_scan_store (vec_info *vinfo, stmt_vec_info stmt_info, tree vectype,
   6809 		  enum vect_def_type rhs_dt, bool slp, tree mask,
   6810 		  vect_memory_access_type memory_access_type)
   6811 {
   6812   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   6813   dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
   6814   tree ref_type;
   6815 
   6816   gcc_assert (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) > 1);
   6817   if (slp
   6818       || mask
   6819       || memory_access_type != VMAT_CONTIGUOUS
   6820       || TREE_CODE (DR_BASE_ADDRESS (dr_info->dr)) != ADDR_EXPR
   6821       || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0))
   6822       || loop_vinfo == NULL
   6823       || LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
   6824       || STMT_VINFO_GROUPED_ACCESS (stmt_info)
   6825       || !integer_zerop (get_dr_vinfo_offset (vinfo, dr_info))
   6826       || !integer_zerop (DR_INIT (dr_info->dr))
   6827       || !(ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr)))
   6828       || !alias_sets_conflict_p (get_alias_set (vectype),
   6829 				 get_alias_set (TREE_TYPE (ref_type))))
   6830     {
   6831       if (dump_enabled_p ())
   6832 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6833 			 "unsupported OpenMP scan store.\n");
   6834       return false;
   6835     }
   6836 
   6837   /* We need to pattern match code built by OpenMP lowering and simplified
   6838      by following optimizations into something we can handle.
   6839      #pragma omp simd reduction(inscan,+:r)
   6840      for (...)
   6841        {
   6842 	 r += something ();
   6843 	 #pragma omp scan inclusive (r)
   6844 	 use (r);
   6845        }
   6846      shall have body with:
   6847        // Initialization for input phase, store the reduction initializer:
   6848        _20 = .GOMP_SIMD_LANE (simduid.3_14(D), 0);
   6849        _21 = .GOMP_SIMD_LANE (simduid.3_14(D), 1);
   6850        D.2042[_21] = 0;
   6851        // Actual input phase:
   6852        ...
   6853        r.0_5 = D.2042[_20];
   6854        _6 = _4 + r.0_5;
   6855        D.2042[_20] = _6;
   6856        // Initialization for scan phase:
   6857        _25 = .GOMP_SIMD_LANE (simduid.3_14(D), 2);
   6858        _26 = D.2043[_25];
   6859        _27 = D.2042[_25];
   6860        _28 = _26 + _27;
   6861        D.2043[_25] = _28;
   6862        D.2042[_25] = _28;
   6863        // Actual scan phase:
   6864        ...
   6865        r.1_8 = D.2042[_20];
   6866        ...
   6867      The "omp simd array" variable D.2042 holds the privatized copy used
   6868      inside of the loop and D.2043 is another one that holds copies of
   6869      the current original list item.  The separate GOMP_SIMD_LANE ifn
   6870      kinds are there in order to allow optimizing the initializer store
   6871      and combiner sequence, e.g. if it is originally some C++ish user
   6872      defined reduction, but allow the vectorizer to pattern recognize it
   6873      and turn into the appropriate vectorized scan.
   6874 
   6875      For exclusive scan, this is slightly different:
   6876      #pragma omp simd reduction(inscan,+:r)
   6877      for (...)
   6878        {
   6879 	 use (r);
   6880 	 #pragma omp scan exclusive (r)
   6881 	 r += something ();
   6882        }
   6883      shall have body with:
   6884        // Initialization for input phase, store the reduction initializer:
   6885        _20 = .GOMP_SIMD_LANE (simduid.3_14(D), 0);
   6886        _21 = .GOMP_SIMD_LANE (simduid.3_14(D), 1);
   6887        D.2042[_21] = 0;
   6888        // Actual input phase:
   6889        ...
   6890        r.0_5 = D.2042[_20];
   6891        _6 = _4 + r.0_5;
   6892        D.2042[_20] = _6;
   6893        // Initialization for scan phase:
   6894        _25 = .GOMP_SIMD_LANE (simduid.3_14(D), 3);
   6895        _26 = D.2043[_25];
   6896        D.2044[_25] = _26;
   6897        _27 = D.2042[_25];
   6898        _28 = _26 + _27;
   6899        D.2043[_25] = _28;
   6900        // Actual scan phase:
   6901        ...
   6902        r.1_8 = D.2044[_20];
   6903        ...  */
   6904 
   6905   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 2)
   6906     {
   6907       /* Match the D.2042[_21] = 0; store above.  Just require that
   6908 	 it is a constant or external definition store.  */
   6909       if (rhs_dt != vect_constant_def && rhs_dt != vect_external_def)
   6910 	{
   6911 	 fail_init:
   6912 	  if (dump_enabled_p ())
   6913 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6914 			     "unsupported OpenMP scan initializer store.\n");
   6915 	  return false;
   6916 	}
   6917 
   6918       if (! loop_vinfo->scan_map)
   6919 	loop_vinfo->scan_map = new hash_map<tree, tree>;
   6920       tree var = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
   6921       tree &cached = loop_vinfo->scan_map->get_or_insert (var);
   6922       if (cached)
   6923 	goto fail_init;
   6924       cached = gimple_assign_rhs1 (STMT_VINFO_STMT (stmt_info));
   6925 
   6926       /* These stores can be vectorized normally.  */
   6927       return true;
   6928     }
   6929 
   6930   if (rhs_dt != vect_internal_def)
   6931     {
   6932      fail:
   6933       if (dump_enabled_p ())
   6934 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   6935 			 "unsupported OpenMP scan combiner pattern.\n");
   6936       return false;
   6937     }
   6938 
   6939   gimple *stmt = STMT_VINFO_STMT (stmt_info);
   6940   tree rhs = gimple_assign_rhs1 (stmt);
   6941   if (TREE_CODE (rhs) != SSA_NAME)
   6942     goto fail;
   6943 
   6944   gimple *other_store_stmt = NULL;
   6945   tree var = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
   6946   bool inscan_var_store
   6947     = lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var)) != NULL;
   6948 
   6949   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
   6950     {
   6951       if (!inscan_var_store)
   6952 	{
   6953 	  use_operand_p use_p;
   6954 	  imm_use_iterator iter;
   6955 	  FOR_EACH_IMM_USE_FAST (use_p, iter, rhs)
   6956 	    {
   6957 	      gimple *use_stmt = USE_STMT (use_p);
   6958 	      if (use_stmt == stmt || is_gimple_debug (use_stmt))
   6959 		continue;
   6960 	      if (gimple_bb (use_stmt) != gimple_bb (stmt)
   6961 		  || !is_gimple_assign (use_stmt)
   6962 		  || gimple_assign_rhs_class (use_stmt) != GIMPLE_BINARY_RHS
   6963 		  || other_store_stmt
   6964 		  || TREE_CODE (gimple_assign_lhs (use_stmt)) != SSA_NAME)
   6965 		goto fail;
   6966 	      other_store_stmt = use_stmt;
   6967 	    }
   6968 	  if (other_store_stmt == NULL)
   6969 	    goto fail;
   6970 	  rhs = gimple_assign_lhs (other_store_stmt);
   6971 	  if (!single_imm_use (rhs, &use_p, &other_store_stmt))
   6972 	    goto fail;
   6973 	}
   6974     }
   6975   else if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 3)
   6976     {
   6977       use_operand_p use_p;
   6978       imm_use_iterator iter;
   6979       FOR_EACH_IMM_USE_FAST (use_p, iter, rhs)
   6980 	{
   6981 	  gimple *use_stmt = USE_STMT (use_p);
   6982 	  if (use_stmt == stmt || is_gimple_debug (use_stmt))
   6983 	    continue;
   6984 	  if (other_store_stmt)
   6985 	    goto fail;
   6986 	  other_store_stmt = use_stmt;
   6987 	}
   6988     }
   6989   else
   6990     goto fail;
   6991 
   6992   gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
   6993   if (gimple_bb (def_stmt) != gimple_bb (stmt)
   6994       || !is_gimple_assign (def_stmt)
   6995       || gimple_assign_rhs_class (def_stmt) != GIMPLE_BINARY_RHS)
   6996     goto fail;
   6997 
   6998   enum tree_code code = gimple_assign_rhs_code (def_stmt);
   6999   /* For pointer addition, we should use the normal plus for the vector
   7000      operation.  */
   7001   switch (code)
   7002     {
   7003     case POINTER_PLUS_EXPR:
   7004       code = PLUS_EXPR;
   7005       break;
   7006     case MULT_HIGHPART_EXPR:
   7007       goto fail;
   7008     default:
   7009       break;
   7010     }
   7011   if (TREE_CODE_LENGTH (code) != binary_op || !commutative_tree_code (code))
   7012     goto fail;
   7013 
   7014   tree rhs1 = gimple_assign_rhs1 (def_stmt);
   7015   tree rhs2 = gimple_assign_rhs2 (def_stmt);
   7016   if (TREE_CODE (rhs1) != SSA_NAME || TREE_CODE (rhs2) != SSA_NAME)
   7017     goto fail;
   7018 
   7019   gimple *load1_stmt = SSA_NAME_DEF_STMT (rhs1);
   7020   gimple *load2_stmt = SSA_NAME_DEF_STMT (rhs2);
   7021   if (gimple_bb (load1_stmt) != gimple_bb (stmt)
   7022       || !gimple_assign_load_p (load1_stmt)
   7023       || gimple_bb (load2_stmt) != gimple_bb (stmt)
   7024       || !gimple_assign_load_p (load2_stmt))
   7025     goto fail;
   7026 
   7027   stmt_vec_info load1_stmt_info = loop_vinfo->lookup_stmt (load1_stmt);
   7028   stmt_vec_info load2_stmt_info = loop_vinfo->lookup_stmt (load2_stmt);
   7029   if (load1_stmt_info == NULL
   7030       || load2_stmt_info == NULL
   7031       || (STMT_VINFO_SIMD_LANE_ACCESS_P (load1_stmt_info)
   7032 	  != STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info))
   7033       || (STMT_VINFO_SIMD_LANE_ACCESS_P (load2_stmt_info)
   7034 	  != STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info)))
   7035     goto fail;
   7036 
   7037   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && inscan_var_store)
   7038     {
   7039       dr_vec_info *load1_dr_info = STMT_VINFO_DR_INFO (load1_stmt_info);
   7040       if (TREE_CODE (DR_BASE_ADDRESS (load1_dr_info->dr)) != ADDR_EXPR
   7041 	  || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (load1_dr_info->dr), 0)))
   7042 	goto fail;
   7043       tree var1 = TREE_OPERAND (DR_BASE_ADDRESS (load1_dr_info->dr), 0);
   7044       tree lrhs;
   7045       if (lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
   7046 	lrhs = rhs1;
   7047       else
   7048 	lrhs = rhs2;
   7049       use_operand_p use_p;
   7050       imm_use_iterator iter;
   7051       FOR_EACH_IMM_USE_FAST (use_p, iter, lrhs)
   7052 	{
   7053 	  gimple *use_stmt = USE_STMT (use_p);
   7054 	  if (use_stmt == def_stmt || is_gimple_debug (use_stmt))
   7055 	    continue;
   7056 	  if (other_store_stmt)
   7057 	    goto fail;
   7058 	  other_store_stmt = use_stmt;
   7059 	}
   7060     }
   7061 
   7062   if (other_store_stmt == NULL)
   7063     goto fail;
   7064   if (gimple_bb (other_store_stmt) != gimple_bb (stmt)
   7065       || !gimple_store_p (other_store_stmt))
   7066     goto fail;
   7067 
   7068   stmt_vec_info other_store_stmt_info
   7069     = loop_vinfo->lookup_stmt (other_store_stmt);
   7070   if (other_store_stmt_info == NULL
   7071       || (STMT_VINFO_SIMD_LANE_ACCESS_P (other_store_stmt_info)
   7072 	  != STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info)))
   7073     goto fail;
   7074 
   7075   gimple *stmt1 = stmt;
   7076   gimple *stmt2 = other_store_stmt;
   7077   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && !inscan_var_store)
   7078     std::swap (stmt1, stmt2);
   7079   if (scan_operand_equal_p (gimple_assign_lhs (stmt1),
   7080 			    gimple_assign_rhs1 (load2_stmt)))
   7081     {
   7082       std::swap (rhs1, rhs2);
   7083       std::swap (load1_stmt, load2_stmt);
   7084       std::swap (load1_stmt_info, load2_stmt_info);
   7085     }
   7086   if (!scan_operand_equal_p (gimple_assign_lhs (stmt1),
   7087 			     gimple_assign_rhs1 (load1_stmt)))
   7088     goto fail;
   7089 
   7090   tree var3 = NULL_TREE;
   7091   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 3
   7092       && !scan_operand_equal_p (gimple_assign_lhs (stmt2),
   7093 				gimple_assign_rhs1 (load2_stmt)))
   7094     goto fail;
   7095   else if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
   7096     {
   7097       dr_vec_info *load2_dr_info = STMT_VINFO_DR_INFO (load2_stmt_info);
   7098       if (TREE_CODE (DR_BASE_ADDRESS (load2_dr_info->dr)) != ADDR_EXPR
   7099 	  || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (load2_dr_info->dr), 0)))
   7100 	goto fail;
   7101       var3 = TREE_OPERAND (DR_BASE_ADDRESS (load2_dr_info->dr), 0);
   7102       if (!lookup_attribute ("omp simd array", DECL_ATTRIBUTES (var3))
   7103 	  || lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var3))
   7104 	  || lookup_attribute ("omp simd inscan exclusive",
   7105 			       DECL_ATTRIBUTES (var3)))
   7106 	goto fail;
   7107     }
   7108 
   7109   dr_vec_info *other_dr_info = STMT_VINFO_DR_INFO (other_store_stmt_info);
   7110   if (TREE_CODE (DR_BASE_ADDRESS (other_dr_info->dr)) != ADDR_EXPR
   7111       || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (other_dr_info->dr), 0)))
   7112     goto fail;
   7113 
   7114   tree var1 = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
   7115   tree var2 = TREE_OPERAND (DR_BASE_ADDRESS (other_dr_info->dr), 0);
   7116   if (!lookup_attribute ("omp simd array", DECL_ATTRIBUTES (var1))
   7117       || !lookup_attribute ("omp simd array", DECL_ATTRIBUTES (var2))
   7118       || (!lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
   7119 	 == (!lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var2))))
   7120     goto fail;
   7121 
   7122   if (lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
   7123     std::swap (var1, var2);
   7124 
   7125   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
   7126     {
   7127       if (!lookup_attribute ("omp simd inscan exclusive",
   7128 			     DECL_ATTRIBUTES (var1)))
   7129 	goto fail;
   7130       var1 = var3;
   7131     }
   7132 
   7133   if (loop_vinfo->scan_map == NULL)
   7134     goto fail;
   7135   tree *init = loop_vinfo->scan_map->get (var1);
   7136   if (init == NULL)
   7137     goto fail;
   7138 
   7139   /* The IL is as expected, now check if we can actually vectorize it.
   7140      Inclusive scan:
   7141        _26 = D.2043[_25];
   7142        _27 = D.2042[_25];
   7143        _28 = _26 + _27;
   7144        D.2043[_25] = _28;
   7145        D.2042[_25] = _28;
   7146      should be vectorized as (where _40 is the vectorized rhs
   7147      from the D.2042[_21] = 0; store):
   7148        _30 = MEM <vector(8) int> [(int *)&D.2043];
   7149        _31 = MEM <vector(8) int> [(int *)&D.2042];
   7150        _32 = VEC_PERM_EXPR <_40, _31, { 0, 8, 9, 10, 11, 12, 13, 14 }>;
   7151        _33 = _31 + _32;
   7152        // _33 = { _31[0], _31[0]+_31[1], _31[1]+_31[2], ..., _31[6]+_31[7] };
   7153        _34 = VEC_PERM_EXPR <_40, _33, { 0, 1, 8, 9, 10, 11, 12, 13 }>;
   7154        _35 = _33 + _34;
   7155        // _35 = { _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
   7156        //         _31[1]+.._31[4], ... _31[4]+.._31[7] };
   7157        _36 = VEC_PERM_EXPR <_40, _35, { 0, 1, 2, 3, 8, 9, 10, 11 }>;
   7158        _37 = _35 + _36;
   7159        // _37 = { _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
   7160        //         _31[0]+.._31[4], ... _31[0]+.._31[7] };
   7161        _38 = _30 + _37;
   7162        _39 = VEC_PERM_EXPR <_38, _38, { 7, 7, 7, 7, 7, 7, 7, 7 }>;
   7163        MEM <vector(8) int> [(int *)&D.2043] = _39;
   7164        MEM <vector(8) int> [(int *)&D.2042] = _38;
   7165      Exclusive scan:
   7166        _26 = D.2043[_25];
   7167        D.2044[_25] = _26;
   7168        _27 = D.2042[_25];
   7169        _28 = _26 + _27;
   7170        D.2043[_25] = _28;
   7171      should be vectorized as (where _40 is the vectorized rhs
   7172      from the D.2042[_21] = 0; store):
   7173        _30 = MEM <vector(8) int> [(int *)&D.2043];
   7174        _31 = MEM <vector(8) int> [(int *)&D.2042];
   7175        _32 = VEC_PERM_EXPR <_40, _31, { 0, 8, 9, 10, 11, 12, 13, 14 }>;
   7176        _33 = VEC_PERM_EXPR <_40, _32, { 0, 8, 9, 10, 11, 12, 13, 14 }>;
   7177        _34 = _32 + _33;
   7178        // _34 = { 0, _31[0], _31[0]+_31[1], _31[1]+_31[2], _31[2]+_31[3],
   7179        //         _31[3]+_31[4], ... _31[5]+.._31[6] };
   7180        _35 = VEC_PERM_EXPR <_40, _34, { 0, 1, 8, 9, 10, 11, 12, 13 }>;
   7181        _36 = _34 + _35;
   7182        // _36 = { 0, _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
   7183        //         _31[1]+.._31[4], ... _31[3]+.._31[6] };
   7184        _37 = VEC_PERM_EXPR <_40, _36, { 0, 1, 2, 3, 8, 9, 10, 11 }>;
   7185        _38 = _36 + _37;
   7186        // _38 = { 0, _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
   7187        //         _31[0]+.._31[4], ... _31[0]+.._31[6] };
   7188        _39 = _30 + _38;
   7189        _50 = _31 + _39;
   7190        _51 = VEC_PERM_EXPR <_50, _50, { 7, 7, 7, 7, 7, 7, 7, 7 }>;
   7191        MEM <vector(8) int> [(int *)&D.2044] = _39;
   7192        MEM <vector(8) int> [(int *)&D.2042] = _51;  */
   7193   enum machine_mode vec_mode = TYPE_MODE (vectype);
   7194   optab optab = optab_for_tree_code (code, vectype, optab_default);
   7195   if (!optab || optab_handler (optab, vec_mode) == CODE_FOR_nothing)
   7196     goto fail;
   7197 
   7198   int units_log2 = scan_store_can_perm_p (vectype, *init);
   7199   if (units_log2 == -1)
   7200     goto fail;
   7201 
   7202   return true;
   7203 }
   7204 
   7205 
   7206 /* Function vectorizable_scan_store.
   7207 
   7208    Helper of vectorizable_score, arguments like on vectorizable_store.
   7209    Handle only the transformation, checking is done in check_scan_store.  */
   7210 
   7211 static bool
   7212 vectorizable_scan_store (vec_info *vinfo,
   7213 			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   7214 			 gimple **vec_stmt, int ncopies)
   7215 {
   7216   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   7217   dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
   7218   tree ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr));
   7219   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   7220 
   7221   if (dump_enabled_p ())
   7222     dump_printf_loc (MSG_NOTE, vect_location,
   7223 		     "transform scan store. ncopies = %d\n", ncopies);
   7224 
   7225   gimple *stmt = STMT_VINFO_STMT (stmt_info);
   7226   tree rhs = gimple_assign_rhs1 (stmt);
   7227   gcc_assert (TREE_CODE (rhs) == SSA_NAME);
   7228 
   7229   tree var = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
   7230   bool inscan_var_store
   7231     = lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var)) != NULL;
   7232 
   7233   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && !inscan_var_store)
   7234     {
   7235       use_operand_p use_p;
   7236       imm_use_iterator iter;
   7237       FOR_EACH_IMM_USE_FAST (use_p, iter, rhs)
   7238 	{
   7239 	  gimple *use_stmt = USE_STMT (use_p);
   7240 	  if (use_stmt == stmt || is_gimple_debug (use_stmt))
   7241 	    continue;
   7242 	  rhs = gimple_assign_lhs (use_stmt);
   7243 	  break;
   7244 	}
   7245     }
   7246 
   7247   gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
   7248   enum tree_code code = gimple_assign_rhs_code (def_stmt);
   7249   if (code == POINTER_PLUS_EXPR)
   7250     code = PLUS_EXPR;
   7251   gcc_assert (TREE_CODE_LENGTH (code) == binary_op
   7252 	      && commutative_tree_code (code));
   7253   tree rhs1 = gimple_assign_rhs1 (def_stmt);
   7254   tree rhs2 = gimple_assign_rhs2 (def_stmt);
   7255   gcc_assert (TREE_CODE (rhs1) == SSA_NAME && TREE_CODE (rhs2) == SSA_NAME);
   7256   gimple *load1_stmt = SSA_NAME_DEF_STMT (rhs1);
   7257   gimple *load2_stmt = SSA_NAME_DEF_STMT (rhs2);
   7258   stmt_vec_info load1_stmt_info = loop_vinfo->lookup_stmt (load1_stmt);
   7259   stmt_vec_info load2_stmt_info = loop_vinfo->lookup_stmt (load2_stmt);
   7260   dr_vec_info *load1_dr_info = STMT_VINFO_DR_INFO (load1_stmt_info);
   7261   dr_vec_info *load2_dr_info = STMT_VINFO_DR_INFO (load2_stmt_info);
   7262   tree var1 = TREE_OPERAND (DR_BASE_ADDRESS (load1_dr_info->dr), 0);
   7263   tree var2 = TREE_OPERAND (DR_BASE_ADDRESS (load2_dr_info->dr), 0);
   7264 
   7265   if (lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
   7266     {
   7267       std::swap (rhs1, rhs2);
   7268       std::swap (var1, var2);
   7269       std::swap (load1_dr_info, load2_dr_info);
   7270     }
   7271 
   7272   tree *init = loop_vinfo->scan_map->get (var1);
   7273   gcc_assert (init);
   7274 
   7275   unsigned HOST_WIDE_INT nunits;
   7276   if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits))
   7277     gcc_unreachable ();
   7278   auto_vec<enum scan_store_kind, 16> use_whole_vector;
   7279   int units_log2 = scan_store_can_perm_p (vectype, *init, &use_whole_vector);
   7280   gcc_assert (units_log2 > 0);
   7281   auto_vec<tree, 16> perms;
   7282   perms.quick_grow (units_log2 + 1);
   7283   tree zero_vec = NULL_TREE, masktype = NULL_TREE;
   7284   for (int i = 0; i <= units_log2; ++i)
   7285     {
   7286       unsigned HOST_WIDE_INT j, k;
   7287       vec_perm_builder sel (nunits, nunits, 1);
   7288       sel.quick_grow (nunits);
   7289       if (i == units_log2)
   7290 	for (j = 0; j < nunits; ++j)
   7291 	  sel[j] = nunits - 1;
   7292       else
   7293 	{
   7294 	  for (j = 0; j < (HOST_WIDE_INT_1U << i); ++j)
   7295 	    sel[j] = j;
   7296 	  for (k = 0; j < nunits; ++j, ++k)
   7297 	    sel[j] = nunits + k;
   7298 	}
   7299       vec_perm_indices indices (sel, i == units_log2 ? 1 : 2, nunits);
   7300       if (!use_whole_vector.is_empty ()
   7301 	  && use_whole_vector[i] != scan_store_kind_perm)
   7302 	{
   7303 	  if (zero_vec == NULL_TREE)
   7304 	    zero_vec = build_zero_cst (vectype);
   7305 	  if (masktype == NULL_TREE
   7306 	      && use_whole_vector[i] == scan_store_kind_lshift_cond)
   7307 	    masktype = truth_type_for (vectype);
   7308 	  perms[i] = vect_gen_perm_mask_any (vectype, indices);
   7309 	}
   7310       else
   7311 	perms[i] = vect_gen_perm_mask_checked (vectype, indices);
   7312     }
   7313 
   7314   tree vec_oprnd1 = NULL_TREE;
   7315   tree vec_oprnd2 = NULL_TREE;
   7316   tree vec_oprnd3 = NULL_TREE;
   7317   tree dataref_ptr = DR_BASE_ADDRESS (dr_info->dr);
   7318   tree dataref_offset = build_int_cst (ref_type, 0);
   7319   tree bump = vect_get_data_ptr_increment (vinfo, dr_info,
   7320 					   vectype, VMAT_CONTIGUOUS);
   7321   tree ldataref_ptr = NULL_TREE;
   7322   tree orig = NULL_TREE;
   7323   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && !inscan_var_store)
   7324     ldataref_ptr = DR_BASE_ADDRESS (load1_dr_info->dr);
   7325   auto_vec<tree> vec_oprnds1;
   7326   auto_vec<tree> vec_oprnds2;
   7327   auto_vec<tree> vec_oprnds3;
   7328   vect_get_vec_defs (vinfo, stmt_info, NULL, ncopies,
   7329 		     *init, &vec_oprnds1,
   7330 		     ldataref_ptr == NULL ? rhs1 : NULL, &vec_oprnds2,
   7331 		     rhs2, &vec_oprnds3);
   7332   for (int j = 0; j < ncopies; j++)
   7333     {
   7334       vec_oprnd1 = vec_oprnds1[j];
   7335       if (ldataref_ptr == NULL)
   7336 	vec_oprnd2 = vec_oprnds2[j];
   7337       vec_oprnd3 = vec_oprnds3[j];
   7338       if (j == 0)
   7339 	orig = vec_oprnd3;
   7340       else if (!inscan_var_store)
   7341 	dataref_offset = int_const_binop (PLUS_EXPR, dataref_offset, bump);
   7342 
   7343       if (ldataref_ptr)
   7344 	{
   7345 	  vec_oprnd2 = make_ssa_name (vectype);
   7346 	  tree data_ref = fold_build2 (MEM_REF, vectype,
   7347 				       unshare_expr (ldataref_ptr),
   7348 				       dataref_offset);
   7349 	  vect_copy_ref_info (data_ref, DR_REF (load1_dr_info->dr));
   7350 	  gimple *g = gimple_build_assign (vec_oprnd2, data_ref);
   7351 	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7352 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7353 	  *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   7354 	}
   7355 
   7356       tree v = vec_oprnd2;
   7357       for (int i = 0; i < units_log2; ++i)
   7358 	{
   7359 	  tree new_temp = make_ssa_name (vectype);
   7360 	  gimple *g = gimple_build_assign (new_temp, VEC_PERM_EXPR,
   7361 					   (zero_vec
   7362 					    && (use_whole_vector[i]
   7363 						!= scan_store_kind_perm))
   7364 					   ? zero_vec : vec_oprnd1, v,
   7365 					   perms[i]);
   7366 	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7367 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7368 	  *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   7369 
   7370 	  if (zero_vec && use_whole_vector[i] == scan_store_kind_lshift_cond)
   7371 	    {
   7372 	      /* Whole vector shift shifted in zero bits, but if *init
   7373 		 is not initializer_zerop, we need to replace those elements
   7374 		 with elements from vec_oprnd1.  */
   7375 	      tree_vector_builder vb (masktype, nunits, 1);
   7376 	      for (unsigned HOST_WIDE_INT k = 0; k < nunits; ++k)
   7377 		vb.quick_push (k < (HOST_WIDE_INT_1U << i)
   7378 			       ? boolean_false_node : boolean_true_node);
   7379 
   7380 	      tree new_temp2 = make_ssa_name (vectype);
   7381 	      g = gimple_build_assign (new_temp2, VEC_COND_EXPR, vb.build (),
   7382 				       new_temp, vec_oprnd1);
   7383 	      vect_finish_stmt_generation (vinfo, stmt_info,
   7384 							   g, gsi);
   7385 	      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7386 	      new_temp = new_temp2;
   7387 	    }
   7388 
   7389 	  /* For exclusive scan, perform the perms[i] permutation once
   7390 	     more.  */
   7391 	  if (i == 0
   7392 	      && STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4
   7393 	      && v == vec_oprnd2)
   7394 	    {
   7395 	      v = new_temp;
   7396 	      --i;
   7397 	      continue;
   7398 	    }
   7399 
   7400 	  tree new_temp2 = make_ssa_name (vectype);
   7401 	  g = gimple_build_assign (new_temp2, code, v, new_temp);
   7402 	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7403 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7404 
   7405 	  v = new_temp2;
   7406 	}
   7407 
   7408       tree new_temp = make_ssa_name (vectype);
   7409       gimple *g = gimple_build_assign (new_temp, code, orig, v);
   7410       vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7411       STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7412 
   7413       tree last_perm_arg = new_temp;
   7414       /* For exclusive scan, new_temp computed above is the exclusive scan
   7415 	 prefix sum.  Turn it into inclusive prefix sum for the broadcast
   7416 	 of the last element into orig.  */
   7417       if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
   7418 	{
   7419 	  last_perm_arg = make_ssa_name (vectype);
   7420 	  g = gimple_build_assign (last_perm_arg, code, new_temp, vec_oprnd2);
   7421 	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7422 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7423 	}
   7424 
   7425       orig = make_ssa_name (vectype);
   7426       g = gimple_build_assign (orig, VEC_PERM_EXPR, last_perm_arg,
   7427 			       last_perm_arg, perms[units_log2]);
   7428       vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7429       STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7430 
   7431       if (!inscan_var_store)
   7432 	{
   7433 	  tree data_ref = fold_build2 (MEM_REF, vectype,
   7434 				       unshare_expr (dataref_ptr),
   7435 				       dataref_offset);
   7436 	  vect_copy_ref_info (data_ref, DR_REF (dr_info->dr));
   7437 	  g = gimple_build_assign (data_ref, new_temp);
   7438 	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7439 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7440 	}
   7441     }
   7442 
   7443   if (inscan_var_store)
   7444     for (int j = 0; j < ncopies; j++)
   7445       {
   7446 	if (j != 0)
   7447 	  dataref_offset = int_const_binop (PLUS_EXPR, dataref_offset, bump);
   7448 
   7449 	tree data_ref = fold_build2 (MEM_REF, vectype,
   7450 				     unshare_expr (dataref_ptr),
   7451 				     dataref_offset);
   7452 	vect_copy_ref_info (data_ref, DR_REF (dr_info->dr));
   7453 	gimple *g = gimple_build_assign (data_ref, orig);
   7454 	vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   7455 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
   7456       }
   7457   return true;
   7458 }
   7459 
   7460 
   7461 /* Function vectorizable_store.
   7462 
   7463    Check if STMT_INFO defines a non scalar data-ref (array/pointer/structure)
   7464    that can be vectorized.
   7465    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   7466    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   7467    Return true if STMT_INFO is vectorizable in this way.  */
   7468 
   7469 static bool
   7470 vectorizable_store (vec_info *vinfo,
   7471 		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   7472 		    gimple **vec_stmt, slp_tree slp_node,
   7473 		    stmt_vector_for_cost *cost_vec)
   7474 {
   7475   tree data_ref;
   7476   tree op;
   7477   tree vec_oprnd = NULL_TREE;
   7478   tree elem_type;
   7479   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   7480   class loop *loop = NULL;
   7481   machine_mode vec_mode;
   7482   tree dummy;
   7483   enum vect_def_type rhs_dt = vect_unknown_def_type;
   7484   enum vect_def_type mask_dt = vect_unknown_def_type;
   7485   tree dataref_ptr = NULL_TREE;
   7486   tree dataref_offset = NULL_TREE;
   7487   gimple *ptr_incr = NULL;
   7488   int ncopies;
   7489   int j;
   7490   stmt_vec_info first_stmt_info;
   7491   bool grouped_store;
   7492   unsigned int group_size, i;
   7493   vec<tree> oprnds = vNULL;
   7494   vec<tree> result_chain = vNULL;
   7495   vec<tree> vec_oprnds = vNULL;
   7496   bool slp = (slp_node != NULL);
   7497   unsigned int vec_num;
   7498   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   7499   tree aggr_type;
   7500   gather_scatter_info gs_info;
   7501   poly_uint64 vf;
   7502   vec_load_store_type vls_type;
   7503   tree ref_type;
   7504 
   7505   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   7506     return false;
   7507 
   7508   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   7509       && ! vec_stmt)
   7510     return false;
   7511 
   7512   /* Is vectorizable store? */
   7513 
   7514   tree mask = NULL_TREE, mask_vectype = NULL_TREE;
   7515   if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
   7516     {
   7517       tree scalar_dest = gimple_assign_lhs (assign);
   7518       if (TREE_CODE (scalar_dest) == VIEW_CONVERT_EXPR
   7519 	  && is_pattern_stmt_p (stmt_info))
   7520 	scalar_dest = TREE_OPERAND (scalar_dest, 0);
   7521       if (TREE_CODE (scalar_dest) != ARRAY_REF
   7522 	  && TREE_CODE (scalar_dest) != BIT_FIELD_REF
   7523 	  && TREE_CODE (scalar_dest) != INDIRECT_REF
   7524 	  && TREE_CODE (scalar_dest) != COMPONENT_REF
   7525 	  && TREE_CODE (scalar_dest) != IMAGPART_EXPR
   7526 	  && TREE_CODE (scalar_dest) != REALPART_EXPR
   7527 	  && TREE_CODE (scalar_dest) != MEM_REF)
   7528 	return false;
   7529     }
   7530   else
   7531     {
   7532       gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
   7533       if (!call || !gimple_call_internal_p (call))
   7534 	return false;
   7535 
   7536       internal_fn ifn = gimple_call_internal_fn (call);
   7537       if (!internal_store_fn_p (ifn))
   7538 	return false;
   7539 
   7540       if (slp_node != NULL)
   7541 	{
   7542 	  if (dump_enabled_p ())
   7543 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   7544 			     "SLP of masked stores not supported.\n");
   7545 	  return false;
   7546 	}
   7547 
   7548       int mask_index = internal_fn_mask_index (ifn);
   7549       if (mask_index >= 0
   7550 	  && !vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_index,
   7551 				      &mask, NULL, &mask_dt, &mask_vectype))
   7552 	return false;
   7553     }
   7554 
   7555   op = vect_get_store_rhs (stmt_info);
   7556 
   7557   /* Cannot have hybrid store SLP -- that would mean storing to the
   7558      same location twice.  */
   7559   gcc_assert (slp == PURE_SLP_STMT (stmt_info));
   7560 
   7561   tree vectype = STMT_VINFO_VECTYPE (stmt_info), rhs_vectype = NULL_TREE;
   7562   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   7563 
   7564   if (loop_vinfo)
   7565     {
   7566       loop = LOOP_VINFO_LOOP (loop_vinfo);
   7567       vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
   7568     }
   7569   else
   7570     vf = 1;
   7571 
   7572   /* Multiple types in SLP are handled by creating the appropriate number of
   7573      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
   7574      case of SLP.  */
   7575   if (slp)
   7576     ncopies = 1;
   7577   else
   7578     ncopies = vect_get_num_copies (loop_vinfo, vectype);
   7579 
   7580   gcc_assert (ncopies >= 1);
   7581 
   7582   /* FORNOW.  This restriction should be relaxed.  */
   7583   if (loop && nested_in_vect_loop_p (loop, stmt_info) && ncopies > 1)
   7584     {
   7585       if (dump_enabled_p ())
   7586 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   7587 			 "multiple types in nested loop.\n");
   7588       return false;
   7589     }
   7590 
   7591   if (!vect_check_store_rhs (vinfo, stmt_info, slp_node,
   7592 			     op, &rhs_dt, &rhs_vectype, &vls_type))
   7593     return false;
   7594 
   7595   elem_type = TREE_TYPE (vectype);
   7596   vec_mode = TYPE_MODE (vectype);
   7597 
   7598   if (!STMT_VINFO_DATA_REF (stmt_info))
   7599     return false;
   7600 
   7601   vect_memory_access_type memory_access_type;
   7602   enum dr_alignment_support alignment_support_scheme;
   7603   int misalignment;
   7604   poly_int64 poffset;
   7605   if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, vls_type,
   7606 			    ncopies, &memory_access_type, &poffset,
   7607 			    &alignment_support_scheme, &misalignment, &gs_info))
   7608     return false;
   7609 
   7610   if (mask)
   7611     {
   7612       if (memory_access_type == VMAT_CONTIGUOUS)
   7613 	{
   7614 	  if (!VECTOR_MODE_P (vec_mode)
   7615 	      || !can_vec_mask_load_store_p (vec_mode,
   7616 					     TYPE_MODE (mask_vectype), false))
   7617 	    return false;
   7618 	}
   7619       else if (memory_access_type != VMAT_LOAD_STORE_LANES
   7620 	       && (memory_access_type != VMAT_GATHER_SCATTER
   7621 		   || (gs_info.decl && !VECTOR_BOOLEAN_TYPE_P (mask_vectype))))
   7622 	{
   7623 	  if (dump_enabled_p ())
   7624 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   7625 			     "unsupported access type for masked store.\n");
   7626 	  return false;
   7627 	}
   7628     }
   7629   else
   7630     {
   7631       /* FORNOW. In some cases can vectorize even if data-type not supported
   7632 	 (e.g. - array initialization with 0).  */
   7633       if (optab_handler (mov_optab, vec_mode) == CODE_FOR_nothing)
   7634 	return false;
   7635     }
   7636 
   7637   dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info), *first_dr_info = NULL;
   7638   grouped_store = (STMT_VINFO_GROUPED_ACCESS (stmt_info)
   7639 		   && memory_access_type != VMAT_GATHER_SCATTER
   7640 		   && (slp || memory_access_type != VMAT_CONTIGUOUS));
   7641   if (grouped_store)
   7642     {
   7643       first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   7644       first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
   7645       group_size = DR_GROUP_SIZE (first_stmt_info);
   7646     }
   7647   else
   7648     {
   7649       first_stmt_info = stmt_info;
   7650       first_dr_info = dr_info;
   7651       group_size = vec_num = 1;
   7652     }
   7653 
   7654   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) > 1 && !vec_stmt)
   7655     {
   7656       if (!check_scan_store (vinfo, stmt_info, vectype, rhs_dt, slp, mask,
   7657 			     memory_access_type))
   7658 	return false;
   7659     }
   7660 
   7661   if (!vec_stmt) /* transformation not required.  */
   7662     {
   7663       STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) = memory_access_type;
   7664 
   7665       if (loop_vinfo
   7666 	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))
   7667 	check_load_store_for_partial_vectors (loop_vinfo, vectype, slp_node,
   7668 					      vls_type, group_size,
   7669 					      memory_access_type, &gs_info,
   7670 					      mask);
   7671 
   7672       if (slp_node
   7673 	  && !vect_maybe_update_slp_op_vectype (SLP_TREE_CHILDREN (slp_node)[0],
   7674 						vectype))
   7675 	{
   7676 	  if (dump_enabled_p ())
   7677 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   7678 			     "incompatible vector types for invariants\n");
   7679 	  return false;
   7680 	}
   7681 
   7682       if (dump_enabled_p ()
   7683 	  && memory_access_type != VMAT_ELEMENTWISE
   7684 	  && memory_access_type != VMAT_GATHER_SCATTER
   7685 	  && alignment_support_scheme != dr_aligned)
   7686 	dump_printf_loc (MSG_NOTE, vect_location,
   7687 			 "Vectorizing an unaligned access.\n");
   7688 
   7689       STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
   7690       vect_model_store_cost (vinfo, stmt_info, ncopies,
   7691 			     memory_access_type, alignment_support_scheme,
   7692 			     misalignment, vls_type, slp_node, cost_vec);
   7693       return true;
   7694     }
   7695   gcc_assert (memory_access_type == STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info));
   7696 
   7697   /* Transform.  */
   7698 
   7699   ensure_base_align (dr_info);
   7700 
   7701   if (memory_access_type == VMAT_GATHER_SCATTER && gs_info.decl)
   7702     {
   7703       tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE, src;
   7704       tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gs_info.decl));
   7705       tree rettype, srctype, ptrtype, idxtype, masktype, scaletype;
   7706       tree ptr, var, scale, vec_mask;
   7707       tree mask_arg = NULL_TREE, mask_op = NULL_TREE, perm_mask = NULL_TREE;
   7708       tree mask_halfvectype = mask_vectype;
   7709       edge pe = loop_preheader_edge (loop);
   7710       gimple_seq seq;
   7711       basic_block new_bb;
   7712       enum { NARROW, NONE, WIDEN } modifier;
   7713       poly_uint64 scatter_off_nunits
   7714 	= TYPE_VECTOR_SUBPARTS (gs_info.offset_vectype);
   7715 
   7716       if (known_eq (nunits, scatter_off_nunits))
   7717 	modifier = NONE;
   7718       else if (known_eq (nunits * 2, scatter_off_nunits))
   7719 	{
   7720 	  modifier = WIDEN;
   7721 
   7722 	  /* Currently gathers and scatters are only supported for
   7723 	     fixed-length vectors.  */
   7724 	  unsigned int count = scatter_off_nunits.to_constant ();
   7725 	  vec_perm_builder sel (count, count, 1);
   7726 	  for (i = 0; i < (unsigned int) count; ++i)
   7727 	    sel.quick_push (i | (count / 2));
   7728 
   7729 	  vec_perm_indices indices (sel, 1, count);
   7730 	  perm_mask = vect_gen_perm_mask_checked (gs_info.offset_vectype,
   7731 						  indices);
   7732 	  gcc_assert (perm_mask != NULL_TREE);
   7733 	}
   7734       else if (known_eq (nunits, scatter_off_nunits * 2))
   7735 	{
   7736 	  modifier = NARROW;
   7737 
   7738 	  /* Currently gathers and scatters are only supported for
   7739 	     fixed-length vectors.  */
   7740 	  unsigned int count = nunits.to_constant ();
   7741 	  vec_perm_builder sel (count, count, 1);
   7742 	  for (i = 0; i < (unsigned int) count; ++i)
   7743 	    sel.quick_push (i | (count / 2));
   7744 
   7745 	  vec_perm_indices indices (sel, 2, count);
   7746 	  perm_mask = vect_gen_perm_mask_checked (vectype, indices);
   7747 	  gcc_assert (perm_mask != NULL_TREE);
   7748 	  ncopies *= 2;
   7749 
   7750 	  if (mask)
   7751 	    mask_halfvectype = truth_type_for (gs_info.offset_vectype);
   7752 	}
   7753       else
   7754 	gcc_unreachable ();
   7755 
   7756       rettype = TREE_TYPE (TREE_TYPE (gs_info.decl));
   7757       ptrtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   7758       masktype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   7759       idxtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   7760       srctype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
   7761       scaletype = TREE_VALUE (arglist);
   7762 
   7763       gcc_checking_assert (TREE_CODE (masktype) == INTEGER_TYPE
   7764 			   && TREE_CODE (rettype) == VOID_TYPE);
   7765 
   7766       ptr = fold_convert (ptrtype, gs_info.base);
   7767       if (!is_gimple_min_invariant (ptr))
   7768 	{
   7769 	  ptr = force_gimple_operand (ptr, &seq, true, NULL_TREE);
   7770 	  new_bb = gsi_insert_seq_on_edge_immediate (pe, seq);
   7771 	  gcc_assert (!new_bb);
   7772 	}
   7773 
   7774       if (mask == NULL_TREE)
   7775 	{
   7776 	  mask_arg = build_int_cst (masktype, -1);
   7777 	  mask_arg = vect_init_vector (vinfo, stmt_info,
   7778 				       mask_arg, masktype, NULL);
   7779 	}
   7780 
   7781       scale = build_int_cst (scaletype, gs_info.scale);
   7782 
   7783       auto_vec<tree> vec_oprnds0;
   7784       auto_vec<tree> vec_oprnds1;
   7785       auto_vec<tree> vec_masks;
   7786       if (mask)
   7787 	{
   7788 	  tree mask_vectype = truth_type_for (vectype);
   7789 	  vect_get_vec_defs_for_operand (vinfo, stmt_info,
   7790 					 modifier == NARROW
   7791 					 ? ncopies / 2 : ncopies,
   7792 					 mask, &vec_masks, mask_vectype);
   7793 	}
   7794       vect_get_vec_defs_for_operand (vinfo, stmt_info,
   7795 				     modifier == WIDEN
   7796 				     ? ncopies / 2 : ncopies,
   7797 				     gs_info.offset, &vec_oprnds0);
   7798       vect_get_vec_defs_for_operand (vinfo, stmt_info,
   7799 				     modifier == NARROW
   7800 				     ? ncopies / 2 : ncopies,
   7801 				     op, &vec_oprnds1);
   7802       for (j = 0; j < ncopies; ++j)
   7803 	{
   7804 	  if (modifier == WIDEN)
   7805 	    {
   7806 	      if (j & 1)
   7807 		op = permute_vec_elements (vinfo, vec_oprnd0, vec_oprnd0,
   7808 					   perm_mask, stmt_info, gsi);
   7809 	      else
   7810 		op = vec_oprnd0 = vec_oprnds0[j / 2];
   7811 	      src = vec_oprnd1 = vec_oprnds1[j];
   7812 	      if (mask)
   7813 		mask_op = vec_mask = vec_masks[j];
   7814 	    }
   7815 	  else if (modifier == NARROW)
   7816 	    {
   7817 	      if (j & 1)
   7818 		src = permute_vec_elements (vinfo, vec_oprnd1, vec_oprnd1,
   7819 					    perm_mask, stmt_info, gsi);
   7820 	      else
   7821 		src = vec_oprnd1 = vec_oprnds1[j / 2];
   7822 	      op = vec_oprnd0 = vec_oprnds0[j];
   7823 	      if (mask)
   7824 		mask_op = vec_mask = vec_masks[j / 2];
   7825 	    }
   7826 	  else
   7827 	    {
   7828 	      op = vec_oprnd0 = vec_oprnds0[j];
   7829 	      src = vec_oprnd1 = vec_oprnds1[j];
   7830 	      if (mask)
   7831 		mask_op = vec_mask = vec_masks[j];
   7832 	    }
   7833 
   7834 	  if (!useless_type_conversion_p (srctype, TREE_TYPE (src)))
   7835 	    {
   7836 	      gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (src)),
   7837 				    TYPE_VECTOR_SUBPARTS (srctype)));
   7838 	      var = vect_get_new_ssa_name (srctype, vect_simple_var);
   7839 	      src = build1 (VIEW_CONVERT_EXPR, srctype, src);
   7840 	      gassign *new_stmt
   7841 		= gimple_build_assign (var, VIEW_CONVERT_EXPR, src);
   7842 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   7843 	      src = var;
   7844 	    }
   7845 
   7846 	  if (!useless_type_conversion_p (idxtype, TREE_TYPE (op)))
   7847 	    {
   7848 	      gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (op)),
   7849 				    TYPE_VECTOR_SUBPARTS (idxtype)));
   7850 	      var = vect_get_new_ssa_name (idxtype, vect_simple_var);
   7851 	      op = build1 (VIEW_CONVERT_EXPR, idxtype, op);
   7852 	      gassign *new_stmt
   7853 		= gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
   7854 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   7855 	      op = var;
   7856 	    }
   7857 
   7858 	  if (mask)
   7859 	    {
   7860 	      tree utype;
   7861 	      mask_arg = mask_op;
   7862 	      if (modifier == NARROW)
   7863 		{
   7864 		  var = vect_get_new_ssa_name (mask_halfvectype,
   7865 					       vect_simple_var);
   7866 		  gassign *new_stmt
   7867 		    = gimple_build_assign (var, (j & 1) ? VEC_UNPACK_HI_EXPR
   7868 							: VEC_UNPACK_LO_EXPR,
   7869 					   mask_op);
   7870 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   7871 		  mask_arg = var;
   7872 		}
   7873 	      tree optype = TREE_TYPE (mask_arg);
   7874 	      if (TYPE_MODE (masktype) == TYPE_MODE (optype))
   7875 		utype = masktype;
   7876 	      else
   7877 		utype = lang_hooks.types.type_for_mode (TYPE_MODE (optype), 1);
   7878 	      var = vect_get_new_ssa_name (utype, vect_scalar_var);
   7879 	      mask_arg = build1 (VIEW_CONVERT_EXPR, utype, mask_arg);
   7880 	      gassign *new_stmt
   7881 		= gimple_build_assign (var, VIEW_CONVERT_EXPR, mask_arg);
   7882 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   7883 	      mask_arg = var;
   7884 	      if (!useless_type_conversion_p (masktype, utype))
   7885 		{
   7886 		  gcc_assert (TYPE_PRECISION (utype)
   7887 			      <= TYPE_PRECISION (masktype));
   7888 		  var = vect_get_new_ssa_name (masktype, vect_scalar_var);
   7889 		  new_stmt = gimple_build_assign (var, NOP_EXPR, mask_arg);
   7890 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   7891 		  mask_arg = var;
   7892 		}
   7893 	    }
   7894 
   7895 	  gcall *new_stmt
   7896 	    = gimple_build_call (gs_info.decl, 5, ptr, mask_arg, op, src, scale);
   7897 	   vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   7898 
   7899 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   7900 	}
   7901       *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   7902       return true;
   7903     }
   7904   else if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) >= 3)
   7905     return vectorizable_scan_store (vinfo, stmt_info, gsi, vec_stmt, ncopies);
   7906 
   7907   if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
   7908     DR_GROUP_STORE_COUNT (DR_GROUP_FIRST_ELEMENT (stmt_info))++;
   7909 
   7910   if (grouped_store)
   7911     {
   7912       /* FORNOW */
   7913       gcc_assert (!loop || !nested_in_vect_loop_p (loop, stmt_info));
   7914 
   7915       /* We vectorize all the stmts of the interleaving group when we
   7916 	 reach the last stmt in the group.  */
   7917       if (DR_GROUP_STORE_COUNT (first_stmt_info)
   7918 	  < DR_GROUP_SIZE (first_stmt_info)
   7919 	  && !slp)
   7920 	{
   7921 	  *vec_stmt = NULL;
   7922 	  return true;
   7923 	}
   7924 
   7925       if (slp)
   7926         {
   7927           grouped_store = false;
   7928           /* VEC_NUM is the number of vect stmts to be created for this
   7929              group.  */
   7930           vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   7931 	  first_stmt_info = SLP_TREE_SCALAR_STMTS (slp_node)[0];
   7932 	  gcc_assert (DR_GROUP_FIRST_ELEMENT (first_stmt_info)
   7933 		      == first_stmt_info);
   7934 	  first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
   7935 	  op = vect_get_store_rhs (first_stmt_info);
   7936         }
   7937       else
   7938         /* VEC_NUM is the number of vect stmts to be created for this
   7939            group.  */
   7940 	vec_num = group_size;
   7941 
   7942       ref_type = get_group_alias_ptr_type (first_stmt_info);
   7943     }
   7944   else
   7945     ref_type = reference_alias_ptr_type (DR_REF (first_dr_info->dr));
   7946 
   7947   if (dump_enabled_p ())
   7948     dump_printf_loc (MSG_NOTE, vect_location,
   7949                      "transform store. ncopies = %d\n", ncopies);
   7950 
   7951   if (memory_access_type == VMAT_ELEMENTWISE
   7952       || memory_access_type == VMAT_STRIDED_SLP)
   7953     {
   7954       gimple_stmt_iterator incr_gsi;
   7955       bool insert_after;
   7956       gimple *incr;
   7957       tree offvar;
   7958       tree ivstep;
   7959       tree running_off;
   7960       tree stride_base, stride_step, alias_off;
   7961       tree vec_oprnd;
   7962       tree dr_offset;
   7963       unsigned int g;
   7964       /* Checked by get_load_store_type.  */
   7965       unsigned int const_nunits = nunits.to_constant ();
   7966 
   7967       gcc_assert (!LOOP_VINFO_FULLY_MASKED_P (loop_vinfo));
   7968       gcc_assert (!nested_in_vect_loop_p (loop, stmt_info));
   7969 
   7970       dr_offset = get_dr_vinfo_offset (vinfo, first_dr_info);
   7971       stride_base
   7972 	= fold_build_pointer_plus
   7973 	    (DR_BASE_ADDRESS (first_dr_info->dr),
   7974 	     size_binop (PLUS_EXPR,
   7975 			 convert_to_ptrofftype (dr_offset),
   7976 			 convert_to_ptrofftype (DR_INIT (first_dr_info->dr))));
   7977       stride_step = fold_convert (sizetype, DR_STEP (first_dr_info->dr));
   7978 
   7979       /* For a store with loop-invariant (but other than power-of-2)
   7980          stride (i.e. not a grouped access) like so:
   7981 
   7982 	   for (i = 0; i < n; i += stride)
   7983 	     array[i] = ...;
   7984 
   7985 	 we generate a new induction variable and new stores from
   7986 	 the components of the (vectorized) rhs:
   7987 
   7988 	   for (j = 0; ; j += VF*stride)
   7989 	     vectemp = ...;
   7990 	     tmp1 = vectemp[0];
   7991 	     array[j] = tmp1;
   7992 	     tmp2 = vectemp[1];
   7993 	     array[j + stride] = tmp2;
   7994 	     ...
   7995          */
   7996 
   7997       unsigned nstores = const_nunits;
   7998       unsigned lnel = 1;
   7999       tree ltype = elem_type;
   8000       tree lvectype = vectype;
   8001       if (slp)
   8002 	{
   8003 	  if (group_size < const_nunits
   8004 	      && const_nunits % group_size == 0)
   8005 	    {
   8006 	      nstores = const_nunits / group_size;
   8007 	      lnel = group_size;
   8008 	      ltype = build_vector_type (elem_type, group_size);
   8009 	      lvectype = vectype;
   8010 
   8011 	      /* First check if vec_extract optab doesn't support extraction
   8012 		 of vector elts directly.  */
   8013 	      scalar_mode elmode = SCALAR_TYPE_MODE (elem_type);
   8014 	      machine_mode vmode;
   8015 	      if (!VECTOR_MODE_P (TYPE_MODE (vectype))
   8016 		  || !related_vector_mode (TYPE_MODE (vectype), elmode,
   8017 					   group_size).exists (&vmode)
   8018 		  || (convert_optab_handler (vec_extract_optab,
   8019 					     TYPE_MODE (vectype), vmode)
   8020 		      == CODE_FOR_nothing))
   8021 		{
   8022 		  /* Try to avoid emitting an extract of vector elements
   8023 		     by performing the extracts using an integer type of the
   8024 		     same size, extracting from a vector of those and then
   8025 		     re-interpreting it as the original vector type if
   8026 		     supported.  */
   8027 		  unsigned lsize
   8028 		    = group_size * GET_MODE_BITSIZE (elmode);
   8029 		  unsigned int lnunits = const_nunits / group_size;
   8030 		  /* If we can't construct such a vector fall back to
   8031 		     element extracts from the original vector type and
   8032 		     element size stores.  */
   8033 		  if (int_mode_for_size (lsize, 0).exists (&elmode)
   8034 		      && VECTOR_MODE_P (TYPE_MODE (vectype))
   8035 		      && related_vector_mode (TYPE_MODE (vectype), elmode,
   8036 					      lnunits).exists (&vmode)
   8037 		      && (convert_optab_handler (vec_extract_optab,
   8038 						 vmode, elmode)
   8039 			  != CODE_FOR_nothing))
   8040 		    {
   8041 		      nstores = lnunits;
   8042 		      lnel = group_size;
   8043 		      ltype = build_nonstandard_integer_type (lsize, 1);
   8044 		      lvectype = build_vector_type (ltype, nstores);
   8045 		    }
   8046 		  /* Else fall back to vector extraction anyway.
   8047 		     Fewer stores are more important than avoiding spilling
   8048 		     of the vector we extract from.  Compared to the
   8049 		     construction case in vectorizable_load no store-forwarding
   8050 		     issue exists here for reasonable archs.  */
   8051 		}
   8052 	    }
   8053 	  else if (group_size >= const_nunits
   8054 		   && group_size % const_nunits == 0)
   8055 	    {
   8056 	      nstores = 1;
   8057 	      lnel = const_nunits;
   8058 	      ltype = vectype;
   8059 	      lvectype = vectype;
   8060 	    }
   8061 	  ltype = build_aligned_type (ltype, TYPE_ALIGN (elem_type));
   8062 	  ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   8063 	}
   8064 
   8065       ivstep = stride_step;
   8066       ivstep = fold_build2 (MULT_EXPR, TREE_TYPE (ivstep), ivstep,
   8067 			    build_int_cst (TREE_TYPE (ivstep), vf));
   8068 
   8069       standard_iv_increment_position (loop, &incr_gsi, &insert_after);
   8070 
   8071       stride_base = cse_and_gimplify_to_preheader (loop_vinfo, stride_base);
   8072       ivstep = cse_and_gimplify_to_preheader (loop_vinfo, ivstep);
   8073       create_iv (stride_base, ivstep, NULL,
   8074 		 loop, &incr_gsi, insert_after,
   8075 		 &offvar, NULL);
   8076       incr = gsi_stmt (incr_gsi);
   8077 
   8078       stride_step = cse_and_gimplify_to_preheader (loop_vinfo, stride_step);
   8079 
   8080       alias_off = build_int_cst (ref_type, 0);
   8081       stmt_vec_info next_stmt_info = first_stmt_info;
   8082       for (g = 0; g < group_size; g++)
   8083 	{
   8084 	  running_off = offvar;
   8085 	  if (g)
   8086 	    {
   8087 	      tree size = TYPE_SIZE_UNIT (ltype);
   8088 	      tree pos = fold_build2 (MULT_EXPR, sizetype, size_int (g),
   8089 				      size);
   8090 	      tree newoff = copy_ssa_name (running_off, NULL);
   8091 	      incr = gimple_build_assign (newoff, POINTER_PLUS_EXPR,
   8092 					  running_off, pos);
   8093 	      vect_finish_stmt_generation (vinfo, stmt_info, incr, gsi);
   8094 	      running_off = newoff;
   8095 	    }
   8096 	  if (!slp)
   8097 	    op = vect_get_store_rhs (next_stmt_info);
   8098 	  vect_get_vec_defs (vinfo, next_stmt_info, slp_node, ncopies,
   8099 			     op, &vec_oprnds);
   8100 	  unsigned int group_el = 0;
   8101 	  unsigned HOST_WIDE_INT
   8102 	    elsz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
   8103 	  for (j = 0; j < ncopies; j++)
   8104 	    {
   8105 	      vec_oprnd = vec_oprnds[j];
   8106 	      /* Pun the vector to extract from if necessary.  */
   8107 	      if (lvectype != vectype)
   8108 		{
   8109 		  tree tem = make_ssa_name (lvectype);
   8110 		  gimple *pun
   8111 		    = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
   8112 							lvectype, vec_oprnd));
   8113 		  vect_finish_stmt_generation (vinfo, stmt_info, pun, gsi);
   8114 		  vec_oprnd = tem;
   8115 		}
   8116 	      for (i = 0; i < nstores; i++)
   8117 		{
   8118 		  tree newref, newoff;
   8119 		  gimple *incr, *assign;
   8120 		  tree size = TYPE_SIZE (ltype);
   8121 		  /* Extract the i'th component.  */
   8122 		  tree pos = fold_build2 (MULT_EXPR, bitsizetype,
   8123 					  bitsize_int (i), size);
   8124 		  tree elem = fold_build3 (BIT_FIELD_REF, ltype, vec_oprnd,
   8125 					   size, pos);
   8126 
   8127 		  elem = force_gimple_operand_gsi (gsi, elem, true,
   8128 						   NULL_TREE, true,
   8129 						   GSI_SAME_STMT);
   8130 
   8131 		  tree this_off = build_int_cst (TREE_TYPE (alias_off),
   8132 						 group_el * elsz);
   8133 		  newref = build2 (MEM_REF, ltype,
   8134 				   running_off, this_off);
   8135 		  vect_copy_ref_info (newref, DR_REF (first_dr_info->dr));
   8136 
   8137 		  /* And store it to *running_off.  */
   8138 		  assign = gimple_build_assign (newref, elem);
   8139 		  vect_finish_stmt_generation (vinfo, stmt_info, assign, gsi);
   8140 
   8141 		  group_el += lnel;
   8142 		  if (! slp
   8143 		      || group_el == group_size)
   8144 		    {
   8145 		      newoff = copy_ssa_name (running_off, NULL);
   8146 		      incr = gimple_build_assign (newoff, POINTER_PLUS_EXPR,
   8147 						  running_off, stride_step);
   8148 		      vect_finish_stmt_generation (vinfo, stmt_info, incr, gsi);
   8149 
   8150 		      running_off = newoff;
   8151 		      group_el = 0;
   8152 		    }
   8153 		  if (g == group_size - 1
   8154 		      && !slp)
   8155 		    {
   8156 		      if (j == 0 && i == 0)
   8157 			*vec_stmt = assign;
   8158 		      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (assign);
   8159 		    }
   8160 		}
   8161 	    }
   8162 	  next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
   8163 	  vec_oprnds.release ();
   8164 	  if (slp)
   8165 	    break;
   8166 	}
   8167 
   8168       return true;
   8169     }
   8170 
   8171   auto_vec<tree> dr_chain (group_size);
   8172   oprnds.create (group_size);
   8173 
   8174   gcc_assert (alignment_support_scheme);
   8175   vec_loop_masks *loop_masks
   8176     = (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
   8177        ? &LOOP_VINFO_MASKS (loop_vinfo)
   8178        : NULL);
   8179   vec_loop_lens *loop_lens
   8180     = (loop_vinfo && LOOP_VINFO_FULLY_WITH_LENGTH_P (loop_vinfo)
   8181        ? &LOOP_VINFO_LENS (loop_vinfo)
   8182        : NULL);
   8183 
   8184   /* Shouldn't go with length-based approach if fully masked.  */
   8185   gcc_assert (!loop_lens || !loop_masks);
   8186 
   8187   /* Targets with store-lane instructions must not require explicit
   8188      realignment.  vect_supportable_dr_alignment always returns either
   8189      dr_aligned or dr_unaligned_supported for masked operations.  */
   8190   gcc_assert ((memory_access_type != VMAT_LOAD_STORE_LANES
   8191 	       && !mask
   8192 	       && !loop_masks)
   8193 	      || alignment_support_scheme == dr_aligned
   8194 	      || alignment_support_scheme == dr_unaligned_supported);
   8195 
   8196   tree offset = NULL_TREE;
   8197   if (!known_eq (poffset, 0))
   8198     offset = size_int (poffset);
   8199 
   8200   tree bump;
   8201   tree vec_offset = NULL_TREE;
   8202   if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   8203     {
   8204       aggr_type = NULL_TREE;
   8205       bump = NULL_TREE;
   8206     }
   8207   else if (memory_access_type == VMAT_GATHER_SCATTER)
   8208     {
   8209       aggr_type = elem_type;
   8210       vect_get_strided_load_store_ops (stmt_info, loop_vinfo, &gs_info,
   8211 				       &bump, &vec_offset);
   8212     }
   8213   else
   8214     {
   8215       if (memory_access_type == VMAT_LOAD_STORE_LANES)
   8216 	aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
   8217       else
   8218 	aggr_type = vectype;
   8219       bump = vect_get_data_ptr_increment (vinfo, dr_info, aggr_type,
   8220 					  memory_access_type);
   8221     }
   8222 
   8223   if (mask)
   8224     LOOP_VINFO_HAS_MASK_STORE (loop_vinfo) = true;
   8225 
   8226   /* In case the vectorization factor (VF) is bigger than the number
   8227      of elements that we can fit in a vectype (nunits), we have to generate
   8228      more than one vector stmt - i.e - we need to "unroll" the
   8229      vector stmt by a factor VF/nunits.  */
   8230 
   8231   /* In case of interleaving (non-unit grouped access):
   8232 
   8233         S1:  &base + 2 = x2
   8234         S2:  &base = x0
   8235         S3:  &base + 1 = x1
   8236         S4:  &base + 3 = x3
   8237 
   8238      We create vectorized stores starting from base address (the access of the
   8239      first stmt in the chain (S2 in the above example), when the last store stmt
   8240      of the chain (S4) is reached:
   8241 
   8242         VS1: &base = vx2
   8243 	VS2: &base + vec_size*1 = vx0
   8244 	VS3: &base + vec_size*2 = vx1
   8245 	VS4: &base + vec_size*3 = vx3
   8246 
   8247      Then permutation statements are generated:
   8248 
   8249 	VS5: vx5 = VEC_PERM_EXPR < vx0, vx3, {0, 8, 1, 9, 2, 10, 3, 11} >
   8250 	VS6: vx6 = VEC_PERM_EXPR < vx0, vx3, {4, 12, 5, 13, 6, 14, 7, 15} >
   8251 	...
   8252 
   8253      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
   8254      (the order of the data-refs in the output of vect_permute_store_chain
   8255      corresponds to the order of scalar stmts in the interleaving chain - see
   8256      the documentation of vect_permute_store_chain()).
   8257 
   8258      In case of both multiple types and interleaving, above vector stores and
   8259      permutation stmts are created for every copy.  The result vector stmts are
   8260      put in STMT_VINFO_VEC_STMT for the first copy and in the corresponding
   8261      STMT_VINFO_RELATED_STMT for the next copies.
   8262   */
   8263 
   8264   auto_vec<tree> vec_masks;
   8265   tree vec_mask = NULL;
   8266   auto_vec<tree> vec_offsets;
   8267   auto_vec<vec<tree> > gvec_oprnds;
   8268   gvec_oprnds.safe_grow_cleared (group_size, true);
   8269   for (j = 0; j < ncopies; j++)
   8270     {
   8271       gimple *new_stmt;
   8272       if (j == 0)
   8273 	{
   8274           if (slp)
   8275             {
   8276 	      /* Get vectorized arguments for SLP_NODE.  */
   8277 	      vect_get_vec_defs (vinfo, stmt_info, slp_node, 1,
   8278 				 op, &vec_oprnds);
   8279               vec_oprnd = vec_oprnds[0];
   8280             }
   8281           else
   8282             {
   8283 	      /* For interleaved stores we collect vectorized defs for all the
   8284 		 stores in the group in DR_CHAIN and OPRNDS. DR_CHAIN is then
   8285 		 used as an input to vect_permute_store_chain().
   8286 
   8287 		 If the store is not grouped, DR_GROUP_SIZE is 1, and DR_CHAIN
   8288 		 and OPRNDS are of size 1.  */
   8289 	      stmt_vec_info next_stmt_info = first_stmt_info;
   8290 	      for (i = 0; i < group_size; i++)
   8291 		{
   8292 		  /* Since gaps are not supported for interleaved stores,
   8293 		     DR_GROUP_SIZE is the exact number of stmts in the chain.
   8294 		     Therefore, NEXT_STMT_INFO can't be NULL_TREE.  In case
   8295 		     that there is no interleaving, DR_GROUP_SIZE is 1,
   8296 		     and only one iteration of the loop will be executed.  */
   8297 		  op = vect_get_store_rhs (next_stmt_info);
   8298 		  vect_get_vec_defs_for_operand (vinfo, next_stmt_info,
   8299 						 ncopies, op, &gvec_oprnds[i]);
   8300 		  vec_oprnd = gvec_oprnds[i][0];
   8301 		  dr_chain.quick_push (gvec_oprnds[i][0]);
   8302 		  oprnds.quick_push (gvec_oprnds[i][0]);
   8303 		  next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
   8304 		}
   8305 	      if (mask)
   8306 		{
   8307 		  vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
   8308 						 mask, &vec_masks, mask_vectype);
   8309 		  vec_mask = vec_masks[0];
   8310 		}
   8311 	    }
   8312 
   8313 	  /* We should have catched mismatched types earlier.  */
   8314 	  gcc_assert (useless_type_conversion_p (vectype,
   8315 						 TREE_TYPE (vec_oprnd)));
   8316 	  bool simd_lane_access_p
   8317 	    = STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) != 0;
   8318 	  if (simd_lane_access_p
   8319 	      && !loop_masks
   8320 	      && TREE_CODE (DR_BASE_ADDRESS (first_dr_info->dr)) == ADDR_EXPR
   8321 	      && VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (first_dr_info->dr), 0))
   8322 	      && integer_zerop (get_dr_vinfo_offset (vinfo, first_dr_info))
   8323 	      && integer_zerop (DR_INIT (first_dr_info->dr))
   8324 	      && alias_sets_conflict_p (get_alias_set (aggr_type),
   8325 					get_alias_set (TREE_TYPE (ref_type))))
   8326 	    {
   8327 	      dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr_info->dr));
   8328 	      dataref_offset = build_int_cst (ref_type, 0);
   8329 	    }
   8330 	  else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   8331 	    {
   8332 	      vect_get_gather_scatter_ops (loop_vinfo, loop, stmt_info,
   8333 					   slp_node, &gs_info, &dataref_ptr,
   8334 					   &vec_offsets);
   8335 	      vec_offset = vec_offsets[0];
   8336 	    }
   8337 	  else
   8338 	    dataref_ptr
   8339 	      = vect_create_data_ref_ptr (vinfo, first_stmt_info, aggr_type,
   8340 					  simd_lane_access_p ? loop : NULL,
   8341 					  offset, &dummy, gsi, &ptr_incr,
   8342 					  simd_lane_access_p, bump);
   8343 	}
   8344       else
   8345 	{
   8346 	  /* For interleaved stores we created vectorized defs for all the
   8347 	     defs stored in OPRNDS in the previous iteration (previous copy).
   8348 	     DR_CHAIN is then used as an input to vect_permute_store_chain().
   8349 	     If the store is not grouped, DR_GROUP_SIZE is 1, and DR_CHAIN and
   8350 	     OPRNDS are of size 1.  */
   8351 	  for (i = 0; i < group_size; i++)
   8352 	    {
   8353 	      vec_oprnd = gvec_oprnds[i][j];
   8354 	      dr_chain[i] = gvec_oprnds[i][j];
   8355 	      oprnds[i] = gvec_oprnds[i][j];
   8356 	    }
   8357 	  if (mask)
   8358 	    vec_mask = vec_masks[j];
   8359 	  if (dataref_offset)
   8360 	    dataref_offset
   8361 	      = int_const_binop (PLUS_EXPR, dataref_offset, bump);
   8362 	  else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   8363 	    vec_offset = vec_offsets[j];
   8364 	  else
   8365 	    dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr, gsi,
   8366 					   stmt_info, bump);
   8367 	}
   8368 
   8369       if (memory_access_type == VMAT_LOAD_STORE_LANES)
   8370 	{
   8371 	  tree vec_array;
   8372 
   8373 	  /* Get an array into which we can store the individual vectors.  */
   8374 	  vec_array = create_vector_array (vectype, vec_num);
   8375 
   8376 	  /* Invalidate the current contents of VEC_ARRAY.  This should
   8377 	     become an RTL clobber too, which prevents the vector registers
   8378 	     from being upward-exposed.  */
   8379 	  vect_clobber_variable (vinfo, stmt_info, gsi, vec_array);
   8380 
   8381 	  /* Store the individual vectors into the array.  */
   8382 	  for (i = 0; i < vec_num; i++)
   8383 	    {
   8384 	      vec_oprnd = dr_chain[i];
   8385 	      write_vector_array (vinfo, stmt_info,
   8386 				  gsi, vec_oprnd, vec_array, i);
   8387 	    }
   8388 
   8389 	  tree final_mask = NULL;
   8390 	  if (loop_masks)
   8391 	    final_mask = vect_get_loop_mask (gsi, loop_masks, ncopies,
   8392 					     vectype, j);
   8393 	  if (vec_mask)
   8394 	    final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
   8395 					   final_mask, vec_mask, gsi);
   8396 
   8397 	  gcall *call;
   8398 	  if (final_mask)
   8399 	    {
   8400 	      /* Emit:
   8401 		   MASK_STORE_LANES (DATAREF_PTR, ALIAS_PTR, VEC_MASK,
   8402 				     VEC_ARRAY).  */
   8403 	      unsigned int align = TYPE_ALIGN (TREE_TYPE (vectype));
   8404 	      tree alias_ptr = build_int_cst (ref_type, align);
   8405 	      call = gimple_build_call_internal (IFN_MASK_STORE_LANES, 4,
   8406 						 dataref_ptr, alias_ptr,
   8407 						 final_mask, vec_array);
   8408 	    }
   8409 	  else
   8410 	    {
   8411 	      /* Emit:
   8412 		   MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY).  */
   8413 	      data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type);
   8414 	      call = gimple_build_call_internal (IFN_STORE_LANES, 1,
   8415 						 vec_array);
   8416 	      gimple_call_set_lhs (call, data_ref);
   8417 	    }
   8418 	  gimple_call_set_nothrow (call, true);
   8419 	  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   8420 	  new_stmt = call;
   8421 
   8422 	  /* Record that VEC_ARRAY is now dead.  */
   8423 	  vect_clobber_variable (vinfo, stmt_info, gsi, vec_array);
   8424 	}
   8425       else
   8426 	{
   8427 	  new_stmt = NULL;
   8428 	  if (grouped_store)
   8429 	    {
   8430 	      if (j == 0)
   8431 		result_chain.create (group_size);
   8432 	      /* Permute.  */
   8433 	      vect_permute_store_chain (vinfo, dr_chain, group_size, stmt_info,
   8434 					gsi, &result_chain);
   8435 	    }
   8436 
   8437 	  stmt_vec_info next_stmt_info = first_stmt_info;
   8438 	  for (i = 0; i < vec_num; i++)
   8439 	    {
   8440 	      unsigned misalign;
   8441 	      unsigned HOST_WIDE_INT align;
   8442 
   8443 	      tree final_mask = NULL_TREE;
   8444 	      if (loop_masks)
   8445 		final_mask = vect_get_loop_mask (gsi, loop_masks,
   8446 						 vec_num * ncopies,
   8447 						 vectype, vec_num * j + i);
   8448 	      if (vec_mask)
   8449 		final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
   8450 					       final_mask, vec_mask, gsi);
   8451 
   8452 	      if (memory_access_type == VMAT_GATHER_SCATTER)
   8453 		{
   8454 		  tree scale = size_int (gs_info.scale);
   8455 		  gcall *call;
   8456 		  if (final_mask)
   8457 		    call = gimple_build_call_internal
   8458 		      (IFN_MASK_SCATTER_STORE, 5, dataref_ptr, vec_offset,
   8459 		       scale, vec_oprnd, final_mask);
   8460 		  else
   8461 		    call = gimple_build_call_internal
   8462 		      (IFN_SCATTER_STORE, 4, dataref_ptr, vec_offset,
   8463 		       scale, vec_oprnd);
   8464 		  gimple_call_set_nothrow (call, true);
   8465 		  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   8466 		  new_stmt = call;
   8467 		  break;
   8468 		}
   8469 
   8470 	      if (i > 0)
   8471 		/* Bump the vector pointer.  */
   8472 		dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr,
   8473 					       gsi, stmt_info, bump);
   8474 
   8475 	      if (slp)
   8476 		vec_oprnd = vec_oprnds[i];
   8477 	      else if (grouped_store)
   8478 		/* For grouped stores vectorized defs are interleaved in
   8479 		   vect_permute_store_chain().  */
   8480 		vec_oprnd = result_chain[i];
   8481 
   8482 	      align = known_alignment (DR_TARGET_ALIGNMENT (first_dr_info));
   8483 	      if (alignment_support_scheme == dr_aligned)
   8484 		misalign = 0;
   8485 	      else if (misalignment == DR_MISALIGNMENT_UNKNOWN)
   8486 		{
   8487 		  align = dr_alignment (vect_dr_behavior (vinfo, first_dr_info));
   8488 		  misalign = 0;
   8489 		}
   8490 	      else
   8491 		misalign = misalignment;
   8492 	      if (dataref_offset == NULL_TREE
   8493 		  && TREE_CODE (dataref_ptr) == SSA_NAME)
   8494 		set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
   8495 					misalign);
   8496 	      align = least_bit_hwi (misalign | align);
   8497 
   8498 	      if (memory_access_type == VMAT_CONTIGUOUS_REVERSE)
   8499 		{
   8500 		  tree perm_mask = perm_mask_for_reverse (vectype);
   8501 		  tree perm_dest = vect_create_destination_var
   8502 		    (vect_get_store_rhs (stmt_info), vectype);
   8503 		  tree new_temp = make_ssa_name (perm_dest);
   8504 
   8505 		  /* Generate the permute statement.  */
   8506 		  gimple *perm_stmt
   8507 		    = gimple_build_assign (new_temp, VEC_PERM_EXPR, vec_oprnd,
   8508 					   vec_oprnd, perm_mask);
   8509 		  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
   8510 
   8511 		  perm_stmt = SSA_NAME_DEF_STMT (new_temp);
   8512 		  vec_oprnd = new_temp;
   8513 		}
   8514 
   8515 	      /* Arguments are ready.  Create the new vector stmt.  */
   8516 	      if (final_mask)
   8517 		{
   8518 		  tree ptr = build_int_cst (ref_type, align * BITS_PER_UNIT);
   8519 		  gcall *call
   8520 		    = gimple_build_call_internal (IFN_MASK_STORE, 4,
   8521 						  dataref_ptr, ptr,
   8522 						  final_mask, vec_oprnd);
   8523 		  gimple_call_set_nothrow (call, true);
   8524 		  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   8525 		  new_stmt = call;
   8526 		}
   8527 	      else if (loop_lens)
   8528 		{
   8529 		  tree final_len
   8530 		    = vect_get_loop_len (loop_vinfo, loop_lens,
   8531 					 vec_num * ncopies, vec_num * j + i);
   8532 		  tree ptr = build_int_cst (ref_type, align * BITS_PER_UNIT);
   8533 		  machine_mode vmode = TYPE_MODE (vectype);
   8534 		  opt_machine_mode new_ovmode
   8535 		    = get_len_load_store_mode (vmode, false);
   8536 		  machine_mode new_vmode = new_ovmode.require ();
   8537 		  /* Need conversion if it's wrapped with VnQI.  */
   8538 		  if (vmode != new_vmode)
   8539 		    {
   8540 		      tree new_vtype
   8541 			= build_vector_type_for_mode (unsigned_intQI_type_node,
   8542 						      new_vmode);
   8543 		      tree var
   8544 			= vect_get_new_ssa_name (new_vtype, vect_simple_var);
   8545 		      vec_oprnd
   8546 			= build1 (VIEW_CONVERT_EXPR, new_vtype, vec_oprnd);
   8547 		      gassign *new_stmt
   8548 			= gimple_build_assign (var, VIEW_CONVERT_EXPR,
   8549 					       vec_oprnd);
   8550 		      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt,
   8551 						   gsi);
   8552 		      vec_oprnd = var;
   8553 		    }
   8554 
   8555 		  signed char biasval =
   8556 		    LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
   8557 
   8558 		  tree bias = build_int_cst (intQI_type_node, biasval);
   8559 		  gcall *call
   8560 		    = gimple_build_call_internal (IFN_LEN_STORE, 5, dataref_ptr,
   8561 						  ptr, final_len, vec_oprnd,
   8562 						  bias);
   8563 		  gimple_call_set_nothrow (call, true);
   8564 		  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   8565 		  new_stmt = call;
   8566 		}
   8567 	      else
   8568 		{
   8569 		  data_ref = fold_build2 (MEM_REF, vectype,
   8570 					  dataref_ptr,
   8571 					  dataref_offset
   8572 					  ? dataref_offset
   8573 					  : build_int_cst (ref_type, 0));
   8574 		  if (alignment_support_scheme == dr_aligned)
   8575 		    ;
   8576 		  else
   8577 		    TREE_TYPE (data_ref)
   8578 		      = build_aligned_type (TREE_TYPE (data_ref),
   8579 					    align * BITS_PER_UNIT);
   8580 		  vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
   8581 		  new_stmt = gimple_build_assign (data_ref, vec_oprnd);
   8582 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   8583 		}
   8584 
   8585 	      if (slp)
   8586 		continue;
   8587 
   8588 	      next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
   8589 	      if (!next_stmt_info)
   8590 		break;
   8591 	    }
   8592 	}
   8593       if (!slp)
   8594 	{
   8595 	  if (j == 0)
   8596 	    *vec_stmt = new_stmt;
   8597 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   8598 	}
   8599     }
   8600 
   8601   for (i = 0; i < group_size; ++i)
   8602     {
   8603       vec<tree> oprndsi = gvec_oprnds[i];
   8604       oprndsi.release ();
   8605     }
   8606   oprnds.release ();
   8607   result_chain.release ();
   8608   vec_oprnds.release ();
   8609 
   8610   return true;
   8611 }
   8612 
   8613 /* Given a vector type VECTYPE, turns permutation SEL into the equivalent
   8614    VECTOR_CST mask.  No checks are made that the target platform supports the
   8615    mask, so callers may wish to test can_vec_perm_const_p separately, or use
   8616    vect_gen_perm_mask_checked.  */
   8617 
   8618 tree
   8619 vect_gen_perm_mask_any (tree vectype, const vec_perm_indices &sel)
   8620 {
   8621   tree mask_type;
   8622 
   8623   poly_uint64 nunits = sel.length ();
   8624   gcc_assert (known_eq (nunits, TYPE_VECTOR_SUBPARTS (vectype)));
   8625 
   8626   mask_type = build_vector_type (ssizetype, nunits);
   8627   return vec_perm_indices_to_tree (mask_type, sel);
   8628 }
   8629 
   8630 /* Checked version of vect_gen_perm_mask_any.  Asserts can_vec_perm_const_p,
   8631    i.e. that the target supports the pattern _for arbitrary input vectors_.  */
   8632 
   8633 tree
   8634 vect_gen_perm_mask_checked (tree vectype, const vec_perm_indices &sel)
   8635 {
   8636   gcc_assert (can_vec_perm_const_p (TYPE_MODE (vectype), sel));
   8637   return vect_gen_perm_mask_any (vectype, sel);
   8638 }
   8639 
   8640 /* Given a vector variable X and Y, that was generated for the scalar
   8641    STMT_INFO, generate instructions to permute the vector elements of X and Y
   8642    using permutation mask MASK_VEC, insert them at *GSI and return the
   8643    permuted vector variable.  */
   8644 
   8645 static tree
   8646 permute_vec_elements (vec_info *vinfo,
   8647 		      tree x, tree y, tree mask_vec, stmt_vec_info stmt_info,
   8648 		      gimple_stmt_iterator *gsi)
   8649 {
   8650   tree vectype = TREE_TYPE (x);
   8651   tree perm_dest, data_ref;
   8652   gimple *perm_stmt;
   8653 
   8654   tree scalar_dest = gimple_get_lhs (stmt_info->stmt);
   8655   if (scalar_dest && TREE_CODE (scalar_dest) == SSA_NAME)
   8656     perm_dest = vect_create_destination_var (scalar_dest, vectype);
   8657   else
   8658     perm_dest = vect_get_new_vect_var (vectype, vect_simple_var, NULL);
   8659   data_ref = make_ssa_name (perm_dest);
   8660 
   8661   /* Generate the permute statement.  */
   8662   perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, x, y, mask_vec);
   8663   vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
   8664 
   8665   return data_ref;
   8666 }
   8667 
   8668 /* Hoist the definitions of all SSA uses on STMT_INFO out of the loop LOOP,
   8669    inserting them on the loops preheader edge.  Returns true if we
   8670    were successful in doing so (and thus STMT_INFO can be moved then),
   8671    otherwise returns false.  */
   8672 
   8673 static bool
   8674 hoist_defs_of_uses (stmt_vec_info stmt_info, class loop *loop)
   8675 {
   8676   ssa_op_iter i;
   8677   tree op;
   8678   bool any = false;
   8679 
   8680   FOR_EACH_SSA_TREE_OPERAND (op, stmt_info->stmt, i, SSA_OP_USE)
   8681     {
   8682       gimple *def_stmt = SSA_NAME_DEF_STMT (op);
   8683       if (!gimple_nop_p (def_stmt)
   8684 	  && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
   8685 	{
   8686 	  /* Make sure we don't need to recurse.  While we could do
   8687 	     so in simple cases when there are more complex use webs
   8688 	     we don't have an easy way to preserve stmt order to fulfil
   8689 	     dependencies within them.  */
   8690 	  tree op2;
   8691 	  ssa_op_iter i2;
   8692 	  if (gimple_code (def_stmt) == GIMPLE_PHI)
   8693 	    return false;
   8694 	  FOR_EACH_SSA_TREE_OPERAND (op2, def_stmt, i2, SSA_OP_USE)
   8695 	    {
   8696 	      gimple *def_stmt2 = SSA_NAME_DEF_STMT (op2);
   8697 	      if (!gimple_nop_p (def_stmt2)
   8698 		  && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt2)))
   8699 		return false;
   8700 	    }
   8701 	  any = true;
   8702 	}
   8703     }
   8704 
   8705   if (!any)
   8706     return true;
   8707 
   8708   FOR_EACH_SSA_TREE_OPERAND (op, stmt_info->stmt, i, SSA_OP_USE)
   8709     {
   8710       gimple *def_stmt = SSA_NAME_DEF_STMT (op);
   8711       if (!gimple_nop_p (def_stmt)
   8712 	  && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
   8713 	{
   8714 	  gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt);
   8715 	  gsi_remove (&gsi, false);
   8716 	  gsi_insert_on_edge_immediate (loop_preheader_edge (loop), def_stmt);
   8717 	}
   8718     }
   8719 
   8720   return true;
   8721 }
   8722 
   8723 /* vectorizable_load.
   8724 
   8725    Check if STMT_INFO reads a non scalar data-ref (array/pointer/structure)
   8726    that can be vectorized.
   8727    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   8728    stmt to replace it, put it in VEC_STMT, and insert it at GSI.
   8729    Return true if STMT_INFO is vectorizable in this way.  */
   8730 
   8731 static bool
   8732 vectorizable_load (vec_info *vinfo,
   8733 		   stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   8734 		   gimple **vec_stmt, slp_tree slp_node,
   8735 		   stmt_vector_for_cost *cost_vec)
   8736 {
   8737   tree scalar_dest;
   8738   tree vec_dest = NULL;
   8739   tree data_ref = NULL;
   8740   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   8741   class loop *loop = NULL;
   8742   class loop *containing_loop = gimple_bb (stmt_info->stmt)->loop_father;
   8743   bool nested_in_vect_loop = false;
   8744   tree elem_type;
   8745   tree new_temp;
   8746   machine_mode mode;
   8747   tree dummy;
   8748   tree dataref_ptr = NULL_TREE;
   8749   tree dataref_offset = NULL_TREE;
   8750   gimple *ptr_incr = NULL;
   8751   int ncopies;
   8752   int i, j;
   8753   unsigned int group_size;
   8754   poly_uint64 group_gap_adj;
   8755   tree msq = NULL_TREE, lsq;
   8756   tree realignment_token = NULL_TREE;
   8757   gphi *phi = NULL;
   8758   vec<tree> dr_chain = vNULL;
   8759   bool grouped_load = false;
   8760   stmt_vec_info first_stmt_info;
   8761   stmt_vec_info first_stmt_info_for_drptr = NULL;
   8762   bool compute_in_loop = false;
   8763   class loop *at_loop;
   8764   int vec_num;
   8765   bool slp = (slp_node != NULL);
   8766   bool slp_perm = false;
   8767   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   8768   poly_uint64 vf;
   8769   tree aggr_type;
   8770   gather_scatter_info gs_info;
   8771   tree ref_type;
   8772   enum vect_def_type mask_dt = vect_unknown_def_type;
   8773 
   8774   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   8775     return false;
   8776 
   8777   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
   8778       && ! vec_stmt)
   8779     return false;
   8780 
   8781   if (!STMT_VINFO_DATA_REF (stmt_info))
   8782     return false;
   8783 
   8784   tree mask = NULL_TREE, mask_vectype = NULL_TREE;
   8785   int mask_index = -1;
   8786   if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
   8787     {
   8788       scalar_dest = gimple_assign_lhs (assign);
   8789       if (TREE_CODE (scalar_dest) != SSA_NAME)
   8790 	return false;
   8791 
   8792       tree_code code = gimple_assign_rhs_code (assign);
   8793       if (code != ARRAY_REF
   8794 	  && code != BIT_FIELD_REF
   8795 	  && code != INDIRECT_REF
   8796 	  && code != COMPONENT_REF
   8797 	  && code != IMAGPART_EXPR
   8798 	  && code != REALPART_EXPR
   8799 	  && code != MEM_REF
   8800 	  && TREE_CODE_CLASS (code) != tcc_declaration)
   8801 	return false;
   8802     }
   8803   else
   8804     {
   8805       gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
   8806       if (!call || !gimple_call_internal_p (call))
   8807 	return false;
   8808 
   8809       internal_fn ifn = gimple_call_internal_fn (call);
   8810       if (!internal_load_fn_p (ifn))
   8811 	return false;
   8812 
   8813       scalar_dest = gimple_call_lhs (call);
   8814       if (!scalar_dest)
   8815 	return false;
   8816 
   8817       mask_index = internal_fn_mask_index (ifn);
   8818       /* ??? For SLP the mask operand is always last.  */
   8819       if (mask_index >= 0 && slp_node)
   8820 	mask_index = SLP_TREE_CHILDREN (slp_node).length () - 1;
   8821       if (mask_index >= 0
   8822 	  && !vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_index,
   8823 				      &mask, NULL, &mask_dt, &mask_vectype))
   8824 	return false;
   8825     }
   8826 
   8827   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   8828   poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
   8829 
   8830   if (loop_vinfo)
   8831     {
   8832       loop = LOOP_VINFO_LOOP (loop_vinfo);
   8833       nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt_info);
   8834       vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
   8835     }
   8836   else
   8837     vf = 1;
   8838 
   8839   /* Multiple types in SLP are handled by creating the appropriate number of
   8840      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
   8841      case of SLP.  */
   8842   if (slp)
   8843     ncopies = 1;
   8844   else
   8845     ncopies = vect_get_num_copies (loop_vinfo, vectype);
   8846 
   8847   gcc_assert (ncopies >= 1);
   8848 
   8849   /* FORNOW. This restriction should be relaxed.  */
   8850   if (nested_in_vect_loop && ncopies > 1)
   8851     {
   8852       if (dump_enabled_p ())
   8853         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8854                          "multiple types in nested loop.\n");
   8855       return false;
   8856     }
   8857 
   8858   /* Invalidate assumptions made by dependence analysis when vectorization
   8859      on the unrolled body effectively re-orders stmts.  */
   8860   if (ncopies > 1
   8861       && STMT_VINFO_MIN_NEG_DIST (stmt_info) != 0
   8862       && maybe_gt (LOOP_VINFO_VECT_FACTOR (loop_vinfo),
   8863 		   STMT_VINFO_MIN_NEG_DIST (stmt_info)))
   8864     {
   8865       if (dump_enabled_p ())
   8866 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8867 			 "cannot perform implicit CSE when unrolling "
   8868 			 "with negative dependence distance\n");
   8869       return false;
   8870     }
   8871 
   8872   elem_type = TREE_TYPE (vectype);
   8873   mode = TYPE_MODE (vectype);
   8874 
   8875   /* FORNOW. In some cases can vectorize even if data-type not supported
   8876     (e.g. - data copies).  */
   8877   if (optab_handler (mov_optab, mode) == CODE_FOR_nothing)
   8878     {
   8879       if (dump_enabled_p ())
   8880         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8881                          "Aligned load, but unsupported type.\n");
   8882       return false;
   8883     }
   8884 
   8885   /* Check if the load is a part of an interleaving chain.  */
   8886   if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
   8887     {
   8888       grouped_load = true;
   8889       /* FORNOW */
   8890       gcc_assert (!nested_in_vect_loop);
   8891       gcc_assert (!STMT_VINFO_GATHER_SCATTER_P (stmt_info));
   8892 
   8893       first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   8894       group_size = DR_GROUP_SIZE (first_stmt_info);
   8895 
   8896       /* Refuse non-SLP vectorization of SLP-only groups.  */
   8897       if (!slp && STMT_VINFO_SLP_VECT_ONLY (first_stmt_info))
   8898 	{
   8899 	  if (dump_enabled_p ())
   8900 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8901 			     "cannot vectorize load in non-SLP mode.\n");
   8902 	  return false;
   8903 	}
   8904 
   8905       if (slp && SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
   8906 	{
   8907 	  slp_perm = true;
   8908 
   8909 	  if (!loop_vinfo)
   8910 	    {
   8911 	      /* In BB vectorization we may not actually use a loaded vector
   8912 		 accessing elements in excess of DR_GROUP_SIZE.  */
   8913 	      stmt_vec_info group_info = SLP_TREE_SCALAR_STMTS (slp_node)[0];
   8914 	      group_info = DR_GROUP_FIRST_ELEMENT (group_info);
   8915 	      unsigned HOST_WIDE_INT nunits;
   8916 	      unsigned j, k, maxk = 0;
   8917 	      FOR_EACH_VEC_ELT (SLP_TREE_LOAD_PERMUTATION (slp_node), j, k)
   8918 		if (k > maxk)
   8919 		  maxk = k;
   8920 	      tree vectype = SLP_TREE_VECTYPE (slp_node);
   8921 	      if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits)
   8922 		  || maxk >= (DR_GROUP_SIZE (group_info) & ~(nunits - 1)))
   8923 		{
   8924 		  if (dump_enabled_p ())
   8925 		    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8926 				     "BB vectorization with gaps at the end of "
   8927 				     "a load is not supported\n");
   8928 		  return false;
   8929 		}
   8930 	    }
   8931 
   8932 	  auto_vec<tree> tem;
   8933 	  unsigned n_perms;
   8934 	  if (!vect_transform_slp_perm_load (vinfo, slp_node, tem, NULL, vf,
   8935 					     true, &n_perms))
   8936 	    {
   8937 	      if (dump_enabled_p ())
   8938 		dump_printf_loc (MSG_MISSED_OPTIMIZATION,
   8939 				 vect_location,
   8940 				 "unsupported load permutation\n");
   8941 	      return false;
   8942 	    }
   8943 	}
   8944 
   8945       /* Invalidate assumptions made by dependence analysis when vectorization
   8946 	 on the unrolled body effectively re-orders stmts.  */
   8947       if (!PURE_SLP_STMT (stmt_info)
   8948 	  && STMT_VINFO_MIN_NEG_DIST (stmt_info) != 0
   8949 	  && maybe_gt (LOOP_VINFO_VECT_FACTOR (loop_vinfo),
   8950 		       STMT_VINFO_MIN_NEG_DIST (stmt_info)))
   8951 	{
   8952 	  if (dump_enabled_p ())
   8953 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8954 			     "cannot perform implicit CSE when performing "
   8955 			     "group loads with negative dependence distance\n");
   8956 	  return false;
   8957 	}
   8958     }
   8959   else
   8960     group_size = 1;
   8961 
   8962   vect_memory_access_type memory_access_type;
   8963   enum dr_alignment_support alignment_support_scheme;
   8964   int misalignment;
   8965   poly_int64 poffset;
   8966   if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, VLS_LOAD,
   8967 			    ncopies, &memory_access_type, &poffset,
   8968 			    &alignment_support_scheme, &misalignment, &gs_info))
   8969     return false;
   8970 
   8971   if (mask)
   8972     {
   8973       if (memory_access_type == VMAT_CONTIGUOUS)
   8974 	{
   8975 	  machine_mode vec_mode = TYPE_MODE (vectype);
   8976 	  if (!VECTOR_MODE_P (vec_mode)
   8977 	      || !can_vec_mask_load_store_p (vec_mode,
   8978 					     TYPE_MODE (mask_vectype), true))
   8979 	    return false;
   8980 	}
   8981       else if (memory_access_type != VMAT_LOAD_STORE_LANES
   8982 	       && memory_access_type != VMAT_GATHER_SCATTER)
   8983 	{
   8984 	  if (dump_enabled_p ())
   8985 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8986 			     "unsupported access type for masked load.\n");
   8987 	  return false;
   8988 	}
   8989       else if (memory_access_type == VMAT_GATHER_SCATTER
   8990 	       && gs_info.ifn == IFN_LAST
   8991 	       && !gs_info.decl)
   8992 	{
   8993 	  if (dump_enabled_p ())
   8994 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   8995 			     "unsupported masked emulated gather.\n");
   8996 	  return false;
   8997 	}
   8998       else if (memory_access_type == VMAT_ELEMENTWISE
   8999 	       || memory_access_type == VMAT_STRIDED_SLP)
   9000 	{
   9001 	  if (dump_enabled_p ())
   9002 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   9003 			     "unsupported masked strided access.\n");
   9004 	  return false;
   9005 	}
   9006     }
   9007 
   9008   if (!vec_stmt) /* transformation not required.  */
   9009     {
   9010       if (slp_node
   9011 	  && mask
   9012 	  && !vect_maybe_update_slp_op_vectype (SLP_TREE_CHILDREN (slp_node)[0],
   9013 						mask_vectype))
   9014 	{
   9015 	  if (dump_enabled_p ())
   9016 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   9017 			     "incompatible vector types for invariants\n");
   9018 	  return false;
   9019 	}
   9020 
   9021       if (!slp)
   9022 	STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) = memory_access_type;
   9023 
   9024       if (loop_vinfo
   9025 	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))
   9026 	check_load_store_for_partial_vectors (loop_vinfo, vectype, slp_node,
   9027 					      VLS_LOAD, group_size,
   9028 					      memory_access_type, &gs_info,
   9029 					      mask);
   9030 
   9031       if (dump_enabled_p ()
   9032 	  && memory_access_type != VMAT_ELEMENTWISE
   9033 	  && memory_access_type != VMAT_GATHER_SCATTER
   9034 	  && alignment_support_scheme != dr_aligned)
   9035 	dump_printf_loc (MSG_NOTE, vect_location,
   9036 			 "Vectorizing an unaligned access.\n");
   9037 
   9038       STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
   9039       vect_model_load_cost (vinfo, stmt_info, ncopies, vf, memory_access_type,
   9040 			    alignment_support_scheme, misalignment,
   9041 			    &gs_info, slp_node, cost_vec);
   9042       return true;
   9043     }
   9044 
   9045   if (!slp)
   9046     gcc_assert (memory_access_type
   9047 		== STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info));
   9048 
   9049   if (dump_enabled_p ())
   9050     dump_printf_loc (MSG_NOTE, vect_location,
   9051                      "transform load. ncopies = %d\n", ncopies);
   9052 
   9053   /* Transform.  */
   9054 
   9055   dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info), *first_dr_info = NULL;
   9056   ensure_base_align (dr_info);
   9057 
   9058   if (memory_access_type == VMAT_GATHER_SCATTER && gs_info.decl)
   9059     {
   9060       vect_build_gather_load_calls (vinfo,
   9061 				    stmt_info, gsi, vec_stmt, &gs_info, mask);
   9062       return true;
   9063     }
   9064 
   9065   if (memory_access_type == VMAT_INVARIANT)
   9066     {
   9067       gcc_assert (!grouped_load && !mask && !bb_vinfo);
   9068       /* If we have versioned for aliasing or the loop doesn't
   9069 	 have any data dependencies that would preclude this,
   9070 	 then we are sure this is a loop invariant load and
   9071 	 thus we can insert it on the preheader edge.  */
   9072       bool hoist_p = (LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo)
   9073 		      && !nested_in_vect_loop
   9074 		      && hoist_defs_of_uses (stmt_info, loop));
   9075       if (hoist_p)
   9076 	{
   9077 	  gassign *stmt = as_a <gassign *> (stmt_info->stmt);
   9078 	  if (dump_enabled_p ())
   9079 	    dump_printf_loc (MSG_NOTE, vect_location,
   9080 			     "hoisting out of the vectorized loop: %G", stmt);
   9081 	  scalar_dest = copy_ssa_name (scalar_dest);
   9082 	  tree rhs = unshare_expr (gimple_assign_rhs1 (stmt));
   9083 	  gsi_insert_on_edge_immediate
   9084 	    (loop_preheader_edge (loop),
   9085 	     gimple_build_assign (scalar_dest, rhs));
   9086 	}
   9087       /* These copies are all equivalent, but currently the representation
   9088 	 requires a separate STMT_VINFO_VEC_STMT for each one.  */
   9089       gimple_stmt_iterator gsi2 = *gsi;
   9090       gsi_next (&gsi2);
   9091       for (j = 0; j < ncopies; j++)
   9092 	{
   9093 	  if (hoist_p)
   9094 	    new_temp = vect_init_vector (vinfo, stmt_info, scalar_dest,
   9095 					 vectype, NULL);
   9096 	  else
   9097 	    new_temp = vect_init_vector (vinfo, stmt_info, scalar_dest,
   9098 					 vectype, &gsi2);
   9099 	  gimple *new_stmt = SSA_NAME_DEF_STMT (new_temp);
   9100 	  if (slp)
   9101 	    SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   9102 	  else
   9103 	    {
   9104 	      if (j == 0)
   9105 		*vec_stmt = new_stmt;
   9106 	      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   9107 	    }
   9108 	}
   9109       return true;
   9110     }
   9111 
   9112   if (memory_access_type == VMAT_ELEMENTWISE
   9113       || memory_access_type == VMAT_STRIDED_SLP)
   9114     {
   9115       gimple_stmt_iterator incr_gsi;
   9116       bool insert_after;
   9117       tree offvar;
   9118       tree ivstep;
   9119       tree running_off;
   9120       vec<constructor_elt, va_gc> *v = NULL;
   9121       tree stride_base, stride_step, alias_off;
   9122       /* Checked by get_load_store_type.  */
   9123       unsigned int const_nunits = nunits.to_constant ();
   9124       unsigned HOST_WIDE_INT cst_offset = 0;
   9125       tree dr_offset;
   9126 
   9127       gcc_assert (!LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo));
   9128       gcc_assert (!nested_in_vect_loop);
   9129 
   9130       if (grouped_load)
   9131 	{
   9132 	  first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   9133 	  first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
   9134 	}
   9135       else
   9136 	{
   9137 	  first_stmt_info = stmt_info;
   9138 	  first_dr_info = dr_info;
   9139 	}
   9140       if (slp && grouped_load)
   9141 	{
   9142 	  group_size = DR_GROUP_SIZE (first_stmt_info);
   9143 	  ref_type = get_group_alias_ptr_type (first_stmt_info);
   9144 	}
   9145       else
   9146 	{
   9147 	  if (grouped_load)
   9148 	    cst_offset
   9149 	      = (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (vectype)))
   9150 		 * vect_get_place_in_interleaving_chain (stmt_info,
   9151 							 first_stmt_info));
   9152 	  group_size = 1;
   9153 	  ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr));
   9154 	}
   9155 
   9156       dr_offset = get_dr_vinfo_offset (vinfo, first_dr_info);
   9157       stride_base
   9158 	= fold_build_pointer_plus
   9159 	    (DR_BASE_ADDRESS (first_dr_info->dr),
   9160 	     size_binop (PLUS_EXPR,
   9161 			 convert_to_ptrofftype (dr_offset),
   9162 			 convert_to_ptrofftype (DR_INIT (first_dr_info->dr))));
   9163       stride_step = fold_convert (sizetype, DR_STEP (first_dr_info->dr));
   9164 
   9165       /* For a load with loop-invariant (but other than power-of-2)
   9166          stride (i.e. not a grouped access) like so:
   9167 
   9168 	   for (i = 0; i < n; i += stride)
   9169 	     ... = array[i];
   9170 
   9171 	 we generate a new induction variable and new accesses to
   9172 	 form a new vector (or vectors, depending on ncopies):
   9173 
   9174 	   for (j = 0; ; j += VF*stride)
   9175 	     tmp1 = array[j];
   9176 	     tmp2 = array[j + stride];
   9177 	     ...
   9178 	     vectemp = {tmp1, tmp2, ...}
   9179          */
   9180 
   9181       ivstep = fold_build2 (MULT_EXPR, TREE_TYPE (stride_step), stride_step,
   9182 			    build_int_cst (TREE_TYPE (stride_step), vf));
   9183 
   9184       standard_iv_increment_position (loop, &incr_gsi, &insert_after);
   9185 
   9186       stride_base = cse_and_gimplify_to_preheader (loop_vinfo, stride_base);
   9187       ivstep = cse_and_gimplify_to_preheader (loop_vinfo, ivstep);
   9188       create_iv (stride_base, ivstep, NULL,
   9189 		 loop, &incr_gsi, insert_after,
   9190 		 &offvar, NULL);
   9191 
   9192       stride_step = cse_and_gimplify_to_preheader (loop_vinfo, stride_step);
   9193 
   9194       running_off = offvar;
   9195       alias_off = build_int_cst (ref_type, 0);
   9196       int nloads = const_nunits;
   9197       int lnel = 1;
   9198       tree ltype = TREE_TYPE (vectype);
   9199       tree lvectype = vectype;
   9200       auto_vec<tree> dr_chain;
   9201       if (memory_access_type == VMAT_STRIDED_SLP)
   9202 	{
   9203 	  if (group_size < const_nunits)
   9204 	    {
   9205 	      /* First check if vec_init optab supports construction from vector
   9206 		 elts directly.  Otherwise avoid emitting a constructor of
   9207 		 vector elements by performing the loads using an integer type
   9208 		 of the same size, constructing a vector of those and then
   9209 		 re-interpreting it as the original vector type.  This avoids a
   9210 		 huge runtime penalty due to the general inability to perform
   9211 		 store forwarding from smaller stores to a larger load.  */
   9212 	      tree ptype;
   9213 	      tree vtype
   9214 		= vector_vector_composition_type (vectype,
   9215 						  const_nunits / group_size,
   9216 						  &ptype);
   9217 	      if (vtype != NULL_TREE)
   9218 		{
   9219 		  nloads = const_nunits / group_size;
   9220 		  lnel = group_size;
   9221 		  lvectype = vtype;
   9222 		  ltype = ptype;
   9223 		}
   9224 	    }
   9225 	  else
   9226 	    {
   9227 	      nloads = 1;
   9228 	      lnel = const_nunits;
   9229 	      ltype = vectype;
   9230 	    }
   9231 	  ltype = build_aligned_type (ltype, TYPE_ALIGN (TREE_TYPE (vectype)));
   9232 	}
   9233       /* Load vector(1) scalar_type if it's 1 element-wise vectype.  */
   9234       else if (nloads == 1)
   9235 	ltype = vectype;
   9236 
   9237       if (slp)
   9238 	{
   9239 	  /* For SLP permutation support we need to load the whole group,
   9240 	     not only the number of vector stmts the permutation result
   9241 	     fits in.  */
   9242 	  if (slp_perm)
   9243 	    {
   9244 	      /* We don't yet generate SLP_TREE_LOAD_PERMUTATIONs for
   9245 		 variable VF.  */
   9246 	      unsigned int const_vf = vf.to_constant ();
   9247 	      ncopies = CEIL (group_size * const_vf, const_nunits);
   9248 	      dr_chain.create (ncopies);
   9249 	    }
   9250 	  else
   9251 	    ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   9252 	}
   9253       unsigned int group_el = 0;
   9254       unsigned HOST_WIDE_INT
   9255 	elsz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
   9256       unsigned int n_groups = 0;
   9257       for (j = 0; j < ncopies; j++)
   9258 	{
   9259 	  if (nloads > 1)
   9260 	    vec_alloc (v, nloads);
   9261 	  gimple *new_stmt = NULL;
   9262 	  for (i = 0; i < nloads; i++)
   9263 	    {
   9264 	      tree this_off = build_int_cst (TREE_TYPE (alias_off),
   9265 					     group_el * elsz + cst_offset);
   9266 	      tree data_ref = build2 (MEM_REF, ltype, running_off, this_off);
   9267 	      vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
   9268 	      new_stmt = gimple_build_assign (make_ssa_name (ltype), data_ref);
   9269 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   9270 	      if (nloads > 1)
   9271 		CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
   9272 					gimple_assign_lhs (new_stmt));
   9273 
   9274 	      group_el += lnel;
   9275 	      if (! slp
   9276 		  || group_el == group_size)
   9277 		{
   9278 		  n_groups++;
   9279 		  /* When doing SLP make sure to not load elements from
   9280 		     the next vector iteration, those will not be accessed
   9281 		     so just use the last element again.  See PR107451.  */
   9282 		  if (!slp || known_lt (n_groups, vf))
   9283 		    {
   9284 		      tree newoff = copy_ssa_name (running_off);
   9285 		      gimple *incr
   9286 			= gimple_build_assign (newoff, POINTER_PLUS_EXPR,
   9287 					       running_off, stride_step);
   9288 		      vect_finish_stmt_generation (vinfo, stmt_info, incr, gsi);
   9289 		      running_off = newoff;
   9290 		    }
   9291 		  group_el = 0;
   9292 		}
   9293 	    }
   9294 	  if (nloads > 1)
   9295 	    {
   9296 	      tree vec_inv = build_constructor (lvectype, v);
   9297 	      new_temp = vect_init_vector (vinfo, stmt_info,
   9298 					   vec_inv, lvectype, gsi);
   9299 	      new_stmt = SSA_NAME_DEF_STMT (new_temp);
   9300 	      if (lvectype != vectype)
   9301 		{
   9302 		  new_stmt = gimple_build_assign (make_ssa_name (vectype),
   9303 						  VIEW_CONVERT_EXPR,
   9304 						  build1 (VIEW_CONVERT_EXPR,
   9305 							  vectype, new_temp));
   9306 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   9307 		}
   9308 	    }
   9309 
   9310 	  if (slp)
   9311 	    {
   9312 	      if (slp_perm)
   9313 		dr_chain.quick_push (gimple_assign_lhs (new_stmt));
   9314 	      else
   9315 		SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   9316 	    }
   9317 	  else
   9318 	    {
   9319 	      if (j == 0)
   9320 		*vec_stmt = new_stmt;
   9321 	      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   9322 	    }
   9323 	}
   9324       if (slp_perm)
   9325 	{
   9326 	  unsigned n_perms;
   9327 	  vect_transform_slp_perm_load (vinfo, slp_node, dr_chain, gsi, vf,
   9328 					false, &n_perms);
   9329 	}
   9330       return true;
   9331     }
   9332 
   9333   if (memory_access_type == VMAT_GATHER_SCATTER
   9334       || (!slp && memory_access_type == VMAT_CONTIGUOUS))
   9335     grouped_load = false;
   9336 
   9337   if (grouped_load)
   9338     {
   9339       first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   9340       group_size = DR_GROUP_SIZE (first_stmt_info);
   9341       /* For SLP vectorization we directly vectorize a subchain
   9342          without permutation.  */
   9343       if (slp && ! SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
   9344 	first_stmt_info = SLP_TREE_SCALAR_STMTS (slp_node)[0];
   9345       /* For BB vectorization always use the first stmt to base
   9346 	 the data ref pointer on.  */
   9347       if (bb_vinfo)
   9348 	first_stmt_info_for_drptr
   9349 	  = vect_find_first_scalar_stmt_in_slp (slp_node);
   9350 
   9351       /* Check if the chain of loads is already vectorized.  */
   9352       if (STMT_VINFO_VEC_STMTS (first_stmt_info).exists ()
   9353 	  /* For SLP we would need to copy over SLP_TREE_VEC_STMTS.
   9354 	     ???  But we can only do so if there is exactly one
   9355 	     as we have no way to get at the rest.  Leave the CSE
   9356 	     opportunity alone.
   9357 	     ???  With the group load eventually participating
   9358 	     in multiple different permutations (having multiple
   9359 	     slp nodes which refer to the same group) the CSE
   9360 	     is even wrong code.  See PR56270.  */
   9361 	  && !slp)
   9362 	{
   9363 	  *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   9364 	  return true;
   9365 	}
   9366       first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
   9367       group_gap_adj = 0;
   9368 
   9369       /* VEC_NUM is the number of vect stmts to be created for this group.  */
   9370       if (slp)
   9371 	{
   9372 	  grouped_load = false;
   9373 	  /* If an SLP permutation is from N elements to N elements,
   9374 	     and if one vector holds a whole number of N, we can load
   9375 	     the inputs to the permutation in the same way as an
   9376 	     unpermuted sequence.  In other cases we need to load the
   9377 	     whole group, not only the number of vector stmts the
   9378 	     permutation result fits in.  */
   9379 	  unsigned scalar_lanes = SLP_TREE_LANES (slp_node);
   9380 	  if (slp_perm
   9381 	      && (group_size != scalar_lanes
   9382 		  || !multiple_p (nunits, group_size)))
   9383 	    {
   9384 	      /* We don't yet generate such SLP_TREE_LOAD_PERMUTATIONs for
   9385 		 variable VF; see vect_transform_slp_perm_load.  */
   9386 	      unsigned int const_vf = vf.to_constant ();
   9387 	      unsigned int const_nunits = nunits.to_constant ();
   9388 	      vec_num = CEIL (group_size * const_vf, const_nunits);
   9389 	      group_gap_adj = vf * group_size - nunits * vec_num;
   9390 	    }
   9391 	  else
   9392 	    {
   9393 	      vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   9394 	      group_gap_adj
   9395 		= group_size - scalar_lanes;
   9396 	    }
   9397     	}
   9398       else
   9399 	vec_num = group_size;
   9400 
   9401       ref_type = get_group_alias_ptr_type (first_stmt_info);
   9402     }
   9403   else
   9404     {
   9405       first_stmt_info = stmt_info;
   9406       first_dr_info = dr_info;
   9407       group_size = vec_num = 1;
   9408       group_gap_adj = 0;
   9409       ref_type = reference_alias_ptr_type (DR_REF (first_dr_info->dr));
   9410       if (slp)
   9411 	vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   9412     }
   9413 
   9414   gcc_assert (alignment_support_scheme);
   9415   vec_loop_masks *loop_masks
   9416     = (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
   9417        ? &LOOP_VINFO_MASKS (loop_vinfo)
   9418        : NULL);
   9419   vec_loop_lens *loop_lens
   9420     = (loop_vinfo && LOOP_VINFO_FULLY_WITH_LENGTH_P (loop_vinfo)
   9421        ? &LOOP_VINFO_LENS (loop_vinfo)
   9422        : NULL);
   9423 
   9424   /* Shouldn't go with length-based approach if fully masked.  */
   9425   gcc_assert (!loop_lens || !loop_masks);
   9426 
   9427   /* Targets with store-lane instructions must not require explicit
   9428      realignment.  vect_supportable_dr_alignment always returns either
   9429      dr_aligned or dr_unaligned_supported for masked operations.  */
   9430   gcc_assert ((memory_access_type != VMAT_LOAD_STORE_LANES
   9431 	       && !mask
   9432 	       && !loop_masks)
   9433 	      || alignment_support_scheme == dr_aligned
   9434 	      || alignment_support_scheme == dr_unaligned_supported);
   9435 
   9436   /* In case the vectorization factor (VF) is bigger than the number
   9437      of elements that we can fit in a vectype (nunits), we have to generate
   9438      more than one vector stmt - i.e - we need to "unroll" the
   9439      vector stmt by a factor VF/nunits.  In doing so, we record a pointer
   9440      from one copy of the vector stmt to the next, in the field
   9441      STMT_VINFO_RELATED_STMT.  This is necessary in order to allow following
   9442      stages to find the correct vector defs to be used when vectorizing
   9443      stmts that use the defs of the current stmt.  The example below
   9444      illustrates the vectorization process when VF=16 and nunits=4 (i.e., we
   9445      need to create 4 vectorized stmts):
   9446 
   9447      before vectorization:
   9448                                 RELATED_STMT    VEC_STMT
   9449         S1:     x = memref      -               -
   9450         S2:     z = x + 1       -               -
   9451 
   9452      step 1: vectorize stmt S1:
   9453         We first create the vector stmt VS1_0, and, as usual, record a
   9454         pointer to it in the STMT_VINFO_VEC_STMT of the scalar stmt S1.
   9455         Next, we create the vector stmt VS1_1, and record a pointer to
   9456         it in the STMT_VINFO_RELATED_STMT of the vector stmt VS1_0.
   9457         Similarly, for VS1_2 and VS1_3.  This is the resulting chain of
   9458         stmts and pointers:
   9459                                 RELATED_STMT    VEC_STMT
   9460         VS1_0:  vx0 = memref0   VS1_1           -
   9461         VS1_1:  vx1 = memref1   VS1_2           -
   9462         VS1_2:  vx2 = memref2   VS1_3           -
   9463         VS1_3:  vx3 = memref3   -               -
   9464         S1:     x = load        -               VS1_0
   9465         S2:     z = x + 1       -               -
   9466   */
   9467 
   9468   /* In case of interleaving (non-unit grouped access):
   9469 
   9470      S1:  x2 = &base + 2
   9471      S2:  x0 = &base
   9472      S3:  x1 = &base + 1
   9473      S4:  x3 = &base + 3
   9474 
   9475      Vectorized loads are created in the order of memory accesses
   9476      starting from the access of the first stmt of the chain:
   9477 
   9478      VS1: vx0 = &base
   9479      VS2: vx1 = &base + vec_size*1
   9480      VS3: vx3 = &base + vec_size*2
   9481      VS4: vx4 = &base + vec_size*3
   9482 
   9483      Then permutation statements are generated:
   9484 
   9485      VS5: vx5 = VEC_PERM_EXPR < vx0, vx1, { 0, 2, ..., i*2 } >
   9486      VS6: vx6 = VEC_PERM_EXPR < vx0, vx1, { 1, 3, ..., i*2+1 } >
   9487        ...
   9488 
   9489      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
   9490      (the order of the data-refs in the output of vect_permute_load_chain
   9491      corresponds to the order of scalar stmts in the interleaving chain - see
   9492      the documentation of vect_permute_load_chain()).
   9493      The generation of permutation stmts and recording them in
   9494      STMT_VINFO_VEC_STMT is done in vect_transform_grouped_load().
   9495 
   9496      In case of both multiple types and interleaving, the vector loads and
   9497      permutation stmts above are created for every copy.  The result vector
   9498      stmts are put in STMT_VINFO_VEC_STMT for the first copy and in the
   9499      corresponding STMT_VINFO_RELATED_STMT for the next copies.  */
   9500 
   9501   /* If the data reference is aligned (dr_aligned) or potentially unaligned
   9502      on a target that supports unaligned accesses (dr_unaligned_supported)
   9503      we generate the following code:
   9504          p = initial_addr;
   9505          indx = 0;
   9506          loop {
   9507 	   p = p + indx * vectype_size;
   9508            vec_dest = *(p);
   9509            indx = indx + 1;
   9510          }
   9511 
   9512      Otherwise, the data reference is potentially unaligned on a target that
   9513      does not support unaligned accesses (dr_explicit_realign_optimized) -
   9514      then generate the following code, in which the data in each iteration is
   9515      obtained by two vector loads, one from the previous iteration, and one
   9516      from the current iteration:
   9517          p1 = initial_addr;
   9518          msq_init = *(floor(p1))
   9519          p2 = initial_addr + VS - 1;
   9520          realignment_token = call target_builtin;
   9521          indx = 0;
   9522          loop {
   9523            p2 = p2 + indx * vectype_size
   9524            lsq = *(floor(p2))
   9525            vec_dest = realign_load (msq, lsq, realignment_token)
   9526            indx = indx + 1;
   9527            msq = lsq;
   9528          }   */
   9529 
   9530   /* If the misalignment remains the same throughout the execution of the
   9531      loop, we can create the init_addr and permutation mask at the loop
   9532      preheader.  Otherwise, it needs to be created inside the loop.
   9533      This can only occur when vectorizing memory accesses in the inner-loop
   9534      nested within an outer-loop that is being vectorized.  */
   9535 
   9536   if (nested_in_vect_loop
   9537       && !multiple_p (DR_STEP_ALIGNMENT (dr_info->dr),
   9538 		      GET_MODE_SIZE (TYPE_MODE (vectype))))
   9539     {
   9540       gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
   9541       compute_in_loop = true;
   9542     }
   9543 
   9544   bool diff_first_stmt_info
   9545     = first_stmt_info_for_drptr && first_stmt_info != first_stmt_info_for_drptr;
   9546 
   9547   tree offset = NULL_TREE;
   9548   if ((alignment_support_scheme == dr_explicit_realign_optimized
   9549        || alignment_support_scheme == dr_explicit_realign)
   9550       && !compute_in_loop)
   9551     {
   9552       /* If we have different first_stmt_info, we can't set up realignment
   9553 	 here, since we can't guarantee first_stmt_info DR has been
   9554 	 initialized yet, use first_stmt_info_for_drptr DR by bumping the
   9555 	 distance from first_stmt_info DR instead as below.  */
   9556       if (!diff_first_stmt_info)
   9557 	msq = vect_setup_realignment (vinfo,
   9558 				      first_stmt_info, gsi, &realignment_token,
   9559 				      alignment_support_scheme, NULL_TREE,
   9560 				      &at_loop);
   9561       if (alignment_support_scheme == dr_explicit_realign_optimized)
   9562 	{
   9563 	  phi = as_a <gphi *> (SSA_NAME_DEF_STMT (msq));
   9564 	  offset = size_binop (MINUS_EXPR, TYPE_SIZE_UNIT (vectype),
   9565 			       size_one_node);
   9566 	  gcc_assert (!first_stmt_info_for_drptr);
   9567 	}
   9568     }
   9569   else
   9570     at_loop = loop;
   9571 
   9572   if (!known_eq (poffset, 0))
   9573     offset = (offset
   9574 	      ? size_binop (PLUS_EXPR, offset, size_int (poffset))
   9575 	      : size_int (poffset));
   9576 
   9577   tree bump;
   9578   tree vec_offset = NULL_TREE;
   9579   if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   9580     {
   9581       aggr_type = NULL_TREE;
   9582       bump = NULL_TREE;
   9583     }
   9584   else if (memory_access_type == VMAT_GATHER_SCATTER)
   9585     {
   9586       aggr_type = elem_type;
   9587       vect_get_strided_load_store_ops (stmt_info, loop_vinfo, &gs_info,
   9588 				       &bump, &vec_offset);
   9589     }
   9590   else
   9591     {
   9592       if (memory_access_type == VMAT_LOAD_STORE_LANES)
   9593 	aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
   9594       else
   9595 	aggr_type = vectype;
   9596       bump = vect_get_data_ptr_increment (vinfo, dr_info, aggr_type,
   9597 					  memory_access_type);
   9598     }
   9599 
   9600   auto_vec<tree> vec_offsets;
   9601   auto_vec<tree> vec_masks;
   9602   if (mask)
   9603     {
   9604       if (slp_node)
   9605 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[mask_index],
   9606 			   &vec_masks);
   9607       else
   9608 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies, mask,
   9609 				       &vec_masks, mask_vectype);
   9610     }
   9611   tree vec_mask = NULL_TREE;
   9612   poly_uint64 group_elt = 0;
   9613   for (j = 0; j < ncopies; j++)
   9614     {
   9615       /* 1. Create the vector or array pointer update chain.  */
   9616       if (j == 0)
   9617 	{
   9618 	  bool simd_lane_access_p
   9619 	    = STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) != 0;
   9620 	  if (simd_lane_access_p
   9621 	      && TREE_CODE (DR_BASE_ADDRESS (first_dr_info->dr)) == ADDR_EXPR
   9622 	      && VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (first_dr_info->dr), 0))
   9623 	      && integer_zerop (get_dr_vinfo_offset (vinfo, first_dr_info))
   9624 	      && integer_zerop (DR_INIT (first_dr_info->dr))
   9625 	      && alias_sets_conflict_p (get_alias_set (aggr_type),
   9626 					get_alias_set (TREE_TYPE (ref_type)))
   9627 	      && (alignment_support_scheme == dr_aligned
   9628 		  || alignment_support_scheme == dr_unaligned_supported))
   9629 	    {
   9630 	      dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr_info->dr));
   9631 	      dataref_offset = build_int_cst (ref_type, 0);
   9632 	    }
   9633 	  else if (diff_first_stmt_info)
   9634 	    {
   9635 	      dataref_ptr
   9636 		= vect_create_data_ref_ptr (vinfo, first_stmt_info_for_drptr,
   9637 					    aggr_type, at_loop, offset, &dummy,
   9638 					    gsi, &ptr_incr, simd_lane_access_p,
   9639 					    bump);
   9640 	      /* Adjust the pointer by the difference to first_stmt.  */
   9641 	      data_reference_p ptrdr
   9642 		= STMT_VINFO_DATA_REF (first_stmt_info_for_drptr);
   9643 	      tree diff
   9644 		= fold_convert (sizetype,
   9645 				size_binop (MINUS_EXPR,
   9646 					    DR_INIT (first_dr_info->dr),
   9647 					    DR_INIT (ptrdr)));
   9648 	      dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr, gsi,
   9649 					     stmt_info, diff);
   9650 	      if (alignment_support_scheme == dr_explicit_realign)
   9651 		{
   9652 		  msq = vect_setup_realignment (vinfo,
   9653 						first_stmt_info_for_drptr, gsi,
   9654 						&realignment_token,
   9655 						alignment_support_scheme,
   9656 						dataref_ptr, &at_loop);
   9657 		  gcc_assert (!compute_in_loop);
   9658 		}
   9659 	    }
   9660 	  else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   9661 	    {
   9662 	      vect_get_gather_scatter_ops (loop_vinfo, loop, stmt_info,
   9663 					   slp_node, &gs_info, &dataref_ptr,
   9664 					   &vec_offsets);
   9665 	    }
   9666 	  else
   9667 	    dataref_ptr
   9668 	      = vect_create_data_ref_ptr (vinfo, first_stmt_info, aggr_type,
   9669 					  at_loop,
   9670 					  offset, &dummy, gsi, &ptr_incr,
   9671 					  simd_lane_access_p, bump);
   9672 	  if (mask)
   9673 	    vec_mask = vec_masks[0];
   9674 	}
   9675       else
   9676 	{
   9677 	  if (dataref_offset)
   9678 	    dataref_offset = int_const_binop (PLUS_EXPR, dataref_offset,
   9679 					      bump);
   9680 	  else if (!STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   9681 	    dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr, gsi,
   9682 					   stmt_info, bump);
   9683 	  if (mask)
   9684 	    vec_mask = vec_masks[j];
   9685 	}
   9686 
   9687       if (grouped_load || slp_perm)
   9688 	dr_chain.create (vec_num);
   9689 
   9690       gimple *new_stmt = NULL;
   9691       if (memory_access_type == VMAT_LOAD_STORE_LANES)
   9692 	{
   9693 	  tree vec_array;
   9694 
   9695 	  vec_array = create_vector_array (vectype, vec_num);
   9696 
   9697 	  tree final_mask = NULL_TREE;
   9698 	  if (loop_masks)
   9699 	    final_mask = vect_get_loop_mask (gsi, loop_masks, ncopies,
   9700 					     vectype, j);
   9701 	  if (vec_mask)
   9702 	    final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
   9703 					   final_mask, vec_mask, gsi);
   9704 
   9705 	  gcall *call;
   9706 	  if (final_mask)
   9707 	    {
   9708 	      /* Emit:
   9709 		   VEC_ARRAY = MASK_LOAD_LANES (DATAREF_PTR, ALIAS_PTR,
   9710 		                                VEC_MASK).  */
   9711 	      unsigned int align = TYPE_ALIGN (TREE_TYPE (vectype));
   9712 	      tree alias_ptr = build_int_cst (ref_type, align);
   9713 	      call = gimple_build_call_internal (IFN_MASK_LOAD_LANES, 3,
   9714 						 dataref_ptr, alias_ptr,
   9715 						 final_mask);
   9716 	    }
   9717 	  else
   9718 	    {
   9719 	      /* Emit:
   9720 		   VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]).  */
   9721 	      data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type);
   9722 	      call = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref);
   9723 	    }
   9724 	  gimple_call_set_lhs (call, vec_array);
   9725 	  gimple_call_set_nothrow (call, true);
   9726 	  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
   9727 	  new_stmt = call;
   9728 
   9729 	  /* Extract each vector into an SSA_NAME.  */
   9730 	  for (i = 0; i < vec_num; i++)
   9731 	    {
   9732 	      new_temp = read_vector_array (vinfo, stmt_info, gsi, scalar_dest,
   9733 					    vec_array, i);
   9734 	      dr_chain.quick_push (new_temp);
   9735 	    }
   9736 
   9737 	  /* Record the mapping between SSA_NAMEs and statements.  */
   9738 	  vect_record_grouped_load_vectors (vinfo, stmt_info, dr_chain);
   9739 
   9740 	  /* Record that VEC_ARRAY is now dead.  */
   9741 	  vect_clobber_variable (vinfo, stmt_info, gsi, vec_array);
   9742 	}
   9743       else
   9744 	{
   9745 	  for (i = 0; i < vec_num; i++)
   9746 	    {
   9747 	      tree final_mask = NULL_TREE;
   9748 	      if (loop_masks
   9749 		  && memory_access_type != VMAT_INVARIANT)
   9750 		final_mask = vect_get_loop_mask (gsi, loop_masks,
   9751 						 vec_num * ncopies,
   9752 						 vectype, vec_num * j + i);
   9753 	      if (vec_mask)
   9754 		final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
   9755 					       final_mask, vec_mask, gsi);
   9756 
   9757 	      if (i > 0 && !STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   9758 		dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr,
   9759 					       gsi, stmt_info, bump);
   9760 
   9761 	      /* 2. Create the vector-load in the loop.  */
   9762 	      switch (alignment_support_scheme)
   9763 		{
   9764 		case dr_aligned:
   9765 		case dr_unaligned_supported:
   9766 		  {
   9767 		    unsigned int misalign;
   9768 		    unsigned HOST_WIDE_INT align;
   9769 
   9770 		    if (memory_access_type == VMAT_GATHER_SCATTER
   9771 			&& gs_info.ifn != IFN_LAST)
   9772 		      {
   9773 			if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
   9774 			  vec_offset = vec_offsets[vec_num * j + i];
   9775 			tree zero = build_zero_cst (vectype);
   9776 			tree scale = size_int (gs_info.scale);
   9777 			gcall *call;
   9778 			if (final_mask)
   9779 			  call = gimple_build_call_internal
   9780 			    (IFN_MASK_GATHER_LOAD, 5, dataref_ptr,
   9781 			     vec_offset, scale, zero, final_mask);
   9782 			else
   9783 			  call = gimple_build_call_internal
   9784 			    (IFN_GATHER_LOAD, 4, dataref_ptr,
   9785 			     vec_offset, scale, zero);
   9786 			gimple_call_set_nothrow (call, true);
   9787 			new_stmt = call;
   9788 			data_ref = NULL_TREE;
   9789 			break;
   9790 		      }
   9791 		    else if (memory_access_type == VMAT_GATHER_SCATTER)
   9792 		      {
   9793 			/* Emulated gather-scatter.  */
   9794 			gcc_assert (!final_mask);
   9795 			unsigned HOST_WIDE_INT const_nunits
   9796 			  = nunits.to_constant ();
   9797 			unsigned HOST_WIDE_INT const_offset_nunits
   9798 			  = TYPE_VECTOR_SUBPARTS (gs_info.offset_vectype)
   9799 			      .to_constant ();
   9800 			vec<constructor_elt, va_gc> *ctor_elts;
   9801 			vec_alloc (ctor_elts, const_nunits);
   9802 			gimple_seq stmts = NULL;
   9803 			/* We support offset vectors with more elements
   9804 			   than the data vector for now.  */
   9805 			unsigned HOST_WIDE_INT factor
   9806 			  = const_offset_nunits / const_nunits;
   9807 			vec_offset = vec_offsets[j / factor];
   9808 			unsigned elt_offset = (j % factor) * const_nunits;
   9809 			tree idx_type = TREE_TYPE (TREE_TYPE (vec_offset));
   9810 			tree scale = size_int (gs_info.scale);
   9811 			align
   9812 			  = get_object_alignment (DR_REF (first_dr_info->dr));
   9813 			tree ltype = build_aligned_type (TREE_TYPE (vectype),
   9814 							 align);
   9815 			for (unsigned k = 0; k < const_nunits; ++k)
   9816 			  {
   9817 			    tree boff = size_binop (MULT_EXPR,
   9818 						    TYPE_SIZE (idx_type),
   9819 						    bitsize_int
   9820 						      (k + elt_offset));
   9821 			    tree idx = gimple_build (&stmts, BIT_FIELD_REF,
   9822 						     idx_type, vec_offset,
   9823 						     TYPE_SIZE (idx_type),
   9824 						     boff);
   9825 			    idx = gimple_convert (&stmts, sizetype, idx);
   9826 			    idx = gimple_build (&stmts, MULT_EXPR,
   9827 						sizetype, idx, scale);
   9828 			    tree ptr = gimple_build (&stmts, PLUS_EXPR,
   9829 						     TREE_TYPE (dataref_ptr),
   9830 						     dataref_ptr, idx);
   9831 			    ptr = gimple_convert (&stmts, ptr_type_node, ptr);
   9832 			    tree elt = make_ssa_name (TREE_TYPE (vectype));
   9833 			    tree ref = build2 (MEM_REF, ltype, ptr,
   9834 					       build_int_cst (ref_type, 0));
   9835 			    new_stmt = gimple_build_assign (elt, ref);
   9836 			    gimple_seq_add_stmt (&stmts, new_stmt);
   9837 			    CONSTRUCTOR_APPEND_ELT (ctor_elts, NULL_TREE, elt);
   9838 			  }
   9839 			gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
   9840 			new_stmt = gimple_build_assign (NULL_TREE,
   9841 							build_constructor
   9842 							  (vectype, ctor_elts));
   9843 			data_ref = NULL_TREE;
   9844 			break;
   9845 		      }
   9846 
   9847 		    align =
   9848 		      known_alignment (DR_TARGET_ALIGNMENT (first_dr_info));
   9849 		    if (alignment_support_scheme == dr_aligned)
   9850 		      misalign = 0;
   9851 		    else if (misalignment == DR_MISALIGNMENT_UNKNOWN)
   9852 		      {
   9853 			align = dr_alignment
   9854 			  (vect_dr_behavior (vinfo, first_dr_info));
   9855 			misalign = 0;
   9856 		      }
   9857 		    else
   9858 		      misalign = misalignment;
   9859 		    if (dataref_offset == NULL_TREE
   9860 			&& TREE_CODE (dataref_ptr) == SSA_NAME)
   9861 		      set_ptr_info_alignment (get_ptr_info (dataref_ptr),
   9862 					      align, misalign);
   9863 		    align = least_bit_hwi (misalign | align);
   9864 
   9865 		    if (final_mask)
   9866 		      {
   9867 			tree ptr = build_int_cst (ref_type,
   9868 						  align * BITS_PER_UNIT);
   9869 			gcall *call
   9870 			  = gimple_build_call_internal (IFN_MASK_LOAD, 3,
   9871 							dataref_ptr, ptr,
   9872 							final_mask);
   9873 			gimple_call_set_nothrow (call, true);
   9874 			new_stmt = call;
   9875 			data_ref = NULL_TREE;
   9876 		      }
   9877 		    else if (loop_lens && memory_access_type != VMAT_INVARIANT)
   9878 		      {
   9879 			tree final_len
   9880 			  = vect_get_loop_len (loop_vinfo, loop_lens,
   9881 					       vec_num * ncopies,
   9882 					       vec_num * j + i);
   9883 			tree ptr = build_int_cst (ref_type,
   9884 						  align * BITS_PER_UNIT);
   9885 
   9886 			machine_mode vmode = TYPE_MODE (vectype);
   9887 			opt_machine_mode new_ovmode
   9888 			  = get_len_load_store_mode (vmode, true);
   9889 			machine_mode new_vmode = new_ovmode.require ();
   9890 			tree qi_type = unsigned_intQI_type_node;
   9891 
   9892 			signed char biasval =
   9893 			  LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
   9894 
   9895 			tree bias = build_int_cst (intQI_type_node, biasval);
   9896 
   9897 			gcall *call
   9898 			  = gimple_build_call_internal (IFN_LEN_LOAD, 4,
   9899 							dataref_ptr, ptr,
   9900 							final_len, bias);
   9901 			gimple_call_set_nothrow (call, true);
   9902 			new_stmt = call;
   9903 			data_ref = NULL_TREE;
   9904 
   9905 			/* Need conversion if it's wrapped with VnQI.  */
   9906 			if (vmode != new_vmode)
   9907 			  {
   9908 			    tree new_vtype
   9909 			      = build_vector_type_for_mode (qi_type, new_vmode);
   9910 			    tree var = vect_get_new_ssa_name (new_vtype,
   9911 							      vect_simple_var);
   9912 			    gimple_set_lhs (call, var);
   9913 			    vect_finish_stmt_generation (vinfo, stmt_info, call,
   9914 							 gsi);
   9915 			    tree op = build1 (VIEW_CONVERT_EXPR, vectype, var);
   9916 			    new_stmt
   9917 			      = gimple_build_assign (vec_dest,
   9918 						     VIEW_CONVERT_EXPR, op);
   9919 			  }
   9920 		      }
   9921 		    else
   9922 		      {
   9923 			tree ltype = vectype;
   9924 			tree new_vtype = NULL_TREE;
   9925 			unsigned HOST_WIDE_INT gap
   9926 			  = DR_GROUP_GAP (first_stmt_info);
   9927 			unsigned int vect_align
   9928 			  = vect_known_alignment_in_bytes (first_dr_info,
   9929 							   vectype);
   9930 			unsigned int scalar_dr_size
   9931 			  = vect_get_scalar_dr_size (first_dr_info);
   9932 			/* If there's no peeling for gaps but we have a gap
   9933 			   with slp loads then load the lower half of the
   9934 			   vector only.  See get_group_load_store_type for
   9935 			   when we apply this optimization.  */
   9936 			if (slp
   9937 			    && loop_vinfo
   9938 			    && !LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)
   9939 			    && gap != 0
   9940 			    && known_eq (nunits, (group_size - gap) * 2)
   9941 			    && known_eq (nunits, group_size)
   9942 			    && gap >= (vect_align / scalar_dr_size))
   9943 			  {
   9944 			    tree half_vtype;
   9945 			    new_vtype
   9946 			      = vector_vector_composition_type (vectype, 2,
   9947 								&half_vtype);
   9948 			    if (new_vtype != NULL_TREE)
   9949 			      ltype = half_vtype;
   9950 			  }
   9951 			tree offset
   9952 			  = (dataref_offset ? dataref_offset
   9953 					    : build_int_cst (ref_type, 0));
   9954 			if (ltype != vectype
   9955 			    && memory_access_type == VMAT_CONTIGUOUS_REVERSE)
   9956 			  {
   9957 			    unsigned HOST_WIDE_INT gap_offset
   9958 			      = gap * tree_to_uhwi (TYPE_SIZE_UNIT (elem_type));
   9959 			    tree gapcst = build_int_cst (ref_type, gap_offset);
   9960 			    offset = size_binop (PLUS_EXPR, offset, gapcst);
   9961 			  }
   9962 			data_ref
   9963 			  = fold_build2 (MEM_REF, ltype, dataref_ptr, offset);
   9964 			if (alignment_support_scheme == dr_aligned)
   9965 			  ;
   9966 			else
   9967 			  TREE_TYPE (data_ref)
   9968 			    = build_aligned_type (TREE_TYPE (data_ref),
   9969 						  align * BITS_PER_UNIT);
   9970 			if (ltype != vectype)
   9971 			  {
   9972 			    vect_copy_ref_info (data_ref,
   9973 						DR_REF (first_dr_info->dr));
   9974 			    tree tem = make_ssa_name (ltype);
   9975 			    new_stmt = gimple_build_assign (tem, data_ref);
   9976 			    vect_finish_stmt_generation (vinfo, stmt_info,
   9977 							 new_stmt, gsi);
   9978 			    data_ref = NULL;
   9979 			    vec<constructor_elt, va_gc> *v;
   9980 			    vec_alloc (v, 2);
   9981 			    if (memory_access_type == VMAT_CONTIGUOUS_REVERSE)
   9982 			      {
   9983 				CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
   9984 							build_zero_cst (ltype));
   9985 				CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tem);
   9986 			      }
   9987 			    else
   9988 			      {
   9989 				CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tem);
   9990 				CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
   9991 							build_zero_cst (ltype));
   9992 			      }
   9993 			    gcc_assert (new_vtype != NULL_TREE);
   9994 			    if (new_vtype == vectype)
   9995 			      new_stmt = gimple_build_assign (
   9996 				vec_dest, build_constructor (vectype, v));
   9997 			    else
   9998 			      {
   9999 				tree new_vname = make_ssa_name (new_vtype);
   10000 				new_stmt = gimple_build_assign (
   10001 				  new_vname, build_constructor (new_vtype, v));
   10002 				vect_finish_stmt_generation (vinfo, stmt_info,
   10003 							     new_stmt, gsi);
   10004 				new_stmt = gimple_build_assign (
   10005 				  vec_dest, build1 (VIEW_CONVERT_EXPR, vectype,
   10006 						    new_vname));
   10007 			      }
   10008 			  }
   10009 		      }
   10010 		    break;
   10011 		  }
   10012 		case dr_explicit_realign:
   10013 		  {
   10014 		    tree ptr, bump;
   10015 
   10016 		    tree vs = size_int (TYPE_VECTOR_SUBPARTS (vectype));
   10017 
   10018 		    if (compute_in_loop)
   10019 		      msq = vect_setup_realignment (vinfo, first_stmt_info, gsi,
   10020 						    &realignment_token,
   10021 						    dr_explicit_realign,
   10022 						    dataref_ptr, NULL);
   10023 
   10024 		    if (TREE_CODE (dataref_ptr) == SSA_NAME)
   10025 		      ptr = copy_ssa_name (dataref_ptr);
   10026 		    else
   10027 		      ptr = make_ssa_name (TREE_TYPE (dataref_ptr));
   10028 		    // For explicit realign the target alignment should be
   10029 		    // known at compile time.
   10030 		    unsigned HOST_WIDE_INT align =
   10031 		      DR_TARGET_ALIGNMENT (first_dr_info).to_constant ();
   10032 		    new_stmt = gimple_build_assign
   10033 				 (ptr, BIT_AND_EXPR, dataref_ptr,
   10034 				  build_int_cst
   10035 				  (TREE_TYPE (dataref_ptr),
   10036 				   -(HOST_WIDE_INT) align));
   10037 		    vect_finish_stmt_generation (vinfo, stmt_info,
   10038 						 new_stmt, gsi);
   10039 		    data_ref
   10040 		      = build2 (MEM_REF, vectype, ptr,
   10041 				build_int_cst (ref_type, 0));
   10042 		    vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
   10043 		    vec_dest = vect_create_destination_var (scalar_dest,
   10044 							    vectype);
   10045 		    new_stmt = gimple_build_assign (vec_dest, data_ref);
   10046 		    new_temp = make_ssa_name (vec_dest, new_stmt);
   10047 		    gimple_assign_set_lhs (new_stmt, new_temp);
   10048 		    gimple_move_vops (new_stmt, stmt_info->stmt);
   10049 		    vect_finish_stmt_generation (vinfo, stmt_info,
   10050 						 new_stmt, gsi);
   10051 		    msq = new_temp;
   10052 
   10053 		    bump = size_binop (MULT_EXPR, vs,
   10054 				       TYPE_SIZE_UNIT (elem_type));
   10055 		    bump = size_binop (MINUS_EXPR, bump, size_one_node);
   10056 		    ptr = bump_vector_ptr (vinfo, dataref_ptr, NULL, gsi,
   10057 					   stmt_info, bump);
   10058 		    new_stmt = gimple_build_assign
   10059 				 (NULL_TREE, BIT_AND_EXPR, ptr,
   10060 				  build_int_cst
   10061 				  (TREE_TYPE (ptr), -(HOST_WIDE_INT) align));
   10062 		    ptr = copy_ssa_name (ptr, new_stmt);
   10063 		    gimple_assign_set_lhs (new_stmt, ptr);
   10064 		    vect_finish_stmt_generation (vinfo, stmt_info,
   10065 						 new_stmt, gsi);
   10066 		    data_ref
   10067 		      = build2 (MEM_REF, vectype, ptr,
   10068 				build_int_cst (ref_type, 0));
   10069 		    break;
   10070 		  }
   10071 		case dr_explicit_realign_optimized:
   10072 		  {
   10073 		    if (TREE_CODE (dataref_ptr) == SSA_NAME)
   10074 		      new_temp = copy_ssa_name (dataref_ptr);
   10075 		    else
   10076 		      new_temp = make_ssa_name (TREE_TYPE (dataref_ptr));
   10077 		    // We should only be doing this if we know the target
   10078 		    // alignment at compile time.
   10079 		    unsigned HOST_WIDE_INT align =
   10080 		      DR_TARGET_ALIGNMENT (first_dr_info).to_constant ();
   10081 		    new_stmt = gimple_build_assign
   10082 		      (new_temp, BIT_AND_EXPR, dataref_ptr,
   10083 		       build_int_cst (TREE_TYPE (dataref_ptr),
   10084 				     -(HOST_WIDE_INT) align));
   10085 		    vect_finish_stmt_generation (vinfo, stmt_info,
   10086 						 new_stmt, gsi);
   10087 		    data_ref
   10088 		      = build2 (MEM_REF, vectype, new_temp,
   10089 				build_int_cst (ref_type, 0));
   10090 		    break;
   10091 		  }
   10092 		default:
   10093 		  gcc_unreachable ();
   10094 		}
   10095 	      vec_dest = vect_create_destination_var (scalar_dest, vectype);
   10096 	      /* DATA_REF is null if we've already built the statement.  */
   10097 	      if (data_ref)
   10098 		{
   10099 		  vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
   10100 		  new_stmt = gimple_build_assign (vec_dest, data_ref);
   10101 		}
   10102 	      new_temp = make_ssa_name (vec_dest, new_stmt);
   10103 	      gimple_set_lhs (new_stmt, new_temp);
   10104 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   10105 
   10106 	      /* 3. Handle explicit realignment if necessary/supported.
   10107 		 Create in loop:
   10108 		   vec_dest = realign_load (msq, lsq, realignment_token)  */
   10109 	      if (alignment_support_scheme == dr_explicit_realign_optimized
   10110 		  || alignment_support_scheme == dr_explicit_realign)
   10111 		{
   10112 		  lsq = gimple_assign_lhs (new_stmt);
   10113 		  if (!realignment_token)
   10114 		    realignment_token = dataref_ptr;
   10115 		  vec_dest = vect_create_destination_var (scalar_dest, vectype);
   10116 		  new_stmt = gimple_build_assign (vec_dest, REALIGN_LOAD_EXPR,
   10117 						  msq, lsq, realignment_token);
   10118 		  new_temp = make_ssa_name (vec_dest, new_stmt);
   10119 		  gimple_assign_set_lhs (new_stmt, new_temp);
   10120 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   10121 
   10122 		  if (alignment_support_scheme == dr_explicit_realign_optimized)
   10123 		    {
   10124 		      gcc_assert (phi);
   10125 		      if (i == vec_num - 1 && j == ncopies - 1)
   10126 			add_phi_arg (phi, lsq,
   10127 				     loop_latch_edge (containing_loop),
   10128 				     UNKNOWN_LOCATION);
   10129 		      msq = lsq;
   10130 		    }
   10131 		}
   10132 
   10133 	      if (memory_access_type == VMAT_CONTIGUOUS_REVERSE)
   10134 		{
   10135 		  tree perm_mask = perm_mask_for_reverse (vectype);
   10136 		  new_temp = permute_vec_elements (vinfo, new_temp, new_temp,
   10137 						   perm_mask, stmt_info, gsi);
   10138 		  new_stmt = SSA_NAME_DEF_STMT (new_temp);
   10139 		}
   10140 
   10141 	      /* Collect vector loads and later create their permutation in
   10142 		 vect_transform_grouped_load ().  */
   10143 	      if (grouped_load || slp_perm)
   10144 		dr_chain.quick_push (new_temp);
   10145 
   10146 	      /* Store vector loads in the corresponding SLP_NODE.  */
   10147 	      if (slp && !slp_perm)
   10148 		SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   10149 
   10150 	      /* With SLP permutation we load the gaps as well, without
   10151 	         we need to skip the gaps after we manage to fully load
   10152 		 all elements.  group_gap_adj is DR_GROUP_SIZE here.  */
   10153 	      group_elt += nunits;
   10154 	      if (maybe_ne (group_gap_adj, 0U)
   10155 		  && !slp_perm
   10156 		  && known_eq (group_elt, group_size - group_gap_adj))
   10157 		{
   10158 		  poly_wide_int bump_val
   10159 		    = (wi::to_wide (TYPE_SIZE_UNIT (elem_type))
   10160 		       * group_gap_adj);
   10161 		  if (tree_int_cst_sgn
   10162 			(vect_dr_behavior (vinfo, dr_info)->step) == -1)
   10163 		    bump_val = -bump_val;
   10164 		  tree bump = wide_int_to_tree (sizetype, bump_val);
   10165 		  dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr,
   10166 						 gsi, stmt_info, bump);
   10167 		  group_elt = 0;
   10168 		}
   10169 	    }
   10170 	  /* Bump the vector pointer to account for a gap or for excess
   10171 	     elements loaded for a permuted SLP load.  */
   10172 	  if (maybe_ne (group_gap_adj, 0U) && slp_perm)
   10173 	    {
   10174 	      poly_wide_int bump_val
   10175 		= (wi::to_wide (TYPE_SIZE_UNIT (elem_type))
   10176 		   * group_gap_adj);
   10177 	      if (tree_int_cst_sgn
   10178 		    (vect_dr_behavior (vinfo, dr_info)->step) == -1)
   10179 		bump_val = -bump_val;
   10180 	      tree bump = wide_int_to_tree (sizetype, bump_val);
   10181 	      dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr, gsi,
   10182 					     stmt_info, bump);
   10183 	    }
   10184 	}
   10185 
   10186       if (slp && !slp_perm)
   10187 	continue;
   10188 
   10189       if (slp_perm)
   10190         {
   10191 	  unsigned n_perms;
   10192 	  /* For SLP we know we've seen all possible uses of dr_chain so
   10193 	     direct vect_transform_slp_perm_load to DCE the unused parts.
   10194 	     ???  This is a hack to prevent compile-time issues as seen
   10195 	     in PR101120 and friends.  */
   10196 	  bool ok = vect_transform_slp_perm_load (vinfo, slp_node, dr_chain,
   10197 						  gsi, vf, false, &n_perms,
   10198 						  nullptr, true);
   10199 	  gcc_assert (ok);
   10200         }
   10201       else
   10202         {
   10203           if (grouped_load)
   10204   	    {
   10205 	      if (memory_access_type != VMAT_LOAD_STORE_LANES)
   10206 		vect_transform_grouped_load (vinfo, stmt_info, dr_chain,
   10207 					     group_size, gsi);
   10208 	      *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   10209 	    }
   10210           else
   10211 	    {
   10212 	      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   10213 	    }
   10214         }
   10215       dr_chain.release ();
   10216     }
   10217   if (!slp)
   10218     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   10219 
   10220   return true;
   10221 }
   10222 
   10223 /* Function vect_is_simple_cond.
   10224 
   10225    Input:
   10226    LOOP - the loop that is being vectorized.
   10227    COND - Condition that is checked for simple use.
   10228 
   10229    Output:
   10230    *COMP_VECTYPE - the vector type for the comparison.
   10231    *DTS - The def types for the arguments of the comparison
   10232 
   10233    Returns whether a COND can be vectorized.  Checks whether
   10234    condition operands are supportable using vec_is_simple_use.  */
   10235 
   10236 static bool
   10237 vect_is_simple_cond (tree cond, vec_info *vinfo, stmt_vec_info stmt_info,
   10238 		     slp_tree slp_node, tree *comp_vectype,
   10239 		     enum vect_def_type *dts, tree vectype)
   10240 {
   10241   tree lhs, rhs;
   10242   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
   10243   slp_tree slp_op;
   10244 
   10245   /* Mask case.  */
   10246   if (TREE_CODE (cond) == SSA_NAME
   10247       && VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (cond)))
   10248     {
   10249       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0, &cond,
   10250 			       &slp_op, &dts[0], comp_vectype)
   10251 	  || !*comp_vectype
   10252 	  || !VECTOR_BOOLEAN_TYPE_P (*comp_vectype))
   10253 	return false;
   10254       return true;
   10255     }
   10256 
   10257   if (!COMPARISON_CLASS_P (cond))
   10258     return false;
   10259 
   10260   lhs = TREE_OPERAND (cond, 0);
   10261   rhs = TREE_OPERAND (cond, 1);
   10262 
   10263   if (TREE_CODE (lhs) == SSA_NAME)
   10264     {
   10265       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0,
   10266 			       &lhs, &slp_op, &dts[0], &vectype1))
   10267 	return false;
   10268     }
   10269   else if (TREE_CODE (lhs) == INTEGER_CST || TREE_CODE (lhs) == REAL_CST
   10270 	   || TREE_CODE (lhs) == FIXED_CST)
   10271     dts[0] = vect_constant_def;
   10272   else
   10273     return false;
   10274 
   10275   if (TREE_CODE (rhs) == SSA_NAME)
   10276     {
   10277       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1,
   10278 			       &rhs, &slp_op, &dts[1], &vectype2))
   10279 	return false;
   10280     }
   10281   else if (TREE_CODE (rhs) == INTEGER_CST || TREE_CODE (rhs) == REAL_CST
   10282 	   || TREE_CODE (rhs) == FIXED_CST)
   10283     dts[1] = vect_constant_def;
   10284   else
   10285     return false;
   10286 
   10287   if (vectype1 && vectype2
   10288       && maybe_ne (TYPE_VECTOR_SUBPARTS (vectype1),
   10289 		   TYPE_VECTOR_SUBPARTS (vectype2)))
   10290     return false;
   10291 
   10292   *comp_vectype = vectype1 ? vectype1 : vectype2;
   10293   /* Invariant comparison.  */
   10294   if (! *comp_vectype)
   10295     {
   10296       tree scalar_type = TREE_TYPE (lhs);
   10297       if (VECT_SCALAR_BOOLEAN_TYPE_P (scalar_type))
   10298 	*comp_vectype = truth_type_for (vectype);
   10299       else
   10300 	{
   10301 	  /* If we can widen the comparison to match vectype do so.  */
   10302 	  if (INTEGRAL_TYPE_P (scalar_type)
   10303 	      && !slp_node
   10304 	      && tree_int_cst_lt (TYPE_SIZE (scalar_type),
   10305 				  TYPE_SIZE (TREE_TYPE (vectype))))
   10306 	    scalar_type = build_nonstandard_integer_type
   10307 	      (vector_element_bits (vectype), TYPE_UNSIGNED (scalar_type));
   10308 	  *comp_vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
   10309 						       slp_node);
   10310 	}
   10311     }
   10312 
   10313   return true;
   10314 }
   10315 
   10316 /* vectorizable_condition.
   10317 
   10318    Check if STMT_INFO is conditional modify expression that can be vectorized.
   10319    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   10320    stmt using VEC_COND_EXPR  to replace it, put it in VEC_STMT, and insert it
   10321    at GSI.
   10322 
   10323    When STMT_INFO is vectorized as a nested cycle, for_reduction is true.
   10324 
   10325    Return true if STMT_INFO is vectorizable in this way.  */
   10326 
   10327 static bool
   10328 vectorizable_condition (vec_info *vinfo,
   10329 			stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   10330 			gimple **vec_stmt,
   10331 			slp_tree slp_node, stmt_vector_for_cost *cost_vec)
   10332 {
   10333   tree scalar_dest = NULL_TREE;
   10334   tree vec_dest = NULL_TREE;
   10335   tree cond_expr, cond_expr0 = NULL_TREE, cond_expr1 = NULL_TREE;
   10336   tree then_clause, else_clause;
   10337   tree comp_vectype = NULL_TREE;
   10338   tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
   10339   tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
   10340   tree vec_compare;
   10341   tree new_temp;
   10342   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   10343   enum vect_def_type dts[4]
   10344     = {vect_unknown_def_type, vect_unknown_def_type,
   10345        vect_unknown_def_type, vect_unknown_def_type};
   10346   int ndts = 4;
   10347   int ncopies;
   10348   int vec_num;
   10349   enum tree_code code, cond_code, bitop1 = NOP_EXPR, bitop2 = NOP_EXPR;
   10350   int i;
   10351   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   10352   vec<tree> vec_oprnds0 = vNULL;
   10353   vec<tree> vec_oprnds1 = vNULL;
   10354   vec<tree> vec_oprnds2 = vNULL;
   10355   vec<tree> vec_oprnds3 = vNULL;
   10356   tree vec_cmp_type;
   10357   bool masked = false;
   10358 
   10359   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   10360     return false;
   10361 
   10362   /* Is vectorizable conditional operation?  */
   10363   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
   10364   if (!stmt)
   10365     return false;
   10366 
   10367   code = gimple_assign_rhs_code (stmt);
   10368   if (code != COND_EXPR)
   10369     return false;
   10370 
   10371   stmt_vec_info reduc_info = NULL;
   10372   int reduc_index = -1;
   10373   vect_reduction_type reduction_type = TREE_CODE_REDUCTION;
   10374   bool for_reduction
   10375     = STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info)) != NULL;
   10376   if (for_reduction)
   10377     {
   10378       if (slp_node)
   10379 	return false;
   10380       reduc_info = info_for_reduction (vinfo, stmt_info);
   10381       reduction_type = STMT_VINFO_REDUC_TYPE (reduc_info);
   10382       reduc_index = STMT_VINFO_REDUC_IDX (stmt_info);
   10383       gcc_assert (reduction_type != EXTRACT_LAST_REDUCTION
   10384 		  || reduc_index != -1);
   10385     }
   10386   else
   10387     {
   10388       if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
   10389 	return false;
   10390     }
   10391 
   10392   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   10393   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
   10394 
   10395   if (slp_node)
   10396     {
   10397       ncopies = 1;
   10398       vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
   10399     }
   10400   else
   10401     {
   10402       ncopies = vect_get_num_copies (loop_vinfo, vectype);
   10403       vec_num = 1;
   10404     }
   10405 
   10406   gcc_assert (ncopies >= 1);
   10407   if (for_reduction && ncopies > 1)
   10408     return false; /* FORNOW */
   10409 
   10410   cond_expr = gimple_assign_rhs1 (stmt);
   10411 
   10412   if (!vect_is_simple_cond (cond_expr, vinfo, stmt_info, slp_node,
   10413 			    &comp_vectype, &dts[0], vectype)
   10414       || !comp_vectype)
   10415     return false;
   10416 
   10417   unsigned op_adjust = COMPARISON_CLASS_P (cond_expr) ? 1 : 0;
   10418   slp_tree then_slp_node, else_slp_node;
   10419   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1 + op_adjust,
   10420 			   &then_clause, &then_slp_node, &dts[2], &vectype1))
   10421     return false;
   10422   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 2 + op_adjust,
   10423 			   &else_clause, &else_slp_node, &dts[3], &vectype2))
   10424     return false;
   10425 
   10426   if (vectype1 && !useless_type_conversion_p (vectype, vectype1))
   10427     return false;
   10428 
   10429   if (vectype2 && !useless_type_conversion_p (vectype, vectype2))
   10430     return false;
   10431 
   10432   masked = !COMPARISON_CLASS_P (cond_expr);
   10433   vec_cmp_type = truth_type_for (comp_vectype);
   10434 
   10435   if (vec_cmp_type == NULL_TREE)
   10436     return false;
   10437 
   10438   cond_code = TREE_CODE (cond_expr);
   10439   if (!masked)
   10440     {
   10441       cond_expr0 = TREE_OPERAND (cond_expr, 0);
   10442       cond_expr1 = TREE_OPERAND (cond_expr, 1);
   10443     }
   10444 
   10445   /* For conditional reductions, the "then" value needs to be the candidate
   10446      value calculated by this iteration while the "else" value needs to be
   10447      the result carried over from previous iterations.  If the COND_EXPR
   10448      is the other way around, we need to swap it.  */
   10449   bool must_invert_cmp_result = false;
   10450   if (reduction_type == EXTRACT_LAST_REDUCTION && reduc_index == 1)
   10451     {
   10452       if (masked)
   10453 	must_invert_cmp_result = true;
   10454       else
   10455 	{
   10456 	  bool honor_nans = HONOR_NANS (TREE_TYPE (cond_expr0));
   10457 	  tree_code new_code = invert_tree_comparison (cond_code, honor_nans);
   10458 	  if (new_code == ERROR_MARK)
   10459 	    must_invert_cmp_result = true;
   10460 	  else
   10461 	    {
   10462 	      cond_code = new_code;
   10463 	      /* Make sure we don't accidentally use the old condition.  */
   10464 	      cond_expr = NULL_TREE;
   10465 	    }
   10466 	}
   10467       std::swap (then_clause, else_clause);
   10468     }
   10469 
   10470   if (!masked && VECTOR_BOOLEAN_TYPE_P (comp_vectype))
   10471     {
   10472       /* Boolean values may have another representation in vectors
   10473 	 and therefore we prefer bit operations over comparison for
   10474 	 them (which also works for scalar masks).  We store opcodes
   10475 	 to use in bitop1 and bitop2.  Statement is vectorized as
   10476 	 BITOP2 (rhs1 BITOP1 rhs2) or rhs1 BITOP2 (BITOP1 rhs2)
   10477 	 depending on bitop1 and bitop2 arity.  */
   10478       switch (cond_code)
   10479 	{
   10480 	case GT_EXPR:
   10481 	  bitop1 = BIT_NOT_EXPR;
   10482 	  bitop2 = BIT_AND_EXPR;
   10483 	  break;
   10484 	case GE_EXPR:
   10485 	  bitop1 = BIT_NOT_EXPR;
   10486 	  bitop2 = BIT_IOR_EXPR;
   10487 	  break;
   10488 	case LT_EXPR:
   10489 	  bitop1 = BIT_NOT_EXPR;
   10490 	  bitop2 = BIT_AND_EXPR;
   10491 	  std::swap (cond_expr0, cond_expr1);
   10492 	  break;
   10493 	case LE_EXPR:
   10494 	  bitop1 = BIT_NOT_EXPR;
   10495 	  bitop2 = BIT_IOR_EXPR;
   10496 	  std::swap (cond_expr0, cond_expr1);
   10497 	  break;
   10498 	case NE_EXPR:
   10499 	  bitop1 = BIT_XOR_EXPR;
   10500 	  break;
   10501 	case EQ_EXPR:
   10502 	  bitop1 = BIT_XOR_EXPR;
   10503 	  bitop2 = BIT_NOT_EXPR;
   10504 	  break;
   10505 	default:
   10506 	  return false;
   10507 	}
   10508       cond_code = SSA_NAME;
   10509     }
   10510 
   10511   if (TREE_CODE_CLASS (cond_code) == tcc_comparison
   10512       && reduction_type == EXTRACT_LAST_REDUCTION
   10513       && !expand_vec_cmp_expr_p (comp_vectype, vec_cmp_type, cond_code))
   10514     {
   10515       if (dump_enabled_p ())
   10516 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   10517 			 "reduction comparison operation not supported.\n");
   10518       return false;
   10519     }
   10520 
   10521   if (!vec_stmt)
   10522     {
   10523       if (bitop1 != NOP_EXPR)
   10524 	{
   10525 	  machine_mode mode = TYPE_MODE (comp_vectype);
   10526 	  optab optab;
   10527 
   10528 	  optab = optab_for_tree_code (bitop1, comp_vectype, optab_default);
   10529 	  if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
   10530 	    return false;
   10531 
   10532 	  if (bitop2 != NOP_EXPR)
   10533 	    {
   10534 	      optab = optab_for_tree_code (bitop2, comp_vectype,
   10535 					   optab_default);
   10536 	      if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
   10537 		return false;
   10538 	    }
   10539 	}
   10540 
   10541       vect_cost_for_stmt kind = vector_stmt;
   10542       if (reduction_type == EXTRACT_LAST_REDUCTION)
   10543 	/* Count one reduction-like operation per vector.  */
   10544 	kind = vec_to_scalar;
   10545       else if (!expand_vec_cond_expr_p (vectype, comp_vectype, cond_code))
   10546 	return false;
   10547 
   10548       if (slp_node
   10549 	  && (!vect_maybe_update_slp_op_vectype
   10550 		 (SLP_TREE_CHILDREN (slp_node)[0], comp_vectype)
   10551 	      || (op_adjust == 1
   10552 		  && !vect_maybe_update_slp_op_vectype
   10553 			(SLP_TREE_CHILDREN (slp_node)[1], comp_vectype))
   10554 	      || !vect_maybe_update_slp_op_vectype (then_slp_node, vectype)
   10555 	      || !vect_maybe_update_slp_op_vectype (else_slp_node, vectype)))
   10556 	{
   10557 	  if (dump_enabled_p ())
   10558 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   10559 			     "incompatible vector types for invariants\n");
   10560 	  return false;
   10561 	}
   10562 
   10563       if (loop_vinfo && for_reduction
   10564 	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))
   10565 	{
   10566 	  if (reduction_type == EXTRACT_LAST_REDUCTION)
   10567 	    vect_record_loop_mask (loop_vinfo, &LOOP_VINFO_MASKS (loop_vinfo),
   10568 				   ncopies * vec_num, vectype, NULL);
   10569 	  /* Extra inactive lanes should be safe for vect_nested_cycle.  */
   10570 	  else if (STMT_VINFO_DEF_TYPE (reduc_info) != vect_nested_cycle)
   10571 	    {
   10572 	      if (dump_enabled_p ())
   10573 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   10574 				 "conditional reduction prevents the use"
   10575 				 " of partial vectors.\n");
   10576 	      LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
   10577 	    }
   10578 	}
   10579 
   10580       STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
   10581       vect_model_simple_cost (vinfo, stmt_info, ncopies, dts, ndts, slp_node,
   10582 			      cost_vec, kind);
   10583       return true;
   10584     }
   10585 
   10586   /* Transform.  */
   10587 
   10588   /* Handle def.  */
   10589   scalar_dest = gimple_assign_lhs (stmt);
   10590   if (reduction_type != EXTRACT_LAST_REDUCTION)
   10591     vec_dest = vect_create_destination_var (scalar_dest, vectype);
   10592 
   10593   bool swap_cond_operands = false;
   10594 
   10595   /* See whether another part of the vectorized code applies a loop
   10596      mask to the condition, or to its inverse.  */
   10597 
   10598   vec_loop_masks *masks = NULL;
   10599   if (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo))
   10600     {
   10601       if (reduction_type == EXTRACT_LAST_REDUCTION)
   10602 	masks = &LOOP_VINFO_MASKS (loop_vinfo);
   10603       else
   10604 	{
   10605 	  scalar_cond_masked_key cond (cond_expr, ncopies);
   10606 	  if (loop_vinfo->scalar_cond_masked_set.contains (cond))
   10607 	    masks = &LOOP_VINFO_MASKS (loop_vinfo);
   10608 	  else
   10609 	    {
   10610 	      bool honor_nans = HONOR_NANS (TREE_TYPE (cond.op0));
   10611 	      tree_code orig_code = cond.code;
   10612 	      cond.code = invert_tree_comparison (cond.code, honor_nans);
   10613 	      if (!masked && loop_vinfo->scalar_cond_masked_set.contains (cond))
   10614 		{
   10615 		  masks = &LOOP_VINFO_MASKS (loop_vinfo);
   10616 		  cond_code = cond.code;
   10617 		  swap_cond_operands = true;
   10618 		}
   10619 	      else
   10620 		{
   10621 		  /* Try the inverse of the current mask.  We check if the
   10622 		     inverse mask is live and if so we generate a negate of
   10623 		     the current mask such that we still honor NaNs.  */
   10624 		  cond.inverted_p = true;
   10625 		  cond.code = orig_code;
   10626 		  if (loop_vinfo->scalar_cond_masked_set.contains (cond))
   10627 		    {
   10628 		      masks = &LOOP_VINFO_MASKS (loop_vinfo);
   10629 		      cond_code = cond.code;
   10630 		      swap_cond_operands = true;
   10631 		      must_invert_cmp_result = true;
   10632 		    }
   10633 		}
   10634 	    }
   10635 	}
   10636     }
   10637 
   10638   /* Handle cond expr.  */
   10639   if (masked)
   10640     vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   10641 		       cond_expr, &vec_oprnds0, comp_vectype,
   10642 		       then_clause, &vec_oprnds2, vectype,
   10643 		       reduction_type != EXTRACT_LAST_REDUCTION
   10644 		       ? else_clause : NULL, &vec_oprnds3, vectype);
   10645   else
   10646     vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   10647 		       cond_expr0, &vec_oprnds0, comp_vectype,
   10648 		       cond_expr1, &vec_oprnds1, comp_vectype,
   10649 		       then_clause, &vec_oprnds2, vectype,
   10650 		       reduction_type != EXTRACT_LAST_REDUCTION
   10651 		       ? else_clause : NULL, &vec_oprnds3, vectype);
   10652 
   10653   /* Arguments are ready.  Create the new vector stmt.  */
   10654   FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_cond_lhs)
   10655     {
   10656       vec_then_clause = vec_oprnds2[i];
   10657       if (reduction_type != EXTRACT_LAST_REDUCTION)
   10658 	vec_else_clause = vec_oprnds3[i];
   10659 
   10660       if (swap_cond_operands)
   10661 	std::swap (vec_then_clause, vec_else_clause);
   10662 
   10663       if (masked)
   10664 	vec_compare = vec_cond_lhs;
   10665       else
   10666 	{
   10667 	  vec_cond_rhs = vec_oprnds1[i];
   10668 	  if (bitop1 == NOP_EXPR)
   10669 	    {
   10670 	      gimple_seq stmts = NULL;
   10671 	      vec_compare = gimple_build (&stmts, cond_code, vec_cmp_type,
   10672 					   vec_cond_lhs, vec_cond_rhs);
   10673 	      gsi_insert_before (gsi, stmts, GSI_SAME_STMT);
   10674 	    }
   10675 	  else
   10676 	    {
   10677 	      new_temp = make_ssa_name (vec_cmp_type);
   10678 	      gassign *new_stmt;
   10679 	      if (bitop1 == BIT_NOT_EXPR)
   10680 		new_stmt = gimple_build_assign (new_temp, bitop1,
   10681 						vec_cond_rhs);
   10682 	      else
   10683 		new_stmt
   10684 		  = gimple_build_assign (new_temp, bitop1, vec_cond_lhs,
   10685 					 vec_cond_rhs);
   10686 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   10687 	      if (bitop2 == NOP_EXPR)
   10688 		vec_compare = new_temp;
   10689 	      else if (bitop2 == BIT_NOT_EXPR)
   10690 		{
   10691 		  /* Instead of doing ~x ? y : z do x ? z : y.  */
   10692 		  vec_compare = new_temp;
   10693 		  std::swap (vec_then_clause, vec_else_clause);
   10694 		}
   10695 	      else
   10696 		{
   10697 		  vec_compare = make_ssa_name (vec_cmp_type);
   10698 		  new_stmt
   10699 		    = gimple_build_assign (vec_compare, bitop2,
   10700 					   vec_cond_lhs, new_temp);
   10701 		  vect_finish_stmt_generation (vinfo, stmt_info,
   10702 					       new_stmt, gsi);
   10703 		}
   10704 	    }
   10705 	}
   10706 
   10707       /* If we decided to apply a loop mask to the result of the vector
   10708 	 comparison, AND the comparison with the mask now.  Later passes
   10709 	 should then be able to reuse the AND results between mulitple
   10710 	 vector statements.
   10711 
   10712 	 For example:
   10713 	 for (int i = 0; i < 100; ++i)
   10714 	 x[i] = y[i] ? z[i] : 10;
   10715 
   10716 	 results in following optimized GIMPLE:
   10717 
   10718 	 mask__35.8_43 = vect__4.7_41 != { 0, ... };
   10719 	 vec_mask_and_46 = loop_mask_40 & mask__35.8_43;
   10720 	 _19 = &MEM[base: z_12(D), index: ivtmp_56, step: 4, offset: 0B];
   10721 	 vect_iftmp.11_47 = .MASK_LOAD (_19, 4B, vec_mask_and_46);
   10722 	 vect_iftmp.12_52 = VEC_COND_EXPR <vec_mask_and_46,
   10723 	 vect_iftmp.11_47, { 10, ... }>;
   10724 
   10725 	 instead of using a masked and unmasked forms of
   10726 	 vec != { 0, ... } (masked in the MASK_LOAD,
   10727 	 unmasked in the VEC_COND_EXPR).  */
   10728 
   10729       /* Force vec_compare to be an SSA_NAME rather than a comparison,
   10730 	 in cases where that's necessary.  */
   10731 
   10732       if (masks || reduction_type == EXTRACT_LAST_REDUCTION)
   10733 	{
   10734 	  if (!is_gimple_val (vec_compare))
   10735 	    {
   10736 	      tree vec_compare_name = make_ssa_name (vec_cmp_type);
   10737 	      gassign *new_stmt = gimple_build_assign (vec_compare_name,
   10738 						       vec_compare);
   10739 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   10740 	      vec_compare = vec_compare_name;
   10741 	    }
   10742 
   10743 	  if (must_invert_cmp_result)
   10744 	    {
   10745 	      tree vec_compare_name = make_ssa_name (vec_cmp_type);
   10746 	      gassign *new_stmt = gimple_build_assign (vec_compare_name,
   10747 						       BIT_NOT_EXPR,
   10748 						       vec_compare);
   10749 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   10750 	      vec_compare = vec_compare_name;
   10751 	    }
   10752 
   10753 	  if (masks)
   10754 	    {
   10755 	      tree loop_mask
   10756 		= vect_get_loop_mask (gsi, masks, vec_num * ncopies,
   10757 				      vectype, i);
   10758 	      tree tmp2 = make_ssa_name (vec_cmp_type);
   10759 	      gassign *g
   10760 		= gimple_build_assign (tmp2, BIT_AND_EXPR, vec_compare,
   10761 				       loop_mask);
   10762 	      vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
   10763 	      vec_compare = tmp2;
   10764 	    }
   10765 	}
   10766 
   10767       gimple *new_stmt;
   10768       if (reduction_type == EXTRACT_LAST_REDUCTION)
   10769 	{
   10770 	  gimple *old_stmt = vect_orig_stmt (stmt_info)->stmt;
   10771 	  tree lhs = gimple_get_lhs (old_stmt);
   10772 	  new_stmt = gimple_build_call_internal
   10773 	      (IFN_FOLD_EXTRACT_LAST, 3, else_clause, vec_compare,
   10774 	       vec_then_clause);
   10775 	  gimple_call_set_lhs (new_stmt, lhs);
   10776 	  SSA_NAME_DEF_STMT (lhs) = new_stmt;
   10777 	  if (old_stmt == gsi_stmt (*gsi))
   10778 	    vect_finish_replace_stmt (vinfo, stmt_info, new_stmt);
   10779 	  else
   10780 	    {
   10781 	      /* In this case we're moving the definition to later in the
   10782 		 block.  That doesn't matter because the only uses of the
   10783 		 lhs are in phi statements.  */
   10784 	      gimple_stmt_iterator old_gsi = gsi_for_stmt (old_stmt);
   10785 	      gsi_remove (&old_gsi, true);
   10786 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   10787 	    }
   10788 	}
   10789       else
   10790 	{
   10791 	  new_temp = make_ssa_name (vec_dest);
   10792 	  new_stmt = gimple_build_assign (new_temp, VEC_COND_EXPR, vec_compare,
   10793 					  vec_then_clause, vec_else_clause);
   10794 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   10795 	}
   10796       if (slp_node)
   10797 	SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   10798       else
   10799 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   10800     }
   10801 
   10802   if (!slp_node)
   10803     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   10804 
   10805   vec_oprnds0.release ();
   10806   vec_oprnds1.release ();
   10807   vec_oprnds2.release ();
   10808   vec_oprnds3.release ();
   10809 
   10810   return true;
   10811 }
   10812 
   10813 /* vectorizable_comparison.
   10814 
   10815    Check if STMT_INFO is comparison expression that can be vectorized.
   10816    If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
   10817    comparison, put it in VEC_STMT, and insert it at GSI.
   10818 
   10819    Return true if STMT_INFO is vectorizable in this way.  */
   10820 
   10821 static bool
   10822 vectorizable_comparison (vec_info *vinfo,
   10823 			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   10824 			 gimple **vec_stmt,
   10825 			 slp_tree slp_node, stmt_vector_for_cost *cost_vec)
   10826 {
   10827   tree lhs, rhs1, rhs2;
   10828   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
   10829   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   10830   tree vec_rhs1 = NULL_TREE, vec_rhs2 = NULL_TREE;
   10831   tree new_temp;
   10832   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   10833   enum vect_def_type dts[2] = {vect_unknown_def_type, vect_unknown_def_type};
   10834   int ndts = 2;
   10835   poly_uint64 nunits;
   10836   int ncopies;
   10837   enum tree_code code, bitop1 = NOP_EXPR, bitop2 = NOP_EXPR;
   10838   int i;
   10839   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   10840   vec<tree> vec_oprnds0 = vNULL;
   10841   vec<tree> vec_oprnds1 = vNULL;
   10842   tree mask_type;
   10843   tree mask;
   10844 
   10845   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
   10846     return false;
   10847 
   10848   if (!vectype || !VECTOR_BOOLEAN_TYPE_P (vectype))
   10849     return false;
   10850 
   10851   mask_type = vectype;
   10852   nunits = TYPE_VECTOR_SUBPARTS (vectype);
   10853 
   10854   if (slp_node)
   10855     ncopies = 1;
   10856   else
   10857     ncopies = vect_get_num_copies (loop_vinfo, vectype);
   10858 
   10859   gcc_assert (ncopies >= 1);
   10860   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
   10861     return false;
   10862 
   10863   gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
   10864   if (!stmt)
   10865     return false;
   10866 
   10867   code = gimple_assign_rhs_code (stmt);
   10868 
   10869   if (TREE_CODE_CLASS (code) != tcc_comparison)
   10870     return false;
   10871 
   10872   slp_tree slp_rhs1, slp_rhs2;
   10873   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   10874 			   0, &rhs1, &slp_rhs1, &dts[0], &vectype1))
   10875     return false;
   10876 
   10877   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
   10878 			   1, &rhs2, &slp_rhs2, &dts[1], &vectype2))
   10879     return false;
   10880 
   10881   if (vectype1 && vectype2
   10882       && maybe_ne (TYPE_VECTOR_SUBPARTS (vectype1),
   10883 		   TYPE_VECTOR_SUBPARTS (vectype2)))
   10884     return false;
   10885 
   10886   vectype = vectype1 ? vectype1 : vectype2;
   10887 
   10888   /* Invariant comparison.  */
   10889   if (!vectype)
   10890     {
   10891       if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)))
   10892 	vectype = mask_type;
   10893       else
   10894 	vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (rhs1),
   10895 					       slp_node);
   10896       if (!vectype || maybe_ne (TYPE_VECTOR_SUBPARTS (vectype), nunits))
   10897 	return false;
   10898     }
   10899   else if (maybe_ne (nunits, TYPE_VECTOR_SUBPARTS (vectype)))
   10900     return false;
   10901 
   10902   /* Can't compare mask and non-mask types.  */
   10903   if (vectype1 && vectype2
   10904       && (VECTOR_BOOLEAN_TYPE_P (vectype1) ^ VECTOR_BOOLEAN_TYPE_P (vectype2)))
   10905     return false;
   10906 
   10907   /* Boolean values may have another representation in vectors
   10908      and therefore we prefer bit operations over comparison for
   10909      them (which also works for scalar masks).  We store opcodes
   10910      to use in bitop1 and bitop2.  Statement is vectorized as
   10911        BITOP2 (rhs1 BITOP1 rhs2) or
   10912        rhs1 BITOP2 (BITOP1 rhs2)
   10913      depending on bitop1 and bitop2 arity.  */
   10914   bool swap_p = false;
   10915   if (VECTOR_BOOLEAN_TYPE_P (vectype))
   10916     {
   10917       if (code == GT_EXPR)
   10918 	{
   10919 	  bitop1 = BIT_NOT_EXPR;
   10920 	  bitop2 = BIT_AND_EXPR;
   10921 	}
   10922       else if (code == GE_EXPR)
   10923 	{
   10924 	  bitop1 = BIT_NOT_EXPR;
   10925 	  bitop2 = BIT_IOR_EXPR;
   10926 	}
   10927       else if (code == LT_EXPR)
   10928 	{
   10929 	  bitop1 = BIT_NOT_EXPR;
   10930 	  bitop2 = BIT_AND_EXPR;
   10931 	  swap_p = true;
   10932 	}
   10933       else if (code == LE_EXPR)
   10934 	{
   10935 	  bitop1 = BIT_NOT_EXPR;
   10936 	  bitop2 = BIT_IOR_EXPR;
   10937 	  swap_p = true;
   10938 	}
   10939       else
   10940 	{
   10941 	  bitop1 = BIT_XOR_EXPR;
   10942 	  if (code == EQ_EXPR)
   10943 	    bitop2 = BIT_NOT_EXPR;
   10944 	}
   10945     }
   10946 
   10947   if (!vec_stmt)
   10948     {
   10949       if (bitop1 == NOP_EXPR)
   10950 	{
   10951 	  if (!expand_vec_cmp_expr_p (vectype, mask_type, code))
   10952 	    return false;
   10953 	}
   10954       else
   10955 	{
   10956 	  machine_mode mode = TYPE_MODE (vectype);
   10957 	  optab optab;
   10958 
   10959 	  optab = optab_for_tree_code (bitop1, vectype, optab_default);
   10960 	  if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
   10961 	    return false;
   10962 
   10963 	  if (bitop2 != NOP_EXPR)
   10964 	    {
   10965 	      optab = optab_for_tree_code (bitop2, vectype, optab_default);
   10966 	      if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
   10967 		return false;
   10968 	    }
   10969 	}
   10970 
   10971       /* Put types on constant and invariant SLP children.  */
   10972       if (slp_node
   10973 	  && (!vect_maybe_update_slp_op_vectype (slp_rhs1, vectype)
   10974 	      || !vect_maybe_update_slp_op_vectype (slp_rhs2, vectype)))
   10975 	{
   10976 	  if (dump_enabled_p ())
   10977 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   10978 			     "incompatible vector types for invariants\n");
   10979 	  return false;
   10980 	}
   10981 
   10982       STMT_VINFO_TYPE (stmt_info) = comparison_vec_info_type;
   10983       vect_model_simple_cost (vinfo, stmt_info,
   10984 			      ncopies * (1 + (bitop2 != NOP_EXPR)),
   10985 			      dts, ndts, slp_node, cost_vec);
   10986       return true;
   10987     }
   10988 
   10989   /* Transform.  */
   10990 
   10991   /* Handle def.  */
   10992   lhs = gimple_assign_lhs (stmt);
   10993   mask = vect_create_destination_var (lhs, mask_type);
   10994 
   10995   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
   10996 		     rhs1, &vec_oprnds0, vectype,
   10997 		     rhs2, &vec_oprnds1, vectype);
   10998   if (swap_p)
   10999     std::swap (vec_oprnds0, vec_oprnds1);
   11000 
   11001   /* Arguments are ready.  Create the new vector stmt.  */
   11002   FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_rhs1)
   11003     {
   11004       gimple *new_stmt;
   11005       vec_rhs2 = vec_oprnds1[i];
   11006 
   11007       new_temp = make_ssa_name (mask);
   11008       if (bitop1 == NOP_EXPR)
   11009 	{
   11010 	  new_stmt = gimple_build_assign (new_temp, code,
   11011 					  vec_rhs1, vec_rhs2);
   11012 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   11013 	}
   11014       else
   11015 	{
   11016 	  if (bitop1 == BIT_NOT_EXPR)
   11017 	    new_stmt = gimple_build_assign (new_temp, bitop1, vec_rhs2);
   11018 	  else
   11019 	    new_stmt = gimple_build_assign (new_temp, bitop1, vec_rhs1,
   11020 					    vec_rhs2);
   11021 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   11022 	  if (bitop2 != NOP_EXPR)
   11023 	    {
   11024 	      tree res = make_ssa_name (mask);
   11025 	      if (bitop2 == BIT_NOT_EXPR)
   11026 		new_stmt = gimple_build_assign (res, bitop2, new_temp);
   11027 	      else
   11028 		new_stmt = gimple_build_assign (res, bitop2, vec_rhs1,
   11029 						new_temp);
   11030 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
   11031 	    }
   11032 	}
   11033       if (slp_node)
   11034 	SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
   11035       else
   11036 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
   11037     }
   11038 
   11039   if (!slp_node)
   11040     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
   11041 
   11042   vec_oprnds0.release ();
   11043   vec_oprnds1.release ();
   11044 
   11045   return true;
   11046 }
   11047 
   11048 /* If SLP_NODE is nonnull, return true if vectorizable_live_operation
   11049    can handle all live statements in the node.  Otherwise return true
   11050    if STMT_INFO is not live or if vectorizable_live_operation can handle it.
   11051    GSI and VEC_STMT_P are as for vectorizable_live_operation.  */
   11052 
   11053 static bool
   11054 can_vectorize_live_stmts (vec_info *vinfo,
   11055 			  stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   11056 			  slp_tree slp_node, slp_instance slp_node_instance,
   11057 			  bool vec_stmt_p,
   11058 			  stmt_vector_for_cost *cost_vec)
   11059 {
   11060   if (slp_node)
   11061     {
   11062       stmt_vec_info slp_stmt_info;
   11063       unsigned int i;
   11064       FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, slp_stmt_info)
   11065 	{
   11066 	  if (STMT_VINFO_LIVE_P (slp_stmt_info)
   11067 	      && !vectorizable_live_operation (vinfo,
   11068 					       slp_stmt_info, gsi, slp_node,
   11069 					       slp_node_instance, i,
   11070 					       vec_stmt_p, cost_vec))
   11071 	    return false;
   11072 	}
   11073     }
   11074   else if (STMT_VINFO_LIVE_P (stmt_info)
   11075 	   && !vectorizable_live_operation (vinfo, stmt_info, gsi,
   11076 					    slp_node, slp_node_instance, -1,
   11077 					    vec_stmt_p, cost_vec))
   11078     return false;
   11079 
   11080   return true;
   11081 }
   11082 
   11083 /* Make sure the statement is vectorizable.  */
   11084 
   11085 opt_result
   11086 vect_analyze_stmt (vec_info *vinfo,
   11087 		   stmt_vec_info stmt_info, bool *need_to_vectorize,
   11088 		   slp_tree node, slp_instance node_instance,
   11089 		   stmt_vector_for_cost *cost_vec)
   11090 {
   11091   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
   11092   enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
   11093   bool ok;
   11094   gimple_seq pattern_def_seq;
   11095 
   11096   if (dump_enabled_p ())
   11097     dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G",
   11098 		     stmt_info->stmt);
   11099 
   11100   if (gimple_has_volatile_ops (stmt_info->stmt))
   11101     return opt_result::failure_at (stmt_info->stmt,
   11102 				   "not vectorized:"
   11103 				   " stmt has volatile operands: %G\n",
   11104 				   stmt_info->stmt);
   11105 
   11106   if (STMT_VINFO_IN_PATTERN_P (stmt_info)
   11107       && node == NULL
   11108       && (pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info)))
   11109     {
   11110       gimple_stmt_iterator si;
   11111 
   11112       for (si = gsi_start (pattern_def_seq); !gsi_end_p (si); gsi_next (&si))
   11113 	{
   11114 	  stmt_vec_info pattern_def_stmt_info
   11115 	    = vinfo->lookup_stmt (gsi_stmt (si));
   11116 	  if (STMT_VINFO_RELEVANT_P (pattern_def_stmt_info)
   11117 	      || STMT_VINFO_LIVE_P (pattern_def_stmt_info))
   11118 	    {
   11119 	      /* Analyze def stmt of STMT if it's a pattern stmt.  */
   11120 	      if (dump_enabled_p ())
   11121 		dump_printf_loc (MSG_NOTE, vect_location,
   11122 				 "==> examining pattern def statement: %G",
   11123 				 pattern_def_stmt_info->stmt);
   11124 
   11125 	      opt_result res
   11126 		= vect_analyze_stmt (vinfo, pattern_def_stmt_info,
   11127 				     need_to_vectorize, node, node_instance,
   11128 				     cost_vec);
   11129 	      if (!res)
   11130 		return res;
   11131 	    }
   11132 	}
   11133     }
   11134 
   11135   /* Skip stmts that do not need to be vectorized. In loops this is expected
   11136      to include:
   11137      - the COND_EXPR which is the loop exit condition
   11138      - any LABEL_EXPRs in the loop
   11139      - computations that are used only for array indexing or loop control.
   11140      In basic blocks we only analyze statements that are a part of some SLP
   11141      instance, therefore, all the statements are relevant.
   11142 
   11143      Pattern statement needs to be analyzed instead of the original statement
   11144      if the original statement is not relevant.  Otherwise, we analyze both
   11145      statements.  In basic blocks we are called from some SLP instance
   11146      traversal, don't analyze pattern stmts instead, the pattern stmts
   11147      already will be part of SLP instance.  */
   11148 
   11149   stmt_vec_info pattern_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
   11150   if (!STMT_VINFO_RELEVANT_P (stmt_info)
   11151       && !STMT_VINFO_LIVE_P (stmt_info))
   11152     {
   11153       if (STMT_VINFO_IN_PATTERN_P (stmt_info)
   11154 	  && pattern_stmt_info
   11155 	  && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
   11156 	      || STMT_VINFO_LIVE_P (pattern_stmt_info)))
   11157         {
   11158           /* Analyze PATTERN_STMT instead of the original stmt.  */
   11159 	  stmt_info = pattern_stmt_info;
   11160           if (dump_enabled_p ())
   11161 	    dump_printf_loc (MSG_NOTE, vect_location,
   11162 			     "==> examining pattern statement: %G",
   11163 			     stmt_info->stmt);
   11164         }
   11165       else
   11166         {
   11167           if (dump_enabled_p ())
   11168             dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n");
   11169 
   11170           return opt_result::success ();
   11171         }
   11172     }
   11173   else if (STMT_VINFO_IN_PATTERN_P (stmt_info)
   11174 	   && node == NULL
   11175 	   && pattern_stmt_info
   11176 	   && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
   11177 	       || STMT_VINFO_LIVE_P (pattern_stmt_info)))
   11178     {
   11179       /* Analyze PATTERN_STMT too.  */
   11180       if (dump_enabled_p ())
   11181 	dump_printf_loc (MSG_NOTE, vect_location,
   11182 			 "==> examining pattern statement: %G",
   11183 			 pattern_stmt_info->stmt);
   11184 
   11185       opt_result res
   11186 	= vect_analyze_stmt (vinfo, pattern_stmt_info, need_to_vectorize, node,
   11187 			     node_instance, cost_vec);
   11188       if (!res)
   11189 	return res;
   11190    }
   11191 
   11192   switch (STMT_VINFO_DEF_TYPE (stmt_info))
   11193     {
   11194       case vect_internal_def:
   11195         break;
   11196 
   11197       case vect_reduction_def:
   11198       case vect_nested_cycle:
   11199          gcc_assert (!bb_vinfo
   11200 		     && (relevance == vect_used_in_outer
   11201 			 || relevance == vect_used_in_outer_by_reduction
   11202 			 || relevance == vect_used_by_reduction
   11203 			 || relevance == vect_unused_in_scope
   11204 			 || relevance == vect_used_only_live));
   11205          break;
   11206 
   11207       case vect_induction_def:
   11208 	gcc_assert (!bb_vinfo);
   11209 	break;
   11210 
   11211       case vect_constant_def:
   11212       case vect_external_def:
   11213       case vect_unknown_def_type:
   11214       default:
   11215         gcc_unreachable ();
   11216     }
   11217 
   11218   tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
   11219   if (node)
   11220     STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (node);
   11221 
   11222   if (STMT_VINFO_RELEVANT_P (stmt_info))
   11223     {
   11224       gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
   11225       gcc_assert (STMT_VINFO_VECTYPE (stmt_info)
   11226 		  || (call && gimple_call_lhs (call) == NULL_TREE));
   11227       *need_to_vectorize = true;
   11228     }
   11229 
   11230   if (PURE_SLP_STMT (stmt_info) && !node)
   11231     {
   11232       if (dump_enabled_p ())
   11233 	dump_printf_loc (MSG_NOTE, vect_location,
   11234 			 "handled only by SLP analysis\n");
   11235       return opt_result::success ();
   11236     }
   11237 
   11238   ok = true;
   11239   if (!bb_vinfo
   11240       && (STMT_VINFO_RELEVANT_P (stmt_info)
   11241 	  || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def))
   11242     /* Prefer vectorizable_call over vectorizable_simd_clone_call so
   11243        -mveclibabi= takes preference over library functions with
   11244        the simd attribute.  */
   11245     ok = (vectorizable_call (vinfo, stmt_info, NULL, NULL, node, cost_vec)
   11246 	  || vectorizable_simd_clone_call (vinfo, stmt_info, NULL, NULL, node,
   11247 					   cost_vec)
   11248 	  || vectorizable_conversion (vinfo, stmt_info,
   11249 				      NULL, NULL, node, cost_vec)
   11250 	  || vectorizable_operation (vinfo, stmt_info,
   11251 				     NULL, NULL, node, cost_vec)
   11252 	  || vectorizable_assignment (vinfo, stmt_info,
   11253 				      NULL, NULL, node, cost_vec)
   11254 	  || vectorizable_load (vinfo, stmt_info, NULL, NULL, node, cost_vec)
   11255 	  || vectorizable_store (vinfo, stmt_info, NULL, NULL, node, cost_vec)
   11256 	  || vectorizable_reduction (as_a <loop_vec_info> (vinfo), stmt_info,
   11257 				     node, node_instance, cost_vec)
   11258 	  || vectorizable_induction (as_a <loop_vec_info> (vinfo), stmt_info,
   11259 				     NULL, node, cost_vec)
   11260 	  || vectorizable_shift (vinfo, stmt_info, NULL, NULL, node, cost_vec)
   11261 	  || vectorizable_condition (vinfo, stmt_info,
   11262 				     NULL, NULL, node, cost_vec)
   11263 	  || vectorizable_comparison (vinfo, stmt_info, NULL, NULL, node,
   11264 				      cost_vec)
   11265 	  || vectorizable_lc_phi (as_a <loop_vec_info> (vinfo),
   11266 				  stmt_info, NULL, node));
   11267   else
   11268     {
   11269       if (bb_vinfo)
   11270 	ok = (vectorizable_call (vinfo, stmt_info, NULL, NULL, node, cost_vec)
   11271 	      || vectorizable_simd_clone_call (vinfo, stmt_info,
   11272 					       NULL, NULL, node, cost_vec)
   11273 	      || vectorizable_conversion (vinfo, stmt_info, NULL, NULL, node,
   11274 					  cost_vec)
   11275 	      || vectorizable_shift (vinfo, stmt_info,
   11276 				     NULL, NULL, node, cost_vec)
   11277 	      || vectorizable_operation (vinfo, stmt_info,
   11278 					 NULL, NULL, node, cost_vec)
   11279 	      || vectorizable_assignment (vinfo, stmt_info, NULL, NULL, node,
   11280 					  cost_vec)
   11281 	      || vectorizable_load (vinfo, stmt_info,
   11282 				    NULL, NULL, node, cost_vec)
   11283 	      || vectorizable_store (vinfo, stmt_info,
   11284 				     NULL, NULL, node, cost_vec)
   11285 	      || vectorizable_condition (vinfo, stmt_info,
   11286 					 NULL, NULL, node, cost_vec)
   11287 	      || vectorizable_comparison (vinfo, stmt_info, NULL, NULL, node,
   11288 					  cost_vec)
   11289 	      || vectorizable_phi (vinfo, stmt_info, NULL, node, cost_vec));
   11290     }
   11291 
   11292   if (node)
   11293     STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
   11294 
   11295   if (!ok)
   11296     return opt_result::failure_at (stmt_info->stmt,
   11297 				   "not vectorized:"
   11298 				   " relevant stmt not supported: %G",
   11299 				   stmt_info->stmt);
   11300 
   11301   /* Stmts that are (also) "live" (i.e. - that are used out of the loop)
   11302       need extra handling, except for vectorizable reductions.  */
   11303   if (!bb_vinfo
   11304       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type
   11305       && STMT_VINFO_TYPE (stmt_info) != lc_phi_info_type
   11306       && !can_vectorize_live_stmts (as_a <loop_vec_info> (vinfo),
   11307 				    stmt_info, NULL, node, node_instance,
   11308 				    false, cost_vec))
   11309     return opt_result::failure_at (stmt_info->stmt,
   11310 				   "not vectorized:"
   11311 				   " live stmt not supported: %G",
   11312 				   stmt_info->stmt);
   11313 
   11314   return opt_result::success ();
   11315 }
   11316 
   11317 
   11318 /* Function vect_transform_stmt.
   11319 
   11320    Create a vectorized stmt to replace STMT_INFO, and insert it at GSI.  */
   11321 
   11322 bool
   11323 vect_transform_stmt (vec_info *vinfo,
   11324 		     stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
   11325 		     slp_tree slp_node, slp_instance slp_node_instance)
   11326 {
   11327   bool is_store = false;
   11328   gimple *vec_stmt = NULL;
   11329   bool done;
   11330 
   11331   gcc_assert (slp_node || !PURE_SLP_STMT (stmt_info));
   11332 
   11333   tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
   11334   if (slp_node)
   11335     STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (slp_node);
   11336 
   11337   switch (STMT_VINFO_TYPE (stmt_info))
   11338     {
   11339     case type_demotion_vec_info_type:
   11340     case type_promotion_vec_info_type:
   11341     case type_conversion_vec_info_type:
   11342       done = vectorizable_conversion (vinfo, stmt_info,
   11343 				      gsi, &vec_stmt, slp_node, NULL);
   11344       gcc_assert (done);
   11345       break;
   11346 
   11347     case induc_vec_info_type:
   11348       done = vectorizable_induction (as_a <loop_vec_info> (vinfo),
   11349 				     stmt_info, &vec_stmt, slp_node,
   11350 				     NULL);
   11351       gcc_assert (done);
   11352       break;
   11353 
   11354     case shift_vec_info_type:
   11355       done = vectorizable_shift (vinfo, stmt_info,
   11356 				 gsi, &vec_stmt, slp_node, NULL);
   11357       gcc_assert (done);
   11358       break;
   11359 
   11360     case op_vec_info_type:
   11361       done = vectorizable_operation (vinfo, stmt_info, gsi, &vec_stmt, slp_node,
   11362 				     NULL);
   11363       gcc_assert (done);
   11364       break;
   11365 
   11366     case assignment_vec_info_type:
   11367       done = vectorizable_assignment (vinfo, stmt_info,
   11368 				      gsi, &vec_stmt, slp_node, NULL);
   11369       gcc_assert (done);
   11370       break;
   11371 
   11372     case load_vec_info_type:
   11373       done = vectorizable_load (vinfo, stmt_info, gsi, &vec_stmt, slp_node,
   11374 				NULL);
   11375       gcc_assert (done);
   11376       break;
   11377 
   11378     case store_vec_info_type:
   11379       done = vectorizable_store (vinfo, stmt_info,
   11380 				 gsi, &vec_stmt, slp_node, NULL);
   11381       gcc_assert (done);
   11382       if (STMT_VINFO_GROUPED_ACCESS (stmt_info) && !slp_node)
   11383 	{
   11384 	  /* In case of interleaving, the whole chain is vectorized when the
   11385 	     last store in the chain is reached.  Store stmts before the last
   11386 	     one are skipped, and there vec_stmt_info shouldn't be freed
   11387 	     meanwhile.  */
   11388 	  stmt_vec_info group_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
   11389 	  if (DR_GROUP_STORE_COUNT (group_info) == DR_GROUP_SIZE (group_info))
   11390 	    is_store = true;
   11391 	}
   11392       else
   11393 	is_store = true;
   11394       break;
   11395 
   11396     case condition_vec_info_type:
   11397       done = vectorizable_condition (vinfo, stmt_info,
   11398 				     gsi, &vec_stmt, slp_node, NULL);
   11399       gcc_assert (done);
   11400       break;
   11401 
   11402     case comparison_vec_info_type:
   11403       done = vectorizable_comparison (vinfo, stmt_info, gsi, &vec_stmt,
   11404 				      slp_node, NULL);
   11405       gcc_assert (done);
   11406       break;
   11407 
   11408     case call_vec_info_type:
   11409       done = vectorizable_call (vinfo, stmt_info,
   11410 				gsi, &vec_stmt, slp_node, NULL);
   11411       break;
   11412 
   11413     case call_simd_clone_vec_info_type:
   11414       done = vectorizable_simd_clone_call (vinfo, stmt_info, gsi, &vec_stmt,
   11415 					   slp_node, NULL);
   11416       break;
   11417 
   11418     case reduc_vec_info_type:
   11419       done = vect_transform_reduction (as_a <loop_vec_info> (vinfo), stmt_info,
   11420 				       gsi, &vec_stmt, slp_node);
   11421       gcc_assert (done);
   11422       break;
   11423 
   11424     case cycle_phi_info_type:
   11425       done = vect_transform_cycle_phi (as_a <loop_vec_info> (vinfo), stmt_info,
   11426 				       &vec_stmt, slp_node, slp_node_instance);
   11427       gcc_assert (done);
   11428       break;
   11429 
   11430     case lc_phi_info_type:
   11431       done = vectorizable_lc_phi (as_a <loop_vec_info> (vinfo),
   11432 				  stmt_info, &vec_stmt, slp_node);
   11433       gcc_assert (done);
   11434       break;
   11435 
   11436     case phi_info_type:
   11437       done = vectorizable_phi (vinfo, stmt_info, &vec_stmt, slp_node, NULL);
   11438       gcc_assert (done);
   11439       break;
   11440 
   11441     default:
   11442       if (!STMT_VINFO_LIVE_P (stmt_info))
   11443 	{
   11444 	  if (dump_enabled_p ())
   11445 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   11446                              "stmt not supported.\n");
   11447 	  gcc_unreachable ();
   11448 	}
   11449       done = true;
   11450     }
   11451 
   11452   if (!slp_node && vec_stmt)
   11453     gcc_assert (STMT_VINFO_VEC_STMTS (stmt_info).exists ());
   11454 
   11455   if (STMT_VINFO_TYPE (stmt_info) != store_vec_info_type)
   11456     {
   11457       /* Handle stmts whose DEF is used outside the loop-nest that is
   11458 	 being vectorized.  */
   11459       done = can_vectorize_live_stmts (vinfo, stmt_info, gsi, slp_node,
   11460 				       slp_node_instance, true, NULL);
   11461       gcc_assert (done);
   11462     }
   11463 
   11464   if (slp_node)
   11465     STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
   11466 
   11467   return is_store;
   11468 }
   11469 
   11470 
   11471 /* Remove a group of stores (for SLP or interleaving), free their
   11472    stmt_vec_info.  */
   11473 
   11474 void
   11475 vect_remove_stores (vec_info *vinfo, stmt_vec_info first_stmt_info)
   11476 {
   11477   stmt_vec_info next_stmt_info = first_stmt_info;
   11478 
   11479   while (next_stmt_info)
   11480     {
   11481       stmt_vec_info tmp = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
   11482       next_stmt_info = vect_orig_stmt (next_stmt_info);
   11483       /* Free the attached stmt_vec_info and remove the stmt.  */
   11484       vinfo->remove_stmt (next_stmt_info);
   11485       next_stmt_info = tmp;
   11486     }
   11487 }
   11488 
   11489 /* If NUNITS is nonzero, return a vector type that contains NUNITS
   11490    elements of type SCALAR_TYPE, or null if the target doesn't support
   11491    such a type.
   11492 
   11493    If NUNITS is zero, return a vector type that contains elements of
   11494    type SCALAR_TYPE, choosing whichever vector size the target prefers.
   11495 
   11496    If PREVAILING_MODE is VOIDmode, we have not yet chosen a vector mode
   11497    for this vectorization region and want to "autodetect" the best choice.
   11498    Otherwise, PREVAILING_MODE is a previously-chosen vector TYPE_MODE
   11499    and we want the new type to be interoperable with it.   PREVAILING_MODE
   11500    in this case can be a scalar integer mode or a vector mode; when it
   11501    is a vector mode, the function acts like a tree-level version of
   11502    related_vector_mode.  */
   11503 
   11504 tree
   11505 get_related_vectype_for_scalar_type (machine_mode prevailing_mode,
   11506 				     tree scalar_type, poly_uint64 nunits)
   11507 {
   11508   tree orig_scalar_type = scalar_type;
   11509   scalar_mode inner_mode;
   11510   machine_mode simd_mode;
   11511   tree vectype;
   11512 
   11513   if (!is_int_mode (TYPE_MODE (scalar_type), &inner_mode)
   11514       && !is_float_mode (TYPE_MODE (scalar_type), &inner_mode))
   11515     return NULL_TREE;
   11516 
   11517   unsigned int nbytes = GET_MODE_SIZE (inner_mode);
   11518 
   11519   /* For vector types of elements whose mode precision doesn't
   11520      match their types precision we use a element type of mode
   11521      precision.  The vectorization routines will have to make sure
   11522      they support the proper result truncation/extension.
   11523      We also make sure to build vector types with INTEGER_TYPE
   11524      component type only.  */
   11525   if (INTEGRAL_TYPE_P (scalar_type)
   11526       && (GET_MODE_BITSIZE (inner_mode) != TYPE_PRECISION (scalar_type)
   11527 	  || TREE_CODE (scalar_type) != INTEGER_TYPE))
   11528     scalar_type = build_nonstandard_integer_type (GET_MODE_BITSIZE (inner_mode),
   11529 						  TYPE_UNSIGNED (scalar_type));
   11530 
   11531   /* We shouldn't end up building VECTOR_TYPEs of non-scalar components.
   11532      When the component mode passes the above test simply use a type
   11533      corresponding to that mode.  The theory is that any use that
   11534      would cause problems with this will disable vectorization anyway.  */
   11535   else if (!SCALAR_FLOAT_TYPE_P (scalar_type)
   11536 	   && !INTEGRAL_TYPE_P (scalar_type))
   11537     scalar_type = lang_hooks.types.type_for_mode (inner_mode, 1);
   11538 
   11539   /* We can't build a vector type of elements with alignment bigger than
   11540      their size.  */
   11541   else if (nbytes < TYPE_ALIGN_UNIT (scalar_type))
   11542     scalar_type = lang_hooks.types.type_for_mode (inner_mode,
   11543 						  TYPE_UNSIGNED (scalar_type));
   11544 
   11545   /* If we felt back to using the mode fail if there was
   11546      no scalar type for it.  */
   11547   if (scalar_type == NULL_TREE)
   11548     return NULL_TREE;
   11549 
   11550   /* If no prevailing mode was supplied, use the mode the target prefers.
   11551      Otherwise lookup a vector mode based on the prevailing mode.  */
   11552   if (prevailing_mode == VOIDmode)
   11553     {
   11554       gcc_assert (known_eq (nunits, 0U));
   11555       simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
   11556       if (SCALAR_INT_MODE_P (simd_mode))
   11557 	{
   11558 	  /* Traditional behavior is not to take the integer mode
   11559 	     literally, but simply to use it as a way of determining
   11560 	     the vector size.  It is up to mode_for_vector to decide
   11561 	     what the TYPE_MODE should be.
   11562 
   11563 	     Note that nunits == 1 is allowed in order to support single
   11564 	     element vector types.  */
   11565 	  if (!multiple_p (GET_MODE_SIZE (simd_mode), nbytes, &nunits)
   11566 	      || !mode_for_vector (inner_mode, nunits).exists (&simd_mode))
   11567 	    return NULL_TREE;
   11568 	}
   11569     }
   11570   else if (SCALAR_INT_MODE_P (prevailing_mode)
   11571 	   || !related_vector_mode (prevailing_mode,
   11572 				    inner_mode, nunits).exists (&simd_mode))
   11573     {
   11574       /* Fall back to using mode_for_vector, mostly in the hope of being
   11575 	 able to use an integer mode.  */
   11576       if (known_eq (nunits, 0U)
   11577 	  && !multiple_p (GET_MODE_SIZE (prevailing_mode), nbytes, &nunits))
   11578 	return NULL_TREE;
   11579 
   11580       if (!mode_for_vector (inner_mode, nunits).exists (&simd_mode))
   11581 	return NULL_TREE;
   11582     }
   11583 
   11584   vectype = build_vector_type_for_mode (scalar_type, simd_mode);
   11585 
   11586   /* In cases where the mode was chosen by mode_for_vector, check that
   11587      the target actually supports the chosen mode, or that it at least
   11588      allows the vector mode to be replaced by a like-sized integer.  */
   11589   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
   11590       && !INTEGRAL_MODE_P (TYPE_MODE (vectype)))
   11591     return NULL_TREE;
   11592 
   11593   /* Re-attach the address-space qualifier if we canonicalized the scalar
   11594      type.  */
   11595   if (TYPE_ADDR_SPACE (orig_scalar_type) != TYPE_ADDR_SPACE (vectype))
   11596     return build_qualified_type
   11597 	     (vectype, KEEP_QUAL_ADDR_SPACE (TYPE_QUALS (orig_scalar_type)));
   11598 
   11599   return vectype;
   11600 }
   11601 
   11602 /* Function get_vectype_for_scalar_type.
   11603 
   11604    Returns the vector type corresponding to SCALAR_TYPE as supported
   11605    by the target.  If GROUP_SIZE is nonzero and we're performing BB
   11606    vectorization, make sure that the number of elements in the vector
   11607    is no bigger than GROUP_SIZE.  */
   11608 
   11609 tree
   11610 get_vectype_for_scalar_type (vec_info *vinfo, tree scalar_type,
   11611 			     unsigned int group_size)
   11612 {
   11613   /* For BB vectorization, we should always have a group size once we've
   11614      constructed the SLP tree; the only valid uses of zero GROUP_SIZEs
   11615      are tentative requests during things like early data reference
   11616      analysis and pattern recognition.  */
   11617   if (is_a <bb_vec_info> (vinfo))
   11618     gcc_assert (vinfo->slp_instances.is_empty () || group_size != 0);
   11619   else
   11620     group_size = 0;
   11621 
   11622   tree vectype = get_related_vectype_for_scalar_type (vinfo->vector_mode,
   11623 						      scalar_type);
   11624   if (vectype && vinfo->vector_mode == VOIDmode)
   11625     vinfo->vector_mode = TYPE_MODE (vectype);
   11626 
   11627   /* Register the natural choice of vector type, before the group size
   11628      has been applied.  */
   11629   if (vectype)
   11630     vinfo->used_vector_modes.add (TYPE_MODE (vectype));
   11631 
   11632   /* If the natural choice of vector type doesn't satisfy GROUP_SIZE,
   11633      try again with an explicit number of elements.  */
   11634   if (vectype
   11635       && group_size
   11636       && maybe_ge (TYPE_VECTOR_SUBPARTS (vectype), group_size))
   11637     {
   11638       /* Start with the biggest number of units that fits within
   11639 	 GROUP_SIZE and halve it until we find a valid vector type.
   11640 	 Usually either the first attempt will succeed or all will
   11641 	 fail (in the latter case because GROUP_SIZE is too small
   11642 	 for the target), but it's possible that a target could have
   11643 	 a hole between supported vector types.
   11644 
   11645 	 If GROUP_SIZE is not a power of 2, this has the effect of
   11646 	 trying the largest power of 2 that fits within the group,
   11647 	 even though the group is not a multiple of that vector size.
   11648 	 The BB vectorizer will then try to carve up the group into
   11649 	 smaller pieces.  */
   11650       unsigned int nunits = 1 << floor_log2 (group_size);
   11651       do
   11652 	{
   11653 	  vectype = get_related_vectype_for_scalar_type (vinfo->vector_mode,
   11654 							 scalar_type, nunits);
   11655 	  nunits /= 2;
   11656 	}
   11657       while (nunits > 1 && !vectype);
   11658     }
   11659 
   11660   return vectype;
   11661 }
   11662 
   11663 /* Return the vector type corresponding to SCALAR_TYPE as supported
   11664    by the target.  NODE, if nonnull, is the SLP tree node that will
   11665    use the returned vector type.  */
   11666 
   11667 tree
   11668 get_vectype_for_scalar_type (vec_info *vinfo, tree scalar_type, slp_tree node)
   11669 {
   11670   unsigned int group_size = 0;
   11671   if (node)
   11672     group_size = SLP_TREE_LANES (node);
   11673   return get_vectype_for_scalar_type (vinfo, scalar_type, group_size);
   11674 }
   11675 
   11676 /* Function get_mask_type_for_scalar_type.
   11677 
   11678    Returns the mask type corresponding to a result of comparison
   11679    of vectors of specified SCALAR_TYPE as supported by target.
   11680    If GROUP_SIZE is nonzero and we're performing BB vectorization,
   11681    make sure that the number of elements in the vector is no bigger
   11682    than GROUP_SIZE.  */
   11683 
   11684 tree
   11685 get_mask_type_for_scalar_type (vec_info *vinfo, tree scalar_type,
   11686 			       unsigned int group_size)
   11687 {
   11688   tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type, group_size);
   11689 
   11690   if (!vectype)
   11691     return NULL;
   11692 
   11693   return truth_type_for (vectype);
   11694 }
   11695 
   11696 /* Function get_same_sized_vectype
   11697 
   11698    Returns a vector type corresponding to SCALAR_TYPE of size
   11699    VECTOR_TYPE if supported by the target.  */
   11700 
   11701 tree
   11702 get_same_sized_vectype (tree scalar_type, tree vector_type)
   11703 {
   11704   if (VECT_SCALAR_BOOLEAN_TYPE_P (scalar_type))
   11705     return truth_type_for (vector_type);
   11706 
   11707   poly_uint64 nunits;
   11708   if (!multiple_p (GET_MODE_SIZE (TYPE_MODE (vector_type)),
   11709 		   GET_MODE_SIZE (TYPE_MODE (scalar_type)), &nunits))
   11710     return NULL_TREE;
   11711 
   11712   return get_related_vectype_for_scalar_type (TYPE_MODE (vector_type),
   11713 					      scalar_type, nunits);
   11714 }
   11715 
   11716 /* Return true if replacing LOOP_VINFO->vector_mode with VECTOR_MODE
   11717    would not change the chosen vector modes.  */
   11718 
   11719 bool
   11720 vect_chooses_same_modes_p (vec_info *vinfo, machine_mode vector_mode)
   11721 {
   11722   for (vec_info::mode_set::iterator i = vinfo->used_vector_modes.begin ();
   11723        i != vinfo->used_vector_modes.end (); ++i)
   11724     if (!VECTOR_MODE_P (*i)
   11725 	|| related_vector_mode (vector_mode, GET_MODE_INNER (*i), 0) != *i)
   11726       return false;
   11727   return true;
   11728 }
   11729 
   11730 /* Function vect_is_simple_use.
   11731 
   11732    Input:
   11733    VINFO - the vect info of the loop or basic block that is being vectorized.
   11734    OPERAND - operand in the loop or bb.
   11735    Output:
   11736    DEF_STMT_INFO_OUT (optional) - information about the defining stmt in
   11737      case OPERAND is an SSA_NAME that is defined in the vectorizable region
   11738    DEF_STMT_OUT (optional) - the defining stmt in case OPERAND is an SSA_NAME;
   11739      the definition could be anywhere in the function
   11740    DT - the type of definition
   11741 
   11742    Returns whether a stmt with OPERAND can be vectorized.
   11743    For loops, supportable operands are constants, loop invariants, and operands
   11744    that are defined by the current iteration of the loop.  Unsupportable
   11745    operands are those that are defined by a previous iteration of the loop (as
   11746    is the case in reduction/induction computations).
   11747    For basic blocks, supportable operands are constants and bb invariants.
   11748    For now, operands defined outside the basic block are not supported.  */
   11749 
   11750 bool
   11751 vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
   11752 		    stmt_vec_info *def_stmt_info_out, gimple **def_stmt_out)
   11753 {
   11754   if (def_stmt_info_out)
   11755     *def_stmt_info_out = NULL;
   11756   if (def_stmt_out)
   11757     *def_stmt_out = NULL;
   11758   *dt = vect_unknown_def_type;
   11759 
   11760   if (dump_enabled_p ())
   11761     {
   11762       dump_printf_loc (MSG_NOTE, vect_location,
   11763                        "vect_is_simple_use: operand ");
   11764       if (TREE_CODE (operand) == SSA_NAME
   11765 	  && !SSA_NAME_IS_DEFAULT_DEF (operand))
   11766 	dump_gimple_expr (MSG_NOTE, TDF_SLIM, SSA_NAME_DEF_STMT (operand), 0);
   11767       else
   11768 	dump_generic_expr (MSG_NOTE, TDF_SLIM, operand);
   11769     }
   11770 
   11771   if (CONSTANT_CLASS_P (operand))
   11772     *dt = vect_constant_def;
   11773   else if (is_gimple_min_invariant (operand))
   11774     *dt = vect_external_def;
   11775   else if (TREE_CODE (operand) != SSA_NAME)
   11776     *dt = vect_unknown_def_type;
   11777   else if (SSA_NAME_IS_DEFAULT_DEF (operand))
   11778     *dt = vect_external_def;
   11779   else
   11780     {
   11781       gimple *def_stmt = SSA_NAME_DEF_STMT (operand);
   11782       stmt_vec_info stmt_vinfo = vinfo->lookup_def (operand);
   11783       if (!stmt_vinfo)
   11784 	*dt = vect_external_def;
   11785       else
   11786 	{
   11787 	  stmt_vinfo = vect_stmt_to_vectorize (stmt_vinfo);
   11788 	  def_stmt = stmt_vinfo->stmt;
   11789 	  *dt = STMT_VINFO_DEF_TYPE (stmt_vinfo);
   11790 	  if (def_stmt_info_out)
   11791 	    *def_stmt_info_out = stmt_vinfo;
   11792 	}
   11793       if (def_stmt_out)
   11794 	*def_stmt_out = def_stmt;
   11795     }
   11796 
   11797   if (dump_enabled_p ())
   11798     {
   11799       dump_printf (MSG_NOTE, ", type of def: ");
   11800       switch (*dt)
   11801 	{
   11802 	case vect_uninitialized_def:
   11803 	  dump_printf (MSG_NOTE, "uninitialized\n");
   11804 	  break;
   11805 	case vect_constant_def:
   11806 	  dump_printf (MSG_NOTE, "constant\n");
   11807 	  break;
   11808 	case vect_external_def:
   11809 	  dump_printf (MSG_NOTE, "external\n");
   11810 	  break;
   11811 	case vect_internal_def:
   11812 	  dump_printf (MSG_NOTE, "internal\n");
   11813 	  break;
   11814 	case vect_induction_def:
   11815 	  dump_printf (MSG_NOTE, "induction\n");
   11816 	  break;
   11817 	case vect_reduction_def:
   11818 	  dump_printf (MSG_NOTE, "reduction\n");
   11819 	  break;
   11820 	case vect_double_reduction_def:
   11821 	  dump_printf (MSG_NOTE, "double reduction\n");
   11822 	  break;
   11823 	case vect_nested_cycle:
   11824 	  dump_printf (MSG_NOTE, "nested cycle\n");
   11825 	  break;
   11826 	case vect_unknown_def_type:
   11827 	  dump_printf (MSG_NOTE, "unknown\n");
   11828 	  break;
   11829 	}
   11830     }
   11831 
   11832   if (*dt == vect_unknown_def_type)
   11833     {
   11834       if (dump_enabled_p ())
   11835         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
   11836                          "Unsupported pattern.\n");
   11837       return false;
   11838     }
   11839 
   11840   return true;
   11841 }
   11842 
   11843 /* Function vect_is_simple_use.
   11844 
   11845    Same as vect_is_simple_use but also determines the vector operand
   11846    type of OPERAND and stores it to *VECTYPE.  If the definition of
   11847    OPERAND is vect_uninitialized_def, vect_constant_def or
   11848    vect_external_def *VECTYPE will be set to NULL_TREE and the caller
   11849    is responsible to compute the best suited vector type for the
   11850    scalar operand.  */
   11851 
   11852 bool
   11853 vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
   11854 		    tree *vectype, stmt_vec_info *def_stmt_info_out,
   11855 		    gimple **def_stmt_out)
   11856 {
   11857   stmt_vec_info def_stmt_info;
   11858   gimple *def_stmt;
   11859   if (!vect_is_simple_use (operand, vinfo, dt, &def_stmt_info, &def_stmt))
   11860     return false;
   11861 
   11862   if (def_stmt_out)
   11863     *def_stmt_out = def_stmt;
   11864   if (def_stmt_info_out)
   11865     *def_stmt_info_out = def_stmt_info;
   11866 
   11867   /* Now get a vector type if the def is internal, otherwise supply
   11868      NULL_TREE and leave it up to the caller to figure out a proper
   11869      type for the use stmt.  */
   11870   if (*dt == vect_internal_def
   11871       || *dt == vect_induction_def
   11872       || *dt == vect_reduction_def
   11873       || *dt == vect_double_reduction_def
   11874       || *dt == vect_nested_cycle)
   11875     {
   11876       *vectype = STMT_VINFO_VECTYPE (def_stmt_info);
   11877       gcc_assert (*vectype != NULL_TREE);
   11878       if (dump_enabled_p ())
   11879 	dump_printf_loc (MSG_NOTE, vect_location,
   11880 			 "vect_is_simple_use: vectype %T\n", *vectype);
   11881     }
   11882   else if (*dt == vect_uninitialized_def
   11883 	   || *dt == vect_constant_def
   11884 	   || *dt == vect_external_def)
   11885     *vectype = NULL_TREE;
   11886   else
   11887     gcc_unreachable ();
   11888 
   11889   return true;
   11890 }
   11891 
   11892 /* Function vect_is_simple_use.
   11893 
   11894    Same as vect_is_simple_use but determines the operand by operand
   11895    position OPERAND from either STMT or SLP_NODE, filling in *OP
   11896    and *SLP_DEF (when SLP_NODE is not NULL).  */
   11897 
   11898 bool
   11899 vect_is_simple_use (vec_info *vinfo, stmt_vec_info stmt, slp_tree slp_node,
   11900 		    unsigned operand, tree *op, slp_tree *slp_def,
   11901 		    enum vect_def_type *dt,
   11902 		    tree *vectype, stmt_vec_info *def_stmt_info_out)
   11903 {
   11904   if (slp_node)
   11905     {
   11906       slp_tree child = SLP_TREE_CHILDREN (slp_node)[operand];
   11907       *slp_def = child;
   11908       *vectype = SLP_TREE_VECTYPE (child);
   11909       if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
   11910 	{
   11911 	  *op = gimple_get_lhs (SLP_TREE_REPRESENTATIVE (child)->stmt);
   11912 	  return vect_is_simple_use (*op, vinfo, dt, def_stmt_info_out);
   11913 	}
   11914       else
   11915 	{
   11916 	  if (def_stmt_info_out)
   11917 	    *def_stmt_info_out = NULL;
   11918 	  *op = SLP_TREE_SCALAR_OPS (child)[0];
   11919 	  *dt = SLP_TREE_DEF_TYPE (child);
   11920 	  return true;
   11921 	}
   11922     }
   11923   else
   11924     {
   11925       *slp_def = NULL;
   11926       if (gassign *ass = dyn_cast <gassign *> (stmt->stmt))
   11927 	{
   11928 	  if (gimple_assign_rhs_code (ass) == COND_EXPR
   11929 	      && COMPARISON_CLASS_P (gimple_assign_rhs1 (ass)))
   11930 	    {
   11931 	      if (operand < 2)
   11932 		*op = TREE_OPERAND (gimple_assign_rhs1 (ass), operand);
   11933 	      else
   11934 		*op = gimple_op (ass, operand);
   11935 	    }
   11936 	  else if (gimple_assign_rhs_code (ass) == VIEW_CONVERT_EXPR)
   11937 	    *op = TREE_OPERAND (gimple_assign_rhs1 (ass), 0);
   11938 	  else
   11939 	    *op = gimple_op (ass, operand + 1);
   11940 	}
   11941       else if (gcall *call = dyn_cast <gcall *> (stmt->stmt))
   11942 	*op = gimple_call_arg (call, operand);
   11943       else
   11944 	gcc_unreachable ();
   11945       return vect_is_simple_use (*op, vinfo, dt, vectype, def_stmt_info_out);
   11946     }
   11947 }
   11948 
   11949 /* If OP is not NULL and is external or constant update its vector
   11950    type with VECTYPE.  Returns true if successful or false if not,
   11951    for example when conflicting vector types are present.  */
   11952 
   11953 bool
   11954 vect_maybe_update_slp_op_vectype (slp_tree op, tree vectype)
   11955 {
   11956   if (!op || SLP_TREE_DEF_TYPE (op) == vect_internal_def)
   11957     return true;
   11958   if (SLP_TREE_VECTYPE (op))
   11959     return types_compatible_p (SLP_TREE_VECTYPE (op), vectype);
   11960   SLP_TREE_VECTYPE (op) = vectype;
   11961   return true;
   11962 }
   11963 
   11964 /* Function supportable_widening_operation
   11965 
   11966    Check whether an operation represented by the code CODE is a
   11967    widening operation that is supported by the target platform in
   11968    vector form (i.e., when operating on arguments of type VECTYPE_IN
   11969    producing a result of type VECTYPE_OUT).
   11970 
   11971    Widening operations we currently support are NOP (CONVERT), FLOAT,
   11972    FIX_TRUNC and WIDEN_MULT.  This function checks if these operations
   11973    are supported by the target platform either directly (via vector
   11974    tree-codes), or via target builtins.
   11975 
   11976    Output:
   11977    - CODE1 and CODE2 are codes of vector operations to be used when
   11978    vectorizing the operation, if available.
   11979    - MULTI_STEP_CVT determines the number of required intermediate steps in
   11980    case of multi-step conversion (like char->short->int - in that case
   11981    MULTI_STEP_CVT will be 1).
   11982    - INTERM_TYPES contains the intermediate type required to perform the
   11983    widening operation (short in the above example).  */
   11984 
   11985 bool
   11986 supportable_widening_operation (vec_info *vinfo,
   11987 				enum tree_code code, stmt_vec_info stmt_info,
   11988 				tree vectype_out, tree vectype_in,
   11989                                 enum tree_code *code1, enum tree_code *code2,
   11990                                 int *multi_step_cvt,
   11991                                 vec<tree> *interm_types)
   11992 {
   11993   loop_vec_info loop_info = dyn_cast <loop_vec_info> (vinfo);
   11994   class loop *vect_loop = NULL;
   11995   machine_mode vec_mode;
   11996   enum insn_code icode1, icode2;
   11997   optab optab1, optab2;
   11998   tree vectype = vectype_in;
   11999   tree wide_vectype = vectype_out;
   12000   enum tree_code c1, c2;
   12001   int i;
   12002   tree prev_type, intermediate_type;
   12003   machine_mode intermediate_mode, prev_mode;
   12004   optab optab3, optab4;
   12005 
   12006   *multi_step_cvt = 0;
   12007   if (loop_info)
   12008     vect_loop = LOOP_VINFO_LOOP (loop_info);
   12009 
   12010   switch (code)
   12011     {
   12012     case WIDEN_MULT_EXPR:
   12013       /* The result of a vectorized widening operation usually requires
   12014 	 two vectors (because the widened results do not fit into one vector).
   12015 	 The generated vector results would normally be expected to be
   12016 	 generated in the same order as in the original scalar computation,
   12017 	 i.e. if 8 results are generated in each vector iteration, they are
   12018 	 to be organized as follows:
   12019 		vect1: [res1,res2,res3,res4],
   12020 		vect2: [res5,res6,res7,res8].
   12021 
   12022 	 However, in the special case that the result of the widening
   12023 	 operation is used in a reduction computation only, the order doesn't
   12024 	 matter (because when vectorizing a reduction we change the order of
   12025 	 the computation).  Some targets can take advantage of this and
   12026 	 generate more efficient code.  For example, targets like Altivec,
   12027 	 that support widen_mult using a sequence of {mult_even,mult_odd}
   12028 	 generate the following vectors:
   12029 		vect1: [res1,res3,res5,res7],
   12030 		vect2: [res2,res4,res6,res8].
   12031 
   12032 	 When vectorizing outer-loops, we execute the inner-loop sequentially
   12033 	 (each vectorized inner-loop iteration contributes to VF outer-loop
   12034 	 iterations in parallel).  We therefore don't allow to change the
   12035 	 order of the computation in the inner-loop during outer-loop
   12036 	 vectorization.  */
   12037       /* TODO: Another case in which order doesn't *really* matter is when we
   12038 	 widen and then contract again, e.g. (short)((int)x * y >> 8).
   12039 	 Normally, pack_trunc performs an even/odd permute, whereas the
   12040 	 repack from an even/odd expansion would be an interleave, which
   12041 	 would be significantly simpler for e.g. AVX2.  */
   12042       /* In any case, in order to avoid duplicating the code below, recurse
   12043 	 on VEC_WIDEN_MULT_EVEN_EXPR.  If it succeeds, all the return values
   12044 	 are properly set up for the caller.  If we fail, we'll continue with
   12045 	 a VEC_WIDEN_MULT_LO/HI_EXPR check.  */
   12046       if (vect_loop
   12047 	  && STMT_VINFO_RELEVANT (stmt_info) == vect_used_by_reduction
   12048 	  && !nested_in_vect_loop_p (vect_loop, stmt_info)
   12049 	  && supportable_widening_operation (vinfo, VEC_WIDEN_MULT_EVEN_EXPR,
   12050 					     stmt_info, vectype_out,
   12051 					     vectype_in, code1, code2,
   12052 					     multi_step_cvt, interm_types))
   12053         {
   12054           /* Elements in a vector with vect_used_by_reduction property cannot
   12055              be reordered if the use chain with this property does not have the
   12056              same operation.  One such an example is s += a * b, where elements
   12057              in a and b cannot be reordered.  Here we check if the vector defined
   12058              by STMT is only directly used in the reduction statement.  */
   12059 	  tree lhs = gimple_assign_lhs (stmt_info->stmt);
   12060 	  stmt_vec_info use_stmt_info = loop_info->lookup_single_use (lhs);
   12061 	  if (use_stmt_info
   12062 	      && STMT_VINFO_DEF_TYPE (use_stmt_info) == vect_reduction_def)
   12063 	    return true;
   12064         }
   12065       c1 = VEC_WIDEN_MULT_LO_EXPR;
   12066       c2 = VEC_WIDEN_MULT_HI_EXPR;
   12067       break;
   12068 
   12069     case DOT_PROD_EXPR:
   12070       c1 = DOT_PROD_EXPR;
   12071       c2 = DOT_PROD_EXPR;
   12072       break;
   12073 
   12074     case SAD_EXPR:
   12075       c1 = SAD_EXPR;
   12076       c2 = SAD_EXPR;
   12077       break;
   12078 
   12079     case VEC_WIDEN_MULT_EVEN_EXPR:
   12080       /* Support the recursion induced just above.  */
   12081       c1 = VEC_WIDEN_MULT_EVEN_EXPR;
   12082       c2 = VEC_WIDEN_MULT_ODD_EXPR;
   12083       break;
   12084 
   12085     case WIDEN_LSHIFT_EXPR:
   12086       c1 = VEC_WIDEN_LSHIFT_LO_EXPR;
   12087       c2 = VEC_WIDEN_LSHIFT_HI_EXPR;
   12088       break;
   12089 
   12090     case WIDEN_PLUS_EXPR:
   12091       c1 = VEC_WIDEN_PLUS_LO_EXPR;
   12092       c2 = VEC_WIDEN_PLUS_HI_EXPR;
   12093       break;
   12094 
   12095     case WIDEN_MINUS_EXPR:
   12096       c1 = VEC_WIDEN_MINUS_LO_EXPR;
   12097       c2 = VEC_WIDEN_MINUS_HI_EXPR;
   12098       break;
   12099 
   12100     CASE_CONVERT:
   12101       c1 = VEC_UNPACK_LO_EXPR;
   12102       c2 = VEC_UNPACK_HI_EXPR;
   12103       break;
   12104 
   12105     case FLOAT_EXPR:
   12106       c1 = VEC_UNPACK_FLOAT_LO_EXPR;
   12107       c2 = VEC_UNPACK_FLOAT_HI_EXPR;
   12108       break;
   12109 
   12110     case FIX_TRUNC_EXPR:
   12111       c1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
   12112       c2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
   12113       break;
   12114 
   12115     default:
   12116       gcc_unreachable ();
   12117     }
   12118 
   12119   if (BYTES_BIG_ENDIAN && c1 != VEC_WIDEN_MULT_EVEN_EXPR)
   12120     std::swap (c1, c2);
   12121 
   12122   if (code == FIX_TRUNC_EXPR)
   12123     {
   12124       /* The signedness is determined from output operand.  */
   12125       optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
   12126       optab2 = optab_for_tree_code (c2, vectype_out, optab_default);
   12127     }
   12128   else if (CONVERT_EXPR_CODE_P (code)
   12129 	   && VECTOR_BOOLEAN_TYPE_P (wide_vectype)
   12130 	   && VECTOR_BOOLEAN_TYPE_P (vectype)
   12131 	   && TYPE_MODE (wide_vectype) == TYPE_MODE (vectype)
   12132 	   && SCALAR_INT_MODE_P (TYPE_MODE (vectype)))
   12133     {
   12134       /* If the input and result modes are the same, a different optab
   12135 	 is needed where we pass in the number of units in vectype.  */
   12136       optab1 = vec_unpacks_sbool_lo_optab;
   12137       optab2 = vec_unpacks_sbool_hi_optab;
   12138     }
   12139   else
   12140     {
   12141       optab1 = optab_for_tree_code (c1, vectype, optab_default);
   12142       optab2 = optab_for_tree_code (c2, vectype, optab_default);
   12143     }
   12144 
   12145   if (!optab1 || !optab2)
   12146     return false;
   12147 
   12148   vec_mode = TYPE_MODE (vectype);
   12149   if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing
   12150        || (icode2 = optab_handler (optab2, vec_mode)) == CODE_FOR_nothing)
   12151     return false;
   12152 
   12153   *code1 = c1;
   12154   *code2 = c2;
   12155 
   12156   if (insn_data[icode1].operand[0].mode == TYPE_MODE (wide_vectype)
   12157       && insn_data[icode2].operand[0].mode == TYPE_MODE (wide_vectype))
   12158     {
   12159       if (!VECTOR_BOOLEAN_TYPE_P (vectype))
   12160 	return true;
   12161       /* For scalar masks we may have different boolean
   12162 	 vector types having the same QImode.  Thus we
   12163 	 add additional check for elements number.  */
   12164       if (known_eq (TYPE_VECTOR_SUBPARTS (vectype),
   12165 		    TYPE_VECTOR_SUBPARTS (wide_vectype) * 2))
   12166 	return true;
   12167     }
   12168 
   12169   /* Check if it's a multi-step conversion that can be done using intermediate
   12170      types.  */
   12171 
   12172   prev_type = vectype;
   12173   prev_mode = vec_mode;
   12174 
   12175   if (!CONVERT_EXPR_CODE_P (code))
   12176     return false;
   12177 
   12178   /* We assume here that there will not be more than MAX_INTERM_CVT_STEPS
   12179      intermediate steps in promotion sequence.  We try
   12180      MAX_INTERM_CVT_STEPS to get to NARROW_VECTYPE, and fail if we do
   12181      not.  */
   12182   interm_types->create (MAX_INTERM_CVT_STEPS);
   12183   for (i = 0; i < MAX_INTERM_CVT_STEPS; i++)
   12184     {
   12185       intermediate_mode = insn_data[icode1].operand[0].mode;
   12186       if (VECTOR_BOOLEAN_TYPE_P (prev_type))
   12187 	intermediate_type
   12188 	  = vect_halve_mask_nunits (prev_type, intermediate_mode);
   12189       else
   12190 	intermediate_type
   12191 	  = lang_hooks.types.type_for_mode (intermediate_mode,
   12192 					    TYPE_UNSIGNED (prev_type));
   12193 
   12194       if (VECTOR_BOOLEAN_TYPE_P (intermediate_type)
   12195 	  && VECTOR_BOOLEAN_TYPE_P (prev_type)
   12196 	  && intermediate_mode == prev_mode
   12197 	  && SCALAR_INT_MODE_P (prev_mode))
   12198 	{
   12199 	  /* If the input and result modes are the same, a different optab
   12200 	     is needed where we pass in the number of units in vectype.  */
   12201 	  optab3 = vec_unpacks_sbool_lo_optab;
   12202 	  optab4 = vec_unpacks_sbool_hi_optab;
   12203 	}
   12204       else
   12205 	{
   12206 	  optab3 = optab_for_tree_code (c1, intermediate_type, optab_default);
   12207 	  optab4 = optab_for_tree_code (c2, intermediate_type, optab_default);
   12208 	}
   12209 
   12210       if (!optab3 || !optab4
   12211           || (icode1 = optab_handler (optab1, prev_mode)) == CODE_FOR_nothing
   12212 	  || insn_data[icode1].operand[0].mode != intermediate_mode
   12213 	  || (icode2 = optab_handler (optab2, prev_mode)) == CODE_FOR_nothing
   12214 	  || insn_data[icode2].operand[0].mode != intermediate_mode
   12215 	  || ((icode1 = optab_handler (optab3, intermediate_mode))
   12216 	      == CODE_FOR_nothing)
   12217 	  || ((icode2 = optab_handler (optab4, intermediate_mode))
   12218 	      == CODE_FOR_nothing))
   12219 	break;
   12220 
   12221       interm_types->quick_push (intermediate_type);
   12222       (*multi_step_cvt)++;
   12223 
   12224       if (insn_data[icode1].operand[0].mode == TYPE_MODE (wide_vectype)
   12225 	  && insn_data[icode2].operand[0].mode == TYPE_MODE (wide_vectype))
   12226 	{
   12227 	  if (!VECTOR_BOOLEAN_TYPE_P (vectype))
   12228 	    return true;
   12229 	  if (known_eq (TYPE_VECTOR_SUBPARTS (intermediate_type),
   12230 			TYPE_VECTOR_SUBPARTS (wide_vectype) * 2))
   12231 	    return true;
   12232 	}
   12233 
   12234       prev_type = intermediate_type;
   12235       prev_mode = intermediate_mode;
   12236     }
   12237 
   12238   interm_types->release ();
   12239   return false;
   12240 }
   12241 
   12242 
   12243 /* Function supportable_narrowing_operation
   12244 
   12245    Check whether an operation represented by the code CODE is a
   12246    narrowing operation that is supported by the target platform in
   12247    vector form (i.e., when operating on arguments of type VECTYPE_IN
   12248    and producing a result of type VECTYPE_OUT).
   12249 
   12250    Narrowing operations we currently support are NOP (CONVERT), FIX_TRUNC
   12251    and FLOAT.  This function checks if these operations are supported by
   12252    the target platform directly via vector tree-codes.
   12253 
   12254    Output:
   12255    - CODE1 is the code of a vector operation to be used when
   12256    vectorizing the operation, if available.
   12257    - MULTI_STEP_CVT determines the number of required intermediate steps in
   12258    case of multi-step conversion (like int->short->char - in that case
   12259    MULTI_STEP_CVT will be 1).
   12260    - INTERM_TYPES contains the intermediate type required to perform the
   12261    narrowing operation (short in the above example).   */
   12262 
   12263 bool
   12264 supportable_narrowing_operation (enum tree_code code,
   12265 				 tree vectype_out, tree vectype_in,
   12266 				 enum tree_code *code1, int *multi_step_cvt,
   12267                                  vec<tree> *interm_types)
   12268 {
   12269   machine_mode vec_mode;
   12270   enum insn_code icode1;
   12271   optab optab1, interm_optab;
   12272   tree vectype = vectype_in;
   12273   tree narrow_vectype = vectype_out;
   12274   enum tree_code c1;
   12275   tree intermediate_type, prev_type;
   12276   machine_mode intermediate_mode, prev_mode;
   12277   int i;
   12278   unsigned HOST_WIDE_INT n_elts;
   12279   bool uns;
   12280 
   12281   *multi_step_cvt = 0;
   12282   switch (code)
   12283     {
   12284     CASE_CONVERT:
   12285       c1 = VEC_PACK_TRUNC_EXPR;
   12286       if (VECTOR_BOOLEAN_TYPE_P (narrow_vectype)
   12287 	  && VECTOR_BOOLEAN_TYPE_P (vectype)
   12288 	  && SCALAR_INT_MODE_P (TYPE_MODE (vectype))
   12289 	  && TYPE_VECTOR_SUBPARTS (vectype).is_constant (&n_elts)
   12290 	  && n_elts < BITS_PER_UNIT)
   12291 	optab1 = vec_pack_sbool_trunc_optab;
   12292       else
   12293 	optab1 = optab_for_tree_code (c1, vectype, optab_default);
   12294       break;
   12295 
   12296     case FIX_TRUNC_EXPR:
   12297       c1 = VEC_PACK_FIX_TRUNC_EXPR;
   12298       /* The signedness is determined from output operand.  */
   12299       optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
   12300       break;
   12301 
   12302     case FLOAT_EXPR:
   12303       c1 = VEC_PACK_FLOAT_EXPR;
   12304       optab1 = optab_for_tree_code (c1, vectype, optab_default);
   12305       break;
   12306 
   12307     default:
   12308       gcc_unreachable ();
   12309     }
   12310 
   12311   if (!optab1)
   12312     return false;
   12313 
   12314   vec_mode = TYPE_MODE (vectype);
   12315   if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing)
   12316     return false;
   12317 
   12318   *code1 = c1;
   12319 
   12320   if (insn_data[icode1].operand[0].mode == TYPE_MODE (narrow_vectype))
   12321     {
   12322       if (!VECTOR_BOOLEAN_TYPE_P (vectype))
   12323 	return true;
   12324       /* For scalar masks we may have different boolean
   12325 	 vector types having the same QImode.  Thus we
   12326 	 add additional check for elements number.  */
   12327       if (known_eq (TYPE_VECTOR_SUBPARTS (vectype) * 2,
   12328 		    TYPE_VECTOR_SUBPARTS (narrow_vectype)))
   12329 	return true;
   12330     }
   12331 
   12332   if (code == FLOAT_EXPR)
   12333     return false;
   12334 
   12335   /* Check if it's a multi-step conversion that can be done using intermediate
   12336      types.  */
   12337   prev_mode = vec_mode;
   12338   prev_type = vectype;
   12339   if (code == FIX_TRUNC_EXPR)
   12340     uns = TYPE_UNSIGNED (vectype_out);
   12341   else
   12342     uns = TYPE_UNSIGNED (vectype);
   12343 
   12344   /* For multi-step FIX_TRUNC_EXPR prefer signed floating to integer
   12345      conversion over unsigned, as unsigned FIX_TRUNC_EXPR is often more
   12346      costly than signed.  */
   12347   if (code == FIX_TRUNC_EXPR && uns)
   12348     {
   12349       enum insn_code icode2;
   12350 
   12351       intermediate_type
   12352 	= lang_hooks.types.type_for_mode (TYPE_MODE (vectype_out), 0);
   12353       interm_optab
   12354 	= optab_for_tree_code (c1, intermediate_type, optab_default);
   12355       if (interm_optab != unknown_optab
   12356 	  && (icode2 = optab_handler (optab1, vec_mode)) != CODE_FOR_nothing
   12357 	  && insn_data[icode1].operand[0].mode
   12358 	     == insn_data[icode2].operand[0].mode)
   12359 	{
   12360 	  uns = false;
   12361 	  optab1 = interm_optab;
   12362 	  icode1 = icode2;
   12363 	}
   12364     }
   12365 
   12366   /* We assume here that there will not be more than MAX_INTERM_CVT_STEPS
   12367      intermediate steps in promotion sequence.  We try
   12368      MAX_INTERM_CVT_STEPS to get to NARROW_VECTYPE, and fail if we do not.  */
   12369   interm_types->create (MAX_INTERM_CVT_STEPS);
   12370   for (i = 0; i < MAX_INTERM_CVT_STEPS; i++)
   12371     {
   12372       intermediate_mode = insn_data[icode1].operand[0].mode;
   12373       if (VECTOR_BOOLEAN_TYPE_P (prev_type))
   12374 	intermediate_type
   12375 	  = vect_double_mask_nunits (prev_type, intermediate_mode);
   12376       else
   12377 	intermediate_type
   12378 	  = lang_hooks.types.type_for_mode (intermediate_mode, uns);
   12379       if (VECTOR_BOOLEAN_TYPE_P (intermediate_type)
   12380 	  && VECTOR_BOOLEAN_TYPE_P (prev_type)
   12381 	  && SCALAR_INT_MODE_P (prev_mode)
   12382 	  && TYPE_VECTOR_SUBPARTS (intermediate_type).is_constant (&n_elts)
   12383 	  && n_elts < BITS_PER_UNIT)
   12384 	interm_optab = vec_pack_sbool_trunc_optab;
   12385       else
   12386 	interm_optab
   12387 	  = optab_for_tree_code (VEC_PACK_TRUNC_EXPR, intermediate_type,
   12388 				 optab_default);
   12389       if (!interm_optab
   12390 	  || ((icode1 = optab_handler (optab1, prev_mode)) == CODE_FOR_nothing)
   12391 	  || insn_data[icode1].operand[0].mode != intermediate_mode
   12392 	  || ((icode1 = optab_handler (interm_optab, intermediate_mode))
   12393 	      == CODE_FOR_nothing))
   12394 	break;
   12395 
   12396       interm_types->quick_push (intermediate_type);
   12397       (*multi_step_cvt)++;
   12398 
   12399       if (insn_data[icode1].operand[0].mode == TYPE_MODE (narrow_vectype))
   12400 	{
   12401 	  if (!VECTOR_BOOLEAN_TYPE_P (vectype))
   12402 	    return true;
   12403 	  if (known_eq (TYPE_VECTOR_SUBPARTS (intermediate_type) * 2,
   12404 			TYPE_VECTOR_SUBPARTS (narrow_vectype)))
   12405 	    return true;
   12406 	}
   12407 
   12408       prev_mode = intermediate_mode;
   12409       prev_type = intermediate_type;
   12410       optab1 = interm_optab;
   12411     }
   12412 
   12413   interm_types->release ();
   12414   return false;
   12415 }
   12416 
   12417 /* Generate and return a vector mask of MASK_TYPE such that
   12418    mask[I] is true iff J + START_INDEX < END_INDEX for all J <= I.
   12419    Add the statements to SEQ.  */
   12420 
   12421 tree
   12422 vect_gen_while (gimple_seq *seq, tree mask_type, tree start_index,
   12423 		tree end_index, const char *name)
   12424 {
   12425   tree cmp_type = TREE_TYPE (start_index);
   12426   gcc_checking_assert (direct_internal_fn_supported_p (IFN_WHILE_ULT,
   12427 						       cmp_type, mask_type,
   12428 						       OPTIMIZE_FOR_SPEED));
   12429   gcall *call = gimple_build_call_internal (IFN_WHILE_ULT, 3,
   12430 					    start_index, end_index,
   12431 					    build_zero_cst (mask_type));
   12432   tree tmp;
   12433   if (name)
   12434     tmp = make_temp_ssa_name (mask_type, NULL, name);
   12435   else
   12436     tmp = make_ssa_name (mask_type);
   12437   gimple_call_set_lhs (call, tmp);
   12438   gimple_seq_add_stmt (seq, call);
   12439   return tmp;
   12440 }
   12441 
   12442 /* Generate a vector mask of type MASK_TYPE for which index I is false iff
   12443    J + START_INDEX < END_INDEX for all J <= I.  Add the statements to SEQ.  */
   12444 
   12445 tree
   12446 vect_gen_while_not (gimple_seq *seq, tree mask_type, tree start_index,
   12447 		    tree end_index)
   12448 {
   12449   tree tmp = vect_gen_while (seq, mask_type, start_index, end_index);
   12450   return gimple_build (seq, BIT_NOT_EXPR, mask_type, tmp);
   12451 }
   12452 
   12453 /* Try to compute the vector types required to vectorize STMT_INFO,
   12454    returning true on success and false if vectorization isn't possible.
   12455    If GROUP_SIZE is nonzero and we're performing BB vectorization,
   12456    take sure that the number of elements in the vectors is no bigger
   12457    than GROUP_SIZE.
   12458 
   12459    On success:
   12460 
   12461    - Set *STMT_VECTYPE_OUT to:
   12462      - NULL_TREE if the statement doesn't need to be vectorized;
   12463      - the equivalent of STMT_VINFO_VECTYPE otherwise.
   12464 
   12465    - Set *NUNITS_VECTYPE_OUT to the vector type that contains the maximum
   12466      number of units needed to vectorize STMT_INFO, or NULL_TREE if the
   12467      statement does not help to determine the overall number of units.  */
   12468 
   12469 opt_result
   12470 vect_get_vector_types_for_stmt (vec_info *vinfo, stmt_vec_info stmt_info,
   12471 				tree *stmt_vectype_out,
   12472 				tree *nunits_vectype_out,
   12473 				unsigned int group_size)
   12474 {
   12475   gimple *stmt = stmt_info->stmt;
   12476 
   12477   /* For BB vectorization, we should always have a group size once we've
   12478      constructed the SLP tree; the only valid uses of zero GROUP_SIZEs
   12479      are tentative requests during things like early data reference
   12480      analysis and pattern recognition.  */
   12481   if (is_a <bb_vec_info> (vinfo))
   12482     gcc_assert (vinfo->slp_instances.is_empty () || group_size != 0);
   12483   else
   12484     group_size = 0;
   12485 
   12486   *stmt_vectype_out = NULL_TREE;
   12487   *nunits_vectype_out = NULL_TREE;
   12488 
   12489   if (gimple_get_lhs (stmt) == NULL_TREE
   12490       /* MASK_STORE has no lhs, but is ok.  */
   12491       && !gimple_call_internal_p (stmt, IFN_MASK_STORE))
   12492     {
   12493       if (is_a <gcall *> (stmt))
   12494 	{
   12495 	  /* Ignore calls with no lhs.  These must be calls to
   12496 	     #pragma omp simd functions, and what vectorization factor
   12497 	     it really needs can't be determined until
   12498 	     vectorizable_simd_clone_call.  */
   12499 	  if (dump_enabled_p ())
   12500 	    dump_printf_loc (MSG_NOTE, vect_location,
   12501 			     "defer to SIMD clone analysis.\n");
   12502 	  return opt_result::success ();
   12503 	}
   12504 
   12505       return opt_result::failure_at (stmt,
   12506 				     "not vectorized: irregular stmt.%G", stmt);
   12507     }
   12508 
   12509   tree vectype;
   12510   tree scalar_type = NULL_TREE;
   12511   if (group_size == 0 && STMT_VINFO_VECTYPE (stmt_info))
   12512     {
   12513       vectype = STMT_VINFO_VECTYPE (stmt_info);
   12514       if (dump_enabled_p ())
   12515 	dump_printf_loc (MSG_NOTE, vect_location,
   12516 			 "precomputed vectype: %T\n", vectype);
   12517     }
   12518   else if (vect_use_mask_type_p (stmt_info))
   12519     {
   12520       unsigned int precision = stmt_info->mask_precision;
   12521       scalar_type = build_nonstandard_integer_type (precision, 1);
   12522       vectype = get_mask_type_for_scalar_type (vinfo, scalar_type, group_size);
   12523       if (!vectype)
   12524 	return opt_result::failure_at (stmt, "not vectorized: unsupported"
   12525 				       " data-type %T\n", scalar_type);
   12526       if (dump_enabled_p ())
   12527 	dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype);
   12528     }
   12529   else
   12530     {
   12531       if (data_reference *dr = STMT_VINFO_DATA_REF (stmt_info))
   12532 	scalar_type = TREE_TYPE (DR_REF (dr));
   12533       else if (gimple_call_internal_p (stmt, IFN_MASK_STORE))
   12534 	scalar_type = TREE_TYPE (gimple_call_arg (stmt, 3));
   12535       else
   12536 	scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
   12537 
   12538       if (dump_enabled_p ())
   12539 	{
   12540 	  if (group_size)
   12541 	    dump_printf_loc (MSG_NOTE, vect_location,
   12542 			     "get vectype for scalar type (group size %d):"
   12543 			     " %T\n", group_size, scalar_type);
   12544 	  else
   12545 	    dump_printf_loc (MSG_NOTE, vect_location,
   12546 			     "get vectype for scalar type: %T\n", scalar_type);
   12547 	}
   12548       vectype = get_vectype_for_scalar_type (vinfo, scalar_type, group_size);
   12549       if (!vectype)
   12550 	return opt_result::failure_at (stmt,
   12551 				       "not vectorized:"
   12552 				       " unsupported data-type %T\n",
   12553 				       scalar_type);
   12554 
   12555       if (dump_enabled_p ())
   12556 	dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype);
   12557     }
   12558 
   12559   if (scalar_type && VECTOR_MODE_P (TYPE_MODE (scalar_type)))
   12560     return opt_result::failure_at (stmt,
   12561 				   "not vectorized: vector stmt in loop:%G",
   12562 				   stmt);
   12563 
   12564   *stmt_vectype_out = vectype;
   12565 
   12566   /* Don't try to compute scalar types if the stmt produces a boolean
   12567      vector; use the existing vector type instead.  */
   12568   tree nunits_vectype = vectype;
   12569   if (!VECTOR_BOOLEAN_TYPE_P (vectype))
   12570     {
   12571       /* The number of units is set according to the smallest scalar
   12572 	 type (or the largest vector size, but we only support one
   12573 	 vector size per vectorization).  */
   12574       scalar_type = vect_get_smallest_scalar_type (stmt_info,
   12575 						   TREE_TYPE (vectype));
   12576       if (scalar_type != TREE_TYPE (vectype))
   12577 	{
   12578 	  if (dump_enabled_p ())
   12579 	    dump_printf_loc (MSG_NOTE, vect_location,
   12580 			     "get vectype for smallest scalar type: %T\n",
   12581 			     scalar_type);
   12582 	  nunits_vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
   12583 							group_size);
   12584 	  if (!nunits_vectype)
   12585 	    return opt_result::failure_at
   12586 	      (stmt, "not vectorized: unsupported data-type %T\n",
   12587 	       scalar_type);
   12588 	  if (dump_enabled_p ())
   12589 	    dump_printf_loc (MSG_NOTE, vect_location, "nunits vectype: %T\n",
   12590 			     nunits_vectype);
   12591 	}
   12592     }
   12593 
   12594   if (!multiple_p (TYPE_VECTOR_SUBPARTS (nunits_vectype),
   12595 		   TYPE_VECTOR_SUBPARTS (*stmt_vectype_out)))
   12596     return opt_result::failure_at (stmt,
   12597 				   "Not vectorized: Incompatible number "
   12598 				   "of vector subparts between %T and %T\n",
   12599 				   nunits_vectype, *stmt_vectype_out);
   12600 
   12601   if (dump_enabled_p ())
   12602     {
   12603       dump_printf_loc (MSG_NOTE, vect_location, "nunits = ");
   12604       dump_dec (MSG_NOTE, TYPE_VECTOR_SUBPARTS (nunits_vectype));
   12605       dump_printf (MSG_NOTE, "\n");
   12606     }
   12607 
   12608   *nunits_vectype_out = nunits_vectype;
   12609   return opt_result::success ();
   12610 }
   12611 
   12612 /* Generate and return statement sequence that sets vector length LEN that is:
   12613 
   12614    min_of_start_and_end = min (START_INDEX, END_INDEX);
   12615    left_len = END_INDEX - min_of_start_and_end;
   12616    rhs = min (left_len, LEN_LIMIT);
   12617    LEN = rhs;
   12618 
   12619    Note: the cost of the code generated by this function is modeled
   12620    by vect_estimate_min_profitable_iters, so changes here may need
   12621    corresponding changes there.  */
   12622 
   12623 gimple_seq
   12624 vect_gen_len (tree len, tree start_index, tree end_index, tree len_limit)
   12625 {
   12626   gimple_seq stmts = NULL;
   12627   tree len_type = TREE_TYPE (len);
   12628   gcc_assert (TREE_TYPE (start_index) == len_type);
   12629 
   12630   tree min = gimple_build (&stmts, MIN_EXPR, len_type, start_index, end_index);
   12631   tree left_len = gimple_build (&stmts, MINUS_EXPR, len_type, end_index, min);
   12632   tree rhs = gimple_build (&stmts, MIN_EXPR, len_type, left_len, len_limit);
   12633   gimple* stmt = gimple_build_assign (len, rhs);
   12634   gimple_seq_add_stmt (&stmts, stmt);
   12635 
   12636   return stmts;
   12637 }
   12638 
   12639