md.texi (automata_option): Document collapse-ndfa.

* doc/md.texi (automata_option): Document collapse-ndfa.
	* genautomata.c (COLLAPSE_OPTION): New macro.
	(collapse_flag): New static variable.
	(struct description): New member normal_decls_num.
	(struct automaton): New members advance_ainsn and collapse_ainsn.
	(gen_automata_option): Check for COLLAPSE_OPTION.
	(collapse_ndfa_insn_decl): New static variable.
	(add_collapse_ndfa_insn_decl, special_decl_p): New functions.
	(find_arc): If insn is the collapse-ndfa insn, accept any arc we
	find.
	(transform_insn_regexps): Call add_collapse_ndfa_insn_decl if
	necessary.  Use normal_decls_num rather than decls_num, remove
	test for special decls.
	(create_alt_states, form_ainsn_with_same_reservs): Use
	special_decl_p.
	(make_automaton); Likewise.  Use the new advance_cycle_insn member
	of struct automaton.
	(create_composed_state): Disallow advance-cycle arcs if collapse_flag
	is set.
	(NDFA_to_DFA): Don't create composed states for the collapse-ndfa
	transition.  Create the necessary transitions for it.
	(create_ainsns): Return void.  Take an automaton_t argument, and
	update its ainsn_list, advance_ainsn and collapse_ainsn members.  All
	callers changed.
	(COLLAPSE_NDFA_VALUE_NAME): New macro.
	(output_tables): Output code to define it.
	(output_internal_insn_code_evaluation): Output code to accept
	const0_rtx as collapse-ndfa transition.
	(output_default_latencies, output_print_reservation_func,
	output_print_description): Reorganize loops to use normal_decls_num
	as loop bound; remove special case for advance_cycle_insn_decl.
	(initiate_automaton_gen): Handle COLLAPSE_OPTION.
	(check_automata_insn_issues): Check for collapse_ainsn.
	(expand_automate): Allocate sufficient space.  Initialize
	normal_decls_num.

From-SVN: r178059
This commit is contained in:
Bernd Schmidt 2011-08-25 10:30:13 +00:00 committed by Bernd Schmidt
parent 07f1047289
commit 1e6a9047b3
3 changed files with 174 additions and 46 deletions

View file

@ -1,5 +1,43 @@
2011-08-25 Bernd Schmidt <bernds@codesourcery.com>
* doc/md.texi (automata_option): Document collapse-ndfa.
* genautomata.c (COLLAPSE_OPTION): New macro.
(collapse_flag): New static variable.
(struct description): New member normal_decls_num.
(struct automaton): New members advance_ainsn and collapse_ainsn.
(gen_automata_option): Check for COLLAPSE_OPTION.
(collapse_ndfa_insn_decl): New static variable.
(add_collapse_ndfa_insn_decl, special_decl_p): New functions.
(find_arc): If insn is the collapse-ndfa insn, accept any arc we
find.
(transform_insn_regexps): Call add_collapse_ndfa_insn_decl if
necessary. Use normal_decls_num rather than decls_num, remove
test for special decls.
(create_alt_states, form_ainsn_with_same_reservs): Use
special_decl_p.
(make_automaton); Likewise. Use the new advance_cycle_insn member
of struct automaton.
(create_composed_state): Disallow advance-cycle arcs if collapse_flag
is set.
(NDFA_to_DFA): Don't create composed states for the collapse-ndfa
transition. Create the necessary transitions for it.
(create_ainsns): Return void. Take an automaton_t argument, and
update its ainsn_list, advance_ainsn and collapse_ainsn members. All
callers changed.
(COLLAPSE_NDFA_VALUE_NAME): New macro.
(output_tables): Output code to define it.
(output_internal_insn_code_evaluation): Output code to accept
const0_rtx as collapse-ndfa transition.
(output_default_latencies, output_print_reservation_func,
output_print_description): Reorganize loops to use normal_decls_num
as loop bound; remove special case for advance_cycle_insn_decl.
(initiate_automaton_gen): Handle COLLAPSE_OPTION.
(check_automata_insn_issues): Check for collapse_ainsn.
(expand_automate): Allocate sufficient space. Initialize
normal_decls_num.
2011-08-25 Georg-Johann Lay <avr@gjlay.de>
* config/avr/avr.md: Fix indentation from r177991.
2011-08-25 Bernd Schmidt <bernds@codesourcery.com>

