xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-vect-patterns.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* Analysis Utilities for Loop Vectorization.
2    Copyright (C) 2006-2015 Free Software Foundation, Inc.
3    Contributed by Dorit Nuzman <dorit@il.ibm.com>
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "hash-set.h"
26 #include "machmode.h"
27 #include "vec.h"
28 #include "double-int.h"
29 #include "input.h"
30 #include "alias.h"
31 #include "symtab.h"
32 #include "wide-int.h"
33 #include "inchash.h"
34 #include "tree.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "target.h"
38 #include "predict.h"
39 #include "hard-reg-set.h"
40 #include "function.h"
41 #include "dominance.h"
42 #include "basic-block.h"
43 #include "gimple-pretty-print.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "tree-eh.h"
47 #include "gimple-expr.h"
48 #include "is-a.h"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimple-ssa.h"
53 #include "tree-phinodes.h"
54 #include "ssa-iterators.h"
55 #include "stringpool.h"
56 #include "tree-ssanames.h"
57 #include "cfgloop.h"
58 #include "hashtab.h"
59 #include "rtl.h"
60 #include "flags.h"
61 #include "statistics.h"
62 #include "real.h"
63 #include "fixed-value.h"
64 #include "insn-config.h"
65 #include "expmed.h"
66 #include "dojump.h"
67 #include "explow.h"
68 #include "calls.h"
69 #include "emit-rtl.h"
70 #include "varasm.h"
71 #include "stmt.h"
72 #include "expr.h"
73 #include "insn-codes.h"
74 #include "optabs.h"
75 #include "params.h"
76 #include "tree-data-ref.h"
77 #include "tree-vectorizer.h"
78 #include "recog.h"		/* FIXME: for insn_data */
79 #include "diagnostic-core.h"
80 #include "dumpfile.h"
81 #include "builtins.h"
82 
83 /* Pattern recognition functions  */
84 static gimple vect_recog_widen_sum_pattern (vec<gimple> *, tree *,
85 					    tree *);
86 static gimple vect_recog_widen_mult_pattern (vec<gimple> *, tree *,
87 					     tree *);
88 static gimple vect_recog_dot_prod_pattern (vec<gimple> *, tree *,
89 					   tree *);
90 static gimple vect_recog_sad_pattern (vec<gimple> *, tree *,
91 				      tree *);
92 static gimple vect_recog_pow_pattern (vec<gimple> *, tree *, tree *);
93 static gimple vect_recog_over_widening_pattern (vec<gimple> *, tree *,
94                                                  tree *);
95 static gimple vect_recog_widen_shift_pattern (vec<gimple> *,
96 	                                tree *, tree *);
97 static gimple vect_recog_rotate_pattern (vec<gimple> *, tree *, tree *);
98 static gimple vect_recog_vector_vector_shift_pattern (vec<gimple> *,
99 						      tree *, tree *);
100 static gimple vect_recog_divmod_pattern (vec<gimple> *,
101 					 tree *, tree *);
102 static gimple vect_recog_mixed_size_cond_pattern (vec<gimple> *,
103 						  tree *, tree *);
104 static gimple vect_recog_bool_pattern (vec<gimple> *, tree *, tree *);
105 static vect_recog_func_ptr vect_vect_recog_func_ptrs[NUM_PATTERNS] = {
106 	vect_recog_widen_mult_pattern,
107 	vect_recog_widen_sum_pattern,
108 	vect_recog_dot_prod_pattern,
109         vect_recog_sad_pattern,
110 	vect_recog_pow_pattern,
111 	vect_recog_widen_shift_pattern,
112 	vect_recog_over_widening_pattern,
113 	vect_recog_rotate_pattern,
114 	vect_recog_vector_vector_shift_pattern,
115 	vect_recog_divmod_pattern,
116 	vect_recog_mixed_size_cond_pattern,
117 	vect_recog_bool_pattern};
118 
119 static inline void
120 append_pattern_def_seq (stmt_vec_info stmt_info, gimple stmt)
121 {
122   gimple_seq_add_stmt_without_update (&STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
123 				      stmt);
124 }
125 
126 static inline void
127 new_pattern_def_seq (stmt_vec_info stmt_info, gimple stmt)
128 {
129   STMT_VINFO_PATTERN_DEF_SEQ (stmt_info) = NULL;
130   append_pattern_def_seq (stmt_info, stmt);
131 }
132 
133 /* Check whether STMT2 is in the same loop or basic block as STMT1.
134    Which of the two applies depends on whether we're currently doing
135    loop-based or basic-block-based vectorization, as determined by
136    the vinfo_for_stmt for STMT1 (which must be defined).
137 
138    If this returns true, vinfo_for_stmt for STMT2 is guaranteed
139    to be defined as well.  */
140 
141 static bool
142 vect_same_loop_or_bb_p (gimple stmt1, gimple stmt2)
143 {
144   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt1);
145   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
146   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
147 
148   if (!gimple_bb (stmt2))
149     return false;
150 
151   if (loop_vinfo)
152     {
153       struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
154       if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt2)))
155 	return false;
156     }
157   else
158     {
159       if (gimple_bb (stmt2) != BB_VINFO_BB (bb_vinfo)
160 	  || gimple_code (stmt2) == GIMPLE_PHI)
161 	return false;
162     }
163 
164   gcc_assert (vinfo_for_stmt (stmt2));
165   return true;
166 }
167 
168 /* If the LHS of DEF_STMT has a single use, and that statement is
169    in the same loop or basic block, return it.  */
170 
171 static gimple
172 vect_single_imm_use (gimple def_stmt)
173 {
174   tree lhs = gimple_assign_lhs (def_stmt);
175   use_operand_p use_p;
176   gimple use_stmt;
177 
178   if (!single_imm_use (lhs, &use_p, &use_stmt))
179     return NULL;
180 
181   if (!vect_same_loop_or_bb_p (def_stmt, use_stmt))
182     return NULL;
183 
184   return use_stmt;
185 }
186 
187 /* Check whether NAME, an ssa-name used in USE_STMT,
188    is a result of a type promotion, such that:
189      DEF_STMT: NAME = NOP (name0)
190    If CHECK_SIGN is TRUE, check that either both types are signed or both are
191    unsigned.  */
192 
193 static bool
194 type_conversion_p (tree name, gimple use_stmt, bool check_sign,
195 		   tree *orig_type, gimple *def_stmt, bool *promotion)
196 {
197   tree dummy;
198   gimple dummy_gimple;
199   loop_vec_info loop_vinfo;
200   stmt_vec_info stmt_vinfo;
201   tree type = TREE_TYPE (name);
202   tree oprnd0;
203   enum vect_def_type dt;
204   tree def;
205   bb_vec_info bb_vinfo;
206 
207   stmt_vinfo = vinfo_for_stmt (use_stmt);
208   loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
209   bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
210   if (!vect_is_simple_use (name, use_stmt, loop_vinfo, bb_vinfo, def_stmt,
211 			   &def, &dt))
212     return false;
213 
214   if (dt != vect_internal_def
215       && dt != vect_external_def && dt != vect_constant_def)
216     return false;
217 
218   if (!*def_stmt)
219     return false;
220 
221   if (!is_gimple_assign (*def_stmt))
222     return false;
223 
224   if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (*def_stmt)))
225     return false;
226 
227   oprnd0 = gimple_assign_rhs1 (*def_stmt);
228 
229   *orig_type = TREE_TYPE (oprnd0);
230   if (!INTEGRAL_TYPE_P (type) || !INTEGRAL_TYPE_P (*orig_type)
231       || ((TYPE_UNSIGNED (type) != TYPE_UNSIGNED (*orig_type)) && check_sign))
232     return false;
233 
234   if (TYPE_PRECISION (type) >= (TYPE_PRECISION (*orig_type) * 2))
235     *promotion = true;
236   else
237     *promotion = false;
238 
239   if (!vect_is_simple_use (oprnd0, *def_stmt, loop_vinfo,
240 			   bb_vinfo, &dummy_gimple, &dummy, &dt))
241     return false;
242 
243   return true;
244 }
245 
246 /* Helper to return a new temporary for pattern of TYPE for STMT.  If STMT
247    is NULL, the caller must set SSA_NAME_DEF_STMT for the returned SSA var. */
248 
249 static tree
250 vect_recog_temp_ssa_var (tree type, gimple stmt)
251 {
252   return make_temp_ssa_name (type, stmt, "patt");
253 }
254 
255 /* Function vect_recog_dot_prod_pattern
256 
257    Try to find the following pattern:
258 
259      type x_t, y_t;
260      TYPE1 prod;
261      TYPE2 sum = init;
262    loop:
263      sum_0 = phi <init, sum_1>
264      S1  x_t = ...
265      S2  y_t = ...
266      S3  x_T = (TYPE1) x_t;
267      S4  y_T = (TYPE1) y_t;
268      S5  prod = x_T * y_T;
269      [S6  prod = (TYPE2) prod;  #optional]
270      S7  sum_1 = prod + sum_0;
271 
272    where 'TYPE1' is exactly double the size of type 'type', and 'TYPE2' is the
273    same size of 'TYPE1' or bigger. This is a special case of a reduction
274    computation.
275 
276    Input:
277 
278    * STMTS: Contains a stmt from which the pattern search begins.  In the
279    example, when this function is called with S7, the pattern {S3,S4,S5,S6,S7}
280    will be detected.
281 
282    Output:
283 
284    * TYPE_IN: The type of the input arguments to the pattern.
285 
286    * TYPE_OUT: The type of the output  of this pattern.
287 
288    * Return value: A new stmt that will be used to replace the sequence of
289    stmts that constitute the pattern. In this case it will be:
290         WIDEN_DOT_PRODUCT <x_t, y_t, sum_0>
291 
292    Note: The dot-prod idiom is a widening reduction pattern that is
293          vectorized without preserving all the intermediate results. It
294          produces only N/2 (widened) results (by summing up pairs of
295          intermediate results) rather than all N results.  Therefore, we
296          cannot allow this pattern when we want to get all the results and in
297          the correct order (as is the case when this computation is in an
298          inner-loop nested in an outer-loop that us being vectorized).  */
299 
300 static gimple
301 vect_recog_dot_prod_pattern (vec<gimple> *stmts, tree *type_in,
302 			     tree *type_out)
303 {
304   gimple stmt, last_stmt = (*stmts)[0];
305   tree oprnd0, oprnd1;
306   tree oprnd00, oprnd01;
307   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
308   tree type, half_type;
309   gimple pattern_stmt;
310   tree prod_type;
311   loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
312   struct loop *loop;
313   tree var;
314   bool promotion;
315 
316   if (!loop_info)
317     return NULL;
318 
319   loop = LOOP_VINFO_LOOP (loop_info);
320 
321   if (!is_gimple_assign (last_stmt))
322     return NULL;
323 
324   type = gimple_expr_type (last_stmt);
325 
326   /* Look for the following pattern
327           DX = (TYPE1) X;
328           DY = (TYPE1) Y;
329           DPROD = DX * DY;
330           DDPROD = (TYPE2) DPROD;
331           sum_1 = DDPROD + sum_0;
332      In which
333      - DX is double the size of X
334      - DY is double the size of Y
335      - DX, DY, DPROD all have the same type
336      - sum is the same size of DPROD or bigger
337      - sum has been recognized as a reduction variable.
338 
339      This is equivalent to:
340        DPROD = X w* Y;          #widen mult
341        sum_1 = DPROD w+ sum_0;  #widen summation
342      or
343        DPROD = X w* Y;          #widen mult
344        sum_1 = DPROD + sum_0;   #summation
345    */
346 
347   /* Starting from LAST_STMT, follow the defs of its uses in search
348      of the above pattern.  */
349 
350   if (gimple_assign_rhs_code (last_stmt) != PLUS_EXPR)
351     return NULL;
352 
353   if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
354     {
355       /* Has been detected as widening-summation?  */
356 
357       stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
358       type = gimple_expr_type (stmt);
359       if (gimple_assign_rhs_code (stmt) != WIDEN_SUM_EXPR)
360         return NULL;
361       oprnd0 = gimple_assign_rhs1 (stmt);
362       oprnd1 = gimple_assign_rhs2 (stmt);
363       half_type = TREE_TYPE (oprnd0);
364     }
365   else
366     {
367       gimple def_stmt;
368 
369       if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
370         return NULL;
371       oprnd0 = gimple_assign_rhs1 (last_stmt);
372       oprnd1 = gimple_assign_rhs2 (last_stmt);
373       if (!types_compatible_p (TREE_TYPE (oprnd0), type)
374 	  || !types_compatible_p (TREE_TYPE (oprnd1), type))
375         return NULL;
376       stmt = last_stmt;
377 
378       if (type_conversion_p (oprnd0, stmt, true, &half_type, &def_stmt,
379                                &promotion)
380          && promotion)
381         {
382           stmt = def_stmt;
383           oprnd0 = gimple_assign_rhs1 (stmt);
384         }
385       else
386         half_type = type;
387     }
388 
389   /* So far so good.  Since last_stmt was detected as a (summation) reduction,
390      we know that oprnd1 is the reduction variable (defined by a loop-header
391      phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
392      Left to check that oprnd0 is defined by a (widen_)mult_expr  */
393   if (TREE_CODE (oprnd0) != SSA_NAME)
394     return NULL;
395 
396   prod_type = half_type;
397   stmt = SSA_NAME_DEF_STMT (oprnd0);
398 
399   /* It could not be the dot_prod pattern if the stmt is outside the loop.  */
400   if (!gimple_bb (stmt) || !flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
401     return NULL;
402 
403   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
404      inside the loop (in case we are analyzing an outer-loop).  */
405   if (!is_gimple_assign (stmt))
406     return NULL;
407   stmt_vinfo = vinfo_for_stmt (stmt);
408   gcc_assert (stmt_vinfo);
409   if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_internal_def)
410     return NULL;
411   if (gimple_assign_rhs_code (stmt) != MULT_EXPR)
412     return NULL;
413   if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
414     {
415       /* Has been detected as a widening multiplication?  */
416 
417       stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
418       if (gimple_assign_rhs_code (stmt) != WIDEN_MULT_EXPR)
419         return NULL;
420       stmt_vinfo = vinfo_for_stmt (stmt);
421       gcc_assert (stmt_vinfo);
422       gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_internal_def);
423       oprnd00 = gimple_assign_rhs1 (stmt);
424       oprnd01 = gimple_assign_rhs2 (stmt);
425       STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (last_stmt))
426 	  = STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo);
427     }
428   else
429     {
430       tree half_type0, half_type1;
431       gimple def_stmt;
432       tree oprnd0, oprnd1;
433 
434       oprnd0 = gimple_assign_rhs1 (stmt);
435       oprnd1 = gimple_assign_rhs2 (stmt);
436       if (!types_compatible_p (TREE_TYPE (oprnd0), prod_type)
437           || !types_compatible_p (TREE_TYPE (oprnd1), prod_type))
438         return NULL;
439       if (!type_conversion_p (oprnd0, stmt, true, &half_type0, &def_stmt,
440                                 &promotion)
441           || !promotion)
442         return NULL;
443       oprnd00 = gimple_assign_rhs1 (def_stmt);
444       if (!type_conversion_p (oprnd1, stmt, true, &half_type1, &def_stmt,
445                                 &promotion)
446           || !promotion)
447         return NULL;
448       oprnd01 = gimple_assign_rhs1 (def_stmt);
449       if (!types_compatible_p (half_type0, half_type1))
450         return NULL;
451       if (TYPE_PRECISION (prod_type) != TYPE_PRECISION (half_type0) * 2)
452 	return NULL;
453     }
454 
455   half_type = TREE_TYPE (oprnd00);
456   *type_in = half_type;
457   *type_out = type;
458 
459   /* Pattern detected. Create a stmt to be used to replace the pattern: */
460   var = vect_recog_temp_ssa_var (type, NULL);
461   pattern_stmt = gimple_build_assign (var, DOT_PROD_EXPR,
462 				      oprnd00, oprnd01, oprnd1);
463 
464   if (dump_enabled_p ())
465     {
466       dump_printf_loc (MSG_NOTE, vect_location,
467                        "vect_recog_dot_prod_pattern: detected: ");
468       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
469       dump_printf (MSG_NOTE, "\n");
470     }
471 
472   /* We don't allow changing the order of the computation in the inner-loop
473      when doing outer-loop vectorization.  */
474   gcc_assert (!nested_in_vect_loop_p (loop, last_stmt));
475 
476   return pattern_stmt;
477 }
478 
479 
480 /* Function vect_recog_sad_pattern
481 
482    Try to find the following Sum of Absolute Difference (SAD) pattern:
483 
484      type x_t, y_t;
485      signed TYPE1 diff, abs_diff;
486      TYPE2 sum = init;
487    loop:
488      sum_0 = phi <init, sum_1>
489      S1  x_t = ...
490      S2  y_t = ...
491      S3  x_T = (TYPE1) x_t;
492      S4  y_T = (TYPE1) y_t;
493      S5  diff = x_T - y_T;
494      S6  abs_diff = ABS_EXPR <diff>;
495      [S7  abs_diff = (TYPE2) abs_diff;  #optional]
496      S8  sum_1 = abs_diff + sum_0;
497 
498    where 'TYPE1' is at least double the size of type 'type', and 'TYPE2' is the
499    same size of 'TYPE1' or bigger. This is a special case of a reduction
500    computation.
501 
502    Input:
503 
504    * STMTS: Contains a stmt from which the pattern search begins.  In the
505    example, when this function is called with S8, the pattern
506    {S3,S4,S5,S6,S7,S8} will be detected.
507 
508    Output:
509 
510    * TYPE_IN: The type of the input arguments to the pattern.
511 
512    * TYPE_OUT: The type of the output of this pattern.
513 
514    * Return value: A new stmt that will be used to replace the sequence of
515    stmts that constitute the pattern. In this case it will be:
516         SAD_EXPR <x_t, y_t, sum_0>
517   */
518 
519 static gimple
520 vect_recog_sad_pattern (vec<gimple> *stmts, tree *type_in,
521 			     tree *type_out)
522 {
523   gimple last_stmt = (*stmts)[0];
524   tree sad_oprnd0, sad_oprnd1;
525   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
526   tree half_type;
527   loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
528   struct loop *loop;
529   bool promotion;
530 
531   if (!loop_info)
532     return NULL;
533 
534   loop = LOOP_VINFO_LOOP (loop_info);
535 
536   if (!is_gimple_assign (last_stmt))
537     return NULL;
538 
539   tree sum_type = gimple_expr_type (last_stmt);
540 
541   /* Look for the following pattern
542           DX = (TYPE1) X;
543           DY = (TYPE1) Y;
544           DDIFF = DX - DY;
545           DAD = ABS_EXPR <DDIFF>;
546           DDPROD = (TYPE2) DPROD;
547           sum_1 = DAD + sum_0;
548      In which
549      - DX is at least double the size of X
550      - DY is at least double the size of Y
551      - DX, DY, DDIFF, DAD all have the same type
552      - sum is the same size of DAD or bigger
553      - sum has been recognized as a reduction variable.
554 
555      This is equivalent to:
556        DDIFF = X w- Y;          #widen sub
557        DAD = ABS_EXPR <DDIFF>;
558        sum_1 = DAD w+ sum_0;    #widen summation
559      or
560        DDIFF = X w- Y;          #widen sub
561        DAD = ABS_EXPR <DDIFF>;
562        sum_1 = DAD + sum_0;     #summation
563    */
564 
565   /* Starting from LAST_STMT, follow the defs of its uses in search
566      of the above pattern.  */
567 
568   if (gimple_assign_rhs_code (last_stmt) != PLUS_EXPR)
569     return NULL;
570 
571   tree plus_oprnd0, plus_oprnd1;
572 
573   if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
574     {
575       /* Has been detected as widening-summation?  */
576 
577       gimple stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
578       sum_type = gimple_expr_type (stmt);
579       if (gimple_assign_rhs_code (stmt) != WIDEN_SUM_EXPR)
580         return NULL;
581       plus_oprnd0 = gimple_assign_rhs1 (stmt);
582       plus_oprnd1 = gimple_assign_rhs2 (stmt);
583       half_type = TREE_TYPE (plus_oprnd0);
584     }
585   else
586     {
587       gimple def_stmt;
588 
589       if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
590         return NULL;
591       plus_oprnd0 = gimple_assign_rhs1 (last_stmt);
592       plus_oprnd1 = gimple_assign_rhs2 (last_stmt);
593       if (!types_compatible_p (TREE_TYPE (plus_oprnd0), sum_type)
594 	  || !types_compatible_p (TREE_TYPE (plus_oprnd1), sum_type))
595         return NULL;
596 
597       /* The type conversion could be promotion, demotion,
598          or just signed -> unsigned.  */
599       if (type_conversion_p (plus_oprnd0, last_stmt, false,
600                              &half_type, &def_stmt, &promotion))
601         plus_oprnd0 = gimple_assign_rhs1 (def_stmt);
602       else
603         half_type = sum_type;
604     }
605 
606   /* So far so good.  Since last_stmt was detected as a (summation) reduction,
607      we know that plus_oprnd1 is the reduction variable (defined by a loop-header
608      phi), and plus_oprnd0 is an ssa-name defined by a stmt in the loop body.
609      Then check that plus_oprnd0 is defined by an abs_expr.  */
610 
611   if (TREE_CODE (plus_oprnd0) != SSA_NAME)
612     return NULL;
613 
614   tree abs_type = half_type;
615   gimple abs_stmt = SSA_NAME_DEF_STMT (plus_oprnd0);
616 
617   /* It could not be the sad pattern if the abs_stmt is outside the loop.  */
618   if (!gimple_bb (abs_stmt) || !flow_bb_inside_loop_p (loop, gimple_bb (abs_stmt)))
619     return NULL;
620 
621   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
622      inside the loop (in case we are analyzing an outer-loop).  */
623   if (!is_gimple_assign (abs_stmt))
624     return NULL;
625 
626   stmt_vec_info abs_stmt_vinfo = vinfo_for_stmt (abs_stmt);
627   gcc_assert (abs_stmt_vinfo);
628   if (STMT_VINFO_DEF_TYPE (abs_stmt_vinfo) != vect_internal_def)
629     return NULL;
630   if (gimple_assign_rhs_code (abs_stmt) != ABS_EXPR)
631     return NULL;
632 
633   tree abs_oprnd = gimple_assign_rhs1 (abs_stmt);
634   if (!types_compatible_p (TREE_TYPE (abs_oprnd), abs_type))
635     return NULL;
636   if (TYPE_UNSIGNED (abs_type))
637     return NULL;
638 
639   /* We then detect if the operand of abs_expr is defined by a minus_expr.  */
640 
641   if (TREE_CODE (abs_oprnd) != SSA_NAME)
642     return NULL;
643 
644   gimple diff_stmt = SSA_NAME_DEF_STMT (abs_oprnd);
645 
646   /* It could not be the sad pattern if the diff_stmt is outside the loop.  */
647   if (!gimple_bb (diff_stmt)
648       || !flow_bb_inside_loop_p (loop, gimple_bb (diff_stmt)))
649     return NULL;
650 
651   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
652      inside the loop (in case we are analyzing an outer-loop).  */
653   if (!is_gimple_assign (diff_stmt))
654     return NULL;
655 
656   stmt_vec_info diff_stmt_vinfo = vinfo_for_stmt (diff_stmt);
657   gcc_assert (diff_stmt_vinfo);
658   if (STMT_VINFO_DEF_TYPE (diff_stmt_vinfo) != vect_internal_def)
659     return NULL;
660   if (gimple_assign_rhs_code (diff_stmt) != MINUS_EXPR)
661     return NULL;
662 
663   tree half_type0, half_type1;
664   gimple def_stmt;
665 
666   tree minus_oprnd0 = gimple_assign_rhs1 (diff_stmt);
667   tree minus_oprnd1 = gimple_assign_rhs2 (diff_stmt);
668 
669   if (!types_compatible_p (TREE_TYPE (minus_oprnd0), abs_type)
670       || !types_compatible_p (TREE_TYPE (minus_oprnd1), abs_type))
671     return NULL;
672   if (!type_conversion_p (minus_oprnd0, diff_stmt, false,
673                           &half_type0, &def_stmt, &promotion)
674       || !promotion)
675     return NULL;
676   sad_oprnd0 = gimple_assign_rhs1 (def_stmt);
677 
678   if (!type_conversion_p (minus_oprnd1, diff_stmt, false,
679                           &half_type1, &def_stmt, &promotion)
680       || !promotion)
681     return NULL;
682   sad_oprnd1 = gimple_assign_rhs1 (def_stmt);
683 
684   if (!types_compatible_p (half_type0, half_type1))
685     return NULL;
686   if (TYPE_PRECISION (abs_type) < TYPE_PRECISION (half_type0) * 2
687       || TYPE_PRECISION (sum_type) < TYPE_PRECISION (half_type0) * 2)
688     return NULL;
689 
690   *type_in = TREE_TYPE (sad_oprnd0);
691   *type_out = sum_type;
692 
693   /* Pattern detected. Create a stmt to be used to replace the pattern: */
694   tree var = vect_recog_temp_ssa_var (sum_type, NULL);
695   gimple pattern_stmt = gimple_build_assign (var, SAD_EXPR, sad_oprnd0,
696 					     sad_oprnd1, plus_oprnd1);
697 
698   if (dump_enabled_p ())
699     {
700       dump_printf_loc (MSG_NOTE, vect_location,
701                        "vect_recog_sad_pattern: detected: ");
702       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
703       dump_printf (MSG_NOTE, "\n");
704     }
705 
706   /* We don't allow changing the order of the computation in the inner-loop
707      when doing outer-loop vectorization.  */
708   gcc_assert (!nested_in_vect_loop_p (loop, last_stmt));
709 
710   return pattern_stmt;
711 }
712 
713 
714 /* Handle widening operation by a constant.  At the moment we support MULT_EXPR
715    and LSHIFT_EXPR.
716 
717    For MULT_EXPR we check that CONST_OPRND fits HALF_TYPE, and for LSHIFT_EXPR
718    we check that CONST_OPRND is less or equal to the size of HALF_TYPE.
719 
720    Otherwise, if the type of the result (TYPE) is at least 4 times bigger than
721    HALF_TYPE, and there is an intermediate type (2 times smaller than TYPE)
722    that satisfies the above restrictions,  we can perform a widening opeartion
723    from the intermediate type to TYPE and replace a_T = (TYPE) a_t;
724    with a_it = (interm_type) a_t;  Store such operation in *WSTMT.  */
725 
726 static bool
727 vect_handle_widen_op_by_const (gimple stmt, enum tree_code code,
728 		               tree const_oprnd, tree *oprnd,
729    		               gimple *wstmt, tree type,
730 			       tree *half_type, gimple def_stmt)
731 {
732   tree new_type, new_oprnd;
733 
734   if (code != MULT_EXPR && code != LSHIFT_EXPR)
735     return false;
736 
737   if (((code == MULT_EXPR && int_fits_type_p (const_oprnd, *half_type))
738         || (code == LSHIFT_EXPR
739             && compare_tree_int (const_oprnd, TYPE_PRECISION (*half_type))
740 	    	!= 1))
741       && TYPE_PRECISION (type) == (TYPE_PRECISION (*half_type) * 2))
742     {
743       /* CONST_OPRND is a constant of HALF_TYPE.  */
744       *oprnd = gimple_assign_rhs1 (def_stmt);
745       return true;
746     }
747 
748   if (TYPE_PRECISION (type) < (TYPE_PRECISION (*half_type) * 4))
749     return false;
750 
751   if (!vect_same_loop_or_bb_p (stmt, def_stmt))
752     return false;
753 
754   /* TYPE is 4 times bigger than HALF_TYPE, try widening operation for
755      a type 2 times bigger than HALF_TYPE.  */
756   new_type = build_nonstandard_integer_type (TYPE_PRECISION (type) / 2,
757                                              TYPE_UNSIGNED (type));
758   if ((code == MULT_EXPR && !int_fits_type_p (const_oprnd, new_type))
759       || (code == LSHIFT_EXPR
760           && compare_tree_int (const_oprnd, TYPE_PRECISION (new_type)) == 1))
761     return false;
762 
763   /* Use NEW_TYPE for widening operation and create a_T = (NEW_TYPE) a_t;  */
764   *oprnd = gimple_assign_rhs1 (def_stmt);
765   new_oprnd = make_ssa_name (new_type);
766   *wstmt = gimple_build_assign (new_oprnd, NOP_EXPR, *oprnd);
767   *oprnd = new_oprnd;
768 
769   *half_type = new_type;
770   return true;
771 }
772 
773 
774 /* Function vect_recog_widen_mult_pattern
775 
776    Try to find the following pattern:
777 
778      type1 a_t;
779      type2 b_t;
780      TYPE a_T, b_T, prod_T;
781 
782      S1  a_t = ;
783      S2  b_t = ;
784      S3  a_T = (TYPE) a_t;
785      S4  b_T = (TYPE) b_t;
786      S5  prod_T = a_T * b_T;
787 
788    where type 'TYPE' is at least double the size of type 'type1' and 'type2'.
789 
790    Also detect unsigned cases:
791 
792      unsigned type1 a_t;
793      unsigned type2 b_t;
794      unsigned TYPE u_prod_T;
795      TYPE a_T, b_T, prod_T;
796 
797      S1  a_t = ;
798      S2  b_t = ;
799      S3  a_T = (TYPE) a_t;
800      S4  b_T = (TYPE) b_t;
801      S5  prod_T = a_T * b_T;
802      S6  u_prod_T = (unsigned TYPE) prod_T;
803 
804    and multiplication by constants:
805 
806      type a_t;
807      TYPE a_T, prod_T;
808 
809      S1  a_t = ;
810      S3  a_T = (TYPE) a_t;
811      S5  prod_T = a_T * CONST;
812 
813    A special case of multiplication by constants is when 'TYPE' is 4 times
814    bigger than 'type', but CONST fits an intermediate type 2 times smaller
815    than 'TYPE'.  In that case we create an additional pattern stmt for S3
816    to create a variable of the intermediate type, and perform widen-mult
817    on the intermediate type as well:
818 
819      type a_t;
820      interm_type a_it;
821      TYPE a_T, prod_T,  prod_T';
822 
823      S1  a_t = ;
824      S3  a_T = (TYPE) a_t;
825            '--> a_it = (interm_type) a_t;
826      S5  prod_T = a_T * CONST;
827            '--> prod_T' = a_it w* CONST;
828 
829    Input/Output:
830 
831    * STMTS: Contains a stmt from which the pattern search begins.  In the
832    example, when this function is called with S5, the pattern {S3,S4,S5,(S6)}
833    is detected.  In case of unsigned widen-mult, the original stmt (S5) is
834    replaced with S6 in STMTS.  In case of multiplication by a constant
835    of an intermediate type (the last case above), STMTS also contains S3
836    (inserted before S5).
837 
838    Output:
839 
840    * TYPE_IN: The type of the input arguments to the pattern.
841 
842    * TYPE_OUT: The type of the output of this pattern.
843 
844    * Return value: A new stmt that will be used to replace the sequence of
845    stmts that constitute the pattern.  In this case it will be:
846         WIDEN_MULT <a_t, b_t>
847    If the result of WIDEN_MULT needs to be converted to a larger type, the
848    returned stmt will be this type conversion stmt.
849 */
850 
851 static gimple
852 vect_recog_widen_mult_pattern (vec<gimple> *stmts,
853                                tree *type_in, tree *type_out)
854 {
855   gimple last_stmt = stmts->pop ();
856   gimple def_stmt0, def_stmt1;
857   tree oprnd0, oprnd1;
858   tree type, half_type0, half_type1;
859   gimple new_stmt = NULL, pattern_stmt = NULL;
860   tree vectype, vecitype;
861   tree var;
862   enum tree_code dummy_code;
863   int dummy_int;
864   vec<tree> dummy_vec;
865   bool op1_ok;
866   bool promotion;
867 
868   if (!is_gimple_assign (last_stmt))
869     return NULL;
870 
871   type = gimple_expr_type (last_stmt);
872 
873   /* Starting from LAST_STMT, follow the defs of its uses in search
874      of the above pattern.  */
875 
876   if (gimple_assign_rhs_code (last_stmt) != MULT_EXPR)
877     return NULL;
878 
879   oprnd0 = gimple_assign_rhs1 (last_stmt);
880   oprnd1 = gimple_assign_rhs2 (last_stmt);
881   if (!types_compatible_p (TREE_TYPE (oprnd0), type)
882       || !types_compatible_p (TREE_TYPE (oprnd1), type))
883     return NULL;
884 
885   /* Check argument 0.  */
886   if (!type_conversion_p (oprnd0, last_stmt, false, &half_type0, &def_stmt0,
887                          &promotion)
888       || !promotion)
889      return NULL;
890   /* Check argument 1.  */
891   op1_ok = type_conversion_p (oprnd1, last_stmt, false, &half_type1,
892                               &def_stmt1, &promotion);
893 
894   if (op1_ok && promotion)
895     {
896       oprnd0 = gimple_assign_rhs1 (def_stmt0);
897       oprnd1 = gimple_assign_rhs1 (def_stmt1);
898     }
899   else
900     {
901       if (TREE_CODE (oprnd1) == INTEGER_CST
902           && TREE_CODE (half_type0) == INTEGER_TYPE
903           && vect_handle_widen_op_by_const (last_stmt, MULT_EXPR, oprnd1,
904 		                            &oprnd0, &new_stmt, type,
905 					    &half_type0, def_stmt0))
906 	{
907 	  half_type1 = half_type0;
908 	  oprnd1 = fold_convert (half_type1, oprnd1);
909 	}
910       else
911         return NULL;
912     }
913 
914   /* If the two arguments have different sizes, convert the one with
915      the smaller type into the larger type.  */
916   if (TYPE_PRECISION (half_type0) != TYPE_PRECISION (half_type1))
917     {
918       /* If we already used up the single-stmt slot give up.  */
919       if (new_stmt)
920 	return NULL;
921 
922       tree* oprnd = NULL;
923       gimple def_stmt = NULL;
924 
925       if (TYPE_PRECISION (half_type0) < TYPE_PRECISION (half_type1))
926 	{
927 	  def_stmt = def_stmt0;
928 	  half_type0 = half_type1;
929 	  oprnd = &oprnd0;
930 	}
931       else
932 	{
933 	  def_stmt = def_stmt1;
934 	  half_type1 = half_type0;
935 	  oprnd = &oprnd1;
936 	}
937 
938         tree old_oprnd = gimple_assign_rhs1 (def_stmt);
939 	tree new_oprnd = make_ssa_name (half_type0);
940 	new_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, old_oprnd);
941         *oprnd = new_oprnd;
942     }
943 
944   /* Handle unsigned case.  Look for
945      S6  u_prod_T = (unsigned TYPE) prod_T;
946      Use unsigned TYPE as the type for WIDEN_MULT_EXPR.  */
947   if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (half_type0))
948     {
949       gimple use_stmt;
950       tree use_lhs;
951       tree use_type;
952 
953       if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (half_type1))
954         return NULL;
955 
956       use_stmt = vect_single_imm_use (last_stmt);
957       if (!use_stmt || !is_gimple_assign (use_stmt)
958 	  || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
959         return NULL;
960 
961       use_lhs = gimple_assign_lhs (use_stmt);
962       use_type = TREE_TYPE (use_lhs);
963       if (!INTEGRAL_TYPE_P (use_type)
964           || (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (use_type))
965           || (TYPE_PRECISION (type) != TYPE_PRECISION (use_type)))
966         return NULL;
967 
968       type = use_type;
969       last_stmt = use_stmt;
970     }
971 
972   if (!types_compatible_p (half_type0, half_type1))
973     return NULL;
974 
975   /* If TYPE is more than twice larger than HALF_TYPE, we use WIDEN_MULT
976      to get an intermediate result of type ITYPE.  In this case we need
977      to build a statement to convert this intermediate result to type TYPE.  */
978   tree itype = type;
979   if (TYPE_PRECISION (type) > TYPE_PRECISION (half_type0) * 2)
980     itype = build_nonstandard_integer_type
981               (GET_MODE_BITSIZE (TYPE_MODE (half_type0)) * 2,
982                TYPE_UNSIGNED (type));
983 
984   /* Pattern detected.  */
985   if (dump_enabled_p ())
986     dump_printf_loc (MSG_NOTE, vect_location,
987                      "vect_recog_widen_mult_pattern: detected:\n");
988 
989   /* Check target support  */
990   vectype = get_vectype_for_scalar_type (half_type0);
991   vecitype = get_vectype_for_scalar_type (itype);
992   if (!vectype
993       || !vecitype
994       || !supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt,
995 					  vecitype, vectype,
996 					  &dummy_code, &dummy_code,
997 					  &dummy_int, &dummy_vec))
998     return NULL;
999 
1000   *type_in = vectype;
1001   *type_out = get_vectype_for_scalar_type (type);
1002 
1003   /* Pattern supported. Create a stmt to be used to replace the pattern: */
1004   var = vect_recog_temp_ssa_var (itype, NULL);
1005   pattern_stmt = gimple_build_assign (var, WIDEN_MULT_EXPR, oprnd0, oprnd1);
1006 
1007   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
1008   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1009   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
1010   STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo) = NULL;
1011 
1012   /* If the original two operands have different sizes, we may need to convert
1013      the smaller one into the larget type.  If this is the case, at this point
1014      the new stmt is already built.  */
1015   if (new_stmt)
1016     {
1017       append_pattern_def_seq (stmt_vinfo, new_stmt);
1018       stmt_vec_info new_stmt_info
1019         = new_stmt_vec_info (new_stmt, loop_vinfo, bb_vinfo);
1020       set_vinfo_for_stmt (new_stmt, new_stmt_info);
1021       STMT_VINFO_VECTYPE (new_stmt_info) = vectype;
1022     }
1023 
1024   /* If ITYPE is not TYPE, we need to build a type convertion stmt to convert
1025      the result of the widen-mult operation into type TYPE.  */
1026   if (itype != type)
1027     {
1028       append_pattern_def_seq (stmt_vinfo, pattern_stmt);
1029       stmt_vec_info pattern_stmt_info
1030         = new_stmt_vec_info (pattern_stmt, loop_vinfo, bb_vinfo);
1031       set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
1032       STMT_VINFO_VECTYPE (pattern_stmt_info) = vecitype;
1033       pattern_stmt = gimple_build_assign (vect_recog_temp_ssa_var (type, NULL),
1034 					  NOP_EXPR,
1035 					  gimple_assign_lhs (pattern_stmt));
1036     }
1037 
1038   if (dump_enabled_p ())
1039     dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt, 0);
1040 
1041   stmts->safe_push (last_stmt);
1042   return pattern_stmt;
1043 }
1044 
1045 
1046 /* Function vect_recog_pow_pattern
1047 
1048    Try to find the following pattern:
1049 
1050      x = POW (y, N);
1051 
1052    with POW being one of pow, powf, powi, powif and N being
1053    either 2 or 0.5.
1054 
1055    Input:
1056 
1057    * LAST_STMT: A stmt from which the pattern search begins.
1058 
1059    Output:
1060 
1061    * TYPE_IN: The type of the input arguments to the pattern.
1062 
1063    * TYPE_OUT: The type of the output of this pattern.
1064 
1065    * Return value: A new stmt that will be used to replace the sequence of
1066    stmts that constitute the pattern. In this case it will be:
1067         x = x * x
1068    or
1069 	x = sqrt (x)
1070 */
1071 
1072 static gimple
1073 vect_recog_pow_pattern (vec<gimple> *stmts, tree *type_in,
1074 			tree *type_out)
1075 {
1076   gimple last_stmt = (*stmts)[0];
1077   tree fn, base, exp = NULL;
1078   gimple stmt;
1079   tree var;
1080 
1081   if (!is_gimple_call (last_stmt) || gimple_call_lhs (last_stmt) == NULL)
1082     return NULL;
1083 
1084   fn = gimple_call_fndecl (last_stmt);
1085   if (fn == NULL_TREE || DECL_BUILT_IN_CLASS (fn) != BUILT_IN_NORMAL)
1086    return NULL;
1087 
1088   switch (DECL_FUNCTION_CODE (fn))
1089     {
1090     case BUILT_IN_POWIF:
1091     case BUILT_IN_POWI:
1092     case BUILT_IN_POWF:
1093     case BUILT_IN_POW:
1094       base = gimple_call_arg (last_stmt, 0);
1095       exp = gimple_call_arg (last_stmt, 1);
1096       if (TREE_CODE (exp) != REAL_CST
1097 	  && TREE_CODE (exp) != INTEGER_CST)
1098         return NULL;
1099       break;
1100 
1101     default:
1102       return NULL;
1103     }
1104 
1105   /* We now have a pow or powi builtin function call with a constant
1106      exponent.  */
1107 
1108   *type_out = NULL_TREE;
1109 
1110   /* Catch squaring.  */
1111   if ((tree_fits_shwi_p (exp)
1112        && tree_to_shwi (exp) == 2)
1113       || (TREE_CODE (exp) == REAL_CST
1114           && REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconst2)))
1115     {
1116       *type_in = TREE_TYPE (base);
1117 
1118       var = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
1119       stmt = gimple_build_assign (var, MULT_EXPR, base, base);
1120       return stmt;
1121     }
1122 
1123   /* Catch square root.  */
1124   if (TREE_CODE (exp) == REAL_CST
1125       && REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconsthalf))
1126     {
1127       tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
1128       *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
1129       if (*type_in)
1130 	{
1131 	  gcall *stmt = gimple_build_call (newfn, 1, base);
1132 	  if (vectorizable_function (stmt, *type_in, *type_in)
1133 	      != NULL_TREE)
1134 	    {
1135 	      var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
1136 	      gimple_call_set_lhs (stmt, var);
1137 	      return stmt;
1138 	    }
1139 	}
1140     }
1141 
1142   return NULL;
1143 }
1144 
1145 
1146 /* Function vect_recog_widen_sum_pattern
1147 
1148    Try to find the following pattern:
1149 
1150      type x_t;
1151      TYPE x_T, sum = init;
1152    loop:
1153      sum_0 = phi <init, sum_1>
1154      S1  x_t = *p;
1155      S2  x_T = (TYPE) x_t;
1156      S3  sum_1 = x_T + sum_0;
1157 
1158    where type 'TYPE' is at least double the size of type 'type', i.e - we're
1159    summing elements of type 'type' into an accumulator of type 'TYPE'. This is
1160    a special case of a reduction computation.
1161 
1162    Input:
1163 
1164    * LAST_STMT: A stmt from which the pattern search begins. In the example,
1165    when this function is called with S3, the pattern {S2,S3} will be detected.
1166 
1167    Output:
1168 
1169    * TYPE_IN: The type of the input arguments to the pattern.
1170 
1171    * TYPE_OUT: The type of the output of this pattern.
1172 
1173    * Return value: A new stmt that will be used to replace the sequence of
1174    stmts that constitute the pattern. In this case it will be:
1175         WIDEN_SUM <x_t, sum_0>
1176 
1177    Note: The widening-sum idiom is a widening reduction pattern that is
1178 	 vectorized without preserving all the intermediate results. It
1179          produces only N/2 (widened) results (by summing up pairs of
1180 	 intermediate results) rather than all N results.  Therefore, we
1181 	 cannot allow this pattern when we want to get all the results and in
1182 	 the correct order (as is the case when this computation is in an
1183 	 inner-loop nested in an outer-loop that us being vectorized).  */
1184 
1185 static gimple
1186 vect_recog_widen_sum_pattern (vec<gimple> *stmts, tree *type_in,
1187 			      tree *type_out)
1188 {
1189   gimple stmt, last_stmt = (*stmts)[0];
1190   tree oprnd0, oprnd1;
1191   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
1192   tree type, half_type;
1193   gimple pattern_stmt;
1194   loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1195   struct loop *loop;
1196   tree var;
1197   bool promotion;
1198 
1199   if (!loop_info)
1200     return NULL;
1201 
1202   loop = LOOP_VINFO_LOOP (loop_info);
1203 
1204   if (!is_gimple_assign (last_stmt))
1205     return NULL;
1206 
1207   type = gimple_expr_type (last_stmt);
1208 
1209   /* Look for the following pattern
1210           DX = (TYPE) X;
1211           sum_1 = DX + sum_0;
1212      In which DX is at least double the size of X, and sum_1 has been
1213      recognized as a reduction variable.
1214    */
1215 
1216   /* Starting from LAST_STMT, follow the defs of its uses in search
1217      of the above pattern.  */
1218 
1219   if (gimple_assign_rhs_code (last_stmt) != PLUS_EXPR)
1220     return NULL;
1221 
1222   if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
1223     return NULL;
1224 
1225   oprnd0 = gimple_assign_rhs1 (last_stmt);
1226   oprnd1 = gimple_assign_rhs2 (last_stmt);
1227   if (!types_compatible_p (TREE_TYPE (oprnd0), type)
1228       || !types_compatible_p (TREE_TYPE (oprnd1), type))
1229     return NULL;
1230 
1231   /* So far so good.  Since last_stmt was detected as a (summation) reduction,
1232      we know that oprnd1 is the reduction variable (defined by a loop-header
1233      phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
1234      Left to check that oprnd0 is defined by a cast from type 'type' to type
1235      'TYPE'.  */
1236 
1237   if (!type_conversion_p (oprnd0, last_stmt, true, &half_type, &stmt,
1238                           &promotion)
1239       || !promotion)
1240      return NULL;
1241 
1242   oprnd0 = gimple_assign_rhs1 (stmt);
1243   *type_in = half_type;
1244   *type_out = type;
1245 
1246   /* Pattern detected. Create a stmt to be used to replace the pattern: */
1247   var = vect_recog_temp_ssa_var (type, NULL);
1248   pattern_stmt = gimple_build_assign (var, WIDEN_SUM_EXPR, oprnd0, oprnd1);
1249 
1250   if (dump_enabled_p ())
1251     {
1252       dump_printf_loc (MSG_NOTE, vect_location,
1253                        "vect_recog_widen_sum_pattern: detected: ");
1254       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
1255       dump_printf (MSG_NOTE, "\n");
1256     }
1257 
1258   /* We don't allow changing the order of the computation in the inner-loop
1259      when doing outer-loop vectorization.  */
1260   gcc_assert (!nested_in_vect_loop_p (loop, last_stmt));
1261 
1262   return pattern_stmt;
1263 }
1264 
1265 
1266 /* Return TRUE if the operation in STMT can be performed on a smaller type.
1267 
1268    Input:
1269    STMT - a statement to check.
1270    DEF - we support operations with two operands, one of which is constant.
1271          The other operand can be defined by a demotion operation, or by a
1272          previous statement in a sequence of over-promoted operations.  In the
1273          later case DEF is used to replace that operand.  (It is defined by a
1274          pattern statement we created for the previous statement in the
1275          sequence).
1276 
1277    Input/output:
1278    NEW_TYPE - Output: a smaller type that we are trying to use.  Input: if not
1279          NULL, it's the type of DEF.
1280    STMTS - additional pattern statements.  If a pattern statement (type
1281          conversion) is created in this function, its original statement is
1282          added to STMTS.
1283 
1284    Output:
1285    OP0, OP1 - if the operation fits a smaller type, OP0 and OP1 are the new
1286          operands to use in the new pattern statement for STMT (will be created
1287          in vect_recog_over_widening_pattern ()).
1288    NEW_DEF_STMT - in case DEF has to be promoted, we create two pattern
1289          statements for STMT: the first one is a type promotion and the second
1290          one is the operation itself.  We return the type promotion statement
1291 	 in NEW_DEF_STMT and further store it in STMT_VINFO_PATTERN_DEF_SEQ of
1292          the second pattern statement.  */
1293 
1294 static bool
1295 vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type,
1296                                   tree *op0, tree *op1, gimple *new_def_stmt,
1297                                   vec<gimple> *stmts)
1298 {
1299   enum tree_code code;
1300   tree const_oprnd, oprnd;
1301   tree interm_type = NULL_TREE, half_type, new_oprnd, type;
1302   gimple def_stmt, new_stmt;
1303   bool first = false;
1304   bool promotion;
1305 
1306   *op0 = NULL_TREE;
1307   *op1 = NULL_TREE;
1308   *new_def_stmt = NULL;
1309 
1310   if (!is_gimple_assign (stmt))
1311     return false;
1312 
1313   code = gimple_assign_rhs_code (stmt);
1314   if (code != LSHIFT_EXPR && code != RSHIFT_EXPR
1315       && code != BIT_IOR_EXPR && code != BIT_XOR_EXPR && code != BIT_AND_EXPR)
1316     return false;
1317 
1318   oprnd = gimple_assign_rhs1 (stmt);
1319   const_oprnd = gimple_assign_rhs2 (stmt);
1320   type = gimple_expr_type (stmt);
1321 
1322   if (TREE_CODE (oprnd) != SSA_NAME
1323       || TREE_CODE (const_oprnd) != INTEGER_CST)
1324     return false;
1325 
1326   /* If oprnd has other uses besides that in stmt we cannot mark it
1327      as being part of a pattern only.  */
1328   if (!has_single_use (oprnd))
1329     return false;
1330 
1331   /* If we are in the middle of a sequence, we use DEF from a previous
1332      statement.  Otherwise, OPRND has to be a result of type promotion.  */
1333   if (*new_type)
1334     {
1335       half_type = *new_type;
1336       oprnd = def;
1337     }
1338   else
1339     {
1340       first = true;
1341       if (!type_conversion_p (oprnd, stmt, false, &half_type, &def_stmt,
1342 			      &promotion)
1343 	  || !promotion
1344 	  || !vect_same_loop_or_bb_p (stmt, def_stmt))
1345         return false;
1346     }
1347 
1348   /* Can we perform the operation on a smaller type?  */
1349   switch (code)
1350     {
1351       case BIT_IOR_EXPR:
1352       case BIT_XOR_EXPR:
1353       case BIT_AND_EXPR:
1354         if (!int_fits_type_p (const_oprnd, half_type))
1355           {
1356             /* HALF_TYPE is not enough.  Try a bigger type if possible.  */
1357             if (TYPE_PRECISION (type) < (TYPE_PRECISION (half_type) * 4))
1358               return false;
1359 
1360             interm_type = build_nonstandard_integer_type (
1361                         TYPE_PRECISION (half_type) * 2, TYPE_UNSIGNED (type));
1362             if (!int_fits_type_p (const_oprnd, interm_type))
1363               return false;
1364           }
1365 
1366         break;
1367 
1368       case LSHIFT_EXPR:
1369         /* Try intermediate type - HALF_TYPE is not enough for sure.  */
1370         if (TYPE_PRECISION (type) < (TYPE_PRECISION (half_type) * 4))
1371           return false;
1372 
1373         /* Check that HALF_TYPE size + shift amount <= INTERM_TYPE size.
1374           (e.g., if the original value was char, the shift amount is at most 8
1375            if we want to use short).  */
1376         if (compare_tree_int (const_oprnd, TYPE_PRECISION (half_type)) == 1)
1377           return false;
1378 
1379         interm_type = build_nonstandard_integer_type (
1380                         TYPE_PRECISION (half_type) * 2, TYPE_UNSIGNED (type));
1381 
1382         if (!vect_supportable_shift (code, interm_type))
1383           return false;
1384 
1385         break;
1386 
1387       case RSHIFT_EXPR:
1388         if (vect_supportable_shift (code, half_type))
1389           break;
1390 
1391         /* Try intermediate type - HALF_TYPE is not supported.  */
1392         if (TYPE_PRECISION (type) < (TYPE_PRECISION (half_type) * 4))
1393           return false;
1394 
1395         interm_type = build_nonstandard_integer_type (
1396                         TYPE_PRECISION (half_type) * 2, TYPE_UNSIGNED (type));
1397 
1398         if (!vect_supportable_shift (code, interm_type))
1399           return false;
1400 
1401         break;
1402 
1403       default:
1404         gcc_unreachable ();
1405     }
1406 
1407   /* There are four possible cases:
1408      1. OPRND is defined by a type promotion (in that case FIRST is TRUE, it's
1409         the first statement in the sequence)
1410         a. The original, HALF_TYPE, is not enough - we replace the promotion
1411            from HALF_TYPE to TYPE with a promotion to INTERM_TYPE.
1412         b. HALF_TYPE is sufficient, OPRND is set as the RHS of the original
1413            promotion.
1414      2. OPRND is defined by a pattern statement we created.
1415         a. Its type is not sufficient for the operation, we create a new stmt:
1416            a type conversion for OPRND from HALF_TYPE to INTERM_TYPE.  We store
1417            this statement in NEW_DEF_STMT, and it is later put in
1418 	   STMT_VINFO_PATTERN_DEF_SEQ of the pattern statement for STMT.
1419         b. OPRND is good to use in the new statement.  */
1420   if (first)
1421     {
1422       if (interm_type)
1423         {
1424           /* Replace the original type conversion HALF_TYPE->TYPE with
1425              HALF_TYPE->INTERM_TYPE.  */
1426           if (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)))
1427             {
1428               new_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt));
1429               /* Check if the already created pattern stmt is what we need.  */
1430               if (!is_gimple_assign (new_stmt)
1431                   || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (new_stmt))
1432                   || TREE_TYPE (gimple_assign_lhs (new_stmt)) != interm_type)
1433                 return false;
1434 
1435 	      stmts->safe_push (def_stmt);
1436               oprnd = gimple_assign_lhs (new_stmt);
1437             }
1438           else
1439             {
1440               /* Create NEW_OPRND = (INTERM_TYPE) OPRND.  */
1441               oprnd = gimple_assign_rhs1 (def_stmt);
1442 	      new_oprnd = make_ssa_name (interm_type);
1443 	      new_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, oprnd);
1444               STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)) = new_stmt;
1445               stmts->safe_push (def_stmt);
1446               oprnd = new_oprnd;
1447             }
1448         }
1449       else
1450         {
1451           /* Retrieve the operand before the type promotion.  */
1452           oprnd = gimple_assign_rhs1 (def_stmt);
1453         }
1454     }
1455   else
1456     {
1457       if (interm_type)
1458         {
1459           /* Create a type conversion HALF_TYPE->INTERM_TYPE.  */
1460 	  new_oprnd = make_ssa_name (interm_type);
1461 	  new_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, oprnd);
1462           oprnd = new_oprnd;
1463           *new_def_stmt = new_stmt;
1464         }
1465 
1466       /* Otherwise, OPRND is already set.  */
1467     }
1468 
1469   if (interm_type)
1470     *new_type = interm_type;
1471   else
1472     *new_type = half_type;
1473 
1474   *op0 = oprnd;
1475   *op1 = fold_convert (*new_type, const_oprnd);
1476 
1477   return true;
1478 }
1479 
1480 
1481 /* Try to find a statement or a sequence of statements that can be performed
1482    on a smaller type:
1483 
1484      type x_t;
1485      TYPE x_T, res0_T, res1_T;
1486    loop:
1487      S1  x_t = *p;
1488      S2  x_T = (TYPE) x_t;
1489      S3  res0_T = op (x_T, C0);
1490      S4  res1_T = op (res0_T, C1);
1491      S5  ... = () res1_T;  - type demotion
1492 
1493    where type 'TYPE' is at least double the size of type 'type', C0 and C1 are
1494    constants.
1495    Check if S3 and S4 can be done on a smaller type than 'TYPE', it can either
1496    be 'type' or some intermediate type.  For now, we expect S5 to be a type
1497    demotion operation.  We also check that S3 and S4 have only one use.  */
1498 
1499 static gimple
1500 vect_recog_over_widening_pattern (vec<gimple> *stmts,
1501                                   tree *type_in, tree *type_out)
1502 {
1503   gimple stmt = stmts->pop ();
1504   gimple pattern_stmt = NULL, new_def_stmt, prev_stmt = NULL, use_stmt = NULL;
1505   tree op0, op1, vectype = NULL_TREE, use_lhs, use_type;
1506   tree var = NULL_TREE, new_type = NULL_TREE, new_oprnd;
1507   bool first;
1508   tree type = NULL;
1509 
1510   first = true;
1511   while (1)
1512     {
1513       if (!vinfo_for_stmt (stmt)
1514           || STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (stmt)))
1515         return NULL;
1516 
1517       new_def_stmt = NULL;
1518       if (!vect_operation_fits_smaller_type (stmt, var, &new_type,
1519                                              &op0, &op1, &new_def_stmt,
1520                                              stmts))
1521         {
1522           if (first)
1523             return NULL;
1524           else
1525             break;
1526         }
1527 
1528       /* STMT can be performed on a smaller type.  Check its uses.  */
1529       use_stmt = vect_single_imm_use (stmt);
1530       if (!use_stmt || !is_gimple_assign (use_stmt))
1531         return NULL;
1532 
1533       /* Create pattern statement for STMT.  */
1534       vectype = get_vectype_for_scalar_type (new_type);
1535       if (!vectype)
1536         return NULL;
1537 
1538       /* We want to collect all the statements for which we create pattern
1539          statetments, except for the case when the last statement in the
1540          sequence doesn't have a corresponding pattern statement.  In such
1541          case we associate the last pattern statement with the last statement
1542          in the sequence.  Therefore, we only add the original statement to
1543          the list if we know that it is not the last.  */
1544       if (prev_stmt)
1545         stmts->safe_push (prev_stmt);
1546 
1547       var = vect_recog_temp_ssa_var (new_type, NULL);
1548       pattern_stmt
1549 	= gimple_build_assign (var, gimple_assign_rhs_code (stmt), op0, op1);
1550       STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt)) = pattern_stmt;
1551       new_pattern_def_seq (vinfo_for_stmt (stmt), new_def_stmt);
1552 
1553       if (dump_enabled_p ())
1554         {
1555           dump_printf_loc (MSG_NOTE, vect_location,
1556                            "created pattern stmt: ");
1557           dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
1558           dump_printf (MSG_NOTE, "\n");
1559         }
1560 
1561       type = gimple_expr_type (stmt);
1562       prev_stmt = stmt;
1563       stmt = use_stmt;
1564 
1565       first = false;
1566     }
1567 
1568   /* We got a sequence.  We expect it to end with a type demotion operation.
1569      Otherwise, we quit (for now).  There are three possible cases: the
1570      conversion is to NEW_TYPE (we don't do anything), the conversion is to
1571      a type bigger than NEW_TYPE and/or the signedness of USE_TYPE and
1572      NEW_TYPE differs (we create a new conversion statement).  */
1573   if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
1574     {
1575       use_lhs = gimple_assign_lhs (use_stmt);
1576       use_type = TREE_TYPE (use_lhs);
1577       /* Support only type demotion or signedess change.  */
1578       if (!INTEGRAL_TYPE_P (use_type)
1579 	  || TYPE_PRECISION (type) <= TYPE_PRECISION (use_type))
1580         return NULL;
1581 
1582       /* Check that NEW_TYPE is not bigger than the conversion result.  */
1583       if (TYPE_PRECISION (new_type) > TYPE_PRECISION (use_type))
1584 	return NULL;
1585 
1586       if (TYPE_UNSIGNED (new_type) != TYPE_UNSIGNED (use_type)
1587           || TYPE_PRECISION (new_type) != TYPE_PRECISION (use_type))
1588         {
1589           /* Create NEW_TYPE->USE_TYPE conversion.  */
1590 	  new_oprnd = make_ssa_name (use_type);
1591 	  pattern_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, var);
1592           STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt)) = pattern_stmt;
1593 
1594           *type_in = get_vectype_for_scalar_type (new_type);
1595           *type_out = get_vectype_for_scalar_type (use_type);
1596 
1597           /* We created a pattern statement for the last statement in the
1598              sequence, so we don't need to associate it with the pattern
1599              statement created for PREV_STMT.  Therefore, we add PREV_STMT
1600              to the list in order to mark it later in vect_pattern_recog_1.  */
1601           if (prev_stmt)
1602             stmts->safe_push (prev_stmt);
1603         }
1604       else
1605         {
1606           if (prev_stmt)
1607 	    STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (use_stmt))
1608 	       = STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (prev_stmt));
1609 
1610           *type_in = vectype;
1611           *type_out = NULL_TREE;
1612         }
1613 
1614       stmts->safe_push (use_stmt);
1615     }
1616   else
1617     /* TODO: support general case, create a conversion to the correct type.  */
1618     return NULL;
1619 
1620   /* Pattern detected.  */
1621   if (dump_enabled_p ())
1622     {
1623       dump_printf_loc (MSG_NOTE, vect_location,
1624                        "vect_recog_over_widening_pattern: detected: ");
1625       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
1626       dump_printf (MSG_NOTE, "\n");
1627     }
1628 
1629   return pattern_stmt;
1630 }
1631 
1632 /* Detect widening shift pattern:
1633 
1634    type a_t;
1635    TYPE a_T, res_T;
1636 
1637    S1 a_t = ;
1638    S2 a_T = (TYPE) a_t;
1639    S3 res_T = a_T << CONST;
1640 
1641   where type 'TYPE' is at least double the size of type 'type'.
1642 
1643   Also detect cases where the shift result is immediately converted
1644   to another type 'result_type' that is no larger in size than 'TYPE'.
1645   In those cases we perform a widen-shift that directly results in
1646   'result_type', to avoid a possible over-widening situation:
1647 
1648   type a_t;
1649   TYPE a_T, res_T;
1650   result_type res_result;
1651 
1652   S1 a_t = ;
1653   S2 a_T = (TYPE) a_t;
1654   S3 res_T = a_T << CONST;
1655   S4 res_result = (result_type) res_T;
1656       '--> res_result' = a_t w<< CONST;
1657 
1658   And a case when 'TYPE' is 4 times bigger than 'type'.  In that case we
1659   create an additional pattern stmt for S2 to create a variable of an
1660   intermediate type, and perform widen-shift on the intermediate type:
1661 
1662   type a_t;
1663   interm_type a_it;
1664   TYPE a_T, res_T, res_T';
1665 
1666   S1 a_t = ;
1667   S2 a_T = (TYPE) a_t;
1668       '--> a_it = (interm_type) a_t;
1669   S3 res_T = a_T << CONST;
1670       '--> res_T' = a_it <<* CONST;
1671 
1672   Input/Output:
1673 
1674   * STMTS: Contains a stmt from which the pattern search begins.
1675     In case of unsigned widen-shift, the original stmt (S3) is replaced with S4
1676     in STMTS.  When an intermediate type is used and a pattern statement is
1677     created for S2, we also put S2 here (before S3).
1678 
1679   Output:
1680 
1681   * TYPE_IN: The type of the input arguments to the pattern.
1682 
1683   * TYPE_OUT: The type of the output of this pattern.
1684 
1685   * Return value: A new stmt that will be used to replace the sequence of
1686     stmts that constitute the pattern.  In this case it will be:
1687     WIDEN_LSHIFT_EXPR <a_t, CONST>.  */
1688 
1689 static gimple
1690 vect_recog_widen_shift_pattern (vec<gimple> *stmts,
1691 				tree *type_in, tree *type_out)
1692 {
1693   gimple last_stmt = stmts->pop ();
1694   gimple def_stmt0;
1695   tree oprnd0, oprnd1;
1696   tree type, half_type0;
1697   gimple pattern_stmt;
1698   tree vectype, vectype_out = NULL_TREE;
1699   tree var;
1700   enum tree_code dummy_code;
1701   int dummy_int;
1702   vec<tree>  dummy_vec;
1703   gimple use_stmt;
1704   bool promotion;
1705 
1706   if (!is_gimple_assign (last_stmt) || !vinfo_for_stmt (last_stmt))
1707     return NULL;
1708 
1709   if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt)))
1710     return NULL;
1711 
1712   if (gimple_assign_rhs_code (last_stmt) != LSHIFT_EXPR)
1713     return NULL;
1714 
1715   oprnd0 = gimple_assign_rhs1 (last_stmt);
1716   oprnd1 = gimple_assign_rhs2 (last_stmt);
1717   if (TREE_CODE (oprnd0) != SSA_NAME || TREE_CODE (oprnd1) != INTEGER_CST)
1718     return NULL;
1719 
1720   /* Check operand 0: it has to be defined by a type promotion.  */
1721   if (!type_conversion_p (oprnd0, last_stmt, false, &half_type0, &def_stmt0,
1722 			  &promotion)
1723       || !promotion)
1724      return NULL;
1725 
1726   /* Check operand 1: has to be positive.  We check that it fits the type
1727      in vect_handle_widen_op_by_const ().  */
1728   if (tree_int_cst_compare (oprnd1, size_zero_node) <= 0)
1729     return NULL;
1730 
1731   oprnd0 = gimple_assign_rhs1 (def_stmt0);
1732   type = gimple_expr_type (last_stmt);
1733 
1734   /* Check for subsequent conversion to another type.  */
1735   use_stmt = vect_single_imm_use (last_stmt);
1736   if (use_stmt && is_gimple_assign (use_stmt)
1737       && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt))
1738       && !STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt)))
1739     {
1740       tree use_lhs = gimple_assign_lhs (use_stmt);
1741       tree use_type = TREE_TYPE (use_lhs);
1742 
1743       if (INTEGRAL_TYPE_P (use_type)
1744 	  && TYPE_PRECISION (use_type) <= TYPE_PRECISION (type))
1745 	{
1746 	  last_stmt = use_stmt;
1747 	  type = use_type;
1748 	}
1749     }
1750 
1751   /* Check if this a widening operation.  */
1752   gimple wstmt = NULL;
1753   if (!vect_handle_widen_op_by_const (last_stmt, LSHIFT_EXPR, oprnd1,
1754        				      &oprnd0, &wstmt,
1755 	                              type, &half_type0, def_stmt0))
1756     return NULL;
1757 
1758   /* Pattern detected.  */
1759   if (dump_enabled_p ())
1760     dump_printf_loc (MSG_NOTE, vect_location,
1761                      "vect_recog_widen_shift_pattern: detected:\n");
1762 
1763   /* Check target support.  */
1764   vectype = get_vectype_for_scalar_type (half_type0);
1765   vectype_out = get_vectype_for_scalar_type (type);
1766 
1767   if (!vectype
1768       || !vectype_out
1769       || !supportable_widening_operation (WIDEN_LSHIFT_EXPR, last_stmt,
1770 					  vectype_out, vectype,
1771 					  &dummy_code, &dummy_code,
1772 					  &dummy_int, &dummy_vec))
1773     return NULL;
1774 
1775   *type_in = vectype;
1776   *type_out = vectype_out;
1777 
1778   /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
1779   var = vect_recog_temp_ssa_var (type, NULL);
1780   pattern_stmt =
1781     gimple_build_assign (var, WIDEN_LSHIFT_EXPR, oprnd0, oprnd1);
1782   if (wstmt)
1783     {
1784       stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
1785       loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1786       bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
1787       new_pattern_def_seq (stmt_vinfo, wstmt);
1788       stmt_vec_info new_stmt_info
1789 	= new_stmt_vec_info (wstmt, loop_vinfo, bb_vinfo);
1790       set_vinfo_for_stmt (wstmt, new_stmt_info);
1791       STMT_VINFO_VECTYPE (new_stmt_info) = vectype;
1792     }
1793 
1794   if (dump_enabled_p ())
1795     dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt, 0);
1796 
1797   stmts->safe_push (last_stmt);
1798   return pattern_stmt;
1799 }
1800 
1801 /* Detect a rotate pattern wouldn't be otherwise vectorized:
1802 
1803    type a_t, b_t, c_t;
1804 
1805    S0 a_t = b_t r<< c_t;
1806 
1807   Input/Output:
1808 
1809   * STMTS: Contains a stmt from which the pattern search begins,
1810     i.e. the shift/rotate stmt.  The original stmt (S0) is replaced
1811     with a sequence:
1812 
1813    S1 d_t = -c_t;
1814    S2 e_t = d_t & (B - 1);
1815    S3 f_t = b_t << c_t;
1816    S4 g_t = b_t >> e_t;
1817    S0 a_t = f_t | g_t;
1818 
1819     where B is element bitsize of type.
1820 
1821   Output:
1822 
1823   * TYPE_IN: The type of the input arguments to the pattern.
1824 
1825   * TYPE_OUT: The type of the output of this pattern.
1826 
1827   * Return value: A new stmt that will be used to replace the rotate
1828     S0 stmt.  */
1829 
1830 static gimple
1831 vect_recog_rotate_pattern (vec<gimple> *stmts, tree *type_in, tree *type_out)
1832 {
1833   gimple last_stmt = stmts->pop ();
1834   tree oprnd0, oprnd1, lhs, var, var1, var2, vectype, type, stype, def, def2;
1835   gimple pattern_stmt, def_stmt;
1836   enum tree_code rhs_code;
1837   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
1838   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1839   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
1840   enum vect_def_type dt;
1841   optab optab1, optab2;
1842   edge ext_def = NULL;
1843 
1844   if (!is_gimple_assign (last_stmt))
1845     return NULL;
1846 
1847   rhs_code = gimple_assign_rhs_code (last_stmt);
1848   switch (rhs_code)
1849     {
1850     case LROTATE_EXPR:
1851     case RROTATE_EXPR:
1852       break;
1853     default:
1854       return NULL;
1855     }
1856 
1857   if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
1858     return NULL;
1859 
1860   lhs = gimple_assign_lhs (last_stmt);
1861   oprnd0 = gimple_assign_rhs1 (last_stmt);
1862   type = TREE_TYPE (oprnd0);
1863   oprnd1 = gimple_assign_rhs2 (last_stmt);
1864   if (TREE_CODE (oprnd0) != SSA_NAME
1865       || TYPE_PRECISION (TREE_TYPE (lhs)) != TYPE_PRECISION (type)
1866       || !INTEGRAL_TYPE_P (type)
1867       || !TYPE_UNSIGNED (type))
1868     return NULL;
1869 
1870   if (!vect_is_simple_use (oprnd1, last_stmt, loop_vinfo, bb_vinfo, &def_stmt,
1871 			   &def, &dt))
1872     return NULL;
1873 
1874   if (dt != vect_internal_def
1875       && dt != vect_constant_def
1876       && dt != vect_external_def)
1877     return NULL;
1878 
1879   vectype = get_vectype_for_scalar_type (type);
1880   if (vectype == NULL_TREE)
1881     return NULL;
1882 
1883   /* If vector/vector or vector/scalar rotate is supported by the target,
1884      don't do anything here.  */
1885   optab1 = optab_for_tree_code (rhs_code, vectype, optab_vector);
1886   if (optab1
1887       && optab_handler (optab1, TYPE_MODE (vectype)) != CODE_FOR_nothing)
1888     return NULL;
1889 
1890   if (bb_vinfo != NULL || dt != vect_internal_def)
1891     {
1892       optab2 = optab_for_tree_code (rhs_code, vectype, optab_scalar);
1893       if (optab2
1894 	  && optab_handler (optab2, TYPE_MODE (vectype)) != CODE_FOR_nothing)
1895 	return NULL;
1896     }
1897 
1898   /* If vector/vector or vector/scalar shifts aren't supported by the target,
1899      don't do anything here either.  */
1900   optab1 = optab_for_tree_code (LSHIFT_EXPR, vectype, optab_vector);
1901   optab2 = optab_for_tree_code (RSHIFT_EXPR, vectype, optab_vector);
1902   if (!optab1
1903       || optab_handler (optab1, TYPE_MODE (vectype)) == CODE_FOR_nothing
1904       || !optab2
1905       || optab_handler (optab2, TYPE_MODE (vectype)) == CODE_FOR_nothing)
1906     {
1907       if (bb_vinfo == NULL && dt == vect_internal_def)
1908 	return NULL;
1909       optab1 = optab_for_tree_code (LSHIFT_EXPR, vectype, optab_scalar);
1910       optab2 = optab_for_tree_code (RSHIFT_EXPR, vectype, optab_scalar);
1911       if (!optab1
1912 	  || optab_handler (optab1, TYPE_MODE (vectype)) == CODE_FOR_nothing
1913 	  || !optab2
1914 	  || optab_handler (optab2, TYPE_MODE (vectype)) == CODE_FOR_nothing)
1915 	return NULL;
1916     }
1917 
1918   *type_in = vectype;
1919   *type_out = vectype;
1920   if (*type_in == NULL_TREE)
1921     return NULL;
1922 
1923   if (dt == vect_external_def
1924       && TREE_CODE (oprnd1) == SSA_NAME
1925       && loop_vinfo)
1926     {
1927       struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1928       ext_def = loop_preheader_edge (loop);
1929       if (!SSA_NAME_IS_DEFAULT_DEF (oprnd1))
1930 	{
1931 	  basic_block bb = gimple_bb (SSA_NAME_DEF_STMT (oprnd1));
1932 	  if (bb == NULL
1933 	      || !dominated_by_p (CDI_DOMINATORS, ext_def->dest, bb))
1934 	    ext_def = NULL;
1935 	}
1936     }
1937 
1938   def = NULL_TREE;
1939   if (TREE_CODE (oprnd1) == INTEGER_CST
1940       || TYPE_MODE (TREE_TYPE (oprnd1)) == TYPE_MODE (type))
1941     def = oprnd1;
1942   else if (def_stmt && gimple_assign_cast_p (def_stmt))
1943     {
1944       tree rhs1 = gimple_assign_rhs1 (def_stmt);
1945       if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (type)
1946 	  && TYPE_PRECISION (TREE_TYPE (rhs1))
1947 	     == TYPE_PRECISION (type))
1948 	def = rhs1;
1949     }
1950 
1951   STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo) = NULL;
1952   if (def == NULL_TREE)
1953     {
1954       def = vect_recog_temp_ssa_var (type, NULL);
1955       def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd1);
1956       if (ext_def)
1957 	{
1958 	  basic_block new_bb
1959 	    = gsi_insert_on_edge_immediate (ext_def, def_stmt);
1960 	  gcc_assert (!new_bb);
1961 	}
1962       else
1963 	append_pattern_def_seq (stmt_vinfo, def_stmt);
1964     }
1965   stype = TREE_TYPE (def);
1966 
1967   if (TREE_CODE (def) == INTEGER_CST)
1968     {
1969       if (!tree_fits_uhwi_p (def)
1970 	  || tree_to_uhwi (def) >= GET_MODE_PRECISION (TYPE_MODE (type))
1971 	  || integer_zerop (def))
1972 	return NULL;
1973       def2 = build_int_cst (stype,
1974 			    GET_MODE_PRECISION (TYPE_MODE (type))
1975 			    - tree_to_uhwi (def));
1976     }
1977   else
1978     {
1979       tree vecstype = get_vectype_for_scalar_type (stype);
1980       stmt_vec_info def_stmt_vinfo;
1981 
1982       if (vecstype == NULL_TREE)
1983 	return NULL;
1984       def2 = vect_recog_temp_ssa_var (stype, NULL);
1985       def_stmt = gimple_build_assign (def2, NEGATE_EXPR, def);
1986       if (ext_def)
1987 	{
1988 	  basic_block new_bb
1989 	    = gsi_insert_on_edge_immediate (ext_def, def_stmt);
1990 	  gcc_assert (!new_bb);
1991 	}
1992       else
1993 	{
1994 	  def_stmt_vinfo = new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo);
1995 	  set_vinfo_for_stmt (def_stmt, def_stmt_vinfo);
1996 	  STMT_VINFO_VECTYPE (def_stmt_vinfo) = vecstype;
1997 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
1998 	}
1999 
2000       def2 = vect_recog_temp_ssa_var (stype, NULL);
2001       tree mask
2002 	= build_int_cst (stype, GET_MODE_PRECISION (TYPE_MODE (stype)) - 1);
2003       def_stmt = gimple_build_assign (def2, BIT_AND_EXPR,
2004 				      gimple_assign_lhs (def_stmt), mask);
2005       if (ext_def)
2006 	{
2007 	  basic_block new_bb
2008 	    = gsi_insert_on_edge_immediate (ext_def, def_stmt);
2009 	  gcc_assert (!new_bb);
2010 	}
2011       else
2012 	{
2013 	  def_stmt_vinfo = new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo);
2014 	  set_vinfo_for_stmt (def_stmt, def_stmt_vinfo);
2015 	  STMT_VINFO_VECTYPE (def_stmt_vinfo) = vecstype;
2016 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2017 	}
2018     }
2019 
2020   var1 = vect_recog_temp_ssa_var (type, NULL);
2021   def_stmt = gimple_build_assign (var1, rhs_code == LROTATE_EXPR
2022 					? LSHIFT_EXPR : RSHIFT_EXPR,
2023 				  oprnd0, def);
2024   append_pattern_def_seq (stmt_vinfo, def_stmt);
2025 
2026   var2 = vect_recog_temp_ssa_var (type, NULL);
2027   def_stmt = gimple_build_assign (var2, rhs_code == LROTATE_EXPR
2028 					? RSHIFT_EXPR : LSHIFT_EXPR,
2029 				  oprnd0, def2);
2030   append_pattern_def_seq (stmt_vinfo, def_stmt);
2031 
2032   /* Pattern detected.  */
2033   if (dump_enabled_p ())
2034     dump_printf_loc (MSG_NOTE, vect_location,
2035 		     "vect_recog_rotate_pattern: detected:\n");
2036 
2037   /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
2038   var = vect_recog_temp_ssa_var (type, NULL);
2039   pattern_stmt = gimple_build_assign (var, BIT_IOR_EXPR, var1, var2);
2040 
2041   if (dump_enabled_p ())
2042     dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt, 0);
2043 
2044   stmts->safe_push (last_stmt);
2045   return pattern_stmt;
2046 }
2047 
2048 /* Detect a vector by vector shift pattern that wouldn't be otherwise
2049    vectorized:
2050 
2051    type a_t;
2052    TYPE b_T, res_T;
2053 
2054    S1 a_t = ;
2055    S2 b_T = ;
2056    S3 res_T = b_T op a_t;
2057 
2058   where type 'TYPE' is a type with different size than 'type',
2059   and op is <<, >> or rotate.
2060 
2061   Also detect cases:
2062 
2063    type a_t;
2064    TYPE b_T, c_T, res_T;
2065 
2066    S0 c_T = ;
2067    S1 a_t = (type) c_T;
2068    S2 b_T = ;
2069    S3 res_T = b_T op a_t;
2070 
2071   Input/Output:
2072 
2073   * STMTS: Contains a stmt from which the pattern search begins,
2074     i.e. the shift/rotate stmt.  The original stmt (S3) is replaced
2075     with a shift/rotate which has same type on both operands, in the
2076     second case just b_T op c_T, in the first case with added cast
2077     from a_t to c_T in STMT_VINFO_PATTERN_DEF_SEQ.
2078 
2079   Output:
2080 
2081   * TYPE_IN: The type of the input arguments to the pattern.
2082 
2083   * TYPE_OUT: The type of the output of this pattern.
2084 
2085   * Return value: A new stmt that will be used to replace the shift/rotate
2086     S3 stmt.  */
2087 
2088 static gimple
2089 vect_recog_vector_vector_shift_pattern (vec<gimple> *stmts,
2090 					tree *type_in, tree *type_out)
2091 {
2092   gimple last_stmt = stmts->pop ();
2093   tree oprnd0, oprnd1, lhs, var;
2094   gimple pattern_stmt, def_stmt;
2095   enum tree_code rhs_code;
2096   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
2097   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
2098   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
2099   enum vect_def_type dt;
2100   tree def;
2101 
2102   if (!is_gimple_assign (last_stmt))
2103     return NULL;
2104 
2105   rhs_code = gimple_assign_rhs_code (last_stmt);
2106   switch (rhs_code)
2107     {
2108     case LSHIFT_EXPR:
2109     case RSHIFT_EXPR:
2110     case LROTATE_EXPR:
2111     case RROTATE_EXPR:
2112       break;
2113     default:
2114       return NULL;
2115     }
2116 
2117   if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
2118     return NULL;
2119 
2120   lhs = gimple_assign_lhs (last_stmt);
2121   oprnd0 = gimple_assign_rhs1 (last_stmt);
2122   oprnd1 = gimple_assign_rhs2 (last_stmt);
2123   if (TREE_CODE (oprnd0) != SSA_NAME
2124       || TREE_CODE (oprnd1) != SSA_NAME
2125       || TYPE_MODE (TREE_TYPE (oprnd0)) == TYPE_MODE (TREE_TYPE (oprnd1))
2126       || TYPE_PRECISION (TREE_TYPE (oprnd1))
2127 	 != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (oprnd1)))
2128       || TYPE_PRECISION (TREE_TYPE (lhs))
2129 	 != TYPE_PRECISION (TREE_TYPE (oprnd0)))
2130     return NULL;
2131 
2132   if (!vect_is_simple_use (oprnd1, last_stmt, loop_vinfo, bb_vinfo, &def_stmt,
2133 			   &def, &dt))
2134     return NULL;
2135 
2136   if (dt != vect_internal_def)
2137     return NULL;
2138 
2139   *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0));
2140   *type_out = *type_in;
2141   if (*type_in == NULL_TREE)
2142     return NULL;
2143 
2144   def = NULL_TREE;
2145   if (gimple_assign_cast_p (def_stmt))
2146     {
2147       tree rhs1 = gimple_assign_rhs1 (def_stmt);
2148       if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0))
2149 	  && TYPE_PRECISION (TREE_TYPE (rhs1))
2150 	     == TYPE_PRECISION (TREE_TYPE (oprnd0)))
2151 	def = rhs1;
2152     }
2153 
2154   if (def == NULL_TREE)
2155     {
2156       def = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
2157       def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd1);
2158       new_pattern_def_seq (stmt_vinfo, def_stmt);
2159     }
2160 
2161   /* Pattern detected.  */
2162   if (dump_enabled_p ())
2163     dump_printf_loc (MSG_NOTE, vect_location,
2164                      "vect_recog_vector_vector_shift_pattern: detected:\n");
2165 
2166   /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
2167   var = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
2168   pattern_stmt = gimple_build_assign (var, rhs_code, oprnd0, def);
2169 
2170   if (dump_enabled_p ())
2171     dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt, 0);
2172 
2173   stmts->safe_push (last_stmt);
2174   return pattern_stmt;
2175 }
2176 
2177 /* Detect a signed division by a constant that wouldn't be
2178    otherwise vectorized:
2179 
2180    type a_t, b_t;
2181 
2182    S1 a_t = b_t / N;
2183 
2184   where type 'type' is an integral type and N is a constant.
2185 
2186   Similarly handle modulo by a constant:
2187 
2188    S4 a_t = b_t % N;
2189 
2190   Input/Output:
2191 
2192   * STMTS: Contains a stmt from which the pattern search begins,
2193     i.e. the division stmt.  S1 is replaced by if N is a power
2194     of two constant and type is signed:
2195   S3  y_t = b_t < 0 ? N - 1 : 0;
2196   S2  x_t = b_t + y_t;
2197   S1' a_t = x_t >> log2 (N);
2198 
2199     S4 is replaced if N is a power of two constant and
2200     type is signed by (where *_T temporaries have unsigned type):
2201   S9  y_T = b_t < 0 ? -1U : 0U;
2202   S8  z_T = y_T >> (sizeof (type_t) * CHAR_BIT - log2 (N));
2203   S7  z_t = (type) z_T;
2204   S6  w_t = b_t + z_t;
2205   S5  x_t = w_t & (N - 1);
2206   S4' a_t = x_t - z_t;
2207 
2208   Output:
2209 
2210   * TYPE_IN: The type of the input arguments to the pattern.
2211 
2212   * TYPE_OUT: The type of the output of this pattern.
2213 
2214   * Return value: A new stmt that will be used to replace the division
2215     S1 or modulo S4 stmt.  */
2216 
2217 static gimple
2218 vect_recog_divmod_pattern (vec<gimple> *stmts,
2219 			   tree *type_in, tree *type_out)
2220 {
2221   gimple last_stmt = stmts->pop ();
2222   tree oprnd0, oprnd1, vectype, itype, cond;
2223   gimple pattern_stmt, def_stmt;
2224   enum tree_code rhs_code;
2225   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
2226   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
2227   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
2228   optab optab;
2229   tree q;
2230   int dummy_int, prec;
2231   stmt_vec_info def_stmt_vinfo;
2232 
2233   if (!is_gimple_assign (last_stmt))
2234     return NULL;
2235 
2236   rhs_code = gimple_assign_rhs_code (last_stmt);
2237   switch (rhs_code)
2238     {
2239     case TRUNC_DIV_EXPR:
2240     case TRUNC_MOD_EXPR:
2241       break;
2242     default:
2243       return NULL;
2244     }
2245 
2246   if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
2247     return NULL;
2248 
2249   oprnd0 = gimple_assign_rhs1 (last_stmt);
2250   oprnd1 = gimple_assign_rhs2 (last_stmt);
2251   itype = TREE_TYPE (oprnd0);
2252   if (TREE_CODE (oprnd0) != SSA_NAME
2253       || TREE_CODE (oprnd1) != INTEGER_CST
2254       || TREE_CODE (itype) != INTEGER_TYPE
2255       || TYPE_PRECISION (itype) != GET_MODE_PRECISION (TYPE_MODE (itype)))
2256     return NULL;
2257 
2258   vectype = get_vectype_for_scalar_type (itype);
2259   if (vectype == NULL_TREE)
2260     return NULL;
2261 
2262   /* If the target can handle vectorized division or modulo natively,
2263      don't attempt to optimize this.  */
2264   optab = optab_for_tree_code (rhs_code, vectype, optab_default);
2265   if (optab != unknown_optab)
2266     {
2267       machine_mode vec_mode = TYPE_MODE (vectype);
2268       int icode = (int) optab_handler (optab, vec_mode);
2269       if (icode != CODE_FOR_nothing)
2270 	return NULL;
2271     }
2272 
2273   prec = TYPE_PRECISION (itype);
2274   if (integer_pow2p (oprnd1))
2275     {
2276       if (TYPE_UNSIGNED (itype) || tree_int_cst_sgn (oprnd1) != 1)
2277 	return NULL;
2278 
2279       /* Pattern detected.  */
2280       if (dump_enabled_p ())
2281         dump_printf_loc (MSG_NOTE, vect_location,
2282                          "vect_recog_divmod_pattern: detected:\n");
2283 
2284       cond = build2 (LT_EXPR, boolean_type_node, oprnd0,
2285 		     build_int_cst (itype, 0));
2286       if (rhs_code == TRUNC_DIV_EXPR)
2287 	{
2288 	  tree var = vect_recog_temp_ssa_var (itype, NULL);
2289 	  tree shift;
2290 	  def_stmt
2291 	    = gimple_build_assign (var, COND_EXPR, cond,
2292 				   fold_build2 (MINUS_EXPR, itype, oprnd1,
2293 						build_int_cst (itype, 1)),
2294 				   build_int_cst (itype, 0));
2295 	  new_pattern_def_seq (stmt_vinfo, def_stmt);
2296 	  var = vect_recog_temp_ssa_var (itype, NULL);
2297 	  def_stmt
2298 	    = gimple_build_assign (var, PLUS_EXPR, oprnd0,
2299 				   gimple_assign_lhs (def_stmt));
2300 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2301 
2302 	  shift = build_int_cst (itype, tree_log2 (oprnd1));
2303 	  pattern_stmt
2304 	    = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
2305 				   RSHIFT_EXPR, var, shift);
2306 	}
2307       else
2308 	{
2309 	  tree signmask;
2310 	  STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo) = NULL;
2311 	  if (compare_tree_int (oprnd1, 2) == 0)
2312 	    {
2313 	      signmask = vect_recog_temp_ssa_var (itype, NULL);
2314 	      def_stmt = gimple_build_assign (signmask, COND_EXPR, cond,
2315 					      build_int_cst (itype, 1),
2316 					      build_int_cst (itype, 0));
2317 	      append_pattern_def_seq (stmt_vinfo, def_stmt);
2318 	    }
2319 	  else
2320 	    {
2321 	      tree utype
2322 		= build_nonstandard_integer_type (prec, 1);
2323 	      tree vecutype = get_vectype_for_scalar_type (utype);
2324 	      tree shift
2325 		= build_int_cst (utype, GET_MODE_BITSIZE (TYPE_MODE (itype))
2326 					- tree_log2 (oprnd1));
2327 	      tree var = vect_recog_temp_ssa_var (utype, NULL);
2328 
2329 	      def_stmt = gimple_build_assign (var, COND_EXPR, cond,
2330 					      build_int_cst (utype, -1),
2331 					      build_int_cst (utype, 0));
2332 	      def_stmt_vinfo
2333 		= new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo);
2334 	      set_vinfo_for_stmt (def_stmt, def_stmt_vinfo);
2335 	      STMT_VINFO_VECTYPE (def_stmt_vinfo) = vecutype;
2336 	      append_pattern_def_seq (stmt_vinfo, def_stmt);
2337 	      var = vect_recog_temp_ssa_var (utype, NULL);
2338 	      def_stmt = gimple_build_assign (var, RSHIFT_EXPR,
2339 					      gimple_assign_lhs (def_stmt),
2340 					      shift);
2341 	      def_stmt_vinfo
2342 		= new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo);
2343 	      set_vinfo_for_stmt (def_stmt, def_stmt_vinfo);
2344 	      STMT_VINFO_VECTYPE (def_stmt_vinfo) = vecutype;
2345 	      append_pattern_def_seq (stmt_vinfo, def_stmt);
2346 	      signmask = vect_recog_temp_ssa_var (itype, NULL);
2347 	      def_stmt
2348 		= gimple_build_assign (signmask, NOP_EXPR, var);
2349 	      append_pattern_def_seq (stmt_vinfo, def_stmt);
2350 	    }
2351 	  def_stmt
2352 	    = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
2353 				   PLUS_EXPR, oprnd0, signmask);
2354 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2355 	  def_stmt
2356 	    = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
2357 				   BIT_AND_EXPR, gimple_assign_lhs (def_stmt),
2358 				   fold_build2 (MINUS_EXPR, itype, oprnd1,
2359 						build_int_cst (itype, 1)));
2360 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2361 
2362 	  pattern_stmt
2363 	    = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
2364 				   MINUS_EXPR, gimple_assign_lhs (def_stmt),
2365 				   signmask);
2366 	}
2367 
2368       if (dump_enabled_p ())
2369 	dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt,
2370                               0);
2371 
2372       stmts->safe_push (last_stmt);
2373 
2374       *type_in = vectype;
2375       *type_out = vectype;
2376       return pattern_stmt;
2377     }
2378 
2379   if (prec > HOST_BITS_PER_WIDE_INT
2380       || integer_zerop (oprnd1))
2381     return NULL;
2382 
2383   if (!can_mult_highpart_p (TYPE_MODE (vectype), TYPE_UNSIGNED (itype)))
2384     return NULL;
2385 
2386   STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo) = NULL;
2387 
2388   if (TYPE_UNSIGNED (itype))
2389     {
2390       unsigned HOST_WIDE_INT mh, ml;
2391       int pre_shift, post_shift;
2392       unsigned HOST_WIDE_INT d = (TREE_INT_CST_LOW (oprnd1)
2393 				  & GET_MODE_MASK (TYPE_MODE (itype)));
2394       tree t1, t2, t3, t4;
2395 
2396       if (d >= ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))
2397 	/* FIXME: Can transform this into oprnd0 >= oprnd1 ? 1 : 0.  */
2398 	return NULL;
2399 
2400       /* Find a suitable multiplier and right shift count
2401 	 instead of multiplying with D.  */
2402       mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
2403 
2404       /* If the suggested multiplier is more than SIZE bits, we can do better
2405 	 for even divisors, using an initial right shift.  */
2406       if (mh != 0 && (d & 1) == 0)
2407 	{
2408 	  pre_shift = floor_log2 (d & -d);
2409 	  mh = choose_multiplier (d >> pre_shift, prec, prec - pre_shift,
2410 				  &ml, &post_shift, &dummy_int);
2411 	  gcc_assert (!mh);
2412 	}
2413       else
2414 	pre_shift = 0;
2415 
2416       if (mh != 0)
2417 	{
2418 	  if (post_shift - 1 >= prec)
2419 	    return NULL;
2420 
2421 	  /* t1 = oprnd0 h* ml;
2422 	     t2 = oprnd0 - t1;
2423 	     t3 = t2 >> 1;
2424 	     t4 = t1 + t3;
2425 	     q = t4 >> (post_shift - 1);  */
2426 	  t1 = vect_recog_temp_ssa_var (itype, NULL);
2427 	  def_stmt = gimple_build_assign (t1, MULT_HIGHPART_EXPR, oprnd0,
2428 					  build_int_cst (itype, ml));
2429 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2430 
2431 	  t2 = vect_recog_temp_ssa_var (itype, NULL);
2432 	  def_stmt
2433 	    = gimple_build_assign (t2, MINUS_EXPR, oprnd0, t1);
2434 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2435 
2436 	  t3 = vect_recog_temp_ssa_var (itype, NULL);
2437 	  def_stmt
2438 	    = gimple_build_assign (t3, RSHIFT_EXPR, t2, integer_one_node);
2439 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2440 
2441 	  t4 = vect_recog_temp_ssa_var (itype, NULL);
2442 	  def_stmt
2443 	    = gimple_build_assign (t4, PLUS_EXPR, t1, t3);
2444 
2445 	  if (post_shift != 1)
2446 	    {
2447 	      append_pattern_def_seq (stmt_vinfo, def_stmt);
2448 
2449 	      q = vect_recog_temp_ssa_var (itype, NULL);
2450 	      pattern_stmt
2451 		= gimple_build_assign (q, RSHIFT_EXPR, t4,
2452 				       build_int_cst (itype, post_shift - 1));
2453 	    }
2454 	  else
2455 	    {
2456 	      q = t4;
2457 	      pattern_stmt = def_stmt;
2458 	    }
2459 	}
2460       else
2461 	{
2462 	  if (pre_shift >= prec || post_shift >= prec)
2463 	    return NULL;
2464 
2465 	  /* t1 = oprnd0 >> pre_shift;
2466 	     t2 = t1 h* ml;
2467 	     q = t2 >> post_shift;  */
2468 	  if (pre_shift)
2469 	    {
2470 	      t1 = vect_recog_temp_ssa_var (itype, NULL);
2471 	      def_stmt
2472 		= gimple_build_assign (t1, RSHIFT_EXPR, oprnd0,
2473 				       build_int_cst (NULL, pre_shift));
2474 	      append_pattern_def_seq (stmt_vinfo, def_stmt);
2475 	    }
2476 	  else
2477 	    t1 = oprnd0;
2478 
2479 	  t2 = vect_recog_temp_ssa_var (itype, NULL);
2480 	  def_stmt = gimple_build_assign (t2, MULT_HIGHPART_EXPR, t1,
2481 					  build_int_cst (itype, ml));
2482 
2483 	  if (post_shift)
2484 	    {
2485 	      append_pattern_def_seq (stmt_vinfo, def_stmt);
2486 
2487 	      q = vect_recog_temp_ssa_var (itype, NULL);
2488 	      def_stmt
2489 		= gimple_build_assign (q, RSHIFT_EXPR, t2,
2490 				       build_int_cst (itype, post_shift));
2491 	    }
2492 	  else
2493 	    q = t2;
2494 
2495 	  pattern_stmt = def_stmt;
2496 	}
2497     }
2498   else
2499     {
2500       unsigned HOST_WIDE_INT ml;
2501       int post_shift;
2502       HOST_WIDE_INT d = TREE_INT_CST_LOW (oprnd1);
2503       unsigned HOST_WIDE_INT abs_d;
2504       bool add = false;
2505       tree t1, t2, t3, t4;
2506 
2507       /* Give up for -1.  */
2508       if (d == -1)
2509 	return NULL;
2510 
2511       /* Since d might be INT_MIN, we have to cast to
2512 	 unsigned HOST_WIDE_INT before negating to avoid
2513 	 undefined signed overflow.  */
2514       abs_d = (d >= 0
2515 	       ? (unsigned HOST_WIDE_INT) d
2516 	       : - (unsigned HOST_WIDE_INT) d);
2517 
2518       /* n rem d = n rem -d */
2519       if (rhs_code == TRUNC_MOD_EXPR && d < 0)
2520 	{
2521 	  d = abs_d;
2522 	  oprnd1 = build_int_cst (itype, abs_d);
2523 	}
2524       else if (HOST_BITS_PER_WIDE_INT >= prec
2525 	       && abs_d == (unsigned HOST_WIDE_INT) 1 << (prec - 1))
2526 	/* This case is not handled correctly below.  */
2527 	return NULL;
2528 
2529       choose_multiplier (abs_d, prec, prec - 1, &ml, &post_shift, &dummy_int);
2530       if (ml >= (unsigned HOST_WIDE_INT) 1 << (prec - 1))
2531 	{
2532 	  add = true;
2533 	  ml |= (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
2534 	}
2535       if (post_shift >= prec)
2536 	return NULL;
2537 
2538       /* t1 = oprnd0 h* ml;  */
2539       t1 = vect_recog_temp_ssa_var (itype, NULL);
2540       def_stmt = gimple_build_assign (t1, MULT_HIGHPART_EXPR, oprnd0,
2541 				      build_int_cst (itype, ml));
2542 
2543       if (add)
2544 	{
2545 	  /* t2 = t1 + oprnd0;  */
2546 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2547 	  t2 = vect_recog_temp_ssa_var (itype, NULL);
2548 	  def_stmt = gimple_build_assign (t2, PLUS_EXPR, t1, oprnd0);
2549 	}
2550       else
2551 	t2 = t1;
2552 
2553       if (post_shift)
2554 	{
2555 	  /* t3 = t2 >> post_shift;  */
2556 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2557 	  t3 = vect_recog_temp_ssa_var (itype, NULL);
2558 	  def_stmt = gimple_build_assign (t3, RSHIFT_EXPR, t2,
2559 					  build_int_cst (itype, post_shift));
2560 	}
2561       else
2562 	t3 = t2;
2563 
2564       wide_int oprnd0_min, oprnd0_max;
2565       int msb = 1;
2566       if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE)
2567 	{
2568 	  if (!wi::neg_p (oprnd0_min, TYPE_SIGN (itype)))
2569 	    msb = 0;
2570 	  else if (wi::neg_p (oprnd0_max, TYPE_SIGN (itype)))
2571 	    msb = -1;
2572 	}
2573 
2574       if (msb == 0 && d >= 0)
2575 	{
2576 	  /* q = t3;  */
2577 	  q = t3;
2578 	  pattern_stmt = def_stmt;
2579 	}
2580       else
2581 	{
2582 	  /* t4 = oprnd0 >> (prec - 1);
2583 	     or if we know from VRP that oprnd0 >= 0
2584 	     t4 = 0;
2585 	     or if we know from VRP that oprnd0 < 0
2586 	     t4 = -1;  */
2587 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2588 	  t4 = vect_recog_temp_ssa_var (itype, NULL);
2589 	  if (msb != 1)
2590 	    def_stmt = gimple_build_assign (t4, INTEGER_CST,
2591 					    build_int_cst (itype, msb));
2592 	  else
2593 	    def_stmt = gimple_build_assign (t4, RSHIFT_EXPR, oprnd0,
2594 					    build_int_cst (itype, prec - 1));
2595 	  append_pattern_def_seq (stmt_vinfo, def_stmt);
2596 
2597 	  /* q = t3 - t4;  or q = t4 - t3;  */
2598 	  q = vect_recog_temp_ssa_var (itype, NULL);
2599 	  pattern_stmt = gimple_build_assign (q, MINUS_EXPR, d < 0 ? t4 : t3,
2600 					      d < 0 ? t3 : t4);
2601 	}
2602     }
2603 
2604   if (rhs_code == TRUNC_MOD_EXPR)
2605     {
2606       tree r, t1;
2607 
2608       /* We divided.  Now finish by:
2609 	 t1 = q * oprnd1;
2610 	 r = oprnd0 - t1;  */
2611       append_pattern_def_seq (stmt_vinfo, pattern_stmt);
2612 
2613       t1 = vect_recog_temp_ssa_var (itype, NULL);
2614       def_stmt = gimple_build_assign (t1, MULT_EXPR, q, oprnd1);
2615       append_pattern_def_seq (stmt_vinfo, def_stmt);
2616 
2617       r = vect_recog_temp_ssa_var (itype, NULL);
2618       pattern_stmt = gimple_build_assign (r, MINUS_EXPR, oprnd0, t1);
2619     }
2620 
2621   /* Pattern detected.  */
2622   if (dump_enabled_p ())
2623     {
2624       dump_printf_loc (MSG_NOTE, vect_location,
2625                        "vect_recog_divmod_pattern: detected: ");
2626       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
2627       dump_printf (MSG_NOTE, "\n");
2628     }
2629 
2630   stmts->safe_push (last_stmt);
2631 
2632   *type_in = vectype;
2633   *type_out = vectype;
2634   return pattern_stmt;
2635 }
2636 
2637 /* Function vect_recog_mixed_size_cond_pattern
2638 
2639    Try to find the following pattern:
2640 
2641      type x_t, y_t;
2642      TYPE a_T, b_T, c_T;
2643    loop:
2644      S1  a_T = x_t CMP y_t ? b_T : c_T;
2645 
2646    where type 'TYPE' is an integral type which has different size
2647    from 'type'.  b_T and c_T are either constants (and if 'TYPE' is wider
2648    than 'type', the constants need to fit into an integer type
2649    with the same width as 'type') or results of conversion from 'type'.
2650 
2651    Input:
2652 
2653    * LAST_STMT: A stmt from which the pattern search begins.
2654 
2655    Output:
2656 
2657    * TYPE_IN: The type of the input arguments to the pattern.
2658 
2659    * TYPE_OUT: The type of the output of this pattern.
2660 
2661    * Return value: A new stmt that will be used to replace the pattern.
2662 	Additionally a def_stmt is added.
2663 
2664 	a_it = x_t CMP y_t ? b_it : c_it;
2665 	a_T = (TYPE) a_it;  */
2666 
2667 static gimple
2668 vect_recog_mixed_size_cond_pattern (vec<gimple> *stmts, tree *type_in,
2669 				    tree *type_out)
2670 {
2671   gimple last_stmt = (*stmts)[0];
2672   tree cond_expr, then_clause, else_clause;
2673   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt), def_stmt_info;
2674   tree type, vectype, comp_vectype, itype = NULL_TREE, vecitype;
2675   machine_mode cmpmode;
2676   gimple pattern_stmt, def_stmt;
2677   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
2678   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
2679   tree orig_type0 = NULL_TREE, orig_type1 = NULL_TREE;
2680   gimple def_stmt0 = NULL, def_stmt1 = NULL;
2681   bool promotion;
2682   tree comp_scalar_type;
2683 
2684   if (!is_gimple_assign (last_stmt)
2685       || gimple_assign_rhs_code (last_stmt) != COND_EXPR
2686       || STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_internal_def)
2687     return NULL;
2688 
2689   cond_expr = gimple_assign_rhs1 (last_stmt);
2690   then_clause = gimple_assign_rhs2 (last_stmt);
2691   else_clause = gimple_assign_rhs3 (last_stmt);
2692 
2693   if (!COMPARISON_CLASS_P (cond_expr))
2694     return NULL;
2695 
2696   comp_scalar_type = TREE_TYPE (TREE_OPERAND (cond_expr, 0));
2697   comp_vectype = get_vectype_for_scalar_type (comp_scalar_type);
2698   if (comp_vectype == NULL_TREE)
2699     return NULL;
2700 
2701   type = gimple_expr_type (last_stmt);
2702   if (types_compatible_p (type, comp_scalar_type)
2703       || ((TREE_CODE (then_clause) != INTEGER_CST
2704 	   || TREE_CODE (else_clause) != INTEGER_CST)
2705 	  && !INTEGRAL_TYPE_P (comp_scalar_type))
2706       || !INTEGRAL_TYPE_P (type))
2707     return NULL;
2708 
2709   if ((TREE_CODE (then_clause) != INTEGER_CST
2710        && !type_conversion_p (then_clause, last_stmt, false, &orig_type0,
2711                               &def_stmt0, &promotion))
2712       || (TREE_CODE (else_clause) != INTEGER_CST
2713           && !type_conversion_p (else_clause, last_stmt, false, &orig_type1,
2714                                  &def_stmt1, &promotion)))
2715     return NULL;
2716 
2717   if (orig_type0 && orig_type1
2718       && !types_compatible_p (orig_type0, orig_type1))
2719     return NULL;
2720 
2721   if (orig_type0)
2722     {
2723       if (!types_compatible_p (orig_type0, comp_scalar_type))
2724 	return NULL;
2725       then_clause = gimple_assign_rhs1 (def_stmt0);
2726       itype = orig_type0;
2727     }
2728 
2729   if (orig_type1)
2730     {
2731       if (!types_compatible_p (orig_type1, comp_scalar_type))
2732 	return NULL;
2733       else_clause = gimple_assign_rhs1 (def_stmt1);
2734       itype = orig_type1;
2735     }
2736 
2737   cmpmode = GET_MODE_INNER (TYPE_MODE (comp_vectype));
2738 
2739   if (GET_MODE_BITSIZE (TYPE_MODE (type)) == GET_MODE_BITSIZE (cmpmode))
2740     return NULL;
2741 
2742   vectype = get_vectype_for_scalar_type (type);
2743   if (vectype == NULL_TREE)
2744     return NULL;
2745 
2746   if (expand_vec_cond_expr_p (vectype, comp_vectype))
2747     return NULL;
2748 
2749   if (itype == NULL_TREE)
2750     itype = build_nonstandard_integer_type (GET_MODE_BITSIZE (cmpmode),
2751   					    TYPE_UNSIGNED (type));
2752 
2753   if (itype == NULL_TREE
2754       || GET_MODE_BITSIZE (TYPE_MODE (itype)) != GET_MODE_BITSIZE (cmpmode))
2755     return NULL;
2756 
2757   vecitype = get_vectype_for_scalar_type (itype);
2758   if (vecitype == NULL_TREE)
2759     return NULL;
2760 
2761   if (!expand_vec_cond_expr_p (vecitype, comp_vectype))
2762     return NULL;
2763 
2764   if (GET_MODE_BITSIZE (TYPE_MODE (type)) > GET_MODE_BITSIZE (cmpmode))
2765     {
2766       if ((TREE_CODE (then_clause) == INTEGER_CST
2767 	   && !int_fits_type_p (then_clause, itype))
2768 	  || (TREE_CODE (else_clause) == INTEGER_CST
2769 	      && !int_fits_type_p (else_clause, itype)))
2770 	return NULL;
2771     }
2772 
2773   def_stmt = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
2774 				  COND_EXPR, unshare_expr (cond_expr),
2775 				  fold_convert (itype, then_clause),
2776 				  fold_convert (itype, else_clause));
2777   pattern_stmt = gimple_build_assign (vect_recog_temp_ssa_var (type, NULL),
2778 				      NOP_EXPR, gimple_assign_lhs (def_stmt));
2779 
2780   new_pattern_def_seq (stmt_vinfo, def_stmt);
2781   def_stmt_info = new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo);
2782   set_vinfo_for_stmt (def_stmt, def_stmt_info);
2783   STMT_VINFO_VECTYPE (def_stmt_info) = vecitype;
2784   *type_in = vecitype;
2785   *type_out = vectype;
2786 
2787   if (dump_enabled_p ())
2788     dump_printf_loc (MSG_NOTE, vect_location,
2789                      "vect_recog_mixed_size_cond_pattern: detected:\n");
2790 
2791   return pattern_stmt;
2792 }
2793 
2794 
2795 /* Helper function of vect_recog_bool_pattern.  Called recursively, return
2796    true if bool VAR can be optimized that way.  */
2797 
2798 static bool
2799 check_bool_pattern (tree var, loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
2800 {
2801   gimple def_stmt;
2802   enum vect_def_type dt;
2803   tree def, rhs1;
2804   enum tree_code rhs_code;
2805 
2806   if (!vect_is_simple_use (var, NULL, loop_vinfo, bb_vinfo, &def_stmt, &def,
2807 			   &dt))
2808     return false;
2809 
2810   if (dt != vect_internal_def)
2811     return false;
2812 
2813   if (!is_gimple_assign (def_stmt))
2814     return false;
2815 
2816   if (!has_single_use (def))
2817     return false;
2818 
2819   rhs1 = gimple_assign_rhs1 (def_stmt);
2820   rhs_code = gimple_assign_rhs_code (def_stmt);
2821   switch (rhs_code)
2822     {
2823     case SSA_NAME:
2824       return check_bool_pattern (rhs1, loop_vinfo, bb_vinfo);
2825 
2826     CASE_CONVERT:
2827       if ((TYPE_PRECISION (TREE_TYPE (rhs1)) != 1
2828 	   || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
2829 	  && TREE_CODE (TREE_TYPE (rhs1)) != BOOLEAN_TYPE)
2830 	return false;
2831       return check_bool_pattern (rhs1, loop_vinfo, bb_vinfo);
2832 
2833     case BIT_NOT_EXPR:
2834       return check_bool_pattern (rhs1, loop_vinfo, bb_vinfo);
2835 
2836     case BIT_AND_EXPR:
2837     case BIT_IOR_EXPR:
2838     case BIT_XOR_EXPR:
2839       if (!check_bool_pattern (rhs1, loop_vinfo, bb_vinfo))
2840 	return false;
2841       return check_bool_pattern (gimple_assign_rhs2 (def_stmt), loop_vinfo,
2842 				 bb_vinfo);
2843 
2844     default:
2845       if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
2846 	{
2847 	  tree vecitype, comp_vectype;
2848 
2849 	  /* If the comparison can throw, then is_gimple_condexpr will be
2850 	     false and we can't make a COND_EXPR/VEC_COND_EXPR out of it.  */
2851 	  if (stmt_could_throw_p (def_stmt))
2852 	    return false;
2853 
2854 	  comp_vectype = get_vectype_for_scalar_type (TREE_TYPE (rhs1));
2855 	  if (comp_vectype == NULL_TREE)
2856 	    return false;
2857 
2858 	  if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE)
2859 	    {
2860 	      machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
2861 	      tree itype
2862 		= build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
2863 	      vecitype = get_vectype_for_scalar_type (itype);
2864 	      if (vecitype == NULL_TREE)
2865 		return false;
2866 	    }
2867 	  else
2868 	    vecitype = comp_vectype;
2869 	  return expand_vec_cond_expr_p (vecitype, comp_vectype);
2870 	}
2871       return false;
2872     }
2873 }
2874 
2875 
2876 /* Helper function of adjust_bool_pattern.  Add a cast to TYPE to a previous
2877    stmt (SSA_NAME_DEF_STMT of VAR) by moving the COND_EXPR from RELATED_STMT
2878    to PATTERN_DEF_SEQ and adding a cast as RELATED_STMT.  */
2879 
2880 static tree
2881 adjust_bool_pattern_cast (tree type, tree var)
2882 {
2883   stmt_vec_info stmt_vinfo = vinfo_for_stmt (SSA_NAME_DEF_STMT (var));
2884   gimple cast_stmt, pattern_stmt;
2885 
2886   gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo));
2887   pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
2888   new_pattern_def_seq (stmt_vinfo, pattern_stmt);
2889   cast_stmt = gimple_build_assign (vect_recog_temp_ssa_var (type, NULL),
2890 				   NOP_EXPR, gimple_assign_lhs (pattern_stmt));
2891   STMT_VINFO_RELATED_STMT (stmt_vinfo) = cast_stmt;
2892   return gimple_assign_lhs (cast_stmt);
2893 }
2894 
2895 
2896 /* Helper function of vect_recog_bool_pattern.  Do the actual transformations,
2897    recursively.  VAR is an SSA_NAME that should be transformed from bool
2898    to a wider integer type, OUT_TYPE is the desired final integer type of
2899    the whole pattern, TRUEVAL should be NULL unless optimizing
2900    BIT_AND_EXPR into a COND_EXPR with one integer from one of the operands
2901    in the then_clause, STMTS is where statements with added pattern stmts
2902    should be pushed to.  */
2903 
2904 static tree
2905 adjust_bool_pattern (tree var, tree out_type, tree trueval,
2906 		     vec<gimple> *stmts)
2907 {
2908   gimple stmt = SSA_NAME_DEF_STMT (var);
2909   enum tree_code rhs_code, def_rhs_code;
2910   tree itype, cond_expr, rhs1, rhs2, irhs1, irhs2;
2911   location_t loc;
2912   gimple pattern_stmt, def_stmt;
2913 
2914   rhs1 = gimple_assign_rhs1 (stmt);
2915   rhs2 = gimple_assign_rhs2 (stmt);
2916   rhs_code = gimple_assign_rhs_code (stmt);
2917   loc = gimple_location (stmt);
2918   switch (rhs_code)
2919     {
2920     case SSA_NAME:
2921     CASE_CONVERT:
2922       irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
2923       itype = TREE_TYPE (irhs1);
2924       pattern_stmt
2925 	= gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
2926 			       SSA_NAME, irhs1);
2927       break;
2928 
2929     case BIT_NOT_EXPR:
2930       irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
2931       itype = TREE_TYPE (irhs1);
2932       pattern_stmt
2933 	= gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
2934 			       BIT_XOR_EXPR, irhs1, build_int_cst (itype, 1));
2935       break;
2936 
2937     case BIT_AND_EXPR:
2938       /* Try to optimize x = y & (a < b ? 1 : 0); into
2939 	 x = (a < b ? y : 0);
2940 
2941 	 E.g. for:
2942 	   bool a_b, b_b, c_b;
2943 	   TYPE d_T;
2944 
2945 	   S1  a_b = x1 CMP1 y1;
2946 	   S2  b_b = x2 CMP2 y2;
2947 	   S3  c_b = a_b & b_b;
2948 	   S4  d_T = (TYPE) c_b;
2949 
2950 	 we would normally emit:
2951 
2952 	   S1'  a_T = x1 CMP1 y1 ? 1 : 0;
2953 	   S2'  b_T = x2 CMP2 y2 ? 1 : 0;
2954 	   S3'  c_T = a_T & b_T;
2955 	   S4'  d_T = c_T;
2956 
2957 	 but we can save one stmt by using the
2958 	 result of one of the COND_EXPRs in the other COND_EXPR and leave
2959 	 BIT_AND_EXPR stmt out:
2960 
2961 	   S1'  a_T = x1 CMP1 y1 ? 1 : 0;
2962 	   S3'  c_T = x2 CMP2 y2 ? a_T : 0;
2963 	   S4'  f_T = c_T;
2964 
2965 	 At least when VEC_COND_EXPR is implemented using masks
2966 	 cond ? 1 : 0 is as expensive as cond ? var : 0, in both cases it
2967 	 computes the comparison masks and ands it, in one case with
2968 	 all ones vector, in the other case with a vector register.
2969 	 Don't do this for BIT_IOR_EXPR, because cond ? 1 : var; is
2970 	 often more expensive.  */
2971       def_stmt = SSA_NAME_DEF_STMT (rhs2);
2972       def_rhs_code = gimple_assign_rhs_code (def_stmt);
2973       if (TREE_CODE_CLASS (def_rhs_code) == tcc_comparison)
2974 	{
2975 	  tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
2976 	  irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
2977 	  if (TYPE_PRECISION (TREE_TYPE (irhs1))
2978 	      == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
2979 	    {
2980 	      gimple tstmt;
2981 	      stmt_vec_info stmt_def_vinfo = vinfo_for_stmt (def_stmt);
2982 	      irhs2 = adjust_bool_pattern (rhs2, out_type, irhs1, stmts);
2983 	      tstmt = stmts->pop ();
2984 	      gcc_assert (tstmt == def_stmt);
2985 	      stmts->quick_push (stmt);
2986 	      STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt))
2987 		= STMT_VINFO_RELATED_STMT (stmt_def_vinfo);
2988 	      gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_def_vinfo));
2989 	      STMT_VINFO_RELATED_STMT (stmt_def_vinfo) = NULL;
2990 	      return irhs2;
2991 	    }
2992 	  else
2993 	    irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
2994 	  goto and_ior_xor;
2995 	}
2996       def_stmt = SSA_NAME_DEF_STMT (rhs1);
2997       def_rhs_code = gimple_assign_rhs_code (def_stmt);
2998       if (TREE_CODE_CLASS (def_rhs_code) == tcc_comparison)
2999 	{
3000 	  tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
3001 	  irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
3002 	  if (TYPE_PRECISION (TREE_TYPE (irhs2))
3003 	      == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
3004 	    {
3005 	      gimple tstmt;
3006 	      stmt_vec_info stmt_def_vinfo = vinfo_for_stmt (def_stmt);
3007 	      irhs1 = adjust_bool_pattern (rhs1, out_type, irhs2, stmts);
3008 	      tstmt = stmts->pop ();
3009 	      gcc_assert (tstmt == def_stmt);
3010 	      stmts->quick_push (stmt);
3011 	      STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt))
3012 		= STMT_VINFO_RELATED_STMT (stmt_def_vinfo);
3013 	      gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_def_vinfo));
3014 	      STMT_VINFO_RELATED_STMT (stmt_def_vinfo) = NULL;
3015 	      return irhs1;
3016 	    }
3017 	  else
3018 	    irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
3019 	  goto and_ior_xor;
3020 	}
3021       /* FALLTHRU */
3022     case BIT_IOR_EXPR:
3023     case BIT_XOR_EXPR:
3024       irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
3025       irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
3026     and_ior_xor:
3027       if (TYPE_PRECISION (TREE_TYPE (irhs1))
3028 	  != TYPE_PRECISION (TREE_TYPE (irhs2)))
3029 	{
3030 	  int prec1 = TYPE_PRECISION (TREE_TYPE (irhs1));
3031 	  int prec2 = TYPE_PRECISION (TREE_TYPE (irhs2));
3032 	  int out_prec = TYPE_PRECISION (out_type);
3033 	  if (absu_hwi (out_prec - prec1) < absu_hwi (out_prec - prec2))
3034 	    irhs2 = adjust_bool_pattern_cast (TREE_TYPE (irhs1), rhs2);
3035 	  else if (absu_hwi (out_prec - prec1) > absu_hwi (out_prec - prec2))
3036 	    irhs1 = adjust_bool_pattern_cast (TREE_TYPE (irhs2), rhs1);
3037 	  else
3038 	    {
3039 	      irhs1 = adjust_bool_pattern_cast (out_type, rhs1);
3040 	      irhs2 = adjust_bool_pattern_cast (out_type, rhs2);
3041 	    }
3042 	}
3043       itype = TREE_TYPE (irhs1);
3044       pattern_stmt
3045 	= gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
3046 			       rhs_code, irhs1, irhs2);
3047       break;
3048 
3049     default:
3050       gcc_assert (TREE_CODE_CLASS (rhs_code) == tcc_comparison);
3051       if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE
3052 	  || !TYPE_UNSIGNED (TREE_TYPE (rhs1))
3053 	  || (TYPE_PRECISION (TREE_TYPE (rhs1))
3054 	      != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1)))))
3055 	{
3056 	  machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
3057 	  itype
3058 	    = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
3059 	}
3060       else
3061 	itype = TREE_TYPE (rhs1);
3062       cond_expr = build2_loc (loc, rhs_code, itype, rhs1, rhs2);
3063       if (trueval == NULL_TREE)
3064 	trueval = build_int_cst (itype, 1);
3065       else
3066 	gcc_checking_assert (useless_type_conversion_p (itype,
3067 							TREE_TYPE (trueval)));
3068       pattern_stmt
3069 	= gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
3070 			       COND_EXPR, cond_expr, trueval,
3071 			       build_int_cst (itype, 0));
3072       break;
3073     }
3074 
3075   stmts->safe_push (stmt);
3076   gimple_set_location (pattern_stmt, loc);
3077   STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt)) = pattern_stmt;
3078   return gimple_assign_lhs (pattern_stmt);
3079 }
3080 
3081 
3082 /* Function vect_recog_bool_pattern
3083 
3084    Try to find pattern like following:
3085 
3086      bool a_b, b_b, c_b, d_b, e_b;
3087      TYPE f_T;
3088    loop:
3089      S1  a_b = x1 CMP1 y1;
3090      S2  b_b = x2 CMP2 y2;
3091      S3  c_b = a_b & b_b;
3092      S4  d_b = x3 CMP3 y3;
3093      S5  e_b = c_b | d_b;
3094      S6  f_T = (TYPE) e_b;
3095 
3096    where type 'TYPE' is an integral type.  Or a similar pattern
3097    ending in
3098 
3099      S6  f_Y = e_b ? r_Y : s_Y;
3100 
3101    as results from if-conversion of a complex condition.
3102 
3103    Input:
3104 
3105    * LAST_STMT: A stmt at the end from which the pattern
3106 		search begins, i.e. cast of a bool to
3107 		an integer type.
3108 
3109    Output:
3110 
3111    * TYPE_IN: The type of the input arguments to the pattern.
3112 
3113    * TYPE_OUT: The type of the output of this pattern.
3114 
3115    * Return value: A new stmt that will be used to replace the pattern.
3116 
3117 	Assuming size of TYPE is the same as size of all comparisons
3118 	(otherwise some casts would be added where needed), the above
3119 	sequence we create related pattern stmts:
3120 	S1'  a_T = x1 CMP1 y1 ? 1 : 0;
3121 	S3'  c_T = x2 CMP2 y2 ? a_T : 0;
3122 	S4'  d_T = x3 CMP3 y3 ? 1 : 0;
3123 	S5'  e_T = c_T | d_T;
3124 	S6'  f_T = e_T;
3125 
3126 	Instead of the above S3' we could emit:
3127 	S2'  b_T = x2 CMP2 y2 ? 1 : 0;
3128 	S3'  c_T = a_T | b_T;
3129 	but the above is more efficient.  */
3130 
3131 static gimple
3132 vect_recog_bool_pattern (vec<gimple> *stmts, tree *type_in,
3133 			 tree *type_out)
3134 {
3135   gimple last_stmt = stmts->pop ();
3136   enum tree_code rhs_code;
3137   tree var, lhs, rhs, vectype;
3138   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
3139   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
3140   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
3141   gimple pattern_stmt;
3142 
3143   if (!is_gimple_assign (last_stmt))
3144     return NULL;
3145 
3146   var = gimple_assign_rhs1 (last_stmt);
3147   lhs = gimple_assign_lhs (last_stmt);
3148 
3149   if ((TYPE_PRECISION (TREE_TYPE (var)) != 1
3150        || !TYPE_UNSIGNED (TREE_TYPE (var)))
3151       && TREE_CODE (TREE_TYPE (var)) != BOOLEAN_TYPE)
3152     return NULL;
3153 
3154   rhs_code = gimple_assign_rhs_code (last_stmt);
3155   if (CONVERT_EXPR_CODE_P (rhs_code))
3156     {
3157       if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE
3158 	  || TYPE_PRECISION (TREE_TYPE (lhs)) == 1)
3159 	return NULL;
3160       vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs));
3161       if (vectype == NULL_TREE)
3162 	return NULL;
3163 
3164       if (!check_bool_pattern (var, loop_vinfo, bb_vinfo))
3165 	return NULL;
3166 
3167       rhs = adjust_bool_pattern (var, TREE_TYPE (lhs), NULL_TREE, stmts);
3168       lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
3169       if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3170 	pattern_stmt = gimple_build_assign (lhs, SSA_NAME, rhs);
3171       else
3172 	pattern_stmt
3173 	  = gimple_build_assign (lhs, NOP_EXPR, rhs);
3174       *type_out = vectype;
3175       *type_in = vectype;
3176       stmts->safe_push (last_stmt);
3177       if (dump_enabled_p ())
3178 	dump_printf_loc (MSG_NOTE, vect_location,
3179                          "vect_recog_bool_pattern: detected:\n");
3180 
3181       return pattern_stmt;
3182     }
3183   else if (rhs_code == COND_EXPR
3184 	   && TREE_CODE (var) == SSA_NAME)
3185     {
3186       vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs));
3187       if (vectype == NULL_TREE)
3188 	return NULL;
3189 
3190       /* Build a scalar type for the boolean result that when
3191          vectorized matches the vector type of the result in
3192 	 size and number of elements.  */
3193       unsigned prec
3194 	= wi::udiv_trunc (TYPE_SIZE (vectype),
3195 			  TYPE_VECTOR_SUBPARTS (vectype)).to_uhwi ();
3196       tree type
3197 	= build_nonstandard_integer_type (prec,
3198 					  TYPE_UNSIGNED (TREE_TYPE (var)));
3199       if (get_vectype_for_scalar_type (type) == NULL_TREE)
3200 	return NULL;
3201 
3202       if (!check_bool_pattern (var, loop_vinfo, bb_vinfo))
3203 	return NULL;
3204 
3205       rhs = adjust_bool_pattern (var, type, NULL_TREE, stmts);
3206       lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
3207       pattern_stmt
3208 	  = gimple_build_assign (lhs, COND_EXPR,
3209 				 build2 (NE_EXPR, boolean_type_node,
3210 					 rhs, build_int_cst (type, 0)),
3211 				 gimple_assign_rhs2 (last_stmt),
3212 				 gimple_assign_rhs3 (last_stmt));
3213       *type_out = vectype;
3214       *type_in = vectype;
3215       stmts->safe_push (last_stmt);
3216       if (dump_enabled_p ())
3217 	dump_printf_loc (MSG_NOTE, vect_location,
3218                          "vect_recog_bool_pattern: detected:\n");
3219 
3220       return pattern_stmt;
3221     }
3222   else if (rhs_code == SSA_NAME
3223 	   && STMT_VINFO_DATA_REF (stmt_vinfo))
3224     {
3225       stmt_vec_info pattern_stmt_info;
3226       vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
3227       gcc_assert (vectype != NULL_TREE);
3228       if (!VECTOR_MODE_P (TYPE_MODE (vectype)))
3229 	return NULL;
3230       if (!check_bool_pattern (var, loop_vinfo, bb_vinfo))
3231 	return NULL;
3232 
3233       rhs = adjust_bool_pattern (var, TREE_TYPE (vectype), NULL_TREE, stmts);
3234       lhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (vectype), lhs);
3235       if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3236 	{
3237 	  tree rhs2 = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
3238 	  gimple cast_stmt = gimple_build_assign (rhs2, NOP_EXPR, rhs);
3239 	  new_pattern_def_seq (stmt_vinfo, cast_stmt);
3240 	  rhs = rhs2;
3241 	}
3242       pattern_stmt = gimple_build_assign (lhs, SSA_NAME, rhs);
3243       pattern_stmt_info = new_stmt_vec_info (pattern_stmt, loop_vinfo,
3244 						bb_vinfo);
3245       set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
3246       STMT_VINFO_DATA_REF (pattern_stmt_info)
3247 	= STMT_VINFO_DATA_REF (stmt_vinfo);
3248       STMT_VINFO_DR_BASE_ADDRESS (pattern_stmt_info)
3249 	= STMT_VINFO_DR_BASE_ADDRESS (stmt_vinfo);
3250       STMT_VINFO_DR_INIT (pattern_stmt_info) = STMT_VINFO_DR_INIT (stmt_vinfo);
3251       STMT_VINFO_DR_OFFSET (pattern_stmt_info)
3252 	= STMT_VINFO_DR_OFFSET (stmt_vinfo);
3253       STMT_VINFO_DR_STEP (pattern_stmt_info) = STMT_VINFO_DR_STEP (stmt_vinfo);
3254       STMT_VINFO_DR_ALIGNED_TO (pattern_stmt_info)
3255 	= STMT_VINFO_DR_ALIGNED_TO (stmt_vinfo);
3256       DR_STMT (STMT_VINFO_DATA_REF (stmt_vinfo)) = pattern_stmt;
3257       *type_out = vectype;
3258       *type_in = vectype;
3259       stmts->safe_push (last_stmt);
3260       if (dump_enabled_p ())
3261 	dump_printf_loc (MSG_NOTE, vect_location,
3262                          "vect_recog_bool_pattern: detected:\n");
3263       return pattern_stmt;
3264     }
3265   else
3266     return NULL;
3267 }
3268 
3269 
3270 /* Mark statements that are involved in a pattern.  */
3271 
3272 static inline void
3273 vect_mark_pattern_stmts (gimple orig_stmt, gimple pattern_stmt,
3274                          tree pattern_vectype)
3275 {
3276   stmt_vec_info pattern_stmt_info, def_stmt_info;
3277   stmt_vec_info orig_stmt_info = vinfo_for_stmt (orig_stmt);
3278   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (orig_stmt_info);
3279   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (orig_stmt_info);
3280   gimple def_stmt;
3281 
3282   pattern_stmt_info = vinfo_for_stmt (pattern_stmt);
3283   if (pattern_stmt_info == NULL)
3284     {
3285       pattern_stmt_info = new_stmt_vec_info (pattern_stmt, loop_vinfo,
3286 						bb_vinfo);
3287       set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
3288     }
3289   gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt));
3290 
3291   STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt;
3292   STMT_VINFO_DEF_TYPE (pattern_stmt_info)
3293     = STMT_VINFO_DEF_TYPE (orig_stmt_info);
3294   STMT_VINFO_VECTYPE (pattern_stmt_info) = pattern_vectype;
3295   STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
3296   STMT_VINFO_RELATED_STMT (orig_stmt_info) = pattern_stmt;
3297   STMT_VINFO_PATTERN_DEF_SEQ (pattern_stmt_info)
3298     = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
3299   if (STMT_VINFO_PATTERN_DEF_SEQ (pattern_stmt_info))
3300     {
3301       gimple_stmt_iterator si;
3302       for (si = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (pattern_stmt_info));
3303 	   !gsi_end_p (si); gsi_next (&si))
3304 	{
3305 	  def_stmt = gsi_stmt (si);
3306 	  def_stmt_info = vinfo_for_stmt (def_stmt);
3307 	  if (def_stmt_info == NULL)
3308 	    {
3309 	      def_stmt_info = new_stmt_vec_info (def_stmt, loop_vinfo,
3310 						 bb_vinfo);
3311 	      set_vinfo_for_stmt (def_stmt, def_stmt_info);
3312 	    }
3313 	  gimple_set_bb (def_stmt, gimple_bb (orig_stmt));
3314 	  STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt;
3315 	  STMT_VINFO_DEF_TYPE (def_stmt_info) = vect_internal_def;
3316 	  if (STMT_VINFO_VECTYPE (def_stmt_info) == NULL_TREE)
3317 	    STMT_VINFO_VECTYPE (def_stmt_info) = pattern_vectype;
3318 	}
3319     }
3320 }
3321 
3322 /* Function vect_pattern_recog_1
3323 
3324    Input:
3325    PATTERN_RECOG_FUNC: A pointer to a function that detects a certain
3326         computation pattern.
3327    STMT: A stmt from which the pattern search should start.
3328 
3329    If PATTERN_RECOG_FUNC successfully detected the pattern, it creates an
3330    expression that computes the same functionality and can be used to
3331    replace the sequence of stmts that are involved in the pattern.
3332 
3333    Output:
3334    This function checks if the expression returned by PATTERN_RECOG_FUNC is
3335    supported in vector form by the target.  We use 'TYPE_IN' to obtain the
3336    relevant vector type. If 'TYPE_IN' is already a vector type, then this
3337    indicates that target support had already been checked by PATTERN_RECOG_FUNC.
3338    If 'TYPE_OUT' is also returned by PATTERN_RECOG_FUNC, we check that it fits
3339    to the available target pattern.
3340 
3341    This function also does some bookkeeping, as explained in the documentation
3342    for vect_recog_pattern.  */
3343 
3344 static void
3345 vect_pattern_recog_1 (vect_recog_func_ptr vect_recog_func,
3346 		      gimple_stmt_iterator si,
3347 		      vec<gimple> *stmts_to_replace)
3348 {
3349   gimple stmt = gsi_stmt (si), pattern_stmt;
3350   stmt_vec_info stmt_info;
3351   loop_vec_info loop_vinfo;
3352   tree pattern_vectype;
3353   tree type_in, type_out;
3354   enum tree_code code;
3355   int i;
3356   gimple next;
3357 
3358   stmts_to_replace->truncate (0);
3359   stmts_to_replace->quick_push (stmt);
3360   pattern_stmt = (* vect_recog_func) (stmts_to_replace, &type_in, &type_out);
3361   if (!pattern_stmt)
3362     return;
3363 
3364   stmt = stmts_to_replace->last ();
3365   stmt_info = vinfo_for_stmt (stmt);
3366   loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3367 
3368   if (VECTOR_MODE_P (TYPE_MODE (type_in)))
3369     {
3370       /* No need to check target support (already checked by the pattern
3371          recognition function).  */
3372       pattern_vectype = type_out ? type_out : type_in;
3373     }
3374   else
3375     {
3376       machine_mode vec_mode;
3377       enum insn_code icode;
3378       optab optab;
3379 
3380       /* Check target support  */
3381       type_in = get_vectype_for_scalar_type (type_in);
3382       if (!type_in)
3383 	return;
3384       if (type_out)
3385 	type_out = get_vectype_for_scalar_type (type_out);
3386       else
3387 	type_out = type_in;
3388       if (!type_out)
3389 	return;
3390       pattern_vectype = type_out;
3391 
3392       if (is_gimple_assign (pattern_stmt))
3393 	code = gimple_assign_rhs_code (pattern_stmt);
3394       else
3395         {
3396 	  gcc_assert (is_gimple_call (pattern_stmt));
3397 	  code = CALL_EXPR;
3398 	}
3399 
3400       optab = optab_for_tree_code (code, type_in, optab_default);
3401       vec_mode = TYPE_MODE (type_in);
3402       if (!optab
3403           || (icode = optab_handler (optab, vec_mode)) == CODE_FOR_nothing
3404           || (insn_data[icode].operand[0].mode != TYPE_MODE (type_out)))
3405 	return;
3406     }
3407 
3408   /* Found a vectorizable pattern.  */
3409   if (dump_enabled_p ())
3410     {
3411       dump_printf_loc (MSG_NOTE, vect_location,
3412                        "pattern recognized: ");
3413       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
3414     }
3415 
3416   /* Mark the stmts that are involved in the pattern. */
3417   vect_mark_pattern_stmts (stmt, pattern_stmt, pattern_vectype);
3418 
3419   /* Patterns cannot be vectorized using SLP, because they change the order of
3420      computation.  */
3421   if (loop_vinfo)
3422     FOR_EACH_VEC_ELT (LOOP_VINFO_REDUCTIONS (loop_vinfo), i, next)
3423       if (next == stmt)
3424         LOOP_VINFO_REDUCTIONS (loop_vinfo).ordered_remove (i);
3425 
3426   /* It is possible that additional pattern stmts are created and inserted in
3427      STMTS_TO_REPLACE.  We create a stmt_info for each of them, and mark the
3428      relevant statements.  */
3429   for (i = 0; stmts_to_replace->iterate (i, &stmt)
3430 	      && (unsigned) i < (stmts_to_replace->length () - 1);
3431        i++)
3432     {
3433       stmt_info = vinfo_for_stmt (stmt);
3434       pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
3435       if (dump_enabled_p ())
3436         {
3437           dump_printf_loc (MSG_NOTE, vect_location,
3438                            "additional pattern stmt: ");
3439           dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
3440         }
3441 
3442       vect_mark_pattern_stmts (stmt, pattern_stmt, NULL_TREE);
3443     }
3444 }
3445 
3446 
3447 /* Function vect_pattern_recog
3448 
3449    Input:
3450    LOOP_VINFO - a struct_loop_info of a loop in which we want to look for
3451         computation idioms.
3452 
3453    Output - for each computation idiom that is detected we create a new stmt
3454         that provides the same functionality and that can be vectorized.  We
3455         also record some information in the struct_stmt_info of the relevant
3456         stmts, as explained below:
3457 
3458    At the entry to this function we have the following stmts, with the
3459    following initial value in the STMT_VINFO fields:
3460 
3461          stmt                     in_pattern_p  related_stmt    vec_stmt
3462          S1: a_i = ....                 -       -               -
3463          S2: a_2 = ..use(a_i)..         -       -               -
3464          S3: a_1 = ..use(a_2)..         -       -               -
3465          S4: a_0 = ..use(a_1)..         -       -               -
3466          S5: ... = ..use(a_0)..         -       -               -
3467 
3468    Say the sequence {S1,S2,S3,S4} was detected as a pattern that can be
3469    represented by a single stmt.  We then:
3470    - create a new stmt S6 equivalent to the pattern (the stmt is not
3471      inserted into the code)
3472    - fill in the STMT_VINFO fields as follows:
3473 
3474                                   in_pattern_p  related_stmt    vec_stmt
3475          S1: a_i = ....                 -       -               -
3476          S2: a_2 = ..use(a_i)..         -       -               -
3477          S3: a_1 = ..use(a_2)..         -       -               -
3478          S4: a_0 = ..use(a_1)..         true    S6              -
3479           '---> S6: a_new = ....        -       S4              -
3480          S5: ... = ..use(a_0)..         -       -               -
3481 
3482    (the last stmt in the pattern (S4) and the new pattern stmt (S6) point
3483    to each other through the RELATED_STMT field).
3484 
3485    S6 will be marked as relevant in vect_mark_stmts_to_be_vectorized instead
3486    of S4 because it will replace all its uses.  Stmts {S1,S2,S3} will
3487    remain irrelevant unless used by stmts other than S4.
3488 
3489    If vectorization succeeds, vect_transform_stmt will skip over {S1,S2,S3}
3490    (because they are marked as irrelevant).  It will vectorize S6, and record
3491    a pointer to the new vector stmt VS6 from S6 (as usual).
3492    S4 will be skipped, and S5 will be vectorized as usual:
3493 
3494                                   in_pattern_p  related_stmt    vec_stmt
3495          S1: a_i = ....                 -       -               -
3496          S2: a_2 = ..use(a_i)..         -       -               -
3497          S3: a_1 = ..use(a_2)..         -       -               -
3498        > VS6: va_new = ....             -       -               -
3499          S4: a_0 = ..use(a_1)..         true    S6              VS6
3500           '---> S6: a_new = ....        -       S4              VS6
3501        > VS5: ... = ..vuse(va_new)..    -       -               -
3502          S5: ... = ..use(a_0)..         -       -               -
3503 
3504    DCE could then get rid of {S1,S2,S3,S4,S5} (if their defs are not used
3505    elsewhere), and we'll end up with:
3506 
3507         VS6: va_new = ....
3508         VS5: ... = ..vuse(va_new)..
3509 
3510    In case of more than one pattern statements, e.g., widen-mult with
3511    intermediate type:
3512 
3513      S1  a_t = ;
3514      S2  a_T = (TYPE) a_t;
3515            '--> S3: a_it = (interm_type) a_t;
3516      S4  prod_T = a_T * CONST;
3517            '--> S5: prod_T' = a_it w* CONST;
3518 
3519    there may be other users of a_T outside the pattern.  In that case S2 will
3520    be marked as relevant (as well as S3), and both S2 and S3 will be analyzed
3521    and vectorized.  The vector stmt VS2 will be recorded in S2, and VS3 will
3522    be recorded in S3.  */
3523 
3524 void
3525 vect_pattern_recog (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
3526 {
3527   struct loop *loop;
3528   basic_block *bbs;
3529   unsigned int nbbs;
3530   gimple_stmt_iterator si;
3531   unsigned int i, j;
3532   vect_recog_func_ptr vect_recog_func;
3533   auto_vec<gimple, 1> stmts_to_replace;
3534   gimple stmt;
3535 
3536   if (dump_enabled_p ())
3537     dump_printf_loc (MSG_NOTE, vect_location,
3538                      "=== vect_pattern_recog ===\n");
3539 
3540   if (loop_vinfo)
3541     {
3542       loop = LOOP_VINFO_LOOP (loop_vinfo);
3543       bbs = LOOP_VINFO_BBS (loop_vinfo);
3544       nbbs = loop->num_nodes;
3545     }
3546   else
3547     {
3548       bbs = &BB_VINFO_BB (bb_vinfo);
3549       nbbs = 1;
3550     }
3551 
3552   /* Scan through the loop stmts, applying the pattern recognition
3553      functions starting at each stmt visited:  */
3554   for (i = 0; i < nbbs; i++)
3555     {
3556       basic_block bb = bbs[i];
3557       for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
3558         {
3559 	  if (bb_vinfo && (stmt = gsi_stmt (si))
3560 	      && vinfo_for_stmt (stmt)
3561 	      && !STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)))
3562 	   continue;
3563 
3564           /* Scan over all generic vect_recog_xxx_pattern functions.  */
3565           for (j = 0; j < NUM_PATTERNS; j++)
3566             {
3567 	      vect_recog_func = vect_vect_recog_func_ptrs[j];
3568 	      vect_pattern_recog_1 (vect_recog_func, si,
3569 				    &stmts_to_replace);
3570             }
3571         }
3572     }
3573 }
3574