GCC后端及汇编发布(27-续)

 

build_automaton (continued)

 

6418   if (progress_flag )

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

6420   ticker_off (&NDFA_time );

6421   count_states_and_arcs (automaton, &states_num, &arcs_num);

6422   automaton->NDFA_states_num = states_num;

6423   automaton->NDFA_arcs_num = arcs_num;

6424   ticker_on (&NDFA_to_DFA_time );

6425   if (progress_flag )

6426   {

6427     if (automaton->corresponding_automaton_decl == NULL)

6428       fprintf (stderr , "Make anonymous DFA");

6429     else

6430       fprintf (stderr , "Make DFA `%s'",

6431             automaton->corresponding_automaton_decl->name);

6432       fprintf (stderr , " (1 dot is 100 new states):");

6433   }

 

count_states_and_arcs 计算指定自动机的状态及迁移的数目。

 

6387 static void

6388 count_states_and_arcs (automaton_t automaton, int *states_num,            in genautomata.c

6389                      int *arcs_num)

6390 {

6391   curr_counted_states_num = 0;

6392   curr_counted_arcs_num = 0;

6393   pass_states (automaton, incr_states_and_arcs_nums );

6394   *states_num = curr_counted_states_num ;

6395   *arcs_num = curr_counted_arcs_num ;

6396 }

 

5978 static void

5979 pass_states (automaton_t automaton, void (*applied_func) (state_t state)) in genautomata.c

5980 {

5981   curr_state_graph_pass_num ++;

5982   pass_state_graph (automaton->start_state, applied_func );

5983 }

 

上面在 6394 行, curr_state_graph_pass_num 确保每个状态将仅会被计算一次。在下面的 5966 行我们可以看到这一点。

 

5961 static void

5962 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))  in genautomata.c

5963 {

5964   arc_t arc;

5965

5966   if (start_state->pass_num == curr_state_graph_pass_num )

5967     return ;

5968   start_state->pass_num = curr_state_graph_pass_num ;

5969   (*applied_func ) (start_state);

5970   for (arc = first_out_arc (start_state);

5971        arc != NULL;

5972        arc = next_out_arc (arc))

5973     pass_state_graph (arc->to_state, applied_func);

5974 }

 

对于每个状态,调用 incr_states_and_arcs_nums

 

6376 static void

6377 incr_states_and_arcs_nums (state_t state)                                              in genautomata.c

6378 {

6379   arc_t arc;

6380

6381   curr_counted_states_num ++;

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

6383     curr_counted_arcs_num ++;

6384 }

 

现在是时候把 NDFA 转换为 DFA 了。继续看 build_automaton

 

build_automaton (continued)

 

6434   NDFA_to_DFA (automaton);

6435   if (progress_flag )

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

6437   ticker_off (&NDFA_to_DFA_time );

6438   count_states_and_arcs (automaton, &states_num, &arcs_num);

6439   automaton->DFA_states_num = states_num;

6440   automaton->DFA_arcs_num = arcs_num;

6441   if (!no_minimization_flag )

6442   {

6443     ticker_on (&minimize_time );

6444     if (progress_flag )

6445     {

6446       if (automaton->corresponding_automaton_decl == NULL)

6447         fprintf (stderr, "Minimize anonymous DFA...");

6448       else

6449         fprintf (stderr , "Minimize DFA `%s'...",

6450               automaton->corresponding_automaton_decl->name);

6451     }

6452     minimize_DFA (automaton);

6453     if (progress_flag )

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

6455     ticker_off (&minimize_time );

6456     count_states_and_arcs (automaton, &states_num, &arcs_num);

6457     automaton->minimal_DFA_states_num = states_num;

6458     automaton->minimal_DFA_arcs_num = arcs_num;

6459   }

6460 }

 

