GCC后端及汇编发布(23)

9.5. 构建基于DFA 的流水线危险识别器

9.5.1. DEFINE_AUTOMATON 模式构建的 decl

gen_automaton 中,我们看到这个模式转换来的 rtx 对象将被保存入 decl 实例。对于在 读入 DEFINE_AUTOMATON模式 一节中所使用的例子,我们已经看过如下的 rtx 对象。 这个例子来自文件 pentium.md

tf1

那么由 gen_automaton 处理后,我们将得到以下的数据结构。注意到在这个向量中实际上是 decl 的指针。

t61

9.5.2. DEFINE_CPU_UNIT 模式构建 decl

同样对于 读入 DEFINE_CPU_UNIT模式 一节中的例子,我们已经看到了如下的 rtx 对象。这个例子来自 pentium.md 文件。

tf2

在经由 gen_cpu_unit 的处理之后,我们将得到以下的数据结构。注意到在这个向量中实际上是 decl 的指针。

t62

62 DEFINE_CUP_UNIT 模式的 decl 对象的例子

9.5.3. DEFINE_BYPASS 模式构建 decl

而对于 DEFINE_BYPASS 的例子,我们已经看到如下从 md 文件构建的 rtx 对象。这个例子来自 pentium.md 文件。

tf3

在经过 gen_bypass 的处理之后,我们将得到如下的数据结构。所有的 decl 都链接在一起。注意到在这个向量中实际上是 decl 的指针。

t63

63 DEFINE_BYPASS 模式的 decl 对象的例子

9.5.4. EXCULSION_SET 模式构建 decl

而对于 EXCLUSION_SET 的例子,我们已经看到如下从 md 文件构建的 rtx 对象。这个例子来自 itantium.md 文件。

tf4

我们知道上面的这两个字符串描述了两组互斥的单元。在经过的处理 gen_excl_set 后,我们将得到以下的数据结构,所有的 decl 都链接在一起。注意到在这个向量中实际上是 decl 的指针。

t64

64 EXCLUSION_SET 模式的 decl 对象的例子

9.5.5. DEFINE_RESERVATION 模式构建 decl

那么对于 DEFINE_RESERVATION 的例子,我们已经看到如下从 md 文件构建的 rtx 对象。这个例子来自 pentium.md 文件。

tf5

那么在 gen_reserv 的处理之后,我们将得到如下的数据结构。

t65

65 DEFINE_RESERVATION 模式的 decl 对象的例子

9.5.6. DEFINE_INSN_RESERVATION 模式构建 decl

而对于 DEFINE_INSN_RESERVATION 的例子,我们已经看到如下从 md 文件构建的 rtx 对象。这个例子来自 pentium.md 文件。

tf6

那么在 gen_insn_reserv 的处理之后,我们将得到如下的数据结构。

t66

66 DEFINE_INSN_RESERVATION 模式的 decl 对象的例子

9.5.7. 处理 decl

指令调度器的目的是尽可能多地发布指令。流水线危险识别器可以告诉调度器某个指令是否可以与其它运行中指令一同执行。所有所需的信息被分散地记录在机器描述文件中相关的模式里,不过 expand_automata 将组织这些信息,并为构建基于 DFA 的流水线危险识别器生成结构化信息。

 

9810 void

9811 expand_automata (void)                                                                             in genautomata.c

