现在的位置: 首页 > 综合 > 正文

GCC’s bacl-end & assemble emission (32)

2013年08月10日 ⁄ 综合 ⁄ 共 23397字 ⁄ 字号 评论关闭

9.6.1.4.    Outputattributes

Though we have created attributes related data, for using bypipeline hazards recognizer, they are needed be output as functions whichaccept rtx object of the instructions, and return attributes’ value for theinstruction. These functions are output into file insn-attrtab.c, and will becompiled as part of source code of the gcc to produce the executive file.

 

main (continued)

 

6190   /* Now write outall the `gen_attr_...' routines. Do these before the

6191     special routines (specifically beforewrite_function_unit_info), so

6192     that they get defined before they areused.  */

6193

6194   for (i = 0; i < MAX_ATTRS_INDEX; i++)

6195     for (attr =attrs[i];attr; attr = attr->next)

6196     {

6197       if (! attr->is_special && !attr->is_const)

6198      {

6199        int insn_alts_p;

6200

6201        insn_alts_p

6202            = (attr->name [0] == '*'

6203              && strcmp(&attr->name[1], INSN_ALTS_FUNC_NAME) == 0);

6204         if(insn_alts_p)

6205           printf ("\n#ifAUTOMATON_ALTS\n");

6206         write_attr_get (attr);

6207         if (insn_alts_p)

6208           printf ("#endif\n\n");

6209       }

6210     }

 

Above at line 6197, is_special is set for attributes needed specialtreatment – they will not produce the normal attribute value fetchers.Following is the list of attributes having is_special set:

*delay_type (it is singleton across the system)

*delay_`delay-no`_`slot-no` (it is per slot for every define_delaypattern)

*annul_true_`delay-no`_`slot-no` (it is per slot for everydefine_delay pattern)

*annul_false_`delay-no`_`slot-no` (it is per slot for everydefine_delay pattern)

*`unit-name`_cost_`op-num` (issue cost of the instruction upon theunit)

*`unit-name`_block_`op-num` (issue delay of the instruction upon theunit)

*`unit-name`_cases (singleton, and case expression for all units,see expand_units)

For attributes containing constant content, is_const is set.

At line 6203, INSN_ATLS_FUNC_NAME is defined as “insn_alts”, theattribute associated is created in make_insn_alts_attr, and the attributedescribes the number of alternatives in define_insn_reservation.

write_attr_get writes out a function to fetch the value of the attribute for giveninstruction.

 

5004 static void

5005 write_attr_get (structattr_desc *attr)                                                    in genattrtab.c

5006 {

5007   struct attr_value*av, *common_av;

5008

5009   /* Find the mostused attribute value. Handle that as the `default' of the

5010     switch we will generate.  */

5011   common_av = find_most_used (attr);

5012

5013   /* Write out startof function, then all values with explicit `case' lines,

5014     then a `default', then the value with themost uses.  */

5015   if (attr->static_p)

5016     printf ("static ");

5017   if (!attr->is_numeric)

5018     printf ("enum attr_%s\n",attr->name);

5019   else if (attr->unsigned_p)

5020     printf ("unsigned int\n");

5021   else

5022     printf ("int\n");

5023

5024   /* If the attributename starts with a star, the remainder is the name of

5025     the subroutine to use, instead of`get_attr_...'.  */

5026   if (attr->name[0] == '*')

5027     printf ("%s (rtx insnATTRIBUTE_UNUSED)\n", &attr->name[1]);

5028   else if (attr->is_const == 0)

5029     printf ("get_attr_%s (rtx insnATTRIBUTE_UNUSED)\n", attr->name);

5030   else

5031   {

5032     printf ("get_attr_%s (void)\n",attr->name);

5033     printf ("{\n");

5034

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

5036       if (av->num_insns != 0)

5037         write_attr_set (attr, 2, av->value,"return", ";",

5038                     true_rtx, av->first_insn->insn_code,

5039                    av->first_insn->insn_index);

5040

5041     printf ("}\n\n");

5042     return;

5043   }

5044

5045   printf ("{\n");

5046

5047   if (GET_CODE (common_av->value) == FFS)

5048   {

5049     rtx p = XEXP (common_av->value, 0);

5050

5051     /* No need toemit code to abort if the insn is unrecognized; the

5052       other get_attr_foo functions will do thatwhen we call them.  */

5053

5054     write_toplevel_expr (p);

5055

5056     printf ("\n  if (accum && accum == (accum &-accum))\n");

5057     printf ("    {\n");

5058     printf ("      int i;\n");

5059     printf ("      for (i = 0; accum >>= 1; ++i)continue;\n");

5060     printf ("      accum = i;\n");

5061     printf ("    }\n else\n");

5062     printf ("    accum = ~accum;\n");

5063     printf ("  return accum;\n}\n\n");

5064   }

5065   else

5066   {

5067     printf ("  switch (recog_memoized (insn))\n");

5068     printf ("    {\n");

5069

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

5071       if (av != common_av)

5072         write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);

5073

5074     write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);

