00001 #include <lestes/backend_v2/structs/func_data.g.hh>
00002 #include <lestes/backend_v2/intercode/ge.g.hh>
00003 #include <lestes/backend_v2/workers/linscan_regalloc.g.hh>
00004 #include <lestes/backend_v2/workers/alloc_int_finder.g.hh>
00005 #include <lestes/backend_v2/workers/bb_finder.g.hh>
00006 #include <lestes/backend_v2/workers/helpers.hh>
00007 #include <lestes/md/instructions/tm_instr.g.hh>
00008 #include <lestes/md/registers/tm_register.g.hh>
00009
00010 #include <lestes/backend_v2/debug/debug.hh>
00011
00012 package(lestes);
00013 package(backend_v2);
00014 package(workers);
00015
00016 using namespace ::lestes::msg;
00017 using namespace ::lestes::backend_v2::intercode;
00018 using namespace ::lestes::backend_v2::debug;
00019 using namespace ::lestes::md::instructions;
00020 using namespace ::lestes::md::registers;
00021
00022 typedef set<ulint> id_set__type;
00023 typedef vector<ulint> id_vector__type;
00024 typedef vector<srp<ge_pi> > ge_pi_vector__type;
00025 typedef vector<srp<liveness_range> > liveness_rng_vector__type;
00026 typedef vector<srp<alloc_interval> > alloc_int_vector__type;
00027 typedef map<ulint, srp<alloc_interval> > reg2alloc_int__type;
00028 typedef map<srp<ge_operand_reg>, srp<tm_register> > ge_op_reg2tm_reg__type;
00029
00030 declare_logger(rlog);
00031 initialize_logger( rlog, "register_allocator", backend_v2_logger );
00032
00033
00034
00035
00036 void linscan_regalloc::process() {
00037 rlog << "process start\n" << eolog;
00038
00039
00040 setup_registers();
00041
00042
00043 waiting_intervals = alloc_int_vector__type::create(data_get()->alloc_ints_get());
00044
00045
00046 ::std::sort(waiting_intervals->begin(),waiting_intervals->end(),alloc_int_cmp1);
00047
00048 for(alloc_int_vector__type::iterator it = waiting_intervals->begin(); it!=waiting_intervals->end();) {
00049 ptr<alloc_interval> interval = *it;
00050
00051
00052 expire_old_intervals(interval);
00053
00054
00055 ptr<tm_register> allocated_reg = get_free_register(interval);
00056
00057 if ( allocated_reg ) {
00058
00059 interval->allocated_reg_set(allocated_reg);
00060
00061
00062
00063
00064
00065
00066
00067 reg2alloc_int__type::iterator tmp = register_owners->find(allocated_reg->id_get());
00068
00069 if ( tmp!=register_owners->end() ) {
00070 interval->allocated_obj_prev_owner_set(tmp->second);
00071 }
00072
00073 set_register_owner(allocated_reg,interval);
00074 }
00075
00076
00077 it = waiting_intervals->erase(it);
00078 active_intervals->push_back(interval);
00079 }
00080
00081
00082 for(alloc_int_vector__type::iterator it = active_intervals->begin(); it!=active_intervals->end();) {
00083 expired_intervals->push_back(*it);
00084 it = active_intervals->erase(it);
00085 }
00086
00087 lassert(destroyers->size()==0);
00088 lassert(waiting_intervals->size()==0);
00089 lassert(active_intervals->size()==0);
00090
00091 rlog << "process end\n" << eolog;
00092 }
00093
00094
00095
00096
00097 void linscan_regalloc::setup_registers() {
00098 for(ulint i = R_UNDEFINED+1; i<RIT_TERMINATOR; ++i) {
00099 all_registers->insert(i);
00100 }
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 ptr<tm_register> linscan_regalloc::get_free_register(ptr<alloc_interval> interval) {
00116 rlog << "get_free_register start\n" << eolog;
00117
00118 ptr<tm_register> reg = get_destroyed_register(interval->operand_get());
00119
00120 ptr<id_set__type> avail_regs;
00121 if (reg) {
00122 rlog << "** found destroyed register **\n" << eolog;
00123 lassert(free_registers->find(reg->id_get())!=free_registers->end());
00124
00125 avail_regs = id_set__type::create();
00126
00127 ptr<id_set__type> tmp_set = reg->aliases_get();
00128
00129 ::std::set_intersection(
00130 interval->allowed_registers_get()->begin(),
00131 interval->allowed_registers_get()->end(),
00132 tmp_set->begin(),
00133 tmp_set->end(),
00134 ::std::inserter(*avail_regs,avail_regs->begin()));
00135 } else {
00136 avail_regs = id_set__type::create();
00137
00138 ::std::set_intersection(
00139 free_registers->begin(),
00140 free_registers->end(),
00141 interval->allowed_registers_get()->begin(),
00142 interval->allowed_registers_get()->end(),
00143 ::std::inserter(*avail_regs,avail_regs->begin()));
00144 }
00145
00146 if ( avail_regs->size()==0 ) {
00147
00148 ::std::sort(active_intervals->begin(),active_intervals->end(),alloc_int_cmp2);
00149
00150
00151 for(alloc_int_vector__type::iterator it = active_intervals->begin(); it!=active_intervals->end();++it) {
00152 ptr<alloc_interval> victim = *it;
00153
00154 if ( !victim->allocated_reg_get() ) {
00155 continue;
00156 }
00157
00158 ::std::set_intersection(
00159 interval->allowed_registers_get()->begin(),
00160 interval->allowed_registers_get()->end(),
00161 victim->allocated_reg_get()->aliases_get()->begin(),
00162 victim->allocated_reg_get()->aliases_get()->end(),
00163 ::std::inserter(*avail_regs,avail_regs->begin()));
00164
00165 if ( avail_regs->size()!=0 ) {
00166 active_intervals->erase(it);
00167 expired_intervals->push_back(victim);
00168
00169
00170 used_registers->erase(victim->allocated_reg_get()->id_get());
00171
00172
00173 set_register_owner(victim->allocated_reg_get(),victim->allocated_obj_prev_owner_get());
00174
00175 victim->allocated_reg_set(NULL);
00176 victim->allocated_obj_prev_owner_set(NULL);
00177 break;
00178 }
00179 }
00180 }
00181
00182 if (avail_regs->size()!=0) {
00183 reg = tm_register::instance(*avail_regs->begin());
00184
00185
00186 used_registers->insert(reg->id_get());
00187 } else {
00188 reg = NULL;
00189 }
00190
00191 rlog << "get_free_register end\n" << eolog;
00192 return reg;
00193 }
00194
00195
00196
00197
00198 void linscan_regalloc::set_register_owner(ptr<tm_register> reg, ptr<alloc_interval> interval) {
00199 for(id_set__type::iterator it = reg->aliases_get()->begin(); it!=reg->aliases_get()->end(); ++it) {
00200 (*register_owners)[*it] = interval;
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 void linscan_regalloc::find_free_registers() {
00211 rlog << "find_free_registers start\n" << eolog;
00212
00213 ptr<id_set__type> deep_used_registers = id_set__type::create();
00214
00215 for(id_set__type::iterator it=used_registers->begin(); it!=used_registers->end(); ++it) {
00216 ptr<tm_register> reg = tm_register::instance(*it);
00217
00218 ptr<id_set__type> new_deep_used_registers = id_set__type::create();
00219
00220 ::std::set_union(
00221 reg->aliases_get()->begin(),
00222 reg->aliases_get()->end(),
00223 deep_used_registers->begin(),
00224 deep_used_registers->end(),
00225 ::std::inserter(*new_deep_used_registers,new_deep_used_registers->begin()));
00226
00227 deep_used_registers = new_deep_used_registers;
00228 }
00229
00230 ptr<id_set__type> updated_free_registers = id_set__type::create();
00231
00232 ::std::set_difference(
00233 all_registers->begin(),
00234 all_registers->end(),
00235 deep_used_registers->begin(),
00236 deep_used_registers->end(),
00237 ::std::inserter(*updated_free_registers,updated_free_registers->begin()));
00238
00239 free_registers = updated_free_registers;
00240
00241 rlog << "find_free_registers end\n" << eolog;
00242 }
00243
00244
00245
00246
00247 ptr<tm_register> linscan_regalloc::get_destroyed_register(ptr<ge_operand_reg> op) {
00248 rlog << "get_destroyed_register start\n" << eolog;
00249
00250 ptr<tm_register> reg = NULL;
00251
00252 ge_op_reg2tm_reg__type::iterator it = destroyers->find(op);
00253
00254 if (it!=destroyers->end()) {
00255 reg = it->second;
00256 destroyers->erase(it);
00257 }
00258
00259 rlog << "get_destroyed_register end\n" << eolog;
00260 return reg;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270 void linscan_regalloc::set_destroyed_register(ptr<ge_pi> ge, ptr<ge_operand_reg> op, ptr<tm_register> reg) {
00271 rlog << "set_destroyed_register start\n" << eolog;
00272
00273 ptr<tm_instr_op_reg_base> tmop = ge_pi__find_tm_op_by_ge_op(ge,op);
00274
00275 if ( !tmop ) {
00276 rlog << "set_destroyed_register end 1\n" << eolog;
00277 return;
00278 }
00279
00280 ptr<id_vector__type> destroyed_by = tmop->destroyed_by_get();
00281
00282 if ( !destroyed_by || destroyed_by->size()==0 ) {
00283 rlog << "set_destroyed_register end 2\n" << eolog;
00284 return;
00285 }
00286
00287 ptr<tm_instr_base> tm = ge->instruction_get();
00288 lassert(tm);
00289
00290 for(ulint i=0; i<destroyed_by->size();++i) {
00291 ulint destroyer = (*destroyed_by)[i];
00292
00293 for(ulint j=0; j<ge->operands_output_get()->size(); ++j) {
00294 if ( (*tm->operands_output_get())[j]->id_get()==destroyer ) {
00295 (*destroyers)[(*ge->operands_output_get())[j].dncast<ge_operand_reg>()] = reg;
00296 rlog << "** destroyer set **\n" << eolog;
00297 break;
00298 }
00299 }
00300 }
00301
00302 rlog << "set_destroyed_register end\n" << eolog;
00303
00304 }
00305
00306
00307
00308
00309
00310
00311 void linscan_regalloc::expire_old_intervals(ptr<alloc_interval> curr_interval) {
00312 rlog << "expire_old_intervals start\n" << eolog;
00313
00314 ulint curr_point = curr_interval->start_get();
00315
00316 for(alloc_int_vector__type::iterator it = active_intervals->begin(); it!=active_intervals->end();) {
00317 ptr<alloc_interval> interval = *it;
00318
00319 if ( interval->end_get() <= curr_point ) {
00320 rlog << "interval expired\n" << eolog;
00321
00322 it = active_intervals->erase(it);
00323 expired_intervals->push_back(interval);
00324
00325 if ( interval->allocated_reg_get() ) {
00326
00327 used_registers->erase(interval->allocated_reg_get()->id_get());
00328
00329 if ( (*curr_interval->instructions_get())[0]==(*interval->instructions_get())[interval->instructions_get()->size()-1] ) {
00330 set_destroyed_register((*curr_interval->instructions_get())[0],interval->operand_get(),interval->allocated_reg_get());
00331 }
00332 }
00333
00334 } else {
00335 ++it;
00336 }
00337 }
00338
00339 find_free_registers();
00340
00341 rlog << "expire_old_intervals end\n" << eolog;
00342 }
00343
00344 ptr<id_set__type> linscan_regalloc::ge_pi__get_allowed_regs_for_op(ptr<ge_pi> ge,ptr<ge_operand_reg> op) {
00345 rlog << "ge_pi__get_allowed_regs_for_op start\n" << eolog;
00346
00347
00348 ptr<tm_instr_op_reg_base> tm_op = ge_pi__find_tm_op_by_ge_op(ge,op);
00349 lassert(tm_op);
00350
00351
00352 ptr<id_set__type> regs = id_set__type::create(tm_op->allowed_registers_get());
00353
00354 ulint type_id = op->type_get()->id_get();
00355
00356
00357
00358
00359 for(id_set__type::iterator it = regs->begin(); it!=regs->end();) {
00360 ptr<tm_register_base> reg = tm_register::instance(*it);
00361 if ( reg->compatible_types_get()->find(type_id)==reg->compatible_types_get()->end() ) {
00362 id_set__type::iterator del_it = it++;
00363 regs->erase(del_it);
00364 }
00365 }
00366
00367 lassert(regs->size()!=0);
00368
00369 rlog << "ge_pi__get_allowed_regs_for_op end\n" << eolog;
00370 return regs;
00371 }
00372
00373
00374
00375
00376 ptr<tm_instr_op_reg_base> linscan_regalloc::ge_pi__find_tm_op_by_ge_op(ptr<ge_pi> ge,ptr<ge_operand_reg> op) {
00377 rlog << "ge_pi__find_tm_op_by_ge_op start\n" << eolog;
00378
00379 ptr<tm_instr_base> tm = ge->instruction_get();
00380
00381 lassert(tm);
00382
00383 for(ulint i=0; i<ge->operands_input_get()->size(); ++i) {
00384 if ( op==(*ge->operands_input_get())[i] ) {
00385 rlog << "ge_pi__find_tm_op_by_ge_op end 1\n" << eolog;
00386 return (*tm->operands_input_get())[i].dncast<tm_instr_op_reg_base>();
00387 }
00388 }
00389
00390 for(ulint i=0; i<ge->operands_output_get()->size(); ++i) {
00391 if ( op==(*ge->operands_output_get())[i] ) {
00392 rlog << "ge_pi__find_tm_op_by_ge_op end 2\n" << eolog;
00393 return (*tm->operands_output_get())[i].dncast<tm_instr_op_reg_base>();
00394 }
00395 }
00396
00397 rlog << "ge_pi__find_tm_op_by_ge_op end\n" << eolog;
00398 return NULL;
00399
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409 void linscan_regalloc::set_interval_dependencies() {
00410 rlog << "set_dependencies start\n" << eolog;
00411
00412
00413
00414
00415
00416 for(alloc_int_vector__type::iterator it = expired_intervals->begin(); it!=expired_intervals->end(); ++it) {
00417 ptr<alloc_interval> interval = *it;
00418 ptr<alloc_interval> alloc_obj_prev_owner = interval->allocated_obj_prev_owner_get();
00419
00420 if ( alloc_obj_prev_owner ) {
00421 ptr<ge_pi> ge1 = alloc_obj_prev_owner->instructions_get()->back();
00422 ptr<ge_pi> ge2 = interval->instructions_get()->front();
00423
00424 if ( ge1->bb_get()==ge2->bb_get() ) {
00425 ge2->dependencies_get()->insert(ge1);
00426 }
00427 }
00428 }
00429
00430 rlog << "set_dependencies end\n" << eolog;
00431 }
00432
00433
00434
00435
00436 void linscan_regalloc::set_registers_to_operands() {
00437 rlog << "set_registers start\n" << eolog;
00438
00439
00440
00441
00442 for(alloc_int_vector__type::iterator it = expired_intervals->begin(); it!=expired_intervals->end(); ++it) {
00443 ptr<alloc_interval> interval = *it;
00444
00445 ptr<ge_operand_reg> operand = interval->operand_get();
00446
00447 if ( interval->allocated_reg_get() ) {
00448
00449 ulint assigned_register = interval->allocated_reg_get()->id_get();
00450
00451 lassert(interval->allowed_registers_get()->find(assigned_register)!=interval->allowed_registers_get()->end());
00452
00453 ptr<ge_pi_vector__type> instructions = interval->instructions_get();
00454 for(ge_pi_vector__type::iterator it2 = instructions->begin(); it2!=instructions->end(); ++it2) {
00455 (*operand->assigned_registers_get())[*it2] = assigned_register;
00456 }
00457
00458 }
00459 }
00460 rlog << "set_registers end\n" << eolog;
00461 }
00462
00463
00464
00465
00466 ptr< ::lestes::backend_v2::structs::func_data > linscan_regalloc::get_result() {
00467 rlog << "get_result start\n" << eolog;
00468
00469 set_registers_to_operands();
00470
00471 set_interval_dependencies();
00472
00473 data_get()->alloc_ints_set(expired_intervals);
00474
00475 rlog << "get_result end\n" << eolog;
00476 return data_get();
00477 }
00478
00479 end_package(workers);
00480 end_package(backend_v2);
00481 end_package(lestes);
00482