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

9.6.2. Output data for delay

For i386 architecture, no define_delay is used. However, it is worthto have a look how this pattern works.

 

main (continued)

 

6212   /* Write out delay eligibility information,if DEFINE_DELAY present.

6213     (The function to compute the number ofdelay slots will be written

6214     below.) */

6215   if (num_delays)

6216   {

6217     write_eligible_delay("delay");

6218     if (have_annul_true)

6219       write_eligible_delay("annul_true");

6220     if (have_annul_false)

6221       write_eligible_delay("annul_false");

6222   }

 

In expand_delays, system will create attribute “*delay_type” in following shape:

*delay_type(

  cond ([

    (condexp-1)            ;; test part of first define_delay

    (const_string “1”)    ;;NO. of the define_delay

        (condexp-2)           ;; test part of second define_delay

        (const_string “2”)   ;;NO. of the define_delay

        …                         ;; other define_delay

]

const_string “0”)

)

Then are series of attribute “*delay_`NO`_`slot-NO`” whichcontains following data. These attribute indicate the testings that must besatisified for instruction being placed into the slot.

*delay_`NO`_`slot-NO` (

cond [ (DELAY-`slot-NO`“1”) ]   ;; attribute test for delay slot

     “0”)

)

Following are series of attribute “*annul_true_`NO`_`slot-NO`” whichcontains following data. These attributes indicate the testing that must besatisified for instruction being annulled if the branch is true.

*annul_true_`NO`_`slot-NO` (

        cond [ (ANNUL-TRUE-`slot-NO` “1”) ]      ;;attribute test for insn annul

“0”)

)

Next are series of attribute “*annul_false_`NO`_`slot-NO`” whichcontains following data. These attributes indicate the testing that must besatisified for instruction being annulled if the branch is false.

*annul_false_`NO`_`slot-NO` (

        cond [ (ANNUL-FALSE-`slot-NO` “1”) ]    ;;attribute test for insn annul

 “0”)

)

Notice that though expand_delay usesif_then_else for the rear 3 attribute series, make_internal_attr it uses tocreate these attributes will transform if_then_else into cond by make_canonical. Here write_eligible_delay will outputfunctions for these attributes.

 

5497 static void

5498 write_eligible_delay (const char *kind)                                                in genattrtab.c

5499 {

5500   struct delay_desc*delay;

5501   int max_slots;

5502   char str[50];

5503  const char*pstr;

5504   struct attr_desc*attr;

5505   struct attr_value*av, *common_av;

5506   int i;

5507

5508   /* Compute themaximum number of delay slots required. We use the delay

5509     ordinal times this number plus one, plusthe slot number as an index into

5510     the appropriate predicate to test.  */

5511

5512   for (delay = delays,max_slots = 0; delay; delay = delay->next)

5513     if (XVECLEN (delay->def, 1) / 3 >max_slots)

5514       max_slots = XVECLEN (delay->def, 1) /3;

5515

5516   /* Write functionprelude.  */

5517

5518   printf ("int\n");

5519   printf ("eligible_for_%s (rtx delay_insnATTRIBUTE_UNUSED, int slot, rtx

5520             candidate_insn, int flags ATTRIBUTE_UNUSED)\n", kind);

5521   printf ("{\n");

5522   printf ("  rtx insn;\n");

5523   printf ("\n");

5524   printf ("  if (slot >= %d)\n", max_slots);

5525   printf ("    abort ();\n");

5526   printf ("\n");

5527

5528   /* If more than onedelay type, find out which type the delay insn is.  */

5529

5530   if (num_delays > 1)

5531   {

5532     attr = find_attr(&delay_type_str,0);

5533     if (! attr)

5534       abort ();

5535     common_av = find_most_used (attr);

5536

5537     printf ("  insn = delay_insn;\n");

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

5539     printf ("    {\n");

5540

5541     sprintf (str, " * %d;\n      break;", max_slots);

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

5543       if(av != common_av)

5544         write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);

5545

5546     write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);

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

5548

5549     /* Ensurematched. Otherwise, shouldn't have been called. */

5550     printf ("  if (slot < %d)\n", max_slots);

5551     printf ("    abort ();\n\n");

