diff options
author | David Malcolm <dmalcolm@redhat.com> | 2018-10-04 17:50:52 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2018-10-04 17:50:52 +0000 |
commit | f4ebbd243f887b3c5e01c65ad80a8f64a8261e61 (patch) | |
tree | f76bbe59cb30638b7432efe17c3ddd67c6378b9d /gcc/tree-vect-data-refs.c | |
parent | 7db960c5b6adad2fd11789870aa514985ea0da04 (diff) |
Report vectorization problems via a new opt_problem class
This is v3 of the patch; previous versions were:
v2: https://gcc.gnu.org/ml/gcc-patches/2018-07/msg00446.html
v1: https://gcc.gnu.org/ml/gcc-patches/2018-06/msg01462.html
This patch introduces a class opt_problem, along with wrapper
classes for bool (opt_result) and for pointers (e.g. opt_loop_vec_info
for loop_vec_info).
opt_problem instances are created when an optimization problem
is encountered, but only if dump_enabled_p. They are manually
propagated up the callstack, and are manually reported at the
"top level" of an optimization if dumping is enabled, to give the user
a concise summary of the problem *after* the failure is reported.
In particular, the location of the problematic statement is
captured and emitted, rather than just the loop's location.
For example:
no-vfa-vect-102.c:24:3: missed: couldn't vectorize loop
no-vfa-vect-102.c:27:7: missed: statement clobbers memory: __asm__ __volatile__("" : : : "memory");
Changed in v3:
* This version bootstraps and passes regression testing (on
x86_64-pc-linux-gnu).
* added selftests, to exercise the opt_problem machinery
* removed the "bool to opt_result" ctor, so that attempts to
use e.g. return a bool from an opt_result-returning function
will fail at compile time
* use formatted printing within opt_problem ctor to replace the
various dump_printf_loc calls
* dropped i18n
* changed the sense of vect_analyze_data_ref_dependence's return
value (see the ChangeLog)
* add MSG_PRIORITY_REEMITTED, so that -fopt-info can show the
messages, without them messing up the counts in scan-tree-dump-times
in DejaGnu tests
gcc/ChangeLog:
* Makefile.in (OBJS): Add opt-problem.o.
* dump-context.h: Include "selftest.h.
(selftest::temp_dump_context): New forward decl.
(class dump_context): Make friend of class
selftest::temp_dump_context.
(dump_context::dump_loc_immediate): New decl.
(class dump_pretty_printer): Move here from dumpfile.c.
(class temp_dump_context): Move to namespace selftest.
(temp_dump_context::temp_dump_context): Add param
"forcibly_enable_dumping".
(selftest::verify_dumped_text):
(ASSERT_DUMPED_TEXT_EQ): Move here from dumpfile.c.
(selftest::verify_item):
(ASSERT_IS_TEXT): Move here from dumpfile.c.
(ASSERT_IS_TREE): Likewise.
(ASSERT_IS_GIMPLE): Likewise.
* dumpfile.c (dump_context::dump_loc): Move immediate dumping
to...
(dump_context::dump_loc_immediate): ...this new function.
(class dump_pretty_printer): Move to dump-context.h.
(dump_switch_p_1): Don't enable MSG_PRIORITY_REEMITTED.
(opt_info_switch_p_1): Enable MSG_PRIORITY_REEMITTED.
(temp_dump_context::temp_dump_context): Move to "selftest"
namespace. Add param "forcibly_enable_dumping", and use it to
conditionalize the use of m_pp;
(selftest::verify_dumped_text): Make non-static.
(ASSERT_DUMPED_TEXT_EQ): Move to dump-context.h.
(selftest::verify_item): Make non-static.
(ASSERT_IS_TEXT): Move to dump-context.h.
(ASSERT_IS_TREE): Likewise.
(ASSERT_IS_GIMPLE): Likewise.
(selftest::test_capture_of_dump_calls): Pass "true" for new
param of temp_dump_context.
* dumpfile.h (enum dump_flag): Add MSG_PRIORITY_REEMITTED, adding
it to MSG_ALL_PRIORITIES. Update values of TDF_COMPARE_DEBUG and
TDF_COMPARE_DEBUG.
* opt-problem.cc: New file.
* opt-problem.h: New file.
* optinfo-emit-json.cc
(selftest::test_building_json_from_dump_calls): Pass "true" for
new param of temp_dump_context.
* optinfo.cc (optinfo_kind_to_dump_flag): New function.
(optinfo::emit_for_opt_problem): New function.
(optinfo::emit): Clarity which emit_item is used.
* optinfo.h (optinfo::get_dump_location): New accessor.
(optinfo::emit_for_opt_problem): New decl.
(optinfo::emit): Make const.
* selftest-run-tests.c (selftest::run_tests): Call
selftest::opt_problem_cc_tests.
* selftest.h (selftest::opt_problem_cc_tests): New decl.
* tree-data-ref.c (dr_analyze_innermost): Convert return type from
bool to opt_result, converting fprintf messages to
opt_result::failure_at calls. Add "stmt" param for use by the
failure_at calls.
(create_data_ref): Pass "stmt" to the dr_analyze_innermost call.
(runtime_alias_check_p): Convert return type from bool to
opt_result, converting dump_printf calls to
opt_result::failure_at, using the statement DDR_A for their
location.
(find_data_references_in_stmt): Convert return type from bool to
opt_result, converting "return false" to opt_result::failure_at
with a new message.
* tree-data-ref.h: Include "opt-problem.h".
(dr_analyze_innermost): Convert return type from bool to opt_result,
and add a const gimple * param.
(find_data_references_in_stmt): Convert return type from bool to
opt_result.
(runtime_alias_check_p): Likewise.
* tree-predcom.c (find_looparound_phi): Pass "init_stmt" to
dr_analyze_innermost.
* tree-vect-data-refs.c (vect_mark_for_runtime_alias_test):
Convert return type from bool to opt_result, adding a message for
the PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS zero case.
(vect_analyze_data_ref_dependence): Convert return type from bool
to opt_result. Change sense of return type from "false"
effectively meaning "no problems" to "false" meaning a problem,
so that "return false" becomes "return opt_result::success".
Convert "return true" calls to opt_result::failure_at, using
the location of statement A rather than vect_location.
(vect_analyze_data_ref_dependences): Convert return type from bool
to opt_result.
(verify_data_ref_alignment): Likewise, converting dump_printf_loc
calls to opt_result::failure_at, using the stmt location rather
than vect_location.
(vect_verify_datarefs_alignment): Convert return type from bool
to opt_result.
(vect_enhance_data_refs_alignment): Likewise. Split local "stat"
into multiple more-tightly-scoped copies.
(vect_analyze_data_refs_alignment): Convert return type from bool
to opt_result.
(vect_analyze_data_ref_accesses): Likewise, converting a
"return false" to a "return opt_result::failure_at", adding a
new message.
(vect_prune_runtime_alias_test_list): Convert return type from
bool to opt_result, converting dump_printf_loc to
opt_result::failure_at. Add a %G to show the pertinent statement,
and use the stmt's location rather than vect_location.
(vect_find_stmt_data_reference): Convert return type from
bool to opt_result, converting dump_printf_loc to
opt_result::failure_at, using stmt's location.
(vect_analyze_data_refs): Convert return type from bool to
opt_result. Convert "return false" to "return
opt_result::failure_at", adding messages as needed.
* tree-vect-loop.c (vect_determine_vf_for_stmt_1): Convert return
type from bool to opt_result.
(vect_determine_vf_for_stmt): Likewise.
(vect_determine_vectorization_factor): Likewise, converting
dump_printf_loc to opt_result::failure_at, using location of phi
rather than vect_location.
(vect_analyze_loop_form_1): Convert return type from bool to
opt_result, converting dump_printf_loc calls, retaining the use of
vect_location.
(vect_analyze_loop_form): Convert return type from loop_vec_info
to opt_loop_vec_info.
(vect_analyze_loop_operations): Convert return type from bool to
opt_result, converting dump_printf_loc calls, using the location
of phi/stmt rather than vect_location where available. Convert
various "return false" to "return opt_result::failure_at" with
"unsupported phi" messages.
(vect_get_datarefs_in_loop): Convert return type from bool to
opt_result. Add a message for the
PARAM_LOOP_MAX_DATAREFS_FOR_DATADEPS failure.
(vect_analyze_loop_2): Convert return type from bool to
opt_result. Ensure "ok" is set to a opt_result::failure_at before
each "goto again;", adding new messages where needed.
Add "unsupported grouped {store|load}" messages.
(vect_analyze_loop): Convert return type from loop_vec_info to
opt_loop_vec_info.
* tree-vect-slp.c (vect_analyze_slp): Convert return type from
bool to opt_result.
* tree-vect-stmts.c (process_use): Likewise, converting
dump_printf_loc call and using stmt location, rather than
vect_location.
(vect_mark_stmts_to_be_vectorized): Likeise.
(vect_analyze_stmt): Likewise, adding a %G.
(vect_get_vector_types_for_stmt): Convert return type from bool to
opt_result, converting dump_printf_loc calls and using stmt
location, rather than vect_location.
(vect_get_mask_type_for_stmt): Convert return type from tree to
opt_tree, converting dump_printf_loc calls and using stmt location.
* tree-vectorizer.c: Include "opt-problem.h.
(try_vectorize_loop_1): Flag "Analyzing loop at" dump message as
MSG_PRIORITY_INTERNALS. Convert local "loop_vinfo" from
loop_vec_info to opt_loop_vec_info. If if fails, and dumping is
enabled, use it to report at the top level "couldn't vectorize
loop" followed by the problem.
* tree-vectorizer.h (opt_loop_vec_info): New typedef.
(vect_mark_stmts_to_be_vectorized): Convert return type from bool
to opt_result.
(vect_analyze_stmt): Likewise.
(vect_get_vector_types_for_stmt): Likewise.
(tree vect_get_mask_type_for_stmt): Likewise.
(vect_analyze_data_ref_dependences): Likewise.
(vect_enhance_data_refs_alignment): Likewise.
(vect_analyze_data_refs_alignment): Likewise.
(vect_verify_datarefs_alignment): Likewise.
(vect_analyze_data_ref_accesses): Likewise.
(vect_prune_runtime_alias_test_list): Likewise.
(vect_find_stmt_data_reference): Likewise.
(vect_analyze_data_refs): Likewise.
(vect_analyze_loop): Convert return type from loop_vec_info to
opt_loop_vec_info.
(vect_analyze_loop_form): Likewise.
(vect_analyze_slp): Convert return type from bool to opt_result.
gcc/testsuite/ChangeLog:
* gcc.dg/vect/nodump-vect-opt-info-2.c: New test.
* gcc.dg/vect/vect-alias-check-4.c: Add "-fopt-info-vec-all" to
dg-additional-options. Add dg-message and dg-missed directives
to verify that -fopt-info messages are written at the correct
locations.
From-SVN: r264852
Diffstat (limited to 'gcc/tree-vect-data-refs.c')
-rw-r--r-- | gcc/tree-vect-data-refs.c | 347 |
1 files changed, 155 insertions, 192 deletions
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 56b7968dab0..c4805e72447 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -156,20 +156,25 @@ vect_get_smallest_scalar_type (stmt_vec_info stmt_info, 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; + return opt_result::failure_at (vect_location, + "will not create alias checks, as" + " --param vect-max-version-for-alias-checks" + " == 0\n"); - 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. */ @@ -277,12 +282,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) @@ -305,11 +312,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 @@ -318,7 +325,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. @@ -330,7 +337,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) @@ -342,28 +349,25 @@ 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) || STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "versioning for alias not supported for: " - "can't determine dependence between %T and %T\n", - DR_REF (dra), DR_REF (drb)); - return true; - } + return opt_result::failure_at + (stmtinfo_a->stmt, + "versioning for alias not supported for: " + "can't determine dependence between %T and %T\n", + DR_REF (dra), DR_REF (drb)); if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmtinfo_a->stmt, "versioning for alias required: " "can't determine dependence between %T and %T\n", DR_REF (dra), DR_REF (drb)); /* 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. */ @@ -376,27 +380,24 @@ 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) || STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "versioning for alias not supported for: " - "bad dist vector for %T and %T\n", - DR_REF (dra), DR_REF (drb)); - return true; - } + return opt_result::failure_at + (stmtinfo_a->stmt, + "versioning for alias not supported for: " + "bad dist vector for %T and %T\n", + DR_REF (dra), DR_REF (drb)); if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmtinfo_a->stmt, "versioning for alias required: " "bad dist vector for %T and %T\n", DR_REF (dra), DR_REF (drb)); /* 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)); @@ -404,7 +405,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) { @@ -440,23 +441,16 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, a[i+1] = ...; where loads from the group interleave with the store. */ if (!vect_preserves_scalar_order_p (dr_info_a, dr_info_b)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "READ_WRITE dependence in interleaving.\n"); - return true; - } + return opt_result::failure_at (stmtinfo_a->stmt, + "READ_WRITE dependence" + " in interleaving.\n"); if (loop->safelen < 2) { tree indicator = dr_zero_step_indicator (dra); if (!indicator || integer_zerop (indicator)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "access also has a zero step\n"); - return true; - } + return opt_result::failure_at (stmtinfo_a->stmt, + "access also has a zero step\n"); else if (TREE_CODE (indicator) != INTEGER_CST) vect_check_nonzero_value (loop_vinfo, indicator); } @@ -503,16 +497,13 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, continue; } - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized, possible dependence " - "between data-refs %T and %T\n", - DR_REF (dra), DR_REF (drb)); - - return true; + return opt_result::failure_at (stmtinfo_a->stmt, + "not vectorized, possible dependence " + "between data-refs %T and %T\n", + DR_REF (dra), DR_REF (drb)); } - return false; + return opt_result::success (); } /* Function vect_analyze_data_ref_dependences. @@ -521,7 +512,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) { @@ -553,10 +544,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 (); } @@ -1055,33 +1050,24 @@ vect_update_misalignment_for_peel (dr_vec_info *dr_info, Return TRUE if DR_INFO can be handled with respect to alignment. */ -static bool +static opt_result verify_data_ref_alignment (dr_vec_info *dr_info) { enum dr_alignment_support supportable_dr_alignment = vect_supportable_dr_alignment (dr_info, false); if (!supportable_dr_alignment) - { - if (dump_enabled_p ()) - { - if (DR_IS_READ (dr_info->dr)) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: unsupported unaligned load."); - else - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: unsupported unaligned " - "store."); - - dump_printf (MSG_MISSED_OPTIMIZATION, "%T\n", DR_REF (dr_info->dr)); - } - return false; - } + return opt_result::failure_at + (dr_info->stmt->stmt, + DR_IS_READ (dr_info->dr) + ? "not vectorized: unsupported unaligned load: %T\n" + : "not vectorized: unsupported unaligned store: %T\n", + DR_REF (dr_info->dr)); 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 @@ -1089,7 +1075,7 @@ verify_data_ref_alignment (dr_vec_info *dr_info) 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<data_reference_p> datarefs = vinfo->shared->datarefs; @@ -1115,11 +1101,12 @@ vect_verify_datarefs_alignment (loop_vec_info vinfo) && !STMT_VINFO_GROUPED_ACCESS (stmt_info)) continue; - if (! verify_data_ref_alignment (dr_info)) - return false; + opt_result res = verify_data_ref_alignment (dr_info); + if (!res) + return res; } - return true; + return opt_result::success (); } /* Given an memory reference EXP return whether its alignment is less @@ -1593,7 +1580,7 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info, (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<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); @@ -1605,7 +1592,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; unsigned int npeel = 0; bool one_misalignment_known = false; bool one_misalignment_unknown = false; @@ -1992,7 +1978,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_info) && npeel == 0) { - stat = vect_verify_datarefs_alignment (loop_vinfo); + opt_result stat = vect_verify_datarefs_alignment (loop_vinfo); if (!stat) do_peeling = false; else @@ -2078,7 +2064,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; } @@ -2201,7 +2187,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; } @@ -2209,7 +2195,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; } @@ -2275,7 +2261,7 @@ vect_find_same_alignment_drs (vec_info *vinfo, 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"); @@ -2300,7 +2286,7 @@ vect_analyze_data_refs_alignment (loop_vec_info vinfo) vect_compute_data_ref_alignment (dr_info); } - return true; + return opt_result::success (); } @@ -2825,7 +2811,7 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info) FORNOW: handle only arrays and pointer accesses. */ -bool +opt_result vect_analyze_data_ref_accesses (vec_info *vinfo) { unsigned int i; @@ -2835,7 +2821,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 @@ -2994,13 +2980,15 @@ vect_analyze_data_ref_accesses (vec_info *vinfo) else { datarefs_copy.release (); - return false; + return opt_result::failure_at (dr_info->stmt->stmt, + "not vectorized:" + " complicated access pattern.\n"); } } } datarefs_copy.release (); - return true; + return opt_result::success (); } /* Function vect_vfa_segment_size. @@ -3258,7 +3246,7 @@ vectorizable_with_step_bound_p (dr_vec_info *dr_info_a, dr_vec_info *dr_info_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_operand_hash, tree_operand_hash> tree_pair_hash; @@ -3292,7 +3280,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 ()); @@ -3452,12 +3440,11 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) continue; if (res == 1) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "not vectorized: compilation time alias.\n"); - return false; - } + return opt_result::failure_at (stmt_info_b->stmt, + "not vectorized:" + " compilation time alias: %G%G", + stmt_info_a->stmt, + stmt_info_b->stmt); } dr_with_seg_len_pair_t dr_with_seg_len_pair @@ -3482,17 +3469,14 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) "improved number of alias checks from %d to %d\n", may_alias_ddrs.length (), count); if ((int) count > PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "number of versioning for alias " - "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 true; + return opt_result::failure_at + (vect_location, + "number of versioning for alias " + "run-time tests exceeds %d " + "(--param vect-max-version-for-alias-checks)\n", + PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS)); + + return opt_result::success (); } /* Check whether we can use an internal function for a gather load @@ -3846,7 +3830,7 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, 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<data_reference_p> *datarefs) { @@ -3854,72 +3838,50 @@ 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)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: volatile type %G", stmt); - return false; - } + return opt_result::failure_at (stmt, "not vectorized: volatile type: %G", + stmt); if (stmt_can_throw_internal (stmt)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: statement can throw an exception %G", - stmt); - return false; - } + return opt_result::failure_at (stmt, + "not vectorized:" + " statement can throw an exception: %G", + stmt); auto_vec<data_reference_p, 2> 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) + return res; if (refs.is_empty ()) - return true; + return opt_result::success (); if (refs.length () > 1) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: more than one data ref " - "in stmt: %G", stmt); - return false; - } + return opt_result::failure_at (stmt, + "not vectorized:" + " more than one data ref in stmt: %G", stmt); if (gcall *call = dyn_cast <gcall *> (stmt)) if (!gimple_call_internal_p (call) || (gimple_call_internal_fn (call) != IFN_MASK_LOAD && gimple_call_internal_fn (call) != IFN_MASK_STORE)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: dr in a call %G", stmt); - return false; - } + return opt_result::failure_at (stmt, + "not vectorized: dr in a call %G", stmt); data_reference_p dr = refs.pop (); if (TREE_CODE (DR_REF (dr)) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (dr), 1))) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: statement is bitfield " - "access %G", stmt); - return false; - } + return opt_result::failure_at (stmt, + "not vectorized:" + " statement is bitfield access %G", stmt); if (DR_BASE_ADDRESS (dr) && TREE_CODE (DR_BASE_ADDRESS (dr)) == INTEGER_CST) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: base addr of dr is a " - "constant\n"); - return false; - } + return opt_result::failure_at (stmt, + "not vectorized:" + " base addr of dr is a constant\n"); /* Check whether this may be a SIMD lane access and adjust the DR to make it easier for us to handle it. */ @@ -3976,7 +3938,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 (); } } } @@ -3986,7 +3948,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. @@ -4004,7 +3966,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; @@ -4074,7 +4036,10 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) STMT_VINFO_VECTORIZABLE (stmt_info) = false; continue; } - return false; + return opt_result::failure_at (stmt_info->stmt, + "not vectorized:" + " data ref analysis failed: %G", + stmt_info->stmt); } } @@ -4082,13 +4047,10 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) if (dr->aux == (void *)-1) { if (nested_in_vect_loop_p (loop, stmt_info)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: data ref analysis " - "failed %G", stmt_info->stmt); - return false; - } + return opt_result::failure_at (stmt_info->stmt, + "not vectorized:" + " data ref analysis failed: %G", + stmt_info->stmt); STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) = true; } @@ -4106,7 +4068,10 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) STMT_VINFO_VECTORIZABLE (stmt_info) = false; continue; } - return false; + return opt_result::failure_at (stmt_info->stmt, + "not vectorized: base object not" + " addressable for stmt: %G", + stmt_info->stmt); } if (is_a <loop_vec_info> (vinfo) @@ -4114,13 +4079,10 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) && TREE_CODE (DR_STEP (dr)) != INTEGER_CST) { if (nested_in_vect_loop_p (loop, stmt_info)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: not suitable for strided " - "load %G", stmt_info->stmt); - return false; - } + return opt_result::failure_at (stmt_info->stmt, + "not vectorized:" + "not suitable for strided load %G", + stmt_info->stmt); STMT_VINFO_STRIDED_P (stmt_info) = true; } @@ -4150,10 +4112,12 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) dump_printf_loc (MSG_NOTE, vect_location, "analyze in outer loop: %T\n", init_ref); - 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, stmt_info->stmt); + if (!res) /* dr_analyze_innermost already explained the failure. */ - return false; + return res; if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -4199,7 +4163,11 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) STMT_VINFO_VECTORIZABLE (stmt_info) = false; continue; } - return false; + return opt_result::failure_at (stmt_info->stmt, + "not vectorized:" + " no vectype for stmt: %G" + " scalar_type: %T\n", + stmt_info->stmt, scalar_type); } else { @@ -4221,17 +4189,12 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf) as_a <loop_vec_info> (vinfo), &gs_info) || !get_vectype_for_scalar_type (TREE_TYPE (gs_info.offset))) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - (gatherscatter == GATHER) ? - "not vectorized: not suitable for gather " - "load %G" : - "not vectorized: not suitable for scatter " - "store %G", - stmt_info->stmt); - return false; - } + return opt_result::failure_at + (stmt_info->stmt, + (gatherscatter == GATHER) ? + "not vectorized: not suitable for gather load %G" : + "not vectorized: not suitable for scatter store %G", + stmt_info->stmt); STMT_VINFO_GATHER_SCATTER_P (stmt_info) = gatherscatter; } } @@ -4240,7 +4203,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 (); } |