9812 {

9813   int i;

9814

9815   description = create_node (sizeof (struct description)

9816                          /* One entry for cycle advancing insn.  */

9817                         + sizeof (decl_t) * VLA_PTR_LENGTH (decls ));

9818   description ->decls_num = VLA_PTR_LENGTH (decls );

9819   description ->query_units_num = 0;

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

9821   {

9822     description ->decls [i] = VLA_PTR (decls , i);

9823     if (description ->decls [i]->mode == dm_unit

9824        && DECL_UNIT (description ->decls [i])->query_p)

9825       DECL_UNIT (description ->decls [i])->query_num

9826                    = description ->query_units_num++;

9827   }

9828   all_time = create_ticker ();

9829   check_time = create_ticker ();

9830   if (progress_flag )

9831     fprintf (stderr, "Check description...");

9832   check_all_description ();

9833   if (progress_flag )

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

9835   ticker_off (&check_time );

9836   generation_time = create_ticker ();

 

expand_automata 首先创建一个 description 对象来收集所有构建的 decl ,这个对象具有如下的定义。

 

1009 struct description                                                                                 in genautomata.c

1010 {

1011   int decls_num;

1012

1013   /* The following fields are defined by checker.  */

1014

1015   /* The following fields values are correspondingly number of all

1016     units, query units, and insns in the description.  */

1017   int units_num;

1018   int query_units_num;

1019   int insns_num;

1020   /* The following field value is max length (in cycles) of

1021     reservations of insns. The field value is defined only for

1022     correct programs.  */

1023   int max_insn_reserv_cycles;

1024

1025   /* The following fields are defined by automaton generator.  */

1026

1027   /* The following field value is the first automaton.  */

1028   automaton_t first_automaton;

1029

1030   /* The following field is created by pipeline hazard parser and

1031     contains all declarations. We allocate additional entry for

1032     special insn "cycle advancing" which is added by the automaton

1033     generator.  */

1034   decl_t decls [1];

1035 };

 

expand_automata 中,直到 9832 行,将创建如下的 description 对象。

t67

67 description 对象的例子

接着 check_all_description 将以如下方式来处理这个对象。

 

3387 static void

3388 check_all_description (void)                                                                in genautomata.c

3389 {

3390   process_decls ();

3391   check_automaton_usage ();

3392   process_regexp_decls ();

3393   check_usage ();

3394   check_loops_in_regexps ();

3395   if (!have_error )

3396     evaluate_max_reserv_cycles ();

3397 }

9.5.7.1.    处理 decl 的第一个循环 – DECL_AUTOMATON

process_decls 6 个循环中处理 decl 。在这个循环里,需要找出一共声明了多少个自动机,并为随后的循环准备必须的数据对象。

 

2802 static void

2803 process_decls (void)                                                                            in genautomata.c

2804 {

2805   decl_t decl;

2806   decl_t automaton_decl;

2807   decl_t decl_in_table;

2808   decl_t out_insn_reserv;

2809   decl_t in_insn_reserv;

2810   struct bypass_decl *bypass;

2811   int automaton_presence;

2812   int i;

2813

2814   /* Checking repeated automata declarations.  */

2815   automaton_presence = 0;

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

2817   {

2818     decl = description ->decls [i];

2819     if (decl->mode == dm_automaton)

2820     {

2821       automaton_presence = 1;

2822       decl_in_table = insert_automaton_decl (decl);

2823       if (decl_in_table != decl)

2824       {

2825         if (!w_flag )

2826           error ("repeated declaration of automaton `%s'",

2827                 DECL_AUTOMATON (decl)->name);

2828         else

2829            warning ("repeated declaration of automaton `%s'",

2830                    DECL_AUTOMATON (decl)->name);

2831       }

2832     }

2833   }

 

首先得到处理的是 DEFINE_AUTOMATON 模式的 decl 。这个类别的 decl 被保存在静态哈希表 automaton_decl_table 中。自动机的名字必须是唯一的,否则将触发警告或错误。

 

2202 static decl_t

2203 insert_automaton_decl ( decl_t automaton_decl)                                     in genautomata.c

2204 {

2205   void **entry_ptr;

2206

2207   entry_ptr = htab_find_slot (automaton_decl_table , automaton_decl, 1);

2208   if (*entry_ptr == NULL)

2209     *entry_ptr = (void *) automaton_decl;

2210   return (decl_t) *entry_ptr;

2211 }

9.5.7.2.    处理 decl 的第二个循环 – DECL_UNIT

这次循环只是把 CPU 单元的 decl 与其从属的自动机绑定在一起。

 

process_decls (continued)

 

2834   /* Checking undeclared automata, repeated declarations (except for

2835     automata) and correctness of their attributes (insn latency times

2836     etc.).  */

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

2838   {

2839     decl = description ->decls [i];

2840     if (decl->mode == dm_insn_reserv)

2841     {

2842       DECL_INSN_RESERV (decl)->condexp

2843           = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);

2844       if (DECL_INSN_RESERV (decl)->default_latency < 0)

2845         error ("define_insn_reservation `%s' has negative latency time",

2846               DECL_INSN_RESERV (decl)->name);

2847                DECL_INSN_RESERV (decl)->insn_num = description ->insns_num;

2848        description ->insns_num++;

2849       decl_in_table = insert_insn_decl (decl);

2850       if (decl_in_table != decl)

2851         error ("`%s' is already used as insn reservation name",

2852              DECL_INSN_RESERV (decl)->name);

2853     }

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

2855     {

2856       if (DECL_BYPASS (decl)->latency < 0)

2857         error ("define_bypass `%s - %s' has negative latency time",

2858                DECL_BYPASS (decl)->out_insn_name,

2859               DECL_BYPASS (decl)->in_insn_name);

2860     }

2861     else if (decl->mode == dm_unit || decl->mode == dm_reserv)

2862     {

2863       if (decl->mode == dm_unit)

2864       {

2865         DECL_UNIT (decl)->automaton_decl = NULL;

2866         if (DECL_UNIT (decl)->automaton_name != NULL)

2867         {

2868           automaton_decl

2869                = find_automaton_decl (DECL_UNIT (decl)->automaton_name);

2870           if (automaton_decl == NULL)

2871             error ("automaton `%s' is not declared",

2872                   DECL_UNIT (decl)->automaton_name);

2873           else

2874           {

2875             DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;

2876             DECL_UNIT (decl)->automaton_decl

2877                    = DECL_AUTOMATON (automaton_decl);

2878           }

2879         }

2880         else if (automaton_presence)

2881           error ("define_unit `%s' without automaton when one defined",

2882                 DECL_UNIT (decl)->name);

2883         DECL_UNIT (decl)->unit_num = description ->units_num;

2884         description ->units_num++;

2885         if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)

2886         {

2887           error ("`%s' is declared as cpu unit", NOTHING_NAME);

2888           continue ;

2889         }

2890         decl_in_table = find_decl (DECL_UNIT (decl)->name);

2891       }

2892       else

2893       {

2894         if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)

2895         {

2896           error ("`%s' is declared as cpu reservation", NOTHING_NAME);

2897           continue ;

2898         }

2899         decl_in_table = find_decl (DECL_RESERV (decl)->name);

2900       }

2901       if (decl_in_table == NULL)

2902         decl_in_table = insert_decl (decl);

2903       else

2904       {

2905         if (decl->mode == dm_unit)

2906           error ("repeated declaration of unit `%s'",

2907                 DECL_UNIT (decl)->name);

2908         else

2909           error ("repeated declaration of reservation `%s'",

2910                 DECL_RESERV (decl)->name);

2911       }

2912     }

