From 4eb02815f6d4f2578ea0115837d9e39aca77ea12 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 14 Jul 2016 06:40:55 -0400
Subject: [PATCH 30/36] FIXME: start adding selftest for RTL loader

---
 gcc/Makefile.in          |  1 +
 gcc/combine.c            | 40 +++-------------------
 gcc/emit-rtl.c           | 13 +++++++
 gcc/function-tests.c     |  2 +-
 gcc/read-rtl-function.c  | 89 ++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/rtl.h                |  2 ++
 gcc/selftest-rtl.c       | 68 ++++++++++++++++++++++++++++++++++++
 gcc/selftest-run-tests.c |  1 +
 gcc/selftest.h           | 13 +++++++
 9 files changed, 192 insertions(+), 37 deletions(-)
 create mode 100644 gcc/selftest-rtl.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index b761ddc..3097dc0 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1433,6 +1433,7 @@ OBJS = \
 	sel-sched-ir.o \
 	sel-sched-dump.o \
 	sel-sched.o \
+	selftest-rtl.o \
 	selftest-run-tests.o \
 	sese.o \
 	shrink-wrap.o \
diff --git a/gcc/combine.c b/gcc/combine.c
index 3c5256e..c092ba1 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -103,7 +103,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl-iter.h"
 #include "print-rtl.h"
 #include "selftest.h"
-#include "read-rtl-function.h"
 #include "context.h" // for g
 #include "pass_manager.h"
 
@@ -14440,24 +14439,14 @@ make_pass_combine (gcc::context *ctxt)
 
 namespace selftest {
 
-/* FIXME: does this exist already?  */
-static rtx_insn *
-get_insn_by_uid (int uid)
-{
-  for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    if (INSN_UID (insn) == uid)
-      return insn;
-
-  /* Not found.  */
-  return NULL;
-}
-
 /* Verify that try_combine works.  */
+
 static void
 test_try_combine ()
 {
   // TODO: parse the input
-  /* Taken from gcc/testsuite/gcc.dg/asr_div1.c -O2 -fdump-rtl-all -mtune=cortex-a53
+  /* Taken from
+       gcc/testsuite/gcc.dg/asr_div1.c -O2 -fdump-rtl-all -mtune=cortex-a53
      for aarch64, hand editing the prev/next insns to 0 as needed.  */
   // TODO: filter on target?
   const char *input_dump = (
@@ -14471,21 +14460,7 @@ test_try_combine ()
     "            (const_int 3 [0x3]))) ../../src/gcc/testsuite/gcc.dg/asr_div1.c:14 642 {*aarch64_ashr_sisd_or_int_si3}\n"
     "     (expr_list:REG_DEAD (reg:DI 78)\n"
     "        (nil)))\n");
-  temp_source_file tmp (SELFTEST_LOCATION, ".rtl", input_dump);
-
-  /* Remap registers >= 76 to be target-appropriate pseudos, for the target's
-     current value of LAST_VIRTUAL_REGISTER.  */
-  regno_remapper r (76);
-
-  g_regno_remapper = &r;
-
-  /* Parse it.  */
-  auto_vec<const char *> argv (2);
-  argv.safe_push ("foo"); // progname
-  argv.safe_push (tmp.get_filename ());
-  bool read_ok
-    = read_rtl_function_body (argv.length (), argv.address (), NULL);
-  ASSERT_TRUE (read_ok);
+  rtl_dump_test t (input_dump, 76);
 
   rtx_insn *insn_8 = get_insn_by_uid (8);
   ASSERT_TRUE (insn_8);
@@ -14549,15 +14524,8 @@ test_try_combine ()
   rtx amt = XEXP (src_of_9, 1);
   ASSERT_TRUE (CONST_INT_P (amt));
   ASSERT_EQ (35, INTVAL (amt));
-
-  /* Cleanups.  */
-  current_function_decl = NULL;
-  free_after_compilation (cfun);
-  set_cfun (NULL);
-  g_regno_remapper = NULL;
 }
 
-
 /* Run all of the selftests within this file.  */
 
 void
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index cf66aa7..45231d0 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -6373,5 +6373,18 @@ rtl_data::init_stack_alignment ()
   preferred_stack_boundary = STACK_BOUNDARY;
 }
 
+/* FIXME: does this exist already?  */
+
+rtx_insn *
+get_insn_by_uid (int uid)
+{
+  for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    if (INSN_UID (insn) == uid)
+      return insn;
+
+  /* Not found.  */
+  return NULL;
+}
+
 
 #include "gt-emit-rtl.h"