5075     printf ("    }\n}\n\n");

5076   }

5077 }

 

At line 5037, notice that write_attr_set is invoked for attributes ofconstant and haven’t “*” at beginning of their names. However, before entering write_attr_get,attributes of this kind have been filtered out (see line 6197 in main). write_attr_set will not be invoked here.

FFS at line 5047 means the operation of “find first bit set”. Here,for instruction using FFS mostly, we don’t attempt to recognize it. In releaseV4, the special treatment for FFS is removed. Anyway, for other instructions,recognition is must. See recog_memoized outputat line 5067, this function is a wrapper for recog which is output by genrecog(3. Tool of genrecog). The returned value isthe insn code of the instruction object input.

For every attribute value, write_attr_case writes out the computation.

 

5201 static void

5202 write_attr_case (struct attr_desc *attr, struct attr_value*av,                    in genattrtab.c

5203               int write_case_lines, const char *prefix, constchar *suffix,

5204               int indent, rtx known_true)

5205 {

5206   struct insn_ent*ie;

5207

5208   if (av->num_insns == 0)

5209     return;

5210

5211   if (av->has_asm_insn)

5212   {

5213     write_indent (indent);

5214     printf ("case -1:\n");

5215     write_indent (indent + 2);

5216     printf ("if (GET_CODE (PATTERN (insn))!= ASM_INPUT\n");

5217     write_indent (indent + 2);

5218     printf ("    && asm_noperands (PATTERN (insn))< 0)\n");

5219     write_indent (indent + 2);

5220     printf ("  fatal_insn_not_found (insn);\n");

5221   }

5222

5223   if (write_case_lines)

5224   {

5225     for (ie =av->first_insn; ie; ie = ie->next)

5226       if (ie->insn_code != -1)

5227       {

5228         write_indent (indent);

5229         printf ("case %d:\n",ie->insn_code);

5230       }

5231   }

5232   else

5233   {

5234     write_indent (indent);

5235     printf ("default:\n");

5236   }

5237

5238   /* See what we haveto do to output this value.  */

5239   must_extract = must_constrain = address_used= 0;

5240   walk_attr_value (av->value);

5241

5242   if (must_constrain)

5243   {

5244     write_indent (indent + 2);

5245     printf ("extract_constrain_insn_cached(insn);\n");

5246   }

5247   else if (must_extract)

5248   {

5249     write_indent (indent + 2);

5250     printf ("extract_insn_cached(insn);\n");

5251   }

5252

5253   write_attr_set (attr, indent + 2, av->value, prefix, suffix,

5254               known_true,av->first_insn->insn_code,

5255              av->first_insn->insn_index);

5256

5257   if (strncmp (prefix, "return", 6))

5258   {

5259     write_indent (indent + 2);

5260     printf ("break;\n");

5261   }

5262   printf ("\n");

5263 }

 

Above at line 5211, field has_asm_insn is set as long as the attribute has valueset in certain asm statement (no matter how many other places this value setagain). And for the asm statement, its insn code is -1.

 

5112 static void