在这里转换 NDFA DFA 的算法很简单。对于我们的例子,从 start_state 状态出发,可以迁移到 SA SB SC 状态。为了解决这个非确定性,我们构建了一个新状态 A’ A’ = {SA SB SC} – 这意味着它是一个在状态 S 下由类别为 (A|B|C) 的指令所触发的组合状态,它具有所有从状态 SA SB SC 出发的迁移。看到这个从状态 S A’ 的迁移,现在是确定性的。对所有具有非确定性迁移的状态重复上述步骤,直到不存在这样的状态。

为了更好地清楚这个算法,考虑以下自动机。

t74

74 NDFA 转换到 DFA 的例子,步骤 1

除了状态 S 以外,从每个状态出发,可以找到至少一个闭环 对于可行的芯片这是个必须条件,因为任意开放的节点意味着芯片将死在那一点上。并且注意到初始状态( S )不能有进入的迁移。这个自动机例子是一个 NDFA ,看到从状态 S 到状态 A1 的迁移是非确定性的。

t75

75 NDFA 转换到 DFA 的例子,步骤 2

在状态 A1 A2 上应用这个算法,我们可以得到上图。状态 A12 仍然是非确定性的,因为指令类别 ib 可以触发两个迁移。看到状态 A12 是从状态 A1 A2 构建的复合状态,现在我们不能确定其单元预订了。不过,我们不再需要单元预订,我们所需要的仅是状态及其之间的迁移。

t76

76 NDFA 转换到 DFA 的例子,步骤 3

又,合并状态 B1 B2 ,我们得到上图,不过这个状态仍然是非确定性的,因为 advance_cycle_insn_decl 将触发两个状态迁移。看到这个状态 B12 甚至不能在前面自动机生成过程中存在。

t77

77 NDFA 转换到 DFA 的例子,步骤 4

最后修改出的确定性自动机显示于上图。注意到这个确定性版本及非确定性版本,仅从指令发布机会的意义上而言,是相等的。

 

5917 static void

5918 NDFA_to_DFA (automaton_t automaton)

5919 {

5920   state_t start_state;

5921   state_t state;

5922   decl_t decl;

5923   vla_ptr_t state_stack;

5924   int i;

5925   int states_n;

5926

5927   VLA_PTR_CREATE (state_stack, 150, "state stack");

5928   /* Create the start state (empty state).  */

5929   start_state = automaton->start_state;

5930   start_state->it_was_placed_in_stack_for_DFA_forming = 1;

5931   VLA_PTR_ADD (state_stack, start_state);

5932   states_n = 1;

5933   while (VLA_PTR_LENGTH (state_stack) != 0)

5934   {

5935     state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);

5936     VLA_PTR_SHORTEN (state_stack, 1);

5937     form_arcs_marked_by_insn (state);

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

5939     {

5940       decl = description ->decls [i];

5941       if (decl->mode == dm_insn_reserv

5942           && create_composed_state

5943              (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,

5944               &state_stack))

5945       {

5946         states_n++;

5947         if (progress_flag && states_n % 100 == 0)

5948           fprintf (stderr , ".");

5949       }

5950     }

5951   }

5952   VLA_PTR_DELETE (state_stack);

5953 }

 

记住对于非确定性自动机,在我们上面的例子中,将评估 define_insn_reservation 中的每个替代;而对于确定性自动机,将仅评估第一个合格的替代。从这之后,这将形成很大的区别。事实上,当替代以确定性方式来处理时,构建出的自动机已经就是确定性的。

 

5787 static void

5788 form_arcs_marked_by_insn (state_t state)                                             in genautomata.c

5789 {

5790   decl_t decl;

5791   arc_t arc;

5792   int i;

5793

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

5795   {

5796     decl = description ->decls [i];

5797     if (decl->mode == dm_insn_reserv)

5798       DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;

5799   }

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

5801   {

5802     if (arc->insn == NULL)

5803       abort ();

5804     arc->next_arc_marked_by_insn

5805          = arc->insn->insn_reserv_decl->arcs_marked_by_insn;

5806     arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;

5807   }

5808 }

 