diff --git a/gcc/function-tests.c b/gcc/function-tests.c
index edd355f..52c654e 100644
--- a/gcc/function-tests.c
+++ b/gcc/function-tests.c
@@ -419,7 +419,7 @@ verify_three_block_gimple_cfg (function *fun)
 
 /* As above, but additionally verify the RTL insns are sane.  */
 
-static void
+void
 verify_three_block_rtl_cfg (function *fun)
 {
   verify_three_block_cfg (fun);
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index c6b80bf..a2ff96a 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "varasm.h"
 #include "insn-addr.h"
 #include "read-rtl-function.h"
+#include "selftest.h"
 
 class function_reader;
 
@@ -648,6 +649,8 @@ function_reader::create_cfg_and_basic_blocks ()
 {
   /* Create bare-bones cfg.  This creates the entry and exit blocks.  */
   init_empty_tree_cfg_for_function (cfun);
+  ENTRY_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_RTL;
+  EXIT_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_RTL;
 
   /* Ensure that the vector of basic_block pointers is big enough.  */
   unsigned highest_bb_idx = bitmap_last_set_bit (&m_bb_indices);
@@ -885,3 +888,89 @@ read_rtl_function_body_from_file_range (location_t start_loc,
 
   return true;
 }
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that we can load RTL dumps.  */
+
+static void
+test_loading_dump_fragment ()
+{
+  /* Taken from
+       gcc/testsuite/gcc.dg/asr_div1.c -O2 -fdump-rtl-all -mtune=cortex-a53
+     for aarch64, hand editing the prev/next insns to 0 as needed.  */
+  // TODO: filter on target?
+  const char *input_dump = (
+    "(insn 8 0 9 2 (set (reg:DI 78)\n"
+    "        (lshiftrt:DI (reg:DI 76)\n"
+    "            (const_int 32 [0x20]))) ../../src/gcc/testsuite/gcc.dg/asr_div1.c:14 641 {*aarch64_lshr_sisd_or_int_di3}\n"
+    "     (expr_list:REG_DEAD (reg:DI 76)\n"
+    "        (nil)))\n"
+    "(insn 9 8 0 2 (set (reg:SI 79)\n"
+    "        (ashiftrt:SI (subreg:SI (reg:DI 78) 0)\n"
+    "            (const_int 3 [0x3]))) ../../src/gcc/testsuite/gcc.dg/asr_div1.c:14 642 {*aarch64_ashr_sisd_or_int_si3}\n"
+    "     (expr_list:REG_DEAD (reg:DI 78)\n"
+    "        (nil)))\n");
+  const int dumped_first_pseudo_regno = 76;
+  rtl_dump_test t (input_dump, dumped_first_pseudo_regno);
+
+  /* Verify that the insns were loaded correctly.  */
+  rtx_insn *insn_8 = get_insns ();
+  ASSERT_TRUE (insn_8);
+  ASSERT_EQ (8, INSN_UID (insn_8));
+  ASSERT_EQ (GET_CODE (insn_8), INSN);
+  ASSERT_EQ (GET_CODE (PATTERN (insn_8)), SET);
+  ASSERT_EQ (NULL, PREV_INSN (insn_8));
+
+  rtx_insn *insn_9 = NEXT_INSN (insn_8);
+  ASSERT_TRUE (insn_9);
+  ASSERT_EQ (9, INSN_UID (insn_9));
+  ASSERT_EQ (GET_CODE (insn_9), INSN);
+  ASSERT_EQ (insn_8, PREV_INSN (insn_9));
+  ASSERT_EQ (NULL, NEXT_INSN (insn_9));
+
+  /* Verify that registers were remapped.  */
+  const int pseudo_reg_offset = (LAST_VIRTUAL_REGISTER + 1);
+  rtx insn_8_dest = SET_DEST (PATTERN (insn_8));
+  ASSERT_EQ (REG, GET_CODE (insn_8_dest));
+  /* Should have remapped reg "78" to offset + 2.  */
+  ASSERT_EQ (pseudo_reg_offset + 2, REGNO (insn_8_dest));
+  rtx insn_8_src = SET_SRC (PATTERN (insn_8));
+  ASSERT_EQ (LSHIFTRT, GET_CODE (insn_8_src));
+  rtx reg = XEXP (insn_8_src, 0);
+  ASSERT_EQ (REG, GET_CODE (reg));
+  /* Should have remapped reg "76" to offset + 0.  */
+  ASSERT_EQ (pseudo_reg_offset + 0, REGNO (reg));
+
+  /* Verify that get_insn_by_uid works.  */
+  ASSERT_EQ (insn_8, get_insn_by_uid (8));
+  ASSERT_EQ (insn_9, get_insn_by_uid (9));
+
+  /* Verify that basic blocks were created.  */
+  ASSERT_EQ (2, BLOCK_FOR_INSN (insn_8)->index);
+  ASSERT_EQ (2, BLOCK_FOR_INSN (insn_9)->index);
+
+  /* Verify that a sane CFG was created.  */
+  ASSERT_TRUE (cfun);
+  verify_three_block_rtl_cfg (cfun);
+  basic_block bb2 = BASIC_BLOCK_FOR_FN (cfun, 2);
+  ASSERT_TRUE (bb2 != NULL);
+  ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
+  ASSERT_EQ (2, bb2->index);
+  ASSERT_EQ (insn_8, BB_HEAD (bb2));
+  ASSERT_EQ (insn_9, BB_END (bb2));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+read_rtl_function_c_tests ()
+{
+  test_loading_dump_fragment ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 33fc413..4e6cf76 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3772,4 +3772,6 @@ class regno_remapper
 
 extern regno_remapper *g_regno_remapper;
 
+extern rtx_insn *get_insn_by_uid (int uid);
+
 #endif /* ! GCC_RTL_H */
diff --git a/gcc/selftest-rtl.c b/gcc/selftest-rtl.c
new file mode 100644
index 0000000..6499f77
--- /dev/null
+++ b/gcc/selftest-rtl.c
@@ -0,0 +1,68 @@
+/* Selftest support for 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/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "selftest.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "read-rtl-function.h"
+#include "tree-core.h"
+
+#if CHECKING_P
+
+/* FIXME.  */
+
+selftest::rtl_dump_test::rtl_dump_test (const char *dump_content,
+					int dumped_first_pseudo_regno)
+{
+  /* Write out DUMP_CONTENT to a tempfile.  */
+  temp_source_file tmp (SELFTEST_LOCATION, ".rtl", dump_content);
+
+  // FIXME:
+  /* Remap registers >= 76 to be target-appropriate pseudos, for the target's
+     current value of LAST_VIRTUAL_REGISTER.  */
+  regno_remapper r (dumped_first_pseudo_regno);
+
+  g_regno_remapper = &r;
+
+  /* Parse the tempfile.  */
+  auto_vec<const char *> argv (2);
+  argv.safe_push ("foo"); // progname
+  argv.safe_push (tmp.get_filename ());
+  bool read_ok
+    = read_rtl_function_body (argv.length (), argv.address (), NULL);
+  ASSERT_TRUE (read_ok);
+
+  g_regno_remapper = NULL;
+}
+
+/* FIXME.  */
+
+selftest::rtl_dump_test::~rtl_dump_test ()
+{
+  /* Cleanups.  */
+  current_function_decl = NULL;
+  free_after_compilation (cfun);
+  set_cfun (NULL);
+}
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 3d43d31..8504935 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -55,6 +55,7 @@ selftest::run_tests ()
   tree_c_tests ();
   gimple_c_tests ();
   rtl_tests_c_tests ();
+  read_rtl_function_c_tests ();
 
   /* Higher-level tests, or for components that other selftests don't
      rely on.  */
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 0f2c60a..7bccff5 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -85,6 +85,18 @@ class temp_source_file
   char *m_filename;
 };
 
+
+/* FIXME.  */
+
+class rtl_dump_test
+{
+ public:
+   rtl_dump_test (const char *dump_content, int dumped_first_pseudo_regno);
+   ~rtl_dump_test ();
+};
+
+extern void verify_three_block_rtl_cfg (function *fun);
+
 /* Declarations for specific families of tests (by source file), in
    alphabetical order.  */
 extern void bitmap_c_tests ();
@@ -100,6 +112,7 @@ extern void hash_map_tests_c_tests ();
 extern void hash_set_tests_c_tests ();
 extern void input_c_tests ();
 extern void pretty_print_c_tests ();
+extern void read_rtl_function_c_tests ();
 extern void rtl_tests_c_tests ();
 extern void spellcheck_c_tests ();
 extern void spellcheck_tree_c_tests ();
-- 
1.8.5.3

