LCOV - code coverage report
Current view: top level - gcc - tree-vect-generic.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.8 % 1209 1086
Test Date: 2024-11-30 13:30:02 Functions: 94.9 % 39 37
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Lower vector operations to scalar operations.
       2                 :             :    Copyright (C) 2004-2024 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it
       7                 :             : under the terms of the GNU General Public License as published by the
       8                 :             : Free Software Foundation; either version 3, or (at your option) any
       9                 :             : later version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT
      12                 :             : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : #include "config.h"
      21                 :             : #include "system.h"
      22                 :             : #include "coretypes.h"
      23                 :             : #include "backend.h"
      24                 :             : #include "rtl.h"
      25                 :             : #include "tree.h"
      26                 :             : #include "gimple.h"
      27                 :             : #include "tree-pass.h"
      28                 :             : #include "ssa.h"
      29                 :             : #include "expmed.h"
      30                 :             : #include "optabs-tree.h"
      31                 :             : #include "diagnostic.h"
      32                 :             : #include "fold-const.h"
      33                 :             : #include "stor-layout.h"
      34                 :             : #include "langhooks.h"
      35                 :             : #include "tree-eh.h"
      36                 :             : #include "gimple-iterator.h"
      37                 :             : #include "gimplify-me.h"
      38                 :             : #include "gimplify.h"
      39                 :             : #include "tree-cfg.h"
      40                 :             : #include "tree-vector-builder.h"
      41                 :             : #include "vec-perm-indices.h"
      42                 :             : #include "insn-config.h"
      43                 :             : #include "gimple-fold.h"
      44                 :             : #include "gimple-match.h"
      45                 :             : #include "recog.h"            /* FIXME: for insn_data */
      46                 :             : #include "optabs-libfuncs.h"
      47                 :             : #include "cfgloop.h"
      48                 :             : #include "tree-vectorizer.h"
      49                 :             : 
      50                 :             : 
      51                 :             : /* Build a ternary operation and gimplify it.  Emit code before GSI.
      52                 :             :    Return the gimple_val holding the result.  */
      53                 :             : 
      54                 :             : static tree
      55                 :       11023 : gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
      56                 :             :                  tree type, tree a, tree b, tree c)
      57                 :             : {
      58                 :       11023 :   location_t loc = gimple_location (gsi_stmt (*gsi));
      59                 :       11023 :   return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a, b, c);
      60                 :             : }
      61                 :             : 
      62                 :             : /* Build a binary operation and gimplify it.  Emit code before GSI.
      63                 :             :    Return the gimple_val holding the result.  */
      64                 :             : 
      65                 :             : static tree
      66                 :       16421 : gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
      67                 :             :                  tree type, tree a, tree b)
      68                 :             : {
      69                 :       16421 :   location_t loc = gimple_location (gsi_stmt (*gsi));
      70                 :       16421 :   return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a, b);
      71                 :             : }
      72                 :             : 
      73                 :             : /* Build a unary operation and gimplify it.  Emit code before GSI.
      74                 :             :    Return the gimple_val holding the result.  */
      75                 :             : 
      76                 :             : static tree
      77                 :       18660 : gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
      78                 :             :                  tree a)
      79                 :             : {
      80                 :       18660 :   location_t loc = gimple_location (gsi_stmt (*gsi));
      81                 :       18660 :   return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a);
      82                 :             : }
      83                 :             : 
      84                 :             : 
      85                 :             : /* Return the number of elements in a vector type TYPE that we have
      86                 :             :    already decided needs to be expanded piecewise.  We don't support
      87                 :             :    this kind of expansion for variable-length vectors, since we should
      88                 :             :    always check for target support before introducing uses of those.  */
      89                 :             : static unsigned int
      90                 :      108802 : nunits_for_known_piecewise_op (const_tree type)
      91                 :             : {
      92                 :      108802 :   return TYPE_VECTOR_SUBPARTS (type).to_constant ();
      93                 :             : }
      94                 :             : 
      95                 :             : /* Return true if TYPE1 has more elements than TYPE2, where either
      96                 :             :    type may be a vector or a scalar.  */
      97                 :             : 
      98                 :             : static inline bool
      99                 :         292 : subparts_gt (tree type1, tree type2)
     100                 :             : {
     101                 :         292 :   poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
     102                 :         292 :   poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
     103                 :         292 :   return known_gt (n1, n2);
     104                 :             : }
     105                 :             : 
     106                 :             : static GTY(()) tree vector_inner_type;
     107                 :             : static GTY(()) tree vector_last_type;
     108                 :             : static GTY(()) int vector_last_nunits;
     109                 :             : 
     110                 :             : /* Return a suitable vector types made of SUBPARTS units each of mode
     111                 :             :    "word_mode" (the global variable).  */
     112                 :             : static tree
     113                 :          57 : build_word_mode_vector_type (int nunits)
     114                 :             : {
     115                 :          57 :   if (!vector_inner_type)
     116                 :          42 :     vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
     117                 :          15 :   else if (vector_last_nunits == nunits)
     118                 :             :     {
     119                 :          13 :       gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
     120                 :             :       return vector_last_type;
     121                 :             :     }
     122                 :             : 
     123                 :          44 :   vector_last_nunits = nunits;
     124                 :          44 :   vector_last_type = build_vector_type (vector_inner_type, nunits);
     125                 :          44 :   return vector_last_type;
     126                 :             : }
     127                 :             : 
     128                 :             : typedef tree (*elem_op_func) (gimple_stmt_iterator *,
     129                 :             :                               tree, tree, tree, tree, tree, enum tree_code,
     130                 :             :                               tree);
     131                 :             : 
     132                 :             : /* Extract the vector element of type TYPE at BITPOS with BITSIZE from T
     133                 :             :    and return it.  */
     134                 :             : 
     135                 :             : tree
     136                 :       63586 : tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
     137                 :             :                   tree t, tree bitsize, tree bitpos)
     138                 :             : {
     139                 :             :   /* We're using the resimplify API and maybe_push_res_to_seq to
     140                 :             :      simplify the BIT_FIELD_REF but restrict the simplification to
     141                 :             :      a single stmt while at the same time following SSA edges for
     142                 :             :      simplification with already emitted CTORs.  */
     143                 :       63586 :   gimple_match_op opr;
     144                 :       63586 :   opr.set_op (BIT_FIELD_REF, type, t, bitsize, bitpos);
     145                 :       63586 :   opr.resimplify (NULL, follow_all_ssa_edges);
     146                 :       63586 :   gimple_seq stmts = NULL;
     147                 :       63586 :   tree res = maybe_push_res_to_seq (&opr, &stmts);
     148                 :       63586 :   if (!res)
     149                 :             :     {
     150                 :             :       /* This can happen if SSA_NAME_OCCURS_IN_ABNORMAL_PHI are
     151                 :             :          used.  Build BIT_FIELD_REF manually otherwise.  */
     152                 :          64 :       t = build3 (BIT_FIELD_REF, type, t, bitsize, bitpos);
     153                 :          64 :       res = make_ssa_name (type);
     154                 :          64 :       gimple *g = gimple_build_assign (res, t);
     155                 :          64 :       gsi_insert_before (gsi, g, GSI_SAME_STMT);
     156                 :          64 :       return res;
     157                 :             :     }
     158                 :       63522 :   gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
     159                 :       63522 :   return res;
     160                 :             : }
     161                 :             : 
     162                 :             : static tree
     163                 :         344 : do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
     164                 :             :          tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
     165                 :             :          enum tree_code code, tree type ATTRIBUTE_UNUSED)
     166                 :             : {
     167                 :         344 :   tree rhs_type = inner_type;
     168                 :             : 
     169                 :             :   /* For ABSU_EXPR, use the signed type for the rhs if the rhs was signed. */
     170                 :         344 :   if (code == ABSU_EXPR
     171                 :           9 :       && ANY_INTEGRAL_TYPE_P (TREE_TYPE (a))
     172                 :         353 :       && !TYPE_UNSIGNED (TREE_TYPE (a)))
     173                 :           9 :     rhs_type = signed_type_for (rhs_type);
     174                 :             : 
     175                 :         344 :   a = tree_vec_extract (gsi, rhs_type, a, bitsize, bitpos);
     176                 :         344 :   return gimplify_build1 (gsi, code, inner_type, a);
     177                 :             : }
     178                 :             : 
     179                 :             : static tree
     180                 :        8969 : do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
     181                 :             :           tree bitpos, tree bitsize, enum tree_code code,
     182                 :             :           tree type ATTRIBUTE_UNUSED)
     183                 :             : {
     184                 :        8969 :   if (VECTOR_TYPE_P (TREE_TYPE (a)))
     185                 :        8969 :     a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
     186                 :        8969 :   if (VECTOR_TYPE_P (TREE_TYPE (b)))
     187                 :        8659 :     b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
     188                 :        8969 :   return gimplify_build2 (gsi, code, inner_type, a, b);
     189                 :             : }
     190                 :             : 
     191                 :             : /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
     192                 :             : 
     193                 :             :    INNER_TYPE is the type of A and B elements
     194                 :             : 
     195                 :             :    returned expression is of signed integer type with the
     196                 :             :    size equal to the size of INNER_TYPE.  */
     197                 :             : static tree
     198                 :        5514 : do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
     199                 :             :             tree bitpos, tree bitsize, enum tree_code code, tree type)
     200                 :             : {
     201                 :        5514 :   tree stype = TREE_TYPE (type);
     202                 :        5514 :   tree cst_false = build_zero_cst (stype);
     203                 :        5514 :   tree cst_true = build_all_ones_cst (stype);
     204                 :        5514 :   tree cmp;
     205                 :             : 
     206                 :        5514 :   a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
     207                 :        5514 :   b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
     208                 :             : 
     209                 :        5514 :   cmp = build2 (code, boolean_type_node, a, b);
     210                 :        5514 :   return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
     211                 :             : }
     212                 :             : 
     213                 :             : /* Expand vector addition to scalars.  This does bit twiddling
     214                 :             :    in order to increase parallelism:
     215                 :             : 
     216                 :             :    a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
     217                 :             :            (a ^ b) & 0x80808080
     218                 :             : 
     219                 :             :    a - b =  (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
     220                 :             :             (a ^ ~b) & 0x80808080
     221                 :             : 
     222                 :             :    -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
     223                 :             : 
     224                 :             :    This optimization should be done only if 4 vector items or more
     225                 :             :    fit into a word.  */
     226                 :             : static tree
     227                 :           6 : do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
     228                 :             :                tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
     229                 :             :                enum tree_code code, tree type ATTRIBUTE_UNUSED)
     230                 :             : {
     231                 :           6 :   unsigned int width = vector_element_bits (TREE_TYPE (a));
     232                 :           6 :   tree inner_type = TREE_TYPE (TREE_TYPE (a));
     233                 :           6 :   unsigned HOST_WIDE_INT max;
     234                 :           6 :   tree low_bits, high_bits, a_low, b_low, result_low, signs;
     235                 :             : 
     236                 :           6 :   max = GET_MODE_MASK (TYPE_MODE (inner_type));
     237                 :           6 :   low_bits = build_replicated_int_cst (word_type, width, max >> 1);
     238                 :           6 :   high_bits = build_replicated_int_cst (word_type, width, max & ~(max >> 1));
     239                 :             : 
     240                 :           6 :   a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
     241                 :           6 :   b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
     242                 :             : 
     243                 :           6 :   signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
     244                 :           6 :   b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
     245                 :           6 :   if (code == PLUS_EXPR)
     246                 :           2 :     a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
     247                 :             :   else
     248                 :             :     {
     249                 :           4 :       a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
     250                 :           4 :       signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
     251                 :             :     }
     252                 :             : 
     253                 :           6 :   signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
     254                 :           6 :   result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
     255                 :           6 :   return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
     256                 :             : }
     257                 :             : 
     258                 :             : static tree
     259                 :           0 : do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
     260                 :             :            tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
     261                 :             :            tree bitsize ATTRIBUTE_UNUSED,
     262                 :             :            enum tree_code code ATTRIBUTE_UNUSED,
     263                 :             :            tree type ATTRIBUTE_UNUSED)
     264                 :             : {
     265                 :           0 :   unsigned int width = vector_element_bits (TREE_TYPE (b));
     266                 :           0 :   tree inner_type = TREE_TYPE (TREE_TYPE (b));
     267                 :           0 :   HOST_WIDE_INT max;
     268                 :           0 :   tree low_bits, high_bits, b_low, result_low, signs;
     269                 :             : 
     270                 :           0 :   max = GET_MODE_MASK (TYPE_MODE (inner_type));
     271                 :           0 :   low_bits = build_replicated_int_cst (word_type, width, max >> 1);
     272                 :           0 :   high_bits = build_replicated_int_cst (word_type, width, max & ~(max >> 1));
     273                 :             : 
     274                 :           0 :   b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
     275                 :             : 
     276                 :           0 :   b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
     277                 :           0 :   signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
     278                 :           0 :   signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
     279                 :           0 :   result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
     280                 :           0 :   return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
     281                 :             : }
     282                 :             : 
     283                 :             : /* Expand a vector operation to scalars, by using many operations
     284                 :             :    whose type is the vector type's inner type.  */
     285                 :             : static tree
     286                 :        2628 : expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
     287                 :             :                          tree type, tree inner_type,
     288                 :             :                          tree a, tree b, enum tree_code code,
     289                 :             :                          bool parallel_p, tree ret_type = NULL_TREE)
     290                 :             : {
     291                 :        2628 :   vec<constructor_elt, va_gc> *v;
     292                 :        2628 :   tree part_width = TYPE_SIZE (inner_type);
     293                 :        2628 :   tree index = bitsize_int (0);
     294                 :        2628 :   int nunits = nunits_for_known_piecewise_op (type);
     295                 :        2628 :   int delta = tree_to_uhwi (part_width) / vector_element_bits (type);
     296                 :        2628 :   int i;
     297                 :        2628 :   location_t loc = gimple_location (gsi_stmt (*gsi));
     298                 :             : 
     299                 :        2628 :   if (nunits == 1
     300                 :        2628 :       || warning_suppressed_p (gsi_stmt (*gsi),
     301                 :             :                                OPT_Wvector_operation_performance))
     302                 :             :     /* Do not diagnose decomposing single element vectors or when
     303                 :             :        decomposing vectorizer produced operations.  */
     304                 :             :     ;
     305                 :        2315 :   else if (ret_type || !parallel_p)
     306                 :        2258 :     warning_at (loc, OPT_Wvector_operation_performance,
     307                 :             :                 "vector operation will be expanded piecewise");
     308                 :             :   else
     309                 :          57 :     warning_at (loc, OPT_Wvector_operation_performance,
     310                 :             :                 "vector operation will be expanded in parallel");
     311                 :             : 
     312                 :        2628 :   if (!ret_type)
     313                 :        2542 :     ret_type = type;
     314                 :        2628 :   vec_alloc (v, (nunits + delta - 1) / delta);
     315                 :        2628 :   bool constant_p = true;
     316                 :       35429 :   for (i = 0; i < nunits;
     317                 :       32801 :        i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
     318                 :             :     {
     319                 :       32801 :       tree result = f (gsi, inner_type, a, b, index, part_width, code,
     320                 :             :                        ret_type);
     321                 :       32801 :       if (!CONSTANT_CLASS_P (result))
     322                 :       32384 :         constant_p = false;
     323                 :       32801 :       constructor_elt ce = {NULL_TREE, result};
     324                 :       32801 :       v->quick_push (ce);
     325                 :             :     }
     326                 :             : 
     327                 :        2628 :   if (constant_p)
     328                 :           2 :     return build_vector_from_ctor (ret_type, v);
     329                 :             :   else
     330                 :        2626 :     return build_constructor (ret_type, v);
     331                 :             : }
     332                 :             : 
     333                 :             : /* Expand a vector operation to scalars with the freedom to use
     334                 :             :    a scalar integer type, or to use a different size for the items
     335                 :             :    in the vector type.  */
     336                 :             : static tree
     337                 :          86 : expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
     338                 :             :                         tree a, tree b, enum tree_code code)
     339                 :             : {
     340                 :          86 :   tree result, compute_type;
     341                 :          86 :   int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
     342                 :          86 :   location_t loc = gimple_location (gsi_stmt (*gsi));
     343                 :             : 
     344                 :             :   /* We have three strategies.  If the type is already correct, just do
     345                 :             :      the operation an element at a time.  Else, if the vector is wider than
     346                 :             :      one word, do it a word at a time; finally, if the vector is smaller
     347                 :             :      than one word, do it as a scalar.  */
     348                 :          86 :   if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
     349                 :           1 :      return expand_vector_piecewise (gsi, f,
     350                 :           1 :                                      type, TREE_TYPE (type),
     351                 :           1 :                                      a, b, code, true);
     352                 :          85 :   else if (n_words > 1)
     353                 :             :     {
     354                 :          57 :       tree word_type = build_word_mode_vector_type (n_words);
     355                 :          57 :       result = expand_vector_piecewise (gsi, f,
     356                 :          57 :                                         word_type, TREE_TYPE (word_type),
     357                 :             :                                         a, b, code, true);
     358                 :          57 :       result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
     359                 :             :                                          GSI_SAME_STMT);
     360                 :             :     }
     361                 :             :   else
     362                 :             :     {
     363                 :             :       /* Use a single scalar operation with a mode no wider than word_mode.  */
     364                 :          28 :       if (!warning_suppressed_p (gsi_stmt (*gsi),
     365                 :             :                                  OPT_Wvector_operation_performance))
     366                 :          27 :         warning_at (loc, OPT_Wvector_operation_performance,
     367                 :             :                     "vector operation will be expanded with a "
     368                 :             :                     "single scalar operation");
     369                 :          28 :       scalar_int_mode mode
     370                 :          28 :         = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
     371                 :          28 :       compute_type = lang_hooks.types.type_for_mode (mode, 1);
     372                 :          28 :       result = f (gsi, compute_type, a, b, bitsize_zero_node,
     373                 :          28 :                   TYPE_SIZE (compute_type), code, type);
     374                 :             :     }
     375                 :             : 
     376                 :             :   return result;
     377                 :             : }
     378                 :             : 
     379                 :             : /* Expand a vector operation to scalars; for integer types we can use
     380                 :             :    special bit twiddling tricks to do the sums a word at a time, using
     381                 :             :    function F_PARALLEL instead of F.  These tricks are done only if
     382                 :             :    they can process at least four items, that is, only if the vector
     383                 :             :    holds at least four items and if a word can hold four items.  */
     384                 :             : static tree
     385                 :         141 : expand_vector_addition (gimple_stmt_iterator *gsi,
     386                 :             :                         elem_op_func f, elem_op_func f_parallel,
     387                 :             :                         tree type, tree a, tree b, enum tree_code code)
     388                 :             : {
     389                 :         141 :   int parts_per_word = BITS_PER_WORD / vector_element_bits (type);
     390                 :             : 
     391                 :         282 :   if (INTEGRAL_TYPE_P (TREE_TYPE (type))
     392                 :         141 :       && parts_per_word >= 4
     393                 :         151 :       && nunits_for_known_piecewise_op (type) >= 4)
     394                 :           3 :     return expand_vector_parallel (gsi, f_parallel,
     395                 :           3 :                                    type, a, b, code);
     396                 :             :   else
     397                 :         138 :     return expand_vector_piecewise (gsi, f,
     398                 :         138 :                                     type, TREE_TYPE (type),
     399                 :         138 :                                     a, b, code, false);
     400                 :             : }
     401                 :             : 
     402                 :             : /* Expand vector comparison expression OP0 CODE OP1 if the compare optab
     403                 :             :    is not implemented.  */
     404                 :             : 
     405                 :             : static tree
     406                 :       19834 : expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
     407                 :             :                           tree op1, enum tree_code code)
     408                 :             : {
     409                 :       19834 :   if (expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code))
     410                 :             :     return NULL_TREE;
     411                 :             : 
     412                 :         566 :   tree t;
     413                 :         566 :   if (VECTOR_BOOLEAN_TYPE_P (type)
     414                 :         566 :       && SCALAR_INT_MODE_P (TYPE_MODE (type))
     415                 :         692 :       && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
     416                 :             :                    TYPE_VECTOR_SUBPARTS (type)
     417                 :             :                    * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
     418                 :             :                                        (TREE_TYPE (type)))))
     419                 :             :     {
     420                 :           0 :       tree inner_type = TREE_TYPE (TREE_TYPE (op0));
     421                 :           0 :       tree part_width = vector_element_bits_tree (TREE_TYPE (op0));
     422                 :           0 :       tree index = bitsize_int (0);
     423                 :           0 :       int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0));
     424                 :           0 :       int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type));
     425                 :           0 :       tree ret_type = build_nonstandard_integer_type (prec, 1);
     426                 :           0 :       tree ret_inner_type = boolean_type_node;
     427                 :           0 :       int i;
     428                 :           0 :       location_t loc = gimple_location (gsi_stmt (*gsi));
     429                 :           0 :       t = build_zero_cst (ret_type);
     430                 :             : 
     431                 :           0 :       if (TYPE_PRECISION (ret_inner_type) != 1)
     432                 :           0 :         ret_inner_type = build_nonstandard_integer_type (1, 1);
     433                 :           0 :       if (!warning_suppressed_p (gsi_stmt (*gsi),
     434                 :             :                                  OPT_Wvector_operation_performance))
     435                 :           0 :         warning_at (loc, OPT_Wvector_operation_performance,
     436                 :             :                     "vector operation will be expanded piecewise");
     437                 :           0 :       for (i = 0; i < nunits;
     438                 :           0 :            i++, index = int_const_binop (PLUS_EXPR, index, part_width))
     439                 :             :         {
     440                 :           0 :           tree a = tree_vec_extract (gsi, inner_type, op0, part_width,
     441                 :             :                                      index);
     442                 :           0 :           tree b = tree_vec_extract (gsi, inner_type, op1, part_width,
     443                 :             :                                      index);
     444                 :           0 :           tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b);
     445                 :           0 :           t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result,
     446                 :           0 :                                bitsize_int (i));
     447                 :             :         }
     448                 :           0 :       t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
     449                 :             :     }
     450                 :             :   else
     451                 :         566 :     t = expand_vector_piecewise (gsi, do_compare, type,
     452                 :         566 :                                  TREE_TYPE (TREE_TYPE (op0)), op0, op1,
     453                 :             :                                  code, false);
     454                 :             : 
     455                 :             :   return t;
     456                 :             : }
     457                 :             : 
     458                 :             : /* Helper function of expand_vector_divmod.  Gimplify a RSHIFT_EXPR in type
     459                 :             :    of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
     460                 :             :    the result if successful, otherwise return NULL_TREE.  */
     461                 :             : static tree
     462                 :         490 : add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
     463                 :             : {
     464                 :         490 :   optab op;
     465                 :         490 :   unsigned int i, nunits = nunits_for_known_piecewise_op (type);
     466                 :         490 :   bool scalar_shift = true;
     467                 :             : 
     468                 :        3120 :   for (i = 1; i < nunits; i++)
     469                 :             :     {
     470                 :        2630 :       if (shiftcnts[i] != shiftcnts[0])
     471                 :           0 :         scalar_shift = false;
     472                 :             :     }
     473                 :             : 
     474                 :         490 :   if (scalar_shift && shiftcnts[0] == 0)
     475                 :             :     return op0;
     476                 :             : 
     477                 :         391 :   if (scalar_shift)
     478                 :             :     {
     479                 :         391 :       op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
     480                 :         391 :       if (op != unknown_optab
     481                 :         391 :           && can_implement_p (op, TYPE_MODE (type)))
     482                 :         391 :         return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
     483                 :         391 :                                 build_int_cst (NULL_TREE, shiftcnts[0]));
     484                 :             :     }
     485                 :             : 
     486                 :           0 :   op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
     487                 :           0 :   if (op != unknown_optab
     488                 :           0 :       && can_implement_p (op, TYPE_MODE (type)))
     489                 :             :     {
     490                 :           0 :       tree_vector_builder vec (type, nunits, 1);
     491                 :           0 :       for (i = 0; i < nunits; i++)
     492                 :           0 :         vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
     493                 :           0 :       return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ());
     494                 :           0 :     }
     495                 :             : 
     496                 :             :   return NULL_TREE;
     497                 :             : }
     498                 :             : 
     499                 :             : /* Try to expand integer vector division by constant using
     500                 :             :    widening multiply, shifts and additions.  */
     501                 :             : static tree
     502                 :         448 : expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
     503                 :             :                       tree op1, enum tree_code code)
     504                 :             : {
     505                 :         448 :   bool use_pow2 = true;
     506                 :         448 :   bool has_vector_shift = true;
     507                 :         448 :   bool use_abs_op1 = false;
     508                 :         448 :   int mode = -1, this_mode;
     509                 :         448 :   int pre_shift = -1, post_shift;
     510                 :         448 :   unsigned int nunits = nunits_for_known_piecewise_op (type);
     511                 :         448 :   int *shifts = XALLOCAVEC (int, nunits * 4);
     512                 :         448 :   int *pre_shifts = shifts + nunits;
     513                 :         448 :   int *post_shifts = pre_shifts + nunits;
     514                 :         448 :   int *shift_temps = post_shifts + nunits;
     515                 :         448 :   unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
     516                 :         448 :   int prec = TYPE_PRECISION (TREE_TYPE (type));
     517                 :         448 :   unsigned int i;
     518                 :         448 :   signop sign_p = TYPE_SIGN (TREE_TYPE (type));
     519                 :         448 :   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
     520                 :         448 :   tree cur_op, mulcst, tem;
     521                 :         448 :   optab op;
     522                 :             : 
     523                 :         448 :   if (prec > HOST_BITS_PER_WIDE_INT)
     524                 :             :     return NULL_TREE;
     525                 :             : 
     526                 :         447 :   op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
     527                 :         447 :   if (op == unknown_optab
     528                 :         447 :       || !can_implement_p (op, TYPE_MODE (type)))
     529                 :             :     has_vector_shift = false;
     530                 :             : 
     531                 :             :   /* Analysis phase.  Determine if all op1 elements are either power
     532                 :             :      of two and it is possible to expand it using shifts (or for remainder
     533                 :             :      using masking).  Additionally compute the multiplicative constants
     534                 :             :      and pre and post shifts if the division is to be expanded using
     535                 :             :      widening or high part multiplication plus shifts.  */
     536                 :        3189 :   for (i = 0; i < nunits; i++)
     537                 :             :     {
     538                 :        2752 :       tree cst = VECTOR_CST_ELT (op1, i);
     539                 :        2752 :       unsigned HOST_WIDE_INT ml;
     540                 :             : 
     541                 :        2752 :       if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
     542                 :          10 :         return NULL_TREE;
     543                 :        2744 :       pre_shifts[i] = 0;
     544                 :        2744 :       post_shifts[i] = 0;
     545                 :        2744 :       mulc[i] = 0;
     546                 :        2744 :       if (use_pow2
     547                 :        2744 :           && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
     548                 :             :         use_pow2 = false;
     549                 :        2457 :       if (use_pow2)
     550                 :             :         {
     551                 :         824 :           shifts[i] = tree_log2 (cst);
     552                 :         824 :           if (shifts[i] != shifts[0]
     553                 :         192 :               && code == TRUNC_DIV_EXPR
     554                 :         192 :               && !has_vector_shift)
     555                 :        1952 :             use_pow2 = false;
     556                 :             :         }
     557                 :        2744 :       if (mode == -2)
     558                 :        1000 :         continue;
     559                 :        1861 :       if (sign_p == UNSIGNED)
     560                 :             :         {
     561                 :         814 :           unsigned HOST_WIDE_INT mh;
     562                 :         814 :           unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
     563                 :             : 
     564                 :         814 :           if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
     565                 :             :             /* FIXME: Can transform this into op0 >= op1 ? 1 : 0.  */
     566                 :             :             return NULL_TREE;
     567                 :             : 
     568                 :         812 :           if (d <= 1)
     569                 :             :             {
     570                 :          32 :               mode = -2;
     571                 :          32 :               continue;
     572                 :             :             }
     573                 :             : 
     574                 :             :           /* Find a suitable multiplier and right shift count instead of
     575                 :             :              directly dividing by D.  */
     576                 :         780 :           mh = choose_multiplier (d, prec, prec, &ml, &post_shift);
     577                 :             : 
     578                 :             :           /* If the suggested multiplier is more than PREC bits, we can
     579                 :             :              do better for even divisors, using an initial right shift.  */
     580                 :         780 :           if ((mh != 0 && (d & 1) == 0)
     581                 :         638 :               || (!has_vector_shift && pre_shift != -1))
     582                 :             :             {
     583                 :         142 :               if (has_vector_shift)
     584                 :           0 :                 pre_shift = ctz_or_zero (d);
     585                 :         174 :               else if (pre_shift == -1)
     586                 :             :                 {
     587                 :             :                   unsigned int j;
     588                 :         518 :                   for (j = 0; j < nunits; j++)
     589                 :             :                     {
     590                 :         440 :                       tree cst2 = VECTOR_CST_ELT (op1, j);
     591                 :         440 :                       unsigned HOST_WIDE_INT d2;
     592                 :         440 :                       int this_pre_shift;
     593                 :             : 
     594                 :         440 :                       if (!tree_fits_uhwi_p (cst2))
     595                 :             :                         return NULL_TREE;
     596                 :         440 :                       d2 = tree_to_uhwi (cst2) & mask;
     597                 :         440 :                       if (d2 == 0)
     598                 :             :                         return NULL_TREE;
     599                 :         440 :                       this_pre_shift = floor_log2 (d2 & -d2);
     600                 :         440 :                       if (pre_shift == -1 || this_pre_shift < pre_shift)
     601                 :          78 :                         pre_shift = this_pre_shift;
     602                 :             :                     }
     603                 :          78 :                   if (i != 0 && pre_shift != 0)
     604                 :             :                     {
     605                 :             :                       /* Restart.  */
     606                 :           0 :                       i = -1U;
     607                 :           0 :                       mode = -1;
     608                 :           0 :                       continue;
     609                 :             :                     }
     610                 :             :                 }
     611                 :         174 :               if (pre_shift != 0)
     612                 :             :                 {
     613                 :         174 :                   if ((d >> pre_shift) <= 1)
     614                 :             :                     {
     615                 :          46 :                       mode = -2;
     616                 :          46 :                       continue;
     617                 :             :                     }
     618                 :         128 :                   mh = choose_multiplier (d >> pre_shift, prec,
     619                 :             :                                           prec - pre_shift,
     620                 :             :                                           &ml, &post_shift);
     621                 :         128 :                   gcc_assert (!mh);
     622                 :         128 :                   pre_shifts[i] = pre_shift;
     623                 :             :                 }
     624                 :             :             }
     625                 :         734 :           if (!mh)
     626                 :             :             this_mode = 0;
     627                 :             :           else
     628                 :         192 :             this_mode = 1;
     629                 :             :         }
     630                 :             :       else
     631                 :             :         {
     632                 :        1047 :           HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
     633                 :        1047 :           unsigned HOST_WIDE_INT abs_d;
     634                 :             : 
     635                 :        1047 :           if (d == -1)
     636                 :             :             return NULL_TREE;
     637                 :             : 
     638                 :             :           /* Since d might be INT_MIN, we have to cast to
     639                 :             :              unsigned HOST_WIDE_INT before negating to avoid
     640                 :             :              undefined signed overflow.  */
     641                 :        1047 :           abs_d = (d >= 0
     642                 :             :                   ? (unsigned HOST_WIDE_INT) d
     643                 :             :                   : - (unsigned HOST_WIDE_INT) d);
     644                 :             : 
     645                 :             :           /* n rem d = n rem -d */
     646                 :        1047 :           if (code == TRUNC_MOD_EXPR && d < 0)
     647                 :             :             {
     648                 :         119 :               d = abs_d;
     649                 :         119 :               use_abs_op1 = true;
     650                 :             :             }
     651                 :        1047 :           if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
     652                 :             :             {
     653                 :             :               /* This case is not handled correctly below.  */
     654                 :           7 :               mode = -2;
     655                 :           7 :               continue;
     656                 :             :             }
     657                 :        1040 :           if (abs_d <= 1)
     658                 :             :             {
     659                 :          32 :               mode = -2;
     660                 :          32 :               continue;
     661                 :             :             }
     662                 :             : 
     663                 :        1008 :           choose_multiplier (abs_d, prec, prec - 1, &ml,
     664                 :             :                              &post_shift);
     665                 :        1008 :           if (ml >= HOST_WIDE_INT_1U << (prec - 1))
     666                 :             :             {
     667                 :         432 :               this_mode = 4 + (d < 0);
     668                 :         432 :               ml |= HOST_WIDE_INT_M1U << (prec - 1);
     669                 :             :             }
     670                 :             :           else
     671                 :         576 :             this_mode = 2 + (d < 0);
     672                 :             :         }
     673                 :        1742 :       mulc[i] = ml;
     674                 :        1742 :       post_shifts[i] = post_shift;
     675                 :        1742 :       if ((i && !has_vector_shift && post_shifts[0] != post_shift)
     676                 :        1646 :           || post_shift >= prec
     677                 :        1646 :           || pre_shifts[i] >= prec)
     678                 :          96 :         this_mode = -2;
     679                 :             : 
     680                 :        1742 :       if (i == 0)
     681                 :             :         mode = this_mode;
     682                 :        1416 :       else if (mode != this_mode)
     683                 :          96 :         mode = -2;
     684                 :             :     }
     685                 :             : 
     686                 :         437 :   if (use_pow2)
     687                 :             :     {
     688                 :         126 :       tree addend = NULL_TREE;
     689                 :         126 :       if (sign_p == SIGNED)
     690                 :             :         {
     691                 :             :           tree uns_type;
     692                 :             : 
     693                 :             :           /* Both division and remainder sequences need
     694                 :             :              op0 < 0 ? mask : 0 computed.  It can be either computed as
     695                 :             :              (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
     696                 :             :              if none of the shifts is 0, or as the conditional.  */
     697                 :         384 :           for (i = 0; i < nunits; i++)
     698                 :         336 :             if (shifts[i] == 0)
     699                 :             :               break;
     700                 :          64 :           uns_type
     701                 :          64 :             = build_vector_type (build_nonstandard_integer_type (prec, 1),
     702                 :             :                                  nunits);
     703                 :          64 :           if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
     704                 :             :             {
     705                 :         368 :               for (i = 0; i < nunits; i++)
     706                 :         320 :                 shift_temps[i] = prec - 1;
     707                 :          48 :               cur_op = add_rshift (gsi, type, op0, shift_temps);
     708                 :          48 :               if (cur_op != NULL_TREE)
     709                 :             :                 {
     710                 :          48 :                   cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
     711                 :             :                                             uns_type, cur_op);
     712                 :         416 :                   for (i = 0; i < nunits; i++)
     713                 :         320 :                     shift_temps[i] = prec - shifts[i];
     714                 :          48 :                   cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
     715                 :          48 :                   if (cur_op != NULL_TREE)
     716                 :          48 :                     addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
     717                 :             :                                               type, cur_op);
     718                 :             :                 }
     719                 :             :             }
     720                 :          64 :           tree mask_type = truth_type_for (type);
     721                 :          64 :           if (addend == NULL_TREE
     722                 :          16 :               && expand_vec_cmp_expr_p (type, mask_type, LT_EXPR)
     723                 :          80 :               && expand_vec_cond_expr_p (type, mask_type))
     724                 :             :             {
     725                 :          16 :               tree zero, cst, mask_type, mask;
     726                 :          16 :               gimple *stmt, *cond;
     727                 :             : 
     728                 :          16 :               mask_type = truth_type_for (type);
     729                 :          16 :               zero = build_zero_cst (type);
     730                 :          16 :               mask = make_ssa_name (mask_type);
     731                 :          16 :               cond = gimple_build_assign (mask, LT_EXPR, op0, zero);
     732                 :          16 :               gsi_insert_before (gsi, cond, GSI_SAME_STMT);
     733                 :          16 :               tree_vector_builder vec (type, nunits, 1);
     734                 :         128 :               for (i = 0; i < nunits; i++)
     735                 :          96 :                 vec.quick_push (build_int_cst (TREE_TYPE (type),
     736                 :             :                                                (HOST_WIDE_INT_1U
     737                 :          96 :                                                 << shifts[i]) - 1));
     738                 :          16 :               cst = vec.build ();
     739                 :          16 :               addend = make_ssa_name (type);
     740                 :          16 :               stmt
     741                 :          16 :                 = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero);
     742                 :          16 :               gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
     743                 :          16 :             }
     744                 :             :         }
     745                 :         126 :       if (code == TRUNC_DIV_EXPR)
     746                 :             :         {
     747                 :          54 :           if (sign_p == UNSIGNED)
     748                 :             :             {
     749                 :             :               /* q = op0 >> shift;  */
     750                 :          30 :               cur_op = add_rshift (gsi, type, op0, shifts);
     751                 :          30 :               if (cur_op != NULL_TREE)
     752                 :             :                 return cur_op;
     753                 :             :             }
     754                 :          24 :           else if (addend != NULL_TREE)
     755                 :             :             {
     756                 :             :               /* t1 = op0 + addend;
     757                 :             :                  q = t1 >> shift;  */
     758                 :          24 :               op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
     759                 :          24 :               if (op != unknown_optab
     760                 :          24 :                   && can_implement_p (op, TYPE_MODE (type)))
     761                 :             :                 {
     762                 :          24 :                   cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
     763                 :          24 :                   cur_op = add_rshift (gsi, type, cur_op, shifts);
     764                 :          24 :                   if (cur_op != NULL_TREE)
     765                 :             :                     return cur_op;
     766                 :             :                 }
     767                 :             :             }
     768                 :             :         }
     769                 :             :       else
     770                 :             :         {
     771                 :          72 :           tree mask;
     772                 :          72 :           tree_vector_builder vec (type, nunits, 1);
     773                 :         592 :           for (i = 0; i < nunits; i++)
     774                 :         448 :             vec.quick_push (build_int_cst (TREE_TYPE (type),
     775                 :             :                                            (HOST_WIDE_INT_1U
     776                 :         448 :                                             << shifts[i]) - 1));
     777                 :          72 :           mask = vec.build ();
     778                 :          72 :           op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
     779                 :          72 :           if (op != unknown_optab
     780                 :          72 :               && can_implement_p (op, TYPE_MODE (type)))
     781                 :             :             {
     782                 :          72 :               if (sign_p == UNSIGNED)
     783                 :             :                 /* r = op0 & mask;  */
     784                 :          32 :                 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
     785                 :          40 :               else if (addend != NULL_TREE)
     786                 :             :                 {
     787                 :             :                   /* t1 = op0 + addend;
     788                 :             :                      t2 = t1 & mask;
     789                 :             :                      r = t2 - addend;  */
     790                 :          40 :                   op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
     791                 :          40 :                   if (op != unknown_optab
     792                 :          40 :                       && can_implement_p (op, TYPE_MODE (type)))
     793                 :             :                     {
     794                 :          40 :                       cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
     795                 :             :                                                 addend);
     796                 :          40 :                       cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
     797                 :             :                                                 cur_op, mask);
     798                 :          40 :                       op = optab_for_tree_code (MINUS_EXPR, type,
     799                 :             :                                                 optab_default);
     800                 :          40 :                       if (op != unknown_optab
     801                 :          40 :                           && can_implement_p (op, TYPE_MODE (type)))
     802                 :          40 :                         return gimplify_build2 (gsi, MINUS_EXPR, type,
     803                 :          40 :                                                 cur_op, addend);
     804                 :             :                     }
     805                 :             :                 }
     806                 :             :             }
     807                 :          72 :         }
     808                 :             :     }
     809                 :             : 
     810                 :         311 :   if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
     811                 :             :     return NULL_TREE;
     812                 :             : 
     813                 :         176 :   if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
     814                 :             :     return NULL_TREE;
     815                 :             : 
     816                 :         170 :   cur_op = op0;
     817                 :             : 
     818                 :         170 :   switch (mode)
     819                 :             :     {
     820                 :          67 :     case 0:
     821                 :          67 :       gcc_assert (sign_p == UNSIGNED);
     822                 :             :       /* t1 = oprnd0 >> pre_shift;
     823                 :             :          t2 = t1 h* ml;
     824                 :             :          q = t2 >> post_shift;  */
     825                 :          67 :       cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
     826                 :          67 :       if (cur_op == NULL_TREE)
     827                 :             :         return NULL_TREE;
     828                 :             :       break;
     829                 :          32 :     case 1:
     830                 :          32 :       gcc_assert (sign_p == UNSIGNED);
     831                 :         224 :       for (i = 0; i < nunits; i++)
     832                 :             :         {
     833                 :         192 :           shift_temps[i] = 1;
     834                 :         192 :           post_shifts[i]--;
     835                 :             :         }
     836                 :             :       break;
     837                 :          71 :     case 2:
     838                 :          71 :     case 3:
     839                 :          71 :     case 4:
     840                 :          71 :     case 5:
     841                 :          71 :       gcc_assert (sign_p == SIGNED);
     842                 :         567 :       for (i = 0; i < nunits; i++)
     843                 :         496 :         shift_temps[i] = prec - 1;
     844                 :             :       break;
     845                 :             :     default:
     846                 :             :       return NULL_TREE;
     847                 :             :     }
     848                 :             : 
     849                 :         170 :   tree_vector_builder vec (type, nunits, 1);
     850                 :        1424 :   for (i = 0; i < nunits; i++)
     851                 :        1084 :     vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
     852                 :         170 :   mulcst = vec.build ();
     853                 :             : 
     854                 :         170 :   cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
     855                 :             : 
     856                 :         170 :   switch (mode)
     857                 :             :     {
     858                 :          67 :     case 0:
     859                 :             :       /* t1 = oprnd0 >> pre_shift;
     860                 :             :          t2 = t1 h* ml;
     861                 :             :          q = t2 >> post_shift;  */
     862                 :          67 :       cur_op = add_rshift (gsi, type, cur_op, post_shifts);
     863                 :          67 :       break;
     864                 :          32 :     case 1:
     865                 :             :       /* t1 = oprnd0 h* ml;
     866                 :             :          t2 = oprnd0 - t1;
     867                 :             :          t3 = t2 >> 1;
     868                 :             :          t4 = t1 + t3;
     869                 :             :          q = t4 >> (post_shift - 1);  */
     870                 :          32 :       op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
     871                 :          32 :       if (op == unknown_optab
     872                 :          32 :           || !can_implement_p (op, TYPE_MODE (type)))
     873                 :           0 :         return NULL_TREE;
     874                 :          32 :       tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
     875                 :          32 :       tem = add_rshift (gsi, type, tem, shift_temps);
     876                 :          32 :       op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
     877                 :          32 :       if (op == unknown_optab
     878                 :          32 :           || !can_implement_p (op, TYPE_MODE (type)))
     879                 :           0 :         return NULL_TREE;
     880                 :          32 :       tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
     881                 :          32 :       cur_op = add_rshift (gsi, type, tem, post_shifts);
     882                 :          32 :       if (cur_op == NULL_TREE)
     883                 :             :         return NULL_TREE;
     884                 :             :       break;
     885                 :          71 :     case 2:
     886                 :          71 :     case 3:
     887                 :          71 :     case 4:
     888                 :          71 :     case 5:
     889                 :             :       /* t1 = oprnd0 h* ml;
     890                 :             :          t2 = t1; [ iff (mode & 2) != 0 ]
     891                 :             :          t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
     892                 :             :          t3 = t2 >> post_shift;
     893                 :             :          t4 = oprnd0 >> (prec - 1);
     894                 :             :          q = t3 - t4; [ iff (mode & 1) == 0 ]
     895                 :             :          q = t4 - t3; [ iff (mode & 1) != 0 ]  */
     896                 :          71 :       if ((mode & 2) == 0)
     897                 :             :         {
     898                 :          16 :           op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
     899                 :          16 :           if (op == unknown_optab
     900                 :          16 :               || !can_implement_p (op, TYPE_MODE (type)))
     901                 :           0 :             return NULL_TREE;
     902                 :          16 :           cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
     903                 :             :         }
     904                 :          71 :       cur_op = add_rshift (gsi, type, cur_op, post_shifts);
     905                 :          71 :       if (cur_op == NULL_TREE)
     906                 :             :         return NULL_TREE;
     907                 :          71 :       tem = add_rshift (gsi, type, op0, shift_temps);
     908                 :          71 :       if (tem == NULL_TREE)
     909                 :             :         return NULL_TREE;
     910                 :          71 :       op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
     911                 :          71 :       if (op == unknown_optab
     912                 :          71 :           || !can_implement_p (op, TYPE_MODE (type)))
     913                 :           0 :         return NULL_TREE;
     914                 :          71 :       if ((mode & 1) == 0)
     915                 :          71 :         cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
     916                 :             :       else
     917                 :           0 :         cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
     918                 :             :       break;
     919                 :             :     default:
     920                 :             :       gcc_unreachable ();
     921                 :             :     }
     922                 :             : 
     923                 :         170 :   if (code == TRUNC_DIV_EXPR)
     924                 :             :     return cur_op;
     925                 :             : 
     926                 :             :   /* We divided.  Now finish by:
     927                 :             :      t1 = q * oprnd1;
     928                 :             :      r = oprnd0 - t1;  */
     929                 :          87 :   op = optab_for_tree_code (MULT_EXPR, type, optab_default);
     930                 :          87 :   if (op == unknown_optab
     931                 :          87 :       || !can_implement_p (op, TYPE_MODE (type)))
     932                 :           0 :     return NULL_TREE;
     933                 :          87 :   if (use_abs_op1)
     934                 :             :     {
     935                 :           7 :       tree_vector_builder elts;
     936                 :           7 :       if (!elts.new_unary_operation (type, op1, false))
     937                 :             :         return NULL_TREE;
     938                 :           7 :       unsigned int count = elts.encoded_nelts ();
     939                 :          14 :       for (unsigned int i = 0; i < count; ++i)
     940                 :             :         {
     941                 :           7 :           tree elem1 = VECTOR_CST_ELT (op1, i);
     942                 :             : 
     943                 :           7 :           tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1);
     944                 :           7 :           if (elt == NULL_TREE)
     945                 :           0 :             return NULL_TREE;
     946                 :           7 :           elts.quick_push (elt);
     947                 :             :         }
     948                 :           7 :       op1 = elts.build ();
     949                 :           7 :     }
     950                 :          87 :   tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
     951                 :          87 :   op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
     952                 :          87 :   if (op == unknown_optab
     953                 :          87 :       || !can_implement_p (op, TYPE_MODE (type)))
     954                 :           0 :     return NULL_TREE;
     955                 :          87 :   return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
     956                 :             : }
     957                 :             : 
     958                 :             : /* Expand a vector condition to scalars, by using many conditions
     959                 :             :    on the vector's elements.  */
     960                 :             : 
     961                 :             : static bool
     962                 :       17315 : expand_vector_condition (gimple_stmt_iterator *gsi)
     963                 :             : {
     964                 :       17315 :   gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
     965                 :       17315 :   tree type = TREE_TYPE (gimple_assign_lhs (stmt));
     966                 :       17315 :   tree a = gimple_assign_rhs1 (stmt);
     967                 :       17315 :   tree a1 = a;
     968                 :       17315 :   tree a2 = NULL_TREE;
     969                 :       17315 :   bool a_is_scalar_bitmask = false;
     970                 :       17315 :   tree b = gimple_assign_rhs2 (stmt);
     971                 :       17315 :   tree c = gimple_assign_rhs3 (stmt);
     972                 :       17315 :   vec<constructor_elt, va_gc> *v;
     973                 :       17315 :   tree constr;
     974                 :       17315 :   tree inner_type = TREE_TYPE (type);
     975                 :       17315 :   tree width = vector_element_bits_tree (type);
     976                 :       17315 :   tree cond_type = TREE_TYPE (TREE_TYPE (a));
     977                 :       17315 :   tree index = bitsize_int (0);
     978                 :       17315 :   tree comp_width = width;
     979                 :       17315 :   tree comp_index = index;
     980                 :       17315 :   location_t loc = gimple_location (gsi_stmt (*gsi));
     981                 :             : 
     982                 :       17315 :   gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)));
     983                 :             : 
     984                 :       17315 :   if (expand_vec_cond_expr_p (type, TREE_TYPE (a)))
     985                 :             :     return true;
     986                 :             : 
     987                 :             :   /* Handle vector boolean types with bitmasks.  We can transform
     988                 :             :       vbfld_1 = tmp_6 ? vbfld_4 : vbfld_5;
     989                 :             :      into
     990                 :             :       tmp_7 = tmp_6 & vbfld_4;
     991                 :             :       tmp_8 = ~tmp_6;
     992                 :             :       tmp_9 = tmp_8 & vbfld_5;
     993                 :             :       vbfld_1 = tmp_7 | tmp_9;  */
     994                 :         498 :   if (VECTOR_BOOLEAN_TYPE_P (type)
     995                 :           0 :       && SCALAR_INT_MODE_P (TYPE_MODE (type))
     996                 :         498 :       && useless_type_conversion_p (type, TREE_TYPE (a)))
     997                 :             :     {
     998                 :           0 :       a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
     999                 :           0 :       a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
    1000                 :           0 :       a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
    1001                 :           0 :       a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
    1002                 :           0 :       gimple_assign_set_rhs_from_tree (gsi, a);
    1003                 :           0 :       update_stmt (gsi_stmt (*gsi));
    1004                 :           0 :       return true;
    1005                 :             :     }
    1006                 :             : 
    1007                 :             :   /* TODO: try and find a smaller vector type.  */
    1008                 :             : 
    1009                 :         498 :   if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
    1010                 :         498 :     warning_at (loc, OPT_Wvector_operation_performance,
    1011                 :             :                 "vector condition will be expanded piecewise");
    1012                 :             : 
    1013                 :         954 :   if (SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a)))
    1014                 :         582 :       && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))),
    1015                 :             :                    TYPE_VECTOR_SUBPARTS (TREE_TYPE (a))
    1016                 :             :                    * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
    1017                 :             :                                                 (TREE_TYPE (TREE_TYPE (a))))))
    1018                 :             :     {
    1019                 :           0 :       a_is_scalar_bitmask = true;
    1020                 :           0 :       int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a)));
    1021                 :           0 :       tree atype = build_nonstandard_integer_type (prec, 1);
    1022                 :           0 :       a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a);
    1023                 :             :     }
    1024                 :             :   else
    1025                 :         498 :     comp_width = vector_element_bits_tree (TREE_TYPE (a));
    1026                 :             : 
    1027                 :         498 :   int nunits = nunits_for_known_piecewise_op (type);
    1028                 :         498 :   vec_alloc (v, nunits);
    1029                 :         498 :   bool constant_p = true;
    1030                 :        5993 :   for (int i = 0; i < nunits; i++)
    1031                 :             :     {
    1032                 :        5495 :       tree aa, result;
    1033                 :        5495 :       tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
    1034                 :        5495 :       tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
    1035                 :        5495 :       if (a_is_scalar_bitmask)
    1036                 :             :         {
    1037                 :           0 :           wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
    1038                 :           0 :           result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
    1039                 :           0 :                                     a, wide_int_to_tree (TREE_TYPE (a), w));
    1040                 :           0 :           aa = gimplify_build2 (gsi, NE_EXPR, boolean_type_node, result,
    1041                 :           0 :                                 build_zero_cst (TREE_TYPE (a)));
    1042                 :           0 :         }
    1043                 :             :       else
    1044                 :             :         {
    1045                 :        5495 :           result = tree_vec_extract (gsi, cond_type, a, comp_width, comp_index);
    1046                 :        5495 :           aa = gimplify_build2 (gsi, NE_EXPR, boolean_type_node, result,
    1047                 :             :                                 build_zero_cst (cond_type));
    1048                 :             :         }
    1049                 :        5495 :       result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
    1050                 :        5495 :       if (!CONSTANT_CLASS_P (result))
    1051                 :        5411 :         constant_p = false;
    1052                 :        5495 :       constructor_elt ce = {NULL_TREE, result};
    1053                 :        5495 :       v->quick_push (ce);
    1054                 :        5495 :       index = int_const_binop (PLUS_EXPR, index, width);
    1055                 :        5495 :       if (width == comp_width)
    1056                 :             :         comp_index = index;
    1057                 :             :       else
    1058                 :           0 :         comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
    1059                 :             :     }
    1060                 :             : 
    1061                 :         498 :   if (constant_p)
    1062                 :           0 :     constr = build_vector_from_ctor (type, v);
    1063                 :             :   else
    1064                 :         498 :     constr = build_constructor (type, v);
    1065                 :         498 :   gimple_assign_set_rhs_from_tree (gsi, constr);
    1066                 :         498 :   update_stmt (gsi_stmt (*gsi));
    1067                 :             : 
    1068                 :         498 :   return false;
    1069                 :             : }
    1070                 :             : 
    1071                 :             : static tree
    1072                 :       22127 : expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
    1073                 :             :                          gassign *assign, enum tree_code code)
    1074                 :             : {
    1075                 :       22127 :   machine_mode compute_mode = TYPE_MODE (compute_type);
    1076                 :             : 
    1077                 :             :   /* If the compute mode is not a vector mode (hence we are not decomposing
    1078                 :             :      a BLKmode vector to smaller, hardware-supported vectors), we may want
    1079                 :             :      to expand the operations in parallel.  */
    1080                 :       22127 :   if (!VECTOR_MODE_P (compute_mode))
    1081                 :       21320 :     switch (code)
    1082                 :             :       {
    1083                 :         276 :       case PLUS_EXPR:
    1084                 :         276 :       case MINUS_EXPR:
    1085                 :         276 :         if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
    1086                 :         278 :           return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
    1087                 :             :                                          gimple_assign_rhs1 (assign),
    1088                 :         139 :                                          gimple_assign_rhs2 (assign), code);
    1089                 :             :         break;
    1090                 :             : 
    1091                 :           3 :       case NEGATE_EXPR:
    1092                 :           3 :         if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
    1093                 :           2 :           return expand_vector_addition (gsi, do_unop, do_negate, type,
    1094                 :             :                                          gimple_assign_rhs1 (assign),
    1095                 :           2 :                                          NULL_TREE, code);
    1096                 :             :         break;
    1097                 :             : 
    1098                 :          74 :       case BIT_AND_EXPR:
    1099                 :          74 :       case BIT_IOR_EXPR:
    1100                 :          74 :       case BIT_XOR_EXPR:
    1101                 :         148 :         return expand_vector_parallel (gsi, do_binop, type,
    1102                 :             :                                        gimple_assign_rhs1 (assign),
    1103                 :          74 :                                        gimple_assign_rhs2 (assign), code);
    1104                 :             : 
    1105                 :           9 :       case BIT_NOT_EXPR:
    1106                 :           9 :         return expand_vector_parallel (gsi, do_unop, type,
    1107                 :             :                                        gimple_assign_rhs1 (assign),
    1108                 :           9 :                                        NULL_TREE, code);
    1109                 :       19834 :       case EQ_EXPR:
    1110                 :       19834 :       case NE_EXPR:
    1111                 :       19834 :       case GT_EXPR:
    1112                 :       19834 :       case LT_EXPR:
    1113                 :       19834 :       case GE_EXPR:
    1114                 :       19834 :       case LE_EXPR:
    1115                 :       19834 :       case UNEQ_EXPR:
    1116                 :       19834 :       case UNGT_EXPR:
    1117                 :       19834 :       case UNLT_EXPR:
    1118                 :       19834 :       case UNGE_EXPR:
    1119                 :       19834 :       case UNLE_EXPR:
    1120                 :       19834 :       case LTGT_EXPR:
    1121                 :       19834 :       case ORDERED_EXPR:
    1122                 :       19834 :       case UNORDERED_EXPR:
    1123                 :       19834 :         {
    1124                 :       19834 :           tree rhs1 = gimple_assign_rhs1 (assign);
    1125                 :       19834 :           tree rhs2 = gimple_assign_rhs2 (assign);
    1126                 :             : 
    1127                 :       19834 :           return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
    1128                 :             :         }
    1129                 :             : 
    1130                 :         759 :       case TRUNC_DIV_EXPR:
    1131                 :         759 :       case TRUNC_MOD_EXPR:
    1132                 :         759 :         {
    1133                 :         759 :           tree rhs1 = gimple_assign_rhs1 (assign);
    1134                 :         759 :           tree rhs2 = gimple_assign_rhs2 (assign);
    1135                 :         759 :           tree ret;
    1136                 :             : 
    1137                 :         759 :           if (!optimize
    1138                 :         666 :               || !VECTOR_INTEGER_TYPE_P (type)
    1139                 :         666 :               || TREE_CODE (rhs2) != VECTOR_CST
    1140                 :        1213 :               || !VECTOR_MODE_P (TYPE_MODE (type)))
    1141                 :             :             break;
    1142                 :             : 
    1143                 :         448 :           ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
    1144                 :         448 :           if (ret != NULL_TREE)
    1145                 :             :             return ret;
    1146                 :             :           break;
    1147                 :             :         }
    1148                 :             : 
    1149                 :             :       default:
    1150                 :             :         break;
    1151                 :             :       }
    1152                 :             : 
    1153                 :        1773 :   if (TREE_CODE_CLASS (code) == tcc_unary)
    1154                 :          87 :     return expand_vector_piecewise (gsi, do_unop, type, compute_type,
    1155                 :             :                                     gimple_assign_rhs1 (assign),
    1156                 :          87 :                                     NULL_TREE, code, false);
    1157                 :             :   else
    1158                 :        3372 :     return expand_vector_piecewise (gsi, do_binop, type, compute_type,
    1159                 :             :                                     gimple_assign_rhs1 (assign),
    1160                 :        1686 :                                     gimple_assign_rhs2 (assign), code, false);
    1161                 :             : }
    1162                 :             : 
    1163                 :             : /* Try to optimize
    1164                 :             :    a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
    1165                 :             :    style stmts into:
    1166                 :             :    _9 = { b_7, b_7, b_7, b_7 };
    1167                 :             :    a_5 = _9 + { 0, 3, 6, 9 };
    1168                 :             :    because vector splat operation is usually more efficient
    1169                 :             :    than piecewise initialization of the vector.  */
    1170                 :             : 
    1171                 :             : static void
    1172                 :      171242 : optimize_vector_constructor (gimple_stmt_iterator *gsi)
    1173                 :             : {
    1174                 :      171242 :   gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
    1175                 :      171242 :   tree lhs = gimple_assign_lhs (stmt);
    1176                 :      171242 :   tree rhs = gimple_assign_rhs1 (stmt);
    1177                 :      171242 :   tree type = TREE_TYPE (rhs);
    1178                 :      171242 :   unsigned int i, j;
    1179                 :      171242 :   unsigned HOST_WIDE_INT nelts;
    1180                 :      171242 :   bool all_same = true;
    1181                 :      171242 :   constructor_elt *elt;
    1182                 :      171242 :   gimple *g;
    1183                 :      171242 :   tree base = NULL_TREE;
    1184                 :      171242 :   optab op;
    1185                 :             : 
    1186                 :      171242 :   if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
    1187                 :      171242 :       || nelts <= 2
    1188                 :       46584 :       || CONSTRUCTOR_NELTS (rhs) != nelts)
    1189                 :      171213 :     return;
    1190                 :       22180 :   op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
    1191                 :       22180 :   if (op == unknown_optab
    1192                 :       22180 :       || !can_implement_p (op, TYPE_MODE (type)))
    1193                 :         557 :     return;
    1194                 :       98243 :   FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
    1195                 :       87729 :     if (TREE_CODE (elt->value) != SSA_NAME
    1196                 :       87729 :         || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
    1197                 :             :       return;
    1198                 :             :     else
    1199                 :             :       {
    1200                 :       86228 :         tree this_base = elt->value;
    1201                 :       86228 :         if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
    1202                 :        9704 :           all_same = false;
    1203                 :       87362 :         for (j = 0; j < nelts + 1; j++)
    1204                 :             :           {
    1205                 :       87362 :             g = SSA_NAME_DEF_STMT (this_base);
    1206                 :       87362 :             if (is_gimple_assign (g)
    1207                 :       57473 :                 && gimple_assign_rhs_code (g) == PLUS_EXPR
    1208                 :        2550 :                 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
    1209                 :        1134 :                 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
    1210                 :       88496 :                 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
    1211                 :        1134 :               this_base = gimple_assign_rhs1 (g);
    1212                 :             :             else
    1213                 :             :               break;
    1214                 :             :           }
    1215                 :       86228 :         if (i == 0)
    1216                 :             :           base = this_base;
    1217                 :       65095 :         else if (this_base != base)
    1218                 :             :           return;
    1219                 :             :       }
    1220                 :       10514 :   if (all_same)
    1221                 :             :     return;
    1222                 :          29 :   tree_vector_builder cst (type, nelts, 1);
    1223                 :         145 :   for (i = 0; i < nelts; i++)
    1224                 :             :     {
    1225                 :         116 :       tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
    1226                 :         116 :       tree elt = build_zero_cst (TREE_TYPE (base));
    1227                 :         204 :       while (this_base != base)
    1228                 :             :         {
    1229                 :          88 :           g = SSA_NAME_DEF_STMT (this_base);
    1230                 :          88 :           elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
    1231                 :             :                              elt, gimple_assign_rhs2 (g));
    1232                 :          88 :           if (elt == NULL_TREE
    1233                 :          88 :               || TREE_CODE (elt) != INTEGER_CST
    1234                 :         176 :               || TREE_OVERFLOW (elt))
    1235                 :           0 :             return;
    1236                 :          88 :           this_base = gimple_assign_rhs1 (g);
    1237                 :             :         }
    1238                 :         116 :       cst.quick_push (elt);
    1239                 :             :     }
    1240                 :         145 :   for (i = 0; i < nelts; i++)
    1241                 :         116 :     CONSTRUCTOR_ELT (rhs, i)->value = base;
    1242                 :          29 :   g = gimple_build_assign (make_ssa_name (type), rhs);
    1243                 :          29 :   gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1244                 :          29 :   g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
    1245                 :             :                            cst.build ());
    1246                 :          29 :   gsi_replace (gsi, g, false);
    1247                 :          29 : }
    1248                 :             : 
    1249                 :             : /* Return a type for the widest vector mode with the same element type as
    1250                 :             :    type ORIGINAL_VECTOR_TYPE, with at most the same number of elements as type
    1251                 :             :    ORIGINAL_VECTOR_TYPE and that is supported by the target for an operation
    1252                 :             :    with optab OP, or return NULL_TREE if none is found.  */
    1253                 :             : 
    1254                 :             : static tree
    1255                 :        2644 : type_for_widest_vector_mode (tree original_vector_type, optab op)
    1256                 :             : {
    1257                 :        2644 :   gcc_assert (VECTOR_TYPE_P (original_vector_type));
    1258                 :        2644 :   tree type = TREE_TYPE (original_vector_type);
    1259                 :        2644 :   machine_mode inner_mode = TYPE_MODE (type);
    1260                 :        2644 :   machine_mode best_mode = VOIDmode, mode;
    1261                 :        2644 :   poly_int64 best_nunits = 0;
    1262                 :             : 
    1263                 :        2644 :   if (SCALAR_FLOAT_MODE_P (inner_mode))
    1264                 :             :     mode = MIN_MODE_VECTOR_FLOAT;
    1265                 :        2297 :   else if (SCALAR_FRACT_MODE_P (inner_mode))
    1266                 :             :     mode = MIN_MODE_VECTOR_FRACT;
    1267                 :        2297 :   else if (SCALAR_UFRACT_MODE_P (inner_mode))
    1268                 :             :     mode = MIN_MODE_VECTOR_UFRACT;
    1269                 :        2297 :   else if (SCALAR_ACCUM_MODE_P (inner_mode))
    1270                 :             :     mode = MIN_MODE_VECTOR_ACCUM;
    1271                 :        2297 :   else if (SCALAR_UACCUM_MODE_P (inner_mode))
    1272                 :             :     mode = MIN_MODE_VECTOR_UACCUM;
    1273                 :        2297 :   else if (inner_mode == BImode)
    1274                 :             :     mode = MIN_MODE_VECTOR_BOOL;
    1275                 :             :   else
    1276                 :        2644 :     mode = MIN_MODE_VECTOR_INT;
    1277                 :             : 
    1278                 :       86558 :   FOR_EACH_MODE_FROM (mode, mode)
    1279                 :       83914 :     if (GET_MODE_INNER (mode) == inner_mode
    1280                 :       34152 :         && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
    1281                 :       17076 :         && can_implement_p (op, mode)
    1282                 :      103327 :         && known_le (GET_MODE_NUNITS (mode),
    1283                 :             :                      TYPE_VECTOR_SUBPARTS (original_vector_type)))
    1284                 :        3694 :       best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
    1285                 :             : 
    1286                 :        2644 :   if (best_mode == VOIDmode)
    1287                 :             :     return NULL_TREE;
    1288                 :             :   else
    1289                 :         992 :     return build_vector_type_for_mode (type, best_mode);
    1290                 :             : }
    1291                 :             : 
    1292                 :             : 
    1293                 :             : /* Build a reference to the element of the vector VECT.  Function
    1294                 :             :    returns either the element itself, either BIT_FIELD_REF, or an
    1295                 :             :    ARRAY_REF expression.
    1296                 :             : 
    1297                 :             :    GSI is required to insert temporary variables while building a
    1298                 :             :    refernece to the element of the vector VECT.
    1299                 :             : 
    1300                 :             :    PTMPVEC is a pointer to the temporary variable for caching
    1301                 :             :    purposes.  In case when PTMPVEC is NULL new temporary variable
    1302                 :             :    will be created.  */
    1303                 :             : static tree
    1304                 :      104699 : vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
    1305                 :             : {
    1306                 :      104699 :   tree vect_type, vect_elt_type;
    1307                 :      104699 :   gimple *asgn;
    1308                 :      104699 :   tree tmpvec;
    1309                 :      104699 :   tree arraytype;
    1310                 :      104699 :   bool need_asgn = true;
    1311                 :      104699 :   unsigned int elements;
    1312                 :             : 
    1313                 :      104699 :   vect_type = TREE_TYPE (vect);
    1314                 :      104699 :   vect_elt_type = TREE_TYPE (vect_type);
    1315                 :      104699 :   elements = nunits_for_known_piecewise_op (vect_type);
    1316                 :             : 
    1317                 :      104699 :   if (TREE_CODE (idx) == INTEGER_CST)
    1318                 :             :     {
    1319                 :       97122 :       unsigned HOST_WIDE_INT index;
    1320                 :             : 
    1321                 :             :       /* Given that we're about to compute a binary modulus,
    1322                 :             :          we don't care about the high bits of the value.  */
    1323                 :       97122 :       index = TREE_INT_CST_LOW (idx);
    1324                 :       97122 :       if (!tree_fits_uhwi_p (idx) || index >= elements)
    1325                 :             :         {
    1326                 :           0 :           index &= elements - 1;
    1327                 :           0 :           idx = build_int_cst (TREE_TYPE (idx), index);
    1328                 :             :         }
    1329                 :             : 
    1330                 :             :       /* When lowering a vector statement sequence do some easy
    1331                 :             :          simplification by looking through intermediate vector results.  */
    1332                 :       97122 :       if (TREE_CODE (vect) == SSA_NAME)
    1333                 :             :         {
    1334                 :       50941 :           gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
    1335                 :       50941 :           if (is_gimple_assign (def_stmt)
    1336                 :       50941 :               && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
    1337                 :       49810 :                   || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
    1338                 :        2107 :             vect = gimple_assign_rhs1 (def_stmt);
    1339                 :             :         }
    1340                 :             : 
    1341                 :       97122 :       if (TREE_CODE (vect) == VECTOR_CST)
    1342                 :       47212 :         return VECTOR_CST_ELT (vect, index);
    1343                 :       49910 :       else if (TREE_CODE (vect) == CONSTRUCTOR
    1344                 :       49910 :                && (CONSTRUCTOR_NELTS (vect) == 0
    1345                 :        1076 :                    || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
    1346                 :             :                       != VECTOR_TYPE))
    1347                 :             :         {
    1348                 :         169 :           if (index < CONSTRUCTOR_NELTS (vect))
    1349                 :         169 :             return CONSTRUCTOR_ELT (vect, index)->value;
    1350                 :           0 :           return build_zero_cst (vect_elt_type);
    1351                 :             :         }
    1352                 :             :       else
    1353                 :             :         {
    1354                 :       49741 :           tree size = vector_element_bits_tree (vect_type);
    1355                 :       49741 :           tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
    1356                 :             :                                   size);
    1357                 :       49741 :           return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
    1358                 :             :         }
    1359                 :             :     }
    1360                 :             : 
    1361                 :        7577 :   if (!ptmpvec)
    1362                 :           0 :     tmpvec = create_tmp_var (vect_type, "vectmp");
    1363                 :        7577 :   else if (!*ptmpvec)
    1364                 :        1276 :     tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
    1365                 :             :   else
    1366                 :             :     {
    1367                 :             :       tmpvec = *ptmpvec;
    1368                 :             :       need_asgn = false;
    1369                 :             :     }
    1370                 :             : 
    1371                 :        1276 :   if (need_asgn)
    1372                 :             :     {
    1373                 :        1276 :       TREE_ADDRESSABLE (tmpvec) = 1;
    1374                 :        1276 :       asgn = gimple_build_assign (tmpvec, vect);
    1375                 :        1276 :       gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
    1376                 :             :     }
    1377                 :             : 
    1378                 :        7577 :   arraytype = build_array_type_nelts (vect_elt_type, elements);
    1379                 :        7577 :   return build4 (ARRAY_REF, vect_elt_type,
    1380                 :             :                  build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
    1381                 :        7577 :                  idx, NULL_TREE, NULL_TREE);
    1382                 :             : }
    1383                 :             : 
    1384                 :             : /* Check if VEC_PERM_EXPR within the given setting is supported
    1385                 :             :    by hardware, or lower it piecewise.
    1386                 :             : 
    1387                 :             :    When VEC_PERM_EXPR has the same first and second operands:
    1388                 :             :    VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
    1389                 :             :    {v0[mask[0]], v0[mask[1]], ...}
    1390                 :             :    MASK and V0 must have the same number of elements.
    1391                 :             : 
    1392                 :             :    Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
    1393                 :             :    {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
    1394                 :             :    V0 and V1 must have the same type.  MASK, V0, V1 must have the
    1395                 :             :    same number of arguments.  */
    1396                 :             : 
    1397                 :             : static void
    1398                 :       78149 : lower_vec_perm (gimple_stmt_iterator *gsi)
    1399                 :             : {
    1400                 :       78149 :   gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
    1401                 :       78149 :   tree mask = gimple_assign_rhs3 (stmt);
    1402                 :       78149 :   tree vec0 = gimple_assign_rhs1 (stmt);
    1403                 :       78149 :   tree vec1 = gimple_assign_rhs2 (stmt);
    1404                 :       78149 :   tree res_vect_type = TREE_TYPE (gimple_assign_lhs (stmt));
    1405                 :       78149 :   tree vect_type = TREE_TYPE (vec0);
    1406                 :       78149 :   tree mask_type = TREE_TYPE (mask);
    1407                 :       78149 :   tree vect_elt_type = TREE_TYPE (vect_type);
    1408                 :       78149 :   tree mask_elt_type = TREE_TYPE (mask_type);
    1409                 :       78149 :   unsigned HOST_WIDE_INT elements;
    1410                 :       78149 :   vec<constructor_elt, va_gc> *v;
    1411                 :       78149 :   tree constr, t, si, i_val;
    1412                 :       78149 :   tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
    1413                 :       78149 :   bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
    1414                 :       78149 :   location_t loc = gimple_location (gsi_stmt (*gsi));
    1415                 :       78149 :   unsigned i;
    1416                 :             : 
    1417                 :       78149 :   if (!TYPE_VECTOR_SUBPARTS (res_vect_type).is_constant (&elements))
    1418                 :       69234 :     return;
    1419                 :             : 
    1420                 :       78149 :   if (TREE_CODE (mask) == SSA_NAME)
    1421                 :             :     {
    1422                 :         873 :       gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
    1423                 :         873 :       if (is_gimple_assign (def_stmt)
    1424                 :         873 :           && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
    1425                 :          12 :         mask = gimple_assign_rhs1 (def_stmt);
    1426                 :             :     }
    1427                 :             : 
    1428                 :       78149 :   vec_perm_builder sel_int;
    1429                 :             : 
    1430                 :       78149 :   if (TREE_CODE (mask) == VECTOR_CST
    1431                 :       78149 :       && tree_to_vec_perm_builder (&sel_int, mask))
    1432                 :             :     {
    1433                 :       77287 :       vec_perm_indices indices (sel_int, 2, elements);
    1434                 :       77287 :       machine_mode vmode = TYPE_MODE (vect_type);
    1435                 :       77287 :       tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
    1436                 :       77287 :       machine_mode lhs_mode = TYPE_MODE (lhs_type);
    1437                 :       77287 :       if (can_vec_perm_const_p (lhs_mode, vmode, indices))
    1438                 :             :         {
    1439                 :       69209 :           gimple_assign_set_rhs3 (stmt, mask);
    1440                 :       69209 :           update_stmt (stmt);
    1441                 :       69209 :           return;
    1442                 :             :         }
    1443                 :             :       /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
    1444                 :             :          vector as VEC1 and a right element shift MASK.  */
    1445                 :        8078 :       if (can_implement_p (vec_shr_optab, TYPE_MODE (vect_type))
    1446                 :        7321 :           && TREE_CODE (vec1) == VECTOR_CST
    1447                 :          13 :           && initializer_zerop (vec1)
    1448                 :          13 :           && maybe_ne (indices[0], 0)
    1449                 :       15399 :           && known_lt (poly_uint64 (indices[0]), elements))
    1450                 :             :         {
    1451                 :          10 :           bool ok_p = indices.series_p (0, 1, indices[0], 1);
    1452                 :          10 :           if (!ok_p)
    1453                 :             :             {
    1454                 :           1 :               for (i = 1; i < elements; ++i)
    1455                 :             :                 {
    1456                 :           1 :                   poly_uint64 actual = indices[i];
    1457                 :           1 :                   poly_uint64 expected = i + indices[0];
    1458                 :             :                   /* Indices into the second vector are all equivalent.  */
    1459                 :           1 :                   if (maybe_lt (actual, elements)
    1460                 :           1 :                       ? maybe_ne (actual, expected)
    1461                 :           1 :                       : maybe_lt (expected, elements))
    1462                 :             :                     break;
    1463                 :             :                 }
    1464                 :           1 :               ok_p = i == elements;
    1465                 :             :             }
    1466                 :           1 :           if (ok_p)
    1467                 :             :             {
    1468                 :           9 :               gimple_assign_set_rhs3 (stmt, mask);
    1469                 :           9 :               update_stmt (stmt);
    1470                 :           9 :               return;
    1471                 :             :             }
    1472                 :             :         }
    1473                 :             :       /* And similarly vec_shl pattern.  */
    1474                 :        8069 :       if (can_implement_p (vec_shl_optab, TYPE_MODE (vect_type))
    1475                 :        7312 :           && TREE_CODE (vec0) == VECTOR_CST
    1476                 :        8076 :           && initializer_zerop (vec0))
    1477                 :             :         {
    1478                 :             :           unsigned int first = 0;
    1479                 :          47 :           for (i = 0; i < elements; ++i)
    1480                 :          40 :             if (known_eq (poly_uint64 (indices[i]), elements))
    1481                 :             :               {
    1482                 :           5 :                 if (i == 0 || first)
    1483                 :             :                   break;
    1484                 :             :                 first = i;
    1485                 :             :               }
    1486                 :          70 :             else if (first
    1487                 :          70 :                      ? maybe_ne (poly_uint64 (indices[i]),
    1488                 :          14 :                                               elements + i - first)
    1489                 :          35 :                      : maybe_ge (poly_uint64 (indices[i]), elements))
    1490                 :             :               break;
    1491                 :           7 :           if (first && i == elements)
    1492                 :             :             {
    1493                 :           5 :               gimple_assign_set_rhs3 (stmt, mask);
    1494                 :           5 :               update_stmt (stmt);
    1495                 :           5 :               return;
    1496                 :             :             }
    1497                 :             :         }
    1498                 :       77287 :     }
    1499                 :         862 :   else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
    1500                 :             :     return;
    1501                 :             : 
    1502                 :        8915 :   if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
    1503                 :        8915 :     warning_at (loc, OPT_Wvector_operation_performance,
    1504                 :             :                 "vector shuffling operation will be expanded piecewise");
    1505                 :             : 
    1506                 :        8915 :   vec_alloc (v, elements);
    1507                 :        8915 :   bool constant_p = true;
    1508                 :       60027 :   for (i = 0; i < elements; i++)
    1509                 :             :     {
    1510                 :       51112 :       si = size_int (i);
    1511                 :       51112 :       i_val = vector_element (gsi, mask, si, &masktmp);
    1512                 :             : 
    1513                 :       51112 :       if (TREE_CODE (i_val) == INTEGER_CST)
    1514                 :             :         {
    1515                 :       46010 :           unsigned HOST_WIDE_INT index;
    1516                 :             : 
    1517                 :       46010 :           index = TREE_INT_CST_LOW (i_val);
    1518                 :       46010 :           if (!tree_fits_uhwi_p (i_val) || index >= elements)
    1519                 :       14358 :             i_val = build_int_cst (mask_elt_type, index & (elements - 1));
    1520                 :             : 
    1521                 :       46010 :           if (two_operand_p && (index & elements) != 0)
    1522                 :       14344 :             t = vector_element (gsi, vec1, i_val, &vec1tmp);
    1523                 :             :           else
    1524                 :       31666 :             t = vector_element (gsi, vec0, i_val, &vec0tmp);
    1525                 :             : 
    1526                 :       46010 :           t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
    1527                 :             :                                         true, GSI_SAME_STMT);
    1528                 :             :         }
    1529                 :             :       else
    1530                 :             :         {
    1531                 :        5102 :           tree cond = NULL_TREE, v0_val;
    1532                 :             : 
    1533                 :        5102 :           if (two_operand_p)
    1534                 :             :             {
    1535                 :        2475 :               cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
    1536                 :             :                                   build_int_cst (mask_elt_type, elements));
    1537                 :        2475 :               cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
    1538                 :             :                                                true, GSI_SAME_STMT);
    1539                 :             :             }
    1540                 :             : 
    1541                 :        5102 :           i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
    1542                 :             :                                build_int_cst (mask_elt_type, elements - 1));
    1543                 :        5102 :           i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
    1544                 :             :                                             true, GSI_SAME_STMT);
    1545                 :             : 
    1546                 :        5102 :           v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
    1547                 :        5102 :           v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
    1548                 :             :                                              true, GSI_SAME_STMT);
    1549                 :             : 
    1550                 :        5102 :           if (two_operand_p)
    1551                 :             :             {
    1552                 :        2475 :               tree v1_val;
    1553                 :             : 
    1554                 :        2475 :               v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
    1555                 :        2475 :               v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
    1556                 :             :                                                  true, GSI_SAME_STMT);
    1557                 :             : 
    1558                 :        2475 :               cond = fold_build2 (EQ_EXPR, boolean_type_node,
    1559                 :             :                                   cond, build_zero_cst (mask_elt_type));
    1560                 :        2475 :               cond = fold_build3 (COND_EXPR, vect_elt_type,
    1561                 :             :                                   cond, v0_val, v1_val);
    1562                 :        2475 :               t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
    1563                 :             :                                             true, GSI_SAME_STMT);
    1564                 :             :             }
    1565                 :             :           else
    1566                 :             :             t = v0_val;
    1567                 :             :         }
    1568                 :             : 
    1569                 :       51112 :       if (!CONSTANT_CLASS_P (t))
    1570                 :       49289 :         constant_p = false;
    1571                 :       51112 :       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
    1572                 :             :     }
    1573                 :             : 
    1574                 :        8915 :   if (constant_p)
    1575                 :           6 :     constr = build_vector_from_ctor (res_vect_type, v);
    1576                 :             :   else
    1577                 :        8909 :     constr = build_constructor (res_vect_type, v);
    1578                 :        8915 :   gimple_assign_set_rhs_from_tree (gsi, constr);
    1579                 :        8915 :   update_stmt (gsi_stmt (*gsi));
    1580                 :       78149 : }
    1581                 :             : 
    1582                 :             : /* If OP is a uniform vector return the element it is a splat from.  */
    1583                 :             : 
    1584                 :             : static tree
    1585                 :      243450 : ssa_uniform_vector_p (tree op)
    1586                 :             : {
    1587                 :      243450 :   if (TREE_CODE (op) == VECTOR_CST
    1588                 :             :       || TREE_CODE (op) == VEC_DUPLICATE_EXPR
    1589                 :             :       || TREE_CODE (op) == CONSTRUCTOR)
    1590                 :       12191 :     return uniform_vector_p (op);
    1591                 :             :   if (TREE_CODE (op) == SSA_NAME)
    1592                 :             :     {
    1593                 :      231259 :       gimple *def_stmt = SSA_NAME_DEF_STMT (op);
    1594                 :      231259 :       if (gimple_assign_single_p (def_stmt))
    1595                 :       95155 :         return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
    1596                 :             :     }
    1597                 :             :   return NULL_TREE;
    1598                 :             : }
    1599                 :             : 
    1600                 :             : /* Return the type that should be used to implement OP on type TYPE.
    1601                 :             :    This is TYPE itself if the target can do the operation directly,
    1602                 :             :    otherwise it is a scalar type or a smaller vector type.  */
    1603                 :             : 
    1604                 :             : static tree
    1605                 :      195433 : get_compute_type (optab op, tree type)
    1606                 :             : {
    1607                 :      195433 :   if (op)
    1608                 :             :     {
    1609                 :      351198 :       if (VECTOR_MODE_P (TYPE_MODE (type))
    1610                 :      349878 :           && can_implement_p (op, TYPE_MODE (type)))
    1611                 :             :         return type;
    1612                 :             : 
    1613                 :             :       /* For very wide vectors, try using a smaller vector mode.  */
    1614                 :        2573 :       tree vector_compute_type = type_for_widest_vector_mode (type, op);
    1615                 :        2573 :       if (vector_compute_type != NULL_TREE
    1616                 :        2573 :           && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
    1617                 :        3440 :           && can_implement_p (op, TYPE_MODE (vector_compute_type)))
    1618                 :         867 :         return vector_compute_type;
    1619                 :             :     }
    1620                 :             : 
    1621                 :             :   /* There is no operation in hardware, so fall back to scalars.  */
    1622                 :       21540 :   return TREE_TYPE (type);
    1623                 :             : }
    1624                 :             : 
    1625                 :             : static tree
    1626                 :          14 : do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
    1627                 :             :          tree bitpos, tree bitsize, enum tree_code code,
    1628                 :             :          tree type ATTRIBUTE_UNUSED)
    1629                 :             : {
    1630                 :          14 :   if (VECTOR_TYPE_P (TREE_TYPE (a)))
    1631                 :          14 :     a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
    1632                 :          14 :   if (VECTOR_TYPE_P (TREE_TYPE (b)))
    1633                 :          14 :     b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
    1634                 :          14 :   tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
    1635                 :          14 :   return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
    1636                 :             : }
    1637                 :             : 
    1638                 :             : /* Expand a vector COND_EXPR to scalars, piecewise.  */
    1639                 :             : static void
    1640                 :           7 : expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
    1641                 :             : {
    1642                 :           7 :   gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
    1643                 :           7 :   tree lhs = gimple_assign_lhs (stmt);
    1644                 :           7 :   tree type = TREE_TYPE (lhs);
    1645                 :           7 :   tree compute_type = get_compute_type (mov_optab, type);
    1646                 :           7 :   machine_mode compute_mode = TYPE_MODE (compute_type);
    1647                 :           7 :   gcc_assert (compute_mode != BLKmode);
    1648                 :           7 :   tree rhs2 = gimple_assign_rhs2 (stmt);
    1649                 :           7 :   tree rhs3 = gimple_assign_rhs3 (stmt);
    1650                 :           7 :   tree new_rhs;
    1651                 :             : 
    1652                 :             :   /* If the compute mode is not a vector mode (hence we are not decomposing
    1653                 :             :      a BLKmode vector to smaller, hardware-supported vectors), we may want
    1654                 :             :      to expand the operations in parallel.  */
    1655                 :           7 :   if (!VECTOR_MODE_P (compute_mode))
    1656                 :           0 :     new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
    1657                 :             :                                       COND_EXPR);
    1658                 :             :   else
    1659                 :           7 :     new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
    1660                 :             :                                        rhs2, rhs3, COND_EXPR, false);
    1661                 :           7 :   if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
    1662                 :           0 :     new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
    1663                 :             :                                new_rhs);
    1664                 :             : 
    1665                 :             :   /* NOTE:  We should avoid using gimple_assign_set_rhs_from_tree. One
    1666                 :             :      way to do it is change expand_vector_operation and its callees to
    1667                 :             :      return a tree_code, RHS1 and RHS2 instead of a tree. */
    1668                 :           7 :   gimple_assign_set_rhs_from_tree (gsi, new_rhs);
    1669                 :           7 :   update_stmt (gsi_stmt (*gsi));
    1670                 :           7 : }
    1671                 :             : 
    1672                 :             : /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
    1673                 :             :    lowering.  If INNER_TYPE is not a vector type, this is a scalar
    1674                 :             :    fallback.  */
    1675                 :             : 
    1676                 :             : static tree
    1677                 :       17980 : do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
    1678                 :             :                    tree decl, tree bitpos, tree bitsize,
    1679                 :             :                    enum tree_code code, tree type)
    1680                 :             : {
    1681                 :       17980 :   a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
    1682                 :       17980 :   if (!VECTOR_TYPE_P (inner_type))
    1683                 :       17980 :     return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
    1684                 :           0 :   if (code == CALL_EXPR)
    1685                 :             :     {
    1686                 :           0 :       gimple *g = gimple_build_call (decl, 1, a);
    1687                 :           0 :       tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
    1688                 :           0 :       gimple_call_set_lhs (g, lhs);
    1689                 :           0 :       gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1690                 :           0 :       return lhs;
    1691                 :             :     }
    1692                 :             :   else
    1693                 :             :     {
    1694                 :           0 :       tree outer_type = build_vector_type (TREE_TYPE (type),
    1695                 :           0 :                                            TYPE_VECTOR_SUBPARTS (inner_type));
    1696                 :           0 :       return gimplify_build1 (gsi, code, outer_type, a);
    1697                 :             :     }
    1698                 :             : }
    1699                 :             : 
    1700                 :             : /* Similarly, but for narrowing conversion.  */
    1701                 :             : 
    1702                 :             : static tree
    1703                 :          29 : do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
    1704                 :             :                           tree, tree bitpos, tree, enum tree_code code,
    1705                 :             :                           tree type)
    1706                 :             : {
    1707                 :          29 :   tree itype = build_vector_type (TREE_TYPE (inner_type),
    1708                 :          29 :                                   exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
    1709                 :             :                                              2));
    1710                 :          29 :   tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
    1711                 :          29 :   tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
    1712                 :             :                              int_const_binop (PLUS_EXPR, bitpos,
    1713                 :          29 :                                               TYPE_SIZE (itype)));
    1714                 :          29 :   tree outer_type = build_vector_type (TREE_TYPE (type),
    1715                 :          29 :                                        TYPE_VECTOR_SUBPARTS (inner_type));
    1716                 :          29 :   return gimplify_build2 (gsi, code, outer_type, b, c);
    1717                 :             : }
    1718                 :             : 
    1719                 :             : /* Expand VEC_CONVERT ifn call.  */
    1720                 :             : 
    1721                 :             : static void
    1722                 :         448 : expand_vector_conversion (gimple_stmt_iterator *gsi)
    1723                 :             : {
    1724                 :         448 :   gimple *stmt = gsi_stmt (*gsi);
    1725                 :         448 :   gimple *g;
    1726                 :         448 :   tree lhs = gimple_call_lhs (stmt);
    1727                 :         448 :   if (lhs == NULL_TREE)
    1728                 :             :     {
    1729                 :           1 :       g = gimple_build_nop ();
    1730                 :           1 :       gsi_replace (gsi, g, false);
    1731                 :         365 :       return;
    1732                 :             :     }
    1733                 :         447 :   tree arg = gimple_call_arg (stmt, 0);
    1734                 :         447 :   tree ret_type = TREE_TYPE (lhs);
    1735                 :         447 :   tree arg_type = TREE_TYPE (arg);
    1736                 :         447 :   tree new_rhs, new_lhs, compute_type = TREE_TYPE (arg_type);
    1737                 :         447 :   enum tree_code code = NOP_EXPR;
    1738                 :         447 :   enum tree_code code1 = ERROR_MARK;
    1739                 :         447 :   enum { NARROW, NONE, WIDEN } modifier = NONE;
    1740                 :         447 :   optab optab1 = unknown_optab;
    1741                 :             : 
    1742                 :         447 :   gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
    1743                 :         894 :   if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
    1744                 :         719 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
    1745                 :             :     code = FIX_TRUNC_EXPR;
    1746                 :         588 :   else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
    1747                 :         537 :            && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
    1748                 :             :     code = FLOAT_EXPR;
    1749                 :         447 :   unsigned int ret_elt_bits = vector_element_bits (ret_type);
    1750                 :         447 :   unsigned int arg_elt_bits = vector_element_bits (arg_type);
    1751                 :         447 :   if (ret_elt_bits < arg_elt_bits)
    1752                 :             :     modifier = NARROW;
    1753                 :         255 :   else if (ret_elt_bits > arg_elt_bits)
    1754                 :         113 :     modifier = WIDEN;
    1755                 :             : 
    1756                 :         447 :   auto_vec<std::pair<tree, tree_code> > converts;
    1757                 :         447 :   if (supportable_indirect_convert_operation (code,
    1758                 :             :                                               ret_type, arg_type,
    1759                 :             :                                               &converts,
    1760                 :             :                                               arg))
    1761                 :             :     {
    1762                 :             :       new_rhs = arg;
    1763                 :         660 :       for (unsigned int i = 0; i < converts.length () - 1; i++)
    1764                 :             :         {
    1765                 :          48 :           new_lhs = make_ssa_name (converts[i].first);
    1766                 :          48 :           g = gimple_build_assign (new_lhs, converts[i].second, new_rhs);
    1767                 :          48 :           new_rhs = new_lhs;
    1768                 :          48 :           gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1769                 :             :         }
    1770                 :         846 :       g = gimple_build_assign (lhs,
    1771                 :         282 :                                converts[converts.length() - 1].second,
    1772                 :             :                                new_rhs);
    1773                 :         282 :       gsi_replace (gsi, g, false);
    1774                 :         282 :       return;
    1775                 :             :     }
    1776                 :             : 
    1777                 :         165 :   if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
    1778                 :             :     {
    1779                 :             :       /* Can't use get_compute_type here, as supportable_convert_operation
    1780                 :             :          doesn't necessarily use an optab and needs two arguments.  */
    1781                 :          71 :       tree vec_compute_type
    1782                 :          71 :         = type_for_widest_vector_mode (arg_type, mov_optab);
    1783                 :          71 :       if (vec_compute_type
    1784                 :          71 :           && VECTOR_MODE_P (TYPE_MODE (vec_compute_type)))
    1785                 :             :         {
    1786                 :          71 :           unsigned HOST_WIDE_INT nelts
    1787                 :          71 :             = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
    1788                 :         144 :           while (nelts > 1)
    1789                 :             :             {
    1790                 :          73 :               tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
    1791                 :          73 :               tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
    1792                 :          73 :               if (supportable_convert_operation (code, ret1_type, arg1_type,
    1793                 :             :                                                  &code1))
    1794                 :             :                 {
    1795                 :           0 :                   new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
    1796                 :             :                                                      ret_type, arg1_type, arg,
    1797                 :             :                                                      NULL_TREE, code1, false);
    1798                 :           0 :                   g = gimple_build_assign (lhs, new_rhs);
    1799                 :           0 :                   gsi_replace (gsi, g, false);
    1800                 :           0 :                   return;
    1801                 :             :                 }
    1802                 :          73 :               nelts = nelts / 2;
    1803                 :             :             }
    1804                 :             :         }
    1805                 :             :     }
    1806                 :          94 :   else if (modifier == NARROW)
    1807                 :             :     {
    1808                 :          59 :       switch (code)
    1809                 :             :         {
    1810                 :          29 :         CASE_CONVERT:
    1811                 :          29 :           code1 = VEC_PACK_TRUNC_EXPR;
    1812                 :          29 :           optab1 = optab_for_tree_code (code1, arg_type, optab_default);
    1813                 :          29 :           break;
    1814                 :          26 :         case FIX_TRUNC_EXPR:
    1815                 :          26 :           code1 = VEC_PACK_FIX_TRUNC_EXPR;
    1816                 :             :           /* The signedness is determined from output operand.  */
    1817                 :          26 :           optab1 = optab_for_tree_code (code1, ret_type, optab_default);
    1818                 :          26 :           break;
    1819                 :           4 :         case FLOAT_EXPR:
    1820                 :           4 :           code1 = VEC_PACK_FLOAT_EXPR;
    1821                 :           4 :           optab1 = optab_for_tree_code (code1, arg_type, optab_default);
    1822                 :           4 :           break;
    1823                 :           0 :         default:
    1824                 :           0 :           gcc_unreachable ();
    1825                 :             :         }
    1826                 :             : 
    1827                 :          59 :       if (optab1)
    1828                 :          59 :         compute_type = get_compute_type (optab1, arg_type);
    1829                 :          59 :       enum insn_code icode1;
    1830                 :          59 :       if (VECTOR_TYPE_P (compute_type)
    1831                 :          54 :           && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
    1832                 :             :               != CODE_FOR_nothing)
    1833                 :         113 :           && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
    1834                 :             :         {
    1835                 :          54 :           tree cretd_type
    1836                 :          54 :             = build_vector_type (TREE_TYPE (ret_type),
    1837                 :          54 :                                  TYPE_VECTOR_SUBPARTS (compute_type) * 2);
    1838                 :          54 :           if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
    1839                 :             :             {
    1840                 :          52 :               if (compute_type == arg_type)
    1841                 :             :                 {
    1842                 :          23 :                   new_rhs = gimplify_build2 (gsi, code1, cretd_type,
    1843                 :             :                                              arg, build_zero_cst (arg_type));
    1844                 :          23 :                   new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
    1845                 :          23 :                                               TYPE_SIZE (ret_type),
    1846                 :          23 :                                               bitsize_int (0));
    1847                 :          23 :                   g = gimple_build_assign (lhs, new_rhs);
    1848                 :          23 :                   gsi_replace (gsi, g, false);
    1849                 :          23 :                   return;
    1850                 :             :                 }
    1851                 :          29 :               tree dcompute_type
    1852                 :          29 :                 = build_vector_type (TREE_TYPE (compute_type),
    1853                 :          29 :                                      TYPE_VECTOR_SUBPARTS (compute_type) * 2);
    1854                 :          29 :               if (TYPE_MAIN_VARIANT (dcompute_type)
    1855                 :          29 :                   == TYPE_MAIN_VARIANT (arg_type))
    1856                 :          27 :                 new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
    1857                 :          27 :                                                     NULL_TREE, bitsize_int (0),
    1858                 :             :                                                     NULL_TREE, code1,
    1859                 :             :                                                     ret_type);
    1860                 :             :               else
    1861                 :           2 :                 new_rhs = expand_vector_piecewise (gsi,
    1862                 :             :                                                    do_vec_narrow_conversion,
    1863                 :             :                                                    arg_type, dcompute_type,
    1864                 :             :                                                    arg, NULL_TREE, code1,
    1865                 :             :                                                    false, ret_type);
    1866                 :          29 :               g = gimple_build_assign (lhs, new_rhs);
    1867                 :          29 :               gsi_replace (gsi, g, false);
    1868                 :          29 :               return;
    1869                 :             :             }
    1870                 :             :         }
    1871                 :             :     }
    1872                 :          35 :   else if (modifier == WIDEN)
    1873                 :             :     {
    1874                 :          32 :       enum tree_code code2 = ERROR_MARK;
    1875                 :          32 :       optab optab2 = unknown_optab;
    1876                 :          32 :       switch (code)
    1877                 :             :         {
    1878                 :           2 :         CASE_CONVERT:
    1879                 :           2 :           code1 = VEC_UNPACK_LO_EXPR;
    1880                 :           2 :           code2 = VEC_UNPACK_HI_EXPR;
    1881                 :           2 :           break;
    1882                 :           0 :         case FIX_TRUNC_EXPR:
    1883                 :           0 :           code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
    1884                 :           0 :           code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
    1885                 :           0 :           break;
    1886                 :          30 :         case FLOAT_EXPR:
    1887                 :          30 :           code1 = VEC_UNPACK_FLOAT_LO_EXPR;
    1888                 :          30 :           code2 = VEC_UNPACK_FLOAT_HI_EXPR;
    1889                 :          30 :           break;
    1890                 :           0 :         default:
    1891                 :           0 :           gcc_unreachable ();
    1892                 :             :         }
    1893                 :          32 :       if (BYTES_BIG_ENDIAN)
    1894                 :             :         std::swap (code1, code2);
    1895                 :             : 
    1896                 :          32 :       if (code == FIX_TRUNC_EXPR)
    1897                 :             :         {
    1898                 :             :           /* The signedness is determined from output operand.  */
    1899                 :           0 :           optab1 = optab_for_tree_code (code1, ret_type, optab_default);
    1900                 :           0 :           optab2 = optab_for_tree_code (code2, ret_type, optab_default);
    1901                 :             :         }
    1902                 :             :       else
    1903                 :             :         {
    1904                 :          32 :           optab1 = optab_for_tree_code (code1, arg_type, optab_default);
    1905                 :          32 :           optab2 = optab_for_tree_code (code2, arg_type, optab_default);
    1906                 :             :         }
    1907                 :             : 
    1908                 :          32 :       if (optab1 && optab2)
    1909                 :          32 :         compute_type = get_compute_type (optab1, arg_type);
    1910                 :             : 
    1911                 :          32 :       enum insn_code icode1, icode2;
    1912                 :          32 :       if (VECTOR_TYPE_P (compute_type)
    1913                 :          29 :           && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
    1914                 :             :               != CODE_FOR_nothing)
    1915                 :          29 :           && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
    1916                 :             :               != CODE_FOR_nothing)
    1917                 :          29 :           && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
    1918                 :          32 :           && (insn_data[icode1].operand[0].mode
    1919                 :          29 :               == insn_data[icode2].operand[0].mode))
    1920                 :             :         {
    1921                 :          29 :           poly_uint64 nunits
    1922                 :          29 :             = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
    1923                 :          29 :           tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
    1924                 :          29 :           if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
    1925                 :             :             {
    1926                 :          29 :               vec<constructor_elt, va_gc> *v;
    1927                 :          29 :               tree part_width = TYPE_SIZE (compute_type);
    1928                 :          29 :               tree index = bitsize_int (0);
    1929                 :          29 :               int nunits = nunits_for_known_piecewise_op (arg_type);
    1930                 :          29 :               int delta = tree_to_uhwi (part_width) / arg_elt_bits;
    1931                 :          29 :               int i;
    1932                 :          29 :               location_t loc = gimple_location (gsi_stmt (*gsi));
    1933                 :             : 
    1934                 :          29 :               if (compute_type != arg_type)
    1935                 :             :                 {
    1936                 :           0 :                   if (!warning_suppressed_p (gsi_stmt (*gsi),
    1937                 :             :                                              OPT_Wvector_operation_performance))
    1938                 :           0 :                     warning_at (loc, OPT_Wvector_operation_performance,
    1939                 :             :                                 "vector operation will be expanded piecewise");
    1940                 :             :                 }
    1941                 :             :               else
    1942                 :             :                 {
    1943                 :             :                   nunits = 1;
    1944                 :             :                   delta = 1;
    1945                 :             :                 }
    1946                 :             : 
    1947                 :          29 :               vec_alloc (v, (nunits + delta - 1) / delta * 2);
    1948                 :          29 :               bool constant_p = true;
    1949                 :          58 :               for (i = 0; i < nunits;
    1950                 :          29 :                    i += delta, index = int_const_binop (PLUS_EXPR, index,
    1951                 :             :                                                         part_width))
    1952                 :             :                 {
    1953                 :          29 :                   tree a = arg;
    1954                 :          29 :                   if (compute_type != arg_type)
    1955                 :           0 :                     a = tree_vec_extract (gsi, compute_type, a, part_width,
    1956                 :             :                                           index);
    1957                 :          29 :                   tree result = gimplify_build1 (gsi, code1, cretd_type, a);
    1958                 :          29 :                   constructor_elt ce = { NULL_TREE, result };
    1959                 :          29 :                   if (!CONSTANT_CLASS_P (ce.value))
    1960                 :          29 :                     constant_p = false;
    1961                 :          29 :                   v->quick_push (ce);
    1962                 :          29 :                   ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
    1963                 :          29 :                   if (!CONSTANT_CLASS_P (ce.value))
    1964                 :          29 :                     constant_p = false;
    1965                 :          29 :                   v->quick_push (ce);
    1966                 :             :                 }
    1967                 :             : 
    1968                 :          29 :               if (constant_p)
    1969                 :           0 :                 new_rhs = build_vector_from_ctor (ret_type, v);
    1970                 :             :               else
    1971                 :          29 :                 new_rhs = build_constructor (ret_type, v);
    1972                 :          29 :               g = gimple_build_assign (lhs, new_rhs);
    1973                 :          29 :               gsi_replace (gsi, g, false);
    1974                 :          29 :               return;
    1975                 :             :             }
    1976                 :             :         }
    1977                 :             :     }
    1978                 :             : 
    1979                 :          84 :   new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
    1980                 :          84 :                                      TREE_TYPE (arg_type), arg,
    1981                 :             :                                      NULL_TREE, code, false, ret_type);
    1982                 :          84 :   g = gimple_build_assign (lhs, new_rhs);
    1983                 :          84 :   gsi_replace (gsi, g, false);
    1984                 :         447 : }
    1985                 :             : 
    1986                 :             : /* Process one statement.  If we identify a vector operation, expand it.  */
    1987                 :             : 
    1988                 :             : static void
    1989                 :    87652530 : expand_vector_operations_1 (gimple_stmt_iterator *gsi)
    1990                 :             : {
    1991                 :    87652530 :   tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
    1992                 :    87652530 :   enum tree_code code;
    1993                 :    87652530 :   optab op = unknown_optab;
    1994                 :    87652530 :   enum gimple_rhs_class rhs_class;
    1995                 :    87652530 :   tree new_rhs;
    1996                 :             : 
    1997                 :             :   /* Only consider code == GIMPLE_ASSIGN. */
    1998                 :    87652530 :   gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
    1999                 :    87652530 :   if (!stmt)
    2000                 :             :     {
    2001                 :    55288681 :       if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
    2002                 :         448 :         expand_vector_conversion (gsi);
    2003                 :    55288681 :       return;
    2004                 :             :     }
    2005                 :             : 
    2006                 :    32363849 :   code = gimple_assign_rhs_code (stmt);
    2007                 :    32363849 :   rhs_class = get_gimple_rhs_class (code);
    2008                 :    32363849 :   lhs = gimple_assign_lhs (stmt);
    2009                 :             : 
    2010                 :    32363849 :   if (code == VEC_PERM_EXPR)
    2011                 :             :     {
    2012                 :       78149 :       lower_vec_perm (gsi);
    2013                 :       78149 :       return;
    2014                 :             :     }
    2015                 :             : 
    2016                 :    32285700 :   if (code == VEC_COND_EXPR)
    2017                 :             :     {
    2018                 :       17315 :       expand_vector_condition (gsi);
    2019                 :       17315 :       return;
    2020                 :             :     }
    2021                 :             : 
    2022                 :    32268385 :   if (code == COND_EXPR
    2023                 :       12699 :       && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
    2024                 :    32268392 :       && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
    2025                 :             :     {
    2026                 :           7 :       expand_vector_scalar_condition (gsi);
    2027                 :           7 :       return;
    2028                 :             :     }
    2029                 :             : 
    2030                 :    32268378 :   if (code == CONSTRUCTOR
    2031                 :     1852092 :       && TREE_CODE (lhs) == SSA_NAME
    2032                 :      173826 :       && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
    2033                 :      173307 :       && !gimple_clobber_p (stmt)
    2034                 :    32441685 :       && optimize)
    2035                 :             :     {
    2036                 :      171242 :       optimize_vector_constructor (gsi);
    2037                 :      171242 :       return;
    2038                 :             :     }
    2039                 :             : 
    2040                 :    32097136 :   if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
    2041                 :             :     return;
    2042                 :             : 
    2043                 :    11820758 :   rhs1 = gimple_assign_rhs1 (stmt);
    2044                 :    11820758 :   if (rhs_class == GIMPLE_BINARY_RHS)
    2045                 :     7889273 :     rhs2 = gimple_assign_rhs2 (stmt);
    2046                 :             : 
    2047                 :    11820758 :   type = TREE_TYPE (lhs);
    2048                 :    11820758 :   if (!VECTOR_TYPE_P (type)
    2049                 :    11820758 :       || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
    2050                 :             :     return;
    2051                 :             : 
    2052                 :             :   /* A scalar operation pretending to be a vector one.  */
    2053                 :      229258 :   if (VECTOR_BOOLEAN_TYPE_P (type)
    2054                 :       26580 :       && !VECTOR_MODE_P (TYPE_MODE (type))
    2055                 :        8016 :       && TYPE_MODE (type) != BLKmode
    2056                 :        7714 :       && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
    2057                 :        4709 :           || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
    2058                 :           0 :               && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
    2059                 :           0 :               && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
    2060                 :        3005 :     return;
    2061                 :             : 
    2062                 :             :   /* If the vector operation is operating on all same vector elements
    2063                 :             :      implement it with a scalar operation and a splat if the target
    2064                 :             :      supports the scalar operation.  */
    2065                 :      226253 :   tree srhs1, srhs2 = NULL_TREE;
    2066                 :      226253 :   if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
    2067                 :       16257 :       && (rhs2 == NULL_TREE
    2068                 :       15882 :           || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
    2069                 :             :               && (srhs2 = rhs2))
    2070                 :       15822 :           || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
    2071                 :             :       /* As we query direct optabs restrict to non-convert operations.  */
    2072                 :      227718 :       && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
    2073                 :             :     {
    2074                 :        1188 :       op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
    2075                 :        1188 :       if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
    2076                 :        1188 :           && can_implement_p (op, TYPE_MODE (TREE_TYPE (type))))
    2077                 :             :         {
    2078                 :         900 :           tree stype = TREE_TYPE (TREE_TYPE (lhs));
    2079                 :         900 :           tree slhs = (rhs2 != NULL_TREE)
    2080                 :         900 :                       ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
    2081                 :          93 :                       : gimplify_build1 (gsi, code, stype, srhs1);
    2082                 :         900 :           gimple_assign_set_rhs_from_tree (gsi,
    2083                 :             :                                            build_vector_from_val (type, slhs));
    2084                 :         900 :           update_stmt (stmt);
    2085                 :         900 :           return;
    2086                 :             :         }
    2087                 :             :     }
    2088                 :             : 
    2089                 :             :   /* Plain moves do not need lowering.  */
    2090                 :      225353 :   if (code == SSA_NAME
    2091                 :      225353 :       || code == VIEW_CONVERT_EXPR
    2092                 :             :       || code == PAREN_EXPR)
    2093                 :             :     return;
    2094                 :             : 
    2095                 :             :   if (CONVERT_EXPR_CODE_P (code)
    2096                 :             :       || code == FLOAT_EXPR
    2097                 :             :       || code == FIX_TRUNC_EXPR)
    2098                 :             :     return;
    2099                 :             : 
    2100                 :             :   /* The signedness is determined from input argument.  */
    2101                 :             :   if (code == VEC_UNPACK_FLOAT_HI_EXPR
    2102                 :             :       || code == VEC_UNPACK_FLOAT_LO_EXPR
    2103                 :             :       || code == VEC_PACK_FLOAT_EXPR)
    2104                 :             :     {
    2105                 :             :       /* We do not know how to scalarize those.  */
    2106                 :             :       return;
    2107                 :             :     }
    2108                 :             : 
    2109                 :             :   /* For widening/narrowing vector operations, the relevant type is of the
    2110                 :             :      arguments, not the widened result.  VEC_UNPACK_FLOAT_*_EXPR is
    2111                 :             :      calculated in the same way above.  */
    2112                 :             :   if (code == WIDEN_SUM_EXPR
    2113                 :             :       || code == VEC_WIDEN_MULT_HI_EXPR
    2114                 :             :       || code == VEC_WIDEN_MULT_LO_EXPR
    2115                 :             :       || code == VEC_WIDEN_MULT_EVEN_EXPR
    2116                 :             :       || code == VEC_WIDEN_MULT_ODD_EXPR
    2117                 :             :       || code == VEC_UNPACK_HI_EXPR
    2118                 :             :       || code == VEC_UNPACK_LO_EXPR
    2119                 :             :       || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
    2120                 :             :       || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
    2121                 :             :       || code == VEC_PACK_TRUNC_EXPR
    2122                 :             :       || code == VEC_PACK_SAT_EXPR
    2123                 :             :       || code == VEC_PACK_FIX_TRUNC_EXPR
    2124                 :             :       || code == VEC_WIDEN_LSHIFT_HI_EXPR
    2125                 :             :       || code == VEC_WIDEN_LSHIFT_LO_EXPR)
    2126                 :             :     {
    2127                 :             :       /* We do not know how to scalarize those.  */
    2128                 :             :       return;
    2129                 :             :     }
    2130                 :             : 
    2131                 :             :   /* Choose between vector shift/rotate by vector and vector shift/rotate by
    2132                 :             :      scalar */
    2133                 :             :   if (code == LSHIFT_EXPR
    2134                 :             :       || code == RSHIFT_EXPR
    2135                 :             :       || code == LROTATE_EXPR
    2136                 :             :       || code == RROTATE_EXPR)
    2137                 :             :     {
    2138                 :        8423 :       optab opv;
    2139                 :             : 
    2140                 :             :       /* Check whether we have vector <op> {x,x,x,x} where x
    2141                 :             :          could be a scalar variable or a constant.  Transform
    2142                 :             :          vector <op> {x,x,x,x} ==> vector <op> scalar.  */
    2143                 :        8423 :       if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
    2144                 :             :         {
    2145                 :        1375 :           tree first;
    2146                 :             : 
    2147                 :        1375 :           if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
    2148                 :             :             {
    2149                 :           7 :               gimple_assign_set_rhs2 (stmt, first);
    2150                 :           7 :               update_stmt (stmt);
    2151                 :           7 :               rhs2 = first;
    2152                 :             :             }
    2153                 :             :         }
    2154                 :             : 
    2155                 :        8423 :       opv = optab_for_tree_code (code, type, optab_vector);
    2156                 :        8423 :       if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
    2157                 :             :         op = opv;
    2158                 :             :       else
    2159                 :             :         {
    2160                 :        7055 :           op = optab_for_tree_code (code, type, optab_scalar);
    2161                 :             : 
    2162                 :        7055 :           compute_type = get_compute_type (op, type);
    2163                 :        7055 :           if (compute_type == type)
    2164                 :             :             return;
    2165                 :             :           /* The rtl expander will expand vector/scalar as vector/vector
    2166                 :             :              if necessary.  Pick one with wider vector type.  */
    2167                 :         172 :           tree compute_vtype = get_compute_type (opv, type);
    2168                 :         172 :           if (subparts_gt (compute_vtype, compute_type))
    2169                 :             :             {
    2170                 :           0 :               compute_type = compute_vtype;
    2171                 :           0 :               op = opv;
    2172                 :             :             }
    2173                 :             :         }
    2174                 :             : 
    2175                 :        1540 :       if (code == LROTATE_EXPR || code == RROTATE_EXPR)
    2176                 :             :         {
    2177                 :          34 :           if (compute_type == NULL_TREE)
    2178                 :           1 :             compute_type = get_compute_type (op, type);
    2179                 :          34 :           if (compute_type == type)
    2180                 :             :             return;
    2181                 :             :           /* Before splitting vector rotates into scalar rotates,
    2182                 :             :              see if we can't use vector shifts and BIT_IOR_EXPR
    2183                 :             :              instead.  For vector by vector rotates we'd also
    2184                 :             :              need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
    2185                 :             :              for now, fold doesn't seem to create such rotates anyway.  */
    2186                 :          33 :           if (compute_type == TREE_TYPE (type)
    2187                 :          33 :               && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
    2188                 :             :             {
    2189                 :          30 :               optab oplv = vashl_optab, opl = ashl_optab;
    2190                 :          30 :               optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
    2191                 :          30 :               tree compute_lvtype = get_compute_type (oplv, type);
    2192                 :          30 :               tree compute_rvtype = get_compute_type (oprv, type);
    2193                 :          30 :               tree compute_otype = get_compute_type (opo, type);
    2194                 :          30 :               tree compute_ltype = get_compute_type (opl, type);
    2195                 :          30 :               tree compute_rtype = get_compute_type (opr, type);
    2196                 :             :               /* The rtl expander will expand vector/scalar as vector/vector
    2197                 :             :                  if necessary.  Pick one with wider vector type.  */
    2198                 :          30 :               if (subparts_gt (compute_lvtype, compute_ltype))
    2199                 :             :                 {
    2200                 :           0 :                   compute_ltype = compute_lvtype;
    2201                 :           0 :                   opl = oplv;
    2202                 :             :                 }
    2203                 :          30 :               if (subparts_gt (compute_rvtype, compute_rtype))
    2204                 :             :                 {
    2205                 :           0 :                   compute_rtype = compute_rvtype;
    2206                 :           0 :                   opr = oprv;
    2207                 :             :                 }
    2208                 :             :               /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
    2209                 :             :                  BIT_IOR_EXPR.  */
    2210                 :          30 :               compute_type = compute_ltype;
    2211                 :          30 :               if (subparts_gt (compute_type, compute_rtype))
    2212                 :           0 :                 compute_type = compute_rtype;
    2213                 :          30 :               if (subparts_gt (compute_type, compute_otype))
    2214                 :           0 :                 compute_type = compute_otype;
    2215                 :             :               /* Verify all 3 operations can be performed in that type.  */
    2216                 :          30 :               if (compute_type != TREE_TYPE (type))
    2217                 :             :                 {
    2218                 :          30 :                   if (!can_implement_p (opl, TYPE_MODE (compute_type))
    2219                 :          30 :                       || !can_implement_p (opr, TYPE_MODE (compute_type))
    2220                 :          60 :                       || !can_implement_p (opo, TYPE_MODE (compute_type)))
    2221                 :           0 :                     compute_type = TREE_TYPE (type);
    2222                 :             :                 }
    2223                 :             :             }
    2224                 :             :         }
    2225                 :             :     }
    2226                 :             :   else
    2227                 :      186590 :     op = optab_for_tree_code (code, type, optab_default);
    2228                 :             : 
    2229                 :             :   /* Optabs will try converting a negation into a subtraction, so
    2230                 :             :      look for it as well.  TODO: negation of floating-point vectors
    2231                 :             :      might be turned into an exclusive OR toggling the sign bit.  */
    2232                 :      188129 :   if (op == unknown_optab
    2233                 :      188129 :       && code == NEGATE_EXPR
    2234                 :      188129 :       && INTEGRAL_TYPE_P (TREE_TYPE (type)))
    2235                 :           0 :     op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
    2236                 :             : 
    2237                 :      188129 :   if (compute_type == NULL_TREE)
    2238                 :      187957 :     compute_type = get_compute_type (op, type);
    2239                 :      188129 :   if (compute_type == type)
    2240                 :             :     return;
    2241                 :             : 
    2242                 :       22127 :   new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
    2243                 :             : 
    2244                 :             :   /* Leave expression untouched for later expansion.  */
    2245                 :       22127 :   if (new_rhs == NULL_TREE)
    2246                 :             :     return;
    2247                 :             : 
    2248                 :        2859 :   if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
    2249                 :          85 :     new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
    2250                 :             :                                new_rhs);
    2251                 :             : 
    2252                 :             :   /* NOTE:  We should avoid using gimple_assign_set_rhs_from_tree. One
    2253                 :             :      way to do it is change expand_vector_operation and its callees to
    2254                 :             :      return a tree_code, RHS1 and RHS2 instead of a tree. */
    2255                 :        2859 :   gimple_assign_set_rhs_from_tree (gsi, new_rhs);
    2256                 :        2859 :   update_stmt (gsi_stmt (*gsi));
    2257                 :             : }
    2258                 :             : 
    2259                 :             : /* Use this to lower vector operations introduced by the vectorizer,
    2260                 :             :    if it may need the bit-twiddling tricks implemented in this file.  */
    2261                 :             : 
    2262                 :             : static unsigned int
    2263                 :     1487391 : expand_vector_operations (void)
    2264                 :             : {
    2265                 :     1487391 :   gimple_stmt_iterator gsi;
    2266                 :     1487391 :   basic_block bb;
    2267                 :     1487391 :   bool cfg_changed = false;
    2268                 :             : 
    2269                 :    15948797 :   FOR_EACH_BB_FN (bb, cfun)
    2270                 :             :     {
    2271                 :   116575342 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    2272                 :             :         {
    2273                 :    87652530 :           expand_vector_operations_1 (&gsi);
    2274                 :             :           /* ???  If we do not cleanup EH then we will ICE in
    2275                 :             :              verification.  But in reality we have created wrong-code
    2276                 :             :              as we did not properly transition EH info and edges to
    2277                 :             :              the piecewise computations.  */
    2278                 :    87652530 :           if (maybe_clean_eh_stmt (gsi_stmt (gsi))
    2279                 :    87652530 :               && gimple_purge_dead_eh_edges (bb))
    2280                 :             :             cfg_changed = true;
    2281                 :             :           /* If a .LOOP_DIST_ALIAS call prevailed loops got elided
    2282                 :             :              before vectorization got a chance to get at them.  Simply
    2283                 :             :              fold as if loop distribution wasn't performed.  */
    2284                 :    87652530 :           if (gimple_call_internal_p (gsi_stmt (gsi), IFN_LOOP_DIST_ALIAS))
    2285                 :             :             {
    2286                 :           2 :               fold_loop_internal_call (gsi_stmt (gsi), boolean_false_node);
    2287                 :           2 :               cfg_changed = true;
    2288                 :             :             }
    2289                 :             :         }
    2290                 :             :     }
    2291                 :             : 
    2292                 :     1487391 :   return cfg_changed ? TODO_cleanup_cfg : 0;
    2293                 :             : }
    2294                 :             : 
    2295                 :             : namespace {
    2296                 :             : 
    2297                 :             : const pass_data pass_data_lower_vector =
    2298                 :             : {
    2299                 :             :   GIMPLE_PASS, /* type */
    2300                 :             :   "veclower", /* name */
    2301                 :             :   OPTGROUP_VEC, /* optinfo_flags */
    2302                 :             :   TV_NONE, /* tv_id */
    2303                 :             :   PROP_cfg, /* properties_required */
    2304                 :             :   PROP_gimple_lvec, /* properties_provided */
    2305                 :             :   0, /* properties_destroyed */
    2306                 :             :   0, /* todo_flags_start */
    2307                 :             :   TODO_update_ssa, /* todo_flags_finish */
    2308                 :             : };
    2309                 :             : 
    2310                 :             : class pass_lower_vector : public gimple_opt_pass
    2311                 :             : {
    2312                 :             : public:
    2313                 :      281608 :   pass_lower_vector (gcc::context *ctxt)
    2314                 :      563216 :     : gimple_opt_pass (pass_data_lower_vector, ctxt)
    2315                 :             :   {}
    2316                 :             : 
    2317                 :             :   /* opt_pass methods: */
    2318                 :     1487288 :   bool gate (function *fun) final override
    2319                 :             :     {
    2320                 :     1487288 :       return !(fun->curr_properties & PROP_gimple_lvec);
    2321                 :             :     }
    2322                 :             : 
    2323                 :      435760 :   unsigned int execute (function *) final override
    2324                 :             :     {
    2325                 :      435760 :       return expand_vector_operations ();
    2326                 :             :     }
    2327                 :             : 
    2328                 :             : }; // class pass_lower_vector
    2329                 :             : 
    2330                 :             : } // anon namespace
    2331                 :             : 
    2332                 :             : gimple_opt_pass *
    2333                 :      281608 : make_pass_lower_vector (gcc::context *ctxt)
    2334                 :             : {
    2335                 :      281608 :   return new pass_lower_vector (ctxt);
    2336                 :             : }
    2337                 :             : 
    2338                 :             : namespace {
    2339                 :             : 
    2340                 :             : const pass_data pass_data_lower_vector_ssa =
    2341                 :             : {
    2342                 :             :   GIMPLE_PASS, /* type */
    2343                 :             :   "veclower2", /* name */
    2344                 :             :   OPTGROUP_VEC, /* optinfo_flags */
    2345                 :             :   TV_NONE, /* tv_id */
    2346                 :             :   PROP_cfg, /* properties_required */
    2347                 :             :   PROP_gimple_lvec, /* properties_provided */
    2348                 :             :   0, /* properties_destroyed */
    2349                 :             :   0, /* todo_flags_start */
    2350                 :             :   ( TODO_update_ssa
    2351                 :             :     | TODO_cleanup_cfg ), /* todo_flags_finish */
    2352                 :             : };
    2353                 :             : 
    2354                 :             : class pass_lower_vector_ssa : public gimple_opt_pass
    2355                 :             : {
    2356                 :             : public:
    2357                 :      563216 :   pass_lower_vector_ssa (gcc::context *ctxt)
    2358                 :     1126432 :     : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
    2359                 :             :   {}
    2360                 :             : 
    2361                 :             :   /* opt_pass methods: */
    2362                 :      281608 :   opt_pass * clone () final override
    2363                 :             :   {
    2364                 :      281608 :     return new pass_lower_vector_ssa (m_ctxt);
    2365                 :             :   }
    2366                 :     1051631 :   unsigned int execute (function *) final override
    2367                 :             :     {
    2368                 :     1051631 :       return expand_vector_operations ();
    2369                 :             :     }
    2370                 :             : 
    2371                 :             : }; // class pass_lower_vector_ssa
    2372                 :             : 
    2373                 :             : } // anon namespace
    2374                 :             : 
    2375                 :             : gimple_opt_pass *
    2376                 :      281608 : make_pass_lower_vector_ssa (gcc::context *ctxt)
    2377                 :             : {
    2378                 :      281608 :   return new pass_lower_vector_ssa (ctxt);
    2379                 :             : }
    2380                 :             : 
    2381                 :             : #include "gt-tree-vect-generic.h"
        

Generated by: LCOV version 2.1-beta

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