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] simplify-rtx.c: start adding selftests (v2)


On Sun, 2016-07-03 at 18:12 +0100, Richard Sandiford wrote:
> David Malcolm <dmalcolm@redhat.com> writes:
> > This patch starts adding selftests to simplify-rtx.c, to ensure
> > that
> > RTL expressions are simplified as we expect.
> >
> > It adds a new ASSERT_RTX_EQ macro that checks for pointer equality
> > of two rtx values.  If they're non-equal, it aborts, printing both
> > expressions.
>
> This might be a bit confusing when more tests are added, since
> pointer
> equality is only useful in certain specific cases (e.g. when you know
> you're dealing with CONST_INTs or pseudo registers).  How about
> making
> ASSERT_RTX_EQ check for rtx_equal_p equality and have something like
> ASSERT_RTX_PTR_EQ for cases where pointer equality really is needed?

> Also, how about using LAST_VIRTUAL_REGISTER + 1 as the base for
> register numbers?  DImode might not be valid for register 0 on
> all targets.

Thanks.  Here's an updated version which adds both ASSERT_RTX_EQ
and ASSERT_RTX_PTR_EQ.  The simplify-rtx.c tests can use the
stricter pointer equality test, so I updated them to use
ASSERT_RTX_PTR_EQ condition.

I added a selftest::make_test_reg to allocate pseudo regs, starting
at LAST_VIRTUAL_REGISTER + 1.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu

OK for trunk if it passes config-list.mk testing?

gcc/ChangeLog:
	* Makefile.in (OBJS): Add selftest-rtl.o.
	* selftest-rtl.c: New file.
	* selftest-run-tests.c (selftest::run_tests): Add call to
	simplify_rtx_c_tests.
	* selftest.c (selftest::begin_fail): New function.
	(selftest::fail): Reimplement in terms of begin_fail.
	(selftest::fail_formatted): Likewise.
	* selftest.h (selftest::begin_fail): New declaration.
	(selftest::assert_rtx_eq): New declaration.
	(selftest::assert_rtx_ptr_eq): New declaration.
	(selftest::simplify_rtx_c_tests): New declaration.
	(ASSERT_RTX_EQ): New macro.
	(ASSERT_RTX_PTR_EQ): New macro.
	* simplify-rtx.c: Include selftest.h.
	(selftest::make_test_reg): New function.
	(selftest::test_sign_bits): New function.
	(selftest::test_unary): New function.
	(selftest::test_binary): New function.
	(selftest::test_ternary): New function.
	(selftest::run_tests_for_mode): New function.
	(selftest::simplify_rtx_c_tests): New function.
---
 gcc/Makefile.in          |   1 +
 gcc/selftest-rtl.c       |  85 +++++++++++++++++++++++++++++
 gcc/selftest-run-tests.c |   1 +
 gcc/selftest.c           |  17 ++++--
 gcc/selftest.h           |  39 ++++++++++++++
 gcc/simplify-rtx.c       | 138 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 277 insertions(+), 4 deletions(-)
 create mode 100644 gcc/selftest-rtl.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ca7b1f6..de085b0 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1416,6 +1416,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/selftest-rtl.c b/gcc/selftest-rtl.c
new file mode 100644
index 0000000..20f4c21
--- /dev/null
+++ b/gcc/selftest-rtl.c
@@ -0,0 +1,85 @@
+/* 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"
+
+#if CHECKING_P
+
+/* Helper function for selftest::assert_rtx_eq and selftest::assert_rtx_ptr_eq.
+   Print VAL_EXPECTED and VAL_ACTUAL to stderr.  */
+
+static void
+print_non_equal_rtx (rtx val_expected, rtx val_actual)
+{
+  fprintf (stderr, "  expected=%p:\n    ", (void *)val_expected);
+  print_rtl (stderr, val_expected);
+  fprintf (stderr, "\n  actual=%p:\n    ", (void *)val_actual);
+  print_rtl (stderr, val_actual);
+  fprintf (stderr, "\n");
+}
+
+/* Implementation detail of ASSERT_RTX_EQ.  If val_expected and val_actual
+   fail rtx_equal_p, print the location, "FAIL: ", and print the
+   mismatching RTL expressions to stderr, then abort.  */
+
+void
+selftest::assert_rtx_eq (const location &loc,
+			 const char *desc_expected, const char *desc_actual,
+			 rtx val_expected, rtx val_actual)
+{
+  if (rtx_equal_p (val_expected, val_actual))
+    ::selftest::pass (loc, "ASSERT_RTL_EQ");
+  else
+    {
+      ::selftest::begin_fail (loc);
+      fprintf (stderr, "ASSERT_RTL_EQ (%s, %s)\n",
+	       desc_expected, desc_actual);
+      print_non_equal_rtx (val_expected, val_actual);
+      abort ();
+   }
+}
+
+/* Implementation detail of ASSERT_RTX_PTR_EQ.  If val_expected and val_actual
+   fail pointer-equality, print the location, "FAIL: ", and print the
+   mismatching RTL expressions to stderr, then abort.  */
+
+void
+selftest::assert_rtx_ptr_eq (const location &loc,
+			     const char *desc_expected, const char *desc_actual,
+			     rtx val_expected, rtx val_actual)
+{
+  if (val_expected == val_actual)
+    ::selftest::pass (loc, "ASSERT_RTL_PTR_EQ");
+  else
+    {
+      ::selftest::begin_fail (loc);
+      fprintf (stderr, "ASSERT_RTL_PTR_EQ (%s, %s)\n",
+	       desc_expected, desc_actual);
+      print_non_equal_rtx (val_expected, val_actual);
+      abort ();
+   }
+}
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index bddf0b2..cd2883d 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 ();
+  simplify_rtx_c_tests ();
 
   /* Higher-level tests, or for components that other selftests don't
      rely on.  */
diff --git a/gcc/selftest.c b/gcc/selftest.c
index ed6e517..af2b3f6 100644
--- a/gcc/selftest.c
+++ b/gcc/selftest.c
@@ -26,6 +26,16 @@ along with GCC; see the file COPYING3.  If not see
 
 int selftest::num_passes;
 
+/* Implementation detail of various failure handlers.  Print
+   the location, followed by "FAIL: ".  */
+
+void
+selftest::begin_fail (const location &loc)
+{
+  fprintf (stderr, "%s:%i: %s: FAIL: ", loc.m_file, loc.m_line,
+	   loc.m_function);
+}
+
 /* Record the successful outcome of some aspect of a test.  */
 
 void
@@ -39,8 +49,8 @@ selftest::pass (const location &/*loc*/, const char */*msg*/)
 void
 selftest::fail (const location &loc, const char *msg)
 {
-  fprintf (stderr,"%s:%i: %s: FAIL: %s\n", loc.m_file, loc.m_line,
-	   loc.m_function, msg);
+  begin_fail (loc);
+  fprintf (stderr, "%s\n", msg);
   abort ();
 }
 
@@ -51,8 +61,7 @@ selftest::fail_formatted (const location &loc, const char *fmt, ...)
 {
   va_list ap;
 
-  fprintf (stderr, "%s:%i: %s: FAIL: ", loc.m_file, loc.m_line,
-	   loc.m_function);
+  begin_fail (loc);
   va_start (ap, fmt);
   vfprintf (stderr, fmt, ap);
   va_end (ap);
diff --git a/gcc/selftest.h b/gcc/selftest.h
index c6becdd..e133989 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -63,12 +63,30 @@ extern void fail (const location &loc, const char *msg);
 extern void fail_formatted (const location &loc, const char *fmt, ...)
  ATTRIBUTE_PRINTF_2;
 
+/* Implementation detail of various failure handlers.  Print
+   the location, followed by "FAIL: ".  */
+
+extern void begin_fail (const location &loc);
+
 /* Implementation detail of ASSERT_STREQ.  */
 
 extern void assert_streq (const location &loc,
 			  const char *desc_expected, const char *desc_actual,
 			  const char *val_expected, const char *val_actual);
 
+/* Implementation detail of ASSERT_RTX_EQ.  */
+
+extern void assert_rtx_eq (const location &loc,
+			   const char *desc_expected, const char *desc_actual,
+			   rtx val_expected, rtx val_actual);
+
+/* Implementation detail of ASSERT_RTX_PTR_EQ.  */
+
+extern void assert_rtx_ptr_eq (const location &loc,
+			       const char *desc_expected,
+			       const char *desc_actual,
+			       rtx val_expected, rtx val_actual);
+
 /* Declarations for specific families of tests (by source file), in
    alphabetical order.  */
 extern void bitmap_c_tests ();
@@ -84,6 +102,7 @@ extern void hash_set_tests_c_tests ();
 extern void input_c_tests ();
 extern void pretty_print_c_tests ();
 extern void rtl_tests_c_tests ();
+extern void simplify_rtx_c_tests ();
 extern void spellcheck_c_tests ();
 extern void spellcheck_tree_c_tests ();
 extern void tree_c_tests ();
@@ -183,6 +202,26 @@ extern int num_passes;
     ::selftest::fail (SELFTEST_LOCATION, desc);			\
   SELFTEST_END_STMT
 
+/* Evaluate rtx EXPECTED and ACTUAL and compare them (using rtx_equal_p),
+   calling ::selftest::pass if they are equal, aborting if they are
+   non-equal.  */
+
+#define ASSERT_RTX_EQ(EXPECTED, ACTUAL) \
+  SELFTEST_BEGIN_STMT						    \
+  ::selftest::assert_rtx_eq (SELFTEST_LOCATION, #EXPECTED, #ACTUAL, \
+			     (EXPECTED), (ACTUAL));		    \
+  SELFTEST_END_STMT
+
+/* Evaluate rtx EXPECTED and ACTUAL and compare them (by pointer equality),
+   calling ::selftest::pass if they are equal, aborting if they are
+   non-equal.  */
+
+#define ASSERT_RTX_PTR_EQ(EXPECTED, ACTUAL) \
+  SELFTEST_BEGIN_STMT							\
+  ::selftest::assert_rtx_ptr_eq (SELFTEST_LOCATION, #EXPECTED, #ACTUAL, \
+				 (EXPECTED), (ACTUAL));			\
+  SELFTEST_END_STMT
+
 #define SELFTEST_BEGIN_STMT do {
 #define SELFTEST_END_STMT   } while (0)
 
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index a23a6f5..db3c4eb 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #include "varasm.h"
 #include "flags.h"
+#include "selftest.h"
 
 /* Simplification and canonicalization of RTL.  */
 
@@ -170,6 +171,29 @@ val_signbit_known_clear_p (machine_mode mode, unsigned HOST_WIDE_INT val)
   val &= (unsigned HOST_WIDE_INT) 1 << (width - 1);
   return val == 0;
 }
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that the various *_signbit_p functions work correctly.  */
+
+static void
+test_sign_bits ()
+{
+  ASSERT_FALSE (val_signbit_p (QImode, 0));
+  ASSERT_TRUE (val_signbit_p (QImode, 0x80));
+
+  ASSERT_FALSE (val_signbit_known_set_p (SImode, 0));
+  ASSERT_TRUE (val_signbit_known_clear_p (SImode, 0));
+  ASSERT_TRUE (val_signbit_known_set_p (SImode, 0xffffffff));
+  ASSERT_FALSE (val_signbit_known_clear_p (SImode, 0xffffffff));
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
 
 /* Make a binary operation by properly ordering the operands and
    seeing if the expression folds.  */
@@ -6296,3 +6320,117 @@ simplify_rtx (const_rtx x)
     }
   return NULL;
 }
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Make a pseudo REG for use by selftests.  */
+
+static rtx
+make_test_reg (machine_mode mode)
+{
+  static int test_reg_num = LAST_VIRTUAL_REGISTER + 1;
+
+  return gen_rtx_REG (mode, test_reg_num++);
+}
+
+/* Verify that simplify_rtx works correctly on various unary expressions.  */
+
+static void
+test_unary (machine_mode mode)
+{
+  /* (not (not reg)) -> reg.  */
+  rtx reg = make_test_reg (mode);
+  rtx expr = gen_rtx_NOT (mode, gen_rtx_NOT (mode, reg));
+  ASSERT_RTX_PTR_EQ (reg, simplify_rtx (expr));
+}
+
+/* Verify that simplify_rtx works correctly on various binary expressions.  */
+
+static void
+test_binary (machine_mode mode)
+{
+  rtx a = make_test_reg (mode);
+  rtx b = make_test_reg (mode);
+  /* (A & B) | A -> A.  */
+  ASSERT_RTX_PTR_EQ (a,
+		     simplify_rtx (gen_rtx_IOR (mode, gen_rtx_AND (mode, a, b),
+						a)));
+
+  /* A | (A & B) -> A.  */
+  ASSERT_RTX_PTR_EQ (a,
+		     simplify_rtx (gen_rtx_IOR (mode, a,
+						gen_rtx_AND (mode, a, b))));
+
+  if (!HONOR_SIGNED_ZEROS (mode) && CONST0_RTX(mode))
+    {
+      /* (A + 0) -> A.  */
+      ASSERT_RTX_PTR_EQ (a,
+			 simplify_rtx (gen_rtx_PLUS (mode, a,
+						     CONST0_RTX(mode))));
+
+      /* Currently this doesn't work for complex modes.  */
+      if (!COMPLEX_MODE_P (mode))
+	/* (0 + A) -> A.  */
+	ASSERT_RTX_PTR_EQ (a,
+			   simplify_rtx (gen_rtx_PLUS (mode, CONST0_RTX(mode),
+						       a)));
+    }
+
+}
+
+/* Verify that simplify_rtx works correctly on various ternary expressions.  */
+
+static void
+test_ternary (machine_mode mode)
+{
+  rtx a = make_test_reg (mode);
+  rtx b = make_test_reg (mode);
+  rtx c = make_test_reg (mode);
+
+  /* (1 ? a : b) -> a.  */
+  ASSERT_RTX_PTR_EQ (a,
+		 simplify_rtx (gen_rtx_IF_THEN_ELSE (mode,
+						     const1_rtx, a, b)));
+
+  /* (0 ? a : b) -> b.  */
+  ASSERT_RTX_PTR_EQ (b,
+		     simplify_rtx (gen_rtx_IF_THEN_ELSE (mode,
+							 const0_rtx, a, b)));
+
+  /* (c ? a : a) -> a.  */
+  ASSERT_RTX_PTR_EQ (a,
+		     simplify_rtx (gen_rtx_IF_THEN_ELSE (mode,
+							 c, a, a)));
+}
+
+/* Run all tests of simplify_rtx, using the given mode.  */
+
+static void
+run_tests_for_mode (machine_mode mode)
+{
+  test_unary (mode);
+  test_binary (mode);
+  test_ternary (mode);
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+simplify_rtx_c_tests ()
+{
+  test_sign_bits ();
+
+  /* Run run_tests_for_mode for every machine mode available on the
+     target.  */
+  for (int i = VOIDmode; i < NUM_MACHINE_MODES; i++)
+    {
+      machine_mode mode = (machine_mode)i;
+      run_tests_for_mode (mode);
+    }
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
-- 
1.8.5.3


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