GCC's bacl-end & assemble emission (26)

9.5.8.2.    Data initialization

Before building the automaton, resource is allocated first.

 

9416 static void

9417 generate (void)                                                                                   in genautomata.c

9418 {

9419   automata_num = split_argument ;

9420   if (description ->units_num < automata_num )

9421     automata_num = description ->units_num;

9422   initiate_states ();

9423   initiate_arcs ();

9424   initiate_automata_lists ();

9425   initiate_pass_states ();

9426   initiate_excl_sets ();

9427   initiate_presence_absence_pattern_sets ();

9428   automaton_generation_time = create_ticker ();

9429   create_automata ();

9430   ticker_off (&automaton_generation_time );

9431 }

 

split_argument holds the value of “-split” option of the automata generation command, which indicates the number of automatons generated. Of course it can’t be larger than the number of units.

As we have seen before, states of the automaton under creating describes the resource usage of every cycle for instructions’ execution. It is driven by instruction issue or cycle advance which now, after introducing pseudo advance_cycle_insn_decl , also can be regarded as instruction issue. So here, first, it needs to record declared CPU units into units_array – it is the resource with which instruction can be competed, and then allocates resource for the bitmap of state.

 

4221 static void

4222 initiate_states (void)                                                                            in genautomata.c

4223 {

4224   decl_t decl;

4225   int i;

4226

4227   VLA_PTR_CREATE (units_container , description ->units_num, "units_container");

4228   units_array

4229     = (description ->decls_num && description ->units_num

4230        ? VLA_PTR_BEGIN (units_container ) : NULL);

4231   for (i = 0; i < description ->decls_num; i++)

4232   {

4233     decl = description ->decls [i];

4234     if (decl->mode == dm_unit)

4235       units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);

4236   }

4237   max_cycles_num = description ->max_insn_reserv_cycles;

4238   els_in_cycle_reserv

4239     = ((description ->units_num + sizeof (set_el_t) * CHAR_BIT - 1)

4240        / (sizeof (set_el_t) * CHAR_BIT));

4241   els_in_reservs = els_in_cycle_reserv * max_cycles_num ;

4242   curr_unique_state_num = 0;

4243   initiate_alt_states ();

4244   VLA_PTR_CREATE (free_states , 1500, "free states");

4245   state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);

4246   temp_reserv = alloc_empty_reserv_sets ();

4247 }

 

first_free_alt_state will point to list of freed alt_state, which will link alternatives tegother for certain state. It is first initialized as null in initiate_alt_states .

 

3669 static void

3670 initiate_alt_states (void)                                                                      in genautomata.c

3671 {

3672   first_free_alt_state = NULL;

3673 }

 

set_el_t is typedef as “unsigned HOST_WIDE_INT”, and reserv_sets_t is typedef as the pointer type. Obvious the value of reserv_sets_t represents the reservations of function units. els_in_reservs is calculated at line 4241 in initiate_states , in related with: max_cycles_num , and els_in_cycle_reserv

 

3744 static reserv_sets_t

3745 alloc_empty_reserv_sets (void)                                                            in genautomata.c

3746 {

3747   reserv_sets_t result;

3748

3749   obstack_blank (&irp , els_in_reservs * sizeof (set_el_t));

3750   result = (reserv_sets_t) obstack_base (&irp );

3751   obstack_finish (&irp );

3752   memset (result, 0, els_in_reservs * sizeof (set_el_t));

3753   return result;

3754 }

 

first_free_arc will point to list of freed arc, which records the state transition.

 

4368 static void

4369 initiate_arcs (void)                                                                             in genautomata.c

4370 {

4371   first_free_arc = NULL;

4372 }

 

Similarly, first_free_automata_list_el will point to list of freed automaton. And all automaton objects will be kept in hashtable to ensure its unique.

 

4474 static void

4475 initiate_automata_lists (void)                                                               in genautomata.c

4476 {

4477   first_free_automata_list_el = NULL;

4478   automata_list_table = htab_create (1500, automata_list_hash,

4479                                  automata_list_eq_p, (htab_del) 0);

4480 }

 

Static variable curr_state_graph_pass_num will be used to record current number of passing graph of states.

 

5986 static void

5987 initiate_pass_states (void)                                                                    in genautomata.c