2913   }

 

define_insn_reservation define_bypass 模式的 decl 的处理相当简单。上面,宏 DECL_* 访问 decl union 域的对应成员。

2221 行,我们之前已经见过 check_attr_test 。这个函数将验证给定的属性,并把相关的表达式转换为所谓的规范形式。例如,转换“ (eq_attr "att" "a1,a2") ”为“ (ior (eq_attr “att” “a1” ) (eq_attrq “att” “a2”)) ”。另一个例子,转换“ (eq_attr "att" "!a1") ”为“ (not (eq_attr "att" "a1")) ”。

2227 行, insert_insn_decl 将把 define_insn_reservation 模式的 decl 加入静态哈希表 insn_decl_table 中。

2863 行开始,对于 define_cpu_unit 模式的 decl ,它将被与相应的 define_automaton 模式的 decl 绑定如下。

t68

68 DEFINE_CPU_UNIT decl 的例子

9.5.7.3.    处理 decl 的第三个循环 – DECL_BYPASS

我们知道 define_bypass 模式用于描述给定指令对延迟时间的例外。它记录了在字符串 out_insn_name s 中指令的结果,对于在字符串 in_insn_name s 中指令就绪的延迟时间。第三个循环把 define_bypass 模式的 decl define_insn_reservation 模式(描述 CPU 单元的使用,参见 DEFINE_INSN_RESERVATION模式的概览 一节)的 decl 绑定在一起。

 

