/* Pipeline hazard description translator.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Vladimir Makarov <vmakarov@redhat.com>
struct state_ainsn_table;
/* The following typedefs are for brevity. */
+typedef struct unit_decl *unit_decl_t;
typedef struct decl *decl_t;
typedef struct regexp *regexp_t;
typedef struct unit_set_el *unit_set_el_t;
typedef struct arc *arc_t;
typedef struct ainsn *ainsn_t;
typedef struct automaton *automaton_t;
+typedef struct automata_list_el *automata_list_el_t;
typedef struct state_ainsn_table *state_ainsn_table_t;
static void initiate_arcs PARAMS ((void));
static void finish_arcs PARAMS ((void));
+static automata_list_el_t get_free_automata_list_el PARAMS ((void));
+static void free_automata_list_el PARAMS ((automata_list_el_t));
+static void free_automata_list PARAMS ((automata_list_el_t));
+static unsigned automata_list_hash PARAMS ((const void *));
+static int automata_list_eq_p PARAMS ((const void *, const void *));
+static void initiate_automata_lists PARAMS ((void));
+static void automata_list_start PARAMS ((void));
+static void automata_list_add PARAMS ((automaton_t));
+static automata_list_el_t automata_list_finish PARAMS ((void));
+static void finish_automata_lists PARAMS ((void));
+
static void initiate_excl_sets PARAMS ((void));
static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
static regexp_t transform_regexp PARAMS ((regexp_t));
static void transform_insn_regexps PARAMS ((void));
+static void process_unit_to_form_the_same_automaton_unit_lists
+ PARAMS ((regexp_t, regexp_t, int));
+static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
+static void form_the_same_automaton_unit_lists PARAMS ((void));
+static void check_unit_distributions_to_automata PARAMS ((void));
+
static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
int));
static void finish_forming_alt_state PARAMS ((alt_state_t,
static void add_states_vect_el PARAMS ((state_t));
static void output_trans_table PARAMS ((automaton_t));
static void output_state_alts_table PARAMS ((automaton_t));
-static void min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
+static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
static int min_issue_delay PARAMS ((state_t, ainsn_t));
static void initiate_min_issue_delay_pass_states PARAMS ((void));
static void output_min_issue_delay_table PARAMS ((automaton_t));
static void output_reserved_units_table PARAMS ((automaton_t));
static void output_tables PARAMS ((void));
static void output_max_insn_queue_index_def PARAMS ((void));
+static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
+static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
static void output_internal_min_issue_delay_func PARAMS ((void));
+static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
static void output_internal_trans_func PARAMS ((void));
static void output_internal_insn_code_evaluation PARAMS ((const char *,
const char *, int));
static void output_dfa_insn_code_func PARAMS ((void));
static void output_trans_func PARAMS ((void));
+static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
static void output_internal_state_alts_func PARAMS ((void));
static void output_state_alts_func PARAMS ((void));
static void output_min_issue_delay_func PARAMS ((void));
static void output_time_statistics PARAMS ((FILE *));
static void generate PARAMS ((void));
-static void make_insn_alts_attr PARAMS ((void));
-static void make_internal_dfa_insn_code_attr PARAMS ((void));
-static void make_default_insn_latency_attr PARAMS ((void));
-static void make_bypass_attr PARAMS ((void));
-static const char *file_name_suffix PARAMS ((const char *));
-static const char *base_file_name PARAMS ((const char *));
-static void check_automata PARAMS ((void));
+static void make_insn_alts_attr PARAMS ((void));
+static void make_internal_dfa_insn_code_attr PARAMS ((void));
+static void make_default_insn_latency_attr PARAMS ((void));
+static void make_bypass_attr PARAMS ((void));
+static const char *file_name_suffix PARAMS ((const char *));
+static const char *base_file_name PARAMS ((const char *));
+static void check_automata_insn_issues PARAMS ((void));
+static void add_automaton_state PARAMS ((state_t));
+static void form_important_insn_automata_lists PARAMS ((void));
/* Undefined position. */
static pos_t no_pos = 0;
/* The following field value is nonzero if the unit is used in an
regexp. */
char unit_is_used;
+
+ /* The following field value is used to form cyclic lists of units
+ which should be in the same automaton because the unit is
+ reserved not on all alternatives of a regexp on a cycle. */
+ unit_decl_t the_same_automaton_unit;
+ /* The following field is TRUE if we already reported that the unit
+ is not in the same automaton. */
+ int the_same_automaton_message_reported_p;
+
/* The following field value is order number (0, 1, ...) of given
unit. */
int unit_num;
during an automaton minimization) and marked by given insn
enters. */
int state_alts;
+ /* The following member value is the list to automata which can be
+ changed by the insn issue. */
+ automata_list_el_t important_automata_list;
+ /* The following member is used to process insn once for output. */
+ int processed_p;
};
/* This contains a declaration mentioned above. */
struct unit_regexp
{
char *name;
- struct unit_decl *unit_decl;
+ unit_decl_t unit_decl;
};
/* Define_reservation in a reservation. */
presence_list, absence_list. */
struct unit_set_el
{
- struct unit_decl *unit_decl;
+ unit_decl_t unit_decl;
unit_set_el_t next_unit_set_el;
};
};
/* The following macro is an initial value of member
- `longest_path_length' of a state. */
+ `longest_path_length' of a state. */
#define UNDEFINED_LONGEST_PATH_LENGTH -1
/* Automaton arc. */
/* The following member has nonzero value if there is arc from state of
the automaton marked by the ainsn. */
char arc_exists_p;
- /* Cyclic list of insns of a equivalence class is formed with the
+ /* Cyclic list of insns of an equivalence class is formed with the
aid of the following field. */
ainsn_t next_equiv_class_insn;
/* The following field value is nonzero if the insn declaration is
It is necessary because many insns may be equivalent with the
point of view of pipeline hazards. */
int insn_equiv_class_num;
+ /* The following member value is TRUE if there is an arc in the
+ automaton marked by the insn into another state. In other
+ words, the insn can change the state of the automaton. */
+ int important_p;
};
/* The folowing describes an automaton for PHR. */
int min_issue_delay_table_compression_factor;
};
+/* The following is the element of the list of automata. */
+struct automata_list_el
+{
+ /* The automaton itself. */
+ automaton_t automaton;
+ /* The next automata set element. */
+ automata_list_el_t next_automata_list_el;
+};
+
/* The following structure describes a table state X ainsn -> int(>= 0). */
struct state_ainsn_table
{
following. */
static vla_ptr_t decls;
-/* Given a pointer to a (char *) and a separator, return a alloc'ed
+/* Given a pointer to a (char *) and a separator, return an alloc'ed
string containing the next separated element, taking parentheses
into account if PAR_FLAG has nonzero value. Advance the pointer to
after the string scanned, or the end-of-string. Return NULL if at
}
}
-/* Process a EXCLUSION_SET.
+/* Process an EXCLUSION_SET.
This gives information about a cpu unit conflicts. We fill a
struct unit_rel_decl (excl) with information used later by
num_dfa_decls++;
}
-/* Process a ABSENCE_SET.
+/* Process an ABSENCE_SET.
This gives information about a cpu unit reservation requirements.
We fill a struct unit_rel_decl (absence) with information used
}
}
-/* Process a AUTOMATA_OPTION.
+/* Process an AUTOMATA_OPTION.
This gives information how to generate finite state automaton used
for recognizing pipeline hazards. */
Key of the table elements is name of given automaton. Rememeber
that automaton names have own space. */
-/* The function evaluates hash value of a automaton declaration. The
+/* The function evaluates hash value of an automaton declaration. The
function is used by abstract data `hashtab'. The function returns
hash value (0..UINT_MAX) of given automaton declaration. */
static unsigned
define_insn_reservation). Rememeber that insn names have own
space. */
-/* The function evaluates hash value of a insn declaration. The
+/* The function evaluates hash value of an insn declaration. The
function is used by abstract data `hashtab'. The function returns
hash value (0..UINT_MAX) of given insn declaration. */
static unsigned
error ("unit `%s' excludes itself", src->unit_decl->name);
continue;
}
+ if (dst->unit_decl->automaton_name != NULL
+ && src->unit_decl->automaton_name != NULL
+ && strcmp (dst->unit_decl->automaton_name,
+ src->unit_decl->automaton_name) != 0)
+ {
+ error ("units `%s' and `%s' in exclusion set belong to different automata",
+ src->unit_decl->name, dst->unit_decl->name);
+ continue;
+ }
for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
curr_el != NULL;
prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
: "unit `%s' requires own absence"), src->unit_decl->name);
continue;
}
+ if (dst->unit_decl->automaton_name != NULL
+ && src->unit_decl->automaton_name != NULL
+ && strcmp (dst->unit_decl->automaton_name,
+ src->unit_decl->automaton_name) != 0)
+ {
+ error ((presence_p
+ ? "units `%s' and `%s' in presence set belong to different automata"
+ : "units `%s' and `%s' in absence set belong to different automata"),
+ src->unit_decl->name, dst->unit_decl->name);
+ continue;
+ }
for (curr_el = (presence_p
? dst->unit_decl->presence_list
: dst->unit_decl->absence_list), prev_el = NULL;
description->max_insn_reserv_cycles = max_insn_cycles_num;
}
}
+ description->max_insn_reserv_cycles++;
}
/* The following function calls functions for checking all
/* This page contains abstract data `state'. */
-/* Maximal length of reservations in cycles (> 1). */
+/* Maximal length of reservations in cycles (>= 1). */
static int max_cycles_num;
/* Number of set elements (see type set_el_t) needed for
static vla_ptr_t units_container;
/* The start address of the array. */
-static struct unit_decl **units_array;
+static unit_decl_t *units_array;
/* Empty reservation of maximal length. */
static reserv_sets_t empty_reserv;
reserv_sets_hash_value (reservs)
reserv_sets_t reservs;
{
- unsigned int hash_value;
- int reservs_num;
+ set_el_t hash_value;
+ unsigned result;
+ int reservs_num, i;
set_el_t *reserv_ptr;
hash_value = 0;
reservs_num = els_in_reservs;
reserv_ptr = reservs;
+ i = 0;
while (reservs_num != 0)
{
reservs_num--;
- hash_value = ((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
- | (hash_value << CHAR_BIT)) + *reserv_ptr;
+ hash_value += ((*reserv_ptr >> i)
+ | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
+ i++;
+ if (i == sizeof (set_el_t) * CHAR_BIT)
+ i = 0;
reserv_ptr++;
}
- return hash_value;
+ if (sizeof (set_el_t) <= sizeof (unsigned))
+ return hash_value;
+ result = 0;
+ for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
+ {
+ result += (unsigned) hash_value;
+ hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
+ }
+ return result;
}
/* Comparison of given reservation sets. */
fprintf (f, NOTHING_NAME);
if (repetition_num <= 0)
abort ();
- if (reserved_units_num != 0 && repetition_num != 1)
- {
- if (reserved_units_num > 1)
- fprintf (f, ")");
- fprintf (f, "*%d", repetition_num);
- }
+ if (reserved_units_num > 1)
+ fprintf (f, ")");
+ if (repetition_num != 1)
+ fprintf (f, "*%d", repetition_num);
}
/* The function outputs string representation of units reservation in
int start_cycle = 0;
int cycle;
int repetition_num;
- int next_cycle_output_flag;
repetition_num = 0;
- next_cycle_output_flag = 0;
for (cycle = 0; cycle < max_cycles_num; cycle++)
if (repetition_num == 0)
{
repetition_num++;
else
{
- if (next_cycle_output_flag)
+ if (start_cycle != 0)
fprintf (f, ", ");
output_cycle_reservs (f, reservs, start_cycle, repetition_num);
- next_cycle_output_flag = 1;
repetition_num = 1;
start_cycle = cycle;
}
- if (!next_cycle_output_flag)
+ if (start_cycle < max_cycles_num)
{
- if (next_cycle_output_flag)
+ if (start_cycle != 0)
fprintf (f, ", ");
output_cycle_reservs (f, reservs, start_cycle, repetition_num);
}
VLA_PTR_CREATE (units_container, description->units_num, "units_container");
units_array
- = (description->decls_num ? VLA_PTR_BEGIN (units_container) : NULL);
+ = (description->decls_num && description->units_num
+ ? VLA_PTR_BEGIN (units_container) : NULL);
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
units_array [decl->decl.unit.unit_num] = &decl->decl.unit;
}
max_cycles_num = description->max_insn_reserv_cycles;
- if (max_cycles_num == 0)
- max_cycles_num++;
els_in_cycle_reserv
= ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
/ (sizeof (set_el_t) * CHAR_BIT));
\f
+/* Abstract data `automata lists'. */
+
+/* List of free states. */
+static automata_list_el_t first_free_automata_list_el;
+
+/* The list being formed. */
+static automata_list_el_t current_automata_list;
+
+/* Hash table of automata lists. */
+static htab_t automata_list_table;
+
+/* The following function returns free automata list el. It may be
+ new allocated node or node freed earlier. */
+static automata_list_el_t
+get_free_automata_list_el ()
+{
+ automata_list_el_t result;
+
+ if (first_free_automata_list_el != NULL)
+ {
+ result = first_free_automata_list_el;
+ first_free_automata_list_el
+ = first_free_automata_list_el->next_automata_list_el;
+ }
+ else
+ result = create_node (sizeof (struct automata_list_el));
+ result->automaton = NULL;
+ result->next_automata_list_el = NULL;
+ return result;
+}
+
+/* The function frees node AUTOMATA_LIST_EL. */
+static void
+free_automata_list_el (automata_list_el)
+ automata_list_el_t automata_list_el;
+{
+ if (automata_list_el == NULL)
+ return;
+ automata_list_el->next_automata_list_el = first_free_automata_list_el;
+ first_free_automata_list_el = automata_list_el;
+}
+
+/* The function frees list AUTOMATA_LIST. */
+static void
+free_automata_list (automata_list)
+ automata_list_el_t automata_list;
+{
+ automata_list_el_t curr_automata_list_el;
+ automata_list_el_t next_automata_list_el;
+
+ for (curr_automata_list_el = automata_list;
+ curr_automata_list_el != NULL;
+ curr_automata_list_el = next_automata_list_el)
+ {
+ next_automata_list_el = curr_automata_list_el->next_automata_list_el;
+ free_automata_list_el (curr_automata_list_el);
+ }
+}
+
+/* Hash value of AUTOMATA_LIST. */
+static unsigned
+automata_list_hash (automata_list)
+ const void *automata_list;
+{
+ unsigned int hash_value;
+ automata_list_el_t curr_automata_list_el;
+
+ hash_value = 0;
+ for (curr_automata_list_el = (automata_list_el_t) automata_list;
+ curr_automata_list_el != NULL;
+ curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
+ hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
+ | (hash_value << CHAR_BIT))
+ + curr_automata_list_el->automaton->automaton_order_num);
+ return hash_value;
+}
+
+/* Return nonzero value if the automata_lists are the same. */
+static int
+automata_list_eq_p (automata_list_1, automata_list_2)
+ const void *automata_list_1;
+ const void *automata_list_2;
+{
+ automata_list_el_t automata_list_el_1;
+ automata_list_el_t automata_list_el_2;
+
+ for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
+ automata_list_el_2 = (automata_list_el_t) automata_list_2;
+ automata_list_el_1 != NULL && automata_list_el_2 != NULL;
+ automata_list_el_1 = automata_list_el_1->next_automata_list_el,
+ automata_list_el_2 = automata_list_el_2->next_automata_list_el)
+ if (automata_list_el_1->automaton != automata_list_el_2->automaton)
+ return 0;
+ return automata_list_el_1 == automata_list_el_2;
+}
+
+/* Initialization of the abstract data. */
+static void
+initiate_automata_lists ()
+{
+ first_free_automata_list_el = NULL;
+ automata_list_table = htab_create (1500, automata_list_hash,
+ automata_list_eq_p, (htab_del) 0);
+}
+
+/* The following function starts new automata list and makes it the
+ current one. */
+static void
+automata_list_start ()
+{
+ current_automata_list = NULL;
+}
+
+/* The following function adds AUTOMATON to the current list. */
+static void
+automata_list_add (automaton)
+ automaton_t automaton;
+{
+ automata_list_el_t el;
+
+ el = get_free_automata_list_el ();
+ el->automaton = automaton;
+ el->next_automata_list_el = current_automata_list;
+ current_automata_list = el;
+}
+
+/* The following function finishes forming the current list, inserts
+ it into the table and returns it. */
+static automata_list_el_t
+automata_list_finish ()
+{
+ void **entry_ptr;
+
+ if (current_automata_list == NULL)
+ return NULL;
+ entry_ptr = htab_find_slot (automata_list_table,
+ (void *) current_automata_list, 1);
+ if (*entry_ptr == NULL)
+ *entry_ptr = (void *) current_automata_list;
+ else
+ free_automata_list (current_automata_list);
+ current_automata_list = NULL;
+ return (automata_list_el_t) *entry_ptr;
+}
+
+/* Finishing work with the abstract data. */
+static void
+finish_automata_lists ()
+{
+ htab_delete (automata_list_table);
+}
+
+\f
+
/* The page contains abstract data for work with exclusion sets (see
exclusion_set in file rtl.def). */
/* The function makes transformations
...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
- ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|... */
+ ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
+ ...+(A,B,...)+C+... -> (...+A+C+...),B,...
+ ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
static regexp_t
transform_3 (regexp)
regexp_t regexp;
}
else if (regexp->mode == rm_allof)
{
- regexp_t oneof;
- int oneof_index;
+ regexp_t oneof, seq;
+ int oneof_index, max_seq_length, allof_length;
regexp_t result;
- regexp_t allof;
+ regexp_t allof, allof_op;
int i, j;
for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
regexp_transformed_p = 1;
regexp = result;
}
+ max_seq_length = 0;
+ for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
+ if (regexp->regexp.allof.regexps [i]->mode == rm_sequence)
+ {
+ seq = regexp->regexp.allof.regexps [i];
+ if (max_seq_length < seq->regexp.sequence.regexps_num)
+ max_seq_length = seq->regexp.sequence.regexps_num;
+ }
+ else if (regexp->regexp.allof.regexps [i]->mode != rm_unit)
+ {
+ max_seq_length = 0;
+ break;
+ }
+ if (max_seq_length != 0)
+ {
+ if (max_seq_length == 1 || regexp->regexp.allof.regexps_num <= 1)
+ abort ();
+ result = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t) * (max_seq_length - 1));
+ result->mode = rm_sequence;
+ result->pos = regexp->pos;
+ result->regexp.sequence.regexps_num = max_seq_length;
+ for (i = 0; i < max_seq_length; i++)
+ {
+ allof_length = 0;
+ for (j = 0; j < regexp->regexp.allof.regexps_num; j++)
+ if (regexp->regexp.allof.regexps [j]->mode == rm_sequence
+ && (i < (regexp->regexp.allof.regexps [j]
+ ->regexp.sequence.regexps_num)))
+ {
+ allof_op = (regexp->regexp.allof.regexps [j]
+ ->regexp.sequence.regexps [i]);
+ allof_length++;
+ }
+ else if (i == 0
+ && regexp->regexp.allof.regexps [j]->mode == rm_unit)
+ {
+ allof_op = regexp->regexp.allof.regexps [j];
+ allof_length++;
+ }
+ if (allof_length == 1)
+ result->regexp.sequence.regexps [i] = allof_op;
+ else
+ {
+ allof = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (allof_length - 1));
+ allof->mode = rm_allof;
+ allof->pos = regexp->pos;
+ allof->regexp.allof.regexps_num = allof_length;
+ result->regexp.sequence.regexps [i] = allof;
+ allof_length = 0;
+ for (j = 0; j < regexp->regexp.allof.regexps_num; j++)
+ if (regexp->regexp.allof.regexps [j]->mode == rm_sequence
+ && (i < (regexp->regexp.allof.regexps [j]
+ ->regexp.sequence.regexps_num)))
+ {
+ allof_op = (regexp->regexp.allof.regexps [j]
+ ->regexp.sequence.regexps [i]);
+ allof->regexp.allof.regexps [allof_length] = allof_op;
+
+ allof_length++;
+ }
+ else if (i == 0
+ && (regexp->regexp.allof.regexps [j]->mode
+ == rm_unit))
+ {
+ allof_op = regexp->regexp.allof.regexps [j];
+ allof->regexp.allof.regexps [allof_length] = allof_op;
+ allof_length++;
+ }
+ }
+ }
+ regexp_transformed_p = 1;
+ regexp = result;
+ }
}
return regexp;
}
decl_t decl;
int i;
+ transform_time = create_ticker ();
+ add_advance_cycle_insn_decl ();
+ fprintf (stderr, "Reservation transformation...");
+ fflush (stderr);
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
= transform_regexp (copy_insn_regexp
(decl->decl.insn_reserv.regexp));
}
+ fprintf (stderr, "done\n");
+ ticker_off (&transform_time);
+ fflush (stderr);
+}
+
+\f
+
+/* The following variable is an array indexed by cycle. Each element
+ contains cyclic list of units which should be in the same cycle. */
+static unit_decl_t *the_same_automaton_lists;
+
+/* The function processes all alternative reservations on CYCLE in
+ given REGEXP to check the UNIT is not reserved on the all
+ alternatives. If it is true, the unit should be in the same
+ automaton with other analogous units reserved on CYCLE in given
+ REGEXP. */
+static void
+process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
+ regexp_t unit;
+ regexp_t regexp;
+ int cycle;
+{
+ int i, k;
+ regexp_t seq, allof;
+ unit_decl_t unit_decl, last;
+
+ if (regexp == NULL || regexp->mode != rm_oneof)
+ abort ();
+ unit_decl = unit->regexp.unit.unit_decl;
+ for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
+ {
+ seq = regexp->regexp.oneof.regexps [i];
+ if (seq->mode == rm_sequence)
+ {
+ if (cycle >= seq->regexp.sequence.regexps_num)
+ break;
+ allof = seq->regexp.sequence.regexps [cycle];
+ if (allof->mode == rm_allof)
+ {
+ for (k = 0; k < allof->regexp.allof.regexps_num; k++)
+ if (allof->regexp.allof.regexps [k]->mode == rm_unit
+ && (allof->regexp.allof.regexps [k]->regexp.unit.unit_decl
+ == unit_decl))
+ break;
+ if (k >= allof->regexp.allof.regexps_num)
+ break;
+ }
+ else if (allof->mode == rm_unit
+ && allof->regexp.unit.unit_decl != unit_decl)
+ break;
+ }
+ else if (cycle != 0)
+ break;
+ else if (seq->mode == rm_allof)
+ {
+ for (k = 0; k < seq->regexp.allof.regexps_num; k++)
+ if (seq->regexp.allof.regexps [k]->mode == rm_unit
+ && (seq->regexp.allof.regexps [k]->regexp.unit.unit_decl
+ == unit_decl))
+ break;
+ if (k >= seq->regexp.allof.regexps_num)
+ break;
+ }
+ else if (seq->mode == rm_unit && seq->regexp.unit.unit_decl != unit_decl)
+ break;
+ }
+ if (i >= 0)
+ {
+ if (the_same_automaton_lists [cycle] == NULL)
+ the_same_automaton_lists [cycle] = unit_decl;
+ else
+ {
+ for (last = the_same_automaton_lists [cycle];;)
+ {
+ if (last == unit_decl)
+ return;
+ if (last->the_same_automaton_unit
+ == the_same_automaton_lists [cycle])
+ break;
+ last = last->the_same_automaton_unit;
+ }
+ last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
+ unit_decl->the_same_automaton_unit
+ = the_same_automaton_lists [cycle];
+ }
+ }
+}
+
+/* The function processes given REGEXP to find units which should be
+ in the same automaton. */
+static void
+form_the_same_automaton_unit_lists_from_regexp (regexp)
+ regexp_t regexp;
+{
+ int i, j, k;
+ regexp_t seq, allof, unit;
+
+ if (regexp == NULL || regexp->mode != rm_oneof)
+ return;
+ for (i = 0; i < description->max_insn_reserv_cycles; i++)
+ the_same_automaton_lists [i] = NULL;
+ for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
+ {
+ seq = regexp->regexp.oneof.regexps [i];
+ if (seq->mode == rm_sequence)
+ for (j = 0; j < seq->regexp.sequence.regexps_num; j++)
+ {
+ allof = seq->regexp.sequence.regexps [j];
+ if (allof->mode == rm_allof)
+ for (k = 0; k < allof->regexp.allof.regexps_num; k++)
+ {
+ unit = allof->regexp.allof.regexps [k];
+ if (unit->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists
+ (unit, regexp, j);
+ else if (unit->mode != rm_nothing)
+ abort ();
+ }
+ else if (allof->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists
+ (allof, regexp, j);
+ else if (allof->mode != rm_nothing)
+ abort ();
+ }
+ else if (seq->mode == rm_allof)
+ for (k = 0; k < seq->regexp.allof.regexps_num; k++)
+ {
+ unit = seq->regexp.allof.regexps [k];
+ if (unit->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists
+ (unit, regexp, 0);
+ else if (unit->mode != rm_nothing)
+ abort ();
+ }
+ else if (seq->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
+ else if (seq->mode != rm_nothing)
+ abort ();
+ }
+}
+
+/* The function initializes data to search for units which should be
+ in the same automaton and call function
+ `form_the_same_automaton_unit_lists_from_regexp' for each insn
+ reservation regexp. */
+static void
+form_the_same_automaton_unit_lists ()
+{
+ decl_t decl;
+ int i;
+
+ the_same_automaton_lists
+ = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
+ * sizeof (unit_decl_t));
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ decl->decl.unit.the_same_automaton_message_reported_p = FALSE;
+ decl->decl.unit.the_same_automaton_unit = &decl->decl.unit;
+ }
+ }
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ form_the_same_automaton_unit_lists_from_regexp
+ (decl->decl.insn_reserv.transformed_regexp);
+ }
+ free (the_same_automaton_lists);
+}
+
+/* The function finds units which should be in the same automaton and,
+ if they are not, reports about it. */
+static void
+check_unit_distributions_to_automata ()
+{
+ decl_t decl;
+ unit_decl_t start_unit_decl, unit_decl;
+ int i;
+
+ form_the_same_automaton_unit_lists ();
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ start_unit_decl = &decl->decl.unit;
+ if (!start_unit_decl->the_same_automaton_message_reported_p)
+ for (unit_decl = start_unit_decl->the_same_automaton_unit;
+ unit_decl != start_unit_decl;
+ unit_decl = unit_decl->the_same_automaton_unit)
+ if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
+ {
+ error ("Units `%s' and `%s' should be in the same automaton",
+ start_unit_decl->name, unit_decl->name);
+ unit_decl->the_same_automaton_message_reported_p = TRUE;
+ }
+ }
+ }
}
\f
removing nonequivalent states and placing them in
*NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
assigns it to the state equivalence number. If the class has been
- partitioned, the function returns nonzero value. */
+ partitioned, the function returns nonzero value. */
static int
partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
next_iteration_classes, new_equiv_class_num_ptr)
{
curr_ainsn = create_node (sizeof (struct ainsn));
curr_ainsn->insn_reserv_decl = &decl->decl.insn_reserv;
+ curr_ainsn->important_p = FALSE;
curr_ainsn->next_ainsn = NULL;
if (prev_ainsn == NULL)
first_ainsn = curr_ainsn;
curr_automaton != NULL;
curr_automaton = curr_automaton->next_automaton)
{
+ if (curr_automaton->corresponding_automaton_decl == NULL)
+ fprintf (stderr, "Create anonymous automaton ...");
+ else
+ fprintf (stderr, "Create automaton `%s'...",
+ curr_automaton->corresponding_automaton_decl->name);
create_alt_states (curr_automaton);
form_ainsn_with_same_reservs (curr_automaton);
build_automaton (curr_automaton);
ticker_on (&equiv_time);
set_insn_equiv_classes (curr_automaton);
ticker_off (&equiv_time);
+ fprintf (stderr, "done\n");
}
}
result = 0;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
- /* Ignore cycles containing one state and `cycle advance' arcs. */
+ /* Ignore cycles containing one state and `cycle advance' arcs. */
if (arc->to_state != state
&& (arc->insn->insn_reserv_decl
!= &advance_cycle_insn_decl->decl.insn_reserv))
static int max_dfa_issue_rate;
/* The following function processes the longest path length staring
- from STATE to find MAX_DFA_ISSUE_RATE. */
+ from STATE to find MAX_DFA_ISSUE_RATE. */
static void
process_state_longest_path_length (state)
global variable and outputs its declaration. */
static void
-output_dfa_max_issue_rate (void)
+output_dfa_max_issue_rate ()
{
automaton_t automaton;
/* Name of cache of insn dfa codes. */
#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
+/* Name of length of cache of insn dfa codes. */
+#define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
+
/* Names of the PHR interface functions: */
#define SIZE_FUNC_NAME "state_size"
/* This recursive function passes states to find minimal issue delay
- value for AINSN. The state being visited is STATE. */
-static void
+ value for AINSN. The state being visited is STATE. The function
+ returns minimal issue delay value for AINSN in STATE or -1 if we
+ enter into a loop. */
+static int
min_issue_delay_pass_states (state, ainsn)
state_t state;
ainsn_t ainsn;
arc_t arc;
int min_insn_issue_delay, insn_issue_delay;
- if (state->state_pass_num == curr_state_pass_num)
- return;
+ if (state->state_pass_num == curr_state_pass_num
+ || state->min_insn_issue_delay != -1)
+ /* We've entered into a loop or already have the correct value for
+ given state and ainsn. */
+ return state->min_insn_issue_delay;
state->state_pass_num = curr_state_pass_num;
- min_insn_issue_delay = state->min_insn_issue_delay = -1;
+ min_insn_issue_delay = -1;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
if (arc->insn == ainsn)
{
}
else
{
- min_issue_delay_pass_states (arc->to_state, ainsn);
- if (arc->to_state->min_insn_issue_delay != -1)
+ insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
+ if (insn_issue_delay != -1)
{
- insn_issue_delay
- = (arc->to_state->min_insn_issue_delay
- + (arc->insn->insn_reserv_decl
- == &advance_cycle_insn_decl->decl.insn_reserv ? 1 : 0));
+ if (arc->insn->insn_reserv_decl
+ == &advance_cycle_insn_decl->decl.insn_reserv)
+ insn_issue_delay++;
if (min_insn_issue_delay == -1
|| min_insn_issue_delay > insn_issue_delay)
- min_insn_issue_delay = insn_issue_delay;
+ {
+ min_insn_issue_delay = insn_issue_delay;
+ if (insn_issue_delay == 0)
+ break;
+ }
}
}
- state->min_insn_issue_delay = min_insn_issue_delay;
+ return min_insn_issue_delay;
}
/* The function searches minimal issue delay value for AINSN in STATE.
- The function can return negative can not issue AINSN. We will
- report about it later. */
+ The function can return negative value if we can not issue AINSN. We
+ will report about it later. */
static int
min_issue_delay (state, ainsn)
state_t state;
ainsn_t ainsn;
{
curr_state_pass_num++;
- min_issue_delay_pass_states (state, ainsn);
+ state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
return state->min_insn_issue_delay;
}
i++)
VLA_HWINT (min_issue_delay_vect, i) = 0;
automaton->max_min_delay = 0;
- for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
- state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
- state_ptr++)
- {
- for (ainsn = automaton->ainsn_list;
- ainsn != NULL;
- ainsn = ainsn->next_ainsn)
- if (ainsn->first_ainsn_with_given_equialence_num)
- {
+ for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
+ if (ainsn->first_ainsn_with_given_equialence_num)
+ {
+ for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ state_ptr++)
+ (*state_ptr)->min_insn_issue_delay = -1;
+ for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ state_ptr++)
+ {
min_delay = min_issue_delay (*state_ptr, ainsn);
if (automaton->max_min_delay < min_delay)
automaton->max_min_delay = min_delay;
* automaton->insn_equiv_classes_num
+ ainsn->insn_equiv_class_num) = min_delay;
}
- }
+ }
fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
fprintf (output_file, "static const ");
output_range_type (output_file, 0, automaton->max_min_delay);
}
-/* Output function `internal_min_issue_delay'. */
+/* The function outputs switch cases for insn reseravtions using
+ function *output_automata_list_code. */
static void
-output_internal_min_issue_delay_func ()
+output_insn_code_cases (output_automata_list_code)
+ void (*output_automata_list_code) (automata_list_el_t);
{
+ decl_t decl, decl_2;
+ int i, j;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ decl->decl.insn_reserv.processed_p = FALSE;
+ }
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv && !decl->decl.insn_reserv.processed_p)
+ {
+ for (j = i; j < description->decls_num; j++)
+ {
+ decl_2 = description->decls [j];
+ if (decl_2->mode == dm_insn_reserv
+ && (decl_2->decl.insn_reserv.important_automata_list
+ == decl->decl.insn_reserv.important_automata_list))
+ {
+ decl_2->decl.insn_reserv.processed_p = TRUE;
+ fprintf (output_file, " case %d: /* %s */\n",
+ decl_2->decl.insn_reserv.insn_num,
+ decl_2->decl.insn_reserv.name);
+ }
+ }
+ (*output_automata_list_code)
+ (decl->decl.insn_reserv.important_automata_list);
+ }
+ }
+}
+
+
+/* The function outputs a code for evaluation of a minimal delay of
+ issue of insns which have reservations in given AUTOMATA_LIST. */
+static void
+output_automata_list_min_issue_delay_code (automata_list)
+ automata_list_el_t automata_list;
+{
+ automata_list_el_t el;
automaton_t automaton;
- fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
- INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
- fprintf (output_file,
- "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
- INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
- CHIP_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s;\n int %s;\n",
- TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
{
- fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ automaton = el->automaton;
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
output_min_issue_delay_vect_name (output_file, automaton);
fprintf (output_file,
(automaton->min_issue_delay_table_compression_factor != 1
{
fprintf (output_file, ") / %d];\n",
automaton->min_issue_delay_table_compression_factor);
- fprintf (output_file, " %s = (%s >> (8 - (",
+ fprintf (output_file, " %s = (%s >> (8 - (",
TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
output_translate_vect_name (output_file, automaton);
fprintf
(1 << (8 / automaton->min_issue_delay_table_compression_factor))
- 1);
}
- if (automaton == description->first_automaton)
- fprintf (output_file, " %s = %s;\n",
+ if (el == automata_list)
+ fprintf (output_file, " %s = %s;\n",
RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
else
{
- fprintf (output_file, " if (%s > %s)\n",
+ fprintf (output_file, " if (%s > %s)\n",
TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
- fprintf (output_file, " %s = %s;\n",
+ fprintf (output_file, " %s = %s;\n",
RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
}
}
+ fprintf (output_file, " break;\n\n");
+}
+
+/* Output function `internal_min_issue_delay'. */
+static void
+output_internal_min_issue_delay_func ()
+{
+ fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file,
+ "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
+ CHIP_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s;\n",
+ TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
+ fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ output_insn_code_cases (output_automata_list_min_issue_delay_code);
+ fprintf (output_file,
+ "\n default:\n %s = -1;\n break;\n }\n",
+ RESULT_VARIABLE_NAME);
fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
fprintf (output_file, "}\n\n");
}
-/* Output function `internal_state_transition'. */
+/* The function outputs a code changing state after issue of insns
+ which have reservations in given AUTOMATA_LIST. */
static void
-output_internal_trans_func ()
+output_automata_list_transition_code (automata_list)
+ automata_list_el_t automata_list;
{
- automaton_t curr_automaton;
- automaton_t next_automaton;
+ automata_list_el_t el, next_el;
- fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
- INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
- fprintf (output_file,
- "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
- INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
- CHIP_NAME, CHIP_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s;\n", TEMPORARY_VARIABLE_NAME);
- if (description->first_automaton != NULL)
- for (curr_automaton = description->first_automaton;;
- curr_automaton = next_automaton)
+ fprintf (output_file, " {\n");
+ if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
+ for (el = automata_list;; el = next_el)
{
- next_automaton = curr_automaton->next_automaton;
- if (next_automaton == NULL)
+ next_el = el->next_automata_list_el;
+ if (next_el == NULL)
break;
- fprintf (output_file, " ");
- output_state_member_type (output_file, curr_automaton);
+ fprintf (output_file, " ");
+ output_state_member_type (output_file, el->automaton);
fprintf (output_file, " ");
- output_temp_chip_member_name (output_file, curr_automaton);
+ output_temp_chip_member_name (output_file, el->automaton);
fprintf (output_file, ";\n");
}
- for (curr_automaton = description->first_automaton;
- curr_automaton != NULL;
- curr_automaton = curr_automaton->next_automaton)
- if (comb_vect_p (curr_automaton->trans_table))
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
+ if (comb_vect_p (el->automaton->trans_table))
{
- fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
- output_trans_base_vect_name (output_file, curr_automaton);
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ output_trans_base_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, curr_automaton);
+ output_chip_member_name (output_file, el->automaton);
fprintf (output_file, "] + ");
- output_translate_vect_name (output_file, curr_automaton);
+ output_translate_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, " if (");
- output_trans_check_vect_name (output_file, curr_automaton);
+ fprintf (output_file, " if (");
+ output_trans_check_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s] != %s->",
TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, curr_automaton);
+ output_chip_member_name (output_file, el->automaton);
fprintf (output_file, ")\n");
- fprintf (output_file, " return %s (%s, %s);\n",
+ fprintf (output_file, " return %s (%s, %s);\n",
INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
CHIP_PARAMETER_NAME);
- fprintf (output_file, " else\n");
- fprintf (output_file, " ");
- if (curr_automaton->next_automaton != NULL)
- output_temp_chip_member_name (output_file, curr_automaton);
+ fprintf (output_file, " else\n");
+ fprintf (output_file, " ");
+ if (el->next_automata_list_el != NULL)
+ output_temp_chip_member_name (output_file, el->automaton);
else
{
fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, curr_automaton);
+ output_chip_member_name (output_file, el->automaton);
}
fprintf (output_file, " = ");
- output_trans_comb_vect_name (output_file, curr_automaton);
+ output_trans_comb_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
}
else
{
- fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
- output_trans_full_vect_name (output_file, curr_automaton);
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ output_trans_full_vect_name (output_file, el->automaton);
fprintf (output_file, " [");
- output_translate_vect_name (output_file, curr_automaton);
+ output_translate_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, curr_automaton);
+ output_chip_member_name (output_file, el->automaton);
fprintf (output_file, " * %d];\n",
- curr_automaton->insn_equiv_classes_num);
- fprintf (output_file, " if (%s >= %d)\n", TEMPORARY_VARIABLE_NAME,
- curr_automaton->achieved_states_num);
- fprintf (output_file, " return %s (%s, %s);\n",
+ el->automaton->insn_equiv_classes_num);
+ fprintf (output_file, " if (%s >= %d)\n",
+ TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
+ fprintf (output_file, " return %s (%s, %s);\n",
INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
CHIP_PARAMETER_NAME);
- fprintf (output_file, " else\n ");
- if (curr_automaton->next_automaton != NULL)
- output_temp_chip_member_name (output_file, curr_automaton);
+ fprintf (output_file, " else\n ");
+ if (el->next_automata_list_el != NULL)
+ output_temp_chip_member_name (output_file, el->automaton);
else
{
fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, curr_automaton);
+ output_chip_member_name (output_file, el->automaton);
}
fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
}
- if (description->first_automaton != NULL)
- for (curr_automaton = description->first_automaton;;
- curr_automaton = next_automaton)
+ if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
+ for (el = automata_list;; el = next_el)
{
- next_automaton = curr_automaton->next_automaton;
- if (next_automaton == NULL)
+ next_el = el->next_automata_list_el;
+ if (next_el == NULL)
break;
- fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, curr_automaton);
+ fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, el->automaton);
fprintf (output_file, " = ");
- output_temp_chip_member_name (output_file, curr_automaton);
+ output_temp_chip_member_name (output_file, el->automaton);
fprintf (output_file, ";\n");
}
- fprintf (output_file, " return -1;\n");
+ fprintf (output_file, " return -1;\n");
+ fprintf (output_file, " }\n");
+}
+
+/* Output function `internal_state_transition'. */
+static void
+output_internal_trans_func ()
+{
+ fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
+ INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file,
+ "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
+ INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_NAME, CHIP_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
+ fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ output_insn_code_cases (output_automata_list_transition_code);
+ fprintf (output_file, "\n default:\n return -1;\n }\n");
fprintf (output_file, "}\n\n");
}
DFA_INSN_CODE_FUNC_NAME);
fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
- fprintf (output_file, "{\n int %s;\n\n", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, "{\n int %s;\n int %s;\n\n",
+ INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
+ fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
+ INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
+ fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
+ TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
+ DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
+ fprintf (output_file,
+ " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
+ TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
+ TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
+ TEMPORARY_VARIABLE_NAME);
fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
INSN_PARAMETER_NAME);
INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
}
-/* Output function `internal_state_alts'. */
+/* The function outputs a code for evaluation of alternative states
+ number for insns which have reservations in given AUTOMATA_LIST. */
static void
-output_internal_state_alts_func ()
+output_automata_list_state_alts_code (automata_list)
+ automata_list_el_t automata_list;
{
+ automata_list_el_t el;
automaton_t automaton;
+ fprintf (output_file, " {\n");
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
+ if (comb_vect_p (el->automaton->state_alts_table))
+ {
+ fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
+ break;
+ }
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
+ {
+ automaton = el->automaton;
+ if (comb_vect_p (automaton->state_alts_table))
+ {
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ output_state_alts_base_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, "] + ");
+ output_translate_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, " if (");
+ output_state_alts_check_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s] != %s->",
+ TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, ")\n");
+ fprintf (output_file, " return 0;\n");
+ fprintf (output_file, " else\n");
+ fprintf (output_file,
+ (el == automata_list
+ ? " %s = " : " %s += "),
+ RESULT_VARIABLE_NAME);
+ output_state_alts_comb_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
+ }
+ else
+ {
+ fprintf (output_file,
+ (el == automata_list
+ ? "\n %s = " : " %s += "),
+ RESULT_VARIABLE_NAME);
+ output_state_alts_full_vect_name (output_file, automaton);
+ fprintf (output_file, " [");
+ output_translate_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, " * %d];\n",
+ automaton->insn_equiv_classes_num);
+ }
+ }
+ fprintf (output_file, " break;\n }\n\n");
+}
+
+/* Output function `internal_state_alts'. */
+static void
+output_internal_state_alts_func ()
+{
fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
fprintf (output_file,
CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
CHIP_PARAMETER_NAME);
fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- if (comb_vect_p (automaton->state_alts_table))
- {
- fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
- break;
- }
- for (automaton = description->first_automaton;
- automaton != NULL;
- automaton = automaton->next_automaton)
- if (comb_vect_p (automaton->state_alts_table))
- {
- fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
- output_state_alts_base_vect_name (output_file, automaton);
- fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, "] + ");
- output_translate_vect_name (output_file, automaton);
- fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, " if (");
- output_state_alts_check_vect_name (output_file, automaton);
- fprintf (output_file, " [%s] != %s->",
- TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, ")\n");
- fprintf (output_file, " return 0;\n");
- fprintf (output_file, " else\n");
- fprintf (output_file,
- (automaton == description->first_automaton
- ? " %s = " : " %s += "), RESULT_VARIABLE_NAME);
- output_state_alts_comb_vect_name (output_file, automaton);
- fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
- }
- else
- {
- fprintf (output_file,
- (automaton == description->first_automaton
- ? "\n %s = " : " %s += "), RESULT_VARIABLE_NAME);
- output_state_alts_full_vect_name (output_file, automaton);
- fprintf (output_file, " [");
- output_translate_vect_name (output_file, automaton);
- fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
- fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
- output_chip_member_name (output_file, automaton);
- fprintf (output_file, " * %d];\n", automaton->insn_equiv_classes_num);
- }
+ fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ output_insn_code_cases (output_automata_list_state_alts_code);
+ fprintf (output_file,
+ "\n default:\n %s = 0;\n break;\n }\n",
+ RESULT_VARIABLE_NAME);
fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
fprintf (output_file, "}\n\n");
}
INTERNAL_INSN_LATENCY_FUNC_NAME);
fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
- INTERNAL_INSN2_CODE_NAME,
- INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
+ INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
+ INSN2_PARAMETER_NAME);
fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
fprintf (output_file,
units_cmp (unit1, unit2)
const void *unit1, *unit2;
{
- const struct unit_decl *u1 = *(struct unit_decl **) unit1;
- const struct unit_decl *u2 = *(struct unit_decl **) unit2;
+ const unit_decl_t u1 = *(unit_decl_t *) unit1;
+ const unit_decl_t u2 = *(unit_decl_t *) unit2;
return strcmp (u1->name, u2->name);
}
output_get_cpu_unit_code_func ()
{
int i;
- struct unit_decl **units;
+ unit_decl_t *units;
fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
fprintf (output_file, " static struct %s %s [] =\n {\n",
NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
- units = (struct unit_decl **) xmalloc (sizeof (struct unit_decl *)
- * description->units_num);
- memcpy (units, units_array,
- sizeof (struct unit_decl *) * description->units_num);
- qsort (units, description->units_num,
- sizeof (struct unit_decl *), units_cmp);
+ units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
+ * description->units_num);
+ memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
+ qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
for (i = 0; i < description->units_num; i++)
if (units [i]->query_p)
fprintf (output_file, " {\"%s\", %d},\n",
output_dfa_start_func ()
{
fprintf (output_file,
- "void\n%s ()\n{\n int %s;\n int %s = get_max_uid ();\n\n",
- DFA_START_FUNC_NAME, I_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
+ "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
+ DFA_START_FUNC_NAME, I_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
- DFA_INSN_CODES_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
+ DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
fprintf (output_file,
" for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
- I_VARIABLE_NAME, I_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME,
- I_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
+ I_VARIABLE_NAME, I_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
+ DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
}
/* The function outputs PHR interface function `dfa_finish'. */
automata_num = description->units_num;
initiate_states ();
initiate_arcs ();
+ initiate_automata_lists ();
initiate_pass_states ();
initiate_excl_sets ();
initiate_presence_absence_sets ();
automaton_generation_time = create_ticker ();
- transform_time = create_ticker ();
- add_advance_cycle_insn_decl ();
- fprintf (stderr, "Reservation transformation...");
- fflush (stderr);
- transform_insn_regexps ();
- fprintf (stderr, "done\n");
- ticker_off (&transform_time);
- fprintf (stderr, "Create automata...");
- fflush (stderr);
create_automata ();
- fprintf (stderr, "done\n");
ticker_off (&automaton_generation_time);
}
/* The following function checks existence at least one arc marked by
each insn. */
static void
-check_automata ()
+check_automata_insn_issues ()
{
automaton_t automaton;
ainsn_t ainsn, reserv_ainsn;
}
}
+/* The following vla is used for storing pointers to all achieved
+ states. */
+static vla_ptr_t automaton_states;
+
+/* This function is called by function pass_states to add an achieved
+ STATE. */
+static void
+add_automaton_state (state)
+ state_t state;
+{
+ VLA_PTR_ADD (automaton_states, state);
+}
+
+/* The following function forms list of important automata (whose
+ states may be changed after the insn issue) for each insn. */
+static void
+form_important_insn_automata_lists ()
+{
+ automaton_t automaton;
+ state_t *state_ptr;
+ decl_t decl;
+ ainsn_t ainsn;
+ arc_t arc;
+ int i;
+
+ VLA_PTR_CREATE (automaton_states, 1500,
+ "automaton states for forming important insn automata sets");
+ /* Mark important ainsns. */
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ VLA_PTR_NULLIFY (automaton_states);
+ pass_states (automaton, add_automaton_state);
+ for (state_ptr = VLA_PTR_BEGIN (automaton_states);
+ state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
+ state_ptr++)
+ {
+ for (arc = first_out_arc (*state_ptr);
+ arc != NULL;
+ arc = next_out_arc (arc))
+ if (arc->to_state != *state_ptr)
+ {
+ if (!arc->insn->first_insn_with_same_reservs)
+ abort ();
+ for (ainsn = arc->insn;
+ ainsn != NULL;
+ ainsn = ainsn->next_same_reservs_insn)
+ ainsn->important_p = TRUE;
+ }
+ }
+ }
+ VLA_PTR_DELETE (automaton_states);
+ /* Create automata sets for the insns. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ {
+ automata_list_start ();
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ for (ainsn = automaton->ainsn_list;
+ ainsn != NULL;
+ ainsn = ainsn->next_ainsn)
+ if (ainsn->important_p
+ && ainsn->insn_reserv_decl == &decl->decl.insn_reserv)
+ {
+ automata_list_add (automaton);
+ break;
+ }
+ decl->decl.insn_reserv.important_automata_list
+ = automata_list_finish ();
+ }
+ }
+}
+
+
/* The following is top level function to generate automat(a,on) for
fast recognition of pipeline hazards. */
void
{
int i;
- if (VLA_PTR_LENGTH (decls) != 0)
+ description = create_node (sizeof (struct description)
+ /* One entry for cycle advancing insn. */
+ + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
+ description->decls_num = VLA_PTR_LENGTH (decls);
+ description->query_units_num = 0;
+ for (i = 0; i < description->decls_num; i++)
{
- description = create_node (sizeof (struct description)
- + sizeof (decl_t)
- /* One entry for cycle advancing insn. */
- * VLA_PTR_LENGTH (decls));
- description->decls_num = VLA_PTR_LENGTH (decls);
- description->query_units_num = 0;
- for (i = 0; i < description->decls_num; i++)
- {
- description->decls [i] = VLA_PTR (decls, i);
- if (description->decls [i]->mode == dm_unit
- && description->decls [i]->decl.unit.query_p)
- description->decls [i]->decl.unit.query_num
- = description->query_units_num++;
- }
- all_time = create_ticker ();
- check_time = create_ticker ();
- fprintf (stderr, "Check description...");
+ description->decls [i] = VLA_PTR (decls, i);
+ if (description->decls [i]->mode == dm_unit
+ && description->decls [i]->decl.unit.query_p)
+ description->decls [i]->decl.unit.query_num
+ = description->query_units_num++;
+ }
+ all_time = create_ticker ();
+ check_time = create_ticker ();
+ fprintf (stderr, "Check description...");
+ fflush (stderr);
+ check_all_description ();
+ fprintf (stderr, "done\n");
+ ticker_off (&check_time);
+ generation_time = create_ticker ();
+ if (!have_error)
+ {
+ transform_insn_regexps ();
+ check_unit_distributions_to_automata ();
+ }
+ if (!have_error)
+ {
+ generate ();
+ check_automata_insn_issues ();
+ }
+ if (!have_error)
+ {
+ form_important_insn_automata_lists ();
+ fprintf (stderr, "Generation of attributes...");
fflush (stderr);
- check_all_description ();
+ make_internal_dfa_insn_code_attr ();
+ make_insn_alts_attr ();
+ make_default_insn_latency_attr ();
+ make_bypass_attr ();
fprintf (stderr, "done\n");
- ticker_off (&check_time);
- generation_time = create_ticker ();
- if (!have_error)
- {
- generate ();
- check_automata ();
- if (!have_error)
- {
- fprintf (stderr, "Generation of attributes...");
- fflush (stderr);
- make_internal_dfa_insn_code_attr ();
- make_insn_alts_attr ();
- make_default_insn_latency_attr ();
- make_bypass_attr ();
- fprintf (stderr, "done\n");
- }
- }
- ticker_off (&generation_time);
- ticker_off (&all_time);
}
+ ticker_off (&generation_time);
+ ticker_off (&all_time);
fprintf (stderr, "All other genattrtab stuff...");
fflush (stderr);
}
output_internal_min_issue_delay_func ();
output_internal_trans_func ();
/* Cache of insn dfa codes: */
- fprintf (output_file, "\nstatic int *%s;\n\n", DFA_INSN_CODES_VARIABLE_NAME);
+ fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
+ fprintf (output_file, "\nstatic int %s;\n\n",
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
output_dfa_insn_code_func ();
output_trans_func ();
fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
output_time_statistics (stderr);
finish_states ();
finish_arcs ();
+ finish_automata_lists ();
if (time_flag)
{
fprintf (stderr, "Summary:\n");