GCC后端及汇编发布(18)

9.3.4. 读入 DEFINE_DELAY 模式

DEFINE_DELAY 的细节请参考 DEFINE_DELAY模式的概览 。对于这种模式,我们使用以下例子:

 

278  (define_delay (and (eq_attr "type" "branch")                                                        in mips.md

279                   (eq (symbol_ref "TARGET_MIPS16") (const_int 0)))

280    [(eq_attr "can_delay" "yes")

281     (nil)

282     (and (eq_attr "branch_likely" "yes")

283         (eq_attr "can_delay" "yes"))])

 

在经过 init_md_reader_args 的处理后,上面的模式被作为以下 rtx 对象载入内存。

t41

41 DEFINE_DELAY 模式的例子

gen_delay 简单地把这些对象链接在一起。

 

4430 static void

4431 gen_delay (rtx def, int lineno)                                                              in genattrtab.c

4432 {

4433   struct delay_desc *delay;

4434   int i;

4435

4436   if (XVECLEN (def, 1) % 3 != 0)

4437   {

4438     message_with_line (lineno,

4439           "number of elements in DEFINE_DELAY must be multiple of three");

4440     have_error = 1;

4441     return ;

4442   }

4443

4444   for (i = 0; i < XVECLEN (def, 1); i += 3)

4445   {

4446     if (XVECEXP (def, 1, i + 1))

4447       have_annul_true = 1;

4448     if (XVECEXP (def, 1, i + 2))

4449       have_annul_false = 1;

4450   }

4451

4452   delay = oballoc (sizeof (struct delay_desc));

4453   delay->def = def;

4454   delay->num = ++num_delays ;

4455   delay->next = delays ;

4456   delay->lineno = lineno;

4457   delays = delay;

4458 }

 

4433 行, delay_desc 是一个简单结构体,它具有如下定义。

 

213  struct delay_desc                                                                                 in genattrtab.c

214  {

215    rtx def;                     /* DEFINE_DELAY expression.  */

216    struct delay_desc *next;     /* Next DEFINE_DELAY.  */

217    int num;                    /* Number of DEFINE_DELAY, starting at 1.   */

218    int lineno;                 /* Line number.  */

219  };

9.3.5. 读入 DEFINE_FUNCTION_UNIT 模式

DEFINE_FUNCTION_UNIT模式的概览 一节描述了 DEFINE_FUNCTION_UINT 模式的细节。在于这个模式,我们使用以下的这里:

 

