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

Generated by: LCOV version 2.5.0-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.