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 <vector>
> std::size_t f(std::vector<std::vector<float>> 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<std::vector<float> >&)’:
> ../../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<gimple *> *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<gimple *> *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 <dmalc...@redhat.com>.
> +
> +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
> +<http://www.gnu.org/licenses/>.  */
> +
> +#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 <dmalc...@redhat.com>.
> +
> +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
> +<http://www.gnu.org/licenses/>.  */
> +
> +#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> 
> *&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 <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to