process_decls (continued)

 

2914   /* Check bypasses and form list of bypasses for each (output)

2915     insn.  */

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

2917   {

2918     decl = description ->decls [i];

2919     if (decl->mode == dm_bypass)

2920     {

2921       out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);

2922       i n_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);

2923       if (out_insn_reserv == NULL)

2924         error ("there is no insn reservation `%s'",

2925               DECL_BYPASS (decl)->out_insn_name);

2926       else if (in_insn_reserv == NULL)

2927         error ("there is no insn reservation `%s'",

2928               DECL_BYPASS (decl)->in_insn_name);

2929       else

2930       {

2931         DECL_BYPASS (decl)->out_insn_reserv

2932              = DECL_INSN_RESERV (out_insn_reserv);

2933         DECL_BYPASS (decl)->in_insn_reserv

2934              = DECL_INSN_RESERV (in_insn_reserv);

2935         bypass

2936              = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,

2937                           DECL_BYPASS (decl)->in_insn_reserv);

2938         if (bypass != NULL)

2939         {

2940           if (DECL_BYPASS (decl)->latency == bypass->latency)

2941           {

2942             if (!w_flag )

2943               error

2944                   ("the same bypass `%s - %s' is already defined",

2945                   DECL_BYPASS (decl)->out_insn_name,

2946                   DECL_BYPASS (decl)->in_insn_name);

2947             else

2948               warning

2949                    ("the same bypass `%s - %s' is already defined",

2950                   DECL_BYPASS (decl)->out_insn_name,

2951                   DECL_BYPASS (decl)->in_insn_name);

2952           }

2953           else

2954             error ("bypass `%s - %s' is already defined",

2955                   DECL_BYPASS (decl)->out_insn_name,

2956                   DECL_BYPASS (decl)->in_insn_name);

2957         }

2958         else

2959         {

2960           DECL_BYPASS (decl)->next

2961               = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;

2962           DECL_INSN_RESERV (out_insn_reserv)->bypass_list

2963               = DECL_BYPASS (decl);

2964         }

2965       }

2966     }

2967   }

 

对于我们的例子,我们可以得到下图(忽略了对象“ penrt_call ”)。

t69

69 DECL_BYPASS decl 的例子

9.5.7.4.    处理 decl 的第四个循环 – DECL_EXCL

这次的循环根据对应的 decl_excl 填充 define_cpu_unit 模式的 decl

 

process_decls (continued)

 

2969   /* Check exclusion set declarations and form exclusion sets.  */

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

2971   {

2972     decl = description ->decls [i];

2973     if (decl->mode == dm_excl)

2974     {

2975       unit_set_el_t unit_set_el_list;

2976       unit_set_el_t unit_set_el_list_2;

2977

2978       unit_set_el_list

2979               = process_excls (DECL_EXCL (decl)->names,

2980                              DECL_EXCL (decl)->first_list_length, decl->pos);

2981       unit_set_el_list_2

2982               = process_excls (&DECL_EXCL (decl)->names

2983                             [DECL_EXCL (decl)->first_list_length],

2984                              DECL_EXCL (decl)->all_names_num

2985                              - DECL_EXCL (decl)->first_list_length,

2986                              decl->pos);

2987       add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);

2988       add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);

