From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 84662 invoked by alias); 25 Jun 2018 09:15:13 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 65699 invoked by uid 89); 25 Jun 2018 09:10:21 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.2 required=5.0 tests=BAYES_50,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,SPF_PASS autolearn=ham version=3.3.2 spammy=stronger, gmbh, GmbH, ok X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 25 Jun 2018 09:10:18 +0000 Received: from relay1.suse.de (charybdis-ext-too.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 01BEEAB43; Mon, 25 Jun 2018 09:10:15 +0000 (UTC) Date: Mon, 25 Jun 2018 09:15:00 -0000 From: Richard Biener To: David Malcolm cc: gcc-patches@gcc.gnu.org, Richard Sandiford Subject: Re: [PATCH] [RFC] Higher-level reporting of vectorization problems In-Reply-To: <1529701789-40263-1-git-send-email-dmalcolm@redhat.com> Message-ID: References: <1529701789-40263-1-git-send-email-dmalcolm@redhat.com> User-Agent: Alpine 2.20 (LSU 67 2015-01-07) MIME-Version: 1.0 Content-Type: multipart/mixed; BOUNDARY="-1609908220-2045961769-1529917815=:5043" X-SW-Source: 2018-06/txt/msg01523.txt.bz2 This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. ---1609908220-2045961769-1529917815=:5043 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Content-length: 16347 On Fri, 22 Jun 2018, David Malcolm wrote: > NightStrike and I were chatting on IRC last week about > issues with trying to vectorize the following code: > > #include > std::size_t f(std::vector> const & v) { > std::size_t ret = 0; > for (auto const & w: v) > ret += w.size(); > return ret; > } > > icc could vectorize it, but gcc couldn't, but neither of us could > immediately figure out what the problem was. > > Using -fopt-info leads to a wall of text. > > I tried using my patch here: > > "[PATCH] v3 of optinfo, remarks and optimization records" > https://gcc.gnu.org/ml/gcc-patches/2018-06/msg01267.html > > It improved things somewhat, by showing: > (a) the nesting structure via indentation, and > (b) the GCC line at which each message is emitted (by using the > "remark" output) > > but it's still a wall of text: > > https://dmalcolm.fedorapeople.org/gcc/2018-06-18/test.cc.remarks.html > https://dmalcolm.fedorapeople.org/gcc/2018-06-18/test.cc.d/..%7C..%7Csrc%7Ctest.cc.html#line-4 > > It doesn't yet provide a simple high-level message to a > tech-savvy user on what they need to do to get GCC to > vectorize their loop. Yeah, in particular the vectorizer is way too noisy in its low-level functions. IIRC -fopt-info-vec-missed is "somewhat" better: t.C:4:26: note: step unknown. t.C:4:26: note: vector alignment may not be reachable t.C:4:26: note: not ssa-name. t.C:4:26: note: use not simple. t.C:4:26: note: not ssa-name. t.C:4:26: note: use not simple. t.C:4:26: note: no array mode for V2DI[3] t.C:4:26: note: Data access with gaps requires scalar epilogue loop t.C:4:26: note: can't use a fully-masked loop because the target doesn't have the appropriate masked load or store. t.C:4:26: note: not ssa-name. t.C:4:26: note: use not simple. t.C:4:26: note: not ssa-name. t.C:4:26: note: use not simple. t.C:4:26: note: no array mode for V2DI[3] t.C:4:26: note: Data access with gaps requires scalar epilogue loop t.C:4:26: note: op not supported by target. t.C:4:26: note: not vectorized: relevant stmt not supported: _15 = _14 /[ex] 4; t.C:4:26: note: bad operation or unsupported loop bound. t.C:4:26: note: not vectorized: no grouped stores in basic block. t.C:4:26: note: not vectorized: no grouped stores in basic block. t.C:6:12: note: not vectorized: not enough data-refs in basic block. > The pertinent dump messages are: > > test.cc:4:23: remark: === try_vectorize_loop_1 === [../../src/gcc/tree-vectorizer.c:674:try_vectorize_loop_1] > cc1plus: remark: > Analyzing loop at test.cc:4 [../../src/gcc/dumpfile.c:735:ensure_pending_optinfo] > test.cc:4:23: remark: === analyze_loop_nest === [../../src/gcc/tree-vect-loop.c:2299:vect_analyze_loop] > [...snip...] > test.cc:4:23: remark: === vect_analyze_loop_operations === [../../src/gcc/tree-vect-loop.c:1520:vect_analyze_loop_operations] > [...snip...] > test.cc:4:23: remark: ==> examining statement: ‘_15 = _14 /[ex] 4;’ [../../src/gcc/tree-vect-stmts.c:9382:vect_analyze_stmt] > test.cc:4:23: remark: vect_is_simple_use: operand ‘_14’ [../../src/gcc/tree-vect-stmts.c:10064:vect_is_simple_use] > test.cc:4:23: remark: def_stmt: ‘_14 = _8 - _7;’ [../../src/gcc/tree-vect-stmts.c:10098:vect_is_simple_use] > test.cc:4:23: remark: type of def: internal [../../src/gcc/tree-vect-stmts.c:10112:vect_is_simple_use] > test.cc:4:23: remark: vect_is_simple_use: operand ‘4’ [../../src/gcc/tree-vect-stmts.c:10064:vect_is_simple_use] > test.cc:4:23: remark: op not supported by target. [../../src/gcc/tree-vect-stmts.c:5932:vectorizable_operation] > test.cc:4:23: remark: not vectorized: relevant stmt not supported: ‘_15 = _14 /[ex] 4;’ [../../src/gcc/tree-vect-stmts.c:9565:vect_analyze_stmt] > test.cc:4:23: remark: bad operation or unsupported loop bound. [../../src/gcc/tree-vect-loop.c:2043:vect_analyze_loop_2] > cc1plus: remark: vectorized 0 loops in function. [../../src/gcc/tree-vectorizer.c:904:vectorize_loops] > > In particular, that complaint from > [../../src/gcc/tree-vect-stmts.c:9565:vect_analyze_stmt] > is coming from: > > if (!ok) > { > if (dump_enabled_p ()) > { > dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, > "not vectorized: relevant stmt not "); > dump_printf (MSG_MISSED_OPTIMIZATION, "supported: "); > dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); > } > > return false; > } > > This got me thinking: the user presumably wants to know several > things: > > * the location of the loop that can't be vectorized (vect_location > captures this) > * location of the problematic statement > * why it's problematic > * the problematic statement itself. > > The following is an experiment at capturing that information, by > recording an "opt_problem" instance describing what the optimization > problem is, created deep in the callstack when it occurs, for use > later on back at the top of the vectorization callstack. Nice idea. Of course the issue is then for which issues to exactly create those. Like all of the MSG_MISSED_OPTIMIZATION dumpings? I guess the vectorizer needs some axing of useless messages and/or we need a MSG_DEBUG to have an additional level below MSG_NOTE. > This extra work is only done if dump_enabled_p. > > It feels vaguely analogous to an exception object (in terms of > packaging up a problem that occurs deep in the stack for reporting > back at a higher level). > > With this patch, we emit: > > ../../src/test.cc: In function ‘std::size_t f(const std::vector >&)’: > ../../src/test.cc:4:23: remark: couldn't vectorize loop > for (auto const & w: v) > ^ > In file included from ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:64, > from ../../src/test.cc:1: > ../x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_vector.h:806:50: > note: relevant stmt not supported: ‘_15 = _14 /[ex] 4;’ > { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } > ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ > > which reports both the location of the loop and the statement that's > problematic (if I'm reading it right, the pointer arithmetic leads to a > division by 4, and presumably we're not able to handle that). Quite likely because we only handle TRUNC_DIV_EXPR and not EXACT_DIV_EXPR which we can handle the same semantically (EXACT_DIV_EXPR just gives us stronger guarantees). diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 9654bd7818a..0ab977adf33 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -2524,6 +2524,7 @@ vect_recog_divmod_pattern (vec *stmts, tree *type_out) switch (rhs_code) { case TRUNC_DIV_EXPR: + case EXACT_DIV_EXPR: case TRUNC_MOD_EXPR: break; default: @@ -2573,7 +2574,8 @@ vect_recog_divmod_pattern (vec *stmts, tree *type_out) cond = build2 (LT_EXPR, boolean_type_node, oprnd0, build_int_cst (itype, 0)); - if (rhs_code == TRUNC_DIV_EXPR) + if (rhs_code == TRUNC_DIV_EXPR + || rhs_code == EXACT_DIV_EXPR) { tree var = vect_recog_temp_ssa_var (itype, NULL); tree shift; gets us to t.C:4:26: note: not vectorized: relevant stmt not supported: patt_25 = _14 < 0 ? 3 : 0; or with -mavx2 t.C:4:26: note: not vectorized: relevant stmt not supported: patt_18 = patt_19 >> 2; Richard. > (not bootstrapped or anything, just experimenting at this stage) > > Thoughts? > > gcc/ChangeLog: > * Makefile.in (OBJS): Add opt-problem.o. > * opt-problem.cc: New file. > * opt-problem.h: New file. > * tree-vect-stmts.c (vect_analyze_stmt): Replace "not vectorized" > dumps with calls to push_vect_problem. > * tree-vectorizer.c: Include "diagnostic-core.h" and > "opt-problem.h". > (try_vectorize_loop_1): If the_vect_problem has been set by > vect_analyze_loop, issue a "couldn't vectorize loop" remark and > the reason, clearing it. > (the_vect_problem): New global. > (push_vect_problem): New function. > * tree-vectorizer.h (the_vect_problem): New decl. > (push_vect_problem): New decl. > --- > gcc/Makefile.in | 1 + > gcc/opt-problem.cc | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ > gcc/opt-problem.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ > gcc/tree-vect-stmts.c | 16 ++-------------- > gcc/tree-vectorizer.c | 33 +++++++++++++++++++++++++++++++++ > gcc/tree-vectorizer.h | 7 +++++++ > 6 files changed, 137 insertions(+), 14 deletions(-) > create mode 100644 gcc/opt-problem.cc > create mode 100644 gcc/opt-problem.h > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index 68e79a6..8df859c 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1425,6 +1425,7 @@ OBJS = \ > optinfo.o \ > optinfo-emit-diagnostics.o \ > optinfo-emit-json.o \ > + opt-problem.o \ > optabs.o \ > optabs-libfuncs.o \ > optabs-query.o \ > diff --git a/gcc/opt-problem.cc b/gcc/opt-problem.cc > new file mode 100644 > index 0000000..78d5200 > --- /dev/null > +++ b/gcc/opt-problem.cc > @@ -0,0 +1,49 @@ > +/* Rich information on why an optimization wasn't possible. > + Copyright (C) 2018 Free Software Foundation, Inc. > + Contributed by David Malcolm . > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +. */ > + > +#include "config.h" > +#include "system.h" > +#include "coretypes.h" > +#include "backend.h" > +#include "diagnostic.h" > +#include "tree.h" > +#include "gimple.h" > +#include "pretty-print.h" > +#include "gimple-pretty-print.h" > +#include "opt-problem.h" > + > +/* Emit a diagnostic note describing why an optimization wasn't possible. */ > + > +void > +opt_problem::report_reason () > +{ > + bool show_color = pp_show_color (global_dc->printer); > + > + pretty_printer pp; > + pp_string (&pp, m_text); > + pp_string (&pp, ": "); > + pp_begin_quote (&pp, show_color); > + pp_gimple_stmt_1 (&pp, m_stmt, 0, TDF_SLIM); > + pp_end_quote (&pp, show_color); > + > + const char *msg = pp_formatted_text (&pp); > + > + inform (gimple_location_safe (m_stmt), "%s", msg); > +} > diff --git a/gcc/opt-problem.h b/gcc/opt-problem.h > new file mode 100644 > index 0000000..406f348 > --- /dev/null > +++ b/gcc/opt-problem.h > @@ -0,0 +1,45 @@ > +/* Rich information on why an optimization wasn't possible. > + Copyright (C) 2018 Free Software Foundation, Inc. > + Contributed by David Malcolm . > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +. */ > + > +#ifndef GCC_OPT_PROBLEM_H > +#define GCC_OPT_PROBLEM_H > + > +/* When -fopt-info is enabled: information about why an optimization > + failed (e.g. vectorization). */ > + > +class GTY(()) opt_problem > +{ > + public: > + opt_problem (const char *text, gimple *stmt) > + : m_text (text), m_stmt (stmt) > + { > + /* We shouldn't be bothering to construct these objects if > + dumping isn't enabled. */ > + gcc_assert (dump_enabled_p ()); > + } > + > + void report_reason (); > + > + private: > + const char *m_text; > + gimple *m_stmt; > +}; > + > +#endif /* #ifndef GCC_OPT_PROBLEM_H */ > diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c > index 1181bc9..d9727eb 100644 > --- a/gcc/tree-vect-stmts.c > +++ b/gcc/tree-vect-stmts.c > @@ -9559,14 +9559,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, > > if (!ok) > { > - if (dump_enabled_p ()) > - { > - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, > - "not vectorized: relevant stmt not "); > - dump_printf (MSG_MISSED_OPTIMIZATION, "supported: "); > - dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); > - } > - > + push_vect_problem ("relevant stmt not supported", stmt); > return false; > } > > @@ -9576,12 +9569,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node, > && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type > && !can_vectorize_live_stmts (stmt, NULL, node, NULL, cost_vec)) > { > - if (dump_enabled_p ()) > - { > - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, > - "not vectorized: live stmt not supported: "); > - dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); > - } > + push_vect_problem ("live stmt not supported", stmt); > > return false; > } > diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c > index c33f355..2127f2e 100644 > --- a/gcc/tree-vectorizer.c > +++ b/gcc/tree-vectorizer.c > @@ -79,6 +79,8 @@ along with GCC; see the file COPYING3. If not see > #include "stringpool.h" > #include "attribs.h" > #include "gimple-pretty-print.h" > +#include "diagnostic-core.h" > +#include "opt-problem.h" > > > /* Loop or bb location, with hotness information. */ > @@ -682,6 +684,15 @@ try_vectorize_loop_1 (hash_table *&simduid_to_vf_htab, > loop_vec_info loop_vinfo = vect_analyze_loop (loop, orig_loop_vinfo); > loop->aux = loop_vinfo; > > + if (the_vect_problem) > + { > + if (remark (vect_location.get_location_t (), 0, > + "couldn't vectorize loop")) > + the_vect_problem->report_reason (); > + delete the_vect_problem; > + the_vect_problem = NULL; > + } > + > if (!loop_vinfo || !LOOP_VINFO_VECTORIZABLE_P (loop_vinfo)) > { > /* Free existing information if loop is analyzed with some > @@ -1294,3 +1305,25 @@ make_pass_ipa_increase_alignment (gcc::context *ctxt) > { > return new pass_ipa_increase_alignment (ctxt); > } > + > +/* Singleton instance. */ > + > +opt_problem *the_vect_problem; > + > +/* If dumps are enabled emit a "not vectorized" message with the given > + text relating to STMT, and record a opt_problem instance for later > + use. */ > +// FIXME: maybe a stack of these? or not > + > +void > +push_vect_problem (const char *text, gimple *stmt) > +{ > + if (!dump_enabled_p ()) > + return; > + > + the_vect_problem = new opt_problem (text, stmt); > + > + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, > + "not vectorized: %s", text); > + dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); > +} > diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h > index 23c05cd..60fca1b 100644 > --- a/gcc/tree-vectorizer.h > +++ b/gcc/tree-vectorizer.h > @@ -1638,4 +1638,11 @@ unsigned vectorize_loops (void); > bool vect_stmt_in_region_p (vec_info *, gimple *); > void vect_free_loop_info_assumptions (struct loop *); > > +/* Singleton instance. */ > +class opt_problem; > +extern opt_problem *the_vect_problem; > + > +extern void push_vect_problem (const char *text, gimple *stmt); > + > + > #endif /* GCC_TREE_VECTORIZER_H */ > -- Richard Biener SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg) ---1609908220-2045961769-1529917815=:5043--