GCC后端及汇编发布(37)

9.6.4.2.    输出接口函数

现在所有的表已经就绪。事实上,我们可以看到状态与触发迁移的指令间的关系,以及指令间资源竞争关系(通过发布延迟)都被封装入这些表中。同时指令间潜在的依赖关系(通过阻塞代价及就绪代价),以及某个branch/jump指令输出的delay slot的细节,都已经以属性提取函数的形式,连同其它工具生成的属性访问器,输出了。

现在可以为流水线危险识别器生成接口了。

 

write_automata (continued)

 

9885   output_chip_definitions ();

9886   output_max_insn_queue_index_def();

9887   output_internal_min_issue_delay_func();

9888   output_internal_trans_func();

9889   /* Cache of insndfa codes: */

9890   fprintf (output_file, "\nstatic int *%s;\n",DFA_INSN_CODES_VARIABLE_NAME);

9891   fprintf (output_file, "\nstatic int %s;\n\n",

9892          DFA_INSN_CODES_LENGTH_VARIABLE_NAME);

9893   output_dfa_insn_code_func();

9894   output_trans_func();

9895   fprintf (output_file, "\n#if %s\n\n",AUTOMATON_STATE_ALTS_MACRO_NAME);

9896   output_internal_state_alts_func();

9897   output_state_alts_func();

9898   fprintf (output_file, "\n#endif /* #if %s*/\n\n",

9899         AUTOMATON_STATE_ALTS_MACRO_NAME);

9900   output_min_issue_delay_func();

9901   output_internal_dead_lock_func();

9902   output_dead_lock_func();

9903   output_size_func();

9904   output_internal_reset_func();

9905   output_reset_func();

9906   output_min_insn_conflict_delay_func();

9907   output_internal_insn_latency_func();

9908   output_insn_latency_func();

9909   output_print_reservation_func();

9910   /* Output functionget_cpu_unit_code.  */

9911   fprintf (output_file, "\n#if %s\n\n",CPU_UNITS_QUERY_MACRO_NAME);

9912   output_get_cpu_unit_code_func();

9913   output_cpu_unit_reservation_p();

9914   fprintf (output_file, "\n#endif /* #if %s*/\n\n",

9915          CPU_UNITS_QUERY_MACRO_NAME);

9916   output_dfa_clean_insn_cache_func();

9917   output_dfa_start_func();

9918   output_dfa_finish_func();

9.6.4.2.1.           定义伪芯片

为了找出下一个运行的合适的指令,流水线危险器维护一个伪CPU来模拟指令的发布,这由output_chip_definitions来定义。

 

7413 static void

7414 output_chip_definitions (void)                                                             in genautomata.c

7415 {

7416   automaton_tautomaton;

7417

7418   fprintf (output_file, "struct %s\n{\n",CHIP_NAME);

7419   for(automaton = description->first_automaton;

7420       automaton != NULL;

7421       automaton = automaton->next_automaton)

7422   {

7423     fprintf (output_file, "  ");

7424     output_state_member_type (output_file,automaton);

7425     fprintf (output_file, " ");

7426     output_chip_member_name (output_file,automaton);

7427     fprintf (output_file, ";\n");

7428   }

7429   fprintf (output_file, "};\n\n");

7430 #if 0

7431   fprintf (output_file, "static struct %s%s;\n\n", CHIP_NAME, CHIP_NAME);

7432 #endif

7433 }

 

在这里,输出以下内容(绿色部分不是工具产生的),假定自动机的状态的数目不会超过65536,并且自动机没有命名。

 

       struct DFA_chip

       {

         unsigned short automaton_state_0;

      …                             // variables for other automatons

       }

 

这个伪CPU的定义十分简单,它仅包含保存自动机状态的变量。识别器的复杂性隐藏在状态及连接它们的arc后面(参考自动机的生成)。

9.6.4.2.2.           输出函数internal_min_issue_delay

虽然观点不一样,类似于define_function_unit,确定给定指令的发布延迟也是自动机同样重要的部分。在这里,首先找出在该系统中最大的休眠时间。这很简单。

 

8110 static void

8111 output_max_insn_queue_index_def (void)                                             in genautomata.c

