tree-vect-patterns.c revision 225736
1/* Analysis Utilities for Loop Vectorization.
2   Copyright (C) 2006 Free Software Foundation, Inc.
3   Contributed by Dorit Nuzman <dorit@il.ibm.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING.  If not, write to the Free
19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, USA.  */
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "ggc.h"
27#include "tree.h"
28
29#include "target.h"
30#include "basic-block.h"
31#include "diagnostic.h"
32#include "tree-flow.h"
33#include "tree-dump.h"
34#include "timevar.h"
35#include "cfgloop.h"
36#include "expr.h"
37#include "optabs.h"
38#include "params.h"
39#include "tree-data-ref.h"
40#include "tree-vectorizer.h"
41#include "recog.h"
42#include "toplev.h"
43
44/* Function prototypes */
45static void vect_pattern_recog_1
46  (tree (* ) (tree, tree *, tree *), block_stmt_iterator);
47static bool widened_name_p (tree, tree, tree *, tree *);
48
49/* Pattern recognition functions  */
50static tree vect_recog_widen_sum_pattern (tree, tree *, tree *);
51static tree vect_recog_widen_mult_pattern (tree, tree *, tree *);
52static tree vect_recog_dot_prod_pattern (tree, tree *, tree *);
53static vect_recog_func_ptr vect_vect_recog_func_ptrs[NUM_PATTERNS] = {
54	vect_recog_widen_mult_pattern,
55	vect_recog_widen_sum_pattern,
56	vect_recog_dot_prod_pattern};
57
58
59/* Function widened_name_p
60
61   Check whether NAME, an ssa-name used in USE_STMT,
62   is a result of a type-promotion, such that:
63     DEF_STMT: NAME = NOP (name0)
64   where the type of name0 (HALF_TYPE) is smaller than the type of NAME.
65*/
66
67static bool
68widened_name_p (tree name, tree use_stmt, tree *half_type, tree *def_stmt)
69{
70  tree dummy;
71  loop_vec_info loop_vinfo;
72  stmt_vec_info stmt_vinfo;
73  tree expr;
74  tree type = TREE_TYPE (name);
75  tree oprnd0;
76  enum vect_def_type dt;
77  tree def;
78
79  stmt_vinfo = vinfo_for_stmt (use_stmt);
80  loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
81
82  if (!vect_is_simple_use (name, loop_vinfo, def_stmt, &def, &dt))
83    return false;
84
85  if (dt != vect_loop_def
86      && dt != vect_invariant_def && dt != vect_constant_def)
87    return false;
88
89  if (! *def_stmt)
90    return false;
91
92  if (TREE_CODE (*def_stmt) != MODIFY_EXPR)
93    return false;
94
95  expr = TREE_OPERAND (*def_stmt, 1);
96  if (TREE_CODE (expr) != NOP_EXPR)
97    return false;
98
99  oprnd0 = TREE_OPERAND (expr, 0);
100
101  *half_type = TREE_TYPE (oprnd0);
102  if (!INTEGRAL_TYPE_P (type) || !INTEGRAL_TYPE_P (*half_type)
103      || (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (*half_type))
104      || (TYPE_PRECISION (type) < (TYPE_PRECISION (*half_type) * 2)))
105    return false;
106
107  if (!vect_is_simple_use (oprnd0, loop_vinfo, &dummy, &dummy, &dt))
108    return false;
109
110  if (dt != vect_invariant_def && dt != vect_constant_def
111      && dt != vect_loop_def)
112    return false;
113
114  return true;
115}
116
117
118/* Function vect_recog_dot_prod_pattern
119
120   Try to find the following pattern:
121
122     type x_t, y_t;
123     TYPE1 prod;
124     TYPE2 sum = init;
125   loop:
126     sum_0 = phi <init, sum_1>
127     S1  x_t = ...
128     S2  y_t = ...
129     S3  x_T = (TYPE1) x_t;
130     S4  y_T = (TYPE1) y_t;
131     S5  prod = x_T * y_T;
132     [S6  prod = (TYPE2) prod;  #optional]
133     S7  sum_1 = prod + sum_0;
134
135   where 'TYPE1' is exactly double the size of type 'type', and 'TYPE2' is the
136   same size of 'TYPE1' or bigger. This is a special case of a reduction
137   computation.
138
139   Input:
140
141   * LAST_STMT: A stmt from which the pattern search begins. In the example,
142   when this function is called with S7, the pattern {S3,S4,S5,S6,S7} will be
143   detected.
144
145   Output:
146
147   * TYPE_IN: The type of the input arguments to the pattern.
148
149   * TYPE_OUT: The type of the output  of this pattern.
150
151   * Return value: A new stmt that will be used to replace the sequence of
152   stmts that constitute the pattern. In this case it will be:
153        WIDEN_DOT_PRODUCT <x_t, y_t, sum_0>
154*/
155
156static tree
157vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
158{
159  tree stmt, expr;
160  tree oprnd0, oprnd1;
161  tree oprnd00, oprnd01;
162  stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
163  tree type, half_type;
164  tree pattern_expr;
165  tree prod_type;
166
167  if (TREE_CODE (last_stmt) != MODIFY_EXPR)
168    return NULL;
169
170  expr = TREE_OPERAND (last_stmt, 1);
171  type = TREE_TYPE (expr);
172
173  /* Look for the following pattern
174          DX = (TYPE1) X;
175          DY = (TYPE1) Y;
176          DPROD = DX * DY;
177          DDPROD = (TYPE2) DPROD;
178          sum_1 = DDPROD + sum_0;
179     In which
180     - DX is double the size of X
181     - DY is double the size of Y
182     - DX, DY, DPROD all have the same type
183     - sum is the same size of DPROD or bigger
184     - sum has been recognized as a reduction variable.
185
186     This is equivalent to:
187       DPROD = X w* Y;          #widen mult
188       sum_1 = DPROD w+ sum_0;  #widen summation
189     or
190       DPROD = X w* Y;          #widen mult
191       sum_1 = DPROD + sum_0;   #summation
192   */
193
194  /* Starting from LAST_STMT, follow the defs of its uses in search
195     of the above pattern.  */
196
197  if (TREE_CODE (expr) != PLUS_EXPR)
198    return NULL;
199
200  if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
201    {
202      /* Has been detected as widening-summation?  */
203
204      stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
205      expr = TREE_OPERAND (stmt, 1);
206      type = TREE_TYPE (expr);
207      if (TREE_CODE (expr) != WIDEN_SUM_EXPR)
208        return NULL;
209      oprnd0 = TREE_OPERAND (expr, 0);
210      oprnd1 = TREE_OPERAND (expr, 1);
211      half_type = TREE_TYPE (oprnd0);
212    }
213  else
214    {
215      tree def_stmt;
216
217      if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
218        return NULL;
219      oprnd0 = TREE_OPERAND (expr, 0);
220      oprnd1 = TREE_OPERAND (expr, 1);
221      if (TYPE_MAIN_VARIANT (TREE_TYPE (oprnd0)) != TYPE_MAIN_VARIANT (type)
222          || TYPE_MAIN_VARIANT (TREE_TYPE (oprnd1)) != TYPE_MAIN_VARIANT (type))
223        return NULL;
224      stmt = last_stmt;
225
226      if (widened_name_p (oprnd0, stmt, &half_type, &def_stmt))
227        {
228          stmt = def_stmt;
229          expr = TREE_OPERAND (stmt, 1);
230          oprnd0 = TREE_OPERAND (expr, 0);
231        }
232      else
233        half_type = type;
234    }
235
236  /* So far so good. Since last_stmt was detected as a (summation) reduction,
237     we know that oprnd1 is the reduction variable (defined by a loop-header
238     phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
239     Left to check that oprnd0 is defined by a (widen_)mult_expr  */
240
241  prod_type = half_type;
242  stmt = SSA_NAME_DEF_STMT (oprnd0);
243  gcc_assert (stmt);
244  stmt_vinfo = vinfo_for_stmt (stmt);
245  gcc_assert (stmt_vinfo);
246  if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_loop_def)
247    return NULL;
248  expr = TREE_OPERAND (stmt, 1);
249  if (TREE_CODE (expr) != MULT_EXPR)
250    return NULL;
251  if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
252    {
253      /* Has been detected as a widening multiplication?  */
254
255      stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
256      expr = TREE_OPERAND (stmt, 1);
257      if (TREE_CODE (expr) != WIDEN_MULT_EXPR)
258        return NULL;
259      stmt_vinfo = vinfo_for_stmt (stmt);
260      gcc_assert (stmt_vinfo);
261      gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_loop_def);
262      oprnd00 = TREE_OPERAND (expr, 0);
263      oprnd01 = TREE_OPERAND (expr, 1);
264    }
265  else
266    {
267      tree half_type0, half_type1;
268      tree def_stmt;
269      tree oprnd0, oprnd1;
270
271      oprnd0 = TREE_OPERAND (expr, 0);
272      oprnd1 = TREE_OPERAND (expr, 1);
273      if (TYPE_MAIN_VARIANT (TREE_TYPE (oprnd0))
274				!= TYPE_MAIN_VARIANT (prod_type)
275          || TYPE_MAIN_VARIANT (TREE_TYPE (oprnd1))
276				!= TYPE_MAIN_VARIANT (prod_type))
277        return NULL;
278      if (!widened_name_p (oprnd0, stmt, &half_type0, &def_stmt))
279        return NULL;
280      oprnd00 = TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 0);
281      if (!widened_name_p (oprnd1, stmt, &half_type1, &def_stmt))
282        return NULL;
283      oprnd01 = TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 0);
284      if (TYPE_MAIN_VARIANT (half_type0) != TYPE_MAIN_VARIANT (half_type1))
285        return NULL;
286      if (TYPE_PRECISION (prod_type) != TYPE_PRECISION (half_type0) * 2)
287	return NULL;
288    }
289
290  half_type = TREE_TYPE (oprnd00);
291  *type_in = half_type;
292  *type_out = type;
293
294  /* Pattern detected. Create a stmt to be used to replace the pattern: */
295  pattern_expr = build3 (DOT_PROD_EXPR, type, oprnd00, oprnd01, oprnd1);
296  if (vect_print_dump_info (REPORT_DETAILS))
297    {
298      fprintf (vect_dump, "vect_recog_dot_prod_pattern: detected: ");
299      print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
300    }
301  return pattern_expr;
302}
303
304
305/* Function vect_recog_widen_mult_pattern
306
307   Try to find the following pattern:
308
309     type a_t, b_t;
310     TYPE a_T, b_T, prod_T;
311
312     S1  a_t = ;
313     S2  b_t = ;
314     S3  a_T = (TYPE) a_t;
315     S4  b_T = (TYPE) b_t;
316     S5  prod_T = a_T * b_T;
317
318   where type 'TYPE' is at least double the size of type 'type'.
319
320   Input:
321
322   * LAST_STMT: A stmt from which the pattern search begins. In the example,
323   when this function is called with S5, the pattern {S3,S4,S5} is be detected.
324
325   Output:
326
327   * TYPE_IN: The type of the input arguments to the pattern.
328
329   * TYPE_OUT: The type of the output  of this pattern.
330
331   * Return value: A new stmt that will be used to replace the sequence of
332   stmts that constitute the pattern. In this case it will be:
333        WIDEN_MULT <a_t, b_t>
334*/
335
336static tree
337vect_recog_widen_mult_pattern (tree last_stmt ATTRIBUTE_UNUSED,
338			       tree *type_in ATTRIBUTE_UNUSED,
339			       tree *type_out ATTRIBUTE_UNUSED)
340{
341  /* Yet to be implemented.   */
342  return NULL;
343}
344
345
346/* Function vect_recog_widen_sum_pattern
347
348   Try to find the following pattern:
349
350     type x_t;
351     TYPE x_T, sum = init;
352   loop:
353     sum_0 = phi <init, sum_1>
354     S1  x_t = *p;
355     S2  x_T = (TYPE) x_t;
356     S3  sum_1 = x_T + sum_0;
357
358   where type 'TYPE' is at least double the size of type 'type', i.e - we're
359   summing elements of type 'type' into an accumulator of type 'TYPE'. This is
360   a special case of a reduction computation.
361
362   Input:
363
364   * LAST_STMT: A stmt from which the pattern search begins. In the example,
365   when this function is called with S3, the pattern {S2,S3} will be detected.
366
367   Output:
368
369   * TYPE_IN: The type of the input arguments to the pattern.
370
371   * TYPE_OUT: The type of the output of this pattern.
372
373   * Return value: A new stmt that will be used to replace the sequence of
374   stmts that constitute the pattern. In this case it will be:
375        WIDEN_SUM <x_t, sum_0>
376*/
377
378static tree
379vect_recog_widen_sum_pattern (tree last_stmt, tree *type_in, tree *type_out)
380{
381  tree stmt, expr;
382  tree oprnd0, oprnd1;
383  stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
384  tree type, half_type;
385  tree pattern_expr;
386
387  if (TREE_CODE (last_stmt) != MODIFY_EXPR)
388    return NULL;
389
390  expr = TREE_OPERAND (last_stmt, 1);
391  type = TREE_TYPE (expr);
392
393  /* Look for the following pattern
394          DX = (TYPE) X;
395          sum_1 = DX + sum_0;
396     In which DX is at least double the size of X, and sum_1 has been
397     recognized as a reduction variable.
398   */
399
400  /* Starting from LAST_STMT, follow the defs of its uses in search
401     of the above pattern.  */
402
403  if (TREE_CODE (expr) != PLUS_EXPR)
404    return NULL;
405
406  if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
407    return NULL;
408
409  oprnd0 = TREE_OPERAND (expr, 0);
410  oprnd1 = TREE_OPERAND (expr, 1);
411  if (TYPE_MAIN_VARIANT (TREE_TYPE (oprnd0)) != TYPE_MAIN_VARIANT (type)
412      || TYPE_MAIN_VARIANT (TREE_TYPE (oprnd1)) != TYPE_MAIN_VARIANT (type))
413    return NULL;
414
415  /* So far so good. Since last_stmt was detected as a (summation) reduction,
416     we know that oprnd1 is the reduction variable (defined by a loop-header
417     phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
418     Left to check that oprnd0 is defined by a cast from type 'type' to type
419     'TYPE'.  */
420
421  if (!widened_name_p (oprnd0, last_stmt, &half_type, &stmt))
422    return NULL;
423
424  oprnd0 = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
425  *type_in = half_type;
426  *type_out = type;
427
428  /* Pattern detected. Create a stmt to be used to replace the pattern: */
429  pattern_expr = build2 (WIDEN_SUM_EXPR, type, oprnd0, oprnd1);
430  if (vect_print_dump_info (REPORT_DETAILS))
431    {
432      fprintf (vect_dump, "vect_recog_widen_sum_pattern: detected: ");
433      print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
434    }
435  return pattern_expr;
436}
437
438
439/* Function vect_pattern_recog_1
440
441   Input:
442   PATTERN_RECOG_FUNC: A pointer to a function that detects a certain
443        computation pattern.
444   STMT: A stmt from which the pattern search should start.
445
446   If PATTERN_RECOG_FUNC successfully detected the pattern, it creates an
447   expression that computes the same functionality and can be used to
448   replace the sequence of stmts that are involved in the pattern.
449
450   Output:
451   This function checks if the expression returned by PATTERN_RECOG_FUNC is
452   supported in vector form by the target.  We use 'TYPE_IN' to obtain the
453   relevant vector type. If 'TYPE_IN' is already a vector type, then this
454   indicates that target support had already been checked by PATTERN_RECOG_FUNC.
455   If 'TYPE_OUT' is also returned by PATTERN_RECOG_FUNC, we check that it fits
456   to the available target pattern.
457
458   This function also does some bookkeeping, as explained in the documentation
459   for vect_recog_pattern.  */
460
461static void
462vect_pattern_recog_1 (
463	tree (* vect_recog_func) (tree, tree *, tree *),
464	block_stmt_iterator si)
465{
466  tree stmt = bsi_stmt (si);
467  stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
468  stmt_vec_info pattern_stmt_info;
469  loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
470  tree pattern_expr;
471  tree pattern_vectype;
472  tree type_in, type_out;
473  tree pattern_type;
474  enum tree_code code;
475  tree var, var_name;
476  stmt_ann_t ann;
477
478  pattern_expr = (* vect_recog_func) (stmt, &type_in, &type_out);
479  if (!pattern_expr)
480    return;
481
482  if (VECTOR_MODE_P (TYPE_MODE (type_in)))
483    {
484      /* No need to check target support (already checked by the pattern
485         recognition function).  */
486      pattern_vectype = type_in;
487    }
488  else
489    {
490      enum machine_mode vec_mode;
491      enum insn_code icode;
492      optab optab;
493
494      /* Check target support  */
495      pattern_vectype = get_vectype_for_scalar_type (type_in);
496      optab = optab_for_tree_code (TREE_CODE (pattern_expr), pattern_vectype);
497      vec_mode = TYPE_MODE (pattern_vectype);
498      if (!optab
499          || (icode = optab->handlers[(int) vec_mode].insn_code) ==
500              CODE_FOR_nothing
501          || (type_out
502              && (!get_vectype_for_scalar_type (type_out)
503                  || (insn_data[icode].operand[0].mode !=
504                      TYPE_MODE (get_vectype_for_scalar_type (type_out))))))
505	return;
506    }
507
508  /* Found a vectorizable pattern.  */
509  if (vect_print_dump_info (REPORT_DETAILS))
510    {
511      fprintf (vect_dump, "pattern recognized: ");
512      print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
513    }
514
515  /* Mark the stmts that are involved in the pattern,
516     create a new stmt to express the pattern and insert it.  */
517  code = TREE_CODE (pattern_expr);
518  pattern_type = TREE_TYPE (pattern_expr);
519  var = create_tmp_var (pattern_type, "patt");
520  add_referenced_var (var);
521  var_name = make_ssa_name (var, NULL_TREE);
522  pattern_expr = build2 (MODIFY_EXPR, void_type_node, var_name, pattern_expr);
523  SSA_NAME_DEF_STMT (var_name) = pattern_expr;
524  bsi_insert_before (&si, pattern_expr, BSI_SAME_STMT);
525  ann = stmt_ann (pattern_expr);
526  set_stmt_info (ann, new_stmt_vec_info (pattern_expr, loop_vinfo));
527  pattern_stmt_info = vinfo_for_stmt (pattern_expr);
528
529  STMT_VINFO_RELATED_STMT (pattern_stmt_info) = stmt;
530  STMT_VINFO_DEF_TYPE (pattern_stmt_info) = STMT_VINFO_DEF_TYPE (stmt_info);
531  STMT_VINFO_VECTYPE (pattern_stmt_info) = pattern_vectype;
532  STMT_VINFO_IN_PATTERN_P (stmt_info) = true;
533  STMT_VINFO_RELATED_STMT (stmt_info) = pattern_expr;
534
535  return;
536}
537
538
539/* Function vect_pattern_recog
540
541   Input:
542   LOOP_VINFO - a struct_loop_info of a loop in which we want to look for
543        computation idioms.
544
545   Output - for each computation idiom that is detected we insert a new stmt
546        that provides the same functionality and that can be vectorized. We
547        also record some information in the struct_stmt_info of the relevant
548        stmts, as explained below:
549
550   At the entry to this function we have the following stmts, with the
551   following initial value in the STMT_VINFO fields:
552
553         stmt                     in_pattern_p  related_stmt    vec_stmt
554         S1: a_i = ....                 -       -               -
555         S2: a_2 = ..use(a_i)..         -       -               -
556         S3: a_1 = ..use(a_2)..         -       -               -
557         S4: a_0 = ..use(a_1)..         -       -               -
558         S5: ... = ..use(a_0)..         -       -               -
559
560   Say the sequence {S1,S2,S3,S4} was detected as a pattern that can be
561   represented by a single stmt. We then:
562   - create a new stmt S6 that will replace the pattern.
563   - insert the new stmt S6 before the last stmt in the pattern
564   - fill in the STMT_VINFO fields as follows:
565
566                                  in_pattern_p  related_stmt    vec_stmt
567         S1: a_i = ....                 -       -               -
568         S2: a_2 = ..use(a_i)..         -       -               -
569         S3: a_1 = ..use(a_2)..         -       -               -
570       > S6: a_new = ....               -       S4              -
571         S4: a_0 = ..use(a_1)..         true    S6              -
572         S5: ... = ..use(a_0)..         -       -               -
573
574   (the last stmt in the pattern (S4) and the new pattern stmt (S6) point
575    to each other through the RELATED_STMT field).
576
577   S6 will be marked as relevant in vect_mark_stmts_to_be_vectorized instead
578   of S4 because it will replace all its uses.  Stmts {S1,S2,S3} will
579   remain irrelevant unless used by stmts other than S4.
580
581   If vectorization succeeds, vect_transform_stmt will skip over {S1,S2,S3}
582   (because they are marked as irrelevant). It will vectorize S6, and record
583   a pointer to the new vector stmt VS6 both from S6 (as usual), and also
584   from S4. We do that so that when we get to vectorizing stmts that use the
585   def of S4 (like S5 that uses a_0), we'll know where to take the relevant
586   vector-def from. S4 will be skipped, and S5 will be vectorized as usual:
587
588                                  in_pattern_p  related_stmt    vec_stmt
589         S1: a_i = ....                 -       -               -
590         S2: a_2 = ..use(a_i)..         -       -               -
591         S3: a_1 = ..use(a_2)..         -       -               -
592       > VS6: va_new = ....             -       -               -
593         S6: a_new = ....               -       S4              VS6
594         S4: a_0 = ..use(a_1)..         true    S6              VS6
595       > VS5: ... = ..vuse(va_new)..    -       -               -
596         S5: ... = ..use(a_0)..         -       -               -
597
598   DCE could then get rid of {S1,S2,S3,S4,S5,S6} (if their defs are not used
599   elsewhere), and we'll end up with:
600
601        VS6: va_new = ....
602        VS5: ... = ..vuse(va_new)..
603
604   If vectorization does not succeed, DCE will clean S6 away (its def is
605   not used), and we'll end up with the original sequence.
606*/
607
608void
609vect_pattern_recog (loop_vec_info loop_vinfo)
610{
611  struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
612  basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
613  unsigned int nbbs = loop->num_nodes;
614  block_stmt_iterator si;
615  tree stmt;
616  unsigned int i, j;
617  tree (* vect_recog_func_ptr) (tree, tree *, tree *);
618
619  if (vect_print_dump_info (REPORT_DETAILS))
620    fprintf (vect_dump, "=== vect_pattern_recog ===");
621
622  /* Scan through the loop stmts, applying the pattern recognition
623     functions starting at each stmt visited:  */
624  for (i = 0; i < nbbs; i++)
625    {
626      basic_block bb = bbs[i];
627      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
628        {
629          stmt = bsi_stmt (si);
630
631          /* Scan over all generic vect_recog_xxx_pattern functions.  */
632          for (j = 0; j < NUM_PATTERNS; j++)
633            {
634              vect_recog_func_ptr = vect_vect_recog_func_ptrs[j];
635              vect_pattern_recog_1 (vect_recog_func_ptr, si);
636            }
637        }
638    }
639}
640