GCC后端及汇编发布(28)

来源:互联网 发布:日本网友评价关口知宏 编辑:程序博客网 时间:2024/05/06 17:43

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, "nextiteration 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 equivnumbers 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_tstate)                                                         ingenautomata.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)                                           ingenautomata.c

6120 {

6121   state_t *state_ptr;

6122   state_tresult_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   returnresult_equiv_class;

6132 }

 

6224行,copy_equiv_classnext_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_classes6216行,变量odd_iteration_flag显示这是否是奇数次的迭代。这个标记控制equiv_class_num_1equiv_class_num_2的填充及切换。equiv_class_num_1equiv_class_num_2用于记录相同状态的数目。这个数目,对于每个相同状态集来说,是唯一的,并且被用作区分相同状态的集合。我们将在后面看到为什么需要这两个变量。

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

 

6141 static int

6142 partition_equiv_class (state_t*equiv_class_ptr, int odd_iteration_flag,     ingenautomata.c

6143                      vla_ptr_t *next_iteration_classes,

6144                      int *new_equiv_class_num_ptr)

6145 {

6146   state_tnew_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 classequivalence.  */

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 classequivalence.  */

6177           prev_state->next_equiv_class_state= next_state;

6178           /* Add currstate 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   returnpartition_p;

6198 }

 

在前面提及的算法中,在假定相同状态的集合中,其它状态将与第一个状态比较,以找出不同的状态。作为一个快速检测,如果两个状态的出口数目不相同,这两个状态可以被认为不相同。在partition_equiv_class6165行,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   returnstate_out_arcs_num;

6031 }

 

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

 

6082 static int

6083 state_is_differed (state_tstate, state_t another_state,                               ingenautomata.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 thepoint 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         return1;

6112     }

6113   return 0;

6114 }

 

stateanother_state等效,这意味着:

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

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

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

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

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

这个集合则又在partition_equiv_class6175行的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_1equiv_class_num_2(取决于odd_iteration_flag,用于区分不同的集合)。然后对每个新增的集合再次调用partition_equiv_class进行分解。

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

partition_equiv_class6192行,当某个等效集被处理之后,应该恢复对应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_DFA6364行,我们可以通过merge_states把等效状态合并起来形成最小化的自动机。

 

6247 static void

6248 merge_states (automaton_tautomaton, vla_ptr_t *equiv_classes)             ingenautomata.

6249 {

6250   state_t*equiv_class_ptr;

6251   state_t curr_state;

6252   state_t new_state;

6253   state_tfirst_class_state;

6254   alt_state_talt_states;

6255   alt_state_t alt_state, new_alt_state;

6256   arc_t curr_arc;

6257   arc_t next_arc;

6258

6259   /* Create statescorresponding 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 aremore 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 isimportant that alt states were sorted before and

6295         after merging to have the same queryingresults.  */

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 newarcs 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         /* Deleteoutput 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           /* Deletethe 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_statescreate_composed_state十分类似。在上面6261行的FOR循环中,对于每个等效类别的集合,一个新状态被建立,并且所有属于这个类别的状态被排序并链接入component_states。注意62756299行,对于每个状态,其equiv_class_state域被设置为新状态。

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

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

 

6480 static void

6481 enumerate_states (automaton_t automaton)                                                 ingenautomata.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_tstate)                                                        ingenautomata.c

6474 {

6475   state->order_state_num = curr_state_order_num;

6476   curr_state_order_num++;

6477 }

 

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

 

6584 static void

6585 set_insn_equiv_classes (automaton_tautomaton)                                   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 areincluded 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 inorder to make equivalence partition.  */

6601   pass_states (automaton, process_state_for_insn_equiv_partition);

6602   /* Enumerate equivclasses.  */

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_DFAminimize_DFA的处理,这个链表已经过时。因此,接下来需要process_state_for_insn_equiv_partition来重新划分等效的指令集。

 

6562 static void

6563 process_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 ofthe 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_arcnext_out_arc都返回从state出发的迁移(由arc代表),并且arc与(source statetarget stateinsn)对一一对应,检查由上面6597行的process_insn_equiv_classarc为单位进行。

 

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 ofainsns 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

原创粉丝点击