8112 {

8113   int i, max, latency;

8114   decl_t decl;

8115

8116  max = description->max_insn_reserv_cycles;

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

8118   {

8119     decl = description->decls [i];

8120     if(decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)

8121     {

8122       latency = DECL_INSN_RESERV(decl)->default_latency;

8123       if (latency > max)

8124         max = latency;

8125    }

8126    else if (decl->mode == dm_bypass)

8127     {

8128       latency = DECL_BYPASS (decl)->latency;

8129       if (latency > max)

8130         max = latency;

8131    }

8132   }

8133   for (i = 0; (1 << i) <= max; i++)

8134    ;

8135   if(i < 0)

8136     abort ();

8137   fprintf (output_file, "\nint max_insn_queue_index =%d;\n\n", (1 << i) - 1);

8138 }

 

在8122行,default_latency被定义在define_insn_reservation模式里,来描述指令的休眠时间。另外,我们已经看到define_bypass被用来描述给定指令对(instruction pair)休眠时间的例外。output_max_insn_queue_index_def找出已经遇到的最大休眠时间并输出这个值。

 

8235 static void

8236 output_internal_min_issue_delay_func (void)                                        ingenautomata.c

8237 {

8238   fprintf (output_file,

8239          "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",

8240          INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,

8241          CHIP_NAME, CHIP_PARAMETER_NAME);

8242   fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n  int %s = -1;\n",

8243          TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);

8244   fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);

8245   output_insn_code_cases(output_automata_list_min_issue_delay_code);

8246   fprintf (output_file,

8247         "\n    default:\n      %s = -1;\n      break;\n    }\n",

8248         RESULT_VARIABLE_NAME);

8249   fprintf (output_file, "  return %s;\n", RESULT_VARIABLE_NAME);

8250   fprintf (output_file, "}\n\n");

8251 }

 

在输出发布延迟表一节,我们已经输出了表示发布延迟的表。对于某些现代CPU,它们包含一些可以并行执行的功能单元,或换句话来说多个指令可能可以被同时发布。在机器描述文件中,这样的功能单元将被定义作自动机。那么在自动机的生成一节,状态及表示状态迁移的arc,已经为这些自动机所创建。因为这些自动机可能被同时运行,所以给定指令的最小发布延迟应该是,该指令在这些自动机上最小发布延迟中最大的一个。

 

8134 static void

8135 output_insn_code_cases (void(*output_automata_list_code)                    in genautomata.c

8136                     (automata_list_el_t))

8137 {

8138   decl_t decl, decl2;

8139  int i, j;

8140

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

8142   {

8143     decl = description->decls [i];

8144     if (decl->mode == dm_insn_reserv)

8145       DECL_INSN_RESERV (decl)->processed_p =FALSE;

8146   }

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

8148   {

8149     decl = description->decls [i];

8150     if (decl->mode == dm_insn_reserv

8151        && !DECL_INSN_RESERV(decl)->processed_p)

8152     {

8153       for (j =i; j < description->decls_num;j++)

8154       {

8155         decl2 = description->decls [j];

8156         if (decl2->mode == dm_insn_reserv

8157           && (DECL_INSN_RESERV(decl2)->important_automata_list

8158                == DECL_INSN_RESERV(decl)->important_automata_list))

8159         {

8160           DECL_INSN_RESERV(decl2)->processed_p = TRUE;

8161           fprintf (output_file, "    case %d: /* %s */\n",

8162                 DECL_INSN_RESERV(decl2)->insn_num,

8163                 DECL_INSN_RESERV(decl2)->name);

8164         }

8165       }

8166       (*output_automata_list_code)

8167           (DECL_INSN_RESERV(decl)->important_automata_list);

8168     }

8169   }

8170 }

 

在8157行,important_automata_list记录了目前为止所产生的,涉及该指令的自动机。因此在8147及8153行的FOR循环找出在同一个自动机列表中的所有的指令,作为case的操作数。

 

8184 static void

8185 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list) in genautomata.c

