From 9c8a1dc9d8cf653e3632e116d68b622eed132ca9 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 10 May 2018 10:59:15 -0400
Subject: [PATCH 30/67] FIXME: add gimple support; try covering more

---
 gcc/optimization-records.cc |  50 ++-
 gcc/optinfo.cc              |  72 ++--
 gcc/optinfo.h               |  77 +++-
 gcc/tree-vect-data-refs.c   |  14 +-
 gcc/tree-vect-loop.c        | 985 +++++++++++++++++++++-----------------------
 gcc/tree-vect-slp.c         |   8 +-
 gcc/tree-vectorizer.h       |   1 +
 7 files changed, 625 insertions(+), 582 deletions(-)

diff --git a/gcc/optimization-records.cc b/gcc/optimization-records.cc
index 97fa823..07bb114 100644
--- a/gcc/optimization-records.cc
+++ b/gcc/optimization-records.cc
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "pretty-print.h"
 #include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
 
 /* FIXME.  */
 
@@ -175,7 +176,7 @@ maybe_record_optimization (const optinfo *optinfo)
 	    tree node = as_tree->get_node ();
 	    json::object *item = new json::object ();
 	    /* Capture output of:
-	         dump_generic_expr (MSG_NOTE, TDF_DETAILS, node);
+	         dump_generic_expr (MSG_NOTE, flags, node);
 	       into a text buffer, and add it as a attribute of ITEM.
 	       This is:
 	         print_generic_expr (alt_dump_file, node, dump_flags | extra_dump_flags);
@@ -188,7 +189,7 @@ maybe_record_optimization (const optinfo *optinfo)
 	    pp_needs_newline (&pp) = true;
 	    pp_translate_identifiers (&pp) = false;
 
-	    dump_generic_node (&pp, node, 0, TDF_DETAILS, false);
+	    dump_generic_node (&pp, node, 0, as_tree->get_flags (), false);
 
 	    item->set ("expr", new json::string (pp_formatted_text (&pp)));
 
@@ -199,6 +200,34 @@ maybe_record_optimization (const optinfo *optinfo)
 	    message->append (item);
 	  }
 	  break;
+	case OPTINFO_ITEM_KIND_GIMPLE:
+	  {
+	    const optinfo_item_gimple *as_gimple = (const optinfo_item_gimple *)item;
+	    gimple *stmt = as_gimple->get_stmt ();
+	    json::object *item = new json::object ();
+	    /* Capture output of:
+		 dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+	       into a text buffer, and add it as a attribute of ITEM.
+	       This is:
+		 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
+	       which is:
+		 pp_needs_newline (&buffer) = true;
+		 buffer.buffer->stream = file;
+		 pp_gimple_stmt_1 (&buffer, g, spc, flags);
+		 pp_newline_and_flush (&buffer);
+	    */
+	    pretty_printer pp;
+	    pp_needs_newline (&pp) = true;
+	    pp_gimple_stmt_1 (&pp, stmt, 0, TDF_SLIM);
+	    item->set ("stmt", new json::string (pp_formatted_text (&pp)));
+
+	    /* Capture any location for the stmt.  */
+	    if (gimple_location (stmt))
+	      item->set ("location", location_to_json (gimple_location (stmt)));
+
+	    message->append (item);
+	  }
+	  break;
 	}
    }
 
@@ -264,6 +293,16 @@ maybe_record_optimization (const optinfo *optinfo)
 		pp_end_quote (&pp, show_color);
 	      }
 	      break;
+	    case OPTINFO_ITEM_KIND_GIMPLE:
+	      {
+		const optinfo_item_gimple *as_gimple
+		  = (const optinfo_item_gimple *)item;
+		gimple *stmt = as_gimple->get_stmt ();
+		pp_begin_quote (&pp, show_color);
+		pp_gimple_stmt_1 (&pp, stmt, 0, TDF_SLIM);
+		pp_end_quote (&pp, show_color);
+	      }
+	      break;
 	    }
 	}
 
@@ -293,9 +332,10 @@ maybe_record_optimization_va (enum opt_record_kind kind,
   vasprintf (&msg, fmt, *ap);
 
   // FIXME: need to separate the pending from the info
-  optinfo optinfo (kind, optinfo_location (stmt));
-  optinfo << msg;
-  optinfo.emit ();
+  {
+    pending_optinfo optinfo (kind, optinfo_location (stmt));
+    optinfo << msg;
+  }
 
   free (msg);
 }
diff --git a/gcc/optinfo.cc b/gcc/optinfo.cc
index a1f136d..e866a82 100644
--- a/gcc/optinfo.cc
+++ b/gcc/optinfo.cc
@@ -50,21 +50,6 @@ along with GCC; see the file COPYING3.  If not see
 
 /* FIXME.  */
 
-void optinfo_item_text::flush () const
-{
-  // FIXME
-}
-
-/* FIXME.  */
-
-void optinfo_item_tree::flush () const
-{
-  // FIXME
-  dump_generic_expr (MSG_NOTE, TDF_DETAILS, m_node);
-}
-
-/* FIXME.  */
-
 optinfo_location::optinfo_location (struct loop *loop)
   : m_stmt (NULL)
 {
@@ -87,7 +72,7 @@ optinfo_location::optinfo_location (struct loop *loop)
     }
 }
 
-/* FIXME.  */
+/* optinfo's dtor.  */
 
 optinfo::~optinfo ()
 {
@@ -100,24 +85,6 @@ optinfo::~optinfo ()
 
 /* FIXME.  */
 
-optinfo&
-optinfo::operator<< (const char *msg)
-{
-  m_items.safe_push (new optinfo_item_text (msg));
-  return *this;
-}
-
-/* FIXME.  */
-
-optinfo&
-optinfo::operator<< (tree node)
-{
-  m_items.safe_push (new optinfo_item_tree (node));
-  return *this;
-}
-
-/* FIXME.  */
-
 void
 optinfo::emit () const
 {
@@ -149,18 +116,30 @@ optinfo::emit () const
 		dump_generic_expr (MSG_NOTE, TDF_DETAILS, tree->get_node ());
 	      }
 	      break;
+	    case OPTINFO_ITEM_KIND_GIMPLE:
+	      {
+		const optinfo_item_gimple *as_gimple
+		  = (const optinfo_item_gimple *)item;
+		gimple *stmt = as_gimple->get_stmt ();
+		dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+	      }
+	      break;
 	    }
 	}
       dump_printf (MSG_NOTE, "\n");
     }
 }
 
+/* pending_optinfo's ctor.  */
+
 pending_optinfo::pending_optinfo (/*optinfo_emitter *emitter, */enum opt_record_kind kind,
 				  optinfo_location loc)
 {
   m_optinfo = new optinfo (kind, loc);
 }
 
+/* pending_optinfo's dtor.  Emit the pending information, and clean it up.  */
+
 pending_optinfo::~pending_optinfo ()
 {
   /* Flush the pending information.  */
@@ -182,8 +161,29 @@ pending_optinfo::operator<< (const char *msg)
 /* FIXME.  */
 
 pending_optinfo&
-pending_optinfo::operator<< (tree node)
+pending_optinfo::operator<< (optinfo_tree node_with_flags)
+{
+  m_optinfo->m_items.safe_push (new optinfo_item_tree (node_with_flags));
+  return *this;
+}
+
+/* FIXME.  */
+
+pending_optinfo&
+pending_optinfo::operator<< (gimple *stmt)
 {
-  m_optinfo->m_items.safe_push (new optinfo_item_tree (node));
+  m_optinfo->m_items.safe_push (new optinfo_item_gimple (stmt));
+  return *this;
+}
+
+/* FIXME.  */
+
+pending_optinfo&
+pending_optinfo::operator<< (optinfo_printf item)
+{
+  // FIXME
+#if 0
+  m_optinfo->m_items.safe_push (new optinfo_item_text (stmt));
+#endif
   return *this;
 }
diff --git a/gcc/optinfo.h b/gcc/optinfo.h
index af04c40..ae95c66 100644
--- a/gcc/optinfo.h
+++ b/gcc/optinfo.h
@@ -29,6 +29,7 @@ enum optinfo_item_kind
 {
   OPTINFO_ITEM_KIND_TEXT,
   OPTINFO_ITEM_KIND_TREE,
+  OPTINFO_ITEM_KIND_GIMPLE,
 };
 
 /* FIXME.  */
@@ -39,9 +40,6 @@ class optinfo_item
   virtual ~optinfo_item () {}
 
   virtual enum optinfo_item_kind get_kind () const = 0;
-
-  // FIXME: is this used anywhere?
-  virtual void flush () const = 0;
 };
 
 /* FIXME.  */
@@ -54,39 +52,76 @@ class optinfo_item_text : public optinfo_item
   {
     return OPTINFO_ITEM_KIND_TEXT;
   }
-  void flush () const FINAL OVERRIDE;
 
   const char *get_text () const { return m_text; }
 
  private:
   const char *m_text;