5988 {

5989   curr_state_graph_pass_num = 0;

5990 }

 

And for those insn refered in exclusion_set, allocate resource for the bitmap for recording exclusion set. Here it uses storage of obstack, which is described in detail in related sections for the front-end. In short, obstack is the block managed by GCC.

 

4544 static void

4545 initiate_excl_sets (void)                                                                      in genautomata.c

4546 {

4547   decl_t decl;

4548   reserv_sets_t unit_excl_set;

4549   unit_set_el_t el;

4550   int i;

4551

4552   obstack_blank (&irp , els_in_cycle_reserv * sizeof (set_el_t));

4553   excl_set = (reserv_sets_t) obstack_base (&irp );

4554   obstack_finish (&irp );

4555   obstack_blank (&irp , description ->units_num * sizeof (reserv_sets_t));

4556   unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp );

4557   obstack_finish (&irp );

4558   /* Evaluate unit exclusion sets.  */

4559   for (i = 0; i < description ->decls_num; i++)

4560   {

4561     decl = description ->decls [i];

4562     if (decl->mode == dm_unit)

4563     {

4564        obstack_blank (&irp , els_in_cycle_reserv * sizeof (set_el_t));

4565        unit_excl_set = (reserv_sets_t) obstack_base (&irp );

4566        obstack_finish (&irp );

4567        memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));

4568        for (el = DECL_UNIT (decl)->excl_list;

4569           el != NULL;

4570           el = el->next_unit_set_el)

4571        {

4572          SET_BIT (unit_excl_set, el->unit_decl->unit_num);

4573          el->unit_decl->in_set_p = TRUE;

4574        }

4575       unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;

4576     }

4577   }

4578 }

 

Line 4552 to 4554 allocates memory for excl_set , which will be set by get_excl_set . Line 4555~4557 allocates memory for unit_excl_set_table , note that reserv_sets_t is the pointer type of set_el_t.

Above in 4th Loop of Processing Decls – DECL_EXCL , it integrates all exclude set of the unit tegother, which is used here. Loop at line 4568 uses this information of exclude-set to set unit_excl_set_table .

Also unit_presence_set_table , unit_presence_set_table , unit_absence_set_table and unit_final_absence_set_table are also set by the similar way.

 

4653 static void

4654 initiate_presence_absence_pattern_sets (void)                                        in genautomata.c

4655 {

4656   decl_t decl;

4657   int i;

4658

4659   obstack_blank (&irp , description ->units_num * sizeof (pattern_reserv_t));

4660   unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp );

4661   obstack_finish (&irp );

4662   obstack_blank (&irp , description ->units_num * sizeof (pattern_reserv_t));

4663   unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp );

4664   obstack_finish (&irp );

4665   obstack_blank (&irp , description ->units_num * sizeof (pattern_reserv_t));

4666   unit_absence_set_table

4667

4668 = (pattern_reserv_t *) obstack_base (&irp );

4669   obstack_finish (&irp );

4670   obstack_blank (&irp , description ->units_num * sizeof (pattern_reserv_t));

4671   unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp );

4672   obstack_finish (&irp );

4673   /* Evaluate unit presence/absence sets.  */

4674   for (i = 0; i < description ->decls_num; i++)

4675   {

4676     decl = description ->decls [i];

4677     if (decl->mode == dm_unit)

4678     {

4679       unit_presence_set_table [DECL_UNIT (decl)->unit_num]

4680            = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);

4681       unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]

4682           = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);

4683       unit_absence_set_table [DECL_UNIT (decl)->unit_num]

4684           = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);

4685       unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]

4686           = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);

4687     }

4688   }

4689 }

 

The value of automata_num comes from the “-split” option of automata generation command. However, it is not supported in this version, see initiate_automaton_gen , line 9664.

 

6804 static void

6805 create_automata (void)                                                                              in genautomata.c