2989     }

2990   }

 

2978 2981 行, unit_set_el_list unit_set_el_list_2 记录彼此互斥的单元,它们由 process_excls 构建。注意 first_list_length 域显示了 names 数组中前几个元素是来自第一组单元的, all_names_num 则表示一共出现了多少个单元。

 

2460 static unit_set_el_t

2461 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)     in genautomata.c

2462 {

2463   unit_set_el_t el_list;

2464   unit_set_el_t last_el;

2465   unit_set_el_t new_el;

2466   decl_t decl_in_table;

2467   int i;

2468

2469   el_list = NULL;

2470   last_el = NULL;

2471   for (i = 0; i < num; i++)

2472   {

2473     decl_in_table = find_decl (names [i]);

2474     if (decl_in_table == NULL)

2475       error ("unit `%s' in exclusion is not declared", names [i]);

2476     else if (decl_in_table->mode != dm_unit)

2477       error ("`%s' in exclusion is not unit", names [i]);

2478     else

2479     {

2480       new_el = create_node (sizeof (struct unit_set_el ));

2481        new_el->unit_decl = DECL_UNIT (decl_in_table);

2482        new_el->next_unit_set_el = NULL;

2483        if (last_el == NULL)

2484        el_list = last_el = new_el;

2485        else

2486        {

2487         last_el->next_unit_set_el = new_el;

2488          last_el = last_el->next_unit_set_el;

2489        }

2490     }

2491   }

2492   return el_list;

2493 }

 

unit_set_el_list unit_set_el_list_2 链表由如下的 unit_set_el 类型的节点构成。

 

1042 struct unit_set_el                                                                                in genautomata.c

1043 {

1044   unit_decl_t unit_decl;

1045   unit_set_el_t next_unit_set_el;

1046 };

 

198  typedef struct unit_set_el *unit_set_el_t ;

 

在构建了这两个链表后 因为这两个链表记录的是互斥的单元 add_excls src_list 中的单元 decl 填充到 dst_list 中每个单元 decl next_unit_set_el 链表。

 

2498 static void

2499 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,                    in genautomata.c

2500           pos_t excl_pos ATTRIBUTE_UNUSED)

2501 {

2502   unit_set_el_t dst;

2503   unit_set_el_t src;

2504   unit_set_el_t curr_el;

2505   unit_set_el_t prev_el;

2506   unit_set_el_t copy;

2507

2508   for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)

2509     for (src = source_list; src != NULL; src = src->next_unit_set_el)

2510     {

2511       if (dst->unit_decl == src->unit_decl)

2512        {

2513         error ("unit `%s' excludes itself", src->unit_decl->name);

2514          continue ;

2515       }

2516       if (dst->unit_decl->automaton_name != NULL

2517          && src->unit_decl->automaton_name != NULL

2518          && strcmp (dst->unit_decl->automaton_name,

2519                     src->unit_decl->automaton_name) != 0)

2520       {

2521         error ("units `%s' and `%s' in exclusion set belong to different automata",

2522                src->unit_decl->name, dst->unit_decl->name);

2523          continue ;

2524       }

2525       for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;

2526           curr_el != NULL;

2527           prev_el = curr_el, curr_el = curr_el->next_unit_set_el)

2528         if (curr_el->unit_decl == src->unit_decl)

2529             break ;

2530       if (curr_el == NULL)

2531       {

2532         /* Element not found - insert.  */

2533         copy = copy_node (src, sizeof (*src));

2534          copy->next_unit_set_el = NULL;

2535          if (prev_el == NULL)

2536             dst->unit_decl->excl_list = copy;

2537          else

2538           prev_el->next_unit_set_el = copy;

2539       }

2540     }

2541 }

 

注意上面的 dst 以及 src 中的 unit_decl 是其中的某个单元,这个节点中的 excl_list 记录了与其互斥的单元的列表。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值