From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 102806 invoked by alias); 9 Sep 2016 00:01:28 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 102571 invoked by uid 89); 9 Sep 2016 00:01:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.2 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=rdx, Temporarily, tuning, sk:test.c. X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Sep 2016 00:01:20 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 42B2C61E46 for ; Fri, 9 Sep 2016 00:01:19 +0000 (UTC) Received: from c64.redhat.com (vpn-232-118.phx2.redhat.com [10.3.232.118]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u8901DiC023199; Thu, 8 Sep 2016 20:01:18 -0400 From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 8/9] final.c selftests Date: Fri, 09 Sep 2016 00:01:00 -0000 Message-Id: <1473381053-18817-9-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1473381053-18817-1-git-send-email-dmalcolm@redhat.com> References: <1473381053-18817-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes X-SW-Source: 2016-09/txt/msg00482.txt.bz2 gcc/ChangeLog: * final.c: Include selftest.h and selftest-rtl.h. (class selftest::temp_asm_out): New subclass of selftest::named_temp_file. (selftest::temp_asm_out::temp_asm_out): New ctor. (selftest::temp_asm_out::~temp_asm_out): New dtor. (class selftest::asm_out_test): New subclass of selftest::rtl_dump_test. (selftest::asm_out_test::asm_out_test): New ctor. (selftest::test_jump_insn): New function. (selftest::test_empty_function): New function. (selftest::test_asm_for_insn): New function. (TEST_ASM_FOR_INSN): New macro. (selftest::test_x86_64_leal): New function. (selftest::test_x86_64_negl): New function. (selftest::test_x86_64_cmpl): New function. (selftest::test_x86_64_cmovge): New function. (selftest::test_x86_64_ret): New function. (selftest::final_c_tests): New function. * selftest-run-tests.c (selftest::run_tests): Call selftest::final_c_tests. * selftest.h (selftest::final_c_tests): New decl. --- gcc/final.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++ gcc/selftest-run-tests.c | 1 + gcc/selftest.h | 1 + 3 files changed, 273 insertions(+) diff --git a/gcc/final.c b/gcc/final.c index eccc3d8..990f898 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -78,6 +78,8 @@ along with GCC; see the file COPYING3. If not see #include "asan.h" #include "rtl-iter.h" #include "print-rtl.h" +#include "selftest.h" +#include "selftest-rtl.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -4894,3 +4896,272 @@ get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set, COPY_HARD_REG_SET (*reg_set, default_set); return false; } + +#if CHECKING_P + +namespace selftest { + +/* Fixture for temporarily setting the global "asm_out_file" + to a named temporary file. */ + +class temp_asm_out : public named_temp_file +{ + public: + temp_asm_out (const location &loc); + ~temp_asm_out (); +}; + +/* Constructor. Open a tempfile for writing and set "asm_out_file" to it. */ + +temp_asm_out::temp_asm_out (const location &loc) +: named_temp_file (".s") +{ + gcc_assert (asm_out_file == NULL); + asm_out_file = fopen (get_filename (), "w"); + if (!asm_out_file) + ::selftest::fail_formatted (loc, "unable to open tempfile: %s", + get_filename ()); +} + +/* Destructor. Close the tempfile and unset "asm_out_file". + The tempfile is unlinked by the named_temp_file dtor. */ + +temp_asm_out::~temp_asm_out () +{ + fclose (asm_out_file); + asm_out_file = NULL; +} + +/* A subclass of rtl_dump_test for testing asm output. + Overrides asm_out_file to a tempfile, and temporarily + sets "reload_completed = 1;". */ + +class asm_out_test : public rtl_dump_test +{ + public: + asm_out_test (const location &loc, const char *dump_content); + + /* Get the asm output written so far. The caller should free + the returned ptr. */ + char * + get_output (const location &loc) const + { + fflush (asm_out_file); + return read_file (loc, m_asm_out.get_filename ()); + } + + private: + temp_asm_out m_asm_out; + temp_override m_override_reload_completed; + temp_override
m_override_in_section; +}; + +/* asm_out_test's constructor. Write DUMP_CONTENT to a tempfile, + overrides "asm_out_file" to a tempfile, and temporarily + sets "reload_completed = 1;". + Assume that no pseudo regs are present in DUMP_CONTENT (by + using the default arg to rtl_dump_test's ctor). */ + +asm_out_test::asm_out_test (const location &loc, const char *dump_content) +: rtl_dump_test (dump_content), + m_asm_out (loc), + /* Temporarily set reload_completed = true. + Needed e.g. by ix86_can_use_return_insn_p. */ + m_override_reload_completed (reload_completed, true), + /* Temporarily set "in_section = NULL;". */ + m_override_in_section (in_section, NULL) +{ +} + +/* Test writing asm for a jump_insn. */ + +static void +test_jump_insn () +{ + const char *input_dump + = ("(jump_insn 1 0 2 4 (set (pc)\n" + " (label_ref 3)) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1\n" + " (nil)\n" + " -> 3)\n" + "(barrier 2 1 3)\n" + "(code_label 3 2 0 5 2 (nil) [1 uses])\n"); + asm_out_test t (SELFTEST_LOCATION, input_dump); + + rtx_insn *jump_insn = get_insn_by_uid (1); + ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn)); + + rtx_insn *barrier = get_insn_by_uid (2); + ASSERT_EQ (BARRIER, GET_CODE (barrier)); + + rtx_insn *code_label = get_insn_by_uid (3); + ASSERT_EQ (CODE_LABEL, GET_CODE (code_label)); + + int seen; + final_scan_insn (jump_insn, stderr, 0, 0, &seen); + + char *c = t.get_output (SELFTEST_LOCATION); + ASSERT_STREQ ("\tjmp\t.L2\n", c); + free (c); +} + +/* Test writing asm for an empty function. */ + +static void +test_empty_function () +{ + /* Dump of the dump from cc1 in "test.c.289r.dwarf2" given this input: + void test_1 (void) {} + and compiling with -Os (for x86_64). */ + const char *dump + = (";; Function test_1 (test_1, funcdef_no=0, decl_uid=1758, cgraph_uid=0, symbol_order=0)\n" + "(note 1 0 3 (nil) NOTE_INSN_DELETED)\n" + "(note 3 1 8 2 [bb 2] NOTE_INSN_BASIC_BLOCK)\n" + "(note 8 3 2 2 NOTE_INSN_PROLOGUE_END)\n" + "(note 2 8 9 2 NOTE_INSN_FUNCTION_BEG)\n" + "(note 9 2 10 2 NOTE_INSN_EPILOGUE_BEG)\n" + "(jump_insn:TI 10 9 11 2 (simple_return) test.c:3 697 {simple_return_internal}\n" + " (nil)\n" + " -> simple_return)\n" + "(barrier 11 10 7)\n" + "(note 7 11 0 (nil) NOTE_INSN_DELETED)\n"); + + asm_out_test t (SELFTEST_LOCATION, dump); + + shorten_branches (get_insns ()); + rest_of_handle_final (); + + /* Verify that some asm was written out. */ + char *c = t.get_output (SELFTEST_LOCATION); + if (0) + fprintf (stdout, "%s", c); + ASSERT_STR_CONTAINS (c, "\t.text\n"); + ASSERT_STR_CONTAINS (c, "\n\t.type\ttest_1, @function\n"); + ASSERT_STR_CONTAINS (c, "\ntest_1:\n"); + ASSERT_STR_CONTAINS (c, "\n\t.cfi_startproc\n"); + ASSERT_STR_CONTAINS (c, "\n\tret\n"); + ASSERT_STR_CONTAINS (c, "\n\t.cfi_endproc\n"); + ASSERT_STR_CONTAINS (c, "\n\t.size\ttest_1, .-test_1\n"); + free (c); +} + +/* Parse DUMP via an asm_out_test and run final_scan_insn on the first + insn seen in the dump. Verify that the generated asm equals + EXPECTED_ASM. Use LOC as the effective location when reporting any + errors. */ + +static void +test_asm_for_insn (const location &loc, const char *dump, + const char *expected_asm) +{ + asm_out_test t (loc, dump); + + /* Locate the first insn in the dump. */ + rtx_insn *insn = get_insns (); + + /* Write out asm for the insn. */ + int seen; + final_scan_insn (insn, stderr, 0, 0, &seen); + + /* Verify that the expected asm was written out. */ + char *written_asm = t.get_output (loc); + ASSERT_STREQ_AT (loc, expected_asm, written_asm); + free (written_asm); +} + +/* Parse DUMP via an asm_out_test and run final_scan_insn on the first + insn seen in the dump. Verify that the generated asm equals + EXPECTED_ASM. */ + +#define TEST_ASM_FOR_INSN(DUMP, EXPECTED_ASM) \ + SELFTEST_BEGIN_STMT \ + test_asm_for_insn (SELFTEST_LOCATION, (DUMP), (EXPECTED_ASM)); \ + SELFTEST_END_STMT + +/* Various tests of how a particular instruction is recognized and + written out. These all assume x86_64 and perhaps make additional + tuning assumptions. */ + +static void +test_x86_64_leal () +{ + TEST_ASM_FOR_INSN ( + ("(insn:TI 31 0 0 2 (set (reg:SI 0 ax [93])\n" + " (plus:SI (reg/v:SI 1 dx [orig:90 k ] [90])\n" + " (const_int 4 [0x4]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1\n" + " (nil))\n"), + "\tleal\t4(%rdx), %eax\n"); +} + +static void +test_x86_64_negl () +{ + TEST_ASM_FOR_INSN ( + ("(insn 27 0 0 2 (parallel [\n" + " (set (reg:SI 1 dx [92])\n" + " (neg:SI (reg/v:SI 1 dx [orig:90 k ] [90])))\n" + " (clobber (reg:CC 17 flags))\n" + " ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1\n" + " (expr_list:REG_UNUSED (reg:CC 17 flags)\n" + " (nil)))\n"), + "\tnegl\t%edx\n"); +} + +static void +test_x86_64_cmpl () +{ + TEST_ASM_FOR_INSN ( + ("(insn 28 0 0 2 (set (reg:CCGC 17 flags)\n" + " (compare:CCGC (reg/v:SI 5 di [orig:88 i ] [88])\n" + " (reg/v:SI 4 si [orig:89 j ] [89]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1\n" + " (expr_list:REG_DEAD (reg/v:SI 5 di [orig:88 i ] [88])\n" + " (expr_list:REG_DEAD (reg/v:SI 4 si [orig:89 j ] [89])\n" + " (nil))))\n"), + "\tcmpl\t%esi, %edi\n"); +} + +static void +test_x86_64_cmovge () +{ + TEST_ASM_FOR_INSN ( + ("(insn:TI 29 0 0 2 (set (reg:SI 0 ax [orig:87 ] [87])\n" + " (if_then_else:SI (ge (reg:CCGC 17 flags)\n" + " (const_int 0 [0]))\n" + " (reg:SI 1 dx [92])\n" + " (reg:SI 0 ax [93]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1\n" + " (expr_list:REG_DEAD (reg:CCGC 17 flags)\n" + " (expr_list:REG_DEAD (reg:SI 1 dx [92])\n" + " (nil))))\n"), + "\tcmovge\t%edx, %eax\n"); +} + +static void +test_x86_64_ret () +{ + TEST_ASM_FOR_INSN ( + ("(jump_insn:TI 34 0 0 2 (simple_return) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1\n" + " (nil)\n" + " -> simple_return)\n"), + "\tret\n"); +} + +/* Run all of the selftests within this file. */ + +void +final_c_tests () +{ + /* Only run these tests for i386. */ +#ifndef I386_OPTS_H + return; +#endif + + test_jump_insn (); + test_empty_function (); + test_x86_64_leal (); + test_x86_64_negl (); + test_x86_64_cmpl (); + test_x86_64_cmovge (); + test_x86_64_ret (); +} + +} // namespace selftest +#endif /* CHECKING_P */ diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c index 296fe00..015572c 100644 --- a/gcc/selftest-run-tests.c +++ b/gcc/selftest-run-tests.c @@ -76,6 +76,7 @@ selftest::run_tests () spellcheck_c_tests (); spellcheck_tree_c_tests (); tree_cfg_c_tests (); + final_c_tests (); /* This one relies on most of the above. */ function_tests_c_tests (); diff --git a/gcc/selftest.h b/gcc/selftest.h index 8b94c3a..6ad6c88 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -198,6 +198,7 @@ extern void edit_context_c_tests (); extern void et_forest_c_tests (); extern void fold_const_c_tests (); extern void fibonacci_heap_c_tests (); +extern void final_c_tests (); extern void function_tests_c_tests (); extern void gimple_c_tests (); extern void ggc_tests_c_tests (); -- 1.8.5.3