GCC后端及汇编发布(28)

9.5.8.5.    有限状态自动机的最小化

用来把 NDFA 转换到 DFA 的算法不保证生成最小的 DFA 。因此,需要尝试最小化所产生的自动机。在这里最小化的算法是,首先假定所有的状态都是相同的,然后一个个地访问这些状态,并选出那些与第一个状态不同的状态。把这些状态放入另一个集合中,再次假定它们是相同的。然后重复上述步骤访问这些状态,直到在假定相同的集合中找不出不同的状态。接着合并相同的状态来产生最小自动机。

 

6357 static void

6358 minimize_DFA ( automaton_t automaton)                                              in genautomata.c

6359 {

6360   vla_ptr_t equiv_classes;

6361

6362   VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");

6363   evaluate_equiv_classes (automaton, &equiv_classes);

6364   merge_states (automaton, &equiv_classes);

6365   pass_states (automaton, set_new_cycle_flags);

6366   VLA_PTR_DELETE (equiv_classes);

6367 }

 

6363 行的 evaluate_equiv_class ,如上面所说的那样,把状态组合为相同的集合。

 

6201 static void

6202 evaluate_equiv_classes (automaton_t automaton, vla_ptr_t *equiv_classes) in genautomata.c

6203 {

6204   state_t new_equiv_class;

6205   int new_equiv_class_num;

6206   int odd_iteration_flag;

6207   int finish_flag;

6208   vla_ptr_t next_iteration_classes;

6209   state_t *equiv_class_ptr;

6210   state_t *state_ptr;

6211

6212   VLA_PTR_CREATE (all_achieved_states , 1500, "all achieved states");

6213   pass_states (automaton, add_achieved_state );

6214   new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states ),

6215                                 VLA_PTR_LENGTH (all_achieved_states ));

6216   odd_iteration_flag = 0;

6217   new_equiv_class_num = 1;

6218   VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");

6219   VLA_PTR_ADD (next_iteration_classes, new_equiv_class);

6220   do

6221   {

6222     odd_iteration_flag = !odd_iteration_flag;

6223     finish_flag = 1;

6224     copy_equiv_class (equiv_classes, &next_iteration_classes);

6225     /* Transfer equiv numbers for the next iteration.  */

6226     for (state_ptr = VLA_PTR_BEGIN (all_achieved_states );

6227         state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states );

6228         state_ptr++)

6229       if (odd_iteration_flag)

6230         (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;

6231       else

6232         (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;

6233     for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);

6234         equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);

6235         equiv_class_ptr++)

6236       if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,

6237                   &next_iteration_classes,

6238                   &new_equiv_class_num))

6239         finish_flag = 0;

6240   }

6241   while (!finish_flag);

6242   VLA_PTR_DELETE (next_iteration_classes);

6243   VLA_PTR_DELETE (all_achieved_states );

6244 }

 

6213 行的 pass_states 将遍历这个自动机的状态,并通过 add_achieved_state 把状态加入 all_achieved_states

 

5998 static void

5999 add_achieved_state (state_t state)                                                         in genautomata.c

6000 {

6001   VLA_PTR_ADD (all_achieved_states , state);

6002 }

 

然后在 6214 行, init_equiv_class 通过 next_equiv_class_state 域,以反序,链接起这些状态。它只是假定所有的状态都是相等的,因为 next_equiv_class_state 总是应该链接相同的状态。在 6131 行, result_equiv_class 指向 pass_states 所访问的最后的状态。这个值在 6214 行被保存在 next_iteration_classes 里。

 

6118 static state_t

6119 init_equiv_class (state_t *states, int states_num)                                           in genautomata.c

6120 {

6121   state_t *state_ptr;

6122   state_t result_equiv_class;

6123

6124   result_equiv_class = NULL;

6125   for (state_ptr = states; state_ptr < states + states_num; state_ptr++)

6126   {

6127     (*state_ptr)->equiv_class_num_1 = 1;

6128     (*state_ptr)->next_equiv_class_state = result_equiv_class;

6129     result_equiv_class = *state_ptr;

6130   }

6131   return result_equiv_class;

6132 }

 

