From 086d97be84478819ccd27bd0c421a35648f134c6 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 3 Nov 2016 14:10:48 -0400
Subject: [PATCH 16/28] FIXME: WIP on adding reuse_rtx

---
 gcc/print-rtl-function.c |   5 ++
 gcc/print-rtl-reuse.h    |  52 ++++++++++++++++++
 gcc/print-rtl.c          | 139 +++++++++++++++++++++++++++++++++++++++++++++--
 gcc/rtl-tests.c          |  31 +++++++++++
 4 files changed, 223 insertions(+), 4 deletions(-)
 create mode 100644 gcc/print-rtl-reuse.h

diff --git a/gcc/print-rtl-function.c b/gcc/print-rtl-function.c
index f37e1b7..2ccd617 100644
--- a/gcc/print-rtl-function.c
+++ b/gcc/print-rtl-function.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "basic-block.h"
 #include "print-rtl.h"
+#include "print-rtl-reuse.h"
 #include "langhooks.h"
 #include "memmodel.h"
 #include "emit-rtl.h"
@@ -191,6 +192,10 @@ print_rtx_function (FILE *outfile, function *fn, bool compact)
 {
   rtx_writer w (outfile, 0, false, compact);
 
+  rtx_reuse r;
+  for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    r.preprocess (insn);
+
   tree fdecl = fn->decl;
 
   const char *dname = lang_hooks.decl_printable_name (fdecl, 2);
diff --git a/gcc/print-rtl-reuse.h b/gcc/print-rtl-reuse.h
new file mode 100644
index 0000000..505d5be
--- /dev/null
+++ b/gcc/print-rtl-reuse.h
@@ -0,0 +1,52 @@
+/* Track pointer reuse when printing RTL.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_PRINT_RTL_REUSE_H
+#define GCC_PRINT_RTL_REUSE_H
+
+#ifndef GENERATOR_FILE
+
+#include "bitmap.h"
+
+/* Track repeated occurrences of things like SCRATCH, so we can emit
+   them as "reuse_rtx".  */
+class rtx_reuse
+{
+ public:
+  rtx_reuse ();
+  ~rtx_reuse ();
+  static rtx_reuse *get () { return singleton; }
+
+  void preprocess (const_rtx x);
+  bool has_reuse_id (const_rtx x, int *out);
+
+  bool seen_def_p (int id);
+  void set_seen_def (int id);
+
+ private:
+  static rtx_reuse *singleton;
+  hash_map<const_rtx, int> m_rtx_occurrence_count;
+  hash_map<const_rtx, int> m_rtx_reuse_ids;
+  bitmap_head m_defs_seen;
+  int m_next_id;
+};
+
+#endif /* #ifndef GENERATOR_FILE */
+
+#endif  // GCC_PRINT_RTL_REUSE_H
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index a8e9f84..3262928 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -51,6 +51,8 @@ along with GCC; see the file COPYING3.  If not see
 #endif
 
 #include "print-rtl.h"
+#include "print-rtl-reuse.h"
+#include "rtl-iter.h"
 
 /* String printed at beginning of each RTL when it is dumped.
    This string is set to ASM_COMMENT_START when the RTL is dumped in
@@ -81,6 +83,110 @@ rtx_writer::rtx_writer (FILE *outf, int ind, bool simple, bool compact)
 }
 
 #ifndef GENERATOR_FILE
+
+/* FIXME.  */
+
+rtx_reuse *rtx_reuse::singleton = NULL;
+
+/* FIXME.  */
+
+rtx_reuse::rtx_reuse ()
+: m_next_id (0)
+{
+  gcc_assert (singleton == NULL);
+  singleton = this;
+
+  bitmap_initialize (&m_defs_seen, NULL);
+}
+
+/* FIXME.  */
+
+rtx_reuse::~rtx_reuse ()
+{
+  gcc_assert (singleton == this);
+  singleton = NULL;
+}
+
+/* FIXME.  */
+
+static bool
+uses_rtx_reuse_p (const_rtx x)
+{
+  if (x == NULL)
+    return false;
+
+  switch (GET_CODE (x))
+    {
+    case DEBUG_EXPR:
+    case VALUE:
+    case SCRATCH:
+      //CASE_CONST_UNIQUE:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+/* FIXME.  */
+
+void
+rtx_reuse::preprocess (const_rtx x)
+{
+  /* FIXME: locate dups.  */
+
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, NONCONST)
+    if (uses_rtx_reuse_p (*iter))
+      {
+	if (int *count = m_rtx_occurrence_count.get (*iter))
+	  {
+	    if (*count == 1)
+	      {
+		m_rtx_reuse_ids.put (*iter, m_next_id++);
+	      }
+	    (*count)++;
+	  }
+	else
+	  m_rtx_occurrence_count.put (*iter, 1);
+      }
+}
+
+/* FIXME.  */
+
+bool
+rtx_reuse::has_reuse_id (const_rtx x, int *out)
+{
+  int *id = m_rtx_reuse_ids.get (x);
+  if (id)
+    {
+      if (out)
+	*out = *id;
+      return true;
+    }
+  else
+    return false;
+}
+
+/* FIXME.  */
+
+bool
+rtx_reuse::seen_def_p (int id)
+{
+  return bitmap_bit_p (&m_defs_seen, id);
+}
+
+/* FIXME.  */
+
+void
+rtx_reuse::set_seen_def (int id)
+{
+  bitmap_set_bit (&m_defs_seen, id);
+}
+
+#endif /* #ifndef GENERATOR_FILE */
+
+#ifndef GENERATOR_FILE
 void
 print_mem_expr (FILE *outfile, const_tree expr)
 {
@@ -631,8 +737,33 @@ rtx_writer::print_rtx (const_rtx in_rtx)
        return;
     }
 
+  fputc ('(', m_outfile);
+
   /* Print name of expression code.  */
 
+  /* Handle reuse.  */
+#ifndef GENERATOR_FILE
+  if (rtx_reuse::get ())
+    {
+      int reuse_id;
+      if (rtx_reuse::get ()->has_reuse_id (in_rtx, &reuse_id))
+	{
+	  /* Have we already seen the defn of this rtx?  */
+	  if (rtx_reuse::get ()->seen_def_p (reuse_id))
+	    {
+	      fprintf (m_outfile, "reuse_rtx %i)", reuse_id);
+	      m_sawclose = 1;
+	      return;
+	    }
+	  else
+	    {
+	      fprintf (m_outfile, "%i|", reuse_id);
+	      rtx_reuse::get ()->set_seen_def (reuse_id);
+	    }
+	}
+    }
+#endif /* #ifndef GENERATOR_FILE */
+
   /* In compact mode, prefix the code of insns with "c",
      giving "cinsn", "cnote" etc.  */
   if (m_compact && is_a <const rtx_insn *, const struct rtx_def> (in_rtx))
@@ -641,14 +772,14 @@ rtx_writer::print_rtx (const_rtx in_rtx)
 	 just "clabel".  */
       rtx_code code = GET_CODE (in_rtx);
       if (code == CODE_LABEL)
-	fprintf (m_outfile, "(clabel");
+	fprintf (m_outfile, "clabel");
       else
-	fprintf (m_outfile, "(c%s", GET_RTX_NAME (code));
+	fprintf (m_outfile, "c%s", GET_RTX_NAME (code));
     }
   else if (m_simple && CONST_INT_P (in_rtx))
-    fputc ('(', m_outfile);
+    ; /* no code.  */
   else
-    fprintf (m_outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
+    fprintf (m_outfile, "%s", GET_RTX_NAME (GET_CODE (in_rtx)));
 
   if (! m_simple)
     {
diff --git a/gcc/rtl-tests.c b/gcc/rtl-tests.c
index 228226b..3904fa5 100644
--- a/gcc/rtl-tests.c
+++ b/gcc/rtl-tests.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "pretty-print.h"
 #include "cfgbuild.h"
 #include "print-rtl.h"
+#include "print-rtl-reuse.h"
 #include "selftest.h"
 #include "selftest-rtl.h"
 #include "function.h"
@@ -126,6 +127,36 @@ test_dumping_insns ()
 
   LABEL_NAME (label)= "some_label";
   ASSERT_RTL_DUMP_EQ ("(clabel 0 42 (\"some_label\"))\n", label);
+
+  /* Manually exercise the rtx_reuse code.  */
+  {
+    rtx x = rtx_alloc (SCRATCH);
+    rtx y = rtx_alloc (SCRATCH);
+    rtx_reuse r;
+    r.preprocess (x);
+    r.preprocess (x);
+    r.preprocess (y);
+    r.preprocess (y);
+    ASSERT_RTL_DUMP_EQ ("(0|scratch)", x);
+    ASSERT_RTL_DUMP_EQ ("(reuse_rtx 0)", x);
+    ASSERT_RTL_DUMP_EQ ("(1|scratch)", y);
+    ASSERT_RTL_DUMP_EQ ("(reuse_rtx 1)", y);
+  }
+
+  /* Test dumping an insn with repeated references to the same SCRATCH.  */
+#ifdef I386_OPTS_H
+  {
+    rtx pat = gen_memory_blockage ();
+    rtx_reuse r;
+    r.preprocess (pat);
+    ASSERT_RTL_DUMP_EQ
+      ("(cinsn (set (mem/v:BLK (0|scratch:DI) [0  A8])\n"
+       "        (unspec:BLK [\n"
+       "                (mem/v:BLK (reuse_rtx 0) [0  A8])\n"
+       "            ] UNSPEC_MEMORY_BLOCKAGE))\n"
+       "     (nil))\n", pat);
+  }
+#endif /* #ifdef I386_OPTS_H */
 }
 
 /* Unit testing of "single_set".  */
-- 
1.8.5.3

