GCC后端及汇编发布(22)

9.4.2. 处理 DEFINE_FUNCTION_UNIT 模式

我们已经知道 define_function_unit 从功能单元的角度来描述芯片。不过,这个模式仍然主要是人类可读的形式。我们必须构建可以容易被工具处理,来为流水线危险识别器输出函数的数据。这个旧式的芯片描述比新式的要简单得多,这里构建的数据仍然是属性。

 

main (continued)

 

6128   if (num_units || num_dfa_decls )

6129   {

6130     /* Expand DEFINE_FUNCTION_UNIT information into new attributes.  */

6131     expand_units ();

6132      /* Build DFA, output some functions and expand DFA information

6133     into new attributes.  */

6134     expand_automata ();

6135   }

 

对于我们的例子,在由 gen_unit 生成之后,我们可以得到如下数据(至于没有显示的域,表示其内容为 0 )。

t51

51 FUNCTION_UNIT 的例子

以上形式的数据并不适合简单、直接地用于构建流水线危险识别器。我们需要 expand_units 来获取信息,然后通过把这些信息放入哈希表及构建相应的属性,使它们永久化。

 

1812 static void

1813 expand_units (void)                                                                            in genattrtab.c

1814 {

1815   struct function_unit *unit, **unit_num;

1816   struct function_unit_op *op, **op_array, ***unit_ops;

1817   rtx unitsmask;

1818   rtx readycost;

1819   rtx newexp;

1820   const char *str;

1821   int i, j, u, num, nvalues;

1822

1823   /* Rebuild the condition for the unit to share the RTL expressions.

1824     Sharing is required by simplify_by_exploding. Build the issue delay

1825     expressions. Validate the expressions we were given for the conditions

1826     and conflict vector. Then make attributes for use in the conflict

1827     function.  */

1828

1829   for (unit = units ; unit; unit = unit->next)

1830   {

1831     unit->condexp = check_attr_test (unit->condexp, 0, unit->first_lineno);

1832

1833     for (op = unit->ops; op; op = op->next)

1834     {

1835        rtx issue_delay = make_numeric_value (op->issue_delay);

1836        rtx issue_exp = issue_delay;

1837

1838        /* Build, validate, and simplify the issue delay expression.  */

1839        if (op->conflict_exp != true_rtx )

1840          issue_exp = attr_rtx (IF_THEN_ELSE, op->conflict_exp,

1841                    issue_exp, make_numeric_value (0));

1842        issue_exp = check_attr_value (make_canonical (NULL_ATTR,

1843                                              issue_exp),

1844                                 NULL_ATTR);

1845        issue_exp = simplify_knowing (issue_exp, unit->condexp);

1846        op->issue_exp = issue_exp;

1847

1848        /* Make an attribute for use in the conflict function if needed.  */

1849        unit->needs_conflict_function = (unit->issue_delay.min

1850                                   != unit->issue_delay.max);

1851        if (unit->needs_conflict_function)

1852        {

1853          str = attr_printf ((strlen (unit->name) + sizeof "*_cost_"

1854                              + MAX_DIGITS),

1855                      "*%s_cost_%d", unit->name, op->num);

1856          make_internal_attr (str, issue_exp, ATTR_SPECIAL);

1857        }

1858

1859         /* Validate the condition.  */

1860        op->condexp = check_attr_test (op->condexp, 0, op->lineno);

1861     }

1862   }

 

正如我们在 读入 DEFINE_FUNCTION_UNIT模式 一节中所看到的,对于被多条指令所使用的功能单元, function_unit condexp 部分将是所有的 function_unit_op condexp 部分 OR 操作的结果。因此在 1831 1860 行, check_attr_test 实际用于不同的目的。

至于 check_attr_test ,给定一个属性的测试表达式,该函数确保它是一个有效形式。参数 is_const 显示,对于每次编译器运行,该表达式是否为常量(一个常量表达式不可能测试任意具体的指令)。这个函数把 (eq_attr "att" "a1,a2") 转换为 (ior (eq_attr “att” “a1 ) (eq_attr “att” “a2”)) ,以及把 (eq_attr "att" "!a1") 转换为 (not (eq_attr "att" "a1")) 。它首先执行后一个的转换,因此 (eq_attr "att" "!a1,a2,a3") 可以按预期的工作。并且它把在 EQ_ATTR 表达式中的字符串为,在属性所使用的相同的字符串(或 alternative_name ),来加速后面调用的 find_attr ,以及消除绝大多数的 strcmp 调用。这个函数返回新的表达式,如果有的话。

 

919  rtx

920  check_attr_test (rtx exp, int is_const, int lineno)                                           in genattrtab.c

921  {

922    struct attr_desc *attr;

923    struct attr_value *av;

924    const char *name_ptr, *p;

925    rtx orexp, newexp;

926 

927    switch (GET_CODE (exp))

928    {

929      case EQ_ATTR:

930        /* Handle negation test.  */

931        if (XSTR (exp, 1)[0] == '!')

932          return check_attr_test (attr_rtx (NOT,

933                                   attr_eq (XSTR (exp, 0),

934                                         &XSTR (exp, 1)[1])),

935                             is_const, lineno);

936 

937        else if (n_comma_elts (XSTR (exp, 1)) == 1)

938        {

939          attr = find_attr (&XSTR (exp, 0), 0);

940          if (attr == NULL)

941          {

942            if (! strcmp (XSTR (exp, 0), "alternative"))

943              return mk_attr_alt (1 << atoi (XSTR (exp, 1)));

944            else

945              fatal ("unknown attribute `%s' in EQ_ATTR", XSTR (exp, 0));

946          }

947 

948          if (is_const && ! attr->is_const)

949            fatal ("constant expression uses insn attribute `%s' in EQ_ATTR",

950                 XSTR (exp, 0));

951 

952           /* Copy this just to make it permanent,

953             so expressions using it can be permanent too.  */

954          exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1));

955 

956           /* It shouldn't be possible to simplify the value given to a

957             constant attribute, so don't expand this until it's time to

958             write the test expression.  */

959          if (attr->is_const)

960            ATTR_IND_SIMPLIFIED_P (exp) = 1;

961 

962           if (attr->is_numeric)

963          {

964            for (p = XSTR (exp, 1); *p; p++)

965              if (! ISDIGIT (*p))

966                fatal ("attribute `%s' takes only numeric values",

967                     XSTR (exp, 0));

968          }

969          else

970          {

971            for (av = attr->first_value; av; av = av->next)

972              if (GET_CODE (av->value) == CONST_STRING

973                  && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))

974                break ;

975 

976            if (av == NULL)

977              fatal ("unknown value `%s' for `%s' attribute",

978                   XSTR (exp, 1), XSTR (exp, 0));

979          }

980        }