8186 {

8187   automata_list_el_t el;

8188   automaton_t automaton;

8189

8190   for (el = automata_list; el != NULL; el =el->next_automata_list_el)

8191   {

8192     automaton = el->automaton;

8193     fprintf (output_file, "\n      %s = ", TEMPORARY_VARIABLE_NAME);

8194     output_min_issue_delay_vect_name (output_file,automaton);

8195     fprintf (output_file,

8196              (automaton->min_issue_delay_table_compression_factor != 1

8197           ? " [(" : " ["));

8198     output_translate_vect_name (output_file,automaton);

8199     fprintf (output_file, " [%s] + ",INTERNAL_INSN_CODE_NAME);

8200     fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);

8201     output_chip_member_name (output_file,automaton);

8202     fprintf (output_file, " * %d",automaton->insn_equiv_classes_num);

8203     if(automaton->min_issue_delay_table_compression_factor == 1)

8204       fprintf (output_file, "];\n");

8205     else

8206     {

8207       fprintf (output_file, ") /%d];\n",

8208             automaton->min_issue_delay_table_compression_factor);

8209       fprintf (output_file, "      %s = (%s >> (8 - (",

8210             TEMPORARY_VARIABLE_NAME,TEMPORARY_VARIABLE_NAME);

8211       output_translate_vect_name (output_file,automaton);

8212       fprintf

8213           (output_file, " [%s] %% %d + 1) * %d)) &%d;\n",

8214           INTERNAL_INSN_CODE_NAME,

8215          automaton->min_issue_delay_table_compression_factor,

8216           8 /automaton->min_issue_delay_table_compression_factor,

8217           (1 << (8 / automaton->min_issue_delay_table_compression_factor))

8218             - 1);

8219     }

8220     if (el == automata_list)

8221       fprintf (output_file, "      %s = %s;\n",

8222             RESULT_VARIABLE_NAME,TEMPORARY_VARIABLE_NAME);

8223     else

8224    {

8225       fprintf (output_file, "      if (%s > %s)\n",

8226             TEMPORARY_VARIABLE_NAME,RESULT_VARIABLE_NAME);

8227       fprintf (output_file, "        %s = %s;\n",

8228             RESULT_VARIABLE_NAME,TEMPORARY_VARIABLE_NAME);

8229     }

8230   }

8231   fprintf (output_file, "      break;\n\n");

8232 }

 

对于出现在同一个自动机集合中的指令,output_automata_list_min_issue_delay_code将输出以下的代码(假定min_issue_delay_table_compression_factor不等于1)。现在我们得到如下internal_min_issue_delay的定义(红色部分不是工具输出的)。

 

1     static int

2     internal_min_issue_delay (int insn_code,struct DFA_chip * chip ATTRIBUTE_UNUSED)

3     {

4       int temp ATTRIBUTE_UNUSED;

5       int res =-1;

6    

7       switch (insn_code)

8       {

9        case insn-x:             // for instructions reserve same automaton list.

10        …

11       case insn-y:

12        // forfirst automaton

13         temp = min_issue_delay_0[(translate_0[insn_code] +

14            chip->automaton_state_0 * `insn_equiv_classes_num0`)/

15            `min_issue_delay_table_compression_factor0`];

16         temp = (temp >> (8–(translate_0[insn_code]%%`min_issue_delay_table_compression_factor0`

17               + 1) * 8 / `min_issue_delay_table_compression_factor0`))& -1;

18         res =temp;

19          

20        // for other automaton n, not appear in ourassuming example

21         temp =min_issue_delay_n [(translate_n[insn_code] +

22            chip->automaton_state_n * `insn_equiv_classes_numn`)/

23            `min_issue_delay_table_compression_factorn`];

24        temp = (temp >>(8–(translate_n[insn_code]%%`min_issue_delay_table_compression_factorn`

25             + 1) * 8 / `min_issue_delay_table_compression_factorn`))& -1;

26         if(temp > res)

27          res = temp;

28         …

29        break;

30         …  //instructions reserve other automaton list, not appear in our assuming example

31      default:

32        res =-1;

33        break;

34    }

35      return res;

36    }

 

上面vector translate_`x`把指令编码映射到自动机的等效指令类别编码。在这里,我们假定min_issue_delay_table_compression_factor`x`大于1,那么多个最小发布延迟可以被保存入一个字节中。24行获取了对应的数据,看到计算得到的位置,必须与填充时得到的位置相同(参考输出发布延迟表)。看到这个函数,给定一条指令,找出在该指令所使用的自动机中,所面临的最大的最小发布延迟。

9.6.4.2.3.           输出函数internal_state_transition