在跨越发布包含替代的指令类别的状态中,为了把这些特殊的迁移与其它确定性迁移区分开来, form_arcs_marked_by_insn 将通过 next_arc_marked_by_insn 域链接这些迁移(以 arc 的形式)。

在非确定性的例子中,对于 start_state 将得到如下。

对于指令类别( E|F

arcSF->next_arc_marked_by_insn = NULL (arcSF->to_state = stateSF)

arcSF->insn->insn_reserv_decl->arcs_marked_by_insn = arcSF

arcSE->next_arc_marked_by_insn = arcSF (arcSE->to_state = stateSE)

arcSE->insn->insn_reserv_decl->arcs_marked_by_insn = arcSE 最后的值)

对于指令类别( A|B|C

arcSC->next_arc_marked_by_insn = NULL (arcSC->to_state = stateSC)

arcSC->insn->insn_reserv_decl->arcs_marked_by_insn = arcSC

arcSB->next_arc_marked_by_insn = arcSC (arcSB->to_state = stateSB)

arcSB->insn->insn_reserv_decl->arcs_marked_by_insn = arcSB

arcSA->next_arc_marked_by_insn = arcSB (arcSA->to_state = stateSA)

arcSA->insn->insn_reserv_decl->arcs_marked_by_insn = arcSA 最后的值)

(注意到上面的两部分被 state arc next_out_arc 域链接起来)

在确定性的例子中,对于 start_state 将得到如下。

对于指令类别 A

arcSA->next_arc_marked_by_insn = NULL (arcSA->to_state = stateSA)

arcSA->insn->insn_reserv_decl->arcs_marked_by_insn = arcSA

对于指令类别 E

arcSE->next_arc_marked_by_insn = NULL (arcSE->to_state = stateSE)

arcSE->insn->insn_reserv_decl->arcs_marked_by_insn = arcSE

(注意到上面的两部分被 state arc next_out_arc 域链接起来)

显示在下图, insn (x1|x2|x3) 代表在 define_insn_reservation 中具有三个替代: x1 x2 x3 的指令类别。在图中两个 arcs_marked_by_insn 是对应不同 insn_reserv_decl 的域 对应 define_insn_reservations 模式的 decl

t78

78 构建 DFA ,阶段 2

现在在 state_stack 里仅是 state_start 。对于确定性自动机, create_composed_state 是简单的,因为 next_arc_marked_by_insn 总是 NULL (参见 5853 行的检查)。它将把在 5382 行获取的 to_state 压入 state_stack 并返回。现在在 state_stack 里,是 SA SE

在非确定性自动机的例子中,域 component_states 用于所谓的复合状态(例如,上图中的状态 A12 B12 xy )。对于具有替代 A B C 的指令类别来说,第一个参数 original_state start_state ,而第二个参数 arcs_marked_by_insn 指向上图中的 arcs_marked_by_insn ,它是 insn_reserv_decl – define_insn_reservation 模式的 decl ,中的域。

 

5814 static int

5815 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,      in genautomata.c

5816                      vla_ptr_t *state_stack)

5817 {

5818   state_t state;

5819   alt_state_t alt_state, curr_alt_state;

5820   alt_state_t new_alt_state;

5821   arc_t curr_arc;

5822   arc_t next_arc;

5823   state_t state_in_table;

5824   state_t temp_state;

5825   alt_state_t canonical_alt_states_list;

5826   int alts_number;

5827   int new_state_p = 0;

5828

5829   if (arcs_marked_by_insn == NULL)

5830     return new_state_p;

5831   if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)

5832     state = arcs_marked_by_insn->to_state;

5833   else

5834   {

5835     if (!ndfa_flag )

5836       abort ();

5837     /* Create composed state.  */

5838     state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);

5839     curr_alt_state = NULL;

5840     for (curr_arc = arcs_marked_by_insn;

5841         curr_arc != NULL;

5842         curr_arc = curr_arc->next_arc_marked_by_insn)