5113 write_attr_set (structattr_desc *attr, int indent, rtx value,                        ingenattrtab.c

5114               constchar *prefix, const char *suffix, rtxknown_true,

5115               intinsn_code, int insn_index)

5116 {

5117   if (GET_CODE (value) == COND)

5118   {

5119     /* Assume the default value will be thedefault of the COND unless we

5120       find an always true expression.  */

5121     rtx default_val = XEXP (value, 1);

5122     rtx our_known_true = known_true;

5123     rtx newexp;

5124     int first_if = 1;

5125    int i;

5126

5127     for (i = 0; i < XVECLEN (value, 0); i += 2)

5128     {

5129       rtx testexp;

5130       rtx inner_true;

5131

5132       testexp = eliminate_known_true (our_known_true,

5133                                  XVECEXP(value, 0, i),

5134                                  insn_code,insn_index);

5135       newexp = attr_rtx(NOT, testexp);

5136       newexp = insert_right_side (AND, our_known_true, newexp,

5137                              insn_code,insn_index);

5138

5139       /* If the test expression is always true or if the next`known_true'

5140         expression is always false, this is thelast case, so break

5141         out and let this value be the `else'case.  */

5142       if (testexp == true_rtx || newexp == false_rtx)

5143       {

5144         default_val = XVECEXP (value, 0, i +1);

5145         break;

5146       }

5147

5148       /* Compute theexpression to pass to our recursive call as being

5149         known true.  */

5150       inner_true = insert_right_side (AND, our_known_true,

5151                                testexp,insn_code, insn_index);

5152

5153       /* If this is always false, skip it.  */

5154       if (inner_true == false_rtx)

5155         continue;

5156

5157       write_indent (indent);

5158       printf ("%sif ", first_if ?"" : "else ");

5159       first_if = 0;

5160       write_test_expr (testexp, 0);

5161       printf ("\n");

5162       write_indent (indent + 2);

5163       printf ("{\n");

5164

5165       write_attr_set (attr, indent + 4,

5166                   XVECEXP (value, 0, i + 1),prefix, suffix,

5167                   inner_true, insn_code,insn_index);

5168       write_indent (indent + 2);

5169       printf ("}\n");

5170       our_known_true = newexp;

5171     }

5172

5173     if (! first_if)

5174     {

5175       write_indent (indent);

5176       printf ("else\n");

5177       write_indent (indent + 2);

5178       printf ("{\n");

5179     }

5180

5181     write_attr_set (attr, first_if ? indent : indent + 4, default_val,

5182                 prefix, suffix, our_known_true,insn_code, insn_index);

5183

5184     if (! first_if)

5185     {

5186       write_indent (indent + 2);

5187       printf ("}\n");

5188     }

5189   }

5190   else

5191   {

5192     write_indent (indent);

5193     printf ("%s ", prefix);

5194     write_attr_value (attr, value);

5195     printf ("%s\n", suffix);

5196   }

5197 }

 

Though we do simplification in above section, however thissimplification is mostly per conditional test. In simplify_cond, aftersimplification, we will check if adjacent conditional test are same, and mergethem if so. Consider following example.

cond [ cond1

           val1

      cond2

       val2

      cond3

           val1]

It prefers if cond1 and cond3 can be merged. But it is notnecessary. So here don’t try to do that. However, conside another example inbelow:

cond [ cond1

           val1

      cond2

       val2

      NOT (AND (cond1, cond2))

           Val3 ]

The third condition is always true in its position. We should removethis conditon and make the value associated as default value.

The last example, (eq_attr "att" "v1") and(eq_attr "att" "v2") cannot both be true for certaininstruction at any point of time and hence are complementary. If the term orits complement is present in the tree, it can be replaced with TRUE or FALSE,respectively.

There is one special case: if we see

(and (not (eq_attr "att""v1"))

     (eq_attr "att" "v2"))

this can be replaced by (eq_attr "att" "v2").

Pay attention to newexp at line 5135, 5136, and inner_trueat line 5150. At line 5136 and 5150, remember that insert_right_side willinvoke simplify_test_exp_in_temp to simplify the expression constructed.

