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
00041
00042
00043
00044
00045
00047
00048
00049
00050
00051
00052
00053 #ifdef USE_PCH
00054 #include "cg_pch.h"
00055 #endif // USE_PCH
00056 #pragma hdrstop
00057
00058 #include "import.h"
00059 #include "defs.h"
00060 #include "errors.h"
00061 #include "cgir.h"
00062 #include "cg.h"
00063 #include "bb.h"
00064 #include "bb_list.h"
00065 #include "cgexp.h"
00066 #include "cg_flags.h"
00067 #include "cg_spill.h"
00068 #include "cg_region.h"
00069 #include "whirl2ops.h"
00070 #include "opt_alias_interface.h"
00071
00072 #include "gra_bb.h"
00073 #include "gra_lrange.h"
00074 #include "lrange_list.h"
00075 #include "gra_loop.h"
00076 #include "gra_region.h"
00077 #include "gra_trace.h"
00078 #ifdef TARG_IA64
00079 #include "ipfec_options.h"
00080 #include "cgexp_internals.h"
00081 #endif
00082 #ifdef KEY
00083 #include "calls.h"
00084 #include "cxx_template.h"
00085
00086 extern STACK<SAVE_REG_LOC> Saved_Callee_Saved_Regs;
00087 #endif
00088
00089 BOOL GRA_optimize_placement = TRUE;
00090
00091
00092
00093 static LRANGE_LIST* spilled_lranges;
00094 static LUNIT* lunits_with_spills_head;
00095 static LRANGE* split_lranges_head;
00096 static BB_LIST* region_entry_glue_bbs;
00097 static BB_LIST* region_exit_glue_bbs;
00098 static float freq_spill_count, freq_restore_count;
00099 static INT32 spill_count, restore_count;
00100 float priority_count;
00101 #ifdef TARG_IA64
00102 static INT32 spill_count_all, spill_count_with_nat;
00103 static TN* unat_tn;
00104 static TN* orig_lrange_tn;
00105 static TN_MAP tn_unat_map;
00106 #endif
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 class SPILL_LIST {
00126 friend SPILL_LIST *SPILL_LIST_Create_Lunit(LUNIT *lunit, MEM_POOL *mempool);
00127 friend SPILL_LIST* SPILL_LIST_Create_Gbb(GRA_BB* gbb, MEM_POOL *mempool);
00128 LUNIT* lunit;
00129 GRA_BB* gbb;
00130 BOOL split_live_in;
00131 BOOL split_defreach_out;
00132 BOOL load_below_sticks;
00133 SPILL_LIST* next;
00134
00135 void Init(void) { lunit = NULL; gbb = NULL; split_live_in = FALSE;
00136 split_defreach_out = FALSE; load_below_sticks = FALSE;
00137 next = NULL; }
00138 public:
00139 SPILL_LIST(void) {}
00140 ~SPILL_LIST(void) {}
00141
00142
00143 LUNIT *Lunit(void) { return lunit; }
00144 GRA_BB *Gbb(void) { return gbb; }
00145 SPILL_LIST *Next(void) { return next; }
00146 BOOL Split_Live_In(void) { return split_live_in; }
00147 void Split_Live_In_Set(void) { split_live_in = TRUE; }
00148 BOOL Split_Defreach_Out(void) { return split_defreach_out; }
00149 void Split_Defreach_Out_Set(void) { split_defreach_out = TRUE; }
00150 BOOL Load_Below_Sticks(void) { return load_below_sticks; }
00151 void Load_Below_Sticks_Set(void) { load_below_sticks = TRUE; }
00152
00153
00154 GRA_BB* Get_Gbb(void) { return lunit ? lunit->Gbb() : gbb; }
00155
00156
00157
00158 SPILL_LIST *Push(SPILL_LIST *new_sl) { new_sl->next = this; return new_sl; }
00159
00160 };
00161
00162
00163 inline SPILL_LIST *SPILL_LIST_Create_Lunit(LUNIT *lunit, MEM_POOL *mempool)
00164 {
00165 SPILL_LIST *new_sl = TYPE_MEM_POOL_ALLOC(SPILL_LIST, mempool);
00166 new_sl->Init();
00167 new_sl->lunit = lunit;
00168 return(new_sl);
00169 }
00170
00171
00172 inline SPILL_LIST* SPILL_LIST_Create_Gbb(GRA_BB* gbb, MEM_POOL *mempool)
00173 {
00174 SPILL_LIST *new_sl = TYPE_MEM_POOL_ALLOC(SPILL_LIST, mempool);
00175 new_sl->Init();
00176 new_sl->gbb = gbb;
00177 return(new_sl);
00178 }
00179
00180
00182
00183 inline void
00184 Possibly_List_LUNIT(LUNIT* lunit)
00186
00187
00188
00190 {
00191 if ( ! lunit->Spill_Listed() ) {
00192 lunit->Spill_Listed_Set();
00193 lunits_with_spills_head =
00194 lunits_with_spills_head->Spill_List_Push(lunit);
00195 }
00196 }
00197
00198
00200 inline void
00201 Possibly_List_LRANGE( LRANGE* lrange )
00203
00204
00205
00207 {
00208 if (! lrange->Split_Listed()) {
00209 lrange->Split_Listed_Set();
00210 split_lranges_head = split_lranges_head->Split_List_Push(lrange);
00211 }
00212 }
00213
00214 #ifdef TARG_IA64
00216 // Initial unat spill
00217 static void
00218 UNAT_Spill_Initialize(void)
00219 {
00220 LRANGE_LIST *l;
00221 TN *tn;
00222 INT unat_size = 64;
00223
00224 spill_count_all = 0;
00225 spill_count_with_nat = 0;
00226 if (!IPFEC_Enable_Insert_UNAT || !IPFEC_Enable_Speculation) return;
00227
00228 for ( l = spilled_lranges; l != NULL; l = LRANGE_LIST_rest(l)) {
00229 tn = LRANGE_LIST_first(l)->Tn();
00230 if (TN_is_float(tn)) continue;
00231
00232 if (TN_is_take_nat(tn))
00233 spill_count_with_nat++;
00234 spill_count_all++;
00235 }
00236 unat_tn = Build_Dedicated_TN(ISA_REGISTER_CLASS_application,(REGISTER)(REGISTER_MIN + 36),0);
00237 tn_unat_map = TN_MAP_Create();
00238
00239 if (spill_count_all > unat_size && spill_count_with_nat > 1)
00240 DevWarn("Insert UNAT spill for spill count %d > %d. ", spill_count_all, unat_size);
00241 if (spill_count_with_nat >= 1)
00242 DevWarn("Insert UNAT spill for spill count with nat bit %d >= 1",spill_count_with_nat);
00243 }
00244
00246
00247 static void
00248 UNAT_Spill_Finish(void)
00249 {
00250 TN_MAP_Delete(tn_unat_map);
00251 }
00252
00254
00255
00256 static BOOL
00257 Need_UNAT_Spill_Restore(TN *lrange_tn)
00258 {
00259 int unat_size=64;
00260
00261 if (!IPFEC_Enable_Insert_UNAT || !IPFEC_Enable_Speculation) return FALSE;
00262
00263 if (lrange_tn != NULL) {
00264 if (lrange_tn == unat_tn) return TRUE;
00265
00266 if (!TN_is_take_nat(lrange_tn)) return FALSE;
00267 return spill_count_all>unat_size &&
00268 spill_count_with_nat > 1 ? TRUE : FALSE;
00269 }
00270 return FALSE;
00271 }
00272
00274
00275
00276
00278 BOOL
00279 Need_UNAT_Entry_Exit(void) {
00280 if (!IPFEC_Enable_Insert_UNAT || !IPFEC_Enable_Speculation) return FALSE;
00281 return spill_count_with_nat>=1 ? TRUE : FALSE;
00282 }
00283
00285 void
00286 UNAT_Spill_OPS(TN *lrange_tn, ST *lrange_st, OPS *ops, CGSPILL_CLIENT client, BB *bb)
00288
00289
00290
00292 {
00293 ST *st = NULL;
00294 if (TN_is_float(lrange_tn)) return;
00295
00296 TN* tn = unat_tn;
00297
00298 if (!Need_UNAT_Spill_Restore(lrange_tn)) return;
00299
00300 TN* spill_tn = Gen_Register_TN(ISA_REGISTER_CLASS_integer,8);
00301
00302 OPS_Remove_All(ops);
00303 Expand_Copy(spill_tn, tn, MTYPE_I8, ops);
00304 for (OP* op = OPS_first(ops); op != NULL; op = OP_next(op))
00305 {
00306 OP_Change_Opcode(op, TOP_mov_f_ar_m);
00307 Reset_OP_copy(op);
00308 }
00309
00310 if (lrange_tn != tn)
00311 st = (ST *)TN_MAP_Get(tn_unat_map, orig_lrange_tn);
00312 else
00313 orig_lrange_tn = lrange_tn;
00314 if (st == NULL || lrange_tn==tn) {
00315 st = CGSPILL_Get_TN_Spill_Location(spill_tn,CGSPILL_GRA);
00316 TN_MAP_Set(tn_unat_map, orig_lrange_tn, st);
00317 }
00318 CGSPILL_Store_To_Memory(spill_tn, st, ops, CGSPILL_GRA, bb);
00319 }
00321 void
00322 UNAT_Restore_OPS(TN *lrange_tn, ST *lrange_st, OPS *ops, CGSPILL_CLIENT client, BB *bb)
00324
00325
00326
00328 {
00329 if (TN_is_float(lrange_tn)) return;
00330
00331 TN* tn = unat_tn;
00332 if (!Need_UNAT_Spill_Restore(lrange_tn)) return;
00333
00334 TN* restore_tn = Gen_Register_TN(ISA_REGISTER_CLASS_integer,8);
00335
00336 OPS_Remove_All(ops);
00337 Expand_Copy(tn, restore_tn, MTYPE_I8, ops);
00338
00339 for (OP* op = OPS_first(ops); op != NULL; op = OP_next(op))
00340 {
00341 OP_Change_Opcode(op, TOP_mov_t_ar_r_m);
00342 Reset_OP_copy(op);
00343 }
00344
00345
00346 if (lrange_tn == tn) {orig_lrange_tn = tn;}
00347 ST *st = (ST *)TN_MAP_Get(tn_unat_map, orig_lrange_tn);
00348 if (st == NULL) {
00349 st = CGSPILL_Get_TN_Spill_Location(restore_tn,CGSPILL_GRA);
00350 TN_MAP_Set(tn_unat_map, orig_lrange_tn, st);
00351 }
00352 OPS r_ops = OPS_EMPTY;
00353 CGSPILL_Load_From_Memory(restore_tn, st, &r_ops, CGSPILL_GRA, bb);
00354 OPS_Prepend_Ops(ops, &r_ops);
00355 }
00356 #endif // TARG_IA64
00357
00359 inline void
00360 Gen_Spill_Restore( TN* tn, ST* spill_loc, GRA_BB* gbb,
00361 void (*gen_fn)(TN*,ST*,OPS*,CGSPILL_CLIENT,BB*),
00362 void (*add_fn)(BB*,OPS*),
00363 void (*insert_fn)(TN*, BB*, OPS*),
00364 BOOL insert_flag)
00366
00367
00368
00369
00370
00371
00372
00374 {
00375 OPS spill_ops = OPS_EMPTY;
00376 BB* bb = gbb->Bb();
00377
00378 Is_True(gbb->Region_Is_Complement(),
00379 ("Spilling TN%d in previously allocated region BB:%d",
00380 TN_number(tn), BB_id(bb)));
00381
00382 Reset_BB_scheduled(bb);
00383 gen_fn(tn,spill_loc,&spill_ops, CGSPILL_GRA, bb);
00384 if (insert_flag &&
00385 (GRA_ensure_spill_proximity ||
00386 (CG_local_skip_equal != GRA_pu_num &&
00387 GRA_pu_num <= CG_local_skip_after &&
00388 GRA_pu_num >= CG_local_skip_before))) {
00389 insert_fn(tn, bb, &spill_ops);
00390 } else {
00391 add_fn(bb,&spill_ops);
00392 }
00393 }
00394
00396 static void
00397 TN_Spill_Below( TN* tn, ST* spill_loc, GRA_BB* gbb, BOOL insert_after )
00399
00400
00401
00403 {
00404 freq_spill_count += gbb->Freq();
00405 ++spill_count;
00406 #ifdef TARG_IA64
00407 if (insert_after) {
00408 Gen_Spill_Restore(tn,spill_loc,gbb,UNAT_Spill_OPS,
00409 CGSPILL_Append_Ops,
00410 CGSPILL_Insert_Ops_After_Last_Def,
00411 insert_after);
00412 }
00413 #endif
00414 Gen_Spill_Restore(tn,spill_loc,gbb,CGSPILL_Store_To_Memory,
00415 CGSPILL_Append_Ops,
00416 CGSPILL_Insert_Ops_After_Last_Def,
00417 insert_after);
00418 #ifdef TARG_IA64
00419 if (!insert_after) {
00420 Gen_Spill_Restore(tn,spill_loc,gbb,UNAT_Spill_OPS,
00421 CGSPILL_Append_Ops,
00422 CGSPILL_Insert_Ops_After_Last_Def,
00423 insert_after);
00424 }
00425 #endif
00426 }
00427
00429 static void
00430 TN_Restore_Above( TN* tn, ST* spill_loc, GRA_BB* gbb, BOOL insert_before )
00432
00433
00434
00436 {
00437
00438 freq_restore_count += gbb->Freq();
00439 ++restore_count;
00440 #ifdef TARG_IA64
00441 if (insert_before) {
00442 Gen_Spill_Restore(tn,spill_loc,gbb,UNAT_Restore_OPS,
00443 CGSPILL_Prepend_Ops,
00444 CGSPILL_Insert_Ops_Before_First_Use,
00445 insert_before);
00446 }
00447 #endif
00448 Gen_Spill_Restore(tn,spill_loc,gbb,CGSPILL_Load_From_Memory,
00449 CGSPILL_Prepend_Ops,
00450 CGSPILL_Insert_Ops_Before_First_Use,
00451 insert_before);
00452 #ifdef TARG_IA64
00453 if (!insert_before) {
00454 Gen_Spill_Restore(tn,spill_loc,gbb,UNAT_Restore_OPS,
00455 CGSPILL_Prepend_Ops,
00456 CGSPILL_Insert_Ops_Before_First_Use,
00457 insert_before);
00458 }
00459 #endif
00460 }
00461
00463 static void
00464 TN_Spill_Above( TN* tn, ST* spill_loc, GRA_BB* gbb )
00466
00467
00468
00470 {
00471 freq_spill_count += gbb->Freq();
00472 ++spill_count;
00473 #ifdef TARG_IA64
00474 Gen_Spill_Restore(tn,spill_loc,gbb,UNAT_Spill_OPS,
00475 CGSPILL_Prepend_Ops,
00476 CGSPILL_Insert_Ops_After_Last_Def,
00477 FALSE);
00478 #endif
00479 Gen_Spill_Restore(tn,spill_loc,gbb,CGSPILL_Store_To_Memory,
00480 CGSPILL_Prepend_Ops,
00481 CGSPILL_Insert_Ops_After_Last_Def,
00482 FALSE);
00483 }
00484
00486 static void
00487 TN_Restore_Below( TN* tn, ST* spill_loc, GRA_BB* gbb )
00489
00490
00491
00493 {
00494 freq_restore_count += gbb->Freq();
00495 ++restore_count;
00496 #ifdef TARG_IA64
00497 Gen_Spill_Restore(tn,spill_loc,gbb,UNAT_Restore_OPS,
00498 CGSPILL_Append_Ops,
00499 CGSPILL_Insert_Ops_Before_First_Use,
00500 FALSE);
00501 #endif
00502 Gen_Spill_Restore(tn,spill_loc,gbb,CGSPILL_Load_From_Memory,
00503 CGSPILL_Append_Ops,
00504 CGSPILL_Insert_Ops_Before_First_Use,
00505 FALSE);
00506 }
00507
00509 static void
00510 LRANGE_Spill_Above( LRANGE* lrange, GRA_BB* gbb )
00512
00513
00514
00516 {
00517 TN* tn = lrange->Tn();
00518 TN* orig_tn = lrange->Original_TN();
00519 ST* st = CGSPILL_Get_TN_Spill_Location(orig_tn,CGSPILL_GRA);
00520
00521 #ifdef TARG_IA64
00522 orig_lrange_tn = orig_tn;
00523 #endif
00524 TN_Spill_Above(tn,st,gbb);
00525 }
00526
00528 static void
00529 LRANGE_Restore_Below( LRANGE* lrange, GRA_BB* gbb )
00531
00532
00533
00535 {
00536 TN* tn = lrange->Tn();
00537 TN* orig_tn = lrange->Original_TN();
00538 ST* st = CGSPILL_Get_TN_Spill_Location(orig_tn,CGSPILL_GRA);
00539
00540 #ifdef TARG_IA64
00541 orig_lrange_tn = orig_tn;
00542 #endif
00543 TN_Restore_Below(tn,st,gbb);
00544 }
00545
00547 static void
00548 LRANGE_Spill_Below( LRANGE* lrange, GRA_BB* gbb )
00550
00551
00552
00554 {
00555 TN* tn = lrange->Tn();
00556 TN* orig_tn = lrange->Original_TN();
00557 ST* st = CGSPILL_Get_TN_Spill_Location(orig_tn,CGSPILL_GRA);
00558 LUNIT *lunit = NULL;
00559
00560 #ifdef TARG_IA64
00561 orig_lrange_tn = orig_tn;
00562 #endif
00563
00564
00565
00566
00567 (void) lrange->Find_LUNIT_For_GBB(gbb, &lunit);
00568
00569 #ifdef KEY
00570 if (GRA_optimize_boundary ||
00571 gbb->Clobbers_Reg_Class(lrange->Rc())) {
00572
00573
00574 TN_Spill_Below(tn,st,gbb,TRUE);
00575 } else
00576 #endif
00577 TN_Spill_Below(tn,st,gbb,lunit && lunit->True_Reference());
00578 }
00579
00581 static void
00582 LRANGE_Restore_Above( LRANGE* lrange, GRA_BB* gbb )
00584
00585
00586
00588 {
00589 TN* tn = lrange->Tn();
00590 TN* orig_tn = lrange->Original_TN();
00591 ST* st = CGSPILL_Get_TN_Spill_Location(orig_tn,CGSPILL_GRA);
00592 LUNIT *lunit = NULL;
00593
00594 #ifdef TARG_IA64
00595 orig_lrange_tn = orig_tn;
00596 #endif
00597
00598
00599
00600
00601 (void) lrange->Find_LUNIT_For_GBB(gbb, &lunit);
00602
00603 #ifdef KEY
00604 if (GRA_optimize_boundary ||
00605 gbb->Clobbers_Reg_Class(lrange->Rc())) {
00606
00607
00608 TN_Restore_Above(tn,st,gbb,TRUE);
00609 } else
00610 #endif
00611 TN_Restore_Above(tn,st,gbb,lunit && lunit->True_Reference());
00612 }
00613
00614
00616 static void
00617 Spill_Homeable_TN(
00618 GRA_BB* gbb,
00619 TN* orig_tn,
00620 TN* new_tn,
00621 ST* st,
00622 LUNIT* lunit,
00623 LRANGE* lrange
00624 )
00626
00627
00628
00630 {
00631 GRA_BB_OP_FORWARD_ITER iter;
00632 ALIAS_RESULT alias;
00633 BOOL aliased_store_seen = FALSE;
00634 BOOL need_store = FALSE;
00635 BOOL homing_load_removed = FALSE;
00636 BOOL def_seen = FALSE;
00637 BOOL need_load = FALSE;
00638
00639 GRA_Trace_Homing(orig_tn, gbb->Bb());
00640
00641 for (iter.Init(gbb); ! iter.Done(); ) {
00642 INT i;
00643 OP* op = iter.Current();
00644 iter.Step();
00645 BOOL op_is_homing_store = FALSE;
00646 BOOL op_is_homing_load = FALSE;
00647
00648
00649
00650
00651
00652 if (OP_store(op) || OP_load(op)) {
00653 WN *wn = Get_WN_From_Memory_OP(op);
00654 if (wn != NULL) {
00655 alias = Aliased(Alias_Manager, TN_home(orig_tn), wn);
00656 if (alias == SAME_LOCATION) {
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 INT st_op_num = TOP_Find_Operand_Use(OP_code(op), OU_storeval);
00669 if ((OP_store(op) && !need_store &&
00670 orig_tn == OP_opnd(op, st_op_num)) ||
00671 (OP_load(op) && !aliased_store_seen &&
00672 OP_result(op, 0) == orig_tn)) {
00673 #ifdef KEY
00674
00675
00676
00677 if (!OP_cond_def(op))
00678 #endif
00679 {
00680 GRA_Trace_Home_Removal(orig_tn, gbb, op);
00681 BB_Remove_Op(gbb->Bb(), op);
00682 if (OP_load(op)) homing_load_removed = TRUE;
00683 continue;
00684 }
00685 } else if (OP_store(op)) {
00686
00687
00688
00689
00690 #ifdef KEY // Don't need store at bottom of BB only if the earlier store
00691
00692 if (OP_opnd(op, st_op_num) == orig_tn) {
00693 need_store = FALSE;
00694 op_is_homing_store = TRUE;
00695 }
00696 #else
00697 need_store = FALSE;
00698 if (OP_opnd(op, st_op_num) == orig_tn)
00699 op_is_homing_store = TRUE;
00700 #endif
00701 } else if (OP_load(op) && OP_result(op, 0) == orig_tn) {
00702 op_is_homing_load = TRUE;
00703 }
00704 } else if (alias == POSSIBLY_ALIASED && OP_store(op)) {
00705 aliased_store_seen = TRUE;
00706 }
00707 } else {
00708 alias = NOT_ALIASED;
00709 }
00710 } else {
00711 alias = NOT_ALIASED;
00712 }
00713
00714
00715
00716
00717
00718 for ( i = OP_opnds(op) - 1; i >= 0; --i ) {
00719 if ( OP_opnd(op,i) == orig_tn) {
00720
00721
00722
00723 if (!def_seen && !op_is_homing_store) {
00724 need_load = TRUE;
00725 }
00726 Set_OP_opnd(op, i, new_tn);
00727 }
00728 }
00729 for ( i = OP_results(op) - 1; i >= 0; --i ) {
00730 if ( OP_result(op,i) == orig_tn) {
00731
00732
00733
00734 if (!op_is_homing_load) {
00735 need_store = TRUE;
00736 #ifdef KEY
00737 if (OP_cond_def(op) && !def_seen)
00738 need_load = TRUE;
00739 #endif
00740 }
00741 def_seen = TRUE;
00742 Set_OP_result(op, i, new_tn);
00743 }
00744 }
00745 }
00746
00747
00748
00749
00750
00751
00752
00753 if (need_load && (lunit->Restore_Above() ||
00754 gbb->Is_Live_In_LRANGE(lrange) ||
00755 homing_load_removed)) {
00756 TN_Restore_Above(new_tn,st,gbb,TRUE);
00757 gbb->Remove_Live_In_LRANGE(lrange);
00758 }
00759 if (need_store && (lunit->Spill_Below() ||
00760 gbb->Is_Live_Out_LRANGE(lrange))) {
00761 TN_Spill_Below(new_tn,st,gbb,TRUE);
00762 gbb->Remove_Live_Out_LRANGE(lrange);
00763 }
00764 }
00765
00767 static TN*
00768 Make_Dedicated_Save_TN(TN* save_tn, TN* dedicated_tn, ST* spill_st)
00770
00771
00772
00773
00774
00775
00777 {
00778 TN* new_tn = Dup_TN_Even_If_Dedicated(dedicated_tn);
00779 Set_TN_is_dedicated(new_tn);
00780 Set_TN_register_and_class(new_tn, TN_register_and_class(dedicated_tn));
00781 Set_TN_save_creg(new_tn, TN_save_creg(save_tn));
00782 Set_TN_spill(new_tn, spill_st);
00783
00784 return(new_tn);
00785 }
00786
00787
00789 static void
00790 Spill_Prolog_Epilog_Save_LUNIT(LRANGE* lrange, LUNIT* lunit, GRA_BB* gbb,
00791 ST* st)
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00809 {
00810 BB* bb = gbb->Bb();
00811 TN* tn = lrange->Tn();
00812 OP* op;
00813 OPS ops;
00814
00815 if (lunit->Has_Exposed_Use() &&
00816 (lunit->Restore_Above() || gbb->Is_Live_In_LRANGE(lrange))) {
00817
00818
00819
00820
00821 for (op = BB_first_op(bb); op != NULL; op = OP_next(op)) {
00822 if (OP_copy(op) && tn == CGTARG_Copy_Operand_TN(op)) {
00823 break;
00824 }
00825 }
00826 TN* new_tn = Make_Dedicated_Save_TN(tn, OP_result(op, 0), st);
00827 CGSPILL_Load_From_Memory(new_tn, st, OPS_Init(&ops), CGSPILL_GRA, bb);
00828 freq_restore_count += gbb->Freq();
00829 ++restore_count;
00830 CGSPILL_Insert_Ops_Before(bb, op, &ops);
00831 BB_Remove_Op(bb, op);
00832
00833
00834
00835
00836
00837 gbb->Rename_TN_References(tn, OP_result(op, 0));
00838 gbb->Remove_Live_In_LRANGE(lrange);
00839 }
00840
00841 if (lunit->Has_Def() &&
00842 (lunit->Spill_Below() || gbb->Is_Live_Out_LRANGE(lrange))) {
00843
00844
00845
00846 for (op = BB_first_op(bb); op != NULL; op = OP_next(op)) {
00847 if (OP_copy(op) && tn == OP_result(op, 0)) {
00848 break;
00849 }
00850 }
00851 TN* new_tn = Make_Dedicated_Save_TN(tn, CGTARG_Copy_Operand_TN(op), st);
00852 Set_TN_save_creg(new_tn, TN_save_creg(tn));
00853 CGSPILL_Store_To_Memory(new_tn, st, OPS_Init(&ops), CGSPILL_GRA, bb);
00854 freq_spill_count += gbb->Freq();
00855 ++spill_count;
00856 CGSPILL_Insert_Ops_After(bb, op, &ops);
00857 BB_Remove_Op(bb, op);
00858
00859
00860
00861
00862
00863
00864 gbb->Rename_TN_References(tn, CGTARG_Copy_Operand_TN(op));
00865 gbb->Remove_Live_Out_LRANGE(lrange);
00866 }
00867 }
00868
00869
00870 #ifdef TARG_IA64
00871 extern INIT_USE_ONLY_GTN* GTN_USE_ONLY;
00872 extern BOOL Search_Used_Only_Once_GTN (TN *find_tn,BB* def_bb);
00873 #endif
00874
00876 static void
00877 LUNIT_Spill(LUNIT* lunit)
00879
00880
00881
00883 {
00884 if ( lunit->Has_Exposed_Use() || lunit->Has_Def() ) {
00885 LRANGE* lrange = lunit->Lrange();
00886 GRA_BB* gbb = lunit->Gbb();
00887 BB* bb = gbb->Bb();
00888 TN* tn = lrange->Tn();
00889 TN* orig_tn = lrange->Original_TN();
00890 ST* st = CGSPILL_Get_TN_Spill_Location(orig_tn,CGSPILL_GRA);
00891
00892 #ifdef TARG_IA64
00893
00894
00895 orig_lrange_tn = orig_tn;
00896 #endif
00897
00898 #ifdef KEY
00899 if (BB_handler(bb) && BB_entry(bb) && TN_is_save_reg(orig_tn) &&
00900 lunit->Has_Def() &&
00901 (lunit->Spill_Below() || gbb->Is_Live_Out_LRANGE(lrange))) {
00902
00903 TN* ltn = Dup_TN(tn);
00904 Set_TN_spill(ltn, st);
00905 gbb->Rename_TN_References(tn,ltn);
00906 gbb->Remove_Live_Out_LRANGE(lrange);
00907 return;
00908 }
00909
00910
00911 if (TN_is_save_reg(orig_tn) && BB_entry(bb)) {
00912 SAVE_REG_LOC sr;
00913 sr.user_allocated = FALSE;
00914 sr.temp = st;
00915 sr.ded_tn = Build_Dedicated_TN(TN_save_rclass(orig_tn),
00916 TN_save_reg(orig_tn), 0);
00917 Saved_Callee_Saved_Regs.Push(sr);
00918 }
00919 #endif
00920
00921
00922
00923
00924
00925
00926 if (!(TN_is_save_reg(orig_tn) && (BB_entry(bb) || BB_exit(bb)) &&
00927 TN_is_float(orig_tn))) {
00928 TN* ltn = Dup_TN(tn);
00929
00930 Set_TN_spill(ltn, st);
00931 if (TN_is_gra_homeable(tn)) {
00932 Spill_Homeable_TN(gbb,tn,ltn,st,lunit,lrange);
00933 return;
00934 }
00935
00936 gbb->Rename_TN_References(tn,ltn);
00937 #ifdef TARG_IA64 // zhc
00938 BOOL restore_above = FALSE;
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 if (lunit->Has_Exposed_Use() &&
00949 (lunit->Restore_Above() ||
00950 gbb->Is_Live_In_LRANGE(lrange))) {
00951 restore_above = TRUE;
00952 TN_Restore_Above(ltn,st,gbb,TRUE);
00953 gbb->Remove_Live_In_LRANGE(lrange);
00954 }
00955
00956 if (lunit->Has_Def() &&
00957 (lunit->Spill_Below() ||
00958 gbb->Is_Live_Out_LRANGE(lrange))) {
00959 if ((!restore_above)&&(Search_Used_Only_Once_GTN(orig_tn,bb))) {
00960 gbb->Remove_Live_Out_LRANGE(lrange);
00961 return ;
00962
00963 }
00964 if ((restore_above)&&Search_Used_Only_Once_GTN(orig_tn,bb)){
00965 if (BB_nest_level(bb)==0) {
00966 gbb->Remove_Live_Out_LRANGE(lrange);
00967 return ;
00968 }
00969 }
00970 TN_Spill_Below(ltn,st,gbb,TRUE);
00971 gbb->Remove_Live_Out_LRANGE(lrange);
00972 #else // TARG_IA64
00973 if (lunit->Has_Exposed_Use() &&
00974 (lunit->Restore_Above() ||
00975 gbb->Is_Live_In_LRANGE(lrange))) {
00976 TN_Restore_Above(ltn,st,gbb,TRUE);
00977 gbb->Remove_Live_In_LRANGE(lrange);
00978 }
00979
00980 if (lunit->Has_Def() &&
00981 (lunit->Spill_Below() ||
00982 gbb->Is_Live_Out_LRANGE(lrange))) {
00983 TN_Spill_Below(ltn,st,gbb,TRUE);
00984 gbb->Remove_Live_Out_LRANGE(lrange);
00985 #endif // TARG_IA64
00986 }
00987 } else {
00988 Spill_Prolog_Epilog_Save_LUNIT(lrange, lunit, gbb, st);
00989 }
00990 }
00991 }
00992
00993
00995 static void
00996 LRANGE_Spill( LRANGE* lrange )
00998
00999
01000
01001
01002
01004 {
01005 LRANGE_LUNIT_ITER iter;
01006
01007 if (lrange->No_Appearance())
01008 return;
01009
01010 #ifdef TARG_X8664
01011 TN* orig_tn = lrange->Original_TN();
01012 if (CG_push_pop_int_saved_regs && ! Gen_Frame_Pointer &&
01013 ! TN_is_float(orig_tn) && TN_is_save_reg(orig_tn)) {
01014
01015 SAVE_REG_LOC sr;
01016 sr.user_allocated = FALSE;
01017 sr.temp = NULL;
01018 sr.ded_tn = Build_Dedicated_TN(TN_save_rclass(orig_tn),
01019 TN_save_reg(orig_tn), 0);
01020 Saved_Callee_Saved_Regs.Push(sr);
01021
01022 TN_Allocate_Register(orig_tn, TN_register(sr.ded_tn));
01023 return;
01024 }
01025 #endif
01026
01027 for (iter.Init(lrange); ! iter.Done(); iter.Step()) {
01028 LUNIT* lunit = iter.Current();
01029
01030 LUNIT_Spill(lunit);
01031 }
01032 }
01033
01034 #ifdef TARG_IA64
01036 void
01037 Gen_UNAT_Spills_Entry_And_Exit_BB(void)
01039
01040
01041
01043 {
01044
01045 BB_LIST *elist;
01046 BB *bb;
01047 OPS ops = OPS_EMPTY;
01048 TN *spill_tn, *restore_tn;
01049
01050
01051 if ( !Need_UNAT_Entry_Exit() ) return;
01052
01053
01054 TN* tn = unat_tn;
01055
01056
01057
01058 for (elist = Entry_BB_Head; elist; elist = BB_LIST_rest(elist)) {
01059 bb = BB_LIST_first(elist);
01060 UNAT_Spill_OPS(tn, NULL, &ops, CGSPILL_GRA, bb);
01061
01062
01063 CGSPILL_Prepend_Ops(bb, &ops);
01064 OPS_Remove_All(&ops);
01065 }
01066
01067
01068
01069 for (elist = Exit_BB_Head; elist; elist = BB_LIST_rest(elist)) {
01070 bb = BB_LIST_first(elist);
01071 UNAT_Restore_OPS(tn, NULL, &ops, CGSPILL_GRA, bb);
01072
01073
01074 CGSPILL_Append_Ops(bb, &ops);
01075 OPS_Remove_All(&ops);
01076 }
01077
01078
01079 UNAT_Spill_Finish();
01080 }
01081 #endif
01082
01084 static void
01085 Identify_Initialize_Glue_Blocks(void)
01087
01088
01089
01090
01091
01093 {
01094 BB* bb;
01095 BB* succ_bb;
01096 BB* pred_bb;
01097
01098 region_entry_glue_bbs = NULL;
01099 region_exit_glue_bbs = NULL;
01100
01101 for ( bb = REGION_First_BB; bb != NULL; bb = BB_next(bb) ) {
01102 GRA_BB* gbb = gbb_mgr.Get(bb);
01103
01104 if ( gbb->Region_Is_Complement() ) {
01105
01106
01107
01108
01109
01110
01111
01112 pred_bb = BB_Unique_Predecessor(bb);
01113 succ_bb = BB_Unique_Successor(bb);
01114 if (pred_bb != NULL && BB_rid(pred_bb) != NULL) {
01115 if (RID_parent(BB_rid(pred_bb)) == BB_rid(bb)) {
01116 region_exit_glue_bbs = BB_LIST_Push(bb,region_exit_glue_bbs,GRA_pool);
01117 }
01118 }
01119 if (succ_bb != NULL && BB_rid(succ_bb) != NULL) {
01120 if (RID_parent(BB_rid(succ_bb)) == BB_rid(bb)){
01121 region_entry_glue_bbs = BB_LIST_Push(bb,region_entry_glue_bbs,GRA_pool);
01122 }
01123 }
01124 }
01125 }
01126 }
01127
01129 static BOOL
01130 Complement_TN( const TN* tn )
01132
01133
01134
01136 {
01137 LRANGE* lrange = lrange_mgr.Get(tn);
01138
01139 return lrange != NULL && lrange->Type() == LRANGE_TYPE_COMPLEMENT;
01140 }
01141
01143 static BOOL
01144 Region_TN( const TN* tn, const GRA_REGION* region )
01146
01147
01148
01149
01151 {
01152 LRANGE* lrange = lrange_mgr.Get(tn);
01153
01154 if ( lrange != NULL && lrange->Type() == LRANGE_TYPE_REGION ) {
01155 DevAssert(lrange->Region() == region,
01156 ("Unexpected source region in glue copy"));
01157 return TRUE;
01158 }
01159
01160 return FALSE;
01161 }
01162
01164 static BOOL
01165 Uses_Region_TN( const OP* op, const GRA_REGION* region )
01167
01168
01169
01170
01172 {
01173 INT i;
01174
01175 for ( i = OP_opnds(op) - 1; i >= 0; --i ) {
01176 if ( Region_TN(OP_opnd(op,i),region) )
01177 return TRUE;
01178 }
01179
01180 return FALSE;
01181 }
01182
01184 static void
01185 Map_Operands( TN_MAP map, OP* op )
01187
01188
01189
01191 {
01192 INT i;
01193
01194 for ( i = OP_opnds(op) - 1; i >= 0; --i ) {
01195 TN* tn = OP_opnd(op,i);
01196 #ifdef TARG_IA64
01197 if(TN_is_constant(tn)) continue;
01198 #endif
01199
01200 DevAssert(! Complement_TN(tn),("Complement TN%d in glue tree",
01201 TN_number(tn)));
01202 TN_MAP_Set(map,tn,(void*)TRUE);
01203 }
01204 }
01205
01207 inline BOOL
01208 Defines_Mapped_TN( TN_MAP map, OP* op )
01210
01211
01212
01214 {
01215 INT i;
01216
01217 for ( i = OP_results(op) - 1; i >= 0; --i ) {
01218 if ( (BOOL)(INTPTR) TN_MAP_Get(map,OP_result(op,i)) ) return TRUE;
01219 }
01220 return FALSE;
01221 }
01222
01224 static void
01225 BB_Split_Exit_Glue( BB* bb )
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01239 {
01240 OP* op;
01241 OP* prev_op = (OP*) -1;
01242 OPS glue_ops = OPS_EMPTY;
01243 OPS result_copy_ops = OPS_EMPTY;
01244 GRA_REGION* region = gbb_mgr.Get(BB_Unique_Predecessor(bb))->Region();
01245 TN_MAP map = TN_MAP_Create();
01246
01247 for (op = BB_last_op(bb); op != NULL; op = prev_op ) {
01248 prev_op = OP_prev(op);
01249
01250 if ( Uses_Region_TN(op,region) ) {
01251 INT i;
01252 BB_Remove_Op(bb,op);
01253 OPS_Prepend_Op(&glue_ops,op);
01254 Map_Operands(map,op);
01255
01256 for ( i = OP_results(op) - 1; i >= 0; --i ) {
01257 TN *result = OP_result(op,i);
01258 if ( Complement_TN(result)
01259 #ifdef TARG_IA64
01260 || TN_is_dedicated(result) && ! TN_is_zero(result )&& result != True_TN
01261 #else
01262 || TN_is_dedicated(result) && ! TN_is_zero(result)
01263 #endif
01264 ) {
01265 TN* tmp = Dup_TN_Even_If_Dedicated(result);
01266
01267 Set_OP_result(op,i,tmp);
01268 Exp_COPY(result,tmp,&result_copy_ops);
01269 }
01270 }
01271 }
01272 else if ( Defines_Mapped_TN(map,op) ) {
01273 BB_Remove_Op(bb,op);
01274 OPS_Prepend_Op(&glue_ops,op);
01275 Map_Operands(map,op);
01276 }
01277 }
01278
01279 CGSPILL_Prepend_Ops(bb,&result_copy_ops);
01280 CGSPILL_Prepend_Ops(bb,&glue_ops);
01281 TN_MAP_Delete(map);
01282 }
01283
01285 static void
01286 BB_Split_Entry_Glue( BB* bb )
01288
01289
01290
01291
01292
01293
01294
01295
01297 {
01298 INT i, j;
01299 OP* op;
01300 OP* next_op = (OP*) -1;
01301 OPS glue_ops = OPS_EMPTY;
01302 OPS operand_copy_ops = OPS_EMPTY;
01303 GRA_REGION* region = gbb_mgr.Get(BB_Unique_Successor(bb))->Region();
01304
01305 for ( op = BB_first_op(bb); op != NULL; op = next_op ) {
01306 next_op = OP_next(op);
01307 for ( i = OP_results(op) - 1; i >= 0; --i ) {
01308 if ( Region_TN(OP_result(op,i),region) ) {
01309 BB_Remove_Op(bb,op);
01310 OPS_Append_Op(&glue_ops,op);
01311
01312
01313 for ( i = OP_opnds(op) - 1; i >= 0; --i ) {
01314 TN* operand = OP_opnd(op,i);
01315
01316
01317
01318 if ( Complement_TN(operand)
01319 || TN_is_dedicated(operand) && ! TN_is_zero(operand) && ! TN_is_true_pred(operand)
01320 ) {
01321 TN* tmp = Dup_TN_Even_If_Dedicated(operand);
01322
01323 Exp_COPY(tmp,operand,&operand_copy_ops);
01324
01325 for ( j = i ; j >= 0; --j ) {
01326 if ( OP_opnd(op,j) == operand )
01327 Set_OP_opnd(op,j,tmp);
01328 }
01329 }
01330 }
01331 break;
01332 }
01333 }
01334 }
01335
01336 CGSPILL_Append_Ops(bb,&operand_copy_ops);
01337 CGSPILL_Append_Ops(bb,&glue_ops);
01338 }
01339
01341 static void
01342 Divide_Glue_Code(void)
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01362 {
01363 BB_LIST* bb_list;
01364
01365 for ( bb_list = region_exit_glue_bbs; bb_list != NULL;
01366 bb_list = BB_LIST_rest(bb_list)
01367 ) {
01368 BB* exit_glue_bb = BB_LIST_first(bb_list);
01369
01370 BB_Split_Exit_Glue(exit_glue_bb);
01371 }
01372
01373 for ( bb_list = region_entry_glue_bbs; bb_list != NULL;
01374 bb_list = BB_LIST_rest(bb_list)
01375 ) {
01376 BB* entry_glue_bb = BB_LIST_first(bb_list);
01377
01378 BB_Split_Entry_Glue(entry_glue_bb);
01379 }
01380 }
01381
01383 static void
01384 Mark_Defreach_Out_Recur( LRANGE* lrange, GRA_BB* gbb )
01386
01387
01388
01390 {
01391 GRA_BB_FLOW_NEIGHBOR_ITER iter;
01392
01393 if ( ! gbb_mgr.One_Set_MemberP(gbb) ) {
01394
01395
01396
01397
01398 LUNIT* lunit;
01399 if (TN_is_gra_homeable(lrange->Tn()) &&
01400 lrange->Find_LUNIT_For_GBB(gbb, &lunit)) {
01401 if (lunit->Syncs_With_Home()) {
01402 return;
01403 }
01404 }
01405
01406 gbb_mgr.One_Set_Union1(gbb);
01407
01408 for (iter.Succs_Init(gbb); ! iter.Done(); iter.Step()) {
01409 GRA_BB* succ = iter.Current();
01410
01411 if ( lrange->Contains_BB(succ) ) {
01412 Mark_Defreach_Out_Recur(lrange,succ);
01413 } else if ( succ->Spill_Above_Check(lrange) ) {
01414
01415
01416
01417
01418
01419
01420 gbb_mgr.One_Set_Union1(succ);
01421 }
01422 }
01423 }
01424 }
01425
01426
01427
01429 static void
01430 Mark_Defreach_Out( LRANGE* lrange , SPILL_LIST *store_list)
01432
01433
01434
01435
01437 {
01438 LRANGE_LUNIT_ITER iter;
01439
01440 gbb_mgr.Clear_One_Set();
01441
01442
01443
01444 for (iter.Init(lrange); ! iter.Done(); iter.Step()) {
01445 LUNIT* lunit = iter.Current();
01446
01447
01448
01449
01450 if ( lunit->Has_Def() && !lunit->Def_From_Home() )
01451 Mark_Defreach_Out_Recur(lrange,lunit->Gbb());
01452 }
01453
01454
01455
01456 for ( SPILL_LIST *sl = store_list;
01457 sl != NULL;
01458 sl = sl->Next()) {
01459 if ( gbb_mgr.One_Set_MemberP(sl->Get_Gbb())) {
01460 sl->Split_Defreach_Out_Set();
01461 if (sl->Lunit()) {
01462
01463
01464 sl->Lunit()->Split_Defreach_Out_Set();
01465 }
01466 }
01467 }
01468 }
01469
01470
01472 static BOOL
01473 Local_Live_In( LUNIT* lunit )
01475
01476
01477
01478
01479
01480
01482 {
01483 BB* bb = lunit->Gbb()->Bb();
01484 LRANGE* lrange = lunit->Lrange();
01485 TN* tn = lrange->Original_TN();
01486
01487 return
01488 GTN_SET_MemberP(BB_live_use(bb),tn) ||
01489 (lunit->Split_Defreach_Out() &&
01490 lunit->Spill_Below() &&
01491 !lunit->Has_Def());
01492 }
01493
01495 static void
01496 Mark_Live_In_Recur( LRANGE* lrange, GRA_BB* gbb )
01498
01499
01500
01501
01503 {
01504 GRA_BB_FLOW_NEIGHBOR_ITER iter;
01505
01506 if (!gbb_mgr.One_Set_MemberP(gbb) &&
01507 (!GTN_SET_MemberP(BB_live_def(gbb->Bb()), lrange->Original_TN()) ||
01508 GTN_SET_MemberP(BB_live_use(gbb->Bb()), lrange->Original_TN()))) {
01509 gbb_mgr.One_Set_Union1(gbb);
01510
01511 for (iter.Preds_Init(gbb); ! iter.Done(); iter.Step()) {
01512 GRA_BB* pred = iter.Current();
01513
01514 if ( lrange->Contains_BB(pred) ||
01515 pred->Spill_Above_Check(lrange)) {
01516
01517
01518
01519
01520
01521
01522
01523 Mark_Live_In_Recur(lrange,pred);
01524 } else if ( pred->Restore_Below_Check(lrange) ) {
01525
01526
01527
01528
01529
01530
01531 gbb_mgr.One_Set_Union1(pred);
01532 }
01533 }
01534 } else if ( gbb->Restore_Below_Check(lrange) ) {
01535
01536
01537
01538
01539
01540 gbb_mgr.One_Set_Union1(gbb);
01541 }
01542 }
01543
01545 static void
01546 Mark_Live_In( LRANGE* lrange, SPILL_LIST* load_list, SPILL_LIST* store_list )
01548
01549
01550
01551
01552
01554 {
01555 LRANGE_LUNIT_ITER iter;
01556
01557 gbb_mgr.Clear_One_Set();
01558
01559
01560
01561
01562 for (iter.Init(lrange); ! iter.Done(); iter.Step()) {
01563 LUNIT* lunit = iter.Current();
01564
01565 if ( Local_Live_In(lunit) )
01566 Mark_Live_In_Recur(lrange,lunit->Gbb());
01567 }
01568
01569
01570
01571
01572
01573 SPILL_LIST *sl;
01574 for (sl = store_list; sl != NULL; sl = sl->Next()) {
01575 if (!sl->Lunit()) {
01576 Mark_Live_In_Recur(lrange, sl->Gbb());
01577 }
01578 }
01579
01580
01581
01582 for (sl = load_list; sl != NULL; sl = sl->Next()) {
01583 if ( gbb_mgr.One_Set_MemberP(sl->Get_Gbb()) ) {
01584 sl->Split_Live_In_Set();
01585 }
01586 if (sl->Lunit()) {
01587
01588
01589 sl->Lunit()->Split_Live_In_Set();
01590 }
01591 }
01592 }
01593
01595 static BOOL
01596 Has_Successor_Not_In_LRANGE( GRA_BB* gbb, LRANGE* lrange,
01597 GRA_BB* exclude_succ = NULL)
01599
01600
01601
01603 {
01604 GRA_BB_FLOW_NEIGHBOR_ITER iter;
01605
01606 for (iter.Succs_Init(gbb); ! iter.Done(); iter.Step()) {
01607 GRA_BB* succ = iter.Current();
01608
01609 if ( ! lrange->Contains_BB(succ) )
01610 return TRUE;
01611
01612 #ifdef KEY
01613
01614
01615
01616 if (succ->Clobbers_Reg_Class(lrange->Rc()) &&
01617 !succ->Is_Live_In_LRANGE(lrange)) {
01618 return TRUE;
01619 }
01620
01621 if (GRA_optimize_boundary) {
01622
01623
01624
01625
01626 if (succ != exclude_succ) {
01627 LRANGE_BOUNDARY_BB *boundary_bb = lrange->Get_Boundary_Bb(succ->Bb());
01628 if (boundary_bb != NULL &&
01629 ! boundary_bb->Is_Live_In())
01630 return TRUE;
01631 }
01632 }
01633 #endif
01634 }
01635
01636 return FALSE;
01637 }
01638
01639 #ifdef KEY
01641 static BOOL
01642 Reg_Used_Before_By_Other_TNs(LUNIT* lunit)
01644
01645
01647 {
01648 OP *op;
01649 GRA_BB *gbb = lunit->Gbb();
01650 BB *bb = gbb->Bb();
01651 TN *tn = lunit->Lrange()->Tn();
01652 REGISTER reg = lunit->Lrange()->Reg();
01653 ISA_REGISTER_CLASS rc = TN_register_class(tn);
01654
01655 for (op = BB_first_op(bb); op != NULL; op = OP_next(op)) {
01656 #ifdef TARG_X8664
01657
01658
01659 if ((rc == ISA_REGISTER_CLASS_x87 && OP_mmx(op)) ||
01660 (rc == ISA_REGISTER_CLASS_mmx && OP_x87(op)))
01661 return TRUE;
01662 #endif
01663
01664
01665 for (int i = OP_opnds(op) - 1; i >= 0; i--) {
01666 TN *opnd_tn = OP_opnd(op, i);
01667
01668 if (opnd_tn == tn)
01669 return FALSE;
01670 LRANGE *lr = lrange_mgr.Get(opnd_tn);
01671 if (lr != NULL && lr->Allocated() && lr->Reg() == reg)
01672 return TRUE;
01673 }
01674
01675 for (int i = OP_results(op) - 1; i >= 0; i--) {
01676 TN *result_tn = OP_result(op, i);
01677 LRANGE *lr = lrange_mgr.Get(result_tn);
01678 if (lr != NULL && lr->Allocated() && lr->Reg() == reg)
01679 return TRUE;
01680 }
01681 }
01682
01683 return FALSE;
01684 }
01685
01686 static BOOL
01687 Reg_Used_After_By_Other_TNs(LUNIT* lunit)
01689
01690
01692 {
01693 OP *op;
01694 GRA_BB *gbb = lunit->Gbb();
01695 BB *bb = gbb->Bb();
01696 TN *tn = lunit->Lrange()->Tn();
01697 REGISTER reg = lunit->Lrange()->Reg();
01698 ISA_REGISTER_CLASS rc = TN_register_class(tn);
01699
01700 for (op = BB_last_op(bb); op != NULL; op = OP_prev(op)) {
01701 #ifdef TARG_X8664
01702
01703
01704 if ((rc == ISA_REGISTER_CLASS_x87 && OP_mmx(op)) ||
01705 (rc == ISA_REGISTER_CLASS_mmx && OP_x87(op)))
01706 return TRUE;
01707 #endif
01708
01709
01710 for (int i = OP_results(op) - 1; i >= 0; i--) {
01711 TN *result_tn = OP_result(op, i);
01712
01713 if (result_tn == tn)
01714 return FALSE;
01715 LRANGE *lr = lrange_mgr.Get(result_tn);
01716 if (lr != NULL && lr->Allocated() && lr->Reg() == reg)
01717 return TRUE;
01718 }
01719
01720 for (int i = OP_opnds(op) - 1; i >= 0; i--) {
01721 TN *opnd_tn = OP_opnd(op, i);
01722 LRANGE *lr = lrange_mgr.Get(opnd_tn);
01723 if (lr != NULL && lr->Allocated() && lr->Reg() == reg)
01724 return TRUE;
01725 }
01726 }
01727
01728
01729 return FALSE;
01730 }
01731 #endif
01732
01734 static void
01735 Move_Restore_Out_Of_Region( LUNIT* lunit )
01737
01738
01739
01741 {
01742 GRA_BB *gbb_pred;
01743 GRA_BB *gbb = lunit->Gbb();
01744 BB *bb = BB_Unique_Predecessor(gbb->Bb());
01745 LRANGE* lrange = lunit->Lrange();
01746
01747 DevAssert(bb != NULL,("Non-uniique region prolog.\n"));
01748 Is_True(BB_Unique_Successor(bb),
01749 ("Region prolog has multiple successors.\n"));
01750 gbb_pred = gbb_mgr.Get(bb);
01751 gbb_pred->Add_Live_Out_LRANGE(lrange);
01752 GRA_Trace_Place_LRANGE_GBB("load below",lrange,gbb_pred);
01753 gbb_pred->Restore_Below_Set(lrange);
01754 lunit->Gbb()->Add_Live_In_LRANGE(lrange);
01755 lunit->Restore_Above_Reset();
01756 }
01757
01759 static BOOL
01760 Move_Restore_Out_Of_LRANGE( LUNIT* lunit , SPILL_LIST** spill_list)
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01784 {
01785 BOOL do_move = FALSE;
01786 GRA_BB_FLOW_NEIGHBOR_ITER iter;
01787 LRANGE* lrange = lunit->Lrange();
01788 ISA_REGISTER_CLASS rc = lrange->Rc();
01789 REGISTER reg = lrange->Reg();
01790 BOOL callee_saves = REGISTER_SET_MemberP(REGISTER_CLASS_callee_saves(rc),reg);
01791 INT load_count = 0;
01792
01793 if (!GRA_optimize_placement) {
01794 return FALSE;
01795 }
01796
01797
01798 for (iter.Preds_Init(lunit->Gbb()); ! iter.Done(); iter.Step()) {
01799 GRA_BB* gbb = iter.Current();
01800 BB* bb = gbb->Bb();
01801
01802 if ( lrange->Contains_BB(gbb) ) {
01803
01804
01805
01806 if (BB_call(bb) && ! gbb->Is_Live_Out_LRANGE(lrange) && ! callee_saves ) {
01807 return FALSE;
01808 }
01809 #ifdef KEY
01810
01811
01812
01813 if (gbb->Clobbers_Reg_Class(rc) &&
01814 !gbb->Is_Live_Out_LRANGE(lrange)) {
01815 return FALSE;
01816 }
01817
01818 if (GRA_optimize_boundary) {
01819
01820
01821 if (! lrange->Contains_Internal_BB(gbb)) {
01822 LRANGE_BOUNDARY_BB *boundary_bb = lrange->Get_Boundary_Bb(gbb->Bb());
01823 if (! boundary_bb->Is_Live_Out())
01824 return FALSE;
01825 }
01826 }
01827 #endif
01828 do_move = TRUE;
01829 } else {
01830
01831 GRA_BB *exclude_succ = NULL;
01832 #ifdef KEY
01833 if (GRA_optimize_boundary ||
01834 lunit->Gbb()->Clobbers_Reg_Class(rc)) {
01835
01836
01837
01838 exclude_succ = lunit->Gbb();
01839 }
01840 #endif
01841 if (Has_Successor_Not_In_LRANGE(gbb,lrange,exclude_succ) || BB_call(bb))
01842 return FALSE;
01843 else if (BB_rid(bb) != BB_rid(lunit->Gbb()->Bb()))
01844 return FALSE;
01845
01846 load_count++;
01847 }
01848 }
01849
01850 if ( do_move == FALSE )
01851 return FALSE;
01852
01853 if (load_count > 0 && OPT_Space) {
01854
01855 return FALSE;
01856 }
01857
01858 #ifdef KEY
01859 if (GRA_optimize_boundary ||
01860 lunit->Gbb()->Clobbers_Reg_Class(rc)) {
01861
01862
01863
01864
01865 if (Reg_Used_Before_By_Other_TNs(lunit))
01866 return FALSE;
01867 }
01868 #endif
01869
01870 GRA_Trace_Place_LRANGE_GBB("moving load out",lrange,lunit->Gbb());
01871
01872
01873 for (iter.Preds_Init(lunit->Gbb()); ! iter.Done(); iter.Step()) {
01874 GRA_BB* gbb = iter.Current();
01875
01876
01877 gbb->Add_Live_Out_LRANGE(lrange);
01878
01879 if ( !lrange->Contains_BB(gbb) ) {
01880 GRA_Trace_Place_LRANGE_GBB("load below",lrange,gbb);
01881 gbb->Restore_Below_Set(lrange);
01882 SPILL_LIST *sl = SPILL_LIST_Create_Gbb(gbb,&MEM_local_nz_pool);
01883 *spill_list = (*spill_list)->Push(sl);
01884 }
01885
01886 }
01887
01888
01889 lunit->Gbb()->Add_Live_In_LRANGE(lrange);
01890 lunit->Restore_Above_Reset();
01891 return TRUE;
01892 }
01893
01895 static BOOL
01896 No_Successor_Has_Restore( SPILL_LIST *sl, LRANGE *lrange )
01898
01899
01900
01901
01902
01903
01905 {
01906 GRA_BB_FLOW_NEIGHBOR_ITER iter;
01907 LUNIT *lunit = sl->Lunit();
01908 GRA_BB *curgbb = sl->Gbb();
01909
01910 if ( lunit && lunit->Spill_Below_Sticks() ) {
01911 return FALSE;
01912 }
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924 if (curgbb &&
01925 (curgbb->Restore_Below_Check(lrange) ||
01926 GTN_SET_MemberP(BB_live_use(curgbb->Bb()),
01927 lrange->Original_TN()))) {
01928 return FALSE;
01929 }
01930
01931 for (iter.Succs_Init(sl->Get_Gbb()); ! iter.Done(); iter.Step()) {
01932 GRA_BB* gbb = iter.Current();
01933
01934 if ( gbb_mgr.One_Set_MemberP(gbb) )
01935 return FALSE;
01936 else if ( ! lrange->Contains_BB(gbb) )
01937 return FALSE;
01938 }
01939
01940 return TRUE;
01941 }
01942
01944 static BOOL
01945 Needs_Spill( LRANGE* lrange, GRA_BB* gbb )
01947
01948
01949
01950
01952 {
01953 LUNIT* lunit;
01954
01955 if ( ! lrange->Contains_BB(gbb) )
01956 return TRUE;
01957 else if ( lrange->Find_LUNIT_For_GBB(gbb,&lunit)
01958 && lunit->Restore_Above()
01959 ) {
01960 return TRUE;
01961 }
01962 else
01963 return FALSE;
01964 }
01965
01967 static BOOL
01968 Has_Predecessor_Not_In_LRANGE( GRA_BB *gbb, LRANGE* lrange,
01969 GRA_BB *exclude_pred = NULL)
01971
01972
01973
01975 {
01976 GRA_BB_FLOW_NEIGHBOR_ITER iter;
01977 REGISTER reg = lrange->Reg();
01978 ISA_REGISTER_CLASS rc = lrange->Rc();
01979 BOOL not_call_saved =
01980 ! REGISTER_SET_MemberP(REGISTER_CLASS_callee_saves(rc),reg);
01981
01982 for (iter.Preds_Init(gbb); ! iter.Done(); iter.Step()) {
01983 GRA_BB* pred = iter.Current();
01984
01985 if ( ! lrange->Contains_BB(pred) )
01986 return TRUE;
01987 if ( BB_call(pred->Bb()) && not_call_saved )
01988 return TRUE;
01989 #ifdef KEY
01990
01991
01992
01993 if (pred->Clobbers_Reg_Class(lrange->Rc()) &&
01994 !pred->Is_Live_Out_LRANGE(lrange)) {
01995 return TRUE;
01996 }
01997 if (GRA_optimize_boundary) {
01998
01999
02000
02001
02002 if (pred != exclude_pred) {
02003 LRANGE_BOUNDARY_BB *boundary_bb = lrange->Get_Boundary_Bb(pred->Bb());
02004 if (boundary_bb != NULL &&
02005 ! boundary_bb->Is_Live_Out())
02006 return TRUE;
02007 }
02008 }
02009 #endif
02010 }
02011
02012 return FALSE;
02013 }
02014
02016 static void
02017 Add_To_Predecessor_Live_Out( GRA_BB* gbb, LRANGE* lrange )
02019
02020
02021
02023 {
02024 GRA_BB_FLOW_NEIGHBOR_ITER iter;
02025
02026 for (iter.Preds_Init(gbb); ! iter.Done(); iter.Step()) {
02027 GRA_BB* pred = iter.Current();
02028
02029 pred->Add_Live_Out_LRANGE(lrange);
02030 }
02031 }
02032
02034 static BOOL
02035 Move_Spill_Out_Of_LRANGE( LUNIT* lunit , SPILL_LIST** spill_list)
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02054 {
02055 BOOL has_successor_not_needing_spill = FALSE;
02056 GRA_BB_FLOW_NEIGHBOR_ITER iter;
02057 LRANGE* lrange = lunit->Lrange();
02058 INT spill_count = 0;
02059
02060 if (!GRA_optimize_placement) {
02061 return FALSE;
02062 }
02063
02064
02065
02066 if ( lunit->Spill_Below_Sticks() )
02067 return FALSE;
02068
02069 for (iter.Succs_Init(lunit->Gbb()); ! iter.Done(); iter.Step()) {
02070 GRA_BB* gbb = iter.Current();
02071
02072 GRA_BB *exclude_pred = NULL;
02073 #ifdef KEY
02074 if (GRA_optimize_boundary ||
02075 lunit->Gbb()->Clobbers_Reg_Class(lrange->Rc())) {
02076
02077
02078
02079 exclude_pred = lunit->Gbb();
02080 }
02081 #endif
02082
02083 if ( ! Needs_Spill(lrange,gbb) )
02084 has_successor_not_needing_spill = TRUE;
02085 else if ( Has_Predecessor_Not_In_LRANGE(gbb,lrange,exclude_pred) )
02086 return FALSE;
02087 else if ( BB_rid(gbb->Bb()) != BB_rid(lunit->Gbb()->Bb()))
02088 return FALSE;
02089
02090 spill_count++;
02091 }
02092
02093 if ( ! has_successor_not_needing_spill )
02094 return FALSE;
02095
02096 if (spill_count > 1 && OPT_Space) {
02097
02098
02099
02100 return FALSE;
02101 }
02102
02103 #ifdef KEY
02104 if (GRA_optimize_boundary ||
02105 lunit->Gbb()->Clobbers_Reg_Class(lrange->Rc())) {
02106
02107
02108
02109 if (Reg_Used_After_By_Other_TNs(lunit))
02110 return FALSE;
02111 }
02112 #endif
02113
02114 GRA_Trace_Place_LRANGE_GBB("moving store out",lrange,lunit->Gbb());
02115
02116
02117 for (iter.Succs_Init(lunit->Gbb()); ! iter.Done(); iter.Step()) {
02118 GRA_BB* gbb = iter.Current();
02119
02120 if ( Needs_Spill(lrange,gbb) ) {
02121 GRA_Trace_Place_LRANGE_GBB("store above",lrange,gbb);
02122 gbb->Spill_Above_Set(lrange);
02123 gbb->Add_Live_In_LRANGE(lrange);
02124 Add_To_Predecessor_Live_Out(gbb,lrange);
02125 SPILL_LIST *sl = SPILL_LIST_Create_Gbb(gbb,&MEM_local_nz_pool);
02126 *spill_list = (*spill_list)->Push(sl);
02127 }
02128 }
02129
02130
02131 lunit->Spill_Below_Reset();
02132 return TRUE;
02133 }
02134
02136 static GRA_BB*
02137 Region_Pre_Header( GRA_BB* gbb )
02139
02140
02141
02142
02143
02145 {
02146 RID* rid = gbb->Region()->Rid();
02147 BB *bb;
02148 GRA_BB *result = NULL;
02149
02150 if (rid != NULL) {
02151 if (RID_type(rid) != RID_TYPE_swp) {
02152 bb = CGRIN_entry(RID_cginfo(rid));
02153 bb = BB_Unique_Predecessor(bb);
02154 if (bb != NULL) {
02155 result = gbb_mgr.Get(bb);
02156 }
02157 } else {
02158
02159
02160
02161 bb = gbb->Bb();
02162 do {
02163 bb = BB_prev(bb);
02164 DevAssert(bb != NULL,("Couldn't find region pre header for BB%d",
02165 BB_id(gbb->Bb())));
02166 }
02167 while (BB_rid(bb) == rid);
02168
02169 result = gbb_mgr.Get(bb);
02170 }
02171 if (result && !result->Region_Is_Complement()) {
02172 result = NULL;
02173 }
02174 }
02175
02176 return result;
02177 }
02178
02180 static BOOL
02181 Move_Spill_Code_Above_Region( LUNIT* lunit, BOOL move_restore,
02182 SPILL_LIST** spill_list )
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02198 {
02199 LUNIT *ph_lunit;
02200 LRANGE *lrange = lunit->Lrange();
02201 GRA_BB *gbb = lunit->Gbb();
02202 BB *bb = gbb->Bb();
02203 GRA_BB *ph_gbb = Region_Pre_Header(gbb);
02204
02205
02206 if (ph_gbb == NULL) {
02207 return FALSE;
02208 }
02209
02210 GRA_Trace_Place_LRANGE_GBB("store below preheader of region",
02211 lrange,ph_gbb);
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221 if (move_restore) {
02222 ph_gbb->Add_Live_Out_LRANGE(lrange);
02223 GRA_Trace_Place_LRANGE_GBB("load below",lrange,ph_gbb);
02224 ph_gbb->Restore_Below_Set(lrange);
02225 lunit->Gbb()->Add_Live_In_LRANGE(lrange);
02226 lunit->Restore_Above_Reset();
02227
02228
02229 SPILL_LIST *ph_sl = SPILL_LIST_Create_Gbb(ph_gbb,&MEM_local_nz_pool);
02230 ph_sl->Load_Below_Sticks_Set();
02231 *spill_list = (*spill_list)->Push(ph_sl);
02232 } else {
02233 if ( ! lrange->Find_LUNIT_For_GBB(ph_gbb,&ph_lunit) )
02234 ph_lunit = LUNIT_Create(lrange,ph_gbb);
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247 ph_lunit->Spill_Below_Set();
02248 Possibly_List_LUNIT(ph_lunit);
02249 ph_lunit->Spill_Below_Sticks_Set();
02250 lunit->Spill_Below_Reset();
02251
02252
02253 SPILL_LIST *ph_sl = SPILL_LIST_Create_Lunit(ph_lunit,&MEM_local_nz_pool);
02254 *spill_list = (*spill_list)->Push(ph_sl);
02255 }
02256 return TRUE;
02257 }
02258
02260 static void
02261 Check_Split_Borders(LRANGE *lr)
02263
02264
02265
02266
02267 {
02268 }
02269
02270
02272 static void
02273 Optimize_Placement(void)
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02309 {
02310 LRANGE_SPLIT_LIST_ITER sl_iter;
02311 LRANGE_LUNIT_ITER iter;
02312
02313
02314 for (sl_iter.Init(split_lranges_head); ! sl_iter.Done(); sl_iter.Step()) {
02315 LRANGE* split_lrange = sl_iter.Current();
02316 BOOL moved_reload = FALSE;
02317 SPILL_LIST* store_list_head = NULL;
02318 SPILL_LIST* load_list_head = NULL;
02319
02320 if ( ! split_lrange->Spilled() ) {
02321 GRA_Trace_Place(0,"Placing spills/restores for TN%d...",
02322 TN_number(split_lrange->Tn()));
02323
02324 MEM_POOL_Push(&MEM_local_nz_pool);
02325
02326
02327
02328
02329
02330
02331 BOOL change;
02332 do {
02333 change = FALSE;
02334 for (iter.Init(split_lrange); ! iter.Done(); iter.Step()) {
02335 LUNIT* lunit = iter.Current();
02336
02337 if ( lunit->Restore_Above() ) {
02338 if (lunit->Gbb()->Is_Region_Block(TRUE)) {
02339
02340
02341
02342
02343
02344 Move_Spill_Code_Above_Region( lunit, TRUE, &load_list_head);
02345 } else if ( Move_Restore_Out_Of_LRANGE(lunit, &load_list_head) ) {
02346 moved_reload = TRUE;
02347 change = TRUE;
02348 } else {
02349 SPILL_LIST *sl =
02350 SPILL_LIST_Create_Lunit(lunit,&MEM_local_nz_pool);
02351 load_list_head = load_list_head->Push(sl);
02352 }
02353 }
02354 if ( lunit->Spill_Below() ) {
02355 if (lunit->Gbb()->Is_Region_Block(TRUE)) {
02356
02357
02358 if (!Move_Spill_Code_Above_Region(lunit,FALSE,&store_list_head)){
02359 GRA_Trace_Place_LRANGE_GBB("must store in region",split_lrange,
02360 lunit->Gbb());
02361 Possibly_List_LUNIT(lunit);
02362 }
02363 }
02364 else if ( ! Move_Spill_Out_Of_LRANGE(lunit, &store_list_head) ) {
02365 Is_True(lunit->Gbb()->Region_Is_Complement(),
02366 ("Trying to move spill out of region in wrong place.\n"));
02367 SPILL_LIST *sl = SPILL_LIST_Create_Lunit(lunit,
02368 &MEM_local_nz_pool);
02369 store_list_head = store_list_head->Push(sl);
02370 } else {
02371 change = TRUE;
02372 }
02373 }
02374 }
02375 } while (change);
02376
02377
02378
02379
02380
02381
02382 Mark_Defreach_Out(split_lrange, store_list_head);
02383 Mark_Live_In(split_lrange, load_list_head, store_list_head);
02384
02385 gbb_mgr.Clear_One_Set();
02386
02387
02388
02389
02390 SPILL_LIST *sl;
02391 for (sl = load_list_head;
02392 sl != NULL;
02393 sl = sl->Next()) {
02394 GRA_BB *gbb = sl->Get_Gbb();
02395 LUNIT *lunit = sl->Lunit();
02396
02397 if (!sl->Split_Live_In() &&
02398 !sl->Load_Below_Sticks() &&
02399 GRA_remove_spills) {
02400 GRA_Trace_Place_LRANGE_GBB("load unnecessary - no reaching use",
02401 split_lrange, gbb);
02402 if (lunit) {
02403 lunit->Restore_Above_Reset();
02404 } else {
02405 gbb->Restore_Below_Reset(split_lrange);
02406 }
02407 } else {
02408 GRA_Trace_Place_LRANGE_GBB("must load",split_lrange,gbb);
02409
02410
02411
02412 gbb_mgr.One_Set_Union1(gbb);
02413 if (lunit) {
02414 Possibly_List_LUNIT(lunit);
02415 }
02416 }
02417 }
02418
02419
02420
02421
02422 for (sl = store_list_head;
02423 sl != NULL;
02424 sl = sl->Next()) {
02425 GRA_BB *gbb = sl->Get_Gbb();
02426 LUNIT *lunit = sl->Lunit();
02427
02428 if (!sl->Split_Defreach_Out() && GRA_remove_spills) {
02429
02430
02431
02432
02433 GRA_Trace_Place_LRANGE_GBB("store unnecessary -- no reaching def",
02434 split_lrange, gbb);
02435 if (lunit) {
02436 lunit->Spill_Below_Reset();
02437 } else {
02438 gbb->Spill_Above_Reset(split_lrange);
02439 }
02440
02441 } else if ( moved_reload && GRA_remove_spills &&
02442 #ifdef KEY
02443
02444
02445
02446
02447
02448 split_lrange->Contains_BB(gbb) &&
02449 #endif
02450 No_Successor_Has_Restore(sl, split_lrange)) {
02451
02452
02453
02454 GRA_Trace_Place_LRANGE_GBB("store unnecessary -- no successor "
02455 "with restore",
02456 split_lrange, gbb);
02457 if (lunit) {
02458 lunit->Spill_Below_Reset();
02459 } else {
02460 gbb->Spill_Above_Reset(split_lrange);
02461 }
02462
02463 } else {
02464 GRA_Trace_Place_LRANGE_GBB("must store",split_lrange,
02465 sl->Get_Gbb());
02466 if (lunit) {
02467 Possibly_List_LUNIT(lunit);
02468 }
02469 }
02470 }
02471 MEM_POOL_Pop(&MEM_local_nz_pool);
02472 if (GRA_Trace_Check_Splits()) {
02473
02474
02475 Check_Split_Borders(split_lrange);
02476 }
02477 }
02478 }
02479 }
02480
02482 static void
02483 Dumb_Placement(void)
02485
02486
02487
02488
02490 {
02491 LRANGE_SPLIT_LIST_ITER sl_iter;
02492 LRANGE_LUNIT_ITER iter;
02493
02494 for (sl_iter.Init(split_lranges_head); ! sl_iter.Done(); sl_iter.Step()) {
02495 LRANGE* split_lrange = sl_iter.Current();
02496
02497 if ( ! split_lrange->Spilled() ) {
02498 GRA_Trace_Place(0,"Placing spills/restores dumbly for TN%d...",
02499 TN_number(split_lrange->Tn()));
02500
02501 for (iter.Init(split_lrange); ! iter.Done(); iter.Step()) {
02502 LUNIT* lunit = iter.Current();
02503
02504 if ( lunit->Restore_Above() ) {
02505 GRA_Trace_Place_LRANGE_GBB("must load",split_lrange,
02506 lunit->Gbb());
02507 Possibly_List_LUNIT(lunit);
02508 }
02509 }
02510
02511 for (iter.Init(split_lrange); ! iter.Done(); iter.Step()) {
02512 LUNIT* lunit = iter.Current();
02513
02514 if ( lunit->Spill_Below() ) {
02515 GRA_Trace_Place_LRANGE_GBB("must store",split_lrange,
02516 lunit->Gbb());
02517 Possibly_List_LUNIT(lunit);
02518 }
02519 }
02520 }
02521 }
02522 }
02523
02525 static void
02526 Gen_Restores_Above_And_Spills_Below(void)
02528
02529
02530
02531
02532
02534 {
02535 LUNIT_SPILL_LIST_ITER iter;
02536
02537 for (iter.Init(lunits_with_spills_head); ! iter.Done(); iter.Step()) {
02538 LUNIT* lunit = iter.Current();
02539
02540 GRA_Trace_Split_LUNIT_Spill(lunit);
02541
02542 if ( ! (lunit->Live_In() || lunit->Live_Out()) )
02543 LUNIT_Spill(lunit);
02544 else {
02545 if ( lunit->Restore_Above() )
02546 LRANGE_Restore_Above(lunit->Lrange(),lunit->Gbb());
02547
02548 if ( lunit->Spill_Below() )
02549 LRANGE_Spill_Below(lunit->Lrange(),lunit->Gbb());
02550 }
02551 }
02552 }
02553
02555 static void
02556 Gen_Spills_Above_And_Restores_Below(void)
02558
02559
02560
02562 {
02563 BB* bb;
02564
02565 for ( bb = REGION_First_BB; bb != NULL; bb = BB_next(bb) ) {
02566 GRA_BB* gbb = gbb_mgr.Get(bb);
02567 ISA_REGISTER_CLASS rc;
02568
02569 lrange_mgr.Clear_One_Set();
02570
02571 FOR_ALL_ISA_REGISTER_CLASS( rc ) {
02572 if (gbb->Spill_Above(rc)) {
02573 LRANGE_SUBUNIVERSE *su = gbb->Region()->Subuniverse(rc);
02574 LRANGE* lrange;
02575 for (lrange = LRANGE_SET_ChooseS(gbb->Spill_Above(rc), su);
02576 lrange != LRANGE_SET_CHOOSE_FAILURE;
02577 lrange = LRANGE_SET_Choose_NextS(gbb->Spill_Above(rc),
02578 lrange, su)) {
02579 if ( ! lrange_mgr.One_Set_MemberP(lrange) ) {
02580 LRANGE_Spill_Above(lrange,gbb);
02581 lrange_mgr.One_Set_Union1(lrange);
02582 }
02583 }
02584 }
02585 }
02586
02587 lrange_mgr.Clear_One_Set();
02588
02589 FOR_ALL_ISA_REGISTER_CLASS( rc ) {
02590 if (gbb->Restore_Below(rc)) {
02591 LRANGE_SUBUNIVERSE *su = gbb->Region()->Subuniverse(rc);
02592 LRANGE* lrange;
02593 for (lrange = LRANGE_SET_ChooseS(gbb->Restore_Below(rc), su);
02594 lrange != LRANGE_SET_CHOOSE_FAILURE;
02595 lrange=LRANGE_SET_Choose_NextS(gbb->Restore_Below(rc),
02596 lrange, su)){
02597 if ( ! lrange_mgr.One_Set_MemberP(lrange) ) {
02598 LRANGE_Restore_Below(lrange,gbb);
02599 lrange_mgr.One_Set_Union1(lrange);
02600 }
02601 }
02602 }
02603 }
02604 }
02605 }
02606
02608
02609 void
02610 GRA_Spill(void)
02611 {
02612 LRANGE_LIST *l;
02613 ISA_REGISTER_CLASS rc;
02614 GRA_REGION_RC_NL_LRANGE_ITER iter;
02615 LUNIT_SPILL_LIST_ITER lu_iter;
02616 GRA_REGION *region = gra_region_mgr.Complement_Region();
02617
02618 GRA_Init_Trace_Memory();
02619
02620 spill_count = restore_count = 0;
02621 freq_spill_count = freq_restore_count = 0.0F;
02622
02623 Identify_Initialize_Glue_Blocks();
02624
02625 #ifdef TARG_IA64
02626 UNAT_Spill_Initialize();
02627 #endif
02628
02629
02630
02631 for ( l = spilled_lranges; l != NULL; l = LRANGE_LIST_rest(l) )
02632 LRANGE_Spill(LRANGE_LIST_first(l));
02633
02634
02635
02636
02637
02638 for (lu_iter.Init(lunits_with_spills_head); ! lu_iter.Done(); lu_iter.Step()){
02639 LUNIT* lunit = lu_iter.Current();
02640
02641 lunit->Spill_Listed_Reset();
02642 Possibly_List_LRANGE(lunit->Lrange());
02643 }
02644
02645 lunits_with_spills_head = NULL;
02646
02647 Optimize_Placement();
02648
02649 Gen_Restores_Above_And_Spills_Below();
02650 Divide_Glue_Code();
02651 Gen_Spills_Above_And_Restores_Below();
02652
02653
02654
02655 FOR_ALL_ISA_REGISTER_CLASS( rc ) {
02656 for (iter.Init(region,rc); ! iter.Done(); iter.Step()) {
02657 LRANGE* lrange = iter.Current();
02658
02659 Set_TN_spill(lrange->Tn(), TN_spill(lrange->Original_TN()));
02660 }
02661 }
02662
02663 GRA_Trace_Spill_Stats(freq_restore_count,restore_count,freq_spill_count,
02664 spill_count, priority_count);
02665 GRA_Trace_Memory("GRA_Spill()");
02666 }
02667
02669
02670 void
02671 GRA_Note_Restore_Above( LUNIT *lunit )
02672 {
02673 LRANGE* lrange = lunit->Lrange();
02674
02675 lunit->Restore_Above_Set();
02676 Possibly_List_LUNIT(lunit);
02677 }
02678
02680
02681 void
02682 GRA_Note_Save_Below( LUNIT *lunit )
02683 {
02684 lunit->Spill_Below_Set();
02685 Possibly_List_LUNIT(lunit);
02686 }
02687
02689
02690
02691 void
02692 GRA_Note_Spill( LRANGE* lrange )
02693 {
02694 GRA_Trace_Color_LRANGE("Spilling",lrange);
02695 if ( lrange->Type() == LRANGE_TYPE_COMPLEMENT ) {
02696 spilled_lranges = LRANGE_LIST_Push(lrange,spilled_lranges,GRA_pool);
02697 lrange->Spilled_Set();
02698 }
02699 else {
02700 DevAssert(lrange->Type() == LRANGE_TYPE_LOCAL &&
02701 !lrange->Has_Wired_Register(),
02702 ("Spilling a LRANGE of unexpected type"));
02703 }
02704 }
02705
02707
02708 void
02709 GRA_Spill_Initialize(void)
02710 {
02711 spilled_lranges = NULL;
02712 split_lranges_head = NULL;
02713 lunits_with_spills_head = NULL;
02714 }
02715
02717
02718
02719
02720
02721
02722 void
02723 GRA_Remove_Predicates_Save_Restore(void)
02724 {
02725 BB_LIST *elist;
02726 BB *bb;
02727 OP* op;
02728 BOOL found = FALSE;
02729
02730 for (elist = Entry_BB_Head; elist; elist = BB_LIST_rest(elist)) {
02731 found = FALSE;
02732 bb = BB_LIST_first(elist);
02733 for (op = BB_first_op(bb); op; op = OP_next(op)) {
02734 if (OP_save_predicates(op)) {
02735 TN *save_tn = OP_result(op,0);
02736 BB_Remove_Op(bb, op);
02737 found = TRUE;
02738 if (TN_is_global_reg(save_tn)) {
02739 LRANGE *lr = lrange_mgr.Get(save_tn);
02740 lr->No_Appearance_Set();
02741 }
02742 break;
02743 }
02744 }
02745
02746 #if !defined(TARG_IA64)
02747 Is_True(found || Exit_BB_Head == NULL,
02748 ("cannot find predicate register save at entry.\n"));
02749 #endif
02750
02751 }
02752
02753
02754 for (elist = Exit_BB_Head; elist; elist = BB_LIST_rest(elist)) {
02755 found = FALSE;
02756 bb = BB_LIST_first(elist);
02757 for (op = BB_last_op(bb); op; op = OP_prev(op)) {
02758 if (OP_restore_predicates(op)) {
02759 BB_Remove_Op(bb, op);
02760 found = TRUE;
02761 break;
02762 }
02763 }
02764
02765 #if !defined(TARG_IA64)
02766 Is_True(found, ("cannot find predicate register restore at exit.\n"));
02767 #endif
02768 }
02769 }