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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include "defs.h"
00061 #include "tracing.h"
00062 #include "mempool.h"
00063 #include "cgir.h"
00064 #include "tn_map.h"
00065 #include "tn_set.h"
00066 #include "cg_spill.h"
00067 #include "localize.h"
00068 #include "register.h"
00069 #include "bb_set.h"
00070 #include "calls.h"
00071 #include "cgexp.h"
00072 #include "cg_region.h"
00073 #include "cg_internal.h"
00074 #include "targ_sim.h"
00075 #include "whirl2ops.h"
00076
00077 #if defined(TARG_SL)
00078 #include <queue>
00079 #include <set>
00080 #endif
00081
00082 static BOOL Trace_Localize = FALSE;
00083
00084 #define Trace_Replace(msg1,old_tn,msg2,new_tn,bb) \
00085 if ( Trace_Localize) { \
00086 fprintf( TFile, "<loc> replace %s ", msg1); \
00087 Print_TN( old_tn, FALSE ); \
00088 fprintf( TFile, " with %s ", msg2); \
00089 Print_TN( new_tn, FALSE ); \
00090 fprintf(TFile, " in bb %d\n", BB_id(bb)); \
00091 }
00092
00093
00094 static BOOL
00095 BB_Is_Followed_By_Call (BB *current_bb)
00096 {
00097 for (BB *bb = current_bb; bb != NULL; bb = BB_next(bb)) {
00098 if (BB_call(bb))
00099 return TRUE;
00100 if (BB_exit(bb))
00101 return FALSE;
00102 }
00103 return FALSE;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 static void
00117 Localize_Global_Param_Reg (BB *current_bb, TN *parm_tn)
00118 {
00119 BB *bb;
00120 OP *op;
00121 OPS ops = OPS_EMPTY;
00122 INT opndnum;
00123 INT resnum;
00124 BOOL reached_defs = FALSE;
00125 TN *new_tn = Dup_TN_Even_If_Dedicated(parm_tn);
00126 Set_TN_is_global_reg(new_tn);
00127 Trace_Replace("param",parm_tn, "new",new_tn, current_bb);
00128
00129
00130
00131 bb = current_bb;
00132 do {
00133 Set_BB_has_globals(bb);
00134 FOR_ALL_BB_OPs_FWD (bb, op) {
00135 for (resnum = 0; resnum < OP_results(op); resnum++) {
00136 if (OP_result(op, resnum) == parm_tn) {
00137 Set_OP_result(op, resnum, new_tn);
00138 reached_defs = TRUE;
00139 }
00140 }
00141 if (!reached_defs) continue;
00142 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
00143 if (OP_opnd(op, opndnum) == parm_tn) {
00144
00145 Set_OP_opnd(op, opndnum, new_tn);
00146 }
00147 }
00148 }
00149 bb = BB_next(bb);
00150 } while (bb != NULL && !BB_call(BB_prev(bb)));
00151
00152 FmtAssert(bb != NULL && BB_call(BB_prev(bb)),
00153 ("didn't find call BB after bb %d for tn %d",
00154 BB_id(current_bb), TN_number(parm_tn)));
00155 bb = BB_prev(bb);
00156
00157
00158 Exp_COPY (parm_tn, new_tn, &ops);
00159 BB_Insert_Ops_Before (bb, BB_last_op(bb), &ops);
00160 }
00161
00162
00163
00164
00165
00166
00167 static void
00168 Localize_Global_Return_Reg_Def (BB *current_bb, TN *ret_tn)
00169 {
00170 BB *bb;
00171 OP *op;
00172 OPS ops = OPS_EMPTY;
00173 INT opndnum;
00174 INT resnum;
00175 BOOL reached_defs = FALSE;
00176 TN *new_tn = Dup_TN_Even_If_Dedicated(ret_tn);
00177 Set_TN_is_global_reg(new_tn);
00178 Trace_Replace("return",ret_tn, "new",new_tn, current_bb);
00179
00180
00181 for (bb = current_bb; bb != NULL && !BB_exit(bb); bb = BB_next(bb)) {
00182 Set_BB_has_globals(bb);
00183 FOR_ALL_BB_OPs_FWD (bb, op) {
00184 for (resnum = 0; resnum < OP_results(op); resnum++) {
00185 if (OP_result(op, resnum) == ret_tn) {
00186 Set_OP_result(op, resnum, new_tn);
00187 reached_defs = TRUE;
00188 }
00189 }
00190 if (!reached_defs) continue;
00191 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
00192 if (OP_opnd(op, opndnum) == ret_tn) {
00193
00194 Set_OP_opnd(op, opndnum, new_tn);
00195 }
00196 }
00197 }
00198 }
00199 FmtAssert(bb != NULL && BB_exit(bb), ("didn't find exit BB after bb %d for tn %d", BB_id(current_bb), TN_number(ret_tn)));
00200
00201
00202 Exp_COPY (ret_tn, new_tn, &ops);
00203 BB_Prepend_Ops (bb, &ops);
00204 }
00205
00206
00207
00208
00209
00210
00211 static void
00212 Localize_Global_Return_Reg (BB *current_bb, TN *ret_tn)
00213 {
00214 BB *bb;
00215 OP *op;
00216 OPS ops = OPS_EMPTY;
00217 INT opndnum;
00218 INT resnum;
00219 BOOL reached_use = FALSE;
00220 TN *new_tn = Dup_TN_Even_If_Dedicated(ret_tn);
00221 Set_TN_is_global_reg(new_tn);
00222 Trace_Replace ("return", ret_tn, "new", new_tn, current_bb);
00223
00224
00225 for (bb = current_bb; bb != NULL && !BB_call(bb); bb = BB_prev(bb)) {
00226 Set_BB_has_globals(bb);
00227 FOR_ALL_BB_OPs_REV (bb, op) {
00228 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
00229 if (OP_opnd(op, opndnum) == ret_tn) {
00230
00231 Set_OP_opnd(op, opndnum, new_tn);
00232 reached_use = TRUE;
00233 }
00234 }
00235 if (!reached_use) continue;
00236 for (resnum = 0; resnum < OP_results(op); resnum++) {
00237 if (OP_result(op, resnum) == ret_tn) {
00238 Set_OP_result(op, resnum, new_tn);
00239 }
00240 }
00241 }
00242 }
00243 #if defined(TARG_SL)
00244 if (bb == NULL) return;
00245 #endif
00246 FmtAssert(bb != NULL && BB_call(bb), ("didn't find call BB before bb %d for tn %d", BB_id(current_bb), TN_number(ret_tn)));
00247 bb = BB_next(bb);
00248
00249 Exp_COPY (new_tn, ret_tn, &ops);
00250 BB_Prepend_Ops (bb, &ops);
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 extern void
00264 Check_If_Dedicated_TN_Is_Global (TN *tn, BB *current_bb, BOOL def)
00265 {
00266 INT regnum = REGISTER_machine_id(TN_register_class(tn), TN_register(tn))
00267 #ifdef TARG_X8664
00268 + Int_Preg_Min_Offset
00269 #endif
00270 ;
00271 BOOL is_func_arg;
00272 BOOL is_func_retval;
00273
00274 Is_True(TN_is_dedicated(tn), ("tn not dedicated"));
00275
00276
00277 if (def) {
00278 BB *bb = BB_Unique_Successor(current_bb);
00279 if (bb && BB_rid(bb) && (RID_level(BB_rid(bb)) >= RL_CGSCHED)) {
00280
00281 return;
00282 }
00283 }
00284 else {
00285 BB *bb = BB_Unique_Predecessor(current_bb);
00286 if (bb && BB_rid(bb) && (RID_level(BB_rid(bb)) >= RL_CGSCHED)) {
00287
00288 return;
00289 }
00290 }
00291
00292
00293 is_func_arg = REGISTER_SET_MemberP(
00294 REGISTER_CLASS_function_argument(TN_register_class(tn)),
00295 TN_register(tn));
00296 is_func_retval = REGISTER_SET_MemberP(
00297 REGISTER_CLASS_function_value(TN_register_class(tn)),
00298 TN_register(tn));
00299
00300
00301
00302
00303
00304
00305 if ((PU_uplevel(Get_Current_PU()) ||
00306 PU_is_nested_func(Get_Current_PU()) )
00307 && regnum==Static_Link_Preg_Offset
00308 && def)
00309 {
00310
00311 if (!BB_call(current_bb) && !BB_exit(current_bb)) {
00312 Localize_Global_Param_Reg (current_bb, tn);
00313 }
00314 }
00315 else if (regnum==Static_Link_Preg_Offset
00316 && PU_is_nested_func(Get_Current_PU())
00317 && !def
00318 && BB_entry(current_bb) )
00319 {
00320
00321 }
00322 #ifdef TARG_X8664
00323 else if (regnum==RAX && def && BB_call(current_bb)) {
00324
00325 }
00326 #endif
00327 else if (is_func_arg || is_func_retval) {
00328 if (def && is_func_arg && BB_call(current_bb))
00329 ;
00330 else if (def && is_func_retval && BB_exit(current_bb))
00331 ;
00332 #if defined(TARG_IA32)
00333 else if (def && is_func_retval && BB_asm(current_bb))
00334 ;
00335 #endif // TARG_IA32
00336 #if defined(TARG_X8664) || defined(TARG_SL)
00337
00338 else if (BB_asm(current_bb))
00339 ;
00340
00341 else if (!def && is_func_arg
00342 && BB_prev(current_bb) != NULL
00343 && BB_asm(BB_prev(current_bb)))
00344 ;
00345 #endif // TARG_X8664 || TARG_SL
00346 else if (def && is_func_arg && BB_asm(current_bb))
00347 ;
00348 else if (def && is_func_retval && BB_call(current_bb)
00349 && RETURN_INFO_return_via_first_arg(Get_Return_Info(
00350 TY_ret_type(ST_pu_type(CALLINFO_call_st(
00351 ANNOT_callinfo(ANNOT_Get(
00352 BB_annotations(current_bb),ANNOT_CALLINFO)) ))),
00353 No_Simulated
00354 #ifdef TARG_X8664
00355 , PU_ff2c_abi(Pu_Table[ST_pu(CALLINFO_call_st(
00356 ANNOT_callinfo(ANNOT_Get(
00357 BB_annotations(current_bb),ANNOT_CALLINFO)) ))])
00358 #endif
00359 ) ) )
00360
00361 ;
00362 else if (!def && is_func_retval && BB_entry(current_bb)
00363 && RETURN_INFO_return_via_first_arg(Get_Return_Info(
00364 TY_ret_type(PU_prototype(Get_Current_PU())),
00365 No_Simulated
00366 #ifdef TARG_X8664
00367 , PU_ff2c_abi(Get_Current_PU())
00368 #endif
00369 ) ) )
00370
00371 ;
00372
00373
00374
00375
00376
00377
00378 else if (def && is_func_arg && is_func_retval
00379 && !BB_call(current_bb) && !BB_exit(current_bb))
00380 {
00381 if (BB_Is_Followed_By_Call (current_bb))
00382 Localize_Global_Param_Reg (current_bb, tn);
00383 else
00384 Localize_Global_Return_Reg_Def (current_bb, tn);
00385 }
00386 else if (def && is_func_arg && !BB_call(current_bb)) {
00387 Localize_Global_Param_Reg (current_bb, tn);
00388 }
00389 else if (def && is_func_retval && !BB_exit(current_bb)) {
00390 Localize_Global_Return_Reg_Def (current_bb, tn);
00391 }
00392 else if (!def && is_func_arg && BB_entry(current_bb))
00393 ;
00394 #ifdef KEY
00395 else if (!def && is_func_arg && BB_call(current_bb))
00396 ;
00397
00398
00399 #endif
00400 #ifdef TARG_X8664
00401 else if (!def && regnum == RAX && BB_entry(current_bb))
00402 ;
00403 else if (!def && regnum == RDX &&
00404 BB_entry(current_bb) && BB_handler(current_bb))
00405 ;
00406 #endif
00407 else if (!def && is_func_retval
00408 && BB_prev(current_bb) != NULL
00409 && BB_call(BB_prev(current_bb)))
00410 ;
00411 else if (!def && is_func_retval
00412 && BB_prev(current_bb) != NULL
00413 && BB_asm(BB_prev(current_bb)))
00414 ;
00415 #if defined(TARG_SL)
00416 else if (is_func_retval && BB_entry(current_bb) && BB_exit(current_bb))
00417 ;
00418 else if (is_func_retval && BB_exit(current_bb) && !def) {
00419 ;
00420 }
00421 #endif
00422 else if (!def && is_func_retval
00423 && (BB_prev(current_bb) == NULL
00424 || ! BB_call(BB_prev(current_bb))))
00425 {
00426
00427 Localize_Global_Return_Reg (current_bb, tn);
00428 }
00429 else {
00430 FmtAssert (FALSE, ("use of param reg TN%d in bb %d is global", TN_number(tn), BB_id(current_bb)));
00431 }
00432 }
00433 #ifdef HAS_STACKED_REGISTERS
00434
00435
00436
00437 if (REGISTER_Is_Stacked_Output(
00438 TN_register_class(tn),
00439 TN_register(tn) ))
00440 {
00441 if (def && BB_call(current_bb))
00442 ;
00443 else if (def && BB_asm(current_bb))
00444 ;
00445 else if (def && !BB_call(current_bb)) {
00446 Localize_Global_Param_Reg (current_bb, tn);
00447 }
00448 else {
00449 FmtAssert (FALSE, ("use of stacked param reg TN%d in bb %d is global", TN_number(tn), BB_id(current_bb)));
00450 }
00451 }
00452 #endif
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462 static void
00463 Check_If_TN_Is_Global (TN *tn, TN_MAP tn_in_bb, BB *current_bb, BOOL def)
00464 {
00465 BB *mapped_bb;
00466 PREG_NUM preg;
00467 RID *rid = BB_rid(current_bb);
00468
00469 Is_True(!TN_is_dedicated(tn), ("tn is dedicated"));
00470
00471 #if defined(TARG_SL)
00472
00473 if (TN_size(tn) == 8) {
00474 DevWarn("setting TN %d from 8 to 4", TN_number(tn));
00475 Set_TN_size(tn, 4);
00476 }
00477 #endif
00478
00479 mapped_bb = (BB*) TN_MAP_Get (tn_in_bb, tn);
00480
00481 if (rid && (RID_bounds_exist(rid) == REGION_BOUND_EXISTS)
00482 && (preg = (PREG_NUM)(INTPTR) TN_MAP_Get(TN_To_PREG_Map, tn)))
00483 {
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 Set_TN_is_global_reg(tn);
00496 if (Trace_Localize) {
00497 fPrint_TN (TFile, "%s is a global tn,", tn);
00498 fprintf (TFile, "(%d) corresponding to preg %d\n", TN_size(tn), preg);
00499 }
00500 if (def) {
00501 for (INT i=0; i<RID_num_exits(rid); i++)
00502 REGION_add_preg_out(rid, i, preg, MTYPE_V);
00503 } else {
00504 REGION_add_preg_in(rid, preg, MTYPE_V);
00505 }
00506 }
00507
00508 if (TN_is_global_reg(tn)) {
00509 Set_BB_has_globals(current_bb);
00510 } else {
00511 if (mapped_bb == NULL) {
00512 TN_MAP_Set (tn_in_bb, tn, current_bb);
00513 } else if (mapped_bb != current_bb) {
00514
00515 Set_TN_is_global_reg(tn);
00516 Set_BB_has_globals(current_bb);
00517 Set_BB_has_globals(mapped_bb);
00518 if (Trace_Localize) {
00519 fPrint_TN (TFile, "%s is a global tn\n", tn);
00520 }
00521 }
00522 }
00523 }
00524
00525
00526
00527
00528 static void
00529 TN_LIST_Mark_Is_Global( TN_LIST *tnl0 )
00530 {
00531 TN_LIST *tnl;
00532 TN *tn;
00533
00534 for ( tnl = tnl0; tnl; tnl = TN_LIST_rest( tnl ) ) {
00535 tn = TN_LIST_first( tnl );
00536 Set_TN_is_global_reg( tn );
00537 }
00538 }
00539
00540 extern void dump_tn(TN*);
00541
00542
00543
00544
00545
00546 static void
00547 Find_Global_TNs ( RID *rid )
00548 {
00549 BB *bb;
00550 OP *op;
00551 TN *tn;
00552 TN_MAP tn_in_bb = TN_MAP_Create();
00553 INT opndnum;
00554 INT resnum;
00555 RID *bbrid;
00556 CGRIN *cgrin;
00557 TN_LIST *tnl;
00558 INT num_exits, i;
00559
00560 if ( rid ) {
00561
00562
00563
00564
00565
00566
00567 cgrin = RID_cginfo( rid );
00568 tnl = CGRIN_tns_in( cgrin );
00569 TN_LIST_Mark_Is_Global( tnl );
00570 num_exits = RID_num_exits( rid );
00571 for ( i = 0; i < num_exits; i++ ) {
00572 tnl = CGRIN_tns_out_i( cgrin, i );
00573 TN_LIST_Mark_Is_Global( tnl );
00574 }
00575 }
00576
00577 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
00578 if ((bbrid = BB_rid(bb)) && (RID_level(bbrid) >= RL_CGSCHED))
00579
00580
00581
00582
00583 continue;
00584 FOR_ALL_BB_OPs (bb, op) {
00585
00586 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
00587 tn = OP_opnd(op, opndnum);
00588 if (tn == NULL || TN_is_constant(tn)) continue;
00589 if (TN_is_dedicated(tn)) {
00590 if (OP_same_res(op) && tn == OP_result(op,0)) {
00591
00592 continue;
00593 }
00594 #ifdef KEY
00595
00596
00597
00598
00599 if( OP_same_res(op) && OP_Defs_TN(op,tn) ){
00600 continue;
00601 }
00602 #endif
00603 if (OP_copy(op) && tn == OP_result(op,0)) {
00604
00605 continue;
00606 }
00607 Check_If_Dedicated_TN_Is_Global (tn, bb, FALSE );
00608 } else {
00609 Check_If_TN_Is_Global (tn, tn_in_bb, bb, FALSE );
00610 }
00611 }
00612
00613 for (resnum = 0; resnum < OP_results(op); resnum++) {
00614 tn = OP_result(op, resnum);
00615 if (TN_is_dedicated(tn)) {
00616 Check_If_Dedicated_TN_Is_Global (tn, bb, TRUE );
00617 } else {
00618 if (OP_cond_def(op)) {
00619
00620 Check_If_TN_Is_Global (tn, tn_in_bb, bb, FALSE );
00621 }
00622 Check_If_TN_Is_Global (tn, tn_in_bb, bb, TRUE );
00623 }
00624 }
00625 }
00626 }
00627 TN_MAP_Delete (tn_in_bb);
00628 }
00629
00630
00631
00632 typedef struct spill_tn_info {
00633 TN *local_tn;
00634
00635
00636 OP *last_def;
00637 OP *exposed_use;
00638 TN *exposed_use_tn;
00639 struct spill_tn_info *next;
00640 BOOL callee_save;
00641 } SPILL_TN_INFO;
00642 static SPILL_TN_INFO *first_spill_tninfo = NULL;
00643 static SPILL_TN_INFO *last_spill_tninfo = NULL;
00644
00645 static INT num_stacked_regs = 0;
00646
00647
00648
00649
00650
00651
00652 static SPILL_TN_INFO *
00653 Get_Local_TN_For_Global (TN *global_tn, TN_MAP spill_tns, BB *bb, BOOL reuse)
00654 {
00655 SPILL_TN_INFO *tninfo;
00656 TN *local_tn = NULL;
00657 tninfo = (SPILL_TN_INFO*) TN_MAP_Get (spill_tns, global_tn);
00658 if (tninfo == NULL) {
00659 tninfo = TYPE_MEM_POOL_ALLOC (SPILL_TN_INFO, &MEM_local_pool);
00660 TN_MAP_Set (spill_tns, global_tn, tninfo);
00661 if (first_spill_tninfo == NULL) {
00662 first_spill_tninfo = tninfo;
00663 } else {
00664 last_spill_tninfo->next = tninfo;
00665 }
00666 last_spill_tninfo = tninfo;
00667 }
00668 if (reuse)
00669 local_tn = tninfo->local_tn;
00670 if (local_tn == NULL) {
00671 PREG_NUM preg;
00672
00673 if (TN_is_gra_homeable(global_tn)) {
00674 Reset_TN_is_gra_homeable(global_tn);
00675 Set_TN_home(global_tn, NULL);
00676 }
00677
00678 #ifdef HAS_STACKED_REGISTERS
00679
00680
00681
00682
00683 if (LOCALIZE_using_stacked_regs &&
00684 REGISTER_Has_Stacked_Registers(
00685 TN_register_class(global_tn)) )
00686 {
00687
00688
00689
00690
00691
00692 if (TN_register(global_tn) == REGISTER_UNDEFINED) {
00693
00694 if ((num_stacked_regs + 8) <
00695 REGISTER_Number_Stacked_Registers_Available(
00696 TN_register_class(global_tn)))
00697 {
00698 REGISTER reg =
00699 REGISTER_Request_Stacked_Register(
00700 ABI_PROPERTY_callee,
00701 TN_register_class(global_tn) );
00702 if (reg == REGISTER_UNDEFINED) {
00703 DevWarn("localize ran out of stacked regs");
00704 tninfo->callee_save = FALSE;
00705 }
00706 else {
00707 Set_TN_register(global_tn, reg);
00708 ++num_stacked_regs;
00709 tninfo->callee_save = TRUE;
00710 }
00711 }
00712 else {
00713 if (Trace_Localize) fprintf(TFile,
00714 "localize stopped using stacked regs");
00715 tninfo->callee_save = FALSE;
00716 }
00717 }
00718 else {
00719 tninfo->callee_save = TRUE;
00720 }
00721 local_tn = global_tn;
00722 }
00723 #endif
00724 if (tninfo->callee_save == FALSE) {
00725 local_tn = Dup_TN (global_tn);
00726
00727
00728
00729 Set_TN_spill(local_tn, CGSPILL_Get_TN_Spill_Location (
00730 global_tn, CGSPILL_LCL));
00731 tninfo->callee_save = FALSE;
00732 preg = (PREG_NUM)(INTPTR) TN_MAP_Get( TN_To_PREG_Map, global_tn );
00733 #ifdef KEY
00734 Is_True(preg >= 0, ("Get_Local_TN_For_Global: "
00735 "negative index to PREG_To_TN_Array"));
00736 #endif
00737 if (preg) PREG_To_TN_Array[preg] = local_tn;
00738 }
00739 tninfo->local_tn = local_tn;
00740 Trace_Replace ("global",global_tn, "local",local_tn, bb);
00741 }
00742 return tninfo;
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 static void
00756 Insert_Spills_Of_Globals (void)
00757 {
00758 BB *bb;
00759 OP *op;
00760 TN *tn;
00761 TN_MAP spill_tns;
00762 SPILL_TN_INFO *tninfo;
00763 INT opndnum;
00764 INT resnum;
00765 ST *spill_loc;
00766 OPS spill_ops;
00767 RID *bbrid;
00768 num_stacked_regs = 0;
00769
00770 MEM_POOL_Push(&MEM_local_pool);
00771
00772 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
00773 if ((bbrid = BB_rid(bb)) && (RID_level(bbrid) >= RL_CGSCHED))
00774
00775
00776
00777 continue;
00778 if ( ! BB_has_globals(bb)) continue;
00779
00780
00781 spill_tns = TN_MAP_Create();
00782 first_spill_tninfo = last_spill_tninfo = NULL;
00783
00784 FOR_ALL_BB_OPs_FWD (bb, op) {
00785
00786 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
00787 tn = OP_opnd(op, opndnum);
00788 if (tn != NULL && TN_is_global_reg(tn)
00789 #ifdef KEY
00790 && !TN_is_dedicated(tn)
00791 #endif
00792 #ifdef TARG_X8664
00793
00794 && (CG_localize_tns || TN_is_float(tn))
00795 #endif
00796 ) {
00797 tninfo = Get_Local_TN_For_Global (tn, spill_tns, bb, TRUE);
00798
00799 Set_OP_opnd(op, opndnum, tninfo->local_tn);
00800
00801
00802 if (OP_code(op) == TOP_begin_pregtn) continue;
00803 if (OP_code(op) == TOP_end_pregtn) continue;
00804
00805
00806 if (tninfo->exposed_use == NULL && tninfo->last_def == NULL) {
00807 tninfo->exposed_use = op;
00808 tninfo->exposed_use_tn = tninfo->local_tn;
00809 }
00810 }
00811 }
00812 for (resnum = 0; resnum < OP_results(op); resnum++) {
00813 tn = OP_result(op, resnum);
00814 if (TN_is_global_reg(tn)
00815 #ifdef KEY
00816 && !TN_is_dedicated(tn)
00817 #endif
00818 #ifdef TARG_X8664
00819
00820 && (CG_localize_tns || TN_is_float(tn))
00821 #endif
00822 ) {
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833 tninfo = Get_Local_TN_For_Global (tn, spill_tns, bb,
00834 OP_same_res(op) || OP_cond_def(op) );
00835
00836 Set_OP_result(op, resnum, tninfo->local_tn);
00837
00838
00839 if (OP_cond_def(op) &&
00840 tninfo->exposed_use == NULL &&
00841 tninfo->last_def == NULL) {
00842 tninfo->exposed_use = op;
00843 tninfo->exposed_use_tn = tninfo->local_tn;
00844 }
00845
00846
00847 tninfo->last_def = op;
00848 }
00849 }
00850 }
00851
00852
00853
00854
00855
00856
00857 for (tninfo = first_spill_tninfo; tninfo != NULL; tninfo = tninfo->next)
00858 {
00859 if (tninfo->callee_save) continue;
00860 if (tninfo->last_def != NULL) {
00861
00862 spill_loc = CGSPILL_Get_TN_Spill_Location (tninfo->local_tn, CGSPILL_LCL);
00863 OPS_Init(&spill_ops);
00864 CGSPILL_Store_To_Memory (tninfo->local_tn, spill_loc,
00865 &spill_ops, CGSPILL_LCL, bb);
00866 CGSPILL_Insert_Ops_After (bb, tninfo->last_def, &spill_ops);
00867 }
00868 if (tninfo->exposed_use != NULL) {
00869
00870 spill_loc = CGSPILL_Get_TN_Spill_Location (tninfo->exposed_use_tn, CGSPILL_LCL);
00871 OPS_Init(&spill_ops);
00872 CGSPILL_Load_From_Memory (tninfo->exposed_use_tn, spill_loc,
00873 &spill_ops, CGSPILL_LCL, bb);
00874 CGSPILL_Insert_Ops_Before (bb, tninfo->exposed_use, &spill_ops);
00875 }
00876 }
00877
00878
00879 TN_MAP_Delete (spill_tns);
00880 }
00881 MEM_POOL_Pop(&MEM_local_pool);
00882
00883 if (Trace_Localize && num_stacked_regs)
00884 fprintf(TFile, "num_stacked_regs = %d\n", num_stacked_regs);
00885 }
00886
00887
00888
00889
00890
00891 extern void
00892 Localize_Any_Global_TNs ( RID *rid )
00893 {
00894 Trace_Localize = Get_Trace (TP_LOCALIZE, 1);
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 if (NULL != RA_TN && PU_BB_Count > 1) {
00906 Set_TN_is_global_reg(SAVE_tn(Return_Address_Reg));
00907 }
00908
00909 Find_Global_TNs( rid );
00910
00911 Insert_Spills_Of_Globals();
00912
00913 }
00914
00915
00916
00917
00918
00919 #define BB_SEARCH_LIMIT 1000 // some ridiculously high number
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 static BB *
00931 BB_Reaches_Call_or_Exit( BB *start )
00932 {
00933 BB *bb, *ans;
00934 RID *rid;
00935 BB_MAP visited = BB_MAP32_Create();
00936
00937 ans = NULL;
00938 BB_MAP32_Set( visited, start, 1 );
00939
00940 for ( bb=start; bb; bb=BB_Unique_Successor_Not_In_Set(bb, visited) ) {
00941 rid = BB_rid(bb);
00942 if (rid && RID_level(rid) >= RL_CGSCHED)
00943 break;
00944 if (BB_call(bb) || BB_exit(bb) || BB_asm(bb)) {
00945 ans = bb;
00946 break;
00947 }
00948 BB_MAP32_Set( visited, bb, 1 );
00949 }
00950
00951 BB_MAP_Delete( visited );
00952 return ans;
00953 }
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967 static BB *
00968 Call_or_Entry_Reaches_BB(BB *start)
00969 {
00970 BB *bb;
00971 RID *rid;
00972
00973
00974
00975
00976
00977 INT count = 0;
00978
00979 if (BB_entry( start))
00980 return start;
00981 for (bb = BB_Unique_Predecessor(start); bb; bb = BB_Unique_Predecessor(bb)) {
00982 ++count;
00983 if (count > BB_SEARCH_LIMIT) {
00984 DevWarn("Call_or_Entry_Reaches_BB looped too long so give up");
00985 return NULL;
00986 }
00987 rid = BB_rid(bb);
00988 if (rid && RID_level(rid) >= RL_CGSCHED)
00989 return NULL;
00990 if (BB_call(bb) || BB_entry(bb) || BB_asm(bb)) {
00991
00992 if (BB_call(bb) || BB_asm(bb))
00993 bb = BB_next(bb);
00994 return bb;
00995 }
00996 }
00997
00998 #if defined(TARG_SL)
00999
01000
01001
01002
01003
01004 std::queue<BB*> to_visit;
01005 std::set<BB*> visited_bb;
01006 to_visit.push(start);
01007 int cnt = 0;
01008
01009
01010 while ((!to_visit.empty()) && (cnt++ < BB_SEARCH_LIMIT)) {
01011 bb = to_visit.front();
01012 visited_bb.insert(bb);
01013 to_visit.pop();
01014 if (BB_entry(bb)) return bb;
01015
01016 BBLIST* nxt;
01017 BBLIST* prevs;
01018
01019
01020 for (prevs = BB_preds(bb); prevs; prevs = nxt) {
01021 BB* bb_prev = BBLIST_item(prevs);
01022 nxt = BBLIST_next(prevs);
01023
01024 if (visited_bb.count(bb_prev) == 0)
01025 to_visit.push(bb_prev);
01026 }
01027 }
01028 #endif
01029 return NULL;
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042 static RID *
01043 BB_Successor_Compiled_Region( BB *start )
01044 {
01045 BB *bb;
01046 RID *rid;
01047
01048 for ( bb = BB_Unique_Successor( start ); bb; bb = BB_Unique_Successor(bb) ) {
01049 rid = BB_rid( bb );
01050 if ( rid == NULL )
01051 continue;
01052 if ( RID_level( rid ) >= RL_CGSCHED )
01053 return rid;
01054 }
01055 return NULL;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070 static RID *
01071 BB_Predecessor_Compiled_Region( INT *exit_num, BB *start )
01072 {
01073
01074 INT count = 0;
01075 for (BB *bb=BB_Unique_Predecessor(start); bb; bb=BB_Unique_Predecessor(bb)) {
01076 ++count;
01077 if (count > BB_SEARCH_LIMIT) {
01078 DevWarn("BB_Predecessor_Compiled_Region looped too long so give up");
01079 return NULL;
01080 }
01081 RID *rid = BB_rid(bb);
01082 if (rid == NULL)
01083 continue;
01084 if (RID_level( rid ) >= RL_CGSCHED) {
01085 *exit_num = BB_REGION_Exit( bb, rid),
01086 FmtAssert(*exit_num != NO_REGION_EXIT,
01087 ("predecessor %d of %d in already compiled REGION %d is "
01088 "not an exit", BB_id(bb), BB_id(start), RID_id(rid)));
01089 return rid;
01090 }
01091 }
01092 return NULL;
01093 }
01094
01095 #ifdef TARG_SL
01096
01097 static BOOL
01098 TN_Def_Local(BB * bb, OP * end_op, TN * ded_tn)
01099 {
01100 OP * op = NULL;
01101 TN * tn = NULL;
01102 FOR_ALL_BB_OPs (bb, op) {
01103 if (op == end_op) {
01104 break;
01105 }
01106 for (INT i = 0; i < OP_results(op); i++) {
01107 tn = OP_result(op,i);
01108 if (tn == ded_tn)
01109 return TRUE;
01110 }
01111 }
01112
01113 return FALSE;
01114 }
01115 #endif
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 void
01141 Localize_or_Replace_Dedicated_TNs(void)
01142 {
01143 BB *bb, *non_region_use_bb, *non_region_def_bb;
01144 RID *rid, *srid;
01145 OP *op;
01146 OPS ops;
01147 TN *tn, *allocated_tn, *new_tn = NULL, *prev_result = NULL;
01148 TN_LIST *tns_in, *tns_out;
01149 INT opndnum, exit_num;
01150
01151 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
01152
01153 rid = BB_rid(bb);
01154 if ( rid && RID_level(rid) >= RL_CGSCHED )
01155 continue;
01156
01157 if ( ! BB_has_globals(bb) )
01158 continue;
01159
01160 Reset_BB_has_globals( bb );
01161
01162
01163 non_region_use_bb = BB_Reaches_Call_or_Exit( bb );
01164 if ( non_region_use_bb )
01165 srid = NULL;
01166 else
01167 srid = BB_Successor_Compiled_Region( bb );
01168
01169 FOR_ALL_BB_OPs (bb, op) {
01170 for (INT i = 0; i < OP_results(op); i++) {
01171 tn = OP_result(op,i);
01172 if ( ! TN_is_dedicated( tn ) ) continue;
01173
01174 if (!REGISTER_allocatable(TN_register_class(tn), TN_register(tn)))
01175 continue;
01176 if ( non_region_use_bb == bb )
01177 continue;
01178 else if ( non_region_use_bb ) {
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189 if (OP_same_res(op) && (tn == prev_result)
01190 && (OP_opnd(op,OP_opnds(op)-1) == prev_result)) {
01191
01192 Set_OP_result( op, i, new_tn );
01193 Set_OP_opnd (op, OP_opnds(op)-1, new_tn);
01194 } else {
01195 new_tn = Build_TN_Like( tn );
01196 Set_OP_result( op, i, new_tn );
01197 Exp_COPY( tn, new_tn, OPS_Init(&ops) );
01198 BB_Prepend_Ops (non_region_use_bb, &ops);
01199 prev_result = tn;
01200 }
01201 }
01202 else if (srid != NULL) {
01203
01204 tns_in = CGRIN_tns_in( RID_cginfo( srid ) );
01205 allocated_tn = Find_TN_with_Matching_Register( tn, tns_in );
01206 FmtAssert( allocated_tn != NULL,
01207 ("dedicated TN %d in bb %d reaches REGION %d with no matching"
01208 " exposed register",
01209 TN_number(tn), BB_id(bb), RID_id(srid)));
01210 Set_OP_result( op, i, allocated_tn );
01211 Set_OP_glue(op);
01212 if ( Trace_REGION_Interface ) {
01213 fprintf( TFile, "RGN %d, replacing def of dedicated TN ",
01214 RID_id(rid) );
01215 Print_TN( tn, FALSE );
01216 fprintf( TFile, " with allocated TN " );
01217 Print_TN( allocated_tn, FALSE );
01218 fprintf( TFile, " in BB %d\n", BB_id(bb) );
01219 }
01220 }
01221 else {
01222 #pragma mips_frequency_hint NEVER
01223 FmtAssert( FALSE,
01224 ("def of %s in BB:%d does not reach either CALL or "
01225 "allocated REGION",
01226 REGISTER_name(TN_register_class(tn), TN_register(tn)),
01227 BB_id(bb)));
01228
01229 }
01230 }
01231 }
01232
01233
01234 non_region_def_bb = Call_or_Entry_Reaches_BB( bb );
01235 if ( non_region_def_bb )
01236 srid = NULL;
01237 else
01238 srid = BB_Predecessor_Compiled_Region( &exit_num, bb );
01239
01240 FOR_ALL_BB_OPs (bb, op) {
01241
01242 #ifdef TARG_X8664
01243
01244
01245 if( OP_code(op) == TOP_asm ){
01246 continue;
01247 }
01248 #endif
01249 for ( opndnum = 0; opndnum < OP_opnds( op ); opndnum++ ) {
01250 tn = OP_opnd( op, opndnum );
01251 if ( TN_is_constant(tn) || TN_is_zero_reg(tn) )
01252 continue;
01253 if ( ! TN_is_dedicated(tn) )
01254 continue;
01255
01256 if ( ! REGISTER_allocatable(TN_register_class(tn), TN_register(tn)) )
01257 continue;
01258
01259 if ( TN_is_ep_reg(tn) && OP_call(op) )
01260 continue;
01261
01262 if ( OP_same_res(op) && tn == OP_result(op,0) )
01263 continue;
01264 #ifdef TARG_X8664
01265
01266
01267 if ( tn == OP_result(op,0) )
01268 continue;
01269 #endif
01270 if ( non_region_def_bb == bb )
01271 continue;
01272 #if defined(TARG_SL)
01273 else if (TN_Def_Local(bb, op, tn))
01274 continue;
01275 #endif
01276 else if ( non_region_def_bb ) {
01277
01278
01279 new_tn = Build_TN_Like( tn );
01280 Set_OP_opnd( op, opndnum, new_tn );
01281 Exp_COPY( new_tn, tn, OPS_Init(&ops) );
01282 BB_Prepend_Ops(non_region_def_bb, &ops);
01283 } else {
01284
01285 FmtAssert( ( srid != NULL ),
01286 ("use of %s (TN%d) in BB:%d at line %d not reached by "
01287 "CALL/allocated REGION",
01288 REGISTER_name(TN_register_class(tn), TN_register(tn)),
01289 TN_number(tn), BB_id(bb),
01290 SRCPOS_linenum(OP_srcpos(op)) ));
01291 tns_out = CGRIN_tns_out_i( RID_cginfo( srid ), exit_num );
01292 allocated_tn = Find_TN_with_Matching_Register( tn, tns_out );
01293 FmtAssert(allocated_tn != NULL,
01294 ("dedicated TN %d reached by REGION %d with no matching "
01295 "defined register", TN_number(tn), RID_id(srid)));
01296 Set_OP_opnd( op, opndnum, allocated_tn );
01297 Set_OP_glue( op );
01298 if ( Trace_REGION_Interface ) {
01299 fprintf( TFile, "RGN %d, replacing use of dedicated TN ",
01300 RID_id(srid) );
01301 Print_TN( tn, FALSE );
01302 fprintf( TFile, " with allocated TN " );
01303 Print_TN( allocated_tn, FALSE );
01304 fprintf( TFile, " in BB %d\n", BB_id(bb) );
01305 }
01306 }
01307
01308 }
01309 }
01310 }
01311 }
01312