43    (define_function_unit "k6_alux" 1 0                                                                    in k6.md

44      (and (eq_attr "cpu" "k6")

45           (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,cld"))

46      1 1)

 

比较与我们下面将要看到的模式,这个模式是旧式的指令级别的并行性描述。两者的目的都是产生流水线危险识别器。在同一个机器描述文件中,这两个形式不能共存。至于与新描述比较,这个旧式的描述的缺点,请参考 gccint 10.18.8.3 节。

事实上,从其定义我们可以看到,这个模式以功能单元的角度来描述系统——它告诉我们如果被占据了,这个单元将多久才能再次可用,如果输出的结果要被作为输入使用,要多久才可行,同样它也给出了将占据它的指令列表。

而对于新的形式,也就是说我们将在下面看到的 define_insn_reservation ,它从指令的角度来描述系统——它告诉我们,在指令执行过程中,在流水线的每个阶段,哪些单元将被占据(使用模式来定义之),然后多长时间后其结果可用。这无疑是个更好的形式,因为调度器的目的是尽可能多地发布指令。以指令的角度来描述系统,可用更好地服务于这个目的。

在经过 init_md_reader_args 的处理后,上面的模式被作为以下的 rtx 对象载入内存。

t42

42 DEFINE_FUNCTION_UNIT 模式的例子

gen_unit 从这个 rtx 对象获取信息。每个 define_funciton_unit 模式应该具有唯一的名字,这个名字用作甄别器。

 

4466 static void

4467 gen_unit (rtx def, int lineno)                                                               in genattrtab.c

4468 {

4469   struct function_unit *unit;

4470   struct function_unit_op *op;

4471   const char *name = XSTR (def, 0);

4472   int multiplicity = XINT (def, 1);

4473   int simultaneity = XINT (def, 2);

4474   rtx condexp = XEXP (def, 3);

4475   int ready_cost = MAX (XINT (def, 4), 1);

4476   int issue_delay = MAX (XINT (def, 5), 1);

4477

4478   /* See if we have already seen this function unit. If so, check that

4479     the multiplicity and simultaneity values are the same. If not, make

4480     a structure for this function unit.  */

4481   for (unit = units ; unit; unit = unit->next)

4482     if (! strcmp (unit->name, name))

4483     {

4484       if (unit->multiplicity != multiplicity

4485         || unit->simultaneity != simultaneity)

4486        {

4487          message_with_line (lineno,

4488                      "differing specifications given for function unit %s",

4489                 unit->name);

4490          message_with_line (unit->first_lineno, "previous definition");

4491          have_error = 1;

4492          return ;

4493        }

4494       break ;

4495     }

4496

4497   if (unit == 0)

4498   {

4499     unit = oballoc (sizeof (struct function_unit ));

4500     unit->name = name;

4501     unit->multiplicity = multiplicity;

4502     unit->simultaneity = simultaneity;

4503     unit->issue_delay.min = unit->issue_delay.max = issue_delay;

4504     unit->num = num_units ++;

4505     unit->num_opclasses = 0;

4506     unit->condexp = false_rtx ;

4507      unit->ops = 0;

4508     unit->next = units ;

4509     unit->first_lineno = lineno;

4510     units = unit;

4511   }

4512   else

4513     XSTR (def, 0) = unit->name;

4514

4515   /* Make a new operation class structure entry and initialize it.  */

4516   op = oballoc (sizeof (struct function_unit_op ));

4517   op->condexp = condexp;

4518   op->num = unit->num_opclasses++;

4519   op->ready = ready_cost;

4520   op->issue_delay = issue_delay;

4521   op->next = unit->ops;

4522   op->lineno = lineno;

4523   unit->ops = op;

4524   num_unit_opclasses ++;

4525

4526   /* Set our issue expression based on whether or not an optional conflict

4527     vector was specified.  */

4528   if (XVEC (def, 6))

4529   {

4530     /* Compute the IOR of all the specified expressions.  */

4531     rtx orexp = false_rtx ;

4532     int i;

4533

4534     for (i = 0; i < XVECLEN (def, 6); i++)

4535       orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2, -2);

4536

4537     op->conflict_exp = orexp;

4538     extend_range (&unit->issue_delay, 1, issue_delay);

4539   }

4540   else

4541   {

4542     op->conflict_exp = true_rtx ;

4543     extend_range (&unit->issue_delay, issue_delay, issue_delay);

4544   }

4545

4546   /* Merge our conditional into that of the function unit so we can determine

4547     which insns are used by the function unit.  */

4548   unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2);

4549 }

 

function_unit condexp 域指向一个表达式,如果其值是 TURE ,表示需要这个单元。构建出来的 function_unit object 被保存在数组 units 里。

 

238  struct function_unit                                                                                     in genattrtab.c

239  {

240    const char *name;             /* Function unit name.  */

241    struct function_unit *next; /* Next function unit.  */

242    int num;                    /* Ordinal of this unit type.  */

243    int multiplicity;         /* Number of units of this type.  */

244    int simultaneity;  /* Maximum number of simultaneous insns

245                               on this function unit or 0 if unlimited.  */

246    rtx condexp;                     /* Expression TRUE for insn needing unit.  */

247    int num_opclasses;            /* Number of different operation types.  */

248    struct function_unit_op *ops;    /* Pointer to first operation type.  */

249    int needs_conflict_function;      /* Nonzero if a conflict function required.  */

250    int needs_blockage_function;    /* Nonzero if a blockage function required.  */

251    int needs_range_function;  /* Nonzero if blockage range function needed.  */

252    rtx default_cost;         /* Conflict cost, if constant.  */

253    struct range issue_delay;    /* Range of issue delay values.  */

254    int max_blockage;             /* Maximum time an insn blocks the unit.  */

255    int first_lineno;          /* First seen line number.  */

256  };

 

某些功能单元可能被多个指令组所使用(在一个 define_function_unit 里可以出现多个指令,我们称之为一组,因为如果出现,它们具有相似的发布延迟,就绪代价,及冲突列表)。因为每个组可能包含所涉及的特有的参数,这需要额外的数据结构。结构体 function_unit_op 为这个目的而设计。

 

223  struct function_unit_op                                                                         in genattrtab.c

