9.4. Construct old style pipeline hazards recognizer
Now data needed has been read from machine description file, and corresponding rtx objects have been created. However, rtx object is still too coarse for generating pipeline hazards recognizer. Further structured data will be generated from rtx objects created in above sections.
main (continued)
6111 if (have_error )
6112 return FATAL_EXIT_CODE;
6113
6114 insn_code_number ++;
6115
6116 /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one. */
6117 if (! got_define_asm_attributes )
6118 {
6119 tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
6120 XVEC (tem, 0) = rtvec_alloc (0);
6121 gen_insn (tem, 0);
6122 }
6123
6124 /* Expand DEFINE_DELAY information into new attribute. */
6125 if (num_delays )
6126 expand_delays ();
9.4.1. Handling DEFINE_DELAY pattern
In above preparation section, define_delay is linked in list of delay_desc referred by delays . Though function units tell how they are used by instructions via define_function_unit pattern, or instructions tell how they use function units via define_insn_reservation pattern, and these patterns form the core of the pipeline hazards recognizer, they tell little about instructions themselves. Other patterns, i.e., define_insn, define_delay, define_attr etc give the detail of instruction in interested. Then the detail will be turned into attributes for instruction. It is what the data we want.
expand_delays produces attributes for define_delay. Notice that define_delay definition also may used in the new way chip description, this section is also applied to 9.5 Construct DFA-based pipeline hazards recognizer .
1526 static void
1527 expand_delays (void) in genautomata.c
1528 {
1529 struct delay_desc *delay;
1530 rtx condexp;
1531 rtx newexp;
1532 int i;
1533 char *p;
1534
1535 /* First, generate data for `num_delay_slots' function. */
1536
1537 condexp = rtx_alloc (COND);
1538 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1539 XEXP (condexp, 1) = make_numeric_value (0);
1540
1541 for (i = 0, delay = delays ; delay; i += 2, delay = delay->next)
1542 {
1543 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1544 XVECEXP (condexp, 0, i + 1)
1545 = make_numeric_value (XVECLEN (delay->def, 1) / 3);
1546 }
1547
1548 make_internal_attr (num_delay_slots_str , condexp, ATTR_NONE);
1549
1550 /* If more than one delay type, do the same for computing the delay type. */
1551 if (num_delays > 1)
1552 {
1553 condexp = rtx_alloc (COND);
1554 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1555 XEXP (condexp, 1) = make_numeric_value (0);
1556
1557 for (i = 0, delay = delays ; delay; i += 2, delay = delay->next)
1558 {
1559 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1560 XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
1561 }
1562
1563 make_internal_attr (delay_type_str , condexp, ATTR_SPECIAL);
1564 }
num_delay_slots_str and delay_type_str are created and saved into hash table at program entry. For num_delay_slots_str , its content is "*num_delay_slots", and for delay_type_str , its content is "*delay_type".
condexp created at line 1537 records the testing part and the number of delay slots for every define_attr patterns, which is the content of attribute of "*num_delay_slots".
condexp created at line 1553 records the condition part with the delay No. for every define_attr patterns, which is the content of attribute of "*delay_type".
Above make_numeric_value is used to create corresponding rtx object of numeric value.
5911 rtx
5912 make_numeric_value (int n) in genautomata.c
5913 {
5914 static rtx int_values[20];
5915 rtx exp;
5916 char *p;
5917
5918 if (n < 0)
5919 abort ();
5920
5921 if (n < 20 && int_values[n])
5922 return int_values[n];
5923
5924 p = attr_printf (MAX_DIGITS, "%d", n);
5925 exp = attr_rtx (CONST_STRING, p);
5926
5927 if (n < 20)
5928 int_values[n] = exp;
5929
5930 return exp;
5931 }
Then function make_internal_attr fills out attr_desc . Notice that in writing attribute of "*delay_type", ATTR_SPECIAL is passed to make_internal_attr , which later in generating output file will skip the invocation of write_attr_set .
5848 void
5849 make_internal_attr (const char *name, rtx value, int special) in genattrtab.c
5850 {
5851 struct attr_desc *attr;
5852
5853 attr = find_attr (&name, 1);
5854 if (attr->default_val)
5855 abort ();
5856
5857 attr->is_numeric = 1;
5858 attr->is_const = 0;
5859 attr->is_special = (special & ATTR_SPECIAL) != 0;
5860 attr->negative_ok = (special & ATTR_NEGATIVE_OK) != 0;
5861 attr->unsigned_p = (special & ATTR_UNSIGNED) != 0;
5862 attr->func_units_p = (special & ATTR_FUNC_UNITS) != 0;
5863 attr->blockage_p = (special & ATTR_BLOCKAGE) != 0;
5864 attr->static_p = (special & ATTR_STATIC) != 0;
5865 attr->default_val = get_attr_value (value, attr, -2);
5866 }
expand_delays then creates attributes for every define_delay definition. Notice that flag ATTR_SPECIAL passed for all these attributes too.
expand_delays (continued)
1526 /* For each delay possibility and delay slot, compute an eligibility
1527 attribute for non-annulled insns and for each type of annulled (annul
1528 if true and annul if false). */
1529 for (delay = delays ; delay; delay = delay->next)
1530 {
1531 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
1532 {
1533 condexp = XVECEXP (delay->def, 1, i);
1534 if (condexp == 0)
1535 condexp = false_rtx ;
1536 newexp = attr_rtx (IF_THEN_ELSE, condexp,
1537 make_numeric_value (1), make_numeric_value (0));
1538
1539 p = attr_printf (sizeof "*delay__" + MAX_DIGITS * 2,
1540 "*delay_%d_%d", delay->num, i / 3);
1541 make_internal_attr (p, newexp, ATTR_SPECIAL);
1542
1543 if (have_annul_true )
1544 {
1545 condexp = XVECEXP (delay->def, 1, i + 1);
1546 if (condexp == 0) condexp = false_rtx ;
1547 newexp = attr_rtx (IF_THEN_ELSE, condexp,
1548 make_numeric_value (1),
1549 make_numeric_value (0));
1550 p = attr_printf (sizeof "*annul_true__" + MAX_DIGITS * 2,
1551 "*annul_true_%d_%d", delay->num, i / 3);
1552 make_internal_attr (p, newexp, ATTR_SPECIAL);
1553 }
1554
1555 if (have_annul_false )
1556 {
1557 condexp = XVECEXP (delay->def, 1, i + 2);
1558 if (condexp == 0) condexp = false_rtx ;
1559 newexp = attr_rtx (IF_THEN_ELSE, condexp,
1560 make_numeric_value (1),
1561 make_numeric_value (0));
1562 p = attr_printf (sizeof "*annul_false__" + MAX_DIGITS * 2,
1563 "*annul_false_%d_%d", delay->num, i / 3);
1564 make_internal_attr (p, newexp, ATTR_SPECIAL);
1565 }
1566 }
1567 }
1568 }
Above, have_annul_true is 1 when some instructions can be annulled if branch is true; similiar have_annul_false is 1 when some instructions can be annulled if branch is false. They also should be saved as attributes too.