+  // FIXME: currently this is assumed to be a string literal i.e. outlive
+};
+
+/* Packaging up a tree with dump flags.  */
+
+struct optinfo_tree
+{
+  optinfo_tree (tree node, dump_flags_t flags)
+    : m_node (node), m_flags (flags)
+  {
+    // only support TDF_* flags.
+    gcc_assert ((m_flags & MSG_ALL) == 0);
+    // FIXME: what happened to TDF_KIND_MASK, mentioned in dumpfile.h ?
+  }
+
+  tree m_node;
+  dump_flags_t m_flags;
 };
 
+static inline optinfo_tree slim (tree node)
+{
+  return optinfo_tree (node, TDF_SLIM);
+}
+
+static inline optinfo_tree details (tree node)
+{
+  return optinfo_tree (node, TDF_DETAILS);
+}
+
 /* FIXME.  */
 
 class optinfo_item_tree : public optinfo_item
 {
  public:
-  optinfo_item_tree (tree node) : m_node (node) {}
+  optinfo_item_tree (optinfo_tree node_with_flags)
+    : m_node_with_flags (node_with_flags)
+  {}
   enum optinfo_item_kind get_kind () const FINAL OVERRIDE
   {
     return OPTINFO_ITEM_KIND_TREE;
   }
-  void flush () const FINAL OVERRIDE;
 
-  tree get_node () const { return m_node; }
+  tree get_node () const { return m_node_with_flags.m_node; }
+  dump_flags_t get_flags () const { return m_node_with_flags.m_flags; }
 
  private:
-  tree m_node;
+  optinfo_tree m_node_with_flags;
 };
 
-#if 0
 /* FIXME.  */
 
-class optinfo_emitter
+class optinfo_item_gimple : public optinfo_item
 {
+ public:
+  optinfo_item_gimple (gimple *stmt) : m_stmt (stmt) {}
+  enum optinfo_item_kind get_kind () const FINAL OVERRIDE
+  {
+    return OPTINFO_ITEM_KIND_GIMPLE;
+  }
+
+  gimple *get_stmt () const { return m_stmt; }
+
+ private:
+  gimple *m_stmt;
 };
-#endif
 
 /* FIXME.  */
 
@@ -129,9 +164,6 @@ class optinfo
   unsigned int num_items () const { return m_items.length (); }
   const optinfo_item *get_item (unsigned int i) const { return m_items[i]; }
 
-  optinfo& operator<< (const char *);
-  optinfo& operator<< (tree);
-
   void emit () const;
 
  private:
@@ -141,6 +173,18 @@ class optinfo
   auto_vec <optinfo_item *> m_items;
 };
 
+/* FIXME.  */
+
+class optinfo_printf
+{
+ public:
+  optinfo_printf (const char */*fmt*/, ...)
+  {
+    // FIXME: should generate a malloced-text
+    //
+  }
+};
+
 /* Emit the info when this goes out of scope.  */
 
 class pending_optinfo
@@ -151,11 +195,12 @@ class pending_optinfo
   ~pending_optinfo ();
 
   pending_optinfo& operator<< (const char *);
-  pending_optinfo& operator<< (tree);
+  pending_optinfo& operator<< (optinfo_tree);
+  pending_optinfo& operator<< (gimple *);
+  pending_optinfo& operator<< (optinfo_printf);
 
  private:
   optinfo *m_optinfo;
 };
 
-
 #endif /* #ifndef GCC_OPTINFO_H */
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index c8c8f67..d2b2275 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2322,7 +2322,7 @@ vect_analyze_data_refs_alignment (loop_vec_info vinfo)
 {
   if (optinfo_enabled_p ())
     vect_location_writeln (OPT_RECORD_REMARK,
-                     "=== vect_analyze_data_refs_alignment ===\n");
+                     "=== vect_analyze_data_refs_alignment ===");
 
   /* Mark groups of data references with same alignment using
      data dependence information.  */
@@ -3953,7 +3953,7 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
 
   if (optinfo_enabled_p ())
     vect_location_writeln (OPT_RECORD_REMARK,
-		     "=== vect_analyze_data_refs ===\n");
+		     "=== vect_analyze_data_refs ===");
 
   if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
     loop = LOOP_VINFO_LOOP (loop_vinfo);
@@ -4343,12 +4343,10 @@ again:
 	{
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK,
-			       "got vectype for stmt: ");
-	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
-	      dump_generic_expr (MSG_NOTE, TDF_SLIM,
-				 STMT_VINFO_VECTYPE (stmt_info));
-	      dump_printf (MSG_NOTE, "\n");
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "got vectype for stmt: "
+		<< stmt
+		<< slim (STMT_VINFO_VECTYPE (stmt_info));
 	    }
 	}
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index e3819ff..6624c47 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -209,6 +209,14 @@ void vect_location_writeln (enum opt_record_kind kind,
   va_end (ap);
 }
 
+/* FIXME.  */
+
+pending_optinfo
+emit_optinfo_at_vect_location (enum opt_record_kind kind)
+{
+  return pending_optinfo (/*emitter, */kind, vect_location_thing);
+}
+
 /* Function vect_determine_vectorization_factor
 
    Determine the vectorization factor (VF).  VF is the number of data elements
@@ -255,8 +263,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
   auto_vec<stmt_vec_info> mask_producers;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-                     "=== vect_determine_vectorization_factor ===");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "=== vect_determine_vectorization_factor ===";
 
   for (i = 0; i < nbbs; i++)
     {
@@ -268,10 +276,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 	  phi = si.phi ();
 	  stmt_info = vinfo_for_stmt (phi);
 	  if (optinfo_enabled_p ())
-	    {
-	      vect_location_writeln (OPT_RECORD_REMARK, "==> examining phi: ");
-	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
-	    }
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "==> examining phi: "
+	      << phi;
 
 	  gcc_assert (stmt_info);
 
@@ -283,10 +290,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_REMARK,
-                                   "get vectype for scalar type:  ");
-		  dump_generic_expr (MSG_NOTE, TDF_SLIM, scalar_type);
-                  dump_printf (MSG_NOTE, "\n");
+		  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		    << "get vectype for scalar type:  "
+		    << slim (scalar_type);
 		}
 
 	      vectype = get_vectype_for_scalar_type (scalar_type);
@@ -294,29 +300,26 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 		{
 		  if (optinfo_enabled_p ())
 		    {
-		      vect_location_writeln (OPT_RECORD_FAILURE,
-                                       "not vectorized: unsupported "
-                                       "data-type ");
-		      dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-                                         scalar_type);
-                      dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+		      emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+			<< "not vectorized: unsupported data-type "
+			<< slim (scalar_type);
 		    }
 		  return false;
 		}
 	      STMT_VINFO_VECTYPE (stmt_info) = vectype;
 
 	      if (optinfo_enabled_p ())
-		{
-		  vect_location_writeln (OPT_RECORD_REMARK, "vectype: ");
-		  dump_generic_expr (MSG_NOTE, TDF_SLIM, vectype);
-                  dump_printf (MSG_NOTE, "\n");
-		}
+		emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		  << "vectype: "
+		  << slim (vectype);
 
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_REMARK, "nunits = ");
-		  dump_dec (MSG_NOTE, TYPE_VECTOR_SUBPARTS (vectype));
-		  dump_printf (MSG_NOTE, "\n");
+#if 0
+		  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		    << "nunits = "
+		    << dump_dec (MSG_NOTE, TYPE_VECTOR_SUBPARTS (vectype));
+#endif
 		}
 
 	      vect_update_max_nunits (&vectorization_factor, vectype);
@@ -337,9 +340,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK,
-                               "==> examining statement: ");
-	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "==> examining statement: "
+		<< stmt;
 	    }
 
 	  gcc_assert (stmt_info);
@@ -358,15 +361,16 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
                   stmt_info = vinfo_for_stmt (pattern_stmt);
                   if (optinfo_enabled_p ())
                     {
-                      vect_location_writeln (OPT_RECORD_REMARK,
-                                       "==> examining pattern statement: ");
-                      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+                      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+			<< "==> examining pattern statement: "
+			<< stmt;
                     }
                 }
               else
 	        {
 	          if (optinfo_enabled_p ())
-	            vect_location_writeln (OPT_RECORD_REMARK, "skip.\n");
+	            emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		      << "skip";
                   gsi_next (&si);
 	          continue;
                 }
@@ -407,10 +411,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 		    {
 		      if (optinfo_enabled_p ())
 			{
-			  vect_location_writeln (OPT_RECORD_REMARK,
-                                           "==> examining pattern def stmt: ");
-			  dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
-                                            pattern_def_stmt, 0);
+			  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+			    << "==> examining pattern def stmt: "
+			    << pattern_def_stmt;
 			}
 
 		      stmt = pattern_def_stmt;
@@ -447,10 +450,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 		}
 	      if (optinfo_enabled_p ())
 		{
-	          vect_location_writeln (OPT_RECORD_FAILURE,
-                                   "not vectorized: irregular stmt.");
-		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION,  TDF_SLIM, stmt,
-                                    0);
+	          emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		    << "not vectorized: irregular stmt: " << stmt;
 		}
 	      return false;
 	    }
@@ -459,9 +460,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 	    {
 	      if (optinfo_enabled_p ())
 	        {
-	          vect_location_writeln (OPT_RECORD_FAILURE,
-                                   "not vectorized: vector stmt in loop:");
-	          dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
+	          emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		    << "not vectorized: vector stmt in loop: " << stmt;
 	        }
 	      return false;
 	    }
@@ -517,22 +517,18 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_REMARK,
-                                   "get vectype for scalar type:  ");
-		  dump_generic_expr (MSG_NOTE, TDF_SLIM, scalar_type);
-                  dump_printf (MSG_NOTE, "\n");
+		  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		    << "get vectype for scalar type:  "
+		    << slim (scalar_type);
 		}
 	      vectype = get_vectype_for_scalar_type (scalar_type);
 	      if (!vectype)
 		{
 		  if (optinfo_enabled_p ())
 		    {
-		      vect_location_writeln (OPT_RECORD_FAILURE,
-                                       "not vectorized: unsupported "
-                                       "data-type ");
-		      dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-                                         scalar_type);
-                      dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+		      emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+			<< "not vectorized: unsupported data-type: "
+			<< slim (scalar_type);
 		    }
 		  return false;
 		}
@@ -542,9 +538,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_REMARK, "vectype: ");
-		  dump_generic_expr (MSG_NOTE, TDF_SLIM, vectype);
-                  dump_printf (MSG_NOTE, "\n");
+		  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		    << "vectype: "
+		    << slim (vectype);
 		}
             }
 
@@ -562,10 +558,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 							     &dummy);
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_REMARK,
-				   "get vectype for scalar type:  ");
-		  dump_generic_expr (MSG_NOTE, TDF_SLIM, scalar_type);
-		  dump_printf (MSG_NOTE, "\n");
+		  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		    << "get vectype for scalar type:  "
+		    << slim (scalar_type);
 		}
 	      vf_vectype = get_vectype_for_scalar_type (scalar_type);
 	    }
@@ -573,11 +568,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 	    {
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_FAILURE,
-                                   "not vectorized: unsupported data-type ");
-		  dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-                                     scalar_type);
-                  dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+		  emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		    << "not vectorized: unsupported data-type "
+		    << slim (scalar_type);
 		}
 	      return false;
 	    }
@@ -587,31 +580,30 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 	    {
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_FAILURE,
-                                   "not vectorized: different sized vector "
-                                   "types in statement, ");
-		  dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-                                     vectype);
-		  dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
-		  dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-                                     vf_vectype);
-                  dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+		  emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		    << ("not vectorized: different sized vector "
+			"types in statement, ")
+		    << slim (vectype)
+		    << " and "
+		    << slim (vf_vectype);
 		}
 	      return false;
 	    }
 
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK, "vectype: ");
-	      dump_generic_expr (MSG_NOTE, TDF_SLIM, vf_vectype);
-              dump_printf (MSG_NOTE, "\n");
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "vectype: " << slim (vf_vectype);
 	    }
 
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK, "nunits = ");
+#if 0
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "nunits = "
 	      dump_dec (MSG_NOTE, TYPE_VECTOR_SUBPARTS (vf_vectype));
 	      dump_printf (MSG_NOTE, "\n");
+#endif
 	    }
 
 	  vect_update_max_nunits (&vectorization_factor, vf_vectype);
@@ -627,16 +619,18 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
   /* TODO: Analyze cost. Decide if worth while to vectorize.  */
   if (optinfo_enabled_p ())
     {
-      vect_location_writeln (OPT_RECORD_REMARK, "vectorization factor = ");
+#if 0
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "vectorization factor = "
       dump_dec (MSG_NOTE, vectorization_factor);
-      dump_printf (MSG_NOTE, "\n");
+#endif
     }
 
   if (known_le (vectorization_factor, 1U))
     {
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: unsupported data-type");
+        emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: unsupported data-type";
       return false;
     }
   LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
