This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add x86_64-specific selftests for RTL function reader (v2)


Note to i386 maintainters: this patch is part of the RTL frontend.
It adds selftests for verifying that the RTL dump reader works as
expected, with a mixture of real and hand-written "dumps" to
exercise various aspects of the loader.   Many RTL dumps contain
target-specific features (e.g. names of hard regs), and so these
selftests need to be target-specific, and hence this patch puts
them in i386.c.

Tested on i686-pc-linux-gnu and x86_64-pc-linux-gnu.

OK for trunk, assuming bootstrap&regrtest?
(this is dependent on patch 8a within the kit).

Changed in v2:
- fixed selftest failures on i686:
	* config/i386/i386.c
	(selftest::ix86_test_loading_dump_fragment_1): Fix handling of
	"frame" reg.
	(selftest::ix86_test_loading_call_insn): Require TARGET_SSE.
- updated to use "<3>" syntax for pseudos, rather than "$3"

Blurb from v1:
This patch adds more selftests for class function_reader, where
the dumps to be read contain x86_64-specific features.

In an earlier version of the patch kit, these were handled using
preprocessor conditionals.
This version instead runs them via a target hook for running
target-specific selftests, thus putting them within i386.c.

gcc/ChangeLog:
	* config/i386/i386.c
	(selftest::ix86_test_loading_dump_fragment_1): New function.
	(selftest::ix86_test_loading_call_insn): New function.
	(selftest::ix86_test_loading_full_dump): New function.
	(selftest::ix86_test_loading_unspec): New function.
	(selftest::ix86_run_selftests): Call the new functions.

gcc/testsuite/ChangeLog:
	* selftests/x86_64: New subdirectory.
	* selftests/x86_64/call-insn.rtl: New file.
	* selftests/x86_64/copy-hard-reg-into-frame.rtl: New file.
	* selftests/x86_64/times-two.rtl: New file.
	* selftests/x86_64/unspec.rtl: New file.

---
 gcc/config/i386/i386.c                             | 210 +++++++++++++++++++++
 gcc/testsuite/selftests/x86_64/call-insn.rtl       |  17 ++
 .../selftests/x86_64/copy-hard-reg-into-frame.rtl  |  15 ++
 gcc/testsuite/selftests/x86_64/times-two.rtl       |  51 +++++
 gcc/testsuite/selftests/x86_64/unspec.rtl          |  20 ++
 5 files changed, 313 insertions(+)
 create mode 100644 gcc/testsuite/selftests/x86_64/call-insn.rtl
 create mode 100644 gcc/testsuite/selftests/x86_64/copy-hard-reg-into-frame.rtl
 create mode 100644 gcc/testsuite/selftests/x86_64/times-two.rtl
 create mode 100644 gcc/testsuite/selftests/x86_64/unspec.rtl

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1cd1cd8..dc1a86f 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -51200,6 +51200,209 @@ ix86_test_dumping_memory_blockage ()
        "            ] UNSPEC_MEMORY_BLOCKAGE)))\n", pat, &r);
 }
 