224  {

225    rtx condexp;                     /* Expression TRUE for applicable insn.  */

226    struct function_unit_op *next; /* Next operation for this function unit.  */

227    int num;                    /* Ordinal for this operation type in unit.  */

228    int ready;                  /* Cost until data is ready.  */

229    int issue_delay;          /* Cost until unit can accept another insn.  */

230    rtx conflict_exp; /* Expression TRUE for insns incurring issue delay.  */

231    rtx issue_exp;            /* Expression computing issue delay.  */

232    int lineno;                 /* Line number.  */

233  };

 

在这里, function_unit_op 中的 condexp 域包含了识别组的测试的 rtx 对象。这很容易理解,在 gen_unit 里处理了所有相关的 define_cpu_unit 模式后, function_unit condexp 域由 insert_right_side 通过 IOR 所有从属的 function_unit_op condexp 得到。

insert_right_side 接受两个表达式,从它们来构建一个规范的 OR 表达式。这个函数具有以下定义。

 

2653 static rtx                                                                                            in genattrtab.c

2654 insert_right_side (enum rtx_code code, rtx exp, rtx term, int insn_code, int insn_index)

2655 {

2656   rtx newexp;

2657

2658   /* Avoid consing in some special cases.  */

2659   if (code == AND && term == true_rtx )

2660     return exp;

2661   if (code == AND && term == false_rtx )

2662     return false_rtx ;

2663   if (code == AND && exp == true_rtx )

2664     return term;

2665   if (code == AND && exp == false_rtx )

2666     return false_rtx ;

2667   if (code == IOR && term == true_rtx )

2668     return true_rtx ;

2669   if (code == IOR && term == false_rtx )

2670     return exp;

2671   if (code == IOR && exp == true_rtx )

2672     return true_rtx ;

2673   if (code == IOR && exp == false_rtx )

2674     return term;

2675   if (attr_equal_p (exp, term))

2676     return exp;

2677

2678   if (GET_CODE (term) == code)

2679   {

2680     exp = insert_right_side (code, exp, XEXP (term, 0),

2681                              insn_code, insn_index);

2682     exp = insert_right_side (code, exp, XEXP (term, 1),

2683                          insn_code, insn_index);

2684

2685     return exp;

2686   }

2687

2688   if (GET_CODE (exp) == code)

2689   {

2690     rtx new = insert_right_side (code, XEXP (exp, 1),

2691                      term, insn_code, insn_index);

2692     if (new != XEXP (exp, 1))

2693       /* Make a copy of this expression and call recursively.  */

2694       newexp = attr_rtx (code, XEXP (exp, 0), new);

2695     else

2696       newexp = exp;

2697   }

2698   else

2699   {

2700     /* Insert the new term.  */

2701     newexp = attr_rtx (code, exp, term);

2702   }

2703

2704   return simplify_test_exp_in_temp (newexp, insn_code, insn_index);

2705 }

 

对于我们的例子,我们在 2674 行返回。在 2678 行以下的代码用于复杂的情形来简化测试。在 2678 行的代码块用于转换形如: A AND B, B = C AND D 的表达式。在于这种情形,它将被转换为: (A AND C) AND D

类似的,对于形如: A AND B, A = C AND D 的表达式,它将被转换为 C AND (D AND B) ,其值如果“ D AND B ”等于 D ,“ A AND B ”可以被“ A ”所替代,这就是 2696 行的含义。并且如果“ D AND B ”不等于 D ,把语句分解为“ C ”,“ D AND B ”,这正是 2690 2696 行的目的。

2704 行, simplify_test_exp_in_temp 将执行更多的简化。我们在后面来看它。

9.3.6. 读入 DEFINE_CPU_UNIT 模式

DEFINE_INSN_RESERVATION模式的概览 一节描述了 define_cpu_unit 模式的细节。对于这个模式,我们使用以下的例子:

 

88    (define_cpu_unit "pentium-portu,pentium-portv" "pentium")                   in pentium.md

 

从这个模式开始,余下的这些模式用于构建基于 DFA 的流水线危险识别器,这是更新式的,与我们之前看到的指令级别并行性描述比较而言。至于这个新式形式的好处,同样参考 gccint 10.18.8 .3 节。这个模式不能与 define_function_unit 共存在同一个机器描述文件中。