5843        if (curr_arc->to_state->component_states == NULL)

5844       {

5845         new_alt_state = get_free_alt_state ();

5846         new_alt_state->next_alt_state = curr_alt_state;

5847         new_alt_state->state = curr_arc->to_state;

5848         curr_alt_state = new_alt_state;

5849       }

5850       else

5851         for (alt_state = curr_arc->to_state->component_states;

5852             alt_state != NULL;

5853             alt_state = alt_state->next_sorted_alt_state)

5854         {

5855           new_alt_state = get_free_alt_state ();

5856           new_alt_state->next_alt_state = curr_alt_state;

5857           new_alt_state->state = alt_state->state;

5858           if (alt_state->state->component_states != NULL)

5859             abort ();

5860           curr_alt_state = new_alt_state;

5861         }

5862       /* There are not identical sets in the alt state list.  */

5863       canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);

5864       if (canonical_alt_states_list->next_sorted_alt_state == NULL)

5865       {

5866         temp_state = state;

5867         state = canonical_alt_states_list->state;

5868         free_state (temp_state);

5869       }

5870       else

5871       {

5872         state->component_states = canonical_alt_states_list;

5873         state_in_table = insert_state (state);

5874         if (state_in_table != state)

5875         {

5876           if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)

5877             abort ();

5878           free_state (state);

5879            state = state_in_table;

5880         }

5881         else

5882         {

5883           if (state->it_was_placed_in_stack_for_DFA_forming)

5884             abort ();

5885           new_state_p = 1;

5886           for (curr_alt_state = state->component_states;

5887               curr_alt_state != NULL;

5888               curr_alt_state = curr_alt_state->next_sorted_alt_state)

5889              for (curr_arc = first_out_arc (curr_alt_state->state);

5890                  curr_arc != NULL;

5891                   curr_arc = next_out_arc (curr_arc))

5892                add_arc (state, curr_arc->to_state, curr_arc->insn, 1);

5893         }

5894         arcs_marked_by_insn->to_state = state;

5895         for (alts_number = 0,

5896             curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;

5897             curr_arc != NULL;

5898             curr_arc = next_arc)

5899         {

5900           next_arc = curr_arc->next_arc_marked_by_insn;

5901           remove_arc (original_state, curr_arc);

5902           alts_number++;

5903         }

5904         arcs_marked_by_insn->state_alts = alts_number;

5905       }

5906   }

5907   if (!state->it_was_placed_in_stack_for_DFA_forming)

5908   {

5909     state->it_was_placed_in_stack_for_DFA_forming = 1;

5910     VLA_PTR_ADD (*state_stack, state);

5911   }

5912   return new_state_p;

5913 }

 

在我们例子中, curr_alt_state 是一个链表,形如: curr_alt_state(SA)->next_alt_state(SB)-> next_alt_state(SC) 。然后这个链表被传递给 uniq_sort_alt_states ,这个函数排序 alt_states_list ,并从这个链表中移去重复的 alt_state 。在这里,对于我们的非确定性例子,这个链表没有改变。

5864 行,如果 next_sorted_alt_state 不是 NULL ,那么在 5872 行的 state 是新构建的,它必然不出现在 state_table 里,因此我们进入 5882 行。在 create_composed_state 中构建的数据显示如下图。

t79

79 构建 DFA ,阶段 3

正如我们之前提及的,一旦构建了新状态,当前状态的所有替代的迁移目标,就被设置为这个新状态的迁移目标。然后当前状态,在理论上,可以确定性地迁移到这个新状态,注意到在图中 arcSA 被留下了,蓝色的域被修改了;而其它用于当前状态替代的 arc 都被移除了。接着,这个新状态将被压入 state_stack 。然后在这个状态上重复上面的步骤。直到 state_stack 中没有状态(即,没有状态具有非确定性迁移), NDFA_to_DFA 才退出。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值