981        else

982        {

983          if (! strcmp (XSTR (exp, 0), "alternative"))

984          {

985            int set = 0;

986 

987            name_ptr = XSTR (exp, 1);

988            while ((p = next_comma_elt (&name_ptr)) != NULL)

989              set |= 1 << atoi (p);

990 

991            return mk_attr_alt (set);

992          }

993              else

994          {

995            /* Make an IOR tree of the possible values.  */

996            orexp = false_rtx ;

997            name_ptr = XSTR (exp, 1);

998            while ((p = next_comma_elt (&name_ptr)) != NULL)

999            {

1000             newexp = attr_eq (XSTR (exp, 0), p);

1001             orexp = insert_right_side (IOR, orexp, newexp, -2, -2);

1002           }

1003

1004           return check_attr_test (orexp, is_const, lineno);

1005         }

1006       }

1007       break ;

1008

1009     case ATTR_FLAG:

1010       break ;

1011

1012     case CONST_INT:

1013       /* Either TRUE or FALSE.  */

1014       if (XWINT (exp, 0))

1015          return true_rtx ;

1016       else

1017         return false_rtx ;

1018

1019     case IOR:

1020     case AND:

1021       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, lineno);

1022       XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const, lineno);

1023       break ;

1024

1025     case NOT:

1026       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, lineno);

