From c2feaeafb65878e70bb834b15f81fd67bcb9965c Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 20 Oct 2016 21:44:54 -0400
Subject: [PATCH 18/28] FIXME: implement support for reuse_rtx in loader

---
 gcc/read-md.h                             |  3 +++
 gcc/read-rtl-function.c                   | 22 ++++++++++++++++++++++
 gcc/read-rtl.c                            | 28 ++++++++++++++++++++++++++++
 gcc/testsuite/selftests/x86_64/unspec.rtl |  8 ++++----
 4 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/gcc/read-md.h b/gcc/read-md.h
index 7b7fdfa..b20928b 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -280,6 +280,9 @@ class rtx_reader : public md_reader
  protected:
   /* Analogous to print-rtl.c's in_call_function_usage.  */
   bool m_in_call_function_usage;
+
+  /* FIXME.  */
+  auto_vec<rtx> m_reuse_rtx_by_id;
 };
 
 /* Global singleton; constrast with md_reader_ptr above.  */
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index 94cd277..6a0298b 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -56,6 +56,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "read-rtl-function.h"
 #include "selftest.h"
 #include "selftest-rtl.h"
+#include "insn-config.h"
+#include "recog.h"
 
 /* Forward decls.  */
 class function_reader;
@@ -2394,6 +2396,26 @@ test_loading_unspec ()
   ASSERT_EQ (UNSPEC_MEMORY_BLOCKAGE, XINT (src, 1));
 #endif
 
+  rtx v0 = XVECEXP (src, 0, 0);
+
+  /* Verify that the two uses of the first SCRATCH have pointer
+     equality.  */
+  rtx scratch_a = XEXP (dst, 0);
+  ASSERT_EQ (SCRATCH, GET_CODE (scratch_a));
+
+  rtx scratch_b = XEXP (v0, 0);
+  ASSERT_EQ (SCRATCH, GET_CODE (scratch_b));
+
+  ASSERT_EQ (scratch_a, scratch_b);
+
+  /* Verify that the two mems are thus treated as equal.  */
+  ASSERT_TRUE (rtx_equal_p (dst, v0));
+
+#ifdef I386_OPTS_H
+  /* Verify the the insn is recognized.  */
+  ASSERT_NE(-1, recog_memoized (insn));
+#endif
+
   /* Test of an UNSPEC_VOLATILE, which has its own enum values.  */
   insn = NEXT_INSN (insn);
   ASSERT_EQ (INSN, GET_CODE (insn));
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index a00f982..87ca158 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -1223,6 +1223,7 @@ rtx_reader::read_rtx_code (const char *code_name)
   struct md_name name;
   rtx return_rtx;
   int c;
+  long reuse_id = -1;
 
   /* Linked list structure for making RTXs: */
   struct rtx_list
@@ -1233,6 +1234,26 @@ rtx_reader::read_rtx_code (const char *code_name)
 
   one_time_initialization ();
 
+  /* Handle reuse_rtx ids e.g. "(0|scratch:DI)".  */
+  if (ISDIGIT (code_name[0]))
+    {
+      reuse_id = atoi (code_name);
+      while (char ch = *code_name++)
+	if (ch == '|')
+	  break;
+    }
+
+  /* Handle "reuse_rtx".  */
+  if (strcmp (code_name, "reuse_rtx") == 0)
+    {
+      read_name (&name);
+      long idx = atoi (name.string);
+      /* Look it up by ID.  */
+      gcc_assert (idx < m_reuse_rtx_by_id.length ());
+      return_rtx = m_reuse_rtx_by_id[idx];
+      return return_rtx;
+    }
+
   /* If this code is an iterator, build the rtx using the iterator's
      first value.  */
 #ifdef GENERATOR_FILE
@@ -1251,6 +1272,13 @@ rtx_reader::read_rtx_code (const char *code_name)
   memset (return_rtx, 0, RTX_CODE_SIZE (code));
   PUT_CODE (return_rtx, code);
 
+  if (reuse_id != -1)
+    {
+      /* Store away for later reuse.  */
+      m_reuse_rtx_by_id.safe_grow_cleared (reuse_id + 1);
+      m_reuse_rtx_by_id[reuse_id] = return_rtx;
+    }
+
   if (iterator)
     record_iterator_use (iterator, return_rtx);
 
diff --git a/gcc/testsuite/selftests/x86_64/unspec.rtl b/gcc/testsuite/selftests/x86_64/unspec.rtl
index 892c532..5d886dd 100644
--- a/gcc/testsuite/selftests/x86_64/unspec.rtl
+++ b/gcc/testsuite/selftests/x86_64/unspec.rtl
@@ -2,15 +2,15 @@
   (insn-chain
     (block 2
       (edge-from entry (flags "FALLTHRU"))
-      (cinsn (set (mem/v:BLK (scratch:DI) [0  A8])
+      (cinsn (set (mem/v:BLK (0|scratch:DI) [0  A8])
                     (unspec:BLK [
-                            (mem/v:BLK (scratch:DI) [0  A8])
+                            (mem/v:BLK (reuse_rtx 0) [0  A8])
                         ] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
                  (nil))
 
-      (cinsn (set (mem/v:BLK (scratch:DI) [0  A8])
+      (cinsn (set (mem/v:BLK (1|scratch:DI) [0  A8])
                     (unspec_volatile:BLK [
-                            (mem/v:BLK (scratch:DI) [0  A8])
+                            (mem/v:BLK (reuse_rtx 1) [0  A8])
                         ] UNSPECV_RDTSCP)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
                  (nil))
 
-- 
1.8.5.3