6806 {

6807   automaton_t curr_automaton;

6808   automaton_t prev_automaton;

6809   decl_t decl;

6810   int curr_automaton_num;

6811   int i;

6812

6813   if (automata_num != 0)

6814   {

         …

6830   }

6831   else

6832   {

6833     curr_automaton_num = 0;

6834     prev_automaton = NULL;

6835     for (i = 0; i < description ->decls_num; i++)

6836     {

6837       decl = description ->decls [i];

6838       if (decl->mode == dm_automaton

6839          && DECL_AUTOMATON (decl)->automaton_is_used)

6840        {

6841         curr_automaton = create_node (sizeof (struct automaton));

6842          curr_automaton->ainsn_list = create_ainsns ();

6843         curr_automaton->corresponding_automaton_decl

6844                  = DECL_AUTOMATON (decl);

6845         curr_automaton->next_automaton = NULL;

6846         DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;

6847         curr_automaton->automaton_order_num = curr_automaton_num;

6848          if (prev_automaton == NULL)

6849           description ->first_automaton = curr_automaton;

6850         else

6851           prev_automaton->next_automaton = curr_automaton;

6852         curr_automaton_num++;

6853         prev_automaton = curr_automaton;

6854       }

6855     }

6856     if (curr_automaton_num == 0)

6857     {

6858         curr_automaton = create_node (sizeof (struct automaton));

6859         curr_automaton->ainsn_list = create_ainsns ();

6860       curr_automaton->corresponding_automaton_decl = NULL;

6861       curr_automaton->next_automaton = NULL;

6862       description ->first_automaton = curr_automaton;

6863     }

6864     units_to_automata_distr ();

6865   }

 

Loop at line 6835 first create automaton object for all automata, these objects have below definition.

 

1224 struct automaton                                                                                  in genautomata.c

1225 {

1226   /* The following field value is the list of insn declarations for

1227     given automaton.  */

1228   ainsn_t ainsn_list;

1229   /* The following field value is the corresponding automaton

1230     declaration. This field is not NULL only if the automatic

1231     partition on automata is not used.  */

1232   struct automaton_decl *corresponding_automaton_decl;

1233   /* The following field value is the next automaton.  */

1234   automaton_t next_automaton;

1235   /* The following field is start state of FA. There are not unit

1236     reservations in the state.  */

1237   state_t start_state;

1238   /* The following field value is number of equivalence classes of

1239     insns (see field `insn_equiv_class_num' in

1240     `insn_reserv_decl').  */

1241   int insn_equiv_classes_num;

1242   /* The following field value is number of states of final DFA.  */

1243   int achieved_states_num;

1244   /* The following field value is the order number (0, 1, ...) of

1245     given automaton.  */

1246   int automaton_order_num;

1247   /* The following fields contain statistics information about

1248     building automaton.  */

1249   int NDFA_states_num, DFA_states_num;

1250   /* The following field value is defined only if minimization of DFA

1251      is used.  */

1252   int minimal_DFA_states_num;

1253   int NDFA_arcs_num, DFA_arcs_num;

1254   /* The following field value is defined only if minimization of DFA

1255     is used.  */

1256   int minimal_DFA_arcs_num;

1257   /* The following two members refer for two table state x ainsn ->

1258     int.  */

1259   state_ainsn_table_t trans_table;

1260   state_ainsn_table_t state_alts_table;

1261   /* The following member value is maximal value of min issue delay

1262     for insns of the automaton.  */

1263   int max_min_delay;

1264   /* Usually min issue delay is small and we can place several (2, 4,

1265     8) elements in one vector element. So the compression factor can

1266     be 1 (no compression), 2, 4, 8.  */

1267   int min_issue_delay_table_compression_factor;

1268 };

 

205  typedef struct automaton *automaton_t ;                                                in genautomata.c

 

In automaton definition, field ainsn_list records all instructions that drive this automaton from one state to another. And we will see later, ainsn_list also records the states involved as automaton growing. It is the most important field in automaton definition. At line 6842, create_ainsns creates this list for each automaton.

 

6746 static ainsn_t

6747 create_ainsns (void)                                                                            in genautomata.c

6748 {

6749   decl_t decl;

6750   ainsn_t first_ainsn;

6751   ainsn_t curr_ainsn;

6752   ainsn_t prev_ainsn;

6753   int i;

6754

6755   first_ainsn = NULL;

6756   prev_ainsn = NULL;

6757   for (i = 0; i < description ->decls_num; i++)

6758   {

6759     decl = description ->decls [i];

6760     if (decl->mode == dm_insn_reserv)

6761     {

6762        curr_ainsn = create_node (sizeof (struct ainsn ));

6763        curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);

6764        curr_ainsn->important_p = FALSE;

6765        curr_ainsn->next_ainsn = NULL;

6766        if (prev_ainsn == NULL)

6767            first_ainsn = curr_ainsn;

6768        else

6769            prev_ainsn->next_ainsn = curr_ainsn;

6770        prev_ainsn = curr_ainsn;

6771     }

6772   }

6773   return first_ainsn;

6774 }

 