1027       break ;

1028

1029     case MATCH_INSN:

1030     case MATCH_OPERAND:

1031       if (is_const)

1032          fatal ("RTL operator /"%s/" not valid in constant attribute test",

1033              GET_RTX_NAME (GET_CODE (exp)));

1034       /* These cases can't be simplified.  */

1035       ATTR_IND_SIMPLIFIED_P (exp) = 1;

1036       break ;

1037

1038     case LE:  case LT:  case GT:  case GE:

1039     case LEU: case LTU: case GTU: case GEU:

1040     case NE:  case EQ:

1041       if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF

1042           && GET_CODE (XEXP (exp, 1)) == SYMBOL_REF)

1043         exp = attr_rtx (GET_CODE (exp),

1044                      attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),

1045                      attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));

1046       /* These cases can't be simplified.  */

1047       ATTR_IND_SIMPLIFIED_P (exp) = 1;

1048       break ;

1049

1050     case SYMBOL_REF:

1051       if (is_const)

1052       {

1053          /* These cases are valid for constant attributes, but can't be

1054            simplified.  */

1055         exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0));

1056         ATTR_IND_SIMPLIFIED_P (exp) = 1;

1057         break ;

1058       }

1059     default :

1060       fatal ("RTL operator /"%s/" not valid in attribute test",

1061             GET_RTX_NAME (GET_CODE (exp)));

1062   }

1063

1064   return exp;

1065 }

 

函数 n_comma_elts 计算在传入字符串中“ , ”的数目。如果该属性具有名字“ alternative ”,它指向编译器变量 which_alternative ,这个变量必须是一个数值。这个值在 943 行通过 mk_attr_alt 保存入 EQ_ATTR_ALT 。在 960 行的 ATTR_IND_SIMPLIFIED_P 访问这个 rtx 对象的 unchanging 域。这个域如果是 1 ,表示该 rtx 对象所代表的表达式不能被简化。 attr_eq 则构建操作数保存在 attr_hash_table EQ_ATTR 对象。

 

763  static rtx

764  attr_eq (const char *name, const char *value)                                        in genattrtab.c

765  {

766    return attr_rtx (EQ_ATTR, DEF_ATTR_STRING (name), DEF_ATTR_STRING (value));

767  }

 

然后,在 expand_units 1845 行,注意到 simplify_knowing 的第二个参数是由 check_attr_test 生成的 unit condexp 域,我们例子中的 condexp 显示在下图。

t52

52 :由 check_attr_test 生成的 condexp

此处在我们的例子中, simplify_knowing 的第一个参数 exp 是一个 rtx 对象,它等效于:

IF op->conflict_exp THEN

op->issue_delay

ELSE

0