6224 行, copy_equiv_class next_iteration_classes 拷贝相等状态的集合。

 

6049 static void

6050 copy_equiv_class (vla_ptr_t *to, const vla_ptr_t *from)                         in genautomata.c

6051 {

6052   state_t *class_ptr;

6053

6054   VLA_PTR_NULLIFY (*to);

6055   for (class_ptr = VLA_PTR_BEGIN (*from);

6056        class_ptr <= (state_t *) VLA_PTR_LAST (*from);

6057        class_ptr++)

6058     VLA_PTR_ADD (*to, *class_ptr);

6059 }

 

evaluate_equiv_classes 6216 行,变量 odd_iteration_flag 显示这是否是奇数次的迭代。这个标记控制 equiv_class_num_1 equiv_class_num_2 的填充及切换。 equiv_class_num_1 equiv_class_num_2 用于记录相同状态的数目。这个数目,对于每个相同状态集来说,是唯一的,并且被用作区分相同状态的集合。我们将在后面看到为什么需要这两个变量。

evaluate_equiv_classes 6236 行, partition_equiv_class 把初始的假定相同状态的集合分裂为正真相同状态的(多个)集合。

 

6141 static int

6142 partition_equiv_class (state_t *equiv_class_ptr, int odd_iteration_flag,     in genautomata.c

6143                      vla_ptr_t *next_iteration_classes,

6144                      int *new_equiv_class_num_ptr)

6145 {

6146   state_t new_equiv_class;

6147   int partition_p;

6148   state_t first_state;

6149   state_t curr_state;

6150   state_t prev_state;

6151   state_t next_state;

6152   int out_arcs_num;

6153

6154   partition_p = 0;

6155   if (*equiv_class_ptr == NULL)

6156     abort ();

6157   for (first_state = *equiv_class_ptr;

6158       first_state != NULL;

6159       first_state = new_equiv_class)

6160   {

6161     new_equiv_class = NULL;

6162     if (first_state->next_equiv_class_state != NULL)

6163     {

6164        /* There are more one states in the class equivalence.  */

6165       out_arcs_num = set_out_arc_insns_equiv_num (first_state,

6166                            odd_iteration_flag);

6167       for (prev_state = first_state,

6168               curr_state = first_state->next_equiv_class_state;

6169           curr_state != NULL;

6170           curr_state = next_state)

6171       {

6172         next_state = curr_state->next_equiv_class_state;

6173         if (state_is_differed (curr_state, first_state, out_arcs_num,

6174                          odd_iteration_flag))

6175         {

6176            /* Remove curr state from the class equivalence.  */

6177           prev_state->next_equiv_class_state = next_state;

6178           /* Add curr state to the new class equivalence.  */

6179           curr_state->next_equiv_class_state = new_equiv_class;

6180           if (new_equiv_class == NULL)

6181             (*new_equiv_class_num_ptr)++;

6182           if (odd_iteration_flag)

6183             curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;

6184           else

6185             curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;

6186           new_equiv_class = curr_state;

6187           partition_p = 1;

6188         }

6189         else

6190            prev_state = curr_state;

6191       }

6192       clear_arc_insns_equiv_num (first_state);

6193     }

6194     if (new_equiv_class != NULL)

6195       VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);

6196   }

6197   return partition_p;

6198 }

 

在前面提及的算法中,在假定相同状态的集合中,其它状态将与第一个状态比较,以找出不同的状态。作为一个快速检测,如果两个状态的出口数目不相同,这两个状态可以被认为不相同。在 partition_equiv_class 6165 行, set_out_arc_insns_equiv_num 找出集合中第一个状态的出口的数目。同时这个函数还会设置 arc->insn->insn_reserv_decl->equiv_class_num ,及 arc->insn->insn_reserv_decl->state_alts ,以显示已经得到处理 arc 。注意,这里 arc->insn ,已经不代表特定指令类别,它的意义仅在这里的处理中得到体现。

 

