00001
00002
00003
00004
00005
00006 #include <lestes/backend_v2/debug/debug.hh>
00007 #include <lestes/backend_v2/intercode/pi.g.hh>
00008 #include <lestes/backend_v2/intercode/visitor_pi_pi2pi_operands.g.hh>
00009 #include <lestes/backend_v2/structs/pi_operands.g.hh>
00010 #include <lestes/md/instructions/pi_pi2ge_pi_template.g.hh>
00011 #include <lestes/md/instructions/instruction_group.g.hh>
00012 #include <lestes/md/instructions/tm_instr.g.hh>
00013 #include <lestes/md/types/tm_data_type.g.hh>
00014 #include <lestes/md/registers/move_generator.g.hh>
00015
00016 package(lestes);
00017 package(md);
00018 package(registers);
00019
00020 using namespace ::lestes::backend_v2::debug;
00021 using namespace ::lestes::backend_v2::intercode;
00022 using namespace ::lestes::msg;
00023 using namespace ::lestes::md::instructions;
00024 using namespace ::lestes::md::types;
00025
00026
00027 typedef list< ulint > ulint_list__type;
00028 typedef vector< ulint > ulint_vector__type;
00029 typedef set< ulint > id_set__type;
00030 typedef map< ulint, srp<tm_instr_op_base> > ulint2tm_instr_op_base__type;
00031 typedef map< ulint, srp<ge_operand> > ulint2ge_operand__type;
00032 typedef map< ulint, ulint > ulint2ulint__type;
00033 typedef list< srp < instruction_group_base > > instruction_group_base_list__type;
00034 typedef vector< srp < tm_instr_op_base > > tm_instr_op_base_vector__type;
00035 typedef vector< srp < ge_operand > > ge_operand_vector__type;
00036 typedef vector< srp < ge_pi > > ge_pi_vector__type;
00037 typedef set< srp < ge_pi > > ge_pi_set__type;
00038 typedef vector< srp < ge_sp > > ge_sp_vector__type;
00039 typedef vector< srp < pi_sp > > pi_sp_vector__type;
00040
00041
00042 declare_logger(log1);
00043 initialize_logger( log1, "move_generator", md_logger );
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 ptr<ge_pi_vector__type> move_generator::generate_load_from_memory(ptr<ge_operand_mem> op_mem, ptr<ge_operand_reg> op_reg, ptr<tm_register_base> reg) {
00054 lassert(reg);
00055 return generate_move(op_mem,NULL,op_reg,reg);
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 ptr<ge_pi_vector__type> move_generator::generate_store_to_memory(ptr<ge_operand_reg> op_reg, ptr<tm_register_base> reg, ptr<ge_operand_mem> op_mem) {
00067 lassert(reg);
00068 return generate_move(op_reg,reg,op_mem,NULL);
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 ptr<ge_pi_vector__type> move_generator::generate_copy_to_register(ptr<ge_operand_reg> op_reg_src, ptr<tm_register_base> reg_src, ptr<ge_operand_reg> op_reg_dst, ptr<tm_register_base> reg_dst) {
00082 lassert(reg_src);
00083 lassert(reg_dst);
00084 return generate_move(op_reg_src, reg_src, op_reg_dst, reg_dst);
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 ptr<ge_pi_vector__type> move_generator::generate_move(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg) {
00100 log1 << "generate_move - start\n" << eolog;
00101 lassert(input_op);
00102 lassert(!input_reg || input_reg->bitwidth_get()>=input_op->type_get()->bitwidth_get());
00103 lassert(output_op);
00104 lassert(!output_reg || output_reg->bitwidth_get()>=output_op->type_get()->bitwidth_get());
00105
00106 ptr<ulint_vector__type> selected_instrs = ulint_vector__type::create();
00107 ptr<ulint2tm_instr_op_base__type> selected_operands = ulint2tm_instr_op_base__type::create();
00108 ptr<ulint2ulint__type> selected_op_types = ulint2ulint__type::create();
00109
00110 ptr<id_set__type> move_templates = input_reg ? input_reg->move_templates_get() : output_reg->move_templates_get();
00111
00112 for(id_set__type::iterator it = move_templates->begin(); it!=move_templates->end(); ++it) {
00113 ptr<pi_pi2ge_pi_template> pat = pi_pi2ge_pi_template::instance(*it);
00114
00115 if ( find_consistent_instructions(input_op,input_reg,output_op,output_reg,pat,selected_instrs,selected_operands,selected_op_types,0) ) {
00116 log1 << "generate_move - end 1 ( move generated successfuly )\n" << eolog;
00117 return generate_ge_code(input_op,input_reg,output_op,output_reg,pat,selected_instrs,selected_op_types);
00118 }
00119 }
00120
00121 lassert(false);
00122 log1 << "generate_move - end ( no consistent template found )\n" << eolog;
00123 return NULL;
00124
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 ptr<ge_pi_vector__type> move_generator::generate_ge_code(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg, ptr<pi_pi2ge_pi_template_base> pat, ptr<ulint_vector__type> choosed_instrs, ptr<ulint2ulint__type>) {
00140 log1 << "generate_ge_code - start\n" << eolog;
00141
00142 ptr<ge_pi_vector__type> output = ge_pi_vector__type::create();
00143 ptr<ulint2ge_operand__type> tm_op2ge_op = ulint2ge_operand__type::create();
00144
00145 ptr<ge_pi> prev;
00146
00147
00148
00149
00150 for(ulint i=0; i<pat->instruction_groups_get()->size(); ++i) {
00151
00152 ptr<instruction_group_base> instr_group = (*pat->instruction_groups_get())[i];
00153
00154 ptr<tm_instr_base> instr_version = tm_instr::instance((*choosed_instrs)[i]);
00155
00156
00157 ptr<ge_pi> ge = ge_pi::create(instr_version,NULL);
00158
00159 ptr<ge_operand_vector__type> input_ops = ge->operands_input_get();
00160 ptr<ge_operand_vector__type> output_ops = ge->operands_output_get();
00161 ptr<ge_pi_set__type> dependencies = ge->dependencies_get();
00162
00163 if ( prev ) {
00164
00165
00166
00167
00168
00169 dependencies->insert(prev);
00170 }
00171
00172
00173 for(ulint j=0; j<instr_group->input_operand_pids_get()->size(); ++j) {
00174
00175 ulint operand_pid = (*instr_group->input_operand_pids_get())[j];
00176
00177 ulint operand_ref = (*instr_group->input_operand_refs_get())[j];
00178
00179 ptr<tm_instr_op_base> tm_op = (*instr_version->operands_input_get())[j];
00180 lassert(tm_op->id_get()==operand_ref);
00181
00182 ptr<ge_operand> ge_op;
00183
00184 if ( operand_pid <= PIN_4 ) {
00185
00186 ulint i_op_pos = operand_pid - PIN_1;
00187
00188 lassert(i_op_pos==0);
00189
00190 ge_op = input_op;
00191
00192 if ( input_reg ) {
00193 (*ge_op.dncast<ge_operand_reg>()->assigned_registers_get())[ge] = input_reg->id_get();
00194 }
00195 } else {
00196
00197
00198 ulint2ge_operand__type::iterator it_ge = tm_op2ge_op->find(operand_pid);
00199 lassert(it_ge!=tm_op2ge_op->end());
00200 ge_op = it_ge->second;
00201 }
00202
00203
00204 input_ops->push_back(ge_op);
00205 }
00206
00207
00208 for(ulint j=0; j<instr_group->output_operand_pids_get()->size(); ++j) {
00209
00210 ulint operand_pid = (*instr_group->output_operand_pids_get())[j];
00211
00212 ulint operand_ref = (*instr_group->output_operand_refs_get())[j];
00213
00214 ptr<ge_operand> ge_op;
00215
00216 if ( operand_pid <= POUT_4 ) {
00217
00218 ulint i_op_pos = operand_pid - POUT_1;
00219
00220 lassert(i_op_pos==0);
00221
00222
00223 ge_op = output_op;
00224
00225 if ( output_reg ) {
00226 (*ge_op.dncast<ge_operand_reg>()->assigned_registers_get())[ge] = output_reg->id_get();
00227 }
00228 } else {
00229
00230 ptr<tm_instr_op_base> tm_op = (*instr_version->operands_output_get())[j];
00231 lassert(tm_op->id_get()==operand_ref);
00232
00233
00234 ulint type;
00235
00236 if ( tm_op->allowed_types_get()->size()==1 ) {
00237
00238 type = *tm_op->allowed_types_get()->begin();
00239 } else {
00240
00241 lassert(instr_group->input_operand_pids_get()->size()>0);
00242
00243 type = input_op->type_get()->id_get();
00244
00245
00246 lassert(tm_op->allowed_types_get()->find(type)!=tm_op->allowed_types_get()->end());
00247 }
00248
00249
00250 ge_op = tm_op->convert_to_ge(tm_dt_simple::instance((::lestes::md::types::dt_id_type)type));
00251
00252 tm_op2ge_op->insert(::std::pair<ulint, srp<ge_operand> >(operand_pid,ge_op));
00253 }
00254
00255
00256 ge_op->origin_set(ge);
00257
00258
00259 output_ops->push_back(ge_op);
00260 }
00261 prev = ge;
00262 output->push_back(ge);
00263 }
00264
00265 log1 << "generate_ge_code - end\n" << eolog;
00266
00267 return output;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 bool move_generator::find_consistent_instructions(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg, ptr<pi_pi2ge_pi_template_base> pat, ptr<ulint_vector__type> selected_instrs, ptr<ulint2tm_instr_op_base__type> selected_operands, ptr<ulint2ulint__type> selected_op_types, ulint curr_instrs_pat_idx) {
00285 log1 << "find_consisten_instructions - start\n" << eolog;
00286
00287 if ( curr_instrs_pat_idx==pat->instruction_groups_get()->size() ) {
00288
00289 log1 << "find_consisten_instructions - end 1\n" << eolog;
00290 return true;
00291 }
00292
00293
00294 ptr<instruction_group_base> instr_group = (*pat->instruction_groups_get())[curr_instrs_pat_idx];
00295
00296
00297 for(ulint i=0; i<instr_group->instructions_get()->size(); ++i) {
00298 ulint instr_version_id = (*instr_group->instructions_get())[i];
00299 ptr<tm_instr_base> instr_version = tm_instr::instance(instr_version_id);
00300
00301 if ( !is_instruction_consistent(input_op,input_reg,output_op,output_reg,instr_group,instr_version,selected_operands,selected_op_types) ) {
00302
00303 continue;
00304 }
00305
00306
00307 add_selected_operands(input_op,output_op,instr_group,instr_version,selected_operands,selected_op_types);
00308 selected_instrs->push_back(instr_version_id);
00309
00310
00311 if ( find_consistent_instructions(input_op,input_reg,output_op,output_reg,pat,selected_instrs,selected_operands,selected_op_types,curr_instrs_pat_idx+1) ) {
00312
00313 log1 << "find_consisten_instructions - end 2 (good)\n" << eolog;
00314 return true;
00315 }
00316
00317
00318 remove_selected_operands(instr_group,selected_operands,selected_op_types);
00319 selected_instrs->pop_back();
00320 }
00321
00322 log1 << "find_consisten_instructions - end (bad)\n" << eolog;
00323 return false;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 bool move_generator::is_instruction_consistent(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg,ptr<instruction_group_base> instr_group, ptr<tm_instr_base> instr_version, ptr<ulint2tm_instr_op_base__type> selected_operands,ptr<ulint2ulint__type> selected_types) {
00342 log1 << "is_instruction_consistent - start (tm_instr=" << instr_version->id_get() << ")\n" << eolog;
00343
00344
00345
00346
00347 for(ulint i=0; i<instr_group->input_operand_pids_get()->size(); ++i) {
00348 ulint operand_pid = (*instr_group->input_operand_pids_get())[i];
00349 ulint operand_ref = (*instr_group->input_operand_refs_get())[i];
00350
00351 lassert(operand_pid<=PIN_4 || operand_pid>POUT_4 );
00352
00353 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_input_get(),operand_ref);
00354
00355 if ( operand_pid <= PIN_4 ) {
00356
00357 ulint i_op_pos = operand_pid - PIN_1;
00358
00359 lassert(i_op_pos==0);
00360
00361 if ( !is_operand_compatible1(op,input_op,input_op->type_get()->id_get(),input_reg) ) {
00362 log1 << "is_instruction_consistent - end 2 (bad)\n" << eolog;
00363 return false;
00364 }
00365
00366 } else {
00367
00368 ulint2tm_instr_op_base__type::iterator it_op = selected_operands->find(operand_pid);
00369 ulint2ulint__type::iterator it_t = selected_types->find(operand_pid);
00370
00371 lassert(it_op!=selected_operands->end());
00372 lassert(it_t!=selected_types->end());
00373
00374 if ( !is_operand_compatible2(op,it_op->second,it_t->second) ) {
00375 log1 << "is_instruction_consistent - end 3 (bad)\n" << eolog;
00376 return false;
00377 }
00378 }
00379 }
00380
00381
00382
00383
00384 for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00385 ulint operand_ref = (*instr_group->output_operand_refs_get())[i];
00386 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00387
00388 lassert(operand_pid > PIN_4);
00389
00390 if ( operand_pid>=POUT_1 && operand_pid <= POUT_4 ) {
00391 ulint i_op_pos = operand_pid - POUT_1;
00392 lassert(i_op_pos==0);
00393
00394 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_output_get(),operand_ref);
00395
00396 if ( !is_operand_compatible1(op,output_op,output_op->type_get()->id_get(),output_reg) ) {
00397 log1 << "is_instruction_consistent - end 4 (bad)\n" << eolog;
00398 return false;
00399 }
00400
00401 }
00402 }
00403
00404 log1 << "is_instruction_consistent - end\n" << eolog;
00405 return true;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 bool move_generator::is_operand_compatible1(ptr<tm_instr_op_base> instr_op, ptr<ge_operand> ge_op, ulint type, ptr<tm_register_base> reg) {
00417 log1 << "is_operand_compatible1 - start (instr_op=" << instr_op->id_get() << ")\n" << eolog;
00418
00419 if ( instr_op->allowed_types_get()->find(type)==instr_op->allowed_types_get()->end() ) {
00420 log1 << "is_operand_compatible1 - end1 (bad)\n" << eolog;
00421 return false;
00422 }
00423
00424 ulint kind1 = instr_op->kind_get();
00425 ulint kind2 = ge_op->kind_get();
00426
00427 if ( kind1==tm_instr_op_base::REGISTER ) {
00428 if ( kind2!=ge_operand::REGISTER ) {
00429 return false;
00430 }
00431
00432 lassert(reg);
00433
00434 ptr<tm_instr_op_reg_base> tmp_op = instr_op.dncast<tm_instr_op_reg_base>();
00435
00436 return tmp_op->allowed_registers_get()->find(reg->id_get())!=tmp_op->allowed_registers_get()->end();
00437 }
00438
00439
00440 if ( ( kind1==tm_instr_op_base::IMMEDIATE && kind2!=ge_operand::IMMEDIATE ) ||
00441 ( kind1==tm_instr_op_base::MEMORY && kind2!=ge_operand::MEMORY ) ) {
00442 log1 << "is_operand_compatible1 - end2 (bad)\n" << eolog;
00443 return false;
00444 }
00445
00446 log1 << "is_operand_compatible1 - end\n" << eolog;
00447 return true;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 bool move_generator::is_operand_compatible2(ptr<tm_instr_op_base> op1, ptr<tm_instr_op_base> op2, ulint type) {
00459 log1 << "is_operand_compatible2 - start (instr_op=" << op1->id_get() << ")\n" << eolog;
00460
00461 if ( op1->allowed_types_get()->find(type)==op1->allowed_types_get()->end() ) {
00462 log1 << "is_operand_compatible2 - end 1 (bad)\n" << eolog;
00463 return false;
00464 }
00465
00466 if ( op1->kind_get()!=op2->kind_get() ) {
00467 log1 << "is_operand_compatible2 - end 2 (bad)\n" << eolog;
00468 return false;
00469 }
00470
00471 if ( op1->kind_get()==tm_instr_op_base::REGISTER ) {
00472 ptr<id_set__type> allowed_regs1 = op1.dncast<tm_instr_op_reg_base>()->allowed_registers_get();
00473 ptr<id_set__type> allowed_regs2 = op2.dncast<tm_instr_op_reg_base>()->allowed_registers_get();
00474 ptr<id_set__type> allowed_intersec = id_set__type::create();
00475
00476 ::std::set_intersection(
00477 allowed_regs1->begin(),
00478 allowed_regs1->end(),
00479 allowed_regs2->begin(),
00480 allowed_regs2->end(),
00481 ::std::inserter(*allowed_intersec, allowed_intersec->begin()));
00482
00483
00484 if ( allowed_intersec->size()!=0 ) {
00485 log1 << "is_operand_compatible2 - end 3 (good)\n" << eolog;
00486 return true;
00487 }
00488 }
00489
00490 log1 << "is_operand_compatible2 - end (bad)\n" << eolog;
00491 return false;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 void move_generator::add_selected_operands(ptr<ge_operand> input_op,ptr<ge_operand>, ptr<instruction_group_base> instr_group, ptr<tm_instr_base> instr_version, ptr<ulint2tm_instr_op_base__type> selected_operands,ptr<ulint2ulint__type> selected_types) {
00504
00505
00506 for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00507 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00508 ulint operand_ref = (*instr_group->output_operand_refs_get())[i];
00509
00510 lassert(operand_pid > PIN_4);
00511
00512 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_output_get(),operand_ref);
00513 selected_operands->insert(::std::pair<ulint, srp<tm_instr_op_base> >(operand_pid, op));
00514
00515 ulint type;
00516
00517 type = input_op->type_get()->id_get();
00518
00519 selected_types->insert(::std::pair<ulint, ulint>(operand_pid, type));
00520 }
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530 void move_generator::remove_selected_operands(ptr<instruction_group_base> instr_group, ptr<ulint2tm_instr_op_base__type> selected_operands, ptr<ulint2ulint__type> selected_types) {
00531
00532 for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00533 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00534 selected_operands->erase(operand_pid);
00535 selected_types->erase(operand_pid);
00536 }
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546 ptr<tm_instr_op_base> move_generator::find_op_by_id(ptr<tm_instr_op_base_vector__type> list, ulint id) {
00547 for(uint i=0; i<list->size(); ++i) {
00548 ptr<tm_instr_op_base> op = (*list)[i];
00549
00550 if ( op->id_get()==id ) {
00551 return op;
00552 }
00553 }
00554
00555 return NULL;
00556 }
00557
00558
00559 end_package(registers);
00560 end_package(md);
00561 end_package(lestes);
00562