GCC's bacl-end & assemble emission (23)

9.5. Construct DFA-based pipeline hazards recognizer

9.5.1. Decl created for DEFINE_AUTOMATON pattern

In gen_automaton , we see that the pattern transformed into rtx object will be saved into decl instance. For the example used in 9.3.9 Read in DEFINE_AUTOMATON pattern , we have seen that the rtx object as following. This example comes from file pentium.md.

tf1

Then treated by gen_automaton , we will get following data structure. Notice that in fact in the vector is pointer of the decl.

t61

figure 61 : example of decl objects for DEFINE_AUTOMATON pattern

9.5.2. Decl created for DEFINE_CPU_UNIT pattern

Also for the example in 9.3.6 Read in DEFINE_CPU_UNIT pattern , we have seen the rtx object as following. This example is from file pentium.md

tf2

Then treated by gen_cpu_unit , we will get following data structure. Notice that in fact, in the vector is pointer of the decl.

t62

figure 62 : example of decl objects for DEFINE_CUP_UNIT pattern

9.5.3. Decl created for DEFINE_BYPASS pattern

Then for example of DEFINE_BYPASS, we have seen that the rtx object created from md file is as following. This example is from file pentium.md.

tf3

Then treated by gen_bypass , we will get following data structure. All decls are linked. Notice that in fact, in the vector is pointer of the decl.

t63

figure 63 : example of decl objects for DEFINE_BYPASS pattern

9.5.4. Decl created for EXCULSION_SET pattern

Then for example of EXCLUSION_SET, we have seen that the rtx object created from md file is as following. This example is from file itantium.md.

tf4

We know that above two strings describe two set of units that excluded from each other. Then treated by gen_excl_set , we will get following data structure. All decls are linked. Notice that in fact, in the vector is pointer of the decl.

t64

figure 64 : decl objects created for EXCLUSION_SET pattern

9.5.5. Decl created for DEFINE_RESERVATION pattern

Then for example of DEFINE_RESERVATION, we have seen that the rtx object created from md file is as following. This example is from file pentium.md.

tf5

Then treated by gen_reserv , we will get following data structure.

t65

figure 65 : example of decl objects for DEFINE_RESERVATION pattern

9.5.6. Decl created for DEFINE_INSN_RESERVATION pattern

Then for example of DEFINE_INSN_RESERVATION, we have seen that the rtx object created from md file is as following. This example is from file pentium.md

tf6

Then treated by gen_insn_reserv , we will get following data structure.

t66

figure 66 : declexample of objects for DEFINE_INSN_RESERVATION pattern

9.5.7. Handling of decls

The purpose of instruction scheduler is to issue intructions as many as possible. Pipeline hazards recognizer can tell scheduler whether certain instruction can execute with those running. All needed information is recorded dispersedly within related patterns in machine description files, but expand_automata will organize these informations and produce structured data for building DFA-based pipeline hazards recognizer.

 

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 first creates a description object to collect all decls created, which has definition in following.

 

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 };

 

In expand_automata till line 9832, following description object will be created.

t67

figure 67 : example of description

Then check_all_description will handle this object in following way.

 

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.    1st Loop of Processing Decls – DECL_AUTOMATON

process_decls handling decls within six loops. In first loop, it needs find out how many automatons declared, and create data objects which must be ready for coming loops.

 

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   }

 

The first treated is decl of DEFINE_AUTOMATON pattern. This kind of decl is saved into static hash table automaton_decl_table . See that the name of automaton must be unique, otherwise triggers warning or error.

 

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.    2nd Loop of Processing Decls – DECL_UNIT

This loop just binds the decl of CPU unit with the automaton it belongs to.

 

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   }

 

The processes of decl of define_insn_reservation and define_bypass patterns are quite simple. Above, macros DECL_* accesses corresponding member of union field of decl .

At line 2221, we have seen check_attr_test before. This function will validate given attribute, and tranform related expression into so-called canonical form. For example, converts (eq_attr "att" "a1,a2") to (ior (eq_attr “att” “a1” ) (eq_attrq “att” “a2”)). Another example, converts (eq_attr "att" "!a1") to (not (eq_attr "att" "a1"))

At line 2227, insert_insn_decl will insert the decls of define_insn_reservation pattern into static hash table insn_decl_table .

Begin at line 2863, for decl of define_cpu_unit pattern, it will be bound with decl of corresponding define_automaton pattern as following.

t68

figure 68 : example of decl of DEFINE_CPU_UNIT

9.5.7.3.    3rd Loop of Processing Decls – DECL_BYPASS

We know that define_bypass pattern is used to describe exceptions in the latency time for given instruction pair. It records the latency time that the result generated by the instructions given in string out_insn_name s will be ready for the instructions given in string in_insn_name s. The third loop binds decls of define_bypass with decls of define_insn_reservation pattern, which describes CPU units usage. (refer to 8.1.3 Overview of DEFINE_INSN_RESERVATION pattern ).

 

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   }

 

For our examples, we can get below figure (object “penrt_call” is omitted here).

t69

figure 69 : example of decl of DECL_BYPASS

9.5.7.4.    4th Loop of Processing Decls – DECL_EXCL

This loop fills decls of define_cpu_unit pattern according to corresponding decl_excl.

 

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   }

 

At line 2978 and 2981, unit_set_el_list and unit_set_el_list_2 record units that exclusive to each other. process_excls will create the data related. Note field first_list_length tolds how many  initial elements of names comes from the first group, and all_names_num indicates how many units present totally.

 

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 }

 

We see that decls of define_cpu_unit pattern having same name with the decl of define_bypass will be linked tegother. This list is constructed by unit_set_el as following.

 

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 ;

 

After creating the two lists, as they record units excluding each other, add_excls fills unit decl s of src_list in the next_unit_set_el of unit decl s in dst_list .

 

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 }

 

Note that unit_decl in dst and src is one of the units, in which excl_list records the list of units excluded by it.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值