@@ -658,8 +652,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 	  if (!mask_type)
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				       "not vectorized: unsupported mask");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << "not vectorized: unsupported mask";
 	      return false;
 	    }
 	}
@@ -677,11 +671,10 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 		{
 		  if (optinfo_enabled_p ())
 		    {
-		      vect_location_writeln (OPT_RECORD_FAILURE,
-				       "not vectorized: can't compute mask type "
-				       "for statement, ");
-		      dump_gimple_stmt (MSG_MISSED_OPTIMIZATION,  TDF_SLIM, stmt,
-					0);
+		      emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+			<< ("not vectorized: can't compute mask type "
+			    "for statement, ")
+			<< stmt;
 		    }
 		  return false;
 		}
@@ -699,15 +692,12 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 		{
 		  if (optinfo_enabled_p ())
 		    {
-		      vect_location_writeln (OPT_RECORD_FAILURE,
-				       "not vectorized: different sized masks "
-				       "types in statement, ");
-		      dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-					 mask_type);
-		      dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
-		      dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-					 vectype);
-		      dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+		      emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+			<< ("not vectorized: different sized masks "
+			    "types in statement, ")
+			<< slim (mask_type)
+			<< " and "
+			<< slim (vectype);
 		    }
 		  return false;
 		}
@@ -716,15 +706,12 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 		{
 		  if (optinfo_enabled_p ())
 		    {
-		      vect_location_writeln (OPT_RECORD_FAILURE,
-				       "not vectorized: mixed mask and "
-				       "nonmask vector types in statement, ");
-		      dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-					 mask_type);
-		      dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
-		      dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
-					 vectype);
-		      dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+		      emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+			<< ("not vectorized: mixed mask and "
+			    "nonmask vector types in statement, ")
+			<< slim (mask_type)
+			<< " and "
+			<< slim (vectype);
 		    }
 		  return false;
 		}
@@ -746,11 +733,10 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 	{
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: can't compute mask type "
-			       "for statement, ");
-	      dump_gimple_stmt (MSG_MISSED_OPTIMIZATION,  TDF_SLIM, stmt,
-				0);
+	      emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		<< ("not vectorized: can't compute mask type "
+		    "for statement, ")
+		<< stmt;
 	    }
 	  return false;
 	}
@@ -791,11 +777,9 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
 
   if (optinfo_enabled_p ())
     {
-      vect_location_writeln (OPT_RECORD_REMARK, "step: ");
-      dump_generic_expr (MSG_NOTE, TDF_SLIM, step_expr);
-      dump_printf (MSG_NOTE, ",  init: ");
-      dump_generic_expr (MSG_NOTE, TDF_SLIM, init_expr);
-      dump_printf (MSG_NOTE, "\n");
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "step: " << slim (step_expr)
+	<< ",  init: " << slim (init_expr);
     }
 
   *init = init_expr;
@@ -812,8 +796,8 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
 	  || !flag_associative_math))
     {
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_FAILURE,
-			       "step unknown");
+        emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "step unknown";
       return false;
     }
 