接下来,我们需要输出用于状态迁移的函数——自动机的引擎!

 

8348 static void

8349 output_internal_trans_func (void)                                                         ingenautomata.c

8350 {

8351   fprintf (output_file,

8352         "static int\n%s (int %s, struct %s*%s ATTRIBUTE_UNUSED)\n",

8353         INTERNAL_TRANSITION_FUNC_NAME,INTERNAL_INSN_CODE_NAME,

8354         CHIP_NAME, CHIP_PARAMETER_NAME);

8355   fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n",TEMPORARY_VARIABLE_NAME);

8356   fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);

8357   output_insn_code_cases(output_automata_list_transition_code);

8358   fprintf (output_file, "\n    default:\n      return -1;\n    }\n");

8359   fprintf (output_file, "}\n\n");

8360 }

 

至于output_insn_code_cases,我们已经看到它将找出具有相同自动机列表的指令,并且output_automata_list_transition_code为每个有资格的指令组所调用。

 

8255 static void

8256 output_automata_list_transition_code (automata_list_el_t automata_list) ingenautomata.c

8257 {

8258   automata_list_el_t el, next_el;

8259

8260   fprintf (output_file, "      {\n");

8261   if (automata_list != NULL && automata_list->next_automata_list_el!= NULL)

8262     for (el = automata_list;; el = next_el)

8263     {

8264      next_el = el->next_automata_list_el;

8265       if (next_el == NULL)

8266         break;

8267       fprintf (output_file, "        ");

8268       output_state_member_type (output_file,el->automaton);

8269       fprintf (output_file, " ");

8270       output_temp_chip_member_name (output_file,el->automaton);

8271      fprintf (output_file,";\n");

8272    }

8273   for (el = automata_list; el != NULL; el =el->next_automata_list_el)

8274     if (comb_vect_p(el->automaton->trans_table))

8275     {

8276       fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);

8277       output_trans_base_vect_name(output_file,el->automaton);

8278       fprintf (output_file, " [%s->",CHIP_PARAMETER_NAME);

8279       output_chip_member_name (output_file,el->automaton);

8280       fprintf (output_file, "] + ");

8281       output_translate_vect_name(output_file,el->automaton);

8282       fprintf (output_file, " [%s];\n",INTERNAL_INSN_CODE_NAME);

8283       fprintf (output_file, "        if (");

8284       output_trans_check_vect_name(output_file,el->automaton);

8285       fprintf (output_file, " [%s] !=%s->",

8286             TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);

8287       output_chip_member_name (output_file,el->automaton);

8288       fprintf (output_file, ")\n");

8289       fprintf (output_file, "          return %s (%s, %s);\n",

8290          INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME,INTERNAL_INSN_CODE_NAME,

8291          CHIP_PARAMETER_NAME);

8292       fprintf (output_file, "        else\n");

8293       fprintf (output_file, "          ");

8294       if (el->next_automata_list_el != NULL)

8295         output_temp_chip_member_name (output_file,el->automaton);

8296       else

8297       {

8298         fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);

8299         output_chip_member_name (output_file,el->automaton);

8300       }

8301       fprintf (output_file, " = ");

8302       output_trans_comb_vect_name(output_file,el->automaton);

8303       fprintf (output_file, " [%s];\n",TEMPORARY_VARIABLE_NAME);

8304     }

8305     else

8306     {

8307       fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);

8308       output_trans_full_vect_name(output_file,el->automaton);

8309       fprintf (output_file, " [");

8310       output_translate_vect_name(output_file,el->automaton);

8311       fprintf (output_file, " [%s] + ",INTERNAL_INSN_CODE_NAME);

8312       fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);

8313       output_chip_member_name (output_file,el->automaton);

8314       fprintf (output_file, " * %d];\n",

8315            el->automaton->insn_equiv_classes_num);

8316       fprintf (output_file, "        if (%s >= %d)\n",

8317           TEMPORARY_VARIABLE_NAME,el->automaton->achieved_states_num);

8318       fprintf (output_file, "          return %s (%s, %s);\n",

8319            INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,

8320            CHIP_PARAMETER_NAME);

8321       fprintf (output_file, "        else\n          ");

8322      if (el->next_automata_list_el != NULL)

