GCC后端及汇编发布(26)
2011-06-11 09:40
363 查看
9.5.8.2.
数据初始化
在构建自动机之前,首先要分配资源。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
保存了自动机生成命令中“
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)
in
genautomata.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
return
result;
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)
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
}
静态变量
curr_state_graph_pass_num
将用于记录状态传递图
(
passing graph of states
)
的当前数目。
5986
static
void
5987
initiate_pass_states
(void)
in
genautomata.c
5988
{
5989
curr_state_graph_pass_num
= 0;
5990
}
而对于那些被
exclusion_set
所引用的指令,分配用于记录互斥及的位图资源。这里使用到了
obstack
机制的缓存,有关这部分的内容可以参考前端相关章节。总之,
obstack
是
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
}
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)
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_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
(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
}
6835
行的循环首先为所有的自动机创建
automaton
对象,这些对象具有如下定义。
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
在
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
return
first_ainsn;
6774
}
在
6762
行的
ainsn
具有如下定义。看到它与
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
};
某些
define_insn_reservation
模式可能具有多个功能单元预订计划,这意味着,从某个状态出发,通过不同的计划,将导致不同的状态。域
alt_states
将记录这些从同一个状态开始的不同的状态迁移。在当前版本中,如果在机器描述文件中没有定义自动机,所有
CPU
单元将被分配到单个默认自动机,否则分配在机器描述文件中指定。
units_to_automata_distr
执行这个分配。
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
}
实际上设置了单元对象的
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 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
}
我们前面已经看到,
define_insn_reservation
定义了每个周期中资源的使用情况,而且已经分配了位图来记录每条指令每个周期的
CPU
单元的使用情况。当调度指令时,它将显示该指令是否会与其他已经被调度的指令争夺相同的资源,这对于构建聪明、高效的调度器很重要。
create_alt_states
为替代构建数据,并且为每个替代填充位图。
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
}
define_insn_reservation
的
regexp
已经被转换,把“
|
”移到最外面,在替代内部不应该看到“
|
”,即替代内部不会包含替代。下面的函数基于这样的假设(参见
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
}
上面在
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
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
};
而在
1169
行,
state_t
被
typedef
为
state
*
,而
state
的定义如下。一开始,每个
define_insn_reservation
被与替代一一对应的
state
关联起来。在
1085
行,
state
中的
reservs
域记录了每个周期的资源使用情况。
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
则为每个替代构建当前周期的单元预订的位图(这里为周期
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
}
单元预订位图由
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_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
}
上面的
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_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
}
在构建了当前周期的位图之后,
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, "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
}
因此在这一步我们可以得到如下形式的数据。
First
与
last
在函数末尾就被删除了,不过链表保留了下来。
图
72
:等效类别指令的分组,阶段
1
相关文章推荐