/* Analysis Utilities for Loop Vectorization.
- Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Dorit Nuzman <dorit@il.ibm.com>
This file is part of GCC.
#include "tm.h"
#include "ggc.h"
#include "tree.h"
-
#include "target.h"
#include "basic-block.h"
#include "diagnostic.h"
#include "tree-flow.h"
#include "tree-dump.h"
-#include "timevar.h"
#include "cfgloop.h"
#include "expr.h"
#include "optabs.h"
/* Function prototypes */
static void vect_pattern_recog_1
- (tree (* ) (tree, tree *, tree *), block_stmt_iterator);
-static bool widened_name_p (tree, tree, tree *, tree *);
+ (gimple (* ) (gimple, tree *, tree *), gimple_stmt_iterator);
+static bool widened_name_p (tree, gimple, tree *, gimple *);
/* Pattern recognition functions */
-static tree vect_recog_widen_sum_pattern (tree, tree *, tree *);
-static tree vect_recog_widen_mult_pattern (tree, tree *, tree *);
-static tree vect_recog_dot_prod_pattern (tree, tree *, tree *);
-static tree vect_recog_pow_pattern (tree, tree *, tree *);
+static gimple vect_recog_widen_sum_pattern (gimple, tree *, tree *);
+static gimple vect_recog_widen_mult_pattern (gimple, tree *, tree *);
+static gimple vect_recog_dot_prod_pattern (gimple, tree *, tree *);
+static gimple vect_recog_pow_pattern (gimple, tree *, tree *);
static vect_recog_func_ptr vect_vect_recog_func_ptrs[NUM_PATTERNS] = {
vect_recog_widen_mult_pattern,
vect_recog_widen_sum_pattern,
*/
static bool
-widened_name_p (tree name, tree use_stmt, tree *half_type, tree *def_stmt)
+widened_name_p (tree name, gimple use_stmt, tree *half_type, gimple *def_stmt)
{
tree dummy;
+ gimple dummy_gimple;
loop_vec_info loop_vinfo;
stmt_vec_info stmt_vinfo;
- tree expr;
tree type = TREE_TYPE (name);
tree oprnd0;
enum vect_def_type dt;
stmt_vinfo = vinfo_for_stmt (use_stmt);
loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
- if (!vect_is_simple_use (name, loop_vinfo, def_stmt, &def, &dt))
+ if (!vect_is_simple_use (name, loop_vinfo, NULL, def_stmt, &def, &dt))
return false;
- if (dt != vect_loop_def
- && dt != vect_invariant_def && dt != vect_constant_def)
+ if (dt != vect_internal_def
+ && dt != vect_external_def && dt != vect_constant_def)
return false;
if (! *def_stmt)
return false;
- if (TREE_CODE (*def_stmt) != GIMPLE_MODIFY_STMT)
+ if (!is_gimple_assign (*def_stmt))
return false;
- expr = GIMPLE_STMT_OPERAND (*def_stmt, 1);
- if (TREE_CODE (expr) != NOP_EXPR)
+ if (gimple_assign_rhs_code (*def_stmt) != NOP_EXPR)
return false;
- oprnd0 = TREE_OPERAND (expr, 0);
+ oprnd0 = gimple_assign_rhs1 (*def_stmt);
*half_type = TREE_TYPE (oprnd0);
if (!INTEGRAL_TYPE_P (type) || !INTEGRAL_TYPE_P (*half_type)
|| (TYPE_PRECISION (type) < (TYPE_PRECISION (*half_type) * 2)))
return false;
- if (!vect_is_simple_use (oprnd0, loop_vinfo, &dummy, &dummy, &dt))
+ if (!vect_is_simple_use (oprnd0, loop_vinfo, NULL, &dummy_gimple, &dummy,
+ &dt))
return false;
return true;
}
+/* Helper to return a new temporary for pattern of TYPE for STMT. If STMT
+ is NULL, the caller must set SSA_NAME_DEF_STMT for the returned SSA var. */
+
+static tree
+vect_recog_temp_ssa_var (tree type, gimple stmt)
+{
+ tree var = create_tmp_var (type, "patt");
+
+ add_referenced_var (var);
+ var = make_ssa_name (var, stmt);
+ return var;
+}
/* Function vect_recog_dot_prod_pattern
the correct order (as is the case when this computation is in an
inner-loop nested in an outer-loop that us being vectorized). */
-static tree
-vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
+static gimple
+vect_recog_dot_prod_pattern (gimple last_stmt, tree *type_in, tree *type_out)
{
- tree stmt, expr;
+ gimple stmt;
tree oprnd0, oprnd1;
tree oprnd00, oprnd01;
stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
tree type, half_type;
- tree pattern_expr;
+ gimple pattern_stmt;
tree prod_type;
loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
struct loop *loop = LOOP_VINFO_LOOP (loop_info);
+ tree var, rhs;
- if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
+ if (!is_gimple_assign (last_stmt))
return NULL;
- expr = GIMPLE_STMT_OPERAND (last_stmt, 1);
- type = TREE_TYPE (expr);
+ type = gimple_expr_type (last_stmt);
/* Look for the following pattern
DX = (TYPE1) X;
/* Starting from LAST_STMT, follow the defs of its uses in search
of the above pattern. */
- if (TREE_CODE (expr) != PLUS_EXPR)
+ if (gimple_assign_rhs_code (last_stmt) != PLUS_EXPR)
return NULL;
if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
/* Has been detected as widening-summation? */
stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
- expr = GIMPLE_STMT_OPERAND (stmt, 1);
- type = TREE_TYPE (expr);
- if (TREE_CODE (expr) != WIDEN_SUM_EXPR)
+ type = gimple_expr_type (stmt);
+ if (gimple_assign_rhs_code (stmt) != WIDEN_SUM_EXPR)
return NULL;
- oprnd0 = TREE_OPERAND (expr, 0);
- oprnd1 = TREE_OPERAND (expr, 1);
+ oprnd0 = gimple_assign_rhs1 (stmt);
+ oprnd1 = gimple_assign_rhs2 (stmt);
half_type = TREE_TYPE (oprnd0);
}
else
{
- tree def_stmt;
+ gimple def_stmt;
if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
return NULL;
- oprnd0 = TREE_OPERAND (expr, 0);
- oprnd1 = TREE_OPERAND (expr, 1);
- if (TYPE_MAIN_VARIANT (TREE_TYPE (oprnd0)) != TYPE_MAIN_VARIANT (type)
- || TYPE_MAIN_VARIANT (TREE_TYPE (oprnd1)) != TYPE_MAIN_VARIANT (type))
+ oprnd0 = gimple_assign_rhs1 (last_stmt);
+ oprnd1 = gimple_assign_rhs2 (last_stmt);
+ if (!types_compatible_p (TREE_TYPE (oprnd0), type)
+ || !types_compatible_p (TREE_TYPE (oprnd1), type))
return NULL;
stmt = last_stmt;
if (widened_name_p (oprnd0, stmt, &half_type, &def_stmt))
{
stmt = def_stmt;
- expr = GIMPLE_STMT_OPERAND (stmt, 1);
- oprnd0 = TREE_OPERAND (expr, 0);
+ oprnd0 = gimple_assign_rhs1 (stmt);
}
else
half_type = type;
stmt = SSA_NAME_DEF_STMT (oprnd0);
/* FORNOW. Can continue analyzing the def-use chain when this stmt in a phi
inside the loop (in case we are analyzing an outer-loop). */
- if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
+ if (!is_gimple_assign (stmt))
return NULL;
stmt_vinfo = vinfo_for_stmt (stmt);
gcc_assert (stmt_vinfo);
- if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_loop_def)
+ if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_internal_def)
return NULL;
- expr = GIMPLE_STMT_OPERAND (stmt, 1);
- if (TREE_CODE (expr) != MULT_EXPR)
+ if (gimple_assign_rhs_code (stmt) != MULT_EXPR)
return NULL;
if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
{
/* Has been detected as a widening multiplication? */
stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
- expr = GIMPLE_STMT_OPERAND (stmt, 1);
- if (TREE_CODE (expr) != WIDEN_MULT_EXPR)
+ if (gimple_assign_rhs_code (stmt) != WIDEN_MULT_EXPR)
return NULL;
stmt_vinfo = vinfo_for_stmt (stmt);
gcc_assert (stmt_vinfo);
- gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_loop_def);
- oprnd00 = TREE_OPERAND (expr, 0);
- oprnd01 = TREE_OPERAND (expr, 1);
+ gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_internal_def);
+ oprnd00 = gimple_assign_rhs1 (stmt);
+ oprnd01 = gimple_assign_rhs2 (stmt);
}
else
{
tree half_type0, half_type1;
- tree def_stmt;
+ gimple def_stmt;
tree oprnd0, oprnd1;
- oprnd0 = TREE_OPERAND (expr, 0);
- oprnd1 = TREE_OPERAND (expr, 1);
- if (TYPE_MAIN_VARIANT (TREE_TYPE (oprnd0))
- != TYPE_MAIN_VARIANT (prod_type)
- || TYPE_MAIN_VARIANT (TREE_TYPE (oprnd1))
- != TYPE_MAIN_VARIANT (prod_type))
+ oprnd0 = gimple_assign_rhs1 (stmt);
+ oprnd1 = gimple_assign_rhs2 (stmt);
+ if (!types_compatible_p (TREE_TYPE (oprnd0), prod_type)
+ || !types_compatible_p (TREE_TYPE (oprnd1), prod_type))
return NULL;
if (!widened_name_p (oprnd0, stmt, &half_type0, &def_stmt))
return NULL;
- oprnd00 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 0);
+ oprnd00 = gimple_assign_rhs1 (def_stmt);
if (!widened_name_p (oprnd1, stmt, &half_type1, &def_stmt))
return NULL;
- oprnd01 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 0);
- if (TYPE_MAIN_VARIANT (half_type0) != TYPE_MAIN_VARIANT (half_type1))
+ oprnd01 = gimple_assign_rhs1 (def_stmt);
+ if (!types_compatible_p (half_type0, half_type1))
return NULL;
if (TYPE_PRECISION (prod_type) != TYPE_PRECISION (half_type0) * 2)
return NULL;
*type_out = type;
/* Pattern detected. Create a stmt to be used to replace the pattern: */
- pattern_expr = build3 (DOT_PROD_EXPR, type, oprnd00, oprnd01, oprnd1);
+ var = vect_recog_temp_ssa_var (type, NULL);
+ rhs = build3 (DOT_PROD_EXPR, type, oprnd00, oprnd01, oprnd1),
+ pattern_stmt = gimple_build_assign (var, rhs);
+
if (vect_print_dump_info (REPORT_DETAILS))
{
fprintf (vect_dump, "vect_recog_dot_prod_pattern: detected: ");
- print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
}
/* We don't allow changing the order of the computation in the inner-loop
when doing outer-loop vectorization. */
- if (nested_in_vect_loop_p (loop, last_stmt))
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "vect_recog_dot_prod_pattern: not allowed.");
- return NULL;
- }
+ gcc_assert (!nested_in_vect_loop_p (loop, last_stmt));
- return pattern_expr;
+ return pattern_stmt;
}
-
-
+
/* Function vect_recog_widen_mult_pattern
Try to find the following pattern:
WIDEN_MULT <a_t, b_t>
*/
-static tree
-vect_recog_widen_mult_pattern (tree last_stmt,
+static gimple
+vect_recog_widen_mult_pattern (gimple last_stmt,
tree *type_in,
tree *type_out)
{
- tree expr;
- tree def_stmt0, def_stmt1;
+ gimple def_stmt0, def_stmt1;
tree oprnd0, oprnd1;
tree type, half_type0, half_type1;
- tree pattern_expr;
+ gimple pattern_stmt;
tree vectype;
tree dummy;
+ tree var;
enum tree_code dummy_code;
+ int dummy_int;
+ VEC (tree, heap) *dummy_vec;
- if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
+ if (!is_gimple_assign (last_stmt))
return NULL;
- expr = GIMPLE_STMT_OPERAND (last_stmt, 1);
- type = TREE_TYPE (expr);
+ type = gimple_expr_type (last_stmt);
/* Starting from LAST_STMT, follow the defs of its uses in search
of the above pattern. */
- if (TREE_CODE (expr) != MULT_EXPR)
+ if (gimple_assign_rhs_code (last_stmt) != MULT_EXPR)
return NULL;
- oprnd0 = TREE_OPERAND (expr, 0);
- oprnd1 = TREE_OPERAND (expr, 1);
- if (TYPE_MAIN_VARIANT (TREE_TYPE (oprnd0)) != TYPE_MAIN_VARIANT (type)
- || TYPE_MAIN_VARIANT (TREE_TYPE (oprnd1)) != TYPE_MAIN_VARIANT (type))
+ oprnd0 = gimple_assign_rhs1 (last_stmt);
+ oprnd1 = gimple_assign_rhs2 (last_stmt);
+ if (!types_compatible_p (TREE_TYPE (oprnd0), type)
+ || !types_compatible_p (TREE_TYPE (oprnd1), type))
return NULL;
/* Check argument 0 */
if (!widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0))
return NULL;
- oprnd0 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt0, 1), 0);
+ oprnd0 = gimple_assign_rhs1 (def_stmt0);
/* Check argument 1 */
if (!widened_name_p (oprnd1, last_stmt, &half_type1, &def_stmt1))
return NULL;
- oprnd1 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt1, 1), 0);
+ oprnd1 = gimple_assign_rhs1 (def_stmt1);
- if (TYPE_MAIN_VARIANT (half_type0) != TYPE_MAIN_VARIANT (half_type1))
+ if (!types_compatible_p (half_type0, half_type1))
return NULL;
/* Pattern detected. */
vectype = get_vectype_for_scalar_type (half_type0);
if (!vectype
|| !supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt, vectype,
- &dummy, &dummy, &dummy_code,
- &dummy_code))
+ &dummy, &dummy, &dummy_code,
+ &dummy_code, &dummy_int, &dummy_vec))
return NULL;
*type_in = vectype;
*type_out = NULL_TREE;
/* Pattern supported. Create a stmt to be used to replace the pattern: */
- pattern_expr = build2 (WIDEN_MULT_EXPR, type, oprnd0, oprnd1);
+ var = vect_recog_temp_ssa_var (type, NULL);
+ pattern_stmt = gimple_build_assign_with_ops (WIDEN_MULT_EXPR, var, oprnd0,
+ oprnd1);
+ SSA_NAME_DEF_STMT (var) = pattern_stmt;
+
if (vect_print_dump_info (REPORT_DETAILS))
- print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
- return pattern_expr;
+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
+
+ return pattern_stmt;
}
* Return value: A new stmt that will be used to replace the sequence of
stmts that constitute the pattern. In this case it will be:
- x * x
+ x = x * x
or
- sqrt (x)
+ x = sqrt (x)
*/
-static tree
-vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out)
+static gimple
+vect_recog_pow_pattern (gimple last_stmt, tree *type_in, tree *type_out)
{
- tree expr;
tree type;
- tree fn, base, exp;
+ tree fn, base, exp = NULL;
+ gimple stmt;
+ tree var;
- if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
+ if (!is_gimple_call (last_stmt) || gimple_call_lhs (last_stmt) == NULL)
return NULL;
- expr = GIMPLE_STMT_OPERAND (last_stmt, 1);
- type = TREE_TYPE (expr);
+ type = gimple_expr_type (last_stmt);
- if (TREE_CODE (expr) != CALL_EXPR)
- return NULL_TREE;
-
- fn = get_callee_fndecl (expr);
+ fn = gimple_call_fndecl (last_stmt);
switch (DECL_FUNCTION_CODE (fn))
{
case BUILT_IN_POWIF:
case BUILT_IN_POWI:
case BUILT_IN_POWF:
case BUILT_IN_POW:
- base = CALL_EXPR_ARG (expr, 0);
- exp = CALL_EXPR_ARG (expr, 1);
+ base = gimple_call_arg (last_stmt, 0);
+ exp = gimple_call_arg (last_stmt, 1);
if (TREE_CODE (exp) != REAL_CST
&& TREE_CODE (exp) != INTEGER_CST)
- return NULL_TREE;
+ return NULL;
break;
- default:;
- return NULL_TREE;
+ default:
+ return NULL;
}
/* We now have a pow or powi builtin function call with a constant
&& REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconst2)))
{
*type_in = TREE_TYPE (base);
- return build2 (MULT_EXPR, TREE_TYPE (base), base, base);
+
+ var = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
+ stmt = gimple_build_assign_with_ops (MULT_EXPR, var, base, base);
+ SSA_NAME_DEF_STMT (var) = stmt;
+ return stmt;
}
/* Catch square root. */
*type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
if (*type_in)
{
- newfn = build_call_expr (newfn, 1, base);
- if (vectorizable_function (newfn, *type_in, *type_in) != NULL_TREE)
- return newfn;
+ gimple stmt = gimple_build_call (newfn, 1, base);
+ if (vectorizable_function (stmt, *type_in, *type_in)
+ != NULL_TREE)
+ {
+ var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
+ gimple_call_set_lhs (stmt, var);
+ return stmt;
+ }
}
}
- return NULL_TREE;
+ return NULL;
}
the correct order (as is the case when this computation is in an
inner-loop nested in an outer-loop that us being vectorized). */
-static tree
-vect_recog_widen_sum_pattern (tree last_stmt, tree *type_in, tree *type_out)
+static gimple
+vect_recog_widen_sum_pattern (gimple last_stmt, tree *type_in, tree *type_out)
{
- tree stmt, expr;
+ gimple stmt;
tree oprnd0, oprnd1;
stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
tree type, half_type;
- tree pattern_expr;
+ gimple pattern_stmt;
loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
struct loop *loop = LOOP_VINFO_LOOP (loop_info);
+ tree var;
- if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
+ if (!is_gimple_assign (last_stmt))
return NULL;
- expr = GIMPLE_STMT_OPERAND (last_stmt, 1);
- type = TREE_TYPE (expr);
+ type = gimple_expr_type (last_stmt);
/* Look for the following pattern
DX = (TYPE) X;
/* Starting from LAST_STMT, follow the defs of its uses in search
of the above pattern. */
- if (TREE_CODE (expr) != PLUS_EXPR)
+ if (gimple_assign_rhs_code (last_stmt) != PLUS_EXPR)
return NULL;
if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
return NULL;
- oprnd0 = TREE_OPERAND (expr, 0);
- oprnd1 = TREE_OPERAND (expr, 1);
- if (TYPE_MAIN_VARIANT (TREE_TYPE (oprnd0)) != TYPE_MAIN_VARIANT (type)
- || TYPE_MAIN_VARIANT (TREE_TYPE (oprnd1)) != TYPE_MAIN_VARIANT (type))
+ oprnd0 = gimple_assign_rhs1 (last_stmt);
+ oprnd1 = gimple_assign_rhs2 (last_stmt);
+ if (!types_compatible_p (TREE_TYPE (oprnd0), type)
+ || !types_compatible_p (TREE_TYPE (oprnd1), type))
return NULL;
/* So far so good. Since last_stmt was detected as a (summation) reduction,
if (!widened_name_p (oprnd0, last_stmt, &half_type, &stmt))
return NULL;
- oprnd0 = TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 0);
+ oprnd0 = gimple_assign_rhs1 (stmt);
*type_in = half_type;
*type_out = type;
/* Pattern detected. Create a stmt to be used to replace the pattern: */
- pattern_expr = build2 (WIDEN_SUM_EXPR, type, oprnd0, oprnd1);
+ var = vect_recog_temp_ssa_var (type, NULL);
+ pattern_stmt = gimple_build_assign_with_ops (WIDEN_SUM_EXPR, var,
+ oprnd0, oprnd1);
+ SSA_NAME_DEF_STMT (var) = pattern_stmt;
+
if (vect_print_dump_info (REPORT_DETAILS))
{
fprintf (vect_dump, "vect_recog_widen_sum_pattern: detected: ");
- print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
}
/* We don't allow changing the order of the computation in the inner-loop
when doing outer-loop vectorization. */
- if (nested_in_vect_loop_p (loop, last_stmt))
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "vect_recog_widen_sum_pattern: not allowed.");
- return NULL;
- }
+ gcc_assert (!nested_in_vect_loop_p (loop, last_stmt));
- return pattern_expr;
+ return pattern_stmt;
}
static void
vect_pattern_recog_1 (
- tree (* vect_recog_func) (tree, tree *, tree *),
- block_stmt_iterator si)
+ gimple (* vect_recog_func) (gimple, tree *, tree *),
+ gimple_stmt_iterator si)
{
- tree stmt = bsi_stmt (si);
+ gimple stmt = gsi_stmt (si), pattern_stmt;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
stmt_vec_info pattern_stmt_info;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- tree pattern_expr;
tree pattern_vectype;
tree type_in, type_out;
- tree pattern_type;
enum tree_code code;
- tree var, var_name;
- stmt_ann_t ann;
- pattern_expr = (* vect_recog_func) (stmt, &type_in, &type_out);
- if (!pattern_expr)
+ pattern_stmt = (* vect_recog_func) (stmt, &type_in, &type_out);
+ if (!pattern_stmt)
return;
if (VECTOR_MODE_P (TYPE_MODE (type_in)))
}
else
{
- enum tree_code vec_mode;
+ enum machine_mode vec_mode;
enum insn_code icode;
optab optab;
if (!pattern_vectype)
return;
- optab = optab_for_tree_code (TREE_CODE (pattern_expr), pattern_vectype);
+ if (is_gimple_assign (pattern_stmt))
+ code = gimple_assign_rhs_code (pattern_stmt);
+ else
+ {
+ gcc_assert (is_gimple_call (pattern_stmt));
+ code = CALL_EXPR;
+ }
+
+ optab = optab_for_tree_code (code, pattern_vectype, optab_default);
vec_mode = TYPE_MODE (pattern_vectype);
if (!optab
|| (icode = optab_handler (optab, vec_mode)->insn_code) ==
if (vect_print_dump_info (REPORT_DETAILS))
{
fprintf (vect_dump, "pattern recognized: ");
- print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
}
- /* Mark the stmts that are involved in the pattern,
- create a new stmt to express the pattern and insert it. */
- code = TREE_CODE (pattern_expr);
- pattern_type = TREE_TYPE (pattern_expr);
- var = create_tmp_var (pattern_type, "patt");
- add_referenced_var (var);
- var_name = make_ssa_name (var, NULL_TREE);
- pattern_expr = build_gimple_modify_stmt (var_name, pattern_expr);
- SSA_NAME_DEF_STMT (var_name) = pattern_expr;
- bsi_insert_before (&si, pattern_expr, BSI_SAME_STMT);
- ann = stmt_ann (pattern_expr);
- set_stmt_info (ann, new_stmt_vec_info (pattern_expr, loop_vinfo));
- pattern_stmt_info = vinfo_for_stmt (pattern_expr);
+ /* Mark the stmts that are involved in the pattern. */
+ gsi_insert_before (&si, pattern_stmt, GSI_SAME_STMT);
+ set_vinfo_for_stmt (pattern_stmt,
+ new_stmt_vec_info (pattern_stmt, loop_vinfo, NULL));
+ pattern_stmt_info = vinfo_for_stmt (pattern_stmt);
STMT_VINFO_RELATED_STMT (pattern_stmt_info) = stmt;
STMT_VINFO_DEF_TYPE (pattern_stmt_info) = STMT_VINFO_DEF_TYPE (stmt_info);
STMT_VINFO_VECTYPE (pattern_stmt_info) = pattern_vectype;
STMT_VINFO_IN_PATTERN_P (stmt_info) = true;
- STMT_VINFO_RELATED_STMT (stmt_info) = pattern_expr;
+ STMT_VINFO_RELATED_STMT (stmt_info) = pattern_stmt;
return;
}
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
unsigned int nbbs = loop->num_nodes;
- block_stmt_iterator si;
- tree stmt;
+ gimple_stmt_iterator si;
+ gimple stmt;
unsigned int i, j;
- tree (* vect_recog_func_ptr) (tree, tree *, tree *);
+ gimple (* vect_recog_func_ptr) (gimple, tree *, tree *);
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_pattern_recog ===");
for (i = 0; i < nbbs; i++)
{
basic_block bb = bbs[i];
- for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
- stmt = bsi_stmt (si);
+ stmt = gsi_stmt (si);
/* Scan over all generic vect_recog_xxx_pattern functions. */
for (j = 0; j < NUM_PATTERNS; j++)