5552   }

5553

5554   /* If just one typeof delay slot, write simple switch.  */

5555   if (num_delays == 1 && max_slots == 1)

5556   {

5557     printf ("  insn = candidate_insn;\n");

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

5559     printf ("    {\n");

5560

5561     attr = find_attr(&delay_1_0_str,0);

5562     if (! attr)

5563       abort ();

5564     common_av = find_most_used (attr);

5565

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

5567       if (av != common_av)

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

5569

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

5571     printf ("    }\n");

5572   }

5573

5574   else

5575   {

5576     /* Write a nestedCASE. The first indicates which condition we need to

5577       test, and the inner CASE tests thecondition.  */

5578     printf ("  insn = candidate_insn;\n");

5579     printf ("  switch (slot)\n");

5580     printf ("    {\n");

5581

5582     for (delay= delays;delay; delay = delay->next)

5583       for (i =0; i < XVECLEN (delay->def, 1); i += 3)

5584       {

5585         printf ("    case %d:\n",

5586               (i / 3) + (num_delays == 1 ? 0 : delay->num* max_slots));

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

5588         printf ("\t{\n");

5589

5590         sprintf (str, "*%s_%d_%d",kind, delay->num, i / 3);

5591         pstr = str;

5592         attr = find_attr(&pstr, 0);

5593         if (! attr)

5594           abort ();

5595         common_av = find_most_used (attr);

5596

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

5598           if (av != common_av)

5599             write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);

5600

5601         write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);

5602         printf ("      }\n");

5603       }

5604

5605       printf ("    default:\n");

5606       printf ("      abort ();\n");

5607       printf ("    }\n");

5608   }

5609

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

5611 }

 

We take eligible_for_delay for example see what weget. eligible_for_delayis produced for attributes of “*delay_type”, and “*delay_`NO`_`slot-NO`”.

 

int

eligible_for_delay(rtx delay_insn ATTRIBUTE_UNUSED, int slot, rtx

     candidate_insn, int flags ATTRIBUTE_UNUSED)

{

  rtx insn;

 

  if (slot >= `max_slot`)        // max_slot records the biggest slot number in define_delays.

abort();

      

         insn = delay_insn;

         switch (recog_memoized (insn))

         {

           case `insn-code-m` :      // insn of code m matching define_delay of n

              case …                         // other matching insns

extract_constrain_insn_cached (insn);      // used according to attr char.

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

                if (`condexp-n-s`)       // test partof define_delay of n after simplified

                {

               slot += n * `max_slot ;

                  break ;

                }

                else

                {

                     slot+= 0 * `max_slot` ; // should not happen

                     break ;

                }

              …                                // other insns

              default:

extract_constrain_insn_cached (insn);      // used according to attr char.

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

                if (`condexp-d-s`)       // test partof most common used delay after simplified

                {

                  slot += d * `max_slot ;  // d is num of most common used delay

                  break ;

}

else

{

  slot += 0 ;            // slot +=0 * `max_slot`, should not happen

  break ;

}

         }

 

         if (slot < `max_slot`)

           abort() ;

 

         insn = candidate_insn;

         switch (slot)

         {

              case0 * `max_slot` + 0:      

             switch (recog_memoized (insn))

                {

                     case`insn-code-p` :              // insn of code p matching define_delay of 0

                     case… :                       // other matching insns

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

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

                       if (`delay-0-0-s`)        // attr testfor 0 slot of define_delay of 0 after simplified

                         return 1 ;

                       else

                            return0 ;

                       break ;

                     …                                // other insns

                     default :

extract_constrain_insn_cached (insn);      // used according to attr char.

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

                       if (`delay-0-d-s`) // attr test forslot of most used of define_delay of 0 after simplified

                            return1 ;

                       else

                            return0 ;

                }

              case 0 *`max_slot` + 1 :

                …                                    // other slots

              default :

                abort() ;

         }

}

 

eligible_for_delay given instruction delay_insn, checks if instruction candidate_insn canbe placed into slot.See the usage of `delay-NO` * `max_slot` + `slot-NO`, and how it extracts datafrom attributes related.

你可能感兴趣的:(struct,gcc,branch,attributes,testing,delay)