00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "cgir.h"
00029 #include "glob.h"
00030 #include "tn_map.h"
00031 #include "cgtarget.h"
00032 #include "cg_vector.h"
00033 #include "gra_live.h"
00034 #include "freq.h"
00035 #include "ti_res.h"
00036 #include "register.h"
00037 #include "tracing.h"
00038 #include "config_asm.h"
00039 #include "note.h"
00040 #include "cgexp.h"
00041 #include "lra.h"
00042 #include "wn_util.h"
00043 #include "hb_hazards.h"
00044 #include "reg_live.h"
00045 #include <unistd.h>
00046 #include <sys/types.h>
00047 #include <sys/wait.h>
00048 #include <math.h>
00049
00050 #include "cg_sched.h"
00051
00052 enum ICU { NONE = 0, ALU, AGU, FADD, FMUL, FMISC };
00053
00054 static unsigned int BBs_Processed = 0;
00055
00056 static ICU TOP_2_Res[TOP_count];
00057
00058 static uint16_t sched_order = 0;
00059
00060 typedef struct {
00061 TN* mem_base;
00062 TN* mem_index;
00063 ST* mem_sym;
00064 uint64_t mem_ofst;
00065
00066 uint16_t uses;
00067 uint16_t latency;
00068
00069 uint16_t sched_order;
00070 uint16_t pred_order;
00071 int16_t release_time;
00072 int16_t issue_time;
00073 int16_t deadline;
00074
00075 uint16_t num_succs;
00076 uint16_t num_preds;
00077
00078 bool is_scheduled;
00079 } OPR;
00080
00081 static OPR* opr_array = NULL;
00082
00083 #define ASSERT(c) FmtAssert( c, ("KEY_SCH error") );
00084
00085 #define Get_OPR(op) (&opr_array[OP_map_idx(op)])
00086 #define OPR_release_time(o) ((o)->release_time)
00087 #define OPR_deadline(o) ((o)->deadline)
00088 #define OPR_issue_time(o) ((o)->issue_time)
00089 #define OPR_is_scheduled(o) ((o)->is_scheduled == true)
00090 #define Set_OPR_is_scheduled(o) ((o)->is_scheduled = true)
00091 #define OPR_num_preds(o) ((o)->num_preds)
00092 #define OPR_num_succs(o) ((o)->num_succs)
00093 #define OPR_sched_order(o) ((o)->sched_order)
00094 #define OPR_pred_order(o) ((o)->pred_order)
00095 #define OPR_mem_base(o) ((o)->mem_base)
00096 #define OPR_mem_index(o) ((o)->mem_index)
00097 #define OPR_mem_ofst(o) ((o)->mem_ofst)
00098 #define OPR_mem_sym(o) ((o)->mem_sym)
00099 #define OPR_uses(o) ((o)->uses)
00100 #define OPR_latency(o) ((o)->latency)
00101
00102 static const int num_fu[] = {
00103 0,
00104 3,
00105 3,
00106 1,
00107 1,
00108 1,
00109 };
00110
00111
00112 class MRT {
00113 private:
00114 BOOL trace;
00115
00116 REGISTER_SET live_in[ISA_REGISTER_CLASS_MAX+1];
00117 REGISTER_SET live_out[ISA_REGISTER_CLASS_MAX+1];
00118 REGISTER_SET avail_regs[ISA_REGISTER_CLASS_MAX+1];
00119
00120 static const int mem_ops_rate = 2;
00121
00122 struct Resource_Table_Entry {
00123 uint8_t decoded_ops;
00124 uint8_t mem_ops;
00125 uint8_t fp_ops;
00126 bool resources[6][3];
00127 };
00128
00129 void Init_Table_Entry( Resource_Table_Entry* e )
00130 {
00131 e->decoded_ops = e->mem_ops = e->fp_ops = 0;
00132
00133 bzero( e->resources, sizeof(e->resources) );
00134 for( int i = NONE; i <= FMISC; i++ ){
00135 for( int j = 0; j < num_fu[i]; j++ ){
00136 e->resources[i][j] = true;
00137 }
00138 }
00139 }
00140
00141 bool Probe_Resources( int cycle, OP* op, int, bool take_it );
00142 int Get_Dispatch_Unit( OP*, int );
00143
00144 bool TOP_is_convert( const TOP top )
00145 {
00146 return ( top == TOP_cvttss2si || top == TOP_cvttsd2si ||
00147 top == TOP_cvttss2siq || top == TOP_cvttsd2siq ||
00148 top == TOP_cvtsi2sd || top == TOP_cvtsi2ss ||
00149 top == TOP_cvtsi2sdq || top == TOP_cvtsi2ssq ||
00150 top == TOP_cvtss2sd || top == TOP_cvtsd2ss );
00151 }
00152
00153 bool TOP_is_lea( const TOP top )
00154 {
00155 return ( top == TOP_lea32 || top == TOP_lea64 ||
00156 top == TOP_leax32 || top == TOP_leax64 ||
00157 top == TOP_leaxx32 || top == TOP_leaxx64 );
00158 }
00159
00160 int entries;
00161 Resource_Table_Entry** Resource_Table;
00162
00163 public:
00164 MRT() {};
00165 ~MRT() {};
00166
00167 static const int issue_rate = 3;
00168
00169 void Init( BB*, int, BOOL, MEM_POOL* );
00170 void Reserve_Resources( OP*, int );
00171 void Set_Completion_Time( OP* );
00172 void Compute_Issue_Time( OP*, int );
00173 bool Decoder_is_Saturated( int c )
00174 {
00175 return Resource_Table[c]->decoded_ops == issue_rate;
00176 }
00177
00178 bool Memory_Saturated( int cycle )
00179 {
00180 return Resource_Table[cycle]->mem_ops >= mem_ops_rate;
00181 }
00182
00183 int Decoded_Ops( int c ) { return Resource_Table[c]->decoded_ops; }
00184 };
00185
00186 static MRT mrt;
00187
00188
00189 static void Print_Register_Set( const char* name, REGISTER_SET reg_set, ISA_REGISTER_CLASS cl )
00190 {
00191 if( REGISTER_SET_EmptyP( reg_set ) )
00192 return;
00193
00194 fprintf( TFile, "%s: \n\t", name );
00195 REGISTER_SET_Print( reg_set, TFile );
00196 fprintf( TFile, "\n\t(Registers):");
00197
00198 REGISTER reg;
00199 FOR_ALL_REGISTER_SET_members( reg_set, reg) {
00200 fprintf( TFile, " %s", REGISTER_name(cl, reg) );
00201 }
00202
00203 fprintf (TFile, "\n");
00204 }
00205
00206
00207 void MRT::Init( BB* bb, int size, BOOL trace, MEM_POOL* mem_pool )
00208 {
00209 static bool TOP_2_Res_is_valid = false;
00210
00211 entries = size;
00212 this->trace = trace;
00213 Resource_Table = (MRT::Resource_Table_Entry**)
00214 MEM_POOL_Alloc( mem_pool, (sizeof(Resource_Table[0]) * entries) );
00215
00216 for( int i = 0; i < entries; i++ ){
00217 Resource_Table[i] = (MRT::Resource_Table_Entry*)
00218 MEM_POOL_Alloc( mem_pool, sizeof(Resource_Table[i][0]) );
00219 Init_Table_Entry( Resource_Table[i] );
00220 }
00221
00222
00223 if( !TOP_2_Res_is_valid ){
00224 TOP_2_Res_is_valid = true;
00225
00226 for( int i = 0; i < TOP_count; i++ ){
00227 const TOP top = (TOP)i;
00228 ICU res = NONE;
00229
00230 if( TOP_is_load( top ) ){
00231 res = AGU;
00232
00233 } else if( TOP_is_flop(top) ||
00234 TOP_is_convert(top) ){
00235 res = FADD;
00236
00237 if( TOP_is_fmul( top ) ||
00238 TOP_is_sqrt( top ) ||
00239 TOP_is_fdiv( top ) ){
00240 res = FMUL;
00241
00242 } else if( TOP_is_store( top ) ){
00243 res = FMISC;
00244 }
00245
00246 } else {
00247 res = ALU;
00248
00249 if( TOP_is_store( top ) ||
00250 TOP_is_lea( top ) ){
00251 res = AGU;
00252 }
00253 }
00254
00255 TOP_2_Res[top] = res;
00256 }
00257 }
00258
00259
00260 ISA_REGISTER_CLASS cl;
00261 FOR_ALL_ISA_REGISTER_CLASS( cl ){
00262 live_in[cl] = live_out[cl] = REGISTER_SET_EMPTY_SET;
00263 avail_regs[cl] = REGISTER_CLASS_allocatable(cl);
00264
00265 for( REGISTER reg = REGISTER_MIN; reg <= REGISTER_MAX; reg++ ){
00266 if( REG_LIVE_Into_BB( cl, reg, bb ) )
00267 live_in[cl] = REGISTER_SET_Union1( live_in[cl], reg );
00268
00269 if( REG_LIVE_Outof_BB( cl, reg, bb ) )
00270 live_out[cl] = REGISTER_SET_Union1( live_out[cl], reg );
00271 }
00272
00273 avail_regs[cl] = REGISTER_SET_Difference( avail_regs[cl], live_in[cl] );
00274 avail_regs[cl] = REGISTER_SET_Difference( avail_regs[cl], live_out[cl] );
00275
00276 if( trace ){
00277 Print_Register_Set( "live_in", live_in[cl], cl );
00278 Print_Register_Set( "live_out", live_out[cl], cl );
00279 Print_Register_Set( "avail_regs", avail_regs[cl], cl );
00280 }
00281 }
00282 }
00283
00284
00285 int MRT::Get_Dispatch_Unit( OP* op, int cycle )
00286 {
00287 const ICU res = TOP_2_Res[OP_code(op)];
00288
00289 if( res == FADD || res == FMUL || res == FMISC )
00290 return 0;
00291
00292 return Resource_Table[cycle]->decoded_ops - Resource_Table[cycle]->fp_ops;
00293 }
00294
00295
00296
00297
00298
00299 void MRT::Compute_Issue_Time( OP* op, int clock )
00300 {
00301 OPR* opr = Get_OPR( op );
00302 const int dispatch_unit = Get_Dispatch_Unit( op, clock );
00303 const ICU res = TOP_2_Res[OP_code(op)];
00304
00305 if( clock < OPR_release_time( opr ) )
00306 clock = OPR_release_time( opr );
00307
00308 while( clock <= OPR_deadline( opr ) ){
00309 if( Probe_Resources( clock, op, dispatch_unit, false ) )
00310 break;
00311 clock++;
00312 }
00313
00314 ASSERT( clock <= OPR_deadline(opr) );
00315 OPR_issue_time(opr) = clock;
00316 }
00317
00318
00319
00320
00321
00322 bool MRT::Probe_Resources( int cycle, OP* op, int dispatch_unit, bool take_it )
00323 {
00324 const TOP top = OP_code(op);
00325 Resource_Table_Entry* entry = Resource_Table[cycle];
00326
00327 if( OP_memory( op ) &&
00328 entry->mem_ops == mem_ops_rate )
00329 return false;
00330
00331 if( OP_idiv(op) && entry->decoded_ops > 0 )
00332 return false;
00333
00334
00335 if( TOP_is_imul(top) && entry->decoded_ops > 0 )
00336 return false;
00337
00338 const ICU res = TOP_2_Res[top];
00339 ASSERT( num_fu[res] > dispatch_unit );
00340
00341 if( !entry->resources[res][dispatch_unit] )
00342 return false;
00343
00344 if( TOP_is_lea(top) ){
00345 Resource_Table_Entry* entry1 = Resource_Table[cycle+1];
00346 if( !entry1->resources[ALU][dispatch_unit] )
00347 return false;
00348 }
00349
00350 if( take_it ){
00351 entry->resources[res][dispatch_unit] = false;
00352
00353 if( TOP_is_imul(top) ){
00354
00355 entry->resources[ALU][dispatch_unit] = false;
00356
00357 } else if( TOP_is_lea(top) ){
00358 Resource_Table_Entry* entry1 = Resource_Table[cycle+1];
00359 ASSERT( entry1->resources[ALU][dispatch_unit] );
00360 entry1->resources[ALU][dispatch_unit] = false;
00361 }
00362 }
00363
00364 return true;
00365 }
00366
00367
00368
00369
00370
00371 void MRT::Reserve_Resources( OP* op, int cycle )
00372 {
00373 OPR* opr = Get_OPR( op );
00374 const int dispatch_unit = Get_Dispatch_Unit( op, cycle );
00375
00376 if( !Probe_Resources( OPR_issue_time(opr), op, dispatch_unit, true ) ){
00377 ASSERT( false );
00378 }
00379
00380
00381 Resource_Table_Entry* entry = Resource_Table[cycle];
00382 const ICU res = TOP_2_Res[OP_code(op)];
00383
00384 ASSERT( entry->decoded_ops < issue_rate );
00385
00386 if( OP_idiv(op) )
00387 entry->decoded_ops = issue_rate;
00388 else
00389 entry->decoded_ops++;
00390
00391 if( res == FADD || res == FMUL || res == FMISC )
00392 entry->fp_ops++;
00393
00394 if( OP_memory( op ) )
00395 entry->mem_ops++;
00396 }
00397
00398
00399 void KEY_SCH::Build_Ready_Vector()
00400 {
00401 OP* op;
00402
00403 FOR_ALL_BB_OPs_FWD (bb, op) {
00404 OPR* opr = Get_OPR( op );
00405 if( OPR_num_preds(opr) == 0 ){
00406 VECTOR_Add_Element( _ready_vector, op );
00407 }
00408 }
00409 }
00410
00411
00412 void KEY_SCH::Init()
00413 {
00414 OP* op = NULL;
00415
00416
00417 _ready_vector = VECTOR_Init( BB_length(bb), mem_pool );
00418 _sched_vector = VECTOR_Init( BB_length(bb), mem_pool );
00419
00420 int max_indx = 0;
00421 FOR_ALL_BB_OPs( bb, op ){
00422 max_indx = std::max( max_indx, OP_map_idx(op) );
00423 }
00424 max_indx++;
00425
00426 opr_array = (OPR*) MEM_POOL_Alloc( mem_pool,
00427 sizeof(opr_array[0]) * max_indx );
00428 bzero( opr_array, ( sizeof(opr_array[0]) * max_indx ) );
00429
00430
00431 int rtable_size = 0;
00432 int max_resource_cycles = 0;
00433
00434 FOR_ALL_BB_OPs_FWD( bb, op ){
00435 INT cur_resource_cycles = TI_RES_Cycle_Count(OP_code(op));
00436 if (cur_resource_cycles > max_resource_cycles) {
00437 max_resource_cycles = cur_resource_cycles;
00438 }
00439 INT op_latency = cur_resource_cycles;
00440 for( ARC_LIST* arcs = OP_succs(op); arcs != NULL; arcs = ARC_LIST_rest(arcs)) {
00441 ARC *arc = ARC_LIST_first(arcs);
00442 if (ARC_latency(arc) > op_latency) {
00443 op_latency = ARC_latency(arc);
00444 }
00445 }
00446 rtable_size += op_latency;
00447 }
00448
00449
00450
00451 rtable_size += max_resource_cycles;
00452 _U = rtable_size;
00453
00454 mrt.Init( bb, _U, trace, mem_pool );
00455 }
00456
00457
00458 void KEY_SCH::Reorder_BB()
00459 {
00460 ASSERT( VECTOR_count(_sched_vector) == BB_length(bb) );
00461 BB_Remove_All( bb );
00462
00463 for( int i = 0; i < VECTOR_count(_sched_vector); i++ ){
00464 OP* op = OP_VECTOR_element(_sched_vector, i);
00465 OPR* opr = Get_OPR( op );
00466 BB_Append_Op( bb, op );
00467 }
00468 }
00469
00470
00471 void KEY_SCH::Build_OPR()
00472 {
00473 OP* op;
00474
00475 int mem_ops = 0;
00476 _true_cp = _cp = 0;
00477
00478 bzero( defop_by_reg, sizeof(defop_by_reg) );
00479
00480 FOR_ALL_BB_OPs_FWD( bb, op ){
00481 OPR* opr = Get_OPR( op );
00482 OPR_release_time(opr) = 0;
00483 OPR_deadline(opr) = _U-1;
00484 OPR_sched_order(opr) = _U;
00485 OPR_pred_order(opr) = _U;
00486
00487 OPR_uses(opr) = 0;
00488 OPR_latency(opr) = 0;
00489
00490 for( ARC_LIST* arcs = OP_succs(op); arcs != NULL; arcs = ARC_LIST_rest(arcs) ){
00491 ARC* arc = ARC_LIST_first(arcs);
00492 if( ARC_kind(arc) == CG_DEP_REGIN ||
00493 ARC_kind(arc) == CG_DEP_MEMIN ){
00494 OPR_uses(opr)++;
00495 }
00496
00497 if( ARC_latency(arc) > OPR_latency(opr) )
00498 OPR_latency(opr) = ARC_latency(arc);
00499 }
00500
00501 OPR_mem_index(opr) = OPR_mem_base(opr) = NULL;
00502 OPR_mem_sym(opr) = NULL;
00503 OPR_mem_ofst(opr) = 0;
00504
00505 for( int i = 0; i < OP_results(op); i++ ){
00506 TN* result = OP_result( op, i );
00507 defop_by_reg[TN_register_class(result)][TN_register(result)] = op;
00508 }
00509
00510 if( OP_memory( op ) ){
00511 const TOP top = OP_code(op);
00512 const int index_idx = TOP_Find_Operand_Use( top, OU_index );
00513
00514 if( index_idx >= 0 ){
00515 OPR_mem_index(opr) = OP_opnd( op, index_idx );
00516 }
00517
00518 const int base_idx = TOP_Find_Operand_Use( top, OU_base );
00519 if( base_idx >= 0 ){
00520 OPR_mem_base(opr) = OP_opnd( op, base_idx );
00521 }
00522
00523 const int ofst_idx = TOP_Find_Operand_Use( top, OU_offset );
00524 TN* ofst_tn = OP_opnd( op, ofst_idx );
00525 int ofst = TN_value( ofst_tn );
00526
00527 if( TN_is_symbol( ofst_tn ) ){
00528 ST* sym = TN_var( ofst_tn );
00529 ST* root_sym = NULL;
00530 INT64 root_offset = 0;
00531 Base_Symbol_And_Offset( sym, &root_sym, &root_offset);
00532 if( sym != root_sym ){
00533 ofst += root_offset;
00534 }
00535
00536 OPR_mem_sym(opr) = root_sym;
00537 }
00538
00539 OPR_mem_ofst(opr) = ofst;
00540
00541 mem_ops++;
00542 }
00543 }
00544
00545 _true_cp = (int)ceil( mem_ops / 2 );
00546 mem_ops = (int)ceil( BB_length(bb) / mrt.issue_rate );
00547 _cp = _true_cp = std::max( _true_cp, mem_ops );
00548
00549
00550 FOR_ALL_BB_OPs_FWD( bb, op ){
00551 OPR* opr = Get_OPR( op );
00552
00553 for( ARC_LIST* arcs = OP_succs(op); arcs != NULL; arcs = ARC_LIST_rest(arcs) ){
00554 ARC* arc = ARC_LIST_first(arcs);
00555
00556 if( ARC_kind(arc) != CG_DEP_REGIN &&
00557 ARC_kind(arc) != CG_DEP_MEMIN )
00558 continue;
00559
00560 OP* succ_op = ARC_succ(arc);
00561 OPR* succ_opr = Get_OPR( succ_op );
00562
00563 int time = ARC_latency(arc) + OPR_release_time(opr);
00564 if( OPR_release_time(succ_opr) < time ){
00565 OPR_release_time(succ_opr) = time;
00566 }
00567
00568 _true_cp = std::max( _true_cp, time );
00569 }
00570 }
00571
00572
00573 FOR_ALL_BB_OPs_FWD( bb, op ){
00574 OPR* opr = Get_OPR( op );
00575
00576 OPR_issue_time( opr ) = OPR_release_time( opr );
00577
00578 for( ARC_LIST* arcs = OP_succs(op); arcs != NULL; arcs = ARC_LIST_rest(arcs) ){
00579 ARC* arc = ARC_LIST_first(arcs);
00580 OP* succ_op = ARC_succ(arc);
00581 OPR* succ_opr = Get_OPR( succ_op );
00582
00583 int time = ARC_latency(arc) + OPR_release_time(opr);
00584 if( OPR_release_time(succ_opr) < time ){
00585 OPR_release_time(succ_opr) = time;
00586 }
00587
00588 _cp = std::max( _cp, time );
00589 OPR_num_succs(opr)++;
00590 }
00591 }
00592
00593
00594 FOR_ALL_BB_OPs_REV( bb, op ){
00595 OPR* opr = Get_OPR( op );
00596
00597 for( ARC_LIST* arcs = OP_preds(op); arcs != NULL; arcs = ARC_LIST_rest(arcs) ){
00598 ARC* arc = ARC_LIST_first(arcs);
00599 OP* pred_op = ARC_pred(arc);
00600 OPR* pred_opr = Get_OPR( pred_op );
00601
00602 int time = OPR_deadline(opr) - ARC_latency(arc);
00603 if( OPR_deadline(pred_opr) > time ){
00604 OPR_deadline(pred_opr) = time;
00605 ASSERT( time >= OPR_release_time(pred_opr) );
00606 }
00607
00608 OPR_num_preds(opr)++;
00609 }
00610 }
00611
00612 if( trace ){
00613 FOR_ALL_BB_OPs_FWD( bb, op ){
00614 Print_OP_No_SrcLine(op);
00615 OPR* opr = Get_OPR( op );
00616 fprintf( TFile, "release_time:%d deadline:%d num_succs:%d num_preds:%d ",
00617 OPR_release_time(opr), OPR_deadline(opr),
00618 OPR_num_succs(opr), OPR_num_preds(opr) );
00619 fprintf( TFile, "uses:%d latency:%d ",
00620 OPR_uses(opr), OPR_latency(opr) );
00621 fprintf( TFile, "\n" );
00622 }
00623 }
00624 }
00625
00626
00627 void KEY_SCH::Summary_BB()
00628 {
00629 if( _cp > _true_cp + 1 ){
00630 const bool is_loop_body = ( ANNOT_Get(BB_annotations(bb), ANNOT_LOOPINFO) != NULL &&
00631 BB_xfer_op( bb ) != NULL );
00632 const int cycles = 1 + OP_scycle( BB_last_op(bb) );
00633
00634 fprintf( TFile, "%c%s[%d] ops:%d cycles:%d cp:%d true_cp:%d\n",
00635 BB_innermost(bb) ? '*' : ' ', Cur_PU_Name, BB_id(bb),
00636 BB_length(bb), cycles, _cp, _true_cp );
00637
00638 if( BB_innermost(bb) ){
00639
00640 }
00641 }
00642 }
00643
00644
00645 void KEY_SCH::Tighten_Release_Time( OP* op )
00646 {
00647 OPR* opr = Get_OPR( op );
00648 ASSERT( OPR_release_time(opr) <= OPR_deadline(opr) );
00649
00650 for( ARC_LIST* arcs = OP_succs(op); arcs != NULL; arcs = ARC_LIST_rest(arcs) ){
00651 ARC* arc = ARC_LIST_first(arcs);
00652 OP* succ_op = ARC_succ(arc);
00653 OPR* succ_opr = Get_OPR( succ_op );
00654
00655 int time = ARC_latency(arc) + OPR_release_time(opr);
00656
00657 if( OPR_release_time(succ_opr) < time ){
00658 OPR_release_time(succ_opr) = time;
00659 Tighten_Release_Time( succ_op );
00660 }
00661 }
00662 }
00663
00664
00665 int KEY_SCH::Addr_Generation( OP* op )
00666 {
00667 int time = -1;
00668 OPR* opr = Get_OPR( op );
00669
00670 const unsigned int N = 100;
00671
00672 if( OPR_mem_index( opr ) != NULL ){
00673 TN* index = OPR_mem_index( opr );
00674 OP* pred_op = defop_by_reg[TN_register_class(index)][TN_register(index)];
00675 if( pred_op != NULL ){
00676 OPR* pred_opr = Get_OPR( pred_op );
00677 if( sched_order - OPR_sched_order( pred_opr ) < N )
00678 time = MAX( time, OPR_sched_order( pred_opr ) );
00679 }
00680 }
00681
00682 if( OPR_mem_base( opr ) != NULL ){
00683 TN* base = OPR_mem_base( opr );
00684 OP* pred_op = defop_by_reg[TN_register_class(base)][TN_register(base)];
00685 if( pred_op != NULL ){
00686 OPR* pred_opr = Get_OPR( pred_op );
00687 if( sched_order - OPR_sched_order( pred_opr ) < N )
00688 time = MAX( time, OPR_sched_order( pred_opr ) );
00689 }
00690 }
00691
00692 return time;
00693 }
00694
00695
00696 OP* KEY_SCH::Winner( OP* op_a, OP* op_b )
00697 {
00698 OPR* opr_a = Get_OPR( op_a );
00699 OPR* opr_b = Get_OPR( op_b );
00700
00701 #if 0
00702 if( mrt.Memory_Saturated( OPR_issue_time( opr_a ) ) ){
00703 if( OP_memory( op_a ) )
00704 return op_b;
00705 if( OP_memory( op_b ) )
00706 return op_a;
00707 }
00708 #endif
00709
00710
00711 if( OPR_issue_time( opr_a ) != OPR_issue_time( opr_b ) ){
00712 return ( OPR_issue_time( opr_a ) < OPR_issue_time( opr_b ) ? op_a : op_b );
00713 }
00714
00715
00716 if( OP_memory( op_a ) && OP_memory( op_b ) ){
00717 const int op_a_addr_cal = Addr_Generation( op_a );
00718 const int op_b_addr_cal = Addr_Generation( op_b );
00719
00720
00721 if( op_a_addr_cal != op_b_addr_cal ){
00722 return ( op_a_addr_cal < op_b_addr_cal ? op_a : op_b );
00723 }
00724
00725
00726 if( last_mem_op != NULL ){
00727 const OPR* opr_last = Get_OPR( last_mem_op );
00728 const bool a_is_close =
00729 ( ( OPR_mem_base( opr_a ) == OPR_mem_base( opr_last ) ) &&
00730 ( OPR_mem_index( opr_a ) == OPR_mem_index( opr_last ) ) &&
00731 ( OPR_mem_sym( opr_a ) == OPR_mem_sym( opr_last ) ) );
00732 const bool b_is_close =
00733 ( ( OPR_mem_base( opr_b ) == OPR_mem_base( opr_last ) ) &&
00734 ( OPR_mem_index( opr_b ) == OPR_mem_index( opr_last ) ) &&
00735 ( OPR_mem_sym( opr_b ) == OPR_mem_sym( opr_last ) ) );
00736
00737 if( a_is_close != b_is_close )
00738 return ( a_is_close ? op_a : op_b );
00739 }
00740
00741
00742 if( ( OPR_mem_base( opr_a ) == OPR_mem_base( opr_b ) ) &&
00743 ( OPR_mem_ofst( opr_a ) != OPR_mem_ofst( opr_b ) ) ){
00744 return ( OPR_mem_ofst( opr_a ) < OPR_mem_ofst( opr_b ) ? op_a : op_b );
00745 }
00746
00747
00748 if( OP_store( op_a ) || OP_store( op_b ) ){
00749 return ( OP_store( op_b ) ? op_a : op_b );
00750 }
00751 }
00752
00753
00754 if( OPR_latency( opr_a ) != OPR_latency( opr_b ) ){
00755 return ( OPR_latency( opr_a ) > OPR_latency( opr_b ) ? op_a : op_b );
00756 }
00757
00758
00759 if( OP_store( op_a ) && !OP_store( op_b ) )
00760 return op_b;
00761
00762 if( !OP_store( op_a ) && OP_store( op_b ) )
00763 return op_a;
00764
00765
00766 if( OPR_uses( opr_a ) != OPR_uses( opr_b ) ){
00767 return ( OPR_uses( opr_a ) > OPR_uses( opr_b ) ? op_a : op_b );
00768 }
00769
00770
00771 if( OPR_deadline( opr_a ) != OPR_deadline( opr_b ) ){
00772 return ( OPR_deadline( opr_a ) < OPR_deadline( opr_b ) ) ? op_a : op_b;
00773 }
00774
00775
00776 return OPR_pred_order( opr_a ) < OPR_pred_order( opr_b ) ? op_a : op_b;
00777
00778
00779 return OP_map_idx( op_a ) < OP_map_idx( op_b ) ? op_a : op_b;
00780 }
00781
00782
00783 OP* KEY_SCH::Select_Variable( int cycle )
00784 {
00785 const int num = VECTOR_count( _ready_vector );
00786 OP* best = NULL;
00787
00788 ASSERT( num > 0 );
00789
00790 if( trace ){
00791 fprintf( TFile, "Ready list:\n" );
00792 for( int i = 0; i < num; i++ ){
00793 OP* op = (OP*)VECTOR_element( _ready_vector, i );
00794 Print_OP_No_SrcLine( op );
00795 }
00796 }
00797
00798 for( int i = 0; i < num; i++ ){
00799 OP* op = (OP*)VECTOR_element( _ready_vector, i );
00800 OPR* opr = Get_OPR( op );
00801
00802 if( OPR_release_time( opr ) == cycle ){
00803 best = ( best == NULL ) ? op : Winner( best, op );
00804 }
00805 }
00806
00807 if( best == NULL ){
00808
00809
00810 best = (OP*)VECTOR_element( _ready_vector, 0 );
00811
00812 for( int i = 1; i < num; i++ ){
00813 OP* op = (OP*)VECTOR_element( _ready_vector, i );
00814 OPR* opr = Get_OPR( op );
00815 best = Winner( best, op );
00816 }
00817 }
00818
00819 OP_scycle( best ) = OPR_issue_time( Get_OPR(best) );
00820
00821 if( trace ){
00822 fprintf( TFile, "Select: " );
00823 Print_OP_No_SrcLine( best );
00824 }
00825
00826 return best;
00827 }
00828
00829
00830 void KEY_SCH::Schedule_BB()
00831 {
00832 Build_OPR();
00833 Build_Ready_Vector();
00834 int cur_clock = 0;
00835
00836 last_mem_op = NULL;
00837
00838 while( VECTOR_count(_ready_vector) > 0 ){
00839 OP* op = Select_Variable( cur_clock );
00840 OPR* opr = Get_OPR( op );
00841
00842
00843
00844 if( trace ){
00845 fprintf( TFile, "Cycle[%d] : issue_time %d",
00846 cur_clock, OPR_issue_time(opr) );
00847 Print_OP_No_SrcLine( op );
00848 }
00849
00850 if( OP_memory( op ) ){
00851 last_mem_op = op;
00852 }
00853 VECTOR_Delete_Element( _ready_vector, op );
00854 Set_OPR_is_scheduled( opr );
00855 OPR_sched_order(opr) = sched_order++;
00856 VECTOR_Add_Element( _sched_vector, op );
00857
00858 ASSERT( OPR_release_time(opr) <= OPR_issue_time(opr) );
00859
00860
00861 for( ARC_LIST* arcs = OP_succs(op); arcs != NULL; arcs = ARC_LIST_rest(arcs) ){
00862 ARC* arc = ARC_LIST_first(arcs);
00863 OP* succ_op = ARC_succ(arc);
00864 OPR* succ_opr = Get_OPR( succ_op );
00865 OPR_num_preds( succ_opr )--;
00866 if( OPR_num_preds( succ_opr ) == 0 ){
00867 VECTOR_Add_Element( _ready_vector, succ_op );
00868 }
00869
00870 OPR_pred_order( succ_opr ) = OPR_sched_order( opr );
00871 ASSERT( cur_clock + ARC_latency(arc) <= OPR_deadline( succ_opr ) );
00872
00873 if( ARC_kind(arc) == CG_DEP_REGIN &&
00874 OPR_issue_time(opr) + ARC_latency(arc) > OPR_release_time(succ_opr) ){
00875 OPR_release_time(succ_opr) = OPR_issue_time(opr) + ARC_latency(arc);
00876 Tighten_Release_Time( succ_op );
00877 }
00878 }
00879
00880 mrt.Reserve_Resources( op, cur_clock );
00881
00882 if( mrt.Decoder_is_Saturated( cur_clock ) ){
00883 cur_clock++;
00884
00885
00886 for( int i = VECTOR_count( _ready_vector ) - 1; i >= 0; i-- ){
00887 OP* ready_op = (OP*)VECTOR_element( _ready_vector, i );
00888 OPR* ready_opr = Get_OPR( ready_op );
00889
00890 if( OPR_release_time( ready_opr ) < cur_clock ){
00891 OPR_release_time( ready_opr ) = cur_clock;
00892 Tighten_Release_Time( ready_op );
00893 }
00894 }
00895 }
00896
00897
00898
00899
00900
00901 for( int i = VECTOR_count( _ready_vector ) - 1; i >= 0; i-- ){
00902 OP* ready_op = (OP*)VECTOR_element( _ready_vector, i );
00903 mrt.Compute_Issue_Time( ready_op, cur_clock );
00904 }
00905 }
00906 }
00907
00908
00909 KEY_SCH::KEY_SCH( BB* bb, MEM_POOL* pool, BOOL trace )
00910 : bb( bb ), mem_pool( pool ), trace( trace )
00911 {
00912 if( CG_skip_local_sched ){
00913 BBs_Processed++;
00914 if( BBs_Processed < CG_local_skip_before ||
00915 BBs_Processed > CG_local_skip_after ||
00916 BBs_Processed == CG_local_skip_equal ){
00917 fprintf( TFile, "[%d] BB:%d processed in KEY_SCH\n",
00918 BBs_Processed, BB_id(bb) );
00919 return;
00920 }
00921 }
00922
00923 #if 0
00924 if( !( strcmp( Cur_PU_Name, "resid_" ) == 0 &&
00925 BB_id( bb ) == 8 ) ){
00926 return;
00927 }
00928 #endif
00929
00930 if( BB_length(bb) > 2 ){
00931 CG_DEP_Compute_Graph( bb,
00932 INCLUDE_ASSIGNED_REG_DEPS,
00933 NON_CYCLIC,
00934 INCLUDE_MEMREAD_ARCS,
00935 INCLUDE_MEMIN_ARCS,
00936 INCLUDE_CONTROL_ARCS,
00937 NULL );
00938
00939 if( trace ){
00940 CG_DEP_Trace_Graph( bb );
00941 }
00942
00943 Init();
00944 Schedule_BB();
00945 Reorder_BB();
00946 Summary_BB();
00947
00948 CG_DEP_Delete_Graph( bb );
00949 }
00950
00951 Set_BB_scheduled( bb );
00952 if( Assembly && BB_length(bb) > 0 )
00953 Add_Scheduling_Note( bb, NULL );
00954 }
00955
00956
00957 void CG_Sched( MEM_POOL* pool, BOOL trace )
00958 {
00959 return;
00960
00961
00962 REG_LIVE_Analyze_Region();
00963
00964 for( BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb) ){
00965 RID* rid = BB_rid(bb);
00966 if( rid != NULL &&
00967 RID_level(rid) >= RL_CGSCHED )
00968 continue;
00969
00970 KEY_SCH sched( bb, pool, trace );
00971 }
00972
00973
00974 REG_LIVE_Finish ();
00975 }