On Tue, Jan 3, 2017 at 5:47 PM, David Malcolm <dmalc...@redhat.com> wrote: > Ping: > https://gcc.gnu.org/ml/gcc-patches/2016-12/msg01616.html > > (the patch has been successfully bootstrap®rtested on > x86_64-pc-linux-gnu, and also tested on i686-pc-linux-gnu).
I consider this part of testing ifrastructure, not part of target-dependent functionality, IOW, testing infrastructure just happens to live in i386.md. So, if there is nothing fundamentally x86 specific, I think that previous OKs were enough. Uros. > On Mon, 2016-12-19 at 12:12 -0500, David Malcolm wrote: >> 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®rtest? >> (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