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 #ifdef USE_PCH
00059 #include "cg_pch.h"
00060 #endif // USE_PCH
00061 #pragma hdrstop
00062
00063 #define __STDC_LIMIT_MACROS
00064 #include <stdint.h>
00065 #include <alloca.h>
00066
00067 #include "defs.h"
00068 #include "mempool.h"
00069 #include "config.h"
00070 #include "tracing.h"
00071 #include "timing.h"
00072 #include "cgir.h"
00073 #include "targ_sim.h"
00074 #include "wn.h"
00075 #include "erglob.h"
00076 #include "ercg.h"
00077 #include "data_layout.h"
00078 #include "bb_set.h"
00079 #include "tn_set.h"
00080 #include "gtn_universe.h"
00081 #include "gtn_set.h"
00082 #include "gtn_tn_set.h"
00083 #include "tn_set.h"
00084 #include "cg.h"
00085 #include "cg_flags.h"
00086 #include "cg_internal.h"
00087 #include "cxx_memory.h"
00088 #include "calls.h"
00089 #include "cgexp.h"
00090 #include "register.h"
00091 #include "reg_live.h"
00092 #include "bbregs.h"
00093 #include "gra.h"
00094 #include "whirl2ops.h"
00095 #include "tn_map.h"
00096 #include "cg_spill.h"
00097 #include "cg_vector.h"
00098 #include "lra.h"
00099 #include "glob.h"
00100 #include "cgtarget.h"
00101 #include "targ_proc_properties.h"
00102 #include "hb_sched.h"
00103 #include "ebo.h"
00104 #ifdef TARG_X8664
00105 #include "config_lno.h"
00106 #endif
00107 #ifdef TARG_SL //minor_reg_alloc
00108 #include "gra_para_region.h"
00109 #endif
00110 #include "tag.h"
00111
00112 #ifdef KEY
00113 static BOOL large_asm_clobber_set[ISA_REGISTER_CLASS_MAX+1];
00114 #endif
00115 #ifdef TARG_IA64
00116 #define FIRST_INPUT_REG (32+REGISTER_MIN)
00117 #define LAST_STACKED_REG (127+REGISTER_MIN)
00118 #endif
00119
00120 #define TN_is_local_reg(r) (!(TN_is_dedicated(r) | TN_is_global_reg(r)))
00121
00122
00123 static REGISTER_SET Callee_Saved_Regs_Used[ISA_REGISTER_CLASS_MAX+1];
00124
00125
00126
00127
00128 typedef struct {
00129 BOOL reg[REGISTER_MAX+1];
00130 } AVAIL_REGS;
00131
00132 #ifdef TARG_IA64
00133
00134 static AVAIL_REGS has_nat_reg;
00135
00136
00137
00138 INT spill_nat_num;
00139 INT spill_global_num;
00140 #endif
00141
00142 static AVAIL_REGS avail_regs[ISA_REGISTER_CLASS_MAX+1];
00143
00144
00145 static REGISTER_SET avail_set[ISA_REGISTER_CLASS_MAX+1];
00146
00147
00148 static REGISTER_SET exclude_set[ISA_REGISTER_CLASS_MAX+1];
00149
00150
00151
00152 static REGISTER last_assigned_reg[ISA_REGISTER_CLASS_MAX+1];
00153
00154 #ifdef KEY
00155
00156
00157 typedef struct {
00158 INT reg[REGISTER_MAX+1];
00159 } LAST_FREED;
00160 static LAST_FREED last_freed[ISA_REGISTER_CLASS_MAX+1];
00161 #endif
00162
00163
00164 static VECTOR Insts_Vector;
00165 #define OP_VECTOR_element(v,i) ((OP *)VECTOR_element(v,i))
00166 #define Set_OP_VECTOR_element(v,i,op) (VECTOR_element(v,i) = (void *)op)
00167
00168
00169 static REGISTER_SET livethrough[ISA_REGISTER_CLASS_MAX+1];
00170
00171 static BOOL livethrough_computed;
00172
00173
00174
00175 static TN *unused_tn_def[ISA_REGISTER_CLASS_MAX+1];
00176
00177
00178 static BOOL do_global_locking = FALSE;
00179
00180
00181
00182
00183
00184 static MEM_POOL lra_pool;
00185
00186 static BOOL Trace_LRA;
00187 static BOOL Trace_LRA_Detail;
00188 static BOOL Trace_LRA_Spill;
00189 static BOOL Trace_LRA_Entry_Exit;
00190 static BOOL Trace_Move_GRA_Spills;
00191
00192
00193
00194
00195
00196
00197
00198
00199 typedef struct live_range {
00200 TN *tn;
00201 mINT16 first_def;
00202 #if defined(TARG_IA64)
00203 mINT16 first_unc_def;
00204 #endif
00205 mINT16 last_use;
00206 mINT16 exposed_use;
00207 mUINT8 def_cnt;
00208 mUINT8 use_cnt;
00209 mUINT8 flags;
00210 mREGISTER prefer_reg;
00211 mINT16 first_spill;
00212 struct live_range *next;
00213 } LIVE_RANGE;
00214
00215 #define LR_tn(lr) ((lr)->tn)
00216 #define LR_first_def(lr) ((lr)->first_def)
00217 #if defined(TARG_IA64)
00218 #define LR_first_unc_def(lr) ((lr)->first_unc_def)
00219 #endif
00220 #define LR_last_use(lr) ((lr)->last_use)
00221 #define LR_exposed_use(lr) ((lr)->exposed_use)
00222 #define LR_def_cnt(lr) ((lr)->def_cnt)
00223 #define LR_use_cnt(lr) ((lr)->use_cnt)
00224 #define LR_flags(lr) ((lr)->flags)
00225 #define LR_prefer_reg(lr) ((lr)->prefer_reg)
00226 #define LR_first_spill(lr) ((lr)->first_spill)
00227 #define LR_next(lr) ((lr)->next)
00228
00229 #define LR_ASSIGNED 0x1
00230 #define LR_ADDED 0x2
00231 #define LR_RELOADABLE 0x4
00232 #define LR_FAT_ALLOCATED 0x8 // LR was allocated real register by fat point
00233 #define LR_BYTEABLE 0x10 // LR requires a byte-accessible register
00234
00235 #define LR_assigned(lr) (LR_flags(lr) & LR_ASSIGNED)
00236 #define Set_LR_assigned(lr) (LR_flags(lr) |= LR_ASSIGNED)
00237 #define LR_added(lr) (LR_flags(lr) & LR_ADDED)
00238 #define Set_LR_added(lr) (LR_flags(lr) |= LR_ADDED)
00239 #define LR_reloadable(lr) (LR_flags(lr) & LR_RELOADABLE)
00240 #define Set_LR_reloadable(lr) (LR_flags(lr) |= LR_RELOADABLE)
00241 #define Reset_LR_reloadable(lr) (LR_flags(lr) &= ~LR_RELOADABLE)
00242 #define LR_fat_allocated(lr) (LR_flags(lr) & LR_FAT_ALLOCATED)
00243 #define Set_LR_fat_allocated(lr)(LR_flags(lr) |= LR_FAT_ALLOCATED)
00244 #define Reset_LR_fat_allocated(lr)(LR_flags(lr) &= ~LR_FAT_ALLOCATED)
00245 #ifdef TARG_X8664
00246 #define LR_byteable(lr) (LR_flags(lr) & LR_BYTEABLE)
00247 #define Set_LR_byteable(lr) (LR_flags(lr) |= LR_BYTEABLE)
00248 #endif
00249
00250 #define LR_Is_Undefined_Local(lr) \
00251 (TN_is_local_reg(LR_tn(lr)) && LR_def_cnt(lr) == 0)
00252
00253
00254 static LIVE_RANGE *Live_Range_List;
00255
00256 static hTN_MAP live_range_map;
00257
00258
00259
00260
00261 static INT Trip_Count;
00262 #define MAX_TRIP_COUNT 128
00263
00264 static ST *Magic_Spill_Location;
00265
00266
00267 static VECTOR Live_LRs_Vector;
00268 #define LR_VECTOR_element(v,i) ((LIVE_RANGE *)VECTOR_element(v,i))
00269
00270
00271 static BB_OP_MAP op_to_opnum;
00272
00273
00274
00275 typedef enum {
00276 SPILL_NONE,
00277 SPILL_GLOBAL_REG,
00278 SPILL_LIVE_RANGE,
00279 SPILL_MOVE_DEF,
00280 SPILL_MOVE_USE
00281 } SPILL_KIND;
00282
00283 typedef struct spill_candidate {
00284 SPILL_KIND spill_kind;
00285 INT spill_num;
00286 union {
00287 struct {
00288 mREGISTER global_spill_reg;
00289 mISA_REGISTER_CLASS spill_cl;
00290 } s1;
00291 LIVE_RANGE *spill_lr;
00292 struct {
00293 LIVE_RANGE *move_lr;
00294 mUINT16 from;
00295 mUINT16 to;
00296 } s2;
00297 } u1;
00298 float cost;
00299 INT benefit;
00300 struct spill_candidate *next;
00301 } SPILL_CANDIDATE;
00302
00303
00304
00305
00306 typedef INT32 FAT_POINTS_TYPE;
00307 #define FAT_POINTS_MAX INT32_MAX
00308 #define FAT_POINTS_MIN INT32_MIN
00309 static FAT_POINTS_TYPE *fat_points;
00310 static REGISTER last_infinite_freed;
00311 static ISA_REGISTER_CLASS failing_class;
00312 static hTN_MAP fat_point_regs_map;
00313 static BOOL use_fat_point_regs;
00314 static REGISTER reg_infinite;
00315 static INT fatpoint_min;
00316 static TN_SET *bb_live;
00317 static INT local_spills = 0;
00318 static INT global_spills = 0;
00319 static INT trace_tn = 0;
00320 static INT trace_bb = 0;
00321 static INT trace_op = 0;
00322 static ISA_REGISTER_CLASS trace_cl = (ISA_REGISTER_CLASS)2;
00323 #define Calculating_Fat_Points() (failing_class != ISA_REGISTER_CLASS_UNDEFINED)
00324
00325
00326
00327
00328
00329 #define Always_Trace(t) (t)
00330 #define Do_LRA_Trace(t) ((t) && !Calculating_Fat_Points())
00331 #define Do_LRA_Fat_Point_Trace(t) ((t) && Calculating_Fat_Points())
00332
00333 #ifdef TARG_X8664
00334 static mBOOL float_reg_could_be_128bit[REGISTER_MAX + 1];
00335 #endif
00336
00337 #ifdef KEY
00338
00339 static BOOL Need_Dep_Graph_For_Mark_Reloadable_Live_Ranges;
00340 #endif
00341
00342
00343
00344
00345
00346
00347
00348 inline REGISTER
00349 LRA_TN_register(TN *tn)
00350 {
00351 REGISTER reg;
00352
00353
00354
00355
00356
00357 reg = TN_register(tn);
00358 if (use_fat_point_regs && reg == REGISTER_UNDEFINED) {
00359 return((REGISTER)(INTPTR) hTN_MAP_Get(fat_point_regs_map, tn));
00360 }
00361 return(reg);
00362 }
00363
00364 inline void
00365 LRA_TN_Allocate_Register(TN *tn, REGISTER reg)
00366 {
00367
00368
00369
00370
00371 if (use_fat_point_regs && reg > REGISTER_MAX) {
00372 hTN_MAP_Set(fat_point_regs_map, tn, (void *)(INTPTR) reg);
00373 } else {
00374 TN_Allocate_Register(tn, reg);
00375 }
00376 }
00377 #undef TN_register
00378 #undef TN_Allocate_Register
00379 #define TN_register(tn) TN_dont_use_tn_register_error(tn)
00380 #define TN_Allocate_Register(tn) TN_dont_use_tn_Allocate_Register_error(tn)
00381
00382
00383
00384
00385
00386
00387 static void
00388 LRA_Print_Liveness()
00389 {
00390 INT live_count;
00391 TN *tn;
00392
00393 for (tn = TN_SET_Choose(bb_live), live_count=0;
00394 tn != TN_SET_CHOOSE_FAILURE;
00395 tn = TN_SET_Choose_Next(bb_live, tn), live_count++);
00396
00397 fprintf(TFile,"<lra> Live at OP:%d (lc=%d): ", trace_op, live_count);
00398 TN_SET_Print(bb_live, TFile);
00399 fprintf(TFile,"\n");
00400 }
00401
00402 static void
00403 Print_Live_Across()
00404 {
00405 INT cnt = 0;
00406 fprintf(TFile,"<lra> Live across %d: ", trace_op);
00407
00408 for (INT i = 0; i < VECTOR_count(Live_LRs_Vector); i++) {
00409 LIVE_RANGE *lr = LR_VECTOR_element (Live_LRs_Vector, i);
00410 if (LR_first_def(lr) < trace_op && LR_last_use(lr) > trace_op) {
00411 cnt++;
00412 fprintf(TFile," TN%d", TN_number(LR_tn(lr)));
00413 }
00414 }
00415 fprintf(TFile,"(lc=%d)\n", cnt);
00416 }
00417
00418
00419
00420
00421
00422 static inline void
00423 Mark_For_Removal(OP *op)
00424 {
00425 OP_Change_To_Noop(op);
00426 }
00427
00428
00429
00430
00431 inline BOOL
00432 Is_Marked_For_Removal(OP *op)
00433 {
00434 return OP_code(op) == TOP_noop;
00435 }
00436
00437
00438
00439
00440 static BOOL
00441 Check_Allow_Reorder() {
00442 if ((CG_opt_level > 1) &&
00443 (Trip_Count <= CG_opt_level) &&
00444 !Get_Trace (TP_ALLOC, 0x2000)) {
00445 return TRUE;
00446 }
00447 return FALSE;
00448 }
00449
00450
00451
00452
00453
00454 static BOOL
00455 Check_Allow_Reschedule()
00456 {
00457 if (Check_Allow_Reorder() &&
00458 Trip_Count == 1 &&
00459 !Get_Trace (TP_ALLOC, 0x0200)) {
00460 return TRUE;
00461 }
00462 return FALSE;
00463 }
00464
00465
00466
00467
00468 inline void
00469 Clobber_Op_Info(INT opnum, ISA_REGISTER_CLASS spill_cl)
00470 {
00471 Set_OP_VECTOR_element(Insts_Vector, opnum, NULL);
00472 #ifdef KEY
00473 if (fat_points)
00474 #endif
00475 fat_points[opnum] = -1;
00476 }
00477
00478
00479
00480
00481
00482 static BOOL
00483 Op_Uses_TN(TN *spill_tn, INT opnum)
00484 {
00485 BOOL is_local_tn = TN_is_local_reg (spill_tn);
00486 REGISTER spill_reg = REGISTER_UNDEFINED;
00487 OP *op = OP_VECTOR_element(Insts_Vector, opnum);
00488 ISA_REGISTER_CLASS cl = TN_register_class(spill_tn);
00489
00490 if (!is_local_tn) {
00491 spill_reg = LRA_TN_register(spill_tn);
00492 } else {
00493 spill_reg = REGISTER_UNDEFINED;
00494 }
00495
00496
00497
00498
00499 return (op == NULL || (is_local_tn && OP_Refs_TN (op, spill_tn)) ||
00500 (!is_local_tn && OP_Refs_Reg (op, cl, spill_reg)));
00501 }
00502
00503 static void Print_Avail_Set (BB *bb)
00504 {
00505 REGISTER reg;
00506 ISA_REGISTER_CLASS cl;
00507
00508 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00509 fprintf (TFile, "(BB:%d, cl:%d) \n\tAvail:", BB_id(bb), cl);
00510 REGISTER_SET_Print (avail_set[cl], TFile);
00511 fprintf (TFile, "\n\tAvail(Registers):");
00512 FOR_ALL_REGISTER_SET_members (avail_set[cl], reg) {
00513 fprintf (TFile, " %s", REGISTER_name (cl, reg));
00514 }
00515 if (!CG_localize_tns) {
00516 fprintf (TFile, "\n\tGRA Grant:");
00517 REGISTER_SET_Print (GRA_Local_Register_Grant (bb, cl), TFile);
00518 fprintf (TFile, "\n\tLRA Request: %d", LRA_Register_Request (bb, cl));
00519 }
00520 fprintf (TFile, "\n");
00521 }
00522 }
00523
00524
00525 #ifndef TARG_X8664
00526 static
00527 #endif
00528 REGISTER Single_Register_Subclass (ISA_REGISTER_SUBCLASS subclass)
00529 {
00530 REGISTER_SET subclass_regs = REGISTER_SUBCLASS_members(subclass);
00531 if (REGISTER_SET_Size(subclass_regs) == 1) {
00532 return REGISTER_SET_Choose(subclass_regs);
00533 }
00534 return REGISTER_UNDEFINED;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543 static void Init_Avail_Set (BB *bb)
00544 {
00545 REGISTER reg;
00546 ISA_REGISTER_CLASS cl;
00547 OP *op;
00548 INT i;
00549
00550 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00551 if (CG_localize_tns) {
00552
00553
00554
00555
00556
00557 avail_set[cl] =
00558 REGISTER_SET_Difference (REGISTER_CLASS_allocatable(cl),
00559 REGISTER_CLASS_callee_saves(cl));
00560 #ifdef HAS_STACKED_REGISTERS
00561 REGISTER_SET avail_stacked =
00562 REGISTER_Get_Stacked_Avail_Set(ABI_PROPERTY_stacked, cl);
00563 avail_set[cl] = REGISTER_SET_Difference(avail_set[cl],
00564 REGISTER_CLASS_stacked(cl));
00565 avail_set[cl] = REGISTER_SET_Union(avail_set[cl], avail_stacked);
00566 #endif
00567 if (!BB_exit(bb)) {
00568 avail_set[cl] = REGISTER_SET_Union(avail_set[cl],
00569 Callee_Saved_Regs_Used[cl]);
00570 }
00571 }
00572 else {
00573
00574 avail_set[cl] = GRA_Local_Register_Grant (bb, cl);
00575 exclude_set[cl] = REGISTER_SET_EMPTY_SET;
00576 if (BB_call(bb)) {
00577
00578
00579 OP *call_op = BB_last_op(bb);
00580 if ((call_op != NULL) &&
00581 OP_call(call_op) &&
00582 OP_cond_def(call_op)) {
00583
00584
00585 avail_set[cl] = REGISTER_SET_Union (
00586 avail_set[cl],
00587 REGISTER_SET_Difference (REGISTER_CLASS_function_value(cl),
00588 REGISTER_CLASS_caller_saves(cl)));
00589 } else {
00590 avail_set[cl] = REGISTER_SET_Union (
00591 avail_set[cl], REGISTER_CLASS_caller_saves(cl));
00592 }
00593 }
00594 if (BB_mod_rotating_registers(bb) ||
00595 Is_Predicate_REGISTER_CLASS(cl) && BB_mod_pred_rotating_registers(bb)) {
00596 exclude_set[cl] = REGISTER_Get_Requested_Rotating_Registers(cl);
00597 avail_set[cl] = REGISTER_SET_Difference (avail_set[cl], exclude_set[cl]);
00598 }
00599 }
00600 }
00601
00602
00603
00604
00605
00606 FOR_ALL_BB_OPs_FWD (bb, op) {
00607 for (i = 0; i < OP_results(op); ++i) {
00608 TN *result_tn = OP_result(op, i);
00609 if (!TN_is_local_reg(result_tn)) {
00610 reg = LRA_TN_register(result_tn);
00611 cl = TN_register_class (result_tn);
00612 avail_set[cl] = REGISTER_SET_Difference1 (avail_set[cl], reg);
00613 }
00614 }
00615 }
00616
00617 if (Do_LRA_Trace(Trace_LRA)) {
00618 Print_Avail_Set (bb);
00619 }
00620 }
00621
00622
00623 static void
00624 Init_Insts_Vector (BB *bb, MEM_POOL *pool)
00625 {
00626 OP *op;
00627
00628 Insts_Vector = VECTOR_Init (BB_length(bb)+1, pool);
00629
00630 VECTOR_Add_Element (Insts_Vector, NULL);
00631 FOR_ALL_BB_OPs_FWD (bb, op) {
00632 VECTOR_Add_Element (Insts_Vector, op);
00633 }
00634
00635 if (VECTOR_count(Insts_Vector) != (BB_length(bb)+1)) {
00636 fprintf (TFile, "BAD VECTOR: length=%d\n", VECTOR_count(Insts_Vector));
00637 Print_BB (bb);
00638 }
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648 static LIVE_RANGE *
00649 LR_For_TN (TN *tn)
00650 {
00651 LIVE_RANGE *lr;
00652
00653 if (!TN_is_local_reg(tn) && (LRA_TN_register(tn) != REGISTER_UNDEFINED)) {
00654 tn = Build_Dedicated_TN (TN_register_class(tn), LRA_TN_register(tn), 0);
00655 }
00656 lr = (LIVE_RANGE *) hTN_MAP_Get (live_range_map, tn);
00657 return lr;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666 static LIVE_RANGE *
00667 Create_LR_For_TN (TN *tn, BB *bb, BOOL in_lra, MEM_POOL *pool)
00668 {
00669 LIVE_RANGE *lr;
00670 BOOL local_lr = TN_is_local_reg(tn);
00671 TN *orig_tn = tn;
00672 ISA_REGISTER_CLASS cl = TN_register_class(tn);
00673 REGISTER reg = LRA_TN_register(tn);
00674
00675 if (!local_lr && (reg != REGISTER_UNDEFINED)) {
00676 tn = Build_Dedicated_TN (cl, reg, 0);
00677 }
00678 lr = (LIVE_RANGE *) hTN_MAP_Get (live_range_map, tn);
00679 if (lr == NULL) {
00680 lr = TYPE_MEM_POOL_ALLOC (LIVE_RANGE, pool);
00681 bzero (lr, sizeof(LIVE_RANGE));
00682 LR_tn(lr) = orig_tn;
00683 LR_next(lr) = Live_Range_List;
00684
00685
00686
00687
00688
00689 LR_first_spill(lr) = 1;
00690
00691
00692
00693 if (!local_lr && (!in_lra || !REGISTER_SET_MemberP (avail_set[cl], reg))) {
00694
00695 LR_last_use(lr) = BB_length(bb)+1;
00696
00697 LR_use_cnt(lr)++;
00698 }
00699 Live_Range_List = lr;
00700 hTN_MAP_Set (live_range_map, tn, lr);
00701 }
00702 else if (LR_tn(lr) != orig_tn) {
00703 #ifdef TARG_X8664
00704
00705
00706 Is_True(TN_is_dedicated(tn), ("Create_LR_For_TN: not dedicated TN"));
00707 if (TN_size(tn) >= TN_size(LR_tn(lr)))
00708 LR_tn(lr) = tn;
00709 else {
00710 ISA_REGISTER_CLASS cl = TN_register_class(LR_tn(lr));
00711 REGISTER reg = LRA_TN_register(LR_tn(lr));
00712 TN *ded_tn = Build_Dedicated_TN (cl, reg, TN_size(LR_tn(lr)));
00713 LR_tn(lr) = ded_tn;
00714 }
00715 #else
00716 LR_tn(lr) = tn;
00717 #endif
00718 }
00719 return lr;
00720 }
00721
00722
00723 static void
00724 Print_BB_For_LRA (BB *bb)
00725 {
00726 OP *op;
00727 INT i;
00728 fprintf (TFile, "--------------------------------------------\n");
00729 fprintf (TFile, "LRA for BB:%d trip_count:%d\n", BB_id(bb), Trip_Count);
00730 fprintf (TFile, "--------------------------------------------\n");
00731 i = 0;
00732 FOR_ALL_BB_OPs_FWD (bb, op) {
00733 i++;
00734 fprintf (TFile, "OP:%2d> ", i);
00735 Print_OP_No_SrcLine (op);
00736 }
00737 }
00738
00739
00740 static void
00741 Print_Live_Range (LIVE_RANGE *lr)
00742 {
00743 fprintf (TFile, " %s_LR>TN%d %3d(%d) to %3d(%d), exposed:%d\n",
00744 TN_is_local_reg(LR_tn(lr)) ? "LOCAL" : "GLOBAL",
00745 TN_number(LR_tn(lr)), LR_first_def(lr), LR_def_cnt(lr),
00746 LR_last_use(lr), LR_use_cnt(lr), LR_exposed_use(lr));
00747 }
00748
00749
00750 static void
00751 Print_Live_Ranges (BB *bb)
00752 {
00753 LIVE_RANGE *lr;
00754
00755 fprintf (TFile, "--------------------------------------------\n");
00756 fprintf (TFile, "LIVE RANGES for BB%d\n", BB_id(bb));
00757 fprintf (TFile, "--------------------------------------------\n");
00758 for (lr = Live_Range_List; lr != NULL; lr = LR_next(lr)) {
00759 Print_Live_Range (lr);
00760 }
00761 }
00762
00763
00764
00765 static void
00766 Mark_Use (TN *tn, OP *op, INT opnum, BB *bb, BOOL in_lra,
00767 INT res_opnd_idx, BOOL is_result, MEM_POOL *pool)
00768 {
00769 LIVE_RANGE *clr;
00770
00771 clr = Create_LR_For_TN (tn, bb, in_lra, pool);
00772
00773 if (!TN_is_local_reg(tn)) {
00774 if (LR_def_cnt(clr) == 0) {
00775 LR_exposed_use(clr) = opnum;
00776 }
00777
00778 LR_use_cnt(clr)++;
00779 #ifdef KEY
00780
00781
00782
00783 if (LR_last_use(clr) != BB_length(bb)+1)
00784 LR_last_use(clr) = opnum;
00785 #endif
00786 }
00787 else {
00788 #ifdef TARG_X8664
00789 if (!TN_is_preallocated (tn))
00790 #endif
00791 LRA_TN_Allocate_Register (tn, REGISTER_UNDEFINED);
00792 if (LR_def_cnt(clr) == 0) {
00793
00794 if (!OP_dummy(op) && in_lra && (!BB_entry(bb) || (TFile != stdout))) {
00795
00796
00797
00798 DevWarn ("TN%d(PREG%d) used before definition in BB:%d",
00799 TN_number(tn), TN_To_PREG(tn), BB_id(bb));
00800 #ifdef TARG_X8664
00801 #if 0
00802
00803
00804
00805
00806 if( !CGTARG_Is_Preference_Copy(op) ){
00807 FmtAssert ( FALSE, ("TN%d(PREG%d) used before definition in BB:%d",
00808 TN_number(tn), TN_To_PREG(tn), BB_id(bb)));
00809 }
00810 #endif
00811 #endif
00812 }
00813 LR_exposed_use(clr) = opnum;
00814 }
00815
00816 LR_last_use(clr) = opnum;
00817 LR_use_cnt(clr)++;
00818 }
00819 #ifdef TARG_X8664
00820
00821 if (OP_code(op) == TOP_asm) {
00822 ASM_OP_ANNOT* asm_info = (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, op);
00823 ISA_REGISTER_SUBCLASS subclass =
00824 is_result ? ASM_OP_result_subclass(asm_info)[res_opnd_idx] :
00825 ASM_OP_opnd_subclass(asm_info)[res_opnd_idx];
00826 if (subclass == ISA_REGISTER_SUBCLASS_m32_8bit_regs) {
00827 Set_LR_byteable(clr);
00828 }
00829 } else if (Is_Target_32bit() &&
00830 ((is_result && OP_result_size(op, res_opnd_idx) == 8) ||
00831 (!is_result && OP_opnd_size(op, res_opnd_idx) == 8))) {
00832 Set_LR_byteable(clr);
00833 }
00834 #endif
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 static void
00848 Setup_Live_Ranges (BB *bb, BOOL in_lra, MEM_POOL *pool)
00849 {
00850 INT opnum;
00851
00852
00853
00854
00855
00856 live_range_map = hTN_MAP_Create (pool);
00857 Live_Range_List = NULL;
00858
00859 Init_Insts_Vector (bb, pool);
00860
00861 for (opnum = 1; opnum <= BB_length(bb); opnum++) {
00862 OP *op = OP_VECTOR_element (Insts_Vector, opnum);
00863 INT opndnum;
00864 INT resnum;
00865
00866
00867 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
00868 TN *tn = OP_opnd(op, opndnum);
00869 #ifdef TARG_IA64
00870 LIVE_RANGE *clr;
00871
00872 if (!TN_is_register(tn)) continue;
00873
00874 clr = Create_LR_For_TN (tn, bb, in_lra, pool);
00875
00876 if (!TN_is_local_reg(tn)) {
00877 if (LR_def_cnt(clr) == 0) {
00878 LR_exposed_use(clr) = opnum;
00879 }
00880
00881 LR_use_cnt(clr)++;
00882 }
00883 else {
00884 LRA_TN_Allocate_Register (tn, REGISTER_UNDEFINED);
00885 if (LR_def_cnt(clr) == 0) {
00886
00887 if (!OP_dummy(op) && in_lra && (!BB_entry(bb) || (TFile != stdout))) {
00888
00889
00890
00891 DevWarn ("TN%d(PREG%d) used before definition in BB:%d",
00892 TN_number(tn), TN_To_PREG(tn), BB_id(bb));
00893 }
00894 LR_exposed_use(clr) = opnum;
00895 }
00896
00897 LR_last_use(clr) = opnum;
00898 LR_use_cnt(clr)++;
00899 }
00900 #else
00901 if (TN_is_register(tn))
00902 Mark_Use (tn, op, opnum, bb, in_lra, opndnum, FALSE, pool);
00903 #endif
00904 }
00905
00906
00907 for (resnum = 0; resnum < OP_results(op); ++resnum) {
00908 #ifdef KEY
00909 if (OP_cond_def(op)) {
00910 TN *tn = OP_result(op, resnum);
00911 if (TN_is_register(tn)) {
00912 Mark_Use (tn, op, opnum, bb, in_lra, resnum, TRUE, pool);
00913 }
00914 }
00915 #endif
00916 TN *tn = OP_result(op, resnum);
00917 LIVE_RANGE *clr = Create_LR_For_TN (tn, bb, in_lra, pool);
00918 if (OP_cond_def(op) &&
00919 TN_is_global_reg(tn) &&
00920 (!TN_is_dedicated(tn) ||
00921 (CGTARG_Is_Preference_Copy(op) &&
00922 TN_is_local_reg(OP_opnd(op,CGTARG_Copy_Operand(op))) &&
00923 TN_spill(OP_opnd(op,CGTARG_Copy_Operand(op))))) &&
00924 (LRA_TN_register(tn) != REGISTER_UNDEFINED) &&
00925 !REGISTER_SET_MemberP(avail_set[TN_register_class(tn)], LRA_TN_register(tn))) {
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 if (Do_LRA_Trace(Trace_LRA_Detail)) {
00938 fprintf (TFile, "OP:%d>> don't reuse result reg >> ", opnum); Print_OP_No_SrcLine (op);
00939 }
00940
00941 LR_exposed_use(clr) = opnum;
00942
00943 }
00944 if (LR_def_cnt(clr) == 0) {
00945 LR_first_def(clr) = opnum;
00946 }
00947 #if defined(TARG_IA64)
00948 if (LR_first_unc_def(clr) == 0 && !OP_cond_def(op)) {
00949 LR_first_unc_def(clr) = opnum;
00950 }
00951 #endif
00952 LR_def_cnt(clr)++;
00953 if (TN_is_local_reg(tn)) {
00954 #ifdef TARG_X8664
00955 if (!TN_is_preallocated (tn))
00956 #endif
00957 LRA_TN_Allocate_Register (tn, REGISTER_UNDEFINED);
00958 LR_last_use(clr) = opnum;
00959 if (CGTARG_Is_Preference_Copy(op)) {
00960 TN *src_tn = OP_opnd(op, CGTARG_Copy_Operand(op));
00961 if (!TN_is_local_reg(src_tn))
00962 LR_prefer_reg(clr) = LRA_TN_register(src_tn);
00963 }
00964 }
00965 else {
00966 if (CGTARG_Is_Preference_Copy(op)) {
00967 TN *src_tn = OP_opnd(op,CGTARG_Copy_Operand(op));
00968 if (TN_is_local_reg(src_tn)) {
00969 LIVE_RANGE *src_lr = LR_For_TN (src_tn);
00970 LR_prefer_reg(src_lr) = LRA_TN_register(tn);
00971 }
00972 }
00973 }
00974 #ifdef TARG_X8664
00975
00976 if (OP_code(op) == TOP_asm) {
00977 ASM_OP_ANNOT* asm_info = (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, op);
00978 ISA_REGISTER_SUBCLASS subclass =
00979 ASM_OP_result_subclass(asm_info)[resnum];
00980 if (subclass == ISA_REGISTER_SUBCLASS_m32_8bit_regs) {
00981 Set_LR_byteable(clr);
00982 }
00983 } else if (Is_Target_32bit() &&
00984 OP_result_size(op, resnum) == 8) {
00985 Set_LR_byteable(clr);
00986 }
00987 #endif
00988 }
00989 }
00990 }
00991
00992
00993 static BOOL
00994 Is_OP_Spill_Load (OP *op, ST *spill_loc)
00995 {
00996 if (!OP_load(op)) return FALSE;
00997 #ifdef TARG_IA64
00998 if (!OP_spill_restore(op)) return FALSE;
00999 #endif
01000
01001 INT n = TOP_Find_Operand_Use(OP_code(op), OU_offset);
01002 if (n < 0) {
01003 return (TN_spill(OP_result(op,0)) == spill_loc);
01004 }
01005
01006 TN *ctn = OP_opnd(op, n);
01007 return (TN_is_constant(ctn) &&
01008 TN_is_symbol(ctn) &&
01009 TN_var(ctn) == spill_loc);
01010 }
01011
01012 static BOOL
01013 Is_OP_Spill_Store (OP *op, ST *spill_loc)
01014 {
01015 if (!OP_store(op)) return FALSE;
01016
01017 INT n = TOP_Find_Operand_Use(OP_code(op), OU_offset);
01018 if (n < 0) {
01019 n = TOP_Find_Operand_Use(OP_code(op), OU_storeval);
01020 if (n < 0) return FALSE;
01021 return (TN_spill(OP_opnd(op,n)) == spill_loc);
01022 }
01023
01024 TN *ctn = OP_opnd(op, n);
01025 return (TN_is_constant(ctn) &&
01026 TN_is_symbol(ctn) &&
01027 TN_var(ctn) == spill_loc);
01028 }
01029
01030
01031 #ifdef TARG_X8664
01032
01033 static BOOL
01034 Is_Readonly_Mem_Load (OP *op)
01035 {
01036 int i;
01037
01038
01039 for (i = 0; i < OP_opnds(op); i++) {
01040 TN *opnd_tn = OP_opnd(op,i);
01041 if (TN_is_register(opnd_tn) &&
01042 TN_register_class(opnd_tn) == ISA_REGISTER_CLASS_rip)
01043 continue;
01044 if (TN_is_symbol(opnd_tn)) {
01045 ST *var = TN_var(opnd_tn);
01046 if (!strcmp(ST_name(var), ".rodata"))
01047 continue;
01048 }
01049 return FALSE;
01050 }
01051 return TRUE;
01052 }
01053
01054
01055
01056
01057 static void
01058 Quick_Mark_Reloadable_Live_Ranges (ISA_REGISTER_CLASS cl)
01059 {
01060
01061 if (Get_Trace (TP_ALLOC, 0x1000)) return;
01062
01063 for (LIVE_RANGE *lr = Live_Range_List; lr != NULL; lr = LR_next(lr)) {
01064
01065 if (LR_exposed_use(lr) || LR_def_cnt(lr) != 1) continue;
01066
01067 OP *def_op = OP_VECTOR_element (Insts_Vector, LR_first_def(lr));
01068
01069 if (!OP_load(def_op) || OP_has_implicit_interactions(def_op))
01070 continue;
01071
01072 TN *result_tn;
01073 INT i;
01074 for (i = OP_results(def_op) - 1; i >= 0; --i) {
01075 if (OP_result(def_op, i) == LR_tn(lr)) {
01076 result_tn = OP_result(def_op, i);
01077 }
01078 }
01079 if (TN_register_class(result_tn) != cl) continue;
01080
01081 if (! TN_is_rematerializable(result_tn) && ! TN_is_gra_homeable(result_tn))
01082 continue;
01083
01084
01085
01086 if (!Is_Readonly_Mem_Load(def_op))
01087 continue;
01088
01089 Set_LR_reloadable (lr);
01090 }
01091 }
01092 #endif
01093
01094
01095 static void
01096 Mark_Reloadable_Live_Ranges (ISA_REGISTER_CLASS cl)
01097 {
01098
01099 if (Get_Trace (TP_ALLOC, 0x1000)) return;
01100
01101 #ifdef TARG_X8664
01102 Need_Dep_Graph_For_Mark_Reloadable_Live_Ranges = FALSE;
01103 #endif
01104
01105 for (LIVE_RANGE *lr = Live_Range_List; lr != NULL; lr = LR_next(lr))
01106 {
01107
01108 if (LR_exposed_use(lr) || LR_def_cnt(lr) != 1) continue;
01109
01110 OP *def_op = OP_VECTOR_element (Insts_Vector, LR_first_def(lr));
01111
01112 if (!OP_load(def_op) || OP_has_implicit_interactions(def_op))
01113 continue;
01114
01115 TN *result_tn;
01116 INT i;
01117 for (i = OP_results(def_op) - 1; i >= 0; --i) {
01118 if (OP_result(def_op, i) == LR_tn(lr)) {
01119 result_tn = OP_result(def_op, i);
01120 }
01121 }
01122 if (TN_register_class(result_tn) != cl) continue;
01123
01124 #ifdef KEY
01125 if (! TN_is_rematerializable(result_tn) && ! TN_is_gra_homeable(result_tn))
01126 continue;
01127 #endif
01128
01129 BOOL reloadable = TRUE;
01130 for (i = 0; i < OP_opnds(def_op); i++) {
01131 TN *opnd_tn = OP_opnd(def_op,i);
01132 if (TN_is_register(opnd_tn) && TN_register_class(opnd_tn) == cl) {
01133 LIVE_RANGE *opnd_lr = LR_For_TN (opnd_tn);
01134 if (LR_last_use(opnd_lr) < LR_last_use(lr)) {
01135 reloadable = FALSE;
01136 break;
01137 }
01138 }
01139 }
01140 if (!reloadable) continue;
01141
01142 ARC_LIST *arcs;
01143 for (arcs = OP_succs(def_op); arcs != NULL; arcs = ARC_LIST_rest(arcs)) {
01144 ARC *arc = ARC_LIST_first(arcs);
01145 if (ARC_kind(arc) == CG_DEP_REGIN) continue;
01146 OP *succ_op = ARC_succ(arc);
01147 INT succ_opnum = BB_OP_MAP32_Get (op_to_opnum, succ_op);
01148 if (succ_opnum < LR_last_use(lr)) {
01149 reloadable = FALSE;
01150 break;
01151 }
01152 }
01153
01154 if (reloadable) {
01155 Set_LR_reloadable (lr);
01156 #ifdef TARG_X8664
01157 if (!Is_Readonly_Mem_Load(def_op))
01158 Need_Dep_Graph_For_Mark_Reloadable_Live_Ranges = TRUE;
01159 #endif
01160 }
01161 }
01162 }
01163
01164
01165
01166
01167
01168
01169 static BOOL Is_LR_Reloadable (LIVE_RANGE *lr)
01170 {
01171 if (!LR_reloadable(lr)) return FALSE;
01172
01173 OP *def_op = OP_VECTOR_element (Insts_Vector, LR_first_def(lr));
01174
01175 for (INT i = 0; i < OP_opnds(def_op); i++) {
01176 TN *opnd_tn = OP_opnd(def_op,i);
01177 ST *spill_loc;
01178 if (TN_is_register(opnd_tn) &&
01179 !TN_is_rematerializable (opnd_tn) &&
01180 (spill_loc = TN_spill(opnd_tn)) != NULL)
01181 {
01182 OP *last_use = (LR_last_use(lr) < VECTOR_size(Insts_Vector)) ?
01183 OP_VECTOR_element (Insts_Vector, LR_last_use(lr)) :
01184 NULL;
01185
01186 for (OP *op = OP_next(def_op); op != last_use; op = OP_next(op)) {
01187 if (Is_OP_Spill_Store (op, spill_loc)) {
01188 Reset_LR_reloadable (lr);
01189 return FALSE;
01190 }
01191 }
01192 }
01193 }
01194 return TRUE;
01195 }
01196
01197
01198
01199
01200
01201 static void
01202 Remove_Redundant_Code (BB *bb)
01203 {
01204 OP *op = BB_first_op (bb);
01205 do {
01206 OP *next_op = OP_next(op);
01207 if ((CGTARG_Is_Preference_Copy(op) &&
01208 LRA_TN_register(OP_result(op,0)) ==
01209 LRA_TN_register(OP_opnd(op,CGTARG_Copy_Operand(op)))) ||
01210 Is_Marked_For_Removal(op)) {
01211 BB_Remove_Op (bb, op);
01212 Reset_BB_scheduled (bb);
01213 }
01214 op = next_op;
01215 } while (op != NULL);
01216 }
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 static void
01227 Init_Avail_Regs (void)
01228 {
01229 REGISTER reg;
01230 ISA_REGISTER_CLASS cl;
01231
01232 bzero(avail_regs, sizeof(avail_regs));
01233 #ifdef KEY
01234 bzero(last_freed, sizeof(last_freed));
01235 #endif
01236
01237 FOR_ALL_ISA_REGISTER_CLASS(cl) {
01238 FOR_ALL_REGISTER_SET_members (avail_set[cl], reg) {
01239 avail_regs[cl].reg[reg] = TRUE;
01240 #ifdef KEY
01241 last_freed[cl].reg[reg] = INT_MAX;
01242 #endif
01243 }
01244 }
01245 }
01246
01247
01248
01249
01250
01251
01252
01253 static void
01254 Add_Avail_Reg (ISA_REGISTER_CLASS regclass, REGISTER reg, INT cur_op)
01255 {
01256
01257 if (Calculating_Fat_Points()) {
01258 if (fat_points[cur_op] != FAT_POINTS_MIN) fat_points[cur_op]--;
01259
01260
01261
01262 if (reg > REGISTER_MAX) return;
01263 }
01264
01265
01266 if (!REGISTER_allocatable(regclass, reg)) return;
01267
01268
01269 if (REGISTER_SET_MemberP(exclude_set[regclass], reg)) return;
01270
01271 if (Do_LRA_Trace(Trace_LRA_Detail)) {
01272 fprintf (TFile, "Deallocated register %s\n", REGISTER_name(regclass, reg));
01273 }
01274 Is_True (!avail_regs[regclass].reg[reg], (" LRA: Error in Add_Avail_Reg"));
01275 avail_regs[regclass].reg[reg] = TRUE;
01276 #ifdef KEY
01277 #ifdef TARG_MIPS
01278 last_assigned_reg[regclass] = reg;
01279 #else
01280 if( reg > last_assigned_reg[regclass] ||
01281 last_assigned_reg[regclass] == REGISTER_MAX ){
01282 last_assigned_reg[regclass] = reg;
01283 }
01284 #endif
01285
01286 last_freed[regclass].reg[reg] = cur_op;
01287 #endif
01288 }
01289
01290 #ifdef TARG_IA64
01291
01292
01293
01294
01295 static void
01296 Init_Nat_Regs(BB *bb)
01297 {
01298 TN *tn;
01299 REGISTER reg;
01300 ISA_REGISTER_CLASS cl;
01301
01302 spill_nat_num = 0;
01303 spill_global_num = 0;
01304
01305 FOR_ALL_REGISTER_SET_members (avail_set[ISA_REGISTER_CLASS_integer], reg) {
01306 has_nat_reg.reg[reg] = FALSE;
01307 }
01308 if (BB_bbregs(bb) != NULL) {
01309
01310 FOR_ALL_GTN_SET_members(BB_defreach_in(bb), tn) {
01311 if (!TN_is_global_reg(tn)) continue;
01312 cl = TN_register_class(tn);
01313 reg = LRA_TN_register(tn);
01314 if ( cl == ISA_REGISTER_CLASS_integer &&
01315 TN_is_take_nat(tn) &&
01316 reg != REGISTER_UNDEFINED) {
01317 has_nat_reg.reg[reg] = TRUE;
01318 }
01319 }
01320 }
01321 }
01322
01323
01324
01325
01326 static BOOL
01327 Is_Reg_Has_nat(ISA_REGISTER_CLASS cl, REGISTER reg)
01328 {
01329 if (cl != ISA_REGISTER_CLASS_integer) return FALSE;
01330 return has_nat_reg.reg[reg];
01331 }
01332 #endif
01333
01334
01335
01336
01337
01338
01339 inline void
01340 Delete_Avail_Reg (ISA_REGISTER_CLASS regclass, REGISTER reg, INT cur_op)
01341 {
01342
01343 if (Calculating_Fat_Points()) {
01344 if (fat_points[cur_op] != FAT_POINTS_MAX) fat_points[cur_op]++;
01345
01346
01347
01348 if (reg > REGISTER_MAX) return;
01349 }
01350 avail_regs[regclass].reg[reg] = FALSE;
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 static BOOL
01366 Is_Reg_Available (ISA_REGISTER_CLASS regclass,
01367 REGISTER_SET usable_regs,
01368 REGISTER reg,
01369 LIVE_RANGE *lr)
01370 {
01371
01372
01373
01374 if (reg > REGISTER_MAX) {
01375
01376
01377
01378
01379
01380
01381
01382
01383 if (last_infinite_freed == reg) {
01384 return TRUE;
01385 } else {
01386 return FALSE;
01387 }
01388 }
01389 if (reg != REGISTER_UNDEFINED &&
01390 avail_regs[regclass].reg[reg] &&
01391 REGISTER_SET_MemberP(usable_regs, reg)) {
01392 TN *tn = Build_Dedicated_TN (regclass, reg, 0);
01393 LIVE_RANGE *ded_lr = LR_For_TN (tn);
01394 OP *op;
01395 INT lr_def;
01396
01397
01398
01399
01400
01401 if (LR_Is_Undefined_Local(lr)) {
01402 lr_def = LR_exposed_use(lr);
01403 } else {
01404 lr_def = LR_first_def(lr);
01405 }
01406 if (ded_lr == NULL ||
01407 lr_def > LR_exposed_use(ded_lr) ||
01408 (lr_def == LR_exposed_use(ded_lr) &&
01409 (op = OP_VECTOR_element (Insts_Vector, LR_first_def(lr))) &&
01410 !OP_uniq_res(op)))
01411 {
01412 return TRUE;
01413 }
01414 }
01415 return FALSE;
01416 }
01417
01418
01419
01420
01421
01422 static BOOL
01423 Is_Non_Allocatable_Reg_Available (
01424 ISA_REGISTER_CLASS regclass,
01425 REGISTER_SET usable_regs,
01426 REGISTER reg,
01427 LIVE_RANGE *lr)
01428 {
01429 if (! REGISTER_SET_MemberP(usable_regs, reg)) {
01430 return FALSE;
01431 }
01432
01433 TN *tn = Build_Dedicated_TN (regclass, reg, 0);
01434
01435 if (TN_is_zero_reg(tn)) {
01436
01437
01438
01439 if (LR_def_cnt(lr) == 1) {
01440 OP *op = OP_VECTOR_element (Insts_Vector, LR_first_def(lr));
01441 if (CGTARG_Is_Preference_Copy(op) &&
01442 LRA_TN_register(OP_opnd(op, CGTARG_Copy_Operand(op))) == reg)
01443 return TRUE;
01444 }
01445 return FALSE;
01446 }
01447
01448 LIVE_RANGE *ded_lr = LR_For_TN (tn);
01449
01450 if (!REGISTER_allocatable (regclass, reg) &&
01451 ded_lr != NULL &&
01452 LR_first_def(lr) >= LR_exposed_use(ded_lr) &&
01453 LR_last_use(lr) <= LR_first_def(ded_lr))
01454 {
01455
01456 LR_exposed_use(ded_lr) = LR_last_use(lr);
01457 return TRUE;
01458 }
01459 return FALSE;
01460 }
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470 static REGISTER
01471 Get_Avail_Reg (ISA_REGISTER_CLASS regclass,
01472 REGISTER_SET usable_regs,
01473 LIVE_RANGE *lr,
01474 REGISTER skip_reg)
01475 {
01476 REGISTER next_reg = last_assigned_reg[regclass] + 1;
01477 REGISTER reg;
01478
01479 #if defined(TARG_X8664)
01480
01481
01482
01483
01484 if (LRA_prefer_lru_reg) {
01485 REGISTER lru_reg = REGISTER_UNDEFINED;
01486 INT lru_opnum;
01487 for (reg = REGISTER_MIN; reg <= REGISTER_MAX; reg++) {
01488 if (Is_Reg_Available(regclass, usable_regs, reg, lr) &&
01489 reg != skip_reg) {
01490 if (lru_reg == REGISTER_UNDEFINED ||
01491 lru_opnum < last_freed[regclass].reg[reg]) {
01492 lru_reg = reg;
01493 lru_opnum = last_freed[regclass].reg[reg];
01494 }
01495 }
01496 }
01497 if (lru_reg != REGISTER_UNDEFINED) {
01498 return lru_reg;
01499 }
01500 } else
01501 #endif
01502
01503 #ifdef TARG_X8664
01504 if (LRA_prefer_legacy_regs) {
01505
01506
01507
01508 const REGISTER max_preferred_reg =
01509 REGISTER_MIN + ((REGISTER_MAX - REGISTER_MIN + 1) / 2) - 1;
01510 REGISTER start1, start2, start3, end1, end2, end3;
01511
01512 if (next_reg <= max_preferred_reg) {
01513 start1 = next_reg;
01514 end1 = max_preferred_reg;
01515 start2 = REGISTER_MIN;
01516 end2 = next_reg - 1;
01517 start3 = max_preferred_reg + 1;
01518 end3 = REGISTER_MAX;
01519 } else {
01520 start1 = REGISTER_MIN;
01521 end1 = max_preferred_reg;
01522 start2 = next_reg;
01523 end2 = REGISTER_MAX;
01524 start3 = max_preferred_reg + 1;
01525 end3 = next_reg - 1;
01526 }
01527 for (reg = start1; reg <= end1; reg++) {
01528 if (Is_Reg_Available(regclass, usable_regs, reg, lr) && reg != skip_reg)
01529 return reg;
01530 }
01531 for (reg = start2; reg <= end2; reg++) {
01532 if (Is_Reg_Available(regclass, usable_regs, reg, lr) && reg != skip_reg)
01533 return reg;
01534 }
01535 for (reg = start3; reg <= end3; reg++) {
01536 if (Is_Reg_Available(regclass, usable_regs, reg, lr) && reg != skip_reg)
01537 return reg;
01538 }
01539 } else
01540 #endif
01541 {
01542
01543
01544
01545
01546
01547 for (reg = next_reg; reg < REGISTER_MAX+1; reg++) {
01548 if (Is_Reg_Available(regclass, usable_regs, reg, lr) && reg != skip_reg) {
01549 return reg;
01550 }
01551 }
01552 for (reg = REGISTER_MIN; reg < next_reg; reg++) {
01553 if (Is_Reg_Available(regclass, usable_regs, reg, lr) && reg != skip_reg) {
01554 return reg;
01555 }
01556 }
01557 }
01558
01559 #ifdef HAS_STACKED_REGISTERS
01560
01561
01562
01563 reg = REGISTER_Request_Stacked_Register(ABI_PROPERTY_stacked, regclass);
01564 if (reg != REGISTER_UNDEFINED && REGISTER_SET_MemberP(usable_regs, reg)) {
01565 avail_set[regclass] = REGISTER_SET_Union1(avail_set[regclass], reg);
01566 if (Do_LRA_Trace(Trace_LRA_Spill)) {
01567 fprintf (TFile,
01568 "LRA_SPILL>> Got new stack register: %s %d,%d\n",
01569 REGISTER_name(regclass, reg), regclass, reg);
01570 }
01571 avail_regs[regclass].reg[reg] = TRUE;
01572 livethrough_computed = FALSE;
01573 return reg;
01574 }
01575 #endif
01576
01577
01578 if (CG_localize_tns) {
01579 REGISTER_SET unused_callees = REGISTER_SET_Difference (
01580 REGISTER_CLASS_callee_saves(regclass),
01581 Callee_Saved_Regs_Used[regclass]);
01582 unused_callees = REGISTER_SET_Intersection(unused_callees, usable_regs);
01583 reg = REGISTER_SET_Choose (unused_callees);
01584 if (reg != REGISTER_UNDEFINED) {
01585 Callee_Saved_Regs_Used[regclass] =
01586 REGISTER_SET_Union1(Callee_Saved_Regs_Used[regclass], reg);
01587 avail_set[regclass] = REGISTER_SET_Union1 (avail_set[regclass], reg);
01588 if (Do_LRA_Trace(Trace_LRA_Spill)) {
01589 fprintf (TFile,
01590 "LRA_SPILL>> Got new callee save register: %d,%d\n", regclass, reg);
01591 }
01592 avail_regs[regclass].reg[reg] = TRUE;
01593 return reg;
01594 }
01595 }
01596 if (Calculating_Fat_Points()) {
01597 return ++reg_infinite;
01598 } else {
01599 return REGISTER_UNDEFINED;
01600 }
01601 }
01602
01603
01604
01605
01606
01607
01608
01609
01610 static REGISTER
01611 Allocate_Register (
01612 TN *tn,
01613 BOOL uniq_result,
01614 ISA_REGISTER_CLASS result_regclass,
01615 REGISTER_SET usable_regs,
01616 REGISTER result_reg,
01617 INT opnum)
01618 {
01619 ISA_REGISTER_CLASS regclass;
01620 REGISTER reg;
01621 LIVE_RANGE *clr = LR_For_TN (tn);
01622
01623 regclass = TN_register_class(tn);
01624
01625
01626
01627
01628
01629 if (!uniq_result &&
01630 regclass == result_regclass &&
01631 Is_Reg_Available (regclass, usable_regs, result_reg, clr))
01632 {
01633 reg = result_reg;
01634 }
01635 else {
01636 REGISTER skip_reg;
01637
01638 if (uniq_result && regclass == result_regclass) {
01639 skip_reg = result_reg;
01640 }
01641 else {
01642 skip_reg = REGISTER_UNDEFINED;
01643 }
01644
01645 reg = Get_Avail_Reg (regclass, usable_regs, clr, skip_reg);
01646 if (reg == REGISTER_UNDEFINED) return REGISTER_UNDEFINED;
01647 }
01648 Delete_Avail_Reg (regclass, reg, opnum);
01649 if (Do_LRA_Trace(Trace_LRA_Detail)) {
01650 fprintf (TFile, "Allocated register %s for ", REGISTER_name (regclass, reg));
01651 Print_TN(tn,FALSE);fprintf(TFile,"\n");
01652 }
01653 if (Always_Trace(Trace_LRA) && trace_tn && trace_cl == regclass) {
01654 bb_live = TN_SET_Union1D(bb_live, tn, &lra_pool);
01655 }
01656
01657
01658
01659
01660
01661 if (reg <= REGISTER_MAX) {
01662 #ifdef TARG_IA64
01663 last_assigned_reg[regclass] = reg;
01664 #endif
01665 }
01666
01667 return reg;
01668 }
01669
01670
01671
01672
01673
01674
01675 static BOOL
01676 Init_Fat_Point_Calculation(ISA_REGISTER_CLASS cl, INT opnum, BB *bb)
01677 {
01678
01679
01680
01681
01682 if (Check_Allow_Reschedule()) {
01683 return(FALSE);
01684 }
01685 fat_point_regs_map = hTN_MAP_Create (&lra_pool);
01686 use_fat_point_regs = TRUE;
01687 fat_points = TYPE_MEM_POOL_ALLOC_N(FAT_POINTS_TYPE, &lra_pool, BB_length(bb) + 1);
01688 bzero(fat_points, (BB_length(bb)+1)*sizeof(FAT_POINTS_TYPE));
01689 failing_class = cl;
01690 reg_infinite = REGISTER_MAX;
01691
01692 return(TRUE);
01693 }
01694
01695
01696
01697
01698 static void
01699 Clear_Fat_Point_Calculation()
01700 {
01701 fat_points = NULL;
01702 failing_class = ISA_REGISTER_CLASS_UNDEFINED;
01703 reg_infinite = REGISTER_UNDEFINED;
01704 use_fat_point_regs = FALSE;
01705 }
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 static void
01716 Update_Callee_Availability(BB *bb)
01717 {
01718 ISA_REGISTER_CLASS cl;
01719 REGISTER reg;
01720 if (BB_exit(bb)) {
01721
01722
01723
01724
01725 #ifdef KEY
01726 FOR_ALL_ISA_REGISTER_CLASS(cl) {
01727 avail_set[cl] = REGISTER_SET_Union(avail_set[cl],
01728 Callee_Saved_Regs_Used[cl]);
01729
01730 FOR_ALL_REGISTER_SET_members(Callee_Saved_Regs_Used[cl], reg) {
01731 avail_regs[cl].reg[reg] = TRUE;
01732 }
01733 }
01734 #else
01735 FOR_ALL_ISA_REGISTER_CLASS(cl) {
01736 avail_set[cl] = REGISTER_SET_Union(avail_set[cl],
01737 Callee_Saved_Regs_Used[cl]);
01738 }
01739 FOR_ALL_REGISTER_SET_members(Callee_Saved_Regs_Used[cl], reg) {
01740 avail_regs[cl].reg[reg] = TRUE;
01741 }
01742 #endif // KEY
01743 } else if (BB_entry(bb)) {
01744
01745
01746
01747
01748 #ifdef KEY // bug 8300
01749 FOR_ALL_ISA_REGISTER_CLASS(cl) {
01750 avail_set[cl] = REGISTER_SET_Difference(avail_set[cl],
01751 Callee_Saved_Regs_Used[cl]);
01752 FOR_ALL_REGISTER_SET_members(Callee_Saved_Regs_Used[cl], reg) {
01753 avail_regs[cl].reg[reg] = FALSE;
01754 }
01755 }
01756 #else
01757 FOR_ALL_ISA_REGISTER_CLASS(cl) {
01758 avail_set[cl] = REGISTER_SET_Difference(avail_set[cl],
01759 Callee_Saved_Regs_Used[cl]);
01760 }
01761 FOR_ALL_REGISTER_SET_members(Callee_Saved_Regs_Used[cl], reg) {
01762 avail_regs[cl].reg[reg] = FALSE;
01763 }
01764 #endif // KEY
01765 }
01766 }
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781 static REGISTER_SET
01782 Usable_Registers (TN* tn, LIVE_RANGE* lr)
01783 {
01784 ISA_REGISTER_CLASS cl = TN_register_class(tn);
01785 REGISTER_SET usable_regs = REGISTER_CLASS_universe(cl);
01786
01787 #ifdef TARG_X8664
01788 if( TN_is_preallocated(tn) ){
01789 REGISTER reg = LRA_TN_register( tn );
01790 return REGISTER_SET_Intersection1(usable_regs,reg);
01791 }
01792 #endif
01793
01794 INT first_op = MAX(LR_first_def(lr), 1);
01795 INT last_op = MIN(LR_last_use(lr)+1, VECTOR_size(Insts_Vector));
01796
01797 for (INT opnum = first_op; opnum < last_op; opnum++) {
01798
01799 OP* op = OP_VECTOR_element(Insts_Vector, opnum);
01800
01801 ASM_OP_ANNOT* asm_info = (OP_code(op) == TOP_asm) ?
01802 (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, op) : NULL;
01803
01804
01805 if (asm_info) {
01806 usable_regs = REGISTER_SET_Difference(usable_regs,
01807 ASM_OP_clobber_set(asm_info)[cl]);
01808 }
01809
01810 for (INT resnum = 0; resnum < OP_results(op); resnum++) {
01811 #if defined(KEY)
01812 if (asm_info) {
01813 if (TN_is_register(OP_result(op, resnum)) &&
01814 (TN_register_class(OP_result(op, resnum)) != cl) )
01815 continue;
01816 } else
01817 #endif
01818 if (OP_result_reg_class(op, resnum) != cl) {
01819 continue;
01820 }
01821
01822 TN* result = OP_result(op, resnum);
01823
01824 #ifdef TARG_X8664
01825 if( TN_is_preallocated( result ) ){
01826 const REGISTER reg = LRA_TN_register( result );
01827 const LIVE_RANGE* result_lr = LR_For_TN( result );
01828 if( result_lr == NULL ||
01829 LR_last_use(lr) > LR_first_def(result_lr) ){
01830 usable_regs = REGISTER_SET_Difference1(usable_regs, reg);
01831 }
01832 }
01833 #endif
01834
01835 ISA_REGISTER_SUBCLASS sc = asm_info ?
01836 ASM_OP_result_subclass(asm_info)[resnum] :
01837 OP_result_reg_subclass(op, resnum);
01838 if (sc == ISA_REGISTER_SUBCLASS_UNDEFINED) {
01839 continue;
01840 }
01841
01842 REGISTER_SET subclass_regs = REGISTER_SUBCLASS_members(sc);
01843 if (result == tn) {
01844 usable_regs = REGISTER_SET_Intersection(usable_regs, subclass_regs);
01845 }
01846 else if (REGISTER_SET_Size(subclass_regs) == 1) {
01847 usable_regs = REGISTER_SET_Difference(usable_regs, subclass_regs);
01848 }
01849 }
01850
01851 for (INT opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
01852 #if defined(KEY)
01853 if (asm_info) {
01854 if (TN_is_register(OP_opnd(op, opndnum)) &&
01855 (TN_register_class(OP_opnd(op, opndnum)) != cl) )
01856 continue;
01857 } else
01858 #endif
01859 if (OP_opnd_reg_class(op, opndnum) != cl) {
01860 continue;
01861 }
01862
01863 TN* opnd = OP_opnd(op, opndnum);
01864
01865 #ifdef TARG_X8664
01866 if( TN_is_preallocated( opnd ) ){
01867 const REGISTER reg = LRA_TN_register( opnd );
01868 const LIVE_RANGE* opnd_lr = LR_For_TN( opnd );
01869 if( opnd_lr == NULL ||
01870 LR_first_def(lr) < LR_last_use(opnd_lr) ){
01871 usable_regs = REGISTER_SET_Difference1(usable_regs, reg);
01872 }
01873 }
01874 #endif
01875
01876 ISA_REGISTER_SUBCLASS sc = asm_info ?
01877 ASM_OP_opnd_subclass(asm_info)[opndnum] :
01878 OP_opnd_reg_subclass(op, opndnum);
01879 if (sc == ISA_REGISTER_SUBCLASS_UNDEFINED) {
01880 continue;
01881 }
01882 REGISTER_SET subclass_regs = REGISTER_SUBCLASS_members(sc);
01883 if (opnd == tn) {
01884 usable_regs = REGISTER_SET_Intersection(usable_regs, subclass_regs);
01885 }
01886 else if (REGISTER_SET_Size(subclass_regs) == 1) {
01887 usable_regs = REGISTER_SET_Difference(usable_regs, subclass_regs);
01888 }
01889 }
01890 }
01891
01892 FmtAssert(!REGISTER_SET_EmptyP(usable_regs),
01893 ("Could not find a register for TN%d in live range [%d-%d]",
01894 TN_number(tn), LR_first_def(lr), LR_last_use(lr)));
01895
01896 return usable_regs;
01897 }
01898
01899
01900 static BOOL
01901 Assign_Registers_For_OP (OP *op, INT opnum, TN **spill_tn, BB *bb)
01902 {
01903 INT opndnum;
01904 INT resnum;
01905 REGISTER reg, result_reg;
01906 ISA_REGISTER_CLASS result_cl;
01907 BOOL uniq_result;
01908 LIVE_RANGE *clr;
01909 BOOL result_failed = FALSE;
01910 INT nresults = OP_results(op);
01911 mBOOL *free_result = TYPE_ALLOCA_N(mBOOL, nresults);
01912 INT *free_opnum = TYPE_ALLOCA_N(INT, nresults);
01913 TN **free_result_tn = TYPE_ALLOCA_N(TN *, nresults);
01914 REGISTER *free_result_reg = TYPE_ALLOCA_N(REGISTER, nresults);
01915 ISA_REGISTER_CLASS *free_result_cl = TYPE_ALLOCA_N(ISA_REGISTER_CLASS, nresults);
01916 #ifdef KEY
01917 BOOL *free_result_is_early_clobber = TYPE_ALLOCA_N(BOOL, nresults);
01918 #endif
01919
01920 for (resnum = 0; resnum < nresults; resnum++) {
01921 free_result[resnum] = FALSE;
01922 }
01923
01924
01925 if (Do_LRA_Trace(Trace_LRA_Detail)) {
01926 fprintf (TFile, "OP:%d>> ", opnum);
01927 Print_OP_No_SrcLine (op);
01928 #ifdef KEY
01929 fprintf (TFile, "Avail integer registers: ");
01930 for (reg = REGISTER_MIN; reg <= REGISTER_MAX; reg++) {
01931 if (avail_regs[ISA_REGISTER_CLASS_integer].reg[reg])
01932 fprintf (TFile, " %s", REGISTER_name (ISA_REGISTER_CLASS_integer, reg));
01933 }
01934 fprintf (TFile, "\n");
01935
01936 #if !defined(TARG_SL)
01937 fprintf (TFile, "Avail fp registers: ");
01938 for (reg = REGISTER_MIN; reg <= REGISTER_MAX; reg++) {
01939 if (avail_regs[ISA_REGISTER_CLASS_float].reg[reg])
01940 fprintf (TFile, " %s", REGISTER_name (ISA_REGISTER_CLASS_float, reg));
01941 }
01942 fprintf (TFile, "\n");
01943 #endif // !TARG_SL
01944 #endif
01945 }
01946
01947
01948 ASM_OP_ANNOT* asm_info = (OP_code(op) == TOP_asm) ?
01949 (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, op) : NULL;
01950
01951
01952
01953
01954
01955
01956
01957 uniq_result = FALSE;
01958 result_reg = REGISTER_UNDEFINED;
01959 result_cl = ISA_REGISTER_CLASS_UNDEFINED;
01960 for (resnum = 0; resnum < nresults; resnum++) {
01961 TN *result_tn = OP_result (op,resnum);
01962
01963 clr = LR_For_TN (result_tn);
01964 result_reg = LRA_TN_register(result_tn);
01965 result_cl = TN_register_class(result_tn);
01966
01967 REGISTER_SET must_use = Usable_Registers(result_tn, clr);
01968
01969
01970
01971
01972
01973 if (!Calculating_Fat_Points() ||
01974 failing_class == result_cl) {
01975
01976
01977
01978
01979 if (result_reg == REGISTER_UNDEFINED) {
01980 REGISTER prefer_reg = LR_prefer_reg (clr);
01981
01982 if (prefer_reg == REGISTER_UNDEFINED) {
01983 #ifdef TARG_IA64
01984
01985
01986 if (TN_is_local_reg(result_tn) &&
01987 (unused_tn_def[result_cl] != NULL) &&
01988 !OP_has_implicit_interactions(op)) {
01989 #else
01990 if (TN_is_local_reg(result_tn) && (unused_tn_def[result_cl] != NULL) && !OP_side_effects(op)) {
01991 #endif
01992 result_tn = unused_tn_def[result_cl];
01993 Set_OP_result(op,resnum,result_tn);
01994
01995 if (Do_LRA_Trace(Trace_LRA_Detail)) {
01996 fprintf(TFile,"unused def BB:%d %s >>> ",
01997 BB_id(bb),REGISTER_name (result_cl, LRA_TN_register(result_tn)));
01998 Print_OP_No_SrcLine (op);
01999 }
02000
02001 if (!OP_has_implicit_interactions (op) &&
02002 !OP_store(op) &&
02003 !CGTARG_Is_OP_Intrinsic(op)) {
02004
02005 INT k;
02006 BOOL all_results_unneeded = TRUE;
02007 for (k = OP_results(op); 0 < k; k--) {
02008 TN *ck_tn = OP_result (op,k-1);
02009 ISA_REGISTER_CLASS ck_cl;
02010 if (ck_tn != NULL) {
02011 ck_cl = TN_register_class(ck_tn);
02012 if ((unused_tn_def[ck_cl] == NULL) ||
02013 (unused_tn_def[ck_cl] != ck_tn)) {
02014 all_results_unneeded = FALSE;
02015 break;
02016 }
02017 }
02018 }
02019 if (all_results_unneeded) {
02020 if (Do_LRA_Trace(Trace_LRA_Detail)) {
02021 fprintf (TFile, "DELETE OP(unneeded results):%d>> ", opnum);
02022 Print_OP_No_SrcLine (op);
02023 }
02024
02025 BB_Remove_Op (bb, op);
02026 #ifdef TARG_IA64
02027 Reset_BB_scheduled(bb);
02028 #endif
02029 return TRUE;
02030 }
02031 }
02032
02033 continue;
02034 }
02035 }
02036
02037 if (prefer_reg != REGISTER_UNDEFINED &&
02038 (Is_Reg_Available (result_cl, must_use, prefer_reg, clr) ||
02039 Is_Non_Allocatable_Reg_Available(result_cl, must_use, prefer_reg, clr))){
02040 result_reg = prefer_reg;
02041 Delete_Avail_Reg (result_cl, result_reg, opnum);
02042 if (Do_LRA_Trace(Trace_LRA_Detail)) {
02043 fprintf (TFile, "Preferred register %s\n",
02044 REGISTER_name (result_cl, prefer_reg));
02045 }
02046 if (Always_Trace(Trace_LRA) && trace_tn && result_cl == trace_cl) {
02047 bb_live = TN_SET_Union1D(bb_live, result_tn, &lra_pool);
02048 }
02049 } else {
02050 result_reg =
02051 Allocate_Register(result_tn,FALSE, result_cl, must_use, result_reg,opnum);
02052 if (result_reg == REGISTER_UNDEFINED) {
02053 *spill_tn = result_tn;
02054 if (!Calculating_Fat_Points()) {
02055
02056
02057
02058
02059 if (Init_Fat_Point_Calculation(TN_register_class(*spill_tn),
02060 opnum,bb)){
02061 result_reg = Allocate_Register(result_tn, FALSE, result_cl,
02062 must_use, result_reg, opnum);
02063 result_failed = TRUE;
02064 } else {
02065 return FALSE;
02066 }
02067 }
02068 FmtAssert(result_reg != REGISTER_UNDEFINED,
02069 ("LRA: no register found during fat point calculation.\n"
02070 ));
02071 }
02072 }
02073 LRA_TN_Allocate_Register (result_tn, result_reg);
02074 } else if (result_reg == REGISTER_sp &&
02075 #ifdef KEY
02076 result_cl == ISA_REGISTER_CLASS_integer &&
02077 #endif
02078 CG_localize_tns) {
02079 Update_Callee_Availability(bb);
02080 }
02081
02082 #ifdef KEY
02083
02084
02085
02086 bool ok_to_free_result = TRUE;
02087
02088 ok_to_free_result = ok_to_free_result && !OP_cond_def(op);
02089 #endif
02090
02091 #ifdef TARG_IA64
02092
02093 if (result_reg > REGISTER_MAX ||
02094 TN_is_global_reg(result_tn) &&
02095 (OP_cond_def(op) || opnum != LR_first_def(clr)) ||
02096 !TN_is_global_reg(result_tn) && opnum != LR_first_def(clr)) {
02097 ok_to_free_result = FALSE;
02098 }
02099
02100 if (ok_to_free_result) {
02101 #else
02102 if (ok_to_free_result && opnum == LR_first_def(clr)) {
02103 #endif
02104
02105
02106
02107
02108
02109
02110
02111 free_opnum[resnum] = opnum;
02112 free_result_tn[resnum] = result_tn;
02113 free_result[resnum] = TRUE;
02114 free_result_reg[resnum] = result_reg;
02115 free_result_cl [resnum] = result_cl;
02116 #ifdef KEY
02117 free_result_is_early_clobber[resnum] =
02118 (asm_info && ASM_OP_result_clobber(asm_info)[resnum]) ? TRUE : FALSE;
02119 #endif
02120 }
02121 if (OP_uniq_res(op)) uniq_result = TRUE;
02122
02123 #ifdef KEY
02124
02125
02126 if (!result_failed &&
02127 asm_info &&
02128 REGISTER_SET_MemberP(REGISTER_CLASS_callee_saves(result_cl),
02129 result_reg)) {
02130 Callee_Saved_Regs_Used[result_cl] =
02131 REGISTER_SET_Union1(Callee_Saved_Regs_Used[result_cl], result_reg);
02132 }
02133 #endif
02134 }
02135 }
02136
02137
02138
02139
02140 BOOL assignment_undone = FALSE;
02141 for (resnum = 0; resnum < nresults; resnum++) {
02142 if (free_result[resnum]) {
02143 #ifdef KEY
02144
02145
02146 if (free_result_is_early_clobber[resnum])
02147 continue;
02148 #endif
02149 BOOL free_reg = TRUE;
02150 #ifdef TARG_X8664
02151
02152 if( TN_is_preallocated( OP_result(op,resnum) ) &&
02153 avail_regs[free_result_cl[resnum]].reg[free_result_reg[resnum]] ){
02154 free_reg = FALSE;
02155 }
02156 #endif
02157 assignment_undone = TRUE;
02158 if( free_reg )
02159 Add_Avail_Reg (free_result_cl[resnum], free_result_reg[resnum], free_opnum[resnum]);
02160 if (Always_Trace(Trace_LRA) && trace_tn && (free_result_cl[resnum] == trace_cl)) {
02161 bb_live = TN_SET_Difference1D(bb_live, free_result_tn[resnum]);
02162 if (TN_number(free_result_tn[resnum]) == trace_tn) {
02163 LRA_Print_Liveness();
02164 }
02165 }
02166 }
02167 }
02168 if (assignment_undone && result_failed) {
02169
02170
02171
02172
02173
02174
02175 fat_points[opnum] = 1;
02176 }
02177
02178 #ifdef KEY
02179
02180
02181
02182
02183 if (asm_info) {
02184 ISA_REGISTER_CLASS cl;
02185 FOR_ALL_ISA_REGISTER_CLASS(cl) {
02186 Callee_Saved_Regs_Used[cl] =
02187 REGISTER_SET_Union(Callee_Saved_Regs_Used[cl],
02188 REGISTER_SET_Intersection(REGISTER_CLASS_callee_saves(cl),
02189 ASM_OP_clobber_set(asm_info)[cl]));
02190 }
02191 }
02192 #endif
02193
02194
02195
02196
02197 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
02198 TN *tn = OP_opnd(op, opndnum);
02199
02200
02201
02202 if (tn == NULL ||
02203 TN_is_constant(tn)
02204 #ifndef TARG_X8664
02205 || ( (LRA_TN_register(tn) != REGISTER_UNDEFINED) )
02206 #endif
02207 )
02208 {
02209 continue;
02210 }
02211
02212 clr = LR_For_TN (tn);
02213
02214 REGISTER prefer_reg = LR_prefer_reg (clr);
02215 ISA_REGISTER_CLASS regclass = TN_register_class(tn);
02216 REGISTER_SET must_use = Usable_Registers(tn, clr);
02217 #ifdef KEY
02218
02219
02220 if (asm_info &&
02221 LRA_TN_register( tn) != REGISTER_UNDEFINED)
02222 {
02223 const REGISTER reg = LRA_TN_register(tn);
02224 const ISA_REGISTER_CLASS rc = TN_register_class(tn) ;
02225 if (reg <= REGISTER_MAX &&
02226 REGISTER_allocatable(rc, reg) &&
02227 REGISTER_SET_MemberP(REGISTER_CLASS_callee_saves(rc) , reg))
02228 {
02229 Callee_Saved_Regs_Used[ rc] =
02230 REGISTER_SET_Union1(Callee_Saved_Regs_Used[rc], reg);
02231 }
02232 }
02233 #endif
02234
02235 #ifdef TARG_X8664
02236 if (LR_byteable(clr)) {
02237 const REGISTER_SET regs =
02238 REGISTER_SUBCLASS_members(ISA_REGISTER_SUBCLASS_m32_8bit_regs);
02239 must_use = REGISTER_SET_Intersection(must_use, regs);
02240 }
02241
02242
02243
02244
02245 if( LRA_TN_register(tn) != REGISTER_UNDEFINED &&
02246 !TN_is_preallocated(tn) ){
02247 const REGISTER reg = LRA_TN_register(tn);
02248 const ISA_REGISTER_CLASS rc = TN_register_class(tn);
02249 if( reg <= REGISTER_MAX &&
02250 REGISTER_allocatable( rc, reg ) &&
02251 avail_regs[rc].reg[reg] ){
02252 avail_regs[rc].reg[reg] = FALSE;
02253 }
02254
02255 continue;
02256 }
02257
02258 if( opndnum == 0 &&
02259 OP_x86_style( op ) &&
02260 result_reg <= REGISTER_MAX ){
02261 prefer_reg = result_reg;
02262 }
02263 #endif
02264
02265
02266
02267
02268
02269 if (Calculating_Fat_Points() &&
02270 failing_class != regclass) {
02271 continue;
02272 }
02273 if (prefer_reg != REGISTER_UNDEFINED &&
02274 (!uniq_result || (prefer_reg != result_reg)) &&
02275 (Is_Reg_Available (regclass, must_use, prefer_reg, clr) ||
02276 Is_Non_Allocatable_Reg_Available (regclass, must_use, prefer_reg, clr)))
02277 {
02278 LRA_TN_Allocate_Register (tn, prefer_reg);
02279 Delete_Avail_Reg (TN_register_class(tn), prefer_reg, opnum);
02280 if (Do_LRA_Trace(Trace_LRA_Detail)) {
02281 fprintf (TFile, "Preferred register %s\n",
02282 REGISTER_name (regclass, prefer_reg));
02283 }
02284 if (Always_Trace(Trace_LRA) && trace_tn &&
02285 TN_register_class(tn) == trace_cl ) {
02286 bb_live = TN_SET_Union1D(bb_live, tn, &lra_pool);
02287 }
02288 continue;
02289 }
02290
02291
02292
02293
02294
02295 reg = Allocate_Register (tn, uniq_result, result_cl, must_use, result_reg, opnum);
02296
02297 #ifdef TARG_X8664
02298
02299
02300
02301
02302 if( reg == REGISTER_UNDEFINED &&
02303 TN_is_preallocated( tn ) ){
02304 reg = LRA_TN_register( tn );
02305 FmtAssert( !REGISTER_allocatable( regclass, reg ),
02306 ("no register is available for a pre-allocated tn") );
02307
02308 TN* ded_tn = Build_Dedicated_TN( regclass, reg, 0 );
02309 const LIVE_RANGE* ded_lr = LR_For_TN( ded_tn );
02310
02311 if( ded_lr == NULL ||
02312 LR_first_def(clr) < LR_exposed_use(ded_lr ) ||
02313 LR_last_use(clr) > LR_first_def(ded_lr) ){
02314 FmtAssert( false,
02315 ("no register is available for a pre-allocated tn") );
02316 }
02317 }
02318 #endif
02319
02320 if (reg == REGISTER_UNDEFINED) {
02321 *spill_tn = tn;
02322 if (!Calculating_Fat_Points()) {
02323
02324
02325
02326
02327 if (Init_Fat_Point_Calculation(TN_register_class(*spill_tn),opnum,bb)){
02328 fat_points[opnum] = 0;
02329 reg = Allocate_Register (tn, uniq_result, result_cl, must_use, result_reg,
02330 opnum);
02331 } else {
02332 return FALSE;
02333 }
02334 }
02335 FmtAssert(reg != REGISTER_UNDEFINED,
02336 ("LRA: no register found during fat point calculation.\n"));
02337 }
02338
02339 LRA_TN_Allocate_Register (tn, reg);
02340
02341
02342
02343
02344 if (opnum <= LR_exposed_use(clr)) {
02345 Add_Avail_Reg (TN_register_class(tn), reg, opnum);
02346 if (Always_Trace(Trace_LRA) && trace_tn &&
02347 TN_register_class(tn) == result_cl) {
02348 bb_live = TN_SET_Difference1D(bb_live, tn);
02349 if (TN_number(tn) == trace_tn) {
02350 LRA_Print_Liveness();
02351 }
02352 }
02353 }
02354 }
02355 #ifdef KEY
02356
02357 for (resnum = 0; resnum < nresults; resnum++) {
02358 if (free_result[resnum] &&
02359 free_result_is_early_clobber[resnum]) {
02360 Add_Avail_Reg(free_result_cl[resnum], free_result_reg[resnum],
02361 free_opnum[resnum]);
02362 if (Always_Trace(Trace_LRA) &&
02363 trace_tn &&
02364 (free_result_cl[resnum] == trace_cl)) {
02365 bb_live = TN_SET_Difference1D(bb_live, free_result_tn[resnum]);
02366 if (TN_number(free_result_tn[resnum]) == trace_tn) {
02367 LRA_Print_Liveness();
02368 }
02369 }
02370 }
02371 }
02372 #endif
02373
02374 return TRUE;
02375 }
02376
02377
02378
02379
02380
02381
02382
02383 static BOOL
02384 Check_Undefined_Results(OP* op)
02385 {
02386 BOOL defined = FALSE;
02387 for (INT i = OP_results(op) - 1; i >= 0; --i) {
02388 if (LRA_TN_register(OP_result(op,i)) != REGISTER_UNDEFINED) {
02389 defined = TRUE;
02390 break;
02391 }
02392 }
02393
02394 #ifdef TARG_X8664
02395 if( !defined && TOP_is_change_rflags( OP_code(op) ) ){
02396 for( OP* next = OP_next(op); next != NULL; next = OP_next(next) ){
02397 if( OP_reads_rflags( next) ){
02398 defined = TRUE;
02399 break;
02400 }
02401 if( TOP_is_change_rflags( OP_code(next) ) )
02402 break;
02403 }
02404 }
02405 #endif
02406
02407 return !defined;
02408 }
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424 static BOOL
02425 Classes_Match(OP* op)
02426 {
02427 for (INT i = OP_results(op) - 1; i >= 0; --i) {
02428 if (TN_register_class(OP_result(op, i)) != failing_class) {
02429 return FALSE;
02430 }
02431 }
02432 return TRUE;
02433 }
02434
02435
02436
02437
02438
02439
02440
02441 static BOOL
02442 Assign_Registers (BB *bb, TN **spill_tn, BOOL *redundant_code)
02443 {
02444 if (Do_LRA_Trace(Trace_LRA_Detail)) {
02445 fprintf (TFile, "--------------------------------------------\n");
02446 fprintf (TFile, "Register Assignment for BB%d\n", BB_id(bb));
02447 fprintf (TFile, "--------------------------------------------\n");
02448 }
02449
02450 for (INT opnum = BB_length(bb); opnum > 0; opnum--)
02451 {
02452 OP *op = OP_VECTOR_element (Insts_Vector, opnum);
02453
02454
02455
02456
02457
02458
02459 if (Calculating_Fat_Points()) {
02460 fat_points[opnum] = fat_points[opnum+1];
02461 }
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471 if (CG_opt_level > 0 &&
02472 OP_has_result(op) &&
02473 Check_Undefined_Results(op) &&
02474 (!Calculating_Fat_Points() ||
02475 Classes_Match(op)) &&
02476 !OP_has_implicit_interactions (op) &&
02477 !OP_store(op) &&
02478 !CGTARG_Is_OP_Intrinsic(op) &&
02479 !Get_Trace (TP_ALLOC, 0x400))
02480 {
02481
02482
02483 for (INT opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
02484 TN *tn = OP_opnd(op, opndnum);
02485
02486
02487
02488 if (tn == NULL ||
02489 TN_is_constant(tn) ||
02490 LRA_TN_register(tn) != REGISTER_UNDEFINED)
02491 {
02492 #ifdef TARG_X8664
02493 if( tn != NULL &&
02494 TN_is_register( tn ) &&
02495 !TN_is_dedicated( tn ) &&
02496 LRA_TN_register(tn) != REGISTER_UNDEFINED ){
02497 const REGISTER reg = LRA_TN_register(tn);
02498 const ISA_REGISTER_CLASS rc = TN_register_class(tn);
02499 if( reg <= REGISTER_MAX &&
02500 REGISTER_allocatable( rc, reg ) &&
02501 avail_regs[rc].reg[reg] ){
02502 avail_regs[rc].reg[reg] = FALSE;
02503 }
02504 }
02505 #endif
02506 continue;
02507 }
02508 LIVE_RANGE *opnd_lr = LR_For_TN (tn);
02509 LR_use_cnt(opnd_lr)--;
02510 if (LR_use_cnt(opnd_lr) != 0) {
02511
02512 for (INT pnum = opnum-1; pnum > 0; pnum--) {
02513 OP *prev_op = OP_VECTOR_element (Insts_Vector, pnum);
02514 if (OP_Refs_TN (prev_op, tn)) {
02515 LR_last_use(opnd_lr) = pnum;
02516 break;
02517 }
02518 }
02519 }
02520 }
02521 if (Do_LRA_Trace(Trace_LRA_Detail)) {
02522 fprintf (TFile, "DELETE OP:%d>> ", opnum);
02523 Print_OP_No_SrcLine (op);
02524 }
02525
02526 if (!Calculating_Fat_Points()) {
02527 BB_Remove_Op (bb, op);
02528 #ifdef TARG_IA64
02529 Reset_BB_scheduled(bb);
02530 #endif
02531 } else {
02532
02533
02534
02535
02536 Mark_For_Removal(op);
02537 *redundant_code = TRUE;
02538 }
02539 continue;
02540 }
02541
02542 if (!Assign_Registers_For_OP (op, opnum, spill_tn, bb)) {
02543 return FALSE;
02544 }
02545
02546
02547
02548 if (!Calculating_Fat_Points() &&
02549 (Is_Marked_For_Removal(op) ||
02550 (CGTARG_Is_Preference_Copy(op) &&
02551 LRA_TN_register(OP_result(op,0)) ==
02552 LRA_TN_register(OP_opnd(op, CGTARG_Copy_Operand(op)))))) {
02553 *redundant_code = TRUE;
02554 }
02555 }
02556
02557 if (Calculating_Fat_Points()) {
02558 failing_class = ISA_REGISTER_CLASS_UNDEFINED;
02559 return FALSE;
02560 }
02561 return TRUE;
02562 }
02563
02564
02565
02566
02567
02568
02569 static void
02570 Compute_Livethrough_Set (BB *bb)
02571 {
02572 OP *op;
02573 ISA_REGISTER_CLASS cl;
02574
02575 FOR_ALL_ISA_REGISTER_CLASS(cl) {
02576 livethrough[cl] = REGISTER_SET_Difference (
02577 REGISTER_CLASS_allocatable(cl),
02578 avail_set[cl]);
02579
02580
02581
02582 #ifdef TARG_IA64
02583 if (REGISTER_Has_Stacked_Registers(cl)) {
02584 for (REGISTER reg = FIRST_INPUT_REG; reg <= LAST_STACKED_REG; reg++) {
02585 if (reg > Get_Stacked_Callee_Next() && reg <= Get_Stacked_Caller_Next()) {
02586 livethrough[cl] = REGISTER_SET_Difference1 (livethrough[cl], reg);
02587 }
02588 }
02589 }
02590 #endif
02591 }
02592
02593 #ifdef TARG_SL // minor_reg_alloc
02594
02595 if(BB_rid(bb) && RID_TYPE_minor(BB_rid(bb))) {
02596 ISA_REGISTER_CLASS rc = ISA_REGISTER_CLASS_integer;
02597 GRA_PARA_REGION* region = gra_para_region_mgr.Get(BB_rid(bb));
02598 REGISTER_SET exclude_set = region->Registers_Exclude(rc);
02599 livethrough[rc] = REGISTER_SET_Difference(livethrough[rc], exclude_set);
02600 }
02601 #endif
02602
02603 FOR_ALL_BB_OPs_FWD (bb, op) {
02604 INT opndnum;
02605 INT resnum;
02606 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
02607 TN *tn = OP_opnd(op, opndnum);
02608 if (tn != NULL &&
02609 TN_is_register(tn) &&
02610 (TN_is_dedicated(tn) | TN_is_global_reg(tn)))
02611 {
02612 ISA_REGISTER_CLASS cl = TN_register_class(tn);
02613 REGISTER reg = LRA_TN_register(tn);
02614 livethrough[cl] = REGISTER_SET_Difference1 (livethrough[cl], reg);
02615 }
02616 }
02617 for (resnum = 0; resnum < OP_results(op); resnum++) {
02618 TN *tn = OP_result(op, resnum);
02619 if (TN_is_dedicated(tn) | TN_is_global_reg(tn)) {
02620 ISA_REGISTER_CLASS cl = TN_register_class(tn);
02621 REGISTER reg = LRA_TN_register(tn);
02622 livethrough[cl] = REGISTER_SET_Difference1 (livethrough[cl], reg);
02623 }
02624 }
02625 }
02626 }
02627
02628
02629 static void
02630 Analyze_Spilling_Global_Register (
02631 ISA_REGISTER_CLASS cl,
02632 SPILL_CANDIDATE *best,
02633 INT spill_opnum,
02634 INT fatpoint)
02635 {
02636
02637
02638
02639
02640 REGISTER reg = REGISTER_SET_Choose (livethrough[cl]);
02641 if (reg != REGISTER_UNDEFINED) {
02642 float store_cost, restore_cost;
02643 INT benefit = 0;
02644 TN *spill_tn = Build_Dedicated_TN (cl, reg, 0);
02645 CGSPILL_Cost_Estimate (spill_tn, NULL, &store_cost, &restore_cost, CGSPILL_LRA);
02646 best->cost = store_cost + restore_cost;
02647 best->spill_kind = SPILL_GLOBAL_REG;
02648 best->u1.s1.global_spill_reg = reg;
02649 best->u1.s1.spill_cl = cl;
02650 for (INT i = 1; i <= spill_opnum; i++) {
02651 if (fat_points[i] >= fatpoint) benefit++;
02652 }
02653 best->benefit = benefit;
02654 if (Do_LRA_Trace(Trace_LRA_Spill)) {
02655 fprintf (TFile, "Analyze >> (cost:%g, benefit:%d) spill register %s\n",
02656 best->cost, benefit, REGISTER_name (cl, reg));
02657 }
02658 }
02659 }
02660
02661
02662
02663
02664
02665
02666 #ifdef TARG_IA64
02667 static void
02668 Insert_UNAT_Code(BB *bb)
02669 {
02670 extern void UNAT_Spill_OPS(TN *lrange_tn, ST *lrange_st, OPS *ops, CGSPILL_CLIENT client, BB *bb);
02671 extern void UNAT_Restore_OPS(TN *lrange_tn, ST *lrange_st, OPS *ops, CGSPILL_CLIENT client, BB *bb);
02672
02673
02674 OPS spill_nat_ops=OPS_EMPTY;
02675 TN *unat_tn = Build_Dedicated_TN(ISA_REGISTER_CLASS_application,(REGISTER)(REGISTER_MIN + 36),0);
02676 UNAT_Spill_OPS(unat_tn, NULL, &spill_nat_ops, CGSPILL_LRA, bb);
02677 CGSPILL_Prepend_Ops (bb, &spill_nat_ops);
02678
02679
02680 OPS_Remove_All(&spill_nat_ops);
02681 UNAT_Restore_OPS(unat_tn, NULL, &spill_nat_ops, CGSPILL_LRA, bb);
02682 CGSPILL_Append_Ops(bb, &spill_nat_ops);
02683 }
02684 #endif
02685
02686
02687
02688
02689
02690
02691
02692 static void
02693 Spill_Global_Register (BB *bb, SPILL_CANDIDATE *best)
02694 {
02695 #ifdef TARG_IA64
02696 extern void UNAT_Spill_OPS(TN *lrange_tn, ST *lrange_st, OPS *ops, CGSPILL_CLIENT client, BB *bb);
02697 extern void UNAT_Restore_OPS(TN *lrange_tn, ST *lrange_st, OPS *ops, CGSPILL_CLIENT client, BB *bb);
02698 #endif
02699 OPS spill_ops;
02700 TN *new_tn;
02701 REGISTER reg = best->u1.s1.global_spill_reg;
02702 ISA_REGISTER_CLASS cl = (ISA_REGISTER_CLASS)best->u1.s1.spill_cl;
02703
02704 #ifdef TARG_IA64
02705 BOOL nat_bit_tn = Is_Reg_Has_nat(cl,reg);
02706 if (nat_bit_tn) {
02707 DevWarn ("Register %s has nat bit,change format in BB %d!",
02708 REGISTER_name(cl,reg),
02709 BB_id(bb));
02710 spill_nat_num++;
02711
02712
02713
02714
02715
02716
02717 if (spill_nat_num > 1 && spill_global_num > 64) {
02718 DevWarn("Spill too many register with nat bit!");
02719 Insert_UNAT_Code(bb);
02720 spill_nat_num = 0;
02721 spill_global_num = 0;
02722 }
02723 }
02724 spill_global_num++;
02725 #endif
02726 if (Do_LRA_Trace(Trace_LRA_Spill)) {
02727 fprintf (TFile, "LRA_SPILL>> Spilled Global Register : %s\n",
02728 REGISTER_name (cl, reg));
02729 }
02730
02731
02732
02733
02734 TN *spill_tn = Build_Dedicated_TN (cl, reg, 0);
02735 ST *spill_loc;
02736 ST *sv_spill_location = NULL;
02737 BOOL magic_spill_used = FALSE;
02738
02739 #ifdef TARG_X8664
02740 if( cl == ISA_REGISTER_CLASS_float &&
02741 float_reg_could_be_128bit[reg] ){
02742 Set_TN_size( spill_tn, 16 );
02743 }
02744 #endif
02745
02746 if (Trip_Count == MAX_TRIP_COUNT &&
02747 Magic_Spill_Location != NULL &&
02748 !TN_is_float(spill_tn))
02749 {
02750 sv_spill_location = TN_spill(spill_tn);
02751 spill_loc = Magic_Spill_Location;
02752 Set_TN_spill(spill_tn, spill_loc);
02753 magic_spill_used = TRUE;
02754 DevWarn ("Used short-offset spill location in BB%d", BB_id(bb));
02755 }
02756 else {
02757 spill_loc = CGSPILL_Get_TN_Spill_Location (spill_tn, CGSPILL_LGRA);
02758 }
02759
02760 CGSPILL_Store_To_Memory (spill_tn, spill_loc, OPS_Init(&spill_ops),
02761 CGSPILL_LRA, bb);
02762 #ifdef TARG_IA64
02763 if (nat_bit_tn)
02764 st_2_st_spill (&spill_ops, true);
02765 #endif
02766 CGSPILL_Prepend_Ops (bb, &spill_ops);
02767 new_tn = Build_TN_Like (spill_tn);
02768 Set_TN_spill(new_tn, spill_loc);
02769 CGSPILL_Load_From_Memory (new_tn, spill_loc, OPS_Init(&spill_ops),
02770 CGSPILL_LRA, bb);
02771 #ifdef TARG_IA64
02772 if (nat_bit_tn)
02773 ld_2_ld_fill (&spill_ops, true);
02774 #endif
02775 CGSPILL_Append_Ops (bb, &spill_ops);
02776 Set_TN_is_global_reg (new_tn);
02777 LRA_TN_Allocate_Register (new_tn, reg);
02778
02779 if (magic_spill_used) {
02780 Set_TN_spill(spill_tn, sv_spill_location);
02781 Magic_Spill_Location = NULL;
02782 }
02783 }
02784
02785 static BOOL
02786 Can_Use_Be_Moved (
02787 LIVE_RANGE *lr,
02788 INT spill_opnum,
02789 INT *moveto)
02790 {
02791 ARC_LIST *arcs;
02792 INT use_opnum = LR_last_use(lr);
02793 OP *use_op = OP_VECTOR_element (Insts_Vector, use_opnum);
02794 ISA_REGISTER_CLASS cl = TN_register_class (LR_tn(lr));
02795 INT tgt_opnum = LR_first_def(lr);
02796
02797
02798 if (tgt_opnum == 0 || OP_flag1 (use_op) || OP_xfer(use_op)) return FALSE;
02799
02800 #if defined(TARG_MIPS) && !defined(TARG_SL)
02801
02802
02803
02804 if (OP_results(use_op) == 1 &&
02805 TN_register_class(OP_result(use_op, 0)) == ISA_REGISTER_CLASS_fcc)
02806 return FALSE;
02807 #endif
02808
02809 for (arcs = OP_preds(use_op); arcs != NULL; arcs = ARC_LIST_rest(arcs)) {
02810 ARC *arc = ARC_LIST_first(arcs);
02811 OP *pred_op = ARC_pred(arc);
02812
02813 if (OP_flag1(pred_op)) return FALSE;
02814 INT pred_opnum = BB_OP_MAP32_Get (op_to_opnum, pred_op);
02815
02816 if (pred_opnum > tgt_opnum) tgt_opnum = pred_opnum;
02817 }
02818
02819
02820
02821
02822
02823 if (LR_use_cnt(lr) > 1) {
02824 for (INT i = use_opnum-1; i > tgt_opnum; i--) {
02825 OP *op = OP_VECTOR_element (Insts_Vector, i);
02826 if (OP_Refs_TN (op, LR_tn(lr))) {
02827 tgt_opnum = i;
02828 break;
02829 }
02830 }
02831 }
02832
02833
02834 while (tgt_opnum < spill_opnum) {
02835 OP *op = OP_VECTOR_element (Insts_Vector, tgt_opnum);
02836 if (!OP_flag1(op)) break;
02837 tgt_opnum++;
02838 }
02839
02840 if (tgt_opnum >= (spill_opnum - 1)) return FALSE;
02841
02842 INT regs_needed = 0;
02843 INT i;
02844 for (i = 0; i < OP_results(use_op); i++) {
02845 TN *tn = OP_result(use_op, i);
02846 if (!TN_is_const_reg(tn) && (TN_register_class(tn) == cl)) {
02847 LIVE_RANGE *result_lr = LR_For_TN (tn);
02848 if (LR_first_def(result_lr) == use_opnum)
02849 regs_needed--;
02850 }
02851 }
02852 for (i = 0; i < OP_opnds(use_op); i++) {
02853 TN *tn = OP_opnd(use_op, i);
02854 if (!TN_is_const_reg(tn) && TN_is_register(tn) && (TN_register_class(tn) == cl)) {
02855 LIVE_RANGE *lr = LR_For_TN (tn);
02856 if (LR_last_use(lr) == use_opnum) regs_needed++;
02857 }
02858 }
02859 if (regs_needed <= 0) return FALSE;
02860
02861 *moveto = tgt_opnum;
02862 return TRUE;
02863 }
02864
02865
02866
02867
02868
02869 static BOOL
02870 Can_Def_Be_Moved (
02871 LIVE_RANGE *lr,
02872 INT spill_opnum,
02873 INT *moveto)
02874 {
02875 ARC_LIST *arcs;
02876 INT def_opnum = LR_first_def(lr);
02877 OP *def_op = OP_VECTOR_element (Insts_Vector, def_opnum);
02878 ISA_REGISTER_CLASS cl = TN_register_class (LR_tn(lr));
02879 INT tgt_opnum = LR_last_use(lr);
02880
02881 if (OP_side_effects(def_op)) return FALSE;
02882 if (OP_flag1 (def_op)) return FALSE;
02883 if (LR_def_cnt(lr) != 1) return FALSE;
02884 if (tgt_opnum <= spill_opnum) return FALSE;
02885
02886 for (arcs = OP_succs(def_op); arcs != NULL; arcs = ARC_LIST_rest(arcs)) {
02887 ARC *arc = ARC_LIST_first(arcs);
02888 OP *succ_op = ARC_succ(arc);
02889
02890 if (OP_flag1(succ_op)) return FALSE;
02891 INT succ_opnum = BB_OP_MAP32_Get (op_to_opnum, succ_op);
02892
02893 if (succ_opnum < tgt_opnum) tgt_opnum = succ_opnum;
02894 }
02895
02896 INT i;
02897 for (i = 0; i < OP_opnds(def_op); i++) {
02898 TN *tn = OP_opnd(def_op, i);
02899
02900 if (!TN_is_const_reg(tn)) {
02901
02902
02903
02904 for (INT j = 0; j < OP_results(def_op); j++) {
02905 if (OP_result(def_op, j) == tn) return FALSE;
02906 }
02907
02908
02909 if (TN_is_register(tn) && TN_register_class(tn) == cl) {
02910 LIVE_RANGE *opnd_lr = LR_For_TN (tn);
02911 INT opnd_last_use = LR_last_use(opnd_lr);
02912 if (opnd_last_use < tgt_opnum) tgt_opnum = opnd_last_use;
02913 }
02914 }
02915 }
02916
02917
02918 if (tgt_opnum != VECTOR_count(Insts_Vector)) {
02919 while (tgt_opnum > spill_opnum) {
02920 OP *op = OP_VECTOR_element (Insts_Vector, tgt_opnum);
02921 if (!OP_flag1(op)) break;
02922 tgt_opnum--;
02923 }
02924 }
02925
02926 if (tgt_opnum <= spill_opnum) return FALSE;
02927
02928 *moveto = tgt_opnum;
02929 return TRUE;
02930 }
02931
02932
02933
02934
02935
02936
02937
02938 static void
02939 Analyze_Reordering (
02940 LIVE_RANGE *lr,
02941 SPILL_CANDIDATE *best,
02942 INT spill_opnum)
02943 {
02944 INT moveto;
02945
02946 INT use_opnum = LR_last_use(lr);
02947
02948 if (LR_use_cnt(lr) != 0 &&
02949 TN_is_local_reg(LR_tn(lr)) &&
02950 Can_Use_Be_Moved (lr, spill_opnum, &moveto) &&
02951 (best->spill_kind == SPILL_NONE ||
02952 best->benefit < (spill_opnum - moveto)))
02953 {
02954 best->spill_kind = SPILL_MOVE_USE;
02955 best->u1.s2.move_lr = lr;
02956 best->u1.s2.from = use_opnum;
02957 best->u1.s2.to = moveto;
02958 best->cost = 0.0;
02959 best->benefit = spill_opnum - moveto;
02960 }
02961
02962 INT def_opnum = LR_first_def(lr);
02963
02964 if (LR_def_cnt(lr) != 0 &&
02965 def_opnum < spill_opnum &&
02966 Can_Def_Be_Moved (lr, spill_opnum, &moveto) &&
02967 (best->spill_kind == SPILL_NONE ||
02968 best->benefit < (spill_opnum - def_opnum)))
02969 {
02970 best->spill_kind = SPILL_MOVE_DEF;
02971 best->u1.s2.move_lr = lr;
02972 best->u1.s2.from = def_opnum;
02973 best->u1.s2.to = moveto;
02974 best->cost = 0.0;
02975 best->benefit = spill_opnum - def_opnum;
02976 }
02977
02978
02979
02980
02981
02982 }
02983
02984 static void
02985 Move_Def (BB *bb, SPILL_CANDIDATE *best)
02986 {
02987 INT from = best->u1.s2.from;
02988 INT to = best->u1.s2.to;
02989 OP *from_op = OP_VECTOR_element (Insts_Vector, from);
02990
02991 if (Do_LRA_Trace(Trace_LRA_Spill)) {
02992 fprintf (TFile, "LRA_SPILL>> move def %d to before %d\n", from, to);
02993 }
02994 BB_Remove_Op (bb, from_op);
02995 if (to < VECTOR_size(Insts_Vector)) {
02996 OP *to_op = OP_VECTOR_element (Insts_Vector, to);
02997 BB_Insert_Op_Before (bb, to_op, from_op);
02998 }
02999 else {
03000 OPS ops = OPS_EMPTY;
03001 OPS_Append_Op (&ops, from_op);
03002 CGSPILL_Append_Ops (bb, &ops);
03003 }
03004 }
03005
03006
03007 static void
03008 Move_Use (BB *bb, SPILL_CANDIDATE *best)
03009 {
03010 INT from = best->u1.s2.from;
03011 INT to = best->u1.s2.to;
03012 OP *from_op = OP_VECTOR_element (Insts_Vector, from);
03013 OP *to_op = OP_VECTOR_element (Insts_Vector, to);
03014
03015 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03016 fprintf (TFile, "LRA_SPILL>> move use %d to after %d\n", from, to);
03017 }
03018 BB_Remove_Op (bb, from_op);
03019 BB_Insert_Op_After (bb, to_op, from_op);
03020 }
03021
03022
03023
03024
03025 static void
03026 Apply_Move_Transformations ( BB *bb, SPILL_CANDIDATE *transformations)
03027 {
03028 SPILL_CANDIDATE *cand;
03029
03030 for (cand = transformations; cand != NULL; cand = cand->next) {
03031 switch (cand->spill_kind) {
03032 case SPILL_MOVE_DEF:
03033 Move_Def (bb, cand);
03034 break;
03035 case SPILL_MOVE_USE:
03036 Move_Use (bb, cand);
03037 break;
03038 }
03039 }
03040 }
03041
03042
03043
03044
03045
03046 static void
03047 Remove_LRs_For_OP (OP *op)
03048 {
03049 INT i;
03050 if (op == NULL) return;
03051 for (i = 0; i < OP_results(op); i++) {
03052 VECTOR_Delete_Element (Live_LRs_Vector, LR_For_TN (OP_result(op, i)));
03053 }
03054 for (i = 0; i < OP_opnds(op); i++) {
03055 TN *opnd_tn = OP_opnd(op,i);
03056 if (TN_is_register(opnd_tn)) {
03057 VECTOR_Delete_Element (Live_LRs_Vector, LR_For_TN(opnd_tn));
03058 }
03059 }
03060 }
03061
03062
03063 static void
03064 Update_Fat_Points (SPILL_CANDIDATE *best, INT spill_opnum)
03065 {
03066 LIVE_RANGE *lr;
03067 INT low;
03068 BOOL global_lr_spill;
03069
03070 switch (best->spill_kind) {
03071 case SPILL_LIVE_RANGE:
03072 lr = best->u1.spill_lr;
03073 global_lr_spill = !TN_is_local_reg(LR_tn(lr));
03074 if (LR_exposed_use(lr)) {
03075 low = LR_first_spill(lr);
03076 } else {
03077 low = LR_first_def(lr) + 1;
03078 }
03079 VECTOR_Delete_Element (Live_LRs_Vector, lr);
03080 break;
03081
03082 case SPILL_MOVE_DEF:
03083 case SPILL_MOVE_USE:
03084 OP *from_op = OP_VECTOR_element (Insts_Vector, best->u1.s2.from);
03085 Remove_LRs_For_OP (from_op);
03086
03087 Set_OP_flag1 (from_op);
03088 if (best->u1.s2.to != VECTOR_count(Insts_Vector)) {
03089 OP *to_op = OP_VECTOR_element (Insts_Vector, best->u1.s2.to);
03090 Set_OP_flag1 (to_op);
03091 }
03092 if (best->spill_kind == SPILL_MOVE_DEF) {
03093 low = best->u1.s2.from;
03094 }
03095 else {
03096 low = best->u1.s2.to + 1;
03097 }
03098 lr = best->u1.s2.move_lr;
03099 break;
03100 }
03101
03102 INT i;
03103 for (i = low; i <= spill_opnum; i++) {
03104
03105
03106
03107
03108
03109
03110 if (!Op_Uses_TN(LR_tn(lr), i) || (i == spill_opnum && global_lr_spill)) {
03111 fat_points[i]--;
03112 }
03113 }
03114 }
03115
03116
03117
03118
03119
03120
03121 static BOOL
03122 At_Unallocated_Op_Definition(INT fat_opnum, INT cur_opnum,
03123 ISA_REGISTER_CLASS spill_cl)
03124 {
03125 INT opndnum;
03126 OP *op = OP_VECTOR_element (Insts_Vector, fat_opnum);
03127 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
03128 TN *tn = OP_opnd(op, opndnum);
03129 if (tn == NULL || TN_is_constant(tn)) {
03130 continue;
03131 }
03132 LIVE_RANGE *lr = LR_For_TN(tn);
03133
03134
03135
03136 if (TN_register_class(tn) == spill_cl && lr != NULL
03137 && !LR_fat_allocated(lr) && LR_last_use(lr) == fat_opnum &&
03138 LR_first_def(lr) == cur_opnum) {
03139 return(TRUE);
03140 }
03141 }
03142 return(FALSE);
03143 }
03144
03145
03146
03147
03148 static void
03149 Analyze_Spilling_Live_Range (
03150 LIVE_RANGE *spill_lr,
03151 INT spill_opnum,
03152 SPILL_CANDIDATE *best,
03153 INT fatpoint)
03154 {
03155 INT spill_fatpoint = fatpoint_min;
03156 TN *spill_tn = LR_tn(spill_lr);
03157 BOOL is_local_tn = TN_is_local_reg (spill_tn);
03158 ISA_REGISTER_CLASS spill_cl = TN_register_class(spill_tn);
03159 REGISTER spill_reg = REGISTER_UNDEFINED;
03160 ST *spill_loc;
03161 BOOL def_available = FALSE;
03162 BOOL pending_store = FALSE;
03163 BOOL spill_store_deleted = FALSE;
03164 BOOL already_spilled = (TN_spill(spill_tn) == NULL) ? FALSE : TRUE;
03165 BOOL reloadable = (already_spilled || Is_LR_Reloadable(spill_lr)) ? TRUE : FALSE;
03166 float store_cost, restore_cost;
03167 float cost = 0.0;
03168 INT benefit = 0;
03169 INT cur_benefit = 0;
03170 INT first_def = LR_first_def(spill_lr);
03171 INT last_use = LR_last_use(spill_lr);
03172 INT last_def = 0;
03173 INT last_use_seen = 0;
03174 INT def_cnt = 0;
03175 BOOL lr_spans_spill_opnum = FALSE;
03176 BOOL upward_exposed_global = FALSE;
03177
03178 CGSPILL_Cost_Estimate (spill_tn, NULL, &store_cost, &restore_cost, CGSPILL_LRA);
03179
03180
03181
03182
03183
03184
03185
03186 if (restore_cost > 3.0 && TN_is_rematerializable(spill_tn)) {
03187 Reset_TN_is_rematerializable (spill_tn);
03188 Set_TN_home(spill_tn, NULL);
03189 CGSPILL_Cost_Estimate (spill_tn, NULL, &store_cost, &restore_cost, CGSPILL_LRA);
03190 }
03191
03192 spill_loc = TN_spill(spill_tn);
03193
03194
03195
03196
03197 if (spill_loc != NULL
03198 #ifdef KEY
03199 && ! TN_is_rematerializable(spill_tn)
03200 #endif
03201 ) cost += 16.0;
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214 if (TN_register_class(spill_tn) == ISA_REGISTER_CLASS_integer
03215 && !TN_is_rematerializable(spill_tn) && !TN_is_gra_homeable(spill_tn)
03216 && Exp_Is_Large_Stack_Sym(spill_loc, 0)) {
03217 spill_fatpoint--;
03218 }
03219
03220 if (reloadable) store_cost = 0.0;
03221
03222 if (!is_local_tn) {
03223 spill_reg = LRA_TN_register(spill_tn);
03224 if (LR_exposed_use(spill_lr)) {
03225 def_available = TRUE;
03226 pending_store = TRUE;
03227 first_def = 1;
03228 upward_exposed_global = TRUE;
03229 last_def = 0;
03230 }
03231 if (last_use == VECTOR_size(Insts_Vector)) last_use--;
03232 }
03233
03234 for (INT i = first_def; i <= last_use; i++)
03235 {
03236 OP *op = OP_VECTOR_element(Insts_Vector, i);
03237 if (op == NULL) continue;
03238
03239 #ifdef TARG_X8664
03240
03241
03242
03243
03244 for (INT opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
03245 TN* opnd_tn = OP_opnd(op, opndnum);
03246 if (TN_is_register(opnd_tn) &&
03247 TN_is_preallocated(opnd_tn) &&
03248 TNs_Are_Equivalent(opnd_tn, spill_tn)) {
03249 return;
03250 }
03251 }
03252 for (INT resnum = 0; resnum < OP_results(op); resnum++) {
03253 TN* res_tn = OP_result(op, resnum);
03254 if (TN_is_register(res_tn) &&
03255 TN_is_preallocated(res_tn) &&
03256 TNs_Are_Equivalent(res_tn, spill_tn)) {
03257 return;
03258 }
03259 }
03260 #endif
03261
03262 #if defined(TARG_MIPS) && !(TARG_SL)
03263
03264
03265
03266 if (OP_code(op) == TOP_jalr) {
03267 TN* opnd_tn = OP_opnd(op, 0);
03268 if (TNs_Are_Equivalent(opnd_tn, spill_tn))
03269 return;
03270 }
03271 #endif
03272
03273 BOOL at_fatpoint = (fat_points[i] > spill_fatpoint && i <= spill_opnum);
03274
03275
03276
03277 if (at_fatpoint) {
03278 cur_benefit++;
03279 if (pending_store) {
03280 cost += store_cost;
03281 pending_store = FALSE;
03282 upward_exposed_global = FALSE;
03283 }
03284 }
03285
03286
03287
03288
03289 if (Op_Uses_TN(spill_tn, i)) {
03290
03291
03292
03293
03294 if (i == spill_opnum) {
03295 return;
03296 } else if (i > spill_opnum && last_def < spill_opnum) {
03297 lr_spans_spill_opnum = TRUE;
03298 }
03299
03300 if (!reloadable && Is_OP_Spill_Store (op, spill_loc) &&
03301 !already_spilled && (i == last_use)) cost += 1.0;
03302
03303
03304
03305
03306
03307
03308
03309
03310 if (OP_same_res(op) || OP_cond_def(op)) {
03311 cost += 1.0;
03312 }
03313
03314 benefit += cur_benefit;
03315 cur_benefit = 0;
03316 last_use_seen = i;
03317 if (!reloadable && (already_spilled && Is_OP_Spill_Store (op, spill_loc))) {
03318
03319
03320
03321
03322 spill_store_deleted = TRUE;
03323 cost -= store_cost;
03324 if (LR_exposed_use(spill_lr) == i) def_available = FALSE;
03325 continue;
03326 }
03327
03328
03329 if (!def_available) {
03330 def_available = TRUE;
03331 cost += restore_cost;
03332 }
03333 if (LR_exposed_use(spill_lr) == i) def_available = FALSE;
03334 }
03335
03336
03337 if ((TN_is_local_reg (spill_tn) &&
03338 OP_Defs_TN (op, spill_tn)) ||
03339 (!TN_is_local_reg (spill_tn) &&
03340 OP_Defs_Reg (op, spill_cl, spill_reg)))
03341 {
03342 def_cnt++;
03343 if (def_cnt > 1 && last_use_seen < spill_opnum && i > spill_opnum) {
03344
03345
03346
03347
03348
03349
03350 benefit += cur_benefit;
03351 lr_spans_spill_opnum = TRUE;
03352 }
03353 last_def = i;
03354 cur_benefit = 0;
03355 if (reloadable || (already_spilled && Is_OP_Spill_Load (op, spill_loc))) {
03356
03357
03358
03359
03360 cost -= restore_cost;
03361 continue;
03362 }
03363
03364 def_available = TRUE;
03365 pending_store = TRUE;
03366 upward_exposed_global = FALSE;
03367 }
03368 else if (already_spilled && Is_OP_Spill_Load(op, spill_loc) && pending_store &&
03369 spill_store_deleted) {
03370
03371
03372
03373
03374 cost += store_cost;
03375 pending_store = FALSE;
03376 }
03377 else if (at_fatpoint || (upward_exposed_global &&
03378 At_Unallocated_Op_Definition(spill_opnum, i, spill_cl))) {
03379
03380
03381
03382
03383
03384
03385
03386 def_available = FALSE;
03387
03388 if (upward_exposed_global) {
03389 cost += store_cost;
03390 pending_store = FALSE;
03391 upward_exposed_global = FALSE;
03392 }
03393 }
03394 }
03395
03396
03397
03398
03399
03400 if (pending_store && spill_store_deleted) {
03401 cost += store_cost;
03402 pending_store = FALSE;
03403 }
03404
03405
03406
03407 if (LR_last_use(spill_lr) == VECTOR_size(Insts_Vector)) {
03408
03409 if (last_def < spill_opnum) {
03410 lr_spans_spill_opnum = TRUE;
03411 }
03412
03413 benefit += cur_benefit;
03414 if (!def_available) {
03415 cost += restore_cost;
03416 }
03417 else {
03418
03419
03420 cost += 0.5;
03421 }
03422 }
03423
03424 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03425 fprintf (TFile, "Analyze >> (cost:%g, benefit:%d, spans spill:%d)",
03426 cost, benefit, lr_spans_spill_opnum);
03427 Print_Live_Range (spill_lr);
03428 }
03429
03430 if (lr_spans_spill_opnum &&
03431 benefit > 0 &&
03432 (best->spill_kind == SPILL_NONE ||
03433 (float)(benefit - best->benefit) > 16.0 * (cost - best->cost)))
03434 {
03435 best->spill_kind = SPILL_LIVE_RANGE;
03436 best->u1.spill_lr = spill_lr;
03437 best->cost = cost;
03438 best->benefit = benefit;
03439 }
03440 }
03441
03442
03443 static void
03444 Add_Spill_Store_After_Def (TN *tn, INT def, BB *bb)
03445 {
03446 OPS spill_ops = OPS_EMPTY;
03447 ST *spill_loc = TN_spill(tn);
03448
03449 CGSPILL_Store_To_Memory (tn, spill_loc, &spill_ops, CGSPILL_LRA, bb);
03450
03451 if (def != 0) {
03452 OP *def_op = OP_VECTOR_element(Insts_Vector, def);
03453 CGSPILL_Insert_Ops_After (bb, def_op, &spill_ops);
03454 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03455 fprintf (TFile, "LRA_SPILL>> store TN%d after %d\n", TN_number(tn), def);
03456 }
03457 }
03458 else {
03459 CGSPILL_Prepend_Ops (bb, &spill_ops);
03460 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03461 fprintf (TFile, "LRA_SPILL>> store TN%d at top of bb\n", TN_number(tn));
03462 }
03463 }
03464 }
03465
03466
03467 static void
03468 Add_Spill_Load_Before_Use (TN *tn, ST *spill_loc, OP *reload_op, INT use, BB *bb)
03469 {
03470 OPS spill_ops = OPS_EMPTY;
03471
03472 if (reload_op) {
03473 OP *new_op = Dup_OP (reload_op);
03474 Copy_WN_For_Memory_OP (new_op, reload_op);
03475
03476
03477
03478
03479
03480 Set_OP_result (new_op, 0 , tn);
03481 OPS_Append_Op (&spill_ops, new_op);
03482 }
03483 #ifdef KEY
03484 else if (TN_is_rematerializable(tn) || TN_is_gra_homeable(tn)) {
03485 CGSPILL_Load_From_Memory (tn, (ST*)TN_home(tn), &spill_ops,
03486 CGSPILL_GRA, bb);
03487 }
03488 #endif
03489 else {
03490 FmtAssert(spill_loc != NULL,
03491 ("LRA: Add_Spill_Load_Before_Use: spill_loc cannot be NULL\n"));
03492 Set_TN_spill(tn, spill_loc);
03493 CGSPILL_Load_From_Memory (tn, spill_loc, &spill_ops, CGSPILL_LRA, bb);
03494 }
03495
03496 if (use == VECTOR_size(Insts_Vector)) {
03497
03498 CGSPILL_Append_Ops (bb, &spill_ops);
03499 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03500 fprintf (TFile, "LRA_SPILL>> load TN%d at end of bb\n", TN_number(tn));
03501 }
03502 }
03503 else {
03504 OP *use_op = OP_VECTOR_element(Insts_Vector, use);
03505 CGSPILL_Insert_Ops_Before (bb, use_op, &spill_ops);
03506 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03507 fprintf (TFile, "LRA_SPILL>> load TN%d before %d\n", TN_number(tn), use);
03508 }
03509 }
03510
03511 }
03512
03513
03514 static void
03515 Replace_TN_References (TN *old_tn, TN *new_tn, OP *op)
03516 {
03517
03518 for (INT opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
03519 TN *opnd_tn = OP_opnd(op, opndnum);
03520 if (!TN_is_register(opnd_tn)) continue;
03521 ISA_REGISTER_CLASS old_cl = TN_register_class(old_tn);
03522 REGISTER old_reg = LRA_TN_register(old_tn);
03523 if (opnd_tn == old_tn ||
03524 (!TN_is_local_reg(old_tn) &&
03525 TN_register_class(opnd_tn) == old_cl &&
03526 LRA_TN_register(opnd_tn) == old_reg))
03527 {
03528 Set_OP_opnd(op, opndnum, new_tn);
03529 }
03530 }
03531
03532
03533
03534
03535 for (INT i = 0; i < OP_results(op); i++) {
03536 TN *result_tn = OP_result(op, i);
03537 LIVE_RANGE *lr = LR_For_TN (result_tn);
03538 if (lr != NULL)
03539 Reset_LR_reloadable (lr);
03540 }
03541 }
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558 static void
03559 Spill_Live_Range (
03560 BB *bb,
03561 LIVE_RANGE *spill_lr,
03562 INT fatpoint,
03563 INT spill_opnum,
03564 BOOL (*spillpoint)(TN*, OP*) = NULL)
03565 {
03566 INT spill_fatpoint = fatpoint_min;
03567 TN *spill_tn = LR_tn(spill_lr);
03568 BOOL is_local_tn = TN_is_local_reg (spill_tn);
03569 ISA_REGISTER_CLASS spill_cl = TN_register_class(spill_tn);
03570 REGISTER spill_reg = REGISTER_UNDEFINED;
03571 ST *spill_loc = NULL;
03572 ST *sv_spill_location = NULL;
03573 BOOL magic_spill_used = FALSE;
03574 BOOL upward_exposed_global = FALSE;
03575 TN *new_tn = NULL;
03576 INT first_def;
03577 INT last_use;
03578 BOOL pending_store = FALSE;
03579 BOOL spill_store_deleted = FALSE;
03580 BOOL def_available = FALSE;
03581 #ifdef KEY
03582 const BOOL already_spilled = TN_has_spill(spill_tn);
03583 #else
03584 BOOL already_spilled = (TN_spill(spill_tn) == NULL) ? FALSE : TRUE;
03585 #endif
03586 BOOL reloadable = (already_spilled || LR_reloadable(spill_lr)) ? TRUE : FALSE;
03587 OP *reloadable_def = NULL;
03588 INT last_def;
03589 INT last_opnum;
03590
03591 #ifdef KEY
03592 last_def = 0;
03593 #endif
03594
03595 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03596 fprintf (TFile, "LRA_SPILL>> spill lr at OP:%d", spill_opnum);
03597 Print_Live_Range (spill_lr);
03598 }
03599
03600 first_def = LR_first_def(spill_lr);
03601 last_use = LR_last_use(spill_lr);
03602 #ifdef TARG_IA64 // this is problematic because Update_Live_LRs_Vector called
03603 if (reloadable) {
03604
03605
03606 reloadable_def = OP_VECTOR_element(Insts_Vector, first_def);
03607
03608
03609
03610
03611 if ( reloadable_def && !LR_reloadable(spill_lr) && !Is_OP_Spill_Load (reloadable_def, TN_spill(spill_tn)) ){
03612 reloadable_def = NULL;
03613 }
03614 else {
03615
03616
03617
03618
03619 Remove_LRs_For_OP (reloadable_def);
03620 }
03621 if(already_spilled) spill_loc = TN_spill(spill_tn);
03622
03623 }
03624 #else
03625 if( already_spilled ){
03626 spill_loc = (ST*)TN_home(spill_tn);
03627 }
03628 #endif
03629 else {
03630
03631
03632 if (Trip_Count == MAX_TRIP_COUNT &&
03633 Magic_Spill_Location != NULL &&
03634 !TN_is_float(spill_tn))
03635 {
03636 sv_spill_location = TN_spill(spill_tn);
03637 Set_TN_spill(spill_tn, Magic_Spill_Location);
03638 spill_loc = Magic_Spill_Location;
03639 magic_spill_used = TRUE;
03640 DevWarn ("Used short-offset spill location in BB%d", BB_id(bb));
03641 }
03642 else {
03643
03644 if (GP_TN != NULL && TN_is_rematerializable (spill_tn) && BB_exit (bb)) {
03645 LIVE_RANGE *gp_lr = LR_For_TN (GP_TN);
03646 if (gp_lr != NULL &&
03647 LR_def_cnt(gp_lr) != 0 &&
03648 last_use > LR_first_def(gp_lr))
03649 {
03650 Reset_TN_is_rematerializable (spill_tn);
03651 Set_TN_home(spill_tn, NULL);
03652 }
03653 }
03654 spill_loc = CGSPILL_Get_TN_Spill_Location (spill_tn,
03655 (is_local_tn) ? CGSPILL_LRA : CGSPILL_LGRA);
03656 }
03657 }
03658
03659
03660
03661
03662
03663
03664
03665
03666 if (TN_register_class(spill_tn) == ISA_REGISTER_CLASS_integer
03667 && !TN_is_rematerializable(spill_tn) && !TN_is_gra_homeable(spill_tn)
03668 && Exp_Is_Large_Stack_Sym(spill_loc, 0)) {
03669 spill_fatpoint--;
03670 }
03671
03672 if (!is_local_tn) {
03673 spill_reg = LRA_TN_register(spill_tn);
03674 if (LR_exposed_use(spill_lr)) {
03675 new_tn = spill_tn;
03676 def_available = TRUE;
03677 pending_store = TRUE;
03678 upward_exposed_global = TRUE;
03679 last_def = 0;
03680 first_def = 1;
03681 }
03682 if (last_use == VECTOR_size(Insts_Vector)) last_use--;
03683 }
03684
03685 last_opnum = 0;
03686 INT i;
03687 for (i = first_def; i <= last_use; i++)
03688 {
03689 OP *op = OP_VECTOR_element(Insts_Vector, i);
03690 if (op == NULL) continue;
03691
03692 BOOL at_fatpoint;
03693
03694 #ifdef TARG_X8664
03695
03696 if (spillpoint)
03697 at_fatpoint = (*spillpoint)(spill_tn, op);
03698 else
03699 #endif
03700 at_fatpoint = (fat_points[i] > spill_fatpoint && i <= spill_opnum);
03701
03702
03703
03704 if (pending_store && at_fatpoint) {
03705 Add_Spill_Store_After_Def (new_tn, last_def, bb);
03706 if (upward_exposed_global) {
03707 LR_first_spill(spill_lr) = last_def + 1;
03708 upward_exposed_global = FALSE;
03709 }
03710 pending_store = FALSE;
03711 }
03712
03713
03714
03715
03716 if ((is_local_tn &&
03717 OP_Refs_TN (op, spill_tn)) ||
03718 (!is_local_tn &&
03719 OP_Refs_Reg (op, spill_cl, spill_reg)))
03720 {
03721 if (!reloadable && Is_OP_Spill_Store (op, spill_loc) &&
03722 #ifdef TARG_IA64
03723 !already_spilled && (i == last_use)
03724 && OP_code(op)==TOP_st8_spill) {
03725
03726 #else
03727 !already_spilled && (i == last_use)) {
03728 #endif
03729
03730
03731
03732
03733 BB_Remove_Op (bb, op);
03734 Clobber_Op_Info(i, spill_cl);
03735 spill_store_deleted = TRUE;
03736 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03737 fprintf (TFile, "LRA_SPILL>> Removed spill store at %d\n", i);
03738 Print_OP_No_SrcLine(op);
03739 }
03740 if (LR_exposed_use(spill_lr) == i) {
03741 def_available = FALSE;
03742 }
03743 continue;
03744 }
03745
03746
03747 if (!def_available) {
03748 def_available = TRUE;
03749 new_tn = Dup_TN_Even_If_Dedicated (spill_tn);
03750 Is_True(reloadable_def || spill_loc, ("Attempt to locate a NULL spill_loc!"));
03751 #ifdef TARG_X8664
03752 Reset_TN_is_preallocated(new_tn);
03753 #endif
03754
03755 #ifdef KEY
03756 if (TN_has_spill(spill_tn))
03757 #endif
03758 Set_TN_spill(new_tn, spill_loc);
03759 Add_Spill_Load_Before_Use (new_tn, spill_loc, reloadable_def, i, bb);
03760 }
03761 else if (Do_LRA_Trace(Trace_LRA_Spill)) {
03762 fprintf (TFile, "LRA_SPILL>> skipped load of TN%d before %d\n",
03763 TN_number(new_tn), i);
03764 }
03765 Replace_TN_References (spill_tn, new_tn, op);
03766 if (LR_exposed_use(spill_lr) == i) {
03767 def_available = FALSE;
03768 }
03769 }
03770
03771
03772 if ((TN_is_local_reg (spill_tn) &&
03773 OP_Defs_TN (op, spill_tn)) ||
03774 (!TN_is_local_reg (spill_tn) &&
03775 OP_Defs_Reg (op, spill_cl, spill_reg)))
03776 {
03777 if (i == VECTOR_size(Insts_Vector)-1) {
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790 last_def = i;
03791 continue;
03792 }
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802 #ifdef TARG_IA64
03803 if (LR_reloadable(spill_lr) || (already_spilled && Is_OP_Spill_Load (op, spill_loc))) {
03804 #else
03805 if (TN_is_rematerializable(LR_tn(spill_lr)) ||
03806 (TN_is_gra_homeable(LR_tn(spill_lr)) || already_spilled) &&
03807 Is_OP_Spill_Load (op, spill_loc)) {
03808 #endif
03809
03810
03811
03812
03813 BB_Remove_Op (bb, op);
03814 Clobber_Op_Info(i, spill_cl);
03815 Set_OP_VECTOR_element(Insts_Vector, i, NULL);
03816 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03817 if (reloadable) {
03818 fprintf (TFile, "LRA_SPILL>> Removed reloadable load at %d\n",
03819 i);
03820 } else {
03821 fprintf (TFile, "LRA_SPILL>> Removed spill load at %d\n", i);
03822 }
03823 Print_OP_No_SrcLine(op);
03824 }
03825 continue;
03826 }
03827
03828
03829
03830
03831
03832
03833
03834
03835 INT resnum = 0;
03836 TN* prev_tn = new_tn ? new_tn : spill_tn;
03837 new_tn = Dup_TN_Even_If_Dedicated (spill_tn);
03838 #ifdef TARG_X8664
03839 Reset_TN_is_preallocated(new_tn);
03840 #endif
03841
03842 Set_TN_spill(new_tn, spill_loc);
03843 local_spills++;global_spills++;
03844
03845 if ((OP_same_res(op)
03846 #ifdef TARG_X8664
03847 || OP_x86_style(op)
03848 #endif
03849 )
03850 && TN_Pair_In_OP(op, spill_tn, prev_tn)) {
03851
03852
03853
03854
03855
03856 BOOL copy_added = FALSE;
03857 for (INT opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
03858 TN* op_tn = OP_opnd(op, opndnum);
03859 if (op_tn == prev_tn) {
03860 if (!copy_added) {
03861 OPS copy_ops = OPS_EMPTY;
03862 Exp_COPY(new_tn, prev_tn, ©_ops);
03863 OP_srcpos(OPS_last(©_ops)) = OP_srcpos(op);
03864 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03865 fprintf (TFile, "LRA_SPILL>> copy TN%d to TN%d for same_res OP\n",
03866 TN_number(prev_tn), TN_number(new_tn));
03867 }
03868 CGSPILL_Insert_Ops_Before(bb, op, ©_ops);
03869 copy_added = TRUE;
03870 }
03871 Set_OP_opnd(op, opndnum, new_tn);
03872 }
03873 }
03874 FmtAssert(copy_added,
03875 ("LRA: couln't find same_res operand for copy\n"));
03876
03877
03878
03879
03880 #ifndef TARG_IA64
03881 resnum = TN_Resnum_In_OP (op, spill_tn, TRUE);
03882 #else
03883 resnum = TN_Resnum_In_OP (op, spill_tn);
03884 #endif
03885 }
03886
03887 else if (OP_cond_def(op) &&
03888 #ifdef KEY
03889 TNs_Are_Equivalent(OP_result(op, 0), spill_tn)
03890 #else
03891 OP_result(op,0) == spill_tn
03892 #endif
03893 ) {
03894 OPS copy_ops = OPS_EMPTY;
03895 Exp_COPY(new_tn, prev_tn, ©_ops);
03896 OP_srcpos(OPS_last(©_ops)) = OP_srcpos(op);
03897 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03898 fprintf (TFile, "LRA_SPILL>> copy TN%d to TN%d for cond_def OP\n",
03899 TN_number(prev_tn), TN_number(new_tn));
03900 }
03901 CGSPILL_Insert_Ops_Before(bb, op, ©_ops);
03902 #if !defined (TARG_IA64)
03903 resnum = 0;
03904 #else
03905 resnum = TN_Resnum_In_OP (op, spill_tn);
03906 #endif
03907 }
03908
03909 else if ((OP_results(op) > 1) && (OP_result(op, 0) != spill_tn)) {
03910 #ifdef KEY
03911
03912 for( resnum = OP_results(op)-1; resnum >= 0; resnum-- ){
03913 if( TNs_Are_Equivalent( spill_tn, OP_result(op,resnum) ) )
03914 break;
03915 }
03916 FmtAssert( resnum >= 0, ("Spill_Live_Range: invalide result") );
03917 #else
03918 for (resnum = OP_results(op); resnum > 0; resnum--) {
03919 if (spill_tn == OP_result(op,resnum)) break;
03920 }
03921 #endif // KEY
03922 }
03923
03924 Set_OP_result(op, resnum, new_tn);
03925 def_available = TRUE;
03926 upward_exposed_global = FALSE;
03927 pending_store = TRUE;
03928 last_def = i;
03929 }
03930 else if (Is_OP_Spill_Load(op, spill_loc) && pending_store &&
03931 spill_store_deleted) {
03932
03933
03934
03935
03936 Add_Spill_Store_After_Def (new_tn, last_def, bb);
03937 pending_store = FALSE;
03938 }
03939 else if (at_fatpoint || (upward_exposed_global &&
03940 At_Unallocated_Op_Definition(spill_opnum, i, spill_cl))) {
03941
03942
03943
03944
03945
03946
03947
03948 def_available = FALSE;
03949
03950 if (upward_exposed_global) {
03951
03952
03953
03954 LR_first_spill(spill_lr) = last_def + 1;
03955 upward_exposed_global = FALSE;
03956 Add_Spill_Store_After_Def (new_tn, last_opnum, bb);
03957 pending_store = FALSE;
03958 }
03959 }
03960 last_opnum = i;
03961 }
03962
03963
03964
03965
03966
03967 if (pending_store && spill_store_deleted) {
03968 Add_Spill_Store_After_Def (new_tn, last_def, bb);
03969 pending_store = FALSE;
03970 }
03971
03972
03973
03974
03975
03976
03977 if (LR_last_use(spill_lr) == VECTOR_size(Insts_Vector) &&
03978 last_def != VECTOR_size(Insts_Vector)-1) {
03979 if (!def_available) {
03980 Add_Spill_Load_Before_Use (spill_tn, spill_loc, reloadable_def,
03981 LR_last_use(spill_lr), bb);
03982 }
03983 else {
03984
03985 OPS spill_ops = OPS_EMPTY;
03986 Exp_COPY (spill_tn, new_tn, &spill_ops);
03987 CGSPILL_Append_Ops (bb, &spill_ops);
03988 if (Do_LRA_Trace(Trace_LRA_Spill)) {
03989 fprintf (TFile, "LRA_SPILL>> copy TN%d to TN%d at end of %d\n",
03990 TN_number(new_tn), TN_number(spill_tn), i);
03991 }
03992 }
03993 }
03994
03995 if (magic_spill_used) {
03996
03997 Magic_Spill_Location = NULL;
03998
03999 if (!is_local_tn) {
04000 Set_TN_spill(spill_tn, sv_spill_location);
04001 }
04002 }
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016 if (!is_local_tn && do_global_locking) {
04017 OP *op = OP_VECTOR_element (Insts_Vector, spill_opnum);
04018 INT opndnum;
04019 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
04020 TN *tn = OP_opnd(op, opndnum);
04021 if (tn == NULL || TN_is_constant(tn)) {
04022 continue;
04023 }
04024 LIVE_RANGE *lr = LR_For_TN(tn);
04025
04026 if (TN_register_class(tn) == spill_cl && lr != NULL
04027 && !LR_fat_allocated(lr) && LR_last_use(lr) == spill_opnum) {
04028 Set_TN_is_dedicated(tn);
04029 Set_TN_register(tn, spill_reg);
04030 Set_LR_fat_allocated(lr);
04031 }
04032 }
04033 }
04034 }
04035
04036
04037 static void
04038 Add_To_Live_LRs_Vector (LIVE_RANGE *lr)
04039 {
04040 if (!LR_added(lr)) {
04041 Set_LR_added(lr);
04042 VECTOR_Add_Element (Live_LRs_Vector, lr);
04043 }
04044 }
04045
04046
04047 static void
04048 Update_Live_LRs_Vector (INT opnum, ISA_REGISTER_CLASS cl)
04049 {
04050 if (opnum == 1) return;
04051
04052 INT i;
04053 OP *op = OP_VECTOR_element(Insts_Vector, opnum);
04054 if (op != NULL) {
04055 for (i = 0; i < OP_opnds(op); i++) {
04056 TN *tn = OP_opnd(op,i);
04057 if (!TN_is_register(tn) || TN_register_class(tn) != cl) continue;
04058 LIVE_RANGE *lr = LR_For_TN (tn);
04059
04060 if (lr != NULL &&
04061 LR_last_use(lr) == opnum &&
04062 opnum > (LR_first_def(lr)+1))
04063 {
04064 Add_To_Live_LRs_Vector (lr);
04065 }
04066 }
04067 }
04068
04069
04070
04071
04072 op = OP_VECTOR_element (Insts_Vector, opnum-1);
04073 if (op != NULL) {
04074 for (i = 0; i < OP_results(op); i++) {
04075 TN *tn = OP_result(op, i);
04076 LIVE_RANGE *lr = LR_For_TN (tn);
04077
04078 if (lr != NULL &&
04079 LR_first_def(lr) == (opnum-1) &&
04080 LR_exposed_use(lr) == 0)
04081 {
04082 VECTOR_Delete_Element (Live_LRs_Vector, lr);
04083 }
04084 }
04085 }
04086 }
04087
04088
04089
04090
04091
04092
04093
04094
04095 static void
04096 Remove_Current_LR(INT opnum)
04097 {
04098 OP *op = OP_VECTOR_element (Insts_Vector, opnum-1);
04099
04100 if (op != NULL) {
04101 for (INT i = 0; i < OP_results(op); i++) {
04102 TN *tn = OP_result(op, i);
04103 LIVE_RANGE *lr = LR_For_TN (tn);
04104
04105 if (lr != NULL &&
04106 LR_first_def(lr) == (opnum) &&
04107 LR_exposed_use(lr) == 0)
04108 {
04109 VECTOR_Delete_Element (Live_LRs_Vector, lr);
04110 }
04111 }
04112 }
04113 }
04114
04115
04116
04117
04118
04119
04120
04121
04122 static void
04123 Init_Live_LRs_Vector (
04124 BB *bb,
04125 INT failure_point,
04126 ISA_REGISTER_CLASS cl,
04127 MEM_POOL *pool)
04128 {
04129 OP *failure_op = OP_VECTOR_element(Insts_Vector, failure_point);
04130 Live_LRs_Vector = VECTOR_Init (BB_length(bb)+REGISTER_MAX, pool);
04131
04132
04133
04134 if (!Get_Trace (TP_ALLOC, 0x0100)) {
04135
04136 REGISTER_SET rs = REGISTER_CLASS_allocatable(cl);
04137 for (REGISTER reg = REGISTER_SET_Choose(rs);
04138 reg != REGISTER_UNDEFINED;
04139 reg = REGISTER_SET_Choose_Next(rs, reg))
04140 {
04141 LIVE_RANGE *reg_lr = LR_For_TN (Build_Dedicated_TN(cl, reg, 0));
04142 if (reg_lr != NULL &&
04143 LR_last_use(reg_lr) > failure_point &&
04144 (LR_exposed_use(reg_lr) || LR_first_def(reg_lr) < failure_point) &&
04145 !OP_Refs_Reg (failure_op, cl, reg))
04146 {
04147 Add_To_Live_LRs_Vector (reg_lr);
04148 }
04149 }
04150 }
04151
04152
04153 for (INT opnum = 1; opnum < failure_point; opnum++) {
04154 LIVE_RANGE *clr;
04155 OP *op = OP_VECTOR_element(Insts_Vector, opnum);
04156 for (INT resnum = 0; resnum < OP_results(op); resnum++) {
04157 TN *result_tn = OP_result(op, resnum);
04158 if (TN_register_class(result_tn) == cl &&
04159 TN_is_local_reg(result_tn) &&
04160 (clr = LR_For_TN (result_tn)) &&
04161 LR_first_def(clr) == opnum &&
04162 LR_last_use(clr) > failure_point &&
04163 !OP_Refs_TN (failure_op, result_tn))
04164 {
04165 Add_To_Live_LRs_Vector (clr);
04166 }
04167 }
04168 }
04169 }
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189 static void
04190 Fix_LRA_Blues (BB *bb, TN *tn, HB_Schedule *Sched)
04191 {
04192
04193
04194 BOOL need_dep_graph = (CG_opt_level > 0);
04195
04196
04197
04198
04199
04200
04201 BOOL allow_reordering = Check_Allow_Reorder() || (LRA_do_reorder == TRUE);
04202
04203 #ifdef KEY
04204
04205
04206 need_dep_graph = ((need_dep_graph &&
04207 Need_Dep_Graph_For_Mark_Reloadable_Live_Ranges) ||
04208 allow_reordering);
04209 #endif
04210
04211 ISA_REGISTER_CLASS cl = TN_register_class(tn);
04212 LIVE_RANGE *lr = LR_For_TN(tn);
04213 INT failure_point;
04214 INT opnum;
04215
04216 #ifdef KEY
04217 if (Trip_Count > MAX_TRIP_COUNT &&
04218 large_asm_clobber_set[cl]) {
04219 ErrMsg(EC_Misc_Asm,
04220 "Local register allocation unsuccessful due to large ASM clobber set");
04221 }
04222 #endif
04223 FmtAssert (Trip_Count <= MAX_TRIP_COUNT,
04224 ("LRA: Unable to spill TN:%d (cl:%d) in BB:%d, GRA grant:%d",
04225 TN_number(tn), cl, BB_id(bb),
04226 REGISTER_SET_Size(avail_set[cl])));
04227
04228 if (Do_LRA_Trace(Trace_LRA_Spill)) {
04229 fprintf (TFile,"LRA_SPILL>> Attempt to spill (cl:%d) in BB:%d, GRA grant:%d\n",
04230 cl, BB_id(bb), REGISTER_SET_Size(avail_set[cl]));
04231 }
04232
04233
04234
04235 if (Check_Allow_Reschedule()) {
04236 if (Do_LRA_Trace(Trace_LRA_Spill)) {
04237 fprintf (TFile, "LRA_SPILL>> Out of Registers (BB:%d) trip:%d\nLRA_SPILL>>",
04238 BB_id(bb), Trip_Count);
04239 Print_Live_Range (lr);
04240 }
04241 if (Do_LRA_Trace(Trace_LRA_Spill)) {
04242 fprintf (TFile, "LRA_SPILL>> Reschedule to minimize register usage\n");
04243 }
04244
04245 mINT8 regs_avail[ISA_REGISTER_CLASS_MAX+1];
04246 for (INT i = ISA_REGISTER_CLASS_MIN; i <= ISA_REGISTER_CLASS_MAX; i++) {
04247 regs_avail[i] = REGISTER_SET_Size (avail_set[i]);
04248 }
04249
04250 if (!Sched) {
04251 Sched = CXX_NEW(HB_Schedule(), &MEM_local_pool);
04252 }
04253 Sched->Init(bb,
04254 HBS_BEFORE_LRA | HBS_DEPTH_FIRST | HBS_MINIMIZE_REGS,
04255 INT32_MAX,
04256 NULL,
04257 regs_avail);
04258 Sched->Schedule_BB(bb, NULL);
04259 Reset_BB_scheduled (bb);
04260 #ifdef KEY
04261
04262
04263
04264
04265 if (Sched) {
04266 CXX_DELETE(Sched, &MEM_local_pool);
04267 Sched = NULL;
04268 }
04269 #endif // KEY
04270 return;
04271 }
04272
04273 if (Do_LRA_Trace(Trace_LRA_Spill)) {
04274 fprintf(TFile, "LRA_SPILL>> reschedule failed. Must %s in register class %d ",
04275 allow_reordering?"reorder":"spill",cl);
04276 fprintf(TFile, "in block %d ", BB_id(bb));
04277 fprintf(TFile, "for procedure %s in file %s\n",
04278 ST_name(Get_Current_PU_ST()), Src_File_Name);
04279 }
04280
04281
04282 if (PROC_has_branch_delay_slot())
04283 BB_Move_Delay_Slot_Op (bb);
04284
04285
04286 Setup_Live_Ranges (bb, TRUE, &lra_pool);
04287
04288
04289
04290
04291 lr = LR_For_TN(tn);
04292 failure_point = LR_last_use (lr);
04293 if (failure_point == 0) failure_point = LR_exposed_use(lr);
04294 if (Do_LRA_Trace(Trace_LRA_Spill)) {
04295 fprintf (TFile,"LRA_SPILL>> Out of Registers (BB:%d) trip:%d\nLRA_SPILL>>",
04296 BB_id(bb), Trip_Count);
04297 Print_Live_Range (lr);
04298 }
04299
04300 if (failure_point !=0) {
04301 OP *op = OP_VECTOR_element (Insts_Vector, failure_point);
04302 if (!PROC_has_branch_delay_slot() && OP_xfer(op)) {
04303 if (Do_LRA_Trace(Trace_LRA_Spill)) {
04304 fprintf(TFile,"LRA_SPILL>> can not reload registers after a branch.\n");
04305 Print_BB(bb);
04306 }
04307 FmtAssert(!OP_xfer(op),
04308 ("LRA: Spill at end of block OP:%d in BB:%d\n",
04309 failure_point, BB_id(bb)));
04310 }
04311 }
04312
04313
04314
04315
04316 MEM_POOL op_to_opnum_pool;
04317 if (need_dep_graph) {
04318
04319 MEM_POOL_Initialize (&op_to_opnum_pool, "LRA_op_to_opnum", FALSE);
04320 MEM_POOL_Push (&op_to_opnum_pool);
04321 op_to_opnum = BB_OP_MAP32_Create (bb, &op_to_opnum_pool);
04322 for (opnum = 1; opnum <= BB_length(bb); opnum++) {
04323 OP *op = OP_VECTOR_element (Insts_Vector, opnum);
04324 BB_OP_MAP32_Set (op_to_opnum, op, opnum);
04325
04326 Reset_OP_flag1 (op);
04327 }
04328 CG_DEP_Compute_Graph (
04329 bb,
04330 INCLUDE_ASSIGNED_REG_DEPS,
04331 NON_CYCLIC,
04332 NO_MEMREAD_ARCS,
04333 INCLUDE_MEMIN_ARCS,
04334 NO_CONTROL_ARCS,
04335 NULL);
04336
04337
04338
04339
04340 if (!allow_reordering) Mark_Reloadable_Live_Ranges (cl);
04341 }
04342 #ifdef TARG_X8664
04343 else {
04344
04345
04346
04347 Quick_Mark_Reloadable_Live_Ranges (cl);
04348 }
04349 #endif
04350
04351
04352 Init_Live_LRs_Vector (bb, failure_point, cl, &lra_pool);
04353
04354 if (Always_Trace(Trace_LRA) && trace_tn && trace_bb == BB_id(bb)) {
04355 Print_Live_Across();
04356 }
04357
04358 INT fatpoint = fat_points[failure_point];
04359 SPILL_CANDIDATE *transformations = NULL;
04360 INT first_fatpoint = 1;
04361
04362 if (Get_Trace (TP_ALLOC, 0x20, bb)) {
04363 fprintf (TFile, "Fat Points (BB:%d)\n", BB_id(bb));
04364 for (opnum = 1; opnum <= failure_point; opnum++) {
04365 OP *op = OP_VECTOR_element(Insts_Vector, opnum);
04366 fprintf(TFile, "OP:%d [fp=%d]>> ", opnum, fat_points[opnum]);
04367 Print_OP_No_SrcLine(op);
04368 }
04369 }
04370
04371 #ifdef KEY
04372
04373
04374 if (fatpoint < 0) {
04375 OP *op = OP_VECTOR_element(Insts_Vector, failure_point);
04376 FmtAssert(OP_code(op) == TOP_asm && OP_results(op) > 1,
04377 ("Fix_LRA_Blues: negative fatpoint at non-asm OP"));
04378 fatpoint = 0;
04379 }
04380 #endif
04381
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394 FmtAssert(fatpoint >= 0,
04395 ("LRA: Spill at negative fatpoint at OP:%d in BB:%d\n",
04396 failure_point, BB_id(bb)));
04397 if (fatpoint == 0) {
04398 DevWarn("Fat point is zero at OP:%d in BB:%d\n", failure_point,
04399 BB_id(bb));
04400 fatpoint = 1;
04401 fat_points[failure_point] = 1;
04402 }
04403
04404
04405
04406
04407 fatpoint_min = 0;
04408 for (opnum = failure_point; opnum > 0; ) {
04409 FAT_POINTS_TYPE cur_usage = fat_points[opnum];
04410 BOOL reordering_failure = false;
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420 while (fat_points[first_fatpoint] <= fatpoint_min) {
04421 first_fatpoint++;
04422 if (opnum < first_fatpoint) break;
04423 }
04424
04425 if (opnum < first_fatpoint) break;
04426
04427
04428 if (fat_points[opnum] > fatpoint_min) {
04429
04430 SPILL_CANDIDATE *best = TYPE_ALLOCA(SPILL_CANDIDATE);
04431 best->spill_kind = SPILL_NONE;
04432 best->spill_num = opnum;
04433
04434 if (Do_LRA_Trace(Trace_LRA_Spill)) {
04435 fprintf (TFile,
04436 "Analyze >> analyze spilling for OP:%d in BB:%d (fp=%d)\n",
04437 opnum, BB_id(bb), fat_points[opnum]);
04438 }
04439 if (!allow_reordering && !CG_localize_tns) {
04440 if (!livethrough_computed) {
04441
04442 Compute_Livethrough_Set (bb);
04443 livethrough_computed = TRUE;
04444 }
04445 Analyze_Spilling_Global_Register (cl, best, opnum, fatpoint);
04446 }
04447
04448
04449 for (INT i = 0; i < VECTOR_count(Live_LRs_Vector); i++) {
04450 LIVE_RANGE *clr = LR_VECTOR_element (Live_LRs_Vector, i);
04451 if (allow_reordering) {
04452 Analyze_Reordering (clr, best, opnum);
04453 }
04454 else {
04455 Analyze_Spilling_Live_Range (clr, opnum, best, fatpoint);
04456 }
04457 }
04458
04459 if (best->spill_kind == SPILL_MOVE_DEF ||
04460 best->spill_kind == SPILL_MOVE_USE)
04461 {
04462
04463
04464
04465
04466 Update_Fat_Points (best, opnum);
04467 best->next = transformations;
04468 transformations = best;
04469 }
04470 else if (best->spill_kind == SPILL_GLOBAL_REG) {
04471 Spill_Global_Register (bb, best);
04472
04473
04474
04475
04476 fatpoint_min++;
04477 cur_usage++;
04478 livethrough[cl] = REGISTER_SET_Difference1 (
04479 livethrough[cl], best->u1.s1.global_spill_reg);
04480 }
04481 else if (best->spill_kind == SPILL_LIVE_RANGE) {
04482 Spill_Live_Range (bb, best->u1.spill_lr, fatpoint, opnum);
04483 Update_Fat_Points (best, opnum);
04484 } else if (allow_reordering) {
04485
04486
04487
04488 reordering_failure = true;
04489 }
04490
04491
04492
04493
04494 if (Trip_Count == MAX_TRIP_COUNT) break;
04495 }
04496
04497
04498 if (cur_usage <= fat_points[opnum]) {
04499
04500
04501
04502
04503 if (!reordering_failure && Do_LRA_Trace(Trace_LRA_Spill)) {
04504 fprintf (TFile, "LRA: no progress when spilling at OP:%d in BB:%d\n",
04505 opnum, BB_id(bb));
04506 }
04507 Update_Live_LRs_Vector (opnum, cl);
04508 opnum--;
04509 }
04510
04511
04512
04513
04514
04515
04516 while (opnum > 0 && fat_points[opnum] <= fatpoint_min) {
04517 Update_Live_LRs_Vector (opnum, cl);
04518 opnum--;
04519 }
04520 }
04521
04522 if (allow_reordering) {
04523
04524 Apply_Move_Transformations (bb, transformations);
04525 }
04526 if (need_dep_graph) {
04527 MEM_POOL_Pop (&op_to_opnum_pool);
04528 MEM_POOL_Delete (&op_to_opnum_pool);
04529 CG_DEP_Delete_Graph (bb);
04530 }
04531
04532
04533 Reset_BB_scheduled (bb);
04534
04535 Clear_Fat_Point_Calculation();
04536 }
04537
04538
04539 #ifdef TARG_X8664
04540 static void Preallocate_Single_Register_Subclasses (BB* bb);
04541 static void Verify_TARG_X86_Op_For_BB( BB* );
04542 static void Adjust_X86_Style_For_BB( BB*, BOOL*, MEM_POOL* );
04543 static void Adjust_eight_bit_regs (BB*);
04544 static void Presplit_x87_MMX_Live_Ranges (BB*, MEM_POOL*);
04545 #endif
04546 #ifdef KEY
04547 static void Detect_large_asm_clobber (BB*);
04548 #endif
04549
04550
04551
04552
04553
04554
04555 void Alloc_Regs_For_BB (BB *bb, HB_Schedule *Sched)
04556 {
04557 BOOL lra_done;
04558 TN *tn;
04559 BOOL redundant_code = FALSE;
04560
04561 MEM_POOL_Initialize (&lra_pool, "LRA_pool", FALSE);
04562 CGSPILL_Reset_Local_Spills ();
04563 Init_Avail_Set (bb);
04564 #ifdef TARG_IA64
04565 Init_Nat_Regs(bb);
04566 #endif
04567 local_spills = 0;
04568 livethrough_computed = FALSE;
04569 Trip_Count = 0;
04570 Magic_Spill_Location = Local_Spill_Sym;
04571
04572 #ifdef KEY
04573
04574 Detect_large_asm_clobber(bb);
04575 #endif
04576 #ifdef TARG_X8664
04577
04578 Presplit_x87_MMX_Live_Ranges(bb, &lra_pool);
04579 Trip_Count = 0;
04580 Adjust_eight_bit_regs(bb);
04581
04582
04583
04584
04585
04586 Adjust_X86_Style_For_BB( bb, &redundant_code, &lra_pool );
04587 Preallocate_Single_Register_Subclasses(bb);
04588 #endif
04589
04590 do {
04591 MEM_POOL_Push (&lra_pool);
04592 Trip_Count++;
04593
04594 #ifdef TARG_X8664
04595 ISA_REGISTER_CLASS cl;
04596 FOR_ALL_ISA_REGISTER_CLASS(cl){
04597 last_assigned_reg[cl] = REGISTER_UNDEFINED;
04598 }
04599 #endif
04600
04601 Init_Avail_Regs ();
04602 Setup_Live_Ranges (bb, TRUE, &lra_pool);
04603
04604 if (Always_Trace(Trace_LRA)) {
04605 if (trace_tn) {
04606 bb_live = TN_SET_Create_Empty(Last_TN + 1, &lra_pool);
04607 TN *tn;
04608 for (tn = GTN_SET_Choose(BB_live_out(bb));
04609 tn != GTN_SET_CHOOSE_FAILURE;
04610 tn = GTN_SET_Choose_Next(BB_live_out(bb), tn)) {
04611 if (LRA_TN_register(tn) != REGISTER_UNDEFINED &&
04612 TN_register_class(tn) == trace_cl) {
04613 bb_live = TN_SET_Union1D(bb_live, tn, &lra_pool);
04614 }
04615 }
04616 }
04617 Print_BB_For_LRA (bb);
04618 if (Do_LRA_Trace(Trace_LRA_Detail)) {
04619 Print_Live_Ranges (bb);
04620 }
04621 }
04622
04623 lra_done = Assign_Registers (bb, &tn, &redundant_code);
04624 if (!lra_done) {
04625 Fix_LRA_Blues (bb, tn, Sched);
04626 }
04627 MEM_POOL_Pop (&lra_pool);
04628 } while (!lra_done);
04629
04630
04631 #ifdef TARG_X8664
04632 if( BB_length(bb) > 0 ){
04633 #if Is_True_On
04634 Verify_TARG_X86_Op_For_BB( bb );
04635 #endif // Is_True_On
04636
04637 } else {
04638 redundant_code = FALSE;
04639 }
04640 #endif // TARG_X8664
04641
04642 if (redundant_code) Remove_Redundant_Code (bb);
04643
04644 MEM_POOL_Delete (&lra_pool);
04645 Set_BB_reg_alloc (bb);
04646
04647 if (Always_Trace(Trace_LRA)) {
04648 if (Trip_Count > 1) {
04649
04650 fprintf(TFile,"%d iterations and %d spills required to allocate regs for BB:%d\n",
04651 Trip_Count,local_spills,BB_id(bb));
04652 }
04653 }
04654
04655 }
04656
04657
04658
04659
04660
04661
04662
04663 void
04664 Assign_Temp_Regs (OPS *ops, BB *bb)
04665 {
04666 REGISTER_SET temps[ISA_REGISTER_CLASS_MAX+1];
04667 OP *op;
04668 OP *sp_adj;
04669
04670 if (BB_entry(bb)) {
04671 sp_adj = BB_entry_sp_adj_op(bb);
04672 REG_LIVE_Prolog_Temps (bb, sp_adj, sp_adj, temps);
04673 }
04674 else if (BB_exit(bb)) {
04675 sp_adj = BB_exit_sp_adj_op(bb);
04676 REG_LIVE_Epilog_Temps (Get_Current_PU_ST(), bb, sp_adj, temps);
04677 }
04678 else {
04679 FmtAssert(FALSE, ("unexpected bb"));
04680 }
04681 FOR_ALL_OPS_OPs (ops, op) {
04682 REGISTER_CLASS_OP_Update_Mapping(op);
04683 for (INT i = 0; i < OP_results(op); i++) {
04684 TN *result_tn = OP_result(op, i);
04685 if (LRA_TN_register(result_tn) == REGISTER_UNDEFINED) {
04686 ISA_REGISTER_CLASS cl = TN_register_class(result_tn);
04687 REGISTER reg = REGISTER_SET_Choose (temps[cl]);
04688 FmtAssert (reg != REGISTER_UNDEFINED, ("no temp regs available"));
04689 LRA_TN_Allocate_Register (result_tn, reg);
04690 temps[cl] = REGISTER_SET_Difference1 (temps[cl], reg);
04691 }
04692 }
04693 }
04694 }
04695
04696
04697
04698
04699
04700 static void
04701 Prolog_save_code(BB *entrybb)
04702 {
04703 INT callee_num;
04704
04705 for (callee_num = 0; callee_num < Callee_Saved_Regs_Count; callee_num++) {
04706 TN *tn = CALLEE_tn(callee_num);
04707 ISA_REGISTER_CLASS cl = TN_save_rclass(tn);
04708 REGISTER reg = TN_save_reg(tn);
04709 if (REGISTER_SET_MemberP(Callee_Saved_Regs_Used[cl], reg)) {
04710 ST *mem_loc = CGSPILL_Get_TN_Spill_Location (tn, CGSPILL_LCL);
04711 OPS ops = OPS_EMPTY;
04712 LRA_TN_Allocate_Register (tn, reg);
04713
04714 CGSPILL_Store_To_Memory (tn, mem_loc, &ops, CGSPILL_LRA, entrybb);
04715
04716
04717 Assign_Temp_Regs (&ops, entrybb);
04718
04719
04720 CGSPILL_Prepend_Ops (entrybb, &ops);
04721
04722 if ( Do_LRA_Trace(Trace_LRA_Entry_Exit) )
04723 fprintf ( TFile,
04724 "entry BB:%d saved TN%d saved from reg %d:%d\n",
04725 BB_id(entrybb), TN_number(tn), cl, reg );
04726 }
04727 }
04728 }
04729
04730
04731
04732
04733 static void
04734 Epilog_restore_code(BB *exitbb)
04735 {
04736
04737 INT callee_num;
04738
04739 for (callee_num = 0; callee_num < Callee_Saved_Regs_Count; callee_num++) {
04740 TN *tn = CALLEE_tn(callee_num);
04741 ISA_REGISTER_CLASS cl = TN_save_rclass(tn);
04742 REGISTER reg = TN_save_reg(tn);
04743 if (REGISTER_SET_MemberP(Callee_Saved_Regs_Used[cl], reg)) {
04744 ST *mem_loc = CGSPILL_Get_TN_Spill_Location (tn, CGSPILL_LCL);
04745 OPS ops = OPS_EMPTY;
04746
04747 CGSPILL_Load_From_Memory (tn, mem_loc, &ops, CGSPILL_LRA, exitbb);
04748
04749
04750 Assign_Temp_Regs (&ops, exitbb);
04751
04752
04753 CGSPILL_Append_Ops (exitbb, &ops);
04754
04755 if (Do_LRA_Trace(Trace_LRA_Entry_Exit))
04756 fprintf ( TFile,
04757 "exit BB:%d saved TN%d restored to reg %d:%d\n",
04758 BB_id(exitbb), TN_number(tn), cl, reg );
04759 }
04760 }
04761 }
04762
04763
04764
04765
04766
04767 static void
04768 Spill_Callee_Saved_Regs (void)
04769 {
04770 ISA_REGISTER_CLASS cl;
04771 BB_LIST *elist;
04772
04773 if (Do_LRA_Trace(Trace_LRA_Entry_Exit)) {
04774 fprintf(TFile, "Callee_Saved_Regs_Used:\n");
04775 FOR_ALL_ISA_REGISTER_CLASS(cl) {
04776 fprintf(TFile, " class %d: ", cl);
04777 REGISTER_SET_Print(Callee_Saved_Regs_Used[cl], TFile);
04778 fprintf(TFile, "\n");
04779 }
04780 }
04781
04782 for ( elist = Entry_BB_Head; elist; elist = BB_LIST_rest(elist) ) {
04783 Prolog_save_code (BB_LIST_first(elist));
04784 }
04785
04786 for ( elist = Exit_BB_Head; elist; elist = BB_LIST_rest(elist) ) {
04787 Epilog_restore_code (BB_LIST_first(elist));
04788 }
04789
04790
04791 FOR_ALL_ISA_REGISTER_CLASS(cl)
04792 Callee_Saved_Regs_Used[cl] = REGISTER_SET_EMPTY_SET;
04793 }
04794
04795
04796
04797
04798
04799 static void Consistency_Check (void)
04800 {
04801 BB *bb;
04802 TN_MAP Local_TNs;
04803
04804 Local_TNs = TN_MAP_Create ();
04805 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
04806 OP *op;
04807 INT i;
04808 FOR_ALL_BB_OPs_FWD (bb, op) {
04809
04810 for (i = 0; i < OP_results(op); i++) {
04811 TN *tn = OP_result(op, i);
04812 if (TN_is_local_reg(tn)) {
04813 BB *tn_bb = (BB *)TN_MAP_Get (Local_TNs, tn);
04814 if (tn_bb != NULL) {
04815 if (tn_bb != bb &&
04816 (!BB_reg_alloc(bb) || !BB_reg_alloc(tn_bb)))
04817 #ifdef KEY
04818 if (! TN_is_save_reg(tn))
04819 #endif
04820 FmtAssert (FALSE,
04821 ("Local TN%d referenced in BB:%d and BB:%d",
04822 TN_number(tn), BB_id(tn_bb), BB_id(bb)));
04823 }
04824 else {
04825 TN_MAP_Set (Local_TNs, tn, bb);
04826 }
04827 }
04828 else {
04829 FmtAssert (LRA_TN_register(tn) != REGISTER_UNDEFINED,
04830 ("Global TN%d not assigned a register", TN_number(tn)));
04831 }
04832 }
04833
04834 for (i = 0; i < OP_opnds(op); i++) {
04835 TN *tn = OP_opnd(op,i);
04836 if (TN_is_register(tn)) {
04837 if (TN_is_local_reg(tn)) {
04838 BB *tn_bb = (BB *)TN_MAP_Get (Local_TNs, tn);
04839 if (tn_bb != NULL) {
04840 if (tn_bb != bb &&
04841 (!BB_reg_alloc(bb) || !BB_reg_alloc(tn_bb)))
04842 #ifdef KEY
04843 if (! TN_is_save_reg(tn))
04844 #endif
04845 FmtAssert (FALSE,
04846 ("Local TN%d referenced in BB:%d and BB%d",
04847 TN_number(tn), BB_id(tn_bb), BB_id(bb)));
04848 }
04849 else {
04850 TN_MAP_Set (Local_TNs, tn, bb);
04851 }
04852 }
04853 else {
04854 FmtAssert (LRA_TN_register(tn) != REGISTER_UNDEFINED,
04855 ("Global TN%d not assigned by GRA", TN_number(tn)));
04856 }
04857 }
04858 }
04859
04860 }
04861 }
04862 TN_MAP_Delete (Local_TNs);
04863 }
04864
04865
04866
04867
04868 static void
04869 Move_Spill_Loads_Stores (BB *bb)
04870 {
04871
04872 OP *op;
04873 OP *prev_op = NULL;
04874 OP *next_op = NULL;
04875
04876
04877
04878
04879 if (PROC_has_branch_delay_slot())
04880 BB_Move_Delay_Slot_Op (bb);
04881
04882
04883
04884
04885
04886 TN_MAP spills_map = TN_MAP_Create ();
04887 for (op = BB_first_op(bb); op != NULL; op = next_op) {
04888 next_op = OP_next(op);
04889 if (OP_has_result(op)) {
04890 for (INT i = 0; i < OP_results(op); i++) {
04891 TN *result_tn = OP_result(op, i);
04892 TN_MAP_Set (spills_map, result_tn, op);
04893 }
04894 }
04895 else if (OP_store(op)) {
04896 TN *src_tn = OP_opnd(op,TOP_Find_Operand_Use(OP_code(op), OU_storeval));
04897 ST *spill_loc = TN_spill(src_tn);
04898 if (Is_OP_Spill_Store (op, spill_loc)) {
04899 OP *def_op = (OP *)TN_MAP_Get (spills_map, src_tn);
04900 if (def_op != OP_prev(op)) {
04901 OPS ops = OPS_EMPTY;
04902 BB_Remove_Op (bb, op);
04903 if (Do_LRA_Trace(Trace_Move_GRA_Spills)) {
04904 fprintf (TFile, ">> MOVE Delete");
04905 Print_OP_No_SrcLine (op);
04906 }
04907 CGSPILL_Store_To_Memory (src_tn, spill_loc, &ops, CGSPILL_LRA, bb);
04908 if (def_op != NULL) {
04909 CGSPILL_Insert_Ops_After (bb, def_op, &ops);
04910 if (Do_LRA_Trace(Trace_Move_GRA_Spills)) {
04911 fprintf (TFile, ">> MOVE Append");
04912 Print_OP_No_SrcLine (OPS_first(&ops));
04913 fprintf (TFile, ">> MOVE After ");
04914 Print_OP_No_SrcLine (def_op);
04915 }
04916 }
04917 else {
04918 CGSPILL_Prepend_Ops (bb, &ops);
04919 if (Do_LRA_Trace(Trace_Move_GRA_Spills)) {
04920 fprintf (TFile, ">> MOVE_SPILL Prepend");
04921 Print_OP_No_SrcLine (OPS_first(&ops));
04922 }
04923 }
04924 }
04925 }
04926 }
04927 }
04928 TN_MAP_Delete (spills_map);
04929
04930
04931
04932
04933
04934 spills_map = TN_MAP_Create ();
04935 for (op = BB_last_op(bb); op != NULL; op = prev_op) {
04936 prev_op = OP_prev(op);
04937 INT i;
04938 for (i = 0; i < OP_opnds(op); i++) {
04939 TN *tn = OP_opnd(op,i);
04940 if (TN_is_register(tn)) {
04941 TN_MAP_Set (spills_map, tn, op);
04942 }
04943 }
04944 for (i = 0; i < OP_results(op); i++) {
04945 TN *result_tn = OP_result(op, i);
04946 ST *spill_loc = TN_spill(result_tn);
04947 if (Is_OP_Spill_Load (op, spill_loc)) {
04948 OP *use_op = (OP *)TN_MAP_Get (spills_map, result_tn);
04949 if (use_op != OP_next(op)) {
04950 OPS ops = OPS_EMPTY;
04951 BB_Remove_Op (bb, op);
04952 CGSPILL_Load_From_Memory (result_tn, spill_loc, &ops, CGSPILL_LRA,
04953 bb);
04954 if (use_op != NULL) {
04955 CGSPILL_Insert_Ops_Before (bb, use_op, &ops);
04956 }
04957 else {
04958 CGSPILL_Append_Ops (bb, &ops);
04959 }
04960 }
04961 }
04962
04963
04964
04965
04966
04967 TN_MAP_Set (spills_map, result_tn, op);
04968 }
04969 }
04970 TN_MAP_Delete (spills_map);
04971
04972 if (Do_LRA_Trace(Trace_Move_GRA_Spills)) {
04973 Print_BB (bb);
04974 }
04975 }
04976
04977
04978 #ifdef TARG_X8664
04979
04980
04981
04982
04983 static void
04984 Adjust_one_eight_bit_reg( BB* bb, OP* op, int opnd_idx, BOOL is_opnd )
04985 {
04986 TN* opnd = is_opnd ? OP_opnd( op, opnd_idx ) : OP_result( op, opnd_idx );
04987
04988 if (!TN_is_register(opnd))
04989 return;
04990
04991 if (OP_code(op) == TOP_asm) {
04992 ASM_OP_ANNOT* asm_info = (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, op);
04993 ISA_REGISTER_SUBCLASS subclass =
04994 is_opnd ? ASM_OP_opnd_subclass(asm_info)[opnd_idx] :
04995 ASM_OP_result_subclass(asm_info)[opnd_idx];
04996 if (subclass == ISA_REGISTER_SUBCLASS_m32_8bit_regs) {
04997
04998 } else if (Is_Target_64bit() ||
04999 TN_size(opnd) != 1) {
05000 return;
05001 }
05002 } else {
05003 if (Is_Target_64bit())
05004 return;
05005 if (is_opnd) {
05006 if (OP_opnd_size(op, opnd_idx) != 8)
05007 return;
05008 } else {
05009 if (OP_result_size(op, opnd_idx) != 8)
05010 return;
05011 }
05012 }
05013
05014 const ISA_REGISTER_CLASS cl = TN_register_class( opnd );
05015 const REGISTER reg = LRA_TN_register( opnd );
05016
05017 if( reg != REGISTER_UNDEFINED ){
05018 const REGISTER_SET regs =
05019 REGISTER_SUBCLASS_members(ISA_REGISTER_SUBCLASS_m32_8bit_regs);
05020 if( REGISTER_SET_MemberP( regs, reg ) )
05021 return;
05022
05023 } else {
05024 if( TN_size(opnd) == 1 )
05025 return;
05026 }
05027
05028
05029
05030 OPS ops = OPS_EMPTY;
05031
05032
05033
05034 TN* result = Gen_Register_TN(cl, TN_size(opnd));
05035
05036 if( is_opnd ){
05037 Exp_COPY( result, opnd, &ops );
05038 OP_srcpos(OPS_last(&ops)) = OP_srcpos(op);
05039 BB_Insert_Ops_Before( bb, op, &ops );
05040 Set_OP_opnd( op, opnd_idx, result );
05041
05042 } else {
05043
05044
05045 Exp_COPY_Ext(TN_size(result) == 2 ? TOP_movzwl : TOP_movzbl,
05046 opnd, result, &ops );
05047 OP_srcpos(OPS_last(&ops)) = OP_srcpos(op);
05048 BB_Insert_Ops_After( bb, op, &ops );
05049 Set_OP_result( op, opnd_idx, result );
05050
05051
05052
05053 Set_OP_cond_def_kind(op, OP_ALWAYS_UNC_DEF);
05054 }
05055 }
05056
05057
05058 static void
05059 Adjust_eight_bit_regs (BB* bb)
05060 {
05061 OP* op = NULL;
05062
05063
05064
05065
05066
05067 FOR_ALL_BB_OPs( bb, op ){
05068 for( int i = 0; i < OP_opnds( op ); i++ ){
05069 Adjust_one_eight_bit_reg( bb, op, i, TRUE );
05070 }
05071
05072 for( int i = 0; i < OP_results( op ); i++ ){
05073 Adjust_one_eight_bit_reg( bb, op, i, FALSE );
05074 }
05075 }
05076 }
05077
05078
05079
05080
05081 static void
05082 Adjust_X86_Style_For_BB (BB* bb, BOOL* redundant_code, MEM_POOL* pool)
05083 {
05084 OP *op = NULL;
05085
05086 Setup_Live_Ranges( bb, TRUE, pool );
05087
05088 int opnum = 0;
05089
05090 FOR_ALL_BB_OPs( bb, op ){
05091 opnum++;
05092
05093 if( !OP_x86_style( op ) )
05094 continue;
05095
05096 TN* result = OP_result( op, 0 );
05097 TN* opnd0 = OP_opnd( op, 0 );
05098 TN* opnd1 = OP_opnd( op, 1 );
05099
05100 if( TNs_Are_Equivalent( result, opnd0 ) )
05101 continue;
05102
05103 if( ( opnd0 != opnd1 ) &&
05104 TOP_is_commutative( OP_code(op) ) ){
05105 const LIVE_RANGE* opnd1_lr = LR_For_TN( opnd1 );
05106
05107 if( TNs_Are_Equivalent( result, opnd1 ) ||
05108 LR_last_use(opnd1_lr) == opnum ){
05109 Set_OP_opnd( op, 0, opnd1 );
05110 Set_OP_opnd( op, 1, opnd0 );
05111 opnd0 = opnd1;
05112
05113 if( TNs_Are_Equivalent( result, opnd0 ) )
05114 continue;
05115 }
05116 }
05117
05118
05119
05120
05121
05122
05123
05124
05125
05126
05127
05128
05129
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143 if( Do_LRA_Trace(Trace_LRA_Detail) ){
05144 fprintf( TFile, "Convert op to x86-style: " );
05145 Print_OP_No_SrcLine( op );
05146 }
05147
05148 TN* tmp_opnd0;
05149 BOOL add_copy_after = FALSE;
05150 if (TN_register_class(result) == ISA_REGISTER_CLASS_float &&
05151 TN_register_class(opnd0) == ISA_REGISTER_CLASS_float &&
05152 TN_size(result) < TN_size(opnd0)) {
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180
05181
05182 tmp_opnd0 = Build_TN_Like(opnd0);
05183 Set_OP_result(op, 0, tmp_opnd0);
05184 add_copy_after = TRUE;
05185 } else {
05186 tmp_opnd0 = result;
05187 }
05188
05189 OPS ops = OPS_EMPTY;
05190
05191 for( int opnd = 1; opnd < OP_opnds(op); opnd++ ){
05192 TN* opnd1 = OP_opnd( op , opnd );
05193
05194 if( TN_is_register( opnd1 ) &&
05195 TNs_Are_Equivalent( opnd1, result ) ){
05196 TN* tmp_opnd1 = Build_TN_Like( opnd1 );
05197 Exp_COPY( tmp_opnd1, opnd1, &ops );
05198 OP_srcpos(OPS_last(&ops)) = OP_srcpos(op);
05199 Set_OP_opnd( op, opnd, tmp_opnd1 );
05200 }
05201 }
05202
05203 Exp_COPY( tmp_opnd0, opnd0, &ops );
05204 OP_srcpos(OPS_last(&ops)) = OP_srcpos(op);
05205 BB_Insert_Ops_Before( bb, op, &ops );
05206 *redundant_code = TRUE;
05207
05208 if (add_copy_after) {
05209 OPS ops = OPS_EMPTY;
05210 Exp_COPY(result, tmp_opnd0, &ops);
05211 OP_srcpos(OPS_last(&ops)) = OP_srcpos(op);
05212 BB_Insert_Ops_After(bb, op, &ops);
05213 }
05214
05215 for( int opnd = 1; opnd < OP_opnds(op); opnd++ ){
05216 if( OP_opnd( op , opnd ) == OP_opnd( op, 0 ) )
05217 Set_OP_opnd( op, opnd, tmp_opnd0 );
05218 }
05219
05220 Set_OP_opnd( op, 0, tmp_opnd0 );
05221 }
05222 }
05223
05224
05225 static void Verify_TARG_X86_Op_For_BB( BB* bb )
05226 {
05227 OP* op = NULL;
05228
05229 FOR_ALL_BB_OPs( bb, op ){
05230 const TOP top = OP_code( op );
05231
05232 if( top == TOP_asm )
05233 continue;
05234
05235
05236 if( Is_Target_32bit() ){
05237 for( int i = 0; i < OP_opnds( op ); i++ ){
05238 TN* opnd = OP_opnd( op, i );
05239 if( TN_is_register( opnd ) &&
05240 OP_opnd_size( op, i ) == 8 ){
05241 const ISA_REGISTER_CLASS cl = TN_register_class( opnd );
05242 const REGISTER reg = LRA_TN_register( opnd );
05243 const REGISTER_SET regs =
05244 REGISTER_SUBCLASS_members(ISA_REGISTER_SUBCLASS_m32_8bit_regs);
05245 FmtAssert(cl == ISA_REGISTER_CLASS_integer,
05246 ("Verify_TARG_X86_Op_For_BB: 8-bit value not allocated to integer register"));
05247 FmtAssert(REGISTER_SET_MemberP(regs, reg),
05248 ("Verify_TARG_X86_Op_For_BB: 8-bit value not allocated to byte-accessible register"));
05249 }
05250 }
05251 }
05252
05253
05254 if( top == TOP_leax32 || top == TOP_leax64 ){
05255 int index = TOP_Find_Operand_Use( top, OU_index );
05256 REGISTER reg = LRA_TN_register( OP_opnd(op,index) );
05257 FmtAssert( reg != RSP, ("%rsp can not serve as index register in lea") );
05258 }
05259
05260 if( OP_x86_style( op ) ){
05261 TN* result = OP_result( op, 0 );
05262 TN* opnd0 = OP_opnd( op, 0 );
05263
05264 FmtAssert( TN_register_class(result) == TN_register_class(opnd0),
05265 ("Result and opnd0 have different register class.") );
05266 FmtAssert( LRA_TN_register(result) != REGISTER_UNDEFINED,
05267 ("Result has no register.") );
05268 FmtAssert( TNs_Are_Equivalent( result, opnd0 ),
05269 ("The first opnd and result use different registers.") );
05270 }
05271 }
05272 }
05273
05274
05275 static BOOL
05276 Spillpoint_For_x87_MMX (TN *tn, OP *op)
05277 {
05278 ISA_REGISTER_CLASS cl = TN_register_class(tn);
05279
05280 if ((cl == ISA_REGISTER_CLASS_x87 && OP_mmx(op)) ||
05281 (cl == ISA_REGISTER_CLASS_mmx && OP_x87(op)))
05282 return TRUE;
05283 return FALSE;
05284 }
05285
05286
05287
05288
05289
05290
05291 static void
05292 Presplit_x87_MMX_Live_Ranges(BB *bb, MEM_POOL *pool)
05293 {
05294 int opnum;
05295 LIVE_RANGE *lr;
05296
05297 Setup_Live_Ranges(bb, TRUE, pool);
05298 for (lr = Live_Range_List; lr != NULL; lr = LR_next(lr)) {
05299 TN *tn = LR_tn(lr);
05300 ISA_REGISTER_CLASS cl = TN_register_class(tn);
05301 if (cl == ISA_REGISTER_CLASS_x87 ||
05302 cl == ISA_REGISTER_CLASS_mmx) {
05303 for (opnum = LR_last_use(lr) - 1; opnum > LR_first_def(lr); opnum--) {
05304 OP *op = OP_VECTOR_element(Insts_Vector, opnum);
05305 if (op != NULL &&
05306 Spillpoint_For_x87_MMX(tn, op)) {
05307
05308 Spill_Live_Range(bb, lr, -1 , opnum,
05309 Spillpoint_For_x87_MMX);
05310 break;
05311 }
05312 }
05313 }
05314 }
05315 }
05316
05317 #endif
05318
05319 #include <list>
05320 using namespace std;
05321 struct GTN_OP_INFO{
05322 GTN_OP_INFO():gtn(NULL),has_use(false),has_def(false){}
05323 GTN_OP_INFO(TN * t,bool u=false,bool d=false):gtn(t),has_use(u),has_def(d){}
05324 TN * gtn;
05325 bool has_use;
05326 bool has_def;
05327 list<OP *> op_list;
05328 };
05329
05330 #ifdef KEY
05331
05332
05333 static void
05334 Detect_large_asm_clobber (BB *bb)
05335 {
05336 ISA_REGISTER_CLASS cl;
05337 FOR_ALL_ISA_REGISTER_CLASS(cl) {
05338 large_asm_clobber_set[cl] = FALSE;
05339 }
05340
05341 if (BB_asm(bb)) {
05342 ASM_OP_ANNOT* asm_info =
05343 (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, BB_last_op(bb));
05344
05345
05346 if (asm_info) {
05347 FOR_ALL_ISA_REGISTER_CLASS(cl) {
05348 int total = REGISTER_SET_Size(avail_set[cl]);
05349 int clobbered = REGISTER_SET_Size(ASM_OP_clobber_set(asm_info)[cl]);
05350 if (clobbered > 3 &&
05351 total - clobbered < 2) {
05352 large_asm_clobber_set[cl] = TRUE;
05353 }
05354 }
05355 }
05356 }
05357 }
05358 #endif // KEY
05359
05360 static void
05361 Preallocate_Single_Register_Subclasses (BB* bb)
05362 {
05363 OP* op;
05364 #ifdef TARG_X8664
05365
05366
05367 OP *last_preallocation_op = NULL;
05368 FOR_ALL_BB_OPs_REV (bb, op) {
05369
05370
05371
05372 if ((BB_exit(bb) &&
05373 OP_code(op) == TOP_spadjust) ||
05374 OP_code(op) == TOP_asm) {
05375 continue;
05376 }
05377 if (TOP_is_change_rflags(OP_code(op))) {
05378 last_preallocation_op = op;
05379 break;
05380 }
05381 }
05382 #endif
05383 #ifndef KEY
05384 FOR_ALL_BB_OPs (bb, op) {
05385 #else
05386 INT opnum;
05387 INT orig_bb_length = BB_length(bb);
05388 Setup_Live_Ranges(bb, TRUE, &lra_pool);
05389 for (opnum = 1; opnum <= orig_bb_length; opnum++) {
05390 op = OP_VECTOR_element(Insts_Vector, opnum);
05391 OP *prev_op = OP_prev(op);
05392 OP *next_op = OP_next(op);
05393
05394 #ifdef TARG_X8664
05395
05396
05397
05398 if (op == last_preallocation_op)
05399 last_preallocation_op = NULL;
05400 #endif
05401 #endif
05402
05403 ASM_OP_ANNOT* asm_info = (OP_code(op) == TOP_asm) ?
05404 (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, op) : NULL;
05405
05406 INT i;
05407 for (i = 0; i < OP_opnds(op); i++) {
05408 ISA_REGISTER_SUBCLASS subclass = asm_info ?
05409 ASM_OP_opnd_subclass(asm_info)[i] : OP_opnd_reg_subclass(op, i);
05410 REGISTER reg = Single_Register_Subclass(subclass);
05411 if (reg == REGISTER_UNDEFINED) {
05412 continue;
05413 }
05414 TN* old_tn = OP_opnd(op, i);
05415 #ifdef TARG_X8664
05416 if( TN_is_preallocated( old_tn ) ){
05417 continue;
05418 }
05419 #else
05420 if (LRA_TN_register(old_tn) != REGISTER_UNDEFINED) {
05421 Is_True(LRA_TN_register(old_tn) == reg,
05422 ("LRA: wrong register allocated to TN"));
05423 continue;
05424 }
05425 #endif
05426 TN* new_tn = Build_TN_Like(old_tn);
05427 LRA_TN_Allocate_Register(new_tn, reg);
05428 #ifdef TARG_IA64
05429 INT j;
05430 for (j = 0; j < OP_opnds(op); j++) {
05431 if (OP_opnd(op, j) == old_tn) {
05432 Set_OP_opnd(op, j, new_tn);
05433 }
05434 #else
05435 #ifdef TARG_X8664
05436 Set_TN_is_preallocated (new_tn);
05437 Set_OP_opnd( op, i, new_tn );
05438 #endif
05439 OPS pre_ops = OPS_EMPTY;
05440
05441 for( int j = i+1; j < OP_opnds(op); j++ ){
05442 TN* opnd = OP_opnd( op, j );
05443 if( TN_is_register(opnd) &&
05444 LRA_TN_register(opnd) == reg ){
05445
05446 TN* tmp_tn = Build_TN_Like( opnd );
05447 Exp_COPY( tmp_tn, opnd, &pre_ops );
05448 OP_srcpos(OPS_last(&pre_ops)) = OP_srcpos(op);
05449 Set_OP_opnd( op, j, tmp_tn );
05450 }
05451 #endif
05452 }
05453
05454 BOOL has_def = FALSE;
05455 TN* new_result_tn = NULL;
05456 for( int j = 0; j < OP_results(op); j++ ){
05457 if (OP_result(op, j) == old_tn) {
05458 new_result_tn = Build_TN_Like( OP_result(op,j) );
05459 Set_OP_result(op, j, new_result_tn);
05460 has_def = TRUE;
05461 }
05462 }
05463
05464 #ifdef TARG_IA64
05465 OPS pre_ops = OPS_EMPTY;
05466 #endif
05467 Exp_COPY(new_tn, old_tn, &pre_ops);
05468 OP_srcpos(OPS_last(&pre_ops)) = OP_srcpos(op);
05469
05470 #ifdef TARG_X8664
05471
05472
05473
05474
05475 if( OP_x86_style( op ) &&
05476 new_result_tn != NULL ){
05477 Exp_COPY( new_result_tn, old_tn, &pre_ops );
05478 OP_srcpos(OPS_last(&pre_ops)) = OP_srcpos(op);
05479 Set_OP_opnd( op, 0, new_result_tn );
05480 }
05481 #endif
05482
05483 BB_Insert_Ops_Before(bb, op, &pre_ops);
05484 if (has_def) {
05485 OPS post_ops = OPS_EMPTY;
05486 Exp_COPY(old_tn, new_result_tn, &post_ops);
05487 OP_srcpos(OPS_last(&post_ops)) = OP_srcpos(op);
05488 BB_Insert_Ops_After(bb, op, &post_ops);
05489 }
05490 }
05491
05492
05493 OP* latest_new_op = NULL;
05494
05495 for (i = 0; i < OP_results(op); i++) {
05496 ISA_REGISTER_SUBCLASS subclass = asm_info ?
05497 ASM_OP_result_subclass(asm_info)[i] : OP_result_reg_subclass(op, i);
05498 REGISTER reg = Single_Register_Subclass(subclass);
05499 if (reg == REGISTER_UNDEFINED) {
05500 #ifdef TARG_X8664
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513 TN *tn = OP_result(op, i);
05514 if (last_preallocation_op != NULL &&
05515 TN_is_dedicated(tn) &&
05516 REGISTER_allocatable(TN_register_class(tn), LRA_TN_register(tn))) {
05517 LIVE_RANGE *ded_lr = LR_For_TN(tn);
05518
05519
05520
05521
05522
05523
05524 int non_exposed_use_cnt = LR_use_cnt(ded_lr) - LR_exposed_use(ded_lr);
05525 if (LR_last_use(ded_lr) > orig_bb_length &&
05526 LR_def_cnt(ded_lr) == 1 &&
05527 ((!BB_asm(bb) && non_exposed_use_cnt == 1) ||
05528 ( BB_asm(bb) && non_exposed_use_cnt == 2))) {
05529 TN *new_tn = Build_TN_Like(tn);
05530 Set_OP_result(op, i, new_tn);
05531
05532 OPS ops = OPS_EMPTY;
05533 Exp_COPY(tn, new_tn, &ops);
05534 OP_srcpos(OPS_last(&ops)) = OP_srcpos(op);
05535 BB_Insert_Ops_After(bb, last_preallocation_op, &ops);
05536
05537 for (OP *op1 = OP_next(op);
05538 op1 != OP_next(last_preallocation_op);
05539 op1 = OP_next(op1)) {
05540 for (int opndnum = 0; opndnum < OP_opnds(op1); opndnum++) {
05541 TN *opnd_tn = OP_opnd(op1, opndnum);
05542 if (TN_is_register(opnd_tn) &&
05543 TNs_Are_Equivalent(opnd_tn, tn)) {
05544 Set_OP_opnd(op1, opndnum, new_tn);
05545 }
05546 }
05547 #if Is_True_On
05548
05549
05550 for (int resnum = 0; resnum < OP_results(op1); resnum++) {
05551 TN *result_tn = OP_result(op1, resnum);
05552 FmtAssert(!TNs_Are_Equivalent(result_tn, tn),
05553 ("Preallocate_Single_Register_Subclasses: unexpected defintion of TN"));
05554 }
05555 #endif
05556 }
05557 }
05558 }
05559 #endif // TARG_X8664
05560 continue;
05561 }
05562 TN* old_tn = OP_result(op, i);
05563
05564 #ifdef TARG_X8664
05565 if( TN_is_sp_reg( old_tn ) ){
05566 continue;
05567 }
05568
05569 if( TN_is_preallocated( old_tn ) ){
05570 continue;
05571 }
05572 #endif
05573
05574 #ifndef TARG_X8664
05575 if (LRA_TN_register(old_tn) != REGISTER_UNDEFINED) {
05576 Is_True(LRA_TN_register(old_tn) == reg,
05577 ("LRA: wrong register allocated to TN"));
05578 continue;
05579 }
05580 #endif
05581 TN* new_tn = Build_TN_Like(old_tn);
05582 LRA_TN_Allocate_Register(new_tn, reg);
05583 #ifdef TARG_X8664
05584 Set_TN_is_preallocated (new_tn);
05585 #endif
05586 INT j;
05587 for (j = 0; j < OP_results(op); j++) {
05588 if (OP_result(op, j) == old_tn) {
05589 Set_OP_result(op, j, new_tn);
05590 }
05591 }
05592 BOOL has_use = FALSE;
05593 TN* new_opnd_tn = NULL;
05594 for (j = 0; j < OP_opnds(op); j++) {
05595 if (OP_opnd(op, j) == old_tn) {
05596 new_opnd_tn = Build_TN_Like( OP_opnd(op,j) );
05597 Set_OP_opnd(op, j, new_opnd_tn);
05598 has_use = TRUE;
05599 }
05600 }
05601 OPS post_ops = OPS_EMPTY;
05602 Exp_COPY(old_tn, new_tn, &post_ops);
05603 OP_srcpos(OPS_last(&post_ops)) = OP_srcpos(op);
05604
05605 if( latest_new_op == NULL ||
05606 LRA_TN_register(old_tn) == REGISTER_UNDEFINED ){
05607 BB_Insert_Ops_After(bb, op, &post_ops);
05608 latest_new_op = OPS_last( &post_ops );
05609
05610 } else {
05611
05612
05613
05614 BB_Insert_Ops_After(bb, latest_new_op, &post_ops);
05615 latest_new_op = NULL;
05616 }
05617
05618 if (has_use) {
05619 OPS pre_ops = OPS_EMPTY;
05620 Exp_COPY(new_opnd_tn, old_tn, &pre_ops);
05621 OP_srcpos(OPS_last(&pre_ops)) = OP_srcpos(op);
05622 BB_Insert_Ops_Before(bb, op, &pre_ops);
05623 }
05624 }
05625 }
05626 }
05627
05628
05629
05630
05631
05632
05633 void
05634 LRA_Allocate_Registers (BOOL lra_for_pu)
05635 {
05636 BB *bb;
05637 RID *rid;
05638 ISA_REGISTER_CLASS cl;
05639
05640 Set_Error_Phase ( "Local Register Allocation" );
05641 Start_Timer ( T_LRA_CU );
05642
05643 #if Is_True_On
05644 Consistency_Check ();
05645 #endif
05646
05647
05648 FOR_ALL_ISA_REGISTER_CLASS(cl) unused_tn_def[cl] = NULL;
05649 if (True_TN) unused_tn_def[TN_register_class(True_TN)] = True_TN;
05650 if (Zero_TN) unused_tn_def[TN_register_class(Zero_TN)] = Zero_TN;
05651 if (FZero_TN) unused_tn_def[TN_register_class(FZero_TN)] = FZero_TN;
05652
05653 FOR_ALL_ISA_REGISTER_CLASS(cl) last_assigned_reg[cl] = REGISTER_UNDEFINED;
05654 HB_Schedule *Sched = NULL;
05655 global_spills = 0;
05656
05657 #ifdef TARG_X8664
05658
05659
05660
05661
05662
05663
05664
05665
05666
05667
05668
05669
05670 memset( (void*)float_reg_could_be_128bit, sizeof(float_reg_could_be_128bit), 0 );
05671
05672 if( Is_Target_SSE2() &&
05673 !CG_localize_tns &&
05674 LNO_Run_Simd ){
05675
05676 for( BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb) ){
05677 if( BB_reg_alloc(bb) )
05678 continue;
05679 for( OP* op = BB_first_op(bb); op != NULL; op = OP_next(op) ){
05680 if( !TOP_is_vector_op( OP_code(op) ) )
05681 continue;
05682
05683 for( int i = 0; i < OP_results(op); i++ ){
05684 TN* result = OP_result( op, i );
05685 if( TN_is_global_reg(result ) &&
05686 TN_size(result) == 16 ){
05687 const REGISTER reg = LRA_TN_register(result);
05688 float_reg_could_be_128bit[reg] = true;
05689 }
05690 }
05691
05692 }
05693 }
05694 }
05695 #endif
05696
05697 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb))
05698 {
05699 if ( ( rid = BB_rid(bb) )
05700 && ( RID_level(rid) >= RL_CGSCHED ) )
05701 continue;
05702
05703
05704 if ( BB_reg_alloc(bb) )
05705 continue;
05706
05707 Trace_LRA = Get_Trace (TP_ALLOC, 0x01, bb);
05708 Trace_LRA_Detail = Get_Trace (TP_ALLOC, 0x02, bb);
05709 Trace_LRA_Spill = Get_Trace (TP_ALLOC, 0x04, bb);
05710 Trace_LRA_Entry_Exit = Get_Trace (TP_ALLOC, 0x08, bb);
05711 Trace_Move_GRA_Spills = Get_Trace (TP_ALLOC, 0x10, bb);
05712
05713 #if defined(TARG_IA32)
05714 Preallocate_Single_Register_Subclasses (bb);
05715 #endif
05716
05717 Alloc_Regs_For_BB (bb, Sched);
05718 }
05719
05720
05721
05722 if (lra_for_pu && CG_localize_tns) {
05723 Spill_Callee_Saved_Regs ();
05724 }
05725
05726
05727 #ifdef TARG_SL //minor_reg_alloc
05728 if(CG_opt_level > 1) {
05729 if(Enable_Checking_Register_Allocation) {
05730 gra_para_region_mgr.Check_Register_Allocation();
05731 }
05732 gra_para_region_mgr.Finalize();
05733 }
05734 #endif
05735 Check_for_Dump (TP_ALLOC, NULL);
05736 Stop_Timer ( T_LRA_CU );
05737 }
05738
05739
05740
05741 static mINT8 *Reg_Request_Table;
05742 #define Reg_Request(bb,cl) \
05743 (Reg_Request_Table[BB_id(bb)*ISA_REGISTER_CLASS_COUNT + cl - ISA_REGISTER_CLASS_MIN])
05744
05745 static INT Reg_Table_Size;
05746
05747
05748 void
05749 LRA_Init (void)
05750 {
05751 Reg_Request_Table = NULL;
05752 Reg_Table_Size = 0;
05753 #ifdef KEY
05754
05755 Need_Dep_Graph_For_Mark_Reloadable_Live_Ranges = TRUE;
05756 #endif
05757 }
05758
05759
05760
05761
05762
05763
05764 void
05765 LRA_Estimate_Fat_Points (
05766 BB *bb,
05767 mINT8 *fatpoint,
05768 INT *regs_in_use,
05769 MEM_POOL* pool)
05770 {
05771 INT inuse[ISA_REGISTER_CLASS_MAX+1];
05772 OP *op;
05773 INT i, opnum, opndnum;
05774 INT tot_use = 0;
05775
05776 Setup_Live_Ranges (bb, FALSE, pool);
05777 if (Do_LRA_Trace(Trace_LRA_Detail)) {
05778 Print_Live_Ranges (bb);
05779 }
05780
05781 for (i = ISA_REGISTER_CLASS_MIN; i <= ISA_REGISTER_CLASS_MAX; i++) {
05782 fatpoint[i] = 0;
05783 inuse[i] = 0;
05784 }
05785
05786 for (opnum = BB_length(bb); opnum > 0; opnum--)
05787 {
05788 op = OP_VECTOR_element(Insts_Vector, opnum);
05789 if (regs_in_use) regs_in_use[opnum] = tot_use;
05790
05791 for (i = 0; i < OP_results(op); i++) {
05792 TN *result_tn = OP_result(op, i);
05793 ISA_REGISTER_CLASS regclass = TN_register_class(result_tn);
05794 LIVE_RANGE *clr = LR_For_TN (result_tn);
05795 if (opnum == LR_first_def(clr)) {
05796 if ((LR_assigned(clr) ||
05797 (!regs_in_use && !TN_is_local_reg(result_tn))))
05798 {
05799 inuse[regclass]--;
05800 if (regs_in_use &&
05801 (LR_last_use(clr) != BB_length(bb)+1) &&
05802 !LR_exposed_use(clr) &&
05803 (LR_last_use(clr) != LR_first_def(clr))){
05804 regs_in_use[opnum] = --tot_use;
05805 }
05806 }
05807 }
05808
05809
05810 if (fatpoint[regclass] == 0) fatpoint[regclass] = 1;
05811 }
05812
05813
05814 for (opndnum = 0; opndnum < OP_opnds(op); opndnum++) {
05815 TN *tn = OP_opnd(op, opndnum);
05816 if (TN_is_register(tn)) {
05817 ISA_REGISTER_CLASS regclass = TN_register_class(tn);
05818 LIVE_RANGE *clr = LR_For_TN (tn);
05819 if (!LR_assigned(clr)) {
05820 if (TN_is_local_reg(tn) || (!regs_in_use &&
05821 ((LR_def_cnt(clr) != 0 && opnum <= LR_exposed_use(clr)) ||
05822 (OP_copy(op) && !TN_is_local_reg(OP_result(op,0))))))
05823 {
05824 Set_LR_assigned(clr);
05825 inuse[regclass]++;
05826 if (regs_in_use &&
05827 (LR_last_use(clr) != BB_length(bb)+1) &&
05828 !LR_exposed_use(clr) &&
05829 (LR_last_use(clr) != LR_first_def(clr))){
05830 regs_in_use[opnum] = ++tot_use;
05831 }
05832 if (fatpoint[regclass] < inuse[regclass]) {
05833 if (inuse[regclass] <= 127) {
05834 fatpoint[regclass] = inuse[regclass];
05835 }
05836 }
05837 }
05838 }
05839
05840 if (fatpoint[regclass] == 0) fatpoint[regclass] = 1;
05841 }
05842 }
05843 }
05844 if (Get_Trace (TP_ALLOC, 0x20, bb)) {
05845 fprintf (TFile, "Fat Points (BB:%d)\t", BB_id(bb));
05846 for (i = ISA_REGISTER_CLASS_MIN; i <= ISA_REGISTER_CLASS_MAX; i++) {
05847 fprintf (TFile, "[%d]:%d ", i, fatpoint[i]);
05848 }
05849 fprintf (TFile, "\n");
05850 }
05851 }
05852
05853
05854 static
05855 mINT8
05856 LRA_examine_last_op_needs (BB *bb, ISA_REGISTER_CLASS cl)
05857 {
05858 OP *last_op = BB_last_op (bb);
05859 mINT8 min_regs = 0;
05860
05861 if (PROC_has_branch_delay_slot() &&
05862 (last_op != NULL) &&
05863 (OP_prev(last_op) != NULL)) last_op = OP_prev(last_op);
05864
05865 if (last_op != NULL && OP_xfer(last_op)) {
05866 INT i;
05867 TN *tn;
05868
05869 for (i = 0; i < OP_opnds(last_op); i++) {
05870 tn = OP_opnd(last_op, i);
05871 if ((tn != NULL) &&
05872 !TN_is_constant(tn) &&
05873 !TN_is_dedicated(tn) &&
05874 !(LRA_TN_register(tn) != REGISTER_UNDEFINED) &&
05875 (TN_register_class(tn) == cl)) min_regs++;
05876 }
05877
05878 }
05879
05880 if ((min_regs == 0) && (cl == ISA_REGISTER_CLASS_integer)) {
05881
05882 min_regs = 1;
05883 }
05884
05885 return min_regs;
05886 }
05887
05888
05889 mINT8 *
05890 LRA_Compute_Register_Request (BB *bb, MEM_POOL *pool)
05891 {
05892
05893 if (Reg_Request_Table == NULL) {
05894
05895 Reg_Request_Table =
05896 TYPE_PU_ALLOC_N (mINT8, (PU_BB_Count+2)*ISA_REGISTER_CLASS_COUNT);
05897 Reg_Table_Size = PU_BB_Count;
05898 }
05899 Is_True (BB_id(bb) <= Reg_Table_Size, ("incorrect BB_id: %d", BB_id(bb)));
05900
05901 mINT8 *fatpoint = &Reg_Request(bb,0);
05902 ISA_REGISTER_CLASS int_regclass = TN_register_class(SP_TN);
05903
05904 LRA_Estimate_Fat_Points (bb, fatpoint, NULL, pool);
05905
05906
05907
05908
05909
05910
05911
05912
05913 if (fatpoint[int_regclass] < 2) fatpoint[int_regclass] = LRA_examine_last_op_needs (bb, int_regclass);
05914
05915 return fatpoint;
05916 }
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928 INT
05929 LRA_Register_Request (BB *bb, ISA_REGISTER_CLASS cl)
05930 {
05931 INT regs_needed;
05932
05933 FmtAssert (!BB_reg_alloc(bb), ("LRA_Register_Request: Invalid bb %d", BB_id(bb)));
05934
05935 if (BB_id(bb) <= Reg_Table_Size) {
05936
05937
05938
05939
05940
05941
05942
05943
05944 mINT8 min_regs = LRA_examine_last_op_needs (bb, cl);
05945 regs_needed = Reg_Request (bb, cl);
05946 if (regs_needed < min_regs) {
05947 regs_needed = min_regs;
05948 Reg_Request (bb, cl) = min_regs;
05949 }
05950 #ifdef KEY
05951
05952
05953 if (BB_innermost(bb) &&
05954 BB_length(bb) > 20) {
05955
05956 regs_needed += (int)(regs_needed * LRA_inflate_reg_request * 0.01 + 0.5);
05957 }
05958 #endif
05959 }
05960 else {
05961
05962 regs_needed = 5;
05963 }
05964 return regs_needed;
05965 }
05966