View file

@ -7961,6 +7961,16 @@ if the reservation is not possible, the second alternative. The
nondeterministic treatment means trying all alternatives, some of them
may be rejected by reservations in the subsequent insns.
@item
@dfn{collapse-ndfa} modifies the behaviour of the generator when
producing an automaton. An additional state transition to collapse a
nondeterministic @acronym{NDFA} state to a deterministic @acronym{DFA}
state is generated. It can be triggered by passing @code{const0_rtx} to
state_transition. In such an automaton, cycle advance transitions are
available only for these collapsed states. This option is useful for
ports that want to use the @code{ndfa} option, but also want to use
@code{define_query_cpu_unit} to assign units to insns issued in a cycle.
@item
@dfn{progress} means output of a progress bar showing how many states
were generated so far for automaton being processed. This is useful

View file

@ -252,6 +252,7 @@ static arc_t next_out_arc (arc_t);
#define V_OPTION "-v"
#define W_OPTION "-w"
#define NDFA_OPTION "-ndfa"
#define COLLAPSE_OPTION "-collapse-ndfa"
#define PROGRESS_OPTION "-progress"
/* The following flags are set up by function `initiate_automaton_gen'. */
@ -259,6 +260,11 @@ static arc_t next_out_arc (arc_t);
/* Make automata with nondeterministic reservation by insns (`-ndfa'). */
static int ndfa_flag;
/* When making an NDFA, produce additional transitions that collapse
NDFA state into a deterministic one suitable for querying CPU units.
Provide avance-state transitions only for deterministic states. */
static int collapse_flag;
/* Do not make minimization of DFA (`-no-minimization'). */
static int no_minimization_flag;
@ -604,7 +610,7 @@ struct regexp
NDFA. */
struct description
{
int decls_num;
int decls_num, normal_decls_num;
/* The following fields are defined by checker. */
@ -624,9 +630,8 @@ struct description
automaton_t first_automaton;
/* The following field is created by pipeline hazard parser and
contains all declarations. We allocate additional entry for
special insn "cycle advancing" which is added by the automaton
generator. */
contains all declarations. We allocate additional entries for
two special insns which are added by the automaton generator. */
decl_t decls [1];
};
@ -811,6 +816,9 @@ struct automaton
/* The following field value is the list of insn declarations for
given automaton. */
ainsn_t ainsn_list;
/* Pointers to the ainsns corresponding to the special reservations. */
ainsn_t advance_ainsn, collapse_ainsn;
/* The following field value is the corresponding automaton
declaration. This field is not NULL only if the automatic
partition on automata is not used. */
@ -1529,6 +1537,8 @@ gen_automata_option (rtx def)
w_flag = 1;
else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
ndfa_flag = 1;
else if (strcmp (XSTR (def, 0), COLLAPSE_OPTION + 1) == 0)
collapse_flag = 1;
else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
progress_flag = 1;
else
@ -3202,6 +3212,10 @@ static ticker_t all_time;
/* Pseudo insn decl which denotes advancing cycle. */
static decl_t advance_cycle_insn_decl;
/* Pseudo insn decl which denotes collapsing the NDFA state. */
static decl_t collapse_ndfa_insn_decl;
/* Create and record a decl for the special advance-cycle transition. */
static void
add_advance_cycle_insn_decl (void)
{
@ -3217,6 +3231,31 @@ add_advance_cycle_insn_decl (void)
description->insns_num++;
}
/* Create and record a decl for the special collapse-NDFA transition. */
static void
add_collapse_ndfa_insn_decl (void)
{
collapse_ndfa_insn_decl = XCREATENODE (struct decl);
collapse_ndfa_insn_decl->mode = dm_insn_reserv;
collapse_ndfa_insn_decl->pos = no_pos;
DECL_INSN_RESERV (collapse_ndfa_insn_decl)->regexp = NULL;
DECL_INSN_RESERV (collapse_ndfa_insn_decl)->name = "$collapse_ndfa";
DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num
= description->insns_num;
description->decls [description->decls_num] = collapse_ndfa_insn_decl;
description->decls_num++;
description->insns_num++;
}
/* True if DECL is either of the two special decls we created. */
static bool
special_decl_p (struct insn_reserv_decl *decl)
{
return (decl == DECL_INSN_RESERV (advance_cycle_insn_decl)
|| (collapse_flag
&& decl == DECL_INSN_RESERV (collapse_ndfa_insn_decl)));
}
/* Abstract data `alternative states' which represents
nondeterministic nature of the description (see comments for
@ -3971,7 +4010,12 @@ find_arc (state_t from_state, state_t to_state, ainsn_t insn)
arc_t arc;
for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
if (arc->to_state == to_state && arc->insn == insn)
if (arc->insn == insn
&& (arc->to_state == to_state
|| (collapse_flag
/* Any arc is good enough for a collapse-ndfa transition. */
&& (insn->insn_reserv_decl
== DECL_INSN_RESERV (collapse_ndfa_insn_decl)))))
return arc;
return NULL;
}
@ -4956,12 +5000,14 @@ transform_insn_regexps (void)
transform_time = create_ticker ();
add_advance_cycle_insn_decl ();
if (collapse_flag)
add_collapse_ndfa_insn_decl ();
if (progress_flag)
fprintf (stderr, "Reservation transformation...");
for (i = 0; i < description->decls_num; i++)
for (i = 0; i < description->normal_decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
if (decl->mode == dm_insn_reserv)
DECL_INSN_RESERV (decl)->transformed_regexp
= transform_regexp (copy_insn_regexp
(DECL_INSN_RESERV (decl)->regexp));
@ -5432,7 +5478,7 @@ create_alt_states (automaton_t automaton)
curr_ainsn = curr_ainsn->next_ainsn)
{
reserv_decl = curr_ainsn->insn_reserv_decl;
if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
if (!special_decl_p (reserv_decl))
{
curr_ainsn->alt_states = NULL;
process_alts_for_forming_states (reserv_decl->transformed_regexp,
@ -5461,8 +5507,7 @@ form_ainsn_with_same_reservs (automaton_t automaton)
for (curr_ainsn = automaton->ainsn_list;
curr_ainsn != NULL;
curr_ainsn = curr_ainsn->next_ainsn)
if (curr_ainsn->insn_reserv_decl
== DECL_INSN_RESERV (advance_cycle_insn_decl))
if (special_decl_p (curr_ainsn->insn_reserv_decl))
{
curr_ainsn->next_same_reservs_insn = NULL;
curr_ainsn->first_insn_with_same_reservs = 1;
@ -5530,7 +5575,6 @@ make_automaton (automaton_t automaton)
state_t state;
state_t start_state;
state_t state2;
ainsn_t advance_cycle_ainsn;
VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
int states_n;
reserv_sets_t reservs_matter = form_reservs_matter (automaton);
@ -5544,14 +5588,13 @@ make_automaton (automaton_t automaton)
while (VEC_length (state_t, state_stack) != 0)
{
state = VEC_pop (state_t, state_stack);
advance_cycle_ainsn = NULL;
for (ainsn = automaton->ainsn_list;
ainsn != NULL;
ainsn = ainsn->next_ainsn)
if (ainsn->first_insn_with_same_reservs)
{
insn_reserv_decl = ainsn->insn_reserv_decl;
if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
if (!special_decl_p (insn_reserv_decl))
{
/* We process alt_states in the same order as they are
present in the description. */
@ -5578,8 +5621,6 @@ make_automaton (automaton_t automaton)
}
}
}
else
advance_cycle_ainsn = ainsn;
}
/* Add transition to advance cycle. */
state2 = state_shift (state, reservs_matter);
@ -5591,8 +5632,7 @@ make_automaton (automaton_t automaton)
if (progress_flag && states_n % 100 == 0)
fprintf (stderr, ".");
}
gcc_assert (advance_cycle_ainsn);
add_arc (state, state2, advance_cycle_ainsn);
add_arc (state, state2, automaton->advance_ainsn);
}
VEC_free (state_t, heap, state_stack);
}
@ -5700,7 +5740,13 @@ create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
for (curr_arc = first_out_arc (curr_alt_state->state);
curr_arc != NULL;
curr_arc = next_out_arc (curr_arc))
add_arc (state, curr_arc->to_state, curr_arc->insn);
if (!collapse_flag
/* When producing collapse-NDFA transitions, we
only add advance-cycle transitions to the
collapsed states. */
|| (curr_arc->insn->insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl)))
add_arc (state, curr_arc->to_state, curr_arc->insn);
}
arcs_marked_by_insn->to_state = state;
for (alts_number = 0,
@ -5750,6 +5796,7 @@ NDFA_to_DFA (automaton_t automaton)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv
&& decl != collapse_ndfa_insn_decl
&& create_composed_state
(state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
&state_stack))
@ -5759,6 +5806,22 @@ NDFA_to_DFA (automaton_t automaton)
fprintf (stderr, ".");
}
}
/* Add a transition to collapse the NDFA. */
if (collapse_flag)
{
if (state->component_states != NULL)
{
state_t state2 = state->component_states->state;
if (!state2->it_was_placed_in_stack_for_DFA_forming)
{
state2->it_was_placed_in_stack_for_DFA_forming = 1;
VEC_safe_push (state_t, heap, state_stack, state2);
}
add_arc (state, state2, automaton->collapse_ainsn);
}
else
add_arc (state, state, automaton->collapse_ainsn);
}
}
VEC_free (state_t, heap, state_stack);
}
@ -5814,8 +5877,7 @@ add_achieved_state (state_t state)
/* The function sets up equivalence numbers of insns which mark all
out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
nonzero value) or by equiv_class_num_2 of the destination state.
The function returns number of out arcs of STATE. */
nonzero value) or by equiv_class_num_2 of the destination state. */
static void
set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
{
@ -6583,8 +6645,8 @@ units_to_automata_heuristic_distr (void)
/* The functions creates automaton insns for each automata. Automaton
insn is simply insn for given automaton which makes reservation
only of units of the automaton. */
static ainsn_t
create_ainsns (void)
static void
create_ainsns (automaton_t automaton)
{
decl_t decl;
ainsn_t first_ainsn;
@ -6607,10 +6669,14 @@ create_ainsns (void)
first_ainsn = curr_ainsn;
else
prev_ainsn->next_ainsn = curr_ainsn;
if (decl == advance_cycle_insn_decl)
automaton->advance_ainsn = curr_ainsn;
else if (decl == collapse_ndfa_insn_decl)
automaton->collapse_ainsn = curr_ainsn;
prev_ainsn = curr_ainsn;
}
}
return first_ainsn;
automaton->ainsn_list = first_ainsn;
}
/* The function assigns automata to units according to constructions
@ -6658,7 +6724,7 @@ create_automata (void)
curr_automaton_num++, prev_automaton = curr_automaton)
{
curr_automaton = XCREATENODE (struct automaton);
curr_automaton->ainsn_list = create_ainsns ();
create_ainsns (curr_automaton);
curr_automaton->corresponding_automaton_decl = NULL;
curr_automaton->next_automaton = NULL;
curr_automaton->automaton_order_num = curr_automaton_num;
@ -6679,7 +6745,7 @@ create_automata (void)
&& DECL_AUTOMATON (decl)->automaton_is_used)
{
curr_automaton = XCREATENODE (struct automaton);
curr_automaton->ainsn_list = create_ainsns ();
create_ainsns (curr_automaton);
curr_automaton->corresponding_automaton_decl
= DECL_AUTOMATON (decl);
curr_automaton->next_automaton = NULL;
@ -6696,7 +6762,7 @@ create_automata (void)
if (curr_automaton_num == 0)
{
curr_automaton = XCREATENODE (struct automaton);
curr_automaton->ainsn_list = create_ainsns ();
create_ainsns (curr_automaton);
curr_automaton->corresponding_automaton_decl = NULL;
curr_automaton->next_automaton = NULL;
description->first_automaton = curr_automaton;
@ -6925,10 +6991,11 @@ output_temp_chip_member_name (FILE *f, automaton_t automaton)
output_chip_member_name (f, automaton);
}
/* This is name of macro value which is code of pseudo_insn
representing advancing cpu cycle. Its value is used as internal
code unknown insn. */
/* This is name of macro value which is code of pseudo_insns
representing advancing cpu cycle and collapsing the NDFA.
Its value is used as internal code unknown insn. */
#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
#define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
/* Output name of translate vector for given automaton. */
static void
@ -7803,6 +7870,9 @@ output_tables (void)
}
fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
if (collapse_flag)
fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
}
/* The function outputs definition and value of PHR interface variable
@ -8080,13 +8150,20 @@ output_internal_insn_code_evaluation (const char *insn_name,
const char *insn_code_name,
int code)
{
fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
fprintf (output_file, "\n if (%s == 0)\n", insn_name);
fprintf (output_file, " %s = %s;\n\n",
insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
if (collapse_flag)
{
fprintf (output_file, "\n else if (%s == const0_rtx)\n", insn_name);
fprintf (output_file, " %s = %s;\n\n",
insn_code_name, COLLAPSE_NDFA_VALUE_NAME);
}
fprintf (output_file, "\n else\n {\n");
fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
DFA_INSN_CODE_FUNC_NAME, insn_name);
fprintf (output_file, " if (%s > %s)\n return %d;\n",
fprintf (output_file, " if (%s > %s)\n return %d;\n }\n",
insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
fprintf (output_file, " }\n else\n %s = %s;\n\n",
insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
}
@ -8287,9 +8364,8 @@ output_default_latencies (void)
fprintf (output_file, " static const %s default_latencies[] =\n {",
tabletype);
for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
if (description->decls[i]->mode == dm_insn_reserv
&& description->decls[i] != advance_cycle_insn_decl)
for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
if (description->decls[i]->mode == dm_insn_reserv)
{
if ((col = (col+1) % 8) == 0)
fputs ("\n ", output_file);
@ -8298,7 +8374,7 @@ output_default_latencies (void)
fprintf (output_file, "% 4d,",
DECL_INSN_RESERV (decl)->default_latency);
}
gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
fputs ("\n };\n", output_file);
}
@ -8479,10 +8555,10 @@ output_print_reservation_func (void)
fputs (" static const char *const reservation_names[] =\n {",
output_file);
for (i = 0, j = 0; i < description->decls_num; i++)
for (i = 0, j = 0; i < description->normal_decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
if (decl->mode == dm_insn_reserv)
{
gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
j++;
@ -8492,7 +8568,7 @@ output_print_reservation_func (void)
finish_regexp_representation ();
}
}
gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
@ -8802,7 +8878,7 @@ output_description (void)
}
}
fprintf (output_description_file, "\n");
for (i = 0; i < description->decls_num; i++)
for (i = 0; i < description->normal_decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_reserv)
@ -8812,7 +8888,7 @@ output_description (void)
output_regexp (DECL_RESERV (decl)->regexp);
fprintf (output_description_file, "\n");
}
else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
else if (decl->mode == dm_insn_reserv)
{
fprintf (output_description_file, "insn reservation %s ",
DECL_INSN_RESERV (decl)->name);
@ -9218,6 +9294,8 @@ initiate_automaton_gen (int argc, char **argv)
w_flag = 1;
else if (strcmp (argv [i], NDFA_OPTION) == 0)
ndfa_flag = 1;
else if (strcmp (argv [i], COLLAPSE_OPTION) == 0)
collapse_flag = 1;
else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
progress_flag = 1;
else if (strcmp (argv [i], "-split") == 0)
@ -9260,7 +9338,8 @@ check_automata_insn_issues (void)
for (ainsn = automaton->ainsn_list;
ainsn != NULL;
ainsn = ainsn->next_ainsn)
if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
&& ainsn != automaton->collapse_ainsn)
{
for (reserv_ainsn = ainsn;
reserv_ainsn != NULL;
@ -9374,9 +9453,10 @@ expand_automata (void)
description = XCREATENODEVAR (struct description,
sizeof (struct description)
/* One entry for cycle advancing insn. */
+ sizeof (decl_t) * VEC_length (decl_t, decls));
/* Two entries for special insns. */
+ sizeof (decl_t) * (VEC_length (decl_t, decls) + 1));
description->decls_num = VEC_length (decl_t, decls);
description->normal_decls_num = description->decls_num;
description->query_units_num = 0;
for (i = 0; i < description->decls_num; i++)
{