00001 #include <lestes/backend_v2/structs/func_data.g.hh>
00002 #include <lestes/backend_v2/intercode/ge.g.hh>
00003 #include <lestes/backend_v2/intercode/pi.g.hh>
00004 #include <lestes/backend_v2/workers/spillgen.g.hh>
00005 #include <lestes/backend_v2/workers/alloc_int_finder.g.hh>
00006 #include <lestes/backend_v2/workers/bb_finder.g.hh>
00007 #include <lestes/backend_v2/workers/helpers.hh>
00008 #include <lestes/md/mem/mem_alloc_manager.g.hh>
00009 #include <lestes/md/registers/tm_register.g.hh>
00010 #include <lestes/md/registers/move_generator.g.hh>
00011 #include <lestes/md/instructions/tm_instr.g.hh>
00012 #include <lestes/md/types/tm_data_type.g.hh>
00013 #include <lestes/lang/cplus/sem/ss_declaration.g.hh>
00014
00015 package(lestes);
00016 package(backend_v2);
00017 package(workers);
00018
00019 using namespace ::lestes::msg;
00020 using namespace ::lestes::backend_v2::intercode;
00021 using namespace ::lestes::md::instructions;
00022 using namespace ::lestes::md::registers;
00023 using namespace ::lestes::md::mem;
00024 using namespace ::lestes::md::types;
00025
00026 typedef set<srp<pi_mem_factory> > mf_set__type;
00027 typedef set<ulint> id_set__type;
00028 typedef vector<ulint> id_vector__type;
00029 typedef list<srp<ge_pi> > ge_pi_list__type;
00030 typedef vector<srp<liveness_range> > liveness_rng_vector__type;
00031 typedef vector<srp<alloc_interval> > alloc_int_vector__type;
00032 typedef vector<srp<ge_operand> > ge_operand_vector__type;
00033 typedef vector<srp<ge_pi> > ge_pi_vector__type;
00034 typedef set<srp<ge_pi> > ge_pi_set__type;
00035 typedef set<srp<ge_operand_reg> > ge_op_reg_set__type;
00036 typedef map<srp<pi_mem_factory>, srp<ge_pi> > mf2ge_pi__type;
00037 typedef map<ulint, srp<alloc_interval> > reg2alloc_int__type;
00038 typedef map<ulint, srp<ge_pi> > reg2ge_pi__type;
00039 typedef map<ulint, lstring > id2lstring__type;
00040 typedef map<srp<ge_pi>, ulint> ge2reg_map__type;
00041 typedef list<srp<spillgen_group> > spillgen_group_list__type;
00042 typedef set<srp<spillgen_group> > spillgen_group_set__type;
00043 typedef set<srp<alloc_interval> > alloc_int_set__type;
00044
00045 declare_logger(slog);
00046 initialize_logger( slog, "spillgen", backend_v2_logger );
00047
00048 declare_logger(deplog);
00049 initialize_logger( deplog, "spillgen_deps", backend_v2_logger );
00050
00051
00052
00053
00054
00055 void spillgen::process() {
00056 slog << "process start\n" << eolog;
00057
00058 move_gen = move_generator::create();
00059
00060
00061 setup_registers();
00062
00063
00064 waiting_intervals = alloc_int_vector__type::create(data_get()->alloc_ints_get());
00065
00066
00067 ::std::sort(waiting_intervals->begin(),waiting_intervals->end(),alloc_int_cmp1);
00068
00069
00070
00071
00072 ptr<ge_pi_list__type> body = data_get()->ge_body_get();
00073
00074
00075
00076
00077
00078 ge_pi_list__type::iterator it_next;
00079
00080 for(ge_pi_list__type::iterator it = body->begin(); it!=body->end();) {
00081 ptr<ge_pi> ge = *it;
00082
00083 it_next = it;
00084 ++it_next;
00085
00086
00087 expire_old_intervals(ge->schedule_pos_get());
00088
00089
00090 activate_waiting_intervals(ge->schedule_pos_get());
00091
00092
00093 find_free_registers();
00094
00095
00096 process_instruction(ge,body,it);
00097
00098 it = it_next;
00099 }
00100
00101 lassert(waiting_intervals->size()==0);
00102
00103 slog << "process end\n" << eolog;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113 void spillgen::process_instruction(ptr<ge_pi> ge, ptr<ge_pi_list__type> output, ge_pi_list__type::iterator it) {
00114 slog << "process_instruction start\n" << eolog;
00115
00116
00117 bool b_spilling_needed = identify_groups(ge);
00118
00119 if ( !b_spilling_needed ) {
00120
00121
00122
00123 for(spillgen_group_list__type::iterator it = groups->begin(); it!=groups->end(); ++it) {
00124 ptr<spillgen_group> group = *it;
00125
00126 if ( group->backup_space_get() ) {
00127 ptr<pi_mem_factory> mf = group->backup_space_get()->factory_get();
00128
00129 mf2ge_pi__type::iterator it_mf_last_use = spill_space_last_use->find(mf);
00130 if ( it_mf_last_use!=spill_space_last_use->end() ) {
00131 deplog << "A. " << ge->uid_get() << " -> " << it_mf_last_use->second->uid_get() << "\n" << eolog;
00132 ge->dependencies_get()->insert(it_mf_last_use->second);
00133 }
00134
00135 (*spill_space_last_use)[mf] = ge;
00136 }
00137
00138 lassert(group->reg_get());
00139
00140 ptr<ge_pi> last_use = find_last_use_of_register(group->reg_get()->id_get());
00141 if ( last_use ) {
00142 deplog << "B. " << ge->uid_get() << " -> " << last_use->uid_get() << "\n" << eolog;
00143 ge->dependencies_get()->insert(last_use);
00144 }
00145
00146 set_last_use_of_register(group->reg_get()->id_get(),ge);
00147 }
00148 slog << "process_instruction end 1\n" << eolog;
00149 return;
00150 }
00151
00152
00153 allocate_regs_for_groups();
00154
00155
00156 generate_spill_code(ge,output,it);
00157
00158 free_group_resources();
00159
00160 slog << "process_instruction end\n" << eolog;
00161 }
00162
00163
00164
00165
00166 void spillgen::free_group_resources() {
00167 slog << "free_group_resources start\n" << eolog;
00168
00169
00170 for(spillgen_group_list__type::iterator it = groups->begin(); it!=groups->end(); ++it) {
00171 ptr<spillgen_group> group = *it;
00172
00173 if ( group->backup_space_get() ) {
00174 ptr<pi_mem_factory> mf = group->backup_space_get()->factory_get();
00175
00176
00177 free_spill_spaces->insert(mf);
00178 }
00179 }
00180
00181 slog << "free_group_resources end\n" << eolog;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 ptr<ge_pi_vector__type> spillgen::generate_backup_code(ptr<ge_pi> ge,ptr<spillgen_group> group,ptr<alloc_int_set__type> reg_orig_owners) {
00193 ptr<ge_pi_vector__type> backup_code;
00194
00195 ptr<tm_register> group_reg = group->reg_get();
00196
00197 lassert(group_reg);
00198
00199 if ( reg_orig_owners->size()!=0 ) {
00200
00201
00202
00203 ptr<tm_data_type_base> backup_type = tm_dt_simple::instance((dt_id_type)*group_reg->compatible_types_get()->begin());
00204
00205
00206 ptr<pi_mem_factory> mf = get_free_spill_space(backup_type);
00207 lassert(mf);
00208 ptr<ge_operand_mem> backup_space = mf->get_ge_mem(NULL);
00209 group->backup_space_set(backup_space);
00210
00211
00212 ptr<ge_operand_reg> reg_to_backup = ge_operand_reg::create(backup_type,ge->bb_get()->fsp_get(),NULL);
00213
00214 backup_code = move_gen->generate_store_to_memory(reg_to_backup,group_reg,backup_space);
00215
00216
00217
00218
00219
00220 mf2ge_pi__type::iterator it_mf = spill_space_last_use->find(mf);
00221 if ( it_mf!=spill_space_last_use->end() ) {
00222 deplog << "C. " << backup_code->front()->uid_get() << " -> " << it_mf->second->uid_get() << "\n" << eolog;
00223 backup_code->front()->dependencies_get()->insert(it_mf->second);
00224 }
00225
00226
00227 } else {
00228
00229 backup_code = ge_pi_vector__type::create();
00230 backup_code->push_back(ge_sp::create(NULL,NULL));
00231
00232
00233 }
00234
00235 lassert(backup_code && backup_code->size()!=0);
00236
00237
00238 ptr<ge_pi> reg_last_use = find_last_use_of_register(group_reg->id_get());
00239
00240
00241
00242
00243
00244 if ( reg_last_use && curr_generated_instructions->find(reg_last_use)==curr_generated_instructions->end() ) {
00245 deplog << "D. " << backup_code->front()->uid_get() << " -> " << reg_last_use->uid_get() << "\n" << eolog;
00246 backup_code->front()->dependencies_get()->insert(reg_last_use);
00247 }
00248
00249 group->backup_instructions_set(backup_code);
00250
00251
00252 deplog << "E. " << ge->uid_get() << " -> " << backup_code->back()->uid_get() << "\n" << eolog;
00253 ge->dependencies_get()->insert(backup_code->back());
00254
00255
00256 insert_code_to_bb(ge->bb_get(),backup_code,false);
00257
00258 return backup_code;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 ptr<ge_pi_vector__type> spillgen::generate_restore_code(ptr<ge_pi> ge,ptr<spillgen_group> group,ptr<alloc_int_set__type> reg_orig_owners) {
00272 ptr<ge_pi_vector__type> restore_code;
00273
00274 ptr<tm_register> group_reg = group->reg_get();
00275
00276 lassert(group_reg);
00277
00278 if ( reg_orig_owners->size()!=0 ) {
00279
00280 ptr<ge_operand_mem> backup_space = group->backup_space_get();
00281
00282 ptr<pi_mem_factory> mf = backup_space->factory_get();
00283 lassert(mf);
00284
00285 ptr<ge_operand_reg> reg_to_restore = ge_operand_reg::create(backup_space->type_get(),ge->bb_get()->fsp_get(),NULL);
00286
00287 restore_code = move_gen->generate_load_from_memory(backup_space,reg_to_restore,group_reg);
00288
00289
00290 (*spill_space_last_use)[mf] = restore_code->back();
00291 } else {
00292
00293 restore_code = ge_pi_vector__type::create();
00294 restore_code->push_back(ge_sp::create(NULL,NULL));
00295 }
00296
00297 lassert(restore_code && restore_code->size());
00298
00299
00300 set_last_use_of_register(group_reg->id_get(),restore_code->back());
00301
00302 group->restore_instructions_set(restore_code);
00303
00304
00305 insert_code_to_bb(ge->bb_get(),restore_code,true);
00306
00307
00308 deplog << "F. " << restore_code->front()->uid_get() << " -> " << ge->uid_get() << "\n" << eolog;
00309 restore_code->front()->dependencies_get()->insert(ge);
00310
00311 return restore_code;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 ptr<ge_pi_vector__type> spillgen::generate_load_code(ptr<ge_pi> ge,ptr<spillgen_group> group,ptr<alloc_interval> interval,ptr<ge_operand_reg> operand, ptr<tm_register> reg) {
00325 lassert(reg);
00326
00327 ptr<ge_pi_vector__type> load_code;
00328
00329 if ( interval->allocated_reg_get() ) {
00330
00331
00332
00333
00334 ptr<ge_operand_reg> source_operand = ge_operand_reg::create(operand->type_get(),ge->bb_get()->fsp_get(),NULL);
00335 load_code = move_gen->generate_copy_to_register(source_operand,interval->allocated_reg_get(),operand,reg);
00336
00337
00338 ptr<spillgen_group_set__type> thief_groups = find_groups_by_reg(interval->allocated_reg_get());
00339 lassert(thief_groups->size()!=0);
00340
00341 for(spillgen_group_set__type::iterator it = thief_groups->begin(); it!=thief_groups->end(); ++it) {
00342 ptr<spillgen_group> thief = *it;
00343 deplog << "G. " << thief->backup_instructions_get()->front()->uid_get() << " -> " << load_code->back()->uid_get() << "\n" << eolog;
00344 thief->backup_instructions_get()->front()->dependencies_get()->insert(load_code->back());
00345 }
00346 } else {
00347
00348 ptr<pi_mem_factory> mf = interval->allocated_spill_place_get();
00349
00350 if ( !mf ) {
00351
00352 mf = get_free_spill_space(operand->type_get());
00353 interval->allocated_spill_place_set(mf);
00354 }
00355
00356 ptr<ge_operand_mem> spill_place = mf->get_ge_mem(ge->bb_get()->fsp_get());
00357
00358 load_code = move_gen->generate_load_from_memory(spill_place,operand,reg);
00359
00360
00361 mf2ge_pi__type::iterator mf_it = spill_space_last_use->find(mf);
00362 if ( mf_it!=spill_space_last_use->end() ) {
00363 deplog << "H. " << load_code->front()->uid_get() << " -> " << mf_it->second->uid_get() << "\n" << eolog;
00364 load_code->front()->dependencies_get()->insert(mf_it->second);
00365 }
00366
00367
00368 (*spill_space_last_use)[mf] = load_code->back();
00369 }
00370
00371 lassert(load_code && load_code->size());
00372
00373
00374
00375
00376 group->load_instructions_get()->insert(load_code->begin(),load_code->end());
00377
00378
00379 insert_code_to_bb(ge->bb_get(),load_code,false);
00380
00381
00382 deplog << "I. " << load_code->front()->uid_get() << " -> " << group->backup_instructions_get()->back()->uid_get() << "\n" << eolog;
00383 load_code->front()->dependencies_get()->insert(group->backup_instructions_get()->back());
00384
00385
00386 ptr<ge_pi> interval_prev_instr = interval_find_previous_instruction(interval,ge->schedule_pos_get());
00387
00388 if ( interval_prev_instr ) {
00389
00390 deplog << "J. " << load_code->front()->uid_get() << " -> " << interval_prev_instr->uid_get() << "\n" << eolog;
00391 load_code->front()->dependencies_get()->insert(interval_prev_instr);
00392 }
00393
00394
00395 deplog << "K. " << ge->uid_get() << " -> " << load_code->back()->uid_get() << "\n" << eolog;
00396 ge->dependencies_get()->insert(load_code->back());
00397
00398
00399 (*operand->assigned_registers_get())[ge] = reg->id_get();
00400
00401 return load_code;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 ptr<ge_pi_vector__type> spillgen::generate_store_code(ptr<ge_pi> ge,ptr<spillgen_group> group,ptr<alloc_interval> interval,ptr<ge_operand_reg> operand, ptr<tm_register> reg) {
00415 lassert(reg);
00416
00417 ptr<ge_pi_vector__type> store_code;
00418
00419 if ( interval->allocated_reg_get() ) {
00420
00421
00422
00423
00424 ptr<ge_operand_reg> destination_operand = ge_operand_reg::create(operand->type_get(),NULL,NULL);
00425
00426 store_code = move_gen->generate_copy_to_register(operand,reg,destination_operand,interval->allocated_reg_get());
00427
00428 ge->bb_get()->lsp_get()->operands_input_get()->push_back(destination_operand);
00429
00430
00431 ptr<spillgen_group_set__type> thief_groups = find_groups_by_reg(interval->allocated_reg_get());
00432
00433 for(spillgen_group_set__type::iterator it = thief_groups->begin(); it!=thief_groups->end(); ++it) {
00434 ptr<spillgen_group> thief = *it;
00435 deplog << "L. " << store_code->front()->uid_get() << " -> " << thief->restore_instructions_get()->back()->uid_get() << "\n" << eolog;
00436 store_code->front()->dependencies_get()->insert(thief->restore_instructions_get()->back());
00437 }
00438 } else {
00439 ptr<pi_mem_factory> mf = interval->allocated_spill_place_get();
00440
00441 if ( !mf ) {
00442
00443 mf = get_free_spill_space(operand->type_get());
00444 interval->allocated_spill_place_set(mf);
00445 }
00446
00447
00448 ptr<ge_operand_mem> spill_place = mf->get_ge_mem(NULL);
00449 store_code = move_gen->generate_store_to_memory(operand,reg,spill_place);
00450 spill_place->origin_set(store_code->back());
00451
00452
00453 mf2ge_pi__type::iterator mf_it = spill_space_last_use->find(mf);
00454 if ( mf_it!=spill_space_last_use->end() ) {
00455 deplog << "M. " << store_code->front()->uid_get() << " -> " << mf_it->second->uid_get() << "\n" << eolog;
00456 store_code->front()->dependencies_get()->insert(mf_it->second);
00457 }
00458
00459
00460 (*spill_space_last_use)[mf] = store_code->back();
00461 }
00462
00463 lassert(store_code && store_code->size());
00464
00465
00466
00467
00468 group->store_instructions_get()->insert(store_code->begin(),store_code->end());
00469
00470
00471 insert_code_to_bb(ge->bb_get(),store_code,true);
00472
00473
00474 deplog << "N. " << store_code->front()->uid_get() << " -> " << ge->uid_get() << "\n" << eolog;
00475 store_code->front()->dependencies_get()->insert(ge);
00476
00477
00478 deplog << "O. " << group->restore_instructions_get()->front()->uid_get() << " -> " << store_code->back()->uid_get() << "\n" << eolog;
00479 group->restore_instructions_get()->front()->dependencies_get()->insert(store_code->back());
00480
00481
00482 ptr<ge_pi> interval_next_instr = interval_find_next_instruction(interval,ge->schedule_pos_get());
00483 if ( interval_next_instr ) {
00484 deplog << "P. " << interval_next_instr->uid_get() << " -> " << store_code->back()->uid_get() << "\n" << eolog;
00485 interval_next_instr->dependencies_get()->insert(store_code->back());
00486 }
00487
00488
00489 (*operand->assigned_registers_get())[ge] = reg->id_get();
00490
00491 return store_code;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500 ptr<spillgen_group_set__type> spillgen::find_groups_by_reg(ptr<tm_register> reg) {
00501 slog << "find_groups_by_reg start\n" << eolog;
00502
00503 ptr<spillgen_group_set__type> found_groups = spillgen_group_set__type::create();
00504
00505 ptr<id_set__type> aliases = reg->aliases_get();
00506
00507 for(spillgen_group_list__type::iterator it = groups->begin(); it!=groups->end(); ++it) {
00508 ptr<spillgen_group> group = *it;
00509
00510
00511 ptr<tm_register> group_reg = group->reg_get();
00512
00513 if ( aliases->find(group_reg->id_get())!=aliases->end() ) {
00514 found_groups->insert(group);
00515 }
00516 }
00517
00518 slog << "find_groups_by_reg end\n" << eolog;
00519
00520 return found_groups;
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530 void spillgen::generate_spill_code(ptr<ge_pi> ge,ptr<ge_pi_list__type>, ge_pi_list__type::iterator) {
00531 slog << "generate_spill_code start\n" << eolog;
00532
00533 slog << "generate_spill_code for ge_pi=" << ge->uid_get() << "\n" << eolog;
00534
00535 curr_generated_instructions->clear();
00536
00537
00538 for(spillgen_group_list__type::iterator it = groups->begin(); it!=groups->end(); ++it) {
00539 ptr<spillgen_group> group = *it;
00540
00541
00542 ptr<tm_register> group_reg = group->reg_get();
00543 lassert(group_reg);
00544
00545 if ( group_reg->is_unspillable() ) {
00546 ptr<ge_op_reg_set__type> operands = group->operands_get();
00547 for(ge_op_reg_set__type::iterator it2 = operands->begin(); it2!=operands->end(); ++it2) {
00548 (*(*it2)->assigned_registers_get())[ge] = group_reg->id_get();
00549 }
00550 continue;
00551 }
00552
00553
00554 group->avail_regs_for_input_ops_set(id_set__type::create(group_reg->aliases_get()));
00555 group->avail_regs_for_output_ops_set(id_set__type::create(group_reg->aliases_get()));
00556
00557
00558 ptr<alloc_int_set__type> orig_owners = find_register_owners(group_reg);
00559
00560
00561 for(spillgen_group_list__type::iterator it1 = groups->begin(); it1!=groups->end(); ++it1) {
00562
00563 ptr<ge_op_reg_set__type> operands = (*it1)->operands_get();
00564
00565 for(ge_op_reg_set__type::iterator it2 = operands->begin(); it2!=operands->end(); ++it2) {
00566 ptr<alloc_interval> interval = (*op2interval)[*it2];
00567 orig_owners->erase(interval);
00568 }
00569 }
00570
00571
00572 ptr<ge_pi_vector__type> backup_code = generate_backup_code(ge, group, orig_owners);
00573
00574 curr_generated_instructions->insert(backup_code->begin(),backup_code->end());
00575
00576 #ifdef BACKEND_V2_DEBUG
00577 ::std::ostringstream oss1;
00578 oss1 << "backup code (ge_pi=" << ge->uid_get() << ", group=" << group->uid_get() << ")";
00579 set_instruction_property(backup_code,ge_pi::PROPERTY_SPILLGEN_INFO,oss1.str());
00580 #endif
00581
00582
00583 ptr<ge_pi_vector__type> restore_code = generate_restore_code(ge, group, orig_owners);
00584
00585 curr_generated_instructions->insert(restore_code->begin(),restore_code->end());
00586
00587 #ifdef BACKEND_V2_DEBUG
00588 ::std::ostringstream oss2;
00589 oss2 << "restore code (ge_pi=" << ge->uid_get() << ", group=" << group->uid_get() << ")";
00590 set_instruction_property(restore_code,ge_pi::PROPERTY_SPILLGEN_INFO,oss2.str());
00591 #endif
00592
00593 }
00594
00595
00596 ulint op_pos = 0;
00597 ptr<ge_operand_vector__type> ops = ge->operands_input_get();
00598 for(ge_operand_vector__type::iterator it = ops->begin(); it!=ops->end(); ++it, ++op_pos) {
00599
00600 if ( (*it)->kind_get()!=ge_operand::REGISTER ) {
00601 continue;
00602 }
00603
00604 ptr<ge_operand_reg> op = (*it).dncast<ge_operand_reg>();
00605 ptr<tm_instr_op_reg> tmop = (*ge->instruction_get()->operands_input_get())[op_pos].dncast<tm_instr_op_reg>();
00606
00607 ptr<spillgen_group> group = (*op2group)[op];
00608 lassert(group);
00609
00610 ptr<alloc_interval> interval = (*op2interval)[op];
00611 lassert(interval);
00612
00613
00614 ptr<tm_register> group_reg = group->reg_get();
00615 lassert(group_reg);
00616
00617 if ( group_reg->is_unspillable() ) {
00618 continue;
00619 }
00620
00621 ptr<id_set__type> tmp_set = id_set__type::create();
00622
00623 ::std::set_intersection(
00624 group->avail_regs_for_input_ops_get()->begin(),
00625 group->avail_regs_for_input_ops_get()->end(),
00626 tmop->allowed_registers_get()->begin(),
00627 tmop->allowed_registers_get()->end(),
00628 ::std::inserter(*tmp_set,tmp_set->begin()));
00629
00630 lassert(tmp_set->size()!=0);
00631
00632 tmp_set = filter_regs_by_data_type(tmp_set,op->type_get()->id_get());
00633
00634
00635 ptr<tm_register> interval_reg = tm_register::instance(*tmp_set->begin());
00636
00637
00638 tmp_set = id_set__type::create();
00639 ::std::set_difference(
00640 group->avail_regs_for_input_ops_get()->begin(),
00641 group->avail_regs_for_input_ops_get()->end(),
00642 interval_reg->aliases_get()->begin(),
00643 interval_reg->aliases_get()->end(),
00644 ::std::inserter(*tmp_set,tmp_set->begin()));
00645
00646 group->avail_regs_for_input_ops_set(tmp_set);
00647
00648 if ( interval->allocated_reg_get()==interval_reg ) {
00649
00650 continue;
00651 }
00652
00653
00654 ptr<ge_pi_vector__type> load_code = generate_load_code(ge,group,interval,op,interval_reg);
00655
00656 curr_generated_instructions->insert(load_code->begin(),load_code->end());
00657
00658 #ifdef BACKEND_V2_DEBUG
00659 ::std::ostringstream oss1;
00660 oss1 << "load code (ge_pi=" << ge->uid_get() << ", group=" << group->uid_get() << ", interval=" << interval->uid_get() << ")";
00661 set_instruction_property(load_code,ge_pi::PROPERTY_SPILLGEN_INFO,oss1.str());
00662 #endif
00663
00664 }
00665
00666 op_pos = 0;
00667 ops = ge->operands_output_get();
00668 for(ge_operand_vector__type::iterator it = ops->begin(); it!=ops->end(); ++it, ++op_pos) {
00669
00670 if ( (*it)->kind_get()!=ge_operand::REGISTER ) {
00671 continue;
00672 }
00673
00674 ptr<ge_operand_reg> op = (*it).dncast<ge_operand_reg>();
00675 ptr<tm_instr_op_reg> tmop = (*ge->instruction_get()->operands_output_get())[op_pos].dncast<tm_instr_op_reg>();
00676
00677 ptr<spillgen_group> group = (*op2group)[op];
00678 lassert(group);
00679
00680 ptr<alloc_interval> interval = (*op2interval)[op];
00681 lassert(interval);
00682
00683
00684 ptr<tm_register> group_reg = group->reg_get();
00685 lassert(group_reg);
00686
00687 if ( group_reg->is_unspillable() ) {
00688 continue;
00689 }
00690
00691 ptr<id_set__type> tmp_set = id_set__type::create();
00692
00693 ::std::set_intersection(
00694 group->avail_regs_for_output_ops_get()->begin(),
00695 group->avail_regs_for_output_ops_get()->end(),
00696 tmop->allowed_registers_get()->begin(),
00697 tmop->allowed_registers_get()->end(),
00698 ::std::inserter(*tmp_set,tmp_set->begin()));
00699
00700 tmp_set = filter_regs_by_data_type(tmp_set,op->type_get()->id_get());
00701
00702 lassert(tmp_set->size()!=0);
00703
00704
00705 ptr<tm_register> interval_reg = tm_register::instance(*tmp_set->begin());
00706
00707
00708 tmp_set = id_set__type::create();
00709 ::std::set_difference(
00710 group->avail_regs_for_output_ops_get()->begin(),
00711 group->avail_regs_for_output_ops_get()->end(),
00712 interval_reg->aliases_get()->begin(),
00713 interval_reg->aliases_get()->end(),
00714 ::std::inserter(*tmp_set,tmp_set->begin()));
00715
00716 group->avail_regs_for_output_ops_set(tmp_set);
00717
00718 if ( interval->allocated_reg_get()==interval_reg ) {
00719
00720 continue;
00721 }
00722
00723
00724 ptr<ge_pi_vector__type> store_code = generate_store_code(ge,group,interval,op,interval_reg);
00725
00726 curr_generated_instructions->insert(store_code->begin(),store_code->end());
00727
00728 #ifdef BACKEND_V2_DEBUG
00729 ::std::ostringstream oss1;
00730 oss1 << "store code (ge_pi=" << ge->uid_get() << ", group=" << group->uid_get() << ", interval=" << interval->uid_get() << ")";
00731 set_instruction_property(store_code,ge_pi::PROPERTY_SPILLGEN_INFO,oss1.str());
00732 #endif
00733
00734 }
00735
00736 slog << "generate_spill_code end\n" << eolog;
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746 ptr<ge_pi> spillgen::interval_find_previous_instruction(ptr<alloc_interval> interval, ulint curr_pos) {
00747 slog << "interval_find_previous_instruction start\n" << eolog;
00748
00749 ptr<ge_pi_vector__type> instructions = interval->instructions_get();
00750
00751 for(ge_pi_vector__type::reverse_iterator it = instructions->rbegin(); it!=instructions->rend(); ++it) {
00752 if ( (*it)->schedule_pos_get() < curr_pos ) {
00753 slog << "interval_find_revious_instruction end 1\n" << eolog;
00754 return *it;
00755 }
00756 }
00757
00758 slog << "interval_find_previous_instruction end\n" << eolog;
00759
00760 return NULL;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770 ptr<ge_pi> spillgen::interval_find_next_instruction(ptr<alloc_interval> interval, ulint curr_pos) {
00771 slog << "interval_find_next_instruction start\n" << eolog;
00772
00773 ptr<ge_pi_vector__type> instructions = interval->instructions_get();
00774
00775 for(ge_pi_vector__type::iterator it = instructions->begin(); it!=instructions->end(); ++it) {
00776 if ( (*it)->schedule_pos_get() > curr_pos ) {
00777 slog << "interval_find_next_instruction end 1\n" << eolog;
00778 return *it;
00779 }
00780 }
00781
00782 slog << "interval_find_next_instruction end\n" << eolog;
00783
00784 return NULL;
00785 }
00786
00787
00788
00789
00790
00791
00792
00793 ptr<alloc_int_set__type> spillgen::find_register_owners(ptr<tm_register> reg) {
00794 slog << "find_register_owners start\n" << eolog;
00795
00796 ptr<alloc_int_set__type> res = alloc_int_set__type::create();
00797
00798 ptr<id_set__type> aliases = reg->aliases_get();
00799
00800 for(id_set__type::iterator it = aliases->begin(); it!=aliases->end(); ++it) {
00801 reg2alloc_int__type::iterator it_int = register_owners->find(*it);
00802
00803 if ( it_int!=register_owners->end() ) {
00804 res->insert(it_int->second);
00805 }
00806 }
00807
00808 slog << "find_register_owners end\n" << eolog;
00809 return res;
00810 }
00811
00812
00813
00814
00815 void spillgen::allocate_regs_for_groups() {
00816 slog << "allocate_regs_for_groups start\n" << eolog;
00817
00818 spillgen_group_list__type::iterator it_stop = groups->end();
00819 spillgen_group_list__type::iterator it = groups->begin();
00820
00821 while (true) {
00822 if ( it_stop==it ) {
00823 break;
00824 }
00825
00826 if ( it == groups->end() ) {
00827 it = groups->begin();
00828 continue;
00829 }
00830
00831 ptr<spillgen_group> group = *it;
00832
00833 if ( !group->reg_get() ) {
00834 allocate_reg_for_group(group);
00835 it_stop = it;
00836 }
00837
00838 ++it;
00839 }
00840
00841 slog << "allocate_regs_for_groups end\n" << eolog;
00842 }
00843
00844
00845
00846
00847
00848
00849 void spillgen::allocate_reg_for_group(ptr<spillgen_group> group) {
00850 slog << "allocate_reg_for_group start\n" << eolog;
00851
00852 ptr<id_set__type> allowed_regs = group->allowed_registers_get();
00853 ptr<id_set__type> avail_regs = id_set__type::create();
00854
00855 ptr<tm_register> reg;
00856
00857 while (true) {
00858 ptr<id_set__type> avail_regs = id_set__type::create();
00859
00860
00861 ::std::set_intersection(
00862 free_registers->begin(),
00863 free_registers->end(),
00864 allowed_regs->begin(),
00865 allowed_regs->end(),
00866 ::std::inserter(*avail_regs, avail_regs->begin()));
00867
00868
00869 if ( avail_regs->size()==0 ) {
00870
00871
00872
00873
00874 ptr<id_set__type> tmp = id_set__type::create();
00875
00876 ::std::set_difference(
00877 all_registers->begin(),
00878 all_registers->end(),
00879 regs_used_by_groups->begin(),
00880 regs_used_by_groups->end(),
00881 ::std::inserter(*tmp, tmp->begin()));
00882
00883 ::std::set_intersection(
00884 tmp->begin(),
00885 tmp->end(),
00886 allowed_regs->begin(),
00887 allowed_regs->end(),
00888 ::std::inserter(*avail_regs, avail_regs->begin()));
00889
00890 }
00891
00892 if ( avail_regs->size()!=0 ) {
00893 reg = tm_register::instance(*avail_regs->begin());
00894 break;
00895 }
00896
00897
00898 steal_register_from_siblings(group, allowed_regs);
00899 }
00900
00901 lassert(reg);
00902 lassert(allowed_regs->find(reg->id_get())!=allowed_regs->end());
00903
00904 group->reg_set(reg);
00905
00906 regs_used_by_groups->insert(reg->aliases_get()->begin(),reg->aliases_get()->end());
00907
00908 ptr<id_set__type> updated_free_registers = id_set__type::create();
00909
00910 ::std::set_difference(
00911 all_registers->begin(),
00912 all_registers->end(),
00913 reg->aliases_get()->begin(),
00914 reg->aliases_get()->end(),
00915 ::std::inserter(*updated_free_registers,updated_free_registers->begin()));
00916
00917 free_registers = updated_free_registers;
00918
00919 slog << "allocate_reg_for_group end\n" << eolog;
00920 }
00921
00922
00923
00924
00925
00926
00927 void spillgen::steal_register_from_siblings(ptr<spillgen_group> thief, ptr<id_set__type> allowed_regs) {
00928 slog << "steal_register_from_siblings start\n" << eolog;
00929
00930 ptr<spillgen_group> guarded_grp = thief->guarded_group_get();
00931
00932 for(spillgen_group_list__type::iterator it = groups->begin(); it!=groups->end(); ++it) {
00933 ptr<spillgen_group> group = *it;
00934
00935 if ( group!=thief && group!=guarded_grp && group->reg_get() && group->allowed_registers_get()->size()>1 ) {
00936 ptr<tm_register> grp_reg = group->reg_get();
00937 ptr<id_set__type> aliases = grp_reg->aliases_get();
00938
00939 ptr<id_set__type> tmp = id_set__type::create();
00940
00941 ::std::set_intersection(
00942 allowed_regs->begin(),
00943 allowed_regs->end(),
00944 aliases->begin(),
00945 aliases->end(),
00946 ::std::inserter(*tmp, tmp->begin()));
00947
00948 if ( tmp->size()>0 ) {
00949 group->guarded_group_set(thief);
00950
00951 free_registers->insert(aliases->begin(),aliases->end());
00952
00953 ptr<id_set__type> tmp_set = id_set__type::create();
00954 ::std::set_difference(
00955 regs_used_by_groups->begin(),
00956 regs_used_by_groups->end(),
00957 aliases->begin(),
00958 aliases->end(),
00959 ::std::inserter(*tmp_set, tmp_set->begin()));
00960
00961 regs_used_by_groups = tmp_set;
00962 }
00963 }
00964 }
00965
00966 slog << "steal_register_from_siblings end\n" << eolog;
00967 }
00968
00969
00970
00971
00972
00973
00974
00975
00976 bool spillgen::identify_groups(ptr<ge_pi> ge) {
00977 slog << "identify_groups start\n" << eolog;
00978
00979 ptr<tm_instr_base> tm = ge->instruction_get();
00980
00981 regs_used_by_groups->clear();
00982 groups->clear();
00983 op2group->clear();
00984
00985 if ( !tm ) {
00986 slog << "identify_groups end 1\n" << eolog;
00987 return false;
00988 }
00989
00990
00991
00992
00993 bool b_nothing_to_do = true;
00994
00995 ptr<ge_operand_vector__type> ops = ge->operands_input_get();
00996
00997 ulint op_pos = 0;
00998 for(ge_operand_vector__type::iterator it = ops->begin(); it!=ops->end(); ++it, ++op_pos) {
00999
01000 if ( (*it)->kind_get()!=ge_operand::REGISTER ) {
01001 continue;
01002 }
01003
01004 ptr<ge_operand_reg> op = (*it).dncast<ge_operand_reg>();
01005 ptr<tm_instr_op_reg_base> tmop = (*tm->operands_input_get())[op_pos].dncast<tm_instr_op_reg_base>();
01006 ptr<tm_register> reg = NULL;
01007
01008 ge2reg_map__type::iterator it1 = op->assigned_registers_get()->find(ge);
01009 if ( it1!=op->assigned_registers_get()->end() ) {
01010 reg = tm_register::instance(it1->second);
01011 } else {
01012 b_nothing_to_do = false;
01013 }
01014
01015 ptr<spillgen_group> group = spillgen_group::create();
01016 group->reg_set(reg);
01017 group->operands_get()->insert(op);
01018 group->allowed_registers_set(filter_regs_by_data_type(id_set__type::create(tmop->allowed_registers_get()), op->type_get()->id_get()));
01019 group->is_input_set(true);
01020
01021 if (reg && group->allowed_registers_get()->find(reg->id_get())==group->allowed_registers_get()->end()) {
01022 lassert(!reg || group->allowed_registers_get()->find(reg->id_get())!=group->allowed_registers_get()->end());
01023 }
01024
01025 groups->push_back(group);
01026 (*op2group)[op] = group;
01027 }
01028
01029 ops = ge->operands_output_get();
01030
01031 op_pos = 0;
01032 for(ge_operand_vector__type::iterator it = ops->begin(); it!=ops->end(); ++it, ++op_pos) {
01033
01034 if ( (*it)->kind_get()!=ge_operand::REGISTER ) {
01035 continue;
01036 }
01037
01038 ptr<ge_operand_reg> op = (*it).dncast<ge_operand_reg>();
01039 ptr<tm_instr_op_reg_base> tmop = (*tm->operands_output_get())[op_pos].dncast<tm_instr_op_reg_base>();
01040 ptr<tm_register> reg = NULL;
01041
01042 ge2reg_map__type::iterator it1 = op->assigned_registers_get()->find(ge);
01043 if ( it1!=op->assigned_registers_get()->end() ) {
01044 reg = tm_register::instance(it1->second);
01045 } else {
01046 b_nothing_to_do = false;
01047 }
01048
01049 ptr<spillgen_group> group;
01050
01051 if ( tmop->destroys_get()==NO_OPERAND_ID ) {
01052
01053 group = spillgen_group::create();
01054 group->reg_set(reg);
01055 group->allowed_registers_set(filter_regs_by_data_type(id_set__type::create(tmop->allowed_registers_get()), op->type_get()->id_get()));
01056 groups->push_back(group);
01057
01058 lassert(!reg || group->allowed_registers_get()->find(reg->id_get())!=group->allowed_registers_get()->end());
01059 } else {
01060
01061 ptr<ge_operand_reg> destroyed_op = (*ge->operands_input_get())[tmop->destroys_get() - I_1].dncast<ge_operand_reg>();
01062 group = (*op2group)[destroyed_op];
01063 ptr<tm_register> destroyed_reg = group->reg_get();
01064
01065 if ( op->type_get()->bitwidth_get() > destroyed_op->type_get()->bitwidth_get() ) {
01066 group->reg_set(reg);
01067
01068
01069 if ( destroyed_reg ) {
01070 ptr<id_set__type> regs_to_free;
01071
01072 if ( !reg ) {
01073
01074 regs_to_free = destroyed_reg->aliases_get();
01075 } else {
01076
01077 regs_to_free = id_set__type::create();
01078
01079 ::std::set_difference(
01080 reg->aliases_get()->begin(),
01081 reg->aliases_get()->end(),
01082 destroyed_reg->aliases_get()->begin(),
01083 destroyed_reg->aliases_get()->end(),
01084 ::std::inserter(*regs_to_free,regs_to_free->begin()));
01085
01086 }
01087
01088 if ( regs_to_free ) {
01089
01090 free_registers->insert(regs_to_free->begin(),regs_to_free->end());
01091 }
01092 }
01093
01094
01095 group->allowed_registers_set(filter_regs_by_data_type(id_set__type::create(tmop->allowed_registers_get()),op->type_get()->id_get()));
01096
01097 lassert(!reg || group->allowed_registers_get()->find(reg->id_get())!=group->allowed_registers_get()->end());
01098 }
01099 }
01100
01101 group->is_output_set(true);
01102 group->operands_get()->insert(op);
01103 (*op2group)[op] = group;
01104 }
01105
01106
01107 for(spillgen_group_list__type::iterator it = groups->begin(); it!=groups->end(); ++it) {
01108 ptr<spillgen_group> group = *it;
01109
01110 if ( group->reg_get() ) {
01111 ptr<id_set__type> aliases = group->reg_get()->aliases_get();
01112 regs_used_by_groups->insert(aliases->begin(),aliases->end());
01113 }
01114 }
01115
01116 slog << "find_spillgen_groups end\n" << eolog;
01117
01118 return !b_nothing_to_do;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127 ptr<id_set__type> spillgen::filter_regs_by_data_type(ptr<id_set__type> reg_set, ulint type_id) {
01128 slog << "filter_regs_by_data_type start\n" << eolog;
01129
01130 for(id_set__type::iterator it = reg_set->begin(); it!=reg_set->end();) {
01131 ptr<tm_register> reg = tm_register::instance(*it);
01132
01133 if ( reg->compatible_types_get()->find(type_id)==reg->compatible_types_get()->end() ) {
01134 id_set__type::iterator del_it = it++;
01135 reg_set->erase(del_it);
01136 } else {
01137 ++it;
01138 }
01139 }
01140
01141 slog << "filter_regs_by_data_type end\n" << eolog;
01142
01143 return reg_set;
01144 }
01145
01146
01147
01148
01149
01150 void spillgen::setup_registers() {
01151 for(ulint i = R_UNDEFINED+1; i<RIT_TERMINATOR; ++i) {
01152 all_registers->insert(i);
01153 }
01154 }
01155
01156
01157
01158
01159
01160
01161 void spillgen::find_free_registers() {
01162 slog << "find_free_registers start\n" << eolog;
01163
01164 registers_freed = false;
01165
01166 ptr<id_set__type> deep_used_registers = id_set__type::create();
01167
01168 for(id_set__type::iterator it=used_registers->begin(); it!=used_registers->end(); ++it) {
01169 ptr<tm_register> reg = tm_register::instance(*it);
01170
01171 ptr<id_set__type> new_deep_used_registers = id_set__type::create();
01172
01173 ::std::set_union(
01174 reg->aliases_get()->begin(),
01175 reg->aliases_get()->end(),
01176 deep_used_registers->begin(),
01177 deep_used_registers->end(),
01178 ::std::inserter(*new_deep_used_registers,new_deep_used_registers->begin()));
01179
01180 deep_used_registers = new_deep_used_registers;
01181 }
01182
01183 ptr<id_set__type> updated_free_registers = id_set__type::create();
01184
01185 ::std::set_difference(
01186 all_registers->begin(),
01187 all_registers->end(),
01188 deep_used_registers->begin(),
01189 deep_used_registers->end(),
01190 ::std::inserter(*updated_free_registers,updated_free_registers->begin()));
01191
01192 free_registers = updated_free_registers;
01193
01194 slog << "find_free_registers end\n" << eolog;
01195 }
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 ptr<pi_mem_factory> spillgen::get_free_spill_space(ptr<tm_data_type_base> type) {
01208 slog << "get_free_spill_space start\n" << eolog;
01209
01210 ulint bitwidth = type->bitwidth_get();
01211
01212
01213
01214
01215 for(mf_set__type::iterator it = free_spill_spaces->begin(); it!=free_spill_spaces->end(); ++it) {
01216 ptr<pi_mem_factory> mf = *it;
01217 lassert(mf);
01218
01219 if ( mf->type_get()->bitwidth_get()==bitwidth ) {
01220 free_spill_spaces->erase(mf);
01221 slog << "get_free_spill_space end 1\n" << eolog;
01222 mf->type_set(type);
01223 return mf;
01224 }
01225 }
01226
01227
01228 ptr<pi_mem_factory> spill_space = mem_alloc_manager::instance()->allocate_local_tmp(data_get()->function_decl_get(),type);
01229
01230 lassert(spill_space);
01231
01232 slog << "get_free_spill_space end\n" << eolog;
01233 return spill_space;
01234 }
01235
01236
01237
01238
01239
01240
01241
01242 bool spillgen::activate_waiting_intervals(ulint curr_point) {
01243 slog << "activate_waiting_intervals start\n" << eolog;
01244
01245 bool b_free_regs_need_recalculate = false;
01246
01247 for(alloc_int_vector__type::iterator it = waiting_intervals->begin(); it!=waiting_intervals->end();) {
01248 ptr<alloc_interval> interval = *it;
01249
01250 if ( interval->start_get() <= curr_point ) {
01251 slog << "interval(id:" << interval->uid_get() << ") activated\n" << eolog;
01252
01253 active_intervals->push_back(interval);
01254 it = waiting_intervals->erase(it);
01255
01256 ptr<tm_register> allocated_reg = interval->allocated_reg_get();
01257
01258 if ( allocated_reg ) {
01259 (*register_owners)[allocated_reg->id_get()] = interval;
01260 used_registers->insert(allocated_reg->id_get());
01261 b_free_regs_need_recalculate = true;
01262 }
01263
01264 (*op2interval)[interval->operand_get()] = interval;
01265 } else {
01266 break;
01267 }
01268 }
01269
01270 slog << "activate_waiting_intervals end\n" << eolog;
01271
01272 return b_free_regs_need_recalculate;
01273
01274 }
01275
01276
01277
01278
01279
01280
01281
01282 bool spillgen::expire_old_intervals(ulint curr_point) {
01283 slog << "expire_old_intervals start\n" << eolog;
01284
01285 bool b_free_regs_need_recalculate = false;
01286
01287 for(alloc_int_vector__type::iterator it = active_intervals->begin(); it!=active_intervals->end();) {
01288 ptr<alloc_interval> interval = *it;
01289
01290 if ( interval->end_get() < curr_point ) {
01291 slog << "interval(id:" << interval->uid_get() << ") expired\n" << eolog;
01292
01293 it = active_intervals->erase(it);
01294 expired_intervals->push_back(interval);
01295
01296 if ( interval->next_get() ) {
01297
01298 ptr<alloc_interval> next = interval->next_get();
01299
01300 ptr<tm_register> source_reg = interval->allocated_reg_get();
01301 ptr<tm_register> target_reg = next->allocated_reg_get();
01302
01303 if ( interval->allocated_spill_place_get() && !target_reg ) {
01304
01305 next->allocated_spill_place_set(interval->allocated_spill_place_get());
01306 } else {
01307
01308 free_spill_spaces->insert(interval->allocated_spill_place_get());
01309 }
01310
01311 ptr<ge_pi_vector__type> copy_code;
01312
01313 if ( source_reg && target_reg ) {
01314
01315 ptr<ge_operand_reg> target_operand = ge_operand_reg::create(next->operand_get()->type_get(),NULL,NULL);
01316 copy_code = move_gen->generate_copy_to_register(interval->operand_get(),source_reg,target_operand,target_reg);
01317 target_operand->origin_set(copy_code->back());
01318
01319 ptr<ge_pi> prev_use = find_last_use_of_register(source_reg->id_get());
01320 if ( prev_use ) {
01321 deplog << "Q. " << copy_code->front()->uid_get() << " -> " << prev_use->uid_get() << "\n" << eolog;
01322 copy_code->front()->dependencies_get()->insert(prev_use);
01323 }
01324
01325 prev_use = find_last_use_of_register(target_reg->id_get());
01326 if ( prev_use ) {
01327 deplog << "R. " << copy_code->front()->uid_get() << " -> " << prev_use->uid_get() << "\n" << eolog;
01328 copy_code->front()->dependencies_get()->insert(prev_use);
01329 }
01330
01331 set_last_use_of_register(source_reg->id_get(),copy_code->back());
01332 set_last_use_of_register(target_reg->id_get(),copy_code->back());
01333
01334 } else if ( !source_reg && target_reg ) {
01335
01336 ptr<pi_mem_factory> mf = interval->allocated_spill_place_get();
01337 ptr<ge_operand_reg> target_operand = ge_operand_reg::create(next->operand_get()->type_get(),NULL,NULL);
01338 ptr<ge_operand_mem> spill_place = mf->get_ge_mem(interval->instructions_get()->front());
01339 copy_code = move_gen->generate_load_from_memory(spill_place,target_operand,target_reg);
01340 target_operand->origin_set(copy_code->back());
01341
01342 mf2ge_pi__type::iterator mf_it = spill_space_last_use->find(mf);
01343 if ( mf_it!=spill_space_last_use->end() ) {
01344 deplog << "S. " << copy_code->front()->uid_get() << " -> " << mf_it->second->uid_get() << "\n" << eolog;
01345 copy_code->front()->dependencies_get()->insert(mf_it->second);
01346 }
01347
01348 ptr<ge_pi> prev_use = find_last_use_of_register(target_reg->id_get());
01349 if ( prev_use ) {
01350 deplog << "T. " << copy_code->front()->uid_get() << " -> " << prev_use->uid_get() << "\n" << eolog;
01351 copy_code->front()->dependencies_get()->insert(prev_use);
01352 }
01353
01354 set_last_use_of_register(target_reg->id_get(),copy_code->back());
01355 (*spill_space_last_use)[mf] = copy_code->back();
01356 } else if ( source_reg && !target_reg ) {
01357
01358 ptr<pi_mem_factory> mf = next->allocated_spill_place_get();
01359
01360 if ( !mf ) {
01361 mf = get_free_spill_space(next->operand_get()->type_get());
01362 next->allocated_spill_place_set(mf);
01363 }
01364
01365 ptr<ge_operand_mem> spill_place = mf->get_ge_mem(NULL);
01366 copy_code = move_gen->generate_store_to_memory(interval->operand_get(),source_reg,spill_place);
01367 spill_place->origin_set(copy_code->back());
01368
01369 mf2ge_pi__type::iterator mf_it = spill_space_last_use->find(mf);
01370 if ( mf_it!=spill_space_last_use->end() ) {
01371 deplog << "U. " << copy_code->front()->uid_get() << " -> " << mf_it->second->uid_get() << "\n" << eolog;
01372 copy_code->front()->dependencies_get()->insert(mf_it->second);
01373 }
01374
01375 ptr<ge_pi> prev_use = find_last_use_of_register(source_reg->id_get());
01376 if ( prev_use ) {
01377 deplog << "V. " << copy_code->front()->uid_get() << " -> " << prev_use->uid_get() << "\n" << eolog;
01378 copy_code->front()->dependencies_get()->insert(prev_use);
01379 }
01380
01381 set_last_use_of_register(source_reg->id_get(),copy_code->back());
01382 (*spill_space_last_use)[mf] = copy_code->back();
01383 }
01384
01385 if ( copy_code ) {
01386
01387 ptr<basic_block> bb = interval->instructions_get()->back()->bb_get();
01388 bb->instructions_get()->insert(bb->instructions_get()->end(),copy_code->begin(),copy_code->end());
01389
01390 #ifdef BACKEND_V2_DEBUG
01391 ::std::ostringstream oss1;
01392 oss1 << "copy code between intervals (i1=" << interval->uid_get() << ", i2=" << next->uid_get() << ")";
01393 set_instruction_property(copy_code,ge_pi::PROPERTY_SPILLGEN_INFO,oss1.str());
01394 #endif
01395 }
01396
01397 } else {
01398 if ( interval->allocated_spill_place_get() ) {
01399 free_spill_spaces->insert(interval->allocated_spill_place_get());
01400 }
01401 }
01402
01403 if ( interval->allocated_reg_get() && (*register_owners)[interval->allocated_reg_get()->id_get()]==interval ) {
01404 b_free_regs_need_recalculate = true;
01405 used_registers->erase(interval->allocated_reg_get()->id_get());
01406 register_owners->erase(interval->allocated_reg_get()->id_get());
01407 }
01408 } else {
01409 ++it;
01410 }
01411 }
01412
01413 slog << "expire_old_intervals end\n" << eolog;
01414
01415 return b_free_regs_need_recalculate;
01416
01417 }
01418
01419
01420
01421
01422
01423
01424 ptr<ge_pi> spillgen::find_last_use_of_register(ulint regid) {
01425 slog << "find_last_use_of_register start\n" << eolog;
01426
01427 reg2ge_pi__type::iterator it = register_last_use->find(regid);
01428
01429 slog << "find_last_use_of_register end\n" << eolog;
01430 return it==register_last_use->end() ? NULL : it->second;
01431 }
01432
01433
01434
01435
01436
01437
01438 void spillgen::set_last_use_of_register(ulint regid, ptr<ge_pi> ge) {
01439 slog << "set_last_use_of_register start\n" << eolog;
01440
01441 ptr<tm_register> reg = tm_register::instance(regid);
01442 ptr<id_set__type> aliases = reg->aliases_get();
01443
01444 for(id_set__type::iterator it = aliases->begin(); it!=aliases->end(); ++it) {
01445 (*register_last_use)[*it] = ge;
01446 }
01447
01448 slog << "set_last_use_of_register end\n" << eolog;
01449 }
01450
01451
01452
01453
01454
01455
01456
01457 void spillgen::insert_code_to_bb(ptr<basic_block> bb, ptr<ge_pi_vector__type> code, bool back) {
01458 for(ge_pi_vector__type::iterator it = code->begin(); it!=code->end(); ++it) {
01459 (*it)->bb_set(bb);
01460 }
01461
01462 if ( back ) {
01463 bb->instructions_get()->insert(bb->instructions_get()->end(),code->begin(),code->end());
01464 } else {
01465 bb->instructions_get()->insert(bb->instructions_get()->begin(),code->begin(),code->end());
01466 }
01467 }
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 void spillgen::set_instruction_property(ptr<ge_pi_vector__type> instrs,ulint property_id,lstring property_value) {
01478 for(ge_pi_vector__type::iterator it = instrs->begin(); it!=instrs->end(); ++it) {
01479 ptr<ge_pi> ge = *it;
01480
01481 if ( !ge->properties_get() ) {
01482 ge->properties_set(id2lstring__type::create());
01483 }
01484
01485 (*ge->properties_get())[property_id] = property_value;
01486 }
01487 }
01488
01489
01490
01491
01492 ptr< ::lestes::backend_v2::structs::func_data > spillgen::get_result() {
01493 slog << "get_result start\n" << eolog;
01494
01495 slog << "get_result end\n" << eolog;
01496 return data_get();
01497 }
01498
01499
01500
01501 end_package(workers);
01502 end_package(backend_v2);
01503 end_package(lestes);
01504