6008 static int

6009 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)        in genautomata.c

6010 {

6011   int state_out_arcs_num;

6012   arc_t arc;

6013

6014   state_out_arcs_num = 0;

6015   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))

6016   {

6017     if (arc->insn->insn_reserv_decl->equiv_class_num != 0

6018        || arc->insn->insn_reserv_decl->state_alts != 0)

6019       abort ();

6020     state_out_arcs_num++;

6021     arc->insn->insn_reserv_decl->equiv_class_num

6022           = (odd_iteration_flag

6023               ? arc->to_state->equiv_class_num_1

6024                : arc->to_state->equiv_class_num_2);

6025     arc->insn->insn_reserv_decl->state_alts = arc->state_alts;

6026     if (arc->insn->insn_reserv_decl->equiv_class_num == 0

6027         || arc->insn->insn_reserv_decl->state_alts <= 0)

6028       abort ();

6029   }

6030   return state_out_arcs_num;

6031 }

 

自动机现在是 DFA ,因此在 6015 行的 FOR 循环中,每个 arc 必须关联不同的状态。在 6021 行,我们设置与这个状态关联的,所有 arc equiv_class_num ,这将被用作判断状态相等的证据之一。

 

6082 static int

6083 state_is_differed (state_t state, state_t another_state,                               in genautomata.c

6084               int another_state_out_arcs_num, int odd_iteration_flag)

6085 {

6086   arc_t arc;

6087   int state_out_arcs_num;

6088   int i, presence1_p, presence2_p;

6089

6090   state_out_arcs_num = 0;

6091   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))

6092   {

6093     state_out_arcs_num++;

6094     if ((odd_iteration_flag

6095           ? arc->to_state->equiv_class_num_1

6096            : arc->to_state->equiv_class_num_2)

6097              != arc->insn->insn_reserv_decl->equiv_class_num

6098        || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))

6099       return 1;

6100   }

6101   if (state_out_arcs_num != another_state_out_arcs_num)

6102     return 1;

6103   /* Now we are looking at the states with the point of view of query

6104     units.  */

6105   for (i = 0; i < description ->units_num; i++)

6106     if (units_array [i]->query_p)

6107     {

6108       presence1_p = first_cycle_unit_presence (state, i);

6109       presence2_p = first_cycle_unit_presence (another_state, i);

6110       if ((presence1_p && !presence2_p) || (!presence1_p && presence2_p))

6111         return 1;

6112     }

6113   return 0;

6114 }

 

state another_state 等效,这意味着:

1)    它们到达相同的目标状态的集合

2)    它们使用相同的功能单元的集合

3)    它们有等效的源状态的集合

state_is_differed 确保前两点,而 evaluate_equiv_classes 中对分解集合的反复迭代,使第三点得到保证。这也是为什么在 init_equiv_class 中要以倒序排序状态,这样就从最后的目标状态开始,向源状态回溯。

如果状态被判定为不相同,返回到 partition_equiv_class 之后,所有与 first_state 不同的状态都放入同一个集合,同时共享同一个 equiv_class_num 。注意 6182 6185 行的赋值,在 odd_iteration_flag true 时,赋值的是 equiv_class_num_2 (初始值为 2 ),与上面正好相反(此时,当前使用的是 equiv_class_num_1 )。

这个集合则又在 partition_equiv_class 6175 行的 FOR 循环处理(它在 6159 行赋予 first_state )。这个集合继续依照第一个状态进行分解(注意对 set_out_arc_insns_equiv_num 的调用),因为在这个过程中 odd_iteration_flag 维持不变,因此每个不同的集合有递增的 equiv_class_num_2 (假设使用的是 equiv_class_num_1 ,它也在这个过程中维持不变)。