Also notice that at line 5160 write_test_expr is used to output testingstatement, as we needn’t consider nesting COND case (the testing must be simplejudgement. To accomendate complex case, it can include a COND object as itsvalue). While at line 5165, write_attr_set is used to output associatedattribute value.

 

5084 static rtx

5085 eliminate_known_true (rtx known_true,rtx exp, int insn_code, int insn_index)  ingenattrtab.c

5086 {

5087   rtx term;

5088

5089   known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);

5090

5091   if (GET_CODE (known_true) == AND)

5092   {

5093     exp = eliminate_known_true (XEXP (known_true, 0), exp,

5094                             insn_code,insn_index);

5095     exp = eliminate_known_true (XEXP (known_true, 1), exp,

5096                             insn_code,insn_index);

5097   }

5098  else

5099   {

5100     term = known_true;

5101     exp = simplify_and_tree (exp, &term, insn_code, insn_index);

5102   }

5103

5104   return exp;

5105 }

 

Notice that pterm passed in simplify_and_tree below by eliminate_known_true,is same as known_truewhich is believed to be evaluated as true for current condition. If pterm orits complement is present in the tree, it can be replaced with TRUE or FALSE,respectively.

 

2889 static rtx

2890 simplify_and_tree (rtx exp, rtx *pterm,int insn_code, int insn_index)             in genattrtab.c

2891 {

2892   rtx left, right;

2893   rtx newexp;

2894   rtx temp;

2895   int left_eliminates_term,right_eliminates_term;

2896

2897   if (GET_CODE (exp) == AND)

2898   {

2899     left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index);

2900     right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);

2901     if (left != XEXP (exp, 0) || right != XEXP (exp,1))

2902     {

2903       newexp = attr_rtx(AND, left, right);

2904

2905       exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);

2906     }

2907   }

2908

2909   else if (GET_CODE (exp) == IOR)

2910   {

2911     /* For the IORcase, we do the same as above, except that we can

2912       only eliminate `term' if both sides ofthe IOR would do so.  */

2913     temp = *pterm;

2914     left = simplify_and_tree (XEXP (exp, 0), &temp, insn_code, insn_index);

2915     left_eliminates_term = (temp == true_rtx);

2916

2917     temp = *pterm;

2918     right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);

2919     right_eliminates_term = (temp == true_rtx);

2920

2921     if (left_eliminates_term &&right_eliminates_term)

2922       *pterm = true_rtx;

2923

2924     if (left != XEXP (exp, 0) || right != XEXP (exp,1))

2925     {

2926       newexp = attr_rtx(IOR, left, right);

2927

2928       exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);

2929     }

2930   }

2931

2932   /* Check forsimplifications. Do some extra checking here since this

2933     routine is called so many times.  */

2934

2935   if (exp == *pterm)

2936     return true_rtx;

2937

2938   else if (GET_CODE (exp) == NOT && XEXP (exp,0) == *pterm)

2939     return false_rtx;

2940

2941   else if (GET_CODE (*pterm) == NOT &&exp == XEXP (*pterm, 0))

2942     return false_rtx;

2943

2944   else if (GET_CODE (exp) == EQ_ATTR_ALT&& GET_CODE (*pterm) == EQ_ATTR_ALT)

2945   {

2946     if (attr_alt_subset_p (*pterm, exp))

2947       return true_rtx;

2948

2949     if (attr_alt_subset_of_compl_p (*pterm,exp))

2950       return false_rtx;

2951

2952     if (attr_alt_subset_p (exp, *pterm))

2953       *pterm = true_rtx;

2954       

2955     return exp;

2956   }

2957

2958   else if (GET_CODE (exp) == EQ_ATTR &&GET_CODE (*pterm) == EQ_ATTR)

2959   {

2960     if(XSTR (exp, 0) != XSTR (*pterm, 0))

2961       returnexp;

2962

2963     if (! strcmp_check (XSTR (exp, 1), XSTR(*pterm, 1)))

2964       return true_rtx;

2965     else

2966       return false_rtx;

2967   }

2968