@@ -837,8 +821,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
   bool double_reduc;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-			   "=== vect_analyze_scalar_cycles ===");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "=== vect_analyze_scalar_cycles ===";
 
   /* First - identify all inductions.  Reduction detection assumes that all the
      inductions have been identified, therefore, this order must not be
@@ -852,8 +836,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
 
       if (optinfo_enabled_p ())
 	{
-	  vect_location_writeln (OPT_RECORD_REMARK, "Analyze phi: ");
-	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
+	  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	    << "Analyze phi: " << phi;
 	}
 
       /* Skip virtual phi's.  The data dependences that are associated with
@@ -870,10 +854,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
 	  STRIP_NOPS (access_fn);
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK,
-                               "Access function of PHI: ");
-	      dump_generic_expr (MSG_NOTE, TDF_SLIM, access_fn);
-              dump_printf (MSG_NOTE, "\n");
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "Access function of PHI: " << slim (access_fn);
 	    }
 	  STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED (stmt_vinfo)
 	    = initial_condition_in_loop_num (access_fn, loop->num);
@@ -895,7 +877,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
       gcc_assert (STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_vinfo) != NULL_TREE);
 
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_REMARK, "Detected induction");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "Detected induction";
       STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def;
     }
 
@@ -910,8 +893,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
 
       if (optinfo_enabled_p ())
         {
-          vect_location_writeln (OPT_RECORD_REMARK, "Analyze phi: ");
-          dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
+          emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	    << "Analyze phi: " << phi;
         }
 
       gcc_assert (!virtual_operand_p (def)
@@ -924,8 +907,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
           if (double_reduc)
             {
               if (optinfo_enabled_p ())
-                vect_location_writeln (OPT_RECORD_REMARK,
-				       "Detected double reduction");
+                emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		  << "Detected double reduction";
 
               STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_double_reduction_def;
               STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
@@ -936,8 +919,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
               if (loop != LOOP_VINFO_LOOP (loop_vinfo))
                 {
                   if (optinfo_enabled_p ())
-                    vect_location_writeln (OPT_RECORD_REMARK,
-					   "Detected vectorizable nested cycle");
+                    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		      << "Detected vectorizable nested cycle";
 
                   STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_nested_cycle;
                   STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
@@ -946,8 +929,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
               else
                 {
                   if (optinfo_enabled_p ())
-                    vect_location_writeln (OPT_RECORD_REMARK,
-					   "Detected reduction");
+                    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		      << "Detected reduction";
 
                   STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_reduction_def;
                   STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
@@ -962,8 +945,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
         }
       else
         if (optinfo_enabled_p ())
-          vect_location_writeln (OPT_RECORD_FAILURE,
-				 "Unknown def-use cycle pattern");
+          emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	    << "Unknown def-use cycle pattern";
     }
 }
 
@@ -1084,8 +1067,8 @@ vect_get_loop_niters (struct loop *loop, tree *assumptions,
   *number_of_iterationsm1 = chrec_dont_know;
   *number_of_iterations = chrec_dont_know;
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-			   "=== get_loop_niters ===");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "=== get_loop_niters ===";
 
   if (!exit)
     return cond;
@@ -1525,8 +1508,8 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 			  tree *number_of_iterations, gcond **inner_loop_cond)
 {
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-			   "=== vect_analyze_loop_form ===");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "=== vect_analyze_loop_form ===";
 
   /* Different restrictions apply when we are considering an inner-most loop,
      vs. an outer (nested) loop.
@@ -1549,16 +1532,16 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
       if (loop->num_nodes != 2)
         {
           if (optinfo_enabled_p ())
-            vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: control flow in loop");
+            emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: control flow in loop";
           return false;
         }
 
       if (empty_block_p (loop->header))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: empty loop");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: empty loop";
 	  return false;
 	}
     }
@@ -1587,16 +1570,16 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
       if ((loop->inner)->inner || (loop->inner)->next)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: multiple nested loops");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: multiple nested loops";
 	  return false;
 	}
 
       if (loop->num_nodes != 5)
         {
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: control flow in loop");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: control flow in loop";
 	  return false;
         }
 
@@ -1606,8 +1589,8 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 	  || single_exit (innerloop)->dest != EDGE_PRED (loop->latch, 0)->src)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: unsupported outerloop form");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: unsupported outerloop form";
 	  return false;
 	}
 
@@ -1621,23 +1604,22 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 	  || !integer_onep (inner_assumptions))
 	{
 	  if (optinfo_enabled_p ())
-            vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: bad inner loop");
+            emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: bad inner loop";
 	  return false;
 	}
 
       if (!expr_invariant_in_loop_p (loop, inner_niter))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: inner-loop count not"
-				   " invariant");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: inner-loop count not invariant";
 	  return false;
 	}
 
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_REMARK,
-			       "Considering outer-loop vectorization");
+        emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "Considering outer-loop vectorization";
     }
 
   if (!single_exit (loop)
@@ -1646,11 +1628,11 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
       if (optinfo_enabled_p ())
         {
           if (!single_exit (loop))
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "not vectorized: multiple exits");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: multiple exits";
           else if (EDGE_COUNT (loop->header->preds) != 2)
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: too many incoming edges");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: too many incoming edges";
         }
       return false;
     }
@@ -1663,8 +1645,8 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
       || !gimple_seq_empty_p (phi_nodes (loop->latch)))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: latch block not empty");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: latch block not empty";
       return false;
     }
 
@@ -1673,8 +1655,8 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
   if (e->flags & EDGE_ABNORMAL)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: abnormal loop exit edge");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: abnormal loop exit edge";
       return false;
     }
 
@@ -1683,8 +1665,8 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
   if (!*loop_cond)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: complicated exit condition");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: complicated exit condition";
       return false;
     }
 
@@ -1693,31 +1675,22 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
       || chrec_contains_undetermined (*number_of_iterations))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: number of iterations cannot be "
-			       "computed");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: number of iterations cannot be computed";
       return false;
     }
 
   if (integer_zerop (*number_of_iterations))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: number of iterations = 0");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: number of iterations = 0";
       return false;
     }
 
   return true;
 }
 
-/* FIXME.  */
-
-pending_optinfo
-emit_optinfo_at_vect_location (enum opt_record_kind kind)
-{
-  return pending_optinfo (/*emitter, */kind, vect_location_thing);
-}
-
 /* Analyze LOOP form and return a loop_vec_info if it is of suitable form.  */
 
 loop_vec_info
@@ -1753,7 +1726,7 @@ vect_analyze_loop_form (struct loop *loop)
     if (optinfo_enabled_p ())
       emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
 	<< "symbolic number of iterations is "
-	<< number_of_iterations;
+	<< details (number_of_iterations);
 
   STMT_VINFO_TYPE (vinfo_for_stmt (loop_cond)) = loop_exit_ctrl_vec_info_type;
   if (inner_loop_cond)
@@ -1780,8 +1753,8 @@ vect_update_vf_for_slp (loop_vec_info loop_vinfo)
   int i;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-			   "=== vect_update_vf_for_slp ===");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "=== vect_update_vf_for_slp ===";
 
   vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
   gcc_assert (known_ne (vectorization_factor, 0U));
@@ -1816,14 +1789,14 @@ vect_update_vf_for_slp (loop_vec_info loop_vinfo)
 
   if (only_slp_in_loop)
     {
-      vect_location_writeln (OPT_RECORD_REMARK,
-			     "Loop contains only SLP stmts");
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "Loop contains only SLP stmts";
       vectorization_factor = LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo);
     }
   else
     {
-      vect_location_writeln (OPT_RECORD_REMARK,
-			     "Loop contains SLP and non-SLP stmts");
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "Loop contains SLP and non-SLP stmts";
       /* Both the vectorization factor and unroll factor have the form
 	 current_vector_size * X for some rational X, so they must have
 	 a common multiple.  */
@@ -1835,9 +1808,11 @@ vect_update_vf_for_slp (loop_vec_info loop_vinfo)
   LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
   if (optinfo_enabled_p ())
     {
-      vect_location_writeln (OPT_RECORD_REMARK,
-		       "Updating vectorization factor to ");
+#if 0
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "Updating vectorization factor to ");
       dump_dec (MSG_NOTE, vectorization_factor);
+#endif
       dump_printf (MSG_NOTE, ".\n");
     }
 }
@@ -1885,8 +1860,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
   bool ok;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-			   "=== vect_analyze_loop_operations ===");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "=== vect_analyze_loop_operations ===";
 
   for (i = 0; i < nbbs; i++)
     {
@@ -1901,7 +1876,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
           stmt_info = vinfo_for_stmt (phi);
           if (optinfo_enabled_p ())
             {
-              vect_location_writeln (OPT_RECORD_REMARK, "examining phi: ");
+              emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "examining phi: ";
               dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
             }
 	  if (virtual_operand_p (gimple_phi_result (phi)))
@@ -1919,9 +1895,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
 		  && !vect_active_double_reduction_p (stmt_info))
                 {
                   if (optinfo_enabled_p ())
-		    vect_location_writeln (OPT_RECORD_FAILURE,
-					   "Unsupported loop-closed phi in "
-					   "outer-loop");
+		    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		      << "Unsupported loop-closed phi in outer-loop";
                   return false;
                 }
 
@@ -1963,8 +1938,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
             {
               /* A scalar-dependence cycle that we don't support.  */
               if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				       "not vectorized: scalar dependence cycle");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << "not vectorized: scalar dependence cycle";
               return false;
             }
 
@@ -1990,10 +1965,9 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
             {
               if (optinfo_enabled_p ())
                 {
-		  vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: relevant phi not "
-				   "supported: ");
-                  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, phi, 0);
+		  emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		    << "not vectorized: relevant phi not supported: "
+		    << phi;
                 }
 	      return false;
             }
@@ -2017,12 +1991,11 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
   if (!need_to_vectorize)
     {
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_REMARK,
-			       "All the computation can be taken out of the loop");
+        emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "All the computation can be taken out of the loop";
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: redundant loop. no profit to "
-			       "vectorize");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: redundant loop. no profit to vectorize";
       return false;
     }
 
@@ -2054,9 +2027,9 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo)
 	  && (unsigned HOST_WIDE_INT) max_niter < assumed_vf)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-				   "not vectorized: iteration count smaller than "
-				   "vectorization factor");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << ("not vectorized: iteration count smaller than "
+		  "vectorization factor");
 	  return 0;
 	}
     }
@@ -2068,12 +2041,11 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo)
   if (min_profitable_iters < 0)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: vectorization not profitable");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: vectorization not profitable";
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: vector version will never be "
-			       "profitable");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: vector version will never be profitable";
       return -1;
     }
 
@@ -2091,13 +2063,13 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo)
       && LOOP_VINFO_INT_NITERS (loop_vinfo) < th)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: vectorization not profitable");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: vectorization not profitable";
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_REMARK,
-			       "not vectorized: iteration count smaller than user "
-			       "specified loop bound parameter or minimum profitable "
-			       "iterations (whichever is more conservative)");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << ("not vectorized: iteration count smaller than user "
+	      "specified loop bound parameter or minimum profitable "
+	      "iterations (whichever is more conservative)");
       return 0;
     }
 
@@ -2109,15 +2081,14 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo)
 	  < MAX (th, (unsigned) min_profitable_estimate)))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: estimated iteration count too "
-			       "small");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "not vectorized: estimated iteration count too small";
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_REMARK,
-			       "not vectorized: estimated iteration count smaller "
-			       "than specified loop bound parameter or minimum "
-			       "profitable iterations (whichever is more "
-			       "conservative)");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << ("not vectorized: estimated iteration count smaller "
+	      "than specified loop bound parameter or minimum "
+	      "profitable iterations (whichever is more "
+	      "conservative)");
       return -1;
     }
 