返回 evaluate_equiv_classes ,对新增的集合更新 equiv_class_num_1 equiv_class_num_2 (取决于 odd_iteration_flag ,用于区分不同的集合)。然后对每个新增的集合再次调用 partition_equiv_class 进行分解。

这个过程一直重复,直到没有再划分出新的集合为止。

partition_equiv_class 6192 行,当某个等效集被处理之后,应该恢复对应 arc 的域。使得这个集合与其它部分分离开来( state_is_differed 总是在 6009 行返回 1 )。

 

6035 static void

6036 clear_arc_insns_equiv_num (state_t state)                                             in genautomata.c

6037 {

6038   arc_t arc;

6039

6040   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))

6041   {

6042     arc->insn->insn_reserv_decl->equiv_class_num = 0;

6043     arc->insn->insn_reserv_decl->state_alts = 0;

6044   }

6045 }

 

在找出等效类别集合后,在 minimize_DFA 6364 行,我们可以通过 merge_states 把等效状态合并起来形成最小化的自动机。

 

6247 static void

6248 merge_states (automaton_t automaton, vla_ptr_t *equiv_classes)             in genautomata.

6249 {

6250   state_t *equiv_class_ptr;

6251   state_t curr_state;

6252   state_t new_state;

6253   state_t first_class_state;

6254   alt_state_t alt_states;

6255   alt_state_t alt_state, new_alt_state;

6256   arc_t curr_arc;

6257   arc_t next_arc;

6258

6259   /* Create states corresponding to equivalence classes containing two

6260     or more states.  */

6261   for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);

6262       equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);

6263       equiv_class_ptr++)

6264     if ((*equiv_class_ptr)->next_equiv_class_state != NULL)

6265     {

6266       /* There are more one states in the class equivalence.  */

6267       /* Create new compound state.  */

6268       new_state = get_free_state (0, automaton);

6269       alt_states = NULL;

6270       first_class_state = *equiv_class_ptr;

6271       for (curr_state = first_class_state;

6272           curr_state != NULL;

6273           curr_state = curr_state->next_equiv_class_state)

6274       {

6275         curr_state->equiv_class_state = new_state;

6276         if (curr_state->component_states == NULL)

6277         {

6278           new_alt_state = get_free_alt_state ();

6279           new_alt_state->state = curr_state;

6280           new_alt_state->next_alt_state = alt_states;

6281           alt_states = new_alt_state;

6282         }

6283         else

6284           for (alt_state = curr_state->component_states;

6285               alt_state != NULL;

6286               alt_state = alt_state->next_sorted_alt_state)

6287           {

6288             new_alt_state = get_free_alt_state ();

6289             new_alt_state->state = alt_state->state;

6290             new_alt_state->next_alt_state = alt_states;

6291             alt_states = new_alt_state;

6292           }

6293       }

6294       /* Its is important that alt states were sorted before and

6295         after merging to have the same querying results.  */

6296       new_state->component_states = uniq_sort_alt_states (alt_states);

6297     }

6298     else

6299       (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;

6300     for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);

6301         equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);

6302         equiv_class_ptr++)

6303       if ((*equiv_class_ptr)->next_equiv_class_state != NULL)

6304       {

6305         first_class_state = *equiv_class_ptr;

6306         /* Create new arcs output from the state corresponding to

6307            equiv class.  */

6308         for (curr_arc = first_out_arc (first_class_state);

6309             curr_arc != NULL;

6310             curr_arc = next_out_arc (curr_arc))

6311           add_arc (first_class_state->equiv_class_state,

6312                   curr_arc->to_state->equiv_class_state,

6313                   curr_arc->insn, curr_arc->state_alts);

6314         /* Delete output arcs from states of given class equivalence.  */

6315         for (curr_state = first_class_state;

6316             curr_state != NULL;

6317             curr_state = curr_state->next_equiv_class_state)

6318         {

6319           if (automaton->start_state == curr_state)

6320             automaton->start_state = curr_state->equiv_class_state;

6321           /* Delete the state and its output arcs.  */

6322           for (curr_arc = first_out_arc (curr_state);

6323               curr_arc != NULL;

6324               curr_arc = next_arc)

6325           {

6326             next_arc = next_out_arc (curr_arc);

6327             free_arc (curr_arc);

6328           }

6329         }

6330       }

