GCC后端及汇编发布(20)

9.3.11.      读入 DEFINE_RESERVATION 模式

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 对象的例子

9.3.12.      读入 DEFINE_INSN_RESERVATION 模式

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 对象载入内存。

GCC后端及汇编发布(20)_第1张图片

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 处理后,产生以下的数据。

GCC后端及汇编发布(20)_第2张图片

50 :为 define_insn_reservation 模式产生的 regexp 的例子

你可能感兴趣的:(正则表达式,struct,汇编,function,list,gcc)