+/* Verify loading an RTL dump; specifically a dump of copying
+   a param on x86_64 from a hard reg into the frame.
+   This test is target-specific since the dump contains target-specific
+   hard reg names.  */
+
+static void
+ix86_test_loading_dump_fragment_1 ()
+{
+  rtl_dump_test t (SELFTEST_LOCATION,
+		   locate_file ("x86_64/copy-hard-reg-into-frame.rtl"));
+
+  rtx_insn *insn = get_insn_by_uid (1);
+
+  /* The block structure and indentation here is purely for
+     readability; it mirrors the structure of the rtx.  */
+  tree mem_expr;
+  {
+    rtx pat = PATTERN (insn);
+    ASSERT_EQ (SET, GET_CODE (pat));
+    {
+      rtx dest = SET_DEST (pat);
+      ASSERT_EQ (MEM, GET_CODE (dest));
+      /* Verify the "/c" was parsed.  */
+      ASSERT_TRUE (RTX_FLAG (dest, call));
+      ASSERT_EQ (SImode, GET_MODE (dest));
+      {
+	rtx addr = XEXP (dest, 0);
+	ASSERT_EQ (PLUS, GET_CODE (addr));
+	ASSERT_EQ (DImode, GET_MODE (addr));
+	{
+	  rtx lhs = XEXP (addr, 0);
+	  /* Verify that the "frame" REG was consolidated.  */
+	  ASSERT_RTX_PTR_EQ (frame_pointer_rtx, lhs);
+	}
+	{
+	  rtx rhs = XEXP (addr, 1);
+	  ASSERT_EQ (CONST_INT, GET_CODE (rhs));
+	  ASSERT_EQ (-4, INTVAL (rhs));
+	}
+      }
+      /* Verify the "[1 i+0 S4 A32]" was parsed.  */
+      ASSERT_EQ (1, MEM_ALIAS_SET (dest));
+      /* "i" should have been handled by synthesizing a global int
+	 variable named "i".  */
+      mem_expr = MEM_EXPR (dest);
+      ASSERT_NE (mem_expr, NULL);
+      ASSERT_EQ (VAR_DECL, TREE_CODE (mem_expr));
+      ASSERT_EQ (integer_type_node, TREE_TYPE (mem_expr));
+      ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (DECL_NAME (mem_expr)));
+      ASSERT_STREQ ("i", IDENTIFIER_POINTER (DECL_NAME (mem_expr)));
+      /* "+0".  */
+      ASSERT_TRUE (MEM_OFFSET_KNOWN_P (dest));
+      ASSERT_EQ (0, MEM_OFFSET (dest));
+      /* "S4".  */
+      ASSERT_EQ (4, MEM_SIZE (dest));
+      /* "A32.  */
+      ASSERT_EQ (32, MEM_ALIGN (dest));
+    }
+    {
+      rtx src = SET_SRC (pat);
+      ASSERT_EQ (REG, GET_CODE (src));
+      ASSERT_EQ (SImode, GET_MODE (src));
+      ASSERT_EQ (5, REGNO (src));
+      tree reg_expr = REG_EXPR (src);
+      /* "i" here should point to the same var as for the MEM_EXPR.  */
+      ASSERT_EQ (reg_expr, mem_expr);
+    }
+  }
+}
+
+/* Verify that the RTL loader copes with a call_insn dump.
+   This test is target-specific since the dump contains a target-specific
+   hard reg name.  */
+
+static void
+ix86_test_loading_call_insn ()
+{
+  /* The test dump includes register "xmm0", where requires TARGET_SSE
+     to exist.  */
+  if (!TARGET_SSE)
+    return;
+
+  rtl_dump_test t (SELFTEST_LOCATION, locate_file ("x86_64/call-insn.rtl"));
+
+  rtx_insn *insn = get_insns ();
+  ASSERT_EQ (CALL_INSN, GET_CODE (insn));
+
+  /* "/j".  */
+  ASSERT_TRUE (RTX_FLAG (insn, jump));
+
+  rtx pat = PATTERN (insn);
+  ASSERT_EQ (CALL, GET_CODE (SET_SRC (pat)));
+
+  /* Verify REG_NOTES.  */
+  {
+    /* "(expr_list:REG_CALL_DECL".   */
+    ASSERT_EQ (EXPR_LIST, GET_CODE (REG_NOTES (insn)));
+    rtx_expr_list *note0 = as_a <rtx_expr_list *> (REG_NOTES (insn));
+    ASSERT_EQ (REG_CALL_DECL, REG_NOTE_KIND (note0));
+
+    /* "(expr_list:REG_EH_REGION (const_int 0 [0])".  */
+    rtx_expr_list *note1 = note0->next ();
+    ASSERT_EQ (REG_EH_REGION, REG_NOTE_KIND (note1));
+
+    ASSERT_EQ (NULL, note1->next ());
+  }
+
+  /* Verify CALL_INSN_FUNCTION_USAGE.  */
+  {
+    /* "(expr_list:DF (use (reg:DF 21 xmm0))".  */
+    rtx_expr_list *usage
+      = as_a <rtx_expr_list *> (CALL_INSN_FUNCTION_USAGE (insn));
+    ASSERT_EQ (EXPR_LIST, GET_CODE (usage));
+    ASSERT_EQ (DFmode, GET_MODE (usage));
+    ASSERT_EQ (USE, GET_CODE (usage->element ()));
+    ASSERT_EQ (NULL, usage->next ());
+  }
+}
+
+/* Verify that the RTL loader copes a dump from print_rtx_function.
+   This test is target-specific since the dump contains target-specific
+   hard reg names.  */
+
+static void
+ix86_test_loading_full_dump ()
+{
+  rtl_dump_test t (SELFTEST_LOCATION, locate_file ("x86_64/times-two.rtl"));
+
+  ASSERT_STREQ ("times_two", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
+
+  rtx_insn *insn_1 = get_insn_by_uid (1);
+  ASSERT_EQ (NOTE, GET_CODE (insn_1));
+
+  rtx_insn *insn_7 = get_insn_by_uid (7);
+  ASSERT_EQ (INSN, GET_CODE (insn_7));
+  ASSERT_EQ (PARALLEL, GET_CODE (PATTERN (insn_7)));
+
+  rtx_insn *insn_15 = get_insn_by_uid (15);
+  ASSERT_EQ (INSN, GET_CODE (insn_15));
+  ASSERT_EQ (USE, GET_CODE (PATTERN (insn_15)));
+
+  /* Verify crtl->return_rtx.  */
+  ASSERT_EQ (REG, GET_CODE (crtl->return_rtx));
+  ASSERT_EQ (0, REGNO (crtl->return_rtx));
+  ASSERT_EQ (SImode, GET_MODE (crtl->return_rtx));
+}
+
+/* Verify that the RTL loader copes with UNSPEC and UNSPEC_VOLATILE insns.
+   In particular, verify that it correctly loads the 2nd operand.
+   This test is target-specific since these are machine-specific
+   operands (and enums).  */
+
+static void
+ix86_test_loading_unspec ()
+{
+  rtl_dump_test t (SELFTEST_LOCATION, locate_file ("x86_64/unspec.rtl"));
+
+  ASSERT_STREQ ("test_unspec", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
+
+  ASSERT_TRUE (cfun);
+
+  /* Test of an UNSPEC.  */
+   rtx_insn *insn = get_insns ();
+  ASSERT_EQ (INSN, GET_CODE (insn));
+  rtx set = single_set (insn);
+  ASSERT_NE (NULL, set);
+  rtx dst = SET_DEST (set);
+  ASSERT_EQ (MEM, GET_CODE (dst));
+  rtx src = SET_SRC (set);
+  ASSERT_EQ (UNSPEC, GET_CODE (src));
+  ASSERT_EQ (BLKmode, GET_MODE (src));
+  ASSERT_EQ (UNSPEC_MEMORY_BLOCKAGE, XINT (src, 1));
+
+  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));
+
+  /* Verify the the insn is recognized.  */
+  ASSERT_NE(-1, recog_memoized (insn));
+
+  /* Test of an UNSPEC_VOLATILE, which has its own enum values.  */
+  insn = NEXT_INSN (insn);
+  ASSERT_EQ (INSN, GET_CODE (insn));
+
+  set = single_set (insn);
+  ASSERT_NE (NULL, set);
+
+  src = SET_SRC (set);
+  ASSERT_EQ (UNSPEC_VOLATILE, GET_CODE (src));
+  ASSERT_EQ (UNSPECV_RDTSCP, XINT (src, 1));
+}
+
 /* Run all target-specific selftests.  */
 
 static void