@@ -2151,10 +2122,10 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal)
   if (!find_loop_nest (loop, &LOOP_VINFO_LOOP_NEST (loop_vinfo)))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "not vectorized: loop nest containing two "
-			       "or more consecutive inner loops cannot be "
-			       "vectorized");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << ("not vectorized: loop nest containing two "
+	      "or more consecutive inner loops cannot be "
+	      "vectorized");
       return false;
     }
 
@@ -2200,10 +2171,10 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal)
 		  }
 	      }
 	    if (optinfo_enabled_p ())
-	      vect_location_writeln (OPT_RECORD_FAILURE,
-				     "not vectorized: loop contains function "
-				     "calls or data references that cannot "
-				     "be analyzed");
+	      emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		<< ("not vectorized: loop contains function "
+		    "calls or data references that cannot "
+		    "be analyzed");
 	    return false;
 	  }
       }
@@ -2215,8 +2186,8 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal)
   if (!ok)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "bad data references");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "bad data references";
       return false;
     }
 
@@ -2235,8 +2206,8 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal)
   if (!ok)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "bad data access");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "bad data access";
       return false;
     }
 
@@ -2246,8 +2217,8 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal)
   if (!ok)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			       "unexpected pattern");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "unexpected pattern";
       return false;
     }
 
@@ -2265,8 +2236,8 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal)
 	  && maybe_lt (max_vf, min_vf)))
     {
       if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "bad data dependence.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "bad data dependence";
       return false;
     }
   LOOP_VINFO_MAX_VECT_FACTOR (loop_vinfo) = max_vf;
@@ -2275,16 +2246,16 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal)
   if (!ok)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "can't determine vectorization factor.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "can't determine vectorization factor";
       return false;
     }
   if (max_vf != MAX_VECTORIZATION_FACTOR
       && maybe_lt (max_vf, LOOP_VINFO_VECT_FACTOR (loop_vinfo)))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "bad data dependence.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "bad data dependence";
       return false;
     }
 
@@ -2325,11 +2296,13 @@ start_over:
 
   if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) && optinfo_enabled_p ())
     {
-      vect_location_writeln (OPT_RECORD_REMARK,
-		       "vectorization_factor = ");
+#if 0
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "vectorization_factor = "
       dump_dec (MSG_NOTE, vectorization_factor);
       dump_printf (MSG_NOTE, ", niters = " HOST_WIDE_INT_PRINT_DEC "\n",
 		   LOOP_VINFO_INT_NITERS (loop_vinfo));
+#endif
     }
 
   HOST_WIDE_INT max_niter
@@ -2342,8 +2315,8 @@ start_over:
   if (!ok)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "bad data alignment.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "bad data alignment";
       return false;
     }
 
@@ -2364,8 +2337,8 @@ start_over:
     if (!ok)
       {
 	if (optinfo_enabled_p ())
-	  vect_location_writeln (OPT_RECORD_FAILURE,
-			   "bad data alignment.\n");
+	  emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	    << "bad data alignment";
         return false;
       }
     }
@@ -2387,8 +2360,8 @@ start_over:
   if (!ok)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "bad operation or unsupported loop bound.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "bad operation or unsupported loop bound";
       return false;
     }
 
@@ -2400,11 +2373,11 @@ start_over:
   if (optinfo_enabled_p ())
     {
       if (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo))
-	vect_location_writeln (OPT_RECORD_REMARK,
-			 "using a fully-masked loop.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "using a fully-masked loop";
       else
-	vect_location_writeln (OPT_RECORD_REMARK,
-			 "not using a fully-masked loop.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "not using a fully-masked loop";
     }
 
   /* If epilog loop is required because of data accesses with gaps,
@@ -2420,9 +2393,9 @@ start_over:
       if (known_lt (wi::to_widest (scalar_niters), vf))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_REMARK,
-			     "loop has no enough iterations to support"
-			     " peeling for gaps.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << ("loop has not enough iterations to support"
+		  " peeling for gaps");
 	  return false;
 	}
     }
@@ -2434,8 +2407,8 @@ start_over:
   if (!res)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "Loop costings not worthwhile.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "Loop costings not worthwhile";
       return false;
     }
 
@@ -2472,16 +2445,16 @@ start_over:
       || LOOP_VINFO_PEELING_FOR_NITER (loop_vinfo))
     {
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_REMARK, "epilog loop required\n");
+        emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "epilog loop required";
       if (!vect_can_advance_ivs_p (loop_vinfo)
 	  || !slpeel_can_duplicate_loop_p (LOOP_VINFO_LOOP (loop_vinfo),
 					   single_exit (LOOP_VINFO_LOOP
 							 (loop_vinfo))))
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "not vectorized: can't create required "
-			     "epilog loop\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not vectorized: can't create required epilog loop";
           goto again;
         }
     }
@@ -2567,8 +2540,8 @@ again:
     }
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-		     "re-trying with SLP disabled\n");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "re-trying with SLP disabled";
 
   /* Roll back state appropriately.  No SLP this time.  */
   slp = false;
@@ -2645,16 +2618,16 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo)
   unsigned int next_size = 0;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-			   "===== analyze_loop_nest =====");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "===== analyze_loop_nest =====";
 
   if (loop_outer (loop)
       && loop_vec_info_for_loop (loop_outer (loop))
       && LOOP_VINFO_VECTORIZABLE_P (loop_vec_info_for_loop (loop_outer (loop))))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_REMARK,
-			 "outer-loop already vectorized.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "outer-loop already vectorized";
       return NULL;
     }
 
@@ -2666,8 +2639,8 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo)
       if (!loop_vinfo)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "bad loop form.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "bad loop form";
 	  return NULL;
 	}
 
@@ -2701,11 +2674,12 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo)
       current_vector_size = vector_sizes[next_size++];
       if (optinfo_enabled_p ())
 	{
-	  vect_location_writeln (OPT_RECORD_REMARK,
-			   "***** Re-trying analysis with "
-			   "vector size ");
+#if 0
+	  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	    << "***** Re-trying analysis with vector size ";
 	  dump_dec (MSG_NOTE, current_vector_size);
 	  dump_printf (MSG_NOTE, "\n");
+#endif
 	}
     }
 }
@@ -3004,8 +2978,8 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple *phi,
   	    {
 	      if (optinfo_enabled_p ())
 		{
-		  vect_location_writeln (OPT_RECORD_REMARK, "swapping oprnds: ");
-		  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, next_stmt, 0);
+		  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		    << "swapping oprnds: " << next_stmt;
 		}
 
 	      swap_ssa_operands (next_stmt,
@@ -3259,8 +3233,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
       if (!flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "intermediate value used outside loop.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "intermediate value used outside loop";
 
           return NULL;
         }
@@ -3269,8 +3243,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
       if (nloop_uses > 1)
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "reduction value used in loop.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "reduction value used in loop";
           return NULL;
         }
 
@@ -3282,12 +3256,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
   if (TREE_CODE (loop_arg) != SSA_NAME)
     {
       if (optinfo_enabled_p ())
-	{
-	  vect_location_writeln (OPT_RECORD_FAILURE,
-			   "reduction: not ssa_name: ");
-	  dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, loop_arg);
-          dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
-	}
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "reduction: not ssa_name: "
+	  << slim (loop_arg);
       return NULL;
     }
 
@@ -3306,9 +3277,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
     {
       if (optinfo_enabled_p ())
 	{
-	  vect_location_writeln (OPT_RECORD_FAILURE,
-			   "reduction: unhandled reduction operation: ");
-	  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, def_stmt, 0);
+	  emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	    << "reduction: unhandled reduction operation: "
+	    << def_stmt;
 	}
       return NULL;
     }
@@ -3331,8 +3302,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
       if (nloop_uses > 1)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "reduction used in loop.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "reduction used in loop";
 	  return NULL;
 	}
     }
@@ -3347,8 +3318,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
           || TREE_CODE (op1) != SSA_NAME)
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "unsupported phi node definition.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "unsupported phi node definition";
 
           return NULL;
         }
