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&regrtested 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&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

Reply via email to