At line 6762, ainsn has following definition. See that it has one-to-one relationship with define_insn_reservation.

 

1179 struct ainsn                                                                                          in genautomata.c

1180 {

1181   /* The following field value is the corresponding insn declaration

1182     of description.  */

1183   struct insn_reserv_decl *insn_reserv_decl;

1184   /* The following field value is the next insn declaration for an

1185     automaton.  */

1186   ainsn_t next_ainsn;

1187   /* The following field is states which characterize automaton unit

1188     reservations of the instruction. The value can be NULL only if it

1189     is special insn `cycle advancing'.  */

1190   alt_state_t alt_states;

1191   /* The following field is sorted list of states which characterize

1192     automaton unit reservations of the instruction. The value can be

1193     NULL only if it is special insn `cycle advancing'.  */

1194   alt_state_t sorted_alt_states;

1195   /* The following field refers the next automaton insn with

1196     the same reservations.  */

1197   ainsn_t next_same_reservs_insn;

1198   /* The following field is flag of the first automaton insn with the

1199     same reservations in the declaration list. Only arcs marked such

1200     insn is present in the automaton. This significantly decreases

1201     memory requirements especially when several automata are

1202     formed.  */

1203   char first_insn_with_same_reservs;

1204   /* The following member has nonzero value if there is arc from state of

1205     the automaton marked by the ainsn.  */

1206   char arc_exists_p;

1207   /* Cyclic list of insns of an equivalence class is formed with the

1208     aid of the following field.  */

1209   ainsn_t next_equiv_class_insn;

1210   /* The following field value is nonzero if the insn declaration is

1211     the first insn declaration with given equivalence number.  */

1212   char first_ainsn_with_given_equialence_num;

1213   /* The following field is number of class of equivalence of insns.

1214     It is necessary because many insns may be equivalent with the

1215     point of view of pipeline hazards.  */

1216   int insn_equiv_class_num;

1217   /* The following member value is TRUE if there is an arc in the

1218     automaton marked by the insn into another state. In other

1219     words, the insn can change the state of the automaton.  */

1220   int important_p;

1221 };

 

For certain define_insn_reservation pattern, it may have more than one plan of unit reservation, which means from certain state by different plan will lead to different states. Field alt_states will records these different state transitions from the same start state. In this version, if no automaton is defined in machine description file, all cpu units will be assigned to the single default automaton, else the assignment has been done in machine description file. units_to_automata_distr does the distribution.

 

6778 static void

6779 units_to_automata_distr (void)                                                            in genautomata.c

6780 {

6781   decl_t decl;

6782   int i;

6783

6784   for (i = 0; i < description ->decls_num; i++)

6785   {

6786     decl = description ->decls [i];

6787     if (decl->mode == dm_unit)

6788     {

6789        if (DECL_UNIT (decl)->automaton_decl == NULL

6790             || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton

6791               == NULL))

6792           /* Distribute to the first automaton.  */

6793            DECL_UNIT (decl)->corresponding_automaton_num = 0;

6794        else

6795          DECL_UNIT (decl)->corresponding_automaton_num

6796             = (DECL_UNIT (decl)->automaton_decl

6797                 ->corresponding_automaton->automaton_order_num);

6798     }

6799   }

6800 }

 

In fact distribution is done by setting corresponding_automaton_num field of the unit object.

9.5.8.3.    Build bitmap and prepare data for state

All resources have been allocated. It is time to fill in bitmaps and create data to accommodate alternatives. Notice that even only one candidate present, this data still need created for purpose of uniformly handling data. Alternatives just are branches triggered simultaneously from certain state; it is not different from non-alternative in nature.

 

create_automata (continued)

 

6866   NDFA_time = create_ticker ();

6867   ticker_off (&NDFA_time );

6868   NDFA_to_DFA_time = create_ticker ();

6869   ticker_off (&NDFA_to_DFA_time );

6870   minimize_time = create_ticker ();

6871   ticker_off (&minimize_time );