@@ -3466,29 +3437,19 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
     {
       if (optinfo_enabled_p ())
         {
-          vect_location_writeln (OPT_RECORD_REMARK,
-			   "reduction: multiple types: operation type: ");
-          dump_generic_expr (MSG_NOTE, TDF_SLIM, type);
-          dump_printf (MSG_NOTE, ", operands types: ");
-          dump_generic_expr (MSG_NOTE, TDF_SLIM,
-			     TREE_TYPE (op1));
-          dump_printf (MSG_NOTE, ",");
-          dump_generic_expr (MSG_NOTE, TDF_SLIM,
-			     TREE_TYPE (op2));
+	  pending_optinfo info
+	    = emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	        << "reduction: multiple types: operation type: "
+		<< slim (type)
+		<< ", operands types: "
+		<< slim (TREE_TYPE (op1))
+		<< ","
+		<< slim (TREE_TYPE (op2));
           if (op3)
-            {
-              dump_printf (MSG_NOTE, ",");
-              dump_generic_expr (MSG_NOTE, TDF_SLIM,
-				 TREE_TYPE (op3));
-            }
+	    info << "," << slim (TREE_TYPE (op3));
 
           if (op4)
-            {
-              dump_printf (MSG_NOTE, ",");
-              dump_generic_expr (MSG_NOTE, TDF_SLIM,
-				 TREE_TYPE (op4));
-            }
-          dump_printf (MSG_NOTE, "\n");
+	    info << "," << slim (TREE_TYPE (op4));
         }
 
       return NULL;
@@ -3692,9 +3653,9 @@ vect_get_known_peeling_cost (loop_vec_info loop_vinfo, int peel_iters_prologue,
     {
       *peel_iters_epilogue = assumed_vf / 2;
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_REMARK,
-			 "cost model: epilogue peel iters set to vf/2 "
-			 "because loop iterations are unknown .\n");
+        emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << ("cost model: epilogue peel iters set to vf/2 "
+	      "because loop iterations are unknown");
 
       /* If peeled iterations are known but number of scalar loop
          iterations are unknown, count a taken branch per peeled loop.  */
@@ -3777,7 +3738,8 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
   /* Cost model disabled.  */
   if (unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo)))
     {
-      vect_location_writeln (OPT_RECORD_REMARK, "cost model disabled.\n");
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "cost model disabled";
       *ret_min_profitable_niters = 0;
       *ret_min_profitable_estimate = 0;
       return;
@@ -4039,23 +4001,26 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
   
   if (optinfo_enabled_p ())
     {
-      vect_location_writeln (OPT_RECORD_REMARK, "Cost model analysis: \n");
-      dump_printf (MSG_NOTE, "  Vector inside of loop cost: %d\n",
-                   vec_inside_cost);
-      dump_printf (MSG_NOTE, "  Vector prologue cost: %d\n",
-                   vec_prologue_cost);
-      dump_printf (MSG_NOTE, "  Vector epilogue cost: %d\n",
-                   vec_epilogue_cost);
-      dump_printf (MSG_NOTE, "  Scalar iteration cost: %d\n",
-                   scalar_single_iter_cost);
-      dump_printf (MSG_NOTE, "  Scalar outside cost: %d\n",
-                   scalar_outside_cost);
-      dump_printf (MSG_NOTE, "  Vector outside cost: %d\n",
-                   vec_outside_cost);
-      dump_printf (MSG_NOTE, "  prologue iterations: %d\n",
-                   peel_iters_prologue);
-      dump_printf (MSG_NOTE, "  epilogue iterations: %d\n",
-                   peel_iters_epilogue);
+      /* FIXME: do we want to do something special for such a table of
+	 data?  */
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "Cost model analysis:\n"
+	<< optinfo_printf ("  Vector inside of loop cost: %d\n",
+			   vec_inside_cost)
+	<< optinfo_printf ("  Vector prologue cost: %d\n",
+			   vec_prologue_cost)
+	<< optinfo_printf ("  Vector epilogue cost: %d\n",
+			   vec_epilogue_cost)
+	<< optinfo_printf ("  Scalar iteration cost: %d\n",
+			   scalar_single_iter_cost)
+	<< optinfo_printf ("  Scalar outside cost: %d\n",
+			   scalar_outside_cost)
+	<< optinfo_printf ("  Vector outside cost: %d\n",
+			   vec_outside_cost)
+	<< optinfo_printf ("  prologue iterations: %d\n",
+			   peel_iters_prologue)
+	<< optinfo_printf ("  epilogue iterations: %d",
+			   peel_iters_epilogue);
     }
 
   /* Calculate number of iterations required to make the vector version
@@ -4096,12 +4061,11 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
 		    "did not happen for a simd loop");
 
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_FAILURE,
-			 "cost model: the vector iteration cost = %d "
-			 "divided by the scalar iteration cost = %d "
-			 "is greater or equal to the vectorization factor = %d"
-                         ".\n",
-			 vec_inside_cost, scalar_single_iter_cost, assumed_vf);
+        emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << optinfo_printf ("cost model: the vector iteration cost = %d "
+			     "divided by the scalar iteration cost = %d "
+			     "is greater or equal to the vectorization factor = %d",
+			     vec_inside_cost, scalar_single_iter_cost, assumed_vf);
       *ret_min_profitable_niters = -1;
       *ret_min_profitable_estimate = -1;
       return;
@@ -4117,9 +4081,9 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
     min_profitable_iters = assumed_vf + peel_iters_prologue;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-                     "  Runtime profitability threshold = %d\n",
-                     min_profitable_iters);
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << optinfo_printf ("  Runtime profitability threshold = %d",
+			 min_profitable_iters);
 
   *ret_min_profitable_niters = min_profitable_iters;
 
@@ -4143,9 +4107,9 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
     }
   min_profitable_estimate = MAX (min_profitable_estimate, min_profitable_iters);
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-		     "  Static estimate profitability threshold = %d\n",
-		     min_profitable_estimate);
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << optinfo_printf ("  Static estimate profitability threshold = %d",
+			 min_profitable_estimate);
 
   *ret_min_profitable_estimate = min_profitable_estimate;
 }
@@ -4395,9 +4359,10 @@ vect_model_induction_cost (stmt_vec_info stmt_info, int ncopies)
 				 stmt_info, 0, vect_prologue);
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK,
-                     "vect_model_induction_cost: inside_cost = %d, "
-                     "prologue_cost = %d .\n", inside_cost, prologue_cost);
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << optinfo_printf ("vect_model_induction_cost: inside_cost = %d, "
+			 "prologue_cost = %d",
+			 inside_cost, prologue_cost);
 }
 
 
@@ -4989,10 +4954,9 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
 
           if (optinfo_enabled_p ())
             {
-              vect_location_writeln (OPT_RECORD_REMARK,
-			       "transform reduction: created def-use cycle: ");
-              dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
-              dump_gimple_stmt (MSG_NOTE, TDF_SLIM, SSA_NAME_DEF_STMT (def), 0);
+              emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "transform reduction: created def-use cycle: "
+		<< phi << SSA_NAME_DEF_STMT (def);
             }
         }
     }
@@ -5477,8 +5441,8 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
          v_out2 = reduc_expr <v_out1>  */
 
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_REMARK,
-			 "Reduce using direct vector reduction.\n");
+        emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "Reduce using direct vector reduction";
 
       vec_elem_type = TREE_TYPE (TREE_TYPE (new_phi_result));
       if (!useless_type_conversion_p (scalar_type, vec_elem_type))
@@ -5748,8 +5712,8 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
           tree rhs;
 
           if (optinfo_enabled_p ())
-            vect_location_writeln (OPT_RECORD_REMARK,
-			     "Reduce using vector shifts\n");
+            emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "Reduce using vector shifts";
 
 	  mode1 = TYPE_MODE (vectype1);
           vec_dest = vect_create_destination_var (scalar_dest, vectype1);
@@ -5777,8 +5741,8 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
 	     s_out3 = extract_field <v_out2, bitpos>  */
 
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_REMARK,
-			     "extract scalar result\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "extract scalar result";
 
 	  rhs = build3 (BIT_FIELD_REF, scalar_type, new_temp,
 			bitsize, bitsize_zero_node);
@@ -5801,8 +5765,8 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
                }  */
 
           if (optinfo_enabled_p ())
-            vect_location_writeln (OPT_RECORD_REMARK,
-			     "Reduce using scalar code.\n");
+            emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "Reduce using scalar code";
 
 	  int vec_size_in_bits = tree_to_uhwi (TYPE_SIZE (vectype1));
 	  int element_bitsize = tree_to_uhwi (bitsize);
@@ -6125,9 +6089,9 @@ vect_finalize_reduction:
                                loop_latch_edge (outer_loop), UNKNOWN_LOCATION);
                   if (optinfo_enabled_p ())
                     {
-                      vect_location_writeln (OPT_RECORD_REMARK,
-				       "created double reduction phi node: ");
-                      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, vect_phi, 0);
+                      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+			<< "created double reduction phi node: "
+			<< vect_phi;
                     }
 
                   vect_phi_res = PHI_RESULT (vect_phi);
@@ -6807,8 +6771,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       if (STMT_VINFO_REDUC_TYPE (stmt_info) == FOLD_LEFT_REDUCTION)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "in-order reduction chain without SLP.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "in-order reduction chain without SLP";
 	  return false;
 	}
 
@@ -6861,8 +6825,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       if (reduc_index == -1)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "conditional reduction chains not supported\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "conditional reduction chains not supported";
 	  return false;
 	}
 
@@ -6886,9 +6850,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 					       vectype_in, OPTIMIZE_FOR_SPEED))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "optimizing condition reduction with"
-			     " FOLD_EXTRACT_LAST.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "optimizing condition reduction with FOLD_EXTRACT_LAST";
 	  STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info) = EXTRACT_LAST_REDUCTION;
 	}
       else if (cond_reduc_dt == vect_induction_def)
@@ -6927,9 +6890,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	  if (cond_reduc_val)
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_REMARK,
-				 "condition expression based on "
-				 "integer induction.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		  << "condition expression based on integer induction";
 	      STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
 		= INTEGER_INDUC_COND_REDUCTION;
 	    }
