@@ -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 \
new file mode 100644
@@ -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 */
@@ -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. */
@@ -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);
@@ -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)
@@ -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 */