6872   equiv_time = create_ticker ();

6873   ticker_off (&equiv_time );

6874   for (curr_automaton = description ->first_automaton;

6875        curr_automaton != NULL;

6876        curr_automaton = curr_automaton->next_automaton)

6877   {

6878     if (progress_flag )

6879     {

6880       if (curr_automaton->corresponding_automaton_decl == NULL)

6881         fprintf (stderr , "Prepare anonymous automaton creation ... ");

6882       else

6883         fprintf (stderr , "Prepare automaton `%s' creation...",

6884                curr_automaton->corresponding_automaton_decl->name);

6885     }

6886     create_alt_states (curr_automaton);

6887     form_ainsn_with_same_reservs (curr_automaton);

6888     if (progress_flag )

6889       fprintf (stderr , "done/n");

6890     build_automaton (curr_automaton);

6891     enumerate_states (curr_automaton);

6892     ticker_on (&equiv_time );

6893     set_insn_equiv_classes (curr_automaton);

6894     ticker_off (&equiv_time );

6895   }

6896 }

 

As we have seen before, define_insn_reservation defines the resource usage in every cycle, and bitmaps have been allocated to record CPU units usage per cycle per insn. When scheduling instruction, it will tell whether the instruction competes for the same resource with those already scheduled, and this is the important for making clever and efficient scheduler. create_alt_states creates data for alternatives and fills the bitmaps for every alternative.

 

5589 static void

5590 create_alt_states (automaton_t automaton)                                            in genautomata.c

5591 {

5592   struct insn_reserv_decl *reserv_decl;

5593

5594   for (curr_ainsn = automaton->ainsn_list;

5595        curr_ainsn != NULL;

5596        curr_ainsn = curr_ainsn ->next_ainsn)

5597   {

5598     reserv_decl = curr_ainsn ->insn_reserv_decl;

5599     if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl ))

5600     {

5601       curr_ainsn ->alt_states = NULL;

5602       process_alts_for_forming_states (reserv_decl->transformed_regexp,

5603                                   automaton, 0);

5604       curr_ainsn ->sorted_alt_states

5605           = uniq_sort_alt_states (curr_ainsn ->alt_states);

5606     }

5607   }

5608 }

 

Above the regexp of define_insn_reservation has been transformed to move “|” to outmost, no “|” is expected inside alternatives. That is no alternative should be found within another alternative. Below function bases on this assumption (refer to line 5577).

 

5556 static void

5557 process_alts_for_forming_states (regexp_t regexp,                                 in genautomata.c

5558                             automaton_t automaton, int inside_oneof_p)

5559 {

5560   int i;

5561

5562   if (regexp->mode != rm_oneof)

5563   {

5564     alt_state_being_formed = get_free_alt_state ();

5565     state_being_formed = get_free_state (1, automaton);

5566     alt_state_being_formed ->state = state_being_formed ;

5567     /* We inserts in reverse order but we process alternatives also

5568       i n reverse order. So we have the same order of alternative

5569       as in the description.  */

5570     alt_state_being_formed ->next_alt_state = curr_ainsn ->alt_states;

5571     curr_ainsn ->alt_states = alt_state_being_formed ;

5572     (void) process_seq_for_forming_states (regexp, automaton, 0);

5573     finish_forming_alt_state (alt_state_being_formed , automaton);

5574   }

5575   else

5576   {

5577     if (inside_oneof_p)

5578       abort ();

5579     /* We processes it in reverse order to get list with the same

5580        order as in the description. See also the previous

5581        commentary.  */

5582     for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)

5583       process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],

5584                    automaton, 1);

5585   }

5586 }

 

Above, at line 5564, alt_state_being_formed is an object of alt_state which has following definition. The data forms a link per define_insn_reservation, the state field records the data of first alternative, and next_alt_state links other alternatives. next_sorted_alt_state holds sorted alternatives data which is used to distinct different define_insn_reservation.

 

1165 struct alt_state                                                                                            in genautomata.c

1166 {

1167   /* The following field is a deterministic state which characterizes

1168     unit reservations of the instruction.  */

1169   state_t state ;

1170   /* The following field refers to the next state which characterizes

1171     unit reservations of the instruction.  */

1172   alt_state_t next_alt_state;

1173   /* The following field refers to the next state in sorted list.  */

1174   alt_state_t next_sorted_alt_state;

1175 };

 