8323         output_temp_chip_member_name (output_file,el->automaton);

8324       else

8325       {

8326         fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);

8327         output_chip_member_name (output_file,el->automaton);

8328       }

8329       fprintf (output_file, " = %s;\n",TEMPORARY_VARIABLE_NAME);

8330    }

8331   if(automata_list != NULL && automata_list->next_automata_list_el !=NULL)

8332     for (el = automata_list;; el = next_el)

8333     {

8334      next_el = el->next_automata_list_el;

8335       if (next_el == NULL)

8336         break;

8337       fprintf (output_file, "        %s->", CHIP_PARAMETER_NAME);

8338       output_chip_member_name (output_file,el->automaton);

8339       fprintf (output_file, " = ");

8340       output_temp_chip_member_name (output_file,el->automaton);

8341       fprintf (output_file, ";\n");

8342     }

8343   fprintf (output_file, "        return -1;\n");

8344   fprintf (output_file, "      }\n");

8345 }

 

我们得到如下的internal_state_transition的定义(红色部分不是工具输出的),假定向量transition_x没有被合并(transition_x参考输出状态迁移表)。

 

1     static int

2     internal_state_transition (intinsn_code, struct DFA_chip *chip ATTRIBUTE_UNUSED)

3     {

4       int temp ATTRIBUTE_UNUSED;

5       switch(insn_code)

6       {

7         caseinsn-x:           // for instructions reserve same automaton list.

8         …

9         caseinsn-y:

10           {

11             unsigned short _automaton_state_0;

12             …                                                              // declaration for other automatons

13             temp= transitions_0 [translate_0 [insn_code] + chip->automaton_state_0 *

14                  ` insn_equiv_classes_num0`];

15             if (temp >= ` achieved_states_num0` )

16               return internal_min_issue_delay(insn_code, chip);

17             else

18               _automaton_state_0 = transitions_0 [temp];

19               …                                                          // statement for other automatons

20              //statement for last automatons

21             temp= transitions_n [translate_n [insn_code] + chip->automaton_state_n *

22                       ` insn_equiv_classes_numn`];

23             if (temp >= ` achieved_states_numn` )

24               return internal_min_issue_delay(insn_code, chip);

25             else

26               chip->automaton_state_n = transitions_n [temp];

27   

28             chip->automaton_state_0 = _automaton_state_0;

29             …                                                              // statement for other automatons

30             return-1;

31           }

32           … // instructions reserve other automaton list, not appear inour assuming example

33       default:

34        return -1;

35      }

36    }

 

向量translate_x与自动机一一对应。它把指令编码映射到指令等效类别的编码。并且向量transition_x以指令等效类别编码为索引记录了目标状态(记得相同等效类别的指令具有相同的状态迁移)。注意到transition_x的未填充的成员被undefined_vect_el_value所占据,在output_trans_table中它被定义为achieved_states_num。在这个情形下,这意味着该指令不能发布,并且如上面23行所示,internal_min_issue_delay被调用来找出该指令的最小发布延迟。

9.6.4.2.4.           输出函数dfa_insn_code_enlarge与dfa_insn_code

给定一条指令,在系统中直接使用它并不方便,因为经过编译遍的处理,作为优化的结果它会改变形式。因此这个系统为每条指令分配唯一的编号。在编译过程中,它是系统范围内指令的识别符。dfa_insn_code,给定一条指令,返回其指令编号(编码)。

 

8392 static void

8393 output_dfa_insn_code_func (void)                                                        ingenautomata.c

