On Thu, 10 Oct 2024, Tamar Christina wrote: > > > e.g. if (a != 0) where a is loop invariant. For instance test_memcmp_1_1 > > > in /gcc.dg/memcmp-1.c is such loop. Technically we should be able to > > > vectorize such loops, but while we can represent externals in the SLP > > > tree, > > > we can't start discovery at them, as no stmt_info for them. > > > > > > In principle all I need here is an empty SLP tree, since all codegen is > > > driven > > > by the roots for such invariant compares. However vect_build_slp_tree > > > doesn't accept empty stmts. > > > > The externals would have SLP nodes of course but the requirement > > currently is that the SLP instance root is an internal def. > > > > > I believe we are able to vectorize such loops today, so perhaps instead > > > of > > > failing we should support building an SLP instance with only roots? > > > > It might be tempting but I don't think this is generally useful. > > > > > In which case should I try to fit it into vect_build_slp_tree or just > > > special > > > case it for the gcond discovery? > > > > The issue is that you have two operands you technically would like to > > see code-genrated - the 'a' and the '0' vector invariants, but the > > SLP instance only has a single root. You could (as I suggested) > > simply only build the SLP node for the (invariant) LHS of the gcond, > > not by using vect_build_slp_tree but instead by manually building > > the SLP tree for the invariant - see what vect_build_slp_tree_2 does > > here: > > > > Done, > > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. > Will test more targets closer to commit. > > Ok for master? > > gcc/ChangeLog: > > * tree-vect-loop.cc (vect_analyze_loop_2): Handle SLP trees with no > children. > * tree-vectorizer.h (enum slp_instance_kind): Add slp_inst_kind_gcond. > (LOOP_VINFO_EARLY_BREAKS_LIVE_IVS): New. > (vectorizable_early_exit): Expose. > (class _loop_vec_info): Add early_break_live_stmts. > * tree-vect-slp.cc (vect_build_slp_instance, vect_analyze_slp_instance): > Support gcond instances. > (vect_analyze_slp): Analyze gcond roots and early break live statements. > (maybe_push_to_hybrid_worklist): Don't sink gconds. > (vect_slp_analyze_operations): Support gconds. > (vect_slp_check_for_roots): Update comments. > (vectorize_slp_instance_root_stmt): Support gconds. > (vect_schedule_slp): Pass vinfo to vectorize_slp_instance_root_stmt. > * tree-vect-stmts.cc (vect_stmt_relevant_p): Record early break live > statements. > (vectorizable_early_exit): Support SLP. > > gcc/testsuite/ChangeLog: > > * gcc.dg/vect/vect-early-break_126.c: New test. > * gcc.dg/vect/vect-early-break_127.c: New test. > * gcc.dg/vect/vect-early-break_128.c: New test. > > -- inline copy of patch -- > > diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_126.c > b/gcc/testsuite/gcc.dg/vect/vect-early-break_126.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..4bfc9880f9fc869bf616123ff509d13be17ffacf > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_126.c > @@ -0,0 +1,28 @@ > +/* { dg-do compile } */ > +/* { dg-add-options vect_early_break } */ > +/* { dg-require-effective-target vect_early_break } */ > +/* { dg-require-effective-target vect_int } */ > + > +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ > +/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */ > + > +#define N 1024 > +unsigned vect_a[N]; > +unsigned vect_b[N]; > + > +unsigned test4(unsigned x) > +{ > + unsigned ret = 0; > + for (int i = 0; i < N; i++) > + { > + vect_b[i] = x + i; > + if (vect_a[i] > x) > + { > + ret *= vect_a[i]; > + return vect_a[i]; > + } > + vect_a[i] = x; > + ret += vect_a[i] + vect_b[i]; > + } > + return ret; > +} > diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_127.c > b/gcc/testsuite/gcc.dg/vect/vect-early-break_127.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..67cb5d34a77192e5d7d72c35df8e83535ef184ab > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_127.c > @@ -0,0 +1,27 @@ > +/* { dg-do compile } */ > +/* { dg-add-options vect_early_break } */ > +/* { dg-require-effective-target vect_early_break } */ > +/* { dg-require-effective-target vect_int } */ > + > +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ > +/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */ > + > +#ifndef N > +#define N 800 > +#endif > +unsigned vect_a[N]; > +unsigned vect_b[N]; > + > +unsigned test4(unsigned x) > +{ > + unsigned ret = 0; > + for (int i = 0; i < N; i++) > + { > + vect_b[i] = x + i; > + if (vect_a[i]*2 != x) > + break; > + vect_a[i] = x; > + > + } > + return ret; > +} > diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_128.c > b/gcc/testsuite/gcc.dg/vect/vect-early-break_128.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..6d7fb920ec2de529a4aa1de2c4a04286989204fd > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_128.c > @@ -0,0 +1,31 @@ > +/* { dg-do compile } */ > +/* { dg-add-options vect_early_break } */ > +/* { dg-require-effective-target vect_early_break } */ > +/* { dg-require-effective-target vect_int } */ > + > +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ > +/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */ > + > +#ifndef N > +#define N 800 > +#endif > +unsigned vect_a[N]; > +unsigned vect_b[N]; > + > +unsigned test4(unsigned x) > +{ > + unsigned ret = 0; > + for (int i = 0; i < N; i+=2) > + { > + vect_b[i] = x + i; > + vect_b[i+1] = x + i+1; > + if (vect_a[i]*2 != x) > + break; > + if (vect_a[i+1]*2 != x) > + break; > + vect_a[i] = x; > + vect_a[i+1] = x; > + > + } > + return ret; > +} > diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc > index > 9be50aaa621c6f31d95b626042e780a3bcf05cf3..9292449d6811cebc2d1161653727161521916186 > 100644 > --- a/gcc/tree-vect-loop.cc > +++ b/gcc/tree-vect-loop.cc > @@ -3258,6 +3258,10 @@ again: > FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (loop_vinfo), i, instance) > { > stmt_vec_info vinfo; > + auto scalar_stmt = SLP_TREE_SCALAR_STMTS (SLP_INSTANCE_TREE > (instance)); > + if (scalar_stmt.is_empty ()) > + continue; > +
Ah, this whole code blob will probably go away. I'd prefer if (SLP_TREE_DEF_TYPE (SLP_INSTANCE_TREE (instance)) != vect_internal_def) continue; > vinfo = SLP_TREE_SCALAR_STMTS (SLP_INSTANCE_TREE (instance))[0]; > if (! STMT_VINFO_GROUPED_ACCESS (vinfo)) > continue; > diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc > index > 9bb765e2cbacfa2a6e8872c5e00d32954b3398ba..12acde895f70a3b84bd1359e9e3373564c311f0f > 100644 > --- a/gcc/tree-vect-slp.cc > +++ b/gcc/tree-vect-slp.cc > @@ -3758,6 +3758,13 @@ vect_build_slp_instance (vec_info *vinfo, > "Analyzing vectorizable constructor: %G\n", > root_stmt_infos[0]->stmt); > } > + else if (kind == slp_inst_kind_gcond) > + { > + if (dump_enabled_p ()) > + dump_printf_loc (MSG_NOTE, vect_location, > + "Analyzing vectorizable control flow: %G", > + root_stmt_infos[0]->stmt); > + } > > if (dump_enabled_p ()) > { > @@ -4824,6 +4831,80 @@ vect_analyze_slp (vec_info *vinfo, unsigned > max_tree_size, > bst_map, NULL, force_single_lane); > } > } > + > + /* Find SLP sequences starting from gconds. */ > + for (auto cond : LOOP_VINFO_LOOP_CONDS (loop_vinfo)) > + { > + auto cond_info = loop_vinfo->lookup_stmt (cond); > + > + cond_info = vect_stmt_to_vectorize (cond_info); > + vec<stmt_vec_info> roots = vNULL; > + roots.safe_push (cond_info); > + gimple *stmt = STMT_VINFO_STMT (cond_info); > + tree args0 = gimple_cond_lhs (stmt); > + tree args1 = gimple_cond_rhs (stmt); > + > + /* These should be enforced by cond lowering. */ > + gcc_assert (gimple_cond_code (stmt) == NE_EXPR); > + gcc_assert (zerop (args1)); > + > + /* An argument without a loop def will be codegened from vectorizing > the > + root gcond itself. As such we don't need to try to build an SLP > tree > + from them. It's highly likely that the resulting SLP tree here if > both > + arguments have a def will be incompatible, but we rely on it being > split > + later on. */ > + if (auto varg = loop_vinfo->lookup_def (args0)) > + { > + vec<stmt_vec_info> stmts; > + vec<tree> remain = vNULL; > + stmts.create (1); > + stmts.quick_push (vect_stmt_to_vectorize (varg)); > + > + vect_build_slp_instance (vinfo, slp_inst_kind_gcond, > + stmts, roots, remain, > + max_tree_size, &limit, > + bst_map, NULL, force_single_lane); > + } > + else > + { > + /* Create a new SLP instance. */ > + slp_instance new_instance = XNEW (class _slp_instance); > + vec<tree> ops; > + ops.create (1); > + ops.quick_push (args0); > + slp_tree invnode = vect_create_new_slp_node (ops); > + SLP_TREE_DEF_TYPE (invnode) = vect_external_def; > + SLP_INSTANCE_TREE (new_instance) = invnode; > + SLP_INSTANCE_UNROLLING_FACTOR (new_instance) = 1; > + SLP_INSTANCE_LOADS (new_instance) = vNULL; > + SLP_INSTANCE_ROOT_STMTS (new_instance) = roots; > + SLP_INSTANCE_REMAIN_DEFS (new_instance) = vNULL; > + SLP_INSTANCE_KIND (new_instance) = slp_inst_kind_gcond; > + new_instance->reduc_phis = NULL; > + new_instance->cost_vec = vNULL; > + new_instance->subgraph_entries = vNULL; > + vinfo->slp_instances.safe_push (new_instance); > + } > + } > + > + /* Find and create slp instances for inductions that have been forced > + live due to early break. */ > + edge latch_e = loop_latch_edge (LOOP_VINFO_LOOP (loop_vinfo)); > + for (auto stmt_info : LOOP_VINFO_EARLY_BREAKS_LIVE_IVS (loop_vinfo)) > + { > + vec<stmt_vec_info> stmts; > + vec<stmt_vec_info> roots = vNULL; > + vec<tree> remain = vNULL; > + gphi *lc_phi = as_a<gphi *> (STMT_VINFO_STMT (stmt_info)); > + tree def = gimple_phi_arg_def_from_edge (lc_phi, latch_e); > + stmt_vec_info lc_info = loop_vinfo->lookup_def (def); > + stmts.create (1); > + stmts.quick_push (vect_stmt_to_vectorize (lc_info)); > + vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group, > + stmts, roots, remain, > + max_tree_size, &limit, > + bst_map, NULL, force_single_lane); > + } > } > > hash_set<slp_tree> visited_patterns; > @@ -7239,8 +7320,9 @@ maybe_push_to_hybrid_worklist (vec_info *vinfo, > } > } > } > - /* No def means this is a loo_vect sink. */ > - if (!any_def) > + /* No def means this is a loop_vect sink. Gimple conditionals also don't > have a > + def but shouldn't be considered sinks. */ > + if (!any_def && STMT_VINFO_DEF_TYPE (stmt_info) != vect_condition_def) > { > if (dump_enabled_p ()) > dump_printf_loc (MSG_NOTE, vect_location, > @@ -8064,7 +8146,14 @@ vect_slp_analyze_operations (vec_info *vinfo) > (SLP_INSTANCE_TREE (instance)))))) > /* Check we can vectorize the reduction. */ > || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_bb_reduc > - && !vectorizable_bb_reduc_epilogue (instance, &cost_vec))) > + && !vectorizable_bb_reduc_epilogue (instance, &cost_vec)) > + /* Check we can vectorize the gcond. */ > + || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_gcond > + && !vectorizable_early_exit (vinfo, > + SLP_INSTANCE_ROOT_STMTS > (instance)[0], > + NULL, NULL, > + SLP_INSTANCE_TREE (instance), > + &cost_vec))) > { > cost_vec.release (); > slp_tree node = SLP_INSTANCE_TREE (instance); > @@ -8694,6 +8783,8 @@ vect_slp_check_for_roots (bb_vec_info bb_vinfo) > !gsi_end_p (gsi); gsi_next (&gsi)) > { > gassign *assign = dyn_cast<gassign *> (gsi_stmt (gsi)); > + /* This can be used to start SLP discovery for early breaks for BB > early breaks > + when we get that far. */ > if (!assign) > continue; > > @@ -10912,7 +11003,7 @@ vect_remove_slp_scalar_calls (vec_info *vinfo, > slp_tree node) > /* Vectorize the instance root. */ > > void > -vectorize_slp_instance_root_stmt (slp_tree node, slp_instance instance) > +vectorize_slp_instance_root_stmt (vec_info *vinfo, slp_tree node, > slp_instance instance) > { > gassign *rstmt = NULL; > > @@ -11016,6 +11107,21 @@ vectorize_slp_instance_root_stmt (slp_tree node, > slp_instance instance) > update_stmt (gsi_stmt (rgsi)); > return; > } > + else if (instance->kind == slp_inst_kind_gcond) > + { > + /* Only support a single root for now as we can't codegen CFG yet and > so we > + can't support lane > 1 at this time. */ > + gcc_assert (instance->root_stmts.length () == 1); > + auto root_stmt_info = instance->root_stmts[0]; > + auto last_stmt = STMT_VINFO_STMT (root_stmt_info); > + gimple_stmt_iterator rgsi = gsi_for_stmt (last_stmt); > + gimple *vec_stmt = NULL; > + gcc_assert (!SLP_TREE_VEC_DEFS (node).is_empty ()); > + bool res = vectorizable_early_exit (vinfo, root_stmt_info, &rgsi, > + &vec_stmt, node, NULL); > + gcc_assert (res); > + return; > + } > else > gcc_unreachable (); > > @@ -11234,7 +11340,7 @@ vect_schedule_slp (vec_info *vinfo, const > vec<slp_instance> &slp_instances) > vect_schedule_scc (vinfo, node, instance, scc_info, maxdfs, stack); > > if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ()) > - vectorize_slp_instance_root_stmt (node, instance); > + vectorize_slp_instance_root_stmt (vinfo, node, instance); > > if (dump_enabled_p ()) > dump_printf_loc (MSG_NOTE, vect_location, > diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc > index > 43358767934612a9788c587f35f66e007faa8863..bdfc40369a12fb8a15ee9613324c10ad51b31583 > 100644 > --- a/gcc/tree-vect-stmts.cc > +++ b/gcc/tree-vect-stmts.cc > @@ -411,6 +411,7 @@ vect_stmt_relevant_p (stmt_vec_info stmt_info, > loop_vec_info loop_vinfo, > dump_printf_loc (MSG_NOTE, vect_location, > "vec_stmt_relevant_p: induction forced for " > "early break.\n"); > + LOOP_VINFO_EARLY_BREAKS_LIVE_IVS (loop_vinfo).safe_push (stmt_info); > *live_p = true; > > } > @@ -13004,7 +13005,7 @@ vectorizable_comparison (vec_info *vinfo, > /* Check to see if the current early break given in STMT_INFO is valid for > vectorization. */ > > -static bool > +bool > vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info, > gimple_stmt_iterator *gsi, gimple **vec_stmt, > slp_tree slp_node, stmt_vector_for_cost *cost_vec) > @@ -13028,8 +13029,13 @@ vectorizable_early_exit (vec_info *vinfo, > stmt_vec_info stmt_info, > slp_tree slp_op0; > tree op0; > enum vect_def_type dt0; > - if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0, &op0, &slp_op0, > &dt0, > - &vectype)) > + > + /* Early break gcond kind SLP trees can be root only and have no children, > + for instance in the case where the argument is an external. If that's > + the case there is no operand to analyse use of. */ > + if ((!slp_node || !SLP_TREE_CHILDREN (slp_node).is_empty ()) > + && !vect_is_simple_use (vinfo, stmt_info, slp_node, 0, &op0, &slp_op0, > &dt0, > + &vectype)) Hmm, but doesn't this somehow show we're mixing things up here? stmt_info seems to be the gcond but slp_node is for the pattern condition (or alternatively the invariant condition). But yeah, I guess that's how we set this up. Unless you want to create the pattern also for invariant conditions (why not?). I think the patch is good to go with the minor adjustment in the first hunk. Thanks, Richard. > { > if (dump_enabled_p ()) > dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, > @@ -13037,16 +13043,30 @@ vectorizable_early_exit (vec_info *vinfo, > stmt_vec_info stmt_info, > return false; > } > > + /* For SLP we don't want to use the type of the operands of the SLP node, > when > + vectorizing using SLP slp_node will be the children of the gcond and we > + want to use the type of the direct children which since the gcond is > root > + will be the current node, rather than a child node as vect_is_simple_use > + assumes. */ > + if (slp_node) > + vectype = SLP_TREE_VECTYPE (slp_node); > + > if (!vectype) > return false; > > machine_mode mode = TYPE_MODE (vectype); > - int ncopies; > + int ncopies, vec_num; > > if (slp_node) > - ncopies = 1; > + { > + ncopies = 1; > + vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); > + } > else > - ncopies = vect_get_num_copies (loop_vinfo, vectype); > + { > + ncopies = vect_get_num_copies (loop_vinfo, vectype); > + vec_num = 1; > + } > > vec_loop_masks *masks = &LOOP_VINFO_MASKS (loop_vinfo); > vec_loop_lens *lens = &LOOP_VINFO_LENS (loop_vinfo); > @@ -13115,9 +13135,11 @@ vectorizable_early_exit (vec_info *vinfo, > stmt_vec_info stmt_info, > { > if (direct_internal_fn_supported_p (IFN_VCOND_MASK_LEN, vectype, > OPTIMIZE_FOR_SPEED)) > - vect_record_loop_len (loop_vinfo, lens, ncopies, vectype, 1); > + vect_record_loop_len (loop_vinfo, lens, ncopies * vec_num, > + vectype, 1); > else > - vect_record_loop_mask (loop_vinfo, masks, ncopies, vectype, NULL); > + vect_record_loop_mask (loop_vinfo, masks, ncopies * vec_num, > + vectype, NULL); > } > > return true; > @@ -13131,9 +13153,18 @@ vectorizable_early_exit (vec_info *vinfo, > stmt_vec_info stmt_info, > if (dump_enabled_p ()) > dump_printf_loc (MSG_NOTE, vect_location, "transform early-exit.\n"); > > - if (!vectorizable_comparison_1 (vinfo, vectype, stmt_info, code, gsi, > - vec_stmt, slp_node, cost_vec)) > - gcc_unreachable (); > + /* For SLP we don't do codegen of the body starting from the gcond, the > gconds are > + roots and so by the time we get to them we have already codegened the > SLP tree > + and so we shouldn't try to do so again. The arguments have already been > + vectorized. It's not very clean to do this here, But the masking code > below is > + complex and this keeps it all in one place to ease fixes and backports. > Once we > + drop the non-SLP loop vect or split vectorizable_* this can be > simplified. */ > + if (!slp_node) > + { > + if (!vectorizable_comparison_1 (vinfo, vectype, stmt_info, code, gsi, > + vec_stmt, slp_node, cost_vec)) > + gcc_unreachable (); > + } > > gimple *stmt = STMT_VINFO_STMT (stmt_info); > basic_block cond_bb = gimple_bb (stmt); > @@ -13165,8 +13196,8 @@ vectorizable_early_exit (vec_info *vinfo, > stmt_vec_info stmt_info, > for (unsigned i = 0; i < stmts.length (); i++) > { > tree stmt_mask > - = vect_get_loop_mask (loop_vinfo, gsi, masks, ncopies, vectype, > - i); > + = vect_get_loop_mask (loop_vinfo, gsi, masks, ncopies * vec_num, > + vectype, i); > stmt_mask > = prepare_vec_mask (loop_vinfo, TREE_TYPE (stmt_mask), stmt_mask, > stmts[i], &cond_gsi); > @@ -13176,8 +13207,8 @@ vectorizable_early_exit (vec_info *vinfo, > stmt_vec_info stmt_info, > for (unsigned i = 0; i < stmts.length (); i++) > { > tree len_mask = vect_gen_loop_len_mask (loop_vinfo, gsi, &cond_gsi, > - lens, ncopies, vectype, > - stmts[i], i, 1); > + lens, ncopies * vec_num, > + vectype, stmts[i], i, 1); > > workset.quick_push (len_mask); > } > diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h > index > 73bccb5a40a8be4d3f5f600239d63c756d2e35e7..5028dd154d1c114c6ca3a4c6bf068cffef3aaa6c > 100644 > --- a/gcc/tree-vectorizer.h > +++ b/gcc/tree-vectorizer.h > @@ -252,7 +252,8 @@ enum slp_instance_kind { > slp_inst_kind_reduc_group, > slp_inst_kind_reduc_chain, > slp_inst_kind_bb_reduc, > - slp_inst_kind_ctor > + slp_inst_kind_ctor, > + slp_inst_kind_gcond > }; > > /* SLP instance is a sequence of stmts in a loop that can be packed into > @@ -977,6 +978,10 @@ public: > /* Statements whose VUSES need updating if early break vectorization is to > happen. */ > auto_vec<gimple*> early_break_vuses; > + > + /* Record statements that are needed to be live for early break > vectorization > + but may not have an LC PHI node materialized yet in the exits. */ > + auto_vec<stmt_vec_info> early_break_live_ivs; > } *loop_vec_info; > > /* Access Functions. */ > @@ -1036,6 +1041,8 @@ public: > #define LOOP_VINFO_EARLY_BRK_STORES(L) (L)->early_break_stores > #define LOOP_VINFO_EARLY_BREAKS_VECT_PEELED(L) \ > (single_pred ((L)->loop->latch) != (L)->vec_loop_iv_exit->src) > +#define LOOP_VINFO_EARLY_BREAKS_LIVE_IVS(L) \ > + (L)->early_break_live_ivs > #define LOOP_VINFO_EARLY_BRK_DEST_BB(L) (L)->early_break_dest_bb > #define LOOP_VINFO_EARLY_BRK_VUSES(L) (L)->early_break_vuses > #define LOOP_VINFO_LOOP_CONDS(L) (L)->conds > @@ -2524,6 +2531,9 @@ extern bool vectorizable_phi (vec_info *, > stmt_vec_info, gimple **, slp_tree, > stmt_vector_for_cost *); > extern bool vectorizable_recurr (loop_vec_info, stmt_vec_info, > gimple **, slp_tree, stmt_vector_for_cost *); > +extern bool vectorizable_early_exit (vec_info *, stmt_vec_info, > + gimple_stmt_iterator *, gimple **, > + slp_tree, stmt_vector_for_cost *); > extern bool vect_emulated_vector_p (tree); > extern bool vect_can_vectorize_without_simd_p (tree_code); > extern bool vect_can_vectorize_without_simd_p (code_helper); > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)