@@ -51207,6 +51410,13 @@ ix86_run_selftests (void)
 {
   ix86_test_dumping_hard_regs ();
   ix86_test_dumping_memory_blockage ();
+
+  /* Various tests of loading RTL dumps, here because they contain
+     ix86-isms (e.g. names of hard regs).  */
+  ix86_test_loading_dump_fragment_1 ();
+  ix86_test_loading_call_insn ();
+  ix86_test_loading_full_dump ();
+  ix86_test_loading_unspec ();
 }
 
 } // namespace selftest
diff --git a/gcc/testsuite/selftests/x86_64/call-insn.rtl b/gcc/testsuite/selftests/x86_64/call-insn.rtl
new file mode 100644
index 0000000..8f3a781
--- /dev/null
+++ b/gcc/testsuite/selftests/x86_64/call-insn.rtl
@@ -0,0 +1,17 @@
+(function "test"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (ccall_insn/j 1
+        (set (reg:DF xmm0)
+             (call (mem:QI (symbol_ref:DI ("sqrt") [flags 0x41]  <function_decl 0x7f82b1429d00 sqrt>) [0 __builtin_sqrt S1 A8])
+                    (const_int 0))) "test.c":19
+        (expr_list:REG_CALL_DECL (symbol_ref:DI ("sqrt") [flags 0x41]  <function_decl 0x7f82b1429d00 sqrt>)
+           (expr_list:REG_EH_REGION (const_int 0)
+              (nil)))
+        (expr_list:DF (use (reg:DF xmm0))
+           (nil)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "test"
diff --git a/gcc/testsuite/selftests/x86_64/copy-hard-reg-into-frame.rtl b/gcc/testsuite/selftests/x86_64/copy-hard-reg-into-frame.rtl
new file mode 100644
index 0000000..4598a1c
--- /dev/null
+++ b/gcc/testsuite/selftests/x86_64/copy-hard-reg-into-frame.rtl
@@ -0,0 +1,15 @@
+(function "copy_hard_reg_into_frame"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cinsn 1 (set (mem/c:SI
+                      (plus:DI
+                        (reg/f:DI frame)
+                        (const_int -4))
+                      [1 i+0 S4 A32])
+               (reg:SI di [ i ])) "test.c":2
+               (nil))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function
diff --git a/gcc/testsuite/selftests/x86_64/times-two.rtl b/gcc/testsuite/selftests/x86_64/times-two.rtl
new file mode 100644
index 0000000..8cec47a
--- /dev/null
+++ b/gcc/testsuite/selftests/x86_64/times-two.rtl
@@ -0,0 +1,51 @@
+;; Dump of this C function:
+;;
+;; int times_two (int i)
+;; {
+;;   return i * 2;
+;; }
+;;
+;; after expand for target==x86_64
+
+(function "times_two"
+  (insn-chain
+    (cnote 1 NOTE_INSN_DELETED)
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
+                            (const_int -4)) [1 i+0 S4 A32])
+                    (reg:SI di [ i ])) "../../src/times-two.c":2
+                 (nil))
+      (cnote 3 NOTE_INSN_FUNCTION_BEG)
+      (cinsn 6 (set (reg:SI <2>)
+                    (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
+                            (const_int -4)) [1 i+0 S4 A32])) "../../src/times-two.c":3
+                 (nil))
+      (cinsn 7 (parallel [
+                        (set (reg:SI <0> [ _2 ])
+                            (ashift:SI (reg:SI <2>)
+                                (const_int 1)))
+                        (clobber (reg:CC flags))
+                    ]) "../../src/times-two.c":3
+                 (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
+                                (const_int -4)) [1 i+0 S4 A32])
+                        (const_int 1))
+                    (nil)))
+      (cinsn 10 (set (reg:SI <1> [ <retval> ])
+                    (reg:SI <0> [ _2 ])) "../../src/times-two.c":3
+                 (nil))
+      (cinsn 14 (set (reg/i:SI ax)
+                    (reg:SI <1> [ <retval> ])) "../../src/times-two.c":4
+                 (nil))
+      (cinsn 15 (use (reg/i:SI ax)) "../../src/times-two.c":4
+                 (nil))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+  (crtl
+    (return_rtx 
+      (reg/i:SI ax)
+    ) ;; return_rtx
+  ) ;; crtl
+) ;; function "times_two"
diff --git a/gcc/testsuite/selftests/x86_64/unspec.rtl b/gcc/testsuite/selftests/x86_64/unspec.rtl
new file mode 100644
index 0000000..ac822ac
--- /dev/null
+++ b/gcc/testsuite/selftests/x86_64/unspec.rtl
@@ -0,0 +1,20 @@
+(function "test_unspec"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cinsn 1 (set (mem/v:BLK (0|scratch:DI) [0  A8])
+                    (unspec:BLK [
+                            (mem/v:BLK (reuse_rtx 0) [0  A8])
+                        ] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
+                 (nil))
+
+      (cinsn 2 (set (mem/v:BLK (1|scratch:DI) [0  A8])
+                    (unspec_volatile:BLK [
+                            (mem/v:BLK (reuse_rtx 1) [0  A8])
+                        ] UNSPECV_RDTSCP)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
+                 (nil))
+
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function
-- 
1.8.5.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]