8394 {

8395   /* Emacs c-modegets really confused if there's a { or } in column 0

8396     inside a string, so don't do that.  */

8397   fprintf (output_file, "\

8398 static void\n\

8399 dfa_insn_code_enlarge (int uid)\n\

8400 {\n\

8401   int i = %s;\n\

8402   %s = 2 * uid;\n\

8403   %s = xrealloc (%s,\n\

8404                  %s * sizeof(int));\n\

8405   for (; i <%s; i++)\n\

8406     %s[i] = -1;\n}\n\n",

8407          DFA_INSN_CODES_LENGTH_VARIABLE_NAME,

8408          DFA_INSN_CODES_LENGTH_VARIABLE_NAME,

8409          DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,

8410          DFA_INSN_CODES_LENGTH_VARIABLE_NAME,

8411          DFA_INSN_CODES_LENGTH_VARIABLE_NAME,

8412          DFA_INSN_CODES_VARIABLE_NAME);

8413   fprintf (output_file, "\

8414 static inlineint\n%s (rtx %s)\n\

8415 {\n\

8416   int uid = INSN_UID (%s);\n\

8417   int %s;\n\n",

8418          DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,

8419          INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);

8420

8421   fprintf (output_file,

8422          "  if (uid >= %s)\n    dfa_insn_code_enlarge (uid);\n\n",

8423          DFA_INSN_CODES_LENGTH_VARIABLE_NAME);

8424   fprintf (output_file, "  %s = %s[uid];\n",

8425          INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);

8426   fprintf (output_file, "\

8427   if (%s < 0)\n\

8428     {\n\

8429       %s = %s (%s);\n\

8430       %s[uid] = %s;\n\

8431     }\n",

8432          INTERNAL_INSN_CODE_NAME,

8433          INTERNAL_INSN_CODE_NAME,

8434          INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,

8435          DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);

8436   fprintf (output_file, "  return %s;\n}\n\n",INTERNAL_INSN_CODE_NAME);

8437 }

 

输出函数看起来如下。

 

1     static void

2     dfa_insn_code_enlarge (intuid)

3     {

4       int i = dfa_insn_codes_length;

5       dfa_insn_codes_length= 2 * uid;

6      dfa_insn_codes = xrealloc (dfa_insn_codes,

7                             dfa_insn_codes_length *sizeof(int));

8       for (; i< dfa_insn_codes_length; i++)

9        dfa_insn_codes[i]= -1;

10    }

11   

12   staticinline int

13   dfa_insn_code (rtx insn)

14   {

15     int uid = INSN_UID (insn);

16     int insn_code;

17  

18     if (uid >= dfa_insn_codes_length)

19       dfa_insn_code_enlarge (uid);

20     insn_code = dfa_insn_codes [uid];

21     if (insn_code < 0)

22     {

23       insn_code = internal_dfa_insn_code (insn);

24       dfa_insn_codes [uid] = insn_code;

25     }

26     return insn_code;

27   }

 

上面在23行,internal_dfa_insn_code由属性“*internal_dfa_insn_code”所产生。这个属性的内容是一个包含了所有预订指令的COND,其中每一个跳转的测试部分来自预订模式定义的测试部分,而其内容是指令编号。

9.6.4.2.5.           输出函数state_transition

在输出函数state_transition一节,产生了internal_state_transition,它接受insn_code及状态作为参数。不过它不是可以接受指令本身的理想的接口,这里对它进行进一步封装。

 

8440 static void

8441 output_trans_func (void)                                                                     in genautomata.c

8442 {

8443   fprintf (output_file, "int\n%s (%s %s, rtx%s)\n",

8444          TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,

8445          INSN_PARAMETER_NAME);

8446   fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);

8447   output_internal_insn_code_evaluation(INSN_PARAMETER_NAME,

8448                                    INTERNAL_INSN_CODE_NAME,-1);

8449   fprintf (output_file, "  return %s (%s, %s);\n}\n\n",

8450        INTERNAL_TRANSITION_FUNC_NAME,INTERNAL_INSN_CODE_NAME, STATE_NAME);

8451 }

 

下面是输出的函数。

 

1     int

2     state_transition(state_t state, rtx insn)

3     {

4       intinsn_code;

5       if (insn!= 0)

6       {

7         insn_code = dfa_insn_code (insn);

8         if(insn_code > DFA__ADVANCE_CYCLE)

9          return -1;

10      }

11      else

12        insn_code = DFA__ADVANCE_CYCLE;

13      return internal_state_transition(insn_code, state);

14    }

9.6.4.2.6.           输出函数internal_state_alts与state_alts

我们已经看到state_alts域记录了指定状态上指定指令的非确定性程度,在这里输出的函数用于调试目的。

 

8515 static void

8516 output_internal_state_alts_func (void)                                                   n genautomata.c

8517 {

8518   fprintf (output_file,

8519          "static int\n%s (int %s, struct %s *%s)\n",

8520          INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,

8521          CHIP_NAME, CHIP_PARAMETER_NAME);

8522   fprintf (output_file, "{\n  int %s;\n", RESULT_VARIABLE_NAME);

8523   fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);

