LCOV - code coverage report
Current view: top level - gcc - tree-vect-patterns.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 88.9 % 3127 2780
Test Date: 2026-09-19 16:22:48 Functions: 97.6 % 85 83
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Analysis Utilities for Loop Vectorization.
       2              :    Copyright (C) 2006-2026 Free Software Foundation, Inc.
       3              :    Contributed by Dorit Nuzman <dorit@il.ibm.com>
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "rtl.h"
      26              : #include "tree.h"
      27              : #include "gimple.h"
      28              : #include "gimple-iterator.h"
      29              : #include "gimple-fold.h"
      30              : #include "ssa.h"
      31              : #include "expmed.h"
      32              : #include "optabs-tree.h"
      33              : #include "insn-config.h"
      34              : #include "recog.h"            /* FIXME: for insn_data */
      35              : #include "fold-const.h"
      36              : #include "stor-layout.h"
      37              : #include "tree-eh.h"
      38              : #include "gimplify.h"
      39              : #include "gimple-iterator.h"
      40              : #include "gimple-fold.h"
      41              : #include "gimplify-me.h"
      42              : #include "cfgloop.h"
      43              : #include "tree-vectorizer.h"
      44              : #include "dumpfile.h"
      45              : #include "builtins.h"
      46              : #include "internal-fn.h"
      47              : #include "case-cfn-macros.h"
      48              : #include "fold-const-call.h"
      49              : #include "attribs.h"
      50              : #include "cgraph.h"
      51              : #include "omp-simd-clone.h"
      52              : #include "predict.h"
      53              : #include "tree-vector-builder.h"
      54              : #include "tree-ssa-loop-ivopts.h"
      55              : #include "vec-perm-indices.h"
      56              : #include "gimple-range.h"
      57              : #include "alias.h"
      58              : 
      59              : 
      60              : /* TODO:  Note the vectorizer still builds COND_EXPRs with GENERIC compares
      61              :    in the first operand.  Disentangling this is future work, the
      62              :    IL is properly transferred to VEC_COND_EXPRs with separate compares.  */
      63              : 
      64              : 
      65              : /* Return true if we have a useful VR_RANGE range for VAR, storing it
      66              :    in *MIN_VALUE and *MAX_VALUE if so.  Note the range in the dump files.  */
      67              : 
      68              : bool
      69     12620512 : vect_get_range_info (tree var, wide_int *min_value, wide_int *max_value)
      70              : {
      71     12620512 :   int_range_max vr;
      72     12620512 :   tree vr_min, vr_max;
      73     25241024 :   get_range_query (cfun)->range_of_expr (vr, var);
      74     12620512 :   if (vr.undefined_p ())
      75           53 :     vr.set_varying (TREE_TYPE (var));
      76     12620512 :   value_range_kind vr_type = get_legacy_range (vr, vr_min, vr_max);
      77     12620512 :   *min_value = wi::to_wide (vr_min);
      78     12620512 :   *max_value = wi::to_wide (vr_max);
      79     12620512 :   wide_int nonzero = get_nonzero_bits (var);
      80     12620512 :   signop sgn = TYPE_SIGN (TREE_TYPE (var));
      81     12620512 :   if (intersect_range_with_nonzero_bits (vr_type, min_value, max_value,
      82              :                                          nonzero, sgn) == VR_RANGE)
      83              :     {
      84      6186070 :       if (dump_enabled_p ())
      85              :         {
      86        90648 :           dump_generic_expr_loc (MSG_NOTE, vect_location, TDF_SLIM, var);
      87        90648 :           dump_printf (MSG_NOTE, " has range [");
      88        90648 :           dump_hex (MSG_NOTE, *min_value);
      89        90648 :           dump_printf (MSG_NOTE, ", ");
      90        90648 :           dump_hex (MSG_NOTE, *max_value);
      91        90648 :           dump_printf (MSG_NOTE, "]\n");
      92              :         }
      93              :       return true;
      94              :     }
      95              :   else
      96              :     {
      97      6434442 :       if (dump_enabled_p ())
      98              :         {
      99        68738 :           dump_generic_expr_loc (MSG_NOTE, vect_location, TDF_SLIM, var);
     100        68738 :           dump_printf (MSG_NOTE, " has no range info\n");
     101              :         }
     102              :       return false;
     103              :     }
     104     12620512 : }
     105              : 
     106              : /* Report that we've found an instance of pattern PATTERN in
     107              :    statement STMT.  */
     108              : 
     109              : static void
     110      1328601 : vect_pattern_detected (const char *name, gimple *stmt)
     111              : {
     112      1328601 :   if (dump_enabled_p ())
     113        26326 :     dump_printf_loc (MSG_NOTE, vect_location, "%s: detected: %G", name, stmt);
     114      1328601 : }
     115              : 
     116              : /* Associate pattern statement PATTERN_STMT with ORIG_STMT_INFO and
     117              :    return the pattern statement's stmt_vec_info.  Set its vector type to
     118              :    VECTYPE if it doesn't have one already.  */
     119              : 
     120              : static stmt_vec_info
     121      2515146 : vect_init_pattern_stmt (vec_info *vinfo, gimple *pattern_stmt,
     122              :                         stmt_vec_info orig_stmt_info, tree vectype)
     123              : {
     124      2515146 :   stmt_vec_info pattern_stmt_info = vinfo->lookup_stmt (pattern_stmt);
     125      2515146 :   if (pattern_stmt_info == NULL)
     126      1330582 :     pattern_stmt_info = vinfo->add_stmt (pattern_stmt);
     127      2515146 :   gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt_info->stmt));
     128              : 
     129      2515146 :   pattern_stmt_info->pattern_stmt_p = true;
     130      2515146 :   STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt_info;
     131      2515146 :   STMT_VINFO_DEF_TYPE (pattern_stmt_info)
     132      2515146 :     = STMT_VINFO_DEF_TYPE (orig_stmt_info);
     133      2515146 :   if (!STMT_VINFO_VECTYPE (pattern_stmt_info))
     134              :     {
     135      2218483 :       gcc_assert (!vectype
     136              :                   || is_a <gcond *> (pattern_stmt)
     137              :                   || (VECTOR_BOOLEAN_TYPE_P (vectype)
     138              :                       == vect_use_mask_type_p (orig_stmt_info)));
     139      1341116 :       STMT_VINFO_VECTYPE (pattern_stmt_info) = vectype;
     140      1341116 :       pattern_stmt_info->mask_precision = orig_stmt_info->mask_precision;
     141      1341116 :       if (dump_enabled_p ())
     142              :         {
     143        26464 :           if (pattern_stmt_info->mask_precision == ~0U)
     144           63 :             dump_printf_loc (MSG_NOTE, vect_location,
     145              :                              "using normal nonmask vectors for %G",
     146              :                              pattern_stmt_info->stmt);
     147              :           else
     148        26401 :             dump_printf_loc (MSG_NOTE, vect_location,
     149              :                              "using boolean precision %d for %G",
     150              :                              pattern_stmt_info->mask_precision,
     151              :                              pattern_stmt_info->stmt);
     152              :         }
     153              :     }
     154      2515146 :   return pattern_stmt_info;
     155              : }
     156              : 
     157              : /* Set the pattern statement of ORIG_STMT_INFO to PATTERN_STMT.
     158              :    Also set the vector type of PATTERN_STMT to VECTYPE, if it doesn't
     159              :    have one already.  */
     160              : 
     161              : static void
     162      1076129 : vect_set_pattern_stmt (vec_info *vinfo, gimple *pattern_stmt,
     163              :                        stmt_vec_info orig_stmt_info, tree vectype)
     164              : {
     165      1076129 :   STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
     166      1076129 :   STMT_VINFO_RELATED_STMT (orig_stmt_info)
     167            0 :     = vect_init_pattern_stmt (vinfo, pattern_stmt, orig_stmt_info, vectype);
     168            0 : }
     169              : 
     170              : /* Add NEW_STMT to STMT_INFO's pattern definition statements.  If VECTYPE
     171              :    is nonnull, record that NEW_STMT's vector type is VECTYPE, which might
     172              :    be different from the vector type of the final pattern statement.
     173              :    If VECTYPE is a mask type, SCALAR_TYPE_FOR_MASK is the scalar type
     174              :    from which it was derived.  */
     175              : 
     176              : static inline void
     177      1400229 : append_pattern_def_seq (vec_info *vinfo,
     178              :                         stmt_vec_info stmt_info, gimple *new_stmt,
     179              :                         tree vectype = NULL_TREE,
     180              :                         tree scalar_type_for_mask = NULL_TREE)
     181              : {
     182      2122421 :   gcc_assert (!scalar_type_for_mask
     183              :               == (!vectype || !VECTOR_BOOLEAN_TYPE_P (vectype)));
     184      1400229 :   if (vectype)
     185              :     {
     186      1174248 :       stmt_vec_info new_stmt_info = vinfo->add_stmt (new_stmt);
     187      1174248 :       STMT_VINFO_VECTYPE (new_stmt_info) = vectype;
     188      1174248 :       if (scalar_type_for_mask)
     189              :         {
     190       678037 :           new_stmt_info->mask_precision
     191       678037 :             = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (scalar_type_for_mask));
     192       678037 :           if (dump_enabled_p ())
     193              :             {
     194         6249 :               if (new_stmt_info->mask_precision == ~0U)
     195              :                 dump_printf_loc (MSG_NOTE, vect_location,
     196              :                                  "using normal nonmask vectors for %G",
     197              :                                  new_stmt_info->stmt);
     198              :               else
     199         6249 :                 dump_printf_loc (MSG_NOTE, vect_location,
     200              :                                  "using boolean precision %d for %G",
     201              :                                  new_stmt_info->mask_precision,
     202              :                                  new_stmt_info->stmt);
     203              :             }
     204              :         }
     205              :     }
     206      1400229 :   gimple_seq_add_stmt_without_update (&STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
     207              :                                       new_stmt);
     208      1400229 : }
     209              : 
     210              : 
     211              : /* Add NEW_STMT to VINFO's invariant pattern definition statements.  These
     212              :    statements are not vectorized but are materialized as scalar in the loop
     213              :    preheader.  */
     214              : 
     215              : static inline void
     216         1383 : append_inv_pattern_def_seq (vec_info *vinfo, gimple *new_stmt)
     217              : {
     218         1383 :   gimple_seq_add_stmt_without_update (&vinfo->inv_pattern_def_seq, new_stmt);
     219              : }
     220              : 
     221              : /* The caller wants to perform new operations on vect_external variable
     222              :    VAR, so that the result of the operations would also be vect_external.
     223              :    Return the edge on which the operations can be performed, if one exists.
     224              :    Return null if the operations should instead be treated as part of
     225              :    the pattern that needs them.  */
     226              : 
     227              : static edge
     228         8611 : vect_get_external_def_edge (vec_info *vinfo, tree var)
     229              : {
     230         8611 :   edge e = NULL;
     231         8611 :   if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
     232              :     {
     233          769 :       e = loop_preheader_edge (loop_vinfo->loop);
     234          769 :       if (!SSA_NAME_IS_DEFAULT_DEF (var))
     235              :         {
     236          573 :           basic_block bb = gimple_bb (SSA_NAME_DEF_STMT (var));
     237          573 :           if (bb == NULL
     238          573 :               || !dominated_by_p (CDI_DOMINATORS, e->dest, bb))
     239              :             e = NULL;
     240              :         }
     241              :     }
     242         8611 :   return e;
     243              : }
     244              : 
     245              : /* Return true if the target supports a vector version of CODE,
     246              :    where CODE is known to map to a direct optab with the given SUBTYPE.
     247              :    ITYPE specifies the type of (some of) the scalar inputs and OTYPE
     248              :    specifies the type of the scalar result.
     249              : 
     250              :    If CODE allows the inputs and outputs to have different type
     251              :    (such as for WIDEN_SUM_EXPR), it is the input mode rather
     252              :    than the output mode that determines the appropriate target pattern.
     253              :    Operand 0 of the target pattern then specifies the mode that the output
     254              :    must have.
     255              : 
     256              :    When returning true, set *VECOTYPE_OUT to the vector version of OTYPE.
     257              :    Also set *VECITYPE_OUT to the vector version of ITYPE if VECITYPE_OUT
     258              :    is nonnull.  */
     259              : 
     260              : static bool
     261          865 : vect_supportable_direct_optab_p (vec_info *vinfo, tree otype, tree_code code,
     262              :                                  tree itype, tree *vecotype_out,
     263              :                                  tree *vecitype_out = NULL,
     264              :                                  enum optab_subtype subtype = optab_default)
     265              : {
     266          865 :   tree vecitype = get_vectype_for_scalar_type (vinfo, itype);
     267          865 :   if (!vecitype)
     268              :     return false;
     269              : 
     270          863 :   tree vecotype = get_vectype_for_scalar_type (vinfo, otype);
     271          863 :   if (!vecotype)
     272              :     return false;
     273              : 
     274          863 :   optab optab = optab_for_tree_code (code, vecitype, subtype);
     275          863 :   if (!optab)
     276              :     return false;
     277              : 
     278          863 :   insn_code icode = optab_handler (optab, TYPE_MODE (vecitype));
     279          863 :   if (icode == CODE_FOR_nothing
     280          863 :       || insn_data[icode].operand[0].mode != TYPE_MODE (vecotype))
     281              :     return false;
     282              : 
     283          469 :   *vecotype_out = vecotype;
     284          469 :   if (vecitype_out)
     285          460 :     *vecitype_out = vecitype;
     286              :   return true;
     287              : }
     288              : 
     289              : /* Return true if the target supports a vector version of CODE,
     290              :    where CODE is known to map to a conversion optab with the given SUBTYPE.
     291              :    ITYPE specifies the type of (some of) the scalar inputs and OTYPE
     292              :    specifies the type of the scalar result.
     293              : 
     294              :    When returning true, set *VECOTYPE_OUT to the vector version of OTYPE.
     295              :    Also set *VECITYPE_OUT to the vector version of ITYPE if VECITYPE_OUT
     296              :    is nonnull.  */
     297              : 
     298              : static bool
     299         5660 : vect_supportable_conv_optab_p (vec_info *vinfo, tree otype, tree_code code,
     300              :                                  tree itype, tree *vecotype_out,
     301              :                                  tree *vecitype_out = NULL,
     302              :                                  enum optab_subtype subtype = optab_default)
     303              : {
     304         5660 :   tree vecitype = get_vectype_for_scalar_type (vinfo, itype);
     305         5660 :   tree vecotype = get_vectype_for_scalar_type (vinfo, otype);
     306         5660 :   if (!vecitype || !vecotype)
     307              :     return false;
     308              : 
     309         5136 :   if (!directly_supported_p (code, vecotype, vecitype, subtype))
     310              :     return false;
     311              : 
     312          732 :   *vecotype_out = vecotype;
     313          732 :   if (vecitype_out)
     314          732 :     *vecitype_out = vecitype;
     315              :   return true;
     316              : }
     317              : 
     318              : /* Round bit precision PRECISION up to a full element.  */
     319              : 
     320              : static unsigned int
     321      3299929 : vect_element_precision (unsigned int precision)
     322              : {
     323            0 :   precision = 1 << ceil_log2 (precision);
     324      4958926 :   return MAX (precision, BITS_PER_UNIT);
     325              : }
     326              : 
     327              : /* If OP is defined by a statement that's being considered for vectorization,
     328              :    return information about that statement, otherwise return NULL.  */
     329              : 
     330              : static stmt_vec_info
     331       376081 : vect_get_internal_def (vec_info *vinfo, tree op)
     332              : {
     333       376081 :   stmt_vec_info def_stmt_info = vinfo->lookup_def (op);
     334       376081 :   if (def_stmt_info
     335       362318 :       && STMT_VINFO_DEF_TYPE (def_stmt_info) == vect_internal_def)
     336       344295 :     return vect_stmt_to_vectorize (def_stmt_info);
     337              :   return NULL;
     338              : }
     339              : 
     340              : /* Holds information about an input operand after some sign changes
     341              :    and type promotions have been peeled away.  */
     342              : class vect_unpromoted_value {
     343              : public:
     344              :   vect_unpromoted_value ();
     345              : 
     346              :   void set_op (tree, vect_def_type, stmt_vec_info = NULL);
     347              : 
     348              :   /* The value obtained after peeling away zero or more casts.  */
     349              :   tree op;
     350              : 
     351              :   /* The type of OP.  */
     352              :   tree type;
     353              : 
     354              :   /* The definition type of OP.  */
     355              :   vect_def_type dt;
     356              : 
     357              :   /* If OP is the result of peeling at least one cast, and if the cast
     358              :      of OP itself is a vectorizable statement, CASTER identifies that
     359              :      statement, otherwise it is null.  */
     360              :   stmt_vec_info caster;
     361              : };
     362              : 
     363    308955795 : inline vect_unpromoted_value::vect_unpromoted_value ()
     364    308955795 :   : op (NULL_TREE),
     365    308955795 :     type (NULL_TREE),
     366    308955795 :     dt (vect_uninitialized_def),
     367      3304151 :     caster (NULL)
     368              : {
     369              : }
     370              : 
     371              : /* Set the operand to OP_IN, its definition type to DT_IN, and the
     372              :    statement that casts it to CASTER_IN.  */
     373              : 
     374              : inline void
     375     11737986 : vect_unpromoted_value::set_op (tree op_in, vect_def_type dt_in,
     376              :                                stmt_vec_info caster_in)
     377              : {
     378     11737986 :   op = op_in;
     379     11737986 :   type = TREE_TYPE (op);
     380     11737986 :   dt = dt_in;
     381     11737986 :   caster = caster_in;
     382     11737986 : }
     383              : 
     384              : /* If OP is a vectorizable SSA name, strip a sequence of integer conversions
     385              :    to reach some vectorizable inner operand OP', continuing as long as it
     386              :    is possible to convert OP' back to OP using a possible sign change
     387              :    followed by a possible promotion P.  Return this OP', or null if OP is
     388              :    not a vectorizable SSA name.  If there is a promotion P, describe its
     389              :    input in UNPROM, otherwise describe OP' in UNPROM.  If SINGLE_USE_P
     390              :    is nonnull, set *SINGLE_USE_P to false if any of the SSA names involved
     391              :    have more than one user.
     392              : 
     393              :    A successful return means that it is possible to go from OP' to OP
     394              :    via UNPROM.  The cast from OP' to UNPROM is at most a sign change,
     395              :    whereas the cast from UNPROM to OP might be a promotion, a sign
     396              :    change, or a nop.
     397              : 
     398              :    E.g. say we have:
     399              : 
     400              :        signed short *ptr = ...;
     401              :        signed short C = *ptr;
     402              :        unsigned short B = (unsigned short) C;    // sign change
     403              :        signed int A = (signed int) B;            // unsigned promotion
     404              :        ...possible other uses of A...
     405              :        unsigned int OP = (unsigned int) A;       // sign change
     406              : 
     407              :    In this case it's possible to go directly from C to OP using:
     408              : 
     409              :        OP = (unsigned int) (unsigned short) C;
     410              :             +------------+ +--------------+
     411              :                promotion      sign change
     412              : 
     413              :    so OP' would be C.  The input to the promotion is B, so UNPROM
     414              :    would describe B.  */
     415              : 
     416              : static tree
     417      8645393 : vect_look_through_possible_promotion (vec_info *vinfo, tree op,
     418              :                                       vect_unpromoted_value *unprom,
     419              :                                       bool *single_use_p = NULL)
     420              : {
     421      8645393 :   tree op_type = TREE_TYPE (op);
     422      8645393 :   if (!INTEGRAL_TYPE_P (op_type))
     423              :     return NULL_TREE;
     424              : 
     425      8594141 :   tree res = NULL_TREE;
     426      8594141 :   unsigned int orig_precision = TYPE_PRECISION (op_type);
     427      8594141 :   unsigned int min_precision = orig_precision;
     428      8594141 :   stmt_vec_info caster = NULL;
     429     10290523 :   while (TREE_CODE (op) == SSA_NAME && INTEGRAL_TYPE_P (op_type))
     430              :     {
     431              :       /* See whether OP is simple enough to vectorize.  */
     432     10078980 :       stmt_vec_info def_stmt_info;
     433     10078980 :       gimple *def_stmt;
     434     10078980 :       vect_def_type dt;
     435     10078980 :       if (!vect_is_simple_use (op, vinfo, &dt, &def_stmt_info, &def_stmt))
     436              :         break;
     437              : 
     438              :       /* If OP is the input of a demotion, skip over it to see whether
     439              :          OP is itself the result of a promotion.  If so, the combined
     440              :          effect of the promotion and the demotion might fit the required
     441              :          pattern, otherwise neither operation fits.
     442              : 
     443              :          This copes with cases such as the result of an arithmetic
     444              :          operation being truncated before being stored, and where that
     445              :          arithmetic operation has been recognized as an over-widened one.  */
     446     10062087 :       if (TYPE_PRECISION (op_type) <= min_precision)
     447              :         {
     448              :           /* Use OP as the UNPROM described above if we haven't yet
     449              :              found a promotion, or if using the new input preserves the
     450              :              sign of the previous promotion.  */
     451      9930577 :           if (!res
     452      1454122 :               || TYPE_PRECISION (unprom->type) == orig_precision
     453        38910 :               || TYPE_SIGN (unprom->type) == TYPE_SIGN (op_type)
     454      9966159 :               || (TYPE_UNSIGNED (op_type)
     455        24951 :                   && TYPE_PRECISION (op_type) < TYPE_PRECISION (unprom->type)))
     456              :             {
     457      9895425 :               unprom->set_op (op, dt, caster);
     458      9895425 :               min_precision = TYPE_PRECISION (op_type);
     459              :             }
     460              :           /* Stop if we've already seen a promotion and if this
     461              :              conversion does more than change the sign.  */
     462        35152 :           else if (TYPE_PRECISION (op_type)
     463        35152 :                    != TYPE_PRECISION (unprom->type))
     464              :             break;
     465              : 
     466              :           /* The sequence now extends to OP.  */
     467              :           res = op;
     468              :         }
     469              : 
     470              :       /* See whether OP is defined by a cast.  Record it as CASTER if
     471              :          the cast is potentially vectorizable.  */
     472     10062057 :       if (!def_stmt)
     473              :         break;
     474      9848657 :       caster = def_stmt_info;
     475              : 
     476              :       /* Ignore pattern statements, since we don't link uses for them.  */
     477      9848657 :       if (caster
     478      9848657 :           && single_use_p
     479      2004873 :           && !STMT_VINFO_RELATED_STMT (caster)
     480     11707003 :           && !has_single_use (res))
     481      1112556 :         *single_use_p = false;
     482              : 
     483     14602583 :       gassign *assign = dyn_cast <gassign *> (def_stmt);
     484      6219985 :       if (!assign || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
     485              :         break;
     486              : 
     487              :       /* Continue with the input to the cast.  */
     488      1696382 :       op = gimple_assign_rhs1 (def_stmt);
     489      1696382 :       op_type = TREE_TYPE (op);
     490              :     }
     491              :   return res;
     492              : }
     493              : 
     494              : /* OP is an integer operand to an operation that returns TYPE, and we
     495              :    want to treat the operation as a widening one.  So far we can treat
     496              :    it as widening from *COMMON_TYPE.
     497              : 
     498              :    Return true if OP is suitable for such a widening operation,
     499              :    either widening from *COMMON_TYPE or from some supertype of it.
     500              :    Update *COMMON_TYPE to the supertype in the latter case.
     501              : 
     502              :    SHIFT_P is true if OP is a shift amount.  */
     503              : 
     504              : static bool
     505       328884 : vect_joust_widened_integer (tree type, bool shift_p, tree op,
     506              :                             tree *common_type)
     507              : {
     508              :   /* Calculate the minimum precision required by OP, without changing
     509              :      the sign of either operand.  */
     510       328884 :   unsigned int precision;
     511       328884 :   if (shift_p)
     512              :     {
     513        13324 :       if (!wi::leu_p (wi::to_widest (op), TYPE_PRECISION (type) / 2))
     514              :         return false;
     515        10724 :       precision = TREE_INT_CST_LOW (op);
     516              :     }
     517              :   else
     518              :     {
     519       315560 :       precision = wi::min_precision (wi::to_widest (op),
     520       315560 :                                      TYPE_SIGN (*common_type));
     521       315560 :       if (precision * 2 > TYPE_PRECISION (type))
     522              :         return false;
     523              :     }
     524              : 
     525              :   /* If OP requires a wider type, switch to that type.  The checks
     526              :      above ensure that this is still narrower than the result.  */
     527       311535 :   precision = vect_element_precision (precision);
     528       311535 :   if (TYPE_PRECISION (*common_type) < precision)
     529         6530 :     *common_type = build_nonstandard_integer_type
     530         6530 :       (precision, TYPE_UNSIGNED (*common_type));
     531              :   return true;
     532              : }
     533              : 
     534              : /* Return true if the common supertype of NEW_TYPE and *COMMON_TYPE
     535              :    is narrower than type, storing the supertype in *COMMON_TYPE if so.  */
     536              : 
     537              : static bool
     538        47543 : vect_joust_widened_type (tree type, tree new_type, tree *common_type)
     539              : {
     540        47543 :   if (types_compatible_p (*common_type, new_type))
     541              :     return true;
     542              : 
     543              :   /* See if *COMMON_TYPE can hold all values of NEW_TYPE.  */
     544         3976 :   if ((TYPE_PRECISION (new_type) < TYPE_PRECISION (*common_type))
     545         3976 :       && (TYPE_UNSIGNED (new_type) || !TYPE_UNSIGNED (*common_type)))
     546              :     return true;
     547              : 
     548              :   /* See if NEW_TYPE can hold all values of *COMMON_TYPE.  */
     549         3221 :   if (TYPE_PRECISION (*common_type) < TYPE_PRECISION (new_type)
     550         3221 :       && (TYPE_UNSIGNED (*common_type) || !TYPE_UNSIGNED (new_type)))
     551              :     {
     552          382 :       *common_type = new_type;
     553          382 :       return true;
     554              :     }
     555              : 
     556              :   /* We have mismatched signs, with the signed type being
     557              :      no wider than the unsigned type.  In this case we need
     558              :      a wider signed type.  */
     559         2839 :   unsigned int precision = MAX (TYPE_PRECISION (*common_type),
     560              :                                 TYPE_PRECISION (new_type));
     561         2839 :   precision *= 2;
     562              : 
     563         2839 :   if (precision * 2 > TYPE_PRECISION (type))
     564              :     return false;
     565              : 
     566           40 :   *common_type = build_nonstandard_integer_type (precision, false);
     567           40 :   return true;
     568              : }
     569              : 
     570              : /* Check whether STMT_INFO can be viewed as a tree of integer operations
     571              :    in which each node either performs CODE or WIDENED_CODE, and where
     572              :    each leaf operand is narrower than the result of STMT_INFO.  MAX_NOPS
     573              :    specifies the maximum number of leaf operands.  SHIFT_P says whether
     574              :    CODE and WIDENED_CODE are some sort of shift.
     575              : 
     576              :    If STMT_INFO is such a tree, return the number of leaf operands
     577              :    and describe them in UNPROM[0] onwards.  Also set *COMMON_TYPE
     578              :    to a type that (a) is narrower than the result of STMT_INFO and
     579              :    (b) can hold all leaf operand values.
     580              : 
     581              :    If SUBTYPE then allow that the signs of the operands
     582              :    may differ in signs but not in precision.  SUBTYPE is updated to reflect
     583              :    this.
     584              : 
     585              :    Return 0 if STMT_INFO isn't such a tree, or if no such COMMON_TYPE
     586              :    exists.  */
     587              : 
     588              : static unsigned int
     589    129911421 : vect_widened_op_tree (vec_info *vinfo, stmt_vec_info stmt_info, tree_code code,
     590              :                       code_helper widened_code, bool shift_p,
     591              :                       unsigned int max_nops,
     592              :                       vect_unpromoted_value *unprom, tree *common_type,
     593              :                       enum optab_subtype *subtype = NULL)
     594              : {
     595              :   /* Check for an integer operation with the right code.  */
     596    129911421 :   gimple* stmt = stmt_info->stmt;
     597    129911421 :   if (!(is_gimple_assign (stmt) || is_gimple_call (stmt)))
     598              :     return 0;
     599              : 
     600    106753532 :   code_helper rhs_code;
     601    106753532 :   if (is_gimple_assign (stmt))
     602     91525016 :     rhs_code = gimple_assign_rhs_code (stmt);
     603     15228516 :   else if (is_gimple_call (stmt))
     604     15228516 :     rhs_code = gimple_call_combined_fn (stmt);
     605              :   else
     606              :     return 0;
     607              : 
     608    106753532 :   if (rhs_code != code
     609    106753532 :       && rhs_code != widened_code)
     610              :     return 0;
     611              : 
     612      6767747 :   tree lhs = gimple_get_lhs (stmt);
     613      6767747 :   tree type = TREE_TYPE (lhs);
     614      6767747 :   if (!INTEGRAL_TYPE_P (type))
     615              :     return 0;
     616              : 
     617              :   /* Assume that both operands will be leaf operands.  */
     618      5882013 :   max_nops -= 2;
     619              : 
     620              :   /* Check the operands.  */
     621      5882013 :   unsigned int next_op = 0;
     622      6695192 :   for (unsigned int i = 0; i < 2; ++i)
     623              :     {
     624      6338508 :       vect_unpromoted_value *this_unprom = &unprom[next_op];
     625      6338508 :       unsigned int nops = 1;
     626      6338508 :       tree op = gimple_arg (stmt, i);
     627      6338508 :       if (i == 1 && TREE_CODE (op) == INTEGER_CST)
     628              :         {
     629              :           /* We already have a common type from earlier operands.
     630              :              Update it to account for OP.  */
     631       328884 :           this_unprom->set_op (op, vect_constant_def);
     632       328884 :           if (!vect_joust_widened_integer (type, shift_p, op, common_type))
     633              :             return 0;
     634              :         }
     635              :       else
     636              :         {
     637              :           /* Only allow shifts by constants.  */
     638      6009624 :           if (shift_p && i == 1)
     639              :             return 0;
     640              : 
     641      6003536 :           if (rhs_code != code)
     642              :             {
     643              :               /* If rhs_code is widened_code, don't look through further
     644              :                  possible promotions, there is a promotion already embedded
     645              :                  in the WIDEN_*_EXPR.  */
     646         1710 :               if (TREE_CODE (op) != SSA_NAME
     647         1710 :                   || !INTEGRAL_TYPE_P (TREE_TYPE (op)))
     648            0 :                 return 0;
     649              : 
     650         1710 :               stmt_vec_info def_stmt_info;
     651         1710 :               gimple *def_stmt;
     652         1710 :               vect_def_type dt;
     653         1710 :               if (!vect_is_simple_use (op, vinfo, &dt, &def_stmt_info,
     654              :                                        &def_stmt))
     655              :                 return 0;
     656         1710 :               this_unprom->set_op (op, dt, NULL);
     657              :             }
     658      6001826 :           else if (!vect_look_through_possible_promotion (vinfo, op,
     659              :                                                           this_unprom))
     660              :             return 0;
     661              : 
     662      5890184 :           if (TYPE_PRECISION (this_unprom->type) == TYPE_PRECISION (type))
     663              :             {
     664              :               /* The operand isn't widened.  If STMT_INFO has the code
     665              :                  for an unwidened operation, recursively check whether
     666              :                  this operand is a node of the tree.  */
     667      5382036 :               if (rhs_code != code
     668      5382036 :                   || max_nops == 0
     669      5382561 :                   || this_unprom->dt != vect_internal_def)
     670              :                 return 0;
     671              : 
     672              :               /* Give back the leaf slot allocated above now that we're
     673              :                  not treating this as a leaf operand.  */
     674          525 :               max_nops += 1;
     675              : 
     676              :               /* Recursively process the definition of the operand.  */
     677          525 :               stmt_vec_info def_stmt_info
     678          525 :                 = vect_get_internal_def (vinfo, this_unprom->op);
     679              : 
     680          525 :               nops = vect_widened_op_tree (vinfo, def_stmt_info, code,
     681              :                                            widened_code, shift_p, max_nops,
     682              :                                            this_unprom, common_type,
     683              :                                            subtype);
     684          525 :               if (nops == 0)
     685              :                 return 0;
     686              : 
     687          367 :               max_nops -= nops;
     688              :             }
     689              :           else
     690              :             {
     691              :               /* Make sure that the operand is narrower than the result.  */
     692       508148 :               if (TYPE_PRECISION (this_unprom->type) * 2
     693       508148 :                   > TYPE_PRECISION (type))
     694              :                 return 0;
     695              : 
     696              :               /* Update COMMON_TYPE for the new operand.  */
     697       503785 :               if (i == 0)
     698       456242 :                 *common_type = this_unprom->type;
     699        47543 :               else if (!vect_joust_widened_type (type, this_unprom->type,
     700              :                                                  common_type))
     701              :                 {
     702         2799 :                   if (subtype)
     703              :                     {
     704              :                       /* See if we can sign extend the smaller type.  */
     705          291 :                       if (TYPE_PRECISION (this_unprom->type)
     706          291 :                           > TYPE_PRECISION (*common_type))
     707           27 :                         *common_type = this_unprom->type;
     708          291 :                       *subtype = optab_vector_mixed_sign;
     709              :                     }
     710              :                   else
     711              :                     return 0;
     712              :                 }
     713              :             }
     714              :         }
     715       813179 :       next_op += nops;
     716              :     }
     717              :   return next_op;
     718              : }
     719              : 
     720              : /* Helper to return a new temporary for pattern of TYPE for STMT.  If STMT
     721              :    is NULL, the caller must set SSA_NAME_DEF_STMT for the returned SSA var. */
     722              : 
     723              : static tree
     724      2133561 : vect_recog_temp_ssa_var (tree type, gimple *stmt = NULL)
     725              : {
     726            0 :   return make_temp_ssa_name (type, stmt, "patt");
     727              : }
     728              : 
     729              : /* STMT2_INFO describes a type conversion that could be split into STMT1
     730              :    followed by a version of STMT2_INFO that takes NEW_RHS as its first
     731              :    input.  Try to do this using pattern statements, returning true on
     732              :    success.  */
     733              : 
     734              : static bool
     735        28465 : vect_split_statement (vec_info *vinfo, stmt_vec_info stmt2_info, tree new_rhs,
     736              :                       gimple *stmt1, tree vectype)
     737              : {
     738        28465 :   if (is_pattern_stmt_p (stmt2_info))
     739              :     {
     740              :       /* STMT2_INFO is part of a pattern.  Get the statement to which
     741              :          the pattern is attached.  */
     742          454 :       stmt_vec_info orig_stmt2_info = STMT_VINFO_RELATED_STMT (stmt2_info);
     743          454 :       vect_init_pattern_stmt (vinfo, stmt1, orig_stmt2_info, vectype);
     744              : 
     745          454 :       if (dump_enabled_p ())
     746           19 :         dump_printf_loc (MSG_NOTE, vect_location,
     747              :                          "Splitting pattern statement: %G", stmt2_info->stmt);
     748              : 
     749              :       /* Since STMT2_INFO is a pattern statement, we can change it
     750              :          in-situ without worrying about changing the code for the
     751              :          containing block.  */
     752          454 :       gimple_assign_set_rhs1 (stmt2_info->stmt, new_rhs);
     753              : 
     754          454 :       if (dump_enabled_p ())
     755              :         {
     756           19 :           dump_printf_loc (MSG_NOTE, vect_location, "into: %G", stmt1);
     757           19 :           dump_printf_loc (MSG_NOTE, vect_location, "and: %G",
     758              :                            stmt2_info->stmt);
     759              :         }
     760              : 
     761          454 :       gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt2_info);
     762          454 :       if (STMT_VINFO_RELATED_STMT (orig_stmt2_info) == stmt2_info)
     763              :         /* STMT2_INFO is the actual pattern statement.  Add STMT1
     764              :            to the end of the definition sequence.  */
     765          451 :         gimple_seq_add_stmt_without_update (def_seq, stmt1);
     766              :       else
     767              :         {
     768              :           /* STMT2_INFO belongs to the definition sequence.  Insert STMT1
     769              :              before it.  */
     770            3 :           gimple_stmt_iterator gsi = gsi_for_stmt (stmt2_info->stmt, def_seq);
     771            3 :           gsi_insert_before_without_update (&gsi, stmt1, GSI_SAME_STMT);
     772              :         }
     773              :       return true;
     774              :     }
     775              :   else
     776              :     {
     777              :       /* STMT2_INFO doesn't yet have a pattern.  Try to create a
     778              :          two-statement pattern now.  */
     779        28011 :       gcc_assert (!STMT_VINFO_RELATED_STMT (stmt2_info));
     780        28011 :       tree lhs_type = TREE_TYPE (gimple_get_lhs (stmt2_info->stmt));
     781        28011 :       tree lhs_vectype = get_vectype_for_scalar_type (vinfo, lhs_type);
     782        28011 :       if (!lhs_vectype)
     783              :         return false;
     784              : 
     785        28011 :       if (dump_enabled_p ())
     786         2049 :         dump_printf_loc (MSG_NOTE, vect_location,
     787              :                          "Splitting statement: %G", stmt2_info->stmt);
     788              : 
     789              :       /* Add STMT1 as a singleton pattern definition sequence.  */
     790        28011 :       gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (stmt2_info);
     791        28011 :       vect_init_pattern_stmt (vinfo, stmt1, stmt2_info, vectype);
     792        28011 :       gimple_seq_add_stmt_without_update (def_seq, stmt1);
     793              : 
     794              :       /* Build the second of the two pattern statements.  */
     795        28011 :       tree new_lhs = vect_recog_temp_ssa_var (lhs_type, NULL);
     796        28011 :       gassign *new_stmt2 = gimple_build_assign (new_lhs, NOP_EXPR, new_rhs);
     797        28011 :       vect_set_pattern_stmt (vinfo, new_stmt2, stmt2_info, lhs_vectype);
     798              : 
     799        28011 :       if (dump_enabled_p ())
     800              :         {
     801         2049 :           dump_printf_loc (MSG_NOTE, vect_location,
     802              :                            "into pattern statements: %G", stmt1);
     803         2049 :           dump_printf_loc (MSG_NOTE, vect_location, "and: %G",
     804              :                            (gimple *) new_stmt2);
     805              :         }
     806              : 
     807              :       return true;
     808              :     }
     809              : }
     810              : 
     811              : /* Look for the following pattern
     812              :         X = x[i]
     813              :         Y = y[i]
     814              :         DIFF = X - Y
     815              :         DAD = ABS_EXPR<DIFF>
     816              : 
     817              :    ABS_STMT should point to a statement of code ABS_EXPR or ABSU_EXPR.
     818              :    HALF_TYPE and UNPROM will be set should the statement be found to
     819              :    be a widened operation.
     820              :    DIFF_STMT will be set to the MINUS_EXPR
     821              :    statement that precedes the ABS_STMT if it is a MINUS_EXPR..
     822              :  */
     823              : static bool
     824     22494113 : vect_recog_absolute_difference (vec_info *vinfo, gassign *abs_stmt,
     825              :                                 tree *half_type,
     826              :                                 vect_unpromoted_value unprom[2],
     827              :                                 gassign **diff_stmt)
     828              : {
     829     22494113 :   if (!abs_stmt)
     830              :     return false;
     831              : 
     832              :   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
     833              :      inside the loop (in case we are analyzing an outer-loop).  */
     834     22494113 :   enum tree_code code = gimple_assign_rhs_code (abs_stmt);
     835     22494113 :   if (code != ABS_EXPR && code != ABSU_EXPR)
     836              :     return false;
     837              : 
     838        34340 :   tree abs_oprnd = gimple_assign_rhs1 (abs_stmt);
     839        34340 :   tree abs_type = TREE_TYPE (abs_oprnd);
     840        34340 :   if (!abs_oprnd)
     841              :     return false;
     842        26930 :   if (!ANY_INTEGRAL_TYPE_P (abs_type)
     843         7664 :       || TYPE_OVERFLOW_WRAPS (abs_type)
     844        41850 :       || TYPE_UNSIGNED (abs_type))
     845              :     return false;
     846              : 
     847              :   /* Peel off conversions from the ABS input.  This can involve sign
     848              :      changes (e.g. from an unsigned subtraction to a signed ABS input)
     849              :      or signed promotion, but it can't include unsigned promotion.
     850              :      (Note that ABS of an unsigned promotion should have been folded
     851              :      away before now anyway.)  */
     852         7510 :   vect_unpromoted_value unprom_diff;
     853         7510 :   abs_oprnd = vect_look_through_possible_promotion (vinfo, abs_oprnd,
     854              :                                                     &unprom_diff);
     855         7510 :   if (!abs_oprnd)
     856              :     return false;
     857         7256 :   if (TYPE_PRECISION (unprom_diff.type) != TYPE_PRECISION (abs_type)
     858         7256 :       && TYPE_UNSIGNED (unprom_diff.type))
     859              :     return false;
     860              : 
     861              :   /* We then detect if the operand of abs_expr is defined by a minus_expr.  */
     862         7256 :   stmt_vec_info diff_stmt_vinfo = vect_get_internal_def (vinfo, abs_oprnd);
     863         7256 :   if (!diff_stmt_vinfo)
     864              :     return false;
     865              : 
     866         7048 :   gassign *diff = dyn_cast <gassign *> (STMT_VINFO_STMT (diff_stmt_vinfo));
     867         7048 :   if (diff_stmt && diff
     868         5806 :       && gimple_assign_rhs_code (diff) == MINUS_EXPR
     869         8901 :       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (abs_oprnd)))
     870          251 :     *diff_stmt = diff;
     871              : 
     872              :   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
     873              :      inside the loop (in case we are analyzing an outer-loop).  */
     874         7048 :   if (vect_widened_op_tree (vinfo, diff_stmt_vinfo,
     875         7048 :                             MINUS_EXPR, IFN_VEC_WIDEN_MINUS,
     876              :                             false, 2, unprom, half_type))
     877         2408 :     return true;
     878              : 
     879              :   return false;
     880              : }
     881              : 
     882              : /* Convert UNPROM to TYPE and return the result, adding new statements
     883              :    to STMT_INFO's pattern definition statements if no better way is
     884              :    available.  VECTYPE is the vector form of TYPE.
     885              : 
     886              :    If SUBTYPE then convert the type based on the subtype.  */
     887              : 
     888              : static tree
     889       495665 : vect_convert_input (vec_info *vinfo, stmt_vec_info stmt_info, tree type,
     890              :                     vect_unpromoted_value *unprom, tree vectype,
     891              :                     enum optab_subtype subtype = optab_default)
     892              : {
     893              :   /* Update the type if the signs differ.  */
     894       495665 :   if (subtype == optab_vector_mixed_sign)
     895              :     {
     896          328 :       gcc_assert (!TYPE_UNSIGNED (type));
     897          328 :       if (TYPE_UNSIGNED (TREE_TYPE (unprom->op)))
     898              :         {
     899          164 :           type = unsigned_type_for (type);
     900          164 :           vectype = unsigned_type_for (vectype);
     901              :         }
     902              :     }
     903              : 
     904              :   /* Check for a no-op conversion.  */
     905       495665 :   if (types_compatible_p (type, TREE_TYPE (unprom->op)))
     906       173071 :     return unprom->op;
     907              : 
     908              :   /* Allow the caller to create constant vect_unpromoted_values.  */
     909       322594 :   if (TREE_CODE (unprom->op) == INTEGER_CST)
     910       200801 :     return wide_int_to_tree (type, wi::to_widest (unprom->op));
     911              : 
     912       121793 :   tree input = unprom->op;
     913       121793 :   if (unprom->caster)
     914              :     {
     915        63822 :       tree lhs = gimple_get_lhs (unprom->caster->stmt);
     916        63822 :       tree lhs_type = TREE_TYPE (lhs);
     917              : 
     918              :       /* If the result of the existing cast is the right width, use it
     919              :          instead of the source of the cast.  */
     920        63822 :       if (TYPE_PRECISION (lhs_type) == TYPE_PRECISION (type))
     921              :         input = lhs;
     922              :       /* If the precision we want is between the source and result
     923              :          precisions of the existing cast, try splitting the cast into
     924              :          two and tapping into a mid-way point.  */
     925        61591 :       else if (TYPE_PRECISION (lhs_type) > TYPE_PRECISION (type)
     926        61591 :                && TYPE_PRECISION (type) > TYPE_PRECISION (unprom->type))
     927              :         {
     928              :           /* In order to preserve the semantics of the original cast,
     929              :              give the mid-way point the same signedness as the input value.
     930              : 
     931              :              It would be possible to use a signed type here instead if
     932              :              TYPE is signed and UNPROM->TYPE is unsigned, but that would
     933              :              make the sign of the midtype sensitive to the order in
     934              :              which we process the statements, since the signedness of
     935              :              TYPE is the signedness required by just one of possibly
     936              :              many users.  Also, unsigned promotions are usually as cheap
     937              :              as or cheaper than signed ones, so it's better to keep an
     938              :              unsigned promotion.  */
     939        28465 :           tree midtype = build_nonstandard_integer_type
     940        28465 :             (TYPE_PRECISION (type), TYPE_UNSIGNED (unprom->type));
     941        28465 :           tree vec_midtype = get_vectype_for_scalar_type (vinfo, midtype);
     942        28465 :           if (vec_midtype)
     943              :             {
     944        28465 :               input = vect_recog_temp_ssa_var (midtype, NULL);
     945        28465 :               gassign *new_stmt = gimple_build_assign (input, NOP_EXPR,
     946              :                                                        unprom->op);
     947        28465 :               if (!vect_split_statement (vinfo, unprom->caster, input, new_stmt,
     948              :                                          vec_midtype))
     949            0 :                 append_pattern_def_seq (vinfo, stmt_info,
     950              :                                         new_stmt, vec_midtype);
     951              :             }
     952              :         }
     953              : 
     954              :       /* See if we can reuse an existing result.  */
     955        63822 :       if (types_compatible_p (type, TREE_TYPE (input)))
     956              :         return input;
     957              :     }
     958              : 
     959              :   /* We need a new conversion statement.  */
     960       101265 :   tree new_op = vect_recog_temp_ssa_var (type, NULL);
     961       101265 :   gassign *new_stmt = gimple_build_assign (new_op, NOP_EXPR, input);
     962              : 
     963              :   /* If OP is an external value, see if we can insert the new statement
     964              :      on an incoming edge.  */
     965       101265 :   if (input == unprom->op && unprom->dt == vect_external_def)
     966         8596 :     if (edge e = vect_get_external_def_edge (vinfo, input))
     967              :       {
     968          754 :         basic_block new_bb = gsi_insert_on_edge_immediate (e, new_stmt);
     969          754 :         gcc_assert (!new_bb);
     970              :         return new_op;
     971              :       }
     972              : 
     973              :   /* As a (common) last resort, add the statement to the pattern itself.  */
     974       100511 :   append_pattern_def_seq (vinfo, stmt_info, new_stmt, vectype);
     975       100511 :   return new_op;
     976              : }
     977              : 
     978              : /* Invoke vect_convert_input for N elements of UNPROM and store the
     979              :    result in the corresponding elements of RESULT.
     980              : 
     981              :    If SUBTYPE then convert the type based on the subtype.  */
     982              : 
     983              : static void
     984       251815 : vect_convert_inputs (vec_info *vinfo, stmt_vec_info stmt_info, unsigned int n,
     985              :                      tree *result, tree type, vect_unpromoted_value *unprom,
     986              :                      tree vectype, enum optab_subtype subtype = optab_default)
     987              : {
     988       747451 :   for (unsigned int i = 0; i < n; ++i)
     989              :     {
     990              :       unsigned int j;
     991       738978 :       for (j = 0; j < i; ++j)
     992       243821 :         if (unprom[j].op == unprom[i].op)
     993              :           break;
     994              : 
     995       495636 :       if (j < i)
     996          479 :         result[i] = result[j];
     997              :       else
     998       495157 :         result[i] = vect_convert_input (vinfo, stmt_info,
     999       495157 :                                         type, &unprom[i], vectype, subtype);
    1000              :     }
    1001       251815 : }
    1002              : 
    1003              : /* The caller has created a (possibly empty) sequence of pattern definition
    1004              :    statements followed by a single statement PATTERN_STMT.  Cast the result
    1005              :    of this final statement to TYPE.  If a new statement is needed, add
    1006              :    PATTERN_STMT to the end of STMT_INFO's pattern definition statements
    1007              :    and return the new statement, otherwise return PATTERN_STMT as-is.
    1008              :    VECITYPE is the vector form of PATTERN_STMT's result type.  */
    1009              : 
    1010              : static gimple *
    1011       278219 : vect_convert_output (vec_info *vinfo, stmt_vec_info stmt_info, tree type,
    1012              :                      gimple *pattern_stmt, tree vecitype)
    1013              : {
    1014       278219 :   tree lhs = gimple_get_lhs (pattern_stmt);
    1015       278219 :   if (!types_compatible_p (type, TREE_TYPE (lhs)))
    1016              :     {
    1017       247638 :       append_pattern_def_seq (vinfo, stmt_info, pattern_stmt, vecitype);
    1018       247638 :       tree cast_var = vect_recog_temp_ssa_var (type, NULL);
    1019       247638 :       pattern_stmt = gimple_build_assign (cast_var, NOP_EXPR, lhs);
    1020              :     }
    1021       278219 :   return pattern_stmt;
    1022              : }
    1023              : 
    1024              : /* Return true if STMT_VINFO describes a reduction for which reassociation
    1025              :    is allowed.  If STMT_INFO is part of a group, assume that it's part of
    1026              :    a reduction chain and optimistically assume that all statements
    1027              :    except the last allow reassociation.
    1028              :    Also require it to have code CODE and to be a reduction
    1029              :    in the outermost loop.  When returning true, store the operands in
    1030              :    *OP0_OUT and *OP1_OUT.  */
    1031              : 
    1032              : static bool
    1033     96911619 : vect_reassociating_reduction_p (vec_info *vinfo,
    1034              :                                 stmt_vec_info stmt_info, tree_code code,
    1035              :                                 tree *op0_out, tree *op1_out)
    1036              : {
    1037     96911619 :   loop_vec_info loop_info = dyn_cast <loop_vec_info> (vinfo);
    1038     13735974 :   if (!loop_info)
    1039              :     return false;
    1040              : 
    1041     13735974 :   gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
    1042     14997741 :   if (!assign || gimple_assign_rhs_code (assign) != code)
    1043              :     return false;
    1044              : 
    1045              :   /* We don't allow changing the order of the computation in the inner-loop
    1046              :      when doing outer-loop vectorization.  */
    1047      2678453 :   class loop *loop = LOOP_VINFO_LOOP (loop_info);
    1048      2678453 :   if (loop && nested_in_vect_loop_p (loop, stmt_info))
    1049              :     return false;
    1050              : 
    1051      2625227 :   if (!vect_is_reduction (stmt_info))
    1052              :     return false;
    1053              : 
    1054       172808 :   if (needs_fold_left_reduction_p (TREE_TYPE (gimple_assign_lhs (assign)),
    1055       172808 :                                    code))
    1056              :     return false;
    1057              : 
    1058       159887 :   *op0_out = gimple_assign_rhs1 (assign);
    1059       159887 :   *op1_out = gimple_assign_rhs2 (assign);
    1060       159887 :   if (commutative_tree_code (code) && STMT_VINFO_REDUC_IDX (stmt_info) == 0)
    1061        63894 :     std::swap (*op0_out, *op1_out);
    1062              :   return true;
    1063              : }
    1064              : 
    1065              : /* Return true iff the target has a vector optab implementing the operation
    1066              :    CODE on type VECTYPE with SUBTYPE.  */
    1067              : 
    1068              : static bool
    1069       878710 : target_has_vecop_for_code (tree_code code, tree vectype,
    1070              :                            enum optab_subtype subtype = optab_vector)
    1071              : {
    1072       878710 :   optab voptab = optab_for_tree_code (code, vectype, subtype);
    1073       878710 :   return voptab && can_implement_p (voptab, TYPE_MODE (vectype));
    1074              : }
    1075              : 
    1076              : /* match.pd function to match
    1077              :    (cond (cmp@3 a b) (convert@1 c) (convert@2 d))
    1078              :    with conditions:
    1079              :    1) @1, @2, c, d, a, b are all integral type.
    1080              :    2) There's single_use for both @1 and @2.
    1081              :    3) a, c have same precision.
    1082              :    4) c and @1 have different precision.
    1083              :    5) c, d are the same type or they can differ in sign when convert is
    1084              :    truncation.
    1085              : 
    1086              :    record a and c and d and @3.  */
    1087              : 
    1088              : extern bool gimple_cond_expr_convert_p (tree, tree*, tree (*)(tree));
    1089              : 
    1090              : /* Function vect_recog_cond_expr_convert
    1091              : 
    1092              :    Try to find the following pattern:
    1093              : 
    1094              :    TYPE_AB A,B;
    1095              :    TYPE_CD C,D;
    1096              :    TYPE_E E;
    1097              :    TYPE_E op_true = (TYPE_E) A;
    1098              :    TYPE_E op_false = (TYPE_E) B;
    1099              : 
    1100              :    E = C cmp D ? op_true : op_false;
    1101              : 
    1102              :    where
    1103              :    TYPE_PRECISION (TYPE_E) != TYPE_PRECISION (TYPE_CD);
    1104              :    TYPE_PRECISION (TYPE_AB) == TYPE_PRECISION (TYPE_CD);
    1105              :    single_use of op_true and op_false.
    1106              :    TYPE_AB could differ in sign when (TYPE_E) A is a truncation.
    1107              : 
    1108              :    Input:
    1109              : 
    1110              :    * STMT_VINFO: The stmt from which the pattern search begins.
    1111              :    here it starts with E = c cmp D ? op_true : op_false;
    1112              : 
    1113              :    Output:
    1114              : 
    1115              :    TYPE1 E' = C cmp D ? A : B;
    1116              :    TYPE3 E = (TYPE3) E';
    1117              : 
    1118              :    There may extra nop_convert for A or B to handle different signness.
    1119              : 
    1120              :    * TYPE_OUT: The vector type of the output of this pattern.
    1121              : 
    1122              :    * Return value: A new stmt that will be used to replace the sequence of
    1123              :    stmts that constitute the pattern. In this case it will be:
    1124              :    E = (TYPE3)E';
    1125              :    E' = C cmp D ? A : B; is recorded in pattern definition statements;  */
    1126              : 
    1127              : static gimple *
    1128     32380528 : vect_recog_cond_expr_convert_pattern (vec_info *vinfo,
    1129              :                                       stmt_vec_info stmt_vinfo, tree *type_out)
    1130              : {
    1131     32380528 :   gassign *last_stmt = dyn_cast <gassign *> (stmt_vinfo->stmt);
    1132     22591240 :   tree lhs, match[4], temp, type, new_lhs, op2, op1;
    1133     22591240 :   gimple *cond_stmt;
    1134     22591240 :   gimple *pattern_stmt;
    1135     54971768 :   enum tree_code code = NOP_EXPR;
    1136              : 
    1137     22591240 :   if (!last_stmt)
    1138              :     return NULL;
    1139              : 
    1140     22591240 :   lhs = gimple_assign_lhs (last_stmt);
    1141              : 
    1142              :   /* Find E = C cmp D ? (TYPE3) A ? (TYPE3) B;
    1143              :      TYPE_PRECISION (A) == TYPE_PRECISION (C).  */
    1144     22591240 :   if (!gimple_cond_expr_convert_p (lhs, &match[0], NULL))
    1145              :     return NULL;
    1146              : 
    1147           29 :   if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs)))
    1148           20 :     code = INTEGRAL_TYPE_P (TREE_TYPE (match[1])) ? FLOAT_EXPR : CONVERT_EXPR;
    1149            9 :   else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (match[1])))
    1150            0 :     code = FIX_TRUNC_EXPR;
    1151              : 
    1152           29 :   op1 = match[1];
    1153           29 :   op2 = match[2];
    1154           29 :   type = TREE_TYPE (op1);
    1155              :   /* When op1/op2 is REAL_CST, the conversion must be CONVERT_EXPR from
    1156              :      SCALAR_FLOAT_TYPE_P which is restricted in gimple_cond_expr_convert_p.
    1157              :      Otherwise, the conversion could be FLOAT_EXPR, FIX_TRUNC_EXPR
    1158              :      or CONVERT_EXPR.  */
    1159           29 :   if (TREE_CODE (op1) == REAL_CST)
    1160              :     {
    1161           20 :       op1 = const_unop (CONVERT_EXPR, TREE_TYPE (op2), op1);
    1162           20 :       type = TREE_TYPE (op2);
    1163           20 :       if (op1 == NULL_TREE)
    1164              :         return NULL;
    1165              :     }
    1166            9 :   else if (TREE_CODE (op2) == REAL_CST)
    1167              :     {
    1168            0 :       op2 = const_unop (FLOAT_EXPR, TREE_TYPE (op1), op2);
    1169            0 :       if (op2 == NULL_TREE)
    1170              :         return NULL;
    1171              :     }
    1172            9 :   else if (code == NOP_EXPR)
    1173              :     {
    1174            9 :       if (TYPE_SIGN (type) != TYPE_SIGN (TREE_TYPE (match[2])))
    1175              :         {
    1176            9 :           op2 = vect_recog_temp_ssa_var (type, NULL);
    1177            9 :           gimple* nop_stmt = gimple_build_assign (op2, NOP_EXPR, match[2]);
    1178            9 :           append_pattern_def_seq (vinfo, stmt_vinfo, nop_stmt);
    1179              :         }
    1180              :     }
    1181              : 
    1182           29 :   vect_pattern_detected ("vect_recog_cond_expr_convert_pattern", last_stmt);
    1183              : 
    1184           29 :   temp = vect_recog_temp_ssa_var (type, NULL);
    1185           29 :   cond_stmt = gimple_build_assign (temp, build3 (COND_EXPR, type, match[3],
    1186              :                                                  op1, op2));
    1187           29 :   append_pattern_def_seq (vinfo, stmt_vinfo, cond_stmt);
    1188           29 :   new_lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    1189           29 :   pattern_stmt = gimple_build_assign (new_lhs, code, temp);
    1190           29 :   *type_out = NULL_TREE;
    1191              : 
    1192           29 :   if (dump_enabled_p ())
    1193           20 :     dump_printf_loc (MSG_NOTE, vect_location,
    1194              :                      "created pattern stmt: %G", pattern_stmt);
    1195              :   return pattern_stmt;
    1196              : }
    1197              : 
    1198              : /* Function vect_recog_dot_prod_pattern
    1199              : 
    1200              :    Try to find the following pattern:
    1201              : 
    1202              :      type1a x_t
    1203              :      type1b y_t;
    1204              :      TYPE1 prod;
    1205              :      TYPE2 sum = init;
    1206              :    loop:
    1207              :      sum_0 = phi <init, sum_1>
    1208              :      S1  x_t = ...
    1209              :      S2  y_t = ...
    1210              :      S3  x_T = (TYPE1) x_t;
    1211              :      S4  y_T = (TYPE1) y_t;
    1212              :      S5  prod = x_T * y_T;
    1213              :      [S6  prod = (TYPE2) prod;  #optional]
    1214              :      S7  sum_1 = prod + sum_0;
    1215              : 
    1216              :    where 'TYPE1' is exactly double the size of type 'type1a' and 'type1b',
    1217              :    the sign of 'TYPE1' must be one of 'type1a' or 'type1b' but the sign of
    1218              :    'type1a' and 'type1b' can differ.
    1219              : 
    1220              :    Input:
    1221              : 
    1222              :    * STMT_VINFO: The stmt from which the pattern search begins.  In the
    1223              :    example, when this function is called with S7, the pattern {S3,S4,S5,S6,S7}
    1224              :    will be detected.
    1225              : 
    1226              :    Output:
    1227              : 
    1228              :    * TYPE_OUT: The type of the output  of this pattern.
    1229              : 
    1230              :    * Return value: A new stmt that will be used to replace the sequence of
    1231              :    stmts that constitute the pattern. In this case it will be:
    1232              :         WIDEN_DOT_PRODUCT <x_t, y_t, sum_0>
    1233              : 
    1234              :    Note: The dot-prod idiom is a widening reduction pattern that is
    1235              :          vectorized without preserving all the intermediate results. It
    1236              :          produces only N/2 (widened) results (by summing up pairs of
    1237              :          intermediate results) rather than all N results.  Therefore, we
    1238              :          cannot allow this pattern when we want to get all the results and in
    1239              :          the correct order (as is the case when this computation is in an
    1240              :          inner-loop nested in an outer-loop that us being vectorized).  */
    1241              : 
    1242              : static gimple *
    1243     32304511 : vect_recog_dot_prod_pattern (vec_info *vinfo,
    1244              :                              stmt_vec_info stmt_vinfo, tree *type_out)
    1245              : {
    1246     32304511 :   tree oprnd0, oprnd1;
    1247     32304511 :   gimple *last_stmt = stmt_vinfo->stmt;
    1248     32304511 :   tree type, half_type;
    1249     32304511 :   gimple *pattern_stmt;
    1250     32304511 :   tree var;
    1251              : 
    1252              :   /* Look for the following pattern
    1253              :           DX = (TYPE1) X;
    1254              :           DY = (TYPE1) Y;
    1255              :           DPROD = DX * DY;
    1256              :           DDPROD = (TYPE2) DPROD;
    1257              :           sum_1 = DDPROD + sum_0;
    1258              :      In which
    1259              :      - DX is double the size of X
    1260              :      - DY is double the size of Y
    1261              :      - DX, DY, DPROD all have the same type but the sign
    1262              :        between X, Y and DPROD can differ.
    1263              :      - sum is the same size of DPROD or bigger
    1264              :      - sum has been recognized as a reduction variable.
    1265              : 
    1266              :      This is equivalent to:
    1267              :        DPROD = X w* Y;          #widen mult
    1268              :        sum_1 = DPROD w+ sum_0;  #widen summation
    1269              :      or
    1270              :        DPROD = X w* Y;          #widen mult
    1271              :        sum_1 = DPROD + sum_0;   #summation
    1272              :    */
    1273              : 
    1274              :   /* Starting from LAST_STMT, follow the defs of its uses in search
    1275              :      of the above pattern.  */
    1276              : 
    1277     32304511 :   if (!vect_reassociating_reduction_p (vinfo, stmt_vinfo, PLUS_EXPR,
    1278              :                                        &oprnd0, &oprnd1))
    1279              :     return NULL;
    1280              : 
    1281        53937 :   type = TREE_TYPE (gimple_get_lhs (last_stmt));
    1282              : 
    1283        53937 :   vect_unpromoted_value unprom_mult;
    1284        53937 :   oprnd0 = vect_look_through_possible_promotion (vinfo, oprnd0, &unprom_mult);
    1285              : 
    1286              :   /* So far so good.  Since last_stmt was detected as a (summation) reduction,
    1287              :      we know that oprnd1 is the reduction variable (defined by a loop-header
    1288              :      phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
    1289              :      Left to check that oprnd0 is defined by a (widen_)mult_expr  */
    1290        53937 :   if (!oprnd0)
    1291              :     return NULL;
    1292              : 
    1293        36639 :   stmt_vec_info mult_vinfo = vect_get_internal_def (vinfo, oprnd0);
    1294        36639 :   if (!mult_vinfo)
    1295              :     return NULL;
    1296              : 
    1297              :   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
    1298              :      inside the loop (in case we are analyzing an outer-loop).  */
    1299       107364 :   vect_unpromoted_value unprom0[2];
    1300        35788 :   enum optab_subtype subtype = optab_vector;
    1301        35788 :   if (!vect_widened_op_tree (vinfo, mult_vinfo, MULT_EXPR, WIDEN_MULT_EXPR,
    1302              :                              false, 2, unprom0, &half_type, &subtype))
    1303              :     return NULL;
    1304              : 
    1305              :   /* If there are two widening operations, make sure they agree on the sign
    1306              :      of the extension.  The result of an optab_vector_mixed_sign operation
    1307              :      is signed; otherwise, the result has the same sign as the operands.  */
    1308         1386 :   if (TYPE_PRECISION (unprom_mult.type) != TYPE_PRECISION (type)
    1309         2127 :       && (subtype == optab_vector_mixed_sign
    1310          741 :           ? TYPE_UNSIGNED (unprom_mult.type)
    1311          532 :           : TYPE_SIGN (unprom_mult.type) != TYPE_SIGN (half_type)))
    1312              :     return NULL;
    1313              : 
    1314         1305 :   vect_pattern_detected ("vect_recog_dot_prod_pattern", last_stmt);
    1315              : 
    1316              :   /* If the inputs have mixed signs, canonicalize on using the signed
    1317              :      input type for analysis.  This also helps when emulating mixed-sign
    1318              :      operations using signed operations.  */
    1319         1305 :   if (subtype == optab_vector_mixed_sign)
    1320          246 :     half_type = signed_type_for (half_type);
    1321              : 
    1322         1305 :   tree half_vectype;
    1323         1305 :   if (!vect_supportable_conv_optab_p (vinfo, type, DOT_PROD_EXPR, half_type,
    1324              :                                         type_out, &half_vectype, subtype))
    1325              :     {
    1326              :       /* We can emulate a mixed-sign dot-product using a sequence of
    1327              :          signed dot-products; see vect_emulate_mixed_dot_prod for details.  */
    1328          588 :       if (subtype != optab_vector_mixed_sign
    1329          588 :           || !vect_supportable_conv_optab_p (vinfo, signed_type_for (type),
    1330              :                                                DOT_PROD_EXPR, half_type,
    1331              :                                                type_out, &half_vectype,
    1332              :                                                optab_vector))
    1333              :         return NULL;
    1334              : 
    1335           15 :       *type_out = signed_or_unsigned_type_for (TYPE_UNSIGNED (type),
    1336              :                                                *type_out);
    1337              :     }
    1338              : 
    1339              :   /* Get the inputs in the appropriate types.  */
    1340          732 :   tree mult_oprnd[2];
    1341          732 :   vect_convert_inputs (vinfo, stmt_vinfo, 2, mult_oprnd, half_type,
    1342              :                        unprom0, half_vectype, subtype);
    1343              : 
    1344          732 :   var = vect_recog_temp_ssa_var (type, NULL);
    1345          732 :   pattern_stmt = gimple_build_assign (var, DOT_PROD_EXPR,
    1346              :                                       mult_oprnd[0], mult_oprnd[1], oprnd1);
    1347              : 
    1348          732 :   return pattern_stmt;
    1349              : }
    1350              : 
    1351              : 
    1352              : /* Function vect_recog_sad_pattern
    1353              : 
    1354              :    Try to find the following Sum of Absolute Difference (SAD) pattern:
    1355              : 
    1356              :      type x_t, y_t;
    1357              :      signed TYPE1 diff, abs_diff;
    1358              :      TYPE2 sum = init;
    1359              :    loop:
    1360              :      sum_0 = phi <init, sum_1>
    1361              :      S1  x_t = ...
    1362              :      S2  y_t = ...
    1363              :      S3  x_T = (TYPE1) x_t;
    1364              :      S4  y_T = (TYPE1) y_t;
    1365              :      S5  diff = x_T - y_T;
    1366              :      S6  abs_diff = ABS_EXPR <diff>;
    1367              :      [S7  abs_diff = (TYPE2) abs_diff;  #optional]
    1368              :      S8  sum_1 = abs_diff + sum_0;
    1369              : 
    1370              :    where 'TYPE1' is at least double the size of type 'type', and 'TYPE2' is the
    1371              :    same size of 'TYPE1' or bigger. This is a special case of a reduction
    1372              :    computation.
    1373              : 
    1374              :    Input:
    1375              : 
    1376              :    * STMT_VINFO: The stmt from which the pattern search begins.  In the
    1377              :    example, when this function is called with S8, the pattern
    1378              :    {S3,S4,S5,S6,S7,S8} will be detected.
    1379              : 
    1380              :    Output:
    1381              : 
    1382              :    * TYPE_OUT: The type of the output of this pattern.
    1383              : 
    1384              :    * Return value: A new stmt that will be used to replace the sequence of
    1385              :    stmts that constitute the pattern. In this case it will be:
    1386              :         SAD_EXPR <x_t, y_t, sum_0>
    1387              :   */
    1388              : 
    1389              : static gimple *
    1390     32303784 : vect_recog_sad_pattern (vec_info *vinfo,
    1391              :                         stmt_vec_info stmt_vinfo, tree *type_out)
    1392              : {
    1393     32303784 :   gimple *last_stmt = stmt_vinfo->stmt;
    1394     32303784 :   tree half_type;
    1395              : 
    1396              :   /* Look for the following pattern
    1397              :           DX = (TYPE1) X;
    1398              :           DY = (TYPE1) Y;
    1399              :           DDIFF = DX - DY;
    1400              :           DAD = ABS_EXPR <DDIFF>;
    1401              :           DDPROD = (TYPE2) DPROD;
    1402              :           sum_1 = DAD + sum_0;
    1403              :      In which
    1404              :      - DX is at least double the size of X
    1405              :      - DY is at least double the size of Y
    1406              :      - DX, DY, DDIFF, DAD all have the same type
    1407              :      - sum is the same size of DAD or bigger
    1408              :      - sum has been recognized as a reduction variable.
    1409              : 
    1410              :      This is equivalent to:
    1411              :        DDIFF = X w- Y;          #widen sub
    1412              :        DAD = ABS_EXPR <DDIFF>;
    1413              :        sum_1 = DAD w+ sum_0;    #widen summation
    1414              :      or
    1415              :        DDIFF = X w- Y;          #widen sub
    1416              :        DAD = ABS_EXPR <DDIFF>;
    1417              :        sum_1 = DAD + sum_0;     #summation
    1418              :    */
    1419              : 
    1420              :   /* Starting from LAST_STMT, follow the defs of its uses in search
    1421              :      of the above pattern.  */
    1422              : 
    1423     32303784 :   tree plus_oprnd0, plus_oprnd1;
    1424     32303784 :   if (!vect_reassociating_reduction_p (vinfo, stmt_vinfo, PLUS_EXPR,
    1425              :                                        &plus_oprnd0, &plus_oprnd1))
    1426              :     return NULL;
    1427              : 
    1428        53205 :   tree sum_type = TREE_TYPE (gimple_get_lhs (last_stmt));
    1429              : 
    1430              :   /* Any non-truncating sequence of conversions is OK here, since
    1431              :      with a successful match, the result of the ABS(U) is known to fit
    1432              :      within the nonnegative range of the result type.  (It cannot be the
    1433              :      negative of the minimum signed value due to the range of the widening
    1434              :      MINUS_EXPR.)  */
    1435        53205 :   vect_unpromoted_value unprom_abs;
    1436        53205 :   plus_oprnd0 = vect_look_through_possible_promotion (vinfo, plus_oprnd0,
    1437              :                                                       &unprom_abs);
    1438              : 
    1439              :   /* So far so good.  Since last_stmt was detected as a (summation) reduction,
    1440              :      we know that plus_oprnd1 is the reduction variable (defined by a loop-header
    1441              :      phi), and plus_oprnd0 is an ssa-name defined by a stmt in the loop body.
    1442              :      Then check that plus_oprnd0 is defined by an abs_expr.  */
    1443              : 
    1444        53205 :   if (!plus_oprnd0)
    1445              :     return NULL;
    1446              : 
    1447        35907 :   stmt_vec_info abs_stmt_vinfo = vect_get_internal_def (vinfo, plus_oprnd0);
    1448        35907 :   if (!abs_stmt_vinfo)
    1449              :     return NULL;
    1450              : 
    1451              :   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
    1452              :      inside the loop (in case we are analyzing an outer-loop).  */
    1453        35056 :   gassign *abs_stmt = dyn_cast <gassign *> (abs_stmt_vinfo->stmt);
    1454       105168 :   vect_unpromoted_value unprom[2];
    1455              : 
    1456        35056 :   if (!abs_stmt)
    1457              :     {
    1458          367 :       gcall *abd_stmt = dyn_cast <gcall *> (abs_stmt_vinfo->stmt);
    1459          302 :       if (!abd_stmt
    1460          302 :           || !gimple_call_internal_p (abd_stmt)
    1461            0 :           || gimple_call_num_args (abd_stmt) != 2)
    1462              :         return NULL;
    1463              : 
    1464            0 :       tree abd_oprnd0 = gimple_call_arg (abd_stmt, 0);
    1465            0 :       tree abd_oprnd1 = gimple_call_arg (abd_stmt, 1);
    1466              : 
    1467            0 :       if (gimple_call_internal_fn (abd_stmt) == IFN_ABD
    1468            0 :           || gimple_call_internal_fn (abd_stmt) == IFN_VEC_WIDEN_ABD)
    1469              :         {
    1470            0 :           unprom[0].op = abd_oprnd0;
    1471            0 :           unprom[0].type = TREE_TYPE (abd_oprnd0);
    1472            0 :           unprom[1].op = abd_oprnd1;
    1473            0 :           unprom[1].type = TREE_TYPE (abd_oprnd1);
    1474              :         }
    1475              :       else
    1476              :         return NULL;
    1477              : 
    1478            0 :       half_type = unprom[0].type;
    1479              :     }
    1480        34689 :   else if (!vect_recog_absolute_difference (vinfo, abs_stmt, &half_type,
    1481              :                                             unprom, NULL))
    1482              :     return NULL;
    1483              : 
    1484          854 :   vect_pattern_detected ("vect_recog_sad_pattern", last_stmt);
    1485              : 
    1486          854 :   tree half_vectype;
    1487          854 :   if (!vect_supportable_direct_optab_p (vinfo, sum_type, SAD_EXPR, half_type,
    1488              :                                         type_out, &half_vectype))
    1489              :     return NULL;
    1490              : 
    1491              :   /* Get the inputs to the SAD_EXPR in the appropriate types.  */
    1492          460 :   tree sad_oprnd[2];
    1493          460 :   vect_convert_inputs (vinfo, stmt_vinfo, 2, sad_oprnd, half_type,
    1494              :                        unprom, half_vectype);
    1495              : 
    1496          460 :   tree var = vect_recog_temp_ssa_var (sum_type, NULL);
    1497          460 :   gimple *pattern_stmt = gimple_build_assign (var, SAD_EXPR, sad_oprnd[0],
    1498              :                                               sad_oprnd[1], plus_oprnd1);
    1499              : 
    1500          460 :   return pattern_stmt;
    1501              : }
    1502              : 
    1503              : /* Function vect_recog_abd_pattern
    1504              : 
    1505              :    Try to find the following ABsolute Difference (ABD) or
    1506              :    widening ABD (WIDEN_ABD) pattern:
    1507              : 
    1508              :    TYPE1 x;
    1509              :    TYPE2 y;
    1510              :    TYPE3 x_cast = (TYPE3) x;              // widening or no-op
    1511              :    TYPE3 y_cast = (TYPE3) y;              // widening or no-op
    1512              :    TYPE3 diff = x_cast - y_cast;
    1513              :    TYPE4 diff_cast = (TYPE4) diff;        // widening or no-op
    1514              :    TYPE5 abs = ABS(U)_EXPR <diff_cast>;
    1515              : 
    1516              :    WIDEN_ABD exists to optimize the case where TYPE4 is at least
    1517              :    twice as wide as TYPE3.
    1518              : 
    1519              :    Input:
    1520              : 
    1521              :    * STMT_VINFO: The stmt from which the pattern search begins
    1522              : 
    1523              :    Output:
    1524              : 
    1525              :    * TYPE_OUT: The type of the output of this pattern
    1526              : 
    1527              :    * Return value: A new stmt that will be used to replace the sequence of
    1528              :      stmts that constitute the pattern, principally:
    1529              :         out = IFN_ABD (x, y)
    1530              :         out = IFN_WIDEN_ABD (x, y)
    1531              :  */
    1532              : 
    1533              : static gimple *
    1534     32248506 : vect_recog_abd_pattern (vec_info *vinfo,
    1535              :                         stmt_vec_info stmt_vinfo, tree *type_out)
    1536              : {
    1537     32248506 :   gassign *last_stmt = dyn_cast <gassign *> (STMT_VINFO_STMT (stmt_vinfo));
    1538     22459424 :   if (!last_stmt)
    1539              :     return NULL;
    1540              : 
    1541     22459424 :   tree out_type = TREE_TYPE (gimple_assign_lhs (last_stmt));
    1542              : 
    1543     67378272 :   vect_unpromoted_value unprom[2];
    1544     22459424 :   gassign *diff_stmt = NULL;
    1545     22459424 :   tree abd_in_type;
    1546     22459424 :   if (!vect_recog_absolute_difference (vinfo, last_stmt, &abd_in_type,
    1547              :                                        unprom, &diff_stmt))
    1548              :     {
    1549              :       /* We cannot try further without having a non-widening MINUS.  */
    1550     22457870 :       if (!diff_stmt)
    1551              :         return NULL;
    1552              : 
    1553          251 :       unprom[0].op = gimple_assign_rhs1 (diff_stmt);
    1554          251 :       unprom[1].op = gimple_assign_rhs2 (diff_stmt);
    1555          251 :       abd_in_type = signed_type_for (out_type);
    1556              :     }
    1557              : 
    1558         1805 :   tree abd_out_type = abd_in_type;
    1559              : 
    1560         1805 :   tree vectype_in = get_vectype_for_scalar_type (vinfo, abd_in_type);
    1561         1805 :   if (!vectype_in)
    1562              :     return NULL;
    1563              : 
    1564         1787 :   internal_fn ifn = IFN_ABD;
    1565         1787 :   tree vectype_out = vectype_in;
    1566              : 
    1567         1787 :   if (TYPE_PRECISION (out_type) >= TYPE_PRECISION (abd_in_type) * 2
    1568         1787 :       && stmt_vinfo->min_output_precision >= TYPE_PRECISION (abd_in_type) * 2)
    1569              :     {
    1570         1445 :       tree mid_type
    1571         1445 :         = build_nonstandard_integer_type (TYPE_PRECISION (abd_in_type) * 2,
    1572         1445 :                                           TYPE_UNSIGNED (abd_in_type));
    1573         1445 :       tree mid_vectype = get_vectype_for_scalar_type (vinfo, mid_type);
    1574              : 
    1575         1445 :       code_helper dummy_code;
    1576         1445 :       int dummy_int;
    1577         1445 :       auto_vec<tree> dummy_vec;
    1578         1445 :       if (mid_vectype
    1579         1445 :           && supportable_widening_operation (IFN_VEC_WIDEN_ABD,
    1580              :                                              mid_vectype, vectype_in, false,
    1581              :                                              &dummy_code, &dummy_code,
    1582              :                                              &dummy_int, &dummy_vec))
    1583              :         {
    1584            0 :           ifn = IFN_VEC_WIDEN_ABD;
    1585            0 :           abd_out_type = mid_type;
    1586            0 :           vectype_out = mid_vectype;
    1587              :         }
    1588         1445 :     }
    1589              : 
    1590         1445 :   if (ifn == IFN_ABD
    1591         1787 :       && !direct_internal_fn_supported_p (ifn, vectype_in,
    1592              :                                           OPTIMIZE_FOR_SPEED))
    1593              :     return NULL;
    1594              : 
    1595            0 :   vect_pattern_detected ("vect_recog_abd_pattern", last_stmt);
    1596              : 
    1597            0 :   tree abd_oprnds[2];
    1598            0 :   vect_convert_inputs (vinfo, stmt_vinfo, 2, abd_oprnds,
    1599              :                        abd_in_type, unprom, vectype_in);
    1600              : 
    1601            0 :   *type_out = get_vectype_for_scalar_type (vinfo, out_type);
    1602              : 
    1603            0 :   tree abd_result = vect_recog_temp_ssa_var (abd_out_type, NULL);
    1604            0 :   gcall *abd_stmt = gimple_build_call_internal (ifn, 2,
    1605              :                                                 abd_oprnds[0], abd_oprnds[1]);
    1606            0 :   gimple_call_set_lhs (abd_stmt, abd_result);
    1607            0 :   gimple_set_location (abd_stmt, gimple_location (last_stmt));
    1608              : 
    1609            0 :   gimple *stmt = abd_stmt;
    1610            0 :   if (TYPE_PRECISION (abd_in_type) == TYPE_PRECISION (abd_out_type)
    1611            0 :       && TYPE_PRECISION (abd_out_type) < TYPE_PRECISION (out_type)
    1612            0 :       && !TYPE_UNSIGNED (abd_out_type))
    1613              :     {
    1614            0 :       tree unsign = unsigned_type_for (abd_out_type);
    1615            0 :       stmt = vect_convert_output (vinfo, stmt_vinfo, unsign, stmt, vectype_out);
    1616            0 :       vectype_out = get_vectype_for_scalar_type (vinfo, unsign);
    1617              :     }
    1618              : 
    1619            0 :   return vect_convert_output (vinfo, stmt_vinfo, out_type, stmt, vectype_out);
    1620              : }
    1621              : 
    1622              : /* Recognize an operation that performs ORIG_CODE on widened inputs,
    1623              :    so that it can be treated as though it had the form:
    1624              : 
    1625              :       A_TYPE a;
    1626              :       B_TYPE b;
    1627              :       HALF_TYPE a_cast = (HALF_TYPE) a;  // possible no-op
    1628              :       HALF_TYPE b_cast = (HALF_TYPE) b;  // possible no-op
    1629              :     | RES_TYPE a_extend = (RES_TYPE) a_cast;  // promotion from HALF_TYPE
    1630              :     | RES_TYPE b_extend = (RES_TYPE) b_cast;  // promotion from HALF_TYPE
    1631              :     | RES_TYPE res = a_extend ORIG_CODE b_extend;
    1632              : 
    1633              :    Try to replace the pattern with:
    1634              : 
    1635              :       A_TYPE a;
    1636              :       B_TYPE b;
    1637              :       HALF_TYPE a_cast = (HALF_TYPE) a;  // possible no-op
    1638              :       HALF_TYPE b_cast = (HALF_TYPE) b;  // possible no-op
    1639              :     | EXT_TYPE ext = a_cast WIDE_CODE b_cast;
    1640              :     | RES_TYPE res = (EXT_TYPE) ext;  // possible no-op
    1641              : 
    1642              :    where EXT_TYPE is wider than HALF_TYPE but has the same signedness.
    1643              : 
    1644              :    SHIFT_P is true if ORIG_CODE and WIDE_CODE are shifts.  NAME is the
    1645              :    name of the pattern being matched, for dump purposes.  */
    1646              : 
    1647              : static gimple *
    1648    129827369 : vect_recog_widen_op_pattern (vec_info *vinfo,
    1649              :                              stmt_vec_info last_stmt_info, tree *type_out,
    1650              :                              tree_code orig_code, code_helper wide_code,
    1651              :                              bool shift_p, const char *name)
    1652              : {
    1653    129827369 :   gimple *last_stmt = last_stmt_info->stmt;
    1654              : 
    1655    389482107 :   vect_unpromoted_value unprom[2];
    1656    129827369 :   tree half_type;
    1657    129827369 :   if (!vect_widened_op_tree (vinfo, last_stmt_info, orig_code, orig_code,
    1658              :                              shift_p, 2, unprom, &half_type))
    1659              : 
    1660              :     return NULL;
    1661              : 
    1662              :   /* Pattern detected.  */
    1663       342725 :   vect_pattern_detected (name, last_stmt);
    1664              : 
    1665       342725 :   tree type = TREE_TYPE (gimple_get_lhs (last_stmt));
    1666       342725 :   tree itype = type;
    1667       342725 :   if (TYPE_PRECISION (type) != TYPE_PRECISION (half_type) * 2
    1668       342725 :       || TYPE_UNSIGNED (type) != TYPE_UNSIGNED (half_type))
    1669       234012 :     itype = build_nonstandard_integer_type (TYPE_PRECISION (half_type) * 2,
    1670       234012 :                                             TYPE_UNSIGNED (half_type));
    1671              : 
    1672              :   /* Check target support  */
    1673       342725 :   tree vectype = get_vectype_for_scalar_type (vinfo, half_type);
    1674       342725 :   tree vecitype = get_vectype_for_scalar_type (vinfo, itype);
    1675       342725 :   tree ctype = itype;
    1676       342725 :   tree vecctype = vecitype;
    1677       342725 :   if (orig_code == MINUS_EXPR
    1678         6417 :       && TYPE_UNSIGNED (itype)
    1679       347231 :       && TYPE_PRECISION (type) > TYPE_PRECISION (itype))
    1680              :     {
    1681              :       /* Subtraction is special, even if half_type is unsigned and no matter
    1682              :          whether type is signed or unsigned, if type is wider than itype,
    1683              :          we need to sign-extend from the widening operation result to the
    1684              :          result type.
    1685              :          Consider half_type unsigned char, operand 1 0xfe, operand 2 0xff,
    1686              :          itype unsigned short and type either int or unsigned int.
    1687              :          Widened (unsigned short) 0xfe - (unsigned short) 0xff is
    1688              :          (unsigned short) 0xffff, but for type int we want the result -1
    1689              :          and for type unsigned int 0xffffffff rather than 0xffff.  */
    1690          790 :       ctype = build_nonstandard_integer_type (TYPE_PRECISION (itype), 0);
    1691          790 :       vecctype = get_vectype_for_scalar_type (vinfo, ctype);
    1692              :     }
    1693              : 
    1694       342725 :   code_helper dummy_code;
    1695       342725 :   int dummy_int;
    1696       342725 :   auto_vec<tree> dummy_vec;
    1697       342725 :   if (!vectype
    1698       342725 :       || !vecitype
    1699       263551 :       || !vecctype
    1700       606276 :       || !supportable_widening_operation (wide_code, vecitype, vectype, true,
    1701              :                                           &dummy_code, &dummy_code,
    1702              :                                           &dummy_int, &dummy_vec))
    1703              :     return NULL;
    1704              : 
    1705       114699 :   *type_out = get_vectype_for_scalar_type (vinfo, type);
    1706       114699 :   if (!*type_out)
    1707              :     return NULL;
    1708              : 
    1709       114699 :   tree oprnd[2];
    1710       114699 :   vect_convert_inputs (vinfo, last_stmt_info,
    1711              :                        2, oprnd, half_type, unprom, vectype);
    1712              : 
    1713       114699 :   tree var = vect_recog_temp_ssa_var (itype, NULL);
    1714       114699 :   gimple *pattern_stmt = vect_gimple_build (var, wide_code, oprnd[0], oprnd[1]);
    1715              : 
    1716       114699 :   if (vecctype != vecitype)
    1717            0 :     pattern_stmt = vect_convert_output (vinfo, last_stmt_info, ctype,
    1718              :                                         pattern_stmt, vecitype);
    1719              : 
    1720       114699 :   return vect_convert_output (vinfo, last_stmt_info,
    1721       114699 :                               type, pattern_stmt, vecctype);
    1722       342725 : }
    1723              : 
    1724              : /* Try to detect multiplication on widened inputs, converting MULT_EXPR
    1725              :    to WIDEN_MULT_EXPR.  See vect_recog_widen_op_pattern for details.  */
    1726              : 
    1727              : static gimple *
    1728     32332351 : vect_recog_widen_mult_pattern (vec_info *vinfo, stmt_vec_info last_stmt_info,
    1729              :                                tree *type_out)
    1730              : {
    1731     32332351 :   return vect_recog_widen_op_pattern (vinfo, last_stmt_info, type_out,
    1732     32332351 :                                       MULT_EXPR, WIDEN_MULT_EXPR, false,
    1733     32332351 :                                       "vect_recog_widen_mult_pattern");
    1734              : }
    1735              : 
    1736              : /* Try to detect addition on widened inputs, converting PLUS_EXPR
    1737              :    to IFN_VEC_WIDEN_PLUS.  See vect_recog_widen_op_pattern for details.  */
    1738              : 
    1739              : static gimple *
    1740     32595576 : vect_recog_widen_plus_pattern (vec_info *vinfo, stmt_vec_info last_stmt_info,
    1741              :                                tree *type_out)
    1742              : {
    1743     32595576 :   return vect_recog_widen_op_pattern (vinfo, last_stmt_info, type_out,
    1744     32595576 :                                       PLUS_EXPR, IFN_VEC_WIDEN_PLUS,
    1745     32595576 :                                       false, "vect_recog_widen_plus_pattern");
    1746              : }
    1747              : 
    1748              : /* Try to detect subtraction on widened inputs, converting MINUS_EXPR
    1749              :    to IFN_VEC_WIDEN_MINUS.  See vect_recog_widen_op_pattern for details.  */
    1750              : static gimple *
    1751     32595576 : vect_recog_widen_minus_pattern (vec_info *vinfo, stmt_vec_info last_stmt_info,
    1752              :                                tree *type_out)
    1753              : {
    1754     32595576 :   return vect_recog_widen_op_pattern (vinfo, last_stmt_info, type_out,
    1755     32595576 :                                       MINUS_EXPR, IFN_VEC_WIDEN_MINUS,
    1756     32595576 :                                       false, "vect_recog_widen_minus_pattern");
    1757              : }
    1758              : 
    1759              : /* Try to detect abd on widened inputs, converting IFN_ABD
    1760              :    to IFN_VEC_WIDEN_ABD.  */
    1761              : static gimple *
    1762     32595576 : vect_recog_widen_abd_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
    1763              :                               tree *type_out)
    1764              : {
    1765     32595576 :   gassign *last_stmt = dyn_cast <gassign *> (STMT_VINFO_STMT (stmt_vinfo));
    1766     30708906 :   if (!last_stmt || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (last_stmt)))
    1767              :     return NULL;
    1768              : 
    1769      3236377 :   tree last_rhs = gimple_assign_rhs1 (last_stmt);
    1770              : 
    1771      3236377 :   tree in_type = TREE_TYPE (last_rhs);
    1772      3236377 :   tree out_type = TREE_TYPE (gimple_assign_lhs (last_stmt));
    1773      3236377 :   if (!INTEGRAL_TYPE_P (in_type)
    1774      2832116 :       || !INTEGRAL_TYPE_P (out_type)
    1775      2715299 :       || TYPE_PRECISION (in_type) * 2 != TYPE_PRECISION (out_type)
    1776      3900680 :       || !TYPE_UNSIGNED (in_type))
    1777              :     return NULL;
    1778              : 
    1779       239639 :   vect_unpromoted_value unprom;
    1780       239639 :   tree op = vect_look_through_possible_promotion (vinfo, last_rhs, &unprom);
    1781       239639 :   if (!op || TYPE_PRECISION (TREE_TYPE (op)) != TYPE_PRECISION (in_type))
    1782              :     return NULL;
    1783              : 
    1784       237093 :   stmt_vec_info abd_pattern_vinfo = vect_get_internal_def (vinfo, op);
    1785       237093 :   if (!abd_pattern_vinfo)
    1786              :     return NULL;
    1787              : 
    1788       211878 :   gcall *abd_stmt = dyn_cast <gcall *> (STMT_VINFO_STMT (abd_pattern_vinfo));
    1789         9184 :   if (!abd_stmt
    1790         9184 :       || !gimple_call_internal_p (abd_stmt)
    1791          314 :       || gimple_call_internal_fn (abd_stmt) != IFN_ABD)
    1792              :     return NULL;
    1793              : 
    1794            0 :   tree vectype_in = get_vectype_for_scalar_type (vinfo, in_type);
    1795            0 :   tree vectype_out = get_vectype_for_scalar_type (vinfo, out_type);
    1796              : 
    1797            0 :   code_helper dummy_code;
    1798            0 :   int dummy_int;
    1799            0 :   auto_vec<tree> dummy_vec;
    1800            0 :   if (!supportable_widening_operation (IFN_VEC_WIDEN_ABD, vectype_out,
    1801              :                                        vectype_in, false,
    1802              :                                        &dummy_code, &dummy_code,
    1803              :                                        &dummy_int, &dummy_vec))
    1804              :     return NULL;
    1805              : 
    1806            0 :   vect_pattern_detected ("vect_recog_widen_abd_pattern", last_stmt);
    1807              : 
    1808            0 :   *type_out = vectype_out;
    1809              : 
    1810            0 :   tree abd_oprnd0 = gimple_call_arg (abd_stmt, 0);
    1811            0 :   tree abd_oprnd1 = gimple_call_arg (abd_stmt, 1);
    1812            0 :   tree widen_abd_result = vect_recog_temp_ssa_var (out_type, NULL);
    1813            0 :   gcall *widen_abd_stmt = gimple_build_call_internal (IFN_VEC_WIDEN_ABD, 2,
    1814              :                                                       abd_oprnd0, abd_oprnd1);
    1815            0 :   gimple_call_set_lhs (widen_abd_stmt, widen_abd_result);
    1816            0 :   gimple_set_location (widen_abd_stmt, gimple_location (last_stmt));
    1817            0 :   return widen_abd_stmt;
    1818            0 : }
    1819              : 
    1820              : /* Function vect_recog_ctz_ffs_pattern
    1821              : 
    1822              :    Try to find the following pattern:
    1823              : 
    1824              :    TYPE1 A;
    1825              :    TYPE1 B;
    1826              : 
    1827              :    B = __builtin_ctz{,l,ll} (A);
    1828              : 
    1829              :    or
    1830              : 
    1831              :    B = __builtin_ffs{,l,ll} (A);
    1832              : 
    1833              :    Input:
    1834              : 
    1835              :    * STMT_VINFO: The stmt from which the pattern search begins.
    1836              :    here it starts with B = __builtin_* (A);
    1837              : 
    1838              :    Output:
    1839              : 
    1840              :    * TYPE_OUT: The vector type of the output of this pattern.
    1841              : 
    1842              :    * Return value: A new stmt that will be used to replace the sequence of
    1843              :    stmts that constitute the pattern, using clz or popcount builtins.  */
    1844              : 
    1845              : static gimple *
    1846     32303673 : vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
    1847              :                             tree *type_out)
    1848              : {
    1849     32303673 :   gimple *call_stmt = stmt_vinfo->stmt;
    1850     32303673 :   gimple *pattern_stmt;
    1851     32303673 :   tree rhs_oprnd, rhs_type, lhs_oprnd, lhs_type, vec_type, vec_rhs_type;
    1852     32303673 :   tree new_var;
    1853     32303673 :   internal_fn ifn = IFN_LAST, ifnnew = IFN_LAST;
    1854     32303673 :   bool defined_at_zero = true, defined_at_zero_new = false;
    1855     32303673 :   int val = 0, val_new = 0, val_cmp = 0;
    1856     32303673 :   int prec;
    1857     32303673 :   int sub = 0, add = 0;
    1858     32303673 :   location_t loc;
    1859              : 
    1860     32303673 :   if (!is_gimple_call (call_stmt))
    1861              :     return NULL;
    1862              : 
    1863      3810263 :   if (gimple_call_num_args (call_stmt) != 1
    1864      3810263 :       && gimple_call_num_args (call_stmt) != 2)
    1865              :     return NULL;
    1866              : 
    1867      2171672 :   rhs_oprnd = gimple_call_arg (call_stmt, 0);
    1868      2171672 :   rhs_type = TREE_TYPE (rhs_oprnd);
    1869      2171672 :   lhs_oprnd = gimple_call_lhs (call_stmt);
    1870      2171672 :   if (!lhs_oprnd)
    1871              :     return NULL;
    1872      1043835 :   lhs_type = TREE_TYPE (lhs_oprnd);
    1873      1043835 :   if (!INTEGRAL_TYPE_P (lhs_type)
    1874       342219 :       || !INTEGRAL_TYPE_P (rhs_type)
    1875        47867 :       || !type_has_mode_precision_p (rhs_type)
    1876      1090115 :       || TREE_CODE (rhs_oprnd) != SSA_NAME)
    1877              :     return NULL;
    1878              : 
    1879        33112 :   switch (gimple_call_combined_fn (call_stmt))
    1880              :     {
    1881         1980 :     CASE_CFN_CTZ:
    1882         1980 :       ifn = IFN_CTZ;
    1883         1980 :       if (!gimple_call_internal_p (call_stmt)
    1884         1980 :           || gimple_call_num_args (call_stmt) != 2)
    1885              :         defined_at_zero = false;
    1886              :       else
    1887          121 :         val = tree_to_shwi (gimple_call_arg (call_stmt, 1));
    1888              :       break;
    1889              :     CASE_CFN_FFS:
    1890              :       ifn = IFN_FFS;
    1891              :       break;
    1892              :     default:
    1893              :       return NULL;
    1894              :     }
    1895              : 
    1896         2215 :   prec = TYPE_PRECISION (rhs_type);
    1897         2215 :   loc = gimple_location (call_stmt);
    1898              : 
    1899         2215 :   vec_type = get_vectype_for_scalar_type (vinfo, lhs_type);
    1900         2215 :   if (!vec_type)
    1901              :     return NULL;
    1902              : 
    1903         2209 :   vec_rhs_type = get_vectype_for_scalar_type (vinfo, rhs_type);
    1904         2209 :   if (!vec_rhs_type)
    1905              :     return NULL;
    1906              : 
    1907              :   /* Do it only if the backend doesn't have ctz<vector_mode>2 or
    1908              :      ffs<vector_mode>2 pattern but does have clz<vector_mode>2 or
    1909              :      popcount<vector_mode>2.  */
    1910         1946 :   if (!vec_type
    1911         1946 :       || direct_internal_fn_supported_p (ifn, vec_rhs_type,
    1912              :                                          OPTIMIZE_FOR_SPEED))
    1913              :     return NULL;
    1914              : 
    1915         1946 :   if (ifn == IFN_FFS
    1916         1946 :       && direct_internal_fn_supported_p (IFN_CTZ, vec_rhs_type,
    1917              :                                          OPTIMIZE_FOR_SPEED))
    1918              :     {
    1919            0 :       ifnnew = IFN_CTZ;
    1920            0 :       defined_at_zero_new
    1921            0 :         = CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (rhs_type),
    1922              :                                      val_new) == 2;
    1923              :     }
    1924         1946 :   else if (direct_internal_fn_supported_p (IFN_CLZ, vec_rhs_type,
    1925              :                                            OPTIMIZE_FOR_SPEED))
    1926              :     {
    1927          166 :       ifnnew = IFN_CLZ;
    1928          166 :       defined_at_zero_new
    1929          166 :         = CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (rhs_type),
    1930              :                                      val_new) == 2;
    1931              :     }
    1932          166 :   if ((ifnnew == IFN_LAST
    1933          166 :        || (defined_at_zero && !defined_at_zero_new))
    1934         1780 :       && direct_internal_fn_supported_p (IFN_POPCOUNT, vec_rhs_type,
    1935              :                                          OPTIMIZE_FOR_SPEED))
    1936              :     {
    1937              :       ifnnew = IFN_POPCOUNT;
    1938              :       defined_at_zero_new = true;
    1939              :       val_new = prec;
    1940              :     }
    1941         1820 :   if (ifnnew == IFN_LAST)
    1942              :     return NULL;
    1943              : 
    1944          292 :   vect_pattern_detected ("vec_recog_ctz_ffs_pattern", call_stmt);
    1945              : 
    1946          292 :   val_cmp = val_new;
    1947          292 :   if ((ifnnew == IFN_CLZ
    1948          292 :        && defined_at_zero
    1949          106 :        && defined_at_zero_new
    1950          106 :        && val == prec
    1951           54 :        && val_new == prec)
    1952          238 :       || (ifnnew == IFN_POPCOUNT && ifn == IFN_CTZ))
    1953              :     {
    1954          137 :       if (vect_is_reduction (stmt_vinfo))
    1955              :         return NULL;
    1956              : 
    1957              :       /* .CTZ (X) = PREC - .CLZ ((X - 1) & ~X)
    1958              :          .CTZ (X) = .POPCOUNT ((X - 1) & ~X).  */
    1959          137 :       if (ifnnew == IFN_CLZ)
    1960           54 :         sub = prec;
    1961          137 :       val_cmp = prec;
    1962              : 
    1963          137 :       if (!TYPE_UNSIGNED (rhs_type))
    1964              :         {
    1965           12 :           rhs_type = unsigned_type_for (rhs_type);
    1966           12 :           vec_rhs_type = get_vectype_for_scalar_type (vinfo, rhs_type);
    1967           12 :           new_var = vect_recog_temp_ssa_var (rhs_type, NULL);
    1968           12 :           pattern_stmt = gimple_build_assign (new_var, NOP_EXPR, rhs_oprnd);
    1969           12 :           append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt,
    1970              :                                   vec_rhs_type);
    1971           12 :           rhs_oprnd = new_var;
    1972              :         }
    1973              : 
    1974          137 :       tree m1 = vect_recog_temp_ssa_var (rhs_type, NULL);
    1975          137 :       pattern_stmt = gimple_build_assign (m1, PLUS_EXPR, rhs_oprnd,
    1976              :                                           build_int_cst (rhs_type, -1));
    1977          137 :       gimple_set_location (pattern_stmt, loc);
    1978          137 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_rhs_type);
    1979              : 
    1980          137 :       new_var = vect_recog_temp_ssa_var (rhs_type, NULL);
    1981          137 :       pattern_stmt = gimple_build_assign (new_var, BIT_NOT_EXPR, rhs_oprnd);
    1982          137 :       gimple_set_location (pattern_stmt, loc);
    1983          137 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_rhs_type);
    1984          137 :       rhs_oprnd = new_var;
    1985              : 
    1986          137 :       new_var = vect_recog_temp_ssa_var (rhs_type, NULL);
    1987          137 :       pattern_stmt = gimple_build_assign (new_var, BIT_AND_EXPR,
    1988              :                                           m1, rhs_oprnd);
    1989          137 :       gimple_set_location (pattern_stmt, loc);
    1990          137 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_rhs_type);
    1991          137 :       rhs_oprnd = new_var;
    1992          137 :     }
    1993          155 :   else if (ifnnew == IFN_CLZ)
    1994              :     {
    1995          112 :       if (vect_is_reduction (stmt_vinfo))
    1996              :         return NULL;
    1997              : 
    1998              :       /* .CTZ (X) = (PREC - 1) - .CLZ (X & -X)
    1999              :          .FFS (X) = PREC - .CLZ (X & -X).  */
    2000          106 :       sub = prec - (ifn == IFN_CTZ);
    2001          106 :       val_cmp = sub - val_new;
    2002              : 
    2003          106 :       tree neg = vect_recog_temp_ssa_var (rhs_type, NULL);
    2004          106 :       pattern_stmt = gimple_build_assign (neg, NEGATE_EXPR, rhs_oprnd);
    2005          106 :       gimple_set_location (pattern_stmt, loc);
    2006          106 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_rhs_type);
    2007              : 
    2008          106 :       new_var = vect_recog_temp_ssa_var (rhs_type, NULL);
    2009          106 :       pattern_stmt = gimple_build_assign (new_var, BIT_AND_EXPR,
    2010              :                                           rhs_oprnd, neg);
    2011          106 :       gimple_set_location (pattern_stmt, loc);
    2012          106 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_rhs_type);
    2013          106 :       rhs_oprnd = new_var;
    2014              :     }
    2015           43 :   else if (ifnnew == IFN_POPCOUNT)
    2016              :     {
    2017           43 :       if (vect_is_reduction (stmt_vinfo))
    2018              :         return NULL;
    2019              : 
    2020              :       /* .CTZ (X) = PREC - .POPCOUNT (X | -X)
    2021              :          .FFS (X) = (PREC + 1) - .POPCOUNT (X | -X).  */
    2022           43 :       sub = prec + (ifn == IFN_FFS);
    2023           43 :       val_cmp = sub;
    2024              : 
    2025           43 :       tree neg = vect_recog_temp_ssa_var (rhs_type, NULL);
    2026           43 :       pattern_stmt = gimple_build_assign (neg, NEGATE_EXPR, rhs_oprnd);
    2027           43 :       gimple_set_location (pattern_stmt, loc);
    2028           43 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_rhs_type);
    2029              : 
    2030           43 :       new_var = vect_recog_temp_ssa_var (rhs_type, NULL);
    2031           43 :       pattern_stmt = gimple_build_assign (new_var, BIT_IOR_EXPR,
    2032              :                                           rhs_oprnd, neg);
    2033           43 :       gimple_set_location (pattern_stmt, loc);
    2034           43 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_rhs_type);
    2035           43 :       rhs_oprnd = new_var;
    2036              :     }
    2037            0 :   else if (ifnnew == IFN_CTZ)
    2038              :     {
    2039              :       /* .FFS (X) = .CTZ (X) + 1.  */
    2040            0 :       add = 1;
    2041            0 :       val_cmp++;
    2042              : 
    2043            0 :       if (vect_is_reduction (stmt_vinfo)
    2044            0 :           && defined_at_zero
    2045            0 :           && (!defined_at_zero_new || val != val_cmp))
    2046              :         return NULL;
    2047              :     }
    2048              : 
    2049              :   /* Create B = .IFNNEW (A).  */
    2050          286 :   new_var = vect_recog_temp_ssa_var (lhs_type, NULL);
    2051          286 :   if ((ifnnew == IFN_CLZ || ifnnew == IFN_CTZ) && defined_at_zero_new)
    2052          160 :     pattern_stmt
    2053          160 :       = gimple_build_call_internal (ifnnew, 2, rhs_oprnd,
    2054              :                                     build_int_cst (integer_type_node,
    2055          160 :                                                    val_new));
    2056              :   else
    2057          126 :     pattern_stmt = gimple_build_call_internal (ifnnew, 1, rhs_oprnd);
    2058          286 :   gimple_call_set_lhs (pattern_stmt, new_var);
    2059          286 :   gimple_set_location (pattern_stmt, loc);
    2060          286 :   *type_out = vec_type;
    2061              : 
    2062          286 :   if (sub)
    2063              :     {
    2064          203 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_type);
    2065          203 :       tree ret_var = vect_recog_temp_ssa_var (lhs_type, NULL);
    2066          203 :       pattern_stmt = gimple_build_assign (ret_var, MINUS_EXPR,
    2067          203 :                                           build_int_cst (lhs_type, sub),
    2068              :                                           new_var);
    2069          203 :       gimple_set_location (pattern_stmt, loc);
    2070          203 :       new_var = ret_var;
    2071              :     }
    2072           83 :   else if (add)
    2073              :     {
    2074            0 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_type);
    2075            0 :       tree ret_var = vect_recog_temp_ssa_var (lhs_type, NULL);
    2076            0 :       pattern_stmt = gimple_build_assign (ret_var, PLUS_EXPR, new_var,
    2077            0 :                                           build_int_cst (lhs_type, add));
    2078            0 :       gimple_set_location (pattern_stmt, loc);
    2079            0 :       new_var = ret_var;
    2080              :     }
    2081              : 
    2082          286 :   if (defined_at_zero
    2083          210 :       && (!defined_at_zero_new || val != val_cmp))
    2084              :     {
    2085           43 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_type);
    2086           43 :       tree ret_var = vect_recog_temp_ssa_var (lhs_type, NULL);
    2087           43 :       rhs_oprnd = gimple_call_arg (call_stmt, 0);
    2088           43 :       rhs_type = TREE_TYPE (rhs_oprnd);
    2089           43 :       tree cmp = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    2090           43 :       pattern_stmt = gimple_build_assign (cmp, NE_EXPR, rhs_oprnd,
    2091              :                                           build_zero_cst (rhs_type));
    2092           43 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt,
    2093              :                               truth_type_for (vec_type), rhs_type);
    2094           43 :       pattern_stmt = gimple_build_assign (ret_var, COND_EXPR, cmp,
    2095              :                                           new_var,
    2096           43 :                                           build_int_cst (lhs_type, val));
    2097              :     }
    2098              : 
    2099          286 :   if (dump_enabled_p ())
    2100           36 :     dump_printf_loc (MSG_NOTE, vect_location,
    2101              :                      "created pattern stmt: %G", pattern_stmt);
    2102              : 
    2103              :   return pattern_stmt;
    2104              : }
    2105              : 
    2106              : /* Function vect_recog_popcount_clz_ctz_ffs_pattern
    2107              : 
    2108              :    Try to find the following pattern:
    2109              : 
    2110              :    UTYPE1 A;
    2111              :    TYPE1 B;
    2112              :    UTYPE2 temp_in;
    2113              :    TYPE3 temp_out;
    2114              :    temp_in = (UTYPE2)A;
    2115              : 
    2116              :    temp_out = __builtin_popcount{,l,ll} (temp_in);
    2117              :    B = (TYPE1) temp_out;
    2118              : 
    2119              :    TYPE2 may or may not be equal to TYPE3.
    2120              :    i.e. TYPE2 is equal to TYPE3 for __builtin_popcount
    2121              :    i.e. TYPE2 is not equal to TYPE3 for __builtin_popcountll
    2122              : 
    2123              :    Input:
    2124              : 
    2125              :    * STMT_VINFO: The stmt from which the pattern search begins.
    2126              :    here it starts with B = (TYPE1) temp_out;
    2127              : 
    2128              :    Output:
    2129              : 
    2130              :    * TYPE_OUT: The vector type of the output of this pattern.
    2131              : 
    2132              :    * Return value: A new stmt that will be used to replace the sequence of
    2133              :    stmts that constitute the pattern. In this case it will be:
    2134              :    B = .POPCOUNT (A);
    2135              : 
    2136              :    Similarly for clz, ctz and ffs.
    2137              : */
    2138              : 
    2139              : static gimple *
    2140     32303307 : vect_recog_popcount_clz_ctz_ffs_pattern (vec_info *vinfo,
    2141              :                                          stmt_vec_info stmt_vinfo,
    2142              :                                          tree *type_out)
    2143              : {
    2144     32303307 :   gassign *last_stmt = dyn_cast <gassign *> (stmt_vinfo->stmt);
    2145     22513895 :   gimple *call_stmt, *pattern_stmt;
    2146     22513895 :   tree rhs_oprnd, rhs_origin, lhs_oprnd, lhs_type, vec_type, new_var;
    2147     54817202 :   internal_fn ifn = IFN_LAST;
    2148     54817202 :   int addend = 0;
    2149              : 
    2150              :   /* Find B = (TYPE1) temp_out. */
    2151     22513895 :   if (!last_stmt)
    2152              :     return NULL;
    2153     22513895 :   tree_code code = gimple_assign_rhs_code (last_stmt);
    2154     22513895 :   if (!CONVERT_EXPR_CODE_P (code))
    2155              :     return NULL;
    2156              : 
    2157      3080974 :   lhs_oprnd = gimple_assign_lhs (last_stmt);
    2158      3080974 :   lhs_type = TREE_TYPE (lhs_oprnd);
    2159      3080974 :   if (!INTEGRAL_TYPE_P (lhs_type))
    2160              :     return NULL;
    2161              : 
    2162      2802125 :   rhs_oprnd = gimple_assign_rhs1 (last_stmt);
    2163      2802125 :   if (TREE_CODE (rhs_oprnd) != SSA_NAME
    2164      2802125 :       || !has_single_use (rhs_oprnd))
    2165              :     return NULL;
    2166      1416883 :   call_stmt = SSA_NAME_DEF_STMT (rhs_oprnd);
    2167              : 
    2168              :   /* Find temp_out = __builtin_popcount{,l,ll} (temp_in);  */
    2169      1416883 :   if (!is_gimple_call (call_stmt))
    2170              :     return NULL;
    2171        59731 :   switch (gimple_call_combined_fn (call_stmt))
    2172              :     {
    2173              :       int val;
    2174              :     CASE_CFN_POPCOUNT:
    2175              :       ifn = IFN_POPCOUNT;
    2176              :       break;
    2177         2376 :     CASE_CFN_CLZ:
    2178         2376 :       ifn = IFN_CLZ;
    2179              :       /* Punt if call result is unsigned and defined value at zero
    2180              :          is negative, as the negative value doesn't extend correctly.  */
    2181         2376 :       if (TYPE_UNSIGNED (TREE_TYPE (rhs_oprnd))
    2182            0 :           && gimple_call_internal_p (call_stmt)
    2183         2376 :           && CLZ_DEFINED_VALUE_AT_ZERO
    2184              :                (SCALAR_INT_TYPE_MODE (TREE_TYPE (rhs_oprnd)), val) == 2
    2185         2376 :           && val < 0)
    2186              :         return NULL;
    2187              :       break;
    2188          744 :     CASE_CFN_CTZ:
    2189          744 :       ifn = IFN_CTZ;
    2190              :       /* Punt if call result is unsigned and defined value at zero
    2191              :          is negative, as the negative value doesn't extend correctly.  */
    2192          744 :       if (TYPE_UNSIGNED (TREE_TYPE (rhs_oprnd))
    2193            0 :           && gimple_call_internal_p (call_stmt)
    2194          744 :           && CTZ_DEFINED_VALUE_AT_ZERO
    2195              :                (SCALAR_INT_TYPE_MODE (TREE_TYPE (rhs_oprnd)), val) == 2
    2196          744 :           && val < 0)
    2197              :         return NULL;
    2198              :       break;
    2199           57 :     CASE_CFN_FFS:
    2200           57 :       ifn = IFN_FFS;
    2201           57 :       break;
    2202              :     default:
    2203              :       return NULL;
    2204              :     }
    2205              : 
    2206         3530 :   if (gimple_call_num_args (call_stmt) != 1
    2207         3530 :       && gimple_call_num_args (call_stmt) != 2)
    2208              :     return NULL;
    2209              : 
    2210         3530 :   rhs_oprnd = gimple_call_arg (call_stmt, 0);
    2211         3530 :   vect_unpromoted_value unprom_diff;
    2212         3530 :   rhs_origin
    2213         3530 :     = vect_look_through_possible_promotion (vinfo, rhs_oprnd, &unprom_diff);
    2214              : 
    2215         3530 :   if (!rhs_origin)
    2216              :     return NULL;
    2217              : 
    2218              :   /* Input and output of .POPCOUNT should be same-precision integer.  */
    2219         3520 :   if (TYPE_PRECISION (unprom_diff.type) != TYPE_PRECISION (lhs_type))
    2220              :     return NULL;
    2221              : 
    2222              :   /* Also A should be unsigned or same precision as temp_in, otherwise
    2223              :      different builtins/internal functions have different behaviors.  */
    2224         1808 :   if (TYPE_PRECISION (unprom_diff.type)
    2225         1808 :       != TYPE_PRECISION (TREE_TYPE (rhs_oprnd)))
    2226          318 :     switch (ifn)
    2227              :       {
    2228          146 :       case IFN_POPCOUNT:
    2229              :         /* For popcount require zero extension, which doesn't add any
    2230              :            further bits to the count.  */
    2231          146 :         if (!TYPE_UNSIGNED (unprom_diff.type))
    2232              :           return NULL;
    2233              :         break;
    2234          109 :       case IFN_CLZ:
    2235              :         /* clzll (x) == clz (x) + 32 for unsigned x != 0, so ok
    2236              :            if it is undefined at zero or if it matches also for the
    2237              :            defined value there.  */
    2238          109 :         if (!TYPE_UNSIGNED (unprom_diff.type))
    2239              :           return NULL;
    2240          109 :         if (!type_has_mode_precision_p (lhs_type)
    2241          109 :             || !type_has_mode_precision_p (TREE_TYPE (rhs_oprnd)))
    2242              :           return NULL;
    2243          109 :         addend = (TYPE_PRECISION (TREE_TYPE (rhs_oprnd))
    2244          109 :                   - TYPE_PRECISION (lhs_type));
    2245          109 :         if (gimple_call_internal_p (call_stmt)
    2246          109 :             && gimple_call_num_args (call_stmt) == 2)
    2247              :           {
    2248            0 :             int val1, val2;
    2249            0 :             val1 = tree_to_shwi (gimple_call_arg (call_stmt, 1));
    2250            0 :             int d2
    2251            0 :               = CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (lhs_type),
    2252              :                                            val2);
    2253            0 :             if (d2 != 2 || val1 != val2 + addend)
    2254              :               return NULL;
    2255              :           }
    2256              :         break;
    2257           43 :       case IFN_CTZ:
    2258              :         /* ctzll (x) == ctz (x) for unsigned or signed x != 0, so ok
    2259              :            if it is undefined at zero or if it matches also for the
    2260              :            defined value there.  */
    2261           43 :         if (gimple_call_internal_p (call_stmt)
    2262           43 :             && gimple_call_num_args (call_stmt) == 2)
    2263              :           {
    2264            0 :             int val1, val2;
    2265            0 :             val1 = tree_to_shwi (gimple_call_arg (call_stmt, 1));
    2266            0 :             int d2
    2267            0 :               = CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (lhs_type),
    2268              :                                            val2);
    2269            0 :             if (d2 != 2 || val1 != val2)
    2270              :               return NULL;
    2271              :           }
    2272              :         break;
    2273              :       case IFN_FFS:
    2274              :         /* ffsll (x) == ffs (x) for unsigned or signed x.  */
    2275              :         break;
    2276              :       default:
    2277              :         gcc_unreachable ();
    2278              :       }
    2279              : 
    2280         1808 :   vec_type = get_vectype_for_scalar_type (vinfo, lhs_type);
    2281              :   /* Do it only if the backend has popcount<vector_mode>2 etc. pattern.  */
    2282         1808 :   if (!vec_type)
    2283              :     return NULL;
    2284              : 
    2285         1679 :   bool supported
    2286         1679 :     = direct_internal_fn_supported_p (ifn, vec_type, OPTIMIZE_FOR_SPEED);
    2287              :   /* We cannot rely on the reduction check in vect_recog_ctz_ffs_pattern
    2288              :      because we do not set up the temporary pattern stmt finally for
    2289              :      the recursive analysis.  */
    2290         1679 :   if (!supported && vect_is_reduction (stmt_vinfo))
    2291              :     return NULL;
    2292         1663 :   if (!supported)
    2293         1486 :     switch (ifn)
    2294              :       {
    2295              :       case IFN_POPCOUNT:
    2296              :       case IFN_CLZ:
    2297              :         return NULL;
    2298           57 :       case IFN_FFS:
    2299              :         /* vect_recog_ctz_ffs_pattern can implement ffs using ctz.  */
    2300           57 :         if (direct_internal_fn_supported_p (IFN_CTZ, vec_type,
    2301              :                                             OPTIMIZE_FOR_SPEED))
    2302              :           break;
    2303              :         /* FALLTHRU */
    2304          534 :       case IFN_CTZ:
    2305              :         /* vect_recog_ctz_ffs_pattern can implement ffs or ctz using
    2306              :            clz or popcount.  */
    2307          534 :         if (direct_internal_fn_supported_p (IFN_CLZ, vec_type,
    2308              :                                             OPTIMIZE_FOR_SPEED))
    2309              :           break;
    2310          474 :         if (direct_internal_fn_supported_p (IFN_POPCOUNT, vec_type,
    2311              :                                             OPTIMIZE_FOR_SPEED))
    2312              :           break;
    2313              :         return NULL;
    2314              :       default:
    2315              :         gcc_unreachable ();
    2316              :       }
    2317              : 
    2318          318 :   vect_pattern_detected ("vec_recog_popcount_clz_ctz_ffs_pattern",
    2319              :                          call_stmt);
    2320              : 
    2321          318 :   tree orig_lhs_type = lhs_type;
    2322          318 :   gimple *cast_stmt = NULL;
    2323          318 :   if (!type_has_mode_precision_p (lhs_type))
    2324              :     {
    2325            0 :       lhs_type = TREE_TYPE (vec_type);
    2326            0 :       cast_stmt
    2327            0 :         = gimple_build_assign (vect_recog_temp_ssa_var (lhs_type, NULL),
    2328              :                                NOP_EXPR, unprom_diff.op);
    2329            0 :       unprom_diff.op = gimple_assign_lhs (cast_stmt);
    2330              :     }
    2331              : 
    2332              :   /* Create B = .POPCOUNT (A).  */
    2333          318 :   new_var = vect_recog_temp_ssa_var (lhs_type, NULL);
    2334          318 :   tree arg2 = NULL_TREE;
    2335          318 :   int val;
    2336          318 :   if (ifn == IFN_CLZ
    2337          368 :       && CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (lhs_type),
    2338              :                                     val) == 2)
    2339           48 :     arg2 = build_int_cst (integer_type_node, val);
    2340          270 :   else if (ifn == IFN_CTZ
    2341          363 :            && CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (lhs_type),
    2342              :                                          val) == 2)
    2343           93 :     arg2 = build_int_cst (integer_type_node, val);
    2344          318 :   if (arg2)
    2345          141 :     pattern_stmt = gimple_build_call_internal (ifn, 2, unprom_diff.op, arg2);
    2346              :   else
    2347          177 :     pattern_stmt = gimple_build_call_internal (ifn, 1, unprom_diff.op);
    2348          318 :   gimple_call_set_lhs (pattern_stmt, new_var);
    2349          318 :   gimple_set_location (pattern_stmt, gimple_location (last_stmt));
    2350          318 :   *type_out = vec_type;
    2351              : 
    2352          318 :   if (dump_enabled_p ())
    2353           24 :     dump_printf_loc (MSG_NOTE, vect_location,
    2354              :                      "created pattern stmt: %G", pattern_stmt);
    2355              : 
    2356          318 :   if (addend)
    2357              :     {
    2358           12 :       gcc_assert (supported);
    2359           12 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_type);
    2360           12 :       tree ret_var = vect_recog_temp_ssa_var (lhs_type, NULL);
    2361           12 :       pattern_stmt = gimple_build_assign (ret_var, PLUS_EXPR, new_var,
    2362           12 :                                           build_int_cst (lhs_type, addend));
    2363              :     }
    2364          306 :   else if (!supported)
    2365              :     {
    2366          141 :       stmt_vec_info new_stmt_info = vinfo->add_stmt (pattern_stmt);
    2367          141 :       STMT_VINFO_VECTYPE (new_stmt_info) = vec_type;
    2368          141 :       pattern_stmt
    2369          141 :         = vect_recog_ctz_ffs_pattern (vinfo, new_stmt_info, type_out);
    2370          141 :       if (pattern_stmt == NULL)
    2371              :         return NULL;
    2372          141 :       if (cast_stmt)
    2373            0 :         append_pattern_def_seq (vinfo, stmt_vinfo, cast_stmt, vec_type);
    2374          141 :       if (gimple_seq seq = STMT_VINFO_PATTERN_DEF_SEQ (new_stmt_info))
    2375              :         {
    2376          141 :           gimple_seq *pseq = &STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo);
    2377          141 :           gimple_seq_add_seq_without_update (pseq, seq);
    2378              :         }
    2379              :     }
    2380          165 :   else if (cast_stmt)
    2381            0 :     append_pattern_def_seq (vinfo, stmt_vinfo, cast_stmt, vec_type);
    2382              : 
    2383          153 :   if (cast_stmt)
    2384              :     {
    2385            0 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vec_type);
    2386            0 :       tree ret_var = vect_recog_temp_ssa_var (orig_lhs_type, NULL);
    2387            0 :       pattern_stmt = gimple_build_assign (ret_var, NOP_EXPR,
    2388              :                                           gimple_get_lhs (pattern_stmt));
    2389              :     }
    2390              :   return pattern_stmt;
    2391              : }
    2392              : 
    2393              : /* Function vect_recog_pow_pattern
    2394              : 
    2395              :    Try to find the following pattern:
    2396              : 
    2397              :      x = POW (y, N);
    2398              : 
    2399              :    with POW being one of pow, powf, powi, powif and N being
    2400              :    either 2 or 0.5.
    2401              : 
    2402              :    Input:
    2403              : 
    2404              :    * STMT_VINFO: The stmt from which the pattern search begins.
    2405              : 
    2406              :    Output:
    2407              : 
    2408              :    * TYPE_OUT: The type of the output of this pattern.
    2409              : 
    2410              :    * Return value: A new stmt that will be used to replace the sequence of
    2411              :    stmts that constitute the pattern. In this case it will be:
    2412              :         x = x * x
    2413              :    or
    2414              :         x = sqrt (x)
    2415              : */
    2416              : 
    2417              : static gimple *
    2418     32303324 : vect_recog_pow_pattern (vec_info *vinfo,
    2419              :                         stmt_vec_info stmt_vinfo, tree *type_out)
    2420              : {
    2421     32303324 :   gimple *last_stmt = stmt_vinfo->stmt;
    2422     32303324 :   tree base, exp;
    2423     32303324 :   gimple *stmt;
    2424     32303324 :   tree var;
    2425              : 
    2426     32303324 :   if (!is_gimple_call (last_stmt) || gimple_call_lhs (last_stmt) == NULL)
    2427              :     return NULL;
    2428              : 
    2429      1533244 :   switch (gimple_call_combined_fn (last_stmt))
    2430              :     {
    2431          527 :     CASE_CFN_POW:
    2432          527 :     CASE_CFN_POWI:
    2433          527 :       break;
    2434              : 
    2435              :     default:
    2436              :       return NULL;
    2437              :     }
    2438              : 
    2439          527 :   base = gimple_call_arg (last_stmt, 0);
    2440          527 :   exp = gimple_call_arg (last_stmt, 1);
    2441          527 :   if (TREE_CODE (exp) != REAL_CST
    2442          472 :       && TREE_CODE (exp) != INTEGER_CST)
    2443              :     {
    2444          472 :       if (flag_unsafe_math_optimizations
    2445           37 :           && TREE_CODE (base) == REAL_CST
    2446          475 :           && gimple_call_builtin_p (last_stmt, BUILT_IN_NORMAL))
    2447              :         {
    2448            3 :           combined_fn log_cfn;
    2449            3 :           built_in_function exp_bfn;
    2450            3 :           switch (DECL_FUNCTION_CODE (gimple_call_fndecl (last_stmt)))
    2451              :             {
    2452              :             case BUILT_IN_POW:
    2453              :               log_cfn = CFN_BUILT_IN_LOG;
    2454              :               exp_bfn = BUILT_IN_EXP;
    2455              :               break;
    2456            0 :             case BUILT_IN_POWF:
    2457            0 :               log_cfn = CFN_BUILT_IN_LOGF;
    2458            0 :               exp_bfn = BUILT_IN_EXPF;
    2459            0 :               break;
    2460            0 :             case BUILT_IN_POWL:
    2461            0 :               log_cfn = CFN_BUILT_IN_LOGL;
    2462            0 :               exp_bfn = BUILT_IN_EXPL;
    2463            0 :               break;
    2464              :             default:
    2465              :               return NULL;
    2466              :             }
    2467            3 :           tree logc = fold_const_call (log_cfn, TREE_TYPE (base), base);
    2468            3 :           tree exp_decl = builtin_decl_implicit (exp_bfn);
    2469              :           /* Optimize pow (C, x) as exp (log (C) * x).  Normally match.pd
    2470              :              does that, but if C is a power of 2, we want to use
    2471              :              exp2 (log2 (C) * x) in the non-vectorized version, but for
    2472              :              vectorization we don't have vectorized exp2.  */
    2473            3 :           if (logc
    2474            3 :               && TREE_CODE (logc) == REAL_CST
    2475            3 :               && exp_decl
    2476            6 :               && lookup_attribute ("omp declare simd",
    2477            3 :                                    DECL_ATTRIBUTES (exp_decl)))
    2478              :             {
    2479            3 :               cgraph_node *node = cgraph_node::get_create (exp_decl);
    2480            3 :               if (node->simd_clones == NULL)
    2481              :                 {
    2482            2 :                   if (targetm.simd_clone.compute_vecsize_and_simdlen == NULL
    2483            2 :                       || node->definition)
    2484              :                     return NULL;
    2485            2 :                   expand_simd_clones (node);
    2486            2 :                   if (node->simd_clones == NULL)
    2487              :                     return NULL;
    2488              :                 }
    2489            3 :               *type_out = get_vectype_for_scalar_type (vinfo, TREE_TYPE (base));
    2490            3 :               if (!*type_out)
    2491              :                 return NULL;
    2492            3 :               tree def = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
    2493            3 :               gimple *g = gimple_build_assign (def, MULT_EXPR, exp, logc);
    2494            3 :               append_pattern_def_seq (vinfo, stmt_vinfo, g);
    2495            3 :               tree res = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
    2496            3 :               g = gimple_build_call (exp_decl, 1, def);
    2497            3 :               gimple_call_set_lhs (g, res);
    2498            3 :               return g;
    2499              :             }
    2500              :         }
    2501              : 
    2502              :       return NULL;
    2503              :     }
    2504              : 
    2505              :   /* We now have a pow or powi builtin function call with a constant
    2506              :      exponent.  */
    2507              : 
    2508              :   /* Catch squaring.  */
    2509           55 :   if ((tree_fits_shwi_p (exp)
    2510            0 :        && tree_to_shwi (exp) == 2)
    2511           55 :       || (TREE_CODE (exp) == REAL_CST
    2512           55 :           && real_equal (&TREE_REAL_CST (exp), &dconst2)))
    2513              :     {
    2514           11 :       if (!vect_supportable_direct_optab_p (vinfo, TREE_TYPE (base), MULT_EXPR,
    2515           11 :                                             TREE_TYPE (base), type_out))
    2516              :         return NULL;
    2517              : 
    2518            9 :       var = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
    2519            9 :       stmt = gimple_build_assign (var, MULT_EXPR, base, base);
    2520            9 :       return stmt;
    2521              :     }
    2522              : 
    2523              :   /* Catch square root.  */
    2524           44 :   if (TREE_CODE (exp) == REAL_CST
    2525           44 :       && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
    2526              :     {
    2527           10 :       *type_out = get_vectype_for_scalar_type (vinfo, TREE_TYPE (base));
    2528           10 :       if (*type_out
    2529           10 :           && direct_internal_fn_supported_p (IFN_SQRT, *type_out,
    2530              :                                              OPTIMIZE_FOR_SPEED))
    2531              :         {
    2532            8 :           gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
    2533            8 :           var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
    2534            8 :           gimple_call_set_lhs (stmt, var);
    2535            8 :           gimple_call_set_nothrow (stmt, true);
    2536            8 :           return stmt;
    2537              :         }
    2538              :     }
    2539              : 
    2540              :   return NULL;
    2541              : }
    2542              : 
    2543              : 
    2544              : /* Function vect_recog_widen_sum_pattern
    2545              : 
    2546              :    Try to find the following pattern:
    2547              : 
    2548              :      type x_t;
    2549              :      TYPE x_T, sum = init;
    2550              :    loop:
    2551              :      sum_0 = phi <init, sum_1>
    2552              :      S1  x_t = *p;
    2553              :      S2  x_T = (TYPE) x_t;
    2554              :      S3  sum_1 = x_T + sum_0;
    2555              : 
    2556              :    where type 'TYPE' is at least double the size of type 'type', i.e - we're
    2557              :    summing elements of type 'type' into an accumulator of type 'TYPE'. This is
    2558              :    a special case of a reduction computation.
    2559              : 
    2560              :    Input:
    2561              : 
    2562              :    * STMT_VINFO: The stmt from which the pattern search begins. In the example,
    2563              :    when this function is called with S3, the pattern {S2,S3} will be detected.
    2564              : 
    2565              :    Output:
    2566              : 
    2567              :    * TYPE_OUT: The type of the output of this pattern.
    2568              : 
    2569              :    * Return value: A new stmt that will be used to replace the sequence of
    2570              :    stmts that constitute the pattern. In this case it will be:
    2571              :         WIDEN_SUM <x_t, sum_0>
    2572              : 
    2573              :    Note: The widening-sum idiom is a widening reduction pattern that is
    2574              :          vectorized without preserving all the intermediate results. It
    2575              :          produces only N/2 (widened) results (by summing up pairs of
    2576              :          intermediate results) rather than all N results.  Therefore, we
    2577              :          cannot allow this pattern when we want to get all the results and in
    2578              :          the correct order (as is the case when this computation is in an
    2579              :          inner-loop nested in an outer-loop that us being vectorized).  */
    2580              : 
    2581              : static gimple *
    2582     32303324 : vect_recog_widen_sum_pattern (vec_info *vinfo,
    2583              :                               stmt_vec_info stmt_vinfo, tree *type_out)
    2584              : {
    2585     32303324 :   gimple *last_stmt = stmt_vinfo->stmt;
    2586     32303324 :   tree oprnd0, oprnd1;
    2587     32303324 :   tree type;
    2588     32303324 :   gimple *pattern_stmt;
    2589     32303324 :   tree var;
    2590              : 
    2591              :   /* Look for the following pattern
    2592              :           DX = (TYPE) X;
    2593              :           sum_1 = DX + sum_0;
    2594              :      In which DX is at least double the size of X, and sum_1 has been
    2595              :      recognized as a reduction variable.
    2596              :    */
    2597              : 
    2598              :   /* Starting from LAST_STMT, follow the defs of its uses in search
    2599              :      of the above pattern.  */
    2600              : 
    2601     32303324 :   if (!vect_reassociating_reduction_p (vinfo, stmt_vinfo, PLUS_EXPR,
    2602              :                                        &oprnd0, &oprnd1)
    2603        52745 :       || TREE_CODE (oprnd0) != SSA_NAME
    2604     32355800 :       || !vinfo->lookup_def (oprnd0))
    2605              :     return NULL;
    2606              : 
    2607        52399 :   type = TREE_TYPE (gimple_get_lhs (last_stmt));
    2608              : 
    2609              :   /* So far so good.  Since last_stmt was detected as a (summation) reduction,
    2610              :      we know that oprnd1 is the reduction variable (defined by a loop-header
    2611              :      phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
    2612              :      Left to check that oprnd0 is defined by a cast from type 'type' to type
    2613              :      'TYPE'.  */
    2614              : 
    2615        52399 :   vect_unpromoted_value unprom0;
    2616        52399 :   if (!vect_look_through_possible_promotion (vinfo, oprnd0, &unprom0)
    2617        52399 :       || TYPE_PRECISION (unprom0.type) * 2 > TYPE_PRECISION (type))
    2618              :     return NULL;
    2619              : 
    2620         2311 :   vect_pattern_detected ("vect_recog_widen_sum_pattern", last_stmt);
    2621              : 
    2622              :   /* If the exact input type is not supported, widen it to an intermediate
    2623              :      type before adding it to the accumulator.  Start with the narrowest
    2624              :      type in order to retain the largest vectorization factor.  */
    2625         2311 :   tree input_type = unprom0.type;
    2626         2311 :   tree input_vectype = NULL_TREE;
    2627              : 
    2628         4258 :   while (!vect_supportable_conv_optab_p (vinfo, type, WIDEN_SUM_EXPR,
    2629              :                                          input_type, type_out, &input_vectype))
    2630              :     {
    2631         4258 :       unsigned int precision
    2632         4258 :         = vect_element_precision (TYPE_PRECISION (input_type) + 1);
    2633              : 
    2634         4258 :       if (precision > TYPE_PRECISION (type) / 2)
    2635              :         return NULL;
    2636              : 
    2637         1947 :       input_type = build_nonstandard_integer_type
    2638         1947 :         (precision, TYPE_UNSIGNED (unprom0.type));
    2639              :     }
    2640              : 
    2641            0 :   tree input = vect_convert_input (vinfo, stmt_vinfo, input_type, &unprom0,
    2642              :                                    input_vectype);
    2643              : 
    2644            0 :   var = vect_recog_temp_ssa_var (type, NULL);
    2645            0 :   pattern_stmt = gimple_build_assign (var, WIDEN_SUM_EXPR, input, oprnd1);
    2646              : 
    2647            0 :   return pattern_stmt;
    2648              : }
    2649              : 
    2650              : /* Function vect_recog_bitfield_ref_pattern
    2651              : 
    2652              :    Try to find the following pattern:
    2653              : 
    2654              :    bf_value = BIT_FIELD_REF (container, bitsize, bitpos);
    2655              :    result = (type_out) bf_value;
    2656              : 
    2657              :    or
    2658              : 
    2659              :    if (BIT_FIELD_REF (container, bitsize, bitpos) `cmp` <constant>)
    2660              : 
    2661              :    where type_out is a non-bitfield type, that is to say, it's precision matches
    2662              :    2^(TYPE_SIZE(type_out) - (TYPE_UNSIGNED (type_out) ? 1 : 2)).
    2663              : 
    2664              :    Input:
    2665              : 
    2666              :    * STMT_VINFO: The stmt from which the pattern search begins.
    2667              :    here it starts with:
    2668              :    result = (type_out) bf_value;
    2669              : 
    2670              :    or
    2671              : 
    2672              :    if (BIT_FIELD_REF (container, bitsize, bitpos) `cmp` <constant>)
    2673              : 
    2674              :    Output:
    2675              : 
    2676              :    * TYPE_OUT: The vector type of the output of this pattern.
    2677              : 
    2678              :    * Return value: A new stmt that will be used to replace the sequence of
    2679              :    stmts that constitute the pattern. If the precision of type_out is bigger
    2680              :    than the precision type of _1 we perform the widening before the shifting,
    2681              :    since the new precision will be large enough to shift the value and moving
    2682              :    widening operations up the statement chain enables the generation of
    2683              :    widening loads.  If we are widening and the operation after the pattern is
    2684              :    an addition then we mask first and shift later, to enable the generation of
    2685              :    shifting adds.  In the case of narrowing we will always mask first, shift
    2686              :    last and then perform a narrowing operation.  This will enable the
    2687              :    generation of narrowing shifts.
    2688              : 
    2689              :    Widening with mask first, shift later:
    2690              :    container = (type_out) container;
    2691              :    masked = container & (((1 << bitsize) - 1) << bitpos);
    2692              :    result = masked >> bitpos;
    2693              : 
    2694              :    Widening with shift first, mask last:
    2695              :    container = (type_out) container;
    2696              :    shifted = container >> bitpos;
    2697              :    result = shifted & ((1 << bitsize) - 1);
    2698              : 
    2699              :    Narrowing:
    2700              :    masked = container & (((1 << bitsize) - 1) << bitpos);
    2701              :    result = masked >> bitpos;
    2702              :    result = (type_out) result;
    2703              : 
    2704              :    If the bitfield is signed and it's wider than type_out, we need to
    2705              :    keep the result sign-extended:
    2706              :    container = (type) container;
    2707              :    masked = container << (prec - bitsize - bitpos);
    2708              :    result = (type_out) (masked >> (prec - bitsize));
    2709              : 
    2710              :    Here type is the signed variant of the wider of type_out and the type
    2711              :    of container.
    2712              : 
    2713              :    The shifting is always optional depending on whether bitpos != 0.
    2714              : 
    2715              :    When the original bitfield was inside a gcond then an new gcond is also
    2716              :    generated with the newly `result` as the operand to the comparison.
    2717              : 
    2718              : */
    2719              : 
    2720              : static gimple *
    2721     32245000 : vect_recog_bitfield_ref_pattern (vec_info *vinfo, stmt_vec_info stmt_info,
    2722              :                                  tree *type_out)
    2723              : {
    2724     32245000 :   gimple *bf_stmt = NULL;
    2725     32245000 :   tree lhs = NULL_TREE;
    2726     32245000 :   tree ret_type = NULL_TREE;
    2727     32245000 :   gimple *stmt = STMT_VINFO_STMT (stmt_info);
    2728     32245000 :   if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
    2729              :     {
    2730      5384665 :       tree op = gimple_cond_lhs (cond_stmt);
    2731      5384665 :       if (TREE_CODE (op) != SSA_NAME)
    2732              :         return NULL;
    2733      5384365 :       bf_stmt = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op));
    2734      5384365 :       if (TREE_CODE (gimple_cond_rhs (cond_stmt)) != INTEGER_CST)
    2735              :         return NULL;
    2736              :     }
    2737     26860335 :   else if (is_gimple_assign (stmt)
    2738     22455299 :            && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
    2739     29860372 :            && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
    2740              :     {
    2741      2958563 :       gimple *second_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
    2742      2958563 :       bf_stmt = dyn_cast <gassign *> (second_stmt);
    2743      2958563 :       lhs = gimple_assign_lhs (stmt);
    2744      2958563 :       ret_type = TREE_TYPE (lhs);
    2745              :     }
    2746              : 
    2747      6437924 :   if (!bf_stmt
    2748      6437924 :       || gimple_assign_rhs_code (bf_stmt) != BIT_FIELD_REF)
    2749              :     return NULL;
    2750              : 
    2751        16751 :   tree bf_ref = gimple_assign_rhs1 (bf_stmt);
    2752        16751 :   tree container = TREE_OPERAND (bf_ref, 0);
    2753        16751 :   ret_type = ret_type ? ret_type : TREE_TYPE (container);
    2754              : 
    2755        16751 :   if (!bit_field_offset (bf_ref).is_constant ()
    2756        16751 :       || !bit_field_size (bf_ref).is_constant ()
    2757        16751 :       || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (container))))
    2758              :     return NULL;
    2759              : 
    2760        33124 :   if (!INTEGRAL_TYPE_P (TREE_TYPE (bf_ref))
    2761        16749 :       || !INTEGRAL_TYPE_P (TREE_TYPE (container))
    2762        18924 :       || TYPE_MODE (TREE_TYPE (container)) == E_BLKmode)
    2763              :     return NULL;
    2764              : 
    2765         2173 :   gimple *use_stmt, *pattern_stmt;
    2766         2173 :   use_operand_p use_p;
    2767         2173 :   bool shift_first = true;
    2768         2173 :   tree container_type = TREE_TYPE (container);
    2769         2173 :   tree vectype = get_vectype_for_scalar_type (vinfo, container_type);
    2770              : 
    2771              :   /* Calculate shift_n before the adjustments for widening loads, otherwise
    2772              :      the container may change and we have to consider offset change for
    2773              :      widening loads on big endianness.  The shift_n calculated here can be
    2774              :      independent of widening.  */
    2775         2173 :   unsigned HOST_WIDE_INT shift_n = bit_field_offset (bf_ref).to_constant ();
    2776         2173 :   unsigned HOST_WIDE_INT mask_width = bit_field_size (bf_ref).to_constant ();
    2777         2173 :   unsigned HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (container_type));
    2778         2173 :   if (BYTES_BIG_ENDIAN)
    2779              :     shift_n = prec - shift_n - mask_width;
    2780              : 
    2781         2173 :   bool ref_sext = (!TYPE_UNSIGNED (TREE_TYPE (bf_ref)) &&
    2782         1400 :                    TYPE_PRECISION (ret_type) > mask_width);
    2783         2173 :   bool load_widen = (TYPE_PRECISION (TREE_TYPE (container)) <
    2784         2173 :                      TYPE_PRECISION (ret_type));
    2785              : 
    2786              :   /* We move the conversion earlier if the loaded type is smaller than the
    2787              :      return type to enable the use of widening loads.  And if we need a
    2788              :      sign extension, we need to convert the loaded value early to a signed
    2789              :      type as well.  */
    2790         2173 :   if (ref_sext || load_widen)
    2791              :     {
    2792          947 :       tree type = load_widen ? ret_type : container_type;
    2793          947 :       if (ref_sext)
    2794          908 :         type = gimple_signed_type (type);
    2795          947 :       pattern_stmt = gimple_build_assign (vect_recog_temp_ssa_var (type),
    2796              :                                           NOP_EXPR, container);
    2797          947 :       container = gimple_get_lhs (pattern_stmt);
    2798          947 :       container_type = TREE_TYPE (container);
    2799          947 :       prec = tree_to_uhwi (TYPE_SIZE (container_type));
    2800          947 :       vectype = get_vectype_for_scalar_type (vinfo, container_type);
    2801          947 :       append_pattern_def_seq (vinfo, stmt_info, pattern_stmt, vectype);
    2802              :     }
    2803         1226 :   else if (!useless_type_conversion_p (TREE_TYPE (container), ret_type))
    2804              :     /* If we are doing the conversion last then also delay the shift as we may
    2805              :        be able to combine the shift and conversion in certain cases.  */
    2806              :     shift_first = false;
    2807              : 
    2808              :   /* If the only use of the result of this BIT_FIELD_REF + CONVERT is a
    2809              :      PLUS_EXPR then do the shift last as some targets can combine the shift and
    2810              :      add into a single instruction.  */
    2811         1416 :   if (lhs && !is_pattern_stmt_p (stmt_info)
    2812         3589 :       && single_imm_use (lhs, &use_p, &use_stmt))
    2813              :     {
    2814         1049 :       if (gimple_code (use_stmt) == GIMPLE_ASSIGN
    2815         1049 :           && gimple_assign_rhs_code (use_stmt) == PLUS_EXPR)
    2816              :         shift_first = false;
    2817              :     }
    2818              : 
    2819              :   /* If we don't have to shift we only generate the mask, so just fix the
    2820              :      code-path to shift_first.  */
    2821         2173 :   if (shift_n == 0)
    2822          763 :     shift_first = true;
    2823              : 
    2824         2173 :   tree result;
    2825         2173 :   if (shift_first && !ref_sext)
    2826              :     {
    2827          513 :       tree shifted = container;
    2828          513 :       if (shift_n)
    2829              :         {
    2830           65 :           pattern_stmt
    2831           65 :             = gimple_build_assign (vect_recog_temp_ssa_var (container_type),
    2832              :                                    RSHIFT_EXPR, container,
    2833           65 :                                    build_int_cst (sizetype, shift_n));
    2834           65 :           shifted = gimple_assign_lhs (pattern_stmt);
    2835           65 :           append_pattern_def_seq (vinfo, stmt_info, pattern_stmt, vectype);
    2836              :         }
    2837              : 
    2838          513 :       tree mask = wide_int_to_tree (container_type,
    2839          513 :                                     wi::mask (mask_width, false, prec));
    2840              : 
    2841          513 :       pattern_stmt
    2842          513 :         = gimple_build_assign (vect_recog_temp_ssa_var (container_type),
    2843              :                                BIT_AND_EXPR, shifted, mask);
    2844          513 :       result = gimple_assign_lhs (pattern_stmt);
    2845              :     }
    2846              :   else
    2847              :     {
    2848         1660 :       tree temp = vect_recog_temp_ssa_var (container_type);
    2849         1660 :       if (!ref_sext)
    2850              :         {
    2851          752 :           tree mask = wide_int_to_tree (container_type,
    2852          752 :                                         wi::shifted_mask (shift_n,
    2853              :                                                           mask_width,
    2854              :                                                           false, prec));
    2855          752 :           pattern_stmt = gimple_build_assign (temp, BIT_AND_EXPR,
    2856              :                                               container, mask);
    2857              :         }
    2858              :       else
    2859              :         {
    2860          908 :           HOST_WIDE_INT shl = prec - shift_n - mask_width;
    2861          908 :           shift_n += shl;
    2862          908 :           pattern_stmt = gimple_build_assign (temp, LSHIFT_EXPR,
    2863              :                                               container,
    2864              :                                               build_int_cst (sizetype,
    2865          908 :                                                              shl));
    2866              :         }
    2867              : 
    2868         1660 :       tree masked = gimple_assign_lhs (pattern_stmt);
    2869         1660 :       append_pattern_def_seq (vinfo, stmt_info, pattern_stmt, vectype);
    2870         1660 :       pattern_stmt
    2871         1660 :         = gimple_build_assign (vect_recog_temp_ssa_var (container_type),
    2872              :                                RSHIFT_EXPR, masked,
    2873         1660 :                                build_int_cst (sizetype, shift_n));
    2874         1660 :       result = gimple_assign_lhs (pattern_stmt);
    2875              :     }
    2876              : 
    2877         2173 :   if (!useless_type_conversion_p (TREE_TYPE (result), ret_type))
    2878              :     {
    2879         1444 :       append_pattern_def_seq (vinfo, stmt_info, pattern_stmt, vectype);
    2880         1444 :       pattern_stmt
    2881         1444 :         = gimple_build_assign (vect_recog_temp_ssa_var (ret_type),
    2882              :                                NOP_EXPR, result);
    2883              :     }
    2884              : 
    2885         2173 :   if (!lhs)
    2886              :     {
    2887          757 :       if (!vectype)
    2888              :         return NULL;
    2889              : 
    2890          619 :       append_pattern_def_seq (vinfo, stmt_info, pattern_stmt, vectype);
    2891          619 :       vectype = truth_type_for (vectype);
    2892              : 
    2893              :       /* FIXME: This part extracts the boolean value out of the bitfield in the
    2894              :                 same way as vect_recog_gcond_pattern does.  However because
    2895              :                 patterns cannot match the same root twice,  when we handle and
    2896              :                 lower the bitfield in the gcond, vect_recog_gcond_pattern can't
    2897              :                 apply anymore.  We should really fix it so that we don't need to
    2898              :                 duplicate transformations like these.  */
    2899          619 :       tree new_lhs = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    2900          619 :       gcond *cond_stmt = dyn_cast <gcond *> (stmt_info->stmt);
    2901          619 :       tree cond_cst = gimple_cond_rhs (cond_stmt);
    2902          619 :       gimple *new_stmt
    2903          619 :         = gimple_build_assign (new_lhs, gimple_cond_code (cond_stmt),
    2904              :                                gimple_get_lhs (pattern_stmt),
    2905              :                                fold_convert (container_type, cond_cst));
    2906          619 :       append_pattern_def_seq (vinfo, stmt_info, new_stmt, vectype, container_type);
    2907          619 :       pattern_stmt
    2908          619 :         = gimple_build_cond (NE_EXPR, new_lhs,
    2909          619 :                              build_zero_cst (TREE_TYPE (new_lhs)),
    2910              :                              NULL_TREE, NULL_TREE);
    2911              :     }
    2912              : 
    2913         2035 :   *type_out = STMT_VINFO_VECTYPE (stmt_info);
    2914         2035 :   vect_pattern_detected ("bitfield_ref pattern", stmt_info->stmt);
    2915              : 
    2916         2035 :   return pattern_stmt;
    2917              : }
    2918              : 
    2919              : /* Function vect_recog_bit_insert_pattern
    2920              : 
    2921              :    Try to find the following pattern:
    2922              : 
    2923              :    written = BIT_INSERT_EXPR (container, value, bitpos);
    2924              : 
    2925              :    Input:
    2926              : 
    2927              :    * STMT_VINFO: The stmt we want to replace.
    2928              : 
    2929              :    Output:
    2930              : 
    2931              :    * TYPE_OUT: The vector type of the output of this pattern.
    2932              : 
    2933              :    * Return value: A new stmt that will be used to replace the sequence of
    2934              :    stmts that constitute the pattern. In this case it will be:
    2935              :    value = (container_type) value;          // Make sure
    2936              :    shifted = value << bitpos;                 // Shift value into place
    2937              :    masked = shifted & (mask << bitpos);           // Mask off the non-relevant bits in
    2938              :                                             // the 'to-write value'.
    2939              :    cleared = container & ~(mask << bitpos); // Clearing the bits we want to
    2940              :                                             // write to from the value we want
    2941              :                                             // to write to.
    2942              :    written = cleared | masked;              // Write bits.
    2943              : 
    2944              : 
    2945              :    where mask = ((1 << TYPE_PRECISION (value)) - 1), a mask to keep the number of
    2946              :    bits corresponding to the real size of the bitfield value we are writing to.
    2947              :    The shifting is always optional depending on whether bitpos != 0.
    2948              : 
    2949              : */
    2950              : 
    2951              : static gimple *
    2952     32248050 : vect_recog_bit_insert_pattern (vec_info *vinfo, stmt_vec_info stmt_info,
    2953              :                                tree *type_out)
    2954              : {
    2955     32248050 :   gassign *bf_stmt = dyn_cast <gassign *> (stmt_info->stmt);
    2956     29980815 :   if (!bf_stmt || gimple_assign_rhs_code (bf_stmt) != BIT_INSERT_EXPR)
    2957              :     return NULL;
    2958              : 
    2959          680 :   tree container = gimple_assign_rhs1 (bf_stmt);
    2960          680 :   tree value = gimple_assign_rhs2 (bf_stmt);
    2961          680 :   tree shift = gimple_assign_rhs3 (bf_stmt);
    2962              : 
    2963          680 :   tree bf_type = TREE_TYPE (value);
    2964          680 :   tree container_type = TREE_TYPE (container);
    2965              : 
    2966          680 :   if (!INTEGRAL_TYPE_P (container_type)
    2967          680 :       || !tree_fits_uhwi_p (TYPE_SIZE (container_type)))
    2968              :     return NULL;
    2969              : 
    2970          508 :   gimple *pattern_stmt;
    2971              : 
    2972          508 :   vect_unpromoted_value unprom;
    2973          508 :   unprom.set_op (value, vect_internal_def);
    2974          508 :   value = vect_convert_input (vinfo, stmt_info, container_type, &unprom,
    2975              :                               get_vectype_for_scalar_type (vinfo,
    2976              :                                                            container_type));
    2977              : 
    2978          508 :   unsigned HOST_WIDE_INT mask_width = TYPE_PRECISION (bf_type);
    2979          508 :   unsigned HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (container_type));
    2980          508 :   unsigned HOST_WIDE_INT shift_n = tree_to_uhwi (shift);
    2981          508 :   if (BYTES_BIG_ENDIAN)
    2982              :     {
    2983              :       shift_n = prec - shift_n - mask_width;
    2984              :       shift = build_int_cst (TREE_TYPE (shift), shift_n);
    2985              :     }
    2986              : 
    2987          508 :   if (!useless_type_conversion_p (TREE_TYPE (value), container_type))
    2988              :     {
    2989            0 :       pattern_stmt =
    2990            0 :         gimple_build_assign (vect_recog_temp_ssa_var (container_type),
    2991              :                              NOP_EXPR, value);
    2992            0 :       append_pattern_def_seq (vinfo, stmt_info, pattern_stmt);
    2993            0 :       value = gimple_get_lhs (pattern_stmt);
    2994              :     }
    2995              : 
    2996              :   /* Shift VALUE into place.  */
    2997          508 :   tree shifted = value;
    2998          508 :   if (shift_n)
    2999              :     {
    3000          249 :       gimple_seq stmts = NULL;
    3001          249 :       shifted
    3002          249 :         = gimple_build (&stmts, LSHIFT_EXPR, container_type, value, shift);
    3003          249 :       if (!gimple_seq_empty_p (stmts))
    3004          112 :         append_pattern_def_seq (vinfo, stmt_info,
    3005              :                                 gimple_seq_first_stmt (stmts));
    3006              :     }
    3007              : 
    3008          508 :   tree mask_t
    3009          508 :     = wide_int_to_tree (container_type,
    3010          508 :                         wi::shifted_mask (shift_n, mask_width, false, prec));
    3011              : 
    3012              :   /* Clear bits we don't want to write back from SHIFTED.  */
    3013          508 :   gimple_seq stmts = NULL;
    3014          508 :   tree masked = gimple_build (&stmts, BIT_AND_EXPR, container_type, shifted,
    3015              :                               mask_t);
    3016          508 :   if (!gimple_seq_empty_p (stmts))
    3017              :     {
    3018          118 :       pattern_stmt = gimple_seq_first_stmt (stmts);
    3019          118 :       append_pattern_def_seq (vinfo, stmt_info, pattern_stmt);
    3020              :     }
    3021              : 
    3022              :   /* Mask off the bits in the container that we are to write to.  */
    3023          508 :   mask_t = wide_int_to_tree (container_type,
    3024          508 :                              wi::shifted_mask (shift_n, mask_width, true, prec));
    3025          508 :   tree cleared = vect_recog_temp_ssa_var (container_type);
    3026          508 :   pattern_stmt = gimple_build_assign (cleared, BIT_AND_EXPR, container, mask_t);
    3027          508 :   append_pattern_def_seq (vinfo, stmt_info, pattern_stmt);
    3028              : 
    3029              :   /* Write MASKED into CLEARED.  */
    3030          508 :   pattern_stmt
    3031          508 :     = gimple_build_assign (vect_recog_temp_ssa_var (container_type),
    3032              :                            BIT_IOR_EXPR, cleared, masked);
    3033              : 
    3034          508 :   *type_out = STMT_VINFO_VECTYPE (stmt_info);
    3035          508 :   vect_pattern_detected ("bit_insert pattern", stmt_info->stmt);
    3036              : 
    3037          508 :   return pattern_stmt;
    3038              : }
    3039              : 
    3040              : 
    3041              : /* Recognize cases in which an operation is performed in one type WTYPE
    3042              :    but could be done more efficiently in a narrower type NTYPE.  For example,
    3043              :    if we have:
    3044              : 
    3045              :      ATYPE a;  // narrower than NTYPE
    3046              :      BTYPE b;  // narrower than NTYPE
    3047              :      WTYPE aw = (WTYPE) a;
    3048              :      WTYPE bw = (WTYPE) b;
    3049              :      WTYPE res = aw + bw;  // only uses of aw and bw
    3050              : 
    3051              :    then it would be more efficient to do:
    3052              : 
    3053              :      NTYPE an = (NTYPE) a;
    3054              :      NTYPE bn = (NTYPE) b;
    3055              :      NTYPE resn = an + bn;
    3056              :      WTYPE res = (WTYPE) resn;
    3057              : 
    3058              :    Other situations include things like:
    3059              : 
    3060              :      ATYPE a;  // NTYPE or narrower
    3061              :      WTYPE aw = (WTYPE) a;
    3062              :      WTYPE res = aw + b;
    3063              : 
    3064              :    when only "(NTYPE) res" is significant.  In that case it's more efficient
    3065              :    to truncate "b" and do the operation on NTYPE instead:
    3066              : 
    3067              :      NTYPE an = (NTYPE) a;
    3068              :      NTYPE bn = (NTYPE) b;  // truncation
    3069              :      NTYPE resn = an + bn;
    3070              :      WTYPE res = (WTYPE) resn;
    3071              : 
    3072              :    All users of "res" should then use "resn" instead, making the final
    3073              :    statement dead (not marked as relevant).  The final statement is still
    3074              :    needed to maintain the type correctness of the IR.
    3075              : 
    3076              :    vect_determine_precisions has already determined the minimum
    3077              :    precision of the operation and the minimum precision required
    3078              :    by users of the result.  */
    3079              : 
    3080              : static gimple *
    3081     32248506 : vect_recog_over_widening_pattern (vec_info *vinfo,
    3082              :                                   stmt_vec_info last_stmt_info, tree *type_out)
    3083              : {
    3084     32248506 :   gassign *last_stmt = dyn_cast <gassign *> (last_stmt_info->stmt);
    3085     22459424 :   if (!last_stmt)
    3086              :     return NULL;
    3087              : 
    3088              :   /* See whether we have found that this operation can be done on a
    3089              :      narrower type without changing its semantics.  */
    3090     22459424 :   unsigned int new_precision = last_stmt_info->operation_precision;
    3091     22459424 :   if (!new_precision)
    3092              :     return NULL;
    3093              : 
    3094      1669039 :   tree lhs = gimple_assign_lhs (last_stmt);
    3095      1669039 :   tree type = TREE_TYPE (lhs);
    3096      1669039 :   tree_code code = gimple_assign_rhs_code (last_stmt);
    3097              : 
    3098              :   /* Punt for reductions where we don't handle the type conversions.  */
    3099      1669039 :   if (vect_is_reduction (last_stmt_info))
    3100              :     return NULL;
    3101              : 
    3102              :   /* Keep the first operand of a COND_EXPR as-is: only the other two
    3103              :      operands are interesting.  */
    3104      1660709 :   unsigned int first_op = (code == COND_EXPR ? 2 : 1);
    3105              : 
    3106              :   /* Check the operands.  */
    3107      1660709 :   unsigned int nops = gimple_num_ops (last_stmt) - first_op;
    3108      1660709 :   auto_vec <vect_unpromoted_value, 3> unprom (nops);
    3109      1660709 :   unprom.quick_grow_cleared (nops);
    3110      1660709 :   unsigned int min_precision = 0;
    3111      1660709 :   bool single_use_p = false;
    3112      6622510 :   for (unsigned int i = 0; i < nops; ++i)
    3113              :     {
    3114      3302804 :       tree op = gimple_op (last_stmt, first_op + i);
    3115      3302804 :       if (TREE_CODE (op) == INTEGER_CST)
    3116      1511459 :         unprom[i].set_op (op, vect_constant_def);
    3117      1791345 :       else if (TREE_CODE (op) == SSA_NAME)
    3118              :         {
    3119      1791345 :           bool op_single_use_p = true;
    3120      1791345 :           if (!vect_look_through_possible_promotion (vinfo, op, &unprom[i],
    3121              :                                                      &op_single_use_p))
    3122         1712 :             return NULL;
    3123              :           /* If:
    3124              : 
    3125              :              (1) N bits of the result are needed;
    3126              :              (2) all inputs are widened from M<N bits; and
    3127              :              (3) one operand OP is a single-use SSA name
    3128              : 
    3129              :              we can shift the M->N widening from OP to the output
    3130              :              without changing the number or type of extensions involved.
    3131              :              This then reduces the number of copies of STMT_INFO.
    3132              : 
    3133              :              If instead of (3) more than one operand is a single-use SSA name,
    3134              :              shifting the extension to the output is even more of a win.
    3135              : 
    3136              :              If instead:
    3137              : 
    3138              :              (1) N bits of the result are needed;
    3139              :              (2) one operand OP2 is widened from M2<N bits;
    3140              :              (3) another operand OP1 is widened from M1<M2 bits; and
    3141              :              (4) both OP1 and OP2 are single-use
    3142              : 
    3143              :              the choice is between:
    3144              : 
    3145              :              (a) truncating OP2 to M1, doing the operation on M1,
    3146              :                  and then widening the result to N
    3147              : 
    3148              :              (b) widening OP1 to M2, doing the operation on M2, and then
    3149              :                  widening the result to N
    3150              : 
    3151              :              Both shift the M2->N widening of the inputs to the output.
    3152              :              (a) additionally shifts the M1->M2 widening to the output;
    3153              :              it requires fewer copies of STMT_INFO but requires an extra
    3154              :              M2->M1 truncation.
    3155              : 
    3156              :              Which is better will depend on the complexity and cost of
    3157              :              STMT_INFO, which is hard to predict at this stage.  However,
    3158              :              a clear tie-breaker in favor of (b) is the fact that the
    3159              :              truncation in (a) increases the length of the operation chain.
    3160              : 
    3161              :              If instead of (4) only one of OP1 or OP2 is single-use,
    3162              :              (b) is still a win over doing the operation in N bits:
    3163              :              it still shifts the M2->N widening on the single-use operand
    3164              :              to the output and reduces the number of STMT_INFO copies.
    3165              : 
    3166              :              If neither operand is single-use then operating on fewer than
    3167              :              N bits might lead to more extensions overall.  Whether it does
    3168              :              or not depends on global information about the vectorization
    3169              :              region, and whether that's a good trade-off would again
    3170              :              depend on the complexity and cost of the statements involved,
    3171              :              as well as things like register pressure that are not normally
    3172              :              modelled at this stage.  We therefore ignore these cases
    3173              :              and just optimize the clear single-use wins above.
    3174              : 
    3175              :              Thus we take the maximum precision of the unpromoted operands
    3176              :              and record whether any operand is single-use.  */
    3177      1789633 :           if (unprom[i].dt == vect_internal_def)
    3178              :             {
    3179      1029768 :               min_precision = MAX (min_precision,
    3180              :                                    TYPE_PRECISION (unprom[i].type));
    3181      1029768 :               single_use_p |= op_single_use_p;
    3182              :             }
    3183              :         }
    3184              :       else
    3185              :         return NULL;
    3186              :     }
    3187              : 
    3188              :   /* Although the operation could be done in operation_precision, we have
    3189              :      to balance that against introducing extra truncations or extensions.
    3190              :      Calculate the minimum precision that can be handled efficiently.
    3191              : 
    3192              :      The loop above determined that the operation could be handled
    3193              :      efficiently in MIN_PRECISION if SINGLE_USE_P; this would shift an
    3194              :      extension from the inputs to the output without introducing more
    3195              :      instructions, and would reduce the number of instructions required
    3196              :      for STMT_INFO itself.
    3197              : 
    3198              :      vect_determine_precisions has also determined that the result only
    3199              :      needs min_output_precision bits.  Truncating by a factor of N times
    3200              :      requires a tree of N - 1 instructions, so if TYPE is N times wider
    3201              :      than min_output_precision, doing the operation in TYPE and truncating
    3202              :      the result requires N + (N - 1) = 2N - 1 instructions per output vector.
    3203              :      In contrast:
    3204              : 
    3205              :      - truncating the input to a unary operation and doing the operation
    3206              :        in the new type requires at most N - 1 + 1 = N instructions per
    3207              :        output vector
    3208              : 
    3209              :      - doing the same for a binary operation requires at most
    3210              :        (N - 1) * 2 + 1 = 2N - 1 instructions per output vector
    3211              : 
    3212              :      Both unary and binary operations require fewer instructions than
    3213              :      this if the operands were extended from a suitable truncated form.
    3214              :      Thus there is usually nothing to lose by doing operations in
    3215              :      min_output_precision bits, but there can be something to gain.  */
    3216      1658997 :   if (!single_use_p)
    3217      1309752 :     min_precision = last_stmt_info->min_output_precision;
    3218              :   else
    3219       349245 :     min_precision = MIN (min_precision, last_stmt_info->min_output_precision);
    3220              : 
    3221              :   /* Apply the minimum efficient precision we just calculated.  */
    3222      1658997 :   if (new_precision < min_precision)
    3223              :     new_precision = min_precision;
    3224      1658997 :   new_precision = vect_element_precision (new_precision);
    3225      1658997 :   if (new_precision >= TYPE_PRECISION (type))
    3226              :     return NULL;
    3227              : 
    3228       154270 :   vect_pattern_detected ("vect_recog_over_widening_pattern", last_stmt);
    3229              : 
    3230       154270 :   *type_out = get_vectype_for_scalar_type (vinfo, type);
    3231       154270 :   if (!*type_out)
    3232              :     return NULL;
    3233              : 
    3234              :   /* We've found a viable pattern.  Get the new type of the operation.  */
    3235       135989 :   bool unsigned_p = (last_stmt_info->operation_sign == UNSIGNED);
    3236       135989 :   tree new_type = build_nonstandard_integer_type (new_precision, unsigned_p);
    3237              : 
    3238              :   /* If we're truncating an operation, we need to make sure that we
    3239              :      don't introduce new undefined overflow.  The codes tested here are
    3240              :      a subset of those accepted by vect_truncatable_operation_p.  */
    3241       135989 :   tree op_type = new_type;
    3242       135989 :   if (TYPE_OVERFLOW_UNDEFINED (new_type)
    3243       176213 :       && (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR))
    3244        27603 :     op_type = build_nonstandard_integer_type (new_precision, true);
    3245              : 
    3246       135989 :   tree new_vectype = get_vectype_for_scalar_type (vinfo, new_type);
    3247       135989 :   tree op_vectype = get_vectype_for_scalar_type (vinfo, op_type);
    3248       135989 :   if (!new_vectype || !op_vectype)
    3249              :     return NULL;
    3250              : 
    3251              :   /* Verify we can handle the new operation.  For shifts and rotates
    3252              :      apply heuristic of whether we are likely facing vector-vector or
    3253              :      vector-scalar operation.  Since we are eventually expecting that
    3254              :      a later pattern might eventually want to rewrite an unsupported
    3255              :      into a supported case error on that side in case the original
    3256              :      operation was not supported either or this is a binary operation
    3257              :      and the 2nd operand is constant.  */
    3258       135989 :   if (code == RSHIFT_EXPR || code == LSHIFT_EXPR || code == RROTATE_EXPR)
    3259              :     {
    3260        29124 :       if (!target_has_vecop_for_code (code, op_vectype, optab_vector)
    3261        28065 :           && ((unprom[1].dt != vect_external_def
    3262        27653 :                && unprom[1].dt != vect_constant_def)
    3263        19186 :               || !target_has_vecop_for_code (code, op_vectype, optab_scalar))
    3264        38026 :           && !(!target_has_vecop_for_code (code, *type_out, optab_vector)
    3265         7804 :                && ((unprom[1].dt != vect_external_def
    3266         7804 :                     || unprom[1].dt != vect_constant_def)
    3267              :                    || !target_has_vecop_for_code (code, *type_out,
    3268              :                                                   optab_scalar))))
    3269              :         return NULL;
    3270              :     }
    3271       106865 :   else if (!target_has_vecop_for_code (code, op_vectype, optab_vector)
    3272       106865 :            && (target_has_vecop_for_code (code, *type_out, optab_vector)
    3273           29 :                && !(nops == 2 && unprom[1].dt == vect_constant_def)))
    3274              :     return NULL;
    3275              : 
    3276       134881 :   if (dump_enabled_p ())
    3277         4613 :     dump_printf_loc (MSG_NOTE, vect_location, "demoting %T to %T\n",
    3278              :                      type, new_type);
    3279              : 
    3280              :   /* Calculate the rhs operands for an operation on OP_TYPE.  */
    3281       134881 :   tree ops[3] = {};
    3282       135112 :   for (unsigned int i = 1; i < first_op; ++i)
    3283          231 :     ops[i - 1] = gimple_op (last_stmt, i);
    3284       134881 :   vect_convert_inputs (vinfo, last_stmt_info, nops, &ops[first_op - 1],
    3285       134881 :                        op_type, &unprom[0], op_vectype);
    3286              : 
    3287              :   /* Use the operation to produce a result of type OP_TYPE.  */
    3288       134881 :   tree new_var = vect_recog_temp_ssa_var (op_type, NULL);
    3289       134881 :   gimple *pattern_stmt = gimple_build_assign (new_var, code,
    3290              :                                               ops[0], ops[1], ops[2]);
    3291       134881 :   gimple_set_location (pattern_stmt, gimple_location (last_stmt));
    3292              : 
    3293       134881 :   if (dump_enabled_p ())
    3294         4613 :     dump_printf_loc (MSG_NOTE, vect_location,
    3295              :                      "created pattern stmt: %G", pattern_stmt);
    3296              : 
    3297              :   /* Convert back to the original signedness, if OP_TYPE is different
    3298              :      from NEW_TYPE.  */
    3299       134881 :   if (op_type != new_type)
    3300        27596 :     pattern_stmt = vect_convert_output (vinfo, last_stmt_info, new_type,
    3301              :                                         pattern_stmt, op_vectype);
    3302              : 
    3303              :   /* Promote the result to the original type.  */
    3304       134881 :   pattern_stmt = vect_convert_output (vinfo, last_stmt_info, type,
    3305              :                                       pattern_stmt, new_vectype);
    3306              : 
    3307       134881 :   return pattern_stmt;
    3308      1660709 : }
    3309              : 
    3310              : /* Recognize the following patterns:
    3311              : 
    3312              :      ATYPE a;  // narrower than TYPE
    3313              :      BTYPE b;  // narrower than TYPE
    3314              : 
    3315              :    1) Multiply high with scaling
    3316              :      TYPE res = ((TYPE) a * (TYPE) b) >> c;
    3317              :      Here, c is bitsize (TYPE) / 2 - 1.
    3318              : 
    3319              :    2) ... or also with rounding
    3320              :      TYPE res = (((TYPE) a * (TYPE) b) >> d + 1) >> 1;
    3321              :      Here, d is bitsize (TYPE) / 2 - 2.
    3322              : 
    3323              :    3) Normal multiply high
    3324              :      TYPE res = ((TYPE) a * (TYPE) b) >> e;
    3325              :      Here, e is bitsize (TYPE) / 2.
    3326              : 
    3327              :    where only the bottom half of res is used.  */
    3328              : 
    3329              : static gimple *
    3330     32380537 : vect_recog_mulhs_pattern (vec_info *vinfo,
    3331              :                           stmt_vec_info last_stmt_info, tree *type_out)
    3332              : {
    3333              :   /* Check for a right shift.  */
    3334     32380537 :   gassign *last_stmt = dyn_cast <gassign *> (last_stmt_info->stmt);
    3335     22591249 :   if (!last_stmt
    3336     22591249 :       || gimple_assign_rhs_code (last_stmt) != RSHIFT_EXPR)
    3337              :     return NULL;
    3338              : 
    3339              :   /* Check that the shift result is wider than the users of the
    3340              :      result need (i.e. that narrowing would be a natural choice).  */
    3341       353842 :   tree lhs_type = TREE_TYPE (gimple_assign_lhs (last_stmt));
    3342       353842 :   unsigned int target_precision
    3343       353842 :     = vect_element_precision (last_stmt_info->min_output_precision);
    3344       353842 :   if (!INTEGRAL_TYPE_P (lhs_type)
    3345       353842 :       || target_precision >= TYPE_PRECISION (lhs_type))
    3346              :     return NULL;
    3347              : 
    3348              :   /* Look through any change in sign on the outer shift input.  */
    3349        61158 :   vect_unpromoted_value unprom_rshift_input;
    3350        61158 :   tree rshift_input = vect_look_through_possible_promotion
    3351        61158 :     (vinfo, gimple_assign_rhs1 (last_stmt), &unprom_rshift_input);
    3352        61158 :   if (!rshift_input
    3353        61158 :       || TYPE_PRECISION (TREE_TYPE (rshift_input))
    3354        60560 :            != TYPE_PRECISION (lhs_type))
    3355              :     return NULL;
    3356              : 
    3357              :   /* Get the definition of the shift input.  */
    3358        56261 :   stmt_vec_info rshift_input_stmt_info
    3359        56261 :     = vect_get_internal_def (vinfo, rshift_input);
    3360        56261 :   if (!rshift_input_stmt_info)
    3361              :     return NULL;
    3362        51606 :   gassign *rshift_input_stmt
    3363        51606 :     = dyn_cast <gassign *> (rshift_input_stmt_info->stmt);
    3364        48290 :   if (!rshift_input_stmt)
    3365              :     return NULL;
    3366              : 
    3367        48290 :   stmt_vec_info mulh_stmt_info;
    3368        48290 :   tree scale_term;
    3369        48290 :   bool rounding_p = false;
    3370              : 
    3371              :   /* Check for the presence of the rounding term.  */
    3372        55737 :   if (gimple_assign_rhs_code (rshift_input_stmt) == PLUS_EXPR)
    3373              :     {
    3374              :       /* Check that the outer shift was by 1.  */
    3375        17860 :       if (!integer_onep (gimple_assign_rhs2 (last_stmt)))
    3376         8863 :         return NULL;
    3377              : 
    3378              :       /* Check that the second operand of the PLUS_EXPR is 1.  */
    3379          436 :       if (!integer_onep (gimple_assign_rhs2 (rshift_input_stmt)))
    3380              :         return NULL;
    3381              : 
    3382              :       /* Look through any change in sign on the addition input.  */
    3383           69 :       vect_unpromoted_value unprom_plus_input;
    3384           69 :       tree plus_input = vect_look_through_possible_promotion
    3385           69 :         (vinfo, gimple_assign_rhs1 (rshift_input_stmt), &unprom_plus_input);
    3386           69 :       if (!plus_input
    3387           69 :            || TYPE_PRECISION (TREE_TYPE (plus_input))
    3388           69 :                 != TYPE_PRECISION (TREE_TYPE (rshift_input)))
    3389              :         return NULL;
    3390              : 
    3391              :       /* Get the definition of the multiply-high-scale part.  */
    3392           69 :       stmt_vec_info plus_input_stmt_info
    3393           69 :         = vect_get_internal_def (vinfo, plus_input);
    3394           69 :       if (!plus_input_stmt_info)
    3395              :         return NULL;
    3396           69 :       gassign *plus_input_stmt
    3397         8932 :         = dyn_cast <gassign *> (plus_input_stmt_info->stmt);
    3398           69 :       if (!plus_input_stmt
    3399           69 :           || gimple_assign_rhs_code (plus_input_stmt) != RSHIFT_EXPR)
    3400              :         return NULL;
    3401              : 
    3402              :       /* Look through any change in sign on the scaling input.  */
    3403           67 :       vect_unpromoted_value unprom_scale_input;
    3404           67 :       tree scale_input = vect_look_through_possible_promotion
    3405           67 :         (vinfo, gimple_assign_rhs1 (plus_input_stmt), &unprom_scale_input);
    3406           67 :       if (!scale_input
    3407           67 :           || TYPE_PRECISION (TREE_TYPE (scale_input))
    3408           67 :                != TYPE_PRECISION (TREE_TYPE (plus_input)))
    3409              :         return NULL;
    3410              : 
    3411              :       /* Get the definition of the multiply-high part.  */
    3412           67 :       mulh_stmt_info = vect_get_internal_def (vinfo, scale_input);
    3413           67 :       if (!mulh_stmt_info)
    3414              :         return NULL;
    3415              : 
    3416              :       /* Get the scaling term.  */
    3417           67 :       scale_term = gimple_assign_rhs2 (plus_input_stmt);
    3418           67 :       rounding_p = true;
    3419              :     }
    3420              :   else
    3421              :     {
    3422        39360 :       mulh_stmt_info = rshift_input_stmt_info;
    3423        39360 :       scale_term = gimple_assign_rhs2 (last_stmt);
    3424              :     }
    3425              : 
    3426              :   /* Check that the scaling factor is constant.  */
    3427        39427 :   if (TREE_CODE (scale_term) != INTEGER_CST)
    3428              :     return NULL;
    3429              : 
    3430              :   /* Check whether the scaling input term can be seen as two widened
    3431              :      inputs multiplied together.  */
    3432       115299 :   vect_unpromoted_value unprom_mult[2];
    3433        38433 :   tree new_type;
    3434        38433 :   unsigned int nops
    3435        38433 :     = vect_widened_op_tree (vinfo, mulh_stmt_info, MULT_EXPR, WIDEN_MULT_EXPR,
    3436              :                             false, 2, unprom_mult, &new_type);
    3437        38433 :   if (nops != 2)
    3438              :     return NULL;
    3439              : 
    3440              :   /* Adjust output precision.  */
    3441         8839 :   if (TYPE_PRECISION (new_type) < target_precision)
    3442            0 :     new_type = build_nonstandard_integer_type
    3443            0 :       (target_precision, TYPE_UNSIGNED (new_type));
    3444              : 
    3445         8839 :   unsigned mult_precision = TYPE_PRECISION (new_type);
    3446         8839 :   internal_fn ifn;
    3447              :   /* Check that the scaling factor is expected.  Instead of
    3448              :      target_precision, we should use the one that we actually
    3449              :      use for internal function.  */
    3450         8839 :   if (rounding_p)
    3451              :     {
    3452              :       /* Check pattern 2).  */
    3453          134 :       if (wi::to_widest (scale_term) + mult_precision + 2
    3454          201 :           != TYPE_PRECISION (lhs_type))
    3455              :         return NULL;
    3456              : 
    3457              :       ifn = IFN_MULHRS;
    3458              :     }
    3459              :   else
    3460              :     {
    3461              :       /* Check for pattern 1).  */
    3462        17544 :       if (wi::to_widest (scale_term) + mult_precision + 1
    3463        26316 :           == TYPE_PRECISION (lhs_type))
    3464              :         ifn = IFN_MULHS;
    3465              :       /* Check for pattern 3).  */
    3466         8738 :       else if (wi::to_widest (scale_term) + mult_precision
    3467        17476 :                == TYPE_PRECISION (lhs_type))
    3468              :         ifn = IFN_MULH;
    3469              :       else
    3470              :         return NULL;
    3471              :     }
    3472              : 
    3473         8774 :   vect_pattern_detected ("vect_recog_mulhs_pattern", last_stmt);
    3474              : 
    3475              :   /* Check for target support.  */
    3476         8774 :   tree new_vectype = get_vectype_for_scalar_type (vinfo, new_type);
    3477         8774 :   if (!new_vectype
    3478        15462 :       || !direct_internal_fn_supported_p
    3479         6688 :             (ifn, new_vectype, OPTIMIZE_FOR_SPEED))
    3480              :     return NULL;
    3481              : 
    3482              :   /* The result is cast back to LHS_TYPE, a cast that the over-widening
    3483              :      machinery then removes.  LHS_TYPE need not have a vector type, as for the
    3484              :      128-bit product of a 64-bit high-part multiply, so leave *TYPE_OUT null
    3485              :      rather than giving up.  */
    3486          144 :   *type_out = get_vectype_for_scalar_type (vinfo, lhs_type);
    3487              : 
    3488              :   /* Generate the IFN_MULHRS call.  */
    3489          144 :   tree new_var = vect_recog_temp_ssa_var (new_type, NULL);
    3490          144 :   tree new_ops[2];
    3491          144 :   vect_convert_inputs (vinfo, last_stmt_info, 2, new_ops, new_type,
    3492              :                        unprom_mult, new_vectype);
    3493          144 :   gcall *mulhrs_stmt
    3494          144 :     = gimple_build_call_internal (ifn, 2, new_ops[0], new_ops[1]);
    3495          144 :   gimple_call_set_lhs (mulhrs_stmt, new_var);
    3496          144 :   gimple_set_location (mulhrs_stmt, gimple_location (last_stmt));
    3497              : 
    3498          144 :   if (dump_enabled_p ())
    3499            0 :     dump_printf_loc (MSG_NOTE, vect_location,
    3500              :                      "created pattern stmt: %G", (gimple *) mulhrs_stmt);
    3501              : 
    3502          144 :   return vect_convert_output (vinfo, last_stmt_info, lhs_type,
    3503          144 :                               mulhrs_stmt, new_vectype);
    3504              : }
    3505              : 
    3506              : /* Recognize the patterns:
    3507              : 
    3508              :             ATYPE a;  // narrower than TYPE
    3509              :             BTYPE b;  // narrower than TYPE
    3510              :         (1) TYPE avg = ((TYPE) a + (TYPE) b) >> 1;
    3511              :      or (2) TYPE avg = ((TYPE) a + (TYPE) b + 1) >> 1;
    3512              : 
    3513              :    where only the bottom half of avg is used.  Try to transform them into:
    3514              : 
    3515              :         (1) NTYPE avg' = .AVG_FLOOR ((NTYPE) a, (NTYPE) b);
    3516              :      or (2) NTYPE avg' = .AVG_CEIL ((NTYPE) a, (NTYPE) b);
    3517              : 
    3518              :   followed by:
    3519              : 
    3520              :             TYPE avg = (TYPE) avg';
    3521              : 
    3522              :   where NTYPE is no wider than half of TYPE.  Since only the bottom half
    3523              :   of avg is used, all or part of the cast of avg' should become redundant.
    3524              : 
    3525              :   If there is no target support available, generate code to distribute rshift
    3526              :   over plus and add a carry.  */
    3527              : 
    3528              : static gimple *
    3529     32376300 : vect_recog_average_pattern (vec_info *vinfo,
    3530              :                             stmt_vec_info last_stmt_info, tree *type_out)
    3531              : {
    3532              :   /* Check for a shift right by one bit.  */
    3533     32376300 :   gassign *last_stmt = dyn_cast <gassign *> (last_stmt_info->stmt);
    3534     22587218 :   if (!last_stmt
    3535     22587218 :       || gimple_assign_rhs_code (last_stmt) != RSHIFT_EXPR
    3536       353355 :       || !integer_onep (gimple_assign_rhs2 (last_stmt)))
    3537              :     return NULL;
    3538              : 
    3539              :   /* Check that the shift result is wider than the users of the
    3540              :      result need (i.e. that narrowing would be a natural choice).  */
    3541        57299 :   tree lhs = gimple_assign_lhs (last_stmt);
    3542        57299 :   tree type = TREE_TYPE (lhs);
    3543        57299 :   unsigned int target_precision
    3544        57299 :     = vect_element_precision (last_stmt_info->min_output_precision);
    3545        57299 :   if (!INTEGRAL_TYPE_P (type) || target_precision >= TYPE_PRECISION (type))
    3546              :     return NULL;
    3547              : 
    3548              :   /* Look through any change in sign on the shift input.  */
    3549         2268 :   tree rshift_rhs = gimple_assign_rhs1 (last_stmt);
    3550         2268 :   vect_unpromoted_value unprom_plus;
    3551         2268 :   rshift_rhs = vect_look_through_possible_promotion (vinfo, rshift_rhs,
    3552              :                                                      &unprom_plus);
    3553         2268 :   if (!rshift_rhs
    3554         2268 :       || TYPE_PRECISION (TREE_TYPE (rshift_rhs)) != TYPE_PRECISION (type))
    3555              :     return NULL;
    3556              : 
    3557              :   /* Get the definition of the shift input.  */
    3558         2264 :   stmt_vec_info plus_stmt_info = vect_get_internal_def (vinfo, rshift_rhs);
    3559         2264 :   if (!plus_stmt_info)
    3560              :     return NULL;
    3561              : 
    3562              :   /* Check whether the shift input can be seen as a tree of additions on
    3563              :      2 or 3 widened inputs.
    3564              : 
    3565              :      Note that the pattern should be a win even if the result of one or
    3566              :      more additions is reused elsewhere: if the pattern matches, we'd be
    3567              :      replacing 2N RSHIFT_EXPRs and N VEC_PACK_*s with N IFN_AVG_*s.  */
    3568         2258 :   internal_fn ifn = IFN_AVG_FLOOR;
    3569         9032 :   vect_unpromoted_value unprom[3];
    3570         2258 :   tree new_type;
    3571         2258 :   unsigned int nops = vect_widened_op_tree (vinfo, plus_stmt_info, PLUS_EXPR,
    3572         2258 :                                             IFN_VEC_WIDEN_PLUS, false, 3,
    3573              :                                             unprom, &new_type);
    3574         2258 :   if (nops == 0)
    3575              :     return NULL;
    3576          959 :   if (nops == 3)
    3577              :     {
    3578              :       /* Check that one operand is 1.  */
    3579              :       unsigned int i;
    3580         1155 :       for (i = 0; i < 3; ++i)
    3581         1101 :         if (integer_onep (unprom[i].op))
    3582              :           break;
    3583          367 :       if (i == 3)
    3584              :         return NULL;
    3585              :       /* Throw away the 1 operand and keep the other two.  */
    3586          313 :       if (i < 2)
    3587            0 :         unprom[i] = unprom[2];
    3588              :       ifn = IFN_AVG_CEIL;
    3589              :     }
    3590              : 
    3591          905 :   vect_pattern_detected ("vect_recog_average_pattern", last_stmt);
    3592              : 
    3593              :   /* We know that:
    3594              : 
    3595              :      (a) the operation can be viewed as:
    3596              : 
    3597              :            TYPE widened0 = (TYPE) UNPROM[0];
    3598              :            TYPE widened1 = (TYPE) UNPROM[1];
    3599              :            TYPE tmp1 = widened0 + widened1 {+ 1};
    3600              :            TYPE tmp2 = tmp1 >> 1;   // LAST_STMT_INFO
    3601              : 
    3602              :      (b) the first two statements are equivalent to:
    3603              : 
    3604              :            TYPE widened0 = (TYPE) (NEW_TYPE) UNPROM[0];
    3605              :            TYPE widened1 = (TYPE) (NEW_TYPE) UNPROM[1];
    3606              : 
    3607              :      (c) vect_recog_over_widening_pattern has already tried to narrow TYPE
    3608              :          where sensible;
    3609              : 
    3610              :      (d) all the operations can be performed correctly at twice the width of
    3611              :          NEW_TYPE, due to the nature of the average operation; and
    3612              : 
    3613              :      (e) users of the result of the right shift need only TARGET_PRECISION
    3614              :          bits, where TARGET_PRECISION is no more than half of TYPE's
    3615              :          precision.
    3616              : 
    3617              :      Under these circumstances, the only situation in which NEW_TYPE
    3618              :      could be narrower than TARGET_PRECISION is if widened0, widened1
    3619              :      and an addition result are all used more than once.  Thus we can
    3620              :      treat any widening of UNPROM[0] and UNPROM[1] to TARGET_PRECISION
    3621              :      as "free", whereas widening the result of the average instruction
    3622              :      from NEW_TYPE to TARGET_PRECISION would be a new operation.  It's
    3623              :      therefore better not to go narrower than TARGET_PRECISION.  */
    3624          905 :   if (TYPE_PRECISION (new_type) < target_precision)
    3625            0 :     new_type = build_nonstandard_integer_type (target_precision,
    3626            0 :                                                TYPE_UNSIGNED (new_type));
    3627              : 
    3628              :   /* Check for target support.  */
    3629          905 :   tree new_vectype = get_vectype_for_scalar_type (vinfo, new_type);
    3630          905 :   if (!new_vectype)
    3631              :     return NULL;
    3632              : 
    3633          905 :   bool fallback_p = !direct_internal_fn_supported_p (ifn, new_vectype,
    3634          905 :                                                       OPTIMIZE_FOR_SPEED);
    3635          905 :   if (fallback_p
    3636          905 :       && (!target_supports_op_p (new_vectype, RSHIFT_EXPR, optab_scalar)
    3637          697 :           || !target_supports_op_p (new_vectype, PLUS_EXPR, optab_default)
    3638          697 :           || !target_supports_op_p (new_vectype, BIT_AND_EXPR, optab_default)
    3639          697 :           || (ifn == IFN_AVG_CEIL
    3640          105 :               && !target_supports_op_p (new_vectype, BIT_IOR_EXPR,
    3641              :                                         optab_default))))
    3642              :     return NULL;
    3643              : 
    3644              :   /* The IR requires a valid vector type for the cast result, even though
    3645              :      it's likely to be discarded.  */
    3646          903 :   *type_out = get_vectype_for_scalar_type (vinfo, type);
    3647          903 :   if (!*type_out)
    3648              :     return NULL;
    3649              : 
    3650          899 :   tree new_var = vect_recog_temp_ssa_var (new_type, NULL);
    3651          899 :   tree new_ops[2];
    3652          899 :   vect_convert_inputs (vinfo, last_stmt_info, 2, new_ops, new_type,
    3653              :                        unprom, new_vectype);
    3654              : 
    3655          899 :   if (fallback_p)
    3656              :     {
    3657              :       /* As a fallback, generate code for following sequence:
    3658              : 
    3659              :          shifted_op0 = new_ops[0] >> 1;
    3660              :          shifted_op1 = new_ops[1] >> 1;
    3661              :          sum_of_shifted = shifted_op0 + shifted_op1;
    3662              :          unmasked_carry = new_ops[0] and/or new_ops[1];
    3663              :          carry = unmasked_carry & 1;
    3664              :          new_var = sum_of_shifted + carry;
    3665              : 
    3666              :          For signed types, arithmetic shifts round down and the carry is one
    3667              :          when both operands are odd (or either operand for IFN_AVG_CEIL).  */
    3668              : 
    3669          693 :       tree one_cst = build_one_cst (new_type);
    3670          693 :       gassign *g;
    3671              : 
    3672          693 :       tree shifted_op0 = vect_recog_temp_ssa_var (new_type, NULL);
    3673          693 :       g = gimple_build_assign (shifted_op0, RSHIFT_EXPR, new_ops[0], one_cst);
    3674          693 :       append_pattern_def_seq (vinfo, last_stmt_info, g, new_vectype);
    3675              : 
    3676          693 :       tree shifted_op1 = vect_recog_temp_ssa_var (new_type, NULL);
    3677          693 :       g = gimple_build_assign (shifted_op1, RSHIFT_EXPR, new_ops[1], one_cst);
    3678          693 :       append_pattern_def_seq (vinfo, last_stmt_info, g, new_vectype);
    3679              : 
    3680          693 :       tree sum_of_shifted = vect_recog_temp_ssa_var (new_type, NULL);
    3681          693 :       g = gimple_build_assign (sum_of_shifted, PLUS_EXPR,
    3682              :                                shifted_op0, shifted_op1);
    3683          693 :       append_pattern_def_seq (vinfo, last_stmt_info, g, new_vectype);
    3684              : 
    3685          693 :       tree unmasked_carry = vect_recog_temp_ssa_var (new_type, NULL);
    3686          693 :       tree_code c = (ifn == IFN_AVG_CEIL) ? BIT_IOR_EXPR : BIT_AND_EXPR;
    3687          693 :       g = gimple_build_assign (unmasked_carry, c, new_ops[0], new_ops[1]);
    3688          693 :       append_pattern_def_seq (vinfo, last_stmt_info, g, new_vectype);
    3689              : 
    3690          693 :       tree carry = vect_recog_temp_ssa_var (new_type, NULL);
    3691          693 :       g = gimple_build_assign (carry, BIT_AND_EXPR, unmasked_carry, one_cst);
    3692          693 :       append_pattern_def_seq (vinfo, last_stmt_info, g, new_vectype);
    3693              : 
    3694          693 :       g = gimple_build_assign (new_var, PLUS_EXPR, sum_of_shifted, carry);
    3695          693 :       return vect_convert_output (vinfo, last_stmt_info, type, g, new_vectype);
    3696              :     }
    3697              : 
    3698              :   /* Generate the IFN_AVG* call.  */
    3699          206 :   gcall *average_stmt = gimple_build_call_internal (ifn, 2, new_ops[0],
    3700              :                                                     new_ops[1]);
    3701          206 :   gimple_call_set_lhs (average_stmt, new_var);
    3702          206 :   gimple_set_location (average_stmt, gimple_location (last_stmt));
    3703              : 
    3704          206 :   if (dump_enabled_p ())
    3705           79 :     dump_printf_loc (MSG_NOTE, vect_location,
    3706              :                      "created pattern stmt: %G", (gimple *) average_stmt);
    3707              : 
    3708          206 :   return vect_convert_output (vinfo, last_stmt_info,
    3709          206 :                               type, average_stmt, new_vectype);
    3710              : }
    3711              : 
    3712              : /* Recognize cases in which the input to a cast is wider than its
    3713              :    output, and the input is fed by a widening operation.  Fold this
    3714              :    by removing the unnecessary intermediate widening.  E.g.:
    3715              : 
    3716              :      unsigned char a;
    3717              :      unsigned int b = (unsigned int) a;
    3718              :      unsigned short c = (unsigned short) b;
    3719              : 
    3720              :    -->
    3721              : 
    3722              :      unsigned short c = (unsigned short) a;
    3723              : 
    3724              :    Although this is rare in input IR, it is an expected side-effect
    3725              :    of the over-widening pattern above.
    3726              : 
    3727              :    This is beneficial also for integer-to-float conversions, if the
    3728              :    widened integer has more bits than the float, and if the unwidened
    3729              :    input doesn't.  */
    3730              : 
    3731              : static gimple *
    3732     32380537 : vect_recog_cast_forwprop_pattern (vec_info *vinfo,
    3733              :                                   stmt_vec_info last_stmt_info, tree *type_out)
    3734              : {
    3735              :   /* Check for a cast, including an integer-to-float conversion.  */
    3736     32380537 :   gassign *last_stmt = dyn_cast <gassign *> (last_stmt_info->stmt);
    3737     22591105 :   if (!last_stmt)
    3738              :     return NULL;
    3739     22591105 :   tree_code code = gimple_assign_rhs_code (last_stmt);
    3740     22591105 :   if (!CONVERT_EXPR_CODE_P (code) && code != FLOAT_EXPR)
    3741              :     return NULL;
    3742              : 
    3743              :   /* Make sure that the rhs is a scalar with a natural bitsize.  */
    3744      3255522 :   tree lhs = gimple_assign_lhs (last_stmt);
    3745      3255522 :   if (!lhs)
    3746              :     return NULL;
    3747      3255522 :   tree lhs_type = TREE_TYPE (lhs);
    3748      3255522 :   scalar_mode lhs_mode;
    3749      3234728 :   if (VECT_SCALAR_BOOLEAN_TYPE_P (lhs_type)
    3750      6488508 :       || !is_a <scalar_mode> (TYPE_MODE (lhs_type), &lhs_mode))
    3751              :     return NULL;
    3752              : 
    3753              :   /* Check for a narrowing operation (from a vector point of view).  */
    3754      3229258 :   tree rhs = gimple_assign_rhs1 (last_stmt);
    3755      3229258 :   tree rhs_type = TREE_TYPE (rhs);
    3756      3229258 :   if (!INTEGRAL_TYPE_P (rhs_type)
    3757      2827208 :       || VECT_SCALAR_BOOLEAN_TYPE_P (rhs_type)
    3758      8734698 :       || TYPE_PRECISION (rhs_type) <= GET_MODE_BITSIZE (lhs_mode))
    3759              :     return NULL;
    3760              : 
    3761              :   /* Try to find an unpromoted input.  */
    3762       378440 :   vect_unpromoted_value unprom;
    3763       378440 :   if (!vect_look_through_possible_promotion (vinfo, rhs, &unprom)
    3764       378440 :       || TYPE_PRECISION (unprom.type) >= TYPE_PRECISION (rhs_type))
    3765              :     return NULL;
    3766              : 
    3767              :   /* If the bits above RHS_TYPE matter, make sure that they're the
    3768              :      same when extending from UNPROM as they are when extending from RHS.  */
    3769        48306 :   if (!INTEGRAL_TYPE_P (lhs_type)
    3770        48306 :       && TYPE_SIGN (rhs_type) != TYPE_SIGN (unprom.type))
    3771              :     return NULL;
    3772              : 
    3773              :   /* We can get the same result by casting UNPROM directly, to avoid
    3774              :      the unnecessary widening and narrowing.  */
    3775        48186 :   vect_pattern_detected ("vect_recog_cast_forwprop_pattern", last_stmt);
    3776              : 
    3777        48186 :   *type_out = get_vectype_for_scalar_type (vinfo, lhs_type);
    3778        48186 :   if (!*type_out)
    3779              :     return NULL;
    3780              : 
    3781        48186 :   tree new_var = vect_recog_temp_ssa_var (lhs_type, NULL);
    3782        48186 :   gimple *pattern_stmt = gimple_build_assign (new_var, code, unprom.op);
    3783        48186 :   gimple_set_location (pattern_stmt, gimple_location (last_stmt));
    3784              : 
    3785        48186 :   return pattern_stmt;
    3786              : }
    3787              : 
    3788              : /* Try to detect a shift left of a widened input, converting LSHIFT_EXPR
    3789              :    to WIDEN_LSHIFT_EXPR.  See vect_recog_widen_op_pattern for details.  */
    3790              : 
    3791              : static gimple *
    3792     32303866 : vect_recog_widen_shift_pattern (vec_info *vinfo,
    3793              :                                 stmt_vec_info last_stmt_info, tree *type_out)
    3794              : {
    3795     32303866 :   return vect_recog_widen_op_pattern (vinfo, last_stmt_info, type_out,
    3796     32303866 :                                       LSHIFT_EXPR, WIDEN_LSHIFT_EXPR, true,
    3797     32303866 :                                       "vect_recog_widen_shift_pattern");
    3798              : }
    3799              : 
    3800              : /* Detect a rotate pattern wouldn't be otherwise vectorized:
    3801              : 
    3802              :    type a_t, b_t, c_t;
    3803              : 
    3804              :    S0 a_t = b_t r<< c_t;
    3805              : 
    3806              :   Input/Output:
    3807              : 
    3808              :   * STMT_VINFO: The stmt from which the pattern search begins,
    3809              :     i.e. the shift/rotate stmt.  The original stmt (S0) is replaced
    3810              :     with a sequence:
    3811              : 
    3812              :    S1 d_t = -c_t;
    3813              :    S2 e_t = d_t & (B - 1);
    3814              :    S3 f_t = b_t << c_t;
    3815              :    S4 g_t = b_t >> e_t;
    3816              :    S0 a_t = f_t | g_t;
    3817              : 
    3818              :     where B is element bitsize of type.
    3819              : 
    3820              :   Output:
    3821              : 
    3822              :   * TYPE_OUT: The type of the output of this pattern.
    3823              : 
    3824              :   * Return value: A new stmt that will be used to replace the rotate
    3825              :     S0 stmt.  */
    3826              : 
    3827              : static gimple *
    3828     32303866 : vect_recog_rotate_pattern (vec_info *vinfo,
    3829              :                            stmt_vec_info stmt_vinfo, tree *type_out)
    3830              : {
    3831     32303866 :   gimple *last_stmt = stmt_vinfo->stmt;
    3832     32303866 :   tree oprnd0, oprnd1, lhs, var, var1, var2, vectype, type, stype, def, def2;
    3833     32303866 :   gimple *pattern_stmt, *def_stmt;
    3834     32303866 :   enum tree_code rhs_code;
    3835     32303866 :   enum vect_def_type dt;
    3836     32303866 :   optab optab1, optab2;
    3837     32303866 :   edge ext_def = NULL;
    3838     32303866 :   bool bswap16_p = false;
    3839              : 
    3840     32303866 :   if (is_gimple_assign (last_stmt))
    3841              :     {
    3842     22514384 :       rhs_code = gimple_assign_rhs_code (last_stmt);
    3843     22514384 :       switch (rhs_code)
    3844              :         {
    3845         8519 :         case LROTATE_EXPR:
    3846         8519 :         case RROTATE_EXPR:
    3847         8519 :           break;
    3848              :         default:
    3849              :           return NULL;
    3850              :         }
    3851              : 
    3852         8519 :       lhs = gimple_assign_lhs (last_stmt);
    3853         8519 :       oprnd0 = gimple_assign_rhs1 (last_stmt);
    3854         8519 :       type = TREE_TYPE (oprnd0);
    3855         8519 :       oprnd1 = gimple_assign_rhs2 (last_stmt);
    3856              :     }
    3857      9789482 :   else if (gimple_call_builtin_p (last_stmt, BUILT_IN_BSWAP16))
    3858              :     {
    3859              :       /* __builtin_bswap16 (x) is another form of x r>> 8.
    3860              :          The vectorizer has bswap support, but only if the argument isn't
    3861              :          promoted.  */
    3862          206 :       lhs = gimple_call_lhs (last_stmt);
    3863          206 :       oprnd0 = gimple_call_arg (last_stmt, 0);
    3864          206 :       type = TREE_TYPE (oprnd0);
    3865          206 :       if (!lhs
    3866          206 :           || TYPE_PRECISION (TREE_TYPE (lhs)) != 16
    3867          206 :           || TYPE_PRECISION (type) <= 16
    3868            0 :           || TREE_CODE (oprnd0) != SSA_NAME
    3869          206 :           || BITS_PER_UNIT != 8)
    3870          206 :         return NULL;
    3871              : 
    3872            0 :       stmt_vec_info def_stmt_info;
    3873            0 :       if (!vect_is_simple_use (oprnd0, vinfo, &dt, &def_stmt_info, &def_stmt))
    3874              :         return NULL;
    3875              : 
    3876            0 :       if (dt != vect_internal_def)
    3877              :         return NULL;
    3878              : 
    3879            0 :       if (gimple_assign_cast_p (def_stmt))
    3880              :         {
    3881            0 :           def = gimple_assign_rhs1 (def_stmt);
    3882            0 :           if (INTEGRAL_TYPE_P (TREE_TYPE (def))
    3883            0 :               && TYPE_PRECISION (TREE_TYPE (def)) == 16)
    3884              :             oprnd0 = def;
    3885              :         }
    3886              : 
    3887            0 :       type = TREE_TYPE (lhs);
    3888            0 :       vectype = get_vectype_for_scalar_type (vinfo, type);
    3889            0 :       if (vectype == NULL_TREE)
    3890              :         return NULL;
    3891              : 
    3892            0 :       if (tree char_vectype = get_same_sized_vectype (char_type_node, vectype))
    3893              :         {
    3894              :           /* The encoding uses one stepped pattern for each byte in the
    3895              :              16-bit word.  */
    3896            0 :           vec_perm_builder elts (TYPE_VECTOR_SUBPARTS (char_vectype), 2, 3);
    3897            0 :           for (unsigned i = 0; i < 3; ++i)
    3898            0 :             for (unsigned j = 0; j < 2; ++j)
    3899            0 :               elts.quick_push ((i + 1) * 2 - j - 1);
    3900              : 
    3901            0 :           vec_perm_indices indices (elts, 1,
    3902            0 :                                     TYPE_VECTOR_SUBPARTS (char_vectype));
    3903            0 :           machine_mode vmode = TYPE_MODE (char_vectype);
    3904            0 :           if (can_vec_perm_const_p (vmode, vmode, indices))
    3905              :             {
    3906              :               /* vectorizable_bswap can handle the __builtin_bswap16 if we
    3907              :                  undo the argument promotion.  */
    3908            0 :               if (!useless_type_conversion_p (type, TREE_TYPE (oprnd0)))
    3909              :                 {
    3910            0 :                   def = vect_recog_temp_ssa_var (type, NULL);
    3911            0 :                   def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd0);
    3912            0 :                   append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    3913            0 :                   oprnd0 = def;
    3914              :                 }
    3915              : 
    3916              :               /* Pattern detected.  */
    3917            0 :               vect_pattern_detected ("vect_recog_rotate_pattern", last_stmt);
    3918              : 
    3919            0 :               *type_out = vectype;
    3920              : 
    3921              :               /* Pattern supported.  Create a stmt to be used to replace the
    3922              :                  pattern, with the unpromoted argument.  */
    3923            0 :               var = vect_recog_temp_ssa_var (type, NULL);
    3924            0 :               pattern_stmt = gimple_build_call (gimple_call_fndecl (last_stmt),
    3925              :                                                 1, oprnd0);
    3926            0 :               gimple_call_set_lhs (pattern_stmt, var);
    3927            0 :               gimple_call_set_fntype (as_a <gcall *> (pattern_stmt),
    3928              :                                       gimple_call_fntype (last_stmt));
    3929            0 :               return pattern_stmt;
    3930              :             }
    3931            0 :         }
    3932              : 
    3933            0 :       oprnd1 = build_int_cst (integer_type_node, 8);
    3934            0 :       rhs_code = LROTATE_EXPR;
    3935            0 :       bswap16_p = true;
    3936              :     }
    3937              :   else
    3938              :     return NULL;
    3939              : 
    3940         8519 :   if (TREE_CODE (oprnd0) != SSA_NAME
    3941         8399 :       || !INTEGRAL_TYPE_P (type)
    3942        16597 :       || TYPE_PRECISION (TREE_TYPE (lhs)) != TYPE_PRECISION (type))
    3943              :     return NULL;
    3944              : 
    3945         8078 :   stmt_vec_info def_stmt_info;
    3946         8078 :   if (!vect_is_simple_use (oprnd1, vinfo, &dt, &def_stmt_info, &def_stmt))
    3947              :     return NULL;
    3948              : 
    3949         8078 :   if (dt != vect_internal_def
    3950         7011 :       && dt != vect_constant_def
    3951           25 :       && dt != vect_external_def)
    3952              :     return NULL;
    3953              : 
    3954         8072 :   vectype = get_vectype_for_scalar_type (vinfo, type);
    3955         8072 :   if (vectype == NULL_TREE)
    3956              :     return NULL;
    3957              : 
    3958              :   /* If vector/vector or vector/scalar rotate is supported by the target,
    3959              :      don't do anything here.  */
    3960         7777 :   optab1 = optab_for_tree_code (rhs_code, vectype, optab_vector);
    3961         7777 :   if (optab1
    3962         7777 :       && can_implement_p (optab1, TYPE_MODE (vectype)))
    3963              :     {
    3964          564 :      use_rotate:
    3965          564 :       if (bswap16_p)
    3966              :         {
    3967            0 :           if (!useless_type_conversion_p (type, TREE_TYPE (oprnd0)))
    3968              :             {
    3969            0 :               def = vect_recog_temp_ssa_var (type, NULL);
    3970            0 :               def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd0);
    3971            0 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    3972            0 :               oprnd0 = def;
    3973              :             }
    3974              : 
    3975              :           /* Pattern detected.  */
    3976            0 :           vect_pattern_detected ("vect_recog_rotate_pattern", last_stmt);
    3977              : 
    3978            0 :           *type_out = vectype;
    3979              : 
    3980              :           /* Pattern supported.  Create a stmt to be used to replace the
    3981              :              pattern.  */
    3982            0 :           var = vect_recog_temp_ssa_var (type, NULL);
    3983            0 :           pattern_stmt = gimple_build_assign (var, LROTATE_EXPR, oprnd0,
    3984              :                                               oprnd1);
    3985            0 :           return pattern_stmt;
    3986              :         }
    3987              :       return NULL;
    3988              :     }
    3989              : 
    3990         7753 :   if (is_a <bb_vec_info> (vinfo) || dt != vect_internal_def)
    3991              :     {
    3992         7669 :       optab2 = optab_for_tree_code (rhs_code, vectype, optab_scalar);
    3993         7669 :       if (optab2
    3994         7669 :           && can_implement_p (optab2, TYPE_MODE (vectype)))
    3995          540 :         goto use_rotate;
    3996              :     }
    3997              : 
    3998              :   /* We may not use a reduction operand twice.  */
    3999         7213 :   if (vect_is_reduction (stmt_vinfo))
    4000              :     return NULL;
    4001              : 
    4002         7192 :   tree utype = unsigned_type_for (type);
    4003         7192 :   tree uvectype = get_vectype_for_scalar_type (vinfo, utype);
    4004         7192 :   if (!uvectype)
    4005              :     return NULL;
    4006              : 
    4007              :   /* If vector/vector or vector/scalar shifts aren't supported by the target,
    4008              :      don't do anything here either.  */
    4009         7192 :   optab1 = optab_for_tree_code (LSHIFT_EXPR, uvectype, optab_vector);
    4010         7192 :   optab2 = optab_for_tree_code (RSHIFT_EXPR, uvectype, optab_vector);
    4011         7192 :   if (!optab1
    4012         7192 :       || !can_implement_p (optab1, TYPE_MODE (uvectype))
    4013          746 :       || !optab2
    4014         7938 :       || !can_implement_p (optab2, TYPE_MODE (uvectype)))
    4015              :     {
    4016         6446 :       if (! is_a <bb_vec_info> (vinfo) && dt == vect_internal_def)
    4017              :         return NULL;
    4018         6383 :       optab1 = optab_for_tree_code (LSHIFT_EXPR, uvectype, optab_scalar);
    4019         6383 :       optab2 = optab_for_tree_code (RSHIFT_EXPR, uvectype, optab_scalar);
    4020         6383 :       if (!optab1
    4021         6383 :           || !can_implement_p (optab1, TYPE_MODE (uvectype))
    4022         4769 :           || !optab2
    4023        11152 :           || !can_implement_p (optab2, TYPE_MODE (uvectype)))
    4024              :         return NULL;
    4025              :     }
    4026              : 
    4027         5515 :   *type_out = vectype;
    4028              : 
    4029         5515 :   if (!useless_type_conversion_p (utype, TREE_TYPE (oprnd0)))
    4030              :     {
    4031           52 :       def = vect_recog_temp_ssa_var (utype, NULL);
    4032           52 :       def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd0);
    4033           52 :       append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, uvectype);
    4034           52 :       oprnd0 = def;
    4035              :     }
    4036              : 
    4037         5515 :   if (dt == vect_external_def && TREE_CODE (oprnd1) == SSA_NAME)
    4038           15 :     ext_def = vect_get_external_def_edge (vinfo, oprnd1);
    4039              : 
    4040         5515 :   def = NULL_TREE;
    4041         5515 :   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (utype);
    4042         5515 :   if (dt != vect_internal_def || TYPE_MODE (TREE_TYPE (oprnd1)) == mode)
    4043              :     def = oprnd1;
    4044          124 :   else if (def_stmt && gimple_assign_cast_p (def_stmt))
    4045              :     {
    4046           96 :       tree rhs1 = gimple_assign_rhs1 (def_stmt);
    4047           96 :       if (TYPE_MODE (TREE_TYPE (rhs1)) == mode
    4048           96 :           && TYPE_PRECISION (TREE_TYPE (rhs1))
    4049            0 :              == TYPE_PRECISION (type))
    4050              :         def = rhs1;
    4051              :     }
    4052              : 
    4053         5391 :   if (def == NULL_TREE)
    4054              :     {
    4055          124 :       def = vect_recog_temp_ssa_var (utype, NULL);
    4056          124 :       def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd1);
    4057          124 :       append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, uvectype);
    4058              :     }
    4059         5515 :   stype = TREE_TYPE (def);
    4060              : 
    4061         5515 :   if (TREE_CODE (def) == INTEGER_CST)
    4062              :     {
    4063         4937 :       if (!tree_fits_uhwi_p (def)
    4064         4937 :           || tree_to_uhwi (def) >= GET_MODE_PRECISION (mode)
    4065         9874 :           || integer_zerop (def))
    4066              :         return NULL;
    4067         4937 :       def2 = build_int_cst (stype,
    4068         4937 :                             GET_MODE_PRECISION (mode) - tree_to_uhwi (def));
    4069              :     }
    4070              :   else
    4071              :     {
    4072          578 :       tree vecstype = get_vectype_for_scalar_type (vinfo, stype);
    4073              : 
    4074          578 :       if (vecstype == NULL_TREE)
    4075              :         return NULL;
    4076          578 :       def2 = vect_recog_temp_ssa_var (stype, NULL);
    4077          578 :       def_stmt = gimple_build_assign (def2, NEGATE_EXPR, def);
    4078          578 :       if (ext_def)
    4079              :         {
    4080           15 :           basic_block new_bb
    4081           15 :             = gsi_insert_on_edge_immediate (ext_def, def_stmt);
    4082           15 :           gcc_assert (!new_bb);
    4083              :         }
    4084              :       else
    4085          563 :         append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, vecstype);
    4086              : 
    4087          578 :       def2 = vect_recog_temp_ssa_var (stype, NULL);
    4088          578 :       tree mask = build_int_cst (stype, GET_MODE_PRECISION (mode) - 1);
    4089          578 :       def_stmt = gimple_build_assign (def2, BIT_AND_EXPR,
    4090              :                                       gimple_assign_lhs (def_stmt), mask);
    4091          578 :       if (ext_def)
    4092              :         {
    4093           15 :           basic_block new_bb
    4094           15 :             = gsi_insert_on_edge_immediate (ext_def, def_stmt);
    4095           15 :           gcc_assert (!new_bb);
    4096              :         }
    4097              :       else
    4098          563 :         append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, vecstype);
    4099              :     }
    4100              : 
    4101         5515 :   var1 = vect_recog_temp_ssa_var (utype, NULL);
    4102        10719 :   def_stmt = gimple_build_assign (var1, rhs_code == LROTATE_EXPR
    4103              :                                         ? LSHIFT_EXPR : RSHIFT_EXPR,
    4104              :                                   oprnd0, def);
    4105         5515 :   append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, uvectype);
    4106              : 
    4107         5515 :   var2 = vect_recog_temp_ssa_var (utype, NULL);
    4108        10719 :   def_stmt = gimple_build_assign (var2, rhs_code == LROTATE_EXPR
    4109              :                                         ? RSHIFT_EXPR : LSHIFT_EXPR,
    4110              :                                   oprnd0, def2);
    4111         5515 :   append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, uvectype);
    4112              : 
    4113              :   /* Pattern detected.  */
    4114         5515 :   vect_pattern_detected ("vect_recog_rotate_pattern", last_stmt);
    4115              : 
    4116              :   /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
    4117         5515 :   var = vect_recog_temp_ssa_var (utype, NULL);
    4118         5515 :   pattern_stmt = gimple_build_assign (var, BIT_IOR_EXPR, var1, var2);
    4119              : 
    4120         5515 :   if (!useless_type_conversion_p (type, utype))
    4121              :     {
    4122           52 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, uvectype);
    4123           52 :       tree result = vect_recog_temp_ssa_var (type, NULL);
    4124           52 :       pattern_stmt = gimple_build_assign (result, NOP_EXPR, var);
    4125              :     }
    4126              :   return pattern_stmt;
    4127              : }
    4128              : 
    4129              : /* Detect a vector by vector shift pattern that wouldn't be otherwise
    4130              :    vectorized:
    4131              : 
    4132              :    type a_t;
    4133              :    TYPE b_T, res_T;
    4134              : 
    4135              :    S1 a_t = ;
    4136              :    S2 b_T = ;
    4137              :    S3 res_T = b_T op a_t;
    4138              : 
    4139              :   where type 'TYPE' is a type with different size than 'type',
    4140              :   and op is <<, >> or rotate.
    4141              : 
    4142              :   Also detect cases:
    4143              : 
    4144              :    type a_t;
    4145              :    TYPE b_T, c_T, res_T;
    4146              : 
    4147              :    S0 c_T = ;
    4148              :    S1 a_t = (type) c_T;
    4149              :    S2 b_T = ;
    4150              :    S3 res_T = b_T op a_t;
    4151              : 
    4152              :   Input/Output:
    4153              : 
    4154              :   * STMT_VINFO: The stmt from which the pattern search begins,
    4155              :     i.e. the shift/rotate stmt.  The original stmt (S3) is replaced
    4156              :     with a shift/rotate which has same type on both operands, in the
    4157              :     second case just b_T op c_T, in the first case with added cast
    4158              :     from a_t to c_T in STMT_VINFO_PATTERN_DEF_SEQ.
    4159              : 
    4160              :   Output:
    4161              : 
    4162              :   * TYPE_OUT: The type of the output of this pattern.
    4163              : 
    4164              :   * Return value: A new stmt that will be used to replace the shift/rotate
    4165              :     S3 stmt.  */
    4166              : 
    4167              : static gimple *
    4168     32310735 : vect_recog_vector_vector_shift_pattern (vec_info *vinfo,
    4169              :                                         stmt_vec_info stmt_vinfo,
    4170              :                                         tree *type_out)
    4171              : {
    4172     32310735 :   gimple *last_stmt = stmt_vinfo->stmt;
    4173     32310735 :   tree oprnd0, oprnd1, lhs, var;
    4174     32310735 :   gimple *pattern_stmt;
    4175     32310735 :   enum tree_code rhs_code;
    4176              : 
    4177     32310735 :   if (!is_gimple_assign (last_stmt))
    4178              :     return NULL;
    4179              : 
    4180     22521253 :   rhs_code = gimple_assign_rhs_code (last_stmt);
    4181     22521253 :   switch (rhs_code)
    4182              :     {
    4183       503513 :     case LSHIFT_EXPR:
    4184       503513 :     case RSHIFT_EXPR:
    4185       503513 :     case LROTATE_EXPR:
    4186       503513 :     case RROTATE_EXPR:
    4187       503513 :       break;
    4188              :     default:
    4189              :       return NULL;
    4190              :     }
    4191              : 
    4192       503513 :   lhs = gimple_assign_lhs (last_stmt);
    4193       503513 :   oprnd0 = gimple_assign_rhs1 (last_stmt);
    4194       503513 :   oprnd1 = gimple_assign_rhs2 (last_stmt);
    4195       503513 :   if (TREE_CODE (oprnd1) != SSA_NAME
    4196       110693 :       || TYPE_MODE (TREE_TYPE (oprnd0)) == TYPE_MODE (TREE_TYPE (oprnd1))
    4197        49411 :       || !INTEGRAL_TYPE_P (TREE_TYPE (oprnd0))
    4198        48942 :       || !type_has_mode_precision_p (TREE_TYPE (oprnd1))
    4199       552455 :       || TYPE_PRECISION (TREE_TYPE (lhs))
    4200        48942 :          != TYPE_PRECISION (TREE_TYPE (oprnd0)))
    4201              :     return NULL;
    4202              : 
    4203        48942 :   stmt_vec_info def_vinfo = vinfo->lookup_def (oprnd1);
    4204        48942 :   if (!def_vinfo || STMT_VINFO_DEF_TYPE (def_vinfo) == vect_external_def)
    4205              :     return NULL;
    4206              : 
    4207        46098 :   def_vinfo = vect_stmt_to_vectorize (def_vinfo);
    4208         1128 :   gcc_assert (def_vinfo);
    4209              : 
    4210        46098 :   *type_out = get_vectype_for_scalar_type (vinfo, TREE_TYPE (oprnd0));
    4211        46098 :   if (*type_out == NULL_TREE)
    4212              :     return NULL;
    4213              : 
    4214        33324 :   tree def = NULL_TREE;
    4215        33324 :   gassign *def_stmt = dyn_cast <gassign *> (def_vinfo->stmt);
    4216        19505 :   if (def_stmt && gimple_assign_cast_p (def_stmt))
    4217              :     {
    4218         5490 :       tree rhs1 = gimple_assign_rhs1 (def_stmt);
    4219         5490 :       if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0))
    4220         5490 :           && TYPE_PRECISION (TREE_TYPE (rhs1))
    4221         1284 :              == TYPE_PRECISION (TREE_TYPE (oprnd0)))
    4222              :         {
    4223         1284 :           if (TYPE_PRECISION (TREE_TYPE (oprnd1))
    4224         1284 :               >= TYPE_PRECISION (TREE_TYPE (rhs1)))
    4225              :             def = rhs1;
    4226              :           else
    4227              :             {
    4228         1182 :               tree mask
    4229         1182 :                 = build_low_bits_mask (TREE_TYPE (rhs1),
    4230         1182 :                                        TYPE_PRECISION (TREE_TYPE (oprnd1)));
    4231         1182 :               def = vect_recog_temp_ssa_var (TREE_TYPE (rhs1), NULL);
    4232         1182 :               def_stmt = gimple_build_assign (def, BIT_AND_EXPR, rhs1, mask);
    4233         1182 :               tree vecstype = get_vectype_for_scalar_type (vinfo,
    4234         1182 :                                                            TREE_TYPE (rhs1));
    4235         1182 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, vecstype);
    4236              :             }
    4237              :         }
    4238              :     }
    4239              : 
    4240         1284 :   if (def == NULL_TREE)
    4241              :     {
    4242        32040 :       def = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
    4243        32040 :       def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd1);
    4244        32040 :       append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    4245              :     }
    4246              : 
    4247              :   /* Pattern detected.  */
    4248        33324 :   vect_pattern_detected ("vect_recog_vector_vector_shift_pattern", last_stmt);
    4249              : 
    4250              :   /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
    4251        33324 :   var = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
    4252        33324 :   pattern_stmt = gimple_build_assign (var, rhs_code, oprnd0, def);
    4253              : 
    4254        33324 :   return pattern_stmt;
    4255              : }
    4256              : 
    4257              : /* Verify that the target has optabs of VECTYPE to perform all the steps
    4258              :    needed by the multiplication-by-immediate synthesis algorithm described by
    4259              :    ALG and VAR.  If SYNTH_SHIFT_P is true ensure that vector addition is
    4260              :    present.  Return true iff the target supports all the steps.  */
    4261              : 
    4262              : static bool
    4263       306360 : target_supports_mult_synth_alg (struct algorithm *alg, mult_variant var,
    4264              :                                  tree vectype, bool synth_shift_p)
    4265              : {
    4266       306360 :   if (alg->op[0] != alg_zero && alg->op[0] != alg_m)
    4267              :     return false;
    4268              : 
    4269       306360 :   bool supports_vminus = target_has_vecop_for_code (MINUS_EXPR, vectype);
    4270       306360 :   bool supports_vplus = target_has_vecop_for_code (PLUS_EXPR, vectype);
    4271              : 
    4272       306360 :   if (var == negate_variant
    4273       306360 :       && !target_has_vecop_for_code (NEGATE_EXPR, vectype))
    4274              :     return false;
    4275              : 
    4276              :   /* If we must synthesize shifts with additions make sure that vector
    4277              :      addition is available.  */
    4278       305759 :   if ((var == add_variant || synth_shift_p) && !supports_vplus)
    4279              :     return false;
    4280              : 
    4281       148113 :   for (int i = 1; i < alg->ops; i++)
    4282              :     {
    4283       111263 :       switch (alg->op[i])
    4284              :         {
    4285              :         case alg_shift:
    4286              :           break;
    4287        27312 :         case alg_add_t_m2:
    4288        27312 :         case alg_add_t2_m:
    4289        27312 :         case alg_add_factor:
    4290        27312 :           if (!supports_vplus)
    4291              :             return false;
    4292              :           break;
    4293        17434 :         case alg_sub_t_m2:
    4294        17434 :         case alg_sub_t2_m:
    4295        17434 :         case alg_sub_factor:
    4296        17434 :           if (!supports_vminus)
    4297              :             return false;
    4298              :           break;
    4299              :         case alg_unknown:
    4300              :         case alg_m:
    4301              :         case alg_zero:
    4302              :         case alg_impossible:
    4303              :           return false;
    4304            0 :         default:
    4305            0 :           gcc_unreachable ();
    4306              :         }
    4307              :     }
    4308              : 
    4309              :   return true;
    4310              : }
    4311              : 
    4312              : /* Synthesize a left shift of OP by AMNT bits using a series of additions and
    4313              :    putting the final result in DEST.  Append all statements but the last into
    4314              :    VINFO.  Return the last statement.  */
    4315              : 
    4316              : static gimple *
    4317            0 : synth_lshift_by_additions (vec_info *vinfo,
    4318              :                            tree dest, tree op, HOST_WIDE_INT amnt,
    4319              :                            stmt_vec_info stmt_info, tree vectype)
    4320              : {
    4321            0 :   HOST_WIDE_INT i;
    4322            0 :   tree itype = TREE_TYPE (op);
    4323            0 :   tree prev_res = op;
    4324            0 :   gcc_assert (amnt >= 0);
    4325            0 :   for (i = 0; i < amnt; i++)
    4326              :     {
    4327            0 :       tree tmp_var = (i < amnt - 1) ? vect_recog_temp_ssa_var (itype, NULL)
    4328              :                       : dest;
    4329            0 :       gimple *stmt
    4330            0 :         = gimple_build_assign (tmp_var, PLUS_EXPR, prev_res, prev_res);
    4331            0 :       prev_res = tmp_var;
    4332            0 :       if (i < amnt - 1)
    4333            0 :         append_pattern_def_seq (vinfo, stmt_info, stmt, vectype);
    4334              :       else
    4335            0 :         return stmt;
    4336              :     }
    4337            0 :   gcc_unreachable ();
    4338              :   return NULL;
    4339              : }
    4340              : 
    4341              : /* Helper for vect_synth_mult_by_constant.  Apply a binary operation
    4342              :    CODE to operands OP1 and OP2, creating a new temporary SSA var in
    4343              :    the process if necessary.  Append the resulting assignment statements
    4344              :    to the sequence in STMT_VINFO.  Return the SSA variable that holds the
    4345              :    result of the binary operation.  If SYNTH_SHIFT_P is true synthesize
    4346              :    left shifts using additions.  */
    4347              : 
    4348              : static tree
    4349        44428 : apply_binop_and_append_stmt (vec_info *vinfo,
    4350              :                              tree_code code, tree op1, tree op2,
    4351              :                              stmt_vec_info stmt_vinfo, tree vectype,
    4352              :                              bool synth_shift_p)
    4353              : {
    4354        44428 :   if (integer_zerop (op2)
    4355        44428 :       && (code == LSHIFT_EXPR
    4356        38608 :           || code == PLUS_EXPR))
    4357              :     {
    4358        38608 :       gcc_assert (TREE_CODE (op1) == SSA_NAME);
    4359              :       return op1;
    4360              :     }
    4361              : 
    4362         5820 :   gimple *stmt;
    4363         5820 :   tree itype = TREE_TYPE (op1);
    4364         5820 :   tree tmp_var = vect_recog_temp_ssa_var (itype, NULL);
    4365              : 
    4366         5820 :   if (code == LSHIFT_EXPR
    4367         5820 :       && synth_shift_p)
    4368              :     {
    4369            0 :       stmt = synth_lshift_by_additions (vinfo, tmp_var, op1,
    4370            0 :                                         TREE_INT_CST_LOW (op2), stmt_vinfo,
    4371              :                                         vectype);
    4372            0 :       append_pattern_def_seq (vinfo, stmt_vinfo, stmt, vectype);
    4373            0 :       return tmp_var;
    4374              :     }
    4375              : 
    4376         5820 :   stmt = gimple_build_assign (tmp_var, code, op1, op2);
    4377         5820 :   append_pattern_def_seq (vinfo, stmt_vinfo, stmt, vectype);
    4378         5820 :   return tmp_var;
    4379              : }
    4380              : 
    4381              : /* Synthesize a multiplication of OP by an INTEGER_CST VAL using shifts
    4382              :    and simple arithmetic operations to be vectorized.  Record the statements
    4383              :    produced in STMT_VINFO and return the last statement in the sequence or
    4384              :    NULL if it's not possible to synthesize such a multiplication.
    4385              :    This function mirrors the behavior of expand_mult_const in expmed.cc but
    4386              :    works on tree-ssa form.  */
    4387              : 
    4388              : static gimple *
    4389       309719 : vect_synth_mult_by_constant (vec_info *vinfo, tree op, tree val,
    4390              :                              stmt_vec_info stmt_vinfo)
    4391              : {
    4392       309719 :   tree itype = TREE_TYPE (op);
    4393       309719 :   machine_mode mode = TYPE_MODE (itype);
    4394       309719 :   struct algorithm alg;
    4395       309719 :   mult_variant variant;
    4396       309719 :   if (!tree_fits_shwi_p (val))
    4397              :     return NULL;
    4398              : 
    4399              :   /* Multiplication synthesis by shifts, adds and subs can introduce
    4400              :      signed overflow where the original operation didn't.  Perform the
    4401              :      operations on an unsigned type and cast back to avoid this.
    4402              :      In the future we may want to relax this for synthesis algorithms
    4403              :      that we can prove do not cause unexpected overflow.  */
    4404       306375 :   bool cast_to_unsigned_p = !TYPE_OVERFLOW_WRAPS (itype);
    4405              : 
    4406        59805 :   tree multtype = cast_to_unsigned_p ? unsigned_type_for (itype) : itype;
    4407       306375 :   tree vectype = get_vectype_for_scalar_type (vinfo, multtype);
    4408       306375 :   if (!vectype)
    4409              :     return NULL;
    4410              : 
    4411              :   /* Targets that don't support vector shifts but support vector additions
    4412              :      can synthesize shifts that way.  */
    4413       306375 :   bool synth_shift_p = !vect_supportable_shift (vinfo, LSHIFT_EXPR, multtype);
    4414              : 
    4415       306375 :   HOST_WIDE_INT hwval = tree_to_shwi (val);
    4416              :   /* Use MAX_COST here as we don't want to limit the sequence on rtx costs.
    4417              :      The vectorizer's benefit analysis will decide whether it's beneficial
    4418              :      to do this.  */
    4419       612554 :   bool possible = choose_mult_variant (VECTOR_MODE_P (TYPE_MODE (vectype))
    4420       306179 :                                        ? TYPE_MODE (vectype) : mode,
    4421              :                                        hwval, &alg, &variant, MAX_COST);
    4422       306375 :   if (!possible)
    4423              :     return NULL;
    4424              : 
    4425       306375 :   if (vect_is_reduction (stmt_vinfo))
    4426              :     {
    4427           26 :       int op_uses = alg.op[0] != alg_zero;
    4428           45 :       for (int i = 1; i < alg.ops; i++)
    4429           32 :         switch (alg.op[i])
    4430              :           {
    4431            4 :           case alg_add_t_m2:
    4432            4 :           case alg_sub_t_m2:
    4433            4 :             if (synth_shift_p && alg.log[i])
    4434              :               return NULL;
    4435              :             else
    4436            4 :               op_uses++;
    4437            4 :             break;
    4438            0 :           case alg_add_t2_m:
    4439            0 :           case alg_sub_t2_m:
    4440            0 :             op_uses++;
    4441              :             /* Fallthru.  */
    4442           28 :           case alg_shift:
    4443           28 :             if (synth_shift_p && alg.log[i])
    4444              :               return NULL;
    4445              :             break;
    4446              :           case alg_add_factor:
    4447              :           case alg_sub_factor:
    4448              :             return NULL;
    4449              :           default:
    4450              :             break;
    4451              :           }
    4452           13 :       if (variant == add_variant)
    4453            0 :         op_uses++;
    4454              :       /* When we'll synthesize more than a single use of the reduction
    4455              :          operand the reduction constraints are violated.  Avoid this
    4456              :          situation.  */
    4457           13 :       if (op_uses > 1)
    4458              :         return NULL;
    4459              :     }
    4460              : 
    4461       306360 :   if (!target_supports_mult_synth_alg (&alg, variant, vectype, synth_shift_p))
    4462              :     return NULL;
    4463              : 
    4464        36850 :   tree accumulator;
    4465              : 
    4466              :   /* Clear out the sequence of statements so we can populate it below.  */
    4467        36850 :   gimple *stmt = NULL;
    4468              : 
    4469        36850 :   if (cast_to_unsigned_p)
    4470              :     {
    4471        12436 :       tree tmp_op = vect_recog_temp_ssa_var (multtype, NULL);
    4472        12436 :       stmt = gimple_build_assign (tmp_op, CONVERT_EXPR, op);
    4473        12436 :       append_pattern_def_seq (vinfo, stmt_vinfo, stmt, vectype);
    4474        12436 :       op = tmp_op;
    4475              :     }
    4476              : 
    4477        36850 :   if (alg.op[0] == alg_zero)
    4478          205 :     accumulator = build_int_cst (multtype, 0);
    4479              :   else
    4480              :     accumulator = op;
    4481              : 
    4482        36850 :   bool needs_fixup = (variant == negate_variant)
    4483        36850 :                       || (variant == add_variant);
    4484              : 
    4485       147510 :   for (int i = 1; i < alg.ops; i++)
    4486              :     {
    4487       110660 :       tree shft_log = build_int_cst (multtype, alg.log[i]);
    4488       110660 :       tree accum_tmp = vect_recog_temp_ssa_var (multtype, NULL);
    4489       110660 :       tree tmp_var = NULL_TREE;
    4490              : 
    4491       110660 :       switch (alg.op[i])
    4492              :         {
    4493        66232 :         case alg_shift:
    4494        66232 :           if (synth_shift_p)
    4495            0 :             stmt
    4496            0 :               = synth_lshift_by_additions (vinfo, accum_tmp, accumulator,
    4497            0 :                                            alg.log[i], stmt_vinfo, vectype);
    4498              :           else
    4499        66232 :             stmt = gimple_build_assign (accum_tmp, LSHIFT_EXPR, accumulator,
    4500              :                                          shft_log);
    4501              :           break;
    4502        22361 :         case alg_add_t_m2:
    4503        22361 :           tmp_var
    4504        22361 :             = apply_binop_and_append_stmt (vinfo, LSHIFT_EXPR, op, shft_log,
    4505              :                                            stmt_vinfo, vectype, synth_shift_p);
    4506        22361 :           stmt = gimple_build_assign (accum_tmp, PLUS_EXPR, accumulator,
    4507              :                                        tmp_var);
    4508        22361 :           break;
    4509        16450 :         case alg_sub_t_m2:
    4510        16450 :           tmp_var = apply_binop_and_append_stmt (vinfo, LSHIFT_EXPR, op,
    4511              :                                                  shft_log, stmt_vinfo,
    4512              :                                                  vectype, synth_shift_p);
    4513              :           /* In some algorithms the first step involves zeroing the
    4514              :              accumulator.  If subtracting from such an accumulator
    4515              :              just emit the negation directly.  */
    4516        16450 :           if (integer_zerop (accumulator))
    4517          205 :             stmt = gimple_build_assign (accum_tmp, NEGATE_EXPR, tmp_var);
    4518              :           else
    4519        16245 :             stmt = gimple_build_assign (accum_tmp, MINUS_EXPR, accumulator,
    4520              :                                         tmp_var);
    4521              :           break;
    4522            0 :         case alg_add_t2_m:
    4523            0 :           tmp_var
    4524            0 :             = apply_binop_and_append_stmt (vinfo, LSHIFT_EXPR, accumulator,
    4525              :                                            shft_log, stmt_vinfo, vectype,
    4526              :                                            synth_shift_p);
    4527            0 :           stmt = gimple_build_assign (accum_tmp, PLUS_EXPR, tmp_var, op);
    4528            0 :           break;
    4529            0 :         case alg_sub_t2_m:
    4530            0 :           tmp_var
    4531            0 :             = apply_binop_and_append_stmt (vinfo, LSHIFT_EXPR, accumulator,
    4532              :                                            shft_log, stmt_vinfo, vectype,
    4533              :                                            synth_shift_p);
    4534            0 :           stmt = gimple_build_assign (accum_tmp, MINUS_EXPR, tmp_var, op);
    4535            0 :           break;
    4536         4827 :         case alg_add_factor:
    4537         4827 :           tmp_var
    4538         4827 :             = apply_binop_and_append_stmt (vinfo, LSHIFT_EXPR, accumulator,
    4539              :                                            shft_log, stmt_vinfo, vectype,
    4540              :                                            synth_shift_p);
    4541         4827 :           stmt = gimple_build_assign (accum_tmp, PLUS_EXPR, accumulator,
    4542              :                                        tmp_var);
    4543         4827 :           break;
    4544          790 :         case alg_sub_factor:
    4545          790 :           tmp_var
    4546          790 :             = apply_binop_and_append_stmt (vinfo, LSHIFT_EXPR, accumulator,
    4547              :                                            shft_log, stmt_vinfo, vectype,
    4548              :                                            synth_shift_p);
    4549          790 :           stmt = gimple_build_assign (accum_tmp, MINUS_EXPR, tmp_var,
    4550              :                                       accumulator);
    4551          790 :           break;
    4552            0 :         default:
    4553            0 :           gcc_unreachable ();
    4554              :         }
    4555              :       /* We don't want to append the last stmt in the sequence to stmt_vinfo
    4556              :          but rather return it directly.  */
    4557              : 
    4558       110660 :       if ((i < alg.ops - 1) || needs_fixup || cast_to_unsigned_p)
    4559        86549 :         append_pattern_def_seq (vinfo, stmt_vinfo, stmt, vectype);
    4560       110660 :       accumulator = accum_tmp;
    4561              :     }
    4562        36850 :   if (variant == negate_variant)
    4563              :     {
    4564          443 :       tree accum_tmp = vect_recog_temp_ssa_var (multtype, NULL);
    4565          443 :       stmt = gimple_build_assign (accum_tmp, NEGATE_EXPR, accumulator);
    4566          443 :       accumulator = accum_tmp;
    4567          443 :       if (cast_to_unsigned_p)
    4568          150 :         append_pattern_def_seq (vinfo, stmt_vinfo, stmt, vectype);
    4569              :     }
    4570        36407 :   else if (variant == add_variant)
    4571              :     {
    4572          101 :       tree accum_tmp = vect_recog_temp_ssa_var (multtype, NULL);
    4573          101 :       stmt = gimple_build_assign (accum_tmp, PLUS_EXPR, accumulator, op);
    4574          101 :       accumulator = accum_tmp;
    4575          101 :       if (cast_to_unsigned_p)
    4576           91 :         append_pattern_def_seq (vinfo, stmt_vinfo, stmt, vectype);
    4577              :     }
    4578              :   /* Move back to a signed if needed.  */
    4579        36547 :   if (cast_to_unsigned_p)
    4580              :     {
    4581        12436 :       tree accum_tmp = vect_recog_temp_ssa_var (itype, NULL);
    4582        12436 :       stmt = gimple_build_assign (accum_tmp, CONVERT_EXPR, accumulator);
    4583              :     }
    4584              : 
    4585              :   return stmt;
    4586              : }
    4587              : 
    4588              : /* Detect multiplication by constant and convert it into a sequence of
    4589              :    shifts and additions, subtractions, negations.  We reuse the
    4590              :    choose_mult_variant algorithms from expmed.cc
    4591              : 
    4592              :    Input/Output:
    4593              : 
    4594              :    STMT_VINFO: The stmt from which the pattern search begins,
    4595              :    i.e. the mult stmt.
    4596              : 
    4597              :  Output:
    4598              : 
    4599              :   * TYPE_OUT: The type of the output of this pattern.
    4600              : 
    4601              :   * Return value: A new stmt that will be used to replace
    4602              :     the multiplication.  */
    4603              : 
    4604              : static gimple *
    4605     32494956 : vect_recog_mult_pattern (vec_info *vinfo,
    4606              :                          stmt_vec_info stmt_vinfo, tree *type_out)
    4607              : {
    4608     32494956 :   gimple *last_stmt = stmt_vinfo->stmt;
    4609     32494956 :   tree oprnd0, oprnd1, vectype, itype;
    4610     32494956 :   gimple *pattern_stmt;
    4611              : 
    4612     32494956 :   if (!is_gimple_assign (last_stmt))
    4613              :     return NULL;
    4614              : 
    4615     22705474 :   if (gimple_assign_rhs_code (last_stmt) != MULT_EXPR)
    4616              :     return NULL;
    4617              : 
    4618      1541435 :   oprnd0 = gimple_assign_rhs1 (last_stmt);
    4619      1541435 :   oprnd1 = gimple_assign_rhs2 (last_stmt);
    4620      1541435 :   itype = TREE_TYPE (oprnd0);
    4621              : 
    4622      1541435 :   if (TREE_CODE (oprnd0) != SSA_NAME
    4623      1541368 :       || TREE_CODE (oprnd1) != INTEGER_CST
    4624       921809 :       || !INTEGRAL_TYPE_P (itype)
    4625      2463244 :       || !type_has_mode_precision_p (itype))
    4626              :     return NULL;
    4627              : 
    4628       921754 :   vectype = get_vectype_for_scalar_type (vinfo, itype);
    4629       921754 :   if (vectype == NULL_TREE)
    4630              :     return NULL;
    4631              : 
    4632              :   /* If the target can handle vectorized multiplication natively,
    4633              :      don't attempt to optimize this.  */
    4634       750775 :   optab mul_optab = optab_for_tree_code (MULT_EXPR, vectype, optab_default);
    4635       750775 :   if (mul_optab != unknown_optab
    4636       750775 :       && can_implement_p (mul_optab, TYPE_MODE (vectype)))
    4637              :     return NULL;
    4638              : 
    4639       309719 :   pattern_stmt = vect_synth_mult_by_constant (vinfo,
    4640              :                                               oprnd0, oprnd1, stmt_vinfo);
    4641       309719 :   if (!pattern_stmt)
    4642              :     return NULL;
    4643              : 
    4644              :   /* Pattern detected.  */
    4645        36850 :   vect_pattern_detected ("vect_recog_mult_pattern", last_stmt);
    4646              : 
    4647        36850 :   *type_out = vectype;
    4648              : 
    4649        36850 :   return pattern_stmt;
    4650              : }
    4651              : 
    4652              : extern bool gimple_unsigned_integer_sat_add (tree, tree*, tree (*)(tree));
    4653              : extern bool gimple_unsigned_integer_sat_sub (tree, tree*, tree (*)(tree));
    4654              : extern bool gimple_unsigned_integer_sat_trunc (tree, tree*, tree (*)(tree));
    4655              : 
    4656              : extern bool gimple_unsigned_integer_narrow_clip (tree, tree*, tree (*)(tree));
    4657              : 
    4658              : extern bool gimple_signed_integer_sat_add (tree, tree*, tree (*)(tree));
    4659              : extern bool gimple_signed_integer_sat_sub (tree, tree*, tree (*)(tree));
    4660              : extern bool gimple_signed_integer_sat_trunc (tree, tree*, tree (*)(tree));
    4661              : 
    4662              : static gimple *
    4663         1177 : vect_recog_build_binary_gimple_stmt (vec_info *vinfo, stmt_vec_info stmt_info,
    4664              :                                      internal_fn fn, tree *type_out,
    4665              :                                      tree lhs, tree op_0, tree op_1)
    4666              : {
    4667         1177 :   tree itype = TREE_TYPE (op_0);
    4668         1177 :   tree otype = TREE_TYPE (lhs);
    4669         1177 :   tree v_itype = get_vectype_for_scalar_type (vinfo, itype);
    4670         1177 :   tree v_otype = get_vectype_for_scalar_type (vinfo, otype);
    4671              : 
    4672         1177 :   if (v_itype != NULL_TREE && v_otype != NULL_TREE
    4673         1177 :     && direct_internal_fn_supported_p (fn, v_itype, OPTIMIZE_FOR_BOTH))
    4674              :     {
    4675          913 :       gcall *call = gimple_build_call_internal (fn, 2, op_0, op_1);
    4676          913 :       tree in_ssa = vect_recog_temp_ssa_var (itype, NULL);
    4677              : 
    4678          913 :       gimple_call_set_lhs (call, in_ssa);
    4679          913 :       gimple_call_set_nothrow (call, /* nothrow_p */ false);
    4680          913 :       gimple_set_location (call, gimple_location (STMT_VINFO_STMT (stmt_info)));
    4681              : 
    4682          913 :       *type_out = v_otype;
    4683              : 
    4684          913 :       if (types_compatible_p (itype, otype))
    4685              :         return call;
    4686              :       else
    4687              :         {
    4688            0 :           append_pattern_def_seq (vinfo, stmt_info, call, v_itype);
    4689            0 :           tree out_ssa = vect_recog_temp_ssa_var (otype, NULL);
    4690              : 
    4691            0 :           return gimple_build_assign (out_ssa, NOP_EXPR, in_ssa);
    4692              :         }
    4693              :     }
    4694              : 
    4695              :   return NULL;
    4696              : }
    4697              : 
    4698              : /*
    4699              :  * Try to detect saturation add pattern (SAT_ADD), aka below gimple:
    4700              :  *   _7 = _4 + _6;
    4701              :  *   _8 = _4 > _7;
    4702              :  *   _9 = (long unsigned int) _8;
    4703              :  *   _10 = -_9;
    4704              :  *   _12 = _7 | _10;
    4705              :  *
    4706              :  * And then simplified to
    4707              :  *   _12 = .SAT_ADD (_4, _6);
    4708              :  */
    4709              : 
    4710              : static gimple *
    4711     32568312 : vect_recog_sat_add_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
    4712              :                             tree *type_out)
    4713              : {
    4714     32568312 :   gimple *last_stmt = STMT_VINFO_STMT (stmt_vinfo);
    4715              : 
    4716     32568312 :   if (!is_gimple_assign (last_stmt))
    4717              :     return NULL;
    4718              : 
    4719     22778830 :   tree ops[2];
    4720     22778830 :   tree lhs = gimple_assign_lhs (last_stmt);
    4721              : 
    4722     22778830 :   if (gimple_unsigned_integer_sat_add (lhs, ops, NULL)
    4723     22778830 :       || gimple_signed_integer_sat_add (lhs, ops, NULL))
    4724              :     {
    4725          772 :       if (TREE_CODE (ops[1]) == INTEGER_CST)
    4726           13 :         ops[1] = fold_convert (TREE_TYPE (ops[0]), ops[1]);
    4727              : 
    4728          772 :       gimple *stmt = vect_recog_build_binary_gimple_stmt (vinfo, stmt_vinfo,
    4729              :                                                           IFN_SAT_ADD, type_out,
    4730              :                                                           lhs, ops[0], ops[1]);
    4731          772 :       if (stmt)
    4732              :         {
    4733          738 :           vect_pattern_detected ("vect_recog_sat_add_pattern", last_stmt);
    4734          738 :           return stmt;
    4735              :         }
    4736              :     }
    4737              : 
    4738              :   return NULL;
    4739              : }
    4740              : 
    4741              : /*
    4742              :  * Try to transform the truncation for .SAT_SUB pattern,  mostly occurs in
    4743              :  * the benchmark zip.  Aka:
    4744              :  *
    4745              :  *   unsigned int _1;
    4746              :  *   unsigned int _2;
    4747              :  *   unsigned short int _4;
    4748              :  *   _9 = (unsigned short int).SAT_SUB (_1, _2);
    4749              :  *
    4750              :  *   if _1 is known to be in the range of unsigned short int.  For example
    4751              :  *   there is a def _1 = (unsigned short int)_4.  Then we can transform the
    4752              :  *   truncation to:
    4753              :  *
    4754              :  *   _3 = (unsigned short int) MIN (65535, _2); // aka _3 = .SAT_TRUNC (_2);
    4755              :  *   _9 = .SAT_SUB (_4, _3);
    4756              :  *
    4757              :  *   Then,  we can better vectorized code and avoid the unnecessary narrowing
    4758              :  *   stmt during vectorization with below stmt(s).
    4759              :  *
    4760              :  *   _3 = .SAT_TRUNC(_2); // SI => HI
    4761              :  *   _9 = .SAT_SUB (_4, _3);
    4762              :  */
    4763              : static void
    4764          405 : vect_recog_sat_sub_pattern_transform (vec_info *vinfo,
    4765              :                                       stmt_vec_info stmt_vinfo,
    4766              :                                       tree lhs, tree *ops)
    4767              : {
    4768          405 :   tree otype = TREE_TYPE (lhs);
    4769          405 :   tree itype = TREE_TYPE (ops[0]);
    4770          405 :   unsigned itype_prec = TYPE_PRECISION (itype);
    4771          405 :   unsigned otype_prec = TYPE_PRECISION (otype);
    4772              : 
    4773          405 :   if (types_compatible_p (otype, itype) || otype_prec >= itype_prec)
    4774          405 :     return;
    4775              : 
    4776            0 :   tree v_otype = get_vectype_for_scalar_type (vinfo, otype);
    4777            0 :   tree v_itype = get_vectype_for_scalar_type (vinfo, itype);
    4778            0 :   tree_pair v_pair = tree_pair (v_otype, v_itype);
    4779              : 
    4780            0 :   if (v_otype == NULL_TREE || v_itype == NULL_TREE
    4781            0 :     || !direct_internal_fn_supported_p (IFN_SAT_TRUNC, v_pair,
    4782              :                                         OPTIMIZE_FOR_BOTH))
    4783              :     return;
    4784              : 
    4785              :   /* 1. Find the _4 and update ops[0] as above example.  */
    4786            0 :   vect_unpromoted_value unprom;
    4787            0 :   tree tmp = vect_look_through_possible_promotion (vinfo, ops[0], &unprom);
    4788              : 
    4789            0 :   if (tmp == NULL_TREE || TYPE_PRECISION (unprom.type) != otype_prec)
    4790              :     return;
    4791              : 
    4792            0 :   ops[0] = tmp;
    4793              : 
    4794              :   /* 2. Generate _3 = .SAT_TRUNC (_2) and update ops[1] as above example.  */
    4795            0 :   tree trunc_lhs_ssa = vect_recog_temp_ssa_var (otype, NULL);
    4796            0 :   gcall *call = gimple_build_call_internal (IFN_SAT_TRUNC, 1, ops[1]);
    4797              : 
    4798            0 :   gimple_call_set_lhs (call, trunc_lhs_ssa);
    4799            0 :   gimple_call_set_nothrow (call, /* nothrow_p */ false);
    4800            0 :   append_pattern_def_seq (vinfo, stmt_vinfo, call, v_otype);
    4801              : 
    4802            0 :   ops[1] = trunc_lhs_ssa;
    4803              : }
    4804              : 
    4805              : /*
    4806              :  * Try to detect saturation sub pattern (SAT_ADD), aka below gimple:
    4807              :  * Unsigned:
    4808              :  *   _7 = _1 >= _2;
    4809              :  *   _8 = _1 - _2;
    4810              :  *   _10 = (long unsigned int) _7;
    4811              :  *   _9 = _8 * _10;
    4812              :  *
    4813              :  * And then simplified to
    4814              :  *   _9 = .SAT_SUB (_1, _2);
    4815              :  *
    4816              :  * Signed:
    4817              :  *   x.0_4 = (unsigned char) x_16;
    4818              :  *   y.1_5 = (unsigned char) y_18;
    4819              :  *   _6 = x.0_4 - y.1_5;
    4820              :  *   minus_19 = (int8_t) _6;
    4821              :  *   _7 = x_16 ^ y_18;
    4822              :  *   _8 = x_16 ^ minus_19;
    4823              :  *   _44 = _7 < 0;
    4824              :  *   _23 = x_16 < 0;
    4825              :  *   _24 = (signed char) _23;
    4826              :  *   _58 = (unsigned char) _24;
    4827              :  *   _59 = -_58;
    4828              :  *   _25 = (signed char) _59;
    4829              :  *   _26 = _25 ^ 127;
    4830              :  *   _42 = _8 < 0;
    4831              :  *   _41 = _42 & _44;
    4832              :  *   iftmp.2_11 = _41 ? _26 : minus_19;
    4833              :  *
    4834              :  * And then simplified to
    4835              :  *   iftmp.2_11 = .SAT_SUB (x_16, y_18);
    4836              :  */
    4837              : 
    4838              : static gimple *
    4839     32567574 : vect_recog_sat_sub_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
    4840              :                             tree *type_out)
    4841              : {
    4842     32567574 :   gimple *last_stmt = STMT_VINFO_STMT (stmt_vinfo);
    4843              : 
    4844     32567574 :   if (!is_gimple_assign (last_stmt))
    4845              :     return NULL;
    4846              : 
    4847     22778092 :   tree ops[2];
    4848     22778092 :   tree lhs = gimple_assign_lhs (last_stmt);
    4849              : 
    4850     22778092 :   if (gimple_unsigned_integer_sat_sub (lhs, ops, NULL)
    4851     22778092 :       || gimple_signed_integer_sat_sub (lhs, ops, NULL))
    4852              :     {
    4853          405 :       vect_recog_sat_sub_pattern_transform (vinfo, stmt_vinfo, lhs, ops);
    4854          405 :       gimple *stmt = vect_recog_build_binary_gimple_stmt (vinfo, stmt_vinfo,
    4855              :                                                           IFN_SAT_SUB, type_out,
    4856              :                                                           lhs, ops[0], ops[1]);
    4857          405 :       if (stmt)
    4858              :         {
    4859          175 :           vect_pattern_detected ("vect_recog_sat_sub_pattern", last_stmt);
    4860          175 :           return stmt;
    4861              :         }
    4862              :     }
    4863              : 
    4864              :   return NULL;
    4865              : }
    4866              : 
    4867              : /*
    4868              :  * Try to detect saturation truncation pattern (SAT_TRUNC), aka below gimple:
    4869              :  *   overflow_5 = x_4(D) > 4294967295;
    4870              :  *   _1 = (unsigned int) x_4(D);
    4871              :  *   _2 = (unsigned int) overflow_5;
    4872              :  *   _3 = -_2;
    4873              :  *   _6 = _1 | _3;
    4874              :  *
    4875              :  * And then simplified to
    4876              :  *   _6 = .SAT_TRUNC (x_4(D));
    4877              :  */
    4878              : 
    4879              : static gimple *
    4880     32567399 : vect_recog_sat_trunc_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
    4881              :                               tree *type_out)
    4882              : {
    4883     32567399 :   gimple *last_stmt = STMT_VINFO_STMT (stmt_vinfo);
    4884              : 
    4885     32567399 :   if (!is_gimple_assign (last_stmt))
    4886              :     return NULL;
    4887              : 
    4888     22777917 :   tree ops[1];
    4889     22777917 :   tree lhs = gimple_assign_lhs (last_stmt);
    4890     22777917 :   tree otype = TREE_TYPE (lhs);
    4891              : 
    4892     22777917 :   if ((gimple_unsigned_integer_narrow_clip (lhs, ops, NULL))
    4893     22777917 :        && type_has_mode_precision_p (otype))
    4894              :     {
    4895            0 :       tree itype = TREE_TYPE (ops[0]);
    4896            0 :       tree v_itype = get_vectype_for_scalar_type (vinfo, itype);
    4897            0 :       tree v_otype = get_vectype_for_scalar_type (vinfo, otype);
    4898            0 :       internal_fn fn = IFN_SAT_TRUNC;
    4899              : 
    4900            0 :       if (v_itype != NULL_TREE && v_otype != NULL_TREE
    4901            0 :         && direct_internal_fn_supported_p (fn, tree_pair (v_otype, v_itype),
    4902              :                                            OPTIMIZE_FOR_BOTH))
    4903              :         {
    4904            0 :           tree temp = vect_recog_temp_ssa_var (itype, NULL);
    4905            0 :           gimple * max_stmt = gimple_build_assign (temp, build2 (MAX_EXPR, itype, build_zero_cst(itype), ops[0]));
    4906            0 :           append_pattern_def_seq (vinfo, stmt_vinfo, max_stmt, v_itype);
    4907              : 
    4908            0 :           gcall *call = gimple_build_call_internal (fn, 1, temp);
    4909            0 :           tree out_ssa = vect_recog_temp_ssa_var (otype, NULL);
    4910              : 
    4911            0 :           gimple_call_set_lhs (call, out_ssa);
    4912            0 :           gimple_call_set_nothrow (call, /* nothrow_p */ false);
    4913            0 :           gimple_set_location (call, gimple_location (last_stmt));
    4914              : 
    4915            0 :           *type_out = v_otype;
    4916              : 
    4917            0 :           return call;
    4918              :         }
    4919              : 
    4920              :     }
    4921              : 
    4922     22777917 :   if ((gimple_unsigned_integer_sat_trunc (lhs, ops, NULL)
    4923     22777532 :        || gimple_signed_integer_sat_trunc (lhs, ops, NULL))
    4924     22777917 :       && type_has_mode_precision_p (otype))
    4925              :     {
    4926          373 :       tree itype = TREE_TYPE (ops[0]);
    4927          373 :       tree v_itype = get_vectype_for_scalar_type (vinfo, itype);
    4928          373 :       tree v_otype = get_vectype_for_scalar_type (vinfo, otype);
    4929          373 :       internal_fn fn = IFN_SAT_TRUNC;
    4930              : 
    4931          367 :       if (v_itype != NULL_TREE && v_otype != NULL_TREE
    4932          740 :         && direct_internal_fn_supported_p (fn, tree_pair (v_otype, v_itype),
    4933              :                                            OPTIMIZE_FOR_BOTH))
    4934              :         {
    4935            0 :           gcall *call = gimple_build_call_internal (fn, 1, ops[0]);
    4936            0 :           tree out_ssa = vect_recog_temp_ssa_var (otype, NULL);
    4937              : 
    4938            0 :           gimple_call_set_lhs (call, out_ssa);
    4939            0 :           gimple_call_set_nothrow (call, /* nothrow_p */ false);
    4940            0 :           gimple_set_location (call, gimple_location (last_stmt));
    4941              : 
    4942            0 :           *type_out = v_otype;
    4943              : 
    4944            0 :           return call;
    4945              :         }
    4946              :     }
    4947              : 
    4948              :   return NULL;
    4949              : }
    4950              : 
    4951              : 
    4952              : /* Function add_code_for_floorceilround_divmod
    4953              :    A helper function to add compensation code for implementing FLOOR_MOD_EXPR,
    4954              :    FLOOR_DIV_EXPR, CEIL_MOD_EXPR, CEIL_DIV_EXPR, ROUND_MOD_EXPR and
    4955              :    ROUND_DIV_EXPR
    4956              :    The quotient and remainder are needed for implemented these operators.
    4957              :    FLOOR cases
    4958              :    r = x %[fl] y; r = x/[fl] y;
    4959              :    is
    4960              :    r = x % y; if (r && (x ^ y) < 0) r += y;
    4961              :    r = x % y; d = x/y; if (r && (x ^ y) < 0) d--; Respectively
    4962              :    Produce following sequence
    4963              :    v0 = x^y
    4964              :    v1 = -r
    4965              :    v2 = r | -r
    4966              :    v3 = v0 & v2
    4967              :    v4 = v3 < 0
    4968              :    if (floor_mod)
    4969              :      v5 = v4 ? y : 0
    4970              :      v6 = r + v5
    4971              :    if (floor_div)
    4972              :      v5 = v4 ? 1 : 0
    4973              :      v6 = d - 1
    4974              :    Similar sequences of vector instructions are produces for following cases
    4975              :    CEIL cases
    4976              :    r = x %[cl] y; r = x/[cl] y;
    4977              :    is
    4978              :    r = x % y; if (r && (x ^ y) >= 0) r -= y;
    4979              :    r = x % y; if (r) r -= y; (unsigned)
    4980              :    r = x % y; d = x/y; if (r && (x ^ y) >= 0) d++;
    4981              :    r = x % y; d = x/y; if (r) d++; (unsigned)
    4982              :    ROUND cases
    4983              :    r = x %[rd] y; r = x/[rd] y;
    4984              :    is
    4985              :    r = x % y; if (r > ((y-1)/2)) if ((x ^ y) >= 0) r -= y; else r += y;
    4986              :    r = x % y; if (r > ((y-1)/2)) r -= y; (unsigned)
    4987              :    r = x % y; d = x/y; if (r > ((y-1)/2)) if ((x ^ y) >= 0) d++; else d--;
    4988              :    r = x % y; d = x/y; if (r > ((y-1)/2)) d++; (unsigned)
    4989              :    Inputs:
    4990              :      VECTYPE: Vector type of the operands
    4991              :      STMT_VINFO: Statement where pattern begins
    4992              :      RHS_CODE: Should either be FLOOR_MOD_EXPR or FLOOR_DIV_EXPR
    4993              :      Q: The quotient of division
    4994              :      R: Remainder of division
    4995              :      OPRDN0/OPRND1: Actual operands involved
    4996              :      ITYPE: tree type of oprnd0
    4997              :    Output:
    4998              :      NULL if vectorization not possible
    4999              :      Gimple statement based on rhs_code
    5000              : */
    5001              : static gimple *
    5002          414 : add_code_for_floorceilround_divmod (tree vectype, vec_info *vinfo,
    5003              :                                     stmt_vec_info stmt_vinfo,
    5004              :                                     enum tree_code rhs_code, tree q, tree r,
    5005              :                                     tree oprnd0, tree oprnd1, tree itype)
    5006              : {
    5007          414 :   gimple *def_stmt;
    5008          414 :   tree mask_vectype = truth_type_for (vectype);
    5009          414 :   if (!mask_vectype)
    5010              :     return NULL;
    5011          414 :   tree bool_cond;
    5012          414 :   bool unsigned_p = TYPE_UNSIGNED (itype);
    5013              : 
    5014          414 :   switch (rhs_code)
    5015              :     {
    5016          378 :     case FLOOR_MOD_EXPR:
    5017          378 :     case FLOOR_DIV_EXPR:
    5018          378 :     case CEIL_MOD_EXPR:
    5019          378 :     case CEIL_DIV_EXPR:
    5020          378 :       {
    5021          378 :         if (!target_has_vecop_for_code (NEGATE_EXPR, vectype)
    5022          354 :             || !target_has_vecop_for_code (BIT_XOR_EXPR, vectype)
    5023          354 :             || !target_has_vecop_for_code (BIT_IOR_EXPR, vectype)
    5024          354 :             || !target_has_vecop_for_code (PLUS_EXPR, vectype)
    5025          354 :             || !target_has_vecop_for_code (MINUS_EXPR, vectype)
    5026          354 :             || !expand_vec_cmp_expr_p (vectype, mask_vectype, LT_EXPR)
    5027          602 :             || !expand_vec_cond_expr_p (vectype, mask_vectype))
    5028              :           return NULL;
    5029          224 :         if (unsigned_p)
    5030              :           {
    5031           18 :             gcc_assert (rhs_code == CEIL_MOD_EXPR || rhs_code == CEIL_DIV_EXPR);
    5032              : 
    5033           18 :             if (!expand_vec_cmp_expr_p (vectype, mask_vectype, GT_EXPR))
    5034              :               return NULL;
    5035           18 :             bool is_mod = rhs_code == CEIL_MOD_EXPR;
    5036              :             // r > 0
    5037           18 :             bool_cond = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    5038           18 :             def_stmt = gimple_build_assign (bool_cond, GT_EXPR, r,
    5039              :                                             build_int_cst (itype, 0));
    5040           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, mask_vectype,
    5041              :                                     itype);
    5042              : 
    5043              :             // (r > 0) ? y : 0 (mod)
    5044              :             // (r > 0) ? 1 : 0 (ceil)
    5045           18 :             tree extr_cond = vect_recog_temp_ssa_var (itype, NULL);
    5046           18 :             def_stmt
    5047           27 :               = gimple_build_assign (extr_cond, COND_EXPR, bool_cond,
    5048            9 :                                      is_mod ? oprnd1 : build_int_cst (itype, 1),
    5049              :                                      build_int_cst (itype, 0));
    5050           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5051              : 
    5052              :             // r -= (r > 0) ? y : 0 (mod)
    5053              :             // d += (x^y < 0 && r) ? -1 : 0 (ceil)
    5054           18 :             tree result = vect_recog_temp_ssa_var (itype, NULL);
    5055           27 :             return gimple_build_assign (result, is_mod ? MINUS_EXPR : PLUS_EXPR,
    5056           18 :                                         is_mod ? r : q, extr_cond);
    5057              :           }
    5058              :         else
    5059              :           {
    5060          206 :             bool ceil_p
    5061          206 :               = (rhs_code == CEIL_MOD_EXPR || rhs_code == CEIL_DIV_EXPR);
    5062          206 :             if (ceil_p && !target_has_vecop_for_code (BIT_NOT_EXPR, vectype))
    5063              :               return NULL;
    5064              :             // x ^ y
    5065          206 :             tree xort = vect_recog_temp_ssa_var (itype, NULL);
    5066          206 :             def_stmt = gimple_build_assign (xort, BIT_XOR_EXPR, oprnd0, oprnd1);
    5067          206 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5068              : 
    5069          206 :             tree cond_reg = xort;
    5070              :             // ~(x ^ y) (ceil)
    5071          206 :             if (ceil_p)
    5072              :               {
    5073           18 :                 cond_reg = vect_recog_temp_ssa_var (itype, NULL);
    5074           18 :                 def_stmt = gimple_build_assign (cond_reg, BIT_NOT_EXPR, xort);
    5075           18 :                 append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5076              :               }
    5077              : 
    5078              :             // -r
    5079          206 :             tree negate_r = vect_recog_temp_ssa_var (itype, NULL);
    5080          206 :             def_stmt = gimple_build_assign (negate_r, NEGATE_EXPR, r);
    5081          206 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5082              : 
    5083              :             // r | -r , sign bit is set if r!=0
    5084          206 :             tree r_or_negr = vect_recog_temp_ssa_var (itype, NULL);
    5085          206 :             def_stmt
    5086          206 :               = gimple_build_assign (r_or_negr, BIT_IOR_EXPR, r, negate_r);
    5087          206 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5088              : 
    5089              :             // (x ^ y) & (r | -r)
    5090              :             // ~(x ^ y) & (r | -r) (ceil)
    5091          206 :             tree r_or_negr_and_xor = vect_recog_temp_ssa_var (itype, NULL);
    5092          206 :             def_stmt = gimple_build_assign (r_or_negr_and_xor, BIT_AND_EXPR,
    5093              :                                             r_or_negr, cond_reg);
    5094          206 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5095              : 
    5096              :             // (x ^ y) & (r | -r) < 0 which is equivalent to (x^y < 0 && r!=0)
    5097          206 :             bool_cond = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    5098          206 :             def_stmt
    5099          206 :               = gimple_build_assign (bool_cond, LT_EXPR, r_or_negr_and_xor,
    5100              :                                      build_int_cst (itype, 0));
    5101          206 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, mask_vectype,
    5102              :                                     itype);
    5103              : 
    5104              :             // (x^y < 0 && r) ? y : 0 (mod)
    5105              :             // (x^y < 0 && r) ? -1 : 0 (div)
    5106          206 :             bool is_mod
    5107          206 :               = (rhs_code == FLOOR_MOD_EXPR || rhs_code == CEIL_MOD_EXPR);
    5108          206 :             tree extr_cond = vect_recog_temp_ssa_var (itype, NULL);
    5109          246 :             def_stmt = gimple_build_assign (extr_cond, COND_EXPR, bool_cond,
    5110              :                                             is_mod ? oprnd1
    5111           40 :                                                    : build_int_cst (itype, -1),
    5112              :                                             build_int_cst (itype, 0));
    5113          206 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5114              : 
    5115              :             // r += (x ^ y < 0 && r) ? y : 0 (floor mod)
    5116              :             // d += (x^y < 0 && r) ? -1 : 0 (floor div)
    5117              :             // r -= (x ^ y < 0 && r) ? y : 0 (ceil mod)
    5118              :             // d -= (x^y < 0 && r) ? -1 : 0 (ceil div)
    5119          206 :             tree result = vect_recog_temp_ssa_var (itype, NULL);
    5120          412 :             return gimple_build_assign (result,
    5121          206 :                                         (rhs_code == FLOOR_MOD_EXPR
    5122          206 :                                          || rhs_code == FLOOR_DIV_EXPR)
    5123              :                                           ? PLUS_EXPR
    5124              :                                           : MINUS_EXPR,
    5125          206 :                                         is_mod ? r : q, extr_cond);
    5126              :           }
    5127              :       }
    5128           36 :     case ROUND_MOD_EXPR:
    5129           36 :     case ROUND_DIV_EXPR:
    5130           36 :       {
    5131           36 :         if (!target_has_vecop_for_code (BIT_AND_EXPR, vectype)
    5132           36 :             || !target_has_vecop_for_code (PLUS_EXPR, vectype)
    5133           36 :             || !expand_vec_cmp_expr_p (vectype, mask_vectype, LT_EXPR)
    5134           36 :             || !expand_vec_cmp_expr_p (vectype, mask_vectype, GT_EXPR)
    5135           72 :             || !expand_vec_cond_expr_p (vectype, mask_vectype))
    5136              :           return NULL;
    5137              : 
    5138           36 :         bool is_mod = rhs_code == ROUND_MOD_EXPR;
    5139           36 :         HOST_WIDE_INT d = TREE_INT_CST_LOW (oprnd1);
    5140           36 :         unsigned HOST_WIDE_INT abs_d
    5141              :           = (d >= 0 ? (unsigned HOST_WIDE_INT) d : -(unsigned HOST_WIDE_INT) d);
    5142           36 :         unsigned HOST_WIDE_INT mid_d = (abs_d - 1) >> 1;
    5143           36 :         if (!unsigned_p)
    5144              :           {
    5145              :             // check availability of abs expression for vector
    5146           18 :             if (!target_has_vecop_for_code (ABS_EXPR, vectype))
    5147              :               return NULL;
    5148              :             // abs (r)
    5149           18 :             tree abs_r = vect_recog_temp_ssa_var (itype, NULL);
    5150           18 :             def_stmt = gimple_build_assign (abs_r, ABS_EXPR, r);
    5151           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5152              : 
    5153              :             // abs (r) > (abs (y-1) >> 1)
    5154           18 :             tree round_p = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    5155           18 :             def_stmt = gimple_build_assign (round_p, GT_EXPR, abs_r,
    5156           18 :                                             build_int_cst (itype, mid_d));
    5157           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, mask_vectype,
    5158              :                                     itype);
    5159              : 
    5160              :             // x ^ y
    5161           18 :             tree cond_reg = vect_recog_temp_ssa_var (itype, NULL);
    5162           18 :             def_stmt
    5163           18 :               = gimple_build_assign (cond_reg, BIT_XOR_EXPR, oprnd0, oprnd1);
    5164           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5165              : 
    5166              :             // x ^ y < 0
    5167           18 :             bool_cond = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    5168           18 :             def_stmt = gimple_build_assign (bool_cond, LT_EXPR, cond_reg,
    5169              :                                             build_int_cst (itype, 0));
    5170           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, mask_vectype,
    5171              :                                     itype);
    5172              : 
    5173              :             // x ^ y < 0 ? y : -y (mod)
    5174              :             // x ^ y < 0 ? -1 : 1 (div)
    5175           18 :             tree val1 = vect_recog_temp_ssa_var (itype, NULL);
    5176           18 :             def_stmt
    5177           36 :               = gimple_build_assign (val1, COND_EXPR, bool_cond,
    5178           27 :                                      build_int_cst (itype, is_mod ? d : -1),
    5179           18 :                                      build_int_cst (itype, is_mod ? -d : 1));
    5180           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5181           18 :             int precision = TYPE_PRECISION (itype);
    5182           18 :             wide_int wmask = wi::mask (precision, false, precision);
    5183              : 
    5184              :             // abs (r) > (abs (y-1) >> 1) ? 0xffffffff : 0
    5185           18 :             tree val2 = vect_recog_temp_ssa_var (itype, NULL);
    5186           36 :             def_stmt = gimple_build_assign (val2, COND_EXPR, round_p,
    5187           18 :                                             wide_int_to_tree (itype, wmask),
    5188              :                                             build_int_cst (itype, 0));
    5189           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5190              : 
    5191           18 :             tree fval = vect_recog_temp_ssa_var (itype, NULL);
    5192           18 :             def_stmt = gimple_build_assign (fval, BIT_AND_EXPR, val1, val2);
    5193           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5194              : 
    5195           18 :             tree result = vect_recog_temp_ssa_var (itype, NULL);
    5196           27 :             return gimple_build_assign (result, PLUS_EXPR, is_mod ? r : q,
    5197              :                                         fval);
    5198           18 :           }
    5199              :         else
    5200              :           {
    5201              :             // r > (y-1 >> 1)
    5202           18 :             tree round_p = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    5203           18 :             def_stmt = gimple_build_assign (round_p, GT_EXPR, r,
    5204           18 :                                             build_int_cst (itype, mid_d));
    5205           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, mask_vectype,
    5206              :                                     itype);
    5207              : 
    5208              :             // (r > (y-1)>>1) ? -d : 1
    5209           18 :             tree val2 = vect_recog_temp_ssa_var (itype, NULL);
    5210           18 :             def_stmt
    5211           36 :               = gimple_build_assign (val2, COND_EXPR, round_p,
    5212           18 :                                      build_int_cst (itype, is_mod ? -d : 1),
    5213              :                                      build_int_cst (itype, 0));
    5214           18 :             append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5215              : 
    5216           18 :             tree result = vect_recog_temp_ssa_var (itype, NULL);
    5217           27 :             return gimple_build_assign (result, PLUS_EXPR, is_mod ? r : q,
    5218           18 :                                         val2);
    5219              :           }
    5220              :       }
    5221              :     default:
    5222              :       return NULL;
    5223              :     }
    5224              : }
    5225              : 
    5226              : /* Detect a signed division by a constant that wouldn't be
    5227              :    otherwise vectorized:
    5228              : 
    5229              :    type a_t, b_t;
    5230              : 
    5231              :    S1 a_t = b_t / N;
    5232              : 
    5233              :   where type 'type' is an integral type and N is a constant.
    5234              : 
    5235              :   Similarly handle modulo by a constant:
    5236              : 
    5237              :    S4 a_t = b_t % N;
    5238              : 
    5239              :   Input/Output:
    5240              : 
    5241              :   * STMT_VINFO: The stmt from which the pattern search begins,
    5242              :     i.e. the division stmt.  S1 is replaced by if N is a power
    5243              :     of two constant and type is signed:
    5244              :   S3  y_t = b_t < 0 ? N - 1 : 0;
    5245              :   S2  x_t = b_t + y_t;
    5246              :   S1' a_t = x_t >> log2 (N);
    5247              : 
    5248              :     S4 is replaced if N is a power of two constant and
    5249              :     type is signed by (where *_T temporaries have unsigned type):
    5250              :   S9  y_T = b_t < 0 ? -1U : 0U;
    5251              :   S8  z_T = y_T >> (sizeof (type_t) * CHAR_BIT - log2 (N));
    5252              :   S7  z_t = (type) z_T;
    5253              :   S6  w_t = b_t + z_t;
    5254              :   S5  x_t = w_t & (N - 1);
    5255              :   S4' a_t = x_t - z_t;
    5256              : 
    5257              :   Output:
    5258              : 
    5259              :   * TYPE_OUT: The type of the output of this pattern.
    5260              : 
    5261              :   * Return value: A new stmt that will be used to replace the division
    5262              :     S1 or modulo S4 stmt.  */
    5263              : 
    5264              : static gimple *
    5265     32310633 : vect_recog_divmod_pattern (vec_info *vinfo,
    5266              :                            stmt_vec_info stmt_vinfo, tree *type_out)
    5267              : {
    5268     32310633 :   gimple *last_stmt = stmt_vinfo->stmt;
    5269     32310633 :   tree oprnd0, oprnd1, vectype, itype, cond;
    5270     32310633 :   gimple *pattern_stmt = NULL;
    5271     32310633 :   gimple *def_stmt = NULL;
    5272     32310633 :   enum tree_code rhs_code;
    5273     32310633 :   optab optab;
    5274     32310633 :   tree q, cst;
    5275     32310633 :   int prec;
    5276              : 
    5277     32310633 :   if (!is_gimple_assign (last_stmt)
    5278              :       /* The pattern will disrupt the reduction chain with multiple uses.  */
    5279     32310633 :       || vect_is_reduction (stmt_vinfo))
    5280              :     return NULL;
    5281              : 
    5282     22408001 :   rhs_code = gimple_assign_rhs_code (last_stmt);
    5283     22408001 :   switch (rhs_code)
    5284              :     {
    5285       288109 :     case TRUNC_DIV_EXPR:
    5286       288109 :     case EXACT_DIV_EXPR:
    5287       288109 :     case TRUNC_MOD_EXPR:
    5288       288109 :     case FLOOR_MOD_EXPR:
    5289       288109 :     case FLOOR_DIV_EXPR:
    5290       288109 :     case CEIL_MOD_EXPR:
    5291       288109 :     case CEIL_DIV_EXPR:
    5292       288109 :     case ROUND_MOD_EXPR:
    5293       288109 :     case ROUND_DIV_EXPR:
    5294       288109 :       break;
    5295              :     default:
    5296              :       return NULL;
    5297              :     }
    5298              : 
    5299       288109 :   oprnd0 = gimple_assign_rhs1 (last_stmt);
    5300       288109 :   oprnd1 = gimple_assign_rhs2 (last_stmt);
    5301       288109 :   itype = TREE_TYPE (oprnd0);
    5302       288109 :   if (TREE_CODE (oprnd0) != SSA_NAME
    5303       269484 :       || TREE_CODE (oprnd1) != INTEGER_CST
    5304       160157 :       || TREE_CODE (itype) != INTEGER_TYPE
    5305       448266 :       || !type_has_mode_precision_p (itype))
    5306              :     return NULL;
    5307              : 
    5308       160145 :   scalar_int_mode itype_mode = SCALAR_INT_TYPE_MODE (itype);
    5309       160145 :   vectype = get_vectype_for_scalar_type (vinfo, itype);
    5310       160145 :   if (vectype == NULL_TREE)
    5311              :     return NULL;
    5312              : 
    5313       129122 :   if (optimize_bb_for_size_p (gimple_bb (last_stmt)))
    5314              :     {
    5315              :       /* If the target can handle vectorized division or modulo natively,
    5316              :          don't attempt to optimize this, since native division is likely
    5317              :          to give smaller code.  */
    5318         1981 :       optab = optab_for_tree_code (rhs_code, vectype, optab_default);
    5319         1981 :       if (optab != unknown_optab
    5320         1981 :           && can_implement_p (optab, TYPE_MODE (vectype)))
    5321              :         return NULL;
    5322              :     }
    5323              : 
    5324       129122 :   prec = TYPE_PRECISION (itype);
    5325              : 
    5326       258244 :   bool is_flclrd_moddiv_p
    5327       129122 :     = rhs_code == FLOOR_MOD_EXPR || rhs_code == FLOOR_DIV_EXPR
    5328              :     || rhs_code == CEIL_MOD_EXPR || rhs_code == CEIL_DIV_EXPR
    5329       128519 :     || rhs_code == ROUND_MOD_EXPR || rhs_code == ROUND_DIV_EXPR;
    5330       129122 :   if (integer_pow2p (oprnd1))
    5331              :     {
    5332        76575 :       if ((TYPE_UNSIGNED (itype)
    5333           36 :            && (rhs_code == FLOOR_MOD_EXPR || rhs_code == FLOOR_DIV_EXPR))
    5334        76611 :           || tree_int_cst_sgn (oprnd1) != 1)
    5335              :         return NULL;
    5336              : 
    5337              :       /* Pattern detected.  */
    5338        76575 :       vect_pattern_detected ("vect_recog_divmod_pattern", last_stmt);
    5339              : 
    5340        76575 :       *type_out = vectype;
    5341              : 
    5342              :       /* Check if the target supports this internal function.  */
    5343        76575 :       internal_fn ifn = IFN_DIV_POW2;
    5344        76575 :       if (!TYPE_UNSIGNED (itype)
    5345        76575 :           && direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
    5346              :         {
    5347            0 :           tree shift = build_int_cst (itype, tree_log2 (oprnd1));
    5348              : 
    5349            0 :           tree var_div = vect_recog_temp_ssa_var (itype, NULL);
    5350            0 :           gimple *div_stmt = gimple_build_call_internal (ifn, 2, oprnd0, shift);
    5351            0 :           gimple_call_set_lhs (div_stmt, var_div);
    5352            0 :           if (rhs_code == TRUNC_MOD_EXPR || is_flclrd_moddiv_p)
    5353              :             {
    5354            0 :               append_pattern_def_seq (vinfo, stmt_vinfo, div_stmt);
    5355            0 :               tree t1 = vect_recog_temp_ssa_var (itype, NULL);
    5356            0 :               def_stmt
    5357            0 :                 = gimple_build_assign (t1, LSHIFT_EXPR, var_div, shift);
    5358            0 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5359            0 :               tree r = vect_recog_temp_ssa_var (itype, NULL);
    5360            0 :               pattern_stmt = gimple_build_assign (r, MINUS_EXPR, oprnd0, t1);
    5361            0 :               if (is_flclrd_moddiv_p)
    5362              :                 {
    5363            0 :                   append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt);
    5364            0 :                   pattern_stmt
    5365            0 :                     = add_code_for_floorceilround_divmod (vectype, vinfo,
    5366              :                                                           stmt_vinfo, rhs_code,
    5367              :                                                           var_div, r, oprnd0,
    5368              :                                                           oprnd1, itype);
    5369            0 :                   if (pattern_stmt == NULL)
    5370              :                     return NULL;
    5371              :                 }
    5372              :             }
    5373              :           else
    5374              :             pattern_stmt = div_stmt;
    5375            0 :           gimple_set_location (pattern_stmt, gimple_location (last_stmt));
    5376              : 
    5377            0 :           return pattern_stmt;
    5378              :         }
    5379              : 
    5380        76575 :       cond = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    5381        76575 :       def_stmt = gimple_build_assign (cond, LT_EXPR, oprnd0,
    5382              :                                       build_int_cst (itype, 0));
    5383        76575 :       append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt,
    5384              :                               truth_type_for (vectype), itype);
    5385        76575 :       tree div_result = NULL_TREE;
    5386        76575 :       if (rhs_code == TRUNC_DIV_EXPR
    5387        76575 :           || rhs_code == EXACT_DIV_EXPR
    5388              :           || rhs_code == FLOOR_DIV_EXPR
    5389         2702 :           || rhs_code == CEIL_DIV_EXPR
    5390         2540 :           || rhs_code == ROUND_DIV_EXPR)
    5391              :         {
    5392        74047 :           tree var = vect_recog_temp_ssa_var (itype, NULL);
    5393        74047 :           tree shift;
    5394        74047 :           def_stmt
    5395        74047 :             = gimple_build_assign (var, COND_EXPR, cond,
    5396              :                                    fold_build2 (MINUS_EXPR, itype, oprnd1,
    5397              :                                                 build_int_cst (itype, 1)),
    5398              :                                    build_int_cst (itype, 0));
    5399        74047 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5400        74047 :           var = vect_recog_temp_ssa_var (itype, NULL);
    5401        74047 :           def_stmt
    5402        74047 :             = gimple_build_assign (var, PLUS_EXPR, oprnd0,
    5403              :                                    gimple_assign_lhs (def_stmt));
    5404        74047 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5405              : 
    5406        74047 :           shift = build_int_cst (itype, tree_log2 (oprnd1));
    5407        74047 :           div_result = vect_recog_temp_ssa_var (itype, NULL);
    5408        74047 :           pattern_stmt
    5409        74047 :             = gimple_build_assign (div_result, RSHIFT_EXPR, var, shift);
    5410              :         }
    5411        76575 :       if (rhs_code == TRUNC_MOD_EXPR || is_flclrd_moddiv_p)
    5412              :         {
    5413         2702 :           if (rhs_code == FLOOR_DIV_EXPR
    5414              :               || rhs_code == CEIL_DIV_EXPR
    5415         2702 :               || rhs_code == ROUND_DIV_EXPR)
    5416          174 :             append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt);
    5417              : 
    5418         2702 :           tree signmask;
    5419         2702 :           if (compare_tree_int (oprnd1, 2) == 0)
    5420              :             {
    5421         1318 :               signmask = vect_recog_temp_ssa_var (itype, NULL);
    5422         1318 :               def_stmt = gimple_build_assign (signmask, COND_EXPR, cond,
    5423              :                                               build_int_cst (itype, 1),
    5424              :                                               build_int_cst (itype, 0));
    5425         1318 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5426              :             }
    5427              :           else
    5428              :             {
    5429         1384 :               tree utype
    5430         1384 :                 = build_nonstandard_integer_type (prec, 1);
    5431         1384 :               tree vecutype = get_vectype_for_scalar_type (vinfo, utype);
    5432         1384 :               tree shift
    5433         1384 :                 = build_int_cst (utype, GET_MODE_BITSIZE (itype_mode)
    5434         1384 :                                         - tree_log2 (oprnd1));
    5435         1384 :               tree var = vect_recog_temp_ssa_var (utype, NULL);
    5436              : 
    5437         1384 :               def_stmt = gimple_build_assign (var, COND_EXPR, cond,
    5438              :                                               build_int_cst (utype, -1),
    5439              :                                               build_int_cst (utype, 0));
    5440         1384 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, vecutype);
    5441         1384 :               var = vect_recog_temp_ssa_var (utype, NULL);
    5442         1384 :               def_stmt = gimple_build_assign (var, RSHIFT_EXPR,
    5443              :                                               gimple_assign_lhs (def_stmt),
    5444              :                                               shift);
    5445         1384 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, vecutype);
    5446         1384 :               signmask = vect_recog_temp_ssa_var (itype, NULL);
    5447         1384 :               def_stmt
    5448         1384 :                 = gimple_build_assign (signmask, NOP_EXPR, var);
    5449         1384 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5450              :             }
    5451         2702 :           def_stmt
    5452         2702 :             = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
    5453              :                                    PLUS_EXPR, oprnd0, signmask);
    5454         2702 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5455         2702 :           def_stmt
    5456         2702 :             = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
    5457              :                                    BIT_AND_EXPR, gimple_assign_lhs (def_stmt),
    5458              :                                    fold_build2 (MINUS_EXPR, itype, oprnd1,
    5459              :                                                 build_int_cst (itype, 1)));
    5460         2702 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5461              : 
    5462         2702 :           tree r = vect_recog_temp_ssa_var (itype, NULL);
    5463         2702 :           pattern_stmt
    5464         2702 :             = gimple_build_assign (r, MINUS_EXPR, gimple_assign_lhs (def_stmt),
    5465              :                                    signmask);
    5466         2702 :           if (is_flclrd_moddiv_p)
    5467              :             {
    5468          268 :               append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt);
    5469          268 :               pattern_stmt
    5470          268 :                 = add_code_for_floorceilround_divmod (vectype, vinfo,
    5471              :                                                       stmt_vinfo, rhs_code,
    5472              :                                                       div_result, r, oprnd0,
    5473              :                                                       oprnd1, itype);
    5474          268 :               if (pattern_stmt == NULL)
    5475              :                 return NULL;
    5476              :             }
    5477              :         }
    5478              : 
    5479        76421 :       return pattern_stmt;
    5480              :     }
    5481              : 
    5482        52547 :   if ((cst = uniform_integer_cst_p (oprnd1))
    5483        52547 :       && TYPE_UNSIGNED (itype)
    5484              :       && rhs_code == TRUNC_DIV_EXPR
    5485        29885 :       && vectype
    5486        70564 :       && targetm.vectorize.preferred_div_as_shifts_over_mult (vectype))
    5487              :     {
    5488              :       /* We can use the relationship:
    5489              : 
    5490              :            x // N == ((x+N+2) // (N+1) + x) // (N+1)  for 0 <= x < N(N+3)
    5491              : 
    5492              :          to optimize cases where N+1 is a power of 2, and where // (N+1)
    5493              :          is therefore a shift right.  When operating in modes that are
    5494              :          multiples of a byte in size, there are two cases:
    5495              : 
    5496              :          (1) N(N+3) is not representable, in which case the question
    5497              :              becomes whether the replacement expression overflows.
    5498              :              It is enough to test that x+N+2 does not overflow,
    5499              :              i.e. that x < MAX-(N+1).
    5500              : 
    5501              :          (2) N(N+3) is representable, in which case it is the (only)
    5502              :              bound that we need to check.
    5503              : 
    5504              :          ??? For now we just handle the case where // (N+1) is a shift
    5505              :          right by half the precision, since some architectures can
    5506              :          optimize the associated addition and shift combinations
    5507              :          into single instructions.  */
    5508              : 
    5509        12203 :       auto wcst = wi::to_wide (cst);
    5510        12203 :       int pow = wi::exact_log2 (wcst + 1);
    5511        12203 :       if (pow == prec / 2)
    5512              :         {
    5513              :           /* Check that no overflow will occur.  If we don't have range
    5514              :              information we can't perform the optimization.  */
    5515              : 
    5516          472 :           int_range_max r;
    5517          944 :           if (get_range_query (cfun)->range_of_expr (r, oprnd0, last_stmt)
    5518          472 :               && !r.undefined_p ())
    5519              :             {
    5520          472 :               wide_int max = r.upper_bound ();
    5521          472 :               wide_int one = wi::shwi (1, prec);
    5522          472 :               wide_int adder = wi::add (one, wi::lshift (one, pow));
    5523          472 :               wi::overflow_type ovf;
    5524          472 :               wi::add (max, adder, UNSIGNED, &ovf);
    5525          472 :               if (ovf == wi::OVF_NONE)
    5526              :                 {
    5527          305 :                   *type_out = vectype;
    5528          305 :                   tree tadder = wide_int_to_tree (itype, adder);
    5529          305 :                   tree rshift = wide_int_to_tree (itype, pow);
    5530              : 
    5531          305 :                   tree new_lhs1 = vect_recog_temp_ssa_var (itype, NULL);
    5532          305 :                   gassign *patt1
    5533          305 :                     = gimple_build_assign (new_lhs1, PLUS_EXPR, oprnd0, tadder);
    5534          305 :                   append_pattern_def_seq (vinfo, stmt_vinfo, patt1, vectype);
    5535              : 
    5536          305 :                   tree new_lhs2 = vect_recog_temp_ssa_var (itype, NULL);
    5537          305 :                   patt1 = gimple_build_assign (new_lhs2, RSHIFT_EXPR, new_lhs1,
    5538              :                                                rshift);
    5539          305 :                   append_pattern_def_seq (vinfo, stmt_vinfo, patt1, vectype);
    5540              : 
    5541          305 :                   tree new_lhs3 = vect_recog_temp_ssa_var (itype, NULL);
    5542          305 :                   patt1 = gimple_build_assign (new_lhs3, PLUS_EXPR, new_lhs2,
    5543              :                                                oprnd0);
    5544          305 :                   append_pattern_def_seq (vinfo, stmt_vinfo, patt1, vectype);
    5545              : 
    5546          305 :                   tree new_lhs4 = vect_recog_temp_ssa_var (itype, NULL);
    5547          305 :                   pattern_stmt = gimple_build_assign (new_lhs4, RSHIFT_EXPR,
    5548              :                                                       new_lhs3, rshift);
    5549              : 
    5550          305 :                   return pattern_stmt;
    5551              :                 }
    5552          472 :             }
    5553          472 :         }
    5554              :     }
    5555              : 
    5556        52242 :   if (prec > HOST_BITS_PER_WIDE_INT
    5557        52242 :       || integer_zerop (oprnd1))
    5558              :     return NULL;
    5559              : 
    5560        51951 :   if (!can_mult_highpart_p (TYPE_MODE (vectype), TYPE_UNSIGNED (itype)))
    5561              :     return NULL;
    5562              : 
    5563        13733 :   if (TYPE_UNSIGNED (itype))
    5564              :     {
    5565         8911 :       unsigned HOST_WIDE_INT mh, ml;
    5566         8911 :       int pre_shift, post_shift;
    5567         8911 :       unsigned HOST_WIDE_INT d = (TREE_INT_CST_LOW (oprnd1)
    5568         8911 :                                   & GET_MODE_MASK (itype_mode));
    5569         8911 :       tree t1, t2, t3, t4;
    5570              : 
    5571         8911 :       if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
    5572              :         /* FIXME: Can transform this into oprnd0 >= oprnd1 ? 1 : 0.  */
    5573           23 :         return NULL;
    5574              : 
    5575              :       /* Find a suitable multiplier and right shift count instead of
    5576              :          directly dividing by D.  */
    5577         8888 :       mh = choose_multiplier (d, prec, prec, &ml, &post_shift);
    5578              : 
    5579              :       /* If the suggested multiplier is more than PREC bits, we can do better
    5580              :          for even divisors, using an initial right shift.  */
    5581         8888 :       if (mh != 0 && (d & 1) == 0)
    5582              :         {
    5583          248 :           pre_shift = ctz_or_zero (d);
    5584          248 :           mh = choose_multiplier (d >> pre_shift, prec, prec - pre_shift,
    5585              :                                   &ml, &post_shift);
    5586          248 :           gcc_assert (!mh);
    5587              :         }
    5588              :       else
    5589              :         pre_shift = 0;
    5590              : 
    5591          651 :       if (mh != 0)
    5592              :         {
    5593          651 :           if (post_shift - 1 >= prec)
    5594              :             return NULL;
    5595              : 
    5596              :           /* t1 = oprnd0 h* ml;
    5597              :              t2 = oprnd0 - t1;
    5598              :              t3 = t2 >> 1;
    5599              :              t4 = t1 + t3;
    5600              :              q = t4 >> (post_shift - 1);  */
    5601          651 :           t1 = vect_recog_temp_ssa_var (itype, NULL);
    5602          651 :           def_stmt = gimple_build_assign (t1, MULT_HIGHPART_EXPR, oprnd0,
    5603          651 :                                           build_int_cst (itype, ml));
    5604          651 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5605              : 
    5606          651 :           t2 = vect_recog_temp_ssa_var (itype, NULL);
    5607          651 :           def_stmt
    5608          651 :             = gimple_build_assign (t2, MINUS_EXPR, oprnd0, t1);
    5609          651 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5610              : 
    5611          651 :           t3 = vect_recog_temp_ssa_var (itype, NULL);
    5612          651 :           def_stmt
    5613          651 :             = gimple_build_assign (t3, RSHIFT_EXPR, t2, integer_one_node);
    5614          651 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5615              : 
    5616          651 :           t4 = vect_recog_temp_ssa_var (itype, NULL);
    5617          651 :           def_stmt
    5618          651 :             = gimple_build_assign (t4, PLUS_EXPR, t1, t3);
    5619              : 
    5620          651 :           if (post_shift != 1)
    5621              :             {
    5622          651 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5623              : 
    5624          651 :               q = vect_recog_temp_ssa_var (itype, NULL);
    5625          651 :               pattern_stmt
    5626          651 :                 = gimple_build_assign (q, RSHIFT_EXPR, t4,
    5627          651 :                                        build_int_cst (itype, post_shift - 1));
    5628              :             }
    5629              :           else
    5630              :             {
    5631              :               q = t4;
    5632              :               pattern_stmt = def_stmt;
    5633              :             }
    5634              :         }
    5635              :       else
    5636              :         {
    5637         8237 :           if (pre_shift >= prec || post_shift >= prec)
    5638              :             return NULL;
    5639              : 
    5640              :           /* t1 = oprnd0 >> pre_shift;
    5641              :              t2 = t1 h* ml;
    5642              :              q = t2 >> post_shift;  */
    5643         8237 :           if (pre_shift)
    5644              :             {
    5645          248 :               t1 = vect_recog_temp_ssa_var (itype, NULL);
    5646          248 :               def_stmt
    5647          248 :                 = gimple_build_assign (t1, RSHIFT_EXPR, oprnd0,
    5648          248 :                                        build_int_cst (integer_type_node, pre_shift));
    5649          248 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5650              :             }
    5651              :           else
    5652              :             t1 = oprnd0;
    5653              : 
    5654         8237 :           t2 = vect_recog_temp_ssa_var (itype, NULL);
    5655         8237 :           def_stmt = gimple_build_assign (t2, MULT_HIGHPART_EXPR, t1,
    5656         8237 :                                           build_int_cst (itype, ml));
    5657              : 
    5658         8237 :           if (post_shift)
    5659              :             {
    5660         8227 :               append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5661              : 
    5662         8227 :               q = vect_recog_temp_ssa_var (itype, NULL);
    5663         8227 :               def_stmt
    5664         8227 :                 = gimple_build_assign (q, RSHIFT_EXPR, t2,
    5665         8227 :                                        build_int_cst (itype, post_shift));
    5666              :             }
    5667              :           else
    5668              :             q = t2;
    5669              : 
    5670              :           pattern_stmt = def_stmt;
    5671              :         }
    5672              :     }
    5673              :   else
    5674              :     {
    5675         4822 :       unsigned HOST_WIDE_INT ml;
    5676         4822 :       int post_shift;
    5677         4822 :       HOST_WIDE_INT d = TREE_INT_CST_LOW (oprnd1);
    5678         4822 :       unsigned HOST_WIDE_INT abs_d;
    5679         4822 :       bool add = false;
    5680         4822 :       tree t1, t2, t3, t4;
    5681              : 
    5682              :       /* Give up for -1.  */
    5683         4822 :       if (d == -1)
    5684            0 :         return NULL;
    5685              : 
    5686              :       /* Since d might be INT_MIN, we have to cast to
    5687              :          unsigned HOST_WIDE_INT before negating to avoid
    5688              :          undefined signed overflow.  */
    5689         4822 :       abs_d = (d >= 0
    5690         4822 :                ? (unsigned HOST_WIDE_INT) d
    5691              :                : - (unsigned HOST_WIDE_INT) d);
    5692              : 
    5693              :       /* n rem d = n rem -d */
    5694         4822 :       if (rhs_code == TRUNC_MOD_EXPR && d < 0)
    5695              :         {
    5696            0 :           d = abs_d;
    5697            0 :           oprnd1 = build_int_cst (itype, abs_d);
    5698              :         }
    5699         4822 :       if (HOST_BITS_PER_WIDE_INT >= prec
    5700         4822 :           && abs_d == HOST_WIDE_INT_1U << (prec - 1))
    5701              :         /* This case is not handled correctly below.  */
    5702              :         return NULL;
    5703              : 
    5704         4822 :       choose_multiplier (abs_d, prec, prec - 1, &ml, &post_shift);
    5705         4822 :       if (ml >= HOST_WIDE_INT_1U << (prec - 1))
    5706              :         {
    5707         1619 :           add = true;
    5708         1619 :           ml |= HOST_WIDE_INT_M1U << (prec - 1);
    5709              :         }
    5710         4822 :       if (post_shift >= prec)
    5711              :         return NULL;
    5712              : 
    5713              :       /* t1 = oprnd0 h* ml;  */
    5714         4822 :       t1 = vect_recog_temp_ssa_var (itype, NULL);
    5715         4822 :       def_stmt = gimple_build_assign (t1, MULT_HIGHPART_EXPR, oprnd0,
    5716         4822 :                                       build_int_cst (itype, ml));
    5717              : 
    5718         4822 :       if (add)
    5719              :         {
    5720              :           /* t2 = t1 + oprnd0;  */
    5721         1619 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5722         1619 :           t2 = vect_recog_temp_ssa_var (itype, NULL);
    5723         1619 :           def_stmt = gimple_build_assign (t2, PLUS_EXPR, t1, oprnd0);
    5724              :         }
    5725              :       else
    5726              :         t2 = t1;
    5727              : 
    5728         4822 :       if (post_shift)
    5729              :         {
    5730              :           /* t3 = t2 >> post_shift;  */
    5731         4009 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5732         4009 :           t3 = vect_recog_temp_ssa_var (itype, NULL);
    5733         4009 :           def_stmt = gimple_build_assign (t3, RSHIFT_EXPR, t2,
    5734         4009 :                                           build_int_cst (itype, post_shift));
    5735              :         }
    5736              :       else
    5737              :         t3 = t2;
    5738              : 
    5739         4822 :       int msb = 1;
    5740         4822 :       int_range_max r;
    5741         9644 :       get_range_query (cfun)->range_of_expr (r, oprnd0);
    5742         4822 :       if (!r.varying_p () && !r.undefined_p ())
    5743              :         {
    5744         2975 :           if (!wi::neg_p (r.lower_bound (), TYPE_SIGN (itype)))
    5745              :             msb = 0;
    5746          743 :           else if (wi::neg_p (r.upper_bound (), TYPE_SIGN (itype)))
    5747              :             msb = -1;
    5748              :         }
    5749              : 
    5750         2232 :       if (msb == 0 && d >= 0)
    5751              :         {
    5752              :           /* q = t3;  */
    5753              :           q = t3;
    5754              :           pattern_stmt = def_stmt;
    5755              :         }
    5756              :       else
    5757              :         {
    5758              :           /* t4 = oprnd0 >> (prec - 1);
    5759              :              or if we know from VRP that oprnd0 >= 0
    5760              :              t4 = 0;
    5761              :              or if we know from VRP that oprnd0 < 0
    5762              :              t4 = -1;  */
    5763         2650 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5764         2650 :           t4 = vect_recog_temp_ssa_var (itype, NULL);
    5765         2650 :           if (msb != 1)
    5766           68 :             def_stmt = gimple_build_assign (t4, INTEGER_CST,
    5767           68 :                                             build_int_cst (itype, msb));
    5768              :           else
    5769         2582 :             def_stmt = gimple_build_assign (t4, RSHIFT_EXPR, oprnd0,
    5770         2582 :                                             build_int_cst (itype, prec - 1));
    5771         2650 :           append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5772              : 
    5773              :           /* q = t3 - t4;  or q = t4 - t3;  */
    5774         2650 :           q = vect_recog_temp_ssa_var (itype, NULL);
    5775         5116 :           pattern_stmt = gimple_build_assign (q, MINUS_EXPR, d < 0 ? t4 : t3,
    5776              :                                               d < 0 ? t3 : t4);
    5777              :         }
    5778         4822 :     }
    5779              : 
    5780        13710 :   if (rhs_code == TRUNC_MOD_EXPR || is_flclrd_moddiv_p)
    5781              :     {
    5782         6213 :       tree r, t1;
    5783              : 
    5784              :       /* We divided.  Now finish by:
    5785              :          t1 = q * oprnd1;
    5786              :          r = oprnd0 - t1;  */
    5787         6213 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt);
    5788              : 
    5789         6213 :       t1 = vect_recog_temp_ssa_var (itype, NULL);
    5790         6213 :       def_stmt = gimple_build_assign (t1, MULT_EXPR, q, oprnd1);
    5791         6213 :       append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt);
    5792              : 
    5793         6213 :       r = vect_recog_temp_ssa_var (itype, NULL);
    5794         6213 :       pattern_stmt = gimple_build_assign (r, MINUS_EXPR, oprnd0, t1);
    5795              : 
    5796         6213 :       if (is_flclrd_moddiv_p)
    5797              :         {
    5798          146 :         append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt);
    5799          146 :         pattern_stmt
    5800          146 :           = add_code_for_floorceilround_divmod (vectype, vinfo, stmt_vinfo,
    5801              :                                                 rhs_code, q, r, oprnd0, oprnd1,
    5802              :                                                 itype);
    5803          146 :         if (pattern_stmt == NULL)
    5804              :           return NULL;
    5805              :         }
    5806              :     }
    5807              : 
    5808              :   /* Pattern detected.  */
    5809        13710 :   vect_pattern_detected ("vect_recog_divmod_pattern", last_stmt);
    5810              : 
    5811        13710 :   *type_out = vectype;
    5812        13710 :   return pattern_stmt;
    5813              : }
    5814              : 
    5815              : /* Detects pattern with a modulo operation (S1) where both arguments
    5816              :    are variables of integral type.
    5817              :    The statement is replaced by division, multiplication, and subtraction.
    5818              :    The last statement (S4) is returned.
    5819              : 
    5820              :    Example:
    5821              :    S1 c_t = a_t % b_t;
    5822              : 
    5823              :    is replaced by
    5824              :    S2 x_t = a_t / b_t;
    5825              :    S3 y_t = x_t * b_t;
    5826              :    S4 z_t = a_t - y_t;  */
    5827              : 
    5828              : static gimple *
    5829     32494956 : vect_recog_mod_var_pattern (vec_info *vinfo,
    5830              :                             stmt_vec_info stmt_vinfo, tree *type_out)
    5831              : {
    5832     32494956 :   gimple *last_stmt = STMT_VINFO_STMT (stmt_vinfo);
    5833     32494956 :   tree oprnd0, oprnd1, vectype, itype;
    5834     32494956 :   gimple *pattern_stmt, *def_stmt;
    5835     32494956 :   enum tree_code rhs_code;
    5836              : 
    5837     32494956 :   if (!is_gimple_assign (last_stmt) || vect_is_reduction (stmt_vinfo))
    5838              :     return NULL;
    5839              : 
    5840     22592324 :   rhs_code = gimple_assign_rhs_code (last_stmt);
    5841     22592324 :   if (rhs_code != TRUNC_MOD_EXPR)
    5842              :     return NULL;
    5843              : 
    5844        78375 :   oprnd0 = gimple_assign_rhs1 (last_stmt);
    5845        78375 :   oprnd1 = gimple_assign_rhs2 (last_stmt);
    5846        78375 :   itype = TREE_TYPE (oprnd0);
    5847        78375 :   if (TREE_CODE (oprnd0) != SSA_NAME
    5848        69532 :       || TREE_CODE (oprnd1) != SSA_NAME
    5849        52905 :       || TREE_CODE (itype) != INTEGER_TYPE)
    5850              :     return NULL;
    5851              : 
    5852        52802 :   vectype = get_vectype_for_scalar_type (vinfo, itype);
    5853              : 
    5854        52802 :   if (!vectype
    5855        44227 :       || target_has_vecop_for_code (TRUNC_MOD_EXPR, vectype)
    5856        44227 :       || !target_has_vecop_for_code (TRUNC_DIV_EXPR, vectype)
    5857            0 :       || !target_has_vecop_for_code (MULT_EXPR, vectype)
    5858        52802 :       || !target_has_vecop_for_code (MINUS_EXPR, vectype))
    5859              :     return NULL;
    5860              : 
    5861            0 :   tree q, tmp, r;
    5862            0 :   q = vect_recog_temp_ssa_var (itype, NULL);
    5863            0 :   def_stmt = gimple_build_assign (q, TRUNC_DIV_EXPR, oprnd0, oprnd1);
    5864            0 :   append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, vectype);
    5865              : 
    5866            0 :   tmp = vect_recog_temp_ssa_var (itype, NULL);
    5867            0 :   def_stmt = gimple_build_assign (tmp, MULT_EXPR, q, oprnd1);
    5868            0 :   append_pattern_def_seq (vinfo, stmt_vinfo, def_stmt, vectype);
    5869              : 
    5870            0 :   r = vect_recog_temp_ssa_var (itype, NULL);
    5871            0 :   pattern_stmt = gimple_build_assign (r, MINUS_EXPR, oprnd0, tmp);
    5872              : 
    5873              :   /* Pattern detected.  */
    5874            0 :   *type_out = vectype;
    5875            0 :   vect_pattern_detected ("vect_recog_mod_var_pattern", last_stmt);
    5876              : 
    5877            0 :   return pattern_stmt;
    5878              : }
    5879              : 
    5880              : 
    5881              : /* Return the proper type for converting bool VAR into
    5882              :    an integer value or NULL_TREE if no such type exists.
    5883              :    The type is chosen so that the converted value has the
    5884              :    same number of elements as VAR's vector type.  */
    5885              : 
    5886              : static tree
    5887      4793681 : integer_type_for_mask (tree var, vec_info *vinfo, vect_def_type *dt = nullptr)
    5888              : {
    5889      4793681 :   if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (var)))
    5890              :     return NULL_TREE;
    5891              : 
    5892      2206509 :   stmt_vec_info def_stmt_info = vinfo->lookup_def (var);
    5893      2206509 :   if (dt)
    5894              :     {
    5895       402628 :       if (!def_stmt_info)
    5896         3488 :         *dt = vect_external_def;
    5897              :       else
    5898       399140 :         *dt = STMT_VINFO_DEF_TYPE (def_stmt_info);
    5899              :     }
    5900       402628 :   if (!def_stmt_info
    5901      2110837 :       || STMT_VINFO_DEF_TYPE (def_stmt_info) == vect_external_def
    5902      3914718 :       || !vect_use_mask_type_p (def_stmt_info))
    5903              :     return NULL_TREE;
    5904              : 
    5905      1365812 :   return build_nonstandard_integer_type (def_stmt_info->mask_precision, 1);
    5906              : }
    5907              : 
    5908              : /* Function vect_recog_gcond_pattern
    5909              : 
    5910              :    Try to find pattern like following:
    5911              : 
    5912              :      if (a op b)
    5913              : 
    5914              :    where operator 'op' is not != and convert it to an adjusted boolean pattern
    5915              : 
    5916              :      mask = a op b
    5917              :      if (mask != 0)
    5918              : 
    5919              :    and set the mask type on MASK.
    5920              : 
    5921              :    Input:
    5922              : 
    5923              :    * STMT_VINFO: The stmt at the end from which the pattern
    5924              :                  search begins, i.e. cast of a bool to
    5925              :                  an integer type.
    5926              : 
    5927              :    Output:
    5928              : 
    5929              :    * TYPE_OUT: The type of the output of this pattern.
    5930              : 
    5931              :    * Return value: A new stmt that will be used to replace the pattern.  */
    5932              : 
    5933              : static gimple *
    5934     32567399 : vect_recog_gcond_pattern (vec_info *vinfo,
    5935              :                          stmt_vec_info stmt_vinfo, tree *type_out)
    5936              : {
    5937              :   /* Currently we only support this for loop vectorization and when multiple
    5938              :      exits.  */
    5939     32567399 :   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    5940      4599984 :   if (!loop_vinfo || !LOOP_VINFO_EARLY_BREAKS (loop_vinfo))
    5941              :     return NULL;
    5942              : 
    5943      1708168 :   gimple *last_stmt = STMT_VINFO_STMT (stmt_vinfo);
    5944      1708168 :   gcond* cond = NULL;
    5945      1708168 :   if (!(cond = dyn_cast <gcond *> (last_stmt)))
    5946              :     return NULL;
    5947              : 
    5948       400261 :   auto lhs = gimple_cond_lhs (cond);
    5949       400261 :   auto rhs = gimple_cond_rhs (cond);
    5950       400261 :   auto code = gimple_cond_code (cond);
    5951              : 
    5952       400261 :   tree scalar_type = TREE_TYPE (lhs);
    5953       400261 :   if (VECTOR_TYPE_P (scalar_type))
    5954              :     return NULL;
    5955              : 
    5956              :   /* If the input is a boolean then try to figure out the precision that the
    5957              :      vector type should use.  We cannot use the scalar precision as this would
    5958              :      later mismatch.  This is similar to what recog_bool does.  */
    5959       400261 :   if (VECT_SCALAR_BOOLEAN_TYPE_P (scalar_type))
    5960              :     {
    5961        10420 :       if (tree stype = integer_type_for_mask (lhs, vinfo))
    5962       400261 :         scalar_type = stype;
    5963              :     }
    5964              : 
    5965       400261 :   tree vectype = get_mask_type_for_scalar_type (vinfo, scalar_type);
    5966       400261 :   if (vectype == NULL_TREE)
    5967              :     return NULL;
    5968              : 
    5969       380012 :   tree new_lhs = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    5970       380012 :   gimple *new_stmt = gimple_build_assign (new_lhs, code, lhs, rhs);
    5971       380012 :   append_pattern_def_seq (vinfo, stmt_vinfo, new_stmt, vectype, scalar_type);
    5972              : 
    5973       380012 :   gimple *pattern_stmt
    5974       380012 :     = gimple_build_cond (NE_EXPR, new_lhs,
    5975       380012 :                          build_int_cst (TREE_TYPE (new_lhs), 0),
    5976              :                          NULL_TREE, NULL_TREE);
    5977       380012 :   *type_out = vectype;
    5978       380012 :   vect_pattern_detected ("vect_recog_gcond_pattern", last_stmt);
    5979       380012 :   return pattern_stmt;
    5980              : }
    5981              : 
    5982              : 
    5983              : /* A helper for vect_recog_mask_conversion_pattern.  Build
    5984              :    conversion of MASK to a type suitable for masking VECTYPE.
    5985              :    Built statement gets required vectype and is appended to
    5986              :    a pattern sequence of STMT_VINFO.
    5987              :    If VECTYPE is a mask type, SCALAR_TYPE_FOR_MASK is the scalar type
    5988              :    from which it was derived.
    5989              : 
    5990              :    Return converted mask.  */
    5991              : 
    5992              : static tree
    5993       145693 : build_mask_conversion (vec_info *vinfo,
    5994              :                        tree mask, tree vectype, stmt_vec_info stmt_vinfo,
    5995              :                        tree scalar_type_for_mask = NULL_TREE)
    5996              : {
    5997       145693 :   gimple *stmt;
    5998       145693 :   tree masktype, tmp;
    5999              : 
    6000       235229 :   gcc_assert (!scalar_type_for_mask == !VECTOR_BOOLEAN_TYPE_P (vectype));
    6001              : 
    6002       145693 :   masktype = truth_type_for (vectype);
    6003       145693 :   tmp = vect_recog_temp_ssa_var (TREE_TYPE (masktype), NULL);
    6004       145693 :   stmt = gimple_build_assign (tmp, CONVERT_EXPR, mask);
    6005       235229 :   append_pattern_def_seq (vinfo, stmt_vinfo,
    6006              :                           stmt, masktype,
    6007              :                           scalar_type_for_mask
    6008        89536 :                           ? scalar_type_for_mask : TREE_TYPE (vectype));
    6009              : 
    6010       145693 :   return tmp;
    6011              : }
    6012              : 
    6013              : 
    6014              : /* Return MASK if MASK is suitable for masking an operation on vectors
    6015              :    of type VECTYPE, otherwise convert it into such a form and return
    6016              :    the result.  Associate any conversion statements with STMT_INFO's
    6017              :    pattern.  If VECTYPE is a mask type, SCALAR_TYPE_FOR_MASK is the scalar
    6018              :    type from which it was derived.  */
    6019              : 
    6020              : static tree
    6021        79250 : vect_convert_mask_for_vectype (tree mask, tree vectype,
    6022              :                                stmt_vec_info stmt_info, vec_info *vinfo,
    6023              :                                tree scalar_type_for_mask = NULL_TREE)
    6024              : {
    6025        79250 :   tree mask_type = integer_type_for_mask (mask, vinfo);
    6026        79250 :   if (mask_type)
    6027              :     {
    6028        79250 :       tree mask_vectype = get_mask_type_for_scalar_type (vinfo, mask_type);
    6029        79250 :       if (mask_vectype
    6030       158500 :           && maybe_ne (TYPE_VECTOR_SUBPARTS (vectype),
    6031        96474 :                        TYPE_VECTOR_SUBPARTS (mask_vectype)))
    6032        62026 :         mask = build_mask_conversion (vinfo, mask, vectype, stmt_info,
    6033              :                                       scalar_type_for_mask);
    6034              :     }
    6035        79250 :   return mask;
    6036              : }
    6037              : 
    6038              : 
    6039              : /* Function vect_recog_bool_pattern
    6040              : 
    6041              :    Try to find pattern like following:
    6042              : 
    6043              :      bool a_b, b_b, c_b, d_b, e_b;
    6044              :      TYPE f_T;
    6045              :    loop:
    6046              :      S1  a_b = x1 CMP1 y1;
    6047              :      S2  b_b = x2 CMP2 y2;
    6048              :      S3  c_b = a_b & b_b;
    6049              :      S4  d_b = x3 CMP3 y3;
    6050              :      S5  e_b = c_b | d_b;
    6051              :      S6  f_T = (TYPE) e_b;
    6052              : 
    6053              :    where type 'TYPE' is an integral type.  Or a similar pattern
    6054              :    ending in
    6055              : 
    6056              :      S6  f_Y = e_b ? r_Y : s_Y;
    6057              : 
    6058              :    as results from if-conversion of a complex condition.
    6059              : 
    6060              :    Input:
    6061              : 
    6062              :    * STMT_VINFO: The stmt at the end from which the pattern
    6063              :                  search begins, i.e. cast of a bool to
    6064              :                  an integer type.
    6065              : 
    6066              :    Output:
    6067              : 
    6068              :    * TYPE_OUT: The type of the output of this pattern.
    6069              : 
    6070              :    * Return value: A new stmt that will be used to replace the pattern.
    6071              : 
    6072              :         Assuming size of TYPE is the same as size of all comparisons
    6073              :         (otherwise some casts would be added where needed), the above
    6074              :         sequence we create related pattern stmts:
    6075              :         S1'  a_T = x1 CMP1 y1 ? 1 : 0;
    6076              :         S3'  c_T = x2 CMP2 y2 ? a_T : 0;
    6077              :         S4'  d_T = x3 CMP3 y3 ? 1 : 0;
    6078              :         S5'  e_T = c_T | d_T;
    6079              :         S6'  f_T = e_T;
    6080              : 
    6081              :         Instead of the above S3' we could emit:
    6082              :         S2'  b_T = x2 CMP2 y2 ? 1 : 0;
    6083              :         S3'  c_T = a_T | b_T;
    6084              :         but the above is more efficient.  */
    6085              : 
    6086              : static gimple *
    6087     32567399 : vect_recog_bool_pattern (vec_info *vinfo,
    6088              :                          stmt_vec_info stmt_vinfo, tree *type_out)
    6089              : {
    6090     32567399 :   gimple *last_stmt = stmt_vinfo->stmt;
    6091     32567399 :   enum tree_code rhs_code;
    6092     32567399 :   tree var, lhs, rhs, vectype;
    6093     32567399 :   gimple *pattern_stmt;
    6094              : 
    6095     32567399 :   if (!is_gimple_assign (last_stmt))
    6096              :     return NULL;
    6097              : 
    6098     23157929 :   var = gimple_assign_rhs1 (last_stmt);
    6099     23157929 :   lhs = gimple_assign_lhs (last_stmt);
    6100     23157929 :   rhs_code = gimple_assign_rhs_code (last_stmt);
    6101              : 
    6102     23157929 :   if (rhs_code == VIEW_CONVERT_EXPR)
    6103       194692 :     var = TREE_OPERAND (var, 0);
    6104              : 
    6105     23157929 :   if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (var)))
    6106              :     return NULL;
    6107              : 
    6108       775161 :   hash_set<gimple *> bool_stmts;
    6109              : 
    6110       775161 :   if (CONVERT_EXPR_CODE_P (rhs_code)
    6111              :       || rhs_code == VIEW_CONVERT_EXPR
    6112              :       || rhs_code == FLOAT_EXPR)
    6113              :     {
    6114       165464 :       if (! (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
    6115         2411 :              || SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs)))
    6116       163587 :           || VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (lhs)))
    6117              :         return NULL;
    6118        76273 :       vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
    6119              : 
    6120        76273 :       tree type = integer_type_for_mask (var, vinfo);
    6121        76273 :       tree cst0, cst1, tmp;
    6122              : 
    6123        76273 :       if (!type)
    6124              :         return NULL;
    6125              : 
    6126              :       /* We may directly use cond with narrowed type to avoid multiple cond
    6127              :          exprs with following result packing and perform single cond with
    6128              :          packed mask instead.  In case of widening we better make cond first
    6129              :          and then extract results.  */
    6130        37079 :       if (TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (lhs)))
    6131        24157 :         type = TREE_TYPE (lhs);
    6132              : 
    6133        37079 :       cst0 = build_int_cst (type, 0);
    6134        37079 :       cst1 = build_int_cst (type, 1);
    6135        37079 :       tmp = vect_recog_temp_ssa_var (type, NULL);
    6136        37079 :       pattern_stmt = gimple_build_assign (tmp, COND_EXPR, var, cst1, cst0);
    6137              : 
    6138        37079 :       if (!useless_type_conversion_p (type, TREE_TYPE (lhs)))
    6139              :         {
    6140        12922 :           tree new_vectype = get_vectype_for_scalar_type (vinfo, type);
    6141        12922 :           append_pattern_def_seq (vinfo, stmt_vinfo,
    6142              :                                   pattern_stmt, new_vectype);
    6143              : 
    6144        12922 :           lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6145        12922 :           pattern_stmt
    6146        25536 :             = gimple_build_assign (lhs, (rhs_code == FLOAT_EXPR
    6147              :                                          ? FLOAT_EXPR : CONVERT_EXPR), tmp);
    6148              :         }
    6149              : 
    6150        37079 :       *type_out = vectype;
    6151        37079 :       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
    6152              : 
    6153        37079 :       return pattern_stmt;
    6154              :     }
    6155              :   else if (rhs_code == COND_EXPR
    6156       211438 :            && TREE_CODE (var) == SSA_NAME)
    6157              :     {
    6158       211438 :       vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
    6159       211438 :       if (vectype == NULL_TREE)
    6160              :         return NULL;
    6161              : 
    6162              :       /* Build a scalar type for the boolean result that when
    6163              :          vectorized matches the vector type of the result in
    6164              :          size and number of elements.  */
    6165       196079 :       unsigned prec
    6166       196079 :         = vector_element_size (tree_to_poly_uint64 (TYPE_SIZE (vectype)),
    6167              :                                TYPE_VECTOR_SUBPARTS (vectype));
    6168              : 
    6169       196079 :       tree type
    6170       392158 :         = build_nonstandard_integer_type (prec,
    6171       196079 :                                           TYPE_UNSIGNED (TREE_TYPE (var)));
    6172       196079 :       if (get_vectype_for_scalar_type (vinfo, type) == NULL_TREE)
    6173              :         return NULL;
    6174              : 
    6175       196079 :       enum vect_def_type dt;
    6176       196079 :       if (integer_type_for_mask (var, vinfo))
    6177              :         return NULL;
    6178        36746 :       else if (TREE_CODE (TREE_TYPE (var)) == BOOLEAN_TYPE
    6179        36746 :                && vect_is_simple_use (var, vinfo, &dt)
    6180        36746 :                && (dt == vect_external_def
    6181        36739 :                    || dt == vect_constant_def))
    6182              :         {
    6183              :           /* If the condition is already a boolean then manually convert it to a
    6184              :              mask of the given integer type but don't set a vectype.  */
    6185         1383 :           tree lhs_ivar = vect_recog_temp_ssa_var (type, NULL);
    6186         1383 :           pattern_stmt = gimple_build_assign (lhs_ivar, COND_EXPR, var,
    6187              :                                               build_all_ones_cst (type),
    6188              :                                               build_zero_cst (type));
    6189         1383 :           append_inv_pattern_def_seq (vinfo, pattern_stmt);
    6190         1383 :           var = lhs_ivar;
    6191              :         }
    6192              : 
    6193        36746 :       tree lhs_var = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    6194        36746 :       pattern_stmt = gimple_build_assign (lhs_var, NE_EXPR, var,
    6195        36746 :                                           build_zero_cst (TREE_TYPE (var)));
    6196              : 
    6197        36746 :       tree new_vectype = get_mask_type_for_scalar_type (vinfo, TREE_TYPE (var));
    6198        36746 :       if (!new_vectype)
    6199              :         return NULL;
    6200              : 
    6201        36746 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, new_vectype,
    6202        36746 :                               TREE_TYPE (var));
    6203              : 
    6204        36746 :       lhs_var = vect_convert_mask_for_vectype (lhs_var, vectype, stmt_vinfo,
    6205              :                                                vinfo);
    6206              : 
    6207        36746 :       lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6208        36746 :       pattern_stmt
    6209        36746 :         = gimple_build_assign (lhs, COND_EXPR, lhs_var,
    6210              :                                gimple_assign_rhs2 (last_stmt),
    6211              :                                gimple_assign_rhs3 (last_stmt));
    6212        36746 :       *type_out = vectype;
    6213        36746 :       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
    6214              : 
    6215        36746 :       return pattern_stmt;
    6216              :     }
    6217       480616 :   else if (rhs_code == BIT_NOT_EXPR
    6218       480616 :            && !vect_use_mask_type_p (stmt_vinfo))
    6219              :     {
    6220              :       /* When we have a bool data inversion rewrite that to an XOR to
    6221              :          cope with the fact that we'll use a wider vector element type.  */
    6222         9874 :       lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6223         9874 :       pattern_stmt
    6224         9874 :         = gimple_build_assign (lhs, BIT_XOR_EXPR, var,
    6225         9874 :                                build_all_ones_cst (TREE_TYPE (var)));
    6226         9874 :       *type_out = NULL_TREE;
    6227         9874 :       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
    6228              : 
    6229         9874 :       return pattern_stmt;
    6230              :     }
    6231       470742 :   else if ((rhs_code == BIT_XOR_EXPR
    6232              :             || rhs_code == BIT_AND_EXPR
    6233       470742 :             || rhs_code == BIT_IOR_EXPR)
    6234       376631 :            && TREE_CODE (var) == SSA_NAME)
    6235              :     {
    6236       376631 :       tree rhs2 = gimple_assign_rhs2 (last_stmt);
    6237       376631 :       if (TREE_CODE (rhs2) != SSA_NAME)
    6238              :         return NULL;
    6239       376631 :       tree lhs_type = integer_type_for_mask (lhs, vinfo);
    6240       376631 :       if (!lhs_type)
    6241              :         return NULL;
    6242       201314 :       vectype = get_mask_type_for_scalar_type (vinfo, lhs_type);
    6243       201314 :       if (!vectype)
    6244              :         return NULL;
    6245       201314 :       vect_def_type dt1, dt2;
    6246       201314 :       tree rhs1_type = integer_type_for_mask (var, vinfo, &dt1);
    6247       201314 :       tree rhs2_type = integer_type_for_mask (rhs2, vinfo, &dt2);
    6248       201314 :       if ((rhs1_type || dt1 == vect_external_def)
    6249       185877 :           && (rhs2_type || dt2 == vect_external_def))
    6250              :         return NULL;
    6251              :       /* When one input is a mask and the other is not create a pattern
    6252              :          stmt sequence that creates a mask for the non-mask input and
    6253              :          convert it to one suitable for the output mask used.  */
    6254        38071 :       if (rhs1_type && !rhs2_type)
    6255              :         {
    6256        22634 :           tree rhs1_vectype = get_mask_type_for_scalar_type (vinfo, rhs1_type);
    6257        22634 :           if (!rhs1_vectype)
    6258              :             return NULL;
    6259        22634 :           tree rhs2_vectype = get_vectype_for_scalar_type (vinfo,
    6260        22634 :                                                            TREE_TYPE (rhs2));
    6261        22634 :           if (!rhs2_vectype)
    6262              :             return NULL;
    6263        22634 :           tree new_vectype = truth_type_for (rhs2_vectype);
    6264        22634 :           tree tem = vect_recog_temp_ssa_var (TREE_TYPE (new_vectype), NULL);
    6265        22634 :           pattern_stmt = gimple_build_assign (tem, NE_EXPR, rhs2,
    6266              :                                               build_zero_cst
    6267        22634 :                                                 (TREE_TYPE (rhs2)));
    6268        22634 :           append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt,
    6269        22634 :                                   new_vectype, TREE_TYPE (new_vectype));
    6270        22634 :           rhs2 = vect_convert_mask_for_vectype (tem, rhs1_vectype,
    6271              :                                                 stmt_vinfo, vinfo, rhs1_type);
    6272              :         }
    6273        15437 :       else if (!rhs1_type && rhs2_type)
    6274              :         {
    6275        15437 :           tree rhs2_vectype = get_mask_type_for_scalar_type (vinfo, rhs2_type);
    6276        15437 :           if (!rhs2_vectype)
    6277              :             return NULL;
    6278        15437 :           tree rhs1_vectype = get_vectype_for_scalar_type (vinfo,
    6279        15437 :                                                            TREE_TYPE (var));
    6280        15437 :           if (!rhs1_vectype)
    6281              :             return NULL;
    6282        15437 :           tree new_vectype = truth_type_for (rhs1_vectype);
    6283        15437 :           tree tem = vect_recog_temp_ssa_var (TREE_TYPE (new_vectype), NULL);
    6284        15437 :           pattern_stmt = gimple_build_assign (tem, NE_EXPR, var,
    6285              :                                               build_zero_cst
    6286        15437 :                                                 (TREE_TYPE (var)));
    6287        15437 :           append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt,
    6288        15437 :                                   new_vectype, TREE_TYPE (new_vectype));
    6289        15437 :           var = vect_convert_mask_for_vectype (tem, rhs2_vectype,
    6290              :                                                stmt_vinfo, vinfo, rhs2_type);
    6291              :         }
    6292        38071 :       lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6293        38071 :       pattern_stmt = gimple_build_assign (lhs, rhs_code, var, rhs2);
    6294        38071 :       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
    6295        38071 :       *type_out = vectype;
    6296        38071 :       return pattern_stmt;
    6297              :     }
    6298        94111 :   else if (rhs_code == SSA_NAME
    6299        25705 :            && STMT_VINFO_DATA_REF (stmt_vinfo))
    6300              :     {
    6301         7807 :       stmt_vec_info pattern_stmt_info;
    6302         7807 :       vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
    6303         7807 :       if (!vectype || !VECTOR_MODE_P (TYPE_MODE (vectype)))
    6304              :         return NULL;
    6305              : 
    6306         7807 :       tree type = integer_type_for_mask (var, vinfo);
    6307         7807 :       if (!type)
    6308              :         return NULL;
    6309              : 
    6310         4433 :       var = vect_convert_mask_for_vectype (var, vectype, stmt_vinfo, vinfo);
    6311              : 
    6312         4433 :       tree cst0 = build_int_cst (TREE_TYPE (vectype), 0);
    6313         4433 :       tree cst1 = build_int_cst (TREE_TYPE (vectype), 1);
    6314         4433 :       rhs = vect_recog_temp_ssa_var (TREE_TYPE (vectype), NULL);
    6315         4433 :       pattern_stmt = gimple_build_assign (rhs, COND_EXPR, var, cst1, cst0);
    6316         4433 :       append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vectype);
    6317              : 
    6318         4433 :       lhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (vectype), lhs);
    6319         4433 :       pattern_stmt = gimple_build_assign (lhs, SSA_NAME, rhs);
    6320         4433 :       pattern_stmt_info = vinfo->add_stmt (pattern_stmt);
    6321         4433 :       vinfo->move_dr (pattern_stmt_info, stmt_vinfo);
    6322         4433 :       *type_out = vectype;
    6323         4433 :       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
    6324              : 
    6325         4433 :       return pattern_stmt;
    6326              :     }
    6327              :   else
    6328              :     return NULL;
    6329       775161 : }
    6330              : 
    6331              : 
    6332              : /* Function vect_recog_mask_conversion_pattern
    6333              : 
    6334              :    Try to find statements which require boolean type
    6335              :    conversion.  Additional conversion statements are
    6336              :    added to handle such cases.  For example:
    6337              : 
    6338              :    bool m_1, m_2, m_3;
    6339              :    int i_4, i_5;
    6340              :    double d_6, d_7;
    6341              :    char c_1, c_2, c_3;
    6342              : 
    6343              :    S1   m_1 = i_4 > i_5;
    6344              :    S2   m_2 = d_6 < d_7;
    6345              :    S3   m_3 = m_1 & m_2;
    6346              :    S4   c_1 = m_3 ? c_2 : c_3;
    6347              : 
    6348              :    Will be transformed into:
    6349              : 
    6350              :    S1   m_1 = i_4 > i_5;
    6351              :    S2   m_2 = d_6 < d_7;
    6352              :    S3'' m_2' = (_Bool[bitsize=32])m_2
    6353              :    S3'  m_3' = m_1 & m_2';
    6354              :    S4'' m_3'' = (_Bool[bitsize=8])m_3'
    6355              :    S4'  c_1' = m_3'' ? c_2 : c_3;  */
    6356              : 
    6357              : static gimple *
    6358     32595530 : vect_recog_mask_conversion_pattern (vec_info *vinfo,
    6359              :                                     stmt_vec_info stmt_vinfo, tree *type_out)
    6360              : {
    6361     32595530 :   gimple *last_stmt = stmt_vinfo->stmt;
    6362     32595530 :   enum tree_code rhs_code;
    6363     32595530 :   tree lhs = NULL_TREE, rhs1, rhs2, tmp, rhs1_type, rhs2_type;
    6364     32595530 :   tree vectype1, vectype2;
    6365     32595530 :   stmt_vec_info pattern_stmt_info;
    6366              : 
    6367              :   /* Check for MASK_LOAD and MASK_STORE as well as COND_OP calls requiring mask
    6368              :      conversion.  */
    6369     32595530 :   if (is_gimple_call (last_stmt)
    6370     32595530 :       && gimple_call_internal_p (last_stmt))
    6371              :     {
    6372       127690 :       gcall *pattern_stmt;
    6373              : 
    6374       127690 :       internal_fn ifn = gimple_call_internal_fn (last_stmt);
    6375       127690 :       int mask_argno = internal_fn_mask_index (ifn);
    6376       127690 :       if (mask_argno < 0)
    6377              :         return NULL;
    6378              : 
    6379        14600 :       bool store_p = internal_store_fn_p (ifn);
    6380        14600 :       bool load_p = internal_store_fn_p (ifn);
    6381        14600 :       if (store_p)
    6382              :         {
    6383         2488 :           int rhs_index = internal_fn_stored_value_index (ifn);
    6384         2488 :           tree rhs = gimple_call_arg (last_stmt, rhs_index);
    6385         2488 :           vectype1 = get_vectype_for_scalar_type (vinfo, TREE_TYPE (rhs));
    6386              :         }
    6387              :       else
    6388              :         {
    6389        12112 :           lhs = gimple_call_lhs (last_stmt);
    6390        12112 :           if (!lhs)
    6391              :             return NULL;
    6392        12112 :           vectype1 = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
    6393              :         }
    6394              : 
    6395        14600 :       if (!vectype1)
    6396              :         return NULL;
    6397              : 
    6398        14280 :       tree mask_arg = gimple_call_arg (last_stmt, mask_argno);
    6399        14280 :       tree mask_arg_type = integer_type_for_mask (mask_arg, vinfo);
    6400        14280 :       if (mask_arg_type)
    6401              :         {
    6402        12653 :           vectype2 = get_mask_type_for_scalar_type (vinfo, mask_arg_type);
    6403              : 
    6404        12653 :           if (!vectype2
    6405        12653 :               || known_eq (TYPE_VECTOR_SUBPARTS (vectype1),
    6406              :                            TYPE_VECTOR_SUBPARTS (vectype2)))
    6407              :             return NULL;
    6408              :         }
    6409         1627 :       else if (store_p || load_p)
    6410              :         return NULL;
    6411              : 
    6412         6101 :       tmp = build_mask_conversion (vinfo, mask_arg, vectype1, stmt_vinfo);
    6413              : 
    6414         6101 :       auto_vec<tree, 8> args;
    6415         6101 :       unsigned int nargs = gimple_call_num_args (last_stmt);
    6416         6101 :       args.safe_grow (nargs, true);
    6417        36606 :       for (unsigned int i = 0; i < nargs; ++i)
    6418        24404 :         args[i] = ((int) i == mask_argno
    6419        24404 :                    ? tmp
    6420        18303 :                    : gimple_call_arg (last_stmt, i));
    6421         6101 :       pattern_stmt = gimple_build_call_internal_vec (ifn, args);
    6422              : 
    6423         6101 :       if (!store_p)
    6424              :         {
    6425         5829 :           lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6426         5829 :           gimple_call_set_lhs (pattern_stmt, lhs);
    6427              :         }
    6428              : 
    6429         5829 :       if (load_p || store_p)
    6430          272 :         gimple_call_set_nothrow (pattern_stmt, true);
    6431              : 
    6432         6101 :       pattern_stmt_info = vinfo->add_stmt (pattern_stmt);
    6433         6101 :       if (STMT_VINFO_DATA_REF (stmt_vinfo))
    6434         1804 :         vinfo->move_dr (pattern_stmt_info, stmt_vinfo);
    6435              : 
    6436         6101 :       *type_out = vectype1;
    6437         6101 :       vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
    6438              : 
    6439         6101 :       return pattern_stmt;
    6440         6101 :     }
    6441              : 
    6442     32467840 :   if (!is_gimple_assign (last_stmt))
    6443              :     return NULL;
    6444              : 
    6445     23186060 :   gimple *pattern_stmt;
    6446     23186060 :   lhs = gimple_assign_lhs (last_stmt);
    6447     23186060 :   rhs1 = gimple_assign_rhs1 (last_stmt);
    6448     23186060 :   rhs_code = gimple_assign_rhs_code (last_stmt);
    6449              : 
    6450              :   /* Check for cond expression requiring mask conversion.  */
    6451     23186060 :   if (rhs_code == COND_EXPR)
    6452              :     {
    6453       192183 :       vectype1 = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
    6454              : 
    6455       192183 :       gcc_assert (! COMPARISON_CLASS_P (rhs1));
    6456       192183 :       if (TREE_CODE (rhs1) == SSA_NAME)
    6457              :         {
    6458       192183 :           rhs1_type = integer_type_for_mask (rhs1, vinfo);
    6459       192183 :           if (!rhs1_type)
    6460              :             return NULL;
    6461              :         }
    6462              :       else
    6463              :         return NULL;
    6464              : 
    6465       178979 :       vectype2 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
    6466              : 
    6467       178979 :       if (!vectype1 || !vectype2)
    6468              :         return NULL;
    6469              : 
    6470              :       /* Continue if a conversion is needed.  Also continue if we have
    6471              :          a comparison whose vector type would normally be different from
    6472              :          VECTYPE2 when considered in isolation.  In that case we'll
    6473              :          replace the comparison with an SSA name (so that we can record
    6474              :          its vector type) and behave as though the comparison was an SSA
    6475              :          name from the outset.  */
    6476       176824 :       if (known_eq (TYPE_VECTOR_SUBPARTS (vectype1),
    6477              :                     TYPE_VECTOR_SUBPARTS (vectype2)))
    6478              :         return NULL;
    6479              : 
    6480        45736 :       if (maybe_ne (TYPE_VECTOR_SUBPARTS (vectype1),
    6481        91472 :                     TYPE_VECTOR_SUBPARTS (vectype2)))
    6482        45736 :         tmp = build_mask_conversion (vinfo, rhs1, vectype1, stmt_vinfo);
    6483              :       else
    6484              :         tmp = rhs1;
    6485              : 
    6486        45736 :       lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6487        45736 :       pattern_stmt = gimple_build_assign (lhs, COND_EXPR, tmp,
    6488              :                                           gimple_assign_rhs2 (last_stmt),
    6489              :                                           gimple_assign_rhs3 (last_stmt));
    6490              : 
    6491        45736 :       *type_out = vectype1;
    6492        45736 :       vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
    6493              : 
    6494        45736 :       return pattern_stmt;
    6495              :     }
    6496              : 
    6497              :   /* Now check for binary boolean operations requiring conversion for
    6498              :      one of operands.  */
    6499     22993877 :   if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (lhs)))
    6500              :     return NULL;
    6501              : 
    6502      1902789 :   if (rhs_code != BIT_IOR_EXPR
    6503              :       && rhs_code != BIT_XOR_EXPR
    6504      1902789 :       && rhs_code != BIT_AND_EXPR
    6505      1564229 :       && TREE_CODE_CLASS (rhs_code) != tcc_comparison)
    6506              :     return NULL;
    6507              : 
    6508      1719065 :   rhs2 = gimple_assign_rhs2 (last_stmt);
    6509              : 
    6510      1719065 :   rhs1_type = integer_type_for_mask (rhs1, vinfo);
    6511      1719065 :   rhs2_type = integer_type_for_mask (rhs2, vinfo);
    6512              : 
    6513      1719065 :   if (!rhs1_type || !rhs2_type
    6514      1719065 :       || TYPE_PRECISION (rhs1_type) == TYPE_PRECISION (rhs2_type))
    6515              :     return NULL;
    6516              : 
    6517        31830 :   if (TYPE_PRECISION (rhs1_type) < TYPE_PRECISION (rhs2_type))
    6518              :     {
    6519        24499 :       vectype1 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
    6520        24499 :       if (!vectype1)
    6521              :         return NULL;
    6522        24499 :       rhs2 = build_mask_conversion (vinfo, rhs2, vectype1, stmt_vinfo,
    6523              :                                     rhs1_type);
    6524              :     }
    6525              :   else
    6526              :     {
    6527         7331 :       vectype1 = get_mask_type_for_scalar_type (vinfo, rhs2_type);
    6528         7331 :       if (!vectype1)
    6529              :         return NULL;
    6530         7331 :       rhs1 = build_mask_conversion (vinfo, rhs1, vectype1, stmt_vinfo,
    6531              :                                     rhs2_type);
    6532              :     }
    6533              : 
    6534        31830 :   lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6535        31830 :   pattern_stmt = gimple_build_assign (lhs, rhs_code, rhs1, rhs2);
    6536              : 
    6537        31830 :   *type_out = vectype1;
    6538        31830 :   vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
    6539              : 
    6540        31830 :   return pattern_stmt;
    6541              : }
    6542              : 
    6543              : /* STMT_INFO is a load or store.  If the load or store is conditional, return
    6544              :    the boolean condition under which it occurs, otherwise return null.  */
    6545              : 
    6546              : static tree
    6547       104306 : vect_get_load_store_mask (stmt_vec_info stmt_info)
    6548              : {
    6549       104306 :   if (gassign *def_assign = dyn_cast <gassign *> (stmt_info->stmt))
    6550              :     {
    6551       103283 :       gcc_assert (gimple_assign_single_p (def_assign));
    6552              :       return NULL_TREE;
    6553              :     }
    6554              : 
    6555         1023 :   if (gcall *def_call = dyn_cast <gcall *> (stmt_info->stmt))
    6556              :     {
    6557         1023 :       internal_fn ifn = gimple_call_internal_fn (def_call);
    6558         1023 :       int mask_index = internal_fn_mask_index (ifn);
    6559         1023 :       return gimple_call_arg (def_call, mask_index);
    6560              :     }
    6561              : 
    6562            0 :   gcc_unreachable ();
    6563              : }
    6564              : 
    6565              : /* Return the equivalent of:
    6566              : 
    6567              :      fold_convert (TYPE, VALUE)
    6568              : 
    6569              :    with the expectation that the operation will be vectorized.
    6570              :    If new statements are needed, add them as pattern statements
    6571              :    to STMT_INFO.  */
    6572              : 
    6573              : static tree
    6574            0 : vect_add_conversion_to_pattern (vec_info *vinfo,
    6575              :                                 tree type, tree value, stmt_vec_info stmt_info)
    6576              : {
    6577            0 :   if (useless_type_conversion_p (type, TREE_TYPE (value)))
    6578              :     return value;
    6579              : 
    6580            0 :   tree new_value = vect_recog_temp_ssa_var (type, NULL);
    6581            0 :   gassign *conversion = gimple_build_assign (new_value, CONVERT_EXPR, value);
    6582            0 :   append_pattern_def_seq (vinfo, stmt_info, conversion,
    6583              :                           get_vectype_for_scalar_type (vinfo, type));
    6584            0 :   return new_value;
    6585              : }
    6586              : 
    6587              : /* Try to convert STMT_INFO into a call to a gather load or scatter store
    6588              :    internal function.  Return the final statement on success and set
    6589              :    *TYPE_OUT to the vector type being loaded or stored.
    6590              : 
    6591              :    This function only handles gathers and scatters that were recognized
    6592              :    as such from the outset (indicated by STMT_VINFO_GATHER_SCATTER_P).  */
    6593              : 
    6594              : static gimple *
    6595     32595530 : vect_recog_gather_scatter_pattern (vec_info *vinfo,
    6596              :                                    stmt_vec_info stmt_info, tree *type_out)
    6597              : {
    6598              :   /* Currently we only support this for loop vectorization.  */
    6599     32595530 :   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    6600      4612618 :   if (!loop_vinfo)
    6601              :     return NULL;
    6602              : 
    6603              :   /* Make sure that we're looking at a gather load or scatter store.  */
    6604      4612618 :   data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
    6605      4612618 :   if (!dr || !STMT_VINFO_GATHER_SCATTER_P (stmt_info))
    6606              :     return NULL;
    6607              : 
    6608              :   /* Get the boolean that controls whether the load or store happens.
    6609              :      This is null if the operation is unconditional.  */
    6610       104306 :   tree mask = vect_get_load_store_mask (stmt_info);
    6611              : 
    6612              :   /* DR analysis nailed down the vector type for the access.  */
    6613       104306 :   tree gs_vectype = STMT_VINFO_VECTYPE (stmt_info);
    6614              : 
    6615              :   /* Make sure that the target supports an appropriate internal
    6616              :      function for the gather/scatter operation.  */
    6617       104306 :   gather_scatter_info gs_info;
    6618       104306 :   if (!vect_check_gather_scatter (stmt_info, gs_vectype, loop_vinfo, &gs_info)
    6619       104306 :       || gs_info.ifn == IFN_LAST)
    6620              :     return NULL;
    6621              : 
    6622              :   /* Convert the mask to the right form.  */
    6623            0 :   if (mask)
    6624            0 :     mask = vect_convert_mask_for_vectype (mask, gs_vectype, stmt_info,
    6625              :                                           loop_vinfo);
    6626            0 :   else if (gs_info.ifn == IFN_MASK_SCATTER_STORE
    6627            0 :            || gs_info.ifn == IFN_MASK_GATHER_LOAD
    6628            0 :            || gs_info.ifn == IFN_MASK_LEN_SCATTER_STORE
    6629            0 :            || gs_info.ifn == IFN_MASK_LEN_GATHER_LOAD)
    6630            0 :     mask = build_int_cst (TREE_TYPE (truth_type_for (gs_vectype)), -1);
    6631              : 
    6632              :   /* Get the invariant base and non-invariant offset, converting the
    6633              :      latter to the same width as the vector elements.  */
    6634            0 :   tree base = gs_info.base;
    6635            0 :   tree offset_type = TREE_TYPE (gs_info.offset_vectype);
    6636            0 :   tree offset = vect_add_conversion_to_pattern (vinfo, offset_type,
    6637              :                                                 gs_info.offset, stmt_info);
    6638              : 
    6639              :   /* Build the new pattern statement.  */
    6640            0 :   tree scale = size_int (gs_info.scale);
    6641            0 :   gcall *pattern_stmt;
    6642              : 
    6643            0 :   if (DR_IS_READ (dr))
    6644              :     {
    6645            0 :       tree zero = build_zero_cst (gs_info.element_type);
    6646            0 :       if (mask != NULL)
    6647              :         {
    6648            0 :           int elsval = MASK_LOAD_ELSE_ZERO;
    6649              : 
    6650            0 :           tree vec_els
    6651            0 :             = vect_get_mask_load_else (elsval, TREE_TYPE (gs_vectype));
    6652            0 :           pattern_stmt = gimple_build_call_internal (gs_info.ifn, 7, base,
    6653              :                                                      gs_info.alias_ptr,
    6654              :                                                      offset, scale, zero, mask,
    6655              :                                                      vec_els);
    6656              :         }
    6657              :       else
    6658            0 :         pattern_stmt = gimple_build_call_internal (gs_info.ifn, 5, base,
    6659              :                                                    gs_info.alias_ptr,
    6660              :                                                    offset, scale, zero);
    6661            0 :       tree lhs = gimple_get_lhs (stmt_info->stmt);
    6662            0 :       tree load_lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
    6663            0 :       gimple_call_set_lhs (pattern_stmt, load_lhs);
    6664              :     }
    6665              :   else
    6666              :     {
    6667            0 :       tree rhs = vect_get_store_rhs (stmt_info);
    6668            0 :       if (mask != NULL)
    6669            0 :         pattern_stmt = gimple_build_call_internal (gs_info.ifn, 6,
    6670              :                                                    base, gs_info.alias_ptr,
    6671              :                                                    offset, scale, rhs, mask);
    6672              :       else
    6673            0 :         pattern_stmt = gimple_build_call_internal (gs_info.ifn, 5,
    6674              :                                                    base, gs_info.alias_ptr,
    6675              :                                                    offset, scale, rhs);
    6676              :     }
    6677            0 :   gimple_call_set_nothrow (pattern_stmt, true);
    6678              : 
    6679              :   /* Copy across relevant vectorization info and associate DR with the
    6680              :      new pattern statement instead of the original statement.  */
    6681            0 :   stmt_vec_info pattern_stmt_info = loop_vinfo->add_stmt (pattern_stmt);
    6682            0 :   loop_vinfo->move_dr (pattern_stmt_info, stmt_info);
    6683              : 
    6684            0 :   *type_out = gs_vectype;
    6685            0 :   vect_pattern_detected ("gather/scatter pattern", stmt_info->stmt);
    6686              : 
    6687            0 :   return pattern_stmt;
    6688              : }
    6689              : 
    6690              : /* Helper method of vect_recog_cond_store_pattern,  checks to see if COND_ARG
    6691              :    is points to a load statement that reads the same data as that of
    6692              :    STORE_VINFO.  */
    6693              : 
    6694              : static bool
    6695        35416 : vect_cond_store_pattern_same_ref (vec_info *vinfo,
    6696              :                                   stmt_vec_info store_vinfo, tree cond_arg)
    6697              : {
    6698        35416 :   stmt_vec_info load_stmt_vinfo = vinfo->lookup_def (cond_arg);
    6699        35416 :   if (!load_stmt_vinfo
    6700        20230 :       || !STMT_VINFO_DATA_REF (load_stmt_vinfo)
    6701        11986 :       || DR_IS_WRITE (STMT_VINFO_DATA_REF (load_stmt_vinfo))
    6702        47402 :       || !same_data_refs (STMT_VINFO_DATA_REF (store_vinfo),
    6703              :                           STMT_VINFO_DATA_REF (load_stmt_vinfo)))
    6704        26096 :     return false;
    6705              : 
    6706              :   return true;
    6707              : }
    6708              : 
    6709              : /* Function vect_recog_cond_store_pattern
    6710              : 
    6711              :    Try to find the following pattern:
    6712              : 
    6713              :    x = *_3;
    6714              :    c = a CMP b;
    6715              :    y = c ? t_20 : x;
    6716              :    *_3 = y;
    6717              : 
    6718              :    where the store of _3 happens on a conditional select on a value loaded
    6719              :    from the same location.  In such case we can elide the initial load if
    6720              :    MASK_STORE is supported and instead only conditionally write out the result.
    6721              : 
    6722              :    The pattern produces for the above:
    6723              : 
    6724              :    c = a CMP b;
    6725              :    .MASK_STORE (_3, c, t_20)
    6726              : 
    6727              :    Input:
    6728              : 
    6729              :    * STMT_VINFO: The stmt from which the pattern search begins.  In the
    6730              :    example, when this function is called with _3 then the search begins.
    6731              : 
    6732              :    Output:
    6733              : 
    6734              :    * TYPE_OUT: The type of the output  of this pattern.
    6735              : 
    6736              :    * Return value: A new stmt that will be used to replace the sequence.  */
    6737              : 
    6738              : static gimple *
    6739     32595530 : vect_recog_cond_store_pattern (vec_info *vinfo,
    6740              :                                stmt_vec_info stmt_vinfo, tree *type_out)
    6741              : {
    6742     32595530 :   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    6743      4612618 :   if (!loop_vinfo)
    6744              :     return NULL;
    6745              : 
    6746      4612618 :   gimple *store_stmt = STMT_VINFO_STMT (stmt_vinfo);
    6747              : 
    6748              :   /* Needs to be a gimple store where we have DR info for.  */
    6749      4612618 :   if (!STMT_VINFO_DATA_REF (stmt_vinfo)
    6750      1105357 :       || DR_IS_READ (STMT_VINFO_DATA_REF (stmt_vinfo))
    6751      5002200 :       || !gimple_store_p (store_stmt))
    6752              :     return NULL;
    6753              : 
    6754       387194 :   tree st_rhs = gimple_assign_rhs1 (store_stmt);
    6755              : 
    6756       387194 :   if (TREE_CODE (st_rhs) != SSA_NAME)
    6757              :     return NULL;
    6758              : 
    6759       301043 :   auto cond_vinfo = vinfo->lookup_def (st_rhs);
    6760              : 
    6761              :   /* If the condition isn't part of the loop then bool recog wouldn't have seen
    6762              :      it and so this transformation may not be valid.  */
    6763       301043 :   if (!cond_vinfo)
    6764              :     return NULL;
    6765              : 
    6766       283365 :   cond_vinfo = vect_stmt_to_vectorize (cond_vinfo);
    6767       283365 :   gassign *cond_stmt = dyn_cast<gassign *> (STMT_VINFO_STMT (cond_vinfo));
    6768       351791 :   if (!cond_stmt || gimple_assign_rhs_code (cond_stmt) != COND_EXPR)
    6769              :     return NULL;
    6770              : 
    6771              :   /* Check if the else value matches the original loaded one.  */
    6772        18760 :   bool invert = false;
    6773        18760 :   tree cmp_ls = gimple_arg (cond_stmt, 0);
    6774        18760 :   if (TREE_CODE (cmp_ls) != SSA_NAME)
    6775              :     return NULL;
    6776              : 
    6777        18760 :   tree cond_arg1 = gimple_arg (cond_stmt, 1);
    6778        18760 :   tree cond_arg2 = gimple_arg (cond_stmt, 2);
    6779              : 
    6780        18760 :   if (!vect_cond_store_pattern_same_ref (vinfo, stmt_vinfo, cond_arg2)
    6781        18760 :       && !(invert = vect_cond_store_pattern_same_ref (vinfo, stmt_vinfo,
    6782              :                                                       cond_arg1)))
    6783              :     return NULL;
    6784              : 
    6785         9320 :   vect_pattern_detected ("vect_recog_cond_store_pattern", store_stmt);
    6786              : 
    6787         9320 :   tree scalar_type = TREE_TYPE (st_rhs);
    6788         9320 :   if (VECTOR_TYPE_P (scalar_type))
    6789              :     return NULL;
    6790              : 
    6791         9320 :   tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type);
    6792         9320 :   if (vectype == NULL_TREE)
    6793              :     return NULL;
    6794              : 
    6795         9320 :   machine_mode mask_mode;
    6796         9320 :   machine_mode vecmode = TYPE_MODE (vectype);
    6797         1858 :   if (!VECTOR_MODE_P (vecmode)
    6798         9320 :       || targetm.vectorize.conditional_operation_is_expensive (IFN_MASK_STORE)
    6799         9320 :       || !targetm.vectorize.get_mask_mode (vecmode).exists (&mask_mode)
    6800         9320 :       || !can_vec_mask_load_store_p (vecmode, mask_mode, false))
    6801              :     return NULL;
    6802              : 
    6803            0 :   tree base = DR_REF (STMT_VINFO_DATA_REF (stmt_vinfo));
    6804            0 :   if (may_be_nonaddressable_p (base))
    6805              :     return NULL;
    6806              : 
    6807              :   /* We need to use the false parameter of the conditional select.  */
    6808            0 :   tree cond_store_arg = invert ? cond_arg2 : cond_arg1;
    6809            0 :   tree cond_load_arg = invert ? cond_arg1 : cond_arg2;
    6810            0 :   gimple *load_stmt = SSA_NAME_DEF_STMT (cond_load_arg);
    6811              : 
    6812              :   /* This is a rough estimation to check that there aren't any aliasing stores
    6813              :      in between the load and store.  It's a bit strict, but for now it's good
    6814              :      enough.  */
    6815            0 :   if (gimple_vuse (load_stmt) != gimple_vuse (store_stmt))
    6816              :     return NULL;
    6817              : 
    6818              :   /* If we have to invert the condition, i.e. use the true argument rather than
    6819              :      the false argument, we have to negate the mask.  */
    6820            0 :   if (invert)
    6821              :     {
    6822            0 :       tree var = vect_recog_temp_ssa_var (boolean_type_node, NULL);
    6823              : 
    6824              :       /* Invert the mask using ^ 1.  */
    6825            0 :       tree itype = TREE_TYPE (cmp_ls);
    6826            0 :       gassign *conv = gimple_build_assign (var, BIT_XOR_EXPR, cmp_ls,
    6827              :                                            build_int_cst (itype, 1));
    6828              : 
    6829            0 :       tree mask_vec_type = get_mask_type_for_scalar_type (vinfo, itype);
    6830            0 :       append_pattern_def_seq (vinfo, stmt_vinfo, conv, mask_vec_type, itype);
    6831            0 :       cmp_ls= var;
    6832              :     }
    6833              : 
    6834            0 :   if (TREE_CODE (base) != MEM_REF)
    6835            0 :    base = build_fold_addr_expr (base);
    6836              : 
    6837            0 :   tree ptr = build_int_cst (reference_alias_ptr_type (base),
    6838            0 :                             get_object_alignment (base));
    6839              : 
    6840              :   /* Convert the mask to the right form.  */
    6841            0 :   tree mask = vect_convert_mask_for_vectype (cmp_ls, vectype, stmt_vinfo,
    6842              :                                              vinfo);
    6843              : 
    6844            0 :   gcall *call
    6845            0 :     = gimple_build_call_internal (IFN_MASK_STORE, 4, base, ptr, mask,
    6846              :                                   cond_store_arg);
    6847            0 :   gimple_set_location (call, gimple_location (store_stmt));
    6848              : 
    6849              :   /* Copy across relevant vectorization info and associate DR with the
    6850              :      new pattern statement instead of the original statement.  */
    6851            0 :   stmt_vec_info pattern_stmt_info = loop_vinfo->add_stmt (call);
    6852            0 :   loop_vinfo->move_dr (pattern_stmt_info, stmt_vinfo);
    6853              : 
    6854            0 :   *type_out = vectype;
    6855            0 :   return call;
    6856              : }
    6857              : 
    6858              : /* Return true if TYPE is a non-boolean integer type.  These are the types
    6859              :    that we want to consider for narrowing.  */
    6860              : 
    6861              : static bool
    6862     66690349 : vect_narrowable_type_p (tree type)
    6863              : {
    6864     66690349 :   return INTEGRAL_TYPE_P (type) && !VECT_SCALAR_BOOLEAN_TYPE_P (type);
    6865              : }
    6866              : 
    6867              : /* Return true if the operation given by CODE can be truncated to N bits
    6868              :    when only N bits of the output are needed.  This is only true if bit N+1
    6869              :    of the inputs has no effect on the low N bits of the result.  */
    6870              : 
    6871              : static bool
    6872     16545466 : vect_truncatable_operation_p (tree_code code)
    6873              : {
    6874     16545466 :   switch (code)
    6875              :     {
    6876              :     case NEGATE_EXPR:
    6877              :     case PLUS_EXPR:
    6878              :     case MINUS_EXPR:
    6879              :     case MULT_EXPR:
    6880              :     case BIT_NOT_EXPR:
    6881              :     case BIT_AND_EXPR:
    6882              :     case BIT_IOR_EXPR:
    6883              :     case BIT_XOR_EXPR:
    6884              :     case COND_EXPR:
    6885              :       return true;
    6886              : 
    6887      6487463 :     default:
    6888      6487463 :       return false;
    6889              :     }
    6890              : }
    6891              : 
    6892              : /* Record that STMT_INFO could be changed from operating on TYPE to
    6893              :    operating on a type with the precision and sign given by PRECISION
    6894              :    and SIGN respectively.  PRECISION is an arbitrary bit precision;
    6895              :    it might not be a whole number of bytes.  */
    6896              : 
    6897              : static void
    6898      2572995 : vect_set_operation_type (stmt_vec_info stmt_info, tree type,
    6899              :                          unsigned int precision, signop sign)
    6900              : {
    6901              :   /* Round the precision up to a whole number of bytes.  */
    6902      2572995 :   precision = vect_element_precision (precision);
    6903      2572995 :   if (precision < TYPE_PRECISION (type)
    6904      2572995 :       && (!stmt_info->operation_precision
    6905        40590 :           || stmt_info->operation_precision > precision))
    6906              :     {
    6907      1676622 :       stmt_info->operation_precision = precision;
    6908      1676622 :       stmt_info->operation_sign = sign;
    6909              :     }
    6910      2572995 : }
    6911              : 
    6912              : /* Record that STMT_INFO only requires MIN_INPUT_PRECISION from its
    6913              :    non-boolean inputs, all of which have type TYPE.  MIN_INPUT_PRECISION
    6914              :    is an arbitrary bit precision; it might not be a whole number of bytes.  */
    6915              : 
    6916              : static void
    6917     11864509 : vect_set_min_input_precision (stmt_vec_info stmt_info, tree type,
    6918              :                               unsigned int min_input_precision)
    6919              : {
    6920              :   /* This operation in isolation only requires the inputs to have
    6921              :      MIN_INPUT_PRECISION of precision,  However, that doesn't mean
    6922              :      that MIN_INPUT_PRECISION is a natural precision for the chain
    6923              :      as a whole.  E.g. consider something like:
    6924              : 
    6925              :          unsigned short *x, *y;
    6926              :          *y = ((*x & 0xf0) >> 4) | (*y << 4);
    6927              : 
    6928              :      The right shift can be done on unsigned chars, and only requires the
    6929              :      result of "*x & 0xf0" to be done on unsigned chars.  But taking that
    6930              :      approach would mean turning a natural chain of single-vector unsigned
    6931              :      short operations into one that truncates "*x" and then extends
    6932              :      "(*x & 0xf0) >> 4", with two vectors for each unsigned short
    6933              :      operation and one vector for each unsigned char operation.
    6934              :      This would be a significant pessimization.
    6935              : 
    6936              :      Instead only propagate the maximum of this precision and the precision
    6937              :      required by the users of the result.  This means that we don't pessimize
    6938              :      the case above but continue to optimize things like:
    6939              : 
    6940              :          unsigned char *y;
    6941              :          unsigned short *x;
    6942              :          *y = ((*x & 0xf0) >> 4) | (*y << 4);
    6943              : 
    6944              :      Here we would truncate two vectors of *x to a single vector of
    6945              :      unsigned chars and use single-vector unsigned char operations for
    6946              :      everything else, rather than doing two unsigned short copies of
    6947              :      "(*x & 0xf0) >> 4" and then truncating the result.  */
    6948     11864509 :   min_input_precision = MAX (min_input_precision,
    6949              :                              stmt_info->min_output_precision);
    6950              : 
    6951     11864509 :   if (min_input_precision < TYPE_PRECISION (type)
    6952     11864509 :       && (!stmt_info->min_input_precision
    6953        64325 :           || stmt_info->min_input_precision > min_input_precision))
    6954       604266 :     stmt_info->min_input_precision = min_input_precision;
    6955     11864509 : }
    6956              : 
    6957              : /* Subroutine of vect_determine_min_output_precision.  Return true if
    6958              :    we can calculate a reduced number of output bits for STMT_INFO,
    6959              :    whose result is LHS.  */
    6960              : 
    6961              : static bool
    6962     15217436 : vect_determine_min_output_precision_1 (vec_info *vinfo,
    6963              :                                        stmt_vec_info stmt_info, tree lhs)
    6964              : {
    6965              :   /* Take the maximum precision required by users of the result.  */
    6966     15217436 :   unsigned int precision = 0;
    6967     15217436 :   imm_use_iterator iter;
    6968     15217436 :   use_operand_p use;
    6969     16256014 :   FOR_EACH_IMM_USE_FAST (use, iter, lhs)
    6970              :     {
    6971     15966069 :       gimple *use_stmt = USE_STMT (use);
    6972     15966069 :       if (is_gimple_debug (use_stmt))
    6973       745234 :         continue;
    6974     15220835 :       stmt_vec_info use_stmt_info = vinfo->lookup_stmt (use_stmt);
    6975     15220835 :       if (!use_stmt_info || !use_stmt_info->min_input_precision)
    6976              :         return false;
    6977              :       /* The input precision recorded for COND_EXPRs applies only to the
    6978              :          "then" and "else" values.  */
    6979       293924 :       gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
    6980       263012 :       if (assign
    6981       263012 :           && gimple_assign_rhs_code (assign) == COND_EXPR
    6982          580 :           && use->use != gimple_assign_rhs2_ptr (assign)
    6983          580 :           && use->use != gimple_assign_rhs3_ptr (assign))
    6984              :         return false;
    6985      1040280 :       precision = MAX (precision, use_stmt_info->min_input_precision);
    6986     14927491 :     }
    6987              : 
    6988       289945 :   if (dump_enabled_p ())
    6989         5952 :     dump_printf_loc (MSG_NOTE, vect_location,
    6990              :                      "only the low %d bits of %T are significant\n",
    6991              :                      precision, lhs);
    6992       289945 :   stmt_info->min_output_precision = precision;
    6993       289945 :   return true;
    6994              : }
    6995              : 
    6996              : /* Calculate min_output_precision for STMT_INFO.  */
    6997              : 
    6998              : static void
    6999     39313161 : vect_determine_min_output_precision (vec_info *vinfo, stmt_vec_info stmt_info)
    7000              : {
    7001              :   /* We're only interested in statements with a narrowable result.  */
    7002     39313161 :   tree lhs = gimple_get_lhs (stmt_info->stmt);
    7003     39313161 :   if (!lhs
    7004     31056354 :       || TREE_CODE (lhs) != SSA_NAME
    7005     65587450 :       || !vect_narrowable_type_p (TREE_TYPE (lhs)))
    7006              :     return;
    7007              : 
    7008     15217436 :   if (!vect_determine_min_output_precision_1 (vinfo, stmt_info, lhs))
    7009     14927491 :     stmt_info->min_output_precision = TYPE_PRECISION (TREE_TYPE (lhs));
    7010              : }
    7011              : 
    7012              : /* Use range information to decide whether STMT (described by STMT_INFO)
    7013              :    could be done in a narrower type.  This is effectively a forward
    7014              :    propagation, since it uses context-independent information that applies
    7015              :    to all users of an SSA name.  */
    7016              : 
    7017              : static void
    7018     22455299 : vect_determine_precisions_from_range (stmt_vec_info stmt_info, gassign *stmt)
    7019              : {
    7020     22455299 :   tree lhs = gimple_assign_lhs (stmt);
    7021     22455299 :   if (!lhs || TREE_CODE (lhs) != SSA_NAME)
    7022     19998588 :     return;
    7023              : 
    7024     17960761 :   tree type = TREE_TYPE (lhs);
    7025     17960761 :   if (!vect_narrowable_type_p (type))
    7026              :     return;
    7027              : 
    7028              :   /* First see whether we have any useful range information for the result.  */
    7029     11751576 :   unsigned int precision = TYPE_PRECISION (type);
    7030     11751576 :   signop sign = TYPE_SIGN (type);
    7031     11751576 :   wide_int min_value, max_value;
    7032     11751576 :   if (!vect_get_range_info (lhs, &min_value, &max_value))
    7033              :     return;
    7034              : 
    7035      5714646 :   tree_code code = gimple_assign_rhs_code (stmt);
    7036      5714646 :   unsigned int nops = gimple_num_ops (stmt);
    7037              : 
    7038      5714646 :   if (!vect_truncatable_operation_p (code))
    7039              :     {
    7040              :       /* Handle operations that can be computed in type T if all inputs
    7041              :          and outputs can be represented in type T.  Also handle left and
    7042              :          right shifts, where (in addition) the maximum shift amount must
    7043              :          be less than the number of bits in T.  */
    7044      2109520 :       bool is_shift;
    7045      2109520 :       switch (code)
    7046              :         {
    7047              :         case LSHIFT_EXPR:
    7048              :         case RSHIFT_EXPR:
    7049              :           is_shift = true;
    7050              :           break;
    7051              : 
    7052       308310 :         case ABS_EXPR:
    7053       308310 :         case MIN_EXPR:
    7054       308310 :         case MAX_EXPR:
    7055       308310 :         case TRUNC_DIV_EXPR:
    7056       308310 :         case CEIL_DIV_EXPR:
    7057       308310 :         case FLOOR_DIV_EXPR:
    7058       308310 :         case ROUND_DIV_EXPR:
    7059       308310 :         case EXACT_DIV_EXPR:
    7060              :           /* Modulus is excluded because it is typically calculated by doing
    7061              :              a division, for which minimum signed / -1 isn't representable in
    7062              :              the original signed type.  We could take the division range into
    7063              :              account instead, if handling modulus ever becomes important.  */
    7064       308310 :           is_shift = false;
    7065       308310 :           break;
    7066              : 
    7067              :         default:
    7068              :           return;
    7069              :         }
    7070      1394957 :       for (unsigned int i = 1; i < nops; ++i)
    7071              :         {
    7072      1081895 :           tree op = gimple_op (stmt, i);
    7073      1081895 :           wide_int op_min_value, op_max_value;
    7074      1081895 :           if (TREE_CODE (op) == INTEGER_CST)
    7075              :             {
    7076       320356 :               unsigned int op_precision = TYPE_PRECISION (TREE_TYPE (op));
    7077       320356 :               op_min_value = op_max_value = wi::to_wide (op, op_precision);
    7078              :             }
    7079       761539 :           else if (TREE_CODE (op) == SSA_NAME)
    7080              :             {
    7081       761539 :               if (!vect_get_range_info (op, &op_min_value, &op_max_value))
    7082              :                 return;
    7083              :             }
    7084              :           else
    7085              :             return;
    7086              : 
    7087       708935 :           if (is_shift && i == 2)
    7088              :             {
    7089              :               /* There needs to be one more bit than the maximum shift amount.
    7090              : 
    7091              :                  If the maximum shift amount is already 1 less than PRECISION
    7092              :                  then we can't narrow the shift further.  Dealing with that
    7093              :                  case first ensures that we can safely use an unsigned range
    7094              :                  below.
    7095              : 
    7096              :                  op_min_value isn't relevant, since shifts by negative amounts
    7097              :                  are UB.  */
    7098       204672 :               if (wi::geu_p (op_max_value, precision - 1))
    7099              :                 return;
    7100       179591 :               unsigned int min_bits = op_max_value.to_uhwi () + 1;
    7101              : 
    7102              :               /* As explained below, we can convert a signed shift into an
    7103              :                  unsigned shift if the sign bit is always clear.  At this
    7104              :                  point we've already processed the ranges of the output and
    7105              :                  the first input.  */
    7106       179591 :               auto op_sign = sign;
    7107       179591 :               if (sign == SIGNED && !wi::neg_p (min_value))
    7108              :                 op_sign = UNSIGNED;
    7109       359182 :               op_min_value = wide_int::from (wi::min_value (min_bits, op_sign),
    7110       179591 :                                              precision, op_sign);
    7111       359182 :               op_max_value = wide_int::from (wi::max_value (min_bits, op_sign),
    7112       179591 :                                              precision, op_sign);
    7113              :             }
    7114       683854 :           min_value = wi::min (min_value, op_min_value, sign);
    7115       683854 :           max_value = wi::max (max_value, op_max_value, sign);
    7116      1081895 :         }
    7117              :     }
    7118              : 
    7119              :   /* Try to switch signed types for unsigned types if we can.
    7120              :      This is better for two reasons.  First, unsigned ops tend
    7121              :      to be cheaper than signed ops.  Second, it means that we can
    7122              :      handle things like:
    7123              : 
    7124              :         signed char c;
    7125              :         int res = (int) c & 0xff00; // range [0x0000, 0xff00]
    7126              : 
    7127              :      as:
    7128              : 
    7129              :         signed char c;
    7130              :         unsigned short res_1 = (unsigned short) c & 0xff00;
    7131              :         int res = (int) res_1;
    7132              : 
    7133              :      where the intermediate result res_1 has unsigned rather than
    7134              :      signed type.  */
    7135      3918188 :   if (sign == SIGNED && !wi::neg_p (min_value))
    7136              :     sign = UNSIGNED;
    7137              : 
    7138              :   /* See what precision is required for MIN_VALUE and MAX_VALUE.  */
    7139      3918188 :   unsigned int precision1 = wi::min_precision (min_value, sign);
    7140      3918188 :   unsigned int precision2 = wi::min_precision (max_value, sign);
    7141      3918188 :   unsigned int value_precision = MAX (precision1, precision2);
    7142      3918188 :   if (value_precision >= precision)
    7143              :     return;
    7144              : 
    7145      2456711 :   if (dump_enabled_p ())
    7146       113309 :     dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d"
    7147              :                      " without loss of precision: %G",
    7148              :                      sign == SIGNED ? "signed" : "unsigned",
    7149              :                      value_precision, (gimple *) stmt);
    7150              : 
    7151      2456711 :   vect_set_operation_type (stmt_info, type, value_precision, sign);
    7152      2456711 :   vect_set_min_input_precision (stmt_info, type, value_precision);
    7153     11751576 : }
    7154              : 
    7155              : /* Use information about the users of STMT's result to decide whether
    7156              :    STMT (described by STMT_INFO) could be done in a narrower type.
    7157              :    This is effectively a backward propagation.  */
    7158              : 
    7159              : static void
    7160     22455299 : vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt)
    7161              : {
    7162     22455299 :   tree_code code = gimple_assign_rhs_code (stmt);
    7163     22455299 :   unsigned int opno = (code == COND_EXPR ? 2 : 1);
    7164     22455299 :   tree type = TREE_TYPE (gimple_op (stmt, opno));
    7165     22455299 :   if (!vect_narrowable_type_p (type))
    7166     13047501 :     return;
    7167              : 
    7168     13821188 :   unsigned int precision = TYPE_PRECISION (type);
    7169     13821188 :   unsigned int operation_precision, min_input_precision;
    7170     13821188 :   switch (code)
    7171              :     {
    7172      2516842 :     CASE_CONVERT:
    7173              :       /* Only the bits that contribute to the output matter.  Don't change
    7174              :          the precision of the operation itself.  */
    7175      2516842 :       operation_precision = precision;
    7176      2516842 :       min_input_precision = stmt_info->min_output_precision;
    7177      2516842 :       break;
    7178              : 
    7179       473526 :     case LSHIFT_EXPR:
    7180       473526 :     case RSHIFT_EXPR:
    7181       473526 :       {
    7182       473526 :         tree shift = gimple_assign_rhs2 (stmt);
    7183       473526 :         unsigned int min_const_shift, max_const_shift;
    7184       473526 :         wide_int min_shift, max_shift;
    7185       473526 :         if (TREE_CODE (shift) == SSA_NAME
    7186       107264 :             && vect_get_range_info (shift, &min_shift, &max_shift)
    7187        82816 :             && wi::ge_p (min_shift, 0, TYPE_SIGN (TREE_TYPE (shift)))
    7188       553583 :             && wi::lt_p (max_shift, TYPE_PRECISION (type),
    7189        80057 :                          TYPE_SIGN (TREE_TYPE (shift))))
    7190              :           {
    7191        71925 :             min_const_shift = min_shift.to_uhwi ();
    7192        71925 :             max_const_shift = max_shift.to_uhwi ();
    7193              :           }
    7194       401601 :         else if (TREE_CODE (shift) == INTEGER_CST
    7195       767863 :                  && wi::ltu_p (wi::to_widest (shift), precision))
    7196       366154 :           min_const_shift = max_const_shift = TREE_INT_CST_LOW (shift);
    7197              :         else
    7198        35447 :           return;
    7199       438079 :         if (code == LSHIFT_EXPR)
    7200              :           {
    7201              :             /* Avoid creating an undefined shift.
    7202              : 
    7203              :                ??? We could instead use min_output_precision as-is and
    7204              :                optimize out-of-range shifts to zero.  However, only
    7205              :                degenerate testcases shift away all their useful input data,
    7206              :                and it isn't natural to drop input operations in the middle
    7207              :                of vectorization.  This sort of thing should really be
    7208              :                handled before vectorization.  */
    7209       109468 :             operation_precision = MAX (stmt_info->min_output_precision,
    7210              :                                        max_const_shift + 1);
    7211              :             /* We need CONST_SHIFT fewer bits of the input.  */
    7212       109468 :             min_input_precision = (MAX (operation_precision, max_const_shift)
    7213              :                                    - min_const_shift);
    7214              :           }
    7215              :         else
    7216              :           {
    7217              :             /* We need CONST_SHIFT extra bits to do the operation.  */
    7218       328611 :             operation_precision = (stmt_info->min_output_precision
    7219              :                                    + max_const_shift);
    7220       328611 :             min_input_precision = operation_precision;
    7221              :           }
    7222       438079 :         break;
    7223       473526 :       }
    7224              : 
    7225     10830820 :     default:
    7226     10830820 :       if (vect_truncatable_operation_p (code))
    7227              :         {
    7228              :           /* Input bit N has no effect on output bits N-1 and lower.  */
    7229      6452877 :           operation_precision = stmt_info->min_output_precision;
    7230      6452877 :           min_input_precision = operation_precision;
    7231      6452877 :           break;
    7232              :         }
    7233              :       return;
    7234              :     }
    7235              : 
    7236      9407798 :   if (operation_precision < precision)
    7237              :     {
    7238       116284 :       if (dump_enabled_p ())
    7239         2820 :         dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d"
    7240              :                          " without affecting users: %G",
    7241         2820 :                          TYPE_UNSIGNED (type) ? "unsigned" : "signed",
    7242              :                          operation_precision, (gimple *) stmt);
    7243       232568 :       vect_set_operation_type (stmt_info, type, operation_precision,
    7244       116284 :                                TYPE_SIGN (type));
    7245              :     }
    7246      9407798 :   vect_set_min_input_precision (stmt_info, type, min_input_precision);
    7247              : }
    7248              : 
    7249              : /* Return true if the statement described by STMT_INFO sets a boolean
    7250              :    SSA_NAME and if we know how to vectorize this kind of statement using
    7251              :    vector mask types.  */
    7252              : 
    7253              : static bool
    7254     40411044 : possible_vector_mask_operation_p (stmt_vec_info stmt_info)
    7255              : {
    7256     40411044 :   tree lhs = gimple_get_lhs (stmt_info->stmt);
    7257     40411044 :   tree_code code = ERROR_MARK;
    7258     40411044 :   gassign *assign = NULL;
    7259     40411044 :   gcond *cond = NULL;
    7260              : 
    7261     40411044 :   if ((assign = dyn_cast <gassign *> (stmt_info->stmt)))
    7262     23239674 :     code = gimple_assign_rhs_code (assign);
    7263     17171370 :   else if ((cond = dyn_cast <gcond *> (stmt_info->stmt)))
    7264              :     {
    7265      5474350 :       lhs = gimple_cond_lhs (cond);
    7266      5474350 :       code = gimple_cond_code (cond);
    7267              :     }
    7268              : 
    7269     40411044 :   if (!lhs
    7270     37533787 :       || TREE_CODE (lhs) != SSA_NAME
    7271     73124055 :       || !VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (lhs)))
    7272              :     return false;
    7273              : 
    7274      2258974 :   if (code != ERROR_MARK)
    7275              :     {
    7276      2003953 :       switch (code)
    7277              :         {
    7278              :         CASE_CONVERT:
    7279              :         case SSA_NAME:
    7280              :         case BIT_NOT_EXPR:
    7281              :         case BIT_IOR_EXPR:
    7282              :         case BIT_XOR_EXPR:
    7283              :         case BIT_AND_EXPR:
    7284              :           return true;
    7285              : 
    7286      1561334 :         default:
    7287      1561334 :           return TREE_CODE_CLASS (code) == tcc_comparison;
    7288              :         }
    7289              :     }
    7290       255021 :   else if (is_a <gphi *> (stmt_info->stmt))
    7291       143897 :     return true;
    7292              :   return false;
    7293              : }
    7294              : 
    7295              : /* If STMT_INFO sets a boolean SSA_NAME, see whether we should use
    7296              :    a vector mask type instead of a normal vector type.  Record the
    7297              :    result in STMT_INFO->mask_precision.  Returns true when the
    7298              :    precision changed.  */
    7299              : 
    7300              : static bool
    7301     40411044 : vect_determine_mask_precision (vec_info *vinfo, stmt_vec_info stmt_info)
    7302              : {
    7303     40411044 :   if (!possible_vector_mask_operation_p (stmt_info))
    7304              :     return false;
    7305              : 
    7306              :   /* If at least one boolean input uses a vector mask type,
    7307              :      pick the mask type with the narrowest elements.
    7308              : 
    7309              :      ??? This is the traditional behavior.  It should always produce
    7310              :      the smallest number of operations, but isn't necessarily the
    7311              :      optimal choice.  For example, if we have:
    7312              : 
    7313              :        a = b & c
    7314              : 
    7315              :      where:
    7316              : 
    7317              :        - the user of a wants it to have a mask type for 16-bit elements (M16)
    7318              :        - b also uses M16
    7319              :        - c uses a mask type for 8-bit elements (M8)
    7320              : 
    7321              :      then picking M8 gives:
    7322              : 
    7323              :        - 1 M16->M8 pack for b
    7324              :        - 1 M8 AND for a
    7325              :        - 2 M8->M16 unpacks for the user of a
    7326              : 
    7327              :      whereas picking M16 would have given:
    7328              : 
    7329              :        - 2 M8->M16 unpacks for c
    7330              :        - 2 M16 ANDs for a
    7331              : 
    7332              :      The number of operations are equal, but M16 would have given
    7333              :      a shorter dependency chain and allowed more ILP.  */
    7334      2096196 :   unsigned int precision = ~0U;
    7335      2096196 :   gimple *stmt = STMT_VINFO_STMT (stmt_info);
    7336              : 
    7337              :   /* If the statement compares two values that shouldn't use vector masks,
    7338              :      try comparing the values as normal scalars instead.  */
    7339      2096196 :   tree_code code = ERROR_MARK;
    7340      2096196 :   tree op0_type;
    7341      2096196 :   unsigned int nops = -1;
    7342      2096196 :   unsigned int ops_start = 0;
    7343              : 
    7344      2096196 :   if (gassign *assign = dyn_cast <gassign *> (stmt))
    7345              :     {
    7346      1382586 :       code = gimple_assign_rhs_code (assign);
    7347      1382586 :       op0_type = TREE_TYPE (gimple_assign_rhs1 (assign));
    7348      1382586 :       nops = gimple_num_ops (assign);
    7349      1382586 :       ops_start = 1;
    7350              :     }
    7351       713610 :   else if (gcond *cond = dyn_cast <gcond *> (stmt))
    7352              :     {
    7353       569713 :       code = gimple_cond_code (cond);
    7354       569713 :       op0_type = TREE_TYPE (gimple_cond_lhs (cond));
    7355       569713 :       nops = 2;
    7356       569713 :       ops_start = 0;
    7357              :     }
    7358              : 
    7359      1952299 :   if (code != ERROR_MARK)
    7360              :     {
    7361      5812338 :       for (unsigned int i = ops_start; i < nops; ++i)
    7362              :         {
    7363      3860039 :           tree rhs = gimple_op (stmt, i);
    7364      3860039 :           if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs)))
    7365      1890149 :             continue;
    7366              : 
    7367      1969890 :           stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
    7368      1969890 :           if (!def_stmt_info)
    7369              :             /* Don't let external or constant operands influence the choice.
    7370              :                We can convert them to whichever vector type we pick.  */
    7371       586350 :             continue;
    7372              : 
    7373      1383540 :           if (def_stmt_info->mask_precision)
    7374              :             {
    7375      1160511 :               if (precision > def_stmt_info->mask_precision)
    7376      3860039 :                 precision = def_stmt_info->mask_precision;
    7377              :             }
    7378              :         }
    7379              : 
    7380      1952299 :       if (precision == ~0U
    7381      1567165 :           && TREE_CODE_CLASS (code) == tcc_comparison)
    7382              :         {
    7383      1354524 :           scalar_mode mode;
    7384      1354524 :           tree vectype, mask_type;
    7385      1354524 :           if (is_a <scalar_mode> (TYPE_MODE (op0_type), &mode)
    7386              :               /* Do not allow this to set vinfo->vector_mode, this might
    7387              :                  disrupt the result for the next iteration.  */
    7388      1354524 :               && (vectype = get_related_vectype_for_scalar_type
    7389      1627407 :                                                 (vinfo->vector_mode, op0_type))
    7390      1186180 :               && (mask_type = truth_type_for (vectype))
    7391      1186180 :               && expand_vec_cmp_expr_p (vectype, mask_type, code))
    7392      1826594 :             precision = GET_MODE_BITSIZE (mode);
    7393              :         }
    7394              :     }
    7395              :   else
    7396              :     {
    7397       143897 :       gphi *phi = as_a <gphi *> (stmt_info->stmt);
    7398       740118 :       for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
    7399              :         {
    7400       452324 :           tree rhs = gimple_phi_arg_def (phi, i);
    7401              : 
    7402       452324 :           stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
    7403       452324 :           if (!def_stmt_info)
    7404              :             /* Don't let external or constant operands influence the choice.
    7405              :                We can convert them to whichever vector type we pick.  */
    7406       297363 :             continue;
    7407              : 
    7408       154961 :           if (def_stmt_info->mask_precision)
    7409              :             {
    7410       129863 :               if (precision > def_stmt_info->mask_precision)
    7411       452324 :                 precision = def_stmt_info->mask_precision;
    7412              :             }
    7413              :         }
    7414              :     }
    7415              : 
    7416      2096196 :   if (stmt_info->mask_precision != precision)
    7417              :     {
    7418      1966690 :       if (dump_enabled_p ())
    7419              :         {
    7420         8021 :           if (precision == ~0U)
    7421         1764 :             dump_printf_loc (MSG_NOTE, vect_location,
    7422              :                              "using normal nonmask vectors for %G",
    7423              :                              stmt_info->stmt);
    7424              :           else
    7425         6257 :             dump_printf_loc (MSG_NOTE, vect_location,
    7426              :                              "using boolean precision %d for %G",
    7427              :                              precision, stmt_info->stmt);
    7428              :         }
    7429              : 
    7430              :       /* ???  We'd like to assert stmt_info->mask_precision == 0
    7431              :          || stmt_info->mask_precision > precision, thus that we only
    7432              :          decrease mask precisions throughout iteration, but the
    7433              :          tcc_comparison handling above means for comparisons of bools
    7434              :          we start with 8 but might increase in case the bools get mask
    7435              :          precision on their own.  */
    7436      1966690 :       stmt_info->mask_precision = precision;
    7437      1966690 :       return true;
    7438              :     }
    7439              :   return false;
    7440              : }
    7441              : 
    7442              : /* Handle vect_determine_precisions for STMT_INFO, given that we
    7443              :    have already done so for the users of its result.  */
    7444              : 
    7445              : void
    7446     39313161 : vect_determine_stmt_precisions (vec_info *vinfo, stmt_vec_info stmt_info)
    7447              : {
    7448     39313161 :   vect_determine_min_output_precision (vinfo, stmt_info);
    7449     39313161 :   if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt))
    7450              :     {
    7451     22455299 :       vect_determine_precisions_from_range (stmt_info, stmt);
    7452     22455299 :       vect_determine_precisions_from_users (stmt_info, stmt);
    7453              :     }
    7454     39313161 : }
    7455              : 
    7456              : /* Walk backwards through the vectorizable region to determine the
    7457              :    values of these fields:
    7458              : 
    7459              :    - min_output_precision
    7460              :    - min_input_precision
    7461              :    - operation_precision
    7462              :    - operation_sign.  */
    7463              : 
    7464              : void
    7465      1114628 : vect_determine_precisions (vec_info *vinfo)
    7466              : {
    7467      1114628 :   basic_block *bbs = vinfo->bbs;
    7468      1114628 :   unsigned int nbbs = vinfo->nbbs;
    7469              : 
    7470      1134417 :   DUMP_VECT_SCOPE ("vect_determine_precisions");
    7471              : 
    7472              :   /* For mask precisions we have to iterate since otherwise we do not
    7473              :      get reduction PHI precision correct.  For now do this only for
    7474              :      loop vectorization.  */
    7475      1185700 :   bool changed;
    7476      1185700 :   do
    7477              :     {
    7478      1185700 :       changed = false;
    7479     13305782 :       for (unsigned int i = 0; i < nbbs; i++)
    7480              :         {
    7481     12120082 :           basic_block bb = bbs[i];
    7482     12120082 :           for (auto gsi = gsi_start_phis (bb);
    7483     19589864 :                !gsi_end_p (gsi); gsi_next (&gsi))
    7484              :             {
    7485      7469782 :               stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi.phi ());
    7486      7469782 :               if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
    7487      7273870 :                 changed |= vect_determine_mask_precision (vinfo, stmt_info);
    7488              :             }
    7489    130814294 :           for (auto gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    7490              :             {
    7491    106574130 :               stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (gsi));
    7492    106574130 :               if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
    7493     33137174 :                 changed |= vect_determine_mask_precision (vinfo, stmt_info);
    7494              :             }
    7495              :         }
    7496              :     }
    7497      2300328 :   while (changed && is_a <loop_vec_info> (vinfo));
    7498              : 
    7499     13070997 :   for (unsigned int i = 0; i < nbbs; i++)
    7500              :     {
    7501     11956369 :       basic_block bb = bbs[nbbs - i - 1];
    7502    138204527 :       for (auto gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
    7503              :         {
    7504    104919890 :           stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (gsi));
    7505    104919890 :           if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
    7506     32245000 :             vect_determine_stmt_precisions (vinfo, stmt_info);
    7507              :         }
    7508     19220442 :       for (auto gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    7509              :         {
    7510      7264073 :           stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi.phi ());
    7511      7264073 :           if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
    7512      7068161 :             vect_determine_stmt_precisions (vinfo, stmt_info);
    7513              :         }
    7514              :     }
    7515      1114628 : }
    7516              : 
    7517              : typedef gimple *(*vect_recog_func_ptr) (vec_info *, stmt_vec_info, tree *);
    7518              : 
    7519              : struct vect_recog_func
    7520              : {
    7521              :   vect_recog_func_ptr fn;
    7522              :   const char *name;
    7523              : };
    7524              : 
    7525              : /* Note that ordering matters - the first pattern matching on a stmt is
    7526              :    taken which means usually the more complex one needs to precede the
    7527              :    less comples onex (widen_sum only after dot_prod or sad for example).  */
    7528              : static vect_recog_func vect_vect_recog_func_ptrs[] = {
    7529              :   { vect_recog_bitfield_ref_pattern, "bitfield_ref" },
    7530              :   { vect_recog_bit_insert_pattern, "bit_insert" },
    7531              :   { vect_recog_abd_pattern, "abd" },
    7532              :   { vect_recog_over_widening_pattern, "over_widening" },
    7533              :   /* Must come after over_widening, which narrows the shift as much as
    7534              :      possible beforehand.  */
    7535              :   { vect_recog_average_pattern, "average" },
    7536              :   { vect_recog_cond_expr_convert_pattern, "cond_expr_convert" },
    7537              :   { vect_recog_mulhs_pattern, "mult_high" },
    7538              :   { vect_recog_cast_forwprop_pattern, "cast_forwprop" },
    7539              :   { vect_recog_widen_mult_pattern, "widen_mult" },
    7540              :   { vect_recog_dot_prod_pattern, "dot_prod" },
    7541              :   { vect_recog_sad_pattern, "sad" },
    7542              :   { vect_recog_widen_sum_pattern, "widen_sum" },
    7543              :   { vect_recog_pow_pattern, "pow" },
    7544              :   { vect_recog_popcount_clz_ctz_ffs_pattern, "popcount_clz_ctz_ffs" },
    7545              :   { vect_recog_ctz_ffs_pattern, "ctz_ffs" },
    7546              :   { vect_recog_widen_shift_pattern, "widen_shift" },
    7547              :   { vect_recog_rotate_pattern, "rotate" },
    7548              :   { vect_recog_vector_vector_shift_pattern, "vector_vector_shift" },
    7549              :   { vect_recog_divmod_pattern, "divmod" },
    7550              :   { vect_recog_mod_var_pattern, "modvar" },
    7551              :   { vect_recog_mult_pattern, "mult" },
    7552              :   { vect_recog_sat_add_pattern, "sat_add" },
    7553              :   { vect_recog_sat_sub_pattern, "sat_sub" },
    7554              :   { vect_recog_sat_trunc_pattern, "sat_trunc" },
    7555              :   { vect_recog_gcond_pattern, "gcond" },
    7556              :   { vect_recog_bool_pattern, "bool" },
    7557              :   /* This must come before mask conversion, and includes the parts
    7558              :      of mask conversion that are needed for gather and scatter
    7559              :      internal functions.  */
    7560              :   { vect_recog_gather_scatter_pattern, "gather_scatter" },
    7561              :   { vect_recog_cond_store_pattern, "cond_store" },
    7562              :   { vect_recog_mask_conversion_pattern, "mask_conversion" },
    7563              :   { vect_recog_widen_plus_pattern, "widen_plus" },
    7564              :   { vect_recog_widen_minus_pattern, "widen_minus" },
    7565              :   { vect_recog_widen_abd_pattern, "widen_abd" },
    7566              :   /* These must come after the double widening ones.  */
    7567              : };
    7568              : 
    7569              : /* Mark statements that are involved in a pattern.  */
    7570              : 
    7571              : void
    7572      1059976 : vect_mark_pattern_stmts (vec_info *vinfo,
    7573              :                          stmt_vec_info orig_stmt_info, gimple *pattern_stmt,
    7574              :                          tree pattern_vectype)
    7575              : {
    7576      1059976 :   stmt_vec_info orig_stmt_info_saved = orig_stmt_info;
    7577      1059976 :   gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
    7578              : 
    7579      1059976 :   gimple *orig_pattern_stmt = NULL;
    7580      1059976 :   if (is_pattern_stmt_p (orig_stmt_info))
    7581              :     {
    7582              :       /* We're replacing a statement in an existing pattern definition
    7583              :          sequence.  */
    7584        11858 :       orig_pattern_stmt = orig_stmt_info->stmt;
    7585        11858 :       if (dump_enabled_p ())
    7586          987 :         dump_printf_loc (MSG_NOTE, vect_location,
    7587              :                          "replacing earlier pattern %G", orig_pattern_stmt);
    7588              : 
    7589              :       /* To keep the book-keeping simple, just swap the lhs of the
    7590              :          old and new statements, so that the old one has a valid but
    7591              :          unused lhs.  */
    7592        11858 :       tree old_lhs = gimple_get_lhs (orig_pattern_stmt);
    7593        11858 :       gimple_set_lhs (orig_pattern_stmt, gimple_get_lhs (pattern_stmt));
    7594        11858 :       gimple_set_lhs (pattern_stmt, old_lhs);
    7595              : 
    7596        11858 :       if (dump_enabled_p ())
    7597          987 :         dump_printf_loc (MSG_NOTE, vect_location, "with %G", pattern_stmt);
    7598              : 
    7599              :       /* Switch to the statement that ORIG replaces.  */
    7600        11858 :       orig_stmt_info = STMT_VINFO_RELATED_STMT (orig_stmt_info);
    7601              : 
    7602              :       /* We shouldn't be replacing the main pattern statement.  */
    7603        11858 :       gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info)->stmt
    7604              :                   != orig_pattern_stmt);
    7605              :     }
    7606              : 
    7607      1059976 :   if (def_seq)
    7608      2327181 :     for (gimple_stmt_iterator si = gsi_start (def_seq);
    7609      2327181 :          !gsi_end_p (si); gsi_next (&si))
    7610              :       {
    7611      1398694 :         if (dump_enabled_p ())
    7612        27153 :           dump_printf_loc (MSG_NOTE, vect_location,
    7613              :                            "extra pattern stmt: %G", gsi_stmt (si));
    7614      1398694 :         stmt_vec_info pattern_stmt_info
    7615      1398694 :           = vect_init_pattern_stmt (vinfo, gsi_stmt (si),
    7616              :                                     orig_stmt_info, pattern_vectype);
    7617              :         /* Stmts in the def sequence are not vectorizable cycle or
    7618              :            induction defs, instead they should all be vect_internal_def
    7619              :            feeding the main pattern stmt which retains this def type.  */
    7620      1398694 :         STMT_VINFO_DEF_TYPE (pattern_stmt_info) = vect_internal_def;
    7621              :       }
    7622              : 
    7623      1059976 :   if (orig_pattern_stmt)
    7624              :     {
    7625        11858 :       vect_init_pattern_stmt (vinfo, pattern_stmt,
    7626              :                               orig_stmt_info, pattern_vectype);
    7627              : 
    7628              :       /* Insert all the new pattern statements before the original one.  */
    7629        11858 :       gimple_seq *orig_def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
    7630        11858 :       gimple_stmt_iterator gsi = gsi_for_stmt (orig_pattern_stmt,
    7631              :                                                orig_def_seq);
    7632        11858 :       gsi_insert_seq_before_without_update (&gsi, def_seq, GSI_SAME_STMT);
    7633        11858 :       gsi_insert_before_without_update (&gsi, pattern_stmt, GSI_SAME_STMT);
    7634              : 
    7635              :       /* Remove the pattern statement that this new pattern replaces.  */
    7636        11858 :       gsi_remove (&gsi, false);
    7637              :     }
    7638              :   else
    7639      1048118 :     vect_set_pattern_stmt (vinfo,
    7640              :                            pattern_stmt, orig_stmt_info, pattern_vectype);
    7641              : 
    7642              :   /* For any conditionals mark them as vect_condition_def.  */
    7643      1059976 :   if (is_a <gcond *> (pattern_stmt))
    7644       380631 :     STMT_VINFO_DEF_TYPE (STMT_VINFO_RELATED_STMT (orig_stmt_info)) = vect_condition_def;
    7645              : 
    7646              :   /* Transfer reduction path info to the pattern.  */
    7647      1059976 :   if (STMT_VINFO_REDUC_IDX (orig_stmt_info_saved) != -1)
    7648              :     {
    7649        16130 :       gimple_match_op op;
    7650        16130 :       if (!gimple_extract_op (orig_stmt_info_saved->stmt, &op))
    7651            0 :         gcc_unreachable ();
    7652        16130 :       tree lookfor = op.ops[STMT_VINFO_REDUC_IDX (orig_stmt_info)];
    7653              :       /* Search the pattern def sequence and the main pattern stmt.  Note
    7654              :          we may have inserted all into a containing pattern def sequence
    7655              :          so the following is a bit awkward.  */
    7656        16130 :       gimple_stmt_iterator si;
    7657        16130 :       gimple *s;
    7658        16130 :       if (def_seq)
    7659              :         {
    7660        14923 :           si = gsi_start (def_seq);
    7661        14923 :           s = gsi_stmt (si);
    7662        14923 :           gsi_next (&si);
    7663              :         }
    7664              :       else
    7665              :         {
    7666              :           si = gsi_none ();
    7667        16130 :           s = pattern_stmt;
    7668              :         }
    7669        33869 :       do
    7670              :         {
    7671        33869 :           bool found = false;
    7672        33869 :           if (gimple_extract_op (s, &op))
    7673              :             {
    7674        82530 :               for (unsigned i = 0; i < op.num_ops; ++i)
    7675        64785 :                 if (op.ops[i] == lookfor)
    7676              :                   {
    7677        16124 :                     STMT_VINFO_REDUC_IDX (vinfo->lookup_stmt (s)) = i;
    7678        16124 :                     lookfor = gimple_get_lhs (s);
    7679        16124 :                     found = true;
    7680        16124 :                     break;
    7681              :                   }
    7682              :               /* Try harder to find a mid-entry into an earlier pattern
    7683              :                  sequence.  Likewise an entry to a stmt skipping a conversion
    7684              :                  on an input.  This means that the initial 'lookfor' was
    7685              :                  bogus.  */
    7686        16124 :               if (!found)
    7687              :                 {
    7688        38494 :                   for (unsigned i = 0; i < op.num_ops; ++i)
    7689        20755 :                     if (TREE_CODE (op.ops[i]) == SSA_NAME)
    7690        17745 :                       if (auto def = vinfo->lookup_def (op.ops[i]))
    7691        17552 :                         if (vect_is_reduction (def)
    7692        17552 :                             || (is_a <gphi *> (def->stmt)
    7693            6 :                                 && STMT_VINFO_REDUC_DEF (def) != NULL))
    7694              :                           {
    7695            6 :                             STMT_VINFO_REDUC_IDX (vinfo->lookup_stmt (s)) = i;
    7696            6 :                             lookfor = gimple_get_lhs (s);
    7697            6 :                             found = true;
    7698            6 :                             break;
    7699              :                           }
    7700              :                 }
    7701              :             }
    7702        33869 :           if (s == pattern_stmt)
    7703              :             {
    7704        16130 :               if (!found && dump_enabled_p ())
    7705            0 :                 dump_printf_loc (MSG_NOTE, vect_location,
    7706              :                                  "failed to update reduction index.\n");
    7707        16130 :               break;
    7708              :             }
    7709        17739 :           if (gsi_end_p (si))
    7710              :             s = pattern_stmt;
    7711              :           else
    7712              :             {
    7713         2816 :               s = gsi_stmt (si);
    7714         2816 :               if (s == pattern_stmt)
    7715              :                 /* Found the end inside a bigger pattern def seq.  */
    7716              :                 si = gsi_none ();
    7717              :               else
    7718         2816 :                 gsi_next (&si);
    7719              :             }
    7720              :         } while (1);
    7721              :     }
    7722      1059976 : }
    7723              : 
    7724              : /* Function vect_pattern_recog_1
    7725              : 
    7726              :    Input:
    7727              :    PATTERN_RECOG_FUNC: A pointer to a function that detects a certain
    7728              :         computation pattern.
    7729              :    STMT_INFO: A stmt from which the pattern search should start.
    7730              : 
    7731              :    If PATTERN_RECOG_FUNC successfully detected the pattern, it creates
    7732              :    a sequence of statements that has the same functionality and can be
    7733              :    used to replace STMT_INFO.  It returns the last statement in the sequence
    7734              :    and adds any earlier statements to STMT_INFO's STMT_VINFO_PATTERN_DEF_SEQ.
    7735              :    PATTERN_RECOG_FUNC also sets *TYPE_OUT to the vector type of the final
    7736              :    statement, having first checked that the target supports the new operation
    7737              :    in that type.
    7738              : 
    7739              :    This function also does some bookkeeping, as explained in the documentation
    7740              :    for vect_recog_pattern.  */
    7741              : 
    7742              : static void
    7743   1050632847 : vect_pattern_recog_1 (vec_info *vinfo,
    7744              :                       const vect_recog_func &recog_func, stmt_vec_info stmt_info)
    7745              : {
    7746   1050632847 :   gimple *pattern_stmt;
    7747   1050632847 :   tree pattern_vectype;
    7748              : 
    7749              :   /* If this statement has already been replaced with pattern statements,
    7750              :      leave the original statement alone, since the first match wins.
    7751              :      Instead try to match against the definition statements that feed
    7752              :      the main pattern statement.  */
    7753   1050632847 :   if (STMT_VINFO_IN_PATTERN_P (stmt_info))
    7754              :     {
    7755     13340337 :       gimple_stmt_iterator gsi;
    7756     13340337 :       for (gsi = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
    7757     32133184 :            !gsi_end_p (gsi); gsi_next (&gsi))
    7758     18792847 :         vect_pattern_recog_1 (vinfo, recog_func,
    7759              :                               vinfo->lookup_stmt (gsi_stmt (gsi)));
    7760              :       return;
    7761              :     }
    7762              : 
    7763   1037292510 :   gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
    7764   1037292510 :   pattern_stmt = recog_func.fn (vinfo, stmt_info, &pattern_vectype);
    7765   1037292510 :   if (!pattern_stmt)
    7766              :     {
    7767              :       /* Clear any half-formed pattern definition sequence.  */
    7768   1036232534 :       STMT_VINFO_PATTERN_DEF_SEQ (stmt_info) = NULL;
    7769   1036232534 :       return;
    7770              :     }
    7771              : 
    7772              :   /* Found a vectorizable pattern.  */
    7773      1059976 :   if (dump_enabled_p ())
    7774        20057 :     dump_printf_loc (MSG_NOTE, vect_location,
    7775              :                      "%s pattern recognized: %G",
    7776        20057 :                      recog_func.name, pattern_stmt);
    7777              : 
    7778              :   /* Mark the stmts that are involved in the pattern. */
    7779      1059976 :   vect_mark_pattern_stmts (vinfo, stmt_info, pattern_stmt, pattern_vectype);
    7780              : }
    7781              : 
    7782              : 
    7783              : /* Function vect_pattern_recog
    7784              : 
    7785              :    Input:
    7786              :    LOOP_VINFO - a struct_loop_info of a loop in which we want to look for
    7787              :         computation idioms.
    7788              : 
    7789              :    Output - for each computation idiom that is detected we create a new stmt
    7790              :         that provides the same functionality and that can be vectorized.  We
    7791              :         also record some information in the struct_stmt_info of the relevant
    7792              :         stmts, as explained below:
    7793              : 
    7794              :    At the entry to this function we have the following stmts, with the
    7795              :    following initial value in the STMT_VINFO fields:
    7796              : 
    7797              :          stmt                     in_pattern_p  related_stmt    vec_stmt
    7798              :          S1: a_i = ....                 -       -               -
    7799              :          S2: a_2 = ..use(a_i)..         -       -               -
    7800              :          S3: a_1 = ..use(a_2)..         -       -               -
    7801              :          S4: a_0 = ..use(a_1)..         -       -               -
    7802              :          S5: ... = ..use(a_0)..         -       -               -
    7803              : 
    7804              :    Say the sequence {S1,S2,S3,S4} was detected as a pattern that can be
    7805              :    represented by a single stmt.  We then:
    7806              :    - create a new stmt S6 equivalent to the pattern (the stmt is not
    7807              :      inserted into the code)
    7808              :    - fill in the STMT_VINFO fields as follows:
    7809              : 
    7810              :                                   in_pattern_p  related_stmt    vec_stmt
    7811              :          S1: a_i = ....                 -       -               -
    7812              :          S2: a_2 = ..use(a_i)..         -       -               -
    7813              :          S3: a_1 = ..use(a_2)..         -       -               -
    7814              :          S4: a_0 = ..use(a_1)..         true    S6              -
    7815              :           '---> S6: a_new = ....        -       S4              -
    7816              :          S5: ... = ..use(a_0)..         -       -               -
    7817              : 
    7818              :    (the last stmt in the pattern (S4) and the new pattern stmt (S6) point
    7819              :    to each other through the RELATED_STMT field).
    7820              : 
    7821              :    S6 will be marked as relevant in vect_mark_stmts_to_be_vectorized instead
    7822              :    of S4 because it will replace all its uses.  Stmts {S1,S2,S3} will
    7823              :    remain irrelevant unless used by stmts other than S4.
    7824              : 
    7825              :    If vectorization succeeds, vect_transform_stmt will skip over {S1,S2,S3}
    7826              :    (because they are marked as irrelevant).  It will vectorize S6, and record
    7827              :    a pointer to the new vector stmt VS6 from S6 (as usual).
    7828              :    S4 will be skipped, and S5 will be vectorized as usual:
    7829              : 
    7830              :                                   in_pattern_p  related_stmt    vec_stmt
    7831              :          S1: a_i = ....                 -       -               -
    7832              :          S2: a_2 = ..use(a_i)..         -       -               -
    7833              :          S3: a_1 = ..use(a_2)..         -       -               -
    7834              :        > VS6: va_new = ....             -       -               -
    7835              :          S4: a_0 = ..use(a_1)..         true    S6              VS6
    7836              :           '---> S6: a_new = ....        -       S4              VS6
    7837              :        > VS5: ... = ..vuse(va_new)..    -       -               -
    7838              :          S5: ... = ..use(a_0)..         -       -               -
    7839              : 
    7840              :    DCE could then get rid of {S1,S2,S3,S4,S5} (if their defs are not used
    7841              :    elsewhere), and we'll end up with:
    7842              : 
    7843              :         VS6: va_new = ....
    7844              :         VS5: ... = ..vuse(va_new)..
    7845              : 
    7846              :    In case of more than one pattern statements, e.g., widen-mult with
    7847              :    intermediate type:
    7848              : 
    7849              :      S1  a_t = ;
    7850              :      S2  a_T = (TYPE) a_t;
    7851              :            '--> S3: a_it = (interm_type) a_t;
    7852              :      S4  prod_T = a_T * CONST;
    7853              :            '--> S5: prod_T' = a_it w* CONST;
    7854              : 
    7855              :    there may be other users of a_T outside the pattern.  In that case S2 will
    7856              :    be marked as relevant (as well as S3), and both S2 and S3 will be analyzed
    7857              :    and vectorized.  The vector stmt VS2 will be recorded in S2, and VS3 will
    7858              :    be recorded in S3.  */
    7859              : 
    7860              : void
    7861      1114628 : vect_pattern_recog (vec_info *vinfo)
    7862              : {
    7863      1114628 :   basic_block *bbs = vinfo->bbs;
    7864      1114628 :   unsigned int nbbs = vinfo->nbbs;
    7865              : 
    7866      1114628 :   vect_determine_precisions (vinfo);
    7867              : 
    7868      1114628 :   DUMP_VECT_SCOPE ("vect_pattern_recog");
    7869              : 
    7870              :   /* Scan through the stmts in the region, applying the pattern recognition
    7871              :      functions starting at each stmt visited.  */
    7872     13070997 :   for (unsigned i = 0; i < nbbs; i++)
    7873              :     {
    7874     11956369 :       basic_block bb = bbs[i];
    7875              : 
    7876    128832628 :       for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
    7877              :         {
    7878    104919890 :           stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
    7879              : 
    7880    104919890 :           if (!stmt_info || !STMT_VINFO_VECTORIZABLE (stmt_info))
    7881     72674890 :             continue;
    7882              : 
    7883              :           /* Scan over all generic vect_recog_xxx_pattern functions.  */
    7884   1064085000 :           for (const auto &func_ptr : vect_vect_recog_func_ptrs)
    7885   1031840000 :             vect_pattern_recog_1 (vinfo, func_ptr,
    7886              :                                   stmt_info);
    7887              :         }
    7888              :     }
    7889              : 
    7890              :   /* After this no more add_stmt calls are allowed.  */
    7891      1114628 :   vinfo->stmt_vec_info_ro = true;
    7892      1114628 : }
    7893              : 
    7894              : /* Build a GIMPLE_ASSIGN or GIMPLE_CALL with the tree_code,
    7895              :    or internal_fn contained in ch, respectively.  */
    7896              : gimple *
    7897       169084 : vect_gimple_build (tree lhs, code_helper ch, tree op0, tree op1)
    7898              : {
    7899       169084 :   gcc_assert (op0 != NULL_TREE);
    7900       169084 :   if (ch.is_tree_code ())
    7901       169084 :     return gimple_build_assign (lhs, (tree_code) ch, op0, op1);
    7902              : 
    7903            0 :   gcc_assert (ch.is_internal_fn ());
    7904            0 :   gimple* stmt = gimple_build_call_internal (as_internal_fn ((combined_fn) ch),
    7905              :                                              op1 == NULL_TREE ? 1 : 2,
    7906              :                                              op0, op1);
    7907            0 :   gimple_call_set_lhs (stmt, lhs);
    7908            0 :   return stmt;
    7909              : }
        

Generated by: LCOV version 2.4-beta

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