在经过 init_md_reader_args 的处理后,上面的模式将作为以下的 rtx 对象载入内存。

t43

43 DEFINE_CPU_UNIT 模式的例子

Rtx 形式并不是我们所希望的,我们需要 gen_cpu_unit 来打包这些数据。

 

1652 void

1653 gen_cpu_unit (rtx def)                                                                        in genattrtab.c

1654 {

1655   decl_t decl;

1656   char **str_cpu_units;

1657   int vect_length;

1658   int i;

1659

1660   str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',

1661                             FALSE);

1662   if (str_cpu_units == NULL)

1663     fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));

1664   for (i = 0; i < vect_length; i++)

1665   {

1666     decl = create_node (sizeof (struct decl));

1667     decl->mode = dm_unit;

1668     decl->pos = 0;

1669     DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);

1670     DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);

1671     DECL_UNIT (decl)->query_p = 0;

1672     DECL_UNIT (decl)->min_occ_cycle_num = -1;

1673     DECL_UNIT (decl)->in_set_p = 0;

1674     VLA_PTR_ADD (decls , decl);

1675     num_dfa_decls ++;

1676   }

1677 }

 

所有单元的信息被保存在由 decls 指向的列表中 其类型如下。

 

907  struct decl                                                                                            in genautomata.c

908  {

909    /* What node in the union? */

910    enum decl_mode mode;

911    pos_t pos;

912    union

913    {

914      struct unit_decl unit;

915      struct bypass_decl bypass;

916      struct automaton_decl automaton;

917      struct excl_rel_decl excl;

918      struct unit_pattern_rel_decl presence;

919      struct unit_pattern_rel_decl absence;

920      struct reserv_decl reserv;

921      struct insn_reserv_decl insn_reserv;

922    } decl;

923  };

 

196  typedef struct decl *decl_t ;                                                                  in genautomata.c

 

Decl 是由所有类型的模式共享的类型,用于构建基于 DFA 的流水线危险识别器。对于 define_cup_unit 模式,使用了 unit_decl 域。

 

727  struct unit_decl                                                                                    in genautomata.c

728  {

729    char *name;

730    /* NULL if the automaton name is absent.  */

731    char *automaton_name;

732    /* If the following value is not zero, the cpu unit reservation is

733      described in define_query_cpu_unit.  */

734    char query_p;

735 

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

737 

738    /* The following field value is nonzero if the unit is used in an

739      regexp.  */

740    char unit_is_used;

741 

742    /* The following field value is order number (0, 1, ...) of given

743      unit.  */

744    int unit_num;

745    /* The following field value is corresponding declaration of

746      automaton which was given in description. If the field value is

747      NULL then automaton in the unit declaration was absent.  */

748    struct automaton_decl *automaton_decl;

749    /* The following field value is maximal cycle number (1, ...) on

750      which given unit occurs in insns. Zero value means that given

751      unit is not used in insns.  */

752    int max_occ_cycle_num;

753    /* The following field value is minimal cycle number (0, ...) on

754      which given unit occurs in insns. -1 value means that given

755      unit is not used in insns.  */

756    int min_occ_cycle_num;

757    /* The following list contains units which conflict with given

758      unit.  */

759    unit_set_el_t excl_list;

760    /* The following list contains patterns which are required to

761      reservation of given unit.  */

762    pattern_set_el_t presence_list;

763    pattern_set_el_t final_presence_list;

764    /* The following list contains patterns which should be not present

765      i n reservation for given unit.  */

766    pattern_set_el_t absence_list;

767    pattern_set_el_t final_absence_list;

768    /* The following is used only when `query_p' has nonzero value.

769      This is query number for the unit.  */

770    int query_num;

771    /* The following is the last cycle on which the unit was checked for

772      correct distributions of units to automata in a regexp.  */

773    int last_distribution_check_cycle;

774 

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

776 

777    /* The following field value is number of the automaton to which

778      given unit belongs.  */

779    int corresponding_automaton_num;

780    /* If the following value is not zero, the cpu unit is present in a

781      `exclusion_set' or in right part of a `presence_set',

782      `final_presence_set', `absence_set', and

783      `final_absence_set'define_query_cpu_unit.  */

784    char in_set_p;

785  };

 

在上面的 1660 行, get_str_vec 获取由“ , ”分隔的单元名。宏 DECL_UNIT 将访问 decl unit_decl 域。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值