9.3.11. Read in DEFINE_RESERVATION pattern
Section 8.1.3 Overview of DEFINE_INSN_RESERVATION pattern describes the detail of DEFINE_RESERVATION pattern. For this pattern we use following example:
129 (define_reservation "pentium-firstuvboth" "(pentium-load + pentium-firstuv in pentium.md
130 + pentium-memory)
131 | (pentium-firstv,pentium-v,
132 (pentium-load+pentium-firstv))")
This pattern is part of pipe hazards description for construting DFA-based recognizer, this pattern shouldn’t coexist with define_function_unit in same machine description file.
After treated by init_md_reader_args , above pattern will be loaded into memory as rtx object as following.
figure 47 : example of DEFINE_RESERVATION pattern
Obviously, this primitive form isn’t what we want. gen_reserv generates more organized ones.
2106 void
2107 gen_reserv (rtx def) in genautomata.c
2108 {
2109 decl_t decl;
2110
2111 decl = create_node (sizeof (struct decl));
2112 decl->mode = dm_reserv;
2113 decl->pos = 0;
2114 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2115 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2116 VLA_PTR_ADD (decls , decl);
2117 num_dfa_decls ++;
2118 }
DECL_RESERV accesses reserv field of decl.
845 struct reserv_decl in genautomata.c
846 {
847 char *name;
848 regexp_t regexp;
849
850 /* The following fields are defined by checker. */
851
852 /* The following field value is nonzero if the unit is used in an
853 regexp. */
854 char reserv_is_used;
855 /* The following field is used to check up cycle in expression
856 definition. */
857 int loop_pass_num;
858 };
regexp is designed for regular expression describing the occupation of cpu units for certain instructions. Refer to 8.1.3 Overview of DEFINE_INSN_RESERVATION pattern for detail of the regular expression.
990 struct regexp in genautomata.c
991 {
992 /* What node in the union? */
993 enum regexp_mode mode;
994 pos_t pos;
995 union
996 {
997 struct unit_regexp unit;
998 struct reserv_regexp reserv;
999 struct nothing_regexp nothing;
1000 struct sequence_regexp sequence;
1001 struct repeat_regexp repeat;
1002 struct allof_regexp allof;
1003 struct oneof_regexp oneof;
1004 } regexp;
1005 };
197 typedef struct regexp *regexp_t; in genautomata.c
This structure is generated by gen_regexp . The regular expression obeys following sytanx:
regexp = regexp "," oneof
| oneof
oneof = oneof "|" allof
| allof
allof = allof "+" repeat
| repeat
repeat = element "*" number
| element
element = cpu_function_unit_name
| reservation_name
| result_name
| "nothing"
| "(" regexp ")"
gen_regexp forms the regexp object from the expression string in above figure.
2094 static regexp_t
2095 gen_regexp (char *str) in genautomata.c
2096 {
2097 reserv_str = str;
2098 return gen_regexp_sequence (str);;
2099 }
gen_regexp generates the structure by parsing the expression from top-down. For our example, the expression is "(pentium-load + pentium-firstuv + pentium-memory) | (pentium-firstv, pentium-v, (pentium-load + pentium-firstv))".
2069 static regexp_t
2070 gen_regexp_sequence (char *str) in genautomata.c
2071 {
2072 regexp_t sequence;
2073 char **sequence_vect;
2074 int els_num;
2075 int i;
2076
2077 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
2078 if (els_num > 1)
2079 {
2080 sequence = create_node (sizeof (struct regexp)
2081 + sizeof (regexp_t) * (els_num - 1));
2082 sequence->mode = rm_sequence;
2083 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2084 for (i = 0; i < els_num; i++)
2085 REGEXP_SEQUENCE (sequence)->regexps [i]
2086 = gen_regexp_oneof (sequence_vect [i]);
2087 return sequence;
2088 }
2089 else
2090 return gen_regexp_oneof (str);
In regular expression `,' is used for indicating the start of the next cycle in the units reservation. At line 2077, get_str_vect tries to separate the regular expression into cycles. Notice that the third parameter of the funciton is TRUE, the separation will be done only the left and right parentheses are balanced. At both sides of “,” maybe the expression of “|”, so gen_regexp_oneof is invoked to handle both sides.
2043 static regexp_t
2044 gen_regexp_oneof (char *str) in genautomata.c
2045 {
2046 regexp_t oneof;
2047 char **oneof_vect;
2048 int els_num;
2049 int i;
2050
2051 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
2052 if (oneof_vect == NULL)
2053 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2054 if (els_num > 1)
2055 {
2056 oneof = create_node (sizeof (struct regexp )
2057 + sizeof ( regexp_t ) * (els_num - 1));
2058 oneof->mode = rm_oneof;
2059 REGEXP_ONEOF (oneof)->regexps_num = els_num;
2060 for (i = 0; i < els_num; i++)
2061 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
2062 return oneof;
2063 }
2064 else
2065 return gen_regexp_allof (str);
2066 }
This time get_str_vect tries to split the string by ‘|’. Again the third parameter of get_str_vect is TRUE, so for our example, we can get oneof_vect at line 2051 with two elements:
"(pentium-load + pentium-firstuv + pentium-memory)"
"(pentium-firstv, pentium-v, (pentium-load + pentium-firstv))"
The second one can’t be split by get_str_vect with “,” because no “,” can be seen when “(“ balances “)”.
Above at line 2059, macro REGEXP_ONEOF accesses oneof field of regexp , which has definition as following, in which regexps field is a variable array, the size of it depends on the number of operants of “|” (see line 2056 above).
983 struct oneof_regexp in genautomata.c
984 {
985 int regexps_num;
986 regexp_t regexps [1];
987 };
Inside expression of “|”, we may encounter expression of “+”, so we need gen_regexp_allof to handle the separated fragments.
2017 static regexp_t
2018 gen_regexp_allof (char *str) in genautomata.c
2019 {
2020 regexp_t allof;
2021 char **allof_vect;
2022 int els_num;
2023 int i;
2024
2025 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
2026 if (allof_vect == NULL)
2027 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2028 if (els_num > 1)
2029 {
2030 allof = create_node (sizeof (struct regexp)
2031 + sizeof (regexp_t) * (els_num - 1));
2032 allof->mode = rm_allof;
2033 REGEXP_ALLOF (allof)->regexps_num = els_num;
2034 for (i = 0; i < els_num; i++)
2035 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
2036 return allof;
2037 }
2038 else
2039 return gen_regexp_repeat (str);
2040 }
get_str_vect at line 2025 now tries to find out the parts joined by ‘+’, again the third parameter of it is TRUE, balanced parentheses is wanted.
Now for our example, the regular expression had been split into two parts. For both parts, get_str_vect fails to do further split. Both them enter gen_regexp_repeat at line 2039.
1984 static regexp_t
1985 gen_regexp_repeat (char *str) in genautomata.c
1986 {
1987 regexp_t regexp;
1988 regexp_t repeat;
1989 char **repeat_vect;
1990 int els_num;
1991 int i;
1992
1993 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1994 if (repeat_vect == NULL)
1995 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1996 if (els_num > 1)
1997 {
1998 regexp = gen_regexp_el (repeat_vect [0]);
1999 for (i = 1; i < els_num; i++)
2000 {
2001 repeat = create_node (sizeof (struct regexp));
2002 repeat->mode = rm_repeat;
2003 REGEXP_REPEAT (repeat)->regexp = regexp;
2004 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
2005 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
2006 fatal ("repetition `%s' <= 1 in reservation `%s'",
2007 str, reserv_str);
2008 regexp = repeat;
2009 }
2010 return regexp;
2011 }
2012 else
2013 return gen_regexp_el (str);
2014 }
Remember that `*' is used for convenience and simply means a sequence in which the regular expression are repeated NUMBER times with cycle advancing. For example, *5 means repeating for 5 times. In our example, both parts don’t contain ‘*’, they just enter gen_regexp_el at line 2013.
1955 static regexp_t
1956 gen_regexp_e l (char *str) in genautomata.c
1957 {
1958 regexp_t regexp;
1959 int len;
1960
1961 if (*str == '(')
1962 {
1963 len = strlen (str);
1964 if (str [len - 1] != ')')
1965 fatal ("garbage after ) in reservation `%s'", reserv_str);
1966 str [len - 1] = '/0';
1967 regexp = gen_regexp_sequence (str + 1);
1968 }
1969 else if (strcmp (str, NOTHING_NAME) == 0)
1970 {
1971 regexp = create_node (sizeof (struct decl));
1972 regexp->mode = rm_nothing;
1973 }
1974 else
1975 {
1976 regexp = create_node (sizeof (struct decl));
1977 regexp->mode = rm_unit;
1978 REGEXP_UNIT (regexp)->name = str;
1979 }
1980 return regexp;
1981 }
For our example, both two parts are enclosed by parentheses within which should be regarded as a sequence. So gen_regexp_sequence will be recursed at line 1967. In the end the example is transformed to following structure.
figure 48 : example of regexp object generated for define_ reservation pattern
9.3.12. Read in DEFINE_INSN_RESERVATION pattern
Section 8.1.3 Overview of DEFINE_INSN_RESERVATION pattern describes the detail of DEFINE_INSN_RESERVATION pattern. For this pattern, we use following example.
166 (define_insn_reservation "pent_fpmovxf" 3 in pentium.md
167 (and (eq_attr "cpu" "pentium")
168 (and (eq_attr "type" "fmov")
169 (and (eq_attr "memory" "load,store")
170 (eq_attr "mode" "XF"))))
171 "(pentium-fp+pentium-np)*3")
This pattern is part of pipe hazards description for construting DFA-based recognizer, this pattern shouldn’t coexist with define_function_unit in same machine description file. As we have discussed in 9.3.5 Read DEFINE_FUNCTION_UNIT pattern , this pattern describes system from the view-point of instructions instead of the view-point of function units. Commonly, number of instructions is much larger than the number of units, so automaton is the better form for the pipeline hazard recognizer.
After treated by init_md_reader_args , above pattern will be loaded into memory as rtx object as following.
figure 148 : example of DEFINE_INSN_RESERVATION pattern
This rtx object is not eligible for constructing DFA-based pipeline hazards recognizer. gen_insn_reserv is invoked to pack up the data.
2125 void
2126 gen_insn_reserv (rtx def) in genautomata.c
2127 {
2128 decl_t decl;
2129
2130 decl = create_node (sizeof (struct decl));
2131 decl->mode = dm_insn_reserv;
2132 decl->pos = 0;
2133 DECL_INSN_RESERV (decl)->name
2134 = check_name ((char *) XSTR (def, 0), decl->pos);
2135 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2136 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2137 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2138 VLA_PTR_ADD (decls , decl);
2139 num_dfa_decls ++;
2140 }
Macro DECL_INSN_RESERV accesses insn_reserv field of decl, which has definition as following.
861 struct insn_reserv_decl in genautomata.c
862 {
863 rtx condexp;
864 int default_latency;
865 regexp_t regexp;
866 char *name;
867
868 /* The following fields are defined by checker. */
869
870 /* The following field value is order number (0, 1, ...) of given
871 insn. */
872 int insn_num;
873 /* The following field value is list of bypasses in which given insn
874 is output insn. */
875 struct bypass_decl *bypass_list;
876
877 /* The following fields are defined by automaton generator. */
878
879 /* The following field is the insn regexp transformed that
880 the regexp has not optional regexp, repetition regexp, and an
881 reservation name (i.e. reservation identifiers are changed by the
882 corresponding regexp) and all alternations are the topest level
883 of the regexp. The value can be NULL only if it is special
884 insn `cycle advancing'. */
885 regexp_t transformed_regexp;
886 /* The following field value is list of arcs marked given
887 insn. The field is used in transformation NDFA -> DFA. */
888 arc_t arcs_marked_by_insn;
889 /* The two following fields are used during minimization of a finite state
890 automaton. */
891 /* The field value is number of equivalence class of state into
892 which arc marked by given insn enters from a state (fixed during
893 an automaton minimization). */
894 int equiv_class_num;
895 /* The field value is state_alts of arc leaving a state (fixed
896 during an automaton minimization) and marked by given insn
897 enters. */
898 int state_alts;
899 /* The following member value is the list to automata which can be
900 changed by the insn issue. */
901 automata_list_el_t important_automata_list;
902 /* The following member is used to process insn once for output. */
903 int processed_p;
904 };
In gen_insn_reserv , at line 2138 the parameter of gen_regexp is "(pentium-fp+pentium-np)*3". This part after handled by gen_regexp producing following data.
figure 50 : example of regexp generated for define_insn_reservation pattern