8524   output_insn_code_cases(output_automata_list_state_alts_code);

8525   fprintf (output_file,

8526          "\n    default:\n      %s = 0;\n      break;\n    }\n",

8527          RESULT_VARIABLE_NAME);

8528   fprintf (output_file, "  return %s;\n", RESULT_VARIABLE_NAME);

8529   fprintf (output_file, "}\n\n");

8530 }

 

同样指令被依据所预订的自动机列表来分组。

 

8455 static void

8456 output_automata_list_state_alts_code (automata_list_el_t automata_list) in genautomata.c

8457 {

8458   automata_list_el_t el;

8459   automaton_t automaton;

8460

8461  fprintf (output_file,"      {\n");

8462   for (el = automata_list; el != NULL; el =el->next_automata_list_el)

8463     if (comb_vect_p(el->automaton->state_alts_table))

8464     {

8465       fprintf (output_file, "        int %s;\n",TEMPORARY_VARIABLE_NAME);

8466      break;

8467    }

8468   for (el = automata_list; el != NULL; el =el->next_automata_list_el)

8469   {

8470     automaton = el->automaton;

8471     if (comb_vect_p(automaton->state_alts_table))

8472     {

8473       fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);

8474       output_state_alts_base_vect_name (output_file,automaton);

8475       fprintf (output_file, " [%s->",CHIP_PARAMETER_NAME);

8476       output_chip_member_name (output_file,automaton);

8477       fprintf (output_file, "] + ");

8478       output_translate_vect_name(output_file,automaton);

8479       fprintf (output_file, " [%s];\n",INTERNAL_INSN_CODE_NAME);

8480       fprintf (output_file, "        if (");

8481       output_state_alts_check_vect_name(output_file,automaton);

8482       fprintf (output_file, " [%s] !=%s->",

8483                 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);

8484       output_chip_member_name (output_file,automaton);

8485       fprintf (output_file, ")\n");

8486       fprintf (output_file, "          return 0;\n");

8487       fprintf (output_file, "        else\n");

8488       fprintf (output_file,

8489             (el == automata_list

8490              ? "          %s = " : "          %s += "),

8491             RESULT_VARIABLE_NAME);

8492       output_state_alts_comb_vect_name (output_file,automaton);

8493       fprintf (output_file, " [%s];\n",TEMPORARY_VARIABLE_NAME);

8494     }

8495     else

8496     {

8497       fprintf (output_file,

8498             (el == automata_list

8499              ? "\n        %s = " : "        %s += "),

8500              RESULT_VARIABLE_NAME);

8501       output_state_alts_full_vect_name (output_file,automaton);

8502       fprintf (output_file, " [");

8503       output_translate_vect_name(output_file,automaton);

8504       fprintf (output_file, " [%s] + ",INTERNAL_INSN_CODE_NAME);

8505       fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);

8506       output_chip_member_name (output_file,automaton);

8507       fprintf (output_file, " * %d];\n",

8508            automaton->insn_equiv_classes_num);

8509     }

8510   }

8511   fprintf (output_file, "        break;\n      }\n\n");

8512 }

 

输出的函数看起来如下(红色部分不是工具输出的)。

 

1     static int

2     internal_state_alts (intinsn_code, struct DFA_chip *chip)

3     {

4       int res;

5       switch(insn_code)

6       {

7         caseinsn-x:    // for instructions reserve same automaton list.

8         …

9         caseinsn-y:

10         temp = base_state_alts_0[chip->automaton_state_0]+ translate_0[insn_code];

11         if (check_state_alts_0[temp] != chip->automaton_state_0)

12           return 0;

13         else

14           res = state_alts_0[temp];

15         …         // for other automaton in list, notpresent in our example

16         //last automaton in list, not present in our example

17         temp = base_state_alts_n[chip->automaton_state_n]+ translate_n[insn_code];

18         if (check_state_alts_n[temp] != chip->automaton_state_n)

19           return 0;

20         else

21           res += state_alts_n[temp];

22         break;

23         …  // instructions reserve other automaton list, notappear in our assuming example

24        default:

25         res = 0;

26         break;

27      }

28      return res;

29    }

 