2969   else if (GET_CODE (*pterm) == EQ_ATTR&& GET_CODE (exp) == NOT

2970         && GET_CODE (XEXP (exp, 0)) ==EQ_ATTR)

2971   {

2972     if (XSTR (*pterm, 0) != XSTR (XEXP (exp,0), 0))

2973       returnexp;

2974

2975     if (! strcmp_check (XSTR (*pterm, 1), XSTR(XEXP (exp, 0), 1)))

2976       return false_rtx;

2977     else

2978       return true_rtx;

2979   }

2980

2981   else if (GET_CODE (exp) == EQ_ATTR &&GET_CODE (*pterm) == NOT

2982         && GET_CODE (XEXP(*pterm, 0)) == EQ_ATTR)

2983   {

2984     if (XSTR (exp, 0) != XSTR (XEXP(*pterm, 0), 0))

2985       returnexp;

2986

2987     if (! strcmp_check (XSTR (exp, 1), XSTR (XEXP(*pterm, 0), 1)))

2988       return false_rtx;

2989     else

2990       *pterm = true_rtx;

2991   }

2992

2993   else if (GET_CODE (exp) == NOT &&GET_CODE (*pterm) == NOT)

2994   {

2995     if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))

2996       return true_rtx;

2997   }

2998

2999   else if (GET_CODE (exp) == NOT)

3000   {

3001     if (attr_equal_p (XEXP (exp, 0), *pterm))

3002       return false_rtx;

3003   }

3004

3005   else if (GET_CODE (*pterm) == NOT)

3006   {

3007     if (attr_equal_p (XEXP (*pterm, 0), exp))

3008       return false_rtx;

3009   }

3010

3011   else if (attr_equal_p (exp, *pterm))

3012     return true_rtx;

3013

3014   return exp;

3015 }

 

Back write_attr_set, at line 5160, write_test_exprgiven a piece of RTX, prints a C expression to test its truth value. Theparameter exphere is the textexpin write_attr_set – the testing after known true eliminated.

 

4559 static void

4560 write_test_expr (rtx exp, int flags)                                                               in genattrtab.c