And at line 1169, state_t is typedef as state * which defined as below. Initially, every define_insn_reservation is associated with a state per alternative. The reservs field at line 1085 in state records resource usage for every cycle.

 

1078 struct state                                                                                           in genautomata.c

1079 {

1080   /* The following member value is nonzero if there is a transition by

1081     cycle advancing.  */

1082   int new_cycle_p;

1083   /* The following field is list of processor unit reservations on

1084     each cycle.  */

1085   reserv_sets_t reservs;

1086   /* The following field is unique number of given state between other

1087     states.  */

1088   int unique_num;

1089   /* The following field value is automaton to which given state

1090     belongs.  */

1091   automaton_t automaton;

1092   /* The following field value is the first arc output from given

1093     state.  */

1094   arc_t first_out_arc;

1095   /* The following field is used to form NDFA.  */

1096   char it_was_placed_in_stack_for_NDFA_forming;

1097   /* The following field is used to form DFA.  */

1098   char it_was_placed_in_stack_for_DFA_forming;

1099   /* The following field is used to transform NDFA to DFA and DFA

1100     minimization. The field value is not NULL if the state is a

1101     compound state. In this case the value of field `unit_sets_list'

1102     is NULL. All states in the list are in the hash table. The list

1103     is formed through field `next_sorted_alt_state'. We should

1104     support only one level of nesting state.  */

1105   alt_state_t component_states;

1106   /* The following field is used for passing graph of states.  */

1107   int pass_num;

1108   /* The list of states belonging to one equivalence class is formed

1109     with the aid of the following field.  */

1110   state_t next_equiv_class_state;

1111   /* The two following fields are used during minimization of a finite

1112     state automaton.  */

1113   int equiv_class_num_1, equiv_class_num_2;

1114   /* The following field is used during minimization of a finite state

1115     automaton. The field value is state corresponding to equivalence

1116     class to which given state belongs.  */

1117   state_t equiv_class_state;

1118   /* The following field value is the order number of given state.

1119     The states in final DFA is enumerated with the aid of the

1120     following field.  */

1121   int order_state_num;

1122   /* This member is used for passing states for searching minimal

1123     delay time.  */

1124   int state_pass_num;

1125   /* The following member is used to evaluate min issue delay of insn

1126     for a state.  */

1127   int min_insn_issue_delay;

1128   /* The following member is used to evaluate max issue rate of the

1129     processor. The value of the member is maximal length of the path

1130     from given state no containing arcs marked by special insn `cycle

1131     advancing'.  */

1132   int longest_path_length;

1133 };

 

process_seq_for_forming_states builds the bitmap of unit reservation for every alternative in current cycle (here is cycle 0).

 

5484 static int

5485 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,     in genautomata.c

5486                             int curr_cycle)

5487 {

5488   int i;

5489

5490   if (regexp == NULL)

5491     return curr_cycle;

5492   else if (regexp->mode == rm_unit)

5493   {

5494     if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num

5495           == automaton->automaton_order_num)

5496        set_state_reserv (state_being_formed , curr_cycle,

5497                          REGEXP_UNIT (regexp)->unit_decl->unit_num);

5498      return curr_cycle;

5499   }

5500   else if (regexp->mode == rm_sequence)

5501   {

5502     for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)

5503       curr_cycle

5504          = process_seq_for_forming_states

5505             (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;

5506     return curr_cycle;

5507   }

5508   else if (regexp->mode == rm_allof)

5509   {

5510     int finish_cycle = 0;

5511     int cycle;

5512

5513     for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)

5514     {

5515        cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)

5516                        ->regexps [i],

5517                         automaton, curr_cycle);

5518        if (finish_cycle < cycle)

5519          finish_cycle = cycle;

5520     }

5521     return finish_cycle;

5522   }

5523   else

5524   {

5525     if (regexp->mode != rm_nothing)

5526       abort ();

5527     return curr_cycle;

5528   }

5529 }

 

The bitmap of unit reservation is filled by set_state_reser v at line 5496. The bitmap is indexed by CPU cycle and unit_num . The bitmap is represented by state_being_formed which is assigned to alt_state_being_formed ->state at line 5566.

 

4160 static void

