GCC后端及汇编发布(26)
来源:互联网 发布:vb status() 编辑:程序博客网 时间:2024/05/21 11:16
9.5.8.2. 数据初始化
在构建自动机之前,首先要分配资源。
9416 static void
9417 generate(void) ingenautomata.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保存了自动机生成命令中“split”选项的值,它显示了所产生的自动机的数量。当然它不可能大于功能单元的数目。
正如我们之前已经看到的,正在构建的自动机的状态描述了指令执行的每个周期中,资源使用的情况。它由指令发布或周期推进所驱动,而周期推进,现在在引入了伪指令advance_cycle_insn_decl之后,也可以被视为指令发布。因此在这里,首先,需要把CPU功能单元记录入units_array – 它是指令得以完成的资源,然后为状态位图分配资源。
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将指向由空闲alt_state组成的链表,对于某个状态,它将把替代链接起来。它首先在initiate_alt_states中被初始化为null。
3669 static void
3670 initiate_alt_states (void) ingenautomata.c
3671 {
3672 first_free_alt_state = NULL;
3673 }
set_el_t被typedef为unsigned HOST_WIDE_INT,而reserv_sets_t则typedef为其指针类型。显然reserv_sets_t的值用于代表功能单元的预订。els_in_reservs在initiate_states的4241行计算,相关的还有max_cycles_num及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 returnresult;
3754 }
first_free_arc将指向空闲的arc链表,它将记录状态的迁移。
4368 static void
4369 initiate_arcs (void) in genautomata.c
4370 {
4371 first_free_arc = NULL;
4372 }
同样first_free_automata_list_el用于指向空闲的automaton的链表。所有的自动机对象将被保存在哈希表中,以保证其唯一性。
4474 static void
4475 initiate_automata_lists (void) ingenautomata.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 }
静态变量curr_state_graph_pass_num将用于记录状态传递图(passing graph of states)的当前数目。
5986 static void
5987 initiate_pass_states (void) ingenautomata.c
5988 {
5989 curr_state_graph_pass_num = 0;
5990 }
而对于那些被exclusion_set所引用的指令,分配用于记录互斥及的位图资源。这里使用到了obstack机制的缓存,有关这部分的内容可以参考前端相关章节。总之,obstack是GCC自己管理的内存块。
4544 static void
4545 initiate_excl_sets (void) ingenautomata.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 unitexclusion 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 }
4552至4554行为excl_set分配内存,这个对象的内容将由get_excl_set来填充。4555~4557行则是为unit_excl_set_table分配内存,注意reserv_sets_t是set_el_t的指针类型。
前面在处理decl的第四个循环 –DECL_EXCL一节,整合了功能单元所有的互斥信息,这里就用上了。4568行的循环利用这个互斥信息设置unit_excl_set_table。
同样,unit_presence_set_table,unit_presence_set_table,unit_absence_set_table及unit_final_absence_set_table也是通过类似的方式设置的。
4653 static void
4654 initiate_presence_absence_pattern_sets (void) ingenautomata.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 unitpresence/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_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 }
下面,automata_num的值来自自动机生成命令中的选项“-split”。不过,在当前版本中它尚不被支持,参见initiate_automaton_gen,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 (structautomaton));
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 (structautomaton));
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 }
6835行的循环首先为所有的自动机创建automaton对象,这些对象具有如下定义。
1224 struct automaton ingenautomata.c
1225 {
1226 /* The followingfield value is the list of insn declarations for
1227 given automaton. */
1228 ainsn_t ainsn_list;
1229 /* The followingfield value is the corresponding automaton
1230 declaration. This field is not NULL only ifthe automatic
1231 partition on automata is not used. */
1232 struct automaton_decl *corresponding_automaton_decl;
1233 /* The followingfield value is the next automaton. */
1234 automaton_t next_automaton;
1235 /* The followingfield is start state of FA. There are not unit
1236 reservations in the state. */
1237 state_t start_state;
1238 /* The followingfield 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 finalDFA. */
1243 int achieved_states_num;
1244 /* The followingfield value is the order number (0, 1, ...) of
1245 given automaton. */
1246 int automaton_order_num;
1247 /* The followingfields contain statistics information about
1248 building automaton. */
1249 int NDFA_states_num, DFA_states_num;
1250 /* The following field value is defined only ifminimization 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 ifminimization of DFA
1255 is used. */
1256 int minimal_DFA_arcs_num;
1257 /* The following two members refer for two tablestate x ainsn ->
1258 int. */
1259 state_ainsn_table_t trans_table;
1260 state_ainsn_table_t state_alts_table;
1261 /* The followingmember value is maximal value of min issue delay
1262 for insns of the automaton. */
1263 int max_min_delay;
1264 /* Usually minissue delay is small and we can place several (2, 4,
1265 8) elements in one vector element. So thecompression 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; ingenautomata.c
在automaton定义中,域ainsn_list记录了所有会驱动这个自动机从一个状态到另一个状态的指令。而且我们将会看到,在自动机增长时,ainsn_list还会记录涉及的状态。它是在automaton定义中最重要的域。在6842行,create_ainsns为每个自动机构建这个链表。
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 returnfirst_ainsn;
6774 }
在6762行的ainsn具有如下定义。看到它与define_insn_reservation是一一对应的。
1179 struct ainsn ingenautomata.c
1180 {
1181 /* The followingfield value is the corresponding insn declaration
1182 of description. */
1183 struct insn_reserv_decl *insn_reserv_decl;
1184 /* The followingfield value is the next insn declaration for an
1185 automaton. */
1186 ainsn_t next_ainsn;
1187 /* The followingfield is states which characterize automaton unit
1188 reservations of the instruction. The valuecan be NULL only if it
1189 is special insn `cycle advancing'. */
1190 alt_state_t alt_states;
1191 /* The followingfield is sorted list of states which characterize
1192 automaton unit reservations of theinstruction. The value can be
1193 NULL only if it is special insn `cycleadvancing'. */
1194 alt_state_t sorted_alt_states;
1195 /* The following field refers the nextautomaton insn with
1196 the same reservations. */
1197 ainsn_t next_same_reservs_insn;
1198 /* The followingfield 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. Thissignificantly decreases
1201 memory requirements especially when severalautomata are
1202 formed. */
1203 char first_insn_with_same_reservs;
1204 /* The followingmember 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 ofinsns of an equivalence class is formed with the
1208 aid of the following field. */
1209 ainsn_t next_equiv_class_insn;
1210 /* The followingfield value is nonzero if the insn declaration is
1211 the first insn declaration with givenequivalence number. */
1212 char first_ainsn_with_given_equialence_num;
1213 /* The followingfield is number of class of equivalence of insns.
1214 It is necessary because many insns may beequivalent with the
1215 point of view of pipeline hazards. */
1216 int insn_equiv_class_num;
1217 /* The followingmember value is TRUE if there is an arc in the
1218 automaton marked by the insn into anotherstate. In other
1219 words, the insn can change the state of theautomaton. */
1220 int important_p;
1221 };
某些define_insn_reservation模式可能具有多个功能单元预订计划,这意味着,从某个状态出发,通过不同的计划,将导致不同的状态。域alt_states将记录这些从同一个状态开始的不同的状态迁移。在当前版本中,如果在机器描述文件中没有定义自动机,所有CPU单元将被分配到单个默认自动机,否则分配在机器描述文件中指定。units_to_automata_distr执行这个分配。
6778 static void
6779 units_to_automata_distr (void) ingenautomata.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 tothe 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 }
实际上设置了单元对象的corresponding_automaton_num域就完成了分配。
9.5.8.3. 构建位图及准备状态的数据
所有的资源都已经被分配了。是时候填充位图及构建包容替代的数据。注意即便只出现一个候选,出于统一处理的目的,这个数据仍然需要被创建。替代是从某个状态同时触发的分支,本质上它与非替代(non-alternative)没有什么不同。
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 anonymousautomaton 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 }
我们前面已经看到,define_insn_reservation定义了每个周期中资源的使用情况,而且已经分配了位图来记录每条指令每个周期的CPU单元的使用情况。当调度指令时,它将显示该指令是否会与其他已经被调度的指令争夺相同的资源,这对于构建聪明、高效的调度器很重要。create_alt_states为替代构建数据,并且为每个替代填充位图。
5589 static void
5590 create_alt_states (automaton_tautomaton) ingenautomata.c
5591 {
5592 structinsn_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 }
define_insn_reservation的regexp已经被转换,把“|”移到最外面,在替代内部不应该看到“|”,即替代内部不会包含替代。下面的函数基于这样的假设(参见5577行)。
5556 static void
5557 process_alts_for_forming_states (regexp_t regexp, in genautomata.c
5558 automaton_tautomaton, 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 inreverse order but we process alternatives also
5568 in 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 processesit in reverse order to get list with the same
5580 order as in the description. See also theprevious
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 }
上面在5564行,alt_state_being_formed是一个alt_state的对象,它的定义在下面给出。这个数据为每个define_insn_reservation构成了一个链表,其state域记录了第一个替代的数据,而next_alt_state链接其它替代。next_sorted_alt_state保存排序了的替代的数据,这个数据用于区分不同的define_insn_reservation。
1165 struct alt_state ingenautomata.c
1166 {
1167 /* The followingfield is a deterministic state which characterizes
1168 unit reservations of the instruction. */
1169 state_t state;
1170 /* The followingfield refers to the next state which characterizes
1171 unit reservations of the instruction. */
1172 alt_state_t next_alt_state;
1173 /* The followingfield refers to the next state in sorted list. */
1174 alt_state_t next_sorted_alt_state;
1175 };
而在1169行,state_t被typedef为state*,而state的定义如下。一开始,每个define_insn_reservation被与替代一一对应的state关联起来。在1085行,state中的reservs域记录了每个周期的资源使用情况。
1078 struct state ingenautomata.c
1079 {
1080 /* The followingmember value is nonzero if there is a transition by
1081 cycle advancing. */
1082 int new_cycle_p;
1083 /* The following field is list of processorunit reservations on
1084 each cycle. */
1085 reserv_sets_t reservs;
1086 /* The following field is unique number ofgiven state between other
1087 states. */
1088 int unique_num;
1089 /* The followingfield value is automaton to which given state
1090 belongs. */
1091 automaton_t automaton;
1092 /* The following field value is the first arcoutput from given
1093 state. */
1094 arc_t first_out_arc;
1095 /* The following field is used to formNDFA. */
1096 char it_was_placed_in_stack_for_NDFA_forming;
1097 /* The following field is used to formDFA. */
1098 char it_was_placed_in_stack_for_DFA_forming;
1099 /* The followingfield is used to transform NDFA to DFA and DFA
1100 minimization. The field value is not NULLif the state is a
1101 compound state. In this case the value offield `unit_sets_list'
1102 is NULL. All states in the list are in thehash table. The list
1103 is formed through field`next_sorted_alt_state'. We should
1104 support only one level of nestingstate. */
1105 alt_state_t component_states;
1106 /* The followingfield is used for passing graph of states. */
1107 int pass_num;
1108 /* The list of states belonging to oneequivalence 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 duringminimization of a finite
1112 state automaton. */
1113 int equiv_class_num_1, equiv_class_num_2;
1114 /* The followingfield is used during minimization of a finite state
1115 automaton. The field value is statecorresponding to equivalence
1116 class to which given state belongs. */
1117 state_t equiv_class_state;
1118 /* The followingfield value is the order number of given state.
1119 The states in final DFA is enumerated withthe aid of the
1120 following field. */
1121 int order_state_num;
1122 /* This member is used for passing states forsearching minimal
1123 delay time. */
1124 int state_pass_num;
1125 /* The following member is used to evaluate minissue delay of insn
1126 for a state. */
1127 int min_insn_issue_delay;
1128 /* The followingmember is used to evaluate max issue rate of the
1129 processor. The value of the member ismaximal length of the path
1130 from given state no containing arcs markedby special insn `cycle
1131 advancing'. */
1132 int longest_path_length;
1133 };
process_seq_for_forming_states则为每个替代构建当前周期的单元预订的位图(这里为周期0)。
5484 static int
5485 process_seq_for_forming_states (regexp_t regexp, automaton_tautomaton, in genautomata.c
5486 int curr_cycle)
5487 {
5488 int i;
5489
5490 if (regexp == NULL)
5491 returncurr_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 returncurr_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 returnfinish_cycle;
5522 }
5523 else
5524 {
5525 if (regexp->mode != rm_nothing)
5526 abort ();
5527 returncurr_cycle;
5528 }
5529 }
单元预订位图由5496行的set_state_reserv填充。这个位图使用CPU周期及unit_num做索引,这个位图由静态变量state_being_formed表示,并且在5566行state_being_formed被赋予alt_state_being_formed->state。
4160 static void
4161 set_state_reserv (state_tstate, 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 }
上面的els_in_cycle_reserv在initiate_states的4238行初始化。它代表reservs的大小。reservs是记录周期内单元预订的位图。注意到在这里unit_num来自define_cpu_unit的decl的unit_num域,它是由gen_unit赋予的唯一的值。
回到process_alts_for_forming_states,alt_state_being_formed被finish_forming_alt_state插入state_table。
5533 static void
5534 finish_forming_alt_state (alt_state_talt_state, ingenautomata.c
5535 automaton_t automaton ATTRIBUTE_UNUSED)
5536 {
5537 state_tstate_in_table;
5538 state_tcorresponding_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 }
在构建了当前周期的位图之后,form_ainsn_with_same_reservs遍历同一个自动机中所有代表define_insn_reservation的ainsn对象。变长数组first_insns记录使用不同单元预订的ainsn,在5654行看到,last_insns则基本与first_insns相同,除非找到使用相同单元预订的另一个ainsn对象,彼时这些ainsn对象将next_same_reservs_insn链接起来,形成一个队列(queue),last_insns指向最后的ainsn对象。
注意使用相同单元预订的ainsn对象中,第一个被找出的设置了first_insn_with_same_reservs。另外,伪指令advance_cycle_insn_decl总是构建一个单独的集合,因为这条指令总是推进CPU周期。
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, "firstinsns with the same reservs");
5626 VLA_PTR_CREATE (last_insns, 150, "lastinsns 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 }
因此在这一步我们可以得到如下形式的数据。First与last在函数末尾就被删除了,不过链表保留了下来。
图72:等效类别指令的分组,阶段1
- GCC后端及汇编发布(26)
- GCC后端及汇编发布(1)
- GCC后端及汇编发布(2)
- GCC后端及汇编发布(3)
- GCC后端及汇编发布(4)
- GCC后端及汇编发布(5)
- GCC后端及汇编发布(6)
- GCC后端及汇编发布(7)
- GCC后端及汇编发布(8)
- GCC后端及汇编发布(9)
- GCC后端及汇编发布(10)
- GCC后端及汇编发布(11)
- GCC后端及汇编发布(12)
- GCC后端及汇编发布(13)
- GCC后端及汇编发布(14)
- GCC后端及汇编发布(15)
- GCC后端及汇编发布(16)
- GCC后端及汇编发布(17)
- PHP IN_ARRAY 函数使用需要注意的地方
- 男士着装
- GCC's bacl-end & assemble emission (25)
- 朴素贝叶斯与贝叶斯信念网络
- linux c++ pthread_create 用法
- GCC后端及汇编发布(26)
- oracle使用job详解
- symbian文件和目录
- 【转】10年软件开发教会我最重要的10件事
- GCC's bacl-end & assemble emission (26)
- 设置java虚拟机内存
- 什么是Unicode编码?
- GCC后端及汇编发布(27)
- 使用UNICODE提高效率