@@ -6953,9 +6915,9 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	      if (e && (integer_onep (e) || integer_zerop (e)))
 		{
 		  if (optinfo_enabled_p ())
-		    vect_location_writeln (OPT_RECORD_REMARK,
-				     "condition expression based on "
-				     "compile time constant.\n");
+		    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		      << ("condition expression based on "
+			  "compile time constant");
 		  /* Record reduction code at analysis stage.  */
 		  STMT_VINFO_VEC_CONST_COND_REDUC_CODE (stmt_info)
 		    = integer_onep (e) ? MAX_EXPR : MIN_EXPR;
@@ -6996,8 +6958,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 						ops[reduc_index], 0, NULL))
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "unsupported condition in reduction\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "unsupported condition in reduction";
 	  return false;
         }
     }
@@ -7011,8 +6973,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	  /* Shifts and rotates are only supported by vectorizable_shifts,
 	     not vectorizable_reduction.  */
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "unsupported shift or rotation.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "unsupported shift or rotation";
 	  return false;
 	}
 
@@ -7021,8 +6983,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       if (!optab)
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "no optab.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "no optab";
 
           return false;
         }
@@ -7045,8 +7007,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	  && !vect_worthwhile_without_simd_p (loop_vinfo, code))
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "not worthwhile without SIMD support.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "not worthwhile without SIMD support";
 
           return false;
         }
@@ -7151,8 +7113,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 						  OPTIMIZE_FOR_SPEED))
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "reduc op not supported by target.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << "reduc op not supported by target";
 
 	      reduc_fn = IFN_LAST;
 	    }
@@ -7162,8 +7124,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	  if (!nested_cycle || double_reduc)
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "no reduc code for scalar code.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << "no reduc code for scalar code";
 
 	      return false;
 	    }
@@ -7187,9 +7149,9 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       && !nunits_out.is_constant ())
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "missing target support for reduction on"
-			 " variable-length vectors.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << ("missing target support for reduction on"
+	      " variable-length vectors");
       return false;
     }
 
@@ -7197,9 +7159,9 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       && ncopies > 1)
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "multiple types in double reduction or condition "
-			 "reduction.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << ("multiple types in double reduction or condition "
+	      "reduction");
       return false;
     }
 
@@ -7227,8 +7189,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 
 	 which is a reassociation of the original operation.  */
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "in-order double reduction not supported.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "in-order double reduction not supported";
 
       return false;
     }
@@ -7240,8 +7202,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       /* We cannot use in-order reductions in this case because there is
 	 an implicit reassociation of the operations involved.  */
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "in-order unchained SLP reductions not supported.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << "in-order unchained SLP reductions not supported";
       return false;
     }
 
@@ -7255,10 +7217,10 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 					  vectype_out, OPTIMIZE_FOR_SPEED))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "reduction on variable-length vectors requires"
-			 " target support for a vector-shift-and-insert"
-			 " operation.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << ("reduction on variable-length vectors requires"
+	      " target support for a vector-shift-and-insert"
+	      " operation");
       return false;
     }
 
@@ -7278,10 +7240,10 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	  && !can_duplicate_and_interleave_p (group_size, elt_mode))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "unsupported form of SLP reduction for"
-			     " variable-length vectors: cannot build"
-			     " initial vector.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << ("unsupported form of SLP reduction for"
+		  " variable-length vectors: cannot build"
+		  " initial vector");
 	  return false;
 	}
       /* The epilogue code relies on the number of elements being a multiple
@@ -7290,10 +7252,10 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       if (!multiple_p (nunits_out, group_size))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "unsupported form of SLP reduction for"
-			     " variable-length vectors: the vector size"
-			     " is not a multiple of the number of results.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << ("unsupported form of SLP reduction for"
+		  " variable-length vectors: the vector size"
+		  " is not a multiple of the number of results");
 	  return false;
 	}
     }
@@ -7311,8 +7273,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       else
         {
           if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "invalid types in dot-prod\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "invalid types in dot-prod";
 
           return false;
         }
@@ -7325,9 +7287,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       if (! max_loop_iterations (loop, &ni))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_REMARK,
-			     "loop count not known, cannot create cond "
-			     "reduction.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "loop count not known, cannot create cond reduction";
 	  return false;
 	}
       /* Convert backedges to iterations.  */
@@ -7340,8 +7301,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
       if (wi::geu_p (ni, wi::to_widest (max_index)))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_REMARK,
-			     "loop size is greater than data size.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "loop size is greater than data size";
 	  return false;
 	}
     }
@@ -7398,9 +7359,9 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	  || code == SAD_EXPR))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "multi def-use cycle not possible for lane-reducing "
-			 "reduction operation\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << ("multi def-use cycle not possible for lane-reducing "
+	      "reduction operation");
       return false;
     }
 
@@ -7424,17 +7385,17 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 						      OPTIMIZE_FOR_SPEED)))
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "can't use a fully-masked loop because no"
-				 " conditional operation is available.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << ("can't use a fully-masked loop because no"
+		      " conditional operation is available");
 	      LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
 	    }
 	  else if (reduc_index == -1)
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "can't use a fully-masked loop for chained"
-				 " reductions.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << ("can't use a fully-masked loop for chained"
+		      " reductions");
 	      LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
 	    }
 	  else
@@ -7443,8 +7404,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
 	}
       if (optinfo_enabled_p ()
 	  && reduction_type == FOLD_LEFT_REDUCTION)
-	vect_location_writeln (OPT_RECORD_REMARK,
-			 "using an in-order (fold-left) reduction.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "using an in-order (fold-left) reduction";
       STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
       return true;
     }
@@ -7452,7 +7413,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
   /* Transform.  */
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK, "transform reduction.\n");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "transform reduction";
 
   /* FORNOW: Multiple types are not supported for condition.  */
   if (code == COND_EXPR)
@@ -7747,8 +7709,8 @@ vectorizable_induction (gimple *phi,
       if (ncopies > 1)
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "multiple types in nested loop.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << "multiple types in nested loop";
 	  return false;
 	}
 
@@ -7778,9 +7740,9 @@ vectorizable_induction (gimple *phi,
 		&& !STMT_VINFO_LIVE_P (exit_phi_vinfo)))
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "inner-loop induction only used outside "
-				 "of the outer vectorized loop.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << ("inner-loop induction only used outside "
+		      "of the outer vectorized loop");
 	      return false;
 	    }
 	}
@@ -7796,9 +7758,9 @@ vectorizable_induction (gimple *phi,
     {
       /* The current SLP code creates the initial value element-by-element.  */
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_FAILURE,
-			 "SLP induction not supported for variable-length"
-			 " vectors.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	  << ("SLP induction not supported for variable-length"
+	      " vectors.\n");
       return false;
     }
 
@@ -7806,8 +7768,8 @@ vectorizable_induction (gimple *phi,
     {
       STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
       if (optinfo_enabled_p ())
-        vect_location_writeln (OPT_RECORD_REMARK,
-                         "=== vectorizable_induction ===\n");
+        emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "=== vectorizable_induction ===";
       vect_model_induction_cost (stmt_info, ncopies);
       return true;
     }
@@ -7820,7 +7782,8 @@ vectorizable_induction (gimple *phi,
      [X, X + S, X + 2*S, X + 3*S].  */
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK, "transform induction phi.\n");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "transform induction phi";
 
   latch_e = loop_latch_edge (iv_loop);
   loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e);
@@ -8213,9 +8176,8 @@ vectorizable_induction (gimple *phi,
 	  STMT_VINFO_VEC_STMT (stmt_vinfo) = new_stmt;
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK,
-			       "vector of inductions after inner-loop:");
-	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, new_stmt, 0);
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "vector of inductions after inner-loop:" << new_stmt;
 	    }
 	}
     }
@@ -8223,11 +8185,9 @@ vectorizable_induction (gimple *phi,
 
   if (optinfo_enabled_p ())
     {
-      vect_location_writeln (OPT_RECORD_REMARK,
-		       "transform induction: created def-use cycle: ");
-      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, induction_phi, 0);
-      dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
-			SSA_NAME_DEF_STMT (vec_def), 0);
+      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	<< "transform induction: created def-use cycle: "
+	<< induction_phi << SSA_NAME_DEF_STMT (vec_def);
     }
 
   return true;
@@ -8273,9 +8233,8 @@ vectorizable_live_operation (gimple *stmt,
     {
       gcc_assert (is_simple_and_all_uses_invariant (stmt, loop_vinfo));
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_REMARK,
-			 "statement is simple and uses invariant.  Leaving in "
-			 "place.\n");
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << "statement is simple and uses invariant.  Leaving in place";
       return true;
     }
 
@@ -8301,9 +8260,9 @@ vectorizable_live_operation (gimple *stmt,
       if (!can_div_trunc_p (pos, nunits, &vec_entry, &vec_index))
 	{
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_FAILURE,
-			     "Cannot determine which vector holds the"
-			     " final result.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+	      << ("Cannot determine which vector holds the"
+		  " final result");
 	  return false;
 	}
     }