4161 set_state_reserv (state_t state, int cycle_num, int unit_num)                    in genautomata.c

4162 {

4163   set_unit_reserv (state->reservs, cycle_num, unit_num);

4164 }

 

3826 static void

3827 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)

3828 {

3829   if (cycle_num >= max_cycles_num )

3830     abort ();

3831   SET_BIT (reservs, cycle_num * els_in_cycle_reserv

3832            * sizeof (set_el_t) * CHAR_BIT + unit_num);

3833 }

 

Above, els_in_cycle_reserv is initialized in initiate_states at line 4238. It is the size of reservs . reservs is the bitmap to record the unit reservation in cycles. And notice that unit_num here comes from the field unit_num of the decl of define_cpu_unit, which is unique sequence number assigned in gen_unit .

Back to process_alts_for_forming_states , alt_state_being_formed is inserted into state_table by finish_forming_alt_state .

 

5533 static void

5534 finish_forming_alt_state (alt_state_t alt_state,                                       in genautomata.c

5535                        automaton_t automaton ATTRIBUTE_UNUSED)

5536 {

5537   state_t state_in_table;

5538   state_t corresponding_state;

5539

5540   corresponding_state = alt_state->state;

5541   state_in_table = insert_state (corresponding_state);

5542   if (state_in_table != corresponding_state)

5543   {

5544     free_state (corresponding_state);

5545     alt_state->state = state_in_table;

5546   }

5547 }

 

After building the bitmaps of current cycle, form_ainsn_with_same_reservs is invoked to link all instructions using the same unit reservation tegother. For those instructions having the same unit reservation, first_insns records the first one found, and last_insns records the last one found in the set. And those in first_insns have first_insn_with_same_reservs set. Besides, pseudo instruction advance_cycle_insn_decl always creates a seperate set as this instruction always advance CPU cycles.

After building the bitmaps for current cycle, form_ainsn_with_same_reservs traverses all ainsn objects which represent define_insn_reservation in the same automaton. Varray first_insns records ainsns using different units’ reservation, and at line 5654 it can see that last_insns is basically the same as first_insns , except finding another ainsn using the same units’ reservation, at the point these ainsns are linked via next_same_reservs_insn to form a queue, last_insns refers to the last found ainsn object.

Note that among ainsns using the same units’ reservation, only the first one found has first_insn_with_same_reservs set. Besides, pseduo instructuion advance_cycle_insn_decl always forms a single set, as it always advances CPU cycle.

 

5617 static void

5618 form_ainsn_with_same_reservs (automaton_t automaton)                      in genautomata.c

5619 {

5620   ainsn_t curr_ainsn;

5621   size_t i;

5622   vla_ptr_t first_insns;

5623   vla_ptr_t last_insns;

5624

5625   VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");

5626   VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");

5627   for (curr_ainsn = automaton->ainsn_list;

5628        curr_ainsn != NULL;

5629        curr_ainsn = curr_ainsn->next_ainsn)

5630     if (curr_ainsn->insn_reserv_decl

5631           == DECL_INSN_RESERV (advance_cycle_insn_decl ))

5632     {

5633       curr_ainsn->next_same_reservs_insn = NULL;

5634       curr_ainsn->first_insn_with_same_reservs = 1;

5635     }

5636     else

5637     {

5638       for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)

5639         if (alt_states_eq

5640              (curr_ainsn->sorted_alt_states,

5641              ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))

5642           break ;

5643       curr_ainsn->next_same_reservs_insn = NULL;

5644       if (i < VLA_PTR_LENGTH (first_insns))

5645       {

5646         curr_ainsn->first_insn_with_same_reservs = 0;

5647          ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn

5648                    = curr_ainsn;

5649         VLA_PTR (last_insns, i) = curr_ainsn;

5650       }

5651       else

5652       {

5653         VLA_PTR_ADD (first_insns, curr_ainsn);

5654         VLA_PTR_ADD (last_insns, curr_ainsn);

5655         curr_ainsn->first_insn_with_same_reservs = 1;

5656       }

5657     }

5658   VLA_PTR_DELETE (first_insns);

5659   VLA_PTR_DELETE (last_insns);

5660 }

 

So we can get following data at this step. At tail of the function, first and last will be deleted, but the lists are kept.

t72

figure 72  : grouping instruction into equivalent class, stage 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值