DEFINE_INSN_RESERVATION模式的概览 一节描述了 DEFINE_RESERVATION 模式的细节。对于这个模式,我们使用以下的例子:
129 (define_reservation "pentium-firstuvboth" "(pentium-load + pentium-firstuv in pentium.md
130 + penti um-memory)
131 | (pentium-firstv,pentium-v,
132 (pentium-load+pentium-firstv))")
这个模式是构建基于 DFA 识别器的流水线危险描述的一部分 , 该模式不应该与 define_function_unit 共存于同一个机器描述文件里。
在经过 init_md_reader_args 的处理后 , 上面的模式将作为以下的 rtx 对象载入内存。
图 47 : DEFINE_RESERVATION 模式的例子
显然这个原始的形式不是我们想要的。 gen_reserv 产生更有序的对象。
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 访问 decl 的 reserv 域。
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 设计用于描述指令对 cpu 单元占据的正则表达式。正则表达式的细节参考 DEFINE_INSN_RESERVATION模式的概览 一节。
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
这个结构体由 gen_regexp 生成。正则表达式遵循以下的语法:
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 根据上图中的正则表达式,构成 regexp 对象。
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 通过从顶向下解析表达式来生成这个结构体。对于我们的例子,这个表达式是“ (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);
在正则表达式中,‘ , ’用于表示在单元预订中下一个周期的开始。在 2077 行, get_str_vect 尝试把这个正则表达式分解成周期。注意到该函数的第三个参数是 TRUE ,表示这个分解,仅当左右括号数目匹配时,才被执行。在“ , ”的两边可能是“ | ”表达式,因此调用 gen_regexp_oneof 来处理这两边。
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 }
这次 get_str_vect 尝试根据‘ | ’来分解字符串。再次, get_str_vect 的第三个参数是 TRUE ,因此对于我们的例子,我们可以在 2051 行得到具有两个元素的 oneof_vect :
"(pentium-load + pentium-firstuv + pentium-memory)"
"(pentium-firstv, pentium-v, (pentium-load + pentium-firstv))"
第二个不能被 get_str_vect 根据“ , ”来分解,因为当“ ( ”的数目匹配“ ) ”时,没有 “ , ”可见。
上面在 2059 行,宏 REGEXP_ONEOF 访问 regexp 的 oneof 域,它具有如下的定义,其中 regexps 域是一个可变长度数组,其大小依赖于“ | ”操作符的数目(参见上面的 2056 行)。
983 struct oneof_regexp in genautomata.c
984 {
985 int regexps_num;
986 regexp_t regexps [1];
987 };
在“ | ”表达式中,我们可能遇到“ + ”表达式,因此我们需要 gen_regexp_allof 来处理这些分解的片段。
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 }
在 2025 行的 get_str_vect 这次尝试找出由‘ + ’连接的部分,再次第三个参数是 TRUE ,只有匹配的括号对才被考虑。
现在对于我们的例子,正则表达式已经被分解为两部分。对于这两部分 get_str_vect 不能进一步分解。这两者都在 2039 行进入 gen_regexp_repeat 。
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 }
记得‘ * ’为了方便使用,它仅简单地表示一个序列,在其中这个正则表达式重复 NUMBER 次,同时伴随周期的推进。例如, *5 表示重复 5 次。在我们的例子中,这两部分都不包含‘ * ’,它们只是在 2013 行进入 gen_regexp_el 。
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 }
在这个例子中,这两部分都被括号所包围,括号之间应该被视为一个序列。因此 gen_regexp_sequence 将在 1967 行被递归。最后这个例子被转换到如下的结构。
图 48 :为 define_ reservation 模式所产生的 regexp 对象的例子
DEFINE_INSN_RESERVATION模式的概览 一节描述了 DEFINE_INSN_RESERVATION 模式的细节。对于这个模式,我们使用如下的例子:
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")
这个模式是构建基于 DFA 识别器的流水线危险描述的一部分 , 该模式不应该与 define_function_unit 共存于同一个机器描述文件里。正如我们在 读入 DEFINE_FUNCTION_UNIT模式 已经所讨论的, 这个模式以指令的角度来描述系统,而不是从功能单元的角度。通常,指令的数目要远远多于功能单元的数目,因此自动机,对于流水线危险识别器来说,是一个更好的形式。
在经过 init_md_reader_args 的处理后 , 上面的模式将作为以下的 rtx 对象载入内存。
图 49 : DEFINE_INSN_RESERVATION 模式的例子
这个 rtx 对象对于构建基于 DFA 的流水线危险识器起重要作用。 gen_insn_reserv 被调用来收集数据。
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 }
宏 DECL_INSN_RESERV 访问 decl 的 insn_reserv 域,它具有如下的定义。
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 };
在 gen_insn_reserv 中的 2138 行, gen_regexp 的参数是“ (pentium-fp+pentium-np)*3 ”。 这部分在 gen_regexp 处理后,产生以下的数据。
图 50 :为 define_insn_reservation 模式产生的 regexp 的例子