This patch splits the auto-generated inline functions out of insn-modes.h and puts them in a new header file, insn-modes-inline.h. It also makes coretypes.h include these files directly, rather than indirectly via machmode.h. This in turn allows insn-modes-inline.h and machmode.h to come later in the include list, after wide-int.h. This is useful for later patches. insn-modes.h itself still needs to come first, since it provides configuration information like MAX_BITSIZE_MODE_ANY_INT, which is used to control the size of a wide_int. The patch also makes the generator files include machmode.h via coretypes.h. Previously they did it by more indirect means. Finally, the patch makes wide-int-print.h available via coretypes.h too. There didn't seem to be any reason to force only the print routines to be included directly, and it would be painful to extend that approach to the SVE patches. [Based on the code ARM contributed in branches/ARM/sve-branch@242100] 2017-07-02 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> contrib/header-tools/ * graph-header-logs (ignore): Update coretypes.h header list. gcc/ * Makefile.in (MACHMODE_H): Remove insn-modes.h (CORETYPES_H): New define. (MOSTLYCLEANFILES): Add insn-modes-inline.h. (insn-modes-inline.h, s-modes-inline-h): New rules. (generated_files): Add insn-modes-inline.h. (RTL_BASE_H, TREE_CORE_H): Use CORETYPES_H instead of coretypes.h. (build/gensupport.o, build/ggc-none.o, build/print-rtl.o): Likewise. (build/read-md.o, build/read-rtl.o, build/rtl.o): Likewise. (build/vec.o, build/hash-table.o, build/inchash.o): Likewise. (build/gencondmd.o, build/genattr.o, build/genattr-common.o): Likewise. (build/genattrtab.o, build/genautomata.o, build/gencheck.o): Likewise. (build/gencodes.o, build/genconditions.o): Likewise. (build/genconfig.o, build/genconstants.o, build/genemit.o): Likewise. (build/genenums.o, build/genextract.o, build/genflags.o): Likewise. (build/gentarget-def.o, build/genmddeps.o, build/genopinit.o) (build/genoutput.o, build/genpeep.o, build/genpreds.o): Likewise. (build/genrecog.o, build/genmddump.o, build/genmatch.o): Likewise. (build/gencfn-macros.o, build/gcov-iov.o): Likewise. * coretypes.h: Include everything up to real.h for generators. Include insn-modes.h first. Include wide-int-print.h after wide-int.h. Include insn-modes-inline.h and then machmode.h. * machmode.h: Don't include insn-modes.h here. * function-tests.c: Remove includes of signop.h, machmode.h, double-int.h and wide-int.h. * rtl.h: Likewise. * gcc-rich-location.c: Remove includes of machmode.h, double-int.h and wide-int.h. * optc-save-gen.awk: Likewise. * gencheck.c (BITS_PER_UNIT): Delete dummy definition. * godump.c: Remove include of wide-int-print.h. * pretty-print.h: Likewise. * wide-int-print.cc: Likewise. * wide-int.cc: Likewise. * hash-map-tests.c: Remove include of signop.h. * hash-set-tests.c: Likewise. * rtl-tests.c: Likewise. * mkconfig.sh: Remove include of machmode.h. * genmodes.c (emit_insn_modes_h): Split emission of inline functions into... (emit_insn_modes_inline_h): ...this new function. Emit the code into an insn-modes-inline.h header file, adding appropriate include guards and end comments. (emit_insn_modes_c_header): Remove include of machmode.h. (emit_min_insn_modes_c_header): Include coretypes.h rather than machmode.h. (main): Handle -i flag and call emit_insn_modes_inline_h when it is passed. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r249881
249 lines
6.9 KiB
C
249 lines
6.9 KiB
C
/* Unit tests for RTL-handling.
|
|
Copyright (C) 2015-2017 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 "tm.h"
|
|
#include "opts.h"
|
|
#include "hash-set.h"
|
|
#include "fixed-value.h"
|
|
#include "alias.h"
|
|
#include "flags.h"
|
|
#include "symtab.h"
|
|
#include "tree-core.h"
|
|
#include "stor-layout.h"
|
|
#include "tree.h"
|
|
#include "stringpool.h"
|
|
#include "stor-layout.h"
|
|
#include "rtl.h"
|
|
#include "pretty-print.h"
|
|
#include "cfgbuild.h"
|
|
#include "print-rtl.h"
|
|
#include "selftest.h"
|
|
#include "selftest-rtl.h"
|
|
#include "function.h"
|
|
#include "memmodel.h"
|
|
#include "emit-rtl.h"
|
|
|
|
#if CHECKING_P
|
|
|
|
namespace selftest {
|
|
|
|
/* Verify that PAT is printed as EXPECTED. Helper function for
|
|
selftests. */
|
|
|
|
static void
|
|
verify_print_pattern (const char *expected, rtx pat)
|
|
{
|
|
pretty_printer pp;
|
|
print_pattern (&pp, pat, 1);
|
|
ASSERT_STREQ (expected, pp_formatted_text (&pp));
|
|
}
|
|
|
|
/* Verify that X is dumped as EXPECTED_DUMP, using compact mode.
|
|
Use LOC as the effective location when reporting errors. */
|
|
|
|
void
|
|
assert_rtl_dump_eq (const location &loc, const char *expected_dump, rtx x,
|
|
rtx_reuse_manager *reuse_manager)
|
|
{
|
|
named_temp_file tmp_out (".rtl");
|
|
FILE *outfile = fopen (tmp_out.get_filename (), "w");
|
|
rtx_writer w (outfile, 0, false, true, reuse_manager);
|
|
w.print_rtl (x);
|
|
fclose (outfile);
|
|
|
|
char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ());
|
|
ASSERT_STREQ_AT (loc, expected_dump, dump);
|
|
free (dump);
|
|
}
|
|
|
|
/* Verify that regs are dumped as expected (in compact mode). */
|
|
|
|
static void
|
|
test_dumping_regs ()
|
|
{
|
|
/* Dumps of hard regs contain a target-specific name, so we don't test
|
|
it here; this can be tested in target-specific selftests. */
|
|
|
|
/* Test dumping of virtual regs. The various virtual regs are inited as
|
|
Pmode, so this is target-specific. The tests below assume DImode, so
|
|
only run the tests for targets where Pmode is DImode. */
|
|
if (Pmode == DImode)
|
|
{
|
|
ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-incoming-args)",
|
|
virtual_incoming_args_rtx);
|
|
ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-stack-vars)",
|
|
virtual_stack_vars_rtx);
|
|
ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-stack-dynamic)",
|
|
virtual_stack_dynamic_rtx);
|
|
ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-outgoing-args)",
|
|
virtual_outgoing_args_rtx);
|
|
ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-cfa)",
|
|
virtual_cfa_rtx);
|
|
ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-preferred-stack-boundary)",
|
|
virtual_preferred_stack_boundary_rtx);
|
|
}
|
|
|
|
/* Test dumping of non-virtual pseudos. */
|
|
ASSERT_RTL_DUMP_EQ ("(reg:SI <0>)",
|
|
gen_raw_REG (SImode, LAST_VIRTUAL_REGISTER + 1));
|
|
ASSERT_RTL_DUMP_EQ ("(reg:SI <1>)",
|
|
gen_raw_REG (SImode, LAST_VIRTUAL_REGISTER + 2));
|
|
}
|
|
|
|
/* Verify that insns are dumped as expected (in compact mode). */
|
|
|
|
static void
|
|
test_dumping_insns ()
|
|
{
|
|
/* Barriers. */
|
|
rtx_barrier *barrier = as_a <rtx_barrier *> (rtx_alloc (BARRIER));
|
|
SET_NEXT_INSN (barrier) = NULL;
|
|
ASSERT_RTL_DUMP_EQ ("(cbarrier 0)\n", barrier);
|
|
|
|
/* Labels. */
|
|
rtx_insn *label = gen_label_rtx ();
|
|
CODE_LABEL_NUMBER (label) = 42;
|
|
ASSERT_RTL_DUMP_EQ ("(clabel 0 42)\n", label);
|
|
|
|
LABEL_NAME (label)= "some_label";
|
|
ASSERT_RTL_DUMP_EQ ("(clabel 0 42 (\"some_label\"))\n", label);
|
|
}
|
|
|
|
/* Manually exercise the rtx_reuse_manager code. */
|
|
|
|
static void
|
|
test_dumping_rtx_reuse ()
|
|
{
|
|
rtx_reuse_manager r;
|
|
|
|
rtx x = rtx_alloc (SCRATCH);
|
|
rtx y = rtx_alloc (SCRATCH);
|
|
rtx z = rtx_alloc (SCRATCH);
|
|
|
|
/* x and y will be seen more than once. */
|
|
r.preprocess (x);
|
|
r.preprocess (x);
|
|
r.preprocess (y);
|
|
r.preprocess (y);
|
|
|
|
/* z will be only seen once. */
|
|
r.preprocess (z);
|
|
|
|
/* Verify that x and y have been assigned reuse IDs. */
|
|
int reuse_id_for_x;
|
|
ASSERT_TRUE (r.has_reuse_id (x, &reuse_id_for_x));
|
|
ASSERT_EQ (0, reuse_id_for_x);
|
|
|
|
int reuse_id_for_y;
|
|
ASSERT_TRUE (r.has_reuse_id (y, &reuse_id_for_y));
|
|
ASSERT_EQ (1, reuse_id_for_y);
|
|
|
|
/* z is only seen once and thus shouldn't get a reuse ID. */
|
|
ASSERT_FALSE (r.has_reuse_id (z, NULL));
|
|
|
|
/* The first dumps of x and y should be prefixed by reuse ID;
|
|
all subsequent dumps of them should show up as "reuse_rtx". */
|
|
ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(0|scratch)", x, &r);
|
|
ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 0)", x, &r);
|
|
ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 0)", x, &r);
|
|
|
|
ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(1|scratch)", y, &r);
|
|
ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 1)", y, &r);
|
|
ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 1)", y, &r);
|
|
|
|
/* z only appears once and thus shouldn't be prefixed with a
|
|
reuse ID. */
|
|
ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(scratch)", z, &r);
|
|
}
|
|
|
|
/* Unit testing of "single_set". */
|
|
|
|
static void
|
|
test_single_set ()
|
|
{
|
|
/* A label is not a SET. */
|
|
ASSERT_EQ (NULL_RTX, single_set (gen_label_rtx ()));
|
|
|
|
/* An unconditional jump insn is a single SET. */
|
|
rtx set_pc = gen_rtx_SET (pc_rtx,
|
|
gen_rtx_LABEL_REF (VOIDmode,
|
|
gen_label_rtx ()));
|
|
rtx_insn *jump_insn = emit_jump_insn (set_pc);
|
|
ASSERT_EQ (set_pc, single_set (jump_insn));
|
|
|
|
/* etc */
|
|
}
|
|
|
|
/* Construct an unconditional jump to a label, and verify that
|
|
various properties of it are sane. */
|
|
|
|
static void
|
|
test_uncond_jump ()
|
|
{
|
|
set_new_first_and_last_insn (NULL, NULL);
|
|
rtx_insn *label = gen_label_rtx ();
|
|
rtx jump_pat = gen_rtx_SET (pc_rtx,
|
|
gen_rtx_LABEL_REF (VOIDmode,
|
|
label));
|
|
ASSERT_EQ (SET, jump_pat->code);
|
|
ASSERT_EQ (LABEL_REF, SET_SRC (jump_pat)->code);
|
|
ASSERT_EQ (label, label_ref_label (SET_SRC (jump_pat)));
|
|
ASSERT_EQ (PC, SET_DEST (jump_pat)->code);
|
|
|
|
verify_print_pattern ("pc=L0", jump_pat);
|
|
|
|
ASSERT_RTL_DUMP_EQ ("(set (pc)\n"
|
|
" (label_ref 0))",
|
|
jump_pat);
|
|
|
|
rtx_insn *jump_insn = emit_jump_insn (jump_pat);
|
|
ASSERT_FALSE (any_condjump_p (jump_insn));
|
|
ASSERT_TRUE (any_uncondjump_p (jump_insn));
|
|
ASSERT_TRUE (pc_set (jump_insn));
|
|
ASSERT_TRUE (simplejump_p (jump_insn));
|
|
ASSERT_TRUE (onlyjump_p (jump_insn));
|
|
ASSERT_TRUE (control_flow_insn_p (jump_insn));
|
|
|
|
ASSERT_RTL_DUMP_EQ ("(cjump_insn 1 (set (pc)\n"
|
|
" (label_ref 0)))\n",
|
|
jump_insn);
|
|
}
|
|
|
|
/* Run all of the selftests within this file. */
|
|
|
|
void
|
|
rtl_tests_c_tests ()
|
|
{
|
|
test_dumping_regs ();
|
|
test_dumping_insns ();
|
|
test_dumping_rtx_reuse ();
|
|
test_single_set ();
|
|
test_uncond_jump ();
|
|
|
|
/* Purge state. */
|
|
set_first_insn (NULL);
|
|
set_last_insn (NULL);
|
|
}
|
|
|
|
} // namespace selftest
|
|
#endif /* #if CHECKING_P */
|