9.6.2. 输出delay的数据
对于i386架构,没有使用define_delay。不过,还是值得看一下这个模式如何工作。
main (continued)
6212 /* Write out delay eligibility information,if DEFINE_DELAY present.
6213 (The function to compute the number ofdelay slots will be written
6214 below.) */
6215 if (num_delays)
6216 {
6217 write_eligible_delay("delay");
6218 if (have_annul_true)
6219 write_eligible_delay("annul_true");
6220 if (have_annul_false)
6221 write_eligible_delay("annul_false");
6222 }
在expand_delays中,系统将创建以下形式的属性“*delay_type”:
*delay_type(
cond ([
(condexp-1) ;; test part of first define_delay
(const_string “1”) ;;NO. of the define_delay
(condexp-2) ;; test part of second define_delay
(const_string “2”) ;; NO. of the define_delay
… ;; other define_delay
]
const_string “0”)
)
然后是一系列包含以下数据的属性“*delay_`NO`_`slot-NO`”。指向属性显示要放入该槽的指令所必须满足的测试。
*delay_`NO`_`slot-NO` (
cond [ (DELAY-`slot-NO`“1”) ] ;; attribute test for delay slot
“0”)
)
接着是一系列包含以下数据的属性“*annul_true_`NO`_`slot-NO`”这些属性显示,如果该跳转为真时要取消的指令,必须满足的测试。
*annul_true_`NO`_`slot-NO` (
cond [ (ANNUL-TRUE-`slot-NO` “1”) ] ;;attribute test for insn annul
“0”)
)
跟着是一系列包含以下数据的属性“*annul_false_`NO`_`slot-NO`”。这些属性显示如果该跳转为假时要取消的指令,必须满足的测试。
*annul_false_`NO`_`slot-NO` (
cond [ (ANNUL-FALSE-`slot-NO` “1”) ] ;;attribute test for insn annul
“0”)
)
注意虽然expand_delay为后三个系列属性使用if_then_else,它用来构建这些属性的make_internal_attr将通过make_canonical把if_then_else转换为cond。在这里的write_eligible_delay将为这些属性输出函数。
5497 static void
5498 write_eligible_delay (const char *kind) in genattrtab.c
5499 {
5500 struct delay_desc*delay;
5501 int max_slots;
5502 char str[50];
5503 const char*pstr;
5504 struct attr_desc*attr;
5505 struct attr_value*av, *common_av;
5506 int i;
5507
5508 /* Compute themaximum number of delay slots required. We use the delay
5509 ordinal times this number plus one, plusthe slot number as an index into
5510 the appropriate predicate to test. */
5511
5512 for (delay = delays,max_slots = 0; delay; delay = delay->next)
5513 if (XVECLEN (delay->def, 1) / 3 >max_slots)
5514 max_slots = XVECLEN (delay->def, 1) /3;
5515
5516 /* Write functionprelude. */
5517
5518 printf ("int\n");
5519 printf ("eligible_for_%s (rtx delay_insnATTRIBUTE_UNUSED, int slot, rtx
5520 candidate_insn, int flags ATTRIBUTE_UNUSED)\n", kind);
5521 printf ("{\n");
5522 printf (" rtx insn;\n");
5523 printf ("\n");
5524 printf (" if (slot >= %d)\n", max_slots);
5525 printf (" abort ();\n");
5526 printf ("\n");
5527
5528 /* If more than onedelay type, find out which type the delay insn is. */
5529
5530 if (num_delays > 1)
5531 {
5532 attr = find_attr(&delay_type_str,0);
5533 if (! attr)
5534 abort ();
5535 common_av = find_most_used (attr);
5536
5537 printf (" insn = delay_insn;\n");
5538 printf (" switch (recog_memoized (insn))\n");
5539 printf (" {\n");
5540
5541 sprintf (str, " * %d;\n break;", max_slots);
5542 for (av =attr->first_value; av; av = av->next)
5543 if (av != common_av)
5544 write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);
5545
5546 write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
5547 printf (" }\n\n");
5548
5549 /* Ensurematched. Otherwise, shouldn't have been called. */
5550 printf (" if (slot < %d)\n", max_slots);
5551 printf (" abort ();\n\n");
5552 }
5553
5554 /* If just one typeof delay slot, write simple switch. */
5555 if (num_delays == 1 && max_slots == 1)
5556 {
5557 printf (" insn = candidate_insn;\n");
5558 printf (" switch (recog_memoized (insn))\n");
5559 printf (" {\n");
5560
5561 attr = find_attr(&delay_1_0_str,0);
5562 if (! attr)
5563 abort ();
5564 common_av = find_most_used (attr);
5565
5566 for (av =attr->first_value; av; av = av->next)
5567 if (av != common_av)
5568 write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
5569
5570 write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
5571 printf (" }\n");
5572 }
5573
5574 else
5575 {
5576 /* Write a nestedCASE. The first indicates which condition we need to
5577 test, and the inner CASE tests thecondition. */
5578 printf (" insn = candidate_insn;\n");
5579 printf (" switch (slot)\n");
5580 printf (" {\n");
5581
5582 for (delay= delays;delay; delay = delay->next)
5583 for (i =0; i < XVECLEN (delay->def, 1); i += 3)
5584 {
5585 printf (" case %d:\n",
5586 (i / 3) + (num_delays == 1 ? 0 : delay->num* max_slots));
5587 printf (" switch (recog_memoized (insn))\n");
5588 printf ("\t{\n");
5589
5590 sprintf (str, "*%s_%d_%d",kind, delay->num, i / 3);
5591 pstr = str;
5592 attr = find_attr(&pstr, 0);
5593 if (! attr)
5594 abort ();
5595 common_av = find_most_used (attr);
5596
5597 for (av= attr->first_value; av; av = av->next)
5598 if (av != common_av)
5599 write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);
5600
5601 write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
5602 printf (" }\n");
5603 }
5604
5605 printf (" default:\n");
5606 printf (" abort ();\n");
5607 printf (" }\n");
5608 }
5609
5610 printf ("}\n\n");
5611 }
我们以eligible_for_delay为例,看一下我们会得到什么。eligible_for_delay为属性“*delay_type”及“*delay_`NO`_`slot-NO`”所产生。
int
eligible_for_delay(rtx delay_insn ATTRIBUTE_UNUSED, int slot, rtx
candidate_insn, int flags ATTRIBUTE_UNUSED)
{
rtx insn;
if (slot >= `max_slot`) // max_slot records the biggest slot number indefine_delays.
abort();
insn = delay_insn;
switch (recog_memoized (insn))
{
case `insn-code-m` : // insn of code m matching define_delay of n
case … // other matching insns
extract_constrain_insn_cached (insn); // used according to attr char.
extract_insn_cached(insn); // used according to attr char.
if (`condexp-n-s`) // test partof define_delay of n after simplified
{
slot += n * `max_slot ;
break ;
}
else
{
slot+= 0 * `max_slot` ; // should not happen
break ;
}
… // other insns
default:
extract_constrain_insn_cached (insn); // used according to attr char.
extract_insn_cached(insn); // used according to attr char.
if (`condexp-d-s`) // test partof most common used delay after simplified
{
slot += d * `max_slot ; // d is num of most common used delay
break ;
}
else
{
slot += 0 ; // slot +=0 * `max_slot`, should not happen
break ;
}
}
if (slot < `max_slot`)
abort() ;
insn = candidate_insn;
switch (slot)
{
case0 * `max_slot` + 0:
switch (recog_memoized (insn))
{
case`insn-code-p` : // insn of code p matching define_delay of 0
case… : // other matching insns
extract_constrain_insn_cached(insn); // usedaccording to attr char.
extract_insn_cached(insn); // used according to attr char.
if (`delay-0-0-s`) // attr testfor 0 slot of define_delay of 0 after simplified
return 1 ;
else
return0 ;
break ;
… // other insns
default :
extract_constrain_insn_cached (insn); // used according to attr char.
extract_insn_cached(insn); // used according to attr char.
if (`delay-0-d-s`) // attr test for slotof most used of define_delay of 0 after simplified
return1 ;
else
return0 ;
}
case 0 *`max_slot` + 1 :
… // other slots
default :
abort() ;
}
}
eligible_for_delay给定指令delay_insn,检查指令candidate_insn是否可以被放入槽slot。注意`delay-NO` * `max_slot` + `slot-NO`的使用,及如何从相关属性获取数据。