6331       else

6332       {

6333           /* Change `to_state' of arcs output from the state of given

6334            equivalence class.  */

6335         for (curr_arc = first_out_arc (*equiv_class_ptr);

6336             curr_arc != NULL;

6337             curr_arc = next_out_arc (curr_arc))

6338           curr_arc->to_state = curr_arc->to_state->equiv_class_state;

6339       }

6340 }

 

merge_states create_composed_state 十分类似。在上面 6261 行的 FOR 循环中,对于每个等效类别的集合,一个新状态被建立,并且所有属于这个类别的状态被排序并链接入 component_states 。注意 6275 6299 行,对于每个状态,其 equiv_class_state 域被设置为新状态。

接着在 6300 行的 FOR 循环里,首先构建用于来 / 往新状态的 arc (由 6308 行的 FOR 循环处理,注意到 add_arc 将不会构建 arc 如果它已经被构建了),然后把来 / 往过时状态的 arc 移除。

在合并后, build_automaton 返回到 create_automata enumerate_states 找出状态的总数。

 

6480 static void

6481 enumerate_states (automaton_t automaton)                                                  in genautomata.c

6482 {

6483   curr_state_order_num = 0;

6484   pass_states (automaton, set_order_state_num );

6485   automaton->achieved_states_num = curr_state_order_num ;

6486 }

 

6472 static void

6473 set_order_state_num ( state_t state)                                                        in genautomata.c

6474 {

6475   state->order_state_num = curr_state_order_num ;

6476   curr_state_order_num ++;

6477 }

 

我们已经构建了最小化的 DFA ,所有的等效状态都已经被合并。现在我们需要按等效状态类别来分组指令类别,因为属于同一个等效类别状态的指令类别可以以相同的方式处理。这在 create_automata 6893 行的 set_insn_equiv_classes 来完成。

 

6584 static void

6585 set_insn_equiv_classes (automaton_t automaton)                                   in genautomata.c

6586 {

6587   ainsn_t ainsn;

6588   ainsn_t first_insn;

6589   ainsn_t curr_insn;

6590   ainsn_t cyclic_insn_list;

6591   ainsn_t insn_with_same_reservs;

6592   int equiv_classes_num;

6593

6594   /* All insns are included in one equivalence class.  */

6595   cyclic_insn_list = NULL;

6596   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)

6597     if (ainsn->first_insn_with_same_reservs)

6598       cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,

6599                                                  cyclic_insn_list);

6600   /* Process insns in order to make equivalence partition.  */

6601   pass_states (automaton, process_state_for_insn_equiv_partition );

6602   /* Enumerate equiv classes.  */

6603   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)

6604      /* Set undefined value.  */

6605     ainsn->insn_equiv_class_num = -1;

6606   equiv_classes_num = 0;

6607   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)

6608     if (ainsn->insn_equiv_class_num < 0)

6609     {

6610       first_insn = ainsn;

6611       if (!first_insn->first_insn_with_same_reservs)

6612         abort ();

6613       first_insn->first_ainsn_with_given_equialence_num = 1;

6614       curr_insn = first_insn;

6615       do

6616       {

6617         for (insn_with_same_reservs = curr_insn;

6618             insn_with_same_reservs != NULL;

6619             insn_with_same_reservs

6620                    = insn_with_same_reservs->next_same_reservs_insn)

6621           insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;

6622         curr_insn = curr_insn->next_equiv_class_insn;

6623       }

6624       while (curr_insn != first_insn);

6625       equiv_classes_num++;

6626     }