或者 op->issue_delay 。(如果没有定义 conflict_exp

比较上面的表达式与 gccint 中的描述,特别是黑体部分:

CONFLICT-LIST 是一个可选的列表,它给出了这个单元详细的冲突代价。如果指定了,它就是一个条件测试表达式列表,这些表达式将应用到被选择在 NAME 中执行的指令上,而这些指令跟在匹配 TEST 并且正在 NAME 中执行的指令后。对于在该列表中的每条指令, ISSUE-DELAY 指出了冲突代价;而对于不在列表中的指令,这个代价为 0 如果没有指定, CONFLICT-LIST 默认用于所有使用这个功能单元的指令。

 

2173 static rtx

2174 simplify_knowing (rtx exp, rtx known_true)                                         in genattrtab.c

2175 {

2176   if (GET_CODE (exp) != CONST_STRING)

2177   {

2178     int unknown = 0, max;

2179     max = max_attr_value (exp, &unknown);

2180     if (! unknown)

2181     {

2182       exp = attr_rtx (IF_THEN_ELSE, known_true, exp,

2183                   make_numeric_value (max));

2184       exp = simplify_by_exploding (exp);

2185     }

2186   }

2187   return exp;

2188 }

 

2179 行, max_attr_value ,给定一个属性,返回在该属性里找到的最大的数值,如果该属性不是正确的类型,设置 UNKNOWNP 并返回 INT_MAX 。因此它返回的 max 是由于冲突导致的 issue_delay ,如果一切顺利的话。

 

4850 static int

4851 max_attr_value (rtx exp, int *unknownp)                                             in genattrtab.c

4852 {

4853   int current_max;

4854   int i, n;

4855

4856   switch (GET_CODE (exp))

4857   {

4858     case CONST_STRING:

4859       current_max = atoi (XSTR (exp, 0));

4860       break ;

4861

4862     case COND:

4863       current_max = max_attr_value (XEXP (exp, 1), unknownp);

4864       for (i = 0; i < XVECLEN (exp, 0); i += 2)

4865       {

4866         n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);

4867         if (n > current_max)

4868           current_max = n;

4869       }

4870       break ;

4871

4872     case IF_THEN_ELSE:

4873       current_max = max_attr_value (XEXP (exp, 1), unknownp);

4874       n = max_attr_value (XEXP (exp, 2), unknownp);

4875       if (n > current_max)

4876         current_max = n;

4877       break ;

4878

4879     default :

4880       *unknownp = 1;

4881       current_max = INT_MAX;

4882       break ;

4883   }

4884

4885   return current_max;

4886 }

 

回到 expand_units simplify_knowing 被包含在一个 FOR 循环里,并且为每一条指令进行调用。在 simplify_knowing 2182 行,它构建了 IF_THEN_ELSE rtx 对象,它等效于:

IF unit->condexp THEN

IF op->conflict_exp THEN

        op->issue_delay.

ELSE

   0

       ELSE

          op->issue_delay

或者(如果 op->conflict_exp null ):

       IF unit->condexp THEN

          op->issue_delay

       ELSE

          op->issue_delay

该表达式,在执行的某个点上给定参数,返回在该功能单元上的发布延迟。这是旧式流水线危险识别器的核心。不过正如所见的,它还不是简化的形式,因此在 2184 行调用 simplify_by_exploding 来把这个表达式转换为规范及简化的形式。

 

3724 static rtx

3725 simplify_by_exploding (rtx exp)                                                         in genattrtab.c

3726 {

3727   rtx list = 0, link, condexp, defval = NULL_RTX;

3728   struct dimension *space;

3729   rtx *condtest, *condval;

3730   int i, j, total, ndim = 0;

3731   int most_tests, num_marks, new_marks;

3732   rtx ret;

3733

3734   /* Locate all the EQ_ATTR expressions.  */

3735   if (! find_and_mark_used_attributes (exp, &list, &ndim) || ndim == 0)

3736   {

3737     unmark_used_attributes (list, 0, 0);

3738     return exp;

3739   }

 

find_and_mark_used_attributes 只是把所有的 EQ_ATTR 链接在一起, ATTR_EQ_ATTR_P 访问 exp volatil 域,该域在 3896 行设置,以防止 exp 被多次链接。

 

3881 static int

3882 find_and_mark_used_attributes (rtx exp, rtx *terms, int *nterms)            in genattrtab.c

3883 {

3884   int i;

3885

3886   switch (GET_CODE (exp))

3887   {

3888     case EQ_ATTR:

3889       if (! ATTR_EQ_ATTR_P (exp))

3890       {

3891         rtx link = rtx_alloc (EXPR_LIST);

3892         XEXP (link, 0) = exp;

3893         XEXP (link, 1) = *terms;

3894         *terms = link;

3895         *nterms += 1;

3896         ATTR_EQ_ATTR_P (exp) = 1;

3897       }

3898       return 1;

3899

3900     case CONST_STRING:

3901     case CONST_INT:

3902       return 1;

3903

3904     case IF_THEN_ELSE:

3905       if (! find_and_mark_used_attributes (XEXP (exp, 2), terms, nterms))

3906         return 0;

3907     case IOR:

3908     case AND:

3909       if (!find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))

3910         return 0;

3911     case NOT:

3912       if (!find_and_mark_used_attributes (XEXP (exp, 0), terms, nterms))

3913         return 0;

3914       return 1;

3915

3916     case COND:

3917       for (i = 0; i < XVECLEN (exp, 0); i++)

3918         if (!find_and_mark_used_attributes (XVECEXP (exp, 0, i), terms, nterms))

3919           return 0;

3920       if (!find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))

3921         return 0;

3922       return 1;

3923

3924     default :

3925       return 0;

3926   }