向量state_alts_`n`记录了预订替代的数目,它们可以用于从给定状态由给定指令触发的迁移。internal_state_alts计算出给定指令的自动机列表的预订替代的总数。我们已经看到在输出函数internal_state_transition(参见输出函数internal_state_transition一节)里,chipautomaton_state_`x`保存了该指令的等效类别编号,这也同样记录在check_state_alts_`x`里,如果预订替代数目出现在state_alts_`n`中。看到在这里我们假定使用合并向量。

接下来,需要输出internal_state_alts的一个封装。

 

8533 static void

8534 output_state_alts_func (void)                                                                      in genautomata.c

8535 {

8536   fprintf (output_file, "int\n%s (%s, %s)\n\t%s%s;\n\trtx %s;\n",

8537          STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,

8538          STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);

8539   fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);

8540   output_internal_insn_code_evaluation(INSN_PARAMETER_NAME,

8541                                    INTERNAL_INSN_CODE_NAME,0);

8542   fprintf (output_file, "  return %s (%s, %s);\n}\n\n",

8543        INTERNAL_STATE_ALTS_FUNC_NAME,INTERNAL_INSN_CODE_NAME, STATE_NAME);

8544 }

 

8375 static void

8376 output_internal_insn_code_evaluation (const char *insn_name,                ingenautomata.c

8377                                 const char *insn_code_name,

8378                                 int code)

8379 {

8380   fprintf (output_file, "\n  if (%s != 0)\n    {\n", insn_name);

8381   fprintf (output_file, "      %s = %s (%s);\n", insn_code_name,

8382          DFA_INSN_CODE_FUNC_NAME, insn_name);

8383   fprintf (output_file, "      if (%s > %s)\n        return %d;\n",

8384          insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);

8385   fprintf (output_file, "    }\n else\n    %s = %s;\n\n",

8386          insn_code_name, ADVANCE_CYCLE_VALUE_NAME);

8387 }

 

至于这个输出函数,其定义如下。

 

1     int

2     state_alts (state,insn)

3       state_tstate;

4       rtx insn;

5     {

6       intinsn_code;

7       if (insn!= 0)

8       {

9         insn_code = dfa_insn_code (insn);

10        if (insn_code > DFA__ADVANCE_CYCLE)

11         return 0;

12      }

13      else

14        insn_code = DFA__ADVANCE_CYCLE;

15      return internal_state_alts(insn_code, state);

16    }

 

DFA__ADVANCE_CYCLE已经被定义作指令的数目(指令编号advance_cycle_insn_decl)。注意到insn_code也是从0到指令数目减一的序列号。

9.6.4.2.7.           输出函数min_issue_delay

这个函数是对internal_min_issue_delay(参考输出函数internal_min_issue_delay)的封装。

 

8547 static void

8548 output_min_issue_delay_func (void)                                                    ingenautomata.c

8549 {

8550   fprintf (output_file, "int\n%s (%s %s, rtx%s)\n",

8551          MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,

8552          INSN_PARAMETER_NAME);

8553   fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);

8554   fprintf (output_file, "\n  if (%s != 0)\n    {\n", INSN_PARAMETER_NAME);

8555   fprintf (output_file, "      %s = %s (%s);\n",INTERNAL_INSN_CODE_NAME,

8556          DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);

8557   fprintf (output_file, "      if (%s > %s)\n        return 0;\n",

8558          INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);

8559   fprintf (output_file, "    }\n else\n    %s = %s;\n",

8560          INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);

8561   fprintf (output_file, "\n  return %s (%s, %s);\n",

8562        INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME,INTERNAL_INSN_CODE_NAME,

8563          STATE_NAME);

8564   fprintf (output_file, "}\n\n");

8565 }

 

1     int

2     min_issue_delay(state_t state, rtx insn)

3     {

4       intinsn_code;

5       if (insn!= 0)

6       {

7         insn_code = dfa_insn_code (insn);

8         if(insn_code > DFA__ADVANCE_CYCLE)

9          return 0;

10      }

11      else

12        insn_code = DFA__ADVANCE_CYCLE;

13   

14      return internal_min_issue_delay(insn_code, state);

15    }

你可能感兴趣的:(GCC后端及汇编发布(37))