From 6b3d68bc468a15d357f17b3d3f26b8b6c0754caf Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 9 Jul 2018 17:42:16 -0400 Subject: [PATCH 44/46] Use opt_result throughout vectorizer This patch uses the opt_result framework throughout the vectorizer (and a few other places) so that specific details on problems are propagated back up to the top-level of the vectorizer. The changes are mostly fairly mechanical. There are various FIXMEs in the code: for example, in various places it feels like it would be useful to have a formatted printing API for opt_result::failure etc, or other ways to capture the information of interest (e.g. if there's a dependence between two data references that's blocking vectorization, we probably should capture them so we can highlight them to the user). Almost everywhere using "bool" to handle error-checking uses "true" for success, but there was one place where "true" meant "failure": vect_analyze_data_ref_dependence, so the patch changes the sense of that function's return value (as well as converting it from bool to opt_result). Placeholder ChangeLog follows: gcc/ChangeLog: * tree-data-ref.c: Use opt-problem.h in many places. * tree-data-ref.h: Likewise. * tree-vect-data-refs.c: Likewise. * tree-vect-loop.c: Likewise. * tree-vect-slp.c: Likewise. * tree-vect-stmts.c: Likewise. * tree-vectorizer.h: Likewise. --- gcc/tree-data-ref.c | 33 +++++--- gcc/tree-data-ref.h | 10 ++- gcc/tree-vect-data-refs.c | 189 ++++++++++++++++++++++++----------------- gcc/tree-vect-loop.c | 212 +++++++++++++++++++++++++++------------------- gcc/tree-vect-slp.c | 4 +- gcc/tree-vect-stmts.c | 130 ++++++++++++++++------------ gcc/tree-vectorizer.h | 35 ++++---- 7 files changed, 360 insertions(+), 253 deletions(-) diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index b163eaf..a6319f83 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -827,7 +827,7 @@ canonicalize_base_object_address (tree addr) Return true if the analysis succeeded and store the results in DRB if so. BB analysis can only fail for bitfield or reversed-storage accesses. */ -bool +opt_result dr_analyze_innermost (innermost_loop_behavior *drb, tree ref, struct loop *loop) { @@ -851,14 +851,14 @@ dr_analyze_innermost (innermost_loop_behavior *drb, tree ref, { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "failed: bit offset alignment.\n"); - return false; + return opt_result::failure ("bit offset alignment", NULL); } if (preversep) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "failed: reverse storage order.\n"); - return false; + return opt_result::failure ("reverse storage order", NULL); } /* Calculate the alignment and misalignment for the inner reference. */ @@ -898,7 +898,9 @@ dr_analyze_innermost (innermost_loop_behavior *drb, tree ref, { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "failed: evolution of base is not affine.\n"); - return false; + // FIXME: should this propagate an opt_problem from simple_iv? + return opt_result::failure ("evolution of base is not affine", + NULL); } } else @@ -924,7 +926,9 @@ dr_analyze_innermost (innermost_loop_behavior *drb, tree ref, { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "failed: evolution of offset is not affine.\n"); - return false; + // FIXME: should this propagate an opt_problem from simple_iv? + return opt_result::failure ("evolution of offset is not affine", + NULL); } } @@ -981,7 +985,7 @@ dr_analyze_innermost (innermost_loop_behavior *drb, tree ref, if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "success.\n"); - return true; + return opt_result::success (); } /* Return true if OP is a valid component reference for a DR access @@ -1318,7 +1322,7 @@ data_ref_compare_tree (tree t1, tree t2) /* Return TRUE it's possible to resolve data dependence DDR by runtime alias check. */ -bool +opt_result runtime_alias_check_p (ddr_p ddr, struct loop *loop, bool speed_p) { if (dump_enabled_p ()) @@ -1336,7 +1340,8 @@ runtime_alias_check_p (ddr_p ddr, struct loop *loop, bool speed_p) dump_printf (MSG_MISSED_OPTIMIZATION, "runtime alias check not supported when optimizing " "for size.\n"); - return false; + return opt_result::failure ("runtime alias check not supported when" + " optimizing for size", NULL); } /* FORNOW: We don't support versioning with outer-loop in either @@ -1346,10 +1351,11 @@ runtime_alias_check_p (ddr_p ddr, struct loop *loop, bool speed_p) if (dump_enabled_p ()) dump_printf (MSG_MISSED_OPTIMIZATION, "runtime alias check not supported for outer loop.\n"); - return false; + return opt_result::failure ("runtime alias check not supported for" + " outer loop", NULL); } - return true; + return opt_result::success (); } /* Operator == between two dr_with_seg_len objects. @@ -5067,18 +5073,17 @@ loop_nest_has_data_refs (loop_p loop) reference, returns false, otherwise returns true. NEST is the outermost loop of the loop nest in which the references should be analyzed. */ -bool +opt_result find_data_references_in_stmt (struct loop *nest, gimple *stmt, vec *datarefs) { unsigned i; auto_vec references; data_ref_loc *ref; - bool ret = true; data_reference_p dr; if (get_references_in_stmt (stmt, &references)) - return false; + return opt_result::failure ("statement clobbers memory", stmt); FOR_EACH_VEC_ELT (references, i, ref) { @@ -5089,7 +5094,7 @@ find_data_references_in_stmt (struct loop *nest, gimple *stmt, datarefs->safe_push (dr); } - return ret; + return opt_result::success (); } /* Stores the data references in STMT to DATAREFS. If there is an diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h index 8739853..d734708 100644 --- a/gcc/tree-data-ref.h +++ b/gcc/tree-data-ref.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "graphds.h" #include "tree-chrec.h" +#include "opt-problem.h" /* innermost_loop_behavior describes the evolution of the address of the memory @@ -421,7 +422,8 @@ typedef struct data_dependence_relation *ddr_p; #define DDR_COULD_BE_INDEPENDENT_P(DDR) (DDR)->could_be_independent_p -bool dr_analyze_innermost (innermost_loop_behavior *, tree, struct loop *); +opt_result dr_analyze_innermost (innermost_loop_behavior *, tree, + struct loop *); extern bool compute_data_dependences_for_loop (struct loop *, bool, vec *, vec *, @@ -443,8 +445,8 @@ extern void free_dependence_relation (struct data_dependence_relation *); extern void free_dependence_relations (vec ); extern void free_data_ref (data_reference_p); extern void free_data_refs (vec ); -extern bool find_data_references_in_stmt (struct loop *, gimple *, - vec *); +extern opt_result find_data_references_in_stmt (struct loop *, gimple *, + vec *); extern bool graphite_find_data_references_in_stmt (edge, loop_p, gimple *, vec *); tree find_data_references_in_loop (struct loop *, vec *); @@ -479,7 +481,7 @@ extern bool dr_may_alias_p (const struct data_reference *, extern bool dr_equal_offsets_p (struct data_reference *, struct data_reference *); -extern bool runtime_alias_check_p (ddr_p, struct loop *, bool); +extern opt_result runtime_alias_check_p (ddr_p, struct loop *, bool); extern int data_ref_compare_tree (tree, tree); extern void prune_runtime_alias_test_list (vec *, poly_uint64); diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 63429a3..eceb6f2 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -155,20 +155,25 @@ vect_get_smallest_scalar_type (gimple *stmt, HOST_WIDE_INT *lhs_size_unit, tested at run-time. Return TRUE if DDR was successfully inserted. Return false if versioning is not supported. */ -static bool +static opt_result vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo) { struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); if ((unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS) == 0) - return false; + // FIXME: formatted print? + return opt_result::failure ("will not create alias checks, as" + " --param vect-max-version-for-alias-checks" + " == 0", NULL); - if (!runtime_alias_check_p (ddr, loop, - optimize_loop_nest_for_speed_p (loop))) - return false; + opt_result res + = runtime_alias_check_p (ddr, loop, + optimize_loop_nest_for_speed_p (loop)); + if (!res) + return res; LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo).safe_push (ddr); - return true; + return opt_result::success (); } /* Record that loop LOOP_VINFO needs to check that VALUE is nonzero. */ @@ -280,12 +285,14 @@ vect_analyze_possibly_independent_ddr (data_dependence_relation *ddr, /* Function vect_analyze_data_ref_dependence. - Return TRUE if there (might) exist a dependence between a memory-reference + FIXME: I needed to change the sense of the returned flag. + + Return FALSE if there (might) exist a dependence between a memory-reference DRA and a memory-reference DRB. When versioning for alias may check a - dependence at run-time, return FALSE. Adjust *MAX_VF according to + dependence at run-time, return TRUE. Adjust *MAX_VF according to the data dependence. */ -static bool +static opt_result vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, loop_vec_info loop_vinfo, unsigned int *max_vf) @@ -306,11 +313,11 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, /* Independent data accesses. */ if (DDR_ARE_DEPENDENT (ddr) == chrec_known) - return false; + return opt_result::success (); if (dra == drb || (DR_IS_READ (dra) && DR_IS_READ (drb))) - return false; + return opt_result::success (); /* We do not have to consider dependences between accesses that belong to the same group, unless the stride could be smaller than the @@ -319,7 +326,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, && (DR_GROUP_FIRST_ELEMENT (stmtinfo_a) == DR_GROUP_FIRST_ELEMENT (stmtinfo_b)) && !STMT_VINFO_STRIDED_P (stmtinfo_a)) - return false; + return opt_result::success (); /* Even if we have an anti-dependence then, as the vectorized loop covers at least two scalar iterations, there is always also a true dependence. @@ -331,7 +338,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, || (DR_IS_WRITE (dra) && DR_IS_READ (drb))) && !alias_sets_conflict_p (get_alias_set (DR_REF (dra)), get_alias_set (DR_REF (drb)))) - return false; + return opt_result::success (); /* Unknown data dependence. */ if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) @@ -343,7 +350,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if ((unsigned int) loop->safelen < *max_vf) *max_vf = loop->safelen; LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo) = false; - return false; + return opt_result::success (); } if (STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a) @@ -361,7 +368,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, DR_REF (drb)); dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); } - return true; + // FIXME: better message here, capturing the data of interest + return opt_result::failure ("can't determine dependence", NULL); } if (dump_enabled_p ()) @@ -378,7 +386,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, } /* Add to list of ddrs that need to be tested at run-time. */ - return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo); + return vect_mark_for_runtime_alias_test (ddr, loop_vinfo); } /* Known data dependence. */ @@ -391,7 +399,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if ((unsigned int) loop->safelen < *max_vf) *max_vf = loop->safelen; LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo) = false; - return false; + return opt_result::success (); } if (STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a) @@ -409,7 +417,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, DR_REF (drb)); dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); } - return true; + return opt_result::failure ("FIXME", NULL); } if (dump_enabled_p ()) @@ -423,7 +431,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); } /* Add to list of ddrs that need to be tested at run-time. */ - return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo); + return vect_mark_for_runtime_alias_test (ddr, loop_vinfo); } loop_depth = index_in_loop_nest (loop->num, DDR_LOOP_NEST (ddr)); @@ -431,7 +439,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if (DDR_COULD_BE_INDEPENDENT_P (ddr) && vect_analyze_possibly_independent_ddr (ddr, loop_vinfo, loop_depth, max_vf)) - return false; + return opt_result::success (); FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v) { @@ -477,7 +485,9 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "READ_WRITE dependence in interleaving.\n"); - return true; + // FIXME: capture stmts + return opt_result::failure ("READ_WRITE dependence in" + " interleaving", NULL); } if (loop->safelen < 2) @@ -488,7 +498,9 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "access also has a zero step\n"); - return true; + // FIXME: capture stmts + return opt_result::failure ("access also has a zero step", + NULL); } else if (TREE_CODE (indicator) != INTEGER_CST) vect_check_nonzero_value (loop_vinfo, indicator); @@ -547,10 +559,12 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, dump_printf (MSG_NOTE, "\n"); } - return true; + // FIXME: capture stmts + return opt_result::failure ("possible dependence between data-refs", + NULL); } - return false; + return opt_result::success (); } /* Function vect_analyze_data_ref_dependences. @@ -559,7 +573,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, exist any data dependences between them. Set *MAX_VF according to the maximum vectorization factor the data dependences allow. */ -bool +opt_result vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo, unsigned int *max_vf) { @@ -591,10 +605,14 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo, *max_vf = LOOP_VINFO_ORIG_MAX_VECT_FACTOR (loop_vinfo); else FOR_EACH_VEC_ELT (LOOP_VINFO_DDRS (loop_vinfo), i, ddr) - if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf)) - return false; + { + opt_result res + = vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf); + if (!res) + return res; + } - return true; + return opt_result::success (); } @@ -1122,7 +1140,7 @@ vect_update_misalignment_for_peel (struct data_reference *dr, Return TRUE if DR can be handled with respect to alignment. */ -static bool +static opt_result verify_data_ref_alignment (data_reference_p dr) { enum dr_alignment_support supportable_dr_alignment @@ -1143,14 +1161,18 @@ verify_data_ref_alignment (data_reference_p dr) DR_REF (dr)); dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); } - return false; + // FIXME: show dr here: + return opt_result::failure (DR_IS_READ (dr) + ? "unsupported unaligned load" + : "unsupported unaligned store", + NULL); } if (supportable_dr_alignment != dr_aligned && dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "Vectorizing an unaligned access.\n"); - return true; + return opt_result::success (); } /* Function vect_verify_datarefs_alignment @@ -1158,7 +1180,7 @@ verify_data_ref_alignment (data_reference_p dr) Return TRUE if all data references in the loop can be handled with respect to alignment. */ -bool +opt_result vect_verify_datarefs_alignment (loop_vec_info vinfo) { vec datarefs = vinfo->shared->datarefs; @@ -1184,11 +1206,12 @@ vect_verify_datarefs_alignment (loop_vec_info vinfo) && !STMT_VINFO_GROUPED_ACCESS (stmt_info)) continue; - if (! verify_data_ref_alignment (dr)) - return false; + opt_result res = verify_data_ref_alignment (dr); + if (!res) + return res; } - return true; + return opt_result::success (); } /* Given an memory reference EXP return whether its alignment is less @@ -1666,7 +1689,7 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, struct data_reference *dr0, (whether to generate regular loads/stores, or with special handling for misalignment). */ -bool +opt_result vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) { vec datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); @@ -1677,7 +1700,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) unsigned int i, j; bool do_peeling = false; bool do_versioning = false; - bool stat; gimple *stmt; stmt_vec_info stmt_info; unsigned int npeel = 0; @@ -2065,7 +2087,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) /* Check if all datarefs are supportable and log. */ if (do_peeling && known_alignment_for_access_p (dr0) && npeel == 0) { - stat = vect_verify_datarefs_alignment (loop_vinfo); + opt_result stat = vect_verify_datarefs_alignment (loop_vinfo); if (!stat) do_peeling = false; else @@ -2149,7 +2171,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) /* The inside-loop cost will be accounted for in vectorizable_load and vectorizable_store correctly with adjusted alignments. Drop the body_cst_vec on the floor here. */ - stat = vect_verify_datarefs_alignment (loop_vinfo); + opt_result stat = vect_verify_datarefs_alignment (loop_vinfo); gcc_assert (stat); return stat; } @@ -2275,7 +2297,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) /* Peeling and versioning can't be done together at this time. */ gcc_assert (! (do_peeling && do_versioning)); - stat = vect_verify_datarefs_alignment (loop_vinfo); + opt_result stat = vect_verify_datarefs_alignment (loop_vinfo); gcc_assert (stat); return stat; } @@ -2283,7 +2305,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) /* This point is reached if neither peeling nor versioning is being done. */ gcc_assert (! (do_peeling || do_versioning)); - stat = vect_verify_datarefs_alignment (loop_vinfo); + opt_result stat = vect_verify_datarefs_alignment (loop_vinfo); return stat; } @@ -2352,7 +2374,7 @@ vect_find_same_alignment_drs (struct data_dependence_relation *ddr) Analyze the alignment of the data-references in the loop. Return FALSE if a data reference is found that cannot be vectorized. */ -bool +opt_result vect_analyze_data_refs_alignment (loop_vec_info vinfo) { DUMP_VECT_SCOPE ("vect_analyze_data_refs_alignment"); @@ -2377,7 +2399,7 @@ vect_analyze_data_refs_alignment (loop_vec_info vinfo) vect_compute_data_ref_alignment (dr); } - return true; + return opt_result::success (); } @@ -2916,7 +2938,7 @@ can_group_stmts_p (gimple *stmt1, gimple *stmt2) FORNOW: handle only arrays and pointer accesses. */ -bool +opt_result vect_analyze_data_ref_accesses (vec_info *vinfo) { unsigned int i; @@ -2926,7 +2948,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo) DUMP_VECT_SCOPE ("vect_analyze_data_ref_accesses"); if (datarefs.is_empty ()) - return true; + return opt_result::success (); /* Sort the array of datarefs to make building the interleaving chains linear. Don't modify the original vector's order, it is needed for @@ -3088,12 +3110,13 @@ vect_analyze_data_ref_accesses (vec_info *vinfo) else { datarefs_copy.release (); - return false; + return opt_result::failure ("complicated access pattern", + vect_dr_stmt (dr)); } } datarefs_copy.release (); - return true; + return opt_result::success (); } /* Function vect_vfa_segment_size. @@ -3351,7 +3374,7 @@ vectorizable_with_step_bound_p (data_reference *dr_a, data_reference *dr_b, Return FALSE if resulting list of ddrs is longer then allowed by PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS, otherwise return TRUE. */ -bool +opt_result vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) { typedef pair_hash tree_pair_hash; @@ -3385,7 +3408,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) } if (may_alias_ddrs.is_empty ()) - return true; + return opt_result::success (); comp_alias_ddrs.create (may_alias_ddrs.length ()); @@ -3560,7 +3583,8 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "not vectorized: compilation time alias.\n"); - return false; + return opt_result::failure ("compilation time alias", stmt_a); + // FIXME: and stmt_b } } @@ -3591,10 +3615,13 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) "run-time tests exceeds %d " "(--param vect-max-version-for-alias-checks)\n", PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS)); - return false; + return opt_result::failure ("number of versioning for alias " + "run-time tests exceeds %d " + "(--param vect-max-version-for-alias-checks)", + NULL); // FIXME: make it variadic! } - return true; + return opt_result::success (); } /* Check whether we can use an internal function for a gather load @@ -3948,7 +3975,7 @@ vect_check_gather_scatter (gimple *stmt, loop_vec_info loop_vinfo, append them to DATAREFS. Return false if datarefs in this stmt cannot be handled. */ -bool +opt_result vect_find_stmt_data_reference (loop_p loop, gimple *stmt, vec *datarefs) { @@ -3956,7 +3983,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, loop vectorization and BB vectorization checks dependences with a stmt walk. */ if (gimple_clobber_p (stmt)) - return true; + return opt_result::success (); if (gimple_has_volatile_ops (stmt)) { @@ -3966,7 +3993,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, "not vectorized: volatile type "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("volatile type", stmt); } if (stmt_can_throw_internal (stmt)) @@ -3978,15 +4005,17 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, "exception "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("statement can throw an exception", stmt); } auto_vec refs; - if (!find_data_references_in_stmt (loop, stmt, &refs)) - return false; + opt_result res = find_data_references_in_stmt (loop, stmt, &refs); + if (!res) + // ^^^ it's failing in here + return res; if (refs.is_empty ()) - return true; + return opt_result::success (); if (refs.length () > 1) { @@ -3997,7 +4026,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, "in stmt: "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("more than one data ref in statement", stmt); } if (gcall *call = dyn_cast (stmt)) @@ -4011,7 +4040,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, "not vectorized: dr in a call "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("dr in a call", stmt); } data_reference_p dr = refs.pop (); @@ -4025,7 +4054,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, "access "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("statement is bitfield access", stmt); } if (DR_BASE_ADDRESS (dr) @@ -4035,7 +4064,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: base addr of dr is a " "constant\n"); - return false; + return opt_result::failure ("base addr of dr is a constant", stmt); } /* Check whether this may be a SIMD lane access and adjust the @@ -4093,7 +4122,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, newdr->aux = (void *)-1; free_data_ref (dr); datarefs->safe_push (newdr); - return true; + return opt_result::success (); } } } @@ -4103,7 +4132,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, } datarefs->safe_push (dr); - return true; + return opt_result::success (); } /* Function vect_analyze_data_refs. @@ -4121,7 +4150,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, */ -bool +opt_result vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) { struct loop *loop = NULL; @@ -4194,7 +4223,7 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) STMT_VINFO_VECTORIZABLE (stmt_info) = false; continue; } - return false; + return opt_result::failure ("data ref analysis failed", stmt); } } @@ -4210,7 +4239,7 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) "failed "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("data ref analysis failed", stmt); } STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) = true; } @@ -4232,7 +4261,8 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) STMT_VINFO_VECTORIZABLE (stmt_info) = false; continue; } - return false; + return opt_result::failure ("base object not addressable for stmt", + stmt); } if (is_a (vinfo) @@ -4248,7 +4278,8 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) "load "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("not suitable for strided load", + stmt); } STMT_VINFO_STRIDED_P (stmt_info) = true; } @@ -4283,10 +4314,12 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) dump_printf (MSG_NOTE, "\n"); } - if (!dr_analyze_innermost (&STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info), - init_ref, loop)) + opt_result res + = dr_analyze_innermost (&STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info), + init_ref, loop); + if (!res) /* dr_analyze_innermost already explained the failure. */ - return false; + return res; if (dump_enabled_p ()) { @@ -4342,7 +4375,8 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) STMT_VINFO_VECTORIZABLE (stmt_info) = false; continue; } - return false; + return opt_result::bad_type ("no vector type for stmt", stmt, + scalar_type); } else { @@ -4379,7 +4413,10 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) "store "); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ((gatherscatter == GATHER) ? + "not suitable for gather load" : + "not suitable for scatter store", + stmt); } STMT_VINFO_GATHER_SCATTER_P (stmt_info) = gatherscatter; } @@ -4389,7 +4426,7 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) longer need to. */ gcc_assert (i == datarefs.length ()); - return true; + return opt_result::success (); } diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index acd1a8c..a3f1041 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -159,7 +159,7 @@ static void vect_estimate_min_profitable_iters (loop_vec_info, int *, int *); statement. VECTYPE_MAYBE_SET_P is true if STMT_VINFO_VECTYPE may already be set for general statements (not just data refs). */ -static bool +static opt_result vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info, bool vectype_maybe_set_p, poly_uint64 *vf, @@ -173,13 +173,14 @@ vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info, { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "skip.\n"); - return true; + return opt_result::success (); } tree stmt_vectype, nunits_vectype; - if (!vect_get_vector_types_for_stmt (stmt_info, &stmt_vectype, - &nunits_vectype)) - return false; + opt_result res = vect_get_vector_types_for_stmt (stmt_info, &stmt_vectype, + &nunits_vectype); + if (!res) + return res; if (stmt_vectype) { @@ -199,7 +200,7 @@ vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info, if (nunits_vectype) vect_update_max_nunits (vf, nunits_vectype); - return true; + return opt_result::success (); } /* Subroutine of vect_determine_vectorization_factor. Set the vector @@ -209,7 +210,7 @@ vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info, add them to MASK_PRODUCERS. Return true on success or false if something prevented vectorization. */ -static bool +static opt_result vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf, vec *mask_producers) { @@ -218,8 +219,10 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf, dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: "); dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0); } - if (!vect_determine_vf_for_stmt_1 (stmt_info, false, vf, mask_producers)) - return false; + opt_result res + = vect_determine_vf_for_stmt_1 (stmt_info, false, vf, mask_producers); + if (!res) + return res; if (STMT_VINFO_IN_PATTERN_P (stmt_info) && STMT_VINFO_RELATED_STMT (stmt_info)) @@ -239,9 +242,10 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf, dump_gimple_stmt (MSG_NOTE, TDF_SLIM, def_stmt_info->stmt, 0); } - if (!vect_determine_vf_for_stmt_1 (def_stmt_info, true, - vf, mask_producers)) - return false; + res = vect_determine_vf_for_stmt_1 (def_stmt_info, true, + vf, mask_producers); + if (!res) + return res; } if (dump_enabled_p ()) @@ -250,11 +254,12 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf, "==> examining pattern statement: "); dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0); } - if (!vect_determine_vf_for_stmt_1 (stmt_info, true, vf, mask_producers)) - return false; + res = vect_determine_vf_for_stmt_1 (stmt_info, true, vf, mask_producers); + if (!res) + return res; } - return true; + return opt_result::success (); } /* Function vect_determine_vectorization_factor @@ -282,7 +287,7 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf, } */ -static bool +static opt_result vect_determine_vectorization_factor (loop_vec_info loop_vinfo) { struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); @@ -341,7 +346,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) scalar_type); dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); } - return false; + return opt_result::bad_type ("unsupported data-type", phi, + scalar_type); } STMT_VINFO_VECTYPE (stmt_info) = vectype; @@ -367,9 +373,11 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) gsi_next (&si)) { stmt_info = vinfo_for_stmt (gsi_stmt (si)); - if (!vect_determine_vf_for_stmt (stmt_info, &vectorization_factor, - &mask_producers)) - return false; + opt_result res + = vect_determine_vf_for_stmt (stmt_info, &vectorization_factor, + &mask_producers); + if (!res) + return res; } } @@ -386,7 +394,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: unsupported data-type\n"); - return false; + return opt_result::failure ("unsupported data-type", NULL); } LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor; @@ -399,7 +407,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) STMT_VINFO_VECTYPE (stmt_info) = mask_type; } - return true; + return opt_result::success (); } @@ -1159,7 +1167,7 @@ vect_compute_single_scalar_iteration_cost (loop_vec_info loop_vinfo) - the number of iterations can be analyzed, i.e, a countable loop. The niter could be analyzed under some assumptions. */ -bool +opt_result vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, tree *assumptions, tree *number_of_iterationsm1, tree *number_of_iterations, gcond **inner_loop_cond) @@ -1189,7 +1197,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: control flow in loop.\n"); - return false; + return opt_result::failure ("control flow in loop", NULL); } if (empty_block_p (loop->header)) @@ -1197,7 +1205,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: empty loop.\n"); - return false; + return opt_result::failure ("empty loop", NULL); } } else @@ -1227,7 +1235,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: multiple nested loops.\n"); - return false; + return opt_result::failure ("multiple nested loops", NULL); } if (loop->num_nodes != 5) @@ -1235,7 +1243,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: control flow in loop.\n"); - return false; + return opt_result::failure ("control flow in loop", NULL); } entryedge = loop_preheader_edge (innerloop); @@ -1246,7 +1254,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: unsupported outerloop form.\n"); - return false; + return opt_result::failure ("unsupported outerloop form", NULL); } /* Analyze the inner-loop. */ @@ -1303,7 +1311,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: latch block not empty.\n"); - return false; + return opt_result::failure ("latch block not empty", NULL); } /* Make sure the exit is not abnormal. */ @@ -1313,7 +1321,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: abnormal loop exit edge.\n"); - return false; + return opt_result::failure ("abnormal loop exit edge", NULL); } *loop_cond = vect_get_loop_niters (loop, assumptions, number_of_iterations, @@ -1323,7 +1331,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: complicated exit condition.\n"); - return false; + return opt_result::failure ("complicated exit condition", NULL); } if (integer_zerop (*assumptions) @@ -1334,7 +1342,8 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: number of iterations cannot be " "computed.\n"); - return false; + return opt_result::failure ("number of iterations cannot be computed", + NULL); } if (integer_zerop (*number_of_iterations)) @@ -1342,24 +1351,26 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: number of iterations = 0.\n"); - return false; + return opt_result::failure ("number of iterations = 0", NULL); } - return true; + return opt_result::success (); } /* Analyze LOOP form and return a loop_vec_info if it is of suitable form. */ -loop_vec_info +opt_loop_vec_info vect_analyze_loop_form (struct loop *loop, vec_info_shared *shared) { tree assumptions, number_of_iterations, number_of_iterationsm1; gcond *loop_cond, *inner_loop_cond = NULL; - if (! vect_analyze_loop_form_1 (loop, &loop_cond, - &assumptions, &number_of_iterationsm1, - &number_of_iterations, &inner_loop_cond)) - return NULL; + opt_result res + = vect_analyze_loop_form_1 (loop, &loop_cond, + &assumptions, &number_of_iterationsm1, + &number_of_iterations, &inner_loop_cond); + if (!res) + return opt_loop_vec_info::failure (res); loop_vec_info loop_vinfo = new _loop_vec_info (loop, shared); LOOP_VINFO_NITERSM1 (loop_vinfo) = number_of_iterationsm1; @@ -1397,7 +1408,7 @@ vect_analyze_loop_form (struct loop *loop, vec_info_shared *shared) gcc_assert (!loop->aux); loop->aux = loop_vinfo; - return loop_vinfo; + return opt_loop_vec_info::success (loop_vinfo); } @@ -1506,7 +1517,7 @@ vect_active_double_reduction_p (stmt_vec_info stmt_info) Scan the loop stmts and make sure they are all vectorizable. */ -static bool +static opt_result vect_analyze_loop_operations (loop_vec_info loop_vinfo) { struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); @@ -1556,7 +1567,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "Unsupported loop-closed phi in " "outer-loop.\n"); - return false; + return opt_result::failure ("Unsupported loop-closed phi in " + "outer-loop", phi); } /* If PHI is used in the outer loop, we check that its operand @@ -1567,23 +1579,23 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) gimple *op_def_stmt; if (gimple_phi_num_args (phi) != 1) - return false; + return opt_result::failure ("unsupported phi", phi); phi_op = PHI_ARG_DEF (phi, 0); if (TREE_CODE (phi_op) != SSA_NAME) - return false; + return opt_result::failure ("unsupported phi", phi); op_def_stmt = SSA_NAME_DEF_STMT (phi_op); if (gimple_nop_p (op_def_stmt) || !flow_bb_inside_loop_p (loop, gimple_bb (op_def_stmt)) || !vinfo_for_stmt (op_def_stmt)) - return false; + return opt_result::failure ("unsupported phi", phi); if (STMT_VINFO_RELEVANT (vinfo_for_stmt (op_def_stmt)) != vect_used_in_outer && STMT_VINFO_RELEVANT (vinfo_for_stmt (op_def_stmt)) != vect_used_in_outer_by_reduction) - return false; + return opt_result::failure ("unsupported phi", phi); } continue; @@ -1599,7 +1611,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: scalar dependence cycle.\n"); - return false; + return opt_result::failure ("scalar dependence cycle", phi); } if (STMT_VINFO_RELEVANT_P (stmt_info)) @@ -1639,10 +1651,14 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) gsi_next (&si)) { gimple *stmt = gsi_stmt (si); - if (!gimple_clobber_p (stmt) - && !vect_analyze_stmt (stmt, &need_to_vectorize, NULL, NULL, - &cost_vec)) - return false; + if (!gimple_clobber_p (stmt)) + { + opt_result res + = vect_analyze_stmt (stmt, &need_to_vectorize, NULL, NULL, + &cost_vec); + if (!res) + return res; + } } } /* bbs */ @@ -1663,10 +1679,11 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: redundant loop. no profit to " "vectorize.\n"); - return false; + return opt_result::failure ("redundant loop. no profit to vectorize", + NULL); } - return true; + return opt_result::success (); } /* Analyze the cost of the loop described by LOOP_VINFO. Decide if it @@ -1764,7 +1781,7 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo) return 1; } -static bool +static opt_result vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs, vec *datarefs, unsigned int *n_stmts) @@ -1778,7 +1795,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs, if (is_gimple_debug (stmt)) continue; ++(*n_stmts); - if (!vect_find_stmt_data_reference (loop, stmt, datarefs)) + opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs); + if (!res) { if (is_gimple_call (stmt) && loop->safelen) { @@ -1786,7 +1804,14 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs, if (fndecl != NULL_TREE) { cgraph_node *node = cgraph_node::get (fndecl); - if (node != NULL && node->simd_clones != NULL) + if (node == NULL) + { + // FIXME: should we return something else? + return res; + //push_vect_problem ("FIXME 1", stmt); + //return false; + } + if (node->simd_clones != NULL) { unsigned int j, n = gimple_call_num_args (stmt); for (j = 0; j < n; j++) @@ -1810,15 +1835,18 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs, } } } - return false; + return res; + //push_vect_problem ("FIXME 2", stmt); + //return false; } /* If dependence analysis will give up due to the limit on the number of datarefs stop here and fail fatally. */ if (datarefs->length () > (unsigned)PARAM_VALUE (PARAM_LOOP_MAX_DATAREFS_FOR_DATADEPS)) - return false; + return opt_result::failure ("exceeded param " + "loop-max-datarefs-for-datadeps", stmt); } - return true; + return opt_result::success (); } /* Function vect_analyze_loop_2. @@ -1826,10 +1854,10 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs, Apply a set of analyses on LOOP, and create a loop_vec_info struct for it. The different analyses will record information in the loop_vec_info struct. */ -static bool +static opt_result vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) { - bool ok; + opt_result ok = opt_result::success (); int res; unsigned int max_vf = MAX_VECTORIZATION_FACTOR; poly_uint64 min_vf = 2; @@ -1845,16 +1873,19 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) /* Gather the data references and count stmts in the loop. */ if (!LOOP_VINFO_DATAREFS (loop_vinfo).exists ()) { - if (!vect_get_datarefs_in_loop (loop, LOOP_VINFO_BBS (loop_vinfo), - &LOOP_VINFO_DATAREFS (loop_vinfo), - n_stmts)) + opt_result res + = vect_get_datarefs_in_loop (loop, LOOP_VINFO_BBS (loop_vinfo), + &LOOP_VINFO_DATAREFS (loop_vinfo), + n_stmts); + if (!res) { + // FIXME: something in here: ^ if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: loop contains function " "calls or data references that cannot " "be analyzed\n"); - return false; + return res; } loop_vinfo->shared->save_datarefs (); } @@ -1870,7 +1901,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad data references.\n"); - return false; + return ok; } /* Classify all cross-iteration scalar data-flow cycles. @@ -1890,7 +1921,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad data access.\n"); - return false; + return ok; } /* Data-flow analysis to detect stmts that do not need to be vectorized. */ @@ -1901,7 +1932,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "unexpected pattern.\n"); - return false; + return ok; } /* While the rest of the analysis below depends on it in some way. */ @@ -1920,7 +1951,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad data dependence.\n"); - return false; + return ok; } LOOP_VINFO_MAX_VECT_FACTOR (loop_vinfo) = max_vf; @@ -1930,7 +1961,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "can't determine vectorization factor.\n"); - return false; + return ok; } if (max_vf != MAX_VECTORIZATION_FACTOR && maybe_lt (max_vf, LOOP_VINFO_VECT_FACTOR (loop_vinfo))) @@ -1938,7 +1969,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad data dependence.\n"); - return false; + return ok; } /* Compute the scalar iteration cost. */ @@ -1950,7 +1981,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts) /* Check the SLP opportunities in the loop, analyze and build SLP trees. */ ok = vect_analyze_slp (loop_vinfo, *n_stmts); if (!ok) - return false; + return ok; /* If there are any SLP instances mark them as pure_slp. */ bool slp = vect_make_slp_decision (loop_vinfo); @@ -1997,7 +2028,7 @@ start_over: if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad data alignment.\n"); - return false; + return ok; } /* Prune the list of ddrs to be tested at run-time by versioning for alias. @@ -2005,7 +2036,7 @@ start_over: since we use grouping information gathered by interleaving analysis. */ ok = vect_prune_runtime_alias_test_list (loop_vinfo); if (!ok) - return false; + return ok; /* Do not invoke vect_enhance_data_refs_alignment for eplilogue vectorization. */ @@ -2019,7 +2050,7 @@ start_over: if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad data alignment.\n"); - return false; + return ok; } } @@ -2042,7 +2073,7 @@ start_over: if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad operation or unsupported loop bound.\n"); - return false; + return ok; } /* Decide whether to use a fully-masked loop for this vectorization @@ -2076,7 +2107,8 @@ start_over: dump_printf_loc (MSG_NOTE, vect_location, "loop has no enough iterations to support" " peeling for gaps.\n"); - return false; + return opt_result::failure ("loop has not enough iterations to" + " support peeling for gaps", NULL); } } @@ -2089,7 +2121,7 @@ start_over: if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "Loop costings not worthwhile.\n"); - return false; + return opt_result::failure ("Loop costings not worthwhile", NULL); } /* Decide whether we need to create an epilogue loop to handle @@ -2174,7 +2206,7 @@ start_over: LOOP_VINFO_VECT_FACTOR (loop_vinfo))); /* Ok to vectorize! */ - return true; + return opt_result::success (); again: /* Try again with SLP forced off but if we didn't do any SLP there is @@ -2286,11 +2318,10 @@ again: for it. The different analyses will record information in the loop_vec_info struct. If ORIG_LOOP_VINFO is not NULL epilogue must be vectorized. */ -loop_vec_info +opt_loop_vec_info vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo, vec_info_shared *shared) { - loop_vec_info loop_vinfo; auto_vector_sizes vector_sizes; /* Autodetect first vector size we try. */ @@ -2307,7 +2338,7 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "outer-loop already vectorized.\n"); - return NULL; + return opt_loop_vec_info::failure ("outer-loop already vectorized"); } if (!find_loop_nest (loop, &shared->loop_nest)) @@ -2317,7 +2348,9 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo, "not vectorized: loop nest containing two " "or more consecutive inner loops cannot be " "vectorized\n"); - return NULL; + return opt_loop_vec_info::failure ("loop nest containing two " + "or more consecutive inner loops" + " cannot be vectorized"); } unsigned n_stmts = 0; @@ -2325,13 +2358,14 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo, while (1) { /* Check the CFG characteristics of the loop (nesting, entry/exit). */ - loop_vinfo = vect_analyze_loop_form (loop, shared); + opt_loop_vec_info loop_vinfo + = vect_analyze_loop_form (loop, shared); if (!loop_vinfo) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "bad loop form.\n"); - return NULL; + return loop_vinfo; } bool fatal = false; @@ -2339,13 +2373,17 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo, if (orig_loop_vinfo) LOOP_VINFO_ORIG_LOOP_INFO (loop_vinfo) = orig_loop_vinfo; - if (vect_analyze_loop_2 (loop_vinfo, fatal, &n_stmts)) + opt_result res = vect_analyze_loop_2 (loop_vinfo, fatal, &n_stmts); + if (res) { LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1; return loop_vinfo; } + /* FIXME: res is false i.e. a failure, but we're throwing away the + problem information here. */ + delete loop_vinfo; if (next_size == 0) @@ -2358,7 +2396,7 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo, if (fatal || next_size == vector_sizes.length () || known_eq (current_vector_size, 0U)) - return NULL; + return opt_loop_vec_info::failure (res); /* Try the next biggest vector size. */ current_vector_size = vector_sizes[next_size++]; diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 528e1d5..984f44b 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -2169,7 +2169,7 @@ vect_analyze_slp_instance (vec_info *vinfo, /* Check if there are stmts in the loop can be vectorized using SLP. Build SLP trees of packed scalar stmts if SLP is possible. */ -bool +opt_result vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) { unsigned int i; @@ -2211,7 +2211,7 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) max_tree_size); } - return true; + return opt_result::success (); } diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index ea303bd..53a0788 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -454,7 +454,7 @@ exist_non_indexing_operands_for_use_p (tree use, gimple *stmt) Return true if everything is as expected. Return false otherwise. */ -static bool +static opt_result process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo, enum vect_relevant relevant, vec *worklist, bool force) @@ -469,25 +469,26 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo, /* case 1: we are only interested in uses that need to be vectorized. Uses that are used for address computation are not considered relevant. */ if (!force && !exist_non_indexing_operands_for_use_p (use, stmt)) - return true; + return opt_result::success (); if (!vect_is_simple_use (use, loop_vinfo, &dt, &def_stmt)) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: unsupported use in stmt.\n"); - return false; + // FIXME: have this come from vect_is_simple_use? + return opt_result::failure ("unsupported use in stmt", stmt); } if (!def_stmt || gimple_nop_p (def_stmt)) - return true; + return opt_result::success (); def_bb = gimple_bb (def_stmt); if (!flow_bb_inside_loop_p (loop, def_bb)) { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "def_stmt is out of loop.\n"); - return true; + return opt_result::success (); } /* case 2: A reduction phi (STMT) defined by a reduction stmt (DEF_STMT). @@ -509,7 +510,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo, gcc_assert (STMT_VINFO_RELEVANT (dstmt_vinfo) < vect_used_by_reduction); gcc_assert (STMT_VINFO_LIVE_P (dstmt_vinfo) || STMT_VINFO_RELEVANT (dstmt_vinfo) > vect_unused_in_scope); - return true; + return opt_result::success (); } /* case 3a: outer-loop stmt defining an inner-loop stmt: @@ -597,12 +598,12 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "induction value on backedge.\n"); - return true; + return opt_result::success (); } vect_mark_relevant (worklist, def_stmt, relevant, false); - return true; + return opt_result::success (); } @@ -622,7 +623,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo, This pass detects such stmts. */ -bool +opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) { struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); @@ -713,7 +714,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "unsupported use of reduction.\n"); - return false; + return opt_result::failure ("unsupported use of reduction", + stmt); } break; @@ -725,8 +727,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "unsupported use of nested cycle.\n"); - - return false; + return opt_result::failure ("unsupported use of nested cycle", + stmt); } break; @@ -738,8 +740,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "unsupported use of double reduction.\n"); - - return false; + return opt_result::failure ("unsupported use of double" + " reduction", stmt); } break; @@ -760,20 +762,28 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) i = 1; if (rhs_code == COND_EXPR && COMPARISON_CLASS_P (op)) { - if (!process_use (stmt, TREE_OPERAND (op, 0), loop_vinfo, - relevant, &worklist, false) - || !process_use (stmt, TREE_OPERAND (op, 1), loop_vinfo, - relevant, &worklist, false)) - return false; + opt_result res + = process_use (stmt, TREE_OPERAND (op, 0), loop_vinfo, + relevant, &worklist, false); + if (!res) + return res; + res = process_use (stmt, TREE_OPERAND (op, 1), loop_vinfo, + relevant, &worklist, false); + if (!res) + return res; i = 2; } for (; i < gimple_num_ops (stmt); i++) { op = gimple_op (stmt, i); - if (TREE_CODE (op) == SSA_NAME - && !process_use (stmt, op, loop_vinfo, relevant, - &worklist, false)) - return false; + if (TREE_CODE (op) == SSA_NAME) + { + opt_result res + = process_use (stmt, op, loop_vinfo, relevant, + &worklist, false); + if (!res) + return res; + } } } else if (is_gimple_call (stmt)) @@ -781,9 +791,11 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) for (i = 0; i < gimple_call_num_args (stmt); i++) { tree arg = gimple_call_arg (stmt, i); - if (!process_use (stmt, arg, loop_vinfo, relevant, - &worklist, false)) - return false; + opt_result res + = process_use (stmt, arg, loop_vinfo, relevant, + &worklist, false); + if (!res) + return res; } } } @@ -791,9 +803,11 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE) { tree op = USE_FROM_PTR (use_p); - if (!process_use (stmt, op, loop_vinfo, relevant, - &worklist, false)) - return false; + opt_result res + = process_use (stmt, op, loop_vinfo, relevant, + &worklist, false); + if (!res) + return res; } if (STMT_VINFO_GATHER_SCATTER_P (stmt_vinfo)) @@ -801,13 +815,15 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) gather_scatter_info gs_info; if (!vect_check_gather_scatter (stmt, loop_vinfo, &gs_info)) gcc_unreachable (); - if (!process_use (stmt, gs_info.offset, loop_vinfo, relevant, - &worklist, true)) - return false; + opt_result res + = process_use (stmt, gs_info.offset, loop_vinfo, relevant, + &worklist, true); + if (!res) + return res; } } /* while worklist */ - return true; + return opt_result::success (); } /* Compute the prologue cost for invariant or constant operands. */ @@ -9335,7 +9351,7 @@ can_vectorize_live_stmts (gimple *stmt, gimple_stmt_iterator *gsi, /* Make sure the statement is vectorizable. */ -bool +opt_result vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, slp_instance node_instance, stmt_vector_for_cost *cost_vec) { @@ -9358,7 +9374,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not vectorized: stmt has volatile operands\n"); - return false; + return opt_result::failure ("stmt has volatile operands", stmt); } if (STMT_VINFO_IN_PATTERN_P (stmt_info) @@ -9381,10 +9397,12 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_def_stmt, 0); } - if (!vect_analyze_stmt (pattern_def_stmt, - need_to_vectorize, node, node_instance, - cost_vec)) - return false; + opt_result res + = vect_analyze_stmt (pattern_def_stmt, + need_to_vectorize, node, node_instance, + cost_vec); + if (!res) + return res; } } } @@ -9427,7 +9445,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n"); - return true; + return opt_result::success (); } } else if (STMT_VINFO_IN_PATTERN_P (stmt_info) @@ -9444,9 +9462,11 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0); } - if (!vect_analyze_stmt (pattern_stmt, need_to_vectorize, node, - node_instance, cost_vec)) - return false; + opt_result res + = vect_analyze_stmt (pattern_stmt, need_to_vectorize, node, + node_instance, cost_vec); + if (!res) + return res; } switch (STMT_VINFO_DEF_TYPE (stmt_info)) @@ -9488,7 +9508,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, { dump_printf_loc (MSG_NOTE, vect_location, "handled only by SLP analysis\n"); - return true; + return opt_result::success (); } ok = true; @@ -9536,7 +9556,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("relevant stmt not supported", stmt); } /* Stmts that are (also) "live" (i.e. - that are used out of the loop) @@ -9552,10 +9572,10 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("live stmt not supported", stmt); } - return true; + return opt_result::success (); } @@ -10622,7 +10642,7 @@ vect_gen_while_not (gimple_seq *seq, tree mask_type, tree start_index, number of units needed to vectorize STMT_INFO, or NULL_TREE if the statement does not help to determine the overall number of units. */ -bool +opt_result vect_get_vector_types_for_stmt (stmt_vec_info stmt_info, tree *stmt_vectype_out, tree *nunits_vectype_out) @@ -10645,7 +10665,7 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "defer to SIMD clone analysis.\n"); - return true; + return opt_result::success (); } if (dump_enabled_p ()) @@ -10654,7 +10674,7 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info, "not vectorized: irregular stmt."); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("irregular stmt", stmt); } if (VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt)))) @@ -10665,7 +10685,7 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info, "not vectorized: vector stmt in loop:"); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); } - return false; + return opt_result::failure ("vector stmt in loop", stmt); } tree vectype; @@ -10697,7 +10717,7 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "pure bool operation.\n"); - return true; + return opt_result::success (); } } @@ -10782,7 +10802,9 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info, dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, nunits_vectype); dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); } - return false; + // FIXME: capture the types + return opt_result::failure ("different sized vector" + " types in statement", NULL); } if (dump_enabled_p ()) @@ -10797,7 +10819,7 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info, } *nunits_vectype_out = nunits_vectype; - return true; + return opt_result::success (); } /* Try to determine the correct vector type for STMT_INFO, which is a diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 81b64c6..4673764 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -1517,7 +1517,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int, extern void vect_finish_replace_stmt (gimple *, gimple *); extern void vect_finish_stmt_generation (gimple *, gimple *, gimple_stmt_iterator *); -extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info); +extern opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info); extern tree vect_get_store_rhs (gimple *); extern tree vect_get_vec_def_for_operand_1 (gimple *, enum vect_def_type); extern tree vect_get_vec_def_for_operand (tree, gimple *, tree = NULL); @@ -1531,7 +1531,7 @@ extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree); extern bool vect_transform_stmt (gimple *, gimple_stmt_iterator *, bool *, slp_tree, slp_instance); extern void vect_remove_stores (gimple *); -extern bool vect_analyze_stmt (gimple *, bool *, slp_tree, slp_instance, +extern opt_result vect_analyze_stmt (gimple *, bool *, slp_tree, slp_instance, stmt_vector_for_cost *); extern bool vectorizable_condition (gimple *, gimple_stmt_iterator *, gimple **, tree, int, slp_tree, @@ -1548,7 +1548,8 @@ extern tree vect_gen_perm_mask_checked (tree, const vec_perm_indices &); extern void optimize_mask_stores (struct loop*); extern gcall *vect_gen_while (tree, tree, tree); extern tree vect_gen_while_not (gimple_seq *, tree, tree, tree); -extern bool vect_get_vector_types_for_stmt (stmt_vec_info, tree *, tree *); +extern opt_result vect_get_vector_types_for_stmt (stmt_vec_info, tree *, + tree *); extern tree vect_get_mask_type_for_stmt (stmt_vec_info); /* In tree-vect-data-refs.c. */ @@ -1557,21 +1558,21 @@ extern enum dr_alignment_support vect_supportable_dr_alignment (struct data_reference *, bool); extern tree vect_get_smallest_scalar_type (gimple *, HOST_WIDE_INT *, HOST_WIDE_INT *); -extern bool vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *); +extern opt_result vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *); extern bool vect_slp_analyze_instance_dependence (slp_instance); -extern bool vect_enhance_data_refs_alignment (loop_vec_info); -extern bool vect_analyze_data_refs_alignment (loop_vec_info); -extern bool vect_verify_datarefs_alignment (loop_vec_info); +extern opt_result vect_enhance_data_refs_alignment (loop_vec_info); +extern opt_result vect_analyze_data_refs_alignment (loop_vec_info); +extern opt_result vect_verify_datarefs_alignment (loop_vec_info); extern bool vect_slp_analyze_and_verify_instance_alignment (slp_instance); -extern bool vect_analyze_data_ref_accesses (vec_info *); -extern bool vect_prune_runtime_alias_test_list (loop_vec_info); +extern opt_result vect_analyze_data_ref_accesses (vec_info *); +extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info); extern bool vect_gather_scatter_fn_p (bool, bool, tree, tree, unsigned int, signop, int, internal_fn *, tree *); extern bool vect_check_gather_scatter (gimple *, loop_vec_info, gather_scatter_info *); -extern bool vect_find_stmt_data_reference (loop_p, gimple *, - vec *); -extern bool vect_analyze_data_refs (vec_info *, poly_uint64 *); +extern opt_result vect_find_stmt_data_reference (loop_p, gimple *, + vec *); +extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *); extern void vect_record_base_alignments (vec_info *); extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree, tree *, gimple_stmt_iterator *, @@ -1607,8 +1608,9 @@ extern gimple *vect_force_simple_reduction (loop_vec_info, gimple *, extern bool check_reduction_path (dump_user_location_t, loop_p, gphi *, tree, enum tree_code); /* Drive for loop analysis stage. */ -extern loop_vec_info vect_analyze_loop (struct loop *, loop_vec_info, - vec_info_shared *); +extern opt_loop_vec_info vect_analyze_loop (struct loop *, + loop_vec_info, + vec_info_shared *); extern tree vect_build_loop_niters (loop_vec_info, bool * = NULL); extern void vect_gen_vector_loop_niters (loop_vec_info, tree, tree *, tree *, bool); @@ -1621,7 +1623,8 @@ extern tree vect_get_loop_mask (gimple_stmt_iterator *, vec_loop_masks *, /* Drive for loop transformation stage. */ extern struct loop *vect_transform_loop (loop_vec_info); -extern loop_vec_info vect_analyze_loop_form (struct loop *, vec_info_shared *); +extern opt_loop_vec_info vect_analyze_loop_form (struct loop *, + vec_info_shared *); extern bool vectorizable_live_operation (gimple *, gimple_stmt_iterator *, slp_tree, int, gimple **, stmt_vector_for_cost *); @@ -1646,7 +1649,7 @@ extern bool vect_transform_slp_perm_load (slp_tree, vec , slp_instance, bool, unsigned *); extern bool vect_slp_analyze_operations (vec_info *); extern bool vect_schedule_slp (vec_info *); -extern bool vect_analyze_slp (vec_info *, unsigned); +extern opt_result vect_analyze_slp (vec_info *, unsigned); extern bool vect_make_slp_decision (loop_vec_info); extern void vect_detect_hybrid_slp (loop_vec_info); extern void vect_get_slp_defs (vec , slp_tree, vec > *); -- 1.8.5.3