3927 }

 

101  #define ATTR_EQ_ATTR_P (RTX) (RTX_FLAG((RTX), volatil))            in genattrtab.c

 

继续 simpilify_by_exploding ,现在 ndim ,对于我们的例子,是 7 exp 参考 52 ,并假定它是仅有的描述相关单元的 define_funtion_unit ——即在 op 中没有 conflict_exp )。

 

simplify_by_exploding (continued)

 

3741   /* Create an attribute space from the list of used attributes. For each

3742     dimension in the attribute space, record the attribute, list of values

3743     used, and number of values used. Add members to the list of values to

3744     cover the domain of the attribute. This makes the expanded COND form

3745     order independent.  */

3746

3747   space = xmalloc (ndim * sizeof (struct dimension ));

3748

3749   total = 1;

3750   for (ndim = 0; list; ndim++)

3751   {

3752     /* Pull the first attribute value from the list and record that

3753       attribute as another dimension in the attribute space.  */

3754     const char *name = XSTR (XEXP (list, 0), 0);

3755     rtx *prev;

3756

3757     space[ndim].attr = find_attr (&name, 0);

3758     XSTR (XEXP (list, 0), 0) = name;

3759

3760     if (space[ndim].attr == 0

3761       || space[ndim].attr->is_numeric)

3762     {

3763       unmark_used_attributes (list, space, ndim);

3764       return exp;

3765     }

3766

3767     /* Add all remaining attribute values that refer to this attribute.  */

3768     space[ndim].num_values = 0;

3769     space[ndim].values = 0;

3770     prev = &list;

3771     for (link = list; link; link = *prev)

3772       if (! strcmp_check (XSTR (XEXP (link, 0), 0), name))

3773       {

3774          space[ndim].num_values++;

3775          *prev = XEXP (link, 1);

3776          XEXP (link, 1) = space[ndim].values;

3777         space[ndim].values = link;

3778       }

3779       else

3780         prev = &XEXP (link, 1);

3781

3782     /* Add sufficient members to the list of values to make the list

3783       mutually exclusive and record the total size of the attribute

3784       space.  */

3785     total *= add_values_to_cover (&space[ndim]);

3786   }

 

3747 行的 dimension 具有如下的定义。在 3757 行, find_attr 构建了与 attr_hash_table 中的 name 关联的属性,并返回之。注意参数 name 为在 attr_hash_table 中的对等对象所替换。在 3758 行,这个节点的 name 被更新。因此在 3772 行, strcmp_check 可以仅比较这两个字符串的地址。

 

302  struct dimension                                                                                   in genattrtab.c

303  {

304    struct attr_desc *attr;  /* Attribute for this dimension.  */

305    rtx values;                        /* List of attribute values used.  */

306    rtx current_value;             /* Position in the list for the TRUE value.  */

307    int num_values;         /* Length of the values list.  */

308  }

 

3750 行的整个 FOR 循环,其每次循环将找出同名的属性,并把它们链接入 space 同一个元素里,然后为这个 space 的元素调用 add_values_to_cover (属性名是 EQ_ATTR 的第一个孩子的)。

