GCC's bacl-end & assemble emission (22)

9.4.2. Handling DEFINE_FUNCTION_UNIT pattern

We have known that define_function_unit describes the chip in the view of function unit. However, this pattern is still majorly in human readable form. We must create data easily handled by the tool to output functions for pipeline hazards recognizer. This old way of chip description is much simpler than the new way; data created here is still attributes.

 

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   }

 

For our example, after generated by gen_unit , we can get following data (for field not displayed, just means it is 0).

GCC's bacl-end & assemble emission (22)_第1张图片

figure 51 : example of FUNCTION_UNIT

Data with above form is no good for constructing pipeline hazards recognizer easily and directly. We need expand_units to extract informations then make them pernament by placing them into hash table and create attributes accordingly.

 

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   }

 

As we have seen in 9.3.5.Read in DEFINE_FUNCTION_UNIT pattern , for function unit used by more than one instruction, the condexp part of function_unit will be the OR result of all condexp part of function_unit_op s. So at line 1831 and 1860, check_attr_test is for different purposes indeed.

For check_attr_test , given a test expression for an attribute, the function ensures it is in valid form. Parameter is_const indicates whether the expression is constant for each compiler run (a constant expression may not test any particular instruction). The function converts (eq_attr "att" "a1,a2") to (ior (eq_attr “att” “a1 ) (eq_attr “att” “a2”)) and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")) . It does the latter conversion first so that (eq_attr "att" "!a1,a2,a3") works as expected. And it updates the string in EQ_ATTR expression to be the same used in the attribute (or alternative_name ) to speed up subsequent find_attr calls and eliminate most strcmp calls. The function returns the new expression, if any.

 

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 }

 

Function n_comma_elts counts number of “,” in the string passed in. If the attribute has name “alternative”, it refers to compiler variable which_alternative which must be numeric value. This value is saved in EQ_ATTR_ALT at line 943 via mk_attr_alt . ATTR_IND_SIMPLIFIED_P at line 960 accesses unchanging field of the rtx object. This field if 1, means expression the rtx object representing can’t be simplified. attr_eq creates rtx object of EQ_ATTR with operants saved in attr_hash_table .

 

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  }

 

Then, in expand_units at line 1845, notice that the second parameter of simplify_knowing is condexp field of unit generated by check_attr_test , the condexp is shown in below figure for our example.

figure 52 : condexp generated by check_attr_test

And here in our example the first parameter exp of simplify_knowing is an rtx object equivalent to:

IF op->conflict_exp THEN

op->issue_delay

ELSE

0

Or op->issue_delay. (if conflict_exp is not defined)

Compare above expression with the description in gccinfo, especially that in bold:

CONFLICT-LIST is an optional list giving detailed conflict costs for this unit. If specified, it is a list of condition test expressions to be applied to insns chosen to execute in NAME following the particular insn matching TEST that is already executing in NAME. For each insn in the list, ISSUE-DELAY specifies the conflict cost; for insns not in the list, the cost is zero. If not specified, CONFLICT-LIST defaults to all instructions that use the function unit .

 

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 }

 

At line 2179, max_attr_value given an attribute, returns the maximum numeric value found in the attribute, sets UNKNOWNP and returns INT_MAX if the attribute is not of right type. So max it returns is the issue_delay due to conflict if everything is OK.

 

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 }

 

Back expand_units , simplify_knowing is enclosed in a FOR loop and invoked per instruction. At line 2182, in simplify_knowing , it constructs the IF_THEN_ELSE rtx object in equivalent as:

IF unit->condexp THEN

IF op->conflict_exp THEN

        op->issue_delay.

ELSE

   0

       ELSE

          op->issue_delay

Or (if op->conflict_exp is null):

       IF unit->condexp THEN

          op->issue_delay

       ELSE

          op->issue_delay

