1 /* Analysis Utilities for Loop Vectorization.
2 Copyright (C) 2006-2016 Free Software Foundation, Inc.
3 Contributed by Dorit Nuzman <dorit@il.ibm.com>
5 This file is part of GCC.
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
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
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/>. */
23 #include "coretypes.h"
30 #include "optabs-tree.h"
31 #include "insn-config.h"
32 #include "recog.h" /* FIXME: for insn_data */
33 #include "fold-const.h"
34 #include "stor-layout.h"
37 #include "gimple-iterator.h"
39 #include "tree-vectorizer.h"
42 #include "internal-fn.h"
43 #include "case-cfn-macros.h"
45 /* Pattern recognition functions */
46 static gimple
*vect_recog_widen_sum_pattern (vec
<gimple
*> *, tree
*,
48 static gimple
*vect_recog_widen_mult_pattern (vec
<gimple
*> *, tree
*,
50 static gimple
*vect_recog_dot_prod_pattern (vec
<gimple
*> *, tree
*,
52 static gimple
*vect_recog_sad_pattern (vec
<gimple
*> *, tree
*,
54 static gimple
*vect_recog_pow_pattern (vec
<gimple
*> *, tree
*, tree
*);
55 static gimple
*vect_recog_over_widening_pattern (vec
<gimple
*> *, tree
*,
57 static gimple
*vect_recog_widen_shift_pattern (vec
<gimple
*> *,
59 static gimple
*vect_recog_rotate_pattern (vec
<gimple
*> *, tree
*, tree
*);
60 static gimple
*vect_recog_vector_vector_shift_pattern (vec
<gimple
*> *,
62 static gimple
*vect_recog_divmod_pattern (vec
<gimple
*> *,
65 static gimple
*vect_recog_mult_pattern (vec
<gimple
*> *,
68 static gimple
*vect_recog_mixed_size_cond_pattern (vec
<gimple
*> *,
70 static gimple
*vect_recog_bool_pattern (vec
<gimple
*> *, tree
*, tree
*);
71 static gimple
*vect_recog_mask_conversion_pattern (vec
<gimple
*> *, tree
*, tree
*);
73 struct vect_recog_func
75 vect_recog_func_ptr fn
;
79 /* Note that ordering matters - the first pattern matching on a stmt
80 is taken which means usually the more complex one needs to preceed
81 the less comples onex (widen_sum only after dot_prod or sad for example). */
82 static vect_recog_func vect_vect_recog_func_ptrs
[NUM_PATTERNS
] = {
83 { vect_recog_widen_mult_pattern
, "widen_mult" },
84 { vect_recog_dot_prod_pattern
, "dot_prod" },
85 { vect_recog_sad_pattern
, "sad" },
86 { vect_recog_widen_sum_pattern
, "widen_sum" },
87 { vect_recog_pow_pattern
, "pow" },
88 { vect_recog_widen_shift_pattern
, "widen_shift" },
89 { vect_recog_over_widening_pattern
, "over_widening" },
90 { vect_recog_rotate_pattern
, "rotate" },
91 { vect_recog_vector_vector_shift_pattern
, "vector_vector_shift" },
92 { vect_recog_divmod_pattern
, "divmod" },
93 { vect_recog_mult_pattern
, "mult" },
94 { vect_recog_mixed_size_cond_pattern
, "mixed_size_cond" },
95 { vect_recog_bool_pattern
, "bool" },
96 { vect_recog_mask_conversion_pattern
, "mask_conversion" }
100 append_pattern_def_seq (stmt_vec_info stmt_info
, gimple
*stmt
)
102 gimple_seq_add_stmt_without_update (&STMT_VINFO_PATTERN_DEF_SEQ (stmt_info
),
107 new_pattern_def_seq (stmt_vec_info stmt_info
, gimple
*stmt
)
109 STMT_VINFO_PATTERN_DEF_SEQ (stmt_info
) = NULL
;
110 append_pattern_def_seq (stmt_info
, stmt
);
113 /* Check whether STMT2 is in the same loop or basic block as STMT1.
114 Which of the two applies depends on whether we're currently doing
115 loop-based or basic-block-based vectorization, as determined by
116 the vinfo_for_stmt for STMT1 (which must be defined).
118 If this returns true, vinfo_for_stmt for STMT2 is guaranteed
119 to be defined as well. */
122 vect_same_loop_or_bb_p (gimple
*stmt1
, gimple
*stmt2
)
124 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (stmt1
);
125 return vect_stmt_in_region_p (stmt_vinfo
->vinfo
, stmt2
);
128 /* If the LHS of DEF_STMT has a single use, and that statement is
129 in the same loop or basic block, return it. */
132 vect_single_imm_use (gimple
*def_stmt
)
134 tree lhs
= gimple_assign_lhs (def_stmt
);
138 if (!single_imm_use (lhs
, &use_p
, &use_stmt
))
141 if (!vect_same_loop_or_bb_p (def_stmt
, use_stmt
))
147 /* Check whether NAME, an ssa-name used in USE_STMT,
148 is a result of a type promotion, such that:
149 DEF_STMT: NAME = NOP (name0)
150 If CHECK_SIGN is TRUE, check that either both types are signed or both are
154 type_conversion_p (tree name
, gimple
*use_stmt
, bool check_sign
,
155 tree
*orig_type
, gimple
**def_stmt
, bool *promotion
)
157 gimple
*dummy_gimple
;
158 stmt_vec_info stmt_vinfo
;
159 tree type
= TREE_TYPE (name
);
161 enum vect_def_type dt
;
163 stmt_vinfo
= vinfo_for_stmt (use_stmt
);
164 if (!vect_is_simple_use (name
, stmt_vinfo
->vinfo
, def_stmt
, &dt
))
167 if (dt
!= vect_internal_def
168 && dt
!= vect_external_def
&& dt
!= vect_constant_def
)
174 if (dt
== vect_internal_def
)
176 stmt_vec_info def_vinfo
= vinfo_for_stmt (*def_stmt
);
177 if (STMT_VINFO_IN_PATTERN_P (def_vinfo
))
181 if (!is_gimple_assign (*def_stmt
))
184 if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (*def_stmt
)))
187 oprnd0
= gimple_assign_rhs1 (*def_stmt
);
189 *orig_type
= TREE_TYPE (oprnd0
);
190 if (!INTEGRAL_TYPE_P (type
) || !INTEGRAL_TYPE_P (*orig_type
)
191 || ((TYPE_UNSIGNED (type
) != TYPE_UNSIGNED (*orig_type
)) && check_sign
))
194 if (TYPE_PRECISION (type
) >= (TYPE_PRECISION (*orig_type
) * 2))
199 if (!vect_is_simple_use (oprnd0
, stmt_vinfo
->vinfo
, &dummy_gimple
, &dt
))
205 /* Helper to return a new temporary for pattern of TYPE for STMT. If STMT
206 is NULL, the caller must set SSA_NAME_DEF_STMT for the returned SSA var. */
209 vect_recog_temp_ssa_var (tree type
, gimple
*stmt
)
211 return make_temp_ssa_name (type
, stmt
, "patt");
214 /* Function vect_recog_dot_prod_pattern
216 Try to find the following pattern:
222 sum_0 = phi <init, sum_1>
225 S3 x_T = (TYPE1) x_t;
226 S4 y_T = (TYPE1) y_t;
228 [S6 prod = (TYPE2) prod; #optional]
229 S7 sum_1 = prod + sum_0;
231 where 'TYPE1' is exactly double the size of type 'type', and 'TYPE2' is the
232 same size of 'TYPE1' or bigger. This is a special case of a reduction
237 * STMTS: Contains a stmt from which the pattern search begins. In the
238 example, when this function is called with S7, the pattern {S3,S4,S5,S6,S7}
243 * TYPE_IN: The type of the input arguments to the pattern.
245 * TYPE_OUT: The type of the output of this pattern.
247 * Return value: A new stmt that will be used to replace the sequence of
248 stmts that constitute the pattern. In this case it will be:
249 WIDEN_DOT_PRODUCT <x_t, y_t, sum_0>
251 Note: The dot-prod idiom is a widening reduction pattern that is
252 vectorized without preserving all the intermediate results. It
253 produces only N/2 (widened) results (by summing up pairs of
254 intermediate results) rather than all N results. Therefore, we
255 cannot allow this pattern when we want to get all the results and in
256 the correct order (as is the case when this computation is in an
257 inner-loop nested in an outer-loop that us being vectorized). */
260 vect_recog_dot_prod_pattern (vec
<gimple
*> *stmts
, tree
*type_in
,
263 gimple
*stmt
, *last_stmt
= (*stmts
)[0];
265 tree oprnd00
, oprnd01
;
266 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
267 tree type
, half_type
;
268 gimple
*pattern_stmt
;
270 loop_vec_info loop_info
= STMT_VINFO_LOOP_VINFO (stmt_vinfo
);
278 loop
= LOOP_VINFO_LOOP (loop_info
);
280 /* We don't allow changing the order of the computation in the inner-loop
281 when doing outer-loop vectorization. */
282 if (loop
&& nested_in_vect_loop_p (loop
, last_stmt
))
285 if (!is_gimple_assign (last_stmt
))
288 type
= gimple_expr_type (last_stmt
);
290 /* Look for the following pattern
294 DDPROD = (TYPE2) DPROD;
295 sum_1 = DDPROD + sum_0;
297 - DX is double the size of X
298 - DY is double the size of Y
299 - DX, DY, DPROD all have the same type
300 - sum is the same size of DPROD or bigger
301 - sum has been recognized as a reduction variable.
303 This is equivalent to:
304 DPROD = X w* Y; #widen mult
305 sum_1 = DPROD w+ sum_0; #widen summation
307 DPROD = X w* Y; #widen mult
308 sum_1 = DPROD + sum_0; #summation
311 /* Starting from LAST_STMT, follow the defs of its uses in search
312 of the above pattern. */
314 if (gimple_assign_rhs_code (last_stmt
) != PLUS_EXPR
)
317 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo
))
319 /* Has been detected as widening-summation? */
321 stmt
= STMT_VINFO_RELATED_STMT (stmt_vinfo
);
322 type
= gimple_expr_type (stmt
);
323 if (gimple_assign_rhs_code (stmt
) != WIDEN_SUM_EXPR
)
325 oprnd0
= gimple_assign_rhs1 (stmt
);
326 oprnd1
= gimple_assign_rhs2 (stmt
);
327 half_type
= TREE_TYPE (oprnd0
);
333 if (STMT_VINFO_DEF_TYPE (stmt_vinfo
) != vect_reduction_def
334 && ! STMT_VINFO_GROUP_FIRST_ELEMENT (stmt_vinfo
))
336 oprnd0
= gimple_assign_rhs1 (last_stmt
);
337 oprnd1
= gimple_assign_rhs2 (last_stmt
);
338 if (!types_compatible_p (TREE_TYPE (oprnd0
), type
)
339 || !types_compatible_p (TREE_TYPE (oprnd1
), type
))
343 if (type_conversion_p (oprnd0
, stmt
, true, &half_type
, &def_stmt
,
348 oprnd0
= gimple_assign_rhs1 (stmt
);
354 /* So far so good. Since last_stmt was detected as a (summation) reduction,
355 we know that oprnd1 is the reduction variable (defined by a loop-header
356 phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
357 Left to check that oprnd0 is defined by a (widen_)mult_expr */
358 if (TREE_CODE (oprnd0
) != SSA_NAME
)
361 prod_type
= half_type
;
362 stmt
= SSA_NAME_DEF_STMT (oprnd0
);
364 /* It could not be the dot_prod pattern if the stmt is outside the loop. */
365 if (!gimple_bb (stmt
) || !flow_bb_inside_loop_p (loop
, gimple_bb (stmt
)))
368 /* FORNOW. Can continue analyzing the def-use chain when this stmt in a phi
369 inside the loop (in case we are analyzing an outer-loop). */
370 if (!is_gimple_assign (stmt
))
372 stmt_vinfo
= vinfo_for_stmt (stmt
);
373 gcc_assert (stmt_vinfo
);
374 if (STMT_VINFO_DEF_TYPE (stmt_vinfo
) != vect_internal_def
)
376 if (gimple_assign_rhs_code (stmt
) != MULT_EXPR
)
378 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo
))
380 /* Has been detected as a widening multiplication? */
382 stmt
= STMT_VINFO_RELATED_STMT (stmt_vinfo
);
383 if (gimple_assign_rhs_code (stmt
) != WIDEN_MULT_EXPR
)
385 stmt_vinfo
= vinfo_for_stmt (stmt
);
386 gcc_assert (stmt_vinfo
);
387 gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo
) == vect_internal_def
);
388 oprnd00
= gimple_assign_rhs1 (stmt
);
389 oprnd01
= gimple_assign_rhs2 (stmt
);
390 STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (last_stmt
))
391 = STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo
);
395 tree half_type0
, half_type1
;
399 oprnd0
= gimple_assign_rhs1 (stmt
);
400 oprnd1
= gimple_assign_rhs2 (stmt
);
401 if (!types_compatible_p (TREE_TYPE (oprnd0
), prod_type
)
402 || !types_compatible_p (TREE_TYPE (oprnd1
), prod_type
))
404 if (!type_conversion_p (oprnd0
, stmt
, true, &half_type0
, &def_stmt
,
408 oprnd00
= gimple_assign_rhs1 (def_stmt
);
409 if (!type_conversion_p (oprnd1
, stmt
, true, &half_type1
, &def_stmt
,
413 oprnd01
= gimple_assign_rhs1 (def_stmt
);
414 if (!types_compatible_p (half_type0
, half_type1
))
416 if (TYPE_PRECISION (prod_type
) != TYPE_PRECISION (half_type0
) * 2)
420 half_type
= TREE_TYPE (oprnd00
);
421 *type_in
= half_type
;
424 /* Pattern detected. Create a stmt to be used to replace the pattern: */
425 var
= vect_recog_temp_ssa_var (type
, NULL
);
426 pattern_stmt
= gimple_build_assign (var
, DOT_PROD_EXPR
,
427 oprnd00
, oprnd01
, oprnd1
);
429 if (dump_enabled_p ())
431 dump_printf_loc (MSG_NOTE
, vect_location
,
432 "vect_recog_dot_prod_pattern: detected: ");
433 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
434 dump_printf (MSG_NOTE
, "\n");
441 /* Function vect_recog_sad_pattern
443 Try to find the following Sum of Absolute Difference (SAD) pattern:
446 signed TYPE1 diff, abs_diff;
449 sum_0 = phi <init, sum_1>
452 S3 x_T = (TYPE1) x_t;
453 S4 y_T = (TYPE1) y_t;
455 S6 abs_diff = ABS_EXPR <diff>;
456 [S7 abs_diff = (TYPE2) abs_diff; #optional]
457 S8 sum_1 = abs_diff + sum_0;
459 where 'TYPE1' is at least double the size of type 'type', and 'TYPE2' is the
460 same size of 'TYPE1' or bigger. This is a special case of a reduction
465 * STMTS: Contains a stmt from which the pattern search begins. In the
466 example, when this function is called with S8, the pattern
467 {S3,S4,S5,S6,S7,S8} will be detected.
471 * TYPE_IN: The type of the input arguments to the pattern.
473 * TYPE_OUT: The type of the output of this pattern.
475 * Return value: A new stmt that will be used to replace the sequence of
476 stmts that constitute the pattern. In this case it will be:
477 SAD_EXPR <x_t, y_t, sum_0>
481 vect_recog_sad_pattern (vec
<gimple
*> *stmts
, tree
*type_in
,
484 gimple
*last_stmt
= (*stmts
)[0];
485 tree sad_oprnd0
, sad_oprnd1
;
486 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
488 loop_vec_info loop_info
= STMT_VINFO_LOOP_VINFO (stmt_vinfo
);
495 loop
= LOOP_VINFO_LOOP (loop_info
);
497 /* We don't allow changing the order of the computation in the inner-loop
498 when doing outer-loop vectorization. */
499 if (loop
&& nested_in_vect_loop_p (loop
, last_stmt
))
502 if (!is_gimple_assign (last_stmt
))
505 tree sum_type
= gimple_expr_type (last_stmt
);
507 /* Look for the following pattern
511 DAD = ABS_EXPR <DDIFF>;
512 DDPROD = (TYPE2) DPROD;
515 - DX is at least double the size of X
516 - DY is at least double the size of Y
517 - DX, DY, DDIFF, DAD all have the same type
518 - sum is the same size of DAD or bigger
519 - sum has been recognized as a reduction variable.
521 This is equivalent to:
522 DDIFF = X w- Y; #widen sub
523 DAD = ABS_EXPR <DDIFF>;
524 sum_1 = DAD w+ sum_0; #widen summation
526 DDIFF = X w- Y; #widen sub
527 DAD = ABS_EXPR <DDIFF>;
528 sum_1 = DAD + sum_0; #summation
531 /* Starting from LAST_STMT, follow the defs of its uses in search
532 of the above pattern. */
534 if (gimple_assign_rhs_code (last_stmt
) != PLUS_EXPR
)
537 tree plus_oprnd0
, plus_oprnd1
;
539 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo
))
541 /* Has been detected as widening-summation? */
543 gimple
*stmt
= STMT_VINFO_RELATED_STMT (stmt_vinfo
);
544 sum_type
= gimple_expr_type (stmt
);
545 if (gimple_assign_rhs_code (stmt
) != WIDEN_SUM_EXPR
)
547 plus_oprnd0
= gimple_assign_rhs1 (stmt
);
548 plus_oprnd1
= gimple_assign_rhs2 (stmt
);
549 half_type
= TREE_TYPE (plus_oprnd0
);
555 if (STMT_VINFO_DEF_TYPE (stmt_vinfo
) != vect_reduction_def
556 && ! STMT_VINFO_GROUP_FIRST_ELEMENT (stmt_vinfo
))
558 plus_oprnd0
= gimple_assign_rhs1 (last_stmt
);
559 plus_oprnd1
= gimple_assign_rhs2 (last_stmt
);
560 if (!types_compatible_p (TREE_TYPE (plus_oprnd0
), sum_type
)
561 || !types_compatible_p (TREE_TYPE (plus_oprnd1
), sum_type
))
564 /* The type conversion could be promotion, demotion,
565 or just signed -> unsigned. */
566 if (type_conversion_p (plus_oprnd0
, last_stmt
, false,
567 &half_type
, &def_stmt
, &promotion
))
568 plus_oprnd0
= gimple_assign_rhs1 (def_stmt
);
570 half_type
= sum_type
;
573 /* So far so good. Since last_stmt was detected as a (summation) reduction,
574 we know that plus_oprnd1 is the reduction variable (defined by a loop-header
575 phi), and plus_oprnd0 is an ssa-name defined by a stmt in the loop body.
576 Then check that plus_oprnd0 is defined by an abs_expr. */
578 if (TREE_CODE (plus_oprnd0
) != SSA_NAME
)
581 tree abs_type
= half_type
;
582 gimple
*abs_stmt
= SSA_NAME_DEF_STMT (plus_oprnd0
);
584 /* It could not be the sad pattern if the abs_stmt is outside the loop. */
585 if (!gimple_bb (abs_stmt
) || !flow_bb_inside_loop_p (loop
, gimple_bb (abs_stmt
)))
588 /* FORNOW. Can continue analyzing the def-use chain when this stmt in a phi
589 inside the loop (in case we are analyzing an outer-loop). */
590 if (!is_gimple_assign (abs_stmt
))
593 stmt_vec_info abs_stmt_vinfo
= vinfo_for_stmt (abs_stmt
);
594 gcc_assert (abs_stmt_vinfo
);
595 if (STMT_VINFO_DEF_TYPE (abs_stmt_vinfo
) != vect_internal_def
)
597 if (gimple_assign_rhs_code (abs_stmt
) != ABS_EXPR
)
600 tree abs_oprnd
= gimple_assign_rhs1 (abs_stmt
);
601 if (!types_compatible_p (TREE_TYPE (abs_oprnd
), abs_type
))
603 if (TYPE_UNSIGNED (abs_type
))
606 /* We then detect if the operand of abs_expr is defined by a minus_expr. */
608 if (TREE_CODE (abs_oprnd
) != SSA_NAME
)
611 gimple
*diff_stmt
= SSA_NAME_DEF_STMT (abs_oprnd
);
613 /* It could not be the sad pattern if the diff_stmt is outside the loop. */
614 if (!gimple_bb (diff_stmt
)
615 || !flow_bb_inside_loop_p (loop
, gimple_bb (diff_stmt
)))
618 /* FORNOW. Can continue analyzing the def-use chain when this stmt in a phi
619 inside the loop (in case we are analyzing an outer-loop). */
620 if (!is_gimple_assign (diff_stmt
))
623 stmt_vec_info diff_stmt_vinfo
= vinfo_for_stmt (diff_stmt
);
624 gcc_assert (diff_stmt_vinfo
);
625 if (STMT_VINFO_DEF_TYPE (diff_stmt_vinfo
) != vect_internal_def
)
627 if (gimple_assign_rhs_code (diff_stmt
) != MINUS_EXPR
)
630 tree half_type0
, half_type1
;
633 tree minus_oprnd0
= gimple_assign_rhs1 (diff_stmt
);
634 tree minus_oprnd1
= gimple_assign_rhs2 (diff_stmt
);
636 if (!types_compatible_p (TREE_TYPE (minus_oprnd0
), abs_type
)
637 || !types_compatible_p (TREE_TYPE (minus_oprnd1
), abs_type
))
639 if (!type_conversion_p (minus_oprnd0
, diff_stmt
, false,
640 &half_type0
, &def_stmt
, &promotion
)
643 sad_oprnd0
= gimple_assign_rhs1 (def_stmt
);
645 if (!type_conversion_p (minus_oprnd1
, diff_stmt
, false,
646 &half_type1
, &def_stmt
, &promotion
)
649 sad_oprnd1
= gimple_assign_rhs1 (def_stmt
);
651 if (!types_compatible_p (half_type0
, half_type1
))
653 if (TYPE_PRECISION (abs_type
) < TYPE_PRECISION (half_type0
) * 2
654 || TYPE_PRECISION (sum_type
) < TYPE_PRECISION (half_type0
) * 2)
657 *type_in
= TREE_TYPE (sad_oprnd0
);
658 *type_out
= sum_type
;
660 /* Pattern detected. Create a stmt to be used to replace the pattern: */
661 tree var
= vect_recog_temp_ssa_var (sum_type
, NULL
);
662 gimple
*pattern_stmt
= gimple_build_assign (var
, SAD_EXPR
, sad_oprnd0
,
663 sad_oprnd1
, plus_oprnd1
);
665 if (dump_enabled_p ())
667 dump_printf_loc (MSG_NOTE
, vect_location
,
668 "vect_recog_sad_pattern: detected: ");
669 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
670 dump_printf (MSG_NOTE
, "\n");
677 /* Handle widening operation by a constant. At the moment we support MULT_EXPR
680 For MULT_EXPR we check that CONST_OPRND fits HALF_TYPE, and for LSHIFT_EXPR
681 we check that CONST_OPRND is less or equal to the size of HALF_TYPE.
683 Otherwise, if the type of the result (TYPE) is at least 4 times bigger than
684 HALF_TYPE, and there is an intermediate type (2 times smaller than TYPE)
685 that satisfies the above restrictions, we can perform a widening opeartion
686 from the intermediate type to TYPE and replace a_T = (TYPE) a_t;
687 with a_it = (interm_type) a_t; Store such operation in *WSTMT. */
690 vect_handle_widen_op_by_const (gimple
*stmt
, enum tree_code code
,
691 tree const_oprnd
, tree
*oprnd
,
692 gimple
**wstmt
, tree type
,
693 tree
*half_type
, gimple
*def_stmt
)
695 tree new_type
, new_oprnd
;
697 if (code
!= MULT_EXPR
&& code
!= LSHIFT_EXPR
)
700 if (((code
== MULT_EXPR
&& int_fits_type_p (const_oprnd
, *half_type
))
701 || (code
== LSHIFT_EXPR
702 && compare_tree_int (const_oprnd
, TYPE_PRECISION (*half_type
))
704 && TYPE_PRECISION (type
) == (TYPE_PRECISION (*half_type
) * 2))
706 /* CONST_OPRND is a constant of HALF_TYPE. */
707 *oprnd
= gimple_assign_rhs1 (def_stmt
);
711 if (TYPE_PRECISION (type
) < (TYPE_PRECISION (*half_type
) * 4))
714 if (!vect_same_loop_or_bb_p (stmt
, def_stmt
))
717 /* TYPE is 4 times bigger than HALF_TYPE, try widening operation for
718 a type 2 times bigger than HALF_TYPE. */
719 new_type
= build_nonstandard_integer_type (TYPE_PRECISION (type
) / 2,
720 TYPE_UNSIGNED (type
));
721 if ((code
== MULT_EXPR
&& !int_fits_type_p (const_oprnd
, new_type
))
722 || (code
== LSHIFT_EXPR
723 && compare_tree_int (const_oprnd
, TYPE_PRECISION (new_type
)) == 1))
726 /* Use NEW_TYPE for widening operation and create a_T = (NEW_TYPE) a_t; */
727 *oprnd
= gimple_assign_rhs1 (def_stmt
);
728 new_oprnd
= make_ssa_name (new_type
);
729 *wstmt
= gimple_build_assign (new_oprnd
, NOP_EXPR
, *oprnd
);
732 *half_type
= new_type
;
737 /* Function vect_recog_widen_mult_pattern
739 Try to find the following pattern:
743 TYPE a_T, b_T, prod_T;
749 S5 prod_T = a_T * b_T;
751 where type 'TYPE' is at least double the size of type 'type1' and 'type2'.
753 Also detect unsigned cases:
757 unsigned TYPE u_prod_T;
758 TYPE a_T, b_T, prod_T;
764 S5 prod_T = a_T * b_T;
765 S6 u_prod_T = (unsigned TYPE) prod_T;
767 and multiplication by constants:
774 S5 prod_T = a_T * CONST;
776 A special case of multiplication by constants is when 'TYPE' is 4 times
777 bigger than 'type', but CONST fits an intermediate type 2 times smaller
778 than 'TYPE'. In that case we create an additional pattern stmt for S3
779 to create a variable of the intermediate type, and perform widen-mult
780 on the intermediate type as well:
784 TYPE a_T, prod_T, prod_T';
788 '--> a_it = (interm_type) a_t;
789 S5 prod_T = a_T * CONST;
790 '--> prod_T' = a_it w* CONST;
794 * STMTS: Contains a stmt from which the pattern search begins. In the
795 example, when this function is called with S5, the pattern {S3,S4,S5,(S6)}
796 is detected. In case of unsigned widen-mult, the original stmt (S5) is
797 replaced with S6 in STMTS. In case of multiplication by a constant
798 of an intermediate type (the last case above), STMTS also contains S3
799 (inserted before S5).
803 * TYPE_IN: The type of the input arguments to the pattern.
805 * TYPE_OUT: The type of the output of this pattern.
807 * Return value: A new stmt that will be used to replace the sequence of
808 stmts that constitute the pattern. In this case it will be:
809 WIDEN_MULT <a_t, b_t>
810 If the result of WIDEN_MULT needs to be converted to a larger type, the
811 returned stmt will be this type conversion stmt.
815 vect_recog_widen_mult_pattern (vec
<gimple
*> *stmts
,
816 tree
*type_in
, tree
*type_out
)
818 gimple
*last_stmt
= stmts
->pop ();
819 gimple
*def_stmt0
, *def_stmt1
;
821 tree type
, half_type0
, half_type1
;
822 gimple
*new_stmt
= NULL
, *pattern_stmt
= NULL
;
823 tree vectype
, vecitype
;
825 enum tree_code dummy_code
;
831 if (!is_gimple_assign (last_stmt
))
834 type
= gimple_expr_type (last_stmt
);
836 /* Starting from LAST_STMT, follow the defs of its uses in search
837 of the above pattern. */
839 if (gimple_assign_rhs_code (last_stmt
) != MULT_EXPR
)
842 oprnd0
= gimple_assign_rhs1 (last_stmt
);
843 oprnd1
= gimple_assign_rhs2 (last_stmt
);
844 if (!types_compatible_p (TREE_TYPE (oprnd0
), type
)
845 || !types_compatible_p (TREE_TYPE (oprnd1
), type
))
848 /* Check argument 0. */
849 if (!type_conversion_p (oprnd0
, last_stmt
, false, &half_type0
, &def_stmt0
,
853 /* Check argument 1. */
854 op1_ok
= type_conversion_p (oprnd1
, last_stmt
, false, &half_type1
,
855 &def_stmt1
, &promotion
);
857 if (op1_ok
&& promotion
)
859 oprnd0
= gimple_assign_rhs1 (def_stmt0
);
860 oprnd1
= gimple_assign_rhs1 (def_stmt1
);
864 if (TREE_CODE (oprnd1
) == INTEGER_CST
865 && TREE_CODE (half_type0
) == INTEGER_TYPE
866 && vect_handle_widen_op_by_const (last_stmt
, MULT_EXPR
, oprnd1
,
867 &oprnd0
, &new_stmt
, type
,
868 &half_type0
, def_stmt0
))
870 half_type1
= half_type0
;
871 oprnd1
= fold_convert (half_type1
, oprnd1
);
877 /* If the two arguments have different sizes, convert the one with
878 the smaller type into the larger type. */
879 if (TYPE_PRECISION (half_type0
) != TYPE_PRECISION (half_type1
))
881 /* If we already used up the single-stmt slot give up. */
886 gimple
*def_stmt
= NULL
;
888 if (TYPE_PRECISION (half_type0
) < TYPE_PRECISION (half_type1
))
890 def_stmt
= def_stmt0
;
891 half_type0
= half_type1
;
896 def_stmt
= def_stmt1
;
897 half_type1
= half_type0
;
901 tree old_oprnd
= gimple_assign_rhs1 (def_stmt
);
902 tree new_oprnd
= make_ssa_name (half_type0
);
903 new_stmt
= gimple_build_assign (new_oprnd
, NOP_EXPR
, old_oprnd
);
907 /* Handle unsigned case. Look for
908 S6 u_prod_T = (unsigned TYPE) prod_T;
909 Use unsigned TYPE as the type for WIDEN_MULT_EXPR. */
910 if (TYPE_UNSIGNED (type
) != TYPE_UNSIGNED (half_type0
))
916 if (TYPE_UNSIGNED (type
) == TYPE_UNSIGNED (half_type1
))
919 use_stmt
= vect_single_imm_use (last_stmt
);
920 if (!use_stmt
|| !is_gimple_assign (use_stmt
)
921 || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt
)))
924 use_lhs
= gimple_assign_lhs (use_stmt
);
925 use_type
= TREE_TYPE (use_lhs
);
926 if (!INTEGRAL_TYPE_P (use_type
)
927 || (TYPE_UNSIGNED (type
) == TYPE_UNSIGNED (use_type
))
928 || (TYPE_PRECISION (type
) != TYPE_PRECISION (use_type
)))
932 last_stmt
= use_stmt
;
935 if (!types_compatible_p (half_type0
, half_type1
))
938 /* If TYPE is more than twice larger than HALF_TYPE, we use WIDEN_MULT
939 to get an intermediate result of type ITYPE. In this case we need
940 to build a statement to convert this intermediate result to type TYPE. */
942 if (TYPE_PRECISION (type
) > TYPE_PRECISION (half_type0
) * 2)
943 itype
= build_nonstandard_integer_type
944 (GET_MODE_BITSIZE (TYPE_MODE (half_type0
)) * 2,
945 TYPE_UNSIGNED (type
));
947 /* Pattern detected. */
948 if (dump_enabled_p ())
949 dump_printf_loc (MSG_NOTE
, vect_location
,
950 "vect_recog_widen_mult_pattern: detected:\n");
952 /* Check target support */
953 vectype
= get_vectype_for_scalar_type (half_type0
);
954 vecitype
= get_vectype_for_scalar_type (itype
);
957 || !supportable_widening_operation (WIDEN_MULT_EXPR
, last_stmt
,
959 &dummy_code
, &dummy_code
,
960 &dummy_int
, &dummy_vec
))
964 *type_out
= get_vectype_for_scalar_type (type
);
966 /* Pattern supported. Create a stmt to be used to replace the pattern: */
967 var
= vect_recog_temp_ssa_var (itype
, NULL
);
968 pattern_stmt
= gimple_build_assign (var
, WIDEN_MULT_EXPR
, oprnd0
, oprnd1
);
970 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
971 STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo
) = NULL
;
973 /* If the original two operands have different sizes, we may need to convert
974 the smaller one into the larget type. If this is the case, at this point
975 the new stmt is already built. */
978 append_pattern_def_seq (stmt_vinfo
, new_stmt
);
979 stmt_vec_info new_stmt_info
980 = new_stmt_vec_info (new_stmt
, stmt_vinfo
->vinfo
);
981 set_vinfo_for_stmt (new_stmt
, new_stmt_info
);
982 STMT_VINFO_VECTYPE (new_stmt_info
) = vectype
;
985 /* If ITYPE is not TYPE, we need to build a type convertion stmt to convert
986 the result of the widen-mult operation into type TYPE. */
989 append_pattern_def_seq (stmt_vinfo
, pattern_stmt
);
990 stmt_vec_info pattern_stmt_info
991 = new_stmt_vec_info (pattern_stmt
, stmt_vinfo
->vinfo
);
992 set_vinfo_for_stmt (pattern_stmt
, pattern_stmt_info
);
993 STMT_VINFO_VECTYPE (pattern_stmt_info
) = vecitype
;
994 pattern_stmt
= gimple_build_assign (vect_recog_temp_ssa_var (type
, NULL
),
996 gimple_assign_lhs (pattern_stmt
));
999 if (dump_enabled_p ())
1000 dump_gimple_stmt_loc (MSG_NOTE
, vect_location
, TDF_SLIM
, pattern_stmt
, 0);
1002 stmts
->safe_push (last_stmt
);
1003 return pattern_stmt
;
1007 /* Function vect_recog_pow_pattern
1009 Try to find the following pattern:
1013 with POW being one of pow, powf, powi, powif and N being
1018 * LAST_STMT: A stmt from which the pattern search begins.
1022 * TYPE_IN: The type of the input arguments to the pattern.
1024 * TYPE_OUT: The type of the output of this pattern.
1026 * Return value: A new stmt that will be used to replace the sequence of
1027 stmts that constitute the pattern. In this case it will be:
1034 vect_recog_pow_pattern (vec
<gimple
*> *stmts
, tree
*type_in
,
1037 gimple
*last_stmt
= (*stmts
)[0];
1038 tree base
, exp
= NULL
;
1042 if (!is_gimple_call (last_stmt
) || gimple_call_lhs (last_stmt
) == NULL
)
1045 switch (gimple_call_combined_fn (last_stmt
))
1049 base
= gimple_call_arg (last_stmt
, 0);
1050 exp
= gimple_call_arg (last_stmt
, 1);
1051 if (TREE_CODE (exp
) != REAL_CST
1052 && TREE_CODE (exp
) != INTEGER_CST
)
1060 /* We now have a pow or powi builtin function call with a constant
1063 *type_out
= NULL_TREE
;
1065 /* Catch squaring. */
1066 if ((tree_fits_shwi_p (exp
)
1067 && tree_to_shwi (exp
) == 2)
1068 || (TREE_CODE (exp
) == REAL_CST
1069 && real_equal (&TREE_REAL_CST (exp
), &dconst2
)))
1071 *type_in
= TREE_TYPE (base
);
1073 var
= vect_recog_temp_ssa_var (TREE_TYPE (base
), NULL
);
1074 stmt
= gimple_build_assign (var
, MULT_EXPR
, base
, base
);
1078 /* Catch square root. */
1079 if (TREE_CODE (exp
) == REAL_CST
1080 && real_equal (&TREE_REAL_CST (exp
), &dconsthalf
))
1082 *type_in
= get_vectype_for_scalar_type (TREE_TYPE (base
));
1084 && direct_internal_fn_supported_p (IFN_SQRT
, *type_in
,
1085 OPTIMIZE_FOR_SPEED
))
1087 gcall
*stmt
= gimple_build_call_internal (IFN_SQRT
, 1, base
);
1088 var
= vect_recog_temp_ssa_var (TREE_TYPE (base
), stmt
);
1089 gimple_call_set_lhs (stmt
, var
);
1098 /* Function vect_recog_widen_sum_pattern
1100 Try to find the following pattern:
1103 TYPE x_T, sum = init;
1105 sum_0 = phi <init, sum_1>
1107 S2 x_T = (TYPE) x_t;
1108 S3 sum_1 = x_T + sum_0;
1110 where type 'TYPE' is at least double the size of type 'type', i.e - we're
1111 summing elements of type 'type' into an accumulator of type 'TYPE'. This is
1112 a special case of a reduction computation.
1116 * LAST_STMT: A stmt from which the pattern search begins. In the example,
1117 when this function is called with S3, the pattern {S2,S3} will be detected.
1121 * TYPE_IN: The type of the input arguments to the pattern.
1123 * TYPE_OUT: The type of the output of this pattern.
1125 * Return value: A new stmt that will be used to replace the sequence of
1126 stmts that constitute the pattern. In this case it will be:
1127 WIDEN_SUM <x_t, sum_0>
1129 Note: The widening-sum idiom is a widening reduction pattern that is
1130 vectorized without preserving all the intermediate results. It
1131 produces only N/2 (widened) results (by summing up pairs of
1132 intermediate results) rather than all N results. Therefore, we
1133 cannot allow this pattern when we want to get all the results and in
1134 the correct order (as is the case when this computation is in an
1135 inner-loop nested in an outer-loop that us being vectorized). */
1138 vect_recog_widen_sum_pattern (vec
<gimple
*> *stmts
, tree
*type_in
,
1141 gimple
*stmt
, *last_stmt
= (*stmts
)[0];
1142 tree oprnd0
, oprnd1
;
1143 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
1144 tree type
, half_type
;
1145 gimple
*pattern_stmt
;
1146 loop_vec_info loop_info
= STMT_VINFO_LOOP_VINFO (stmt_vinfo
);
1154 loop
= LOOP_VINFO_LOOP (loop_info
);
1156 /* We don't allow changing the order of the computation in the inner-loop
1157 when doing outer-loop vectorization. */
1158 if (loop
&& nested_in_vect_loop_p (loop
, last_stmt
))
1161 if (!is_gimple_assign (last_stmt
))
1164 type
= gimple_expr_type (last_stmt
);
1166 /* Look for the following pattern
1169 In which DX is at least double the size of X, and sum_1 has been
1170 recognized as a reduction variable.
1173 /* Starting from LAST_STMT, follow the defs of its uses in search
1174 of the above pattern. */
1176 if (gimple_assign_rhs_code (last_stmt
) != PLUS_EXPR
)
1179 if (STMT_VINFO_DEF_TYPE (stmt_vinfo
) != vect_reduction_def
1180 && ! STMT_VINFO_GROUP_FIRST_ELEMENT (stmt_vinfo
))
1183 oprnd0
= gimple_assign_rhs1 (last_stmt
);
1184 oprnd1
= gimple_assign_rhs2 (last_stmt
);
1185 if (!types_compatible_p (TREE_TYPE (oprnd0
), type
)
1186 || !types_compatible_p (TREE_TYPE (oprnd1
), type
))
1189 /* So far so good. Since last_stmt was detected as a (summation) reduction,
1190 we know that oprnd1 is the reduction variable (defined by a loop-header
1191 phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
1192 Left to check that oprnd0 is defined by a cast from type 'type' to type
1195 if (!type_conversion_p (oprnd0
, last_stmt
, true, &half_type
, &stmt
,
1200 oprnd0
= gimple_assign_rhs1 (stmt
);
1201 *type_in
= half_type
;
1204 /* Pattern detected. Create a stmt to be used to replace the pattern: */
1205 var
= vect_recog_temp_ssa_var (type
, NULL
);
1206 pattern_stmt
= gimple_build_assign (var
, WIDEN_SUM_EXPR
, oprnd0
, oprnd1
);
1208 if (dump_enabled_p ())
1210 dump_printf_loc (MSG_NOTE
, vect_location
,
1211 "vect_recog_widen_sum_pattern: detected: ");
1212 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
1213 dump_printf (MSG_NOTE
, "\n");
1216 return pattern_stmt
;
1220 /* Return TRUE if the operation in STMT can be performed on a smaller type.
1223 STMT - a statement to check.
1224 DEF - we support operations with two operands, one of which is constant.
1225 The other operand can be defined by a demotion operation, or by a
1226 previous statement in a sequence of over-promoted operations. In the
1227 later case DEF is used to replace that operand. (It is defined by a
1228 pattern statement we created for the previous statement in the
1232 NEW_TYPE - Output: a smaller type that we are trying to use. Input: if not
1233 NULL, it's the type of DEF.
1234 STMTS - additional pattern statements. If a pattern statement (type
1235 conversion) is created in this function, its original statement is
1239 OP0, OP1 - if the operation fits a smaller type, OP0 and OP1 are the new
1240 operands to use in the new pattern statement for STMT (will be created
1241 in vect_recog_over_widening_pattern ()).
1242 NEW_DEF_STMT - in case DEF has to be promoted, we create two pattern
1243 statements for STMT: the first one is a type promotion and the second
1244 one is the operation itself. We return the type promotion statement
1245 in NEW_DEF_STMT and further store it in STMT_VINFO_PATTERN_DEF_SEQ of
1246 the second pattern statement. */
1249 vect_operation_fits_smaller_type (gimple
*stmt
, tree def
, tree
*new_type
,
1250 tree
*op0
, tree
*op1
, gimple
**new_def_stmt
,
1251 vec
<gimple
*> *stmts
)
1253 enum tree_code code
;
1254 tree const_oprnd
, oprnd
;
1255 tree interm_type
= NULL_TREE
, half_type
, new_oprnd
, type
;
1256 gimple
*def_stmt
, *new_stmt
;
1262 *new_def_stmt
= NULL
;
1264 if (!is_gimple_assign (stmt
))
1267 code
= gimple_assign_rhs_code (stmt
);
1268 if (code
!= LSHIFT_EXPR
&& code
!= RSHIFT_EXPR
1269 && code
!= BIT_IOR_EXPR
&& code
!= BIT_XOR_EXPR
&& code
!= BIT_AND_EXPR
)
1272 oprnd
= gimple_assign_rhs1 (stmt
);
1273 const_oprnd
= gimple_assign_rhs2 (stmt
);
1274 type
= gimple_expr_type (stmt
);
1276 if (TREE_CODE (oprnd
) != SSA_NAME
1277 || TREE_CODE (const_oprnd
) != INTEGER_CST
)
1280 /* If oprnd has other uses besides that in stmt we cannot mark it
1281 as being part of a pattern only. */
1282 if (!has_single_use (oprnd
))
1285 /* If we are in the middle of a sequence, we use DEF from a previous
1286 statement. Otherwise, OPRND has to be a result of type promotion. */
1289 half_type
= *new_type
;
1295 if (!type_conversion_p (oprnd
, stmt
, false, &half_type
, &def_stmt
,
1298 || !vect_same_loop_or_bb_p (stmt
, def_stmt
))
1302 /* Can we perform the operation on a smaller type? */
1308 if (!int_fits_type_p (const_oprnd
, half_type
))
1310 /* HALF_TYPE is not enough. Try a bigger type if possible. */
1311 if (TYPE_PRECISION (type
) < (TYPE_PRECISION (half_type
) * 4))
1314 interm_type
= build_nonstandard_integer_type (
1315 TYPE_PRECISION (half_type
) * 2, TYPE_UNSIGNED (type
));
1316 if (!int_fits_type_p (const_oprnd
, interm_type
))
1323 /* Try intermediate type - HALF_TYPE is not enough for sure. */
1324 if (TYPE_PRECISION (type
) < (TYPE_PRECISION (half_type
) * 4))
1327 /* Check that HALF_TYPE size + shift amount <= INTERM_TYPE size.
1328 (e.g., if the original value was char, the shift amount is at most 8
1329 if we want to use short). */
1330 if (compare_tree_int (const_oprnd
, TYPE_PRECISION (half_type
)) == 1)
1333 interm_type
= build_nonstandard_integer_type (
1334 TYPE_PRECISION (half_type
) * 2, TYPE_UNSIGNED (type
));
1336 if (!vect_supportable_shift (code
, interm_type
))
1342 if (vect_supportable_shift (code
, half_type
))
1345 /* Try intermediate type - HALF_TYPE is not supported. */
1346 if (TYPE_PRECISION (type
) < (TYPE_PRECISION (half_type
) * 4))
1349 interm_type
= build_nonstandard_integer_type (
1350 TYPE_PRECISION (half_type
) * 2, TYPE_UNSIGNED (type
));
1352 if (!vect_supportable_shift (code
, interm_type
))
1361 /* There are four possible cases:
1362 1. OPRND is defined by a type promotion (in that case FIRST is TRUE, it's
1363 the first statement in the sequence)
1364 a. The original, HALF_TYPE, is not enough - we replace the promotion
1365 from HALF_TYPE to TYPE with a promotion to INTERM_TYPE.
1366 b. HALF_TYPE is sufficient, OPRND is set as the RHS of the original
1368 2. OPRND is defined by a pattern statement we created.
1369 a. Its type is not sufficient for the operation, we create a new stmt:
1370 a type conversion for OPRND from HALF_TYPE to INTERM_TYPE. We store
1371 this statement in NEW_DEF_STMT, and it is later put in
1372 STMT_VINFO_PATTERN_DEF_SEQ of the pattern statement for STMT.
1373 b. OPRND is good to use in the new statement. */
1378 /* Replace the original type conversion HALF_TYPE->TYPE with
1379 HALF_TYPE->INTERM_TYPE. */
1380 if (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt
)))
1382 new_stmt
= STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt
));
1383 /* Check if the already created pattern stmt is what we need. */
1384 if (!is_gimple_assign (new_stmt
)
1385 || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (new_stmt
))
1386 || TREE_TYPE (gimple_assign_lhs (new_stmt
)) != interm_type
)
1389 stmts
->safe_push (def_stmt
);
1390 oprnd
= gimple_assign_lhs (new_stmt
);
1394 /* Create NEW_OPRND = (INTERM_TYPE) OPRND. */
1395 oprnd
= gimple_assign_rhs1 (def_stmt
);
1396 new_oprnd
= make_ssa_name (interm_type
);
1397 new_stmt
= gimple_build_assign (new_oprnd
, NOP_EXPR
, oprnd
);
1398 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt
)) = new_stmt
;
1399 stmts
->safe_push (def_stmt
);
1405 /* Retrieve the operand before the type promotion. */
1406 oprnd
= gimple_assign_rhs1 (def_stmt
);
1413 /* Create a type conversion HALF_TYPE->INTERM_TYPE. */
1414 new_oprnd
= make_ssa_name (interm_type
);
1415 new_stmt
= gimple_build_assign (new_oprnd
, NOP_EXPR
, oprnd
);
1417 *new_def_stmt
= new_stmt
;
1420 /* Otherwise, OPRND is already set. */
1424 *new_type
= interm_type
;
1426 *new_type
= half_type
;
1429 *op1
= fold_convert (*new_type
, const_oprnd
);
1435 /* Try to find a statement or a sequence of statements that can be performed
1439 TYPE x_T, res0_T, res1_T;
1442 S2 x_T = (TYPE) x_t;
1443 S3 res0_T = op (x_T, C0);
1444 S4 res1_T = op (res0_T, C1);
1445 S5 ... = () res1_T; - type demotion
1447 where type 'TYPE' is at least double the size of type 'type', C0 and C1 are
1449 Check if S3 and S4 can be done on a smaller type than 'TYPE', it can either
1450 be 'type' or some intermediate type. For now, we expect S5 to be a type
1451 demotion operation. We also check that S3 and S4 have only one use. */
1454 vect_recog_over_widening_pattern (vec
<gimple
*> *stmts
,
1455 tree
*type_in
, tree
*type_out
)
1457 gimple
*stmt
= stmts
->pop ();
1458 gimple
*pattern_stmt
= NULL
, *new_def_stmt
, *prev_stmt
= NULL
,
1460 tree op0
, op1
, vectype
= NULL_TREE
, use_lhs
, use_type
;
1461 tree var
= NULL_TREE
, new_type
= NULL_TREE
, new_oprnd
;
1468 if (!vinfo_for_stmt (stmt
)
1469 || STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (stmt
)))
1472 new_def_stmt
= NULL
;
1473 if (!vect_operation_fits_smaller_type (stmt
, var
, &new_type
,
1474 &op0
, &op1
, &new_def_stmt
,
1483 /* STMT can be performed on a smaller type. Check its uses. */
1484 use_stmt
= vect_single_imm_use (stmt
);
1485 if (!use_stmt
|| !is_gimple_assign (use_stmt
))
1488 /* Create pattern statement for STMT. */
1489 vectype
= get_vectype_for_scalar_type (new_type
);
1493 /* We want to collect all the statements for which we create pattern
1494 statetments, except for the case when the last statement in the
1495 sequence doesn't have a corresponding pattern statement. In such
1496 case we associate the last pattern statement with the last statement
1497 in the sequence. Therefore, we only add the original statement to
1498 the list if we know that it is not the last. */
1500 stmts
->safe_push (prev_stmt
);
1502 var
= vect_recog_temp_ssa_var (new_type
, NULL
);
1504 = gimple_build_assign (var
, gimple_assign_rhs_code (stmt
), op0
, op1
);
1505 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt
)) = pattern_stmt
;
1506 new_pattern_def_seq (vinfo_for_stmt (stmt
), new_def_stmt
);
1508 if (dump_enabled_p ())
1510 dump_printf_loc (MSG_NOTE
, vect_location
,
1511 "created pattern stmt: ");
1512 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
1513 dump_printf (MSG_NOTE
, "\n");
1516 type
= gimple_expr_type (stmt
);
1523 /* We got a sequence. We expect it to end with a type demotion operation.
1524 Otherwise, we quit (for now). There are three possible cases: the
1525 conversion is to NEW_TYPE (we don't do anything), the conversion is to
1526 a type bigger than NEW_TYPE and/or the signedness of USE_TYPE and
1527 NEW_TYPE differs (we create a new conversion statement). */
1528 if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt
)))
1530 use_lhs
= gimple_assign_lhs (use_stmt
);
1531 use_type
= TREE_TYPE (use_lhs
);
1532 /* Support only type demotion or signedess change. */
1533 if (!INTEGRAL_TYPE_P (use_type
)
1534 || TYPE_PRECISION (type
) <= TYPE_PRECISION (use_type
))
1537 /* Check that NEW_TYPE is not bigger than the conversion result. */
1538 if (TYPE_PRECISION (new_type
) > TYPE_PRECISION (use_type
))
1541 if (TYPE_UNSIGNED (new_type
) != TYPE_UNSIGNED (use_type
)
1542 || TYPE_PRECISION (new_type
) != TYPE_PRECISION (use_type
))
1544 /* Create NEW_TYPE->USE_TYPE conversion. */
1545 new_oprnd
= make_ssa_name (use_type
);
1546 pattern_stmt
= gimple_build_assign (new_oprnd
, NOP_EXPR
, var
);
1547 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt
)) = pattern_stmt
;
1549 *type_in
= get_vectype_for_scalar_type (new_type
);
1550 *type_out
= get_vectype_for_scalar_type (use_type
);
1552 /* We created a pattern statement for the last statement in the
1553 sequence, so we don't need to associate it with the pattern
1554 statement created for PREV_STMT. Therefore, we add PREV_STMT
1555 to the list in order to mark it later in vect_pattern_recog_1. */
1557 stmts
->safe_push (prev_stmt
);
1562 STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (use_stmt
))
1563 = STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (prev_stmt
));
1566 *type_out
= NULL_TREE
;
1569 stmts
->safe_push (use_stmt
);
1572 /* TODO: support general case, create a conversion to the correct type. */
1575 /* Pattern detected. */
1576 if (dump_enabled_p ())
1578 dump_printf_loc (MSG_NOTE
, vect_location
,
1579 "vect_recog_over_widening_pattern: detected: ");
1580 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
1581 dump_printf (MSG_NOTE
, "\n");
1584 return pattern_stmt
;
1587 /* Detect widening shift pattern:
1593 S2 a_T = (TYPE) a_t;
1594 S3 res_T = a_T << CONST;
1596 where type 'TYPE' is at least double the size of type 'type'.
1598 Also detect cases where the shift result is immediately converted
1599 to another type 'result_type' that is no larger in size than 'TYPE'.
1600 In those cases we perform a widen-shift that directly results in
1601 'result_type', to avoid a possible over-widening situation:
1605 result_type res_result;
1608 S2 a_T = (TYPE) a_t;
1609 S3 res_T = a_T << CONST;
1610 S4 res_result = (result_type) res_T;
1611 '--> res_result' = a_t w<< CONST;
1613 And a case when 'TYPE' is 4 times bigger than 'type'. In that case we
1614 create an additional pattern stmt for S2 to create a variable of an
1615 intermediate type, and perform widen-shift on the intermediate type:
1619 TYPE a_T, res_T, res_T';
1622 S2 a_T = (TYPE) a_t;
1623 '--> a_it = (interm_type) a_t;
1624 S3 res_T = a_T << CONST;
1625 '--> res_T' = a_it <<* CONST;
1629 * STMTS: Contains a stmt from which the pattern search begins.
1630 In case of unsigned widen-shift, the original stmt (S3) is replaced with S4
1631 in STMTS. When an intermediate type is used and a pattern statement is
1632 created for S2, we also put S2 here (before S3).
1636 * TYPE_IN: The type of the input arguments to the pattern.
1638 * TYPE_OUT: The type of the output of this pattern.
1640 * Return value: A new stmt that will be used to replace the sequence of
1641 stmts that constitute the pattern. In this case it will be:
1642 WIDEN_LSHIFT_EXPR <a_t, CONST>. */
1645 vect_recog_widen_shift_pattern (vec
<gimple
*> *stmts
,
1646 tree
*type_in
, tree
*type_out
)
1648 gimple
*last_stmt
= stmts
->pop ();
1650 tree oprnd0
, oprnd1
;
1651 tree type
, half_type0
;
1652 gimple
*pattern_stmt
;
1653 tree vectype
, vectype_out
= NULL_TREE
;
1655 enum tree_code dummy_code
;
1657 vec
<tree
> dummy_vec
;
1661 if (!is_gimple_assign (last_stmt
) || !vinfo_for_stmt (last_stmt
))
1664 if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt
)))
1667 if (gimple_assign_rhs_code (last_stmt
) != LSHIFT_EXPR
)
1670 oprnd0
= gimple_assign_rhs1 (last_stmt
);
1671 oprnd1
= gimple_assign_rhs2 (last_stmt
);
1672 if (TREE_CODE (oprnd0
) != SSA_NAME
|| TREE_CODE (oprnd1
) != INTEGER_CST
)
1675 /* Check operand 0: it has to be defined by a type promotion. */
1676 if (!type_conversion_p (oprnd0
, last_stmt
, false, &half_type0
, &def_stmt0
,
1681 /* Check operand 1: has to be positive. We check that it fits the type
1682 in vect_handle_widen_op_by_const (). */
1683 if (tree_int_cst_compare (oprnd1
, size_zero_node
) <= 0)
1686 oprnd0
= gimple_assign_rhs1 (def_stmt0
);
1687 type
= gimple_expr_type (last_stmt
);
1689 /* Check for subsequent conversion to another type. */
1690 use_stmt
= vect_single_imm_use (last_stmt
);
1691 if (use_stmt
&& is_gimple_assign (use_stmt
)
1692 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt
))
1693 && !STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt
)))
1695 tree use_lhs
= gimple_assign_lhs (use_stmt
);
1696 tree use_type
= TREE_TYPE (use_lhs
);
1698 if (INTEGRAL_TYPE_P (use_type
)
1699 && TYPE_PRECISION (use_type
) <= TYPE_PRECISION (type
))
1701 last_stmt
= use_stmt
;
1706 /* Check if this a widening operation. */
1707 gimple
*wstmt
= NULL
;
1708 if (!vect_handle_widen_op_by_const (last_stmt
, LSHIFT_EXPR
, oprnd1
,
1710 type
, &half_type0
, def_stmt0
))
1713 /* Pattern detected. */
1714 if (dump_enabled_p ())
1715 dump_printf_loc (MSG_NOTE
, vect_location
,
1716 "vect_recog_widen_shift_pattern: detected:\n");
1718 /* Check target support. */
1719 vectype
= get_vectype_for_scalar_type (half_type0
);
1720 vectype_out
= get_vectype_for_scalar_type (type
);
1724 || !supportable_widening_operation (WIDEN_LSHIFT_EXPR
, last_stmt
,
1725 vectype_out
, vectype
,
1726 &dummy_code
, &dummy_code
,
1727 &dummy_int
, &dummy_vec
))
1731 *type_out
= vectype_out
;
1733 /* Pattern supported. Create a stmt to be used to replace the pattern. */
1734 var
= vect_recog_temp_ssa_var (type
, NULL
);
1736 gimple_build_assign (var
, WIDEN_LSHIFT_EXPR
, oprnd0
, oprnd1
);
1739 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
1740 new_pattern_def_seq (stmt_vinfo
, wstmt
);
1741 stmt_vec_info new_stmt_info
1742 = new_stmt_vec_info (wstmt
, stmt_vinfo
->vinfo
);
1743 set_vinfo_for_stmt (wstmt
, new_stmt_info
);
1744 STMT_VINFO_VECTYPE (new_stmt_info
) = vectype
;
1747 if (dump_enabled_p ())
1748 dump_gimple_stmt_loc (MSG_NOTE
, vect_location
, TDF_SLIM
, pattern_stmt
, 0);
1750 stmts
->safe_push (last_stmt
);
1751 return pattern_stmt
;
1754 /* Detect a rotate pattern wouldn't be otherwise vectorized:
1758 S0 a_t = b_t r<< c_t;
1762 * STMTS: Contains a stmt from which the pattern search begins,
1763 i.e. the shift/rotate stmt. The original stmt (S0) is replaced
1767 S2 e_t = d_t & (B - 1);
1768 S3 f_t = b_t << c_t;
1769 S4 g_t = b_t >> e_t;
1772 where B is element bitsize of type.
1776 * TYPE_IN: The type of the input arguments to the pattern.
1778 * TYPE_OUT: The type of the output of this pattern.
1780 * Return value: A new stmt that will be used to replace the rotate
1784 vect_recog_rotate_pattern (vec
<gimple
*> *stmts
, tree
*type_in
, tree
*type_out
)
1786 gimple
*last_stmt
= stmts
->pop ();
1787 tree oprnd0
, oprnd1
, lhs
, var
, var1
, var2
, vectype
, type
, stype
, def
, def2
;
1788 gimple
*pattern_stmt
, *def_stmt
;
1789 enum tree_code rhs_code
;
1790 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
1791 vec_info
*vinfo
= stmt_vinfo
->vinfo
;
1792 enum vect_def_type dt
;
1793 optab optab1
, optab2
;
1794 edge ext_def
= NULL
;
1796 if (!is_gimple_assign (last_stmt
))
1799 rhs_code
= gimple_assign_rhs_code (last_stmt
);
1809 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo
))
1812 lhs
= gimple_assign_lhs (last_stmt
);
1813 oprnd0
= gimple_assign_rhs1 (last_stmt
);
1814 type
= TREE_TYPE (oprnd0
);
1815 oprnd1
= gimple_assign_rhs2 (last_stmt
);
1816 if (TREE_CODE (oprnd0
) != SSA_NAME
1817 || TYPE_PRECISION (TREE_TYPE (lhs
)) != TYPE_PRECISION (type
)
1818 || !INTEGRAL_TYPE_P (type
)
1819 || !TYPE_UNSIGNED (type
))
1822 if (!vect_is_simple_use (oprnd1
, vinfo
, &def_stmt
, &dt
))
1825 if (dt
!= vect_internal_def
1826 && dt
!= vect_constant_def
1827 && dt
!= vect_external_def
)
1830 vectype
= get_vectype_for_scalar_type (type
);
1831 if (vectype
== NULL_TREE
)
1834 /* If vector/vector or vector/scalar rotate is supported by the target,
1835 don't do anything here. */
1836 optab1
= optab_for_tree_code (rhs_code
, vectype
, optab_vector
);
1838 && optab_handler (optab1
, TYPE_MODE (vectype
)) != CODE_FOR_nothing
)
1841 if (is_a
<bb_vec_info
> (vinfo
) || dt
!= vect_internal_def
)
1843 optab2
= optab_for_tree_code (rhs_code
, vectype
, optab_scalar
);
1845 && optab_handler (optab2
, TYPE_MODE (vectype
)) != CODE_FOR_nothing
)
1849 /* If vector/vector or vector/scalar shifts aren't supported by the target,
1850 don't do anything here either. */
1851 optab1
= optab_for_tree_code (LSHIFT_EXPR
, vectype
, optab_vector
);
1852 optab2
= optab_for_tree_code (RSHIFT_EXPR
, vectype
, optab_vector
);
1854 || optab_handler (optab1
, TYPE_MODE (vectype
)) == CODE_FOR_nothing
1856 || optab_handler (optab2
, TYPE_MODE (vectype
)) == CODE_FOR_nothing
)
1858 if (! is_a
<bb_vec_info
> (vinfo
) && dt
== vect_internal_def
)
1860 optab1
= optab_for_tree_code (LSHIFT_EXPR
, vectype
, optab_scalar
);
1861 optab2
= optab_for_tree_code (RSHIFT_EXPR
, vectype
, optab_scalar
);
1863 || optab_handler (optab1
, TYPE_MODE (vectype
)) == CODE_FOR_nothing
1865 || optab_handler (optab2
, TYPE_MODE (vectype
)) == CODE_FOR_nothing
)
1870 *type_out
= vectype
;
1871 if (*type_in
== NULL_TREE
)
1874 if (dt
== vect_external_def
1875 && TREE_CODE (oprnd1
) == SSA_NAME
1876 && is_a
<loop_vec_info
> (vinfo
))
1878 struct loop
*loop
= as_a
<loop_vec_info
> (vinfo
)->loop
;
1879 ext_def
= loop_preheader_edge (loop
);
1880 if (!SSA_NAME_IS_DEFAULT_DEF (oprnd1
))
1882 basic_block bb
= gimple_bb (SSA_NAME_DEF_STMT (oprnd1
));
1884 || !dominated_by_p (CDI_DOMINATORS
, ext_def
->dest
, bb
))
1890 if (TREE_CODE (oprnd1
) == INTEGER_CST
1891 || TYPE_MODE (TREE_TYPE (oprnd1
)) == TYPE_MODE (type
))
1893 else if (def_stmt
&& gimple_assign_cast_p (def_stmt
))
1895 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
1896 if (TYPE_MODE (TREE_TYPE (rhs1
)) == TYPE_MODE (type
)
1897 && TYPE_PRECISION (TREE_TYPE (rhs1
))
1898 == TYPE_PRECISION (type
))
1902 STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo
) = NULL
;
1903 if (def
== NULL_TREE
)
1905 def
= vect_recog_temp_ssa_var (type
, NULL
);
1906 def_stmt
= gimple_build_assign (def
, NOP_EXPR
, oprnd1
);
1910 = gsi_insert_on_edge_immediate (ext_def
, def_stmt
);
1911 gcc_assert (!new_bb
);
1914 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
1916 stype
= TREE_TYPE (def
);
1918 if (TREE_CODE (def
) == INTEGER_CST
)
1920 if (!tree_fits_uhwi_p (def
)
1921 || tree_to_uhwi (def
) >= GET_MODE_PRECISION (TYPE_MODE (type
))
1922 || integer_zerop (def
))
1924 def2
= build_int_cst (stype
,
1925 GET_MODE_PRECISION (TYPE_MODE (type
))
1926 - tree_to_uhwi (def
));
1930 tree vecstype
= get_vectype_for_scalar_type (stype
);
1931 stmt_vec_info def_stmt_vinfo
;
1933 if (vecstype
== NULL_TREE
)
1935 def2
= vect_recog_temp_ssa_var (stype
, NULL
);
1936 def_stmt
= gimple_build_assign (def2
, NEGATE_EXPR
, def
);
1940 = gsi_insert_on_edge_immediate (ext_def
, def_stmt
);
1941 gcc_assert (!new_bb
);
1945 def_stmt_vinfo
= new_stmt_vec_info (def_stmt
, vinfo
);
1946 set_vinfo_for_stmt (def_stmt
, def_stmt_vinfo
);
1947 STMT_VINFO_VECTYPE (def_stmt_vinfo
) = vecstype
;
1948 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
1951 def2
= vect_recog_temp_ssa_var (stype
, NULL
);
1953 = build_int_cst (stype
, GET_MODE_PRECISION (TYPE_MODE (stype
)) - 1);
1954 def_stmt
= gimple_build_assign (def2
, BIT_AND_EXPR
,
1955 gimple_assign_lhs (def_stmt
), mask
);
1959 = gsi_insert_on_edge_immediate (ext_def
, def_stmt
);
1960 gcc_assert (!new_bb
);
1964 def_stmt_vinfo
= new_stmt_vec_info (def_stmt
, vinfo
);
1965 set_vinfo_for_stmt (def_stmt
, def_stmt_vinfo
);
1966 STMT_VINFO_VECTYPE (def_stmt_vinfo
) = vecstype
;
1967 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
1971 var1
= vect_recog_temp_ssa_var (type
, NULL
);
1972 def_stmt
= gimple_build_assign (var1
, rhs_code
== LROTATE_EXPR
1973 ? LSHIFT_EXPR
: RSHIFT_EXPR
,
1975 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
1977 var2
= vect_recog_temp_ssa_var (type
, NULL
);
1978 def_stmt
= gimple_build_assign (var2
, rhs_code
== LROTATE_EXPR
1979 ? RSHIFT_EXPR
: LSHIFT_EXPR
,
1981 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
1983 /* Pattern detected. */
1984 if (dump_enabled_p ())
1985 dump_printf_loc (MSG_NOTE
, vect_location
,
1986 "vect_recog_rotate_pattern: detected:\n");
1988 /* Pattern supported. Create a stmt to be used to replace the pattern. */
1989 var
= vect_recog_temp_ssa_var (type
, NULL
);
1990 pattern_stmt
= gimple_build_assign (var
, BIT_IOR_EXPR
, var1
, var2
);
1992 if (dump_enabled_p ())
1993 dump_gimple_stmt_loc (MSG_NOTE
, vect_location
, TDF_SLIM
, pattern_stmt
, 0);
1995 stmts
->safe_push (last_stmt
);
1996 return pattern_stmt
;
1999 /* Detect a vector by vector shift pattern that wouldn't be otherwise
2007 S3 res_T = b_T op a_t;
2009 where type 'TYPE' is a type with different size than 'type',
2010 and op is <<, >> or rotate.
2015 TYPE b_T, c_T, res_T;
2018 S1 a_t = (type) c_T;
2020 S3 res_T = b_T op a_t;
2024 * STMTS: Contains a stmt from which the pattern search begins,
2025 i.e. the shift/rotate stmt. The original stmt (S3) is replaced
2026 with a shift/rotate which has same type on both operands, in the
2027 second case just b_T op c_T, in the first case with added cast
2028 from a_t to c_T in STMT_VINFO_PATTERN_DEF_SEQ.
2032 * TYPE_IN: The type of the input arguments to the pattern.
2034 * TYPE_OUT: The type of the output of this pattern.
2036 * Return value: A new stmt that will be used to replace the shift/rotate
2040 vect_recog_vector_vector_shift_pattern (vec
<gimple
*> *stmts
,
2041 tree
*type_in
, tree
*type_out
)
2043 gimple
*last_stmt
= stmts
->pop ();
2044 tree oprnd0
, oprnd1
, lhs
, var
;
2045 gimple
*pattern_stmt
, *def_stmt
;
2046 enum tree_code rhs_code
;
2047 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
2048 vec_info
*vinfo
= stmt_vinfo
->vinfo
;
2049 enum vect_def_type dt
;
2051 if (!is_gimple_assign (last_stmt
))
2054 rhs_code
= gimple_assign_rhs_code (last_stmt
);
2066 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo
))
2069 lhs
= gimple_assign_lhs (last_stmt
);
2070 oprnd0
= gimple_assign_rhs1 (last_stmt
);
2071 oprnd1
= gimple_assign_rhs2 (last_stmt
);
2072 if (TREE_CODE (oprnd0
) != SSA_NAME
2073 || TREE_CODE (oprnd1
) != SSA_NAME
2074 || TYPE_MODE (TREE_TYPE (oprnd0
)) == TYPE_MODE (TREE_TYPE (oprnd1
))
2075 || TYPE_PRECISION (TREE_TYPE (oprnd1
))
2076 != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (oprnd1
)))
2077 || TYPE_PRECISION (TREE_TYPE (lhs
))
2078 != TYPE_PRECISION (TREE_TYPE (oprnd0
)))
2081 if (!vect_is_simple_use (oprnd1
, vinfo
, &def_stmt
, &dt
))
2084 if (dt
!= vect_internal_def
)
2087 *type_in
= get_vectype_for_scalar_type (TREE_TYPE (oprnd0
));
2088 *type_out
= *type_in
;
2089 if (*type_in
== NULL_TREE
)
2092 tree def
= NULL_TREE
;
2093 if (gimple_assign_cast_p (def_stmt
))
2095 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
2096 if (TYPE_MODE (TREE_TYPE (rhs1
)) == TYPE_MODE (TREE_TYPE (oprnd0
))
2097 && TYPE_PRECISION (TREE_TYPE (rhs1
))
2098 == TYPE_PRECISION (TREE_TYPE (oprnd0
)))
2102 if (def
== NULL_TREE
)
2104 def
= vect_recog_temp_ssa_var (TREE_TYPE (oprnd0
), NULL
);
2105 def_stmt
= gimple_build_assign (def
, NOP_EXPR
, oprnd1
);
2106 new_pattern_def_seq (stmt_vinfo
, def_stmt
);
2109 /* Pattern detected. */
2110 if (dump_enabled_p ())
2111 dump_printf_loc (MSG_NOTE
, vect_location
,
2112 "vect_recog_vector_vector_shift_pattern: detected:\n");
2114 /* Pattern supported. Create a stmt to be used to replace the pattern. */
2115 var
= vect_recog_temp_ssa_var (TREE_TYPE (oprnd0
), NULL
);
2116 pattern_stmt
= gimple_build_assign (var
, rhs_code
, oprnd0
, def
);
2118 if (dump_enabled_p ())
2119 dump_gimple_stmt_loc (MSG_NOTE
, vect_location
, TDF_SLIM
, pattern_stmt
, 0);
2121 stmts
->safe_push (last_stmt
);
2122 return pattern_stmt
;
2125 /* Detect multiplication by constant which are postive or negatives of power 2,
2126 and convert them to shift patterns.
2128 Mult with constants that are postive power of two.
2135 Mult with constants that are negative power of two.
2140 STMTS: Contains a stmt from which the pattern search begins,
2141 i.e. the mult stmt. Convert the mult operation to LSHIFT if
2142 constant operand is a power of 2.
2144 S1': b_t = a_t << log2 (n)
2146 Convert the mult operation to LSHIFT and followed by a NEGATE
2147 if constant operand is a negative power of 2.
2148 type a_t, b_t, res_T;
2149 S2': b_t = a_t << log2 (n)
2150 S3': res_T = - (b_t)
2154 * TYPE_IN: The type of the input arguments to the pattern.
2156 * TYPE_OUT: The type of the output of this pattern.
2158 * Return value: A new stmt that will be used to replace the multiplication
2162 vect_recog_mult_pattern (vec
<gimple
*> *stmts
,
2163 tree
*type_in
, tree
*type_out
)
2165 gimple
*last_stmt
= stmts
->pop ();
2166 tree oprnd0
, oprnd1
, vectype
, itype
;
2167 gimple
*pattern_stmt
, *def_stmt
;
2169 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
2170 int power2_val
, power2_neg_val
;
2173 if (!is_gimple_assign (last_stmt
))
2176 if (gimple_assign_rhs_code (last_stmt
) != MULT_EXPR
)
2179 oprnd0
= gimple_assign_rhs1 (last_stmt
);
2180 oprnd1
= gimple_assign_rhs2 (last_stmt
);
2181 itype
= TREE_TYPE (oprnd0
);
2183 if (TREE_CODE (oprnd0
) != SSA_NAME
2184 || TREE_CODE (oprnd1
) != INTEGER_CST
2185 || !INTEGRAL_TYPE_P (itype
)
2186 || TYPE_PRECISION (itype
) != GET_MODE_PRECISION (TYPE_MODE (itype
)))
2189 vectype
= get_vectype_for_scalar_type (itype
);
2190 if (vectype
== NULL_TREE
)
2193 /* If the target can handle vectorized multiplication natively,
2194 don't attempt to optimize this. */
2195 optab
= optab_for_tree_code (MULT_EXPR
, vectype
, optab_default
);
2196 if (optab
!= unknown_optab
)
2198 machine_mode vec_mode
= TYPE_MODE (vectype
);
2199 int icode
= (int) optab_handler (optab
, vec_mode
);
2200 if (icode
!= CODE_FOR_nothing
)
2204 /* If target cannot handle vector left shift then we cannot
2205 optimize and bail out. */
2206 optab
= optab_for_tree_code (LSHIFT_EXPR
, vectype
, optab_vector
);
2208 || optab_handler (optab
, TYPE_MODE (vectype
)) == CODE_FOR_nothing
)
2211 power2_val
= wi::exact_log2 (oprnd1
);
2212 power2_neg_val
= wi::exact_log2 (wi::neg (oprnd1
));
2214 /* Handle constant operands that are postive or negative powers of 2. */
2215 if (power2_val
!= -1)
2217 shift
= build_int_cst (itype
, power2_val
);
2219 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2220 LSHIFT_EXPR
, oprnd0
, shift
);
2222 else if (power2_neg_val
!= -1)
2224 /* If the target cannot handle vector NEGATE then we cannot
2225 do the optimization. */
2226 optab
= optab_for_tree_code (NEGATE_EXPR
, vectype
, optab_vector
);
2228 || optab_handler (optab
, TYPE_MODE (vectype
)) == CODE_FOR_nothing
)
2231 shift
= build_int_cst (itype
, power2_neg_val
);
2233 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2234 LSHIFT_EXPR
, oprnd0
, shift
);
2235 new_pattern_def_seq (stmt_vinfo
, def_stmt
);
2237 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2238 NEGATE_EXPR
, gimple_assign_lhs (def_stmt
));
2243 /* Pattern detected. */
2244 if (dump_enabled_p ())
2245 dump_printf_loc (MSG_NOTE
, vect_location
,
2246 "vect_recog_mult_pattern: detected:\n");
2248 if (dump_enabled_p ())
2249 dump_gimple_stmt_loc (MSG_NOTE
, vect_location
, TDF_SLIM
,
2252 stmts
->safe_push (last_stmt
);
2254 *type_out
= vectype
;
2256 return pattern_stmt
;
2259 /* Detect a signed division by a constant that wouldn't be
2260 otherwise vectorized:
2266 where type 'type' is an integral type and N is a constant.
2268 Similarly handle modulo by a constant:
2274 * STMTS: Contains a stmt from which the pattern search begins,
2275 i.e. the division stmt. S1 is replaced by if N is a power
2276 of two constant and type is signed:
2277 S3 y_t = b_t < 0 ? N - 1 : 0;
2279 S1' a_t = x_t >> log2 (N);
2281 S4 is replaced if N is a power of two constant and
2282 type is signed by (where *_T temporaries have unsigned type):
2283 S9 y_T = b_t < 0 ? -1U : 0U;
2284 S8 z_T = y_T >> (sizeof (type_t) * CHAR_BIT - log2 (N));
2285 S7 z_t = (type) z_T;
2287 S5 x_t = w_t & (N - 1);
2288 S4' a_t = x_t - z_t;
2292 * TYPE_IN: The type of the input arguments to the pattern.
2294 * TYPE_OUT: The type of the output of this pattern.
2296 * Return value: A new stmt that will be used to replace the division
2297 S1 or modulo S4 stmt. */
2300 vect_recog_divmod_pattern (vec
<gimple
*> *stmts
,
2301 tree
*type_in
, tree
*type_out
)
2303 gimple
*last_stmt
= stmts
->pop ();
2304 tree oprnd0
, oprnd1
, vectype
, itype
, cond
;
2305 gimple
*pattern_stmt
, *def_stmt
;
2306 enum tree_code rhs_code
;
2307 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
2308 vec_info
*vinfo
= stmt_vinfo
->vinfo
;
2311 int dummy_int
, prec
;
2312 stmt_vec_info def_stmt_vinfo
;
2314 if (!is_gimple_assign (last_stmt
))
2317 rhs_code
= gimple_assign_rhs_code (last_stmt
);
2320 case TRUNC_DIV_EXPR
:
2321 case TRUNC_MOD_EXPR
:
2327 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo
))
2330 oprnd0
= gimple_assign_rhs1 (last_stmt
);
2331 oprnd1
= gimple_assign_rhs2 (last_stmt
);
2332 itype
= TREE_TYPE (oprnd0
);
2333 if (TREE_CODE (oprnd0
) != SSA_NAME
2334 || TREE_CODE (oprnd1
) != INTEGER_CST
2335 || TREE_CODE (itype
) != INTEGER_TYPE
2336 || TYPE_PRECISION (itype
) != GET_MODE_PRECISION (TYPE_MODE (itype
)))
2339 vectype
= get_vectype_for_scalar_type (itype
);
2340 if (vectype
== NULL_TREE
)
2343 /* If the target can handle vectorized division or modulo natively,
2344 don't attempt to optimize this. */
2345 optab
= optab_for_tree_code (rhs_code
, vectype
, optab_default
);
2346 if (optab
!= unknown_optab
)
2348 machine_mode vec_mode
= TYPE_MODE (vectype
);
2349 int icode
= (int) optab_handler (optab
, vec_mode
);
2350 if (icode
!= CODE_FOR_nothing
)
2354 prec
= TYPE_PRECISION (itype
);
2355 if (integer_pow2p (oprnd1
))
2357 if (TYPE_UNSIGNED (itype
) || tree_int_cst_sgn (oprnd1
) != 1)
2360 /* Pattern detected. */
2361 if (dump_enabled_p ())
2362 dump_printf_loc (MSG_NOTE
, vect_location
,
2363 "vect_recog_divmod_pattern: detected:\n");
2365 cond
= build2 (LT_EXPR
, boolean_type_node
, oprnd0
,
2366 build_int_cst (itype
, 0));
2367 if (rhs_code
== TRUNC_DIV_EXPR
)
2369 tree var
= vect_recog_temp_ssa_var (itype
, NULL
);
2372 = gimple_build_assign (var
, COND_EXPR
, cond
,
2373 fold_build2 (MINUS_EXPR
, itype
, oprnd1
,
2374 build_int_cst (itype
, 1)),
2375 build_int_cst (itype
, 0));
2376 new_pattern_def_seq (stmt_vinfo
, def_stmt
);
2377 var
= vect_recog_temp_ssa_var (itype
, NULL
);
2379 = gimple_build_assign (var
, PLUS_EXPR
, oprnd0
,
2380 gimple_assign_lhs (def_stmt
));
2381 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2383 shift
= build_int_cst (itype
, tree_log2 (oprnd1
));
2385 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2386 RSHIFT_EXPR
, var
, shift
);
2391 STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo
) = NULL
;
2392 if (compare_tree_int (oprnd1
, 2) == 0)
2394 signmask
= vect_recog_temp_ssa_var (itype
, NULL
);
2395 def_stmt
= gimple_build_assign (signmask
, COND_EXPR
, cond
,
2396 build_int_cst (itype
, 1),
2397 build_int_cst (itype
, 0));
2398 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2403 = build_nonstandard_integer_type (prec
, 1);
2404 tree vecutype
= get_vectype_for_scalar_type (utype
);
2406 = build_int_cst (utype
, GET_MODE_BITSIZE (TYPE_MODE (itype
))
2407 - tree_log2 (oprnd1
));
2408 tree var
= vect_recog_temp_ssa_var (utype
, NULL
);
2410 def_stmt
= gimple_build_assign (var
, COND_EXPR
, cond
,
2411 build_int_cst (utype
, -1),
2412 build_int_cst (utype
, 0));
2413 def_stmt_vinfo
= new_stmt_vec_info (def_stmt
, vinfo
);
2414 set_vinfo_for_stmt (def_stmt
, def_stmt_vinfo
);
2415 STMT_VINFO_VECTYPE (def_stmt_vinfo
) = vecutype
;
2416 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2417 var
= vect_recog_temp_ssa_var (utype
, NULL
);
2418 def_stmt
= gimple_build_assign (var
, RSHIFT_EXPR
,
2419 gimple_assign_lhs (def_stmt
),
2421 def_stmt_vinfo
= new_stmt_vec_info (def_stmt
, vinfo
);
2422 set_vinfo_for_stmt (def_stmt
, def_stmt_vinfo
);
2423 STMT_VINFO_VECTYPE (def_stmt_vinfo
) = vecutype
;
2424 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2425 signmask
= vect_recog_temp_ssa_var (itype
, NULL
);
2427 = gimple_build_assign (signmask
, NOP_EXPR
, var
);
2428 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2431 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2432 PLUS_EXPR
, oprnd0
, signmask
);
2433 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2435 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2436 BIT_AND_EXPR
, gimple_assign_lhs (def_stmt
),
2437 fold_build2 (MINUS_EXPR
, itype
, oprnd1
,
2438 build_int_cst (itype
, 1)));
2439 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2442 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2443 MINUS_EXPR
, gimple_assign_lhs (def_stmt
),
2447 if (dump_enabled_p ())
2448 dump_gimple_stmt_loc (MSG_NOTE
, vect_location
, TDF_SLIM
, pattern_stmt
,
2451 stmts
->safe_push (last_stmt
);
2454 *type_out
= vectype
;
2455 return pattern_stmt
;
2458 if (prec
> HOST_BITS_PER_WIDE_INT
2459 || integer_zerop (oprnd1
))
2462 if (!can_mult_highpart_p (TYPE_MODE (vectype
), TYPE_UNSIGNED (itype
)))
2465 STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo
) = NULL
;
2467 if (TYPE_UNSIGNED (itype
))
2469 unsigned HOST_WIDE_INT mh
, ml
;
2470 int pre_shift
, post_shift
;
2471 unsigned HOST_WIDE_INT d
= (TREE_INT_CST_LOW (oprnd1
)
2472 & GET_MODE_MASK (TYPE_MODE (itype
)));
2473 tree t1
, t2
, t3
, t4
;
2475 if (d
>= ((unsigned HOST_WIDE_INT
) 1 << (prec
- 1)))
2476 /* FIXME: Can transform this into oprnd0 >= oprnd1 ? 1 : 0. */
2479 /* Find a suitable multiplier and right shift count
2480 instead of multiplying with D. */
2481 mh
= choose_multiplier (d
, prec
, prec
, &ml
, &post_shift
, &dummy_int
);
2483 /* If the suggested multiplier is more than SIZE bits, we can do better
2484 for even divisors, using an initial right shift. */
2485 if (mh
!= 0 && (d
& 1) == 0)
2487 pre_shift
= floor_log2 (d
& -d
);
2488 mh
= choose_multiplier (d
>> pre_shift
, prec
, prec
- pre_shift
,
2489 &ml
, &post_shift
, &dummy_int
);
2497 if (post_shift
- 1 >= prec
)
2500 /* t1 = oprnd0 h* ml;
2504 q = t4 >> (post_shift - 1); */
2505 t1
= vect_recog_temp_ssa_var (itype
, NULL
);
2506 def_stmt
= gimple_build_assign (t1
, MULT_HIGHPART_EXPR
, oprnd0
,
2507 build_int_cst (itype
, ml
));
2508 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2510 t2
= vect_recog_temp_ssa_var (itype
, NULL
);
2512 = gimple_build_assign (t2
, MINUS_EXPR
, oprnd0
, t1
);
2513 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2515 t3
= vect_recog_temp_ssa_var (itype
, NULL
);
2517 = gimple_build_assign (t3
, RSHIFT_EXPR
, t2
, integer_one_node
);
2518 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2520 t4
= vect_recog_temp_ssa_var (itype
, NULL
);
2522 = gimple_build_assign (t4
, PLUS_EXPR
, t1
, t3
);
2524 if (post_shift
!= 1)
2526 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2528 q
= vect_recog_temp_ssa_var (itype
, NULL
);
2530 = gimple_build_assign (q
, RSHIFT_EXPR
, t4
,
2531 build_int_cst (itype
, post_shift
- 1));
2536 pattern_stmt
= def_stmt
;
2541 if (pre_shift
>= prec
|| post_shift
>= prec
)
2544 /* t1 = oprnd0 >> pre_shift;
2546 q = t2 >> post_shift; */
2549 t1
= vect_recog_temp_ssa_var (itype
, NULL
);
2551 = gimple_build_assign (t1
, RSHIFT_EXPR
, oprnd0
,
2552 build_int_cst (NULL
, pre_shift
));
2553 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2558 t2
= vect_recog_temp_ssa_var (itype
, NULL
);
2559 def_stmt
= gimple_build_assign (t2
, MULT_HIGHPART_EXPR
, t1
,
2560 build_int_cst (itype
, ml
));
2564 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2566 q
= vect_recog_temp_ssa_var (itype
, NULL
);
2568 = gimple_build_assign (q
, RSHIFT_EXPR
, t2
,
2569 build_int_cst (itype
, post_shift
));
2574 pattern_stmt
= def_stmt
;
2579 unsigned HOST_WIDE_INT ml
;
2581 HOST_WIDE_INT d
= TREE_INT_CST_LOW (oprnd1
);
2582 unsigned HOST_WIDE_INT abs_d
;
2584 tree t1
, t2
, t3
, t4
;
2586 /* Give up for -1. */
2590 /* Since d might be INT_MIN, we have to cast to
2591 unsigned HOST_WIDE_INT before negating to avoid
2592 undefined signed overflow. */
2594 ? (unsigned HOST_WIDE_INT
) d
2595 : - (unsigned HOST_WIDE_INT
) d
);
2597 /* n rem d = n rem -d */
2598 if (rhs_code
== TRUNC_MOD_EXPR
&& d
< 0)
2601 oprnd1
= build_int_cst (itype
, abs_d
);
2603 else if (HOST_BITS_PER_WIDE_INT
>= prec
2604 && abs_d
== (unsigned HOST_WIDE_INT
) 1 << (prec
- 1))
2605 /* This case is not handled correctly below. */
2608 choose_multiplier (abs_d
, prec
, prec
- 1, &ml
, &post_shift
, &dummy_int
);
2609 if (ml
>= (unsigned HOST_WIDE_INT
) 1 << (prec
- 1))
2612 ml
|= (~(unsigned HOST_WIDE_INT
) 0) << (prec
- 1);
2614 if (post_shift
>= prec
)
2617 /* t1 = oprnd0 h* ml; */
2618 t1
= vect_recog_temp_ssa_var (itype
, NULL
);
2619 def_stmt
= gimple_build_assign (t1
, MULT_HIGHPART_EXPR
, oprnd0
,
2620 build_int_cst (itype
, ml
));
2624 /* t2 = t1 + oprnd0; */
2625 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2626 t2
= vect_recog_temp_ssa_var (itype
, NULL
);
2627 def_stmt
= gimple_build_assign (t2
, PLUS_EXPR
, t1
, oprnd0
);
2634 /* t3 = t2 >> post_shift; */
2635 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2636 t3
= vect_recog_temp_ssa_var (itype
, NULL
);
2637 def_stmt
= gimple_build_assign (t3
, RSHIFT_EXPR
, t2
,
2638 build_int_cst (itype
, post_shift
));
2643 wide_int oprnd0_min
, oprnd0_max
;
2645 if (get_range_info (oprnd0
, &oprnd0_min
, &oprnd0_max
) == VR_RANGE
)
2647 if (!wi::neg_p (oprnd0_min
, TYPE_SIGN (itype
)))
2649 else if (wi::neg_p (oprnd0_max
, TYPE_SIGN (itype
)))
2653 if (msb
== 0 && d
>= 0)
2657 pattern_stmt
= def_stmt
;
2661 /* t4 = oprnd0 >> (prec - 1);
2662 or if we know from VRP that oprnd0 >= 0
2664 or if we know from VRP that oprnd0 < 0
2666 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2667 t4
= vect_recog_temp_ssa_var (itype
, NULL
);
2669 def_stmt
= gimple_build_assign (t4
, INTEGER_CST
,
2670 build_int_cst (itype
, msb
));
2672 def_stmt
= gimple_build_assign (t4
, RSHIFT_EXPR
, oprnd0
,
2673 build_int_cst (itype
, prec
- 1));
2674 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2676 /* q = t3 - t4; or q = t4 - t3; */
2677 q
= vect_recog_temp_ssa_var (itype
, NULL
);
2678 pattern_stmt
= gimple_build_assign (q
, MINUS_EXPR
, d
< 0 ? t4
: t3
,
2683 if (rhs_code
== TRUNC_MOD_EXPR
)
2687 /* We divided. Now finish by:
2690 append_pattern_def_seq (stmt_vinfo
, pattern_stmt
);
2692 t1
= vect_recog_temp_ssa_var (itype
, NULL
);
2693 def_stmt
= gimple_build_assign (t1
, MULT_EXPR
, q
, oprnd1
);
2694 append_pattern_def_seq (stmt_vinfo
, def_stmt
);
2696 r
= vect_recog_temp_ssa_var (itype
, NULL
);
2697 pattern_stmt
= gimple_build_assign (r
, MINUS_EXPR
, oprnd0
, t1
);
2700 /* Pattern detected. */
2701 if (dump_enabled_p ())
2703 dump_printf_loc (MSG_NOTE
, vect_location
,
2704 "vect_recog_divmod_pattern: detected: ");
2705 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
2706 dump_printf (MSG_NOTE
, "\n");
2709 stmts
->safe_push (last_stmt
);
2712 *type_out
= vectype
;
2713 return pattern_stmt
;
2716 /* Function vect_recog_mixed_size_cond_pattern
2718 Try to find the following pattern:
2723 S1 a_T = x_t CMP y_t ? b_T : c_T;
2725 where type 'TYPE' is an integral type which has different size
2726 from 'type'. b_T and c_T are either constants (and if 'TYPE' is wider
2727 than 'type', the constants need to fit into an integer type
2728 with the same width as 'type') or results of conversion from 'type'.
2732 * LAST_STMT: A stmt from which the pattern search begins.
2736 * TYPE_IN: The type of the input arguments to the pattern.
2738 * TYPE_OUT: The type of the output of this pattern.
2740 * Return value: A new stmt that will be used to replace the pattern.
2741 Additionally a def_stmt is added.
2743 a_it = x_t CMP y_t ? b_it : c_it;
2744 a_T = (TYPE) a_it; */
2747 vect_recog_mixed_size_cond_pattern (vec
<gimple
*> *stmts
, tree
*type_in
,
2750 gimple
*last_stmt
= (*stmts
)[0];
2751 tree cond_expr
, then_clause
, else_clause
;
2752 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
), def_stmt_info
;
2753 tree type
, vectype
, comp_vectype
, itype
= NULL_TREE
, vecitype
;
2754 gimple
*pattern_stmt
, *def_stmt
;
2755 vec_info
*vinfo
= stmt_vinfo
->vinfo
;
2756 tree orig_type0
= NULL_TREE
, orig_type1
= NULL_TREE
;
2757 gimple
*def_stmt0
= NULL
, *def_stmt1
= NULL
;
2759 tree comp_scalar_type
;
2761 if (!is_gimple_assign (last_stmt
)
2762 || gimple_assign_rhs_code (last_stmt
) != COND_EXPR
2763 || STMT_VINFO_DEF_TYPE (stmt_vinfo
) != vect_internal_def
)
2766 cond_expr
= gimple_assign_rhs1 (last_stmt
);
2767 then_clause
= gimple_assign_rhs2 (last_stmt
);
2768 else_clause
= gimple_assign_rhs3 (last_stmt
);
2770 if (!COMPARISON_CLASS_P (cond_expr
))
2773 comp_scalar_type
= TREE_TYPE (TREE_OPERAND (cond_expr
, 0));
2774 comp_vectype
= get_vectype_for_scalar_type (comp_scalar_type
);
2775 if (comp_vectype
== NULL_TREE
)
2778 type
= gimple_expr_type (last_stmt
);
2779 if (types_compatible_p (type
, comp_scalar_type
)
2780 || ((TREE_CODE (then_clause
) != INTEGER_CST
2781 || TREE_CODE (else_clause
) != INTEGER_CST
)
2782 && !INTEGRAL_TYPE_P (comp_scalar_type
))
2783 || !INTEGRAL_TYPE_P (type
))
2786 if ((TREE_CODE (then_clause
) != INTEGER_CST
2787 && !type_conversion_p (then_clause
, last_stmt
, false, &orig_type0
,
2788 &def_stmt0
, &promotion
))
2789 || (TREE_CODE (else_clause
) != INTEGER_CST
2790 && !type_conversion_p (else_clause
, last_stmt
, false, &orig_type1
,
2791 &def_stmt1
, &promotion
)))
2794 if (orig_type0
&& orig_type1
2795 && !types_compatible_p (orig_type0
, orig_type1
))
2800 if (!types_compatible_p (orig_type0
, comp_scalar_type
))
2802 then_clause
= gimple_assign_rhs1 (def_stmt0
);
2808 if (!types_compatible_p (orig_type1
, comp_scalar_type
))
2810 else_clause
= gimple_assign_rhs1 (def_stmt1
);
2815 HOST_WIDE_INT cmp_mode_size
2816 = GET_MODE_UNIT_BITSIZE (TYPE_MODE (comp_vectype
));
2818 if (GET_MODE_BITSIZE (TYPE_MODE (type
)) == cmp_mode_size
)
2821 vectype
= get_vectype_for_scalar_type (type
);
2822 if (vectype
== NULL_TREE
)
2825 if (expand_vec_cond_expr_p (vectype
, comp_vectype
))
2828 if (itype
== NULL_TREE
)
2829 itype
= build_nonstandard_integer_type (cmp_mode_size
,
2830 TYPE_UNSIGNED (type
));
2832 if (itype
== NULL_TREE
2833 || GET_MODE_BITSIZE (TYPE_MODE (itype
)) != cmp_mode_size
)
2836 vecitype
= get_vectype_for_scalar_type (itype
);
2837 if (vecitype
== NULL_TREE
)
2840 if (!expand_vec_cond_expr_p (vecitype
, comp_vectype
))
2843 if (GET_MODE_BITSIZE (TYPE_MODE (type
)) > cmp_mode_size
)
2845 if ((TREE_CODE (then_clause
) == INTEGER_CST
2846 && !int_fits_type_p (then_clause
, itype
))
2847 || (TREE_CODE (else_clause
) == INTEGER_CST
2848 && !int_fits_type_p (else_clause
, itype
)))
2852 def_stmt
= gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
2853 COND_EXPR
, unshare_expr (cond_expr
),
2854 fold_convert (itype
, then_clause
),
2855 fold_convert (itype
, else_clause
));
2856 pattern_stmt
= gimple_build_assign (vect_recog_temp_ssa_var (type
, NULL
),
2857 NOP_EXPR
, gimple_assign_lhs (def_stmt
));
2859 new_pattern_def_seq (stmt_vinfo
, def_stmt
);
2860 def_stmt_info
= new_stmt_vec_info (def_stmt
, vinfo
);
2861 set_vinfo_for_stmt (def_stmt
, def_stmt_info
);
2862 STMT_VINFO_VECTYPE (def_stmt_info
) = vecitype
;
2863 *type_in
= vecitype
;
2864 *type_out
= vectype
;
2866 if (dump_enabled_p ())
2867 dump_printf_loc (MSG_NOTE
, vect_location
,
2868 "vect_recog_mixed_size_cond_pattern: detected:\n");
2870 return pattern_stmt
;
2874 /* Helper function of vect_recog_bool_pattern. Called recursively, return
2875 true if bool VAR can and should be optimized that way. Assume it shouldn't
2876 in case it's a result of a comparison which can be directly vectorized into
2877 a vector comparison. */
2880 check_bool_pattern (tree var
, vec_info
*vinfo
)
2883 enum vect_def_type dt
;
2885 enum tree_code rhs_code
;
2887 if (!vect_is_simple_use (var
, vinfo
, &def_stmt
, &dt
))
2890 if (dt
!= vect_internal_def
)
2893 if (!is_gimple_assign (def_stmt
))
2896 if (!has_single_use (var
))
2899 rhs1
= gimple_assign_rhs1 (def_stmt
);
2900 rhs_code
= gimple_assign_rhs_code (def_stmt
);
2904 return check_bool_pattern (rhs1
, vinfo
);
2907 if ((TYPE_PRECISION (TREE_TYPE (rhs1
)) != 1
2908 || !TYPE_UNSIGNED (TREE_TYPE (rhs1
)))
2909 && TREE_CODE (TREE_TYPE (rhs1
)) != BOOLEAN_TYPE
)
2911 return check_bool_pattern (rhs1
, vinfo
);
2914 return check_bool_pattern (rhs1
, vinfo
);
2919 if (!check_bool_pattern (rhs1
, vinfo
))
2921 return check_bool_pattern (gimple_assign_rhs2 (def_stmt
), vinfo
);
2924 if (TREE_CODE_CLASS (rhs_code
) == tcc_comparison
)
2926 tree vecitype
, comp_vectype
, mask_type
;
2928 /* If the comparison can throw, then is_gimple_condexpr will be
2929 false and we can't make a COND_EXPR/VEC_COND_EXPR out of it. */
2930 if (stmt_could_throw_p (def_stmt
))
2933 comp_vectype
= get_vectype_for_scalar_type (TREE_TYPE (rhs1
));
2934 if (comp_vectype
== NULL_TREE
)
2937 mask_type
= get_mask_type_for_scalar_type (TREE_TYPE (rhs1
));
2939 && expand_vec_cmp_expr_p (comp_vectype
, mask_type
))
2942 if (TREE_CODE (TREE_TYPE (rhs1
)) != INTEGER_TYPE
)
2944 machine_mode mode
= TYPE_MODE (TREE_TYPE (rhs1
));
2946 = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode
), 1);
2947 vecitype
= get_vectype_for_scalar_type (itype
);
2948 if (vecitype
== NULL_TREE
)
2952 vecitype
= comp_vectype
;
2953 return expand_vec_cond_expr_p (vecitype
, comp_vectype
);
2960 /* Helper function of adjust_bool_pattern. Add a cast to TYPE to a previous
2961 stmt (SSA_NAME_DEF_STMT of VAR) by moving the COND_EXPR from RELATED_STMT
2962 to PATTERN_DEF_SEQ and adding a cast as RELATED_STMT. */
2965 adjust_bool_pattern_cast (tree type
, tree var
)
2967 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (SSA_NAME_DEF_STMT (var
));
2968 gimple
*cast_stmt
, *pattern_stmt
;
2970 gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo
));
2971 pattern_stmt
= STMT_VINFO_RELATED_STMT (stmt_vinfo
);
2972 new_pattern_def_seq (stmt_vinfo
, pattern_stmt
);
2973 cast_stmt
= gimple_build_assign (vect_recog_temp_ssa_var (type
, NULL
),
2974 NOP_EXPR
, gimple_assign_lhs (pattern_stmt
));
2975 STMT_VINFO_RELATED_STMT (stmt_vinfo
) = cast_stmt
;
2976 return gimple_assign_lhs (cast_stmt
);
2980 /* Helper function of vect_recog_bool_pattern. Do the actual transformations,
2981 recursively. VAR is an SSA_NAME that should be transformed from bool
2982 to a wider integer type, OUT_TYPE is the desired final integer type of
2983 the whole pattern, TRUEVAL should be NULL unless optimizing
2984 BIT_AND_EXPR into a COND_EXPR with one integer from one of the operands
2985 in the then_clause, STMTS is where statements with added pattern stmts
2986 should be pushed to. */
2989 adjust_bool_pattern (tree var
, tree out_type
, tree trueval
,
2990 vec
<gimple
*> *stmts
)
2992 gimple
*stmt
= SSA_NAME_DEF_STMT (var
);
2993 enum tree_code rhs_code
, def_rhs_code
;
2994 tree itype
, cond_expr
, rhs1
, rhs2
, irhs1
, irhs2
;
2996 gimple
*pattern_stmt
, *def_stmt
;
2998 rhs1
= gimple_assign_rhs1 (stmt
);
2999 rhs2
= gimple_assign_rhs2 (stmt
);
3000 rhs_code
= gimple_assign_rhs_code (stmt
);
3001 loc
= gimple_location (stmt
);
3006 irhs1
= adjust_bool_pattern (rhs1
, out_type
, NULL_TREE
, stmts
);
3007 itype
= TREE_TYPE (irhs1
);
3009 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
3014 irhs1
= adjust_bool_pattern (rhs1
, out_type
, NULL_TREE
, stmts
);
3015 itype
= TREE_TYPE (irhs1
);
3017 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
3018 BIT_XOR_EXPR
, irhs1
, build_int_cst (itype
, 1));
3022 /* Try to optimize x = y & (a < b ? 1 : 0); into
3023 x = (a < b ? y : 0);
3029 S1 a_b = x1 CMP1 y1;
3030 S2 b_b = x2 CMP2 y2;
3032 S4 d_T = (TYPE) c_b;
3034 we would normally emit:
3036 S1' a_T = x1 CMP1 y1 ? 1 : 0;
3037 S2' b_T = x2 CMP2 y2 ? 1 : 0;
3038 S3' c_T = a_T & b_T;
3041 but we can save one stmt by using the
3042 result of one of the COND_EXPRs in the other COND_EXPR and leave
3043 BIT_AND_EXPR stmt out:
3045 S1' a_T = x1 CMP1 y1 ? 1 : 0;
3046 S3' c_T = x2 CMP2 y2 ? a_T : 0;
3049 At least when VEC_COND_EXPR is implemented using masks
3050 cond ? 1 : 0 is as expensive as cond ? var : 0, in both cases it
3051 computes the comparison masks and ands it, in one case with
3052 all ones vector, in the other case with a vector register.
3053 Don't do this for BIT_IOR_EXPR, because cond ? 1 : var; is
3054 often more expensive. */
3055 def_stmt
= SSA_NAME_DEF_STMT (rhs2
);
3056 def_rhs_code
= gimple_assign_rhs_code (def_stmt
);
3057 if (TREE_CODE_CLASS (def_rhs_code
) == tcc_comparison
)
3059 tree def_rhs1
= gimple_assign_rhs1 (def_stmt
);
3060 irhs1
= adjust_bool_pattern (rhs1
, out_type
, NULL_TREE
, stmts
);
3061 if (TYPE_PRECISION (TREE_TYPE (irhs1
))
3062 == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1
))))
3065 stmt_vec_info stmt_def_vinfo
= vinfo_for_stmt (def_stmt
);
3066 irhs2
= adjust_bool_pattern (rhs2
, out_type
, irhs1
, stmts
);
3067 tstmt
= stmts
->pop ();
3068 gcc_assert (tstmt
== def_stmt
);
3069 stmts
->quick_push (stmt
);
3070 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt
))
3071 = STMT_VINFO_RELATED_STMT (stmt_def_vinfo
);
3072 gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_def_vinfo
));
3073 STMT_VINFO_RELATED_STMT (stmt_def_vinfo
) = NULL
;
3077 irhs2
= adjust_bool_pattern (rhs2
, out_type
, NULL_TREE
, stmts
);
3080 def_stmt
= SSA_NAME_DEF_STMT (rhs1
);
3081 def_rhs_code
= gimple_assign_rhs_code (def_stmt
);
3082 if (TREE_CODE_CLASS (def_rhs_code
) == tcc_comparison
)
3084 tree def_rhs1
= gimple_assign_rhs1 (def_stmt
);
3085 irhs2
= adjust_bool_pattern (rhs2
, out_type
, NULL_TREE
, stmts
);
3086 if (TYPE_PRECISION (TREE_TYPE (irhs2
))
3087 == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1
))))
3090 stmt_vec_info stmt_def_vinfo
= vinfo_for_stmt (def_stmt
);
3091 irhs1
= adjust_bool_pattern (rhs1
, out_type
, irhs2
, stmts
);
3092 tstmt
= stmts
->pop ();
3093 gcc_assert (tstmt
== def_stmt
);
3094 stmts
->quick_push (stmt
);
3095 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt
))
3096 = STMT_VINFO_RELATED_STMT (stmt_def_vinfo
);
3097 gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_def_vinfo
));
3098 STMT_VINFO_RELATED_STMT (stmt_def_vinfo
) = NULL
;
3102 irhs1
= adjust_bool_pattern (rhs1
, out_type
, NULL_TREE
, stmts
);
3108 irhs1
= adjust_bool_pattern (rhs1
, out_type
, NULL_TREE
, stmts
);
3109 irhs2
= adjust_bool_pattern (rhs2
, out_type
, NULL_TREE
, stmts
);
3111 if (TYPE_PRECISION (TREE_TYPE (irhs1
))
3112 != TYPE_PRECISION (TREE_TYPE (irhs2
)))
3114 int prec1
= TYPE_PRECISION (TREE_TYPE (irhs1
));
3115 int prec2
= TYPE_PRECISION (TREE_TYPE (irhs2
));
3116 int out_prec
= TYPE_PRECISION (out_type
);
3117 if (absu_hwi (out_prec
- prec1
) < absu_hwi (out_prec
- prec2
))
3118 irhs2
= adjust_bool_pattern_cast (TREE_TYPE (irhs1
), rhs2
);
3119 else if (absu_hwi (out_prec
- prec1
) > absu_hwi (out_prec
- prec2
))
3120 irhs1
= adjust_bool_pattern_cast (TREE_TYPE (irhs2
), rhs1
);
3123 irhs1
= adjust_bool_pattern_cast (out_type
, rhs1
);
3124 irhs2
= adjust_bool_pattern_cast (out_type
, rhs2
);
3127 itype
= TREE_TYPE (irhs1
);
3129 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
3130 rhs_code
, irhs1
, irhs2
);
3134 gcc_assert (TREE_CODE_CLASS (rhs_code
) == tcc_comparison
);
3135 if (TREE_CODE (TREE_TYPE (rhs1
)) != INTEGER_TYPE
3136 || !TYPE_UNSIGNED (TREE_TYPE (rhs1
))
3137 || (TYPE_PRECISION (TREE_TYPE (rhs1
))
3138 != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1
)))))
3140 machine_mode mode
= TYPE_MODE (TREE_TYPE (rhs1
));
3142 = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode
), 1);
3145 itype
= TREE_TYPE (rhs1
);
3146 cond_expr
= build2_loc (loc
, rhs_code
, itype
, rhs1
, rhs2
);
3147 if (trueval
== NULL_TREE
)
3148 trueval
= build_int_cst (itype
, 1);
3150 gcc_checking_assert (useless_type_conversion_p (itype
,
3151 TREE_TYPE (trueval
)));
3153 = gimple_build_assign (vect_recog_temp_ssa_var (itype
, NULL
),
3154 COND_EXPR
, cond_expr
, trueval
,
3155 build_int_cst (itype
, 0));
3159 stmts
->safe_push (stmt
);
3160 gimple_set_location (pattern_stmt
, loc
);
3161 STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt
)) = pattern_stmt
;
3162 return gimple_assign_lhs (pattern_stmt
);
3166 /* Return the proper type for converting bool VAR into
3167 an integer value or NULL_TREE if no such type exists.
3168 The type is chosen so that converted value has the
3169 same number of elements as VAR's vector type. */
3172 search_type_for_mask (tree var
, vec_info
*vinfo
)
3175 enum vect_def_type dt
;
3177 enum tree_code rhs_code
;
3178 tree res
= NULL_TREE
, res2
;
3180 if (TREE_CODE (var
) != SSA_NAME
)
3183 if ((TYPE_PRECISION (TREE_TYPE (var
)) != 1
3184 || !TYPE_UNSIGNED (TREE_TYPE (var
)))
3185 && TREE_CODE (TREE_TYPE (var
)) != BOOLEAN_TYPE
)
3188 if (!vect_is_simple_use (var
, vinfo
, &def_stmt
, &dt
))
3191 if (dt
!= vect_internal_def
)
3194 if (!is_gimple_assign (def_stmt
))
3197 rhs_code
= gimple_assign_rhs_code (def_stmt
);
3198 rhs1
= gimple_assign_rhs1 (def_stmt
);
3205 res
= search_type_for_mask (rhs1
, vinfo
);
3211 res
= search_type_for_mask (rhs1
, vinfo
);
3212 res2
= search_type_for_mask (gimple_assign_rhs2 (def_stmt
), vinfo
);
3213 if (!res
|| (res2
&& TYPE_PRECISION (res
) > TYPE_PRECISION (res2
)))
3218 if (TREE_CODE_CLASS (rhs_code
) == tcc_comparison
)
3220 tree comp_vectype
, mask_type
;
3222 comp_vectype
= get_vectype_for_scalar_type (TREE_TYPE (rhs1
));
3223 if (comp_vectype
== NULL_TREE
)
3226 mask_type
= get_mask_type_for_scalar_type (TREE_TYPE (rhs1
));
3228 || !expand_vec_cmp_expr_p (comp_vectype
, mask_type
))
3231 if (TREE_CODE (TREE_TYPE (rhs1
)) != INTEGER_TYPE
3232 || !TYPE_UNSIGNED (TREE_TYPE (rhs1
)))
3234 machine_mode mode
= TYPE_MODE (TREE_TYPE (rhs1
));
3235 res
= build_nonstandard_integer_type (GET_MODE_BITSIZE (mode
), 1);
3238 res
= TREE_TYPE (rhs1
);
3246 /* Function vect_recog_bool_pattern
3248 Try to find pattern like following:
3250 bool a_b, b_b, c_b, d_b, e_b;
3253 S1 a_b = x1 CMP1 y1;
3254 S2 b_b = x2 CMP2 y2;
3256 S4 d_b = x3 CMP3 y3;
3258 S6 f_T = (TYPE) e_b;
3260 where type 'TYPE' is an integral type. Or a similar pattern
3263 S6 f_Y = e_b ? r_Y : s_Y;
3265 as results from if-conversion of a complex condition.
3269 * LAST_STMT: A stmt at the end from which the pattern
3270 search begins, i.e. cast of a bool to
3275 * TYPE_IN: The type of the input arguments to the pattern.
3277 * TYPE_OUT: The type of the output of this pattern.
3279 * Return value: A new stmt that will be used to replace the pattern.
3281 Assuming size of TYPE is the same as size of all comparisons
3282 (otherwise some casts would be added where needed), the above
3283 sequence we create related pattern stmts:
3284 S1' a_T = x1 CMP1 y1 ? 1 : 0;
3285 S3' c_T = x2 CMP2 y2 ? a_T : 0;
3286 S4' d_T = x3 CMP3 y3 ? 1 : 0;
3287 S5' e_T = c_T | d_T;
3290 Instead of the above S3' we could emit:
3291 S2' b_T = x2 CMP2 y2 ? 1 : 0;
3292 S3' c_T = a_T | b_T;
3293 but the above is more efficient. */
3296 vect_recog_bool_pattern (vec
<gimple
*> *stmts
, tree
*type_in
,
3299 gimple
*last_stmt
= stmts
->pop ();
3300 enum tree_code rhs_code
;
3301 tree var
, lhs
, rhs
, vectype
;
3302 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
3303 stmt_vec_info new_stmt_info
;
3304 vec_info
*vinfo
= stmt_vinfo
->vinfo
;
3305 gimple
*pattern_stmt
;
3307 if (!is_gimple_assign (last_stmt
))
3310 var
= gimple_assign_rhs1 (last_stmt
);
3311 lhs
= gimple_assign_lhs (last_stmt
);
3313 if ((TYPE_PRECISION (TREE_TYPE (var
)) != 1
3314 || !TYPE_UNSIGNED (TREE_TYPE (var
)))
3315 && TREE_CODE (TREE_TYPE (var
)) != BOOLEAN_TYPE
)
3318 rhs_code
= gimple_assign_rhs_code (last_stmt
);
3319 if (CONVERT_EXPR_CODE_P (rhs_code
))
3321 if (TREE_CODE (TREE_TYPE (lhs
)) != INTEGER_TYPE
3322 || TYPE_PRECISION (TREE_TYPE (lhs
)) == 1)
3324 vectype
= get_vectype_for_scalar_type (TREE_TYPE (lhs
));
3325 if (vectype
== NULL_TREE
)
3328 if (check_bool_pattern (var
, vinfo
))
3330 rhs
= adjust_bool_pattern (var
, TREE_TYPE (lhs
), NULL_TREE
, stmts
);
3331 lhs
= vect_recog_temp_ssa_var (TREE_TYPE (lhs
), NULL
);
3332 if (useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
3333 pattern_stmt
= gimple_build_assign (lhs
, SSA_NAME
, rhs
);
3336 = gimple_build_assign (lhs
, NOP_EXPR
, rhs
);
3340 tree type
= search_type_for_mask (var
, vinfo
);
3341 tree cst0
, cst1
, tmp
;
3346 /* We may directly use cond with narrowed type to avoid
3347 multiple cond exprs with following result packing and
3348 perform single cond with packed mask instead. In case
3349 of widening we better make cond first and then extract
3351 if (TYPE_MODE (type
) == TYPE_MODE (TREE_TYPE (lhs
)))
3352 type
= TREE_TYPE (lhs
);
3354 cst0
= build_int_cst (type
, 0);
3355 cst1
= build_int_cst (type
, 1);
3356 tmp
= vect_recog_temp_ssa_var (type
, NULL
);
3357 pattern_stmt
= gimple_build_assign (tmp
, COND_EXPR
, var
, cst1
, cst0
);
3359 if (!useless_type_conversion_p (type
, TREE_TYPE (lhs
)))
3361 tree new_vectype
= get_vectype_for_scalar_type (type
);
3362 new_stmt_info
= new_stmt_vec_info (pattern_stmt
, vinfo
);
3363 set_vinfo_for_stmt (pattern_stmt
, new_stmt_info
);
3364 STMT_VINFO_VECTYPE (new_stmt_info
) = new_vectype
;
3365 new_pattern_def_seq (stmt_vinfo
, pattern_stmt
);
3367 lhs
= vect_recog_temp_ssa_var (TREE_TYPE (lhs
), NULL
);
3368 pattern_stmt
= gimple_build_assign (lhs
, CONVERT_EXPR
, tmp
);
3372 *type_out
= vectype
;
3374 stmts
->safe_push (last_stmt
);
3375 if (dump_enabled_p ())
3376 dump_printf_loc (MSG_NOTE
, vect_location
,
3377 "vect_recog_bool_pattern: detected:\n");
3379 return pattern_stmt
;
3381 else if (rhs_code
== COND_EXPR
3382 && TREE_CODE (var
) == SSA_NAME
)
3384 vectype
= get_vectype_for_scalar_type (TREE_TYPE (lhs
));
3385 if (vectype
== NULL_TREE
)
3388 /* Build a scalar type for the boolean result that when
3389 vectorized matches the vector type of the result in
3390 size and number of elements. */
3392 = wi::udiv_trunc (TYPE_SIZE (vectype
),
3393 TYPE_VECTOR_SUBPARTS (vectype
)).to_uhwi ();
3395 = build_nonstandard_integer_type (prec
,
3396 TYPE_UNSIGNED (TREE_TYPE (var
)));
3397 if (get_vectype_for_scalar_type (type
) == NULL_TREE
)
3400 if (!check_bool_pattern (var
, vinfo
))
3403 rhs
= adjust_bool_pattern (var
, type
, NULL_TREE
, stmts
);
3405 lhs
= vect_recog_temp_ssa_var (TREE_TYPE (lhs
), NULL
);
3407 = gimple_build_assign (lhs
, COND_EXPR
,
3408 build2 (NE_EXPR
, boolean_type_node
,
3409 rhs
, build_int_cst (type
, 0)),
3410 gimple_assign_rhs2 (last_stmt
),
3411 gimple_assign_rhs3 (last_stmt
));
3412 *type_out
= vectype
;
3414 stmts
->safe_push (last_stmt
);
3415 if (dump_enabled_p ())
3416 dump_printf_loc (MSG_NOTE
, vect_location
,
3417 "vect_recog_bool_pattern: detected:\n");
3419 return pattern_stmt
;
3421 else if (rhs_code
== SSA_NAME
3422 && STMT_VINFO_DATA_REF (stmt_vinfo
))
3424 stmt_vec_info pattern_stmt_info
;
3425 vectype
= STMT_VINFO_VECTYPE (stmt_vinfo
);
3426 gcc_assert (vectype
!= NULL_TREE
);
3427 if (!VECTOR_MODE_P (TYPE_MODE (vectype
)))
3430 if (check_bool_pattern (var
, vinfo
))
3431 rhs
= adjust_bool_pattern (var
, TREE_TYPE (vectype
),
3435 tree type
= search_type_for_mask (var
, vinfo
);
3436 tree cst0
, cst1
, new_vectype
;
3441 if (TYPE_MODE (type
) == TYPE_MODE (TREE_TYPE (vectype
)))
3442 type
= TREE_TYPE (vectype
);
3444 cst0
= build_int_cst (type
, 0);
3445 cst1
= build_int_cst (type
, 1);
3446 new_vectype
= get_vectype_for_scalar_type (type
);
3448 rhs
= vect_recog_temp_ssa_var (type
, NULL
);
3449 pattern_stmt
= gimple_build_assign (rhs
, COND_EXPR
, var
, cst1
, cst0
);
3451 pattern_stmt_info
= new_stmt_vec_info (pattern_stmt
, vinfo
);
3452 set_vinfo_for_stmt (pattern_stmt
, pattern_stmt_info
);
3453 STMT_VINFO_VECTYPE (pattern_stmt_info
) = new_vectype
;
3454 append_pattern_def_seq (stmt_vinfo
, pattern_stmt
);
3457 lhs
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (vectype
), lhs
);
3458 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
3460 tree rhs2
= vect_recog_temp_ssa_var (TREE_TYPE (lhs
), NULL
);
3461 gimple
*cast_stmt
= gimple_build_assign (rhs2
, NOP_EXPR
, rhs
);
3462 append_pattern_def_seq (stmt_vinfo
, cast_stmt
);
3465 pattern_stmt
= gimple_build_assign (lhs
, SSA_NAME
, rhs
);
3466 pattern_stmt_info
= new_stmt_vec_info (pattern_stmt
, vinfo
);
3467 set_vinfo_for_stmt (pattern_stmt
, pattern_stmt_info
);
3468 STMT_VINFO_DATA_REF (pattern_stmt_info
)
3469 = STMT_VINFO_DATA_REF (stmt_vinfo
);
3470 STMT_VINFO_DR_BASE_ADDRESS (pattern_stmt_info
)
3471 = STMT_VINFO_DR_BASE_ADDRESS (stmt_vinfo
);
3472 STMT_VINFO_DR_INIT (pattern_stmt_info
) = STMT_VINFO_DR_INIT (stmt_vinfo
);
3473 STMT_VINFO_DR_OFFSET (pattern_stmt_info
)
3474 = STMT_VINFO_DR_OFFSET (stmt_vinfo
);
3475 STMT_VINFO_DR_STEP (pattern_stmt_info
) = STMT_VINFO_DR_STEP (stmt_vinfo
);
3476 STMT_VINFO_DR_ALIGNED_TO (pattern_stmt_info
)
3477 = STMT_VINFO_DR_ALIGNED_TO (stmt_vinfo
);
3478 DR_STMT (STMT_VINFO_DATA_REF (stmt_vinfo
)) = pattern_stmt
;
3479 *type_out
= vectype
;
3481 stmts
->safe_push (last_stmt
);
3482 if (dump_enabled_p ())
3483 dump_printf_loc (MSG_NOTE
, vect_location
,
3484 "vect_recog_bool_pattern: detected:\n");
3485 return pattern_stmt
;
3492 /* A helper for vect_recog_mask_conversion_pattern. Build
3493 conversion of MASK to a type suitable for masking VECTYPE.
3494 Built statement gets required vectype and is appended to
3495 a pattern sequence of STMT_VINFO.
3497 Return converted mask. */
3500 build_mask_conversion (tree mask
, tree vectype
, stmt_vec_info stmt_vinfo
,
3505 stmt_vec_info new_stmt_info
;
3507 masktype
= build_same_sized_truth_vector_type (vectype
);
3508 tmp
= vect_recog_temp_ssa_var (TREE_TYPE (masktype
), NULL
);
3509 stmt
= gimple_build_assign (tmp
, CONVERT_EXPR
, mask
);
3510 new_stmt_info
= new_stmt_vec_info (stmt
, vinfo
);
3511 set_vinfo_for_stmt (stmt
, new_stmt_info
);
3512 STMT_VINFO_VECTYPE (new_stmt_info
) = masktype
;
3513 append_pattern_def_seq (stmt_vinfo
, stmt
);
3519 /* Function vect_recog_mask_conversion_pattern
3521 Try to find statements which require boolean type
3522 converison. Additional conversion statements are
3523 added to handle such cases. For example:
3533 S4 c_1 = m_3 ? c_2 : c_3;
3535 Will be transformed into:
3539 S3'' m_2' = (_Bool[bitsize=32])m_2
3540 S3' m_3' = m_1 & m_2';
3541 S4'' m_3'' = (_Bool[bitsize=8])m_3'
3542 S4' c_1' = m_3'' ? c_2 : c_3; */
3545 vect_recog_mask_conversion_pattern (vec
<gimple
*> *stmts
, tree
*type_in
,
3548 gimple
*last_stmt
= stmts
->pop ();
3549 enum tree_code rhs_code
;
3550 tree lhs
, rhs1
, rhs2
, tmp
, rhs1_type
, rhs2_type
, vectype1
, vectype2
;
3551 stmt_vec_info stmt_vinfo
= vinfo_for_stmt (last_stmt
);
3552 stmt_vec_info pattern_stmt_info
;
3553 vec_info
*vinfo
= stmt_vinfo
->vinfo
;
3554 gimple
*pattern_stmt
;
3556 /* Check for MASK_LOAD ans MASK_STORE calls requiring mask conversion. */
3557 if (is_gimple_call (last_stmt
)
3558 && gimple_call_internal_p (last_stmt
)
3559 && (gimple_call_internal_fn (last_stmt
) == IFN_MASK_STORE
3560 || gimple_call_internal_fn (last_stmt
) == IFN_MASK_LOAD
))
3562 bool load
= (gimple_call_internal_fn (last_stmt
) == IFN_MASK_LOAD
);
3566 lhs
= gimple_call_lhs (last_stmt
);
3567 vectype1
= get_vectype_for_scalar_type (TREE_TYPE (lhs
));
3571 rhs2
= gimple_call_arg (last_stmt
, 3);
3572 vectype1
= get_vectype_for_scalar_type (TREE_TYPE (rhs2
));
3575 rhs1
= gimple_call_arg (last_stmt
, 2);
3576 rhs1_type
= search_type_for_mask (rhs1
, vinfo
);
3579 vectype2
= get_mask_type_for_scalar_type (rhs1_type
);
3581 if (!vectype1
|| !vectype2
3582 || TYPE_VECTOR_SUBPARTS (vectype1
) == TYPE_VECTOR_SUBPARTS (vectype2
))
3585 tmp
= build_mask_conversion (rhs1
, vectype1
, stmt_vinfo
, vinfo
);
3589 lhs
= vect_recog_temp_ssa_var (TREE_TYPE (lhs
), NULL
);
3591 = gimple_build_call_internal (IFN_MASK_LOAD
, 3,
3592 gimple_call_arg (last_stmt
, 0),
3593 gimple_call_arg (last_stmt
, 1),
3595 gimple_call_set_lhs (pattern_stmt
, lhs
);
3599 = gimple_build_call_internal (IFN_MASK_STORE
, 4,
3600 gimple_call_arg (last_stmt
, 0),
3601 gimple_call_arg (last_stmt
, 1),
3603 gimple_call_arg (last_stmt
, 3));
3606 pattern_stmt_info
= new_stmt_vec_info (pattern_stmt
, vinfo
);
3607 set_vinfo_for_stmt (pattern_stmt
, pattern_stmt_info
);
3608 STMT_VINFO_DATA_REF (pattern_stmt_info
)
3609 = STMT_VINFO_DATA_REF (stmt_vinfo
);
3610 STMT_VINFO_DR_BASE_ADDRESS (pattern_stmt_info
)
3611 = STMT_VINFO_DR_BASE_ADDRESS (stmt_vinfo
);
3612 STMT_VINFO_DR_INIT (pattern_stmt_info
) = STMT_VINFO_DR_INIT (stmt_vinfo
);
3613 STMT_VINFO_DR_OFFSET (pattern_stmt_info
)
3614 = STMT_VINFO_DR_OFFSET (stmt_vinfo
);
3615 STMT_VINFO_DR_STEP (pattern_stmt_info
) = STMT_VINFO_DR_STEP (stmt_vinfo
);
3616 STMT_VINFO_DR_ALIGNED_TO (pattern_stmt_info
)
3617 = STMT_VINFO_DR_ALIGNED_TO (stmt_vinfo
);
3618 DR_STMT (STMT_VINFO_DATA_REF (stmt_vinfo
)) = pattern_stmt
;
3620 *type_out
= vectype1
;
3621 *type_in
= vectype1
;
3622 stmts
->safe_push (last_stmt
);
3623 if (dump_enabled_p ())
3624 dump_printf_loc (MSG_NOTE
, vect_location
,
3625 "vect_recog_mask_conversion_pattern: detected:\n");
3627 return pattern_stmt
;
3630 if (!is_gimple_assign (last_stmt
))
3633 lhs
= gimple_assign_lhs (last_stmt
);
3634 rhs1
= gimple_assign_rhs1 (last_stmt
);
3635 rhs_code
= gimple_assign_rhs_code (last_stmt
);
3637 /* Check for cond expression requiring mask conversion. */
3638 if (rhs_code
== COND_EXPR
)
3640 /* vect_recog_mixed_size_cond_pattern could apply.
3642 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo
))
3645 vectype1
= get_vectype_for_scalar_type (TREE_TYPE (lhs
));
3647 if (TREE_CODE (rhs1
) == SSA_NAME
)
3649 rhs1_type
= search_type_for_mask (rhs1
, vinfo
);
3654 rhs1_type
= TREE_TYPE (TREE_OPERAND (rhs1
, 0));
3656 vectype2
= get_mask_type_for_scalar_type (rhs1_type
);
3658 if (!vectype1
|| !vectype2
3659 || TYPE_VECTOR_SUBPARTS (vectype1
) == TYPE_VECTOR_SUBPARTS (vectype2
))
3662 /* If rhs1 is a comparison we need to move it into a
3663 separate statement. */
3664 if (TREE_CODE (rhs1
) != SSA_NAME
)
3666 tmp
= vect_recog_temp_ssa_var (TREE_TYPE (rhs1
), NULL
);
3667 pattern_stmt
= gimple_build_assign (tmp
, rhs1
);
3670 pattern_stmt_info
= new_stmt_vec_info (pattern_stmt
, vinfo
);
3671 set_vinfo_for_stmt (pattern_stmt
, pattern_stmt_info
);
3672 STMT_VINFO_VECTYPE (pattern_stmt_info
) = vectype2
;
3673 append_pattern_def_seq (stmt_vinfo
, pattern_stmt
);
3676 tmp
= build_mask_conversion (rhs1
, vectype1
, stmt_vinfo
, vinfo
);
3678 lhs
= vect_recog_temp_ssa_var (TREE_TYPE (lhs
), NULL
);
3679 pattern_stmt
= gimple_build_assign (lhs
, COND_EXPR
, tmp
,
3680 gimple_assign_rhs2 (last_stmt
),
3681 gimple_assign_rhs3 (last_stmt
));
3683 *type_out
= vectype1
;
3684 *type_in
= vectype1
;
3685 stmts
->safe_push (last_stmt
);
3686 if (dump_enabled_p ())
3687 dump_printf_loc (MSG_NOTE
, vect_location
,
3688 "vect_recog_mask_conversion_pattern: detected:\n");
3690 return pattern_stmt
;
3693 /* Now check for binary boolean operations requiring conversion for
3695 if (TREE_CODE (TREE_TYPE (lhs
)) != BOOLEAN_TYPE
)
3698 if (rhs_code
!= BIT_IOR_EXPR
3699 && rhs_code
!= BIT_XOR_EXPR
3700 && rhs_code
!= BIT_AND_EXPR
)
3703 rhs2
= gimple_assign_rhs2 (last_stmt
);
3705 rhs1_type
= search_type_for_mask (rhs1
, vinfo
);
3706 rhs2_type
= search_type_for_mask (rhs2
, vinfo
);
3708 if (!rhs1_type
|| !rhs2_type
3709 || TYPE_PRECISION (rhs1_type
) == TYPE_PRECISION (rhs2_type
))
3712 if (TYPE_PRECISION (rhs1_type
) < TYPE_PRECISION (rhs2_type
))
3714 vectype1
= get_mask_type_for_scalar_type (rhs1_type
);
3717 rhs2
= build_mask_conversion (rhs2
, vectype1
, stmt_vinfo
, vinfo
);
3721 vectype1
= get_mask_type_for_scalar_type (rhs2_type
);
3724 rhs1
= build_mask_conversion (rhs1
, vectype1
, stmt_vinfo
, vinfo
);
3727 lhs
= vect_recog_temp_ssa_var (TREE_TYPE (lhs
), NULL
);
3728 pattern_stmt
= gimple_build_assign (lhs
, rhs_code
, rhs1
, rhs2
);
3730 *type_out
= vectype1
;
3731 *type_in
= vectype1
;
3732 stmts
->safe_push (last_stmt
);
3733 if (dump_enabled_p ())
3734 dump_printf_loc (MSG_NOTE
, vect_location
,
3735 "vect_recog_mask_conversion_pattern: detected:\n");
3737 return pattern_stmt
;
3741 /* Mark statements that are involved in a pattern. */
3744 vect_mark_pattern_stmts (gimple
*orig_stmt
, gimple
*pattern_stmt
,
3745 tree pattern_vectype
)
3747 stmt_vec_info pattern_stmt_info
, def_stmt_info
;
3748 stmt_vec_info orig_stmt_info
= vinfo_for_stmt (orig_stmt
);
3749 vec_info
*vinfo
= orig_stmt_info
->vinfo
;
3752 pattern_stmt_info
= vinfo_for_stmt (pattern_stmt
);
3753 if (pattern_stmt_info
== NULL
)
3755 pattern_stmt_info
= new_stmt_vec_info (pattern_stmt
, vinfo
);
3756 set_vinfo_for_stmt (pattern_stmt
, pattern_stmt_info
);
3758 gimple_set_bb (pattern_stmt
, gimple_bb (orig_stmt
));
3760 STMT_VINFO_RELATED_STMT (pattern_stmt_info
) = orig_stmt
;
3761 STMT_VINFO_DEF_TYPE (pattern_stmt_info
)
3762 = STMT_VINFO_DEF_TYPE (orig_stmt_info
);
3763 STMT_VINFO_VECTYPE (pattern_stmt_info
) = pattern_vectype
;
3764 STMT_VINFO_IN_PATTERN_P (orig_stmt_info
) = true;
3765 STMT_VINFO_RELATED_STMT (orig_stmt_info
) = pattern_stmt
;
3766 STMT_VINFO_PATTERN_DEF_SEQ (pattern_stmt_info
)
3767 = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info
);
3768 if (STMT_VINFO_PATTERN_DEF_SEQ (pattern_stmt_info
))
3770 gimple_stmt_iterator si
;
3771 for (si
= gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (pattern_stmt_info
));
3772 !gsi_end_p (si
); gsi_next (&si
))
3774 def_stmt
= gsi_stmt (si
);
3775 def_stmt_info
= vinfo_for_stmt (def_stmt
);
3776 if (def_stmt_info
== NULL
)
3778 def_stmt_info
= new_stmt_vec_info (def_stmt
, vinfo
);
3779 set_vinfo_for_stmt (def_stmt
, def_stmt_info
);
3781 gimple_set_bb (def_stmt
, gimple_bb (orig_stmt
));
3782 STMT_VINFO_RELATED_STMT (def_stmt_info
) = orig_stmt
;
3783 STMT_VINFO_DEF_TYPE (def_stmt_info
) = vect_internal_def
;
3784 if (STMT_VINFO_VECTYPE (def_stmt_info
) == NULL_TREE
)
3785 STMT_VINFO_VECTYPE (def_stmt_info
) = pattern_vectype
;
3790 /* Function vect_pattern_recog_1
3793 PATTERN_RECOG_FUNC: A pointer to a function that detects a certain
3794 computation pattern.
3795 STMT: A stmt from which the pattern search should start.
3797 If PATTERN_RECOG_FUNC successfully detected the pattern, it creates an
3798 expression that computes the same functionality and can be used to
3799 replace the sequence of stmts that are involved in the pattern.
3802 This function checks if the expression returned by PATTERN_RECOG_FUNC is
3803 supported in vector form by the target. We use 'TYPE_IN' to obtain the
3804 relevant vector type. If 'TYPE_IN' is already a vector type, then this
3805 indicates that target support had already been checked by PATTERN_RECOG_FUNC.
3806 If 'TYPE_OUT' is also returned by PATTERN_RECOG_FUNC, we check that it fits
3807 to the available target pattern.
3809 This function also does some bookkeeping, as explained in the documentation
3810 for vect_recog_pattern. */
3813 vect_pattern_recog_1 (vect_recog_func
*recog_func
,
3814 gimple_stmt_iterator si
,
3815 vec
<gimple
*> *stmts_to_replace
)
3817 gimple
*stmt
= gsi_stmt (si
), *pattern_stmt
;
3818 stmt_vec_info stmt_info
;
3819 loop_vec_info loop_vinfo
;
3820 tree pattern_vectype
;
3821 tree type_in
, type_out
;
3822 enum tree_code code
;
3826 stmts_to_replace
->truncate (0);
3827 stmts_to_replace
->quick_push (stmt
);
3828 pattern_stmt
= recog_func
->fn (stmts_to_replace
, &type_in
, &type_out
);
3832 stmt
= stmts_to_replace
->last ();
3833 stmt_info
= vinfo_for_stmt (stmt
);
3834 loop_vinfo
= STMT_VINFO_LOOP_VINFO (stmt_info
);
3836 if (VECTOR_BOOLEAN_TYPE_P (type_in
)
3837 || VECTOR_MODE_P (TYPE_MODE (type_in
)))
3839 /* No need to check target support (already checked by the pattern
3840 recognition function). */
3841 pattern_vectype
= type_out
? type_out
: type_in
;
3845 machine_mode vec_mode
;
3846 enum insn_code icode
;
3849 /* Check target support */
3850 type_in
= get_vectype_for_scalar_type (type_in
);
3854 type_out
= get_vectype_for_scalar_type (type_out
);
3859 pattern_vectype
= type_out
;
3861 if (is_gimple_assign (pattern_stmt
))
3862 code
= gimple_assign_rhs_code (pattern_stmt
);
3865 gcc_assert (is_gimple_call (pattern_stmt
));
3869 optab
= optab_for_tree_code (code
, type_in
, optab_default
);
3870 vec_mode
= TYPE_MODE (type_in
);
3872 || (icode
= optab_handler (optab
, vec_mode
)) == CODE_FOR_nothing
3873 || (insn_data
[icode
].operand
[0].mode
!= TYPE_MODE (type_out
)))
3877 /* Found a vectorizable pattern. */
3878 if (dump_enabled_p ())
3880 dump_printf_loc (MSG_NOTE
, vect_location
,
3881 "%s pattern recognized: ", recog_func
->name
);
3882 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
3885 /* Mark the stmts that are involved in the pattern. */
3886 vect_mark_pattern_stmts (stmt
, pattern_stmt
, pattern_vectype
);
3888 /* Patterns cannot be vectorized using SLP, because they change the order of
3891 FOR_EACH_VEC_ELT (LOOP_VINFO_REDUCTIONS (loop_vinfo
), i
, next
)
3893 LOOP_VINFO_REDUCTIONS (loop_vinfo
).ordered_remove (i
);
3895 /* It is possible that additional pattern stmts are created and inserted in
3896 STMTS_TO_REPLACE. We create a stmt_info for each of them, and mark the
3897 relevant statements. */
3898 for (i
= 0; stmts_to_replace
->iterate (i
, &stmt
)
3899 && (unsigned) i
< (stmts_to_replace
->length () - 1);
3902 stmt_info
= vinfo_for_stmt (stmt
);
3903 pattern_stmt
= STMT_VINFO_RELATED_STMT (stmt_info
);
3904 if (dump_enabled_p ())
3906 dump_printf_loc (MSG_NOTE
, vect_location
,
3907 "additional pattern stmt: ");
3908 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, pattern_stmt
, 0);
3911 vect_mark_pattern_stmts (stmt
, pattern_stmt
, NULL_TREE
);
3918 /* Function vect_pattern_recog
3921 LOOP_VINFO - a struct_loop_info of a loop in which we want to look for
3924 Output - for each computation idiom that is detected we create a new stmt
3925 that provides the same functionality and that can be vectorized. We
3926 also record some information in the struct_stmt_info of the relevant
3927 stmts, as explained below:
3929 At the entry to this function we have the following stmts, with the
3930 following initial value in the STMT_VINFO fields:
3932 stmt in_pattern_p related_stmt vec_stmt
3933 S1: a_i = .... - - -
3934 S2: a_2 = ..use(a_i).. - - -
3935 S3: a_1 = ..use(a_2).. - - -
3936 S4: a_0 = ..use(a_1).. - - -
3937 S5: ... = ..use(a_0).. - - -
3939 Say the sequence {S1,S2,S3,S4} was detected as a pattern that can be
3940 represented by a single stmt. We then:
3941 - create a new stmt S6 equivalent to the pattern (the stmt is not
3942 inserted into the code)
3943 - fill in the STMT_VINFO fields as follows:
3945 in_pattern_p related_stmt vec_stmt
3946 S1: a_i = .... - - -
3947 S2: a_2 = ..use(a_i).. - - -
3948 S3: a_1 = ..use(a_2).. - - -
3949 S4: a_0 = ..use(a_1).. true S6 -
3950 '---> S6: a_new = .... - S4 -
3951 S5: ... = ..use(a_0).. - - -
3953 (the last stmt in the pattern (S4) and the new pattern stmt (S6) point
3954 to each other through the RELATED_STMT field).
3956 S6 will be marked as relevant in vect_mark_stmts_to_be_vectorized instead
3957 of S4 because it will replace all its uses. Stmts {S1,S2,S3} will
3958 remain irrelevant unless used by stmts other than S4.
3960 If vectorization succeeds, vect_transform_stmt will skip over {S1,S2,S3}
3961 (because they are marked as irrelevant). It will vectorize S6, and record
3962 a pointer to the new vector stmt VS6 from S6 (as usual).
3963 S4 will be skipped, and S5 will be vectorized as usual:
3965 in_pattern_p related_stmt vec_stmt
3966 S1: a_i = .... - - -
3967 S2: a_2 = ..use(a_i).. - - -
3968 S3: a_1 = ..use(a_2).. - - -
3969 > VS6: va_new = .... - - -
3970 S4: a_0 = ..use(a_1).. true S6 VS6
3971 '---> S6: a_new = .... - S4 VS6
3972 > VS5: ... = ..vuse(va_new).. - - -
3973 S5: ... = ..use(a_0).. - - -
3975 DCE could then get rid of {S1,S2,S3,S4,S5} (if their defs are not used
3976 elsewhere), and we'll end up with:
3979 VS5: ... = ..vuse(va_new)..
3981 In case of more than one pattern statements, e.g., widen-mult with
3985 S2 a_T = (TYPE) a_t;
3986 '--> S3: a_it = (interm_type) a_t;
3987 S4 prod_T = a_T * CONST;
3988 '--> S5: prod_T' = a_it w* CONST;
3990 there may be other users of a_T outside the pattern. In that case S2 will
3991 be marked as relevant (as well as S3), and both S2 and S3 will be analyzed
3992 and vectorized. The vector stmt VS2 will be recorded in S2, and VS3 will
3993 be recorded in S3. */
3996 vect_pattern_recog (vec_info
*vinfo
)
4001 gimple_stmt_iterator si
;
4003 auto_vec
<gimple
*, 1> stmts_to_replace
;
4006 if (dump_enabled_p ())
4007 dump_printf_loc (MSG_NOTE
, vect_location
,
4008 "=== vect_pattern_recog ===\n");
4010 if (loop_vec_info loop_vinfo
= dyn_cast
<loop_vec_info
> (vinfo
))
4012 loop
= LOOP_VINFO_LOOP (loop_vinfo
);
4013 bbs
= LOOP_VINFO_BBS (loop_vinfo
);
4014 nbbs
= loop
->num_nodes
;
4016 /* Scan through the loop stmts, applying the pattern recognition
4017 functions starting at each stmt visited: */
4018 for (i
= 0; i
< nbbs
; i
++)
4020 basic_block bb
= bbs
[i
];
4021 for (si
= gsi_start_bb (bb
); !gsi_end_p (si
); gsi_next (&si
))
4023 /* Scan over all generic vect_recog_xxx_pattern functions. */
4024 for (j
= 0; j
< NUM_PATTERNS
; j
++)
4025 if (vect_pattern_recog_1 (&vect_vect_recog_func_ptrs
[j
], si
,
4033 bb_vec_info bb_vinfo
= as_a
<bb_vec_info
> (vinfo
);
4034 for (si
= bb_vinfo
->region_begin
;
4035 gsi_stmt (si
) != gsi_stmt (bb_vinfo
->region_end
); gsi_next (&si
))
4037 if ((stmt
= gsi_stmt (si
))
4038 && vinfo_for_stmt (stmt
)
4039 && !STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt
)))
4042 /* Scan over all generic vect_recog_xxx_pattern functions. */
4043 for (j
= 0; j
< NUM_PATTERNS
; j
++)
4044 if (vect_pattern_recog_1 (&vect_vect_recog_func_ptrs
[j
], si
,