@@ -8317,26 +8276,26 @@ vectorizable_live_operation (gimple *stmt,
 					       OPTIMIZE_FOR_SPEED))
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "can't use a fully-masked loop because "
-				 "the target doesn't support extract last "
-				 "reduction.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << ("can't use a fully-masked loop because "
+		      "the target doesn't support extract last "
+		      "reduction");
 	      LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
 	    }
 	  else if (slp_node)
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "can't use a fully-masked loop because an "
-				 "SLP statement is live after the loop.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << ("can't use a fully-masked loop because an "
+		      "SLP statement is live after the loop");
 	      LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
 	    }
 	  else if (ncopies > 1)
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_FAILURE,
-				 "can't use a fully-masked loop because"
-				 " ncopies is greater than 1.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_FAILURE)
+		  << ("can't use a fully-masked loop because"
+		      " ncopies is greater than 1.\n");
 	      LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
 	    }
 	  else
@@ -8482,8 +8441,8 @@ vect_loop_kill_debug_uses (struct loop *loop, gimple *stmt)
 	      if (gimple_debug_bind_p (ustmt))
 		{
 		  if (optinfo_enabled_p ())
-		    vect_location_writeln (OPT_RECORD_REMARK,
-                                     "killing debug use\n");
+		    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		      << "killing debug use";
 
 		  gimple_debug_bind_reset_value (ustmt);
 		  update_stmt (ustmt);
@@ -8683,7 +8642,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
   unsigned int th;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK, "=== vec_transform_loop ===\n");
+    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+      << "=== vec_transform_loop ===";
 
   /* Use the more conservative vectorization threshold.  If the number
      of iterations is constant assume the cost check has been performed
@@ -8695,9 +8655,9 @@ vect_transform_loop (loop_vec_info loop_vinfo)
       && !LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
     {
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_REMARK,
-			 "Profitability threshold is %d loop iterations.\n",
-                         th);
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << optinfo_printf ("Profitability threshold is %d loop iterations",
+			     th);
       check_profitability = true;
     }
 
@@ -8798,9 +8758,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 	  gphi *phi = si.phi ();
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK,
-                               "------>vectorizing phi: ");
-	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "------>vectorizing phi: " << phi;
 	    }
 	  stmt_info = vinfo_for_stmt (phi);
 	  if (!stmt_info)
@@ -8817,7 +8776,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 	      && (maybe_ne
 		  (TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info)), vf))
 	      && optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_REMARK, "multiple-types.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "multiple-types";
 
 	  if ((STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def
 	       || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def
@@ -8825,7 +8785,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 	      && ! PURE_SLP_STMT (stmt_info))
 	    {
 	      if (optinfo_enabled_p ())
-		vect_location_writeln (OPT_RECORD_REMARK, "transform phi.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		  << "transform phi";
 	      vect_transform_stmt (phi, NULL, NULL, NULL, NULL);
 	    }
 	}
@@ -8853,9 +8814,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK,
-			       "------>vectorizing statement: ");
-	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "------>vectorizing statement: " << stmt;
 	    }
 
 	  stmt_info = vinfo_for_stmt (stmt);
@@ -8925,11 +8885,9 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 		    {
 		      if (optinfo_enabled_p ())
 			{
-			  vect_location_writeln (OPT_RECORD_REMARK,
-					   "==> vectorizing pattern def "
-					   "stmt: ");
-			  dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
-					    pattern_def_stmt, 0);
+			  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+			    << "==> vectorizing pattern def stmt: "
+			    << pattern_def_stmt;
 			}
 
 		      stmt = pattern_def_stmt;
@@ -8954,7 +8912,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 		  && optinfo_enabled_p ())
 		  /* For SLP VF is set according to unrolling factor, and not
 		     to vector size, hence for SLP this print is not valid.  */
-		vect_location_writeln (OPT_RECORD_REMARK, "multiple-types.\n");
+		emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		  << "multiple-types";
 	    }
 
 	  /* SLP. Schedule all the SLP instances when the first SLP stmt is
@@ -8966,8 +8925,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 		  slp_scheduled = true;
 
 		  if (optinfo_enabled_p ())
-		    vect_location_writeln (OPT_RECORD_REMARK,
-				     "=== scheduling SLP instances ===\n");
+		    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		      << "=== scheduling SLP instances ===";
 
 		  vect_schedule_slp (loop_vinfo);
 		}
@@ -8986,7 +8945,8 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 
 	  /* -------- vectorize statement ------------ */
 	  if (optinfo_enabled_p ())
-	    vect_location_writeln (OPT_RECORD_REMARK, "transform statement.\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "transform statement";
 
 	  grouped_store = false;
 	  is_store = vect_transform_stmt (stmt, &si, &grouped_store, NULL, NULL);
@@ -9101,19 +9061,21 @@ vect_transform_loop (loop_vec_info loop_vinfo)
     {
       if (!LOOP_VINFO_EPILOGUE_P (loop_vinfo))
 	{
-	  vect_location_writeln (OPT_RECORD_REMARK,
-			   "LOOP VECTORIZED\n");
+	  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	    << "LOOP VECTORIZED";
 	  if (loop->inner)
-	    vect_location_writeln (OPT_RECORD_REMARK,
-			     "OUTER LOOP VECTORIZED\n");
+	    emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	      << "OUTER LOOP VECTORIZED";
 	  dump_printf (MSG_NOTE, "\n");
 	}
       else
 	{
-	  vect_location_writeln (OPT_RECORD_REMARK,
-			   "LOOP EPILOGUE VECTORIZED (VS=");
+#if 0
+	  emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	    << "LOOP EPILOGUE VECTORIZED (VS="
 	  dump_dec (MSG_NOTE, current_vector_size);
-	  dump_printf (MSG_NOTE, ")\n");
+	    << ")";
+#endif
 	}
     }
 
@@ -9270,9 +9232,9 @@ optimize_mask_stores (struct loop *loop)
       if (dom_info_available_p (CDI_DOMINATORS))
 	set_immediate_dominator (CDI_DOMINATORS, store_bb, bb);
       if (optinfo_enabled_p ())
-	vect_location_writeln (OPT_RECORD_REMARK,
-			 "Create new block %d to sink mask stores.",
-			 store_bb->index);
+	emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+	  << optinfo_printf ("Create new block %d to sink mask stores.",
+			     store_bb->index);
       /* Create vector comparison with boolean result.  */
       vectype = TREE_TYPE (mask);
       zero = build_zero_cst (vectype);
@@ -9310,9 +9272,8 @@ optimize_mask_stores (struct loop *loop)
 	  gsi_to = gsi_start_bb (store_bb);
 	  if (optinfo_enabled_p ())
 	    {
-	      vect_location_writeln (OPT_RECORD_REMARK,
-			       "Move stmt to created bb\n");
-	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, last, 0);
+	      emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		<< "Move stmt to created bb " << last;
 	    }
 	  /* Move all stored value producers if possible.  */
 	  while (!gsi_end_p (gsi))
@@ -9377,11 +9338,9 @@ optimize_mask_stores (struct loop *loop)
 
 	      /* Can move STMT1 to STORE_BB.  */
 	      if (optinfo_enabled_p ())
-		{
-		  vect_location_writeln (OPT_RECORD_REMARK,
-				   "Move stmt to created bb\n");
-		  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt1, 0);
-		}
+		emit_optinfo_at_vect_location (OPT_RECORD_REMARK)
+		  << "move stmt to created bb"
+		  << stmt1;
 	      gsi_move_before (&gsi_from, &gsi_to);
 	      /* Shift GSI_TO for further insertion.  */
 	      gsi_prev (&gsi_to);
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 88556f2..fb6f31e 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -3057,7 +3057,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_iterator region_begin,
       if (optinfo_enabled_p ())
         vect_location_writeln (OPT_RECORD_FAILURE,
 			 "not vectorized: unhandled data-ref in basic "
-			 "block.\n");
+			 "block");
 
       delete bb_vinfo;
       return NULL;
@@ -3068,7 +3068,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_iterator region_begin,
       if (optinfo_enabled_p ())
         vect_location_writeln (OPT_RECORD_FAILURE,
 			 "not vectorized: not enough data-refs in "
-			 "basic block.\n");
+			 "basic block");
 
       delete bb_vinfo;
       return NULL;
@@ -3079,7 +3079,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_iterator region_begin,
      if (optinfo_enabled_p ())
        vect_location_writeln (OPT_RECORD_FAILURE,
 			"not vectorized: unhandled data access in "
-			"basic block.\n");
+			"basic block");
 
       delete bb_vinfo;
       return NULL;
@@ -3196,7 +3196,7 @@ vect_slp_bb (basic_block bb)
   auto_vector_sizes vector_sizes;
 
   if (optinfo_enabled_p ())
-    vect_location_writeln (OPT_RECORD_REMARK, "===vect_slp_analyze_bb===\n");
+    vect_location_writeln (OPT_RECORD_REMARK, "===vect_slp_analyze_bb===");
 
   /* Autodetect first vector size we try.  */
   current_vector_size = 0;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 9360308..1a08b5e 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1393,6 +1393,7 @@ extern void vect_location_writeln (enum opt_record_kind kind,
 				   const char *fmt, ...)
   ATTRIBUTE_PRINTF_2;
 
+extern pending_optinfo emit_optinfo_at_vect_location (enum opt_record_kind);
 
 /*-----------------------------------------------------------------*/
 /* Function prototypes.                                            */
-- 
1.8.5.3