The expression given parameters at certain point of execution returns the issue delay upon the function unit. It is the core for the old style pipeline hazards recognizer. However as can be seen, it’s still not simplified form, so at line 2184 simplify_by_exploding is invoked, to make the expression into canonical and simplified form.

 

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 just links all EQ_ATTR tegother, macro ATTR_EQ_ATTR_P accesses the volatil field of exp , this field is set at line 3896 to prevent exp to be linked more than once.

 

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

 

Continue with simpilify_by_exploding , now ndim , for our example, is 7 (refer to figure 52 for exp , and assuming it is the only define_funtion_unit describes the unit related - that is no conflict_exp in op ).

 

simpilfy_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   }

 

dimension at line 3747, has following definition. At line 3757, find_attr creates attribute associated with name in attr_hash_table and returns the attribute. Notice that parameter name is replaced by the counterpart in attr_hash_table too. At line 3758, name of the node is updated. So at line 3772, strcmp_check can just compares the addresses of the two strings.

 

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  }

 

The whole FOR loop at line 3750, for every iteration, will find out attributes of same name, and link them into same element of space , then invokes add_values_to_cover for the space element (name of attribute is the first child of EQ_ATTR).

For example, orignially we get following data outline. The first node must pass the test at line 3772.

figure 53 : example of define_function_unit handling, figure 1

Then after excuting line 3774 ~ 3777, and line 3771 for next iteration, we can get following. Node 0 is the EQ_ATTR having name “cpu” which is linked into space[0], others are EQ_ATTR having name “type” which are linked into space[1] (see figure 52 ). Notice that for any group of links generated by function unit description pattern, at any point of execution, at most one node in every link will be matched, as attribute can’t take more than one value at one point of time.

figure 54 : example of define_function_unit handling, figure 2

Then add_values_to_cover is invoked to include other unmentioned value of the attribute into the link. By this way, the link becomes integrate for the attribute in interested.

 

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 }

 

attr field of dimension points to object of attr_desc describing the attribute, in which first_value field maintains a list recording all attribute values. And values field of dimension just records values of this attribute used in the define_function_unit pattern. Of course, values must be a subset of first_value of attr . Here is the way we make the link integrate - if the number of values used is close to the total number of attribute values, adds all rest unreferred attribute values from the tail of link (line 3969 ~ 3989), while if the difference is quite large, creates a new EXPR_LIST to stand for rest values (see it is a NOT expression for all unreferred values), and links it at tail. As indicated in below figure.

GCC's bacl-end & assemble emission (22)_第2张图片

figure 55 : example of define_function_unit handling, figure 3

Procedure above of linking attribute of same name tegother and makes the list integrate are repeated until all attributes have been treated. Then below these lists are sorted as constant comes first, then having more values comes first.

 

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 ();

 

ndim at line 3790 indicates the number of elements of space used, total at line 3805 tells the number of rtx objects needed. At line 3803, current_value fields of space are initialized as the first element of values . test_for_current_value creates initial expression for the test.

 

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 }

 

Note that in fact current_value always refers to the unprocessed part of exp . Thus array condtest exhausts all possible test expressions related. Then simplify_with_current_value reduces the expression 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 }

 

In find_and_mark_used_attributes , during creating the list, volital field of its nodes has been set as 1. At line 4061, current_value always refers to the unprocessed part of exp . And if current_value is an EQ_ATTR, we set the ATTR_EQ_ATTR_P as 0, then below at line 4094 in simplify_with_current_value_aux , true_rtx will be returned accordingly, thus can generate value of condval for corresponding condtest . The visit order of members of EXP is roughly displayed in below (the order is shown by the number in rectangle).

GCC's bacl-end & assemble emission (22)_第3张图片

(Note: the object dotted pointer points to is IOR object. XEXP(exp, 0) in fact points to node of tree in figure 52 , becaure rectangles above are shared with rtx objects and spaces. Node1 is the second child of the first IOR object, node2 is the second child of following IOR object which is pointed by the first child of former IOR object, and so on. However, the relation between node7 and node8 is AND. So the dotted pointers gives out the visit order)

figure 56 : example of define_function_unit handling, figure 4

你可能感兴趣的:(function,list,struct,gcc,attributes,conflict)