4561 {

4562   int comparison_operator = 0;

4563   RTX_CODE code;

4564   struct attr_desc*attr;

4565

4566   /* In order not toworry about operator precedence, surround our part of

4567     the expression with parentheses.  */

4568

4569   printf ("(");

4570   code = GET_CODE (exp);

4571   switch (code)

4572   {

4573     /* Binaryoperators.  */

4574     case EQ: case NE:

4575     case GE: case GT: case GEU: case GTU:

4576     case LE: case LT: case LEU: case LTU:

4577       comparison_operator = 1;

4578

4579     casePLUS:   caseMINUS:  caseMULT:     caseDIV:      caseMOD:

4580     caseAND:    caseIOR:    caseXOR:

4581     caseASHIFT:  caseLSHIFTRT: case ASHIFTRT:

4582       write_test_expr (XEXP (exp, 0), flags | comparison_operator);

4583       switch(code)

4584       {

4585         caseEQ:

4586           printf (" == ");

4587           break;

4588         caseNE:

4589           printf (" != ");

4590           break;

4591         caseGE:

4592           printf (" >= ");

4593           break;

4594         caseGT:

4595           printf (" > ");

4596           break;

4597         caseGEU:

4598           printf (" >= (unsigned) ");

4599           break;

4600         caseGTU:

4601           printf (" > (unsigned) ");

4602           break;

4603         case LE:

4604           printf (" <= ");

4605           break;

4606         caseLT:

4607           printf (" < ");

4608           break;

4609         caseLEU:

4610           printf (" <= (unsigned) ");

4611           break;

4612         caseLTU:

4613           printf (" < (unsigned) ");

4614           break;

4615         casePLUS:

4616           printf (" + ");

4617           break;

4618         caseMINUS:

4619           printf (" - ");

4620           break;

4621         caseMULT:

4622           printf (" * ");

4623           break;

4624         caseDIV:

4625           printf (" / ");

4626           break;

4627         caseMOD:

4628           printf (" %% ");

4629           break;

4630         caseAND:

4631           if (flags & 1)

4632             printf (" & ");

4633           else

4634             printf (" && ");

4635           break;

4636         caseIOR:

4637           if (flags & 1)

4638             printf (" | ");

4639           else

4640             printf (" || ");

4641           break;

4642         case XOR:

4643           printf (" ^ ");

4644           break;

4645         caseASHIFT:

4646           printf (" << ");

4647           break;

4648         caseLSHIFTRT:

4649         caseASHIFTRT:

4650           printf (" >> ");

4651           break;

4652         default:

4653           abort ();

4654       }

4655

4656       write_test_expr (XEXP (exp, 1), flags | comparison_operator);

4657       break;

4658

4659     case NOT:

4660       /* Special-case (not (eq_attrq "alternative""x")) */

4661       if (! (flags & 1) && GET_CODE(XEXP (exp, 0)) == EQ_ATTR

4662           && XSTR (XEXP (exp, 0), 0) == alternative_name)

4663       {

4664         printf ("which_alternative != %s",XSTR (XEXP (exp, 0), 1));

4665         break;

4666       }

4667

4668       /* Otherwise,fall through to normal unary operator.  */

4669

4670    /* Unaryoperators.  */

4671    case ABS:  case NEG:

4672       switch(code)

4673       {

4674         caseNOT:

4675           if (flags & 1)

4676             printf ("~ ");

4677           else

4678             printf ("! ");

4679           break;

4680         caseABS:

4681           printf ("abs ");

4682           break;

4683         caseNEG:

4684           printf ("-");

4685           break;

4686         default:

4687           abort ();

4688       }

4689

4690       write_test_expr (XEXP (exp, 0), flags);

4691       break;

4692

4693     caseEQ_ATTR_ALT:

4694     {

4695       intset = XINT (exp, 0), bit = 0;

4696

4697       if(flags & 1)

4698         fatal ("EQ_ATTR_ALT not valid insidecomparison");

4699

4700       if(!set)

4701         fatal ("Empty EQ_ATTR_ALT should beoptimized out");

4702

4703       if(!(set & (set - 1)))

4704       {

4705         if (!(set & 0xffff))

4706         {

4707           bit += 16;

4708           set >>= 16;

4709         }

4710         if (!(set & 0xff))

4711         {

4712           bit += 8;

4713           set >>= 8;

4714         }

4715         if (!(set & 0xf))

4716         {

4717           bit += 4;

4718           set >>= 4;

4719         }

4720         if (!(set & 0x3))

4721         {

4722           bit += 2;

4723           set >>= 2;

4724         }

4725         if (!(set & 1))

4726           bit++;

4727

4728         printf ("which_alternative %s=%d",

4729              XINT (exp, 1) ? "!" : "=", bit);

4730       }

4731       else

4732       {

4733         printf ("%s((1 <<which_alternative) & 0x%x)",

4734              XINT (exp, 1) ? "!" : "", set);

4735       }

4736     }

4737     break;

4738

4739     /* Comparisontest of an attribute with a value. Most of these will

4740       have been removed by optimization. Handle"alternative"

4741       specially and give error if EQ_ATTRpresent inside a comparison.  */

4742     caseEQ_ATTR:

4743       if (flags & 1)

4744         fatal ("EQ_ATTR not valid insidecomparison");

4745

4746       if (XSTR (exp, 0) == alternative_name)

4747       {

4748         printf ("which_alternative == %s",XSTR (exp, 1));

4749         break;

4750       }

4751

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

4753       if (! attr)

4754         abort ();

4755

4756       /* Now is the time to expand the value of aconstant attribute.  */

4757       if (attr->is_const)

4758       {

4759         write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,

4760                                     -2, -2),

4761                       flags);

4762       }

4763       else

4764       {

4765         if (flags & 2)

4766           printf ("attr_%s",attr->name);

4767         else

4768           printf ("get_attr_%s (insn)",attr->name);

4769         printf(" == ");

4770         write_attr_valueq (attr, XSTR (exp, 1));

4771       }

