Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ti_res_res.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 static const char source_file[] = __FILE__;
00037 
00038 #include <alloca.h>
00039 #include <limits.h>
00040 
00041 #include "defs.h"
00042 #include "erglob.h"
00043 #include "mempool.h"
00044 #include "bitset.h"
00045 #include "ti_si.h"
00046 
00047 #include "ti_res_res.h"
00048 
00049 /* Declare the TI_RES_RES opaque type (a context for resource reservation 
00050  * actitivies):
00051  */
00052 struct ti_res_res {
00053   MEM_POOL *pool;               /* For our dynamic memory needs              */
00054   SI_RRW   *rrtab;              /* First cycle (word) of table               */
00055   INT32     length;             /* Current length of the table               */
00056   INT32     alloc_size;         /* Its allocated size (in cycles)            */
00057   BOOL      cyclic;             /* Is this a schedule for a loop, e.g.       */
00058                                 /* modulo scheduling for software pipelining */
00059 
00060   /* Fields used only for cyclic scheduling:
00061    */
00062   BS       *si_ids;             /* Set of the scheduling information IDs     */
00063                                 /* being scheduled                           */
00064   UINT      min_rr_length;      /* minimum length of any or the RRs being    */
00065                                 /* scheduled.                                */
00066   SI_RESOURCE_ID_SET *uncommon_res_ids;
00067                                 /* ith element is a set of resource IDs used */
00068                                 /* in the ith cycle by some, but not all the */
00069                                 /* opcodes being scheduled.                  */
00070   SI_BAD_II_SET bad_iis;        /* Impossible IIs given the opcodes being    */
00071                                 /* scheduled                                 */
00072 };
00073 
00074 /* TI_RES_RES accessors:
00075  */
00076 #define TI_RES_RES_pool(t)              ((t)->pool)
00077 #define TI_RES_RES_rrtab(t)             ((t)->rrtab)
00078 #define TI_RES_RES_length(t)            ((t)->length)
00079 #define TI_RES_RES_alloc_size(t)        ((t)->alloc_size)
00080 #define TI_RES_RES_cyclic(t)            ((t)->cyclic)
00081 #define TI_RES_RES_si_ids(t)            ((t)->si_ids)
00082 #define TI_RES_RES_min_rr_length(t)     ((t)->min_rr_length)
00083 #define TI_RES_RES_uncommon_res_ids(t)  ((t)->uncommon_res_ids)
00084 #define TI_RES_RES_bad_iis(t)           ((t)->bad_iis)
00085 
00086 
00087 /* ====================================================================
00088  *
00089  *  Cycle_Mod_II
00090  *
00091  *  Return the cycle number modulo the II. See be/cg/swp_ii_funcs.[ch]
00092  *  for a discussion of why we just don't use the remainder operator
00093  *  (performance).
00094  *
00095  *  TODO: in general the cycle should be close, so the simple loop is 
00096  *  probably good enough. Verify that this is true.
00097  *
00098  * ====================================================================
00099  */
00100 static INT32
00101 Cycle_Mod_II(
00102   INT32 cyc,
00103   INT32 ii
00104 )
00105 {
00106   if ( cyc < 0 ) {
00107     do {
00108       cyc += ii;
00109     } while (cyc < 0);
00110   } else if (cyc >= ii) {
00111     do {
00112       cyc -= ii;
00113     } while (cyc >= ii);
00114   }
00115 
00116   return cyc;
00117 }
00118 
00119 
00120 /* ====================================================================
00121  *
00122  *  TI_RES_RES_Has_TOP
00123  *
00124  *  See interface description
00125  *
00126  * ====================================================================
00127  */
00128 void TI_RES_RES_Has_TOP( 
00129   TI_RES_RES *res,
00130   TOP         opcode
00131 )
00132 {
00133   if ( !BS_MemberP(TI_RES_RES_si_ids(res), TSI_Id(opcode) ) ) {
00134     UINT rr_length;
00135 
00136     TI_RES_RES_si_ids(res) = BS_Union1D(TI_RES_RES_si_ids(res),
00137                                         TSI_Id(opcode),
00138                                         TI_RES_RES_pool(res));
00139     TI_RES_RES_bad_iis(res) = SI_BAD_II_SET_Union(TI_RES_RES_bad_iis(res),
00140                                                   TSI_Bad_IIs(opcode));
00141 
00142     rr_length = SI_RR_Length(TSI_Resource_Requirement(opcode));
00143     if ( rr_length < TI_RES_RES_min_rr_length(res) ) {
00144       TI_RES_RES_min_rr_length(res) = rr_length;
00145     }
00146   }
00147 }
00148 
00149 
00150 /* Set up some constrol variables common to Resource_Available,
00151  * Reserve_Resources, and Unreserve_Resources.  The idea is to break the
00152  * work into two loops and obviate the need to do a Mod operation for every
00153  * cycle checked.  The first should check <length1> cycles of <rr>, starting
00154  * with cycle 0 of <rr> and cycle <cycle_mod_ii> of the schedule.  The
00155  * second loop should theck <length1> cycles of <rr>, starting with cycle
00156  * <length1> of <rr> and cycle 0 of the schedule.
00157  */
00158 static void Check_Reserve_Loop_Control(
00159   TI_RES_RES *res,
00160   TOP         opcode, 
00161   INT         cycle,
00162   SI_RR      *rr,
00163   INT        *length1, 
00164   INT        *length2,
00165   INT        *cycle_mod_ii
00166 )
00167 {
00168   INT32 rr_length;
00169   INT32 length = TI_RES_RES_length(res);
00170 
00171   if ( TI_RES_RES_cyclic(res) ) {
00172     *rr = TSI_II_Resource_Requirement(opcode,length);
00173   }
00174   else {
00175     *rr = TSI_Resource_Requirement(opcode);
00176   }
00177   *cycle_mod_ii = Cycle_Mod_II(cycle,length);
00178 
00179   rr_length = SI_RR_Length(*rr);
00180   if ( *cycle_mod_ii + rr_length <= length ) {
00181     *length1 = rr_length;
00182     *length2 = 0;
00183   }
00184   else {
00185     *length1 = length - *cycle_mod_ii;
00186     *length2 = rr_length - *length1;
00187   }
00188 }
00189 
00190 
00191 /* ====================================================================
00192  *
00193  *  TI_RES_RES_Set_BB_Cycle_Count
00194  *
00195  *  See interface description
00196  *
00197  * ====================================================================
00198  */
00199 void TI_RES_RES_Set_BB_Cycle_Count(
00200   TI_RES_RES  *res,
00201   INT          length
00202 )
00203 {
00204   INT  i;
00205   BOOL cyclic = TI_RES_RES_cyclic(res);
00206 
00207   if ( length > TI_RES_RES_alloc_size(res) ) {
00208     INT new_alloc_size = length * 2;
00209     TI_RES_RES_alloc_size(res) = new_alloc_size;
00210 
00211     TI_RES_RES_rrtab(res) = TYPE_MEM_POOL_ALLOC_N(SI_RRW,
00212                                         TI_RES_RES_pool(res),
00213                                         new_alloc_size);
00214     if ( cyclic ) {
00215       TI_RES_RES_uncommon_res_ids(res)
00216         = TYPE_MEM_POOL_ALLOC_N(SI_RESOURCE_ID_SET,
00217                                 TI_RES_RES_pool(res),
00218                                 new_alloc_size);
00219     }
00220   }
00221 
00222   TI_RES_RES_length(res) = length;
00223 
00224   /* Initialize the part of the table we will use
00225    */
00226   for ( i = 0; i < length; ++i ) {
00227     TI_RES_RES_rrtab(res)[i] = SI_RRW_Initial();
00228   }
00229 
00230   if ( cyclic ) {
00231     INT id;
00232     BS *si_ids = TI_RES_RES_si_ids(res);
00233     SI_RESOURCE_ID_SET *uncommon_res_ids = TI_RES_RES_uncommon_res_ids(res);
00234     INT common_length = MIN(TI_RES_RES_min_rr_length(res), length);
00235 
00236     /* For each cycle, compute the set of resources that not all the OPs in
00237      * the loop use in that cycle.  We do this by computing its complement --
00238      * the set of resources that all the OPs use in the cycle -- and then
00239      * complementing it in place.
00240      */
00241 
00242     /* Compute common resources into "uncommon_res_ids"
00243      *
00244      * NOTE: the following loop also initializes the "res_ids"
00245      * from common_length to the end of the vector. These
00246      * are by definition not common to all OPs, and we will leave
00247      * the setting unchanged in the following loops.
00248      */
00249     for ( i = 0; i < length; ++i ) {
00250       uncommon_res_ids[i] = SI_RESOURCE_ID_SET_Universe();
00251     }
00252 
00253     for ( id = BS_Choose(si_ids); id != BS_CHOOSE_FAILURE;
00254                                   id = BS_Choose_Next(si_ids,id)
00255     ) {
00256       const SI_RESOURCE_ID_SET* resource_ids_used
00257         = SI_ID_II_Cycle_Resource_Ids_Used(id,length);
00258 
00259       for ( i = 0; i < common_length; ++i ) {
00260         uncommon_res_ids[i]
00261           = SI_RESOURCE_ID_SET_Intersection(uncommon_res_ids[i],
00262                                             resource_ids_used[i]);
00263       }
00264     }
00265 
00266     /* Complement in place
00267      */
00268     for ( i = 0; i < common_length; ++i ) {
00269       uncommon_res_ids[i] =
00270         SI_RESOURCE_ID_SET_Complement(uncommon_res_ids[i]);
00271     }
00272   }
00273 }
00274 
00275 
00276 /* ====================================================================
00277  *
00278  *  TI_RES_RES_Alloc
00279  *
00280  *  See interface description
00281  *
00282  * ====================================================================
00283  */
00284 TI_RES_RES *TI_RES_RES_Alloc(
00285   BOOL      cyclic,
00286   MEM_POOL *pool
00287 )
00288 {
00289   TI_RES_RES *res = TYPE_MEM_POOL_ALLOC(TI_RES_RES, pool);
00290 
00291   TI_RES_RES_pool(res) = pool;
00292   TI_RES_RES_cyclic(res) = cyclic;
00293   TI_RES_RES_bad_iis(res) = SI_BAD_II_SET_Empty();
00294   TI_RES_RES_length(res) = 0;
00295   TI_RES_RES_alloc_size(res) = 0;
00296   TI_RES_RES_min_rr_length(res) = UINT_MAX;
00297 
00298   if ( cyclic ) {
00299     TI_RES_RES_si_ids(res) = BS_Create_Empty(SI_ID_Count(), pool);
00300   }
00301 
00302   return res;
00303 }
00304 
00305 
00306 /* ====================================================================
00307  *
00308  *  TI_RES_RES_Resources_Available
00309  *
00310  *  See interface description
00311  *
00312  * ====================================================================
00313  */
00314 BOOL TI_RES_RES_Resources_Available(
00315   TI_RES_RES  *res,
00316   TOP          opcode,
00317   INT          cycle
00318 )
00319 {
00320   INT     cycle_mod_ii;
00321   INT     length1;
00322   INT     length2;
00323   INT     i;
00324   SI_RR   rr;
00325   SI_RRW *rrtab = TI_RES_RES_rrtab(res);
00326 
00327   Check_Reserve_Loop_Control(res,opcode,cycle,
00328                              &rr,&length1,&length2,&cycle_mod_ii);
00329 
00330   for ( i = 0; i < length1; ++i ) {
00331     SI_RRW reserved = SI_RRW_Reserve(rrtab[cycle_mod_ii+i],
00332                                      SI_RR_Cycle_RRW(rr,i));
00333     if ( SI_RRW_Has_Overuse(reserved) ) return FALSE;
00334   }
00335 
00336   for ( i = 0; i < length2; ++i ) {
00337     SI_RRW reserved = SI_RRW_Reserve(rrtab[i],SI_RR_Cycle_RRW(rr,i+length1));
00338     if ( SI_RRW_Has_Overuse(reserved) ) return FALSE;
00339   }
00340 
00341   return TRUE;
00342 }
00343 
00344 
00345 /* ====================================================================
00346  *
00347  *  TI_RES_RES_Reserve_Resources
00348  *
00349  *  See interface description
00350  *
00351  * ====================================================================
00352  */
00353 void TI_RES_RES_Reserve_Resources(
00354   TI_RES_RES  *res,
00355   TOP          opcode,
00356   INT          cycle
00357 )
00358 {
00359   INT     cycle_mod_ii;
00360   INT     length1;
00361   INT     length2;
00362   INT     i;
00363   SI_RR   rr;
00364   SI_RRW *rrtab = TI_RES_RES_rrtab(res);
00365 
00366   Check_Reserve_Loop_Control(res,opcode,cycle,
00367                              &rr,&length1,&length2,&cycle_mod_ii);
00368 
00369   for ( i = 0; i < length1; ++i ) {
00370     rrtab[cycle_mod_ii+i]
00371       = SI_RRW_Reserve(rrtab[cycle_mod_ii+i],SI_RR_Cycle_RRW(rr,i));
00372   }
00373 
00374   for ( i = 0; i < length2; ++i ) {
00375     rrtab[i] = SI_RRW_Reserve(rrtab[i],SI_RR_Cycle_RRW(rr,i+length1));
00376   }
00377 }
00378 
00379 
00380 /* ====================================================================
00381  *
00382  *  TI_RES_RES_Unreserve_Resources
00383  *
00384  *  See interface description
00385  *
00386  * ====================================================================
00387  */
00388 void TI_RES_RES_Unreserve_Resources(
00389   TI_RES_RES  *res,
00390   TOP          opcode,
00391   INT          cycle
00392 )
00393 {
00394   INT     cycle_mod_ii;
00395   INT     length1;
00396   INT     length2;
00397   INT     i;
00398   SI_RR   rr;
00399   SI_RRW *rrtab = TI_RES_RES_rrtab(res);
00400 
00401   Check_Reserve_Loop_Control(res,opcode,cycle,
00402                              &rr,&length1,&length2,&cycle_mod_ii);
00403 
00404   for ( i = 0; i < length1; ++i ) {
00405     rrtab[cycle_mod_ii+i]
00406       = SI_RRW_Unreserve(rrtab[cycle_mod_ii+i],SI_RR_Cycle_RRW(rr,i));
00407   }
00408 
00409   for ( i = 0; i < length2; ++i ) {
00410     rrtab[i] = SI_RRW_Unreserve(rrtab[i],SI_RR_Cycle_RRW(rr,i+length1));
00411   }
00412 }
00413 
00414 
00415 /* ====================================================================
00416  *
00417  *  TI_RES_RES_Is_Bad_II
00418  *
00419  *  See interface description
00420  *
00421  * ====================================================================
00422  */
00423 BOOL TI_RES_RES_Is_Bad_II(
00424   TI_RES_RES  *res,
00425   INT          ii
00426 )
00427 {
00428   return SI_BAD_II_SET_MemberP(TI_RES_RES_bad_iis(res),ii);
00429 }
00430 
00431 
00432 /* ====================================================================
00433  *
00434  *  TI_RES_RES_Resources_Relevant
00435  *
00436  *  See interface description
00437  *
00438  * ====================================================================
00439  */
00440 BOOL TI_RES_RES_Resources_Relevant(
00441   TI_RES_RES  *res,
00442   TOP          opcode1,
00443   TOP          opcode2,
00444   INT          offset
00445 )
00446 {
00447   INT length1, length2, i;
00448   const INT32 length = TI_RES_RES_length(res);
00449   const SI_RESOURCE_ID_SET *const res_ids1
00450     = TSI_II_Cycle_Resource_Ids_Used(opcode1,length);
00451   const SI_RESOURCE_ID_SET *const res_ids2
00452     = TSI_II_Cycle_Resource_Ids_Used(opcode2,length);
00453   const INT rr1_length
00454     = SI_RR_Length(TSI_II_Resource_Requirement(opcode1,length));
00455   const INT rr2_length
00456     = SI_RR_Length(TSI_II_Resource_Requirement(opcode2,length));
00457   const INT offset_mod_ii = Cycle_Mod_II(offset,length);
00458   const SI_RESOURCE_ID_SET *const uncommon_res_ids 
00459     = TI_RES_RES_uncommon_res_ids(res);
00460 
00461   FmtAssert (TI_RES_RES_cyclic(res),
00462         ("TI_RES_RES_Resources_Relevant not applicable to non-cyclic schedules"));
00463 
00464   /* Check from the start of rr2 until either the end of rr2 or the end of
00465    * rr1 + offset (which cannot be greater than II-1.)
00466    */
00467   length1 = rr1_length - offset_mod_ii;
00468   if ( rr2_length < length1 ) length1 = rr2_length;
00469 
00470   for ( i = 0; i < length1; ++i ) {
00471     if ( SI_RESOURCE_ID_SET_Intersection4_Non_Empty(
00472            res_ids1[i + offset_mod_ii],
00473            uncommon_res_ids[i + offset_mod_ii],
00474            res_ids2[i],
00475            uncommon_res_ids[i] )
00476     ) {
00477       return TRUE;
00478     }
00479   }
00480 
00481   /* The resource requirements for opcode1 (rr1) and opcode2 (rr2)
00482    * are already modulo the II. But we are comparing rr2 at an offset
00483    * from rr1, therefore we may have some cycles and the end of rr2 
00484    * that wrap around to the beginning of rr1. If that is the case,
00485    * check those cycles. Note that rr2 can only wrap once (because
00486    * we have use the offset mod II), and some cycles in the middle 
00487    * of rr2 may not need to be checked against rr1 (because rr1 might
00488    * consume no resource in those cycles).
00489    */
00490   length2 = (rr2_length + offset_mod_ii) - length;
00491   if ( length > 0 ) {
00492     if ( rr1_length < length2 ) length2 = rr1_length;
00493 
00494     for ( i = 0; i < length2; ++i ) {
00495       if ( SI_RESOURCE_ID_SET_Intersection4_Non_Empty(
00496              res_ids1[i],
00497              uncommon_res_ids[i],
00498              res_ids2[i + length - offset_mod_ii],
00499              uncommon_res_ids[i + length - offset_mod_ii] )
00500       ) {
00501         return TRUE;
00502       }
00503     }
00504   }
00505 
00506   return FALSE;
00507 }
00508 
00509 
00510 /* ====================================================================
00511  *
00512  *  TI_RES_RES_Resources_Equivalent
00513  *
00514  *  See interface description
00515  *
00516  * ====================================================================
00517  */
00518 BOOL TI_RES_RES_Resources_Equivalent(
00519   TI_RES_RES  *res,
00520   TOP          opcode1,
00521   TOP          opcode2
00522 )
00523 {
00524   INT i;
00525   const INT32 length = TI_RES_RES_length(res);
00526   SI_RR rr1 = TSI_II_Resource_Requirement(opcode1,length);
00527   SI_RR rr2 = TSI_II_Resource_Requirement(opcode2,length);
00528 
00529   if ( rr1 == rr2 ) return TRUE;
00530 
00531   if ( SI_RR_Length(rr1) != SI_RR_Length(rr2) ) return FALSE;
00532 
00533   for (i = 0; i < SI_RR_Length(rr1); ++i) {
00534     if ( SI_RR_Cycle_RRW(rr1,i) != SI_RR_Cycle_RRW(rr2,i) )
00535       return FALSE;
00536   }
00537 
00538   return TRUE;
00539 }
00540 
00541 
00542 /* ====================================================================
00543  *
00544  *  TI_RES_RES_Resource_Grainy
00545  *
00546  *  See interface description
00547  *
00548  * ====================================================================
00549  */
00550 BOOL TI_RES_RES_Resources_Grainy(
00551   TI_RES_RES  *res,
00552   TOP          opcode
00553 )
00554 {
00555   INT i;
00556   const INT32 length = TI_RES_RES_length(res);
00557   SI_RESOURCE_ID_SET *uncommon_res_ids = TI_RES_RES_uncommon_res_ids(res);
00558   UINT min_rr_length = TI_RES_RES_min_rr_length(res);
00559   const SI_RESOURCE_ID_SET* res_used
00560     = TSI_II_Cycle_Resource_Ids_Used(opcode,length);
00561   INT res_used_length
00562     = SI_RR_Length(TSI_II_Resource_Requirement(opcode,length));
00563 
00564   if ( min_rr_length < res_used_length ) return TRUE;
00565 
00566   for ( i = 0; i < min_rr_length; ++i ) {
00567     if ( SI_RESOURCE_ID_SET_Intersection_Non_Empty(res_used[i],
00568                                                    uncommon_res_ids[i])
00569     ) {
00570       return TRUE;
00571     }
00572   }
00573 
00574   return FALSE;
00575 }
00576 
00577 
00578 INT TI_RES_RES_Resources_Length(
00579   TI_RES_RES  *res,
00580   TOP          opcode
00581 )
00582 {
00583   return SI_RR_Length(TSI_Resource_Requirement(opcode));
00584 }
00585 
00586 
00587 void TI_RES_RES_Print(FILE *fp, TI_RES_RES *res)
00588 {
00589   INT i;
00590   for (i = 0; i < TI_RES_RES_length(res); i++) 
00591     fprintf(fp, "%d --> 0x%0llx\n", i,  TI_RES_RES_rrtab(res)[i]);
00592 }
00593 
00594 
00595 BOOL TI_RES_RES_Equal(TI_RES_RES *res1, TI_RES_RES *res2)
00596 {
00597   INT i;
00598   if (TI_RES_RES_length(res1) != TI_RES_RES_length(res2)) return FALSE;
00599   for (i = 0; i < TI_RES_RES_length(res1); i++) 
00600     if (TI_RES_RES_rrtab(res1)[i] != TI_RES_RES_rrtab(res2)[i])
00601       return FALSE;
00602   return TRUE;
00603 }
00604 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines