00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #define __STDC_LIMIT_MACROS
00060 #include <stdint.h>
00061 #include <alloca.h>
00062 #include "defs.h"
00063 #include "config.h"
00064 #include "mempool.h"
00065 #include "tracing.h"
00066 #include "timing.h"
00067 #include "cgir.h"
00068 #include "cg.h"
00069 #include "cg_flags.h"
00070 #include "cgprep.h"
00071 #include "ttype.h"
00072 #include "targ_sim.h"
00073 #include "bb.h"
00074 #include "variants.h"
00075 #include "bitset.h"
00076 #include "bb_set.h"
00077 #include "freq.h"
00078 #include "cgtarget.h"
00079 #include "cxx_memory.h"
00080 #include "whirl2ops.h"
00081 #include "dominate.h"
00082 #include "findloops.h"
00083 #include "cg_vector.h"
00084 #include "hb_sched.h"
00085 #include "reg_live.h"
00086 #include "gcm.h"
00087 #if defined(TARG_SL)
00088 #include "gcm_licm.h"
00089 #include "loop_dce.h"
00090 #include "loop_rce.h"
00091 #endif
00092 #include "glob.h"
00093 #include "cflow.h"
00094 #include "tn_set.h"
00095 #include "cgemit.h"
00096 #include "gtn_universe.h"
00097 #include "gtn_set.h"
00098 #include "gra_live.h"
00099 #include "tn_map.h"
00100 #include "cg_sched_est.h"
00101 #include "cg_loop.h"
00102 #include "pf_cg.h"
00103 #include "targ_proc_properties.h"
00104 #include "tag.h"
00105 #ifdef TARG_X8664
00106 #include "lra.h"
00107 #endif
00108
00109
00110 #include <utility>
00111 #include <map>
00112
00113
00114 BOOL GCM_POST_Spec_Loads = TRUE;
00115 BOOL GCM_PRE_Spec_Loads = TRUE;
00116 #if defined(TARG_SL)
00117 BOOL GCM_Use_Sched_Est = TRUE;
00118 #else
00119 BOOL GCM_Use_Sched_Est = FALSE;
00120 #endif
00121 BOOL GCM_Forw_Circ_Motion = TRUE;
00122 BOOL GCM_POST_Force_Scheduling = FALSE;
00123 BOOL CG_Skip_GCM = FALSE;
00124 INT32 GCM_From_BB = -1;
00125 INT32 GCM_To_BB = -1;
00126 INT32 GCM_Result_TN = -1;
00127 #ifdef KEY
00128 INT32 GCM_BB_Limit = -1;
00129 INT32 cumulative_cand_bb;
00130 #endif
00131
00132
00133 #define SPEC_NONE 0x00 // no speculative motion
00134 #define SPEC_EAGER_PTR 0x01 // eager ptr speculation
00135 #define SPEC_EAGER_NULL_PTR 0x02 // eager null ptr speculation
00136 #define SPEC_CIRC_PTR_ABOVE 0x04 // circluar ptr speculation (above)
00137 #define SPEC_CSAFE_PTR 0x08 // safe control speculation
00138 #define SPEC_DSAFE_PTR 0x10 // safe data speculation
00139 #define SPEC_CDSAFE_PTR (SPEC_CSAFE_PTR | SPEC_DSAFE_PTR) // safe control (and data) speculation
00140 #define SPEC_PSAFE_PTR 0x20 // safe predicate promotion
00141
00142 #define EAGER_NONE(o) ((o) & SPEC_NONE)
00143 #define Set_EAGER_NONE(o) ((o) |= SPEC_NONE)
00144 #define Reset_EAGER_NONE(o) ((o) &= ~SPEC_NONE)
00145 #define EAGER_PTR_SPEC(o) ((o) & SPEC_EAGER_PTR)
00146 #define Set_EAGER_PTR_SPEC(o) ((o) |= SPEC_EAGER_PTR)
00147 #define Reset_EAGER_PTR_SPEC(o) ((o) &= ~SPEC_EAGER_PTR)
00148 #define EAGER_NULL_PTR_SPEC(o) ((o) & SPEC_EAGER_NULL_PTR)
00149 #define Set_EAGER_NULL_PTR_SPEC(o) ((o) |= SPEC_EAGER_NULL_PTR)
00150 #define Reset_EAGER_NULL_PTR_SPEC(o) ((o) &= ~SPEC_EAGER_NULL_PTR)
00151 #define CIRC_PTR_SPEC(o) ((o) & SPEC_CIRC_PTR_ABOVE)
00152 #define Set_CIRC_PTR_SPEC(o) ((o) |= SPEC_CIRC_PTR_ABOVE)
00153 #define Reset_CIRC_PTR_SPEC(o) ((o) &= ~SPEC_CIRC_PTR_ABOVE)
00154 #define CSAFE_PTR_SPEC(o) ((o) & SPEC_CSAFE_PTR)
00155 #define Set_CSAFE_PTR_SPEC(o) ((o) |= SPEC_CSAFE_PTR)
00156 #define Reset_CSAFE_PTR_SPEC(o) ((o) &= ~SPEC_CSAFE_PTR)
00157 #define DSAFE_PTR_SPEC(o) ((o) & SPEC_DSAFE_PTR)
00158 #define Set_DSAFE_PTR_SPEC(o) ((o) |= SPEC_DSAFE_PTR)
00159 #define Reset_DSAFE_PTR_SPEC(o) ((o) &= ~SPEC_DSAFE_PTR)
00160 #define CDSAFE_PTR_SPEC(o) ((o) & SPEC_CDSAFE_PTR)
00161 #define Set_CDSAFE_PTR_SPEC(o) ((o) |= SPEC_CDSAFE_PTR)
00162 #define Reset_CDSAFE_PTR_SPEC(o) ((o) &= ~SPEC_CDSAFE_PTR)
00163 #define PSAFE_PTR_SPEC(o) ((o) & SPEC_PSAFE_PTR)
00164 #define Set_PSAFE_PTR_SPEC(o) ((o) |= SPEC_PSAFE_PTR)
00165 #define Reset_PSAFE_PTR_SPEC(o) ((o) &= ~SPEC_PSAFE_PTR)
00166
00167
00168 INT32 loop_id;
00169
00170
00171 static float speculation_ratio_wfb = 0.35;
00172 static float speculation_ratio_fb = 0.75;
00173
00174
00175
00176 static BOOL Trace_GCM = FALSE;
00177 static BOOL Trace_GCM_Reg_Usage = FALSE;
00178 static BOOL Trace_Fill_Delay_Slots = FALSE;
00179 static BOOL GCM_Internal_Flag = TRUE;
00180 static BOOL Trace_GCM_Dump_IR = FALSE;
00181 static BOOL Trace_GCM_Dump_Preprocess = FALSE;
00182 static BOOL Trace_GCM_Merge_BBs = FALSE;
00183 static BB* GCM_Loop_Prolog;
00184
00185
00186 static INT32 mispredict, fixed, taken;
00187 static double times;
00188
00189 static BB_MAP bbsch_map;
00190
00191
00192 static MEM_POOL loop_descr_pool;
00193
00194
00195 static MEM_POOL gcm_loop_pool;
00196
00197 static HBS_TYPE cur_hbs_type;
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 static BB_MAP bb_cycle_set_map;
00209
00210 #define BB_cycle_set(bb) ((BS *)BB_MAP_Get(bb_cycle_set_map, (bb)))
00211 #define Set_BB_cycle_set(bb, bs) (BB_MAP_Set(bb_cycle_set_map, (bb), (bs)))
00212
00213
00214
00215 static BOOL Run_Cflow_Delay;
00216
00217 BOOL Run_Cflow_GCM;
00218 GCM_TYPE Cur_Gcm_Type;
00219
00220 static BOOL Ignore_TN_Dep;
00221 static INT cur_pc = 0;
00222
00223 #if defined(TARG_SL)
00224
00225 extern BOOL Should_Skip( int, int , int , int );
00226 static bool GCM_Skip_Loop_Binary_Search( int );
00227 static BOOL GCM_Skip_Op_Binary_Search( int );
00228
00229
00230 static BOOL GCM_LICM_Skip_Loop_Binary_Search( int );
00231 static BOOL GCM_LICM_Skip_Op_Binary_Search( int );
00232
00233
00234 static BOOL LOOP_DCE_Skip_Loop_Binary_Search( int );
00235 BOOL LOOP_DCE_Skip_Op_Binary_Search( int );
00236
00237 static BOOL GCM_Skip_Op( OP*, BB*, OP_LIST* );
00238 static void Preprocess_Loop_Head( BB* );
00239 static void Find_Last_Defs_Of_Branch( BB* );
00240 BB* Loop_Is_Zdl( LOOP_DESCR *loop );
00241 static BOOL Loop_Is_Straight_Line( LOOP_DESCR *loop );
00242
00243
00244 static void GCM_Merge_Small_BBs( LOOP_DESCR *loop, MEM_POOL *pool );
00245
00246 static OP_LIST *moved_loads;
00247 static std::vector< std::pair<OP*, OP*> > load_add_pairs;
00248 static std::vector<OP*> last_defs_of_branch;
00249
00250
00251
00252
00253 static std::vector<OP*> left_ops;
00254
00255 typedef struct{
00256 LOOP_DESCR * orig_loop;
00257 OP * mvtc;
00258 BB * host_bb;
00259 }Mvtc_Pos;
00260 static std::vector<Mvtc_Pos> mvtc_targets;
00261 static std::vector< LOOP_DESCR* > postprocessed_loops;
00262
00263
00264 static INT32 circ_above_limit = 50;
00265 static INT32 circ_above_moves = 0;
00266
00267 static float circ_above_tc_limit = 10;
00268
00269
00270
00271
00272
00273
00274 static INT32 local_tn_promotion_limit = 19;
00275 static TN_SET *promoted_tns = NULL;
00276
00277 #define OP_is_loop(o) (OP_code(o)==TOP_loop)
00278 #define OP_is_mvtc(o) ( (OP_code(o)==TOP_mvtc_i) || (OP_code(o)==TOP_mvtc) )
00279
00280
00281 static BOOL barriered = FALSE;
00282
00283 #endif
00284
00285
00286
00287
00288
00289
00290 static INT
00291 sort_by_bb_frequency (const void *bb1, const void *bb2)
00292 {
00293 #ifdef KEY
00294 const BB* A = *(BB**)bb1;
00295 const BB* B = *(BB**)bb2;
00296
00297 if( BB_freq(A) > BB_freq(B) )
00298 return -1;
00299 if( BB_freq(A) < BB_freq(B) )
00300 return 1;
00301
00302 return BB_id(A) < BB_id(B) ? -1 : 1;
00303
00304 #else
00305 if (BB_freq((BB *)bb1) > BB_freq((BB *)bb2)) return 1;
00306 else if (BB_freq((BB *)bb1) < BB_freq((BB *)bb2)) return -1;
00307 else return 0;
00308 #endif
00309 }
00310
00311
00312
00313
00314
00315
00316
00317 static INT
00318 sort_by_edge_probability (const void *bl1, const void *bl2)
00319 {
00320 if (BBLIST_prob((BBLIST *)bl1) > BBLIST_prob((BBLIST *)bl2)) return 1;
00321 else if (BBLIST_prob((BBLIST *)bl1) < BBLIST_prob((BBLIST *)bl2)) return -1;
00322 else return 0;
00323 }
00324
00325
00326
00327
00328
00329
00330 static INT
00331 sort_by_bb_live_in (const void *bb1, const void *bb2)
00332 {
00333 UINT8 bb1_count = 0, bb2_count = 0;
00334
00335 TN* x;
00336 FOR_ALL_GTN_SET_members(BB_live_in((BB *)bb1), x) bb1_count++;
00337 FOR_ALL_GTN_SET_members(BB_live_in((BB *)bb2), x) bb2_count++;
00338
00339 if ((BB_freq((BB *)bb1) * bb1_count) > (BB_freq((BB *)bb2) * bb2_count)) return 1;
00340 else if ((BB_freq((BB *)bb1) * bb1_count) < (BB_freq((BB *)bb2) * bb2_count)) return -1;
00341 else return 0;
00342 }
00343
00344 #if !defined(TARG_SL)
00345
00346
00347
00348
00349
00350 static BOOL
00351 Is_BB_Empty (BB *bb)
00352 {
00353 for (OP *op = BB_first_op(bb); op != NULL; op = OP_next(op)) {
00354 if (OP_Real_Ops(op) != 0) return FALSE;
00355 }
00356 return TRUE;
00357 }
00358 #endif
00359
00360
00361
00362
00363
00364 static void
00365 Print_Trace_File(OP *cand_op, BB *src_bb, BB *cand_bb, BOOL success)
00366 {
00367 const char *str = (success) ? "SUCCESS" : "FAIL";
00368 fprintf (TFile, "%s_GCM(%s): MOVE ",Ignore_TN_Dep ? "POST":"PRE",str);
00369 Print_OP_No_SrcLine (cand_op);
00370 fprintf (TFile," FROM BB:%d => TO BB:%d:\n",
00371 BB_id(src_bb), BB_id(cand_bb));
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 static BOOL
00384 OP_Is_Expensive (OP *cur_op)
00385 {
00386 return CGTARG_Is_Long_Latency(OP_code(cur_op));
00387 }
00388
00389
00390
00391
00392
00393
00394 static OP *
00395 First_Inst_Of_BB (BB *bb)
00396 {
00397 OP *op;
00398
00399 if (bb == NULL) return NULL;
00400 FOR_ALL_BB_OPs_FWD (bb, op) {
00401 if (OP_dummy(op)) continue;
00402 return op;
00403 }
00404
00405 if (BB_succs(bb) != NULL) {
00406 BB *succ_bb = BBLIST_item (BB_succs(bb));
00407 if (BBlist_Len (BB_preds(succ_bb)) == 1) {
00408 return First_Inst_Of_BB (succ_bb);
00409 }
00410 }
00411 return NULL;
00412 }
00413
00414 inline BOOL within_bounds(INT num1, INT num2, INT lower_bound,INT upper_bound){
00415 return (((num1 - num2) < upper_bound) && ((num1 - num2) > lower_bound));
00416 }
00417
00418
00419
00420
00421
00422
00423 static BOOL
00424 OP_Offset_Within_Limit(OP *mem_op1, OP *mem_op2, INT lower_bound,
00425 INT upper_bound)
00426 {
00427
00428 INT offset_opnd_num1 = TOP_Find_Operand_Use(OP_code(mem_op1), OU_offset);
00429 INT offset_opnd_num2 = TOP_Find_Operand_Use(OP_code(mem_op2), OU_offset);
00430
00431 TN *offset1, *offset2;
00432
00433 offset1 = (offset_opnd_num1 < 0) ? NULL : OP_opnd(mem_op1, offset_opnd_num1);
00434 offset2 = (offset_opnd_num2 < 0) ? NULL : OP_opnd(mem_op2, offset_opnd_num2);
00435
00436 if (offset1 && offset2 &&
00437 TN_has_value(offset1) && TN_has_value(offset2)) {
00438 return within_bounds(TN_value(offset1),
00439 TN_value(offset2),
00440 lower_bound,
00441 upper_bound);
00442 }
00443
00444 return FALSE;
00445 }
00446
00447
00448
00449
00450
00451
00452 #define Large_BB(bb, loop) \
00453 (LOOP_DESCR_nestlevel((loop)) == 0 && \
00454 BB_length((bb)) >= (Split_BB_Length/2 - 60))
00455
00456 #ifdef TARG_X8664
00457
00458
00459
00460
00461 static BOOL
00462 Avoid_GOT_BB (BB *bb)
00463 {
00464 OP *first_op = BB_first_op(bb);
00465 OP *last_op = BB_last_op(bb);
00466
00467 return (((first_op != NULL) && OP_computes_got(first_op)) ||
00468 ((last_op != NULL) && OP_computes_got(last_op)));
00469 }
00470 #endif
00471
00472
00473
00474
00475
00476
00477 static BOOL
00478 Check_If_Ignore_BB(BB *bb, LOOP_DESCR *loop)
00479 {
00480
00481 if (BB_freq(bb) < 0.02)
00482 return TRUE;
00483
00484
00485
00486 #ifdef TARG_IA64
00487 if (LOOP_DESCR_nestlevel(loop) == 0 && BB_length(bb) >= (Split_BB_Length - 60))
00488 #else
00489 if (Large_BB(bb, loop))
00490 #endif
00491 return TRUE;
00492
00493 #if 0
00494
00495
00496
00497
00498 if (!GCM_POST_Force_Scheduling &&
00499 (Cur_Gcm_Type & GCM_AFTER_GRA) &&
00500 GCM_PRE_Pass_Enabled) {
00501 if (BB_scheduled(bb) && !BB_scheduled_hbs(bb))
00502 return TRUE;
00503 }
00504 #endif
00505
00506 #ifdef TARG_X8664
00507
00508 if (Avoid_GOT_BB(bb))
00509 return TRUE;
00510 #endif
00511
00512 return FALSE;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521 inline BOOL Similar_Ptr_Offset_ok(OP *cur_op, OP *deref_op) {
00522
00523 INT cur_offset_num = TOP_Find_Operand_Use(OP_code(cur_op), OU_offset);
00524 INT deref_offset_num = TOP_Find_Operand_Use(OP_code(deref_op), OU_offset);
00525 INT deref_base_num = TOP_Find_Operand_Use (OP_code(deref_op), OU_base);
00526 INT cur_base_num = TOP_Find_Operand_Use(OP_code(cur_op), OU_base);
00527
00528 TN *deref_base_tn = OP_opnd(deref_op, deref_base_num);
00529 TN *cur_base_tn = OP_opnd(cur_op, cur_base_num);
00530
00531 if (cur_offset_num < 0 && deref_offset_num < 0) {
00532 DEF_KIND kind;
00533 OP *defop = TN_Reaching_Value_At_Op(cur_base_tn, cur_op, &kind, TRUE);
00534 if (defop && OP_iadd(defop) && kind == VAL_KNOWN) {
00535 TN *defop_offset_tn = OP_opnd(defop, 1);
00536 TN *defop_base_tn = OP_opnd(defop, 2);
00537 if (defop_base_tn == deref_base_tn && TN_has_value(defop_offset_tn))
00538 return TRUE;
00539 }
00540 } else {
00541
00542
00543
00544
00545
00546 return (CG_opt_level > 2) ?
00547 OP_Offset_Within_Limit(cur_op, deref_op, -64, 64) :
00548 OP_Offset_Within_Limit(cur_op, deref_op, -16, 16);
00549 }
00550
00551 return FALSE;
00552 }
00553
00554 #define Null_Ptr_Offset_ok(op) OP_Offset_Within_Limit(op, -1, 256)
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 static BOOL
00565 Similar_Ptr_Addrs_Match (OP *pred_op, OP *succ_op)
00566 {
00567
00568 #ifdef TARG_SL
00569
00570
00571 if( TOP_is_c3_load(OP_code(pred_op)) ||
00572 TOP_is_c3_store(OP_code(pred_op))||
00573 TOP_is_c3_load(OP_code(succ_op)) ||
00574 TOP_is_c3_store(OP_code(succ_op)) ){
00575 return TRUE;
00576 }
00577
00578
00579
00580
00581
00582 if( TOP_is_c2_load(OP_code(pred_op)) ||
00583 TOP_is_c2_store(OP_code(pred_op)) ) {
00584 if( !TOP_is_c2_load(OP_code(succ_op)) &&
00585 !TOP_is_c2_store(OP_code(succ_op)) )
00586 return FALSE;
00587 else
00588 return TRUE;
00589 } else if( TOP_is_c2_load(OP_code(succ_op)) ||
00590 TOP_is_c2_store(OP_code(succ_op)) ) {
00591 if( !TOP_is_c2_load(OP_code(pred_op)) &&
00592 !TOP_is_c2_store(OP_code(pred_op)) )
00593 return FALSE;
00594 else
00595 return TRUE;
00596 }
00597 #endif
00598
00599 if (OP_unalign_mem(pred_op) || OP_unalign_mem(succ_op))
00600 return TRUE;
00601
00602 INT pred_base_num = TOP_Find_Operand_Use(OP_code(pred_op), OU_base);
00603 INT succ_base_num = TOP_Find_Operand_Use(OP_code(succ_op), OU_base);
00604
00605 #ifdef KEY
00606
00607 if (pred_base_num < 0 ||
00608 succ_base_num < 0) {
00609 return TRUE;
00610 }
00611 #endif
00612
00613 TN *pred_base_tn = OP_opnd(pred_op, pred_base_num);
00614 TN *succ_base_tn = OP_opnd(succ_op, succ_base_num);
00615
00616 BOOL identical = FALSE;
00617 if ( TNs_Are_Equivalent(pred_base_tn, succ_base_tn) &&
00618 CG_DEP_Mem_Ops_Offsets_Overlap(pred_op, succ_op, &identical))
00619 return TRUE;
00620
00621
00622
00623
00624 if (TN_is_zero_reg(pred_base_tn) && TN_is_zero_reg(succ_base_tn))
00625 return TRUE;
00626
00627 return FALSE;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 static BOOL
00639 OP_Has_Restrictions(OP *op, BB *source_bb, BB *target_bb, mINT32 motion_type)
00640 {
00641 if (CGTARG_Is_OP_Intrinsic(op)) return TRUE;
00642
00643 #ifdef TARG_X8664
00644 if( OP_icmp(op) )
00645 return TRUE;
00646
00647 if( TOP_is_change_rflags( OP_code(op) ) ||
00648 OP_reads_rflags( op ) )
00649 return TRUE;
00650 #endif
00651
00652 if (OP_has_hazard(op)) return TRUE;
00653
00654 if ((cur_hbs_type & HBS_BEFORE_GRA) != 0 && OP_no_move_before_gra(op))
00655 return TRUE;
00656
00657
00658 if (OP_access_reg_bank(op)) return TRUE;
00659
00660 if ((BB_entry(source_bb) && BB_entry_sp_adj_op(source_bb) == op) ||
00661 (BB_exit(source_bb) && BB_exit_sp_adj_op(source_bb) == op))
00662 return TRUE;
00663
00664
00665 if (OP_Defs_TN(op, SP_TN) || OP_Defs_Reg(op, REGISTER_CLASS_sp, REGISTER_sp))
00666 return TRUE;
00667
00668 #if !defined(TARG_SL)
00669
00670 if (OP_branch_predict(op)) {
00671 UINT64 num_insts = 0;
00672 BB *prev_bb;
00673 for (prev_bb = source_bb; prev_bb && prev_bb != target_bb;
00674 prev_bb = BB_prev(prev_bb)) {
00675 num_insts += BB_length(prev_bb);
00676 }
00677
00678
00679
00680
00681
00682
00683 if ((num_insts * 1.3 * INST_BYTES) >= DEFAULT_BRP_BRANCH_LIMIT)
00684 return TRUE;
00685 }
00686 #endif
00687
00688
00689 if( Motion_Is_CIRC_ABOVE(motion_type) ) {
00690 if (OP_Refs_TN(op, SP_TN) ||
00691 OP_Refs_Reg(op, REGISTER_CLASS_sp, REGISTER_sp)) return TRUE;
00692
00693 #if !defined(TARG_SL)
00694
00695 if (OP_branch_predict(op)) return TRUE;
00696
00697 if (OP_memory(op)) {
00698 if (OP_no_alias(op) || OP_prefetch(op)) return FALSE;
00699
00700
00701
00702
00703
00704 if (PROC_has_delayed_exception() && OP_has_predicate(op)) {
00705 return FALSE;
00706 } else {
00707
00708
00709
00710
00711
00712
00713
00714 if (TN_is_symbol(OP_opnd(op, 1)) &&
00715 ST_class(TN_var(OP_opnd(op, 1))) == CLASS_VAR &&
00716 TY_kind(ST_type(TN_var(OP_opnd(op, 1)))) != KIND_ARRAY)
00717 return FALSE;
00718 }
00719 return TRUE;
00720 }
00721 #endif
00722 }
00723
00724
00725
00726 if (!Ignore_TN_Dep && (OP_copy(op) || OP_glue(op))) return TRUE;
00727
00728
00729 if (OP_branch_predict(op)) {
00730 UINT64 num_insts = 0;
00731 BB *prev_bb;
00732 for (prev_bb = source_bb; prev_bb && prev_bb != target_bb;
00733 prev_bb = BB_prev(prev_bb)) {
00734 num_insts += BB_length(prev_bb);
00735 }
00736
00737
00738
00739
00740
00741
00742 if ((num_insts * 1.3 * INST_BYTES) >= DEFAULT_BRP_BRANCH_LIMIT)
00743 return TRUE;
00744 }
00745
00746
00747 if (motion_type & GCM_CIRC_ABOVE) {
00748 if (OP_Refs_TN(op, SP_TN) ||
00749 OP_Refs_Reg(op, REGISTER_CLASS_sp, REGISTER_sp)) return TRUE;
00750
00751
00752 if (OP_branch_predict(op)) return TRUE;
00753
00754 if (OP_memory(op)) {
00755 if (OP_no_alias(op) || OP_prefetch(op)) return FALSE;
00756
00757
00758
00759 if (PROC_has_delayed_exception() && OP_has_predicate(op)) {
00760 return FALSE;
00761 } else {
00762
00763
00764
00765
00766
00767
00768
00769 if (TN_is_symbol(OP_opnd(op, 1)) &&
00770 ST_class(TN_var(OP_opnd(op, 1))) == CLASS_VAR &&
00771 TY_kind(ST_type(TN_var(OP_opnd(op, 1)))) != KIND_ARRAY)
00772 return FALSE;
00773 }
00774 return TRUE;
00775 }
00776 }
00777
00778
00779
00780
00781 if (!Ignore_TN_Dep && (OP_copy(op) || OP_glue(op))) return TRUE;
00782
00783 #if !defined(TARG_SL)
00784
00785 INT i;
00786 for (i = 0; i < OP_results(op); ++i) {
00787 TN *result_tn = OP_result(op, i);
00788 ISA_REGISTER_CLASS result_cl = TN_register_class (result_tn);
00789
00790
00791
00792 if ((!Ignore_TN_Dep &&
00793 (TN_is_dedicated(result_tn) || TN_is_gra_homeable(result_tn))) ||
00794
00795
00796
00797
00798 ((Ignore_TN_Dep || TN_is_register(result_tn)) &&
00799 REGISTER_Is_Rotating(result_cl, TN_register(result_tn))))
00800
00801 return TRUE;
00802 }
00803
00804
00805
00806 for (i = 0; i < OP_opnds(op); ++i) {
00807 TN *opnd_tn = OP_opnd(op, i);
00808 if (TN_is_constant(opnd_tn)) continue;
00809
00810 ISA_REGISTER_CLASS opnd_cl = TN_register_class (opnd_tn);
00811
00812
00813 if ((!Ignore_TN_Dep && TN_is_gra_homeable(opnd_tn)) ||
00814
00815
00816 ((Ignore_TN_Dep || TN_is_register(opnd_tn)) &&
00817 REGISTER_Is_Rotating(opnd_cl, TN_register(opnd_tn))))
00818 return TRUE;
00819 }
00820
00821 #ifdef TARG_X8664
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 ASM_OP_ANNOT* asm_info = (OP_code(op) == TOP_asm) ?
00835 (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, op) : NULL;
00836
00837 for (int i = 0; i < OP_opnds(op); i++) {
00838 ISA_REGISTER_SUBCLASS subclass = asm_info ?
00839 ASM_OP_opnd_subclass(asm_info)[i] : OP_opnd_reg_subclass(op, i);
00840 if (Single_Register_Subclass(subclass) != REGISTER_UNDEFINED)
00841 return TRUE;
00842 }
00843 for (int i = 0; i < OP_results(op); i++) {
00844 ISA_REGISTER_SUBCLASS subclass = asm_info ?
00845 ASM_OP_result_subclass(asm_info)[i] : OP_result_reg_subclass(op, i);
00846 if (Single_Register_Subclass(subclass) != REGISTER_UNDEFINED)
00847 return TRUE;
00848 }
00849 #endif
00850 #endif
00851
00852 return FALSE;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861 BOOL
00862 Can_Do_Safe_Predicate_Movement(OP *cur_op,
00863 BB *src_bb,
00864 BB *tgt_bb,
00865 mINT32 motion_type)
00866 {
00867
00868
00869
00870
00871 if (motion_type & (GCM_CIRC_ABOVE | GCM_SPEC_ABOVE)) {
00872
00873
00874
00875
00876
00877 if (OP_has_predicate(cur_op) &&
00878 !TN_is_true_pred(OP_opnd(cur_op, OP_PREDICATE_OPND)) &&
00879 !CGTARG_Can_Be_Speculative(cur_op)) return FALSE;
00880
00881 OP *tgt_br_op = BB_branch_op(tgt_bb);
00882 if (tgt_br_op && OP_has_predicate(tgt_br_op)) {
00883
00884
00885
00886
00887 if (!TN_is_true_pred(OP_opnd(tgt_br_op, OP_PREDICATE_OPND)) &&
00888 (BB_Unique_Source(src_bb) == tgt_bb)) {
00889 TN *tn1, *tn2;
00890 OP *cmp_op;
00891 CGTARG_Analyze_Compare(tgt_br_op, &tn1, &tn2, &cmp_op);
00892
00893
00894
00895 if (cmp_op && cmp_op != tgt_br_op && OP_results(cmp_op) == 2) {
00896 TN *r0 = OP_result(cmp_op, 0);
00897 TN *r1 = OP_result(cmp_op, 1);
00898
00899
00900
00901
00902
00903
00904 if (OP_has_predicate(cmp_op) &&
00905 !TN_is_true_pred(OP_opnd(cmp_op, OP_PREDICATE_OPND)))
00906 return FALSE;
00907
00908
00909
00910
00911
00912
00913 if (!Ignore_TN_Dep && (!TN_is_global_reg(r0) || !TN_is_global_reg(r1)))
00914 return FALSE;
00915
00916 if (!TN_is_true_pred(r0) && !TN_is_true_pred(r1)) return TRUE;
00917
00918 }
00919 }
00920 }
00921 }
00922
00923 return FALSE;
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 static BOOL
00935 #if defined(TARG_SL)
00936 Eager_Ptr_Deref_Spec(OP *deref_op, BB *cur_bb, BB *src_bb, BB *dest_bb, BOOL forw)
00937 #else
00938 Eager_Ptr_Deref_Spec(OP *deref_op, BB *dest_bb, BOOL forw)
00939 #endif
00940 {
00941 #ifdef TARG_SL
00942
00943
00944
00945
00946 if( TOP_is_c2_load(OP_code(deref_op)) ||
00947 TOP_is_c2_store(OP_code(deref_op)) )
00948 return FALSE;
00949 #endif
00950
00951 OP *cur_op;
00952 OP *limit_op;
00953 BOOL valid_addrs_found = FALSE;
00954
00955 limit_op = NULL;
00956 TN *deref_base_tn;
00957
00958 INT dbase_num = TOP_Find_Operand_Use(OP_code(deref_op), OU_base);
00959 INT doffset_num = TOP_Find_Operand_Use(OP_code(deref_op), OU_offset);
00960
00961 #ifdef KEY
00962 deref_base_tn = dbase_num >= 0 ? OP_opnd(deref_op, dbase_num) : NULL;
00963 #else
00964 deref_base_tn = OP_opnd(deref_op, dbase_num);
00965 #endif // KEY
00966
00967 for (cur_op = (forw) ? BB_last_op(dest_bb) : BB_first_op(dest_bb);
00968 cur_op && cur_op != limit_op;
00969 cur_op = (forw) ? OP_prev(cur_op) : OP_next(cur_op)) {
00970 #ifdef TARG_SL
00971
00972 if( TOP_is_c2_load(OP_code(deref_op)) ||
00973 TOP_is_c2_store(OP_code(deref_op)) )
00974 continue;
00975 #endif
00976
00977 if (OP_dummy(cur_op)) continue;
00978
00979
00980
00981 if (OP_load(cur_op) || OP_store(cur_op)) {
00982
00983 INT cbase_num = TOP_Find_Operand_Use(OP_code(cur_op), OU_base);
00984 INT coffset_num = TOP_Find_Operand_Use(OP_code(cur_op), OU_offset);
00985
00986 #ifdef KEY
00987 TN *cur_base_tn = cbase_num >= 0 ? OP_opnd(cur_op, cbase_num) : NULL;
00988 #else
00989 TN *cur_base_tn = OP_opnd(cur_op, cbase_num);
00990 #endif // KEY
00991 TN *cur_result_tn = OP_load(cur_op) ? OP_result(cur_op, 0) : NULL;
00992
00993 if (!Similar_Ptr_Addrs_Match(cur_op, deref_op)) {
00994 if (Similar_Ptr_Offset_ok(cur_op, deref_op)) {
00995
00996 if (coffset_num < 0 && doffset_num < 0) {
00997 valid_addrs_found = TRUE;
00998 break;
00999 } else {
01000
01001
01002 BOOL modifies_base = cur_result_tn &&
01003 #ifdef KEY
01004 ( cur_base_tn != NULL ) &&
01005 #endif
01006 TNs_Are_Equivalent(cur_result_tn, cur_base_tn);
01007
01008 if (!modifies_base &&
01009 TNs_Are_Equivalent(deref_base_tn, cur_base_tn)){
01010 valid_addrs_found = TRUE;
01011 break;
01012 }
01013 }
01014 }
01015 } else {
01016
01017
01018 valid_addrs_found = FALSE;
01019 break;
01020 }
01021 }
01022
01023
01024
01025
01026 #ifdef TARG_IA64
01027 BOOL base_redef = FALSE;
01028 for (INT i = 0; i < OP_results(cur_op); ++i) {
01029 TN *result = OP_result(cur_op,i);
01030 if (Ignore_TN_Dep) {
01031 REGISTER result_reg = TN_register(result);
01032
01033
01034
01035
01036 if (result_reg == TN_register(deref_base_tn))
01037 base_redef = TRUE;
01038 } else {
01039 if (TNs_Are_Equivalent(result, deref_base_tn)) base_redef = TRUE;
01040 }
01041 }
01042
01043
01044 if (base_redef) {
01045 valid_addrs_found = FALSE;
01046 break;
01047 }
01048 #else // TARG_IA64
01049 #ifdef KEY
01050 if( deref_base_tn != NULL )
01051 #endif // KEY
01052 {
01053 BOOL base_redef = FALSE;
01054 for (INT i = 0; i < OP_results(cur_op); ++i) {
01055 TN *result = OP_result(cur_op,i);
01056 if (Ignore_TN_Dep) {
01057 REGISTER result_reg = TN_register(result);
01058
01059
01060
01061
01062 if (result_reg == TN_register(deref_base_tn))
01063 base_redef = TRUE;
01064 } else {
01065 if (TNs_Are_Equivalent(result, deref_base_tn)) base_redef = TRUE;
01066 }
01067 }
01068
01069
01070 if (base_redef) {
01071 valid_addrs_found = FALSE;
01072 break;
01073 }
01074 }
01075 #endif
01076
01077
01078
01079
01080 if (OP_call(cur_op) &&
01081 !CG_DEP_Can_OP_Move_Across_Call(deref_op, cur_op,forw,Ignore_TN_Dep)) {
01082 valid_addrs_found = FALSE;
01083 break;
01084 }
01085 }
01086
01087
01088 if (valid_addrs_found) return TRUE;
01089
01090 return FALSE;
01091 }
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 static BOOL
01105 Null_Ptr_Deref_Spec(OP *deref_op, BB *src, BB *dest)
01106 {
01107 REGISTER condition_reg;
01108 TN *condition_tn;
01109 BOOL taken_path;
01110
01111 OP *branch_op = BB_branch_op(dest);
01112
01113 if (branch_op == NULL || !OP_cond(branch_op)) return FALSE;
01114
01115
01116
01117
01118 TN *opnd1, *opnd2;
01119 INT variant;
01120
01121
01122 variant = CGTARG_Analyze_Branch(branch_op, &opnd1, &opnd2);
01123
01124
01125
01126 if (opnd2 == NULL) return FALSE;
01127
01128 Is_True(opnd1, ("expected two operand TNs from CGTARG_Analyze_Branch"));
01129
01130
01131
01132 if (TN_is_zero(opnd1)) {
01133 condition_tn = opnd2;
01134 } else if (TN_is_zero(opnd2)) {
01135 condition_tn = opnd1;
01136 } else {
01137 return FALSE;
01138 }
01139
01140 if (Ignore_TN_Dep)
01141 condition_reg = TN_register(condition_tn);
01142
01143
01144 switch (variant) {
01145
01146 case V_BR_I8EQ:
01147 taken_path = FALSE;
01148 break;
01149
01150
01151
01152
01153 case V_BR_I8NE:
01154 case V_BR_I8GE:
01155 case V_BR_I8GT:
01156 case V_BR_I8LE:
01157 case V_BR_I8LT:
01158 taken_path = TRUE;
01159 break;
01160
01161 default:
01162 condition_reg = 0;
01163 taken_path = FALSE;
01164 }
01165
01166
01167
01168 BOOL non_post_dom = BS_MemberP (BB_dom_set(src), BB_id(dest)) &&
01169 !BS_MemberP (BB_pdom_set(dest), BB_id(src));
01170 if (non_post_dom || (dest == BB_prev(src))) {
01171 if (taken_path) return FALSE;
01172 } else {
01173 if (!taken_path) return FALSE;
01174 }
01175
01176 #ifdef TARG_X8664
01177 const int base_idx = TOP_Find_Operand_Use( OP_code(deref_op),OU_base );
01178 if( base_idx < 0 )
01179 return FALSE;
01180 TN* base_tn = OP_opnd( deref_op, base_idx );
01181 TN* offset_tn = OP_opnd( deref_op,
01182 TOP_Find_Operand_Use( OP_code(deref_op),OU_offset ) );
01183 #else
01184
01185 TN *base_tn = OP_load(deref_op) ? OP_opnd(deref_op, 0) :
01186 OP_opnd(deref_op, 1);
01187
01188 TN *offset_tn = OP_load(deref_op) ? OP_opnd(deref_op, 1):
01189 OP_opnd(deref_op, 2);
01190 #endif // TARG_X8664
01191
01192
01193
01194 if (Ignore_TN_Dep) {
01195 REGISTER base_reg = TN_register(base_tn);
01196 if (base_reg == condition_reg && TN_value(offset_tn) >= 0)
01197 return TRUE;
01198 } else {
01199 if (TN_number(base_tn) == TN_number(condition_tn) &&
01200 TN_value(offset_tn) >= 0)
01201 return TRUE;
01202 }
01203
01204 return FALSE;
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 static BOOL
01216 Can_Mem_Op_Be_Moved(OP *mem_op, BB *cur_bb, BB *src_bb, BB *dest_bb,
01217 mINT32 motion_type
01218 #if defined(TARG_SL)
01219 , mUINT32 *cur_spec_type
01220 #endif
01221 )
01222 {
01223
01224 if ((Cur_Gcm_Type & GCM_AFTER_GRA) && !GCM_POST_Spec_Loads)
01225 return FALSE;
01226
01227 if ((Cur_Gcm_Type & GCM_BEFORE_GRA) && !GCM_PRE_Spec_Loads)
01228 return FALSE;
01229
01230
01231
01232
01233 #if defined(TARG_SL)
01234 *cur_spec_type = 0;
01235 #endif
01236 BOOL forw = motion_type & (GCM_EQUIV_FWD | GCM_SPEC_ABOVE |
01237 GCM_DUP_ABOVE | GCM_CIRC_ABOVE);
01238 if (motion_type & (GCM_SPEC_ABOVE | GCM_SPEC_BELOW | GCM_CIRC_ABOVE)) {
01239
01240
01241 if (OP_store(mem_op))
01242 return FALSE;
01243 }
01244
01245 #ifdef TARG_X8664
01246
01247
01248
01249
01250
01251
01252
01253
01254 if( mcmodel >= MEDIUM &&
01255 !Ignore_TN_Dep &&
01256 forw ){
01257 BB* prev = BB_prev( src_bb );
01258
01259 if( prev != NULL &&
01260 BB_call( prev ) ){
01261 const TOP top = OP_code(mem_op);
01262 if( top == TOP_ld8_abs || top == TOP_ld16_abs ||
01263 top == TOP_ld32_abs || top == TOP_ld64_abs )
01264 return FALSE;
01265 }
01266 }
01267 #endif
01268
01269
01270 if (OP_volatile(mem_op)) return FALSE;
01271
01272
01273 if (OP_prefetch(mem_op)) return TRUE;
01274
01275 OP *cur_op, *br_op, *limit_op;
01276 BOOL definite = FALSE, alias = FALSE;
01277
01278
01279
01280 OP *last_op = BB_last_op(dest_bb);
01281 if (cur_bb == dest_bb)
01282
01283 limit_op = (br_op = BB_xfer_op(dest_bb)) ? OP_prev(br_op) :
01284 ((last_op = BB_last_op(dest_bb)) ? OP_prev(last_op) : last_op);
01285 else
01286 limit_op = (cur_bb == src_bb) ? mem_op : NULL;
01287
01288 BOOL read_read_dep;
01289 for (cur_op = ((forw && cur_bb != src_bb) || (!forw && cur_bb == src_bb)) ?
01290 BB_last_op(cur_bb) : BB_first_op(cur_bb);
01291 cur_op && cur_op != limit_op;
01292 cur_op = ((forw && cur_bb != src_bb) || (!forw && cur_bb == src_bb)) ?
01293 OP_prev(cur_op) : OP_next(cur_op)) {
01294
01295
01296 if (OP_dummy(cur_op)) continue;
01297
01298
01299 if (OP_prefetch(cur_op)) {
01300 if (Motion_Is_CIRC_ABOVE(motion_type) ) {
01301
01302
01303 WN *memwn = Get_WN_From_Memory_OP(mem_op);
01304 PF_POINTER *pf_ptr1 = memwn ?
01305 (PF_POINTER *)WN_MAP_Get(WN_MAP_PREFETCH, memwn) : NULL;
01306
01307
01308 WN *wn = Get_WN_From_Memory_OP( cur_op);
01309 PF_POINTER *pf_ptr2 = wn ? (PF_POINTER *) WN_MAP_Get(WN_MAP_PREFETCH,wn) : NULL;
01310
01311 if (pf_ptr1 == pf_ptr2)
01312 return FALSE;
01313
01314 } else continue;
01315 }
01316
01317 if (OP_memory(cur_op)
01318 #ifdef TARG_X8664
01319 || OP_load_exe(cur_op)
01320 #endif
01321 ) {
01322 #ifdef TARG_X8664
01323 read_read_dep = ( OP_load(cur_op) || OP_load_exe(cur_op) ) &&
01324 ( OP_load(mem_op) || OP_load_exe(mem_op) );
01325 #else
01326 read_read_dep = OP_load(cur_op) && OP_load(mem_op);
01327 #endif
01328
01329
01330 if (!read_read_dep &&
01331 CG_DEP_Mem_Ops_Alias(cur_op, mem_op, &definite)) {
01332 #if !defined(TARG_SL)
01333 return FALSE;
01334 }
01335 }
01336 }
01337 #else
01338
01339
01340 if (cur_bb != dest_bb) return FALSE;
01341
01342
01343
01344
01345
01346
01347 if (OP_load(cur_op) || OP_store(cur_op)) {
01348 TN *to_base_tn = OP_load(cur_op) ? OP_opnd(cur_op, 0) :
01349 OP_opnd(cur_op, 1);
01350 TN *from_base_tn = OP_load(mem_op) ? OP_opnd(mem_op, 0) :
01351 OP_opnd(mem_op, 1);
01352 if(TN_is_register(to_base_tn) && TN_is_register(from_base_tn)) {
01353 if (!Ignore_TN_Dep) {
01354 if (TN_number(to_base_tn) != TN_number(from_base_tn))
01355
01356
01357
01358 if( !(Motion_Is_CIRC_ABOVE(motion_type) && (cur_bb == src_bb)) )
01359 return FALSE;
01360 } else {
01361 REGISTER to_base_reg = TN_register(to_base_tn);
01362 REGISTER from_base_reg = TN_register(from_base_tn);
01363 if (to_base_reg != from_base_reg)
01364 if( !( Motion_Is_CIRC_ABOVE(motion_type) && (cur_bb == src_bb)) )
01365 return FALSE;
01366 }
01367 }
01368 }
01369
01370
01371 alias |= TRUE;
01372 }
01373 }
01374 }
01375
01376
01377
01378
01379
01380 if (forw) {
01381
01382
01383
01384 if (GCM_Pointer_Spec &&
01385
01386
01387
01388
01389
01390
01391 (GCM_Eager_Ptr_Deref && !definite && !OP_prefetch(mem_op) &&
01392
01393
01394
01395
01396 (cur_bb == dest_bb) &&
01397
01398 Eager_Ptr_Deref_Spec(mem_op, cur_bb, src_bb, dest_bb, forw)))
01399 {
01400 Set_EAGER_PTR_SPEC(*cur_spec_type);
01401 }
01402
01403
01404
01405
01406
01407 if ( Motion_Is_CIRC_ABOVE(motion_type) && (cur_bb == src_bb)) {
01408 Set_CIRC_PTR_SPEC(*cur_spec_type);
01409 }
01410
01411 }
01412 if( !alias || EAGER_PTR_SPEC(*cur_spec_type) || CIRC_PTR_SPEC(*cur_spec_type) )
01413 return TRUE;
01414
01415 return FALSE;
01416 #endif // !TARG_SL
01417
01418
01419
01420
01421
01422 return TRUE;
01423 }
01424
01425
01426
01427
01428
01429 static BOOL
01430 Can_Inst_Be_Moved (OP *op, VECTOR succs_vector, INT succ_num)
01431 {
01432
01433 if (VECTOR_count(succs_vector) == 1) return TRUE;
01434
01435 if (!CGTARG_Can_Be_Speculative (op)) return FALSE;
01436
01437 if (OP_has_hazard(op) || OP_imul(op) || OP_idiv(op)) {
01438 return FALSE;
01439 }
01440
01441
01442
01443 for (INT i = 0; i < OP_results(op); ++i) {
01444 TN *result = OP_result(op,i);
01445 ISA_REGISTER_CLASS result_cl = TN_register_class (result);
01446 REGISTER result_reg = TN_register (result);
01447 for (INT i = 0; i < VECTOR_count(succs_vector); i++) {
01448 if (i == succ_num) continue;
01449 BBLIST *succ_bl = (BBLIST *) VECTOR_element(succs_vector, i);
01450 BB *succ_bb = BBLIST_item(succ_bl);
01451 if (REG_LIVE_Into_BB (result_cl, result_reg, succ_bb)) return FALSE;
01452 }
01453 }
01454 return TRUE;
01455 }
01456
01457
01458
01459
01460
01461
01462
01463 static INT16
01464 Find_Vacant_Slots_BB(BB *bb, INT targ_alignment)
01465 {
01466 BBLIST *bblist;
01467 INT16 vacant_slots = 0;
01468
01469 BBSCH *bbsch = (BBSCH *)BB_MAP_Get (bbsch_map, bb);
01470
01471
01472
01473 if (!BB_loop_head_bb(bb)) {
01474 FOR_ALL_BB_PREDS(bb, bblist) {
01475 BB *pred_bb = BBLIST_item(bblist);
01476 BBSCH *pred_bbsch = (BBSCH *)BB_MAP_Get (bbsch_map, pred_bb);
01477
01478
01479
01480 if (bbsch && pred_bbsch) {
01481 BBSCH_bb_start_pc(bbsch) =
01482 MAX (BBSCH_bb_start_pc(bbsch),
01483 BBSCH_bb_start_pc(pred_bbsch) +
01484 BBSCH_num_real_ops(pred_bbsch));
01485 BB_MAP_Set (bbsch_map, bb, bbsch);
01486 }
01487 }
01488 }
01489
01490
01491
01492 vacant_slots = (targ_alignment - ((BBSCH_bb_start_pc(bbsch) +
01493 BBSCH_num_real_ops(bbsch)) %
01494 targ_alignment));
01495
01496 return vacant_slots;
01497 }
01498
01499
01500
01501
01502
01503
01504
01505 static OP*
01506 Find_OP_For_Delay_Slot (BB *bb)
01507 {
01508 return First_Inst_Of_BB (bb);
01509 }
01510
01511
01512
01513
01514
01515 static BOOL
01516 Fill_From_Successor (BB *bb, OP *xfer_op, VECTOR succs_vector, INT succ_num)
01517 {
01518 BBLIST *succ_bl = (BBLIST *) VECTOR_element(succs_vector, succ_num);
01519 BB *succ_bb = BBLIST_item(succ_bl);
01520 OP *first_op = Find_OP_For_Delay_Slot (succ_bb);
01521
01522
01523
01524
01525
01526
01527
01528 if ( BB_rid(succ_bb) &&
01529 BB_id(succ_bb) == BB_id(REGION_First_BB)) return FALSE;
01530
01531 typedef enum {
01532 FILL_NONE,
01533 FILL_DELETE,
01534 FILL_MOVE,
01535 FILL_DUP
01536 } FILL_TYPE;
01537
01538 FILL_TYPE fill_type = FILL_NONE;
01539 if (Is_Delay_Slot_Op (xfer_op, first_op) &&
01540 !OP_Has_Restrictions(first_op, bb, succ_bb, GCM_DUP_ABOVE)) {
01541 TOP blikely_opcode;
01542 BOOL fallthru = (succ_bb == BB_next(bb));
01543 BOOL single_pred = (BBlist_Len (BB_preds(succ_bb)) == 1);
01544 if (Can_Inst_Be_Moved (first_op, succs_vector, succ_num)) {
01545
01546
01547
01548 if (single_pred) {
01549 fill_type = FILL_MOVE;
01550 }
01551 else if (!(OP_ijump(xfer_op) && !OP_call(xfer_op))) {
01552
01553
01554 if (fallthru && VECTOR_count(succs_vector) != 1) {
01555 fill_type = FILL_DELETE;
01556 }
01557 else {
01558
01559
01560
01561
01562
01563
01564 if (OP_br(xfer_op) && !OP_cond(xfer_op) &&
01565 (VECTOR_count(succs_vector) == 1) &&
01566 (BBlist_Len (BB_preds(bb)) == 1)) {
01567 BB *unique_pred = BB_Unique_Predecessor (bb);
01568
01569
01570
01571 if (unique_pred && (BB_freq(unique_pred) == BB_freq(succ_bb))) {
01572 fill_type = FILL_NONE;
01573 Run_Cflow_Delay = TRUE;
01574 }
01575 else fill_type = FILL_DUP;
01576 }
01577 else fill_type = FILL_DUP;
01578 }
01579 }
01580 }
01581 else if (!fallthru &&
01582 CGTARG_Can_Change_To_Brlikely (xfer_op, &blikely_opcode) &&
01583 CGTARG_Use_Brlikely (BBLIST_prob(succ_bl))
01584 )
01585 {
01586 OP_Change_Opcode(xfer_op, blikely_opcode);
01587 fill_type = (single_pred) ? FILL_MOVE : FILL_DUP;
01588 if (Trace_Fill_Delay_Slots) {
01589 #pragma mips_frequency_hint NEVER
01590 fprintf (TFile, "DELAY_FILL> changed to BRLIKELY\n");
01591 }
01592 }
01593 }
01594
01595 OP *delay_op = BB_last_op(bb);
01596 BB *from_bb;
01597
01598 switch (fill_type) {
01599 case FILL_DELETE:
01600 if (Trace_Fill_Delay_Slots) {
01601 #pragma mips_frequency_hint NEVER
01602 fprintf (TFile,"DELAY_FILL> Remove delay-slot op in BB:%d freq = %#.2f\n",
01603 BB_id(bb), BB_freq(bb));
01604 Print_OP_No_SrcLine (delay_op);
01605 }
01606 BB_Remove_Op (bb, delay_op);
01607 break;
01608 case FILL_MOVE:
01609 if (Trace_Fill_Delay_Slots) {
01610 #pragma mips_frequency_hint NEVER
01611 fprintf (TFile, "DELAY_FILL> Move OP: from BB:%d freq = %#.2f to BB:%d freq = %#.2f\n",
01612 BB_id(OP_bb(first_op)), BB_freq(OP_bb(first_op)),
01613 BB_id(bb), BB_freq(bb));
01614 Print_OP_No_SrcLine (first_op);
01615 }
01616 BB_Remove_Op (bb, delay_op);
01617 from_bb = OP_bb(first_op);
01618 BB_Move_Op_To_End (bb, OP_bb(first_op), first_op);
01619 if (Is_BB_Empty (from_bb)) {
01620 Run_Cflow_Delay = TRUE;
01621 }
01622 break;
01623 case FILL_DUP:
01624 if (Trace_Fill_Delay_Slots) {
01625 #pragma mips_frequency_hint NEVER
01626 fprintf (TFile, "DELAY_FILL> Copy OP: from BB:%d freq = %#.2f to BB:%d frequency = %#.2f\n",
01627 BB_id(OP_bb(first_op)), BB_freq(OP_bb(first_op)),
01628 BB_id(bb), BB_freq(bb));
01629 Print_OP_No_SrcLine (first_op);
01630 }
01631 BB_Remove_Op (bb, delay_op);
01632 BB_Append_Op (bb, Dup_OP (first_op));
01633 TN *label_tn = NULL;
01634 for (INT i = 0; i < OP_opnds(xfer_op); ++i) {
01635 if (TN_is_label(OP_opnd(xfer_op,i))) {
01636 label_tn = OP_opnd(xfer_op,i);
01637 Set_OP_opnd (xfer_op, i, Gen_Adjusted_TN (label_tn, 4));
01638 }
01639 }
01640 FmtAssert (label_tn != NULL, ("Fill_From_Successor: no label in xfer_op"));
01641 break;
01642 }
01643 return (fill_type != FILL_NONE);
01644 }
01645
01646
01647
01648
01649
01650
01651 void
01652 GCM_Fill_Branch_Delay_Slots (void)
01653 {
01654
01655 if (!GCM_Enable_Fill_Delay_Slots) return;
01656
01657 Run_Cflow_Delay = FALSE;
01658
01659 MEM_POOL *pool = &MEM_local_pool;
01660 L_Save ();
01661
01662 Trace_Fill_Delay_Slots = Get_Trace (TP_GCM, 0x02);
01663
01664
01665 REG_LIVE_Analyze_Region ();
01666
01667 for (BB *bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
01668 BBLIST *bl;
01669
01670
01671 if ( (BB_rid(bb)) && (RID_level(BB_rid(bb)) >= RL_CGSCHED)) continue;
01672
01673
01674
01675
01676 if (Is_BB_Empty (bb)) {
01677 Run_Cflow_Delay = TRUE;
01678 continue;
01679 }
01680
01681 if (BB_call(bb)) continue;
01682 OP *delay_op = BB_last_op(bb);
01683
01684 if (delay_op == NULL || !OP_noop(delay_op)) continue;
01685 OP *xfer_op = OP_prev(delay_op);
01686 if (xfer_op == NULL || !OP_xfer(xfer_op)) continue;
01687 if (BB_exit(bb)) {
01688
01689
01690
01691
01692
01693
01694
01695 if (!Run_Cflow_Delay && BB_length(bb) <= 3) {
01696 FOR_ALL_BB_PREDS (bb, bl) {
01697 BB *pred = BBLIST_item(bl);
01698 OP *br = BB_branch_op(pred);
01699 if ( br
01700 && OP_br(br)
01701 && !OP_cond(br)
01702 && (BB_length(bb) == 2 || OP_noop(BB_last_op(pred)))
01703 ) {
01704 Run_Cflow_Delay = TRUE;
01705 break;
01706 }
01707 }
01708 }
01709 continue;
01710 }
01711 INT num_succs = BBlist_Len (BB_succs(bb));
01712 if (Trace_Fill_Delay_Slots) {
01713 #pragma mips_frequency_hint NEVER
01714 fprintf (TFile, "DELAY_FILL> Empty delay slot in BB:%d, succs:%d\n",
01715 BB_id(bb), num_succs);
01716 }
01717
01718
01719 VECTOR succs_vector = VECTOR_Init (num_succs, pool);
01720 FOR_ALL_BB_SUCCS (bb, bl) {
01721 VECTOR_Sorted_Add_Element (succs_vector, (void *)bl,
01722 sort_by_edge_probability);
01723 }
01724 for (INT i = 0; i < num_succs; i++) {
01725 if (Fill_From_Successor (bb, xfer_op, succs_vector, i)) break;
01726 }
01727 }
01728
01729 L_Free ();
01730
01731 if ((Run_Cflow_Delay || Run_Cflow_GCM) && GCM_Enable_Cflow) {
01732
01733
01734
01735
01736
01737
01738
01739
01740 CFLOW_Optimize(CFLOW_BRANCH | CFLOW_UNREACHABLE | CFLOW_FILL_DELAY_SLOTS,
01741 "CFLOW (from gcm)");
01742 }
01743
01744
01745 REG_LIVE_Finish ();
01746 }
01747
01748
01749
01750
01751
01752
01753
01754 static OP*
01755 Find_Limit_OP(OP *cur_op, BB *cur_bb, BB *src_bb, BB *tgt_bb)
01756 {
01757 OP *limit_op;
01758
01759 if (Cur_Gcm_Type & GCM_BEFORE_GRA)
01760 limit_op = BB_copy_xfer_op(tgt_bb);
01761 else
01762 limit_op = BB_xfer_op(tgt_bb);
01763
01764 if (cur_bb == tgt_bb)
01765 limit_op = (limit_op) ? OP_prev(limit_op) : BB_last_op(cur_bb);
01766 else
01767 limit_op = (cur_bb == src_bb) ? cur_op : NULL;
01768
01769 return limit_op;
01770 }
01771
01772 #if defined(TARG_SL)
01773
01774
01775
01776
01777 static void
01778 Cumulate_Local_TN_Promotion( OP *cand_op )
01779 {
01780 INT32 res_num = OP_results( cand_op );
01781 INT32 opnd_num = OP_opnds( cand_op );
01782
01783 for(int i=0; i < res_num; i++ ){
01784 TN *tn = OP_result( cand_op, i );
01785 if( !TN_is_constant(tn) && !TN_is_global_reg(tn) && !TN_is_dedicated(tn) ){
01786 promoted_tns = TN_SET_Union1D( promoted_tns, tn, &gcm_loop_pool );
01787 }
01788 }
01789
01790 for(int i=0; i < opnd_num; i++ ){
01791 TN *tn = OP_opnd( cand_op, i );
01792 if( !TN_is_constant(tn) && !TN_is_global_reg(tn) && !TN_is_dedicated(tn) ){
01793 promoted_tns = TN_SET_Union1D( promoted_tns, tn, &gcm_loop_pool );
01794 }
01795 }
01796 }
01797
01798
01799
01800
01801
01802
01803 static BOOL All_OPs_Visited( BB* bb );
01804 static BOOL
01805 OP_Move_Heuristic( OP *cur_op, mINT32 motion_type, BB *src_bb, BB *tgt_bb )
01806 {
01807
01808
01809
01810
01811
01812
01813 if( OP_has_tag(cur_op) && ( BB_length(src_bb)==1 || All_OPs_Visited(src_bb) ) )
01814 return FALSE;
01815
01816 std::vector<OP*>::const_iterator cit = last_defs_of_branch.begin();
01817 for( ; cit != last_defs_of_branch.end(); cit++ ){
01818 if( *cit == cur_op ){
01819 if( Trace_GCM )
01820 fprintf( TFile, "cur_op is skipped for it is last def of branch" );
01821 return FALSE;
01822 }
01823 }
01824
01825 if( Motion_Is_CIRC_ABOVE(motion_type) && circ_above_moves > circ_above_limit ){
01826 if( Trace_GCM )
01827 fprintf( TFile, "cur_op is skipped for exceeds the limit of circ_above" );
01828 return FALSE;
01829 }
01830
01831 if( Motion_Is_CIRC_ABOVE(motion_type) &&
01832 TN_SET_Size(promoted_tns) > local_tn_promotion_limit ){
01833 if( Trace_GCM )
01834 fprintf( TFile, "cur_op is skipped for exceeds the limit of local tn promotion in circ_above motion" );
01835 return FALSE;
01836 }
01837
01838 return TRUE;
01839 }
01840 #endif // TARG_SL
01841
01842
01843
01844
01845
01846
01847 static BOOL
01848 Can_OP_Move(OP *cur_op, BB *src_bb, BB *tgt_bb, BB_SET **pred_bbs,
01849 void *defs[2], void *uses[2], mINT32 motion_type,mUINT8 *spec_type)
01850 {
01851 BB *cur_bb;
01852 REGISTER_SET mid_reg_defs[ISA_REGISTER_CLASS_MAX+1],
01853 mid_reg_uses[ISA_REGISTER_CLASS_MAX+1];
01854 GTN_SET *mid_gtn_defs, *mid_gtn_uses;
01855 TN_SET *mid_tn_defs, *mid_tn_uses;
01856
01857
01858
01859
01860 BOOL can_spec = TRUE;
01861 BOOL safe_spec = FALSE;
01862 *spec_type = SPEC_NONE;
01863 if (motion_type & (GCM_SPEC_ABOVE | GCM_SPEC_BELOW | GCM_CIRC_ABOVE)) {
01864
01865
01866
01867 if( !( Motion_Is_CIRC_ABOVE(motion_type) && OP_load(cur_op) ) )
01868 if (OP_Is_Expensive(cur_op))
01869 return FALSE;
01870 #if defined(TARG_SL)
01871 if( !CGTARG_Can_Be_Speculative (cur_op) ){
01872
01873 if( !Motion_Is_CIRC_ABOVE(motion_type) )
01874 return FALSE;
01875 else
01876 can_spec = FALSE;
01877 }
01878 }
01879
01880 if (Ignore_TN_Dep) {
01881 REGSET_CLEAR(mid_reg_defs);
01882 REGSET_CLEAR(mid_reg_uses);
01883 } else {
01884
01885 mid_gtn_defs = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
01886 mid_gtn_uses = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
01887
01888 mid_tn_defs = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
01889 mid_tn_uses = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
01890
01891 GTN_SET_ClearD (mid_gtn_defs);
01892 GTN_SET_ClearD (mid_gtn_uses);
01893 }
01894
01895
01896 FOR_ALL_BB_SET_members (*pred_bbs, cur_bb) {
01897
01898 if (CG_Skip_GCM && BB_id(cur_bb) == GCM_To_BB)
01899 return FALSE;
01900
01901 BBLIST *succ_list;
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912 if (cur_bb != src_bb || ( Motion_Is_CIRC_ABOVE(motion_type) &&
01913 cur_bb==src_bb) ) {
01914 for (INT i = 0; i < OP_results(cur_op); ++i) {
01915 TN *result = OP_result(cur_op,i);
01916 if (CG_Skip_GCM && TN_number(result) == GCM_Result_TN)
01917 return FALSE;
01918 FOR_ALL_BB_SUCCS(cur_bb, succ_list) {
01919 BB *succ_bb = BBLIST_item(succ_list);
01920 if (!BB_SET_MemberP(*pred_bbs, succ_bb)) {
01921 if (Ignore_TN_Dep) {
01922 ISA_REGISTER_CLASS result_cl = TN_register_class (result);
01923 REGISTER result_reg = TN_register (result);
01924 if (REG_LIVE_Into_BB (result_cl, result_reg, succ_bb) ||
01925
01926
01927
01928
01929
01930
01931
01932
01933 (TN_is_global_reg(result) &&
01934 GTN_SET_MemberP(BB_live_in(succ_bb), result)))
01935 return FALSE;
01936 } else {
01937 if (TN_is_global_reg(result) &&
01938 (GTN_SET_MemberP(BB_live_in(succ_bb), result) ||
01939 GTN_SET_MemberP(BB_live_def(succ_bb), result)))
01940 return FALSE;
01941 }
01942 }
01943 }
01944 }
01945 }
01946
01947 mUINT32 cur_spec_type;
01948
01949 if ( OP_memory(cur_op) &&
01950 !Can_Mem_Op_Be_Moved(cur_op, cur_bb, src_bb, tgt_bb,
01951 motion_type, &cur_spec_type))
01952 return FALSE;
01953
01954 #if 0
01955
01956
01957
01958
01959
01960
01961
01962
01963 if (OP_memory(cur_op) &&
01964 Null_Ptr_Deref_Spec(cur_op, src_bb, cur_bb)) {
01965 if (!(GCM_Pointer_Spec && GCM_Eager_Null_Ptr_Deref)) {
01966 return FALSE;
01967 } else {
01968 Set_EAGER_NULL_PTR_SPEC(cur_spec_type);
01969 Use_Page_Zero = TRUE;
01970 }
01971 }
01972
01973 *spec_type |= cur_spec_type;
01974
01975
01976
01977
01978
01979 if ( can_spec ||
01980 (*spec_type & SPEC_EAGER_NULL_PTR) ||
01981 (*spec_type & SPEC_EAGER_PTR) ||
01982 (*spec_type & SPEC_CIRC_PTR_ABOVE) )
01983 return FALSE;
01984 #endif
01985
01986 Use_Page_Zero = TRUE;
01987 #else // TARG_SL
01988 if (!CGTARG_Can_Be_Speculative (cur_op)) {
01989
01990 if (!OP_load(cur_op)) return FALSE;
01991 else {
01992 can_spec = FALSE;
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008 if (PROC_has_delayed_exception()) {
02009 if (GCM_Pointer_Spec && GCM_Predicated_Loads &&
02010 Can_Do_Safe_Predicate_Movement(cur_op, src_bb, tgt_bb, motion_type)) {
02011 safe_spec = TRUE;
02012 Set_PSAFE_PTR_SPEC(*spec_type);
02013 }
02014 }
02015
02016
02017
02018
02019
02020 if (GCM_Pointer_Spec) {
02021 if (GCM_Eager_Ptr_Deref &&
02022 Eager_Ptr_Deref_Spec(cur_op, tgt_bb, TRUE)) {
02023 safe_spec = TRUE;
02024 Set_EAGER_PTR_SPEC(*spec_type);
02025 }
02026 #ifndef TARG_MIPS
02027 else if (GCM_Speculative_Loads && Is_Target_Itanium() &&
02028 OP_load(cur_op)) {
02029 safe_spec = TRUE;
02030 Set_CSAFE_PTR_SPEC(*spec_type);
02031 }
02032 #endif
02033 }
02034
02035
02036 if (!PROC_has_delayed_exception() &&
02037 Null_Ptr_Deref_Spec(cur_op, src_bb, tgt_bb)) {
02038 if (!(GCM_Pointer_Spec && GCM_Eager_Null_Ptr_Deref)) {
02039 return FALSE;
02040 } else {
02041 Set_EAGER_NULL_PTR_SPEC(*spec_type);
02042 safe_spec = TRUE;
02043 }
02044 }
02045 }
02046 }
02047 }
02048
02049
02050
02051 #ifdef TARG_X8664
02052 BOOL op_access_mem = OP_memory(cur_op) || OP_load_exe(cur_op);
02053
02054
02055
02056
02057 if( !op_access_mem &&
02058 OP_code(cur_op) == TOP_asm ){
02059 ASM_OP_ANNOT* asm_info = (ASM_OP_ANNOT*)OP_MAP_Get(OP_Asm_Map, cur_op);
02060 for( int i = 0; i < OP_results(cur_op); i++ ){
02061 if( ASM_OP_result_memory(asm_info)[i] )
02062 op_access_mem = TRUE;
02063 }
02064
02065 for( int i = 0; i < OP_opnds(cur_op); i++ ){
02066 if( ASM_OP_opnd_memory(asm_info)[i] )
02067 op_access_mem = TRUE;
02068 }
02069 }
02070
02071 if (op_access_mem && (can_spec || safe_spec)) {
02072 #else
02073 if (OP_memory(cur_op) && (can_spec || safe_spec)) {
02074 #endif // TARG_X8664
02075
02076 FOR_ALL_BB_SET_members (*pred_bbs, cur_bb) {
02077
02078 if (CG_Skip_GCM && BB_id(cur_bb) == GCM_To_BB)
02079 return FALSE;
02080
02081
02082 if (!Can_Mem_Op_Be_Moved(cur_op, cur_bb, src_bb, tgt_bb, motion_type))
02083 return FALSE;
02084
02085
02086
02087
02088 BOOL equiv_fwd = BS_MemberP (BB_pdom_set(tgt_bb), BB_id(cur_bb)) &&
02089 BS_MemberP (BB_dom_set(cur_bb), BB_id(tgt_bb));
02090 if (equiv_fwd && Null_Ptr_Deref_Spec(cur_op, src_bb, cur_bb)) {
02091 if (!(GCM_Pointer_Spec && GCM_Eager_Null_Ptr_Deref)) {
02092 return FALSE;
02093 } else {
02094 Set_EAGER_NULL_PTR_SPEC(*spec_type);
02095 Use_Page_Zero = TRUE;
02096 }
02097 }
02098 }
02099 }
02100
02101
02102
02103
02104
02105 if (!can_spec &&
02106 !(*spec_type & SPEC_EAGER_NULL_PTR) &&
02107 !(*spec_type & SPEC_EAGER_PTR) &&
02108 !(*spec_type & SPEC_CIRC_PTR_ABOVE) &&
02109 !(*spec_type & SPEC_CSAFE_PTR) &&
02110 !(*spec_type & SPEC_DSAFE_PTR) &&
02111 !(*spec_type & SPEC_CDSAFE_PTR) &&
02112 !(*spec_type & SPEC_PSAFE_PTR))
02113 return FALSE;
02114
02115 if (*spec_type & SPEC_EAGER_NULL_PTR) Use_Page_Zero = TRUE;
02116
02117 if (Ignore_TN_Dep) {
02118 REGSET_CLEAR(mid_reg_defs);
02119 REGSET_CLEAR(mid_reg_uses);
02120 } else {
02121
02122 mid_gtn_defs = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
02123 mid_gtn_uses = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
02124
02125 mid_tn_defs = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
02126 mid_tn_uses = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
02127
02128 GTN_SET_ClearD (mid_gtn_defs);
02129 GTN_SET_ClearD (mid_gtn_uses);
02130 }
02131
02132
02133 FOR_ALL_BB_SET_members (*pred_bbs, cur_bb) {
02134
02135 if (CG_Skip_GCM && BB_id(cur_bb) == GCM_To_BB)
02136 return FALSE;
02137
02138 BBLIST *succ_list;
02139
02140
02141
02142
02143
02144 if (cur_bb != src_bb) {
02145 for (INT i = 0; i < OP_results(cur_op); ++i) {
02146 TN *result = OP_result(cur_op,i);
02147 if (CG_Skip_GCM && TN_number(result) == GCM_Result_TN)
02148 return FALSE;
02149 FOR_ALL_BB_SUCCS(cur_bb, succ_list) {
02150 BB *succ_bb = BBLIST_item(succ_list);
02151 if (!BB_SET_MemberP(*pred_bbs, succ_bb)) {
02152 if (Ignore_TN_Dep) {
02153 ISA_REGISTER_CLASS result_cl = TN_register_class (result);
02154 REGISTER result_reg = TN_register (result);
02155 if (REG_LIVE_Into_BB (result_cl, result_reg, succ_bb) ||
02156
02157
02158
02159
02160
02161
02162
02163
02164 (TN_is_global_reg(result) &&
02165 GTN_SET_MemberP(BB_live_in(succ_bb), result))
02166
02167 #ifdef KEY
02168
02169
02170 || (result_reg != REGISTER_UNDEFINED &&
02171 GTN_SET_MemberP(BB_live_in(succ_bb),
02172 Build_Dedicated_TN(result_cl,
02173 result_reg, 0)))
02174 #endif
02175 )
02176 return FALSE;
02177 } else {
02178 if (TN_is_global_reg(result) &&
02179 (GTN_SET_MemberP(BB_live_in(succ_bb), result) ||
02180 GTN_SET_MemberP(BB_live_def(succ_bb), result)))
02181 return FALSE;
02182 }
02183 }
02184 }
02185 }
02186 }
02187 #endif // TARG_SL
02188
02189 OP *limit_op;
02190 limit_op = Find_Limit_OP(cur_op, cur_bb, src_bb, tgt_bb);
02191
02192
02193 OP *op;
02194 BOOL forw = motion_type & (GCM_EQUIV_FWD | GCM_SPEC_ABOVE |
02195 GCM_DUP_ABOVE | GCM_CIRC_ABOVE);
02196 for (op = ((forw && cur_bb != src_bb) || (!forw && cur_bb == src_bb)) ?
02197 BB_last_op(cur_bb) : BB_first_op(cur_bb);
02198 op && op != limit_op;
02199 op = ((forw && cur_bb != src_bb) || (!forw && cur_bb == src_bb)) ?
02200 OP_prev(op) : OP_next(op)) {
02201
02202 if (OP_dummy(op)) {
02203 if (!CGTARG_Is_OP_Barrier(op)) continue;
02204 else if (OP_memory(cur_op)) return FALSE;
02205 }
02206
02207
02208 if (op == cur_op) continue;
02209
02210
02211 if (OP_call(op) &&
02212 !CG_DEP_Can_OP_Move_Across_Call(cur_op, op, forw, Ignore_TN_Dep))
02213 return FALSE;
02214
02215
02216 INT i;
02217 for (i = 0; i < OP_results(op); ++i) {
02218 TN *result_tn = OP_result(op,i);
02219 if (Ignore_TN_Dep) {
02220 REGISTER result_reg = TN_register (result_tn);
02221 ISA_REGISTER_CLASS cl = TN_register_class (result_tn);
02222 mid_reg_defs[cl] = REGISTER_SET_Union1(mid_reg_defs[cl],result_reg);
02223 } else {
02224 if (TN_is_global_reg(result_tn)) {
02225 mid_gtn_defs = GTN_SET_Union1D(mid_gtn_defs, result_tn,
02226 &MEM_local_pool);
02227 } else if (cur_bb == src_bb || TN_is_dedicated(result_tn)) {
02228 mid_tn_defs = TN_SET_Union1D(mid_tn_defs, result_tn,
02229 &MEM_local_pool);
02230 }
02231 }
02232 }
02233
02234 #ifdef KEY
02235
02236 ASM_OP_ANNOT *asm_info = (OP_code(op) == TOP_asm) ?
02237 (ASM_OP_ANNOT *) OP_MAP_Get(OP_Asm_Map, op) : NULL;
02238 if (asm_info) {
02239 ISA_REGISTER_CLASS cl;
02240 FOR_ALL_ISA_REGISTER_CLASS(cl) {
02241 REGISTER_SET clobbers = ASM_OP_clobber_set(asm_info)[cl];
02242 if (Ignore_TN_Dep) {
02243 mid_reg_defs[cl] = REGISTER_SET_Union(mid_reg_defs[cl], clobbers);
02244 } else {
02245 REGISTER reg;
02246 FOR_ALL_REGISTER_SET_members(clobbers, reg) {
02247 TN *ded_tn = Build_Dedicated_TN(cl, reg, 0);
02248 mid_gtn_defs = GTN_SET_Union1D(mid_gtn_defs, ded_tn,
02249 &MEM_local_pool);
02250 }
02251 }
02252 }
02253 }
02254 #endif
02255
02256
02257 for (i = 0; i < OP_opnds(op); ++i) {
02258 TN *opnd_tn = OP_opnd(op,i);
02259 if (TN_is_constant(opnd_tn)) continue;
02260 if (Ignore_TN_Dep) {
02261 REGISTER opnd_reg = TN_register (opnd_tn);
02262 ISA_REGISTER_CLASS cl = TN_register_class (opnd_tn);
02263 mid_reg_uses[cl] = REGISTER_SET_Union1(mid_reg_uses[cl], opnd_reg);
02264
02265
02266
02267
02268
02269
02270 if( Motion_Is_CIRC_ABOVE(motion_type) && OP_br(op) )
02271 mid_reg_defs[cl] = REGISTER_SET_Union1(mid_reg_defs[cl], opnd_reg);
02272 }else{
02273 if(TN_is_global_reg(opnd_tn)) {
02274 mid_gtn_uses = GTN_SET_Union1D(mid_gtn_uses, opnd_tn,
02275 &MEM_local_pool);
02276 }else if(cur_bb == src_bb || TN_is_dedicated(opnd_tn)) {
02277 mid_tn_uses = TN_SET_Union1D(mid_tn_uses, opnd_tn,
02278 &MEM_local_pool);
02279 }
02280 }
02281 }
02282 }
02283 }
02284
02285
02286
02287
02288
02289
02290
02291
02292 BOOL can_move = (src_bb == tgt_bb && Motion_Is_CIRC_ABOVE(motion_type) ) ||
02293
02294
02295 ((Ignore_TN_Dep && !REGSET_INTERSECT((REGSET)defs[0], mid_reg_defs) &&
02296 !REGSET_INTERSECT((REGSET)defs[0], mid_reg_uses) &&
02297 !REGSET_INTERSECT((REGSET)uses[0], mid_reg_defs)) ||
02298
02299
02300 (!Ignore_TN_Dep &&
02301 (!GTN_SET_IntersectsP((GTN_SET *)defs[0], mid_gtn_defs) &&
02302 !GTN_SET_IntersectsP((GTN_SET *)defs[0], mid_gtn_uses) &&
02303 !GTN_SET_IntersectsP((GTN_SET *)uses[0], mid_gtn_defs)) &&
02304
02305 (!TN_SET_IntersectsP((TN_SET *)defs[1], mid_tn_defs) &&
02306 !TN_SET_IntersectsP((TN_SET *)defs[1], mid_tn_uses) &&
02307 !TN_SET_IntersectsP((TN_SET *)uses[1], mid_tn_defs))));
02308
02309 return can_move;
02310 }
02311
02312
02313
02314
02315
02316
02317
02318 static BOOL
02319 GTN_Live_Out_From_BB(BB *cand_bb, TN *use_tn)
02320 {
02321 BBLIST *succ_list;
02322 FOR_ALL_BB_SUCCS(cand_bb, succ_list) {
02323 BB *cur_bb = BBLIST_item(succ_list);
02324 if (TN_is_global_reg(use_tn) &&
02325 GTN_SET_MemberP(BB_live_in(cur_bb), use_tn))
02326 return TRUE;
02327 }
02328
02329 return FALSE;
02330 }
02331
02332
02333
02334
02335
02336
02337
02338 static void
02339 Update_Live_In_Sets(TN *use_tn, BB *src_bb, BB *tgt_bb, BB_SET **pred_bbs)
02340 {
02341
02342 BB *cur_bb;
02343
02344
02345
02346
02347 BOOL tn_use = FALSE;
02348 FOR_ALL_BB_SET_members (*pred_bbs, cur_bb) {
02349
02350 if (cur_bb == src_bb) continue;
02351
02352 BBLIST *succ_list;
02353 FOR_ALL_BB_SUCCS(cur_bb, succ_list) {
02354 BB *succ_bb = BBLIST_item(succ_list);
02355 if ((
02356 GTN_SET_MemberP(BB_live_use(cur_bb), use_tn)) ||
02357 (!BB_SET_MemberP(*pred_bbs, succ_bb) &&
02358 (GTN_SET_MemberP(BB_live_in(succ_bb), use_tn) ||
02359 GTN_SET_MemberP(BB_live_def(succ_bb), use_tn)))) {
02360 tn_use = TRUE;
02361 break;
02362 }
02363 }
02364 }
02365
02366 if (!tn_use) {
02367 FOR_ALL_BB_SET_members(*pred_bbs, cur_bb) {
02368 if (cur_bb == src_bb || cur_bb == tgt_bb) continue;
02369
02370
02371
02372 GRA_LIVE_Remove_Live_In_GTN(cur_bb, use_tn);
02373 GRA_LIVE_Remove_Live_Out_GTN(cur_bb, use_tn);
02374 }
02375 }
02376 }
02377
02378
02379
02380
02381
02382
02383 static void
02384 Update_Live_Use_Counts(BB *cur_bb, OP *cur_op, hTN_MAP *usage_map)
02385 {
02386 UINT32 count, *counter, *tn_count;
02387
02388 for (INT i = 0; i < OP_opnds(cur_op); ++i) {
02389 TN *opnd_tn = OP_opnd(cur_op, i);
02390 if (TN_is_constant(opnd_tn)) continue;
02391
02392 BOOL use_opnd = FALSE;
02393
02394
02395
02396 if (TN_is_global_reg(opnd_tn) &&
02397 (GTN_SET_MemberP(BB_live_use(cur_bb), opnd_tn) ||
02398 GTN_SET_MemberP(BB_live_def(cur_bb), opnd_tn))) {
02399 use_opnd = TRUE;
02400 }
02401
02402 BBLIST *succ_list;
02403 FOR_ALL_BB_SUCCS(cur_bb, succ_list) {
02404 BB *succ_bb = BBLIST_item(succ_list);
02405 if (TN_is_global_reg(opnd_tn) &&
02406 GTN_SET_MemberP(BB_live_in(succ_bb), opnd_tn))
02407 use_opnd = TRUE;
02408 }
02409
02410
02411
02412 if (use_opnd) {
02413 tn_count = (UINT32 *) hTN_MAP_Get (*usage_map, opnd_tn);
02414
02415 count = (tn_count) ? *tn_count : 0;
02416 counter = (tn_count) ? tn_count : (UINT32 *) malloc(sizeof(UINT32));
02417 *counter = ++count;
02418
02419 hTN_MAP_Set (*usage_map, opnd_tn, counter);
02420 }
02421 }
02422 }
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432 static void
02433 Update_GRA_Live_Sets(OP *cand_op, BB *bb, BB *cand_bb, BB_SET **pred_bbs
02434 #if defined(TARG_SL)
02435 , mINT32 motion_type
02436 #endif
02437 )
02438 {
02439
02440
02441 INT i;
02442 BB *cur_bb;
02443 BOOL re_def = FALSE;
02444 hTN_MAP usage_map;
02445 UINT32 count, *counter, *tn_count;
02446
02447 MEM_POOL_Push(&MEM_local_pool);
02448 usage_map = hTN_MAP_Create (&MEM_local_pool);
02449
02450
02451
02452
02453
02454 OP *succ_op;
02455 FOR_ALL_BB_OPs_FWD(bb, succ_op) {
02456 if (OP_dummy(succ_op)) continue;
02457 TN *result_tn = NULL;
02458 for (i = 0; i < OP_results(succ_op); ++i) {
02459 result_tn = OP_result(succ_op,i);
02460 tn_count = (UINT32 *) hTN_MAP_Get (usage_map, result_tn);
02461
02462 count = (tn_count) ? *tn_count : 0;
02463 counter = (tn_count) ? tn_count : (UINT32 *) alloca(sizeof(UINT32));
02464 *counter = ++count;
02465
02466 hTN_MAP_Set (usage_map, result_tn, counter);
02467 }
02468
02469 for (i = 0; i < OP_opnds(succ_op); ++i) {
02470 TN *opnd_tn = OP_opnd(succ_op, i);
02471 if (TN_is_constant(opnd_tn)) continue;
02472
02473
02474
02475 if (TN_is_global_reg(opnd_tn)) {
02476 tn_count = (UINT32 *) hTN_MAP_Get (usage_map, opnd_tn);
02477
02478 count = (tn_count) ? *tn_count : 0;
02479 counter = (tn_count) ? tn_count : (UINT32 *) alloca(sizeof(UINT32));
02480 *counter = ++count;
02481
02482 hTN_MAP_Set (usage_map, opnd_tn, counter);
02483 }
02484 }
02485 }
02486
02487
02488
02489
02490
02491 for (i = 0; i < OP_results(cand_op); ++i) {
02492 BOOL use_before_def = FALSE;
02493
02494 TN *result = OP_result(cand_op, i);
02495 FOR_ALL_BB_OPs_FWD(bb, succ_op) {
02496 if (OP_dummy(succ_op)) continue;
02497 TN *result_tn = NULL;
02498 INT j;
02499
02500 for (j = 0; j < OP_opnds(succ_op); ++j) {
02501 TN *opnd_tn = OP_opnd(succ_op, j);
02502 if (TN_is_constant(opnd_tn)) continue;
02503
02504
02505 if (!re_def && result &&
02506 (TN_number(result) == TN_number(opnd_tn))) {
02507 use_before_def = TRUE;
02508 GTN_UNIVERSE_Add_TN(opnd_tn);
02509
02510
02511 GRA_LIVE_Add_Live_Use_GTN(bb, opnd_tn);
02512 GRA_LIVE_Add_Live_In_GTN(bb, opnd_tn);
02513 }
02514 }
02515
02516 for (j = 0; j < OP_results(succ_op); ++j) {
02517 result_tn = OP_result(succ_op, j);
02518
02519
02520
02521 if( result_tn && result &&
02522 TN_number(result) == TN_number(result_tn)
02523 #if defined(TARG_SL)
02524 && !OP_cond_def(succ_op)
02525 #endif
02526 )
02527 re_def = TRUE;
02528 }
02529 }
02530
02531
02532
02533
02534 if (result) {
02535 if( TN_is_global_reg(result) ) {
02536 #if defined(TARG_SL)
02537 if( use_before_def || !re_def )
02538 GRA_LIVE_Remove_Live_Def_GTN(bb, result);
02539 else
02540 DevWarn("Doubly defined, without usage");
02541 #else
02542 GRA_LIVE_Remove_Live_Def_GTN(bb, result);
02543 #endif
02544 }
02545 GTN_UNIVERSE_Add_TN(result);
02546 GRA_LIVE_Add_Live_Def_GTN(cand_bb, result);
02547 }
02548
02549
02550
02551
02552
02553 FOR_ALL_BB_SET_members (*pred_bbs, cur_bb) {
02554 if( ( cand_bb!=cur_bb
02555 #if defined(TARG_SL)
02556 || Motion_Is_CIRC_ABOVE(motion_type)
02557 #endif
02558 ) && result ) {
02559 GRA_LIVE_Add_Live_In_GTN(cur_bb, result);
02560 GRA_LIVE_Add_Defreach_In_GTN(cur_bb, result);
02561 }
02562
02563
02564
02565 if (cur_bb != bb && cur_bb != cand_bb)
02566 Update_Live_Use_Counts(cur_bb, cand_op, &usage_map);
02567
02568 tn_count = result ? (UINT32 *) hTN_MAP_Get (usage_map, result) : NULL;
02569 count = (tn_count) ? *tn_count : 0;
02570
02571
02572
02573 if( result && ( cur_bb != bb || count != 0
02574 #if defined(TARG_SL)
02575 || Motion_Is_CIRC_ABOVE(motion_type)
02576 #endif
02577 ) ) {
02578 GRA_LIVE_Add_Live_Out_GTN(cur_bb, result);
02579 GRA_LIVE_Add_Defreach_Out_GTN(cur_bb, result);
02580 }
02581 }
02582 }
02583
02584
02585
02586
02587
02588 for (i = 0; i < OP_opnds(cand_op); ++i) {
02589 TN *opnd_tn = OP_opnd(cand_op, i);
02590 if (TN_is_constant(opnd_tn)) continue;
02591
02592 BOOL single_use = FALSE;
02593
02594 if (TN_is_global_reg(opnd_tn)) {
02595
02596
02597 if (!GTN_SET_MemberP(BB_live_in(cand_bb), opnd_tn)) {
02598 single_use = TRUE;
02599 }
02600
02601 GRA_LIVE_Add_Live_Use_GTN(cand_bb, opnd_tn);
02602
02603 if (!GTN_SET_MemberP(BB_live_def(cand_bb), opnd_tn))
02604 GRA_LIVE_Add_Defreach_In_GTN(cand_bb, opnd_tn);
02605
02606 tn_count = (UINT32 *) hTN_MAP_Get (usage_map, opnd_tn);
02607 count = (tn_count) ? *tn_count : 0;
02608
02609 if (count == 0) {
02610
02611
02612
02613 GRA_LIVE_Remove_Live_Use_GTN(bb, opnd_tn);
02614
02615 if (!GTN_SET_MemberP(BB_live_out(bb), opnd_tn))
02616 GRA_LIVE_Remove_Live_In_GTN(bb, opnd_tn);
02617 Update_Live_In_Sets(opnd_tn, bb, cand_bb, pred_bbs);
02618
02619
02620
02621
02622 if (GTN_SET_MemberP(BB_live_def(cand_bb), opnd_tn) &&
02623 !GTN_Live_Out_From_BB(cand_bb, opnd_tn)) {
02624 UINT32 *opndtn_count = (UINT32 *) hTN_MAP_Get (usage_map, opnd_tn);
02625 UINT32 opnd_count = (opndtn_count) ? *opndtn_count : 0;
02626 if (opnd_count == 0 && single_use) {
02627 GRA_LIVE_Remove_Live_Use_GTN(cand_bb, opnd_tn);
02628 GRA_LIVE_Remove_Defreach_Out_GTN(cand_bb, opnd_tn);
02629 GRA_LIVE_Remove_Live_Out_GTN(cand_bb, opnd_tn);
02630 }
02631 }
02632 }
02633 }
02634 }
02635
02636 MEM_POOL_Pop(&MEM_local_pool);
02637 }
02638
02639
02640
02641
02642
02643
02644
02645
02646 static BOOL
02647 Is_OP_Move_Better(OP *cur_op, OP *best_op, mINT32 motion_type)
02648 {
02649
02650
02651
02652
02653 switch (motion_type) {
02654
02655 case GCM_EQUIV_FWD:
02656 case GCM_EQUIV:
02657 case GCM_SPEC_ABOVE:
02658 case GCM_CIRC_ABOVE:
02659
02660 if (OP_scycle(cur_op) < OP_scycle(best_op)) return TRUE;
02661 if (OP_scycle(cur_op) >= OP_scycle(best_op)) return FALSE;
02662 break;
02663 case GCM_EQUIV_BKWD:
02664 case GCM_SPEC_BELOW:
02665
02666 if (OP_scycle(cur_op) > OP_scycle(best_op)) return TRUE;
02667 if (OP_scycle(cur_op) <= OP_scycle(best_op)) return FALSE;
02668 break;
02669 case GCM_DUP_ABOVE:
02670 case GCM_DUP_BELOW:
02671 break;
02672 default:
02673 FmtAssert(FALSE, ("unexpected code motion type in GCM phase"));
02674 }
02675 return FALSE;
02676 }
02677
02678 #if defined(TARG_SL)
02679 static BOOL
02680 Enough_Circ_Loop_Trip_Count (LOOP_DESCR* l) {
02681
02682 LOOPINFO* li LOOP_DESCR_loopinfo(l);
02683
02684 TN* trip_count = NULL;
02685 if (li) {
02686 trip_count = LOOPINFO_trip_count_tn(li);
02687 }
02688
02689 if (trip_count && TN_is_constant(trip_count) &&
02690 TN_has_value(trip_count)) {
02691 if(TN_value(trip_count)<circ_above_tc_limit)
02692 return FALSE;
02693 }
02694
02695 return TRUE;
02696 }
02697 #endif
02698
02699
02700
02701
02702
02703
02704
02705 static mINT32
02706 Determine_Motion_Type(LOOP_DESCR *loop, BB *bb, BBSCH *bbsch)
02707 {
02708 mINT32 motion_type;
02709
02710
02711 if (GCM_Forw_Circ_Motion && !BB_CIRC_ABOVE(bbsch) &&
02712
02714
02715
02716 #if !defined(TARG_SL)
02717 Ignore_TN_Dep &&
02718 #endif
02719
02720 (LOOP_DESCR_loophead(loop) == bb) && !BB_unrolled_fully(bb) &&
02721
02722 #if defined(TARG_SL)
02723
02724 Enough_Circ_Loop_Trip_Count(loop) &&
02725 #endif
02726
02727
02728 LOOP_DESCR_Can_Retarget_Loop_Entrances(loop) &&
02729
02730
02731
02732
02733 !BB_MEM_BARRIER(bbsch) && (BB_rid(bb) == NULL)) {
02734 motion_type = GCM_CIRC_ABOVE;
02735 Set_BB_CIRC_ABOVE(bbsch);
02736 }
02737
02738
02739 else if (!BB_EQUIV_FWD(bbsch) ) {
02740 motion_type = GCM_EQUIV_FWD;
02741 Set_BB_EQUIV_FWD(bbsch);
02742 }
02743
02744 #if !defined(TARG_SL)
02745
02746 else if (!BB_SPEC_ABOVE(bbsch) ) {
02747 motion_type = GCM_SPEC_ABOVE;
02748 Set_BB_SPEC_ABOVE(bbsch);
02749 }
02750 #endif
02751
02752 else
02753 motion_type = GCM_NONE;
02754
02755 return motion_type;
02756 }
02757
02758
02759
02760
02761
02762
02763
02764 static void
02765 Determine_Candidate_Blocks(BB *bb, LOOP_DESCR *loop, mINT32 motion_type,
02766 VECTOR *priority_vector, VECTOR *cand_bbvector)
02767 {
02768 BB *cand_bb;
02769 for (INT i = 0; i < VECTOR_count(*priority_vector); i++) {
02770 cand_bb = (BB *)VECTOR_element(*priority_vector, i);
02771
02772 if (cand_bb == bb) continue;
02773
02774 #ifdef TARG_X8664
02775
02776 if (Avoid_GOT_BB(cand_bb))
02777 continue;
02778 #endif
02779
02780 if (BB_scheduled(cand_bb) && !BB_scheduled_hbs(cand_bb)) continue;
02781
02782
02783
02784 if (Is_BB_Empty(cand_bb)) continue;
02785
02786
02787 BOOL equiv_bkwd = BS_MemberP (BB_pdom_set(bb), BB_id(cand_bb)) &&
02788 BS_MemberP (BB_dom_set(cand_bb), BB_id(bb));
02789 BOOL equiv_fwd = BS_MemberP (BB_pdom_set(cand_bb), BB_id(bb)) &&
02790 BS_MemberP (BB_dom_set(bb), BB_id(cand_bb));
02791
02792 #ifdef KEY
02793
02794
02795
02796
02797
02798
02799 equiv_fwd = equiv_fwd && BB_Has_One_Succ( cand_bb );
02800 #endif
02801
02802 BOOL equiv = equiv_fwd && equiv_bkwd;
02803
02804
02805
02806 if ((BB_freq(cand_bb) * (CG_PU_Has_Feedback ?
02807 speculation_ratio_fb : speculation_ratio_wfb))
02808 > BB_freq(bb)) {
02809
02810
02811 if (!CG_PU_Has_Feedback && !equiv) {
02812
02813
02814
02815
02816
02817
02818
02819 if ((BB_branch_op(bb) != NULL) &&
02820 (BB_Unique_Predecessor(bb) == cand_bb) &&
02821 (BB_length(bb) < 4)) goto profitable_candidate;
02822 else continue;
02823 } else if (!GCM_Test) continue;
02824 }
02825
02826 profitable_candidate:
02827
02828
02829
02830 BOOL multiple_loop = (BB_loop_head_bb(cand_bb) &&
02831 BB_in_succs(bb, cand_bb) &&
02832 (BB_preds_len(cand_bb) > 2));
02833
02834
02835
02836 BOOL cond = FALSE;
02837
02838 switch (motion_type) {
02839
02840 case GCM_EQUIV_FWD:
02841 cond = equiv_fwd && !multiple_loop;
02842 break;
02843
02844 case GCM_EQUIV_BKWD:
02845 cond = equiv_bkwd;
02846 break;
02847
02848 case GCM_EQUIV:
02849 cond = equiv;
02850 break;
02851
02852
02853 case GCM_SPEC_ABOVE:
02854 if (!multiple_loop &&
02855 BS_MemberP (BB_dom_set(bb), BB_id(cand_bb)) &&
02856 !BS_MemberP (BB_pdom_set(cand_bb), BB_id(bb)))
02857 cond = TRUE;
02858 break;
02859
02860 case GCM_CIRC_ABOVE:
02861 break;
02862
02863 case GCM_SPEC_BELOW:
02864 case GCM_DUP_ABOVE:
02865 case GCM_DUP_BELOW:
02866
02867 default:
02868 FmtAssert(FALSE, ("unexpected code motion type in GCM phase"));
02869 }
02870
02871 if (cond) {
02872 VECTOR_Add_Element(*cand_bbvector, (void *)cand_bb);
02873 }
02874 }
02875
02876
02877
02878 if( Motion_Is_CIRC_ABOVE(motion_type) ){
02879 if ((LOOP_DESCR_nestlevel(loop) > 0) &&
02880 (cand_bb = LOOP_DESCR_Find_Unique_Tail(loop)))
02881 VECTOR_Add_Element(*cand_bbvector, (void *)cand_bb);
02882 }
02883 }
02884
02885
02886 #if defined(TARG_SL)
02887
02888 static BOOL Append_Op_To_BB(OP *cand_op, BB *cand_bb, BB *src_bb, mINT32 motion_type, mUINT8 spec_type);
02889
02890
02891
02892
02893
02894
02895 BB* Loop_Is_Zdl( LOOP_DESCR *loop )
02896 {
02897 BB *head = LOOP_DESCR_loophead( loop );
02898 BB *prolog = BB_prev( head );
02899 if( !prolog )
02900 return NULL;
02901
02902 while( Is_BB_Empty(prolog) )
02903 prolog = BB_prev(prolog);
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920 OP *loop_op = BB_last_op( prolog );
02921 if( !OP_is_loop(loop_op) ){
02922 BBLIST *preds_list;
02923 prolog = NULL;
02924 FOR_ALL_BB_PREDS( head, preds_list ){
02925 if( BB_loop_op(BBLIST_item(preds_list)) ){
02926 if( prolog )
02927 Is_True( 0, ("multi loop insn meet on a single loop head") );
02928 prolog = BBLIST_item( preds_list );
02929 }
02930 }
02931 }
02932
02933 return prolog;
02934 }
02935
02936
02937
02938
02939
02940
02941 static BOOL Loop_Is_Straight_Line( LOOP_DESCR *loop )
02942 {
02943 BB *temp;
02944 BB_SET *loop_bbs = LOOP_DESCR_bbset(loop);
02945 FOR_ALL_BB_SET_members( loop_bbs, temp ){
02946 if( BB_branch_op(temp) || BB_call(temp) || BB_loop_op(temp) )
02947 return FALSE;
02948
02949 }
02950 return TRUE;
02951 }
02952 #endif // TARG_SL
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966 static void
02967 Perform_Post_GCM_Steps(BB *bb, BB *cand_bb, OP *cand_op, mINT32 motion_type,
02968 mUINT8 spec_type, BB_SET **pred_bbs,
02969 LOOP_DESCR *loop, BOOL success)
02970 {
02971 BBSCH *bbsch = (BBSCH *)BB_MAP_Get (bbsch_map, bb);
02972 BBSCH *cand_bbsch = (BBSCH *)BB_MAP_Get (bbsch_map, cand_bb);
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982 if (success) {
02983 if (motion_type & (GCM_SPEC_ABOVE | GCM_EQUIV_FWD | GCM_CIRC_ABOVE)) {
02984
02985 INT i;
02986 if (Ignore_TN_Dep) {
02987 for (i = 0; i < OP_results(cand_op); ++i) {
02988 TN *result = OP_result(cand_op, i);
02989 BB *cur_bb;
02990
02991
02992 REGISTER result_reg = TN_register(result);
02993 ISA_REGISTER_CLASS result_cl = TN_register_class (result);
02994 FOR_ALL_BB_SET_members (*pred_bbs, cur_bb) {
02995 REG_LIVE_Update(result_cl, result_reg, cur_bb);
02996 }
02997 REG_LIVE_Update(result_cl, result_reg, bb);
02998 }
02999 }
03000
03001
03002
03003
03004
03005 if( Motion_Is_CIRC_ABOVE(motion_type) ) {
03006
03007
03008
03009 if (GCM_Loop_Prolog == NULL) {
03010 #if defined(TARG_SL)
03011
03012
03013
03014 BOOL need_move_loop_op = FALSE;
03015 if( BB_zdl_body(bb) || Loop_Is_Zdl(loop) ){
03016 Is_True( bb == LOOP_DESCR_loophead(loop),
03017 ("the src bb of GCM_CIRC_ABOVEis not loop head") );
03018 BB* zdl_prolog = Loop_Is_Zdl( loop );
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033 if( zdl_prolog )
03034 GCM_Loop_Prolog = zdl_prolog;
03035 }
03036
03037 if( !GCM_Loop_Prolog ){
03038 GCM_Loop_Prolog = CG_LOOP_Gen_And_Prepend_To_Prolog(bb, loop);
03039 }
03040 #else
03041 GCM_Loop_Prolog = CG_LOOP_Gen_And_Prepend_To_Prolog(bb, loop);
03042 #endif // TARG_SL
03043 GRA_LIVE_Compute_Liveness_For_BB(GCM_Loop_Prolog);
03044 #ifdef KEY
03045
03046
03047
03048 if (Ignore_TN_Dep) {
03049 REG_LIVE_Finish();
03050 REG_LIVE_Analyze_Region();
03051 }
03052 #endif
03053 if (Trace_GCM) {
03054 #pragma mips_frequency_hint NEVER
03055 fprintf (TFile, "GCM: Circular Motion:\n");
03056 fprintf (TFile, "GCM: Add New BB:%d before loophead BB:%d\n",
03057 BB_id(GCM_Loop_Prolog), BB_id(bb));
03058 }
03059 } else {
03060 if (Trace_GCM) {
03061 #pragma mips_frequency_hint NEVER
03062 fprintf (TFile, "GCM: Circular Motion:\n");
03063 fprintf (TFile, "GCM: using existing loop prolog BB:%d \n",
03064 BB_id(GCM_Loop_Prolog));
03065 }
03066 }
03067
03068
03069 OP *br_op = BB_branch_op(GCM_Loop_Prolog);
03070 BB *new_bb;
03071 if (br_op) {
03072 new_bb = CG_LOOP_Append_BB_To_Prolog(GCM_Loop_Prolog, bb);
03073 GRA_LIVE_Compute_Liveness_For_BB(new_bb);
03074 Set_BB_dom_set(new_bb, BS_Create_Empty(2+PU_BB_Count+1,
03075 &gcm_loop_pool));
03076 BS_Union1D(BB_dom_set(new_bb), BB_id(new_bb), NULL);
03077 BS_UnionD(BB_dom_set(new_bb), BB_dom_set(bb), &gcm_loop_pool);
03078
03079 Set_BB_pdom_set(new_bb, BS_Create_Empty(2+PU_BB_Count+1,
03080 &gcm_loop_pool));
03081 BS_Union1D(BB_pdom_set(new_bb), BB_id(new_bb), NULL);
03082 BS_UnionD(BB_pdom_set(new_bb), BB_pdom_set(bb), &gcm_loop_pool);
03083 Run_Cflow_GCM = TRUE;
03084 }
03085
03086 OP *dup_op = Dup_OP(cand_op);
03087 #if defined(TARG_SL)
03088
03089 if( OP_has_tag(dup_op) )
03090 Reset_OP_has_tag(dup_op);
03091 Append_Op_To_BB( dup_op, GCM_Loop_Prolog, bb, motion_type, spec_type);
03092 *pred_bbs = BB_SET_Union1D(*pred_bbs,GCM_Loop_Prolog,&MEM_local_pool);
03093 #else
03094 BB_Append_Op(GCM_Loop_Prolog, dup_op);
03095 #endif // TARG_SL
03096
03097 if (PSAFE_PTR_SPEC(spec_type))
03098 Set_OP_opnd(dup_op, OP_PREDICATE_OPND, True_TN);
03099
03100 Set_BB_dom_set(GCM_Loop_Prolog, BS_Create_Empty(2+PU_BB_Count+1,
03101 &gcm_loop_pool));
03102 BS_Union1D(BB_dom_set(GCM_Loop_Prolog), BB_id(GCM_Loop_Prolog),
03103 NULL);
03104 BS_UnionD(BB_dom_set(GCM_Loop_Prolog), BB_dom_set(bb),
03105 &gcm_loop_pool);
03106 BS_Difference1D( BB_dom_set(GCM_Loop_Prolog), BB_id(bb) );
03107
03108 Set_BB_pdom_set(GCM_Loop_Prolog, BS_Create_Empty(2+PU_BB_Count+1,
03109 &gcm_loop_pool));
03110 BS_Union1D(BB_pdom_set(GCM_Loop_Prolog), BB_id(GCM_Loop_Prolog),
03111 NULL);
03112 BS_UnionD(BB_pdom_set(GCM_Loop_Prolog), BB_pdom_set(bb),
03113 &gcm_loop_pool);
03114
03115 if (Trace_GCM) {
03116 #pragma mips_frequency_hint NEVER
03117 Print_Trace_File(cand_op, bb, GCM_Loop_Prolog, TRUE);
03118 }
03119 }
03120
03121
03122 if(!Ignore_TN_Dep)
03123 Update_GRA_Live_Sets(cand_op, bb, cand_bb, pred_bbs
03124 #if defined(TARG_SL)
03125 , motion_type
03126 #endif
03127 );
03128
03129
03130 if (bbsch && cand_bbsch) {
03131 BBSCH_num_real_ops(bbsch)--;
03132 BBSCH_num_real_ops(cand_bbsch)++;
03133 BBSCH_bb_start_pc(bbsch)++;
03134 BB_MAP_Set (bbsch_map, bb, bbsch);
03135 BB_MAP_Set (bbsch_map, cand_bb, cand_bbsch);
03136 }
03137 }
03138 } else {
03139
03140
03141
03142
03143
03144
03145 if (CGTARG_Is_OP_Addr_Incr(cand_op) &&
03146 !TN_is_sp_reg(OP_result(cand_op,0 ))) {
03147 INT64 addiu_const = TN_value (OP_opnd(cand_op,1));
03148 OP *succ_op;
03149 for (succ_op = cand_op;
03150 succ_op != NULL;
03151 succ_op = OP_next(succ_op)) {
03152 if (OP_memory(succ_op)) {
03153
03154
03155 INT offset_opndnum = Memory_OP_Offset_Opndnum (succ_op);
03156 INT base_opndnum = Memory_OP_Base_Opndnum (succ_op);
03157 #ifdef TARG_X8664
03158 FmtAssert( base_opndnum >= 0, ("NYI") );
03159 #endif
03160 if (TN_has_value(OP_opnd(succ_op, offset_opndnum))) {
03161 if ((Ignore_TN_Dep &&
03162 (TN_register(OP_opnd(succ_op, base_opndnum)) ==
03163 TN_register(OP_result(cand_op,0 )))) ||
03164
03165 (!Ignore_TN_Dep &&
03166 (TN_number(OP_opnd(succ_op, base_opndnum)) ==
03167 TN_number(OP_result(cand_op,0 )))))
03168
03169 Fixup_Ldst_Offset (succ_op, addiu_const, +1, HBS_FROM_GCM);
03170 }
03171 }
03172 }
03173 }
03174 if (OP_memory(cand_op)) {
03175 INT offset_opndnum = Memory_OP_Offset_Opndnum (cand_op);
03176 if (TN_has_value(OP_opnd(cand_op, offset_opndnum))) {
03177 INT base_opndnum = Memory_OP_Base_Opndnum (cand_op);
03178 #ifdef TARG_X8664
03179 FmtAssert( base_opndnum >= 0, ("NYI") );
03180 #endif
03181 OP *succ_op;
03182 for (succ_op= OP_next(cand_op);
03183 succ_op != NULL;
03184 succ_op = OP_next(succ_op))
03185 {
03186 if (CGTARG_Is_OP_Addr_Incr(succ_op)) {
03187 if ((Ignore_TN_Dep &&
03188 (TN_register(OP_opnd(cand_op, base_opndnum)) ==
03189 TN_register(OP_result(succ_op,0 )))) ||
03190
03191 (!Ignore_TN_Dep &&
03192 (TN_number(OP_opnd(cand_op, base_opndnum)) ==
03193 TN_number(OP_result(succ_op,0 )))))
03194 {
03195 INT64 addiu_const = TN_value (OP_opnd(succ_op,1));
03196 Fixup_Ldst_Offset (cand_op, addiu_const, -1, HBS_FROM_GCM);
03197 DevWarn ("Memory OP offset adjusted in GCM");
03198 }
03199 }
03200 }
03201 }
03202 }
03203 }
03204 }
03205
03206 static void Add_Fail_TNs(OP* cur_op,
03207 TN_SET **pfailed_tn_uses,
03208 TN_SET **pfailed_tn_defs,
03209 TN_SET **pfailed_gtn_uses,
03210 TN_SET **pfailed_gtn_defs,
03211 REGISTER_SET *failed_reg_uses,
03212 REGISTER_SET *failed_reg_defs)
03213 {
03214 REGISTER_SET reg_defs[ISA_REGISTER_CLASS_MAX+1],
03215 reg_uses[ISA_REGISTER_CLASS_MAX+1];
03216 GTN_SET *gtn_defs, *gtn_uses;
03217 TN_SET *tn_defs, *tn_uses;
03218
03219 if (Ignore_TN_Dep) {
03220 REGSET_CLEAR (failed_reg_defs);
03221 REGSET_CLEAR (failed_reg_uses);
03222 } else {
03223 tn_defs = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
03224 tn_uses = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
03225 gtn_defs = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
03226 gtn_uses = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
03227 }
03228
03229
03230 INT i;
03231 for (i = 0; i < OP_results(cur_op); ++i) {
03232 TN *result_tn = OP_result(cur_op,i);
03233 if (Ignore_TN_Dep) {
03234 REGISTER result_reg = TN_register (result_tn);
03235 ISA_REGISTER_CLASS result_cl = TN_register_class (result_tn);
03236 reg_defs[result_cl] = REGISTER_SET_Union1(reg_defs[result_cl], result_reg);
03237 }else{
03238 if(TN_is_global_reg(result_tn))
03239 gtn_defs = GTN_SET_Union1D(gtn_defs, result_tn, &MEM_local_pool);
03240 else
03241 tn_defs = TN_SET_Union1D(tn_defs, result_tn, &MEM_local_pool);
03242 }
03243 }
03244
03245
03246 #ifdef TARG_SL
03247 TN_LIST * extra_results = cur_op->extra_result;
03248 while( extra_results ) {
03249 TN *result_tn = TN_LIST_first( extra_results );
03250 if( Ignore_TN_Dep ){
03251 REGISTER result_reg = TN_register (result_tn);
03252 ISA_REGISTER_CLASS result_cl = TN_register_class (result_tn);
03253 reg_defs[result_cl] = REGISTER_SET_Union1(reg_defs[result_cl],
03254 result_reg);
03255 }else{
03256 if (TN_is_global_reg(result_tn))
03257 gtn_defs = GTN_SET_Union1D(gtn_defs, result_tn, &MEM_local_pool);
03258 else
03259 tn_defs = TN_SET_Union1D(tn_defs, result_tn, &MEM_local_pool);
03260 }
03261 extra_results = TN_LIST_rest( extra_results );
03262 }
03263 #endif
03264
03265 for (i = 0; i < OP_opnds(cur_op); ++i) {
03266 TN *opnd_tn = OP_opnd(cur_op,i);
03267 if (TN_is_constant(opnd_tn)) continue;
03268 if (Ignore_TN_Dep) {
03269 REGISTER opnd_reg = TN_register (opnd_tn);
03270 ISA_REGISTER_CLASS opnd_cl = TN_register_class (opnd_tn);
03271 reg_uses[opnd_cl] = REGISTER_SET_Union1(reg_uses[opnd_cl], opnd_reg);
03272 }else{
03273 if(TN_is_global_reg(opnd_tn))
03274 gtn_uses = GTN_SET_Union1D(gtn_uses, opnd_tn, &MEM_local_pool);
03275 else
03276 tn_uses = TN_SET_Union1D(tn_uses, opnd_tn, &MEM_local_pool);
03277 }
03278 }
03279
03280
03281 #ifdef TARG_SL
03282 TN_LIST * extra_opnds = cur_op->extra_operand;
03283 while( extra_opnds ){
03284 TN* opnd_tn = TN_LIST_first( extra_opnds );
03285 if (TN_is_constant(opnd_tn)) continue;
03286 if (Ignore_TN_Dep) {
03287 REGISTER opnd_reg = TN_register (opnd_tn);
03288 ISA_REGISTER_CLASS opnd_cl = TN_register_class (opnd_tn);
03289 reg_uses[opnd_cl] = REGISTER_SET_Union1(reg_uses[opnd_cl],
03290 opnd_reg);
03291 }else{
03292 if(TN_is_global_reg(opnd_tn))
03293 gtn_uses = GTN_SET_Union1D(gtn_uses, opnd_tn, &MEM_local_pool);
03294 else
03295 tn_uses = TN_SET_Union1D(tn_uses, opnd_tn, &MEM_local_pool);
03296 }
03297 extra_opnds = TN_LIST_rest( extra_opnds );
03298 }
03299 #endif
03300 if( Ignore_TN_Dep ){
03301 REGSET_OR(failed_reg_defs, reg_defs);
03302 REGSET_OR(failed_reg_uses, reg_uses);
03303 }else{
03304 *pfailed_gtn_defs = GTN_SET_Union(*pfailed_gtn_defs, gtn_defs, &MEM_local_pool);
03305 *pfailed_gtn_uses = GTN_SET_Union(*pfailed_gtn_uses, gtn_uses, &MEM_local_pool);
03306 *pfailed_tn_defs = TN_SET_Union(*pfailed_tn_defs, tn_defs, &MEM_local_pool);
03307 *pfailed_tn_uses = TN_SET_Union(*pfailed_tn_uses, tn_uses, &MEM_local_pool);
03308 }
03309 }
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319 static OP *
03320 OP_To_Move (BB *bb, BB *tgt_bb, BB_SET **pred_bbs, mINT32 motion_type, mUINT8 *spec_type)
03321 {
03322 #if defined(TARG_SL)
03323
03324 if( barriered )
03325 return NULL;
03326 #endif
03327
03328 OP *cur_op;
03329 OP *best_op = NULL;
03330
03331
03332
03333
03334
03335
03336 REGISTER_SET reg_defs[ISA_REGISTER_CLASS_MAX+1],
03337 reg_uses[ISA_REGISTER_CLASS_MAX+1],
03338 failed_reg_defs[ISA_REGISTER_CLASS_MAX+1],
03339 failed_reg_uses[ISA_REGISTER_CLASS_MAX+1];
03340
03341 GTN_SET *gtn_defs, *gtn_uses, *failed_gtn_defs, *failed_gtn_uses;
03342 TN_SET *tn_defs, *tn_uses, *failed_tn_defs, *failed_tn_uses;
03343
03344 if (Ignore_TN_Dep) {
03345 REGSET_CLEAR (failed_reg_defs);
03346 REGSET_CLEAR (failed_reg_uses);
03347 } else {
03348
03349 failed_gtn_defs = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
03350 failed_gtn_uses = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
03351 failed_tn_defs = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
03352 failed_tn_uses = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
03353
03354 gtn_defs = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
03355 gtn_uses = GTN_SET_Create(GTN_UNIVERSE_size, &MEM_local_pool);
03356 tn_defs = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
03357 tn_uses = TN_SET_Create_Empty(Last_TN + 1, &MEM_local_pool);
03358
03359 GTN_SET_ClearD (failed_gtn_uses);
03360 GTN_SET_ClearD (failed_gtn_defs);
03361 }
03362
03363
03364
03365
03366 BOOL forw = motion_type & (GCM_EQUIV_FWD | GCM_SPEC_ABOVE |
03367 GCM_DUP_ABOVE | GCM_CIRC_ABOVE);
03368 OP *call_op = BB_call(bb) ? BB_xfer_op(bb) : NULL;
03369 for (cur_op = (forw) ? BB_first_op(bb) : BB_last_op(bb); cur_op;
03370 cur_op = (forw) ? OP_next(cur_op) : OP_prev(cur_op)) {
03371
03372 if( Trace_GCM ){
03373 fprintf( TFile, "best_op: %s, cur_op :", best_op ? "not NULL" : "NULL" );
03374 Print_OP_No_SrcLine(cur_op);
03375 }
03376
03377
03378 if( OP_xfer(cur_op) || OP_noop(cur_op)
03379 #if defined(TARG_SL)
03380 || OP_is_loop(cur_op)
03381 #endif
03382 ) {
03383 if( Trace_GCM ){
03384 fprintf(TFile, "skipped for OP_xfer or OP_noop \n");
03385 }
03386
03387 Add_Fail_TNs( cur_op, &failed_tn_uses, &failed_tn_defs,
03388 &failed_gtn_uses, &failed_gtn_defs,
03389 failed_reg_uses, failed_reg_defs );
03390 continue;
03391 }
03392
03393 if (CGTARG_Is_OP_Barrier(cur_op)) {
03394 #if defined(TARG_SL)
03395 if( Trace_GCM ){
03396 fprintf(TFile, "skipped for it is a barrier \n");
03397 }
03398
03399 barriered = TRUE;
03400 return NULL;
03401 #else // TARG_IA64, TARG_X8664, TARG_NVISA
03402 continue;
03403 #endif
03404 }
03405
03406 #ifdef TARG_X8664
03407
03408
03409 if (OP_x87(cur_op) || OP_mmx(cur_op)) continue;
03410 #endif
03411
03412
03413
03414 if (OP_Real_Ops(cur_op) != 1 && OP_Real_Ops(cur_op) != 0) {
03415 if( Trace_GCM ){
03416 fprintf(TFile, "skipped for real_op!=1 \n");
03417 }
03418
03419 Add_Fail_TNs( cur_op, &failed_tn_uses, &failed_tn_defs,
03420 &failed_gtn_uses, &failed_gtn_defs,
03421 failed_reg_uses, failed_reg_defs );
03422 continue;
03423 }
03424
03425
03426 if (OP_visited(cur_op)) {
03427 if( Trace_GCM ){
03428 fprintf(TFile, "skipped for already visited \n");
03429 }
03430
03431 Add_Fail_TNs( cur_op, &failed_tn_uses, &failed_tn_defs,
03432 &failed_gtn_uses, &failed_gtn_defs,
03433 failed_reg_uses, failed_reg_defs );
03434 continue;
03435 }
03436
03437
03438
03439
03440
03441 if (OP_Has_Restrictions(cur_op, bb, tgt_bb, motion_type)){
03442 if( Trace_GCM ){
03443 fprintf(TFile, "skipped for being restricted \n");
03444 }
03445
03446 Add_Fail_TNs( cur_op, &failed_tn_uses, &failed_tn_defs,
03447 &failed_gtn_uses, &failed_gtn_defs,
03448 failed_reg_uses, failed_reg_defs );
03449 continue;
03450 }
03451
03452 if (Ignore_TN_Dep) {
03453 REGSET_CLEAR(reg_defs);
03454 REGSET_CLEAR(reg_uses);
03455 } else {
03456 GTN_SET_ClearD (gtn_defs);
03457 GTN_SET_ClearD (gtn_uses);
03458 #if defined(TARG_SL)
03459 TN_SET_ClearD (tn_defs);
03460 TN_SET_ClearD (tn_uses);
03461 #endif
03462 }
03463
03464 BOOL move_better = TRUE;
03465 if (best_op == NULL || (move_better =
03466 Is_OP_Move_Better(cur_op, best_op, motion_type)))
03467 {
03468 if (*pred_bbs == NULL) {
03469 *pred_bbs = BB_SET_Singleton (tgt_bb, &MEM_local_pool);
03470
03471
03472
03473
03474
03475
03476 if (Motion_Is_CIRC_ABOVE(motion_type)) {
03477 *pred_bbs = BB_SET_Union1 (*pred_bbs, bb, &MEM_local_pool);
03478 } else {
03479 if (BB_Add_Ancestors(pred_bbs, bb, bb, &MEM_local_pool)) return NULL;
03480 }
03481 }
03482
03483
03484 INT i;
03485 for (i = 0; i < OP_results(cur_op); ++i) {
03486 TN *result_tn = OP_result(cur_op,i);
03487 if (Ignore_TN_Dep) {
03488 REGISTER result_reg = TN_register (result_tn);
03489 ISA_REGISTER_CLASS result_cl = TN_register_class (result_tn);
03490 reg_defs[result_cl] = REGISTER_SET_Union1(reg_defs[result_cl],
03491 result_reg);
03492 } else {
03493 if (TN_is_global_reg(result_tn))
03494 gtn_defs = GTN_SET_Union1D(gtn_defs, result_tn, &MEM_local_pool);
03495 else
03496 tn_defs = TN_SET_Union1D(tn_defs, result_tn, &MEM_local_pool);
03497 }
03498 }
03499
03500 #ifdef TARG_SL
03501 TN_LIST * extra_results = cur_op->extra_result;
03502 while ( extra_results ) {
03503 TN *result_tn = TN_LIST_first( extra_results );
03504 if ( Ignore_TN_Dep ){
03505 REGISTER result_reg = TN_register (result_tn);
03506 ISA_REGISTER_CLASS result_cl = TN_register_class (result_tn);
03507 reg_defs[result_cl] = REGISTER_SET_Union1(reg_defs[result_cl],
03508 result_reg);
03509 } else {
03510 if (TN_is_global_reg(result_tn))
03511 gtn_defs = GTN_SET_Union1D(gtn_defs, result_tn, &MEM_local_pool);
03512 else
03513 tn_defs = TN_SET_Union1D(tn_defs, result_tn, &MEM_local_pool);
03514 }
03515 extra_results = TN_LIST_rest( extra_results );
03516 }
03517 #endif
03518
03519 for(i = 0; i < OP_opnds(cur_op); ++i) {
03520 TN *opnd_tn = OP_opnd(cur_op,i);
03521 if (TN_is_constant(opnd_tn)) continue;
03522 if (Ignore_TN_Dep) {
03523 REGISTER opnd_reg = TN_register (opnd_tn);
03524 ISA_REGISTER_CLASS opnd_cl = TN_register_class (opnd_tn);
03525 reg_uses[opnd_cl] = REGISTER_SET_Union1(reg_uses[opnd_cl],
03526 opnd_reg);
03527 } else {
03528 if (TN_is_global_reg(opnd_tn))
03529 gtn_uses = GTN_SET_Union1D(gtn_uses, opnd_tn, &MEM_local_pool);
03530 else
03531 tn_uses = TN_SET_Union1D(tn_uses, opnd_tn, &MEM_local_pool);
03532 }
03533 }
03534
03535
03536 #ifdef TARG_SL
03537 TN_LIST * extra_opnds = cur_op->extra_operand;
03538 while( extra_opnds ){
03539 TN* opnd_tn = TN_LIST_first( extra_opnds );
03540 if (TN_is_constant(opnd_tn)) continue;
03541 if (Ignore_TN_Dep) {
03542 REGISTER opnd_reg = TN_register (opnd_tn);
03543 ISA_REGISTER_CLASS opnd_cl = TN_register_class (opnd_tn);
03544 reg_uses[opnd_cl] = REGISTER_SET_Union1(reg_uses[opnd_cl],
03545 opnd_reg);
03546 }else{
03547 if(TN_is_global_reg(opnd_tn))
03548 gtn_uses = GTN_SET_Union1D(gtn_uses, opnd_tn, &MEM_local_pool);
03549 else
03550 tn_uses = TN_SET_Union1D(tn_uses, opnd_tn, &MEM_local_pool);
03551 }
03552 extra_opnds = TN_LIST_rest( extra_opnds );
03553 }
03554 #endif
03555
03556
03557 BOOL succ_intrsct =
03558 ( Ignore_TN_Dep && !REGSET_INTERSECT(reg_defs, failed_reg_defs) &&
03559 !REGSET_INTERSECT(reg_defs, failed_reg_uses) &&
03560 !REGSET_INTERSECT(reg_uses, failed_reg_defs) ||
03561 (!Ignore_TN_Dep &&
03562 (!GTN_SET_IntersectsP(gtn_defs, failed_gtn_defs) &&
03563 !GTN_SET_IntersectsP(gtn_defs, failed_gtn_uses) &&
03564 !GTN_SET_IntersectsP(gtn_uses, failed_gtn_defs)) &&
03565 (!TN_SET_IntersectsP(tn_defs, failed_tn_defs) &&
03566 !TN_SET_IntersectsP(tn_defs, failed_tn_uses) &&
03567 !TN_SET_IntersectsP(tn_uses, failed_tn_defs))) );
03568
03569 void *defs[2], *uses[2];
03570 defs[0] = Ignore_TN_Dep ? (void *)®_defs : (void *)gtn_defs;
03571 uses[0] = Ignore_TN_Dep ? (void *)®_uses : (void *)gtn_uses;
03572 defs[1] = Ignore_TN_Dep ? NULL : (void *)tn_defs;
03573 uses[1] = Ignore_TN_Dep ? NULL : (void *)tn_uses;
03574
03575 BOOL unsafe = OP_unsafe(cur_op);
03576 BOOL can_across_call = CG_DEP_Can_OP_Move_Across_Call( cur_op,
03577 call_op, forw, Ignore_TN_Dep);
03578 #if defined(TARG_SL)
03579 BOOL meet_heur = OP_Move_Heuristic( cur_op, motion_type, bb, tgt_bb );
03580 #else
03581 BOOL meet_heur = TRUE;
03582 #endif
03583 BOOL can_move = Can_OP_Move(cur_op, bb, tgt_bb, pred_bbs, defs,
03584 uses, motion_type, spec_type);
03585 if( !unsafe && succ_intrsct && can_across_call && meet_heur && can_move ){
03586 best_op = cur_op;
03587 if( Trace_GCM )
03588 fprintf( TFile, " choose cur_op to be best_op \n" );
03589 }else {
03590 if (Ignore_TN_Dep) {
03591 REGSET_OR(failed_reg_defs, reg_defs);
03592 REGSET_OR(failed_reg_uses, reg_uses);
03593 } else {
03594 failed_gtn_defs = GTN_SET_Union(failed_gtn_defs, gtn_defs,
03595 &MEM_local_pool);
03596 failed_gtn_uses = GTN_SET_Union(failed_gtn_uses, gtn_uses,
03597 &MEM_local_pool);
03598 #if defined(TARG_SL)
03599 failed_tn_defs = TN_SET_Union(failed_tn_defs, tn_defs, &MEM_local_pool);
03600 failed_tn_uses = TN_SET_Union(failed_tn_uses, tn_uses, &MEM_local_pool);
03601 #endif
03602 }
03603
03604 if( Trace_GCM ){
03605 fprintf( TFile, " skipped for %s", unsafe ? "unsafe ":" " );
03606 fprintf( TFile, " %s", succ_intrsct ? " ":" TN dependence " );
03607 fprintf( TFile, " %s", !can_across_call ? " cannot across call ":" " );
03608 fprintf( TFile, " %s", !meet_heur ? " not meet heur":" " );
03609 fprintf( TFile, " %s", !can_move ? " cannot move":" " );
03610 fprintf( TFile, "\n" );
03611 }
03612 }
03613 }
03614
03615
03616
03617
03618
03619
03620 else {
03621 if(best_op && !move_better){
03622 if( Trace_GCM )
03623 fprintf( TFile, "take the best op as candidate\n" );
03624 break;
03625 }
03626 }
03627 }
03628
03629 return best_op;
03630 }
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640 static void
03641 Adjust_Qualifying_Predicate(OP *cand_op, BB *src_bb, BB *tgt_bb,
03642 mINT32 motion_type, mUINT8 spec_type)
03643 {
03644
03645 if (motion_type & (GCM_CIRC_ABOVE | GCM_SPEC_ABOVE)) {
03646
03647 if (PSAFE_PTR_SPEC(spec_type)) {
03648 OP *tgt_br_op = BB_xfer_op(tgt_bb);
03649 if (tgt_br_op && OP_has_predicate(tgt_br_op)) {
03650 TN *tn1, *tn2;
03651 OP *cmp;
03652 CGTARG_Analyze_Compare(tgt_br_op, &tn1, &tn2, &cmp);
03653 BOOL fall_thru = BB_Fall_Thru_Successor(tgt_bb) == src_bb;
03654
03655
03656
03657 if (!fall_thru) {
03658 Set_OP_opnd(cand_op, OP_PREDICATE_OPND,
03659 OP_opnd(tgt_br_op, OP_PREDICATE_OPND));
03660 } else if (cmp && OP_results(cmp) == 2) {
03661
03662
03663
03664
03665
03666 BOOL branch_on_true = CGTARG_Branches_On_True(tgt_br_op, cmp);
03667 TN *pred_tn;
03668 if (branch_on_true) {
03669 pred_tn = OP_result(cmp, 1);
03670 Set_OP_opnd(cand_op, OP_PREDICATE_OPND, pred_tn);
03671
03672
03673 if (OP_bb(cmp) != OP_bb(cand_op) && !TN_is_global_reg(pred_tn)) {
03674 GTN_UNIVERSE_Add_TN(pred_tn);
03675
03676 }
03677 } else {
03678 pred_tn = OP_result(cmp, 0);
03679 Set_OP_opnd(cand_op, OP_PREDICATE_OPND, pred_tn);
03680
03681
03682 if (OP_bb(cmp) != OP_bb(cand_op) && !TN_is_global_reg(pred_tn)) {
03683 GTN_UNIVERSE_Add_TN(pred_tn);
03684
03685 }
03686 }
03687 }
03688 }
03689 }
03690 }
03691 }
03692
03693
03694
03695
03696
03697
03698 static BOOL Dependent_Between_OPs( OP *op_a, OP *op_b )
03699 {
03700 int i;
03701 for( i=0; i < OP_results(op_a); i++ ){
03702 int j;
03703 for( j=0; j < OP_results(op_b); j++ ){
03704 if( TN_number(OP_result(op_a, i)) == TN_number(OP_result(op_b,j)) )
03705 return TRUE;
03706 }
03707 for( j=0; j < OP_opnds(op_b); j++ ){
03708 if( TN_is_constant( OP_opnd(op_b,j) ) )
03709 continue;
03710 if( TN_number(OP_result(op_a, i)) == TN_number(OP_opnd(op_b,j)) )
03711 return TRUE;
03712 }
03713 }
03714
03715 for( i=0; i < OP_results(op_b); i++ ){
03716 int j;
03717 for( j=0; j < OP_opnds(op_a); j++ ){
03718 if( TN_is_constant( OP_opnd(op_a,j) ) )
03719 continue;
03720 if( TN_number(OP_result(op_b, i)) == TN_number(OP_opnd(op_a,j)) )
03721 return TRUE;
03722 }
03723 }
03724
03725 return FALSE;
03726 }
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740 static BOOL Append_Op_To_BB(OP *cand_op, BB *cand_bb, BB *src_bb,
03741 mINT32 motion_type, mUINT8 spec_type)
03742 {
03743 OP *limit_op;
03744 BOOL succeed = TRUE;
03745
03746 #if defined(TARG_SL)
03747
03748
03749 if( BB_loop_op(cand_bb) )
03750 limit_op = BB_loop_op(cand_bb);
03751 else
03752 limit_op = BB_xfer_op(cand_bb);
03753 #else
03754 limit_op = BB_xfer_op(cand_bb);
03755 #endif
03756
03757 #ifdef TARG_X8664
03758 if( limit_op != NULL && OP_cond( limit_op ) ){
03759 FmtAssert( !TOP_is_change_rflags(OP_code(cand_op)),
03760 ("cand_op modifies rflags") );
03761 }
03762 #endif
03763
03764 {
03765 if( limit_op ){
03766 BB_Insert_Op_Before (cand_bb, limit_op, cand_op);
03767 #if defined(TARG_SL)
03768
03769
03770
03771 if(Dependent_Between_OPs(limit_op, cand_op))
03772 succeed = FALSE;
03773 #endif
03774 } else
03775 BB_Append_Op (cand_bb, cand_op);
03776 }
03777
03778
03779 Adjust_Qualifying_Predicate(cand_op, src_bb, cand_bb, motion_type,spec_type);
03780
03781 return succeed;
03782 }
03783
03784
03785
03786
03787
03788
03789
03790 static void
03791 Adjust_BBSCH (OP *cand_op, BB *cand_bb, BB *bb,
03792 BBSCH *new_cand_bbsch, BBSCH *new_bbsch)
03793 {
03794
03795 if (OP_has_result(cand_op)) {
03796 TN *result_tn = OP_result(cand_op, 0);
03797 if (!TN_is_global_reg(result_tn)) {
03798 BBSCH_global_regcost(new_cand_bbsch)++;
03799 BBSCH_global_regcost(new_bbsch)++;
03800 #ifndef TARG_MIPS
03801 BBSCH_local_regcost(new_bbsch)--;
03802 #endif
03803 } else {
03804 BBSCH_global_regcost(new_cand_bbsch)++;
03805 BBSCH_global_regcost(new_bbsch)--;
03806 }
03807 }
03808
03809
03810 for (INT i = 0; i < OP_opnds(cand_op); ++i) {
03811 TN *opnd_tn = OP_opnd(cand_op, i);
03812 if (TN_is_constant(opnd_tn)) continue;
03813
03814 if (TN_is_global_reg(opnd_tn)) {
03815 if (!GTN_SET_MemberP(BB_live_out(cand_bb), opnd_tn)) {
03816 BBSCH_global_regcost(new_cand_bbsch)--;
03817 #ifndef TARG_MIPS
03818 BBSCH_local_regcost(new_cand_bbsch)++;
03819 #endif
03820 }
03821 if (!GTN_SET_MemberP(BB_live_out(bb), opnd_tn))
03822 BBSCH_global_regcost(new_bbsch)--;
03823 }
03824 }
03825 }
03826
03827
03828
03829
03830
03831
03832 static BOOL
03833 Is_Schedule_Worse(BB *bb, BB *cand_bb, BBSCH *new_bbsch,
03834 BBSCH *new_cand_bbsch, BBSCH *old_bbsch,
03835 BBSCH *old_cand_bbsch)
03836 {
03837
03838 UINT32 new_from_time, new_to_time, old_from_time, old_to_time;
03839 mINT8 old_from_regcost[ISA_REGISTER_CLASS_MAX+1],
03840 old_to_regcost[ISA_REGISTER_CLASS_MAX+1],
03841 new_from_regcost[ISA_REGISTER_CLASS_MAX+1],
03842 new_to_regcost[ISA_REGISTER_CLASS_MAX+1];
03843
03844 old_from_time = BBSCH_schedule_length(old_bbsch);
03845 old_to_time = BBSCH_schedule_length(old_cand_bbsch);
03846 new_from_time = BBSCH_schedule_length(new_bbsch);
03847 new_to_time = BBSCH_schedule_length(new_cand_bbsch);
03848
03849 if (Cur_Gcm_Type & GCM_MINIMIZE_REGS) {
03850 mINT8 *old_from_local_regcost, *old_to_local_regcost,
03851 *new_from_local_regcost, *new_to_local_regcost;
03852
03853 old_from_local_regcost = BBSCH_local_regcost(old_bbsch);
03854 old_to_local_regcost = BBSCH_local_regcost(old_cand_bbsch);
03855 new_from_local_regcost = BBSCH_local_regcost(new_bbsch);
03856 new_to_local_regcost = BBSCH_local_regcost(new_cand_bbsch);
03857
03858
03859 if (Trace_GCM && Trace_GCM_Reg_Usage && GCM_Internal_Flag) {
03860 #pragma mips_frequency_hint NEVER
03861 fprintf (TFile, "\n FROM BB:%d => TO BB:%d\n", BB_id(bb), BB_id(cand_bb));
03862 fprintf (TFile, "\n LOCAL REGISTER COST");
03863 }
03864
03865
03866
03867
03868
03869
03870
03871 INT i;
03872 FOR_ALL_ISA_REGISTER_CLASS(i) {
03873 #if defined(TARG_SL)
03874 old_from_regcost[i] = old_from_local_regcost ? old_from_local_regcost[i] : 0;
03875 old_to_regcost[i] = old_to_local_regcost ? old_to_local_regcost[i] : 0;
03876 new_from_regcost[i] = new_from_local_regcost ? new_from_local_regcost[i] : 0;
03877 new_to_regcost[i] = new_to_local_regcost ? new_to_local_regcost[i] : 0;
03878 #else
03879 old_from_regcost[i] = BBSCH_global_regcost(old_bbsch) +
03880 ((old_from_local_regcost) ? old_from_local_regcost[i] : 0);
03881
03882 old_to_regcost[i] = BBSCH_global_regcost(old_cand_bbsch) +
03883 ((old_to_local_regcost) ? old_to_local_regcost[i] : 0);
03884
03885 new_from_regcost[i] = BBSCH_global_regcost(new_bbsch) +
03886 ((new_from_local_regcost) ? new_from_local_regcost[i] : 0);
03887
03888 new_to_regcost[i] = BBSCH_global_regcost(new_cand_bbsch) +
03889 ((new_to_local_regcost) ? new_to_local_regcost[i] : 0);
03890 #endif // TARG_SL
03891 if (Trace_GCM && Trace_GCM_Reg_Usage && GCM_Internal_Flag) {
03892 #pragma mips_frequency_hint NEVER
03893 fprintf (TFile, "\nold_from_local_regcost[%d]=%d, old_to_local_regcost[%d]=%d\n",
03894 i, (old_from_local_regcost) ? old_from_local_regcost[i] : 0,
03895 i, (old_to_local_regcost) ? old_to_local_regcost[i] : 0);
03896
03897
03898 fprintf (TFile, "new_from_local_regcost[%d]=%d, new_to_local_regcost[%d]=%d\n",
03899 i, (new_from_local_regcost) ? new_from_local_regcost[i] : 0,
03900 i, (new_to_local_regcost) ? new_to_local_regcost[i] : 0);
03901
03902 }
03903 }
03904 if (Trace_GCM && Trace_GCM_Reg_Usage && GCM_Internal_Flag) {
03905 #pragma mips_frequency_hint NEVER
03906 fprintf (TFile, "\n GLOBAL REGISTER COST");
03907 fprintf (TFile, "\nold_from_global_regcost=%d, old_to_global_regcost=%d\n",
03908 BBSCH_global_regcost(old_bbsch), BBSCH_global_regcost(old_cand_bbsch));
03909
03910 fprintf (TFile, "new_from_global_regcost=%d, new_to_global_regcost=%d\n",
03911 BBSCH_global_regcost(new_bbsch), BBSCH_global_regcost(new_cand_bbsch));
03912 }
03913 }
03914
03915 BOOL equiv_blocks =
03916 BS_MemberP (BB_pdom_set(bb), BB_id(cand_bb)) &&
03917 BS_MemberP (BB_dom_set(cand_bb), BB_id(bb)) ||
03918 BS_MemberP (BB_pdom_set(cand_bb), BB_id(bb)) &&
03919 BS_MemberP (BB_dom_set(bb), BB_id(cand_bb));
03920
03921 UINT32 branch_penalty;
03922 float freq_ratio = BB_freq(cand_bb)/BB_freq(bb);
03923
03924
03925 if (CG_DEP_Adjust_OOO_Latency && !equiv_blocks && (freq_ratio < 0.4))
03926 branch_penalty = (UINT32) (freq_ratio * (1 - freq_ratio) * mispredict);
03927 else
03928 branch_penalty = 0;
03929
03930
03931
03932
03933
03934
03935
03936 INT times = (GCM_Test) ? 10 : 1;
03937 BOOL worsen_schedule =
03938 (((BB_freq(bb) * new_from_time) +
03939 (BB_freq(cand_bb) * new_to_time)) >
03940 (times * ((BB_freq(bb) * old_from_time) +
03941 (BB_freq(cand_bb) * old_to_time) +
03942 branch_penalty)) ||
03943
03944
03945 (!equiv_blocks && (new_to_time > (times * (old_to_time +
03946 branch_penalty)))));
03947
03948
03949
03950
03951 BOOL improve_reg_pressure = TRUE;
03952 if (Cur_Gcm_Type & GCM_MINIMIZE_REGS) {
03953 for (INT i = ISA_REGISTER_CLASS_MIN; i <= ISA_REGISTER_CLASS_MAX &&
03954 improve_reg_pressure; i++) {
03955 UINT8 delta_from = new_from_regcost[i] - old_from_regcost[i];
03956 UINT8 delta_to = new_to_regcost[i] - old_to_regcost[i];
03957
03958 #ifdef KEY
03959
03960
03961 improve_reg_pressure = improve_reg_pressure &&
03962 (old_from_regcost[i] <= REGISTER_CLASS_info[i].register_count &&
03963 old_to_regcost[i] <= REGISTER_CLASS_info[i].register_count &&
03964 ((old_from_regcost[i] + delta_from) <= REGISTER_CLASS_info[i].register_count) &&
03965 ((old_to_regcost[i] + delta_to) <= REGISTER_CLASS_info[i].register_count));
03966 #else
03967 improve_reg_pressure = improve_reg_pressure &&
03968 (old_from_regcost[i] <= REGISTER_MAX &&
03969 old_to_regcost[i] <= REGISTER_MAX &&
03970 ((old_from_regcost[i] + delta_from) <= REGISTER_MAX) &&
03971 ((old_to_regcost[i] + delta_to) <= REGISTER_MAX));
03972 #endif
03973 }
03974 }
03975
03976 return worsen_schedule || !improve_reg_pressure;
03977 }
03978
03979
03980
03981
03982
03983
03984 static BBSCH *
03985 Schedule_BB_For_GCM (BB *bb, HBS_TYPE hb_type, HB_Schedule **Sched)
03986 {
03987 BBSCH *bbsch = (BBSCH *)BB_MAP_Get (bbsch_map, bb);
03988
03989 if (bbsch == NULL) {
03990 bbsch = TYPE_MEM_POOL_ALLOC (BBSCH, &gcm_loop_pool);
03991 bzero (bbsch, sizeof (BBSCH));
03992 Set_BB_SCHEDULE(bbsch);
03993 }
03994
03995 if (BB_SCHEDULE(bbsch) ) {
03996 if (!GCM_Use_Sched_Est) {
03997 if (! *Sched) {
03998 *Sched = CXX_NEW(HB_Schedule(), &MEM_local_pool);
03999 }
04000
04001 (*Sched)->Init(bb, hb_type, INT32_MAX, bbsch, NULL);
04002 (*Sched)->Schedule_BB(bb, bbsch);
04003 } else {
04004 Cur_Gcm_Type |= GCM_USE_SCHED_EST;
04005 BBSCH_schedule_length(bbsch) = CG_SCHED_EST_BB_Cycles(bb,
04006 SCHED_EST_FOR_GCM);
04007 }
04008 BB_MAP_Set (bbsch_map, bb, bbsch);
04009 }
04010 return bbsch;
04011 }
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021 static void Visit_BB_Preds(
04022 BB *bb,
04023 BB *head,
04024 BB_SET *loop_bbs,
04025 INT icycle,
04026 INT ncycles)
04027 {
04028
04029
04030 BS *cycle_set = BB_cycle_set(bb);
04031 if (cycle_set == NULL) {
04032 cycle_set = BS_Create_Empty(ncycles, &MEM_local_pool);
04033 Set_BB_cycle_set(bb, cycle_set);
04034 }
04035
04036 BS_Union1D(cycle_set, icycle, NULL);
04037
04038 if (bb == head) return;
04039
04040 BBLIST *edge;
04041 FOR_ALL_BB_PREDS(bb, edge) {
04042 BB *pred = BBLIST_item(edge);
04043 if (BB_SET_MemberP(loop_bbs, pred)) {
04044 cycle_set = BB_cycle_set(pred);
04045 if (!cycle_set || !BS_MemberP(cycle_set, icycle)) {
04046 Visit_BB_Preds(pred, head, loop_bbs, icycle, ncycles);
04047 }
04048 }
04049 }
04050 }
04051
04052 #if defined(TARG_SL)
04053
04054
04055
04056
04057
04058
04059 static VECTOR
04060 Sort_BBs_In_Rev_Top_Order( BB_SET *processed_bbs, LOOP_DESCR *loop )
04061 {
04062 BB_SET *loop_bbs = LOOP_DESCR_bbset(loop);
04063 BBLIST* predlist = NULL;
04064 BBLIST* succlist = NULL;
04065 BB* pred = NULL;
04066 BB* succ = NULL;
04067
04068
04069
04070
04071
04072 VECTOR sorted_bbs;
04073 VECTOR working_set;
04074
04075 sorted_bbs = VECTOR_Init (PU_BB_Count+2, &MEM_local_pool);
04076 working_set = VECTOR_Init (PU_BB_Count+2, &MEM_local_pool);
04077
04078
04079 BB* temp = NULL;
04080 FOR_ALL_BB_SET_members( loop_bbs, temp ){
04081 if( !BB_SET_MemberP(processed_bbs, temp) )
04082 VECTOR_Add_Element( working_set, (void*)temp );
04083 }
04084
04085
04086
04087
04088
04089
04090
04091
04092 VECTOR preds_of_hole = VECTOR_Init (PU_BB_Count+2, &MEM_local_pool);
04093 VECTOR succs_of_hole = VECTOR_Init (PU_BB_Count+2, &MEM_local_pool);
04094 for( int i=0; i < VECTOR_count(working_set); i++ ){
04095 bool is_pred = false;
04096 bool is_succ = false;
04097 temp = (BB*)VECTOR_element(working_set,i);
04098
04099 FOR_ALL_BB_SUCCS( temp, succlist ){
04100 succ = BBLIST_item( succlist );
04101 if( BB_SET_MemberP(processed_bbs, succ) ){
04102 VECTOR_Add_Element( preds_of_hole, (void*)temp );
04103 is_pred = true;
04104 break;
04105 }
04106 }
04107
04108 FOR_ALL_BB_PREDS( temp, predlist ){
04109 pred = BBLIST_item( predlist );
04110 if( BB_SET_MemberP(processed_bbs, pred) ){
04111 VECTOR_Add_Element( succs_of_hole, (void*)temp );
04112 is_succ = true;
04113 break;
04114 }
04115 }
04116 }
04117
04118 bool changed = false;
04119 bool first_round = true;
04120 while( VECTOR_count(working_set) ) {
04121
04122
04123
04124
04125
04126 if( !changed && !first_round ){
04127
04128 int biggest_id = BB_id( (BB*)VECTOR_element(working_set, 0) );
04129 BB* biggest_bb = (BB*)VECTOR_element(working_set, 0);
04130 for( int j=0; j<VECTOR_count(working_set); j++ ){
04131 if( BB_id( (BB*)VECTOR_element(working_set,j) ) > biggest_id ) {
04132 biggest_id = BB_id( (BB*)VECTOR_element(working_set,j) );
04133 biggest_bb = (BB*)VECTOR_element(working_set,j);
04134 }
04135 }
04136
04137 VECTOR_Add_Element( sorted_bbs, (void*)biggest_bb );
04138 VECTOR_Delete_Element( working_set, (void*)biggest_bb );
04139 FOR_ALL_BB_PREDS( biggest_bb, predlist ){
04140 pred = BBLIST_item( predlist );
04141 if( BB_SET_MemberP(loop_bbs, pred) &&
04142 !VECTOR_Member_Element(working_set, (void*)pred) &&
04143 !VECTOR_Member_Element(sorted_bbs, (void*)pred) ){
04144 VECTOR_Add_Element( working_set, (void*)pred );
04145 changed = true;
04146 }
04147 }
04148
04149 continue;
04150 }
04151
04152 first_round = false;
04153 changed = false;
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170 for( int i=0; i < VECTOR_count(working_set); i++ ){
04171
04172 BB* cand = (BB*)VECTOR_element(working_set,i);
04173 bool ready = TRUE;
04174 BBLIST* succlist;
04175 BB* succ;
04176
04177 FOR_ALL_BB_SUCCS( cand, succlist ){
04178 succ = BBLIST_item( succlist );
04179 if( BB_SET_MemberP(loop_bbs, succ) &&
04180 succ != LOOP_DESCR_loophead(loop) &&
04181 ! BB_SET_MemberP(processed_bbs, succ) ){
04182 if( ! VECTOR_Member_Element(sorted_bbs, (void*)succ) ){
04183 ready = FALSE;
04184 break;
04185 }
04186 }
04187 }
04188
04189
04190
04191
04192 if( VECTOR_Member_Element(preds_of_hole, cand) ){
04193
04194
04195
04196 if( !VECTOR_Member_Element(succs_of_hole, cand) ) {
04197 for( int j=0; j < VECTOR_count(succs_of_hole); j++ ){
04198 void *succ = VECTOR_element(succs_of_hole,j);
04199 if( !VECTOR_Member_Element(sorted_bbs, succ) ) {
04200 ready = FALSE;
04201 break;
04202 }
04203 }
04204 }
04205 }
04206
04207
04208
04209
04210 if( ready ){
04211 VECTOR_Add_Element( sorted_bbs, (void*)cand );
04212 VECTOR_Delete_Element( working_set, (void*)cand );
04213 changed = true;
04214 FOR_ALL_BB_PREDS( cand, predlist ){
04215 pred = BBLIST_item( predlist );
04216 if( BB_SET_MemberP(loop_bbs, pred) &&
04217
04218 !BB_SET_MemberP(processed_bbs, pred) &&
04219 !VECTOR_Member_Element(working_set, (void*)pred) &&
04220 !VECTOR_Member_Element(sorted_bbs, (void*)pred) ){
04221 VECTOR_Add_Element( working_set, (void*)pred );
04222 }
04223 }
04224 }
04225
04226 }
04227 }
04228
04229 return sorted_bbs;
04230 }
04231
04232 static BOOL All_OPs_Visited( BB* bb )
04233 {
04234 BOOL visited = TRUE;
04235 OP* cur_op;
04236 FOR_ALL_BB_OPs( bb, cur_op ){
04237 if( !OP_visited(cur_op) ){
04238 visited = FALSE;
04239 break;
04240 }
04241 }
04242 return visited;
04243 }
04244
04245 static void Break_Dependency( OP_LIST * moved_loads, BB* cand_bb )
04246 {
04247 while( moved_loads ){
04248 OP *op = OP_LIST_first( moved_loads );
04249
04250
04251 Is_True(OP_results(op) == 1, ("strange load Op with more than one results"));
04252
04253 TN *result_tn = OP_result(op, 0);
04254 TN* new_tn = Dup_TN( result_tn );
04255 Set_OP_result( op, 0, new_tn );
04256
04257
04258 OP* copy_op = Mk_OP( TOP_addiu, result_tn, new_tn, Gen_Literal_TN(0,4) );
04259 Set_OP_copy( copy_op );
04260 BB_Insert_Op_After( cand_bb, op, copy_op );
04261
04262
04263 if( OP_has_tag(op) ){
04264 LABEL_IDX tag_idx = 0;
04265 tag_idx = Get_OP_Tag( op );
04266 Is_True( tag_idx > 0, ("incorrect tag index") );
04267 Reset_OP_has_tag( op );
04268 Set_OP_Tag( copy_op, tag_idx );
04269 }
04270
04271 moved_loads = OP_LIST_Delete( op, moved_loads );
04272 }
04273
04274
04275 }
04276
04277 static void Reduce_Loop_Count( LOOP_DESCR *loop, BB* );
04278
04279 #endif // TARG_SL
04280
04281
04282
04283
04284
04285
04286
04287
04288 static INT
04289 GCM_For_Loop (LOOP_DESCR *loop, BB_SET *processed_bbs, HBS_TYPE hb_type)
04290 {
04291
04292 BB *bb;
04293 RID *rid;
04294 VECTOR bbvector, cand_bbvector;
04295 INT num_moves = 0;
04296 PRIORITY_TYPE priority_type;
04297
04298
04299 INT op_id = 0;
04300
04301 L_Save();
04302
04303 bb_cycle_set_map = BB_MAP_Create ();
04304
04305 BB_SET *loop_bbs = LOOP_DESCR_bbset(loop);
04306 BB *loop_head = LOOP_DESCR_loophead(loop);
04307
04308
04309 if (loop_head) {
04310
04311
04312 BBLIST *edge;
04313 INT ncycles = 0;
04314 FOR_ALL_BB_PREDS(loop_head, edge) {
04315 BB *pred = BBLIST_item(edge);
04316 if (BB_SET_MemberP(loop_bbs, pred)) ++ncycles;
04317 }
04318
04319
04320
04321 if (ncycles > 1) {
04322 INT icycle = 0;
04323 FOR_ALL_BB_PREDS(loop_head, edge) {
04324 BB *pred = BBLIST_item(edge);
04325 if (BB_SET_MemberP(loop_bbs, pred)) {
04326 Visit_BB_Preds(pred, loop_head, loop_bbs, icycle, ncycles);
04327 ++icycle;
04328 }
04329 }
04330 }
04331 }
04332
04333 if (Trace_GCM) {
04334 fprintf( TFile, "GCM_For_Loop: list of bbs:" );
04335 BB_SET_Print( loop_bbs, TFile );
04336 fprintf( TFile, "\n" );
04337
04338 BB* temp = NULL;
04339 BBLIST * list;
04340 FOR_ALL_BB_SET_members( loop_bbs, temp ){
04341 fprintf( TFile, "PREDs of BB[%i] are:", BB_id(temp) );
04342 FOR_ALL_BB_PREDS(temp, list) {
04343 BB *pred = BBLIST_item(list);
04344 fprintf( TFile, " %i, ",BB_id(pred) );
04345 }
04346 fprintf( TFile, "\nSUCCs of BB[%i] are:", BB_id(temp) );
04347 FOR_ALL_BB_SUCCS(temp, list) {
04348 BB *succ = BBLIST_item(list);
04349 fprintf( TFile, " %i, ",BB_id(succ) );
04350 }
04351 fprintf( TFile, "\n" );
04352 }
04353 }
04354
04355 HBS_TYPE from_hbs_type, to_hbs_type;
04356
04357 from_hbs_type = to_hbs_type = hb_type;
04358 bbvector = VECTOR_Init (PU_BB_Count+2, &MEM_local_pool);
04359
04360 priority_type = SORT_BY_BB_FREQ;
04361
04362 if (hb_type & (HBS_BEFORE_GRA | HBS_BEFORE_LRA))
04363 priority_type |= SORT_BY_REG_USAGE;
04364 else
04365 priority_type |= SORT_BY_BB_PARALLELISM;
04366
04367 #if defined(TARG_SL)
04368 bbvector = Sort_BBs_In_Rev_Top_Order( processed_bbs, loop );
04369
04370 INT count = VECTOR_count(bbvector);
04371
04372 if (Trace_GCM) {
04373 fprintf (TFile, "GCM_For_Loop: After Reverse TOP Ordering, list of bbs:\n");
04374 for (INT i = 0; i < count; i++) {
04375 BB *bb = (BB *)VECTOR_element(bbvector, i);
04376 fprintf (TFile, "\tBB:%d\tfreq:%g\n", BB_id(bb), BB_freq(bb));
04377 }
04378 }
04379 #else
04380
04381 FOR_ALL_BB_SET_members (loop_bbs, bb) {
04382
04383 if (BB_SET_MemberP (processed_bbs, bb)) continue;
04384
04385
04386 if ( (rid = BB_rid(bb)) && (RID_level(rid) >= RL_CGSCHED)) continue;
04387 if (BB_scheduled(bb) && !BB_scheduled_hbs(bb)) continue;
04388
04389
04390
04391
04392
04393 VECTOR_Add_Element (bbvector, (void *)bb);
04394 }
04395
04396 VECTOR_Sort (bbvector, sort_by_bb_frequency);
04397
04398 INT count = VECTOR_count(bbvector);
04399
04400 if (count <= 1) return 0;
04401
04402 if (Trace_GCM) {
04403 #pragma mips_frequency_hint NEVER
04404 fprintf (TFile, "GCM_For_Loop: Ordered list of bbs:\n");
04405 for (INT i = 0; i < count; i++) {
04406 BB *bb = (BB *)VECTOR_element(bbvector, i);
04407 fprintf (TFile, "\tBB:%d\tfreq:%g\n", BB_id(bb), BB_freq(bb));
04408 }
04409 }
04410 #endif // TARG_SL
04411
04412
04413
04414
04415 INT bb_limit = (LOOP_DESCR_nestlevel(loop) == 0) ? 25 : 100;
04416
04417
04418
04419 BBSCH *old_bbsch = NULL, *old_cand_bbsch = NULL;
04420 HB_Schedule *Sched = NULL;
04421 for (INT i = 0; i < count; i++) {
04422
04423 if (bb_limit-- <= 0) break;
04424
04425 BB *bb = (BB *)VECTOR_element(bbvector, i);
04426
04427 if (BB_SET_MemberP (processed_bbs, bb)) continue;
04428
04429
04430 if ( (rid = BB_rid(bb)) && (RID_level(rid) >= RL_CGSCHED)) continue;
04431 if (BB_scheduled(bb) && !BB_scheduled_hbs(bb)) continue;
04432
04433 if (Check_If_Ignore_BB(bb, loop)) continue;
04434
04435 from_hbs_type |= (Ignore_TN_Dep) ? HBS_FROM_POST_GCM_SCHED :
04436 HBS_FROM_PRE_GCM_SCHED;
04437 to_hbs_type |= (Ignore_TN_Dep) ? HBS_FROM_POST_GCM_SCHED :
04438 HBS_FROM_PRE_GCM_SCHED;
04439 from_hbs_type |= HBS_FROM_GCM_FROM_BB;
04440
04441 BBSCH *bbsch = Schedule_BB_For_GCM (bb, from_hbs_type, &Sched);
04442 if (old_bbsch == NULL) {
04443 old_bbsch = TYPE_MEM_POOL_ALLOC(BBSCH, &MEM_local_pool);
04444 bzero (old_bbsch, sizeof (BBSCH));
04445 }
04446 bcopy(bbsch, old_bbsch, sizeof (BBSCH));
04447 Reset_BB_SCHEDULE(bbsch);
04448
04449 if( Trace_GCM ){
04450 fprintf(TFile, " - scheduling BB: %d\n", BB_id(bb) );
04451 }
04452
04453 if( Trace_GCM_Dump_IR ){
04454 fprintf(TFile, "%s %s %s", DBar, "before gcm", DBar);
04455 Print_BB_No_Srclines(bb);
04456 }
04457
04458
04459
04460 mINT32 motion_type;
04461 while ((motion_type = Determine_Motion_Type(loop, bb, bbsch)) != GCM_NONE){
04462 #if defined(TARG_SL)
04463 if( Trace_GCM ){
04464 fprintf( TFile, "motion types are: " );
04465 if( Motion_Is_CIRC_ABOVE(motion_type) )
04466 fprintf( TFile, " GCM_CIRC_ABOVE" );
04467 if( Motion_Is_EQUIV_FWD(motion_type) )
04468 fprintf( TFile, " GCM_EQUIV_FWD" );
04469 if( Motion_Is_EQUIV_BKWD(motion_type) )
04470 fprintf( TFile, " GCM_EQUIV_BKWD" );
04471 if( Motion_Is_SPEC_ABOVE(motion_type) )
04472 fprintf( TFile, " GCM_SPEC_ABOVE" );
04473 if( Motion_Is_SPEC_BELOW(motion_type) )
04474 fprintf( TFile, " GCM_SPEC_BELOW" );
04475 if( Motion_Is_DUP_ABOVE(motion_type) )
04476 fprintf( TFile, " GCM_DUP_ABOVE" );
04477 if( Motion_Is_DUP_BELOW(motion_type) )
04478 fprintf( TFile, " GCM_DUP_BELOW" );
04479 fprintf( TFile, "\n" );
04480 }
04481
04482 load_add_pairs.clear();
04483 last_defs_of_branch.clear();
04484
04485 if( Motion_Is_CIRC_ABOVE(motion_type) ){
04486 circ_above_moves = 0;
04487 promoted_tns = TN_SET_Create_Empty( Last_TN + 1, &gcm_loop_pool );
04488 Preprocess_Loop_Head(bb);
04489 Find_Last_Defs_Of_Branch(bb);
04490
04491
04492
04493
04494
04495 left_ops.clear();
04496 OP *op;
04497 FOR_ALL_BB_OPs( bb, op ){
04498 left_ops.push_back(op);
04499 }
04500 }
04501
04502
04503
04504
04505 Set_BB_flags(old_bbsch, BBSCH_flags(bbsch));
04506
04507 cand_bbvector = VECTOR_Init (PU_BB_Count+2, &MEM_local_pool);
04508
04509
04510
04511
04512 Determine_Candidate_Blocks(bb, loop, motion_type, &bbvector,
04513 &cand_bbvector);
04514 if( Motion_Is_CIRC_ABOVE(motion_type) ){
04515
04516 Is_True( VECTOR_count(cand_bbvector) <= 1,
04517 ("circ_above has >1 cand bb") );
04518 }
04519
04520 if( Trace_GCM ){
04521 INT i, count = VECTOR_count(cand_bbvector);
04522 #ifdef KEY
04523 FmtAssert(count <= VECTOR_size(cand_bbvector), ("VECTOR overflow"));
04524 #else
04525 FmtAssert(count < VECTOR_size(cand_bbvector), ("VECTOR overflow"));
04526 #endif // KEY
04527 fprintf( TFile, "current cand BBs: " );
04528 for (i = 0; i < count; i++) {
04529 fprintf( TFile, "%d ", BB_id((BB*)VECTOR_element(cand_bbvector,i)) );
04530 }
04531 fprintf( TFile, "\n" );
04532 }
04533 #else
04534 cand_bbvector = VECTOR_Init (PU_BB_Count+2, &MEM_local_pool);
04535
04536
04537
04538
04539 Determine_Candidate_Blocks(bb, loop, motion_type, &bbvector,
04540 &cand_bbvector);
04541 #endif // TARG_SL
04542
04543
04544
04545
04546 INT cand_bb_limit = GCM_Test ? 30 : 10;
04547 INT cand_bbcount = VECTOR_count(cand_bbvector);
04548
04549
04550
04551
04552 for (INT j = cand_bbcount - 1; j >= 0; j--) {
04553 OP *cand_op;
04554 BB_SET *pred_bbs = NULL;
04555 BB *cand_bb = (BB *)VECTOR_element(cand_bbvector, j);
04556
04557 #if defined(TARG_SL)
04558
04559 moved_loads = NULL;
04560
04561
04562
04563
04564 barriered = FALSE;
04565
04566 BB_SET *bookkeepings = NULL;
04567
04568 if( BB_in_preds(bb, cand_bb) &&
04569 BB_preds_len(bb) > 1 &&
04570 BB_succs_len(cand_bb) > 1 ){
04571
04572
04573
04574
04575 if( !CG_GCM_enable_critical_edge_motion ||
04576 !Motion_Is_CIRC_ABOVE(motion_type) ||
04577 BB_preds_len(bb) != 2 ||
04578 BB_succs_len(cand_bb) != 2 ){
04579 continue;
04580 }
04581 }
04582 #endif // TARG_SL
04583
04584 if (Large_BB(cand_bb, loop))
04585 continue;
04586
04587 if (CG_Skip_GCM) {
04588 if (BB_id(bb) == GCM_From_BB && (GCM_To_BB < 0))
04589 continue;
04590 if (BB_id(cand_bb) == GCM_To_BB && (GCM_From_BB < 0))
04591 continue;
04592 if (BB_id(bb) == GCM_From_BB && BB_id(cand_bb) == GCM_To_BB)
04593 continue;
04594 }
04595
04596 if (cand_bb_limit-- <= 0) break;
04597
04598 #ifdef KEY
04599
04600 if (GCM_BB_Limit != -1 &&
04601 cumulative_cand_bb++ >= GCM_BB_Limit)
04602 break;
04603 #endif
04604
04605
04606 if (BB_length(cand_bb) >= (Split_BB_Length - 50))
04607 continue;
04608
04609
04610
04611 BS *bb_cycle_set = BB_cycle_set(bb);
04612 BS *cand_bb_cycle_set = BB_cycle_set(cand_bb);
04613 if (bb_cycle_set && cand_bb_cycle_set) {
04614 if (!BS_EqualP(bb_cycle_set, cand_bb_cycle_set))
04615 continue;
04616 } else if (bb_cycle_set || cand_bb_cycle_set) {
04617 continue;
04618 }
04619
04620
04621
04622
04623 to_hbs_type |= HBS_FROM_GCM_TO_BB;
04624 BBSCH *cand_bbsch = Schedule_BB_For_GCM (cand_bb, to_hbs_type, &Sched);
04625 if (old_cand_bbsch == NULL) {
04626 old_cand_bbsch = TYPE_MEM_POOL_ALLOC(BBSCH, &MEM_local_pool);
04627 bzero (old_cand_bbsch, sizeof (BBSCH));
04628 }
04629 bcopy(cand_bbsch, old_cand_bbsch, sizeof (BBSCH));
04630 Reset_BB_SCHEDULE(cand_bbsch);
04631
04632 L_Save();
04633 mUINT8 spec_type;
04634
04635
04636
04637 while ((cand_op =
04638 OP_To_Move (bb, cand_bb, &pred_bbs, motion_type, &spec_type)) != NULL) {
04639 if( Trace_GCM ){
04640 fprintf( TFile, "op_id:%d, The selected OP:\n", op_id);
04641 Print_OP_No_SrcLine(cand_op);
04642 }
04643 #if defined(TARG_SL)
04644
04645
04646
04647 OP *position = OP_prev( cand_op );
04648 #endif
04649 BB_Remove_Op (bb, cand_op);
04650 Set_BB_SCHEDULE(bbsch);
04651 from_hbs_type |= (Ignore_TN_Dep) ? HBS_FROM_POST_GCM_SCHED_AGAIN :
04652 HBS_FROM_PRE_GCM_SCHED_AGAIN;
04653
04654 to_hbs_type |= (Ignore_TN_Dep) ? HBS_FROM_POST_GCM_SCHED_AGAIN :
04655 HBS_FROM_PRE_GCM_SCHED_AGAIN;
04656
04657
04658
04659
04660
04661 TN *old_pred_tn = OP_opnd(cand_op, OP_PREDICATE_OPND);
04662 BOOL fail = !Append_Op_To_BB( cand_op, cand_bb, bb,
04663 motion_type, spec_type);
04664 Set_BB_SCHEDULE(cand_bbsch);
04665
04666
04667
04668
04669
04670 Set_OP_moved(cand_op);
04671 BBSCH *new_bbsch = Schedule_BB_For_GCM (bb, from_hbs_type, &Sched);
04672 Set_BB_flags(new_bbsch, BBSCH_flags(old_bbsch));
04673 BBSCH *new_cand_bbsch = Schedule_BB_For_GCM(cand_bb, to_hbs_type, &Sched);
04674
04675 from_hbs_type &= (Ignore_TN_Dep) ? ~HBS_FROM_POST_GCM_SCHED_AGAIN:
04676 ~HBS_FROM_PRE_GCM_SCHED_AGAIN;
04677
04678 to_hbs_type &= (Ignore_TN_Dep) ? ~HBS_FROM_POST_GCM_SCHED_AGAIN:
04679 ~HBS_FROM_PRE_GCM_SCHED_AGAIN;
04680
04681
04682 if (Cur_Gcm_Type & GCM_MINIMIZE_REGS)
04683 Adjust_BBSCH(cand_op, cand_bb, bb, new_cand_bbsch, new_bbsch);
04684
04685 Reset_OP_moved(cand_op);
04686 Reset_BB_SCHEDULE(bbsch);
04687 Reset_BB_SCHEDULE(cand_bbsch);
04688 Set_OP_visited(cand_op);
04689
04690 INT targ_alignment = (Align_Instructions) ? Align_Instructions:
04691 CGTARG_Text_Alignment();
04692 targ_alignment /= INST_BYTES;
04693 INT16 cand_bb_vacant_slots = Find_Vacant_Slots_BB(cand_bb,
04694 targ_alignment);
04695 INT16 bb_vacant_slots = Find_Vacant_Slots_BB(bb, targ_alignment);
04696
04697 #if defined(TARG_SL)
04698 BOOL should_skip = GCM_Skip_Op_Binary_Search(op_id );
04699 should_skip |= GCM_Skip_Op(cand_op, bb, moved_loads);
04700 should_skip |= fail;
04701
04702 if( Trace_GCM && should_skip ){
04703 fprintf( TFile, "GCM will skip op_id:%d\n", op_id );
04704 }
04705 #endif
04706
04707
04708
04709
04710 if ((Ignore_TN_Dep && BB_ALIGNED(new_cand_bbsch) &&
04711 ((BB_freq(cand_bb)/BB_freq(bb)) < 1.5) &&
04712 ((2 * cand_bb_vacant_slots > targ_alignment))) ||
04713
04714 Is_Schedule_Worse(bb, cand_bb, new_bbsch, new_cand_bbsch,
04715 old_bbsch, old_cand_bbsch)
04716 #if defined(TARG_SL)
04717 || should_skip
04718 #endif
04719 ) {
04720
04721
04722 Perform_Post_GCM_Steps(bb, cand_bb, cand_op, motion_type,
04723 spec_type, &pred_bbs, loop, FALSE);
04724 BB_Remove_Op (cand_bb, cand_op);
04725 #if defined(TARG_SL)
04726 if( position ){
04727 BB_Insert_Op_After( bb, position, cand_op );
04728 if( OP_has_tag(position) ){
04729 LABEL_IDX tag_idx = 0;
04730 tag_idx = Get_OP_Tag( position );
04731 Is_True( tag_idx > 0, ("incorrect tag index") );
04732 Reset_OP_has_tag( position );
04733 Set_OP_Tag( cand_op, tag_idx );
04734 }
04735 } else
04736 #endif
04737 BB_Prepend_Op( bb, cand_op );
04738 Set_OP_opnd(cand_op, OP_PREDICATE_OPND, old_pred_tn);
04739
04740 if (Trace_GCM && GCM_Internal_Flag) {
04741 #pragma mips_frequency_hint NEVER
04742 Print_Trace_File(cand_op, bb, cand_bb, FALSE);
04743 fprintf (TFile, "GCM: OLD Schedule length: MOVEDFROM = %d MOVEDTO = %d\n",
04744 BBSCH_schedule_length(old_bbsch), BBSCH_schedule_length(old_cand_bbsch));
04745 fprintf (TFile, "GCM: NEW Schedule length: MOVEDFROM = %d MOVEDTO = %d\n",
04746 BBSCH_schedule_length(new_bbsch), BBSCH_schedule_length(new_cand_bbsch));
04747 }
04748
04749 Set_BB_SCHEDULE(bbsch);
04750 Set_BB_SCHEDULE(cand_bbsch);
04751 #ifdef KEY
04752
04753
04754
04755
04756
04757 bbsch = Schedule_BB_For_GCM (bb, from_hbs_type, &Sched);
04758 cand_bbsch = Schedule_BB_For_GCM (cand_bb, to_hbs_type, &Sched);
04759 #endif
04760 }
04761 else {
04762 #if defined(TARG_SL)
04763 if( Motion_Is_CIRC_ABOVE(motion_type) ){
04764 circ_above_moves++;
04765 Cumulate_Local_TN_Promotion(cand_op);
04766
04767 std::vector<OP*>::iterator pos;
04768 pos = find( left_ops.begin(), left_ops.end(), cand_op );
04769 if( pos != left_ops.end() )
04770 left_ops.erase( pos );
04771 else
04772 Is_True(0, ("the cand_op is not in left_ops") );
04773 }
04774 #endif
04775 num_moves++;
04776 Run_Cflow_GCM |= Is_BB_Empty(bb);
04777 #if !defined(TARG_SL)
04778 Reset_OP_visited(cand_op);
04779 #endif
04780 Reset_BB_scheduled(bb);
04781 Reset_BB_scheduled(cand_bb);
04782
04783
04784
04785
04786 if( bb != cand_bb )
04787 Reset_OP_visited(cand_op);
04788
04789 Perform_Post_GCM_Steps(bb, cand_bb, cand_op, motion_type,
04790 spec_type, &pred_bbs, loop, TRUE);
04791 BCOPY(new_bbsch, old_bbsch, sizeof (BBSCH));
04792 BCOPY(new_cand_bbsch, old_cand_bbsch, sizeof (BBSCH));
04793 #if defined(TARG_SL)
04794 if( Motion_Is_CIRC_ABOVE(motion_type) && OP_load(cand_op) )
04795 moved_loads = OP_LIST_Push( cand_op, moved_loads, &gcm_loop_pool );
04796 #endif
04797 if (Trace_GCM) {
04798 #pragma mips_frequency_hint NEVER
04799 Print_Trace_File(cand_op, bb, cand_bb, TRUE);
04800 fprintf (TFile, "GCM: OLD Schedule length: MOVEDFROM = %d MOVEDTO = %d\n",
04801 BBSCH_schedule_length(old_bbsch), BBSCH_schedule_length(old_cand_bbsch));
04802 fprintf (TFile, "GCM: NEW Schedule length: MOVEDFROM = %d MOVEDTO = %d\n",
04803 BBSCH_schedule_length(new_bbsch), BBSCH_schedule_length(new_cand_bbsch));
04804 }
04805 }
04806
04807
04808
04809
04810 if (BB_exit(bb) && BB_length(bb) >= 2) {
04811 OP *delay_op = BB_last_op(bb);
04812
04813 if (delay_op == NULL || !OP_noop(delay_op)) Reset_BB_scheduled(bb);
04814 }
04815
04816 op_id++;
04817 }
04818 L_Free();
04819
04820 #if !defined(TARG_SL)
04821 }
04822 #else
04823
04824 if( CG_GCM_enable_break_dependence && moved_loads )
04825 Break_Dependency( moved_loads, cand_bb );
04826 }
04827
04828 if( Motion_Is_CIRC_ABOVE(motion_type) ){
04829 TN_SET_ClearD( promoted_tns );
04830
04831 if( CG_GCM_enable_reduce_loop_count &&
04832 (circ_above_moves > 0) &&
04833 Loop_Is_Straight_Line(loop) )
04834 Reduce_Loop_Count( loop, bb );
04835
04836 if( CG_GCM_enable_dce &&
04837 circ_above_moves > 0 &&
04838 !LOOP_DCE_Skip_Loop_Binary_Search(loop_id) )
04839 GCM_Dead_Code_Elimination( loop, &gcm_loop_pool );
04840 }
04841 }
04842
04843
04844 if( CG_GCM_enable_merge_small_bbs )
04845 GCM_Merge_Small_BBs( loop, &gcm_loop_pool );
04846
04847 if( Trace_GCM_Dump_IR ){
04848 fprintf(TFile, "%s %s %s", DBar, "after gcm", DBar);
04849 Print_BB_No_Srclines(bb);
04850
04851
04852 if( GCM_Loop_Prolog ){
04853 fprintf(TFile, "%s %s %s", DBar, "GCM Prolog, after gcm", DBar);
04854 Print_BB_No_Srclines(GCM_Loop_Prolog);
04855 }
04856 #endif // TARG_SL
04857 }
04858 }
04859
04860 BB_MAP_Delete (bb_cycle_set_map);
04861
04862 if (Sched) {
04863 CXX_DELETE(Sched, &MEM_local_pool);
04864 }
04865 L_Free();
04866
04867 return num_moves;
04868 }
04869
04870 #if defined(TARG_SL)
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887 static inline INT32 LC_Number( TN * lc_tn );
04888 static void Reduce_Loop_Count( LOOP_DESCR *loop, BB *src_bb )
04889 {
04890 BB *epilog = NULL;
04891 BB *bb = NULL;
04892
04893 if( Trace_GCM )
04894 fprintf( TFile, "==Reduce_Loop_Count, for BB:%i\n", BB_id(src_bb) );
04895
04896 std::vector< LOOP_DESCR* >::const_iterator cit_loop;
04897 cit_loop = postprocessed_loops.begin();
04898 for( ; cit_loop != postprocessed_loops.end(); cit_loop++ ){
04899 if( *cit_loop == loop )
04900 Is_True( 0, ("a loop is postprocessed for two times") );
04901 }
04902 postprocessed_loops.push_back( loop );
04903
04904
04905 FOR_ALL_BB_SET_members(LOOP_DESCR_bbset(loop), bb) {
04906 BBLIST *succs;
04907 FOR_ALL_BB_SUCCS(bb, succs){
04908 BB *succ = BBLIST_item(succs);
04909 if( !BB_SET_MemberP(LOOP_DESCR_bbset(loop), succ) ){
04910 if( epilog && succ != epilog ){
04911 epilog = NULL;
04912 if( Trace_GCM )
04913 fprintf(TFile, "There are more than one epilogs");
04914 return;
04915 }
04916 epilog = succ;
04917 }
04918 }
04919 }
04920
04921 if( epilog == NULL ){
04922 if( Trace_GCM )
04923 fprintf( TFile, "This is an infinite loop, cannot find epilog" );
04924 return;
04925 }else{
04926 if( Trace_GCM )
04927 fprintf( TFile, "epilog is BB:%i\n", BB_id(epilog) );
04928 }
04929
04930
04931
04932 if( !left_ops.size() ){
04933 if( Trace_GCM )
04934 fprintf( TFile, "all OPs in srb_bb are moved" );
04935 return ;
04936 }
04937
04938
04939 BB *prolog = Loop_Is_Zdl( loop );
04940 if( !prolog )
04941 return;
04942
04943 BB *mvtc_host_bb = prolog;
04944 OP *mvtc = NULL;
04945
04946
04947 std::vector< Mvtc_Pos >::const_iterator cit;
04948 cit = mvtc_targets.begin();
04949 for( ; cit != mvtc_targets.end(); cit++ ){
04950 if( cit->orig_loop == loop ){
04951 Is_True( !mvtc, ("there are two same mvtc in mvtc_targets") );
04952 mvtc_host_bb = cit->host_bb;
04953 mvtc = cit->mvtc;
04954 }
04955 }
04956
04957
04958
04959 if( !mvtc ){
04960 OP *loop_op = BB_loop_op( prolog );
04961 Is_True( OP_is_loop(loop_op),
04962 ("last op of zdl loop prolog is not loop") );
04963
04964 TN *lp_lvl_tn = OP_opnd( loop_op, 0 );
04965 Is_True( TN_is_constant(lp_lvl_tn), ("lp_idx_tn is not constant") );
04966 INT32 lp_lvl = TN_value( lp_lvl_tn );
04967
04968 OP *op;
04969 FOR_ALL_BB_OPs( prolog, op ){
04970 if( OP_is_mvtc(op) ){
04971 TN *lp_tn = OP_result( op, 0 );
04972 INT32 lp_tn_value = LC_Number( lp_tn );
04973
04974 if( lp_tn_value == lp_lvl ){
04975 Is_True( !mvtc, ("There are two mvtc's with the same loop count reg") );
04976 mvtc = op;
04977 }
04978 }
04979 }
04980 }
04981
04982 Is_True( mvtc, ("cannot find the mvtc ") );
04983
04984
04985 if( Trace_GCM ){
04986 fprintf( TFile, "reducing loop %p count by 1, from:\n", loop );
04987 Print_OP_No_SrcLine( mvtc );
04988 }
04989
04990 if( OP_code(mvtc) == TOP_mvtc_i ){
04991 TN *tn = OP_opnd( mvtc, 0 );
04992 INT32 lp_val = TN_value( tn );
04993
04994 if( lp_val < 1 )
04995 return;
04996 TN *new_tn = Dup_TN( tn );
04997 Set_TN_value( new_tn, lp_val - 1 );
04998 Set_OP_opnd( mvtc, 0, new_tn );
04999
05000 if( Trace_GCM ){
05001 fprintf( TFile, "to:\n" );
05002 Print_OP_No_SrcLine( mvtc );
05003 }
05004 }else{
05005 Is_True( OP_code(mvtc) == TOP_mvtc, ("incorrect mvtc") );
05006
05007 TN *opnd_tn = OP_opnd(mvtc, 0);
05008 TN *new_tn = Dup_TN( opnd_tn );
05009 Set_OP_opnd( mvtc, 0, new_tn );
05010
05011
05012 OP *addi_op = Mk_OP( TOP_addiu, new_tn, opnd_tn, Gen_Literal_TN(-1,4) );
05013 BB_Insert_Op_Before( mvtc_host_bb, mvtc, addi_op );
05014
05015 if( Trace_GCM ){
05016 fprintf( TFile, "to:\n" );
05017 Print_OP_No_SrcLine( addi_op );
05018 Print_OP_No_SrcLine( mvtc );
05019 }
05020 }
05021
05022 if( Trace_GCM ){
05023 fprintf( TFile, "\n Before copying left OPs, epilog: \n" );
05024 Print_BB_No_Srclines( epilog );
05025
05026 fprintf( TFile, "\ncopy the left OPs to BB:%i\n", BB_id(epilog) );
05027 std::vector<OP*>::const_iterator cit = left_ops.begin();
05028 for( ; cit != left_ops.end(); cit++ )
05029 Print_OP_No_SrcLine( *cit );
05030
05031 }
05032
05033
05034
05035 std::vector<OP*>::reverse_iterator rit = left_ops.rbegin();
05036 for( ; rit != left_ops.rend(); rit++ ){
05037 OP *op = Dup_OP( *rit );
05038 BB_Prepend_Op( epilog, op );
05039 }
05040
05041 BB_SET *bbset;
05042 bbset = BB_SET_Union1D( LOOP_DESCR_bbset(loop), prolog, &gcm_loop_pool );
05043 bbset = BB_SET_Union1D( bbset, epilog, &gcm_loop_pool );
05044 BB_REGION region( bbset, &gcm_loop_pool );
05045 BB_REGION_Recompute_Global_Live_Info( region, TRUE );
05046
05047 if( Trace_GCM ){
05048 fprintf( TFile, "\n After copying left OPs, epilog: \n" );
05049 Print_BB_No_Srclines( epilog );
05050 }
05051 }
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074
05075
05076 typedef std::vector< int > Vector1D;
05077 typedef std::vector< Vector1D > Vector2D;
05078 static void MVTC_Opt_Internal( LOOP_DESCR *, Vector1D & );
05079
05080 static void MVTC_Optimization()
05081 {
05082 LOOP_DESCR_Create_Loop_Tree(&loop_descr_pool);
05083 if( Trace_GCM ){
05084 LOOP_DESCR_Dump_Loop_Tree();
05085 }
05086
05087 for( int i=0; i < VECTOR_count(loop_tree_roots); i++ ){
05088 LOOP_DESCR *loop = (LOOP_DESCR*)VECTOR_element( loop_tree_roots, i );
05089
05090
05091
05092
05093
05094
05095
05096
05097 Vector1D loop_num_per_lvl;
05098 loop_num_per_lvl.push_back(0);
05099 loop_num_per_lvl.push_back(0);
05100 loop_num_per_lvl.push_back(0);
05101 loop_num_per_lvl.push_back(0);
05102 MVTC_Opt_Internal( loop, loop_num_per_lvl );
05103 }
05104 }
05105
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115 static inline INT32 LC_Number( TN * lc_tn )
05116 {
05117
05118 if( lc_tn == LC0_TN )
05119 return 0;
05120 if( lc_tn == LC1_TN )
05121 return 1;
05122 if( lc_tn == LC2_TN )
05123 return 2;
05124 if( lc_tn == LC3_TN )
05125 return 3;
05126 Is_True( 0, ("bad loop counter reigster number") );
05127 return -1;
05128 }
05129
05130 static void MVTC_Opt_Internal( LOOP_DESCR *loop, Vector1D & loop_num )
05131 {
05132 int i = 0;
05133 Vector2D children_data;
05134
05135
05136 for( ; i < VECTOR_count( loop->children ); i++ ){
05137 Vector1D child_data;
05138 child_data.push_back(0);
05139 child_data.push_back(0);
05140 child_data.push_back(0);
05141 child_data.push_back(0);
05142 LOOP_DESCR *child_loop = (LOOP_DESCR*)VECTOR_element( loop->children, i );
05143 MVTC_Opt_Internal( child_loop, child_data );
05144 children_data.push_back( child_data );
05145 }
05146
05147
05148
05149
05150
05151
05152 for( int j=0; j < children_data.size(); j++ ){
05153 for( int k=0 ; k < 4; k++ ){
05154 loop_num[k] += children_data[j][k];
05155 }
05156 }
05157
05158 if( Trace_GCM ){
05159 fprintf( TFile, "OPTing loop:\n" );
05160 LOOP_DESCR_Dump_Loop_Brief( loop );
05161 fprintf( TFile, "it contains: \n" );
05162 for(int i=0 ; i < 4; i++ ){
05163 fprintf( TFile, " %i %ith level child loop\n", loop_num[i], i );
05164 }
05165 }
05166
05167
05168 BB *prolog = Loop_Is_Zdl(loop);
05169 if( !prolog )
05170 return;
05171
05172 OP *loop_op = BB_loop_op( prolog );
05173 Is_True( OP_is_loop(loop_op), ("last op of zdl loop prolog is not loop") );
05174
05175
05176
05177
05178
05179
05180 TN *lp_lvl_tn = OP_opnd( loop_op, 0 );
05181 Is_True( TN_is_constant(lp_lvl_tn), ("lp_idx_tn is not constant") );
05182 INT32 lp_lvl = TN_value( lp_lvl_tn );
05183
05184
05185 loop_num[lp_lvl] += 1;
05186
05187 for( i=0 ; i < 4; i++ ){
05188 for( int j=0; j < VECTOR_count(loop->children); j++ ){
05189
05190
05191 LOOP_DESCR *child_loop = (LOOP_DESCR*)VECTOR_element(loop->children, j);
05192 BB *child_head = LOOP_DESCR_loophead( child_loop );
05193 BB *child_prolog = Loop_Is_Zdl( child_loop );
05194 if( !child_prolog )
05195 continue;
05196
05197 Is_True( OP_is_loop(BB_loop_op(child_prolog)),
05198 ("last op of child zdl loop prolog is not a loop") );
05199
05200 OP *op;
05201 FOR_ALL_BB_OPs( child_prolog, op ){
05202
05203 if( OP_code(op) == TOP_mvtc_i ){
05204 TN *lvl_tn = OP_result( op, 0 );
05205 Is_True( TN_is_dedicated(lvl_tn), ("lvl_tn is not a dedicated tn") );
05206 INT32 level = LC_Number( lvl_tn );
05207 if( loop_num[level] == 1 ){
05208 BB_Remove_Op( child_prolog, op );
05209 Is_True( !Is_BB_Empty(prolog), ("the loop prolog is empty") );
05210 BB_Insert_Op_Before( prolog, BB_loop_op(prolog), op );
05211 if( Trace_GCM ){
05212 fprintf( TFile, ("following OP is moved from BB:%i to BB:%i\n"),
05213 BB_id(child_prolog), BB_id(prolog) );
05214 Print_OP_No_SrcLine( op );
05215 }
05216
05217 std::vector< Mvtc_Pos >::iterator pos = mvtc_targets.begin();
05218 for( ; pos != mvtc_targets.end(); pos++ ){
05219 if( pos->mvtc == op )
05220 break;
05221 }
05222 if( pos == mvtc_targets.end() ){
05223 Mvtc_Pos record;
05224 record.orig_loop = child_loop;
05225 record.mvtc = op;
05226 record.host_bb = prolog;
05227 mvtc_targets.push_back(record);
05228 }else{
05229 pos->host_bb = prolog;
05230 }
05231 }
05232 }
05233 }
05234 }
05235 }
05236
05237 return;
05238 }
05239 #endif // TARG_SL
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251
05252 void GCM_Schedule_Region (HBS_TYPE hbs_type)
05253 {
05254 LOOP_DESCR *loop_list;
05255 LOOP_DESCR *outer_loop;
05256 BB_SET *all_bbs;
05257 INT max_nestlevel;
05258 BB *bb;
05259 RID *rid;
05260 INT totalloops = 0;
05261 INT innerloops = 0;
05262 INT callloops = 0;
05263 INT multibbloops = 0;
05264 INT exitloops = 0;
05265 INT loopinfoloops = 0;
05266
05267 hbs_type |= HBS_FROM_GCM;
05268 cur_hbs_type = hbs_type;
05269 Run_Cflow_GCM = FALSE;
05270 if (hbs_type & (HBS_BEFORE_LRA | HBS_BEFORE_GRA)) {
05271
05272 Ignore_TN_Dep = FALSE;
05273 Cur_Gcm_Type = GCM_BEFORE_GRA;
05274
05275 if (GCM_Min_Reg_Usage) Cur_Gcm_Type |= GCM_MINIMIZE_REGS;
05276
05277 if (!GCM_PRE_Enable_Scheduling) return;
05278 } else {
05279 Ignore_TN_Dep = TRUE;
05280 Cur_Gcm_Type = GCM_AFTER_GRA;
05281
05282 if (!GCM_POST_Enable_Scheduling) return;
05283 }
05284
05285 #ifdef KEY
05286 cumulative_cand_bb = 0;
05287 #endif
05288
05289 if (Trace_GCM) {
05290 #pragma mips_frequency_hint NEVER
05291 fprintf (TFile, "GCM_For_Region: PU %s\n", Cur_PU_Name);
05292 }
05293
05294 Start_Timer (T_GCM_CU);
05295 Set_Error_Phase ("Global Code Motion");
05296 Trace_GCM = Get_Trace (TP_GCM, GCM_TRACE_NORMAL);
05297 Trace_GCM_Dump_IR = Get_Trace( TP_GCM, GCM_TRACE_DUMP_IR );
05298 Trace_GCM_Dump_Preprocess = Get_Trace( TP_GCM, GCM_TRACE_PREPROCESS );
05299 Trace_GCM_Merge_BBs = Get_Trace( TP_GCM, GCM_TRACE_MERGE_BBS );
05300
05301 MEM_POOL_Initialize (&loop_descr_pool, "LOOP_DESCR_pool", FALSE);
05302 MEM_POOL_Initialize (&gcm_loop_pool, "GCM loop pool", FALSE);
05303 MEM_POOL_Push(&loop_descr_pool);
05304 MEM_POOL_Push(&gcm_loop_pool);
05305
05306 Calculate_Dominators ();
05307 if (Ignore_TN_Dep) REG_LIVE_Analyze_Region ();
05308 CGTARG_Compute_Branch_Parameters(&mispredict, &fixed, &taken, ×);
05309
05310 L_Save();
05311
05312 loop_list = LOOP_DESCR_Detect_Loops (&loop_descr_pool);
05313
05314 #if defined(TARG_SL)
05315
05316 if( CG_enable_zero_delay_loop && CG_GCM_enable_mvtc_optimization ){
05317 mvtc_targets.clear();
05318 MVTC_Optimization();
05319 }
05320 #endif
05321
05322
05323
05324
05325 outer_loop = TYPE_L_ALLOC (LOOP_DESCR);
05326 BB_Mark_Unreachable_Blocks ();
05327 all_bbs = BB_SET_Create_Empty (PU_BB_Count+2, &loop_descr_pool);
05328 bbsch_map = BB_MAP_Create ();
05329 INT16 num_real_ops;
05330 INT num_of_nops;
05331 OP *op;
05332
05333
05334
05335
05336
05337 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
05338 if (BB_unreachable(bb)) continue;
05339
05340 BBSCH *bbsch = (BBSCH *)BB_MAP_Get (bbsch_map, bb);
05341 if (bbsch == NULL) {
05342 bbsch = TYPE_MEM_POOL_ALLOC (BBSCH, &gcm_loop_pool);
05343 BZERO (bbsch, sizeof (BBSCH));
05344 Set_BB_SCHEDULE(bbsch);
05345 }
05346
05347
05348
05349 num_of_nops = Check_If_Should_Align_BB(bb, INST_BYTES * cur_pc);
05350 if (num_of_nops || BB_entry(bb)) {
05351 Set_BB_num_align_nops(bbsch, num_of_nops);
05352 cur_pc = 0;
05353 Set_BB_ALIGNED(bbsch);
05354 }
05355
05356 Set_BB_start_pc(bbsch, cur_pc);
05357 INT16 num_ops = 0;
05358 for (op = BB_first_op(bb); op; op = OP_next(op)) {
05359 num_real_ops = OP_Real_Ops (op);
05360 cur_pc += num_real_ops;
05361 num_ops += num_real_ops;
05362 }
05363 Set_BB_num_real_ops(bbsch, num_ops);
05364 BB_MAP_Set (bbsch_map, bb, bbsch);
05365
05366 if ( (rid = BB_rid(bb)) && (RID_level(rid) >= RL_CGSCHED)) continue;
05367 if (BB_scheduled(bb) && !BB_scheduled_hbs(bb)) continue;
05368
05369 all_bbs = BB_SET_Union1D (all_bbs, bb, &loop_descr_pool);
05370 }
05371
05372 outer_loop->mem_pool = &loop_descr_pool;
05373 LOOP_DESCR_bbset(outer_loop) = all_bbs;
05374 LOOP_DESCR_loophead(outer_loop) = NULL;
05375 LOOP_DESCR_nestlevel(outer_loop) = 0;
05376 LOOP_DESCR_num_exits(outer_loop) = 0;
05377 LOOP_DESCR_next(outer_loop) = NULL;
05378 LOOP_DESCR_flags(outer_loop) = 0;
05379
05380
05381 max_nestlevel = 0;
05382 if (loop_list == NULL) {
05383 loop_list = outer_loop;
05384 }
05385 else {
05386 LOOP_DESCR *lastloop = NULL;
05387 for( LOOP_DESCR *cloop = loop_list;
05388 cloop != NULL;
05389 cloop = LOOP_DESCR_next(cloop) ) {
05390 lastloop = cloop;
05391 if (LOOP_DESCR_nestlevel(cloop) > max_nestlevel)
05392 max_nestlevel = LOOP_DESCR_nestlevel (cloop);
05393 }
05394 LOOP_DESCR_next(lastloop) = outer_loop;
05395 }
05396
05397 BB_SET *processed_bbs = BB_SET_Create_Empty (PU_BB_Count+2, &loop_descr_pool);
05398 INT num_moves = 0;
05399
05400
05401
05402
05403 LOOP_DESCR *cloop;
05404 for (cloop = loop_list; cloop != NULL; cloop = LOOP_DESCR_next(cloop)) {
05405
05406
05407 totalloops++;
05408 BB_SET *loop_bbs = LOOP_DESCR_bbset(cloop);
05409 BB_SET *tmpset = BB_SET_Intersection (processed_bbs,
05410 loop_bbs,
05411 &loop_descr_pool);
05412 if (BB_SET_EmptyP (tmpset)) {
05413 Set_Inner_Loop(cloop);
05414 innerloops++;
05415 if (LOOP_DESCR_loopinfo(cloop) != NULL) loopinfoloops++;
05416 INT bb_cnt = 0;
05417 BOOL has_call = FALSE;
05418 FOR_ALL_BB_SET_members (loop_bbs, bb) {
05419 bb_cnt++;
05420 if (BB_call (bb)) has_call = TRUE;
05421 }
05422 if (bb_cnt > 1) {
05423 multibbloops++;
05424 Set_Multibb_Loop(cloop);
05425 if (has_call) {
05426 callloops++;
05427 Set_Call_Loop(cloop);
05428 }
05429 if (LOOP_DESCR_num_exits(cloop) > 1) {
05430 exitloops++;
05431 Set_Exit_Loop(cloop);
05432 }
05433 }
05434 }
05435 }
05436
05437
05438
05439
05440 BB_SET_ClearD(processed_bbs);
05441 #if defined (TARG_SL)
05442 postprocessed_loops.clear();
05443 #endif
05444 loop_id=0;
05445 for (cloop = loop_list; cloop != NULL; cloop = LOOP_DESCR_next(cloop))
05446 {
05447 #if defined(TARG_SL)
05448
05449
05450 if ( CG_GCM_enable_licm && LOOP_DESCR_loophead(cloop)
05451 && !BB_rid(LOOP_DESCR_loophead(cloop)) ) {
05452 if( !GCM_LICM_Skip_Loop_Binary_Search(loop_id) )
05453 Perform_Loop_Invariant_Code_Motion(cloop, &gcm_loop_pool, Ignore_TN_Dep);
05454 }
05455
05456
05457
05458 if ( CG_GCM_enable_rce &&
05459 LOOP_DESCR_loophead(cloop) &&
05460 !BB_rid(LOOP_DESCR_loophead(cloop)) ) {
05461 LOOP_Redundant_Copy_Elimination( cloop, &gcm_loop_pool );
05462 }
05463 #else
05464
05465
05466 if (LOOP_DESCR_nestlevel(cloop) <= (max_nestlevel - CG_opt_level))
05467 continue;
05468 #endif
05469
05470 GCM_Loop_Prolog = NULL;
05471 #if defined(TARG_SL)
05472 if( !GCM_Skip_Loop_Binary_Search(loop_id) )
05473 {
05474 num_moves += GCM_For_Loop (cloop, processed_bbs, hbs_type);
05475 if (Trace_GCM)
05476 fprintf(TFile, ".. Loop:%d, is done by GCM\n", loop_id );
05477 } else {
05478 if (Trace_GCM)
05479 fprintf(TFile, ".. Loop:%d, is skipped by GCM\n", loop_id );
05480 }
05481 #endif
05482 processed_bbs = BB_SET_UnionD (processed_bbs, LOOP_DESCR_bbset(cloop),
05483 &loop_descr_pool);
05484 loop_id++;
05485 }
05486
05487 if (Trace_GCM) {
05488 #pragma mips_frequency_hint NEVER
05489 fprintf (TFile, "GCM_For_Loop: Loop characteristics \n");
05490 fprintf (TFile, "\ttotalloops %d\n", totalloops);
05491 fprintf (TFile, "\tinnerloops %d\n", innerloops);
05492 fprintf (TFile, "\tmultibbloops %d\n", multibbloops);
05493 fprintf (TFile, "\texitloops %d\n", exitloops);
05494 fprintf (TFile, "\tcallloops %d\n", callloops);
05495 fprintf (TFile, "\tloopinfoloops %d\n", loopinfoloops);
05496 fprintf (TFile, "\tNumber of moves: %d\n", num_moves);
05497 }
05498
05499 if (Ignore_TN_Dep) REG_LIVE_Finish ();
05500 BB_MAP_Delete (bbsch_map);
05501 L_Free();
05502 Free_Dominators_Memory ();
05503 MEM_POOL_Pop (&loop_descr_pool);
05504 MEM_POOL_Pop (&gcm_loop_pool);
05505 MEM_POOL_Delete (&loop_descr_pool);
05506 MEM_POOL_Delete (&gcm_loop_pool);
05507
05508 Stop_Timer (T_GCM_CU);
05509 Check_for_Dump (TP_GCM, NULL);
05510 }
05511
05512 #if defined (TARG_SL)
05513
05514
05515 static bool GCM_Skip_Loop_Binary_Search( int loop_id )
05516 {
05517 BOOL skip = Should_Skip( CG_GCM_loop_skip_before,
05518 CG_GCM_loop_skip_after,
05519 CG_GCM_loop_skip_equal,
05520 loop_id );
05521 return skip;
05522 }
05523
05524 static BOOL GCM_Skip_Op_Binary_Search( INT32 op_id )
05525 {
05526 BOOL skip = Should_Skip( CG_GCM_op_skip_before,
05527 CG_GCM_op_skip_after,
05528 CG_GCM_op_skip_equal,
05529 op_id );
05530 return skip;
05531 }
05532
05533 static BOOL GCM_LICM_Skip_Loop_Binary_Search( int loop_id )
05534 {
05535 BOOL skip = Should_Skip( CG_GCM_LICM_loop_skip_before,
05536 CG_GCM_LICM_loop_skip_after,
05537 CG_GCM_LICM_loop_skip_equal,
05538 loop_id );
05539 return skip;
05540 }
05541
05542 static BOOL GCM_LICM_Skip_Op_Binary_Search( int op_id )
05543 {
05544 BOOL skip = Should_Skip( CG_GCM_LICM_op_skip_before,
05545 CG_GCM_LICM_op_skip_after,
05546 CG_GCM_LICM_op_skip_equal,
05547 op_id );
05548 return skip;
05549 }
05550
05551 static BOOL LOOP_DCE_Skip_Loop_Binary_Search( int loop_id )
05552 {
05553 BOOL skip = Should_Skip( CG_LOOP_DCE_loop_skip_before,
05554 CG_LOOP_DCE_loop_skip_after,
05555 CG_LOOP_DCE_loop_skip_equal,
05556 loop_id );
05557 return skip;
05558 }
05559
05560 BOOL LOOP_DCE_Skip_Op_Binary_Search( int op_id )
05561 {
05562 BOOL skip = Should_Skip( CG_LOOP_DCE_op_skip_before,
05563 CG_LOOP_DCE_op_skip_after,
05564 CG_LOOP_DCE_op_skip_equal,
05565 op_id );
05566 return skip;
05567 }
05568
05569
05570
05571
05572
05573 static BOOL GCM_Skip_Op( OP* cand_op, BB* src_bb, OP_LIST* moved_loads )
05574 {
05575 BOOL got_load_and_incr_add = FALSE;
05576 if( OP_code(cand_op)==TOP_addi || OP_code(cand_op)==TOP_add16_i ||
05577 OP_code(cand_op)==TOP_addiu ){
05578
05579 TN *addop_res, *addop_opnd;
05580 addop_res = OP_result( cand_op, 0 );
05581 addop_opnd = OP_opnd( cand_op, 0 );
05582 if( TN_number(addop_res) == TN_number(addop_opnd) ){
05583
05584 OP_LIST *loads = moved_loads;
05585 while( loads ){
05586 OP *load = OP_LIST_first( loads );
05587 Is_True( OP_load(load), ("OP not a load, in moved_loads") );
05588
05589 TN *load_base_tn = OP_opnd(load, 0);
05590
05591 if( TN_number(load_base_tn) == TN_number(addop_res) ){
05592
05593
05594
05595
05596 BOOL redefine = FALSE;
05597 OP *temp_op = load;
05598 for( ; temp_op && temp_op != cand_op; temp_op = OP_next(temp_op) ){
05599 INT32 results = OP_results(temp_op);
05600 for( INT32 i=0; i < results; i++ ){
05601 if( TN_is_constant(OP_result(temp_op,i)) )
05602 continue;
05603 if( TN_number(load_base_tn) == TN_number( OP_result(temp_op,i) ) ){
05604 redefine = TRUE;
05605 break;
05606 }
05607 }
05608 }
05609
05610
05611
05612 if( redefine )
05613 return TRUE;
05614 else {
05615
05616
05617
05618
05619 load_add_pairs.push_back( std::make_pair(load, cand_op) );
05620 return FALSE;
05621 }
05622 }
05623 loads = OP_LIST_rest( loads );
05624 }
05625 }
05626 }
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651 for( INT32 i=0; i < OP_opnds(cand_op); i++ ){
05652 TN *cand_tn = OP_opnd(cand_op, i);
05653 if( TN_is_constant(cand_tn) )
05654 continue;
05655
05656 std::vector< std::pair<OP*, OP*> >::const_iterator cit;
05657 for( cit = load_add_pairs.begin(); cit != load_add_pairs.end(); cit++ ){
05658 OP *load = cit->first;
05659 OP *add = cit->second;
05660 Is_True( TN_number(OP_opnd(load,0)) == TN_number(OP_result(add,0)),
05661 (" result of load is not same as opnd of add ") );
05662 if( TN_number(cand_tn) == TN_number(OP_opnd(load,0)) ){
05663 return TRUE;
05664 }
05665 }
05666 }
05667
05668 return FALSE;
05669 }
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687
05688
05689
05690
05691
05692
05693
05694 typedef enum {
05695 UPWARD,
05696 DOWNWARD
05697 }DIRECTION;
05698
05699 typedef struct
05700 {
05701 OP *addi_op;
05702 OP *load_op;
05703 DIRECTION dir;
05704 } Tuple;
05705
05706 static void Preprocess_Loop_Head( BB* head )
05707 {
05708
05709 std::vector<Tuple> movable_tuples;
05710
05711 OP* op;
05712 OP* addi_op;
05713 FOR_ALL_BB_OPs( head, addi_op ){
05714 if( OP_code(addi_op)==TOP_addi || OP_code(addi_op)==TOP_add16_i ||
05715 OP_code(addi_op)==TOP_addiu ){
05716 Is_True( OP_results(addi_op)==1, ("add.i op has more than one results") );
05717 TN *base_tn = OP_result(addi_op, 0);
05718
05719
05720
05721
05722 if( TN_number(base_tn) != TN_number(OP_opnd(addi_op,0)) )
05723 break;
05724
05725
05726 BOOL redef = FALSE;
05727 BOOL reuse = FALSE;
05728 for( op = OP_next(addi_op); op; op = OP_next(op) ){
05729 if( OP_load(op) && OP_opnds(op)==2 &&
05730 TN_number(base_tn) == TN_number(OP_opnd(op,0)) ){
05731 TN *load_base_tn = OP_opnd(op, 0);
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745
05746
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756
05757 if( !redef && !reuse ){
05758 Tuple t = {addi_op, op, DOWNWARD};
05759 movable_tuples.push_back( t );
05760 if( Trace_GCM_Dump_Preprocess ){
05761 fprintf( TFile, "-- GCM:Preprocess_loop_head exchange the two OPs --\n" );
05762 Print_OP_No_SrcLine(addi_op);
05763 Print_OP_No_SrcLine(op);
05764 }
05765 }else{
05766 BOOL predef = FALSE;
05767 BOOL preuse = FALSE;
05768 TN *res_tn = OP_result( op, 0 );
05769 OP *prev_op;
05770 for( prev_op = OP_prev(op);
05771 prev_op && prev_op != addi_op;
05772 prev_op = OP_prev(prev_op) ){
05773
05774 for( INT32 i=0; i < OP_results(prev_op); i++ ){
05775 TN *temp_res = OP_result(prev_op, i);
05776 if( TN_is_constant(temp_res) )
05777 continue;
05778 if( TN_number(temp_res) == TN_number(res_tn) )
05779 predef = TRUE;
05780 }
05781
05782 for( INT32 i=0; i < OP_opnds(prev_op); i++ ){
05783 TN *temp_opnd = OP_opnd(prev_op, i);
05784 if( TN_is_constant(temp_opnd) )
05785 continue;
05786 if( TN_number(temp_opnd) == TN_number(res_tn) )
05787 preuse = TRUE;
05788 }
05789 }
05790
05791 if( !predef && !preuse ){
05792 Tuple t = {addi_op, op, UPWARD};
05793 movable_tuples.push_back( t );
05794 if( Trace_GCM_Dump_Preprocess ){
05795 fprintf(TFile, "-- GCM:Preprocess_loop_head exchange the two OPs --\n");
05796 Print_OP_No_SrcLine(addi_op);
05797 Print_OP_No_SrcLine(op);
05798 }
05799 }
05800 }
05801
05802 }
05803
05804 for( INT32 i=0; i < OP_results(op); i++ ){
05805 TN *temp_res = OP_result(op, i);
05806 if( TN_is_constant(temp_res) )
05807 continue;
05808 if( TN_number(temp_res) == TN_number(base_tn) )
05809 redef = TRUE;
05810 }
05811
05812 for( INT32 i=0; i < OP_opnds(op); i++ ){
05813 TN *temp_opnd = OP_opnd(op, i);
05814 if( TN_is_constant(temp_opnd) )
05815 continue;
05816 if( TN_number(temp_opnd) == TN_number(base_tn) )
05817 reuse = TRUE;
05818 }
05819 }
05820 }
05821 }
05822
05823
05824
05825
05826
05827 std::vector<Tuple>::const_iterator cit = movable_tuples.begin();
05828 for( ; cit != movable_tuples.end(); cit++ ){
05829
05830 if( cit->dir == UPWARD )
05831 BB_Move_Op_Before( head, cit->addi_op, head, cit->load_op );
05832 else
05833 BB_Move_Op_After( head, cit->load_op, head, cit->addi_op );
05834
05835 TN *incre_tn = OP_opnd( cit->addi_op, 1 );
05836 INT64 increment = TN_value(incre_tn);
05837 TN *offset_tn = OP_opnd( cit->load_op, 1 );
05838 INT64 offset = TN_value(offset_tn);
05839 TN *new_offset_tn = Dup_TN( offset_tn );
05840 Set_TN_value( new_offset_tn, increment + offset );
05841 Set_OP_opnd( cit->load_op, 1, new_offset_tn );
05842 }
05843 }
05844
05845
05846
05847
05848
05849
05850
05851
05852
05853
05854
05855
05856
05857
05858
05859
05860
05861
05862
05863
05864 static void Find_Last_Defs_Of_Branch( BB* head )
05865 {
05866 if( Is_BB_Empty(head) )
05867 return;
05868
05869 OP *br_op = BB_last_op(head);
05870 if( br_op && OP_br(br_op) ){
05871 Is_True( br_op == BB_branch_op(head), ("the two macro of finding branch op is not consistent") );
05872
05873 for( int i=0; i < OP_opnds(br_op); i++ ){
05874 TN *opnd_tn = OP_opnd(br_op, i);
05875 OP *def_op;
05876 FOR_ALL_BB_OPs_REV( head, def_op ){
05877 if( OP_Defs_TN(def_op, opnd_tn) ){
05878 last_defs_of_branch.push_back(def_op);
05879 break;
05880 }
05881 }
05882 }
05883 }
05884
05885 return;
05886 }
05887
05888
05889
05890
05891
05892
05893
05894
05895
05896 static void Relaxed_Topo_Sort( LOOP_DESCR *loop,
05897 std::vector<BB*> *sorted,
05898 MEM_POOL *pool )
05899 {
05900 BB *head = LOOP_DESCR_loophead(loop);
05901 BB_SET *body = LOOP_DESCR_bbset(loop);
05902
05903 sorted->push_back(head);
05904
05905 std::list<BB*> working_list;
05906 working_list.push_back(head);
05907
05908
05909
05910
05911 BB_SET *visited = BB_SET_Create_Empty(PU_BB_Count, pool);
05912 visited = BB_SET_Union1D (visited, head, pool);
05913
05914 BB *cur;
05915 while( !working_list.empty() ){
05916 cur = working_list.front();
05917 working_list.pop_front();
05918
05919 BBLIST *s;
05920 BOOL got_one = FALSE;
05921 FOR_ALL_BB_SUCCS(cur, s){
05922 BB* succ = BBLIST_item(s);
05923 if( !BB_SET_MemberP(body,succ) || BB_SET_MemberP(visited,succ) )
05924 continue;
05925
05926 BOOL all_pred_visited = TRUE;
05927 if(succ != head){
05928 BBLIST *p;
05929 FOR_ALL_BB_PREDS(succ, p){
05930 BB* pred = BBLIST_item (p);
05931 if( (pred != cur) && !BB_SET_MemberP(visited, pred) ) {
05932 all_pred_visited = FALSE;
05933 break;
05934 }
05935 }
05936 }
05937
05938 if(all_pred_visited){
05939 visited = BB_SET_Union1D (visited, succ, pool);
05940 sorted->push_back(succ);
05941 working_list.push_back(succ);
05942 got_one = TRUE;
05943 }
05944 }
05945
05946
05947
05948 FOR_ALL_BB_SUCCS(cur, s){
05949 BB* succ = BBLIST_item(s);
05950 if( !BB_SET_MemberP(body,succ) || BB_SET_MemberP(visited,succ) )
05951 continue;
05952 visited = BB_SET_Union1D (visited, succ, pool);
05953 sorted->push_back(succ);
05954 working_list.push_back(succ);
05955 }
05956 }
05957 }
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974 static void GCM_Merge_Small_BBs( LOOP_DESCR *loop, MEM_POOL *pool )
05975 {
05976 if( !LOOP_DESCR_loophead(loop) ){
05977 if( Trace_GCM_Merge_BBs )
05978 fprintf( TFile, " no loop head, not a real loop, wont merge bbs\n");
05979 return;
05980 }
05981
05982 GRA_LIVE_Init(NULL);
05983
05984 INT32 move_num = 0;
05985
05986 std::vector<BB*> sorted;
05987 Relaxed_Topo_Sort( loop, &sorted, pool );
05988
05989 std::vector<BB*>::const_iterator cit = sorted.begin();
05990 if( Trace_GCM_Merge_BBs ){
05991 fprintf( TFile, " === Begin GCM_Merge_Small_BBs ===\n" );
05992 fprintf( TFile, " the relaxed topo sort ordering of all BBs is: " );
05993 for( cit = sorted.begin(); cit != sorted.end(); cit++ )
05994 fprintf( TFile, " %i", BB_id(*cit) );
05995 fprintf( TFile, "\n" );
05996 }
05997
05998 cit = sorted.begin();
05999 for(; cit != sorted.end(); cit++ ){
06000 BB *cur_bb = *cit;
06001
06002 BB *fall_thru = NULL;
06003 if( BB_next(cur_bb) && BB_Find_Succ(cur_bb, BB_next(cur_bb)) )
06004 fall_thru = BB_next(cur_bb);
06005
06006
06007 if( !fall_thru || BB_succs_len(cur_bb) != 1 || BB_preds_len(fall_thru) != 1 )
06008 continue;
06009
06010
06011 OP *last_op = BB_last_op(cur_bb);
06012 if( !last_op || OP_call(last_op) )
06013 continue;
06014
06015 if( Trace_GCM_Merge_BBs ){
06016 fprintf( TFile, "before merging:\n" );
06017 Print_BB_No_Srclines( cur_bb );
06018 Print_BB_No_Srclines( fall_thru );
06019 }
06020
06021
06022
06023 if( OP_br(last_op) ){
06024 Is_True( OP_jump(last_op), ("last op in pred BB must be jump") );
06025 BB_Remove_Op( cur_bb, last_op );
06026 if( Trace_GCM_Merge_BBs )
06027 fprintf( TFile, "the last OP is jump, remove it\n" );
06028 }
06029
06030
06031 OP *op = NULL;
06032 FOR_ALL_BB_OPs_REV( cur_bb, op ){
06033 BB_Remove_Op( cur_bb, op );
06034 BB_Prepend_Op( fall_thru, op );
06035 move_num++;
06036 }
06037
06038 if( Trace_GCM_Merge_BBs ){
06039 fprintf( TFile, " after merging:\n");
06040 Print_BB_No_Srclines( cur_bb );
06041 Print_BB_No_Srclines( fall_thru );
06042 }
06043 }
06044
06045 if( Trace_GCM_Merge_BBs )
06046 fprintf( TFile, "total moves:%i\n", move_num );
06047
06048 GRA_LIVE_Init(NULL);
06049 }
06050 #endif // TARG_SL