4772       break;

4773

4774     /* Comparison test of flags fordefine_delays.  */

4775     case ATTR_FLAG:

4776      if (flags & 1)

4777         fatal ("ATTR_FLAG not valid insidecomparison");

4778       printf("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));

4779       break;

4780

4781     /* See if an operand matches a predicate.  */

4782     caseMATCH_OPERAND:

4783       /* If only a mode is given, just ensure themode matches the operand.

4784         If neither a mode nor predicate isgiven, error.  */

4785       if (XSTR (exp, 1) == NULL || *XSTR (exp,1) == '\0')

4786       {

4787         if (GET_MODE (exp) == VOIDmode)

4788           fatal ("null MATCH_OPERAND specifiedas test");

4789         else

4790           printf ("GET_MODE (operands[%d]) ==%smode",

4791         XINT (exp,0), GET_MODE_NAME (GET_MODE (exp)));

4792       }

4793       else

4794         printf ("%s (operands[%d],%smode)",

4795             XSTR (exp, 1), XINT (exp,0), GET_MODE_NAME (GET_MODE (exp)));

4796       break;

4797

4798     caseMATCH_INSN:

4799       printf ("%s (insn)", XSTR (exp,0));

4800       break;

4801

4802     /* Constantinteger.  */

4803     caseCONST_INT:

4804       printf (HOST_WIDE_INT_PRINT_DEC, XWINT (exp,0));

4805       break;

4806

4807     /* A random Cexpression.  */

4808     caseSYMBOL_REF:

4809       printf ("%s", XSTR (exp, 0));

4810       break;

4811

4812     /* The address ofthe branch target.  */

4813     caseMATCH_DUP:

4814       printf ("I

4815 NSN_ADDRESSES_SET_P() ? INSN_ADDRESSES (INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP(operands[%d], 0) : operands[%d])) : 0",

4816               XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));

4817       break;

4818

4819     case PC:

4820       /* The addressof the current insn. We implement this actually as the

4821         address of the current insn for backwardbranches, but the last

4822         address of the next insn for forward branches,and both with

4823         adjustments that account for the worst-casepossible stretching of

4824         intervening alignments between this insn andits destination.  */

4825       printf("insn_current_reference_address (insn)");

4826       break;

4827

4828     caseCONST_STRING:

4829       printf ("%s", XSTR (exp, 0));

4830       break;

4831

4832     caseIF_THEN_ELSE:

4833       write_test_expr (XEXP (exp, 0), flags & 2);

4834       printf (" ? ");

4835       write_test_expr (XEXP (exp, 1), flags | 1);

4836       printf (" : ");

4837       write_test_expr (XEXP (exp, 2), flags | 1);

4838       break;

4839

4840     default:

4841       fatal ("bad RTX code `%s' inattribute calculation\n",

4842            GET_RTX_NAME (code));

4843   }

4844

4845   printf (")");

4846 }

 

We can see the output gen_attr_* functions in insn-attrtab.c whichgenerated by this tool. Generally, the functions output will be in form asfollowing (content in green is not output).

 

get_attr_`attr-name`(rtx insn ATTRIBUTE_UNUSED)

{

  switch(recog_memoized (insn))

{

    case insn-code-n:                  //first attribute value expression

    case insn-code-p:

    …                                        // other insn for the same attribute value

extract_constrain_insn_cached(insn);      // usedaccording to attr characteristic.

                extract_insn_cached(insn);                     // used according to attr characteristic.

      if(`attr-test-1` )                 // for attribute value of cond

      {

        returnattr-val-1;

      }

      else if (…)                        // for attribute value of cond

       …

      else                                  // for attribute value of cond

       …

      break;

    …                                        // other insn

         break;

    case insn-code-s:                  // second attribute valueexpression

    …                                        // other insn for the same attribute value

extract_constrain_insn_cached(insn);        // usedaccording to attr characteristic.

extract_insn_cached(insn);                      //used according to attr characteristic.

     returnattr-val-q;                 // for simple attrinute value

     break;

  }

}

抱歉!评论已关闭.