6627   automaton->insn_equiv_classes_num = equiv_classes_num;

6628 }

 

看到在 form_ainsn_with_same_reservs 中,如果这个 ainsn 是所有具有相同单元预订对象的第一个,或者这个指令是单独构成一个集合的 advance_cycle_insn_decl ,设置 first_insn_with_same_reservs 域。在 6598 行, insert_ainsn_into_equiv_class 把这些指令类别通过 next_equiv_class_insn 链接在一起。

 

6495 static ainsn_t

6496 insert_ainsn_into_equiv_class (ainsn_t ainsn,                                         in genautomata.c

6497                      ainsn_t cyclic_equiv_class_insn_list)

6498 {

6499   if (cyclic_equiv_class_insn_list == NULL)

6500     ainsn->next_equiv_class_insn = ainsn;

6501   else

6502   {

6503     ainsn->next_equiv_class_insn

6504          = cyclic_equiv_class_insn_list->next_equiv_class_insn;

6505     cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;

6506   }

6507   return ainsn;

6508 }

 

在这一步,我们得到如下数据结构。图中红色循环链表中的节点代表不同的等效指令类别列表,而蓝色的链表则由是等效的指令类别构成的。

t80

80 :等效类别指令的分组,阶段 2

由于 next_same_reservs_insn 所形成的链表是由 form_ainsn_with_same_reservs 构建的,此后经由 NDFA_to_DFA minimize_DFA 的处理,这个链表已经过时。因此,接下来需要 process_state_for_insn_equiv_partition 来重新划分等效的指令集。

 

6562 static void

6563 pr ocess_state_for_insn_equiv_partition ( state_t state)                             in genautomata.c

6564 {

6565   arc_t arc;

6566   arc_t *insn_arcs_array;

6567   int i;

6568   vla_ptr_t insn_arcs_vect;

6569

6570   VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");

6571   VLA_PTR_EXPAND (insn_arcs_vect, description ->insns_num);

6572   insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);

6573   /* Process insns of the arcs.  */

6574   for (i = 0; i < description ->insns_num; i++)

6575     insn_arcs_array [i] = NULL;

6576   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))

6577     insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;

6578   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))

6579     process_insn_equiv_class (arc->insn, insn_arcs_array);

6580   VLA_PTR_DELETE (insn_arcs_vect);

6581 }

 

记得 first_out_arc next_out_arc 都返回从 state 出发的迁移(由 arc 代表),并且 arc 与( source state target state insn )对一一对应,检查由上面 6597 行的 process_insn_equiv_class arc 为单位进行。

 

6531 static void

6532 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)

6533 {

6534   ainsn_t next_insn;

6535   ainsn_t curr_insn;

6536   ainsn_t cyclic_insn_list;

6537   arc_t arc;

6538

6539   if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)

6540     abort ();

6541   curr_insn = ainsn;

6542   /* New class of ainsns which are not equivalent to given ainsn.  */

6543   cyclic_insn_list = NULL;

6544   do

6545   {

6546     next_insn = curr_insn->next_equiv_class_insn;

6547     arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];

6548     if (arc == NULL

6549         || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state

6550              != arc->to_state))

6551     {

6552       delete_ainsn_from_equiv_class (curr_insn);

6553       cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,

6554                                      cyclic_insn_list);

6555     }

6556     curr_insn = next_insn;

6557   }

6558   while (curr_insn != ainsn);

6559 }

 

我们知道使用相同的单元预订是作为等效指令类别的必要条件,因此由 minimize_DFA 得到的等效指令类别集合,必然不会跨越一条以上在 form_ainsn_with_same_reservs 中构建的 next_same_reservs_insn 链表,相反这些链表可能会分解成多个链表。那么在 set_insn_equiv_classes 中,余下的代码重新设置 equiv_classes_num

t81

81 :等效类别指令的分组,阶段 3

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值