例如,一开始我们得到如下的布局。第一个节点必定通过 3772 行的测试。

t53

53 define_function_unit 处理的案例,图 1

在执行了 3774 ~ 3777 行的代码,以及下一次循环时 3771 行后,我们可以得到如下布局。节点 0 是具有名字“ cpu ”的 EQ_ATTR ,它被链入 space[0] ,其它节点是具有名字“ type ”的 EQ_ATTR ,它们被链入 space[1] (参见 52 )。注意到,任意由功能单元描述模式所产生的链表组,在执行的任一点上,每个链表最多有一个节点被匹配,因为属性在一个时间点上不能取多个值。

t54

54 define_function_unit 处理的案例,图 2

然后调用 add_values_to_cover 来把该属性其它未被提及的数值链入这个链表。通过这个方式,这个链表完整代表了这个令人感兴趣的属性。

 

3952 static int

3953 add_values_to_cover (struct dimension *dim)                                       in genattrtab.c

3954 {

3955   struct attr_value *av;

3956   rtx exp, link, *prev;

3957   int nalt = 0;

3958

3959   for (av = dim->attr->first_value; av; av = av->next)

3960     if (GET_CODE (av->value) == CONST_STRING)

3961       nalt++;

3962

3963   if (nalt < dim->num_values)

3964     abort ();

3965   else if (nalt == dim->num_values)

3966      /* OK.  */

3967     ;

3968   else if (nalt * 2 < dim->num_values * 3)

3969   {

3970     /* Most all the values of the attribute are used, so add all the unused

3971        values.  */

3972     prev = &dim->values;

3973     for (link = dim->values; link; link = *prev)

3974       prev = &XEXP (link, 1);

3975

3976     for (av = dim->attr->first_value; av; av = av->next)

3977       if (GET_CODE (av->value) == CONST_STRING)

3978        {

3979          exp = attr_eq (dim->attr->name, XSTR (av->value, 0));

3980          if (ATTR_EQ_ATTR_P (exp))

3981            continue ;

3982

3983          link = rtx_alloc (EXPR_LIST);

3984         XEXP (link, 0) = exp;

3985         XEXP (link, 1) = 0;

3986         *prev = link;

3987         prev = &XEXP (link, 1);

3988       }

3989       dim->num_values = nalt;

3990   }

3991   else

3992   {

3993     rtx orexp = false_rtx ;

3994

3995     /* Very few values are used, so compute a mutually exclusive

3996       expression. (We could do this for numeric values if that becomes

3997       important.)  */

3998     prev = &dim->values;

3999     for (link = dim->values; link; link = *prev)

4000     {

4001       orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2, -2);

4002       prev = &XEXP (link, 1);

4003     }

4004     link = rtx_alloc (EXPR_LIST);

4005     XEXP (link, 0) = attr_rtx (NOT, orexp);

4006     XEXP (link, 1) = 0;

4007     *prev = link;

4008     dim->num_values++;

4009   }

4010   return dim->num_values;

4011 }

 

dimension attr 域指向描述该属性的 attr_desc 对象,其中的 first_value 域维护记录了所有属性值的一个链表。而 dimension values 域只是记录了用在这个 define_function_unit 模式里的属性的值。显然, values 必定是 attr first_value 的一个子集。这里是我们整合该链表的方式——如果所使用值的数目接近于属性值的总数,把余下未引用的属性值加到链表末尾( 3969 ~ 3989 行),而如果差别相当大的话,则构建一个新的 EXPR_LIST 来代表余下的值(看到它是一个对于所有未被引用值的 NOT 表达式),并从末尾链入。如下图所示。

t55

55 define_function_unit 处理的案例,图 3

上面的把同名属性链接起来,还有整合链表的过程,一再重复,直到所有的属性都得到处理。然后在下面这些链表被排序,常量及数值多优先。

 

simplify_by_exploding (continued)

 

3788   /* Sort the attribute space so that the attributes go from non-constant

3789     to constant and from most values to least values.  */

