Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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