3790   for (i = 0; i < ndim; i++)

3791     for (j = ndim - 1; j > i; j--)

3792       if ((space[j-1].attr->is_const && !space[j].attr->is_const)

3793         || space[j-1].num_values < space[j].num_values)

3794       {

3795         struct dimension tmp;

3796         tmp = space[j];

3797          space[j] = space[j - 1];

3798         space[j - 1] = tmp;

3799       }

3800

3801   /* Estabusagelish the initial current value.  */

3802   for (i = 0; i < ndim; i++)

3803     space[i].current_value = space[i].values;

3804

3805   condtest = xmalloc (total * sizeof (rtx));

3806   condval = xmalloc (total * sizeof (rtx));

3807

3808   /* Expand the tests and values by iterating over all values in the

3809     attribute space.  */

3810   for (i = 0;; i++)

3811   {

3812     condtest[i] = test_for_current_value (space, ndim);

3813     condval[i] = simplify_with_current_value (exp, space, ndim);

3814     if (! increment_current_value (space, ndim))

3815       break ;

3816   }

3817   if (i != total - 1)

3818     abort ();

 

3790 行的 ndim 表示 space 被使用的元素数目,在 3805 行的 total 则显示了所需的 rtx 对象的数目。在 3803 行, space current_value 域被初始化为 values 的第一个元素。 test_for_current_value 为这个测试构建初始化表达式。

 

4034 static rtx

4035 test_for_current_value (struct dimension *space, int ndim)                     in genattrtab.c

4036 {

4037   int i;

4038   rtx exp = true_rtx ;

4039

4040   for (i = 0; i < ndim; i++)

4041     exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0),

4042                           -2, -2);

4043

4044   return exp;

4045 }

 

注意实际上 current_value 总是指向 exp 当前未被处理的部分。因此 condtest 数组穷举了所有的测试表达式。接着 simplify_with_current_value 开始约简表达式 exp

 

4052 static rtx

4053 simplify_with_current_value (rtx exp, struct dimension *space, int ndim)       in genattrtab.c

4054 {

4055   int i;

4056   rtx x;

4057

4058   /* Mark each current value as TRUE.  */

4059   for (i = 0; i < ndim; i++)

4060   {

4061     x = XEXP (space[i].current_value, 0);

4062     if (GET_CODE (x) == EQ_ATTR)

4063       ATTR_EQ_ATTR_P (x) = 0;

4064   }

4065

4066   exp = simplify_with_current_value_aux (exp);

4067

4068   /* Change each current value back to FALSE.  */

4069   for (i = 0; i < ndim; i++)

4070   {

4071     x = XEXP (space[i].current_value, 0);

4072     if (GET_CODE (x) == EQ_ATTR)

4073       ATTR_EQ_ATTR_P (x) = 1;

4074   }

4075

4076   return exp;

4077 }

 

find_and_mark_used_attributes 中,在构建这个链表的时候,其节点的 volital 域已经被设置为 1 。在 4061 行, current_value 总是指向 exp 当前未被处理的部分。如果 current_value 是一个 EQ_ATTR ,我们把 ATTR_EQ_ATTR_P 设为 0 ,在下面 simplify_with_current_value_aux 4094 行将依此返回 true_rtx ,假定已经被处理部分的值为 true ,这样才能产生与 condtest 对应的 condval 的值。 EXP 元素的访问次序大致地显示如下(方框内的数字表示序号)。

t56

(注意:由虚线指针指向的是 IOR 对象。 XEXP(exp, 0) 指向的实际上是 52 中的树节点,因为上面的方框是由 rtx 对象及 space 共享的。节点 1 是第一个 IOR 对象的第二个孩子,节点 2 是被第一个 IOR 对象的第一个孩子指向的 IOR 对象的第二个孩子,依此类推。不过,节点 7 与节点 8 之间的关系是 AND 。因此虚线指针给出了访问的次序)

56 define_function_unit 处理的案例,图 4

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值