00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 #ifdef USE_PCH
00123 #include "cg_pch.h"
00124 #endif // USE_PCH
00125 #pragma hdrstop
00126
00127 #ifdef _KEEP_RCS_ID
00128 static const char source_file[] = __FILE__;
00129 #endif
00130
00131 #include <alloca.h>
00132
00133 #include "defs.h"
00134 #include "errors.h"
00135 #include "mempool.h"
00136 #include "tracing.h"
00137 #include "timing.h"
00138 #include "cgir.h"
00139 #include "tn_map.h"
00140 #include "cg_loop.h"
00141 #include "cg.h"
00142 #include "cgexp.h"
00143 #include "register.h"
00144 #include "cg_region.h"
00145 #include "wn.h"
00146 #include "region_util.h"
00147 #include "op_list.h"
00148 #include "cgprep.h"
00149 #include "gtn_universe.h"
00150 #include "gtn_set.h"
00151 #include "cg_db_op.h"
00152 #include "whirl2ops.h"
00153 #include "cgtarget.h"
00154 #include "gra_live.h"
00155 #include "reg_live.h"
00156 #include "cflow.h"
00157 #include "cg_spill.h"
00158 #include "targ_proc_properties.h"
00159 #ifdef TARG_IA64
00160 #include "vt_region.h"
00161 #endif
00162 #include "ebo.h"
00163 #include "ebo_info.h"
00164 #include "ebo_special.h"
00165 #include "ebo_util.h"
00166 #ifdef TARG_IA64
00167 #include "ipfec_options.h"
00168 #endif
00169 #ifdef TARG_X8664
00170 #include "targ_sim.h"
00171 #include "config_wopt.h"
00172 #include "config_lno.h"
00173 #include "xstats.h"
00174
00175 static void Init_Remove_Dead_LRA_Stores(BS **bs, MEM_POOL *pool);
00176 static void Mark_LRA_Spill_Reference(OP *op, BS **bs, MEM_POOL *pool);
00177 static BOOL Delete_Dead_LRA_Spill(OP *op, BS **bs);
00178 #endif
00179
00180
00181
00182
00183
00184 #if defined(TARG_SL)
00185
00186 INT32 EBO_Opt_Level_Default = 0;
00187 #else
00188 INT32 EBO_Opt_Level_Default = 5;
00189 #endif
00190 INT32 EBO_Opt_Level = 5;
00191 #ifdef KEY
00192 INT32 EBO_Opt_Mask = -1;
00193 #endif
00194 BOOL CG_skip_local_ebo = FALSE;
00195
00196 INT EBO_tninfo_number = 0;
00197 EBO_TN_INFO *EBO_free_tninfo = NULL;
00198 EBO_TN_INFO *EBO_first_tninfo = NULL;
00199 EBO_TN_INFO *EBO_last_tninfo = NULL;
00200 EBO_OP_INFO *EBO_free_opinfo = NULL;
00201 EBO_OP_INFO *EBO_first_opinfo = NULL;
00202 EBO_OP_INFO *EBO_last_opinfo = NULL;
00203 EBO_OP_INFO *EBO_opinfo_table[EBO_MAX_OP_HASH];
00204
00205
00206 BOOL EBO_in_pre = FALSE;
00207 BOOL EBO_in_before_unrolling = FALSE;
00208 BOOL EBO_in_after_unrolling = FALSE;
00209 BOOL EBO_in_peep = FALSE;
00210
00211
00212 BOOL EBO_in_loop = FALSE;
00213
00214 #ifdef KEY
00215 #if !defined(TARG_SL)
00216 BOOL EBO_can_delete_branch_delay_OP = TRUE;
00217 #else
00218 BOOL EBO_can_delete_branch_delay_OP = FALSE;
00219 #endif
00220 BOOL EBO_no_liveness_info_available = FALSE;
00221 BOOL EBO_optimize_single_BB = FALSE;
00222 #endif
00223
00224 TN_MAP EBO_tninfo_table;
00225 MEM_POOL EBO_pool;
00226
00227 INT EBO_num_tninfo_entries = 0;
00228 INT EBO_tninfo_entries_reused = 0;
00229 INT EBO_num_opinfo_entries = 0;
00230 INT EBO_opinfo_entries_reused = 0;
00231
00232 const char *EBO_trace_pfx;
00233 BOOL EBO_Trace_Execution = FALSE;
00234 BOOL EBO_Trace_Optimization = FALSE;
00235 BOOL EBO_Trace_Block_Flow = FALSE;
00236 BOOL EBO_Trace_Data_Flow = FALSE;
00237 BOOL EBO_Trace_Hash_Search = FALSE;
00238 #ifdef TARG_IA64
00239
00240 BOOL EBO_After_RGN_Form = FALSE;
00241 #endif
00242
00243
00244
00245
00246 static BOOL in_delay_slot = FALSE;
00247 static BOOL rerun_cflow = FALSE;
00248
00249 #ifdef KEY
00250
00251
00252
00253
00254
00255 static int avail_regs_count[ISA_REGISTER_CLASS_MAX+1];
00256
00257
00258 static OP_MAP Regs_Delta_Map[ISA_REGISTER_CLASS_MAX+1];
00259
00260
00261 static hTN_MAP regs_map = NULL;
00262
00263
00264 typedef union {
00265 void *ptr;
00266 struct {
00267 unsigned int def_count : 15;
00268 unsigned int last_use_op_num : 15;
00269 unsigned int reg_assigned : 1;
00270 }s;
00271 } EBO_REG_ENTRY;
00272
00273 #define EBO_REG_ENTRY_ptr(re) (re.ptr)
00274 #define EBO_REG_ENTRY_def_count(re) (re.s.def_count)
00275 #define EBO_REG_ENTRY_reg_assigned(re) (re.s.reg_assigned)
00276 #define EBO_REG_ENTRY_last_use_OP_num(re) (re.s.last_use_op_num)
00277
00278 #ifdef KEY
00279 static void EBO_Adjust_Pred_Branch_Target (BB *bb);
00280 #endif
00281
00282
00283
00284 static void
00285 Estimate_Reg_Usage (BB *bb, MEM_POOL *pool)
00286 {
00287 OP *op;
00288 EBO_REG_ENTRY reginfo;
00289 INT32 global_regs_used[ISA_REGISTER_CLASS_MAX+1],
00290 regs_delta[ISA_REGISTER_CLASS_MAX+1];
00291 ISA_REGISTER_CLASS cl;
00292 INT i, op_num = 0;
00293
00294 regs_map = hTN_MAP_Create(pool);
00295
00296 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00297 global_regs_used[cl] = 0;
00298 }
00299
00300
00301
00302 FOR_ALL_BB_OPs_FWD (bb, op) {
00303 op_num++;
00304 for (i = 0; i < OP_results(op); i++) {
00305 TN *result_tn = OP_result(op, i);
00306 EBO_REG_ENTRY_ptr(reginfo) = hTN_MAP_Get (regs_map, result_tn);
00307 EBO_REG_ENTRY_def_count(reginfo)++;
00308 if (TN_is_global_reg(result_tn) || TN_is_dedicated(result_tn)) {
00309 if (!EBO_REG_ENTRY_reg_assigned(reginfo)) {
00310 cl = TN_register_class(result_tn);
00311 global_regs_used[cl]++;
00312 EBO_REG_ENTRY_reg_assigned(reginfo) = TRUE;
00313 }
00314 }
00315 hTN_MAP_Set (regs_map, result_tn, EBO_REG_ENTRY_ptr(reginfo));
00316 }
00317 for (i = 0; i < OP_opnds(op); i++) {
00318 TN *opnd_tn = OP_opnd(op,i);
00319 if (TN_is_constant(opnd_tn)) continue;
00320 if (TN_is_global_reg(opnd_tn) || TN_is_dedicated(opnd_tn)) {
00321 EBO_REG_ENTRY_ptr(reginfo) = hTN_MAP_Get (regs_map, opnd_tn);
00322 if (!EBO_REG_ENTRY_reg_assigned(reginfo)) {
00323 cl = TN_register_class(opnd_tn);
00324 global_regs_used[cl]++;
00325 EBO_REG_ENTRY_reg_assigned(reginfo) = TRUE;
00326 hTN_MAP_Set (regs_map, opnd_tn, EBO_REG_ENTRY_ptr(reginfo));
00327 }
00328 }
00329 }
00330 }
00331
00332
00333 FOR_ALL_BB_OPs_REV (bb, op) {
00334 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00335 regs_delta[cl] = 0;
00336 }
00337 for (i = 0; i < OP_results(op); i++) {
00338 TN *result_tn = OP_result(op, i);
00339 EBO_REG_ENTRY_ptr(reginfo) = hTN_MAP_Get (regs_map, result_tn);
00340 EBO_REG_ENTRY_def_count(reginfo)--;
00341 if (EBO_REG_ENTRY_def_count(reginfo) == 0 &&
00342 EBO_REG_ENTRY_reg_assigned(reginfo))
00343 {
00344 ISA_REGISTER_CLASS cl = TN_register_class(result_tn);
00345 regs_delta[cl]++;
00346 EBO_REG_ENTRY_reg_assigned(reginfo) = FALSE;
00347 }
00348 hTN_MAP_Set (regs_map, result_tn, EBO_REG_ENTRY_ptr(reginfo));
00349 }
00350 for (i = 0; i < OP_opnds(op); i++) {
00351 TN *opnd_tn = OP_opnd(op,i);
00352 if (TN_is_constant(opnd_tn)) continue;
00353 EBO_REG_ENTRY_ptr(reginfo) = hTN_MAP_Get (regs_map, opnd_tn);
00354 if (!EBO_REG_ENTRY_reg_assigned(reginfo)) {
00355 ISA_REGISTER_CLASS cl = TN_register_class(opnd_tn);
00356 regs_delta[cl]--;
00357 EBO_REG_ENTRY_reg_assigned(reginfo) = TRUE;
00358 if (EBO_REG_ENTRY_last_use_OP_num(reginfo) == 0)
00359 EBO_REG_ENTRY_last_use_OP_num(reginfo) = op_num;
00360 hTN_MAP_Set (regs_map, opnd_tn, EBO_REG_ENTRY_ptr(reginfo));
00361 }
00362 }
00363
00364
00365 if (op_num == 1) {
00366 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00367 regs_delta[cl] += global_regs_used[cl];
00368 }
00369 }
00370
00371 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00372 OP_MAP32_Set(Regs_Delta_Map[cl], op, regs_delta[cl]);
00373 }
00374 op_num--;
00375 }
00376 }
00377
00378
00379 static void
00380 Extend_Live_Range (int *regs_used, int *last_fat_point, int op_num,
00381 EBO_TN_INFO *tninfo, EBO_REG_ENTRY reginfo, BB *bb)
00382 {
00383 int i;
00384 ISA_REGISTER_CLASS cl = TN_register_class(tninfo->local_tn);
00385 int regs_avail = avail_regs_count[cl];
00386
00387
00388 int last_use_op = (tninfo->in_bb == bb) ?
00389 EBO_REG_ENTRY_last_use_OP_num(reginfo) : 1;
00390
00391 for (i = op_num - 1; i >= last_use_op; i--) {
00392 EBO_REG(regs_used, cl, i)++;
00393 if (EBO_REG(regs_used, cl, i) > regs_avail) {
00394 last_fat_point[cl] = i;
00395
00396
00397 break;
00398 }
00399 }
00400
00401
00402 EBO_REG_ENTRY_last_use_OP_num(reginfo) = op_num;
00403 hTN_MAP_Set(regs_map, tninfo->local_tn, EBO_REG_ENTRY_ptr(reginfo));
00404 }
00405
00406
00407
00408 static void
00409 Update_Reg_Usage (OP *op, int op_num, int *regs_used, int *last_fat_point,
00410 BOOL op_is_deleted_load)
00411 {
00412 ISA_REGISTER_CLASS cl;
00413
00414 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00415 int regs_delta_at_op = OP_MAP32_Get(Regs_Delta_Map[cl], op);
00416 int regs_avail = avail_regs_count[cl];
00417 int regs_used_after_op =
00418 EBO_REG(regs_used, cl, op_num-1) + regs_delta_at_op;
00419 if (regs_used_after_op > regs_avail)
00420 last_fat_point[cl] = op_num;
00421 EBO_REG(regs_used, cl, op_num) = regs_used_after_op;
00422 }
00423
00424
00425 if (op_is_deleted_load) {
00426 cl = TN_register_class(OP_result(op, 0));
00427 EBO_REG(regs_used, cl, op_num)--;
00428 }
00429 }
00430 #endif
00431
00432
00433
00434
00435
00436
00437
00438 #define BB_visited BB_local_flag1
00439 #define Set_BB_visited Set_BB_local_flag1
00440 #define Reset_BB_visited Reset_BB_local_flag1
00441
00442 inline void clear_bb_flag(BB *first_bb)
00443 {
00444 BB *bb;
00445 for (bb = first_bb; bb != NULL; bb = BB_next(bb)) {
00446 BBLIST *succ_list;
00447
00448 Reset_BB_visited(bb);
00449
00450 FOR_ALL_BB_SUCCS(bb, succ_list) {
00451 BB *succ = BBLIST_item(succ_list);
00452 Reset_BB_visited(succ);
00453 }
00454
00455 }
00456 }
00457
00458
00459
00460 static
00461 BOOL EBO_Fix_Same_Res_Op (OP *op,
00462 TN **opnd_tn,
00463 EBO_TN_INFO **opnd_tninfo)
00464 {
00465 if (EBO_in_loop) return FALSE;;
00466
00467 if (OP_unalign_ld(op)) {
00468 TN *res = OP_result(op, 0);
00469 TN *tnl = OP_opnd(op, OP_opnds(op)-1);
00470
00471 if (!TN_is_zero_reg(tnl) && !tn_registers_identical(res, tnl)) {
00472
00473 OPS ops = OPS_EMPTY;
00474 TN *new_res = Dup_TN (res);
00475 OP *new_op = Dup_OP (op);
00476 Exp_COPY(new_res, tnl, &ops);
00477 Set_OP_result(new_op, 0, new_res);
00478 Set_OP_opnd(new_op, OP_opnds(op)-1, new_res);
00479 OPS_Append_Op(&ops, new_op);
00480 Exp_COPY(res, new_res, &ops);
00481 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00482 return TRUE;
00483 }
00484
00485 } else if (OP_select(op)) {
00486 TN *res = OP_result(op, 0);
00487 TN *tn0 = OP_opnd(op, 0);
00488 TN *tn1;
00489 TN *tn2;
00490
00491
00492 tn1 = opnd_tn[1];
00493 tn2 = opnd_tn[2];
00494
00495 if (tn_registers_identical(tn1, tn2)) {
00496
00497 OPS ops = OPS_EMPTY;
00498 Exp_COPY(res, OP_opnd(op, 1), &ops);
00499 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00500 if (EBO_Trace_Optimization) {
00501 #pragma mips_frequency_hint NEVER
00502 fprintf(TFile,"Optimize select - operands are the same\n");
00503 }
00504 return TRUE;
00505 }
00506
00507 if (TN_is_global_reg(tn1) &&
00508 (opnd_tninfo[1] != NULL) &&
00509 (opnd_tninfo[1]->in_op == NULL) &&
00510 (opnd_tninfo[1]->in_bb != NULL) &&
00511 (opnd_tninfo[1]->in_bb != OP_bb(op)) &&
00512 !tn_has_live_def_into_BB(tn1, opnd_tninfo[1]->in_bb)) {
00513
00514
00515
00516 OPS ops = OPS_EMPTY;
00517 Exp_COPY(res, OP_opnd(op, 2), &ops);
00518 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00519 if (EBO_Trace_Optimization) {
00520 #pragma mips_frequency_hint NEVER
00521 fprintf(TFile,"Optimize select - op1 %s can't be used: ",
00522 EBO_in_peep ? "REG" : "TN");
00523 Print_TN(OP_opnd(op, 2), FALSE);
00524 fprintf(TFile,"\n");
00525 }
00526 return TRUE;
00527 }
00528
00529 if (TN_is_global_reg(tn2) &&
00530 (opnd_tninfo[2] != NULL) &&
00531 (opnd_tninfo[2]->in_op == NULL) &&
00532 (opnd_tninfo[2]->in_bb != NULL) &&
00533 (opnd_tninfo[2]->in_bb != OP_bb(op)) &&
00534 !tn_has_live_def_into_BB(tn2, opnd_tninfo[2]->in_bb)) {
00535
00536
00537
00538 OPS ops = OPS_EMPTY;
00539 Exp_COPY(res, OP_opnd(op, 1), &ops);
00540 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00541 if (EBO_Trace_Optimization) {
00542 #pragma mips_frequency_hint NEVER
00543 fprintf(TFile,"Optimize select - op2 %s can't be used: ",
00544 EBO_in_peep ? "REG" : "TN");
00545 Print_TN(OP_opnd(op, 1), FALSE);
00546 fprintf(TFile,"\n");
00547 }
00548 return TRUE;
00549 }
00550
00551
00552
00553 tn0 = OP_opnd(op, 0);
00554 tn1 = OP_opnd(op, 1);
00555 tn2 = OP_opnd(op, 2);
00556 if ((TN_Is_Constant(tn1) || !tn_registers_identical(res, tn1)) &&
00557 (TN_Is_Constant(tn2) || !tn_registers_identical(res, tn2))) {
00558 OPS ops = OPS_EMPTY;
00559 OP *new_op = Dup_OP (op);
00560
00561 if (has_assigned_reg(res)) {
00562
00563 TN *new_res = OP_result(op,0);
00564 FmtAssert((TN_Is_Constant(tn0) || !tn_registers_identical(res, tn0)),
00565 ("Condition code also used as result of select"));
00566 if (TN_Is_Constant(tn2)) {
00567 Exp_COPY(new_res, tn2, &ops);
00568 Set_OP_opnd(new_op, 2, new_res);
00569 } else {
00570 Exp_COPY(new_res, tn1, &ops);
00571 Set_OP_opnd(new_op, 1, new_res);
00572 }
00573 OPS_Append_Op(&ops, new_op);
00574 } else {
00575
00576 TN *new_res = Dup_TN (res);
00577 Exp_COPY(new_res, tn1, &ops);
00578 Set_OP_result(new_op, 0, new_res);
00579 Set_OP_opnd(new_op, 1, new_res);
00580 OPS_Append_Op(&ops, new_op);
00581 Exp_COPY(res, new_res, &ops);
00582 }
00583
00584 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00585 if (EBO_Trace_Optimization) {
00586 #pragma mips_frequency_hint NEVER
00587 fprintf(TFile,"Rewrite select\n");
00588 }
00589 return TRUE;
00590 }
00591 }
00592
00593 return FALSE;
00594
00595 }
00596
00597 BOOL TN_live_out_of(TN *tn, BB *bb)
00598
00599
00600
00601
00602
00603 {
00604 if (EBO_Trace_Execution) {
00605 #pragma mips_frequency_hint NEVER
00606 fprintf(TFile,"%sEnter TN_live_out_of BB:%d ",EBO_trace_pfx,BB_id(bb));
00607 Print_TN(tn, FALSE);
00608 fprintf(TFile,"\n");
00609 }
00610
00611 #ifdef KEY
00612 if (EBO_no_liveness_info_available)
00613 return TRUE;
00614 #endif
00615
00616 if (EBO_in_peep) {
00617 if (EBO_Trace_Data_Flow) {
00618 #pragma mips_frequency_hint NEVER
00619 fprintf(TFile,"REG_LIVE_Outof_BB %s\n",
00620 REG_LIVE_Outof_BB (TN_register_class(tn), TN_register(tn), bb)?"TRUE":"FALSE");
00621 }
00622 return REG_LIVE_Outof_BB (TN_register_class(tn), TN_register(tn), bb);
00623 }
00624 else {
00625 if (CG_localize_tns) return (TN_is_dedicated(tn) || TN_is_global_reg(tn));
00626 return GRA_LIVE_TN_Live_Outof_BB (tn, bb);
00627 }
00628 }
00629
00630
00631
00632 inline BOOL op_is_needed_globally(OP *op)
00633
00634
00635
00636
00637 {
00638 BB *bb = OP_bb(op);
00639
00640 if (OP_copy(op)) {
00641
00642 if (OP_glue(op) && !EBO_in_peep)
00643 return TRUE;
00644 if ((TN_is_save_reg(OP_result(op,0)) || TN_is_save_reg(OP_opnd(op,OP_COPY_OPND))) &&
00645 !tn_registers_identical(OP_result(op,0), OP_opnd(op,OP_COPY_OPND))) {
00646 return TRUE;
00647 }
00648 return FALSE;
00649 }
00650 if (TN_is_save_reg(OP_result(op,0)))
00651 return TRUE;
00652 if (OP_glue(op) && !has_assigned_reg(OP_result(op,0)))
00653 return TRUE;
00654 if (CGTARG_Is_OP_Intrinsic(op))
00655
00656 return TRUE;
00657 if (OP_call(op))
00658
00659 return TRUE;
00660 if (op == BB_exit_sp_adj_op(bb) || op == BB_entry_sp_adj_op(bb))
00661 return TRUE;
00662 return FALSE;
00663 }
00664
00665
00666
00667
00668
00669 void
00670 tn_info_entry_dump (EBO_TN_INFO *tninfo)
00671 {
00672 fprintf(TFile,"entry %d\tBB:%d, use count = %d, redefined = %s, same as %d, predicate %d: ",
00673 tninfo->sequence_num,tninfo->in_bb?BB_id(tninfo->in_bb):0,
00674 tninfo->reference_count,
00675 tninfo->redefined_before_block_end?"TRUE":"FALSE",
00676 tninfo->same?tninfo->same->sequence_num:0,
00677 tninfo->predicate_tninfo?tninfo->predicate_tninfo->sequence_num:0);
00678 Print_TN (tninfo->local_tn, TRUE);
00679 fprintf(TFile,"[%d]",tninfo->omega);
00680 if (tninfo->replacement_tn != NULL) {
00681 fprintf(TFile,"\n\treplace TN with: ");
00682 Print_TN (tninfo->replacement_tn, TRUE);
00683 if (tninfo->replacement_tninfo != NULL) {
00684 fprintf(TFile," (Entry Number %d)",
00685 tninfo->replacement_tninfo->sequence_num);
00686 }
00687 }
00688 fprintf(TFile,"\n");
00689 if (tninfo->in_op) {
00690 fprintf(TFile,"\t");
00691 Print_OP_No_SrcLine(tninfo->in_op);
00692 }
00693
00694 FmtAssert((TN_number(tninfo->local_tn) <= Last_TN),
00695 ("TN number exceeds allowed range"));
00696
00697 }
00698
00699
00700 void
00701 tn_info_table_dump ()
00702 {
00703 EBO_TN_INFO *tninfo = EBO_first_tninfo;
00704
00705 fprintf(TFile,"\n>>>>>> EBO INFO DUMP <<<<<\n");
00706
00707 while (tninfo != NULL) {
00708 tn_info_entry_dump(tninfo);
00709 tninfo = tninfo->next;
00710 }
00711
00712 fprintf(TFile,">>>>>> EBO INFO DUMP COMPLETE <<<<<\n\n");
00713
00714 }
00715
00716
00717
00718 void EBO_Init(void)
00719
00720
00721
00722
00723 {
00724
00725 EBO_Trace_Execution = FALSE;
00726 EBO_Trace_Optimization = FALSE;
00727 EBO_Trace_Block_Flow = FALSE;
00728 EBO_Trace_Data_Flow = FALSE;
00729 EBO_Trace_Hash_Search = FALSE;
00730
00731 MEM_POOL_Initialize(&EBO_pool, "ebo", FALSE);
00732 MEM_POOL_Push(&EBO_pool);
00733 EBO_tninfo_table = NULL;
00734
00735 EBO_tninfo_number = 0;
00736 EBO_free_tninfo = NULL;
00737 EBO_first_tninfo = NULL;
00738 EBO_last_tninfo = NULL;
00739
00740 EBO_free_opinfo = NULL;
00741 EBO_first_opinfo = NULL;
00742 EBO_last_opinfo = NULL;
00743
00744 bzero(EBO_opinfo_table,sizeof(EBO_opinfo_table));
00745
00746 EBO_num_tninfo_entries = 0;
00747 EBO_tninfo_entries_reused = 0;
00748 EBO_num_opinfo_entries = 0;
00749 EBO_opinfo_entries_reused = 0;
00750 EBO_trace_pfx = "<ebo> ";
00751
00752 #ifdef KEY
00753
00754 ISA_REGISTER_CLASS cl;
00755 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00756 REGISTER_SET reg_set = REGISTER_CLASS_allocatable(cl);
00757 REGISTER reg;
00758 avail_regs_count[cl] = 0;
00759 for (reg = REGISTER_SET_Choose(reg_set);
00760 reg != REGISTER_UNDEFINED;
00761 reg = REGISTER_SET_Choose_Next(reg_set, reg)) {
00762 avail_regs_count[cl]++;
00763 }
00764
00765 if (cl == ISA_REGISTER_CLASS_integer)
00766 avail_regs_count[cl] += CG_cse_regs;
00767 else if (cl == ISA_REGISTER_CLASS_float)
00768 avail_regs_count[cl] += CG_sse_cse_regs;
00769 }
00770 #endif
00771 }
00772
00773
00774
00775
00776 static void EBO_Start()
00777
00778
00779
00780 {
00781
00782 MEM_POOL_Push(&MEM_local_pool);
00783 EBO_tninfo_table = TN_MAP_Create();
00784
00785 ISA_REGISTER_CLASS cl;
00786 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00787 Regs_Delta_Map[cl] = OP_MAP32_Create();
00788 }
00789
00790 #if defined(TARG_X8664) || (defined(TARG_MIPS) && !defined(TARG_SL))
00791 EBO_Special_Start( &MEM_local_pool );
00792 #endif
00793 }
00794
00795
00796
00797 static void EBO_Finish(void)
00798
00799
00800
00801 {
00802 #ifdef KEY
00803 ISA_REGISTER_CLASS cl;
00804 FOR_ALL_ISA_REGISTER_CLASS(cl) {
00805 OP_MAP_Delete(Regs_Delta_Map[cl]);
00806 Regs_Delta_Map[cl] = NULL;
00807 }
00808 EBO_Special_Finish();
00809 #endif
00810
00811 TN_MAP_Delete (EBO_tninfo_table);
00812 EBO_tninfo_table = NULL;
00813 MEM_POOL_Pop(&MEM_local_pool);
00814 }
00815
00816
00817
00818
00819 void EBO_Finalize(void)
00820
00821
00822
00823
00824 {
00825 MEM_POOL_Pop(&EBO_pool);
00826 MEM_POOL_Delete(&EBO_pool);
00827 }
00828
00829
00830
00831
00832
00833 static INT copy_operand(OP *op)
00834
00835
00836
00837
00838
00839 {
00840 INT opnd;
00841
00842 if (OP_copy(op)) {
00843 return OP_COPY_OPND;
00844 }
00845 opnd = CGTARG_Copy_Operand(op);
00846 if (opnd >= 0) {
00847 return opnd;
00848 }
00849 opnd = EBO_Copy_Operand(op);
00850 if (opnd >= 0) {
00851 return opnd;
00852 }
00853 return -1;
00854 }
00855
00856
00857
00858 static void
00859 find_index_and_offset (EBO_TN_INFO *original_tninfo,
00860 TN **base_tn, EBO_TN_INFO **base_tninfo,
00861 TN **offset_tn, EBO_TN_INFO **offset_tninfo)
00862 {
00863
00864 EBO_OP_INFO *indx_opinfo = locate_opinfo_entry(original_tninfo);
00865 if ((indx_opinfo != NULL) &&
00866 (indx_opinfo->in_op != NULL) &&
00867 (OP_iadd(indx_opinfo->in_op) ||
00868 EBO_Can_Merge_Into_Offset(indx_opinfo->in_op))) {
00869 #ifdef TARG_X8664
00870 INT op1_idx = 0;
00871 INT op2_idx = 1;
00872 #else
00873 INT op1_idx = TOP_Find_Operand_Use(OP_code(indx_opinfo->in_op),OU_opnd1);
00874 INT op2_idx = TOP_Find_Operand_Use(OP_code(indx_opinfo->in_op),OU_opnd2);
00875 #endif
00876 if ((op1_idx >= 0) && (op2_idx >= 0)) {
00877 EBO_TN_INFO *op1_tninfo = indx_opinfo->actual_opnd[op1_idx];
00878 EBO_TN_INFO *op2_tninfo = indx_opinfo->actual_opnd[op2_idx];
00879 TN *op1_tn;
00880 TN *op2_tn;
00881 if (op1_tninfo != NULL) {
00882 if ((op1_tninfo->replacement_tn) &&
00883 (TN_is_symbol(op1_tninfo->replacement_tn) || TN_Is_Constant(op1_tninfo->replacement_tn))) {
00884 op1_tn = op1_tninfo->replacement_tn;
00885 op1_tninfo = op1_tninfo->replacement_tninfo;
00886 } else {
00887 op1_tn = op1_tninfo->local_tn;
00888 }
00889 } else {
00890 op1_tn = OP_opnd(indx_opinfo->in_op,op1_idx);
00891 }
00892 if (op2_tninfo != NULL) {
00893 if ((op2_tninfo->replacement_tn) &&
00894 (TN_is_symbol(op2_tninfo->replacement_tn) || TN_Is_Constant(op2_tninfo->replacement_tn))) {
00895 op2_tn = op2_tninfo->replacement_tn;
00896 op2_tninfo = op2_tninfo->replacement_tninfo;
00897 } else {
00898 op2_tn = op2_tninfo->local_tn;
00899 }
00900 } else {
00901 op2_tn = OP_opnd(indx_opinfo->in_op,op2_idx);
00902 }
00903
00904 if (TN_is_symbol(op1_tn) || TN_Is_Constant(op1_tn)) {
00905 TN *save = op1_tn;
00906 op1_tn = op2_tn;
00907 op2_tn = save;
00908 op1_tninfo = op2_tninfo;
00909 op2_tninfo = NULL;
00910 }
00911
00912 *base_tn = op1_tn;
00913 *base_tninfo = op1_tninfo;
00914 *offset_tn = op2_tn;
00915 *offset_tninfo = op2_tninfo;
00916
00917 if (EBO_Trace_Hash_Search) {
00918 #pragma mips_frequency_hint NEVER
00919 fprintf(TFile,"%sUse inputs to index: ",EBO_trace_pfx);
00920 Print_TN(*base_tn,FALSE);
00921 fprintf(TFile," ");
00922 Print_TN(*offset_tn,FALSE);
00923 fprintf(TFile,"\n");
00924 }
00925 }
00926 }
00927 #ifdef TARG_IA64
00928 else if ((indx_opinfo != NULL) &&
00929 (indx_opinfo->in_op != NULL) &&
00930 (OP_memory(indx_opinfo->in_op))) {
00931 OP *input_op = indx_opinfo->in_op;
00932 INT op1_idx = TOP_Find_Operand_Use(OP_code(input_op),OU_base);
00933 INT op2_idx = TOP_Find_Operand_Use(OP_code(input_op),OU_postincr);
00934
00935 if ((op1_idx >= 0) &&
00936 (op2_idx >= 0) &&
00937 TNs_Are_Equivalent(OP_opnd(input_op,op1_idx),original_tninfo->local_tn)) {
00938
00939 EBO_TN_INFO *op1_tninfo = indx_opinfo->actual_opnd[op1_idx];
00940 EBO_TN_INFO *op2_tninfo = indx_opinfo->actual_opnd[op2_idx];
00941 TN *op1_tn;
00942 TN *op2_tn;
00943
00944 if (op1_tninfo != NULL) {
00945 if ((op1_tninfo->replacement_tn) &&
00946 (TN_is_symbol(op1_tninfo->replacement_tn) || TN_Is_Constant(op1_tninfo->replacement_tn))) {
00947 op1_tn = op1_tninfo->replacement_tn;
00948 op1_tninfo = op1_tninfo->replacement_tninfo;
00949 } else {
00950 op1_tn = op1_tninfo->local_tn;
00951 }
00952 } else {
00953 op1_tn = OP_opnd(indx_opinfo->in_op,op1_idx);
00954 }
00955 if (op2_tninfo != NULL) {
00956 if ((op2_tninfo->replacement_tn) &&
00957 (TN_is_symbol(op2_tninfo->replacement_tn) || TN_Is_Constant(op2_tninfo->replacement_tn))) {
00958 op2_tn = op2_tninfo->replacement_tn;
00959 op2_tninfo = op2_tninfo->replacement_tninfo;
00960 } else {
00961 op2_tn = op2_tninfo->local_tn;
00962 }
00963 } else {
00964 op2_tn = OP_opnd(indx_opinfo->in_op,op2_idx);
00965 }
00966
00967 if (TN_is_symbol(op1_tn) || TN_Is_Constant(op1_tn)) {
00968 TN *save = op1_tn;
00969 op1_tn = op2_tn;
00970 op2_tn = save;
00971 op1_tninfo = op2_tninfo;
00972 op2_tninfo = NULL;
00973 }
00974
00975 *base_tn = op1_tn;
00976 *base_tninfo = op1_tninfo;
00977 *offset_tn = op2_tn;
00978 *offset_tninfo = op2_tninfo;
00979
00980 if (EBO_Trace_Hash_Search) {
00981 #pragma mips_frequency_hint NEVER
00982 fprintf(TFile,"%sUse inputs to index: ",EBO_trace_pfx);
00983 Print_TN(*base_tn,FALSE);
00984 fprintf(TFile," ");
00985 Print_TN(*offset_tn,FALSE);
00986 fprintf(TFile,"\n");
00987 }
00988 }
00989 }
00990 #endif
00991 }
00992
00993
00994
00995 static void
00996 merge_memory_offsets( OP *op,
00997 INT index_opnd,
00998 TN **opnd_tn,
00999 EBO_TN_INFO **opnd_tninfo,
01000 EBO_TN_INFO **actual_tninfo)
01001 {
01002 EBO_TN_INFO *index_tninfo = opnd_tninfo[index_opnd];
01003 OP *index_op = (index_tninfo != NULL) ? index_tninfo->in_op : NULL;
01004 TN *immed_tn = opnd_tn[index_opnd+1];
01005 ST *immed_sym = TN_is_symbol(immed_tn) ? TN_var(immed_tn) : NULL;
01006 INT64 immed_offset = TN_is_symbol(immed_tn) ? TN_offset(immed_tn) : TN_Value(immed_tn);
01007 EBO_OP_INFO *index_opinfo;
01008 TN *additive_index_tn;
01009 TN *additive_immed_tn;
01010 EBO_TN_INFO *additive_index_tninfo;
01011
01012 TN *adjust_tn = NULL;
01013 ST *adjust_sym = NULL;
01014 INT64 adjust_offset = 0;
01015 TN *new_tn;
01016
01017 if ((index_tninfo == NULL) ||
01018 (index_op == NULL) ||
01019 (!EBO_Can_Merge_Into_Offset (index_op))) {
01020 return;
01021 }
01022
01023 index_opinfo = locate_opinfo_entry (index_tninfo);
01024 if (index_opinfo == NULL) return;
01025
01026 additive_index_tn = OP_opnd(index_op,0);
01027 additive_index_tninfo = index_opinfo->actual_opnd[0];
01028 #ifdef TARG_X8664
01029
01030 if ( additive_index_tn == Rip_TN() )
01031 return;
01032 #endif
01033
01034 additive_immed_tn = OP_opnd(index_op,1);
01035 if (!TN_Is_Constant(additive_immed_tn)) return;
01036
01037
01038 if (!TN_Is_Constant(additive_index_tn) &&
01039 !EBO_tn_available(OP_bb(op), additive_index_tninfo)) {
01040 return;
01041 }
01042
01043 if (TN_is_symbol(additive_immed_tn)) {
01044 if (immed_sym != NULL) return;
01045 if (OP_isub(index_op)) return;
01046 if (immed_offset != 0) {
01047
01048
01049
01050 return;
01051 }
01052 adjust_sym = TN_var(additive_immed_tn);
01053 adjust_tn = additive_immed_tn;
01054 adjust_offset = immed_offset + TN_offset(additive_immed_tn);
01055 } else {
01056 adjust_sym = immed_sym;
01057 adjust_tn = immed_tn;
01058 #if defined(TARG_X8664)
01059 adjust_offset = TN_value(additive_immed_tn);
01060 #else
01061 adjust_offset = TN_Value(additive_immed_tn);
01062 #endif
01063 if (OP_isub(index_op)) adjust_offset = -adjust_offset;
01064 adjust_offset += immed_offset;
01065 }
01066
01067 if (!TOP_Can_Have_Immediate( adjust_offset, OP_code(op))) {\
01068 if (EBO_Trace_Optimization) {
01069 #pragma mips_frequency_hint NEVER
01070 fprintf(TFile, "%sin BB:%d combined index expressions do not fit in the offset field\n",
01071 EBO_trace_pfx, BB_id(OP_bb(op)));
01072 Print_OP_No_SrcLine(op);
01073 }
01074 return;
01075 }
01076
01077 if (EBO_Trace_Optimization) {
01078 #pragma mips_frequency_hint NEVER
01079 fprintf(TFile, "%sin BB:%d merge memory index expression (from BB:%d) with offset (in BB:%d)\n",
01080 EBO_trace_pfx, BB_id(OP_bb(op)),BB_id(OP_bb(index_op)),BB_id(OP_bb(op)));
01081 Print_OP_No_SrcLine(index_op);
01082 Print_OP_No_SrcLine(op);
01083 }
01084
01085
01086 if (adjust_sym != NULL) {
01087 new_tn = Gen_Symbol_TN(adjust_sym, adjust_offset, TN_relocs(adjust_tn));
01088 } else {
01089 new_tn = Gen_Literal_TN (adjust_offset, TN_size(adjust_tn));
01090 }
01091
01092 if (actual_tninfo[index_opnd] != NULL) {
01093 dec_ref_count(actual_tninfo[index_opnd]);
01094 }
01095 if (additive_index_tninfo != NULL) {
01096 inc_ref_count(additive_index_tninfo);
01097 }
01098 Set_OP_opnd(op, index_opnd, additive_index_tn);
01099 if (EBO_in_loop) {
01100 Set_OP_omega (op, index_opnd, (additive_index_tninfo != NULL) ? additive_index_tninfo->omega : 0);
01101 }
01102 Set_OP_opnd(op, index_opnd+1, new_tn);
01103 if (EBO_in_loop) {
01104 Set_OP_omega (op, index_opnd+1, 0);
01105 }
01106 opnd_tn[index_opnd] = additive_index_tn;
01107 opnd_tn[index_opnd+1] = new_tn;
01108 opnd_tninfo[index_opnd] = additive_index_tninfo;
01109 opnd_tninfo[index_opnd+1] = NULL;
01110 actual_tninfo[index_opnd] = additive_index_tninfo;
01111 actual_tninfo[index_opnd+1] = NULL;
01112
01113 if (EBO_Trace_Optimization) {
01114 #pragma mips_frequency_hint NEVER
01115 fprintf(TFile, " to produce the new expression:\n");
01116 Print_OP_No_SrcLine(op);
01117 }
01118
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131 static BOOL
01132 find_duplicate_mem_op (BB *bb,
01133 OP *op,
01134 TN **opnd_tn,
01135 EBO_TN_INFO **opnd_tninfo,
01136 EBO_TN_INFO **actual_tninfo,
01137 int op_num,
01138 int *regs_used,
01139 int *last_fat_point)
01140
01141
01142
01143
01144
01145 {
01146 INT hash_value = 0;
01147 INT hash_search_length = 0;
01148 EBO_OP_INFO *opinfo;
01149 EBO_OP_INFO *intervening_opinfo = NULL;
01150 EBO_OP_INFO *adjacent_location = NULL;
01151 INT64 adjacent_offset_pred;
01152 INT64 adjacent_offset_succ;
01153 #ifdef KEY
01154
01155 BOOL inside_lr = TRUE;
01156
01157
01158 EBO_TN_INFO *extend_lr_tninfo = NULL;
01159 EBO_REG_ENTRY reginfo;
01160 #endif
01161
01162 if (op == NULL) return FALSE;
01163
01164 if (EBO_Trace_Execution) {
01165 #pragma mips_frequency_hint NEVER
01166 fprintf(TFile,"%sEnter find_duplicate_mem_op\n",EBO_trace_pfx);
01167 }
01168
01169 #if !defined(TARG_IA64) && !defined(TARG_SL) && !defined(TARG_MIPS)
01170
01171 if( OP_prefetch(op) ){
01172 return Combine_L1_L2_Prefetches( op, opnd_tn, opnd_tninfo );
01173 }
01174 #endif
01175
01176 if (!(OP_load(op) || OP_store(op))) return FALSE;
01177
01178
01179 INT succ_base_idx = TOP_Find_Operand_Use(OP_code(op),OU_base);
01180 INT succ_offset_idx = TOP_Find_Operand_Use(OP_code(op),OU_offset);
01181
01182 if ((succ_base_idx >= 0) && (succ_offset_idx >= 0) &&
01183 TN_Is_Constant(opnd_tn[succ_offset_idx])) {
01184
01185 merge_memory_offsets (op, succ_base_idx, opnd_tn, actual_tninfo, opnd_tninfo);
01186 }
01187
01188
01189 TN *succ_base_tn = (succ_base_idx >= 0) ? opnd_tn[succ_base_idx] : NULL;
01190 EBO_TN_INFO *succ_base_tninfo = (succ_base_idx >= 0) ? opnd_tninfo[succ_base_idx] : NULL;
01191 TN *succ_offset_tn = (succ_offset_idx >= 0) ? opnd_tn[succ_offset_idx] : NULL;
01192 EBO_TN_INFO *succ_offset_tninfo = (succ_offset_idx >= 0) ? opnd_tninfo[succ_offset_idx] : NULL;
01193 #ifdef TARG_X8664
01194 const INT succ_index_idx = TOP_Find_Operand_Use(OP_code(op),OU_index);
01195 const INT succ_scale_idx = TOP_Find_Operand_Use(OP_code(op),OU_scale);
01196
01197
01198 if (CG_sse_load_execute != 0 &&
01199 OP_load(op) &&
01200 succ_index_idx == -1 &&
01201 TN_register_class(OP_result(op, 0)) == ISA_REGISTER_CLASS_float) {
01202 return FALSE;
01203 }
01204 TN* succ_index_tn = (succ_index_idx >= 0) ? opnd_tn[succ_index_idx] : NULL;
01205 EBO_TN_INFO* succ_index_tninfo = (succ_index_idx >= 0) ? opnd_tninfo[succ_index_idx] : NULL;
01206 TN* succ_scale_tn = (succ_scale_idx >= 0) ? opnd_tn[succ_scale_idx] : NULL;
01207 EBO_TN_INFO* succ_scale_tninfo = (succ_scale_idx >= 0) ? opnd_tninfo[succ_scale_idx] : NULL;
01208 #endif
01209
01210 if ((succ_offset_tn == NULL) && (succ_base_tn != NULL)) {
01211 find_index_and_offset(succ_base_tninfo,
01212 &succ_base_tn, &succ_base_tninfo,
01213 &succ_offset_tn, &succ_offset_tninfo);
01214 }
01215
01216
01217 hash_value = EBO_hash_op( op, opnd_tninfo);
01218
01219 if (EBO_Trace_Hash_Search) {
01220 #pragma mips_frequency_hint NEVER
01221 fprintf(TFile,"%sLook for redundant memory ops in hash chain %d for\n\t",
01222 EBO_trace_pfx,hash_value);
01223 Print_OP_No_SrcLine(op);
01224 }
01225
01226 opinfo = (OP_has_implicit_interactions(op) || OP_unalign_mem(op)) ? NULL : EBO_opinfo_table[hash_value];
01227
01228 while (opinfo) {
01229 OP *pred_op = opinfo->in_op;
01230 INT64 offset_pred = 0;
01231 INT64 offset_succ = 0;
01232
01233
01234 INT pred_base_idx = 0;
01235 INT pred_offset_idx = 0;
01236 TN *pred_base_tn = NULL;
01237 EBO_TN_INFO *pred_base_tninfo = NULL;
01238 TN *pred_offset_tn = NULL;
01239 EBO_TN_INFO *pred_offset_tninfo = NULL;
01240 #ifdef TARG_X8664
01241 INT pred_index_idx = 0;
01242 TN* pred_index_tn = NULL;
01243 EBO_TN_INFO* pred_index_tninfo = NULL;
01244 INT pred_scale_idx = 0;
01245 TN* pred_scale_tn = NULL;
01246 EBO_TN_INFO* pred_scale_tninfo = NULL;
01247 #endif
01248
01249 if ((pred_op != NULL) &&
01250 (OP_load(pred_op) || OP_store(pred_op)
01251 #ifdef TARG_X8664
01252 || OP_load_exe(pred_op)
01253 #endif
01254 )) {
01255
01256 pred_base_idx = TOP_Find_Operand_Use(OP_code(pred_op),OU_base);
01257 pred_offset_idx = TOP_Find_Operand_Use(OP_code(pred_op),OU_offset);
01258 pred_base_tn = (pred_base_idx >= 0) ? OP_opnd(pred_op,pred_base_idx) : NULL;
01259 pred_base_tninfo = (pred_base_idx >= 0) ? opinfo->optimal_opnd[pred_base_idx] : NULL;
01260 pred_offset_tn = (pred_offset_idx >= 0) ? OP_opnd(pred_op,pred_offset_idx) : NULL;
01261 pred_offset_tninfo = (pred_offset_idx >= 0) ? opinfo->optimal_opnd[pred_offset_idx] : NULL;
01262 #ifdef TARG_X8664
01263 pred_index_idx = TOP_Find_Operand_Use(OP_code(pred_op),OU_index);
01264 pred_scale_idx = TOP_Find_Operand_Use(OP_code(pred_op),OU_scale);
01265 pred_index_tn = (pred_index_idx >= 0) ? OP_opnd(pred_op,pred_index_idx) : NULL;
01266 pred_index_tninfo = (pred_index_idx >= 0) ? opinfo->optimal_opnd[pred_index_idx] : NULL;
01267 pred_scale_tn = (pred_scale_idx >= 0) ? OP_opnd(pred_op,pred_scale_idx) : NULL;
01268 pred_scale_tninfo = (pred_scale_idx >= 0) ? opinfo->optimal_opnd[pred_scale_idx] : NULL;
01269 #endif
01270 }
01271
01272 if ((pred_offset_tn == NULL) && (pred_base_tn != NULL)) {
01273 find_index_and_offset(pred_base_tninfo,
01274 &pred_base_tn, &pred_base_tninfo,
01275 &pred_offset_tn, &pred_offset_tninfo);
01276 }
01277
01278 BOOL hash_op_matches = ((pred_op != NULL) &&
01279 #ifdef TARG_X8664
01280 (OP_memory(pred_op) || OP_load_exe(pred_op)) &&
01281 #else
01282 OP_memory(pred_op) &&
01283 #endif
01284 #ifdef TARG_X8664
01285 (CGTARG_Is_Thread_Local_Memory_OP(op) ==
01286 CGTARG_Is_Thread_Local_Memory_OP(pred_op)) &&
01287 (pred_index_tn == succ_index_tn) &&
01288 (pred_index_tninfo == succ_index_tninfo) &&
01289 (pred_scale_tn == succ_scale_tn) &&
01290 (pred_scale_tninfo == succ_scale_tninfo) &&
01291 #else
01292 OP_memory(pred_op) &&
01293 #endif
01294
01295 (pred_base_tn == succ_base_tn) &&
01296 (pred_base_tninfo == succ_base_tninfo) &&
01297 (pred_offset_tninfo == succ_offset_tninfo))
01298 ? TRUE : FALSE;
01299 BOOL op_is_subset = FALSE;
01300 BOOL offsets_may_overlap = TRUE;
01301
01302 hash_search_length++;
01303
01304 if (hash_op_matches &&
01305 (pred_offset_tn != succ_offset_tn)) {
01306
01307
01308 ST *symbol_pred = ((pred_offset_tn != NULL) && TN_is_symbol(pred_offset_tn)) ?TN_var(pred_offset_tn) : NULL;
01309 ST *symbol_succ = ((succ_offset_tn != NULL) && TN_is_symbol(succ_offset_tn)) ?TN_var(succ_offset_tn) : NULL;
01310 mUINT8 relocs_pred = (pred_offset_tn != NULL) ? TN_relocs(pred_offset_tn) : 0;
01311 mUINT8 relocs_succ = (succ_offset_tn != NULL) ? TN_relocs(succ_offset_tn) : 0;
01312 offset_pred = (pred_offset_tn != NULL) ? TN_offset(pred_offset_tn) : 0;
01313 offset_succ = (succ_offset_tn != NULL) ? TN_offset(succ_offset_tn) : 0;
01314
01315
01316 hash_op_matches = (symbol_pred == symbol_succ) && (relocs_pred == relocs_succ);
01317
01318 if ((OP_prefetch(op) || OP_prefetch(pred_op)) &&
01319 (offset_pred != offset_succ)) {
01320 hash_op_matches = FALSE;
01321 } else if (hash_op_matches) {
01322
01323 INT size_pred = CGTARG_Mem_Ref_Bytes(pred_op);
01324 INT size_succ = CGTARG_Mem_Ref_Bytes(op);
01325
01326 if ((offset_pred == offset_succ) &&
01327 (size_pred == size_succ)) {
01328
01329 } else if ((offset_pred <= offset_succ) &&
01330 ((offset_pred + size_pred) >= (offset_succ + size_succ))) {
01331
01332 op_is_subset = TRUE;
01333 } else if (OP_load(op) && OP_load(pred_op) && (size_pred == size_succ) &&
01334 (((offset_pred + size_pred) == offset_succ) ||
01335 ((offset_succ + size_succ) == offset_pred))) {
01336 offsets_may_overlap = FALSE;
01337 if (adjacent_location == NULL) {
01338 adjacent_location = opinfo;
01339 adjacent_offset_pred = offset_pred;
01340 adjacent_offset_succ = offset_succ;
01341 }
01342 } else if (((offset_pred + size_pred) <= offset_succ) ||
01343 ((offset_succ + size_succ) <= offset_pred)) {
01344
01345 offsets_may_overlap = FALSE;
01346 } else {
01347
01348 hash_op_matches = FALSE;
01349 }
01350 }
01351 }
01352
01353 if (hash_op_matches && !offsets_may_overlap ) {
01354 if (EBO_Trace_Hash_Search) {
01355 #pragma mips_frequency_hint NEVER
01356 fprintf(TFile,"%sMemory overlap not possible with\n\t",
01357 EBO_trace_pfx);
01358 Print_OP_No_SrcLine(pred_op);
01359 }
01360 opinfo = opinfo->same;
01361 continue;
01362 }
01363
01364 if (hash_op_matches && OP_has_predicate(op)) {
01365
01366
01367 if (OP_store(op) && OP_store(pred_op)) {
01368 if (!EBO_predicate_dominates(OP_opnd(op,OP_PREDICATE_OPND),
01369 actual_tninfo[OP_PREDICATE_OPND],
01370 OP_opnd(pred_op,OP_PREDICATE_OPND),
01371 opinfo->optimal_opnd[OP_PREDICATE_OPND]) &&
01372 !EBO_predicate_complements(OP_opnd(op,OP_PREDICATE_OPND),
01373 actual_tninfo[OP_PREDICATE_OPND],
01374 OP_opnd(pred_op,OP_PREDICATE_OPND),
01375 opinfo->optimal_opnd[OP_PREDICATE_OPND])) {
01376
01377 if (EBO_Trace_Hash_Search) {
01378 #pragma mips_frequency_hint NEVER
01379 fprintf(TFile,"%sStore predicates do not match\n\t", EBO_trace_pfx);
01380 Print_OP_No_SrcLine(pred_op);
01381 }
01382
01383
01384 hash_op_matches = FALSE;
01385 break;
01386 }
01387 } else if (!OP_store(op) && !OP_store(pred_op)) {
01388 if ( (intervening_opinfo != NULL) &&
01389 (
01390 #if defined(TARG_IA64)
01391 OP_cond_def(pred_op) ||
01392 #endif
01393 (!EBO_predicate_dominates(OP_opnd(pred_op,OP_PREDICATE_OPND),
01394 opinfo->optimal_opnd[OP_PREDICATE_OPND],
01395 OP_opnd(op,OP_PREDICATE_OPND),
01396 actual_tninfo[OP_PREDICATE_OPND])))) {
01397
01398 if (EBO_Trace_Hash_Search) {
01399 #pragma mips_frequency_hint NEVER
01400 fprintf(TFile,"%sRe-load predicates do not match\n\t", EBO_trace_pfx);
01401 Print_OP_No_SrcLine(pred_op);
01402 }
01403
01404
01405 hash_op_matches = FALSE;
01406 break;
01407 }
01408 if ((
01409 #if defined(TARG_IA64)
01410 OP_cond_def(pred_op) ||
01411 #endif
01412 !EBO_predicate_dominates(OP_opnd(pred_op,OP_PREDICATE_OPND),
01413 opinfo->optimal_opnd[OP_PREDICATE_OPND],
01414 OP_opnd(op,OP_PREDICATE_OPND),
01415 actual_tninfo[OP_PREDICATE_OPND])) &&
01416 !EBO_predicate_complements(OP_opnd(op,OP_PREDICATE_OPND),
01417 actual_tninfo[OP_PREDICATE_OPND],
01418 OP_opnd(pred_op,OP_PREDICATE_OPND),
01419 opinfo->optimal_opnd[OP_PREDICATE_OPND])) {
01420
01421 if (EBO_Trace_Hash_Search) {
01422 #pragma mips_frequency_hint NEVER
01423 fprintf(TFile,"%sLoad predicates do not match\n\t", EBO_trace_pfx);
01424 Print_OP_No_SrcLine(pred_op);
01425 }
01426
01427
01428 hash_op_matches = FALSE;
01429
01430 }
01431 } else if (!OP_store(op) && OP_store(pred_op)) {
01432 if ((
01433 #if defined(TARG_IA64)
01434 OP_cond_def(pred_op) ||
01435 #endif
01436 !EBO_predicate_dominates(OP_opnd(pred_op,OP_PREDICATE_OPND),
01437 opinfo->optimal_opnd[OP_PREDICATE_OPND],
01438 OP_opnd(op,OP_PREDICATE_OPND),
01439 actual_tninfo[OP_PREDICATE_OPND])) &&
01440 !EBO_predicate_complements(OP_opnd(op,OP_PREDICATE_OPND),
01441 actual_tninfo[OP_PREDICATE_OPND],
01442 OP_opnd(pred_op,OP_PREDICATE_OPND),
01443 opinfo->optimal_opnd[OP_PREDICATE_OPND])) {
01444
01445 if (EBO_Trace_Hash_Search) {
01446 #pragma mips_frequency_hint NEVER
01447 fprintf(TFile,"%sStore/load predicates do not match\n\t", EBO_trace_pfx);
01448 Print_OP_No_SrcLine(pred_op);
01449 }
01450
01451
01452 hash_op_matches = FALSE;
01453 break;
01454 }
01455 }
01456 }
01457
01458 if ((pred_op != NULL) &&
01459 (hash_value == EBO_DEFAULT_MEM_HASH) &&
01460 (OP_store(pred_op) != OP_store(op)) &&
01461 (!OP_prefetch(op))) {
01462
01463 WN *pred_wn;
01464 WN *succ_wn;
01465 ALIAS_RESULT result;
01466
01467 if (EBO_Trace_Hash_Search) {
01468 #pragma mips_frequency_hint NEVER
01469 fprintf(TFile,"%sPotential Alias problem with\n\t",EBO_trace_pfx);
01470 Print_OP_No_SrcLine(pred_op);
01471 }
01472
01473 result = POSSIBLY_ALIASED;
01474 if (Alias_Manager != NULL) {
01475 pred_wn = OP_hoisted(pred_op) ? NULL : Get_WN_From_Memory_OP(pred_op);
01476 succ_wn = OP_hoisted(op) ? NULL : Get_WN_From_Memory_OP(op);
01477 if ((pred_wn != NULL) && (succ_wn != NULL)) {
01478 result = Aliased(Alias_Manager, pred_wn, succ_wn);
01479 if ((!hash_op_matches) && (result == SAME_LOCATION)) {
01480
01481 hash_op_matches = TRUE;
01482 if (EBO_Trace_Hash_Search) {
01483 #pragma mips_frequency_hint NEVER
01484 fprintf(TFile,"%sAlias_Manager identifies SAME_LOCATION\n",
01485 EBO_trace_pfx);
01486 }
01487
01488
01489
01490
01491 if (OP_store(op)) opinfo->op_must_not_be_moved = TRUE;
01492 break;
01493 }
01494 }
01495 }
01496
01497 if ((result == POSSIBLY_ALIASED) && (!hash_op_matches)) {
01498
01499 if ((intervening_opinfo == NULL) && OP_store(pred_op) && OP_load(op)) {
01500 intervening_opinfo = opinfo;
01501 if (EBO_Trace_Hash_Search) {
01502 #pragma mips_frequency_hint NEVER
01503 fprintf(TFile,"%sContinue looking for duplicate memory op across interving dependency %d.\n",
01504 EBO_trace_pfx,result);
01505 }
01506 goto do_next;
01507 }
01508
01509 if (OP_store(pred_op)) opinfo->op_must_not_be_removed = TRUE;
01510 if (EBO_Trace_Hash_Search) {
01511 #pragma mips_frequency_hint NEVER
01512 fprintf(TFile,"%sAlias information(%d) prevents us from continuing.\n",
01513 EBO_trace_pfx,result);
01514 }
01515 break;
01516 }
01517 if (hash_op_matches && op_is_subset &&
01518 OP_store(op) && OP_store(pred_op)) {
01519 opinfo->op_must_not_be_removed = TRUE;
01520 if (EBO_Trace_Hash_Search) {
01521 #pragma mips_frequency_hint NEVER
01522 fprintf(TFile,"%sOverlapping store prevents us from continuing.\n",
01523 EBO_trace_pfx);
01524 }
01525 break;
01526 }
01527 if ((intervening_opinfo != NULL) && (!hash_op_matches)) {
01528 opinfo->op_must_not_be_removed = TRUE;
01529 if (EBO_Trace_Hash_Search) {
01530 #pragma mips_frequency_hint NEVER
01531 fprintf(TFile,"%sMultiple possible intervening stores prevents us from continuing.\n",
01532 EBO_trace_pfx);
01533 }
01534 break;
01535 }
01536
01537 if (EBO_Trace_Hash_Search) {
01538 #pragma mips_frequency_hint NEVER
01539 fprintf(TFile,"%sAlias information allows us to continue.\n",EBO_trace_pfx);
01540 }
01541 }
01542
01543 if (in_delay_slot && !OP_store(op)) {
01544
01545
01546 break;
01547 }
01548
01549 if (hash_op_matches &&
01550 (pred_op != NULL) &&
01551 (OP_load(pred_op) ||
01552 (OP_store(pred_op) && !OP_store(op)))) {
01553
01554 if (OP_store(pred_op)) {
01555 INT pred_stored_idx = TOP_Find_Operand_Use(OP_code(pred_op),OU_storeval);
01556 TN *pred_tn = OP_opnd(pred_op,pred_stored_idx);
01557 if (!TN_Is_Constant(pred_tn)) {
01558
01559 if (!EBO_tn_available(bb,opinfo->actual_opnd[pred_stored_idx])) {
01560 opinfo->op_must_not_be_removed = TRUE;
01561 if (EBO_Trace_Hash_Search) {
01562 #pragma mips_frequency_hint NEVER
01563 fprintf(TFile,"%sMemory match found, but stored value is not available\n\t",
01564 EBO_trace_pfx);
01565 Print_OP_No_SrcLine(pred_op);
01566 }
01567 break;
01568 }
01569 #ifdef KEY
01570
01571 EBO_REG_ENTRY_ptr(reginfo) = hTN_MAP_Get(regs_map, pred_tn);
01572 if (!TN_is_global_reg(pred_tn) &&
01573
01574 !(inside_lr = (EBO_REG_ENTRY_last_use_OP_num(reginfo)>=op_num)) &&
01575
01576 opinfo->op_num < last_fat_point[TN_register_class(pred_tn)]) {
01577 if (EBO_Trace_Hash_Search) {
01578 #pragma mips_frequency_hint NEVER
01579 fprintf(TFile,"%sMemory match found, but no register available to keep stored value\n\t",
01580 EBO_trace_pfx);
01581 Print_OP_No_SrcLine(pred_op);
01582 }
01583 break;
01584 }
01585 if (!inside_lr)
01586 extend_lr_tninfo = opinfo->actual_opnd[pred_stored_idx];
01587 #endif
01588 }
01589 } else {
01590 TN *pred_tn = OP_result(pred_op,0);
01591 if (!TN_Is_Constant(pred_tn)) {
01592
01593 if (!EBO_tn_available(bb,opinfo->actual_rslt[0])) {
01594 if (EBO_Trace_Hash_Search) {
01595 #pragma mips_frequency_hint NEVER
01596 fprintf(TFile,"%sMemory match found, but loaded value is not available\n\t",
01597 EBO_trace_pfx);
01598 Print_OP_No_SrcLine(pred_op);
01599 }
01600 break;
01601 }
01602 #ifdef KEY
01603
01604 EBO_REG_ENTRY_ptr(reginfo) = hTN_MAP_Get(regs_map, pred_tn);
01605 if (!TN_is_global_reg(pred_tn) &&
01606
01607 !(inside_lr = (EBO_REG_ENTRY_last_use_OP_num(reginfo)>=op_num)) &&
01608
01609 opinfo->op_num < last_fat_point[TN_register_class(pred_tn)]) {
01610 if (EBO_Trace_Hash_Search) {
01611 #pragma mips_frequency_hint NEVER
01612 fprintf(TFile,"%sMemory match found, but no register available to keep loaded value\n\t",
01613 EBO_trace_pfx);
01614 Print_OP_No_SrcLine(pred_op);
01615 }
01616 break;
01617 }
01618 if (!inside_lr)
01619 extend_lr_tninfo = opinfo->actual_rslt[0];
01620 #endif
01621 }
01622 }
01623 }
01624
01625 if (hash_op_matches) {
01626 BOOL op_replaced = FALSE;
01627
01628 if (OP_volatile(pred_op)) {
01629
01630
01631 break;
01632 }
01633
01634 if (EBO_Trace_Hash_Search) {
01635 #pragma mips_frequency_hint NEVER
01636 fprintf(TFile,"%sMatch after searching %d items on hash chain %d\n",
01637 EBO_trace_pfx,hash_search_length,hash_value);
01638 }
01639
01640 if (intervening_opinfo != NULL) {
01641 #ifdef TARG_IA64
01642 if(!EBO_in_peep && !EBO_data_spec) break;
01643 #endif
01644 op_replaced = delete_reload_across_dependency (op, opnd_tninfo, opinfo, intervening_opinfo);
01645 } else if (op_is_subset) {
01646 op_replaced = delete_subset_mem_op (op, opnd_tninfo, opinfo, offset_pred, offset_succ);
01647 } else {
01648 #ifdef TARG_IA64
01649 BOOL must_not_delete=FALSE;
01650 if (pred_op->bb == op->bb) {
01651 for (pred_op;pred_op!=op;pred_op=pred_op->next) {
01652 if (OP_load(pred_op)) {
01653 INT num_opnds=OP_opnds(pred_op);
01654 if ((num_opnds == 0) && (OP_opnds(op) < 3)) continue;
01655
01656 TN *tn=OP_opnd(op,2);
01657 for (INT opndnum=0; opndnum<num_opnds; opndnum++) {
01658 TN *tn_opnd=OP_opnd(pred_op,opndnum);
01659 if (tn==tn_opnd) {
01660 must_not_delete=TRUE;
01661 break;
01662 }
01663 }
01664 if (must_not_delete==TRUE) break;
01665 }
01666 }
01667 }
01668 if (must_not_delete==FALSE) op_replaced = delete_duplicate_op (op, opnd_tninfo, opinfo);
01669 #else
01670 op_replaced = delete_duplicate_op (op, opnd_tninfo, opinfo
01671 #if defined(TARG_X8664)
01672 , actual_tninfo
01673 #endif
01674 );
01675 #endif // TARG_IA64
01676 }
01677
01678 if (op_replaced) {
01679 #ifdef KEY
01680 if (extend_lr_tninfo != NULL)
01681 Extend_Live_Range(regs_used, last_fat_point, op_num, extend_lr_tninfo,
01682 reginfo, bb);
01683 #endif
01684 return TRUE;
01685 } else {
01686
01687
01688 if (intervening_opinfo != NULL) {
01689 opinfo = intervening_opinfo;
01690 pred_op = intervening_opinfo->in_op;
01691 }
01692 if (OP_store(op)) opinfo->op_must_not_be_moved = TRUE;
01693 if (op_is_subset || (hash_value == EBO_DEFAULT_MEM_HASH)) {
01694 if (OP_store(pred_op)) opinfo->op_must_not_be_removed = TRUE;
01695 break;
01696 }
01697 if (OP_store(pred_op) || OP_store(op)) {
01698 break;
01699 }
01700 }
01701 }
01702
01703 do_next:
01704 opinfo = opinfo->same;
01705 }
01706
01707 if (adjacent_location != NULL) {
01708 BOOL op_replaced = combine_adjacent_loads (op, opnd_tninfo, adjacent_location,
01709 adjacent_offset_pred, adjacent_offset_succ);
01710 if (op_replaced) {
01711 return TRUE;
01712 }
01713 }
01714
01715 if (EBO_Trace_Hash_Search) {
01716 #pragma mips_frequency_hint NEVER
01717 fprintf(TFile,"%sFail after searching %d items on memory hash chain %d\n",
01718 EBO_trace_pfx,hash_search_length,hash_value);
01719 }
01720
01721 return FALSE;
01722 }
01723
01724
01725 static BOOL
01726 OP_can_change(OP* op)
01727 {
01728 #if defined(TARG_SL)
01729 if ((OP_code(op) == TOP_c3_mvtacc)
01730 || (OP_code(op) == TOP_c3_mvfacc))
01731 return FALSE;
01732 #endif
01733 return TRUE;
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744 static BOOL
01745 find_duplicate_op (BB *bb,
01746 OP *op,
01747 TN **opnd_tn,
01748 EBO_TN_INFO **opnd_tninfo,
01749 EBO_TN_INFO **actual_tninfo)
01750
01751
01752
01753
01754
01755 {
01756 INT opcount;
01757 INT opndnum;
01758 INT hash_value = 0;
01759 INT hash_search_length = 0;
01760 EBO_OP_INFO *opinfo;
01761 BOOL hash_op_matches = FALSE;
01762
01763 if (op == NULL) return FALSE;
01764
01765 if (EBO_Trace_Execution) {
01766 #pragma mips_frequency_hint NEVER
01767 fprintf(TFile,"%sEnter find_duplicate_op\n",EBO_trace_pfx);
01768 }
01769
01770 opcount = OP_opnds(op);
01771
01772 if (OP_memory(op)) return FALSE;
01773
01774 #ifdef TARG_X8664
01775 if( OP_load_exe(op) ) return FALSE;
01776
01777 if( TOP_is_change_rflags( OP_code(op) ) ){
01778 for( OP* next_op = OP_next(op); next_op != NULL; next_op = OP_next( next_op ) ){
01779 if( OP_reads_rflags( next_op ) )
01780 return FALSE;
01781
01782 if( TOP_is_change_rflags( OP_code(next_op) ) )
01783 break;
01784 }
01785 }
01786 #endif
01787
01788 if (!OP_results(op)) return FALSE;
01789
01790
01791
01792
01793
01794 #if defined(TARG_MIPS) || defined(TARG_X8664)
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805 if (OP_cond_def(op)) return FALSE;
01806 #endif
01807
01808 hash_value = EBO_hash_op( op, opnd_tninfo);
01809
01810 if (EBO_Trace_Hash_Search) {
01811 #pragma mips_frequency_hint NEVER
01812 fprintf(TFile,"%sLook for duplicates at hash value %d of\n\t",EBO_trace_pfx,hash_value);
01813 Print_OP_No_SrcLine(op);
01814 }
01815
01816 #ifdef TARG_X8664
01817 opinfo = (opcount == 0 && !EBO_Can_Eliminate_Zero_Opnd_OP(op)) ?
01818 NULL : EBO_opinfo_table[hash_value];
01819 #else
01820 opinfo = (opcount == 0) ? NULL : EBO_opinfo_table[hash_value];
01821 #endif
01822
01823 while (opinfo) {
01824 OP *pred_op = opinfo->in_op;
01825
01826 hash_search_length++;
01827 hash_op_matches = (pred_op != NULL)
01828 #ifdef KEY
01829
01830
01831
01832
01833
01834
01835 && OP_bb(pred_op) != NULL
01836 #endif
01837 && OP_can_change(op)
01838 && (OP_results(op) == OP_results(pred_op))
01839 && (OP_opnds(op) == OP_opnds(pred_op))
01840 && (OP_results(op) == 2 || OP_code(op) == OP_code(pred_op));
01841
01842 if (hash_op_matches) {
01843
01844 for (opndnum = 0; opndnum < opcount; opndnum++) {
01845 if (OP_has_predicate(op) && (opndnum == OP_PREDICATE_OPND)) {
01846
01847 continue;
01848 }
01849 if (opinfo->optimal_opnd[opndnum] == opnd_tninfo[opndnum]) {
01850 if (!TN_Is_Constant(opnd_tn[opndnum])) {
01851
01852
01853 continue;
01854 }
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866 if ((opnd_tn[opndnum] == OP_opnd(pred_op, opndnum)) ||
01867 ((OP_opnd(op, opndnum) == OP_opnd(pred_op, opndnum)) &&
01868 EBO_tn_available(bb, opinfo->actual_opnd[opndnum])) ||
01869 ((opinfo->actual_opnd[opndnum] != NULL) &&
01870 (opnd_tn[opndnum] == opinfo->actual_opnd[opndnum]->replacement_tn))) {
01871 continue;
01872 }
01873 }
01874
01875
01876 hash_op_matches = FALSE;
01877 break;
01878 }
01879
01880 }
01881
01882 if (hash_op_matches &&
01883 (pred_op != NULL)) {
01884 int resnum;
01885
01886 for (resnum = 0; resnum < OP_results(op); resnum++) {
01887
01888 if (!TN_is_const_reg(OP_result(op,resnum)) &&
01889 !EBO_tn_available(bb,opinfo->actual_rslt[resnum])) {
01890
01891 if (EBO_Trace_Hash_Search) {
01892 #pragma mips_frequency_hint NEVER
01893 fprintf(TFile,"%sExpression match found, but the result[%d] value is not available\n\t",
01894 EBO_trace_pfx,resnum);
01895 Print_OP_No_SrcLine(pred_op);
01896 }
01897
01898 hash_op_matches = FALSE;
01899 break;
01900 }
01901 }
01902
01903 }
01904
01905 if (in_delay_slot) {
01906
01907 break;
01908 }
01909
01910 if (hash_op_matches && OP_has_predicate(op)) {
01911
01912 if ((
01913 #if defined(TARG_IA64)
01914 OP_cond_def(pred_op) ||
01915 #endif
01916 !EBO_predicate_dominates(OP_opnd(pred_op,OP_PREDICATE_OPND),
01917 opinfo->optimal_opnd[OP_PREDICATE_OPND],
01918 OP_opnd(op,OP_PREDICATE_OPND),
01919 actual_tninfo[OP_PREDICATE_OPND])) &&
01920 !EBO_predicate_complements(OP_opnd(pred_op,OP_PREDICATE_OPND),
01921 opinfo->optimal_opnd[OP_PREDICATE_OPND],
01922 OP_opnd(op,OP_PREDICATE_OPND),
01923 actual_tninfo[OP_PREDICATE_OPND])) {
01924 hash_op_matches = FALSE;
01925
01926 if (EBO_Trace_Hash_Search) {
01927 #pragma mips_frequency_hint NEVER
01928 fprintf(TFile,"%sExpression match found, but the predicates do not match\n\t",
01929 EBO_trace_pfx);
01930 Print_OP_No_SrcLine(pred_op);
01931 }
01932
01933 }
01934 }
01935
01936 if (hash_op_matches) {
01937
01938 if (EBO_Trace_Hash_Search) {
01939 #pragma mips_frequency_hint NEVER
01940 fprintf(TFile,"%sMatch after searching %d items on expression hash chain %d\n",
01941 EBO_trace_pfx,hash_search_length,hash_value);
01942 }
01943
01944 if (delete_duplicate_op (op, opnd_tninfo, opinfo)) {
01945 return TRUE;
01946 } else {
01947
01948
01949 break;
01950 }
01951 }
01952
01953 opinfo = opinfo->same;
01954 }
01955
01956 if (EBO_Trace_Hash_Search) {
01957 #pragma mips_frequency_hint NEVER
01958 fprintf(TFile,"%sFail after searching %d items on hash chain %d\n",
01959 EBO_trace_pfx,hash_search_length,hash_value);
01960 }
01961
01962 return FALSE;
01963 }
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975 static BOOL
01976 find_previous_constant (OP *op,
01977 EBO_TN_INFO **actual_tninfo)
01978 {
01979 TN *const_tn = OP_opnd(op,copy_operand(op));
01980 EBO_TN_INFO *predicate_tninfo = (OP_has_predicate(op)?actual_tninfo[OP_PREDICATE_OPND]:NULL);
01981 EBO_TN_INFO *check_tninfo;
01982
01983 if (!TN_is_constant(const_tn)) return FALSE;
01984 if (TN_is_const_reg(const_tn)) return FALSE;
01985 if (OP_cond_def(op)) return FALSE;
01986
01987 if (EBO_Trace_Execution) {
01988 #pragma mips_frequency_hint NEVER
01989 fprintf(TFile,"%sEnter find_previous_constant %d\n",
01990 EBO_trace_pfx,(INT32)TN_value(const_tn));
01991 }
01992
01993 for (check_tninfo = EBO_last_tninfo;
01994 check_tninfo != NULL;
01995 check_tninfo = check_tninfo->prior) {
01996 if (check_tninfo->replacement_tn == const_tn) {
01997
01998 TN *pred_tn = check_tninfo->local_tn;
01999 OP *pred_op = check_tninfo->in_op;
02000
02001 if (TN_register_class(OP_result(op, 0)) != TN_register_class(pred_tn)) {
02002 continue;
02003 }
02004 if ((pred_op != NULL) && OP_has_predicate(op) && OP_has_predicate(pred_op)) {
02005
02006 EBO_OP_INFO *opinfo = locate_opinfo_entry(check_tninfo);
02007 if ((opinfo == NULL) ||
02008 OP_cond_def(pred_op) ||
02009 !EBO_predicate_dominates(OP_opnd(pred_op,OP_PREDICATE_OPND),
02010 opinfo->optimal_opnd[OP_PREDICATE_OPND],
02011 OP_opnd(op,OP_PREDICATE_OPND),
02012 predicate_tninfo)) {
02013 if ((OP_code(op) == OP_code(pred_op)) &&
02014 EBO_predicate_complements(OP_opnd(pred_op,OP_PREDICATE_OPND),
02015 opinfo->optimal_opnd[OP_PREDICATE_OPND],
02016 OP_opnd(op,OP_PREDICATE_OPND),
02017 predicate_tninfo) &&
02018 delete_duplicate_op (op, actual_tninfo, opinfo)) {
02019 return TRUE;
02020 }
02021
02022
02023 continue;
02024 }
02025 }
02026 if (EBO_tn_available(OP_bb(op),check_tninfo) &&
02027 (TN_is_rematerializable(pred_tn))) {
02028 OPS ops = OPS_EMPTY;
02029
02030 EBO_Exp_COPY((OP_has_predicate(op)?OP_opnd(op,OP_PREDICATE_OPND):NULL),
02031 OP_result(op, 0), pred_tn, &ops);
02032 if (EBO_in_loop) {
02033 CG_LOOP_Init_Op(OPS_first(&ops));
02034 Set_OP_omega (OPS_first(&ops),
02035 OP_PREDICATE_OPND,
02036 (predicate_tninfo != NULL)?predicate_tninfo->omega:0);
02037 }
02038 OP_srcpos(OPS_first(&ops)) = OP_srcpos(op);
02039 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
02040 #ifdef TARG_X8664
02041
02042
02043
02044 inc_ref_count(check_tninfo);
02045 #endif
02046
02047 if (EBO_Trace_Optimization) {
02048 #pragma mips_frequency_hint NEVER
02049 fprintf(TFile,"%sAvoid reloading constant ",EBO_trace_pfx);
02050 Print_TN(const_tn,FALSE);
02051 fprintf(TFile," into ");
02052 Print_TN(OP_result(op, 0),FALSE);
02053 fprintf(TFile,"\n");
02054 }
02055 return TRUE;
02056 }
02057 return FALSE;
02058 }
02059 }
02060
02061 return FALSE;
02062 }
02063
02064
02065
02066
02067
02068 static BOOL
02069 Find_BB_TNs (BB *bb)
02070 {
02071 OP *op;
02072 BOOL no_barriers_encountered = TRUE;
02073 #ifdef KEY
02074 OP *op_with_reg_usage_info, *next_op_with_reg_usage_info;
02075 INT op_count = 0;
02076 #endif
02077
02078 if (EBO_Trace_Execution) {
02079 #pragma mips_frequency_hint NEVER
02080 fprintf(TFile,"%sEnter Find_BB_TNs BB:%d%s\n",
02081 EBO_trace_pfx,BB_id(bb),EBO_in_peep?" - peep ":" ");
02082 Print_BB(bb);
02083 }
02084
02085 #ifdef KEY
02086 Estimate_Reg_Usage(bb, &MEM_local_pool);
02087 #endif
02088
02089 #ifdef TARG_X8664
02090
02091 BS *LRA_spilled_value_is_used = NULL;
02092 if (EBO_in_peep) {
02093 Init_Remove_Dead_LRA_Stores(&LRA_spilled_value_is_used, &MEM_local_pool);
02094 }
02095
02096
02097 BOOL in_x87_state = FALSE;
02098 OP *maybe_redundant_EMMS_OP = NULL;
02099
02100 const BOOL do_load_execute = ( CG_load_execute > 0 ) && !EBO_in_pre && !EBO_in_loop;
02101 if( do_load_execute ){
02102 Init_Load_Exec_Map( bb, &MEM_local_pool );
02103 }
02104 #endif
02105
02106
02107
02108
02109
02110
02111
02112
02113 INT max_opnds = OP_MAX_FIXED_OPNDS;
02114 FOR_ALL_BB_OPs (bb, op) {
02115 INT nopnds = OP_opnds(op);
02116 if (nopnds > max_opnds) max_opnds = nopnds;
02117 #ifdef KEY
02118 op_count++;
02119 #endif
02120 }
02121 TN **opnd_tn = TYPE_ALLOCA_N(TN *, max_opnds);
02122 EBO_TN_INFO **opnd_tninfo = TYPE_ALLOCA_N(EBO_TN_INFO *, max_opnds);
02123 EBO_TN_INFO **orig_tninfo = TYPE_ALLOCA_N(EBO_TN_INFO *, max_opnds);
02124
02125 in_delay_slot = FALSE;
02126
02127 #ifdef KEY
02128 int op_num = 0;
02129 int *regs_used;
02130
02131
02132 int last_fat_point[ISA_REGISTER_CLASS_MAX+1];
02133 ISA_REGISTER_CLASS cl;
02134
02135
02136 regs_used = (int*)alloca((ISA_REGISTER_CLASS_MAX+1)*(op_count+1)*sizeof(int));
02137 memset (regs_used, 0,
02138 (ISA_REGISTER_CLASS_MAX+1) * (op_count+1) * sizeof(int));
02139 FOR_ALL_ISA_REGISTER_CLASS(cl) {
02140 last_fat_point[cl] = 0;
02141 }
02142
02143
02144
02145
02146 op_with_reg_usage_info = BB_first_op(bb);
02147 #endif
02148
02149 FOR_ALL_BB_OPs (bb, op) {
02150 TN *tn;
02151 INT opndnum;
02152 INT resnum;
02153 EBO_TN_INFO *tninfo;
02154 TN *tn_replace;
02155 INT num_opnds = OP_opnds(op);
02156 TN *rslt_tn = NULL;
02157 INT rslt_num = 0;
02158 BOOL opnds_constant = TRUE;
02159 BOOL op_replaced = FALSE;
02160 BOOL op_is_predicated = OP_has_predicate(op)?TRUE:FALSE;
02161 TN *op_predicate_tn = NULL;
02162 EBO_TN_INFO *op_predicate_tninfo = NULL;
02163 BOOL check_omegas = (EBO_in_loop && _CG_LOOP_info(op))?TRUE:FALSE;
02164
02165
02166 FmtAssert(num_opnds <= max_opnds, ("dynamic array allocation was too small!"));
02167
02168 #ifdef KEY
02169
02170 if (op == op_with_reg_usage_info) {
02171 op_num++;
02172 next_op_with_reg_usage_info = OP_next(op);
02173 }
02174 #endif
02175
02176 if (CGTARG_Is_OP_Barrier(op) || OP_access_reg_bank(op)) {
02177 if (Special_Sequence(op, NULL, NULL)) {
02178
02179 if (EBO_Trace_Execution) {
02180 #pragma mips_frequency_hint NEVER
02181 fprintf(TFile,"%sWe were able to restrict propagation of the specific registers in BB:%d\t",
02182 EBO_trace_pfx,BB_id(OP_bb(op)));
02183 Print_OP_No_SrcLine(op);
02184 }
02185 } else {
02186
02187 if (EBO_Trace_Execution) {
02188 #pragma mips_frequency_hint NEVER
02189 fprintf(TFile,"%sFind_BB_TNs Barrier OP encountered\t",EBO_trace_pfx);
02190 Print_OP_No_SrcLine(op);
02191 }
02192 no_barriers_encountered = FALSE;
02193 }
02194 }
02195
02196 #ifdef TARG_X8664
02197
02198
02199
02200 if (OP_code(op) == TOP_emms) {
02201 if (in_x87_state)
02202 OP_Change_To_Noop(op);
02203 else
02204 maybe_redundant_EMMS_OP = op;
02205 in_x87_state = TRUE;
02206 } else if (OP_x87(op)) {
02207 in_x87_state = TRUE;
02208 maybe_redundant_EMMS_OP = NULL;
02209 } else if (OP_mmx(op)) {
02210 if (maybe_redundant_EMMS_OP != NULL) {
02211 OP_Change_To_Noop(maybe_redundant_EMMS_OP);
02212 maybe_redundant_EMMS_OP = NULL;
02213 }
02214 in_x87_state = FALSE;
02215 }
02216 #endif
02217
02218 if ((num_opnds == 0) && (OP_results(op) == 0))
02219 #ifdef KEY
02220 goto finish;
02221 #else
02222 continue;
02223 #endif
02224
02225 if (EBO_Trace_Data_Flow) {
02226 fprintf(TFile,"%sProcess OP\n\t",EBO_trace_pfx); Print_OP_No_SrcLine(op);
02227 }
02228
02229
02230 for (opndnum = 0; opndnum < num_opnds; opndnum++) {
02231 opnd_tn[opndnum] = NULL;
02232 opnd_tninfo[opndnum] = NULL;
02233 orig_tninfo[opndnum] = NULL;
02234 }
02235
02236 for (opndnum = 0; opndnum < num_opnds; opndnum++) {
02237 BOOL replace_result = FALSE;
02238 mUINT8 operand_omega = 0;
02239 #ifdef KEY
02240 BOOL dont_replace = FALSE;
02241 #endif
02242
02243 tn = OP_opnd(op, opndnum);
02244 tninfo = NULL;
02245 tn_replace = NULL;
02246 opnd_tn[opndnum] = tn;
02247 opnd_tninfo[opndnum] = NULL;
02248 orig_tninfo[opndnum] = NULL;
02249 operand_omega = check_omegas ? OP_omega(op,opndnum) : 0;
02250
02251 if (tn == NULL || TN_is_constant(tn) || TN_is_label(tn)) {
02252 continue;
02253 }
02254
02255 #ifdef KEY
02256
02257
02258
02259 if (OP_code(op) == TOP_asm) {
02260 UINT i;
02261 for (i = 0; i < OP_results(op) && !dont_replace; i ++)
02262 if (OP_result(op, i) == tn)
02263 dont_replace = TRUE;
02264
02265
02266
02267
02268
02269 for (i = 0; i < OP_opnds(op) && !dont_replace; i ++)
02270 if (OP_opnd(op, i) == tn)
02271 dont_replace = TRUE;
02272 }
02273
02274
02275
02276
02277 if( !EBO_in_peep &&
02278 !CG_localize_tns &&
02279 TN_is_gra_homeable(tn) &&
02280 TN_is_global_reg(tn) &&
02281 OP_store( op ) ){
02282 WN* wn = Get_WN_From_Memory_OP( op );
02283 if( wn != NULL &&
02284 WN_has_sym(wn) &&
02285
02286 WN_st(wn) == WN_st(TN_home(tn)) ){
02287 dont_replace = TRUE;
02288 }
02289 }
02290 #endif
02291
02292 #ifdef TARG_MIPS
02293 if (OP_code(op) == TOP_jalr) {
02294 dont_replace = TRUE;
02295 }
02296 #endif
02297
02298 if (tn != True_TN) {
02299 #ifdef TARG_X8664
02300 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( op, opndnum, FALSE );
02301 if( tmp_tn == NULL )
02302 tmp_tn = tn;
02303
02304 tninfo = tn_info_use ( bb, op, tmp_tn, op_predicate_tn,
02305 op_predicate_tninfo, operand_omega );
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324 if (tn != tmp_tn)
02325 tninfo = tn_info_use ( bb, op, tn, op_predicate_tn,
02326 op_predicate_tninfo, operand_omega );
02327 #else
02328 tninfo = tn_info_use ( bb, op, tn, op_predicate_tn,
02329 op_predicate_tninfo, operand_omega );
02330 #endif
02331
02332 orig_tninfo[opndnum] = tninfo;
02333 tn_replace = tninfo->replacement_tn;
02334
02335 #ifdef TARG_X8664
02336
02337
02338 if( Is_Target_32bit() &&
02339 tn_replace != NULL &&
02340 TN_is_register(tn_replace) &&
02341 TN_register(tn_replace) != REGISTER_UNDEFINED &&
02342 OP_opnd_size( op, opndnum ) == 8 ){
02343 const REGISTER reg = TN_register(tn_replace);
02344 const REGISTER_SET regs =
02345 REGISTER_SUBCLASS_members(ISA_REGISTER_SUBCLASS_m32_8bit_regs);
02346 Is_True(TN_register_class(tn) == ISA_REGISTER_CLASS_integer,
02347 ("Find_BB_TNs: TN not integer register class"));
02348
02349 if( !REGISTER_SET_MemberP( regs, reg ) )
02350 tn_replace = NULL;
02351 }
02352
02353 if( tn_replace != NULL ){
02354 if( EBO_in_peep &&
02355 opndnum == 0 &&
02356 OP_x86_style( op ) &&
02357 !tn_registers_identical( tn_replace, OP_result(op,0) ) ){
02358 tn_replace = NULL;
02359 }
02360
02361 if( tn_replace != NULL &&
02362 TN_is_register( tn_replace ) &&
02363 TN_register( tn_replace ) == RSP &&
02364 TOP_Find_Operand_Use( OP_code(op), OU_index ) == opndnum ){
02365 tn_replace = NULL;
02366 }
02367 }
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381 if ( tn_replace != NULL &&
02382 !EBO_in_peep &&
02383 TN_is_dedicated( tn_replace ) &&
02384 TN_register_class(tn_replace) == ISA_REGISTER_CLASS_integer ){
02385 const REGISTER reg = TN_register(tn_replace);
02386 if( reg == RAX || reg == RCX || reg == RDX ){
02387 tn_replace = NULL;
02388 }
02389 }
02390 #endif
02391
02392 #ifdef KEY
02393 if( dont_replace ){
02394 tn_replace = NULL;
02395 }
02396 #endif
02397 }
02398
02399 #ifdef KEY
02400 if (!dont_replace)
02401 #endif
02402 if (OP_same_res(op)) {
02403 INT i;
02404 for (i=0; i<OP_results(op); i++) {
02405 if (tn_registers_identical(tn, OP_result(op,i))) {
02406
02407 replace_result = TRUE;
02408 rslt_num = i;
02409 break;
02410 }
02411 }
02412 }
02413
02414 if ((tn_replace != NULL) &&
02415 (TN_Is_Constant(tn_replace) ||
02416 EBO_tn_available(bb,tninfo->replacement_tninfo) ||
02417 ((tn_registers_identical(tn, tn_replace)) && !check_omegas)) &&
02418 (TN_Is_Constant(tn_replace) ||
02419 ((tninfo->replacement_tninfo != NULL) &&
02420 (tninfo->replacement_tninfo->in_bb == bb)) ||
02421 ((has_assigned_reg(tn) == has_assigned_reg(tn_replace)) &&
02422 (EBO_in_peep || (!BB_reg_alloc(bb) && !TN_is_dedicated(tn_replace)))))
02423 #ifdef TARG_IA64
02424 && !OP_ld_st_unat(op)
02425 #endif
02426 ) {
02427
02428
02429
02430 if (EBO_Trace_Data_Flow) {
02431 #pragma mips_frequency_hint NEVER
02432 fprintf(TFile, "%sin BB:%d propagate value for opnd[%d] ",
02433 EBO_trace_pfx, BB_id(OP_bb(op)),opndnum);
02434 Print_TN(tn, FALSE);
02435 fprintf(TFile," with ");
02436 Print_TN(tn_replace, FALSE);
02437 fprintf(TFile,"\n");
02438 }
02439
02440 TN *old_tn = tn;
02441 tn = tninfo->replacement_tn;
02442 tninfo = tninfo->replacement_tninfo;
02443
02444 #ifdef KEY
02445 EBO_REG_ENTRY reginfo;
02446 BOOL inside_lr = TRUE;
02447
02448 EBO_OP_INFO *pred_opinfo = locate_opinfo_entry(tninfo);
02449 #endif
02450 if (!TN_is_constant(tn) &&
02451 (!OP_store(op) ||
02452 (opndnum != TOP_Find_Operand_Use(OP_code(op),OU_storeval)) ||
02453 !TN_has_spill(old_tn)) &&
02454 (!TN_save_reg(tn)) &&
02455 (!replace_result || tn_registers_identical(old_tn, tn_replace)) &&
02456 (EBO_in_peep ||
02457 (has_assigned_reg(old_tn) == has_assigned_reg(tn_replace)) ||
02458 (TN_is_const_reg(tn)) ||
02459 (!OP_copy(op))) &&
02460 (EBO_in_peep ||
02461 !TN_is_gra_homeable(tn_replace) ||
02462 (tninfo->in_bb == bb)) &&
02463 (TN_register_class(old_tn) == TN_register_class(tn_replace)) &&
02464 (!has_assigned_reg(old_tn) ||
02465 (ISA_OPERAND_VALTYP_Register_Subclass(ISA_OPERAND_INFO_Operand(ISA_OPERAND_Info(OP_code(op)),opndnum)) == ISA_REGISTER_SUBCLASS_UNDEFINED) ||
02466 (has_assigned_reg(tn_replace) &&
02467 (REGISTER_SET_MemberP(REGISTER_SUBCLASS_members(ISA_OPERAND_VALTYP_Register_Subclass(ISA_OPERAND_INFO_Operand(ISA_OPERAND_Info(OP_code(op)),opndnum))), TN_register(tn_replace))))) &&
02468 (TN_size(old_tn) <= TN_size(tn_replace)) &&
02469 (TN_is_float(old_tn) == TN_is_float(tn_replace)) &&
02470 (TN_is_fpu_int(old_tn) == TN_is_fpu_int(tn_replace)) &&
02471 ((OP_results(op) == 0) ||
02472 !OP_uniq_res(op) ||
02473 !tn_registers_identical(tn, OP_result(op,0)))
02474 #ifdef TARG_IA64
02475 && !OP_ld_st_unat(op) &&
02476 !TN_is_dedicated(OP_opnd(op,opndnum))
02477 #endif
02478 #ifdef KEY
02479 && (TN_is_global_reg(tn_replace) ||
02480
02481 (EBO_REG_ENTRY_ptr(reginfo) = hTN_MAP_Get(regs_map,tn_replace),
02482 inside_lr =
02483 (EBO_REG_ENTRY_last_use_OP_num(reginfo) >= op_num)) ||
02484
02485 (pred_opinfo == NULL ||
02486 (pred_opinfo->op_num >=
02487 last_fat_point[TN_register_class(tn_replace)])))
02488 #endif
02489 ) {
02490
02491
02492
02493
02494
02495 if (EBO_Trace_Optimization) {
02496 #pragma mips_frequency_hint NEVER
02497 fprintf(TFile, "%sin BB:%d replace opnd[%d] ",
02498 EBO_trace_pfx, BB_id(OP_bb(op)),opndnum);
02499 Print_TN(OP_opnd(op, opndnum), FALSE);
02500 fprintf(TFile," with ");
02501 Print_TN(tn_replace, FALSE);
02502 if (!TN_Is_Constant(tn_replace) &&
02503 (tninfo != NULL) &&
02504 (tninfo->in_bb != NULL)) {
02505 fprintf(TFile," from BB:%d",BB_id(tninfo->in_bb));
02506 }
02507 fprintf(TFile,"\n");
02508 }
02509
02510 dec_ref_count(orig_tninfo[opndnum]);
02511 Set_OP_opnd(op, opndnum, tn);
02512 if (check_omegas) {
02513 Set_OP_omega (op, opndnum, (tninfo != NULL) ? tninfo->omega : 0);
02514 }
02515
02516 if (tninfo != NULL) {
02517 inc_ref_count(tninfo);
02518 }
02519
02520 if (replace_result) {
02521
02522 rslt_tn = tn;
02523 }
02524
02525
02526 orig_tninfo[opndnum] = tninfo;
02527
02528 #ifdef KEY
02529
02530
02531 if (!inside_lr && tninfo)
02532 Extend_Live_Range(regs_used, last_fat_point, op_num, tninfo,
02533 reginfo, bb);
02534 #endif
02535 }
02536 }
02537
02538 opnd_tn[opndnum] = tn;
02539 opnd_tninfo[opndnum] = tninfo;
02540 if (!TN_Is_Constant(tn) &&
02541 (!op_is_predicated || (opndnum != OP_PREDICATE_OPND))) {
02542 opnds_constant = FALSE;
02543 }
02544
02545 if (op_is_predicated && (opndnum == OP_PREDICATE_OPND)) {
02546 if ((tn == Zero_TN) && !OP_xfer(op)) {
02547 #ifdef TARG_X8664
02548 FmtAssert( false, ("X86 has no Zero_TN") );
02549 #endif
02550
02551
02552
02553 op_replaced = Fold_Constant_Expression (op, opnd_tn, opnd_tninfo);
02554 num_opnds = opndnum + 1;
02555
02556 if (EBO_Trace_Optimization) {
02557 #pragma mips_frequency_hint NEVER
02558 fprintf(TFile, "%sin BB:%d Op can not execute with 0 predicate\n",
02559 EBO_trace_pfx, BB_id(OP_bb(op)));
02560 }
02561 if (op_replaced) break;
02562 }
02563
02564 op_predicate_tn = tn;
02565 op_predicate_tninfo = tninfo;
02566 }
02567
02568 }
02569
02570 if (OP_memory(op)) {
02571 if (!op_replaced &&
02572 OP_same_res(op)) {
02573 op_replaced = EBO_Fix_Same_Res_Op (op, opnd_tn, opnd_tninfo);
02574 }
02575 if (!op_replaced &&
02576 !in_delay_slot &&
02577 OP_store(op)) {
02578 op_replaced = Special_Sequence ( op, opnd_tn, orig_tninfo);
02579 }
02580 if (!op_replaced &&
02581 no_barriers_encountered) {
02582 op_replaced = find_duplicate_mem_op (bb, op, opnd_tn, opnd_tninfo,
02583 orig_tninfo, op_num, regs_used,
02584 last_fat_point);
02585 }
02586 #ifdef TARG_X8664
02587 if (WOPT_Enable_Autoaggstr_Reduction_Threshold > 0 &&
02588 LNO_Run_Prefetch != AGGRESSIVE_PREFETCH &&
02589 !EBO_in_peep && !op_replaced && OP_prefetch(op)) {
02590 op_replaced = Delete_Unwanted_Prefetches(op);
02591 }
02592 if( !op_replaced &&
02593 do_load_execute &&
02594 OP_store(op) ){
02595 Update_op_must_not_be_moved( op, opnd_tninfo );
02596 }
02597 if( !op_replaced ){
02598 op_replaced = EBO_Merge_Memory_Addr( op, opnd_tn, opnd_tninfo, orig_tninfo );
02599 }
02600 #endif
02601 } else if (OP_effectively_copy(op)) {
02602 if (!op_replaced &&
02603 opnds_constant && !in_delay_slot) {
02604 op_replaced = find_previous_constant(op, opnd_tninfo);
02605 }
02606 if (!op_replaced) {
02607 op_replaced = Special_Sequence (op, opnd_tn, opnd_tninfo);
02608 }
02609 } else if (!op_replaced &&
02610 !OP_effectively_copy(op) &&
02611 !OP_glue(op) &&
02612 !OP_side_effects(op) &&
02613 !OP_access_reg_bank(op)) {
02614 if (!in_delay_slot) {
02615
02616 if (opnds_constant && (num_opnds > 1)) {
02617 if (OP_xfer(op)) {
02618
02619
02620
02621 op_replaced = Resolve_Conditional_Branch (op, opnd_tn);
02622 rerun_cflow |= op_replaced;
02623 } else if (OP_results(op) >= 1) {
02624 op_replaced = Fold_Constant_Expression (op, opnd_tn, opnd_tninfo);
02625 }
02626 } else if (num_opnds > 1) {
02627 if (OP_results(op) > 0) {
02628
02629 INT o2_idx;
02630 INT o1_idx;
02631 if (op_is_predicated) {
02632 if (OP_fadd(op) || OP_fsub(op) || OP_fmul(op) || OP_fdiv(op)) {
02633
02634 o1_idx = (num_opnds > 2) ? 2 : -1;
02635 o2_idx = (num_opnds > 3) ? 3 : -1;
02636 } else {
02637 o1_idx = (num_opnds > 1) ? 1 : -1;
02638 o2_idx = (num_opnds > 2) ? 2 : -1;
02639 }
02640 } else {
02641 o1_idx = (num_opnds > 0) ? 0 : -1;
02642 o2_idx = (num_opnds > 1) ? 1 : -1;
02643 }
02644
02645 if (OP_same_res(op)) {
02646 op_replaced = EBO_Fix_Same_Res_Op (op, opnd_tn, opnd_tninfo);
02647 }
02648 if (o2_idx >= 0) {
02649 tn = opnd_tn[o2_idx];
02650 if (!op_replaced &&
02651 (tn != NULL) &&
02652 TN_Is_Constant(tn) && TN_Has_Value(tn)) {
02653 op_replaced = Constant_Operand1 (op, opnd_tn, opnd_tninfo);
02654 }
02655 }
02656 if (o1_idx >= 0) {
02657 tn = opnd_tn[o1_idx];
02658 if (!op_replaced &&
02659 (tn != NULL) &&
02660 TN_Is_Constant(tn) && TN_Has_Value(tn)) {
02661 op_replaced = Constant_Operand0 (op, opnd_tn, opnd_tninfo);
02662 }
02663 }
02664 }
02665 if (!op_replaced) {
02666 op_replaced = Special_Sequence (op, opnd_tn, orig_tninfo);
02667 }
02668 }
02669 #ifdef TARG_X8664
02670 else if (num_opnds == 1) {
02671 if (OP_results(op) > 0) {
02672 if (!op_replaced) {
02673 op_replaced = Special_Sequence (op, opnd_tn, orig_tninfo);
02674 }
02675 }
02676 }
02677 #endif
02678 }
02679
02680 if (no_barriers_encountered && !op_replaced && !OP_effectively_copy(op)) {
02681
02682 op_replaced = find_duplicate_op(bb, op, opnd_tn, opnd_tninfo, orig_tninfo);
02683 }
02684
02685 #ifdef TARG_X8664
02686 if( do_load_execute &&
02687 !op_replaced &&
02688 !OP_effectively_copy(op) ){
02689 op_replaced = EBO_Load_Execution( op, opnd_tn, orig_tninfo );
02690 }
02691
02692 if( !op_replaced &&
02693 !OP_effectively_copy(op) ){
02694 op_replaced = EBO_Lea_Insertion( op, opnd_tn, orig_tninfo );
02695 }
02696 if (!op_replaced &&
02697 !OP_effectively_copy(op) ) {
02698 op_replaced = EBO_Fold_Load_Duplicate( op, opnd_tn, orig_tninfo );
02699 }
02700 if (!op_replaced && TOP_is_move_ext( OP_code(op) ))
02701 op_replaced = Special_Sequence( op, opnd_tn, orig_tninfo );
02702 #endif
02703 }
02704
02705 if (op_replaced) {
02706 if (EBO_Trace_Optimization) {
02707 fprintf(TFile,"%sin BB:%d remove simplified op - ",EBO_trace_pfx,BB_id(bb));
02708 Print_OP_No_SrcLine(op);
02709 }
02710 #ifdef KEY
02711
02712
02713
02714
02715
02716 Update_Reg_Usage(op, op_num, regs_used, last_fat_point, OP_load(op));
02717
02718
02719
02720 if (OP_load(op)) {
02721 ST *spill_loc = CGSPILL_OP_Spill_Location(op);
02722 if (spill_loc != (ST *)0) {
02723 SPILL_SYM_INFO &info = CGSPILL_Get_Spill_Sym_Info(spill_loc);
02724 if (info.Restore_Count() == 1 &&
02725 info.Spill_Count() == 1 &&
02726 !info.Used_By_Load_Exe()) {
02727 OP *spill_op = info.Spill_Op();
02728 Is_True(spill_op != NULL, ("Find_BB_TNs: missing spill OP"));
02729 OP_Change_To_Noop(spill_op);
02730 }
02731 }
02732 }
02733 #endif
02734 remove_uses (num_opnds, orig_tninfo);
02735 OP_Change_To_Noop(op);
02736 #ifdef TARG_IA64
02737 Reset_BB_scheduled(bb);
02738 #endif
02739 } else {
02740
02741 add_to_hash_table (in_delay_slot, op, orig_tninfo, opnd_tninfo);
02742
02743 FmtAssert(((EBO_last_opinfo != NULL) && (EBO_last_opinfo->in_op == op)),
02744 ("OP wasn't added to hash table"));
02745
02746 #ifdef KEY
02747 EBO_last_opinfo->op_num = op_num;
02748 #endif
02749
02750
02751 resnum = OP_results(op);
02752 if (OP_effectively_copy(op) || (resnum && OP_glue(op) && !OP_memory(op))) {
02753
02754 INT cix = copy_operand(op);
02755 TN *tnr = OP_result(op, 0);
02756
02757 if ((tnr != NULL) && (tnr != True_TN) && (tnr != Zero_TN)) {
02758 tninfo = EBO_last_opinfo->actual_rslt[0];
02759
02760 if (!OP_glue(op) && (cix >= 0)) {
02761 tninfo->replacement_tn = opnd_tn[cix];
02762 tninfo->replacement_tninfo = opnd_tninfo[cix];
02763
02764 #ifdef TARG_X8664
02765
02766
02767
02768
02769
02770 if( TN_Is_Constant( tninfo->replacement_tn ) &&
02771 OP_code(op) != TOP_ldc64 &&
02772 OP_code(op) != TOP_ldc32 ){
02773 tninfo->replacement_tn = OP_opnd( op, cix );
02774 tninfo->replacement_tninfo = orig_tninfo[cix];
02775 }
02776 #endif
02777
02778 if (EBO_Trace_Data_Flow) {
02779 #pragma mips_frequency_hint NEVER
02780 fprintf(TFile,"%sPropagate Copy of ",EBO_trace_pfx);
02781 Print_TN(tninfo->replacement_tn,FALSE);
02782 fprintf(TFile,"[%d] into ",(tninfo->replacement_tninfo != NULL)?tninfo->replacement_tninfo->omega:0);
02783 Print_TN(tnr,FALSE); fprintf(TFile,"\n");
02784 }
02785 }
02786 }
02787
02788 if ((resnum == 2) && ((tnr=OP_result(op,1)) != NULL) && (tnr != True_TN) && (tnr != Zero_TN)
02789 #ifdef TARG_IA64
02790 && (tnr != FZero_TN)
02791 #endif
02792 ) {
02793
02794
02795 tninfo = EBO_last_opinfo->actual_rslt[1];
02796 tninfo->replacement_tn = Zero_TN;
02797 #ifdef TARG_X8664
02798 FmtAssert( false, ("X86 does not have Zero_TN") );
02799 #endif
02800
02801 if (EBO_Trace_Data_Flow) {
02802 #pragma mips_frequency_hint NEVER
02803 fprintf(TFile,"%sPropagate Copy of ",EBO_trace_pfx);
02804 Print_TN(tninfo->replacement_tn,FALSE); fprintf(TFile," into ");
02805 Print_TN(tnr,FALSE); fprintf(TFile,"\n");
02806 }
02807 }
02808
02809 } else if (rslt_tn != NULL) {
02810 #ifdef KEY
02811 if (op->opr == TOP_asm && TN_is_constant(rslt_tn))
02812 ;
02813 else {
02814 #endif
02815
02816 TN *tnr = OP_result(op, rslt_num);
02817 tninfo = EBO_last_opinfo->actual_rslt[rslt_num];
02818
02819
02820
02821
02822
02823 tninfo->replacement_tn = rslt_tn;
02824 tninfo->replacement_tninfo = tninfo;
02825 Set_OP_result (op, rslt_num, rslt_tn);
02826
02827 if (EBO_Trace_Data_Flow) {
02828 #pragma mips_frequency_hint NEVER
02829 fprintf(TFile,"%sReplace result[%d] tn ",EBO_trace_pfx,rslt_num);
02830 Print_TN(tnr,FALSE); fprintf(TFile," with ");
02831 Print_TN(rslt_tn, FALSE); fprintf(TFile,"\n");
02832 }
02833 #ifdef KEY
02834 }
02835 #endif
02836
02837 }
02838 }
02839
02840 if (PROC_has_branch_delay_slot()) in_delay_slot = OP_xfer(op);
02841
02842 #ifdef KEY
02843 finish:
02844
02845 #ifdef TARG_X8664
02846
02847
02848 if (EBO_in_peep &&
02849 !op_replaced) {
02850 Mark_LRA_Spill_Reference(op, &LRA_spilled_value_is_used, &MEM_local_pool);
02851 }
02852 #endif
02853
02854
02855
02856 Is_True(op_num <= op_count, ("Find_BB_TNs: wrong op_num"));
02857 if (op == op_with_reg_usage_info) {
02858 op_with_reg_usage_info = next_op_with_reg_usage_info;
02859 if (!op_replaced)
02860 Update_Reg_Usage(op, op_num, regs_used, last_fat_point, FALSE);
02861 }
02862 #endif
02863 }
02864
02865 #ifdef TARG_X8664
02866
02867
02868
02869
02870 if (EBO_in_peep) {
02871 FOR_ALL_BB_OPs (bb, op) {
02872 Delete_Dead_LRA_Spill(op, &LRA_spilled_value_is_used);
02873 }
02874 }
02875 #endif
02876
02877 return no_barriers_encountered;
02878 }
02879
02880
02881
02882
02883
02884 #ifdef KEY
02885 static int removed_ops = 0;
02886 #endif
02887 static
02888 void EBO_Remove_Unused_Ops (BB *bb, BOOL BB_completely_processed)
02889
02890
02891
02892 {
02893 EBO_OP_INFO *opinfo;
02894 EBO_TN_INFO *tninfo;
02895 TN *tn;
02896
02897 if (EBO_first_opinfo == NULL) return;
02898
02899 if (EBO_Trace_Execution) {
02900 #pragma mips_frequency_hint NEVER
02901 fprintf(TFile,"%sEnter EBO_Remove_Unused_Ops in BB:%d\n",EBO_trace_pfx,BB_id(bb));
02902 tn_info_table_dump();
02903 }
02904
02905 for (opinfo = EBO_last_opinfo; opinfo != NULL; opinfo = opinfo->prior) {
02906 INT rslt_count = 0;
02907 INT idx;
02908 OP *op = opinfo->in_op;
02909
02910 #ifndef KEY
02911 if (op == NULL) continue;
02912 #else
02913
02914 if (op == NULL || op->bb == NULL) continue;
02915
02916
02917 if (!EBO_can_delete_branch_delay_OP &&
02918 PROC_has_branch_delay_slot() &&
02919 BB_last_op(bb) == op &&
02920 OP_prev(op) != NULL &&
02921 OP_xfer(OP_prev(op))) {
02922 goto op_is_needed;
02923 }
02924 #endif
02925
02926 if (OP_bb(op) != bb) {
02927 if (EBO_Trace_Block_Flow) {
02928 #pragma mips_frequency_hint NEVER
02929 fprintf(TFile,"Stop looking for unused ops, next op is in BB:%d\n",
02930 OP_bb(op) ? BB_id(OP_bb(op)) : -1);
02931 Print_OP_No_SrcLine(op);
02932 }
02933 break;
02934 }
02935
02936 if (EBO_Trace_Data_Flow) {
02937 #pragma mips_frequency_hint NEVER
02938 fprintf(TFile,"%sConsider removing OP:\n\t",
02939 EBO_trace_pfx);
02940 Print_OP_No_SrcLine(op);
02941 }
02942
02943 rslt_count = OP_results(op);
02944 if (rslt_count == 0) goto op_is_needed;
02945 #ifdef TARG_IA64
02946 for (int i = 0; i < rslt_count ; i++) {
02947 if (OP_result(op,i) == RA_TN) goto op_is_needed;
02948 extern TN *Caller_GP_TN;
02949 if (OP_result(op,i) == Caller_GP_TN && PU_has_exc_scopes(Get_Current_PU()))
02950 goto op_is_needed;
02951 }
02952 #endif
02953
02954 if (op_is_needed_globally(op)) goto op_is_needed;
02955
02956
02957 for (idx = 0; idx < rslt_count; idx++) {
02958 tninfo = opinfo->actual_rslt[idx];
02959
02960
02961 if (tninfo == NULL) continue;
02962 if (tninfo->in_bb != bb) goto op_is_needed;
02963 if (tninfo->in_op == NULL) goto op_is_needed;
02964 tn = tninfo->local_tn;
02965
02966 if (EBO_Trace_Data_Flow) {
02967 #pragma mips_frequency_hint NEVER
02968 fprintf(TFile,"%sTry to remove definition of entry[%d] ",
02969 EBO_trace_pfx,tninfo->sequence_num);
02970 Print_TN(tn,FALSE);
02971 fprintf(TFile,"\n");
02972 }
02973
02974
02975 #ifndef TARG_IA64
02976 FmtAssert( tn != Zero_TN, ("NYI") );
02977 #endif
02978
02979 if (tn == FZero_TN) continue;
02980 if (tn == Zero_TN) continue;
02981 if (tn == True_TN) continue;
02982
02983 #ifdef TARG_IA64
02984
02985 if(OP_ld_st_unat(op)) goto op_is_needed;
02986 #endif
02987
02988
02989 if (EBO_in_peep &&
02990 OP_effectively_copy(op) &&
02991 has_assigned_reg(tn) &&
02992 (copy_operand(op) >= 0) &&
02993 has_assigned_reg(OP_opnd(op,copy_operand(op))) &&
02994 (tn_registers_identical(tn, OP_opnd(op,copy_operand(op))))
02995 #ifdef TARG_IA64
02996 && !(OP_has_predicate(op) && tn_registers_identical(tn, OP_opnd(op,OP_PREDICATE_OPND)))
02997 #endif
02998 ) {
02999 INT cpo = copy_operand(op);
03000
03001
03002
03003 if ((opinfo->actual_opnd[cpo] != NULL) &&
03004 (bb != opinfo->actual_opnd[cpo]->in_bb)) {
03005 mark_tn_live_into_BB (tn, bb, opinfo->actual_opnd[cpo]->in_bb);
03006 }
03007
03008
03009 if (tninfo->same != NULL) {
03010 tninfo->same->reference_count += tninfo->reference_count;
03011 }
03012
03013 if (!tninfo->redefined_before_block_end &&
03014 (tninfo->same != NULL) &&
03015 (tninfo->same->in_bb == bb)) {
03016
03017
03018 tninfo->same->redefined_before_block_end = FALSE;
03019 }
03020 goto can_be_removed;
03021 }
03022
03023
03024 if (!BB_completely_processed) goto op_is_needed;
03025 if (tninfo->reference_count != 0) goto op_is_needed;
03026 if (OP_has_implicit_interactions(tninfo->in_op))
03027 goto op_is_needed;
03028
03029
03030 if (!tninfo->redefined_before_block_end &&
03031 TN_live_out_of(tn, tninfo->in_bb)) goto op_is_needed;
03032
03033 if (TN_is_pfs_reg(tn)) goto op_is_needed;
03034 if (TN_is_lc_reg(tn)) goto op_is_needed;
03035 if (TN_is_ec_reg(tn)) goto op_is_needed;
03036 }
03037
03038
03039 if (opinfo->op_must_not_be_removed) goto op_is_needed;
03040 if (OP_store(op)) goto op_is_needed;
03041
03042 #ifdef TARG_IA64
03043
03044 if (CGTARG_Is_OP_Speculative(op)) goto op_is_needed;
03045 if (CGTARG_Is_OP_Check_Load(op)) goto op_is_needed;
03046 if (BB_recovery(OP_bb(op))) goto op_is_needed;
03047 #endif
03048
03049 #ifdef TARG_X8664
03050 if( TOP_is_change_rflags( OP_code(op) ) ){
03051 for( OP* next = OP_next(op); next != NULL; next = OP_next(next) ){
03052 if( OP_reads_rflags( next) )
03053 goto op_is_needed;
03054 if( TOP_is_change_rflags( OP_code(next) ) )
03055 break;
03056 }
03057 }
03058 #endif
03059
03060 can_be_removed:
03061
03062 remove_op (opinfo);
03063
03064 if (EBO_Trace_Optimization) {
03065 #pragma mips_frequency_hint NEVER
03066 fprintf(TFile, "%sin BB:%d removing ",
03067 EBO_trace_pfx, BB_id(bb));
03068 Print_OP_No_SrcLine(op);
03069 }
03070
03071 if (opinfo->in_delay_slot) {
03072 OP_Change_To_Noop(op);
03073 } else {
03074 #ifdef KEY
03075
03076
03077 if (BB_first_op(bb) == op &&
03078 PROC_has_branch_delay_slot()) {
03079 EBO_Adjust_Pred_Branch_Target(bb);
03080 }
03081 #endif
03082 BB_Remove_Op(bb, op);
03083 }
03084 opinfo->in_op = NULL;
03085 opinfo->in_bb = NULL;
03086
03087
03088 for (idx = 0; idx < rslt_count; idx++) {
03089 tninfo = opinfo->actual_rslt[idx];
03090 if ((tninfo != NULL) &&
03091 tninfo->redefined_before_block_end &&
03092 (tninfo->same != NULL) &&
03093 (tninfo->same->in_bb == bb)) {
03094 EBO_TN_INFO *next_tninfo = tninfo->same;
03095 next_tninfo->redefined_before_block_end = TRUE;
03096 }
03097 }
03098 #ifdef TARG_IA64
03099 Reset_BB_scheduled(bb);
03100 #endif
03101 #ifdef KEY
03102 if (EBO_in_peep)
03103 removed_ops ++;
03104 #endif
03105 continue;
03106
03107 op_is_needed:
03108
03109
03110
03111
03112 for (idx = 0; idx < rslt_count; idx++) {
03113 tninfo = opinfo->actual_rslt[idx];
03114 if ((tninfo != NULL) &&
03115 (tninfo->local_tn != NULL) &&
03116 (tninfo->same != NULL)) {
03117 EBO_TN_INFO *next_tninfo = tninfo->same;
03118 BOOL is_may_def = tninfo->in_op?OP_cond_def(tninfo->in_op):FALSE ;
03119
03120 while (next_tninfo != NULL) {
03121 if (
03122 #if defined(TARG_IA64)
03123 is_may_def &&
03124 #endif
03125 (!EBO_predicate_dominates((tninfo->predicate_tninfo != NULL)?tninfo->predicate_tninfo->local_tn:True_TN,
03126 tninfo->predicate_tninfo,
03127 (next_tninfo->predicate_tninfo != NULL)?
03128 next_tninfo->predicate_tninfo->local_tn:True_TN,
03129 next_tninfo->predicate_tninfo)) &&
03130 (!EBO_predicate_complements((tninfo->predicate_tninfo != NULL)?tninfo->predicate_tninfo->local_tn:True_TN,
03131 tninfo->predicate_tninfo,
03132 (next_tninfo->predicate_tninfo != NULL)?
03133 next_tninfo->predicate_tninfo->local_tn:True_TN,
03134 next_tninfo->predicate_tninfo))) {
03135
03136
03137
03138
03139
03140
03141
03142 EBO_OP_INFO *opinfo = locate_opinfo_entry(next_tninfo);
03143 if (opinfo != NULL) {
03144 opinfo->op_must_not_be_removed = TRUE;
03145 } else {
03146
03147
03148 next_tninfo->reference_count += tninfo->reference_count;
03149 }
03150
03151 if (EBO_Trace_Data_Flow) {
03152 #pragma mips_frequency_hint NEVER
03153 fprintf(TFile,"%sMark result same_tn as needed - original [%d]: ",
03154 EBO_trace_pfx,tninfo->sequence_num);
03155 Print_TN(tninfo->local_tn,FALSE);
03156 fprintf(TFile," same as [%d]: ",next_tninfo->sequence_num);
03157 Print_TN(next_tninfo->local_tn,FALSE);
03158 fprintf(TFile,"\n");
03159 }
03160
03161 if (EBO_predicate_dominates((next_tninfo->predicate_tninfo != NULL)?
03162 next_tninfo->predicate_tninfo->local_tn:True_TN,
03163 next_tninfo->predicate_tninfo,
03164 (tninfo->predicate_tninfo != NULL)?tninfo->predicate_tninfo->local_tn:True_TN,
03165 tninfo->predicate_tninfo)) {
03166
03167
03168
03169 break;
03170 }
03171 }
03172 next_tninfo = next_tninfo->same;
03173 }
03174 }
03175 }
03176
03177
03178
03179
03180 for (idx = 0; idx < OP_opnds(op); idx++) {
03181 tninfo = opinfo->actual_opnd[idx];
03182 if ((tninfo != NULL) &&
03183 (tninfo->local_tn != NULL) &&
03184 (tninfo->same != NULL)) {
03185 EBO_TN_INFO *next_tninfo = tninfo->same;
03186
03187 while (next_tninfo != NULL) {
03188 if ((next_tninfo->in_op != NULL) &&
03189 (next_tninfo->omega == tninfo->omega)) {
03190 BOOL is_may_def = OP_cond_def(next_tninfo ->in_op) ;
03191 if (
03192 #if defined(TARG_IA64)
03193 !is_may_def &&
03194 #endif
03195 EBO_predicate_dominates((next_tninfo->predicate_tninfo != NULL)?
03196 next_tninfo->predicate_tninfo->local_tn:True_TN,
03197 next_tninfo->predicate_tninfo,
03198 (tninfo->predicate_tninfo != NULL)?tninfo->predicate_tninfo->local_tn:True_TN,
03199 tninfo->predicate_tninfo)) {
03200
03201
03202
03203 break;
03204 } else if (EBO_predicate_complements((next_tninfo->predicate_tninfo != NULL)?
03205 next_tninfo->predicate_tninfo->local_tn:True_TN,
03206 next_tninfo->predicate_tninfo,
03207 (tninfo->predicate_tninfo != NULL)?tninfo->predicate_tninfo->local_tn:True_TN,
03208 tninfo->predicate_tninfo)) {
03209
03210
03211 } else {
03212
03213
03214
03215
03216
03217 EBO_OP_INFO *opinfo = locate_opinfo_entry(next_tninfo);
03218 if (opinfo != NULL) {
03219 opinfo->op_must_not_be_removed = TRUE;
03220 } else {
03221
03222
03223 next_tninfo->reference_count += tninfo->reference_count;
03224 }
03225
03226
03227 if ((next_tninfo != NULL) &&
03228 (bb != next_tninfo->in_bb)) {
03229 mark_tn_live_into_BB (tninfo->local_tn, bb, next_tninfo->in_bb);
03230 }
03231
03232 if (EBO_Trace_Data_Flow) {
03233 #pragma mips_frequency_hint NEVER
03234 fprintf(TFile,"%sMark operand same_tn as needed - original [%d]: ",
03235 EBO_trace_pfx,tninfo->sequence_num);
03236 Print_TN(tninfo->local_tn,FALSE);
03237 fprintf(TFile," same as [%d]: ",next_tninfo->sequence_num);
03238 Print_TN(next_tninfo->local_tn,FALSE);
03239 fprintf(TFile,"\n");
03240 }
03241
03242 }
03243 }
03244 next_tninfo = next_tninfo->same;
03245 }
03246
03247 }
03248 }
03249
03250
03251
03252
03253
03254 for (idx = 0; idx < OP_opnds(op); idx++) {
03255 tninfo = opinfo->actual_opnd[idx];
03256 if ((tninfo != NULL) &&
03257 (bb != tninfo->in_bb)) {
03258 mark_tn_live_into_BB (tninfo->local_tn, bb, tninfo->in_bb);
03259 }
03260 }
03261
03262 }
03263
03264
03265 {
03266 OP *op;
03267 OP * next_op = NULL;
03268 in_delay_slot = FALSE;
03269 TOP noop_top = CGTARG_Noop_Top();
03270
03271 for (op = BB_first_op(bb); op != NULL; op = next_op) {
03272 next_op = OP_next(op);
03273 if ( (OP_code(op) == noop_top || OP_code(op) == TOP_noop)
03274 && !in_delay_slot)
03275 {
03276 if (EBO_Trace_Optimization) {
03277 #pragma mips_frequency_hint NEVER
03278 fprintf(TFile, "%sin BB:%d removing noop ",
03279 EBO_trace_pfx, BB_id(bb));
03280 Print_OP_No_SrcLine(op);
03281 }
03282
03283 #ifdef KEY
03284
03285
03286 if (BB_first_op(bb) == op &&
03287 PROC_has_branch_delay_slot()) {
03288 EBO_Adjust_Pred_Branch_Target(bb);
03289 }
03290 #endif
03291 BB_Remove_Op(bb, op);
03292 #ifdef TARG_IA64
03293 Reset_BB_scheduled(bb);
03294 #endif
03295 } else if (PROC_has_branch_delay_slot()) {
03296 if (in_delay_slot && OP_code(op) == TOP_noop) {
03297
03298 OP_Change_Opcode(op, noop_top);
03299 }
03300 in_delay_slot = OP_xfer(op);
03301 }
03302 }
03303
03304 }
03305
03306 return;
03307 }
03308
03309
03310
03311
03312
03313
03314
03315 static
03316 void
03317 EBO_Add_BB_to_EB (BB * bb)
03318 {
03319 EBO_TN_INFO *save_last_tninfo = EBO_last_tninfo;
03320 EBO_OP_INFO *save_last_opinfo = EBO_last_opinfo;
03321 BBLIST *succ_list;
03322 BOOL normal_conditions;
03323 #ifdef KEY
03324 hTN_MAP save_regs_map = regs_map;
03325 #endif
03326
03327 if (EBO_Trace_Execution) {
03328 #pragma mips_frequency_hint NEVER
03329 fprintf(TFile,"%sEnter EBO_Add_BB_to_EB BB:%d. It has %d successors\n",
03330 EBO_trace_pfx,BB_id(bb),BB_succs(bb)?BB_succs_len(bb):0);
03331 }
03332
03333 Set_BB_visited(bb);
03334
03335 if (CG_skip_local_ebo &&
03336 ((BB_id(bb) < CG_local_skip_before) ||
03337 (BB_id(bb) > CG_local_skip_after) ||
03338 (BB_id(bb) == CG_local_skip_equal))) return;
03339
03340
03341 normal_conditions = Find_BB_TNs (bb);
03342 if (normal_conditions &&
03343 #ifdef KEY
03344 !EBO_optimize_single_BB &&
03345 #endif
03346 !CG_localize_tns) {
03347
03348 FOR_ALL_BB_SUCCS(bb, succ_list) {
03349 BB *succ = BBLIST_item(succ_list);
03350
03351 if (EBO_Trace_Block_Flow) {
03352 #pragma mips_frequency_hint NEVER
03353 fprintf(TFile,"%sCheck successor BB:%d. It has %d preds and has%s been visited.\n",
03354 EBO_trace_pfx,BB_id(succ),BB_preds_len(succ),BB_visited(succ)?" ":" not");
03355 }
03356
03357 if (!BB_call(bb) &&
03358 #ifdef KEY
03359 !BB_asm(bb) &&
03360 #endif
03361 (BB_preds_len(succ) == 1) &&
03362 !BB_visited(succ) &&
03363 (BB_rid(bb) == BB_rid(succ))) {
03364 EBO_Add_BB_to_EB (succ);
03365 }
03366 }
03367 }
03368
03369
03370 if (EBO_Trace_Block_Flow) {
03371 #pragma mips_frequency_hint NEVER
03372 fprintf(TFile,"%sEBO optimization at BB:%d\n",EBO_trace_pfx,BB_id(bb));
03373 }
03374
03375 #if !defined(TARG_SL)
03376 EBO_Remove_Unused_Ops(bb, normal_conditions);
03377 #endif
03378
03379
03380 backup_tninfo_list(save_last_tninfo);
03381 backup_opinfo_list(save_last_opinfo);
03382 #ifdef KEY
03383 regs_map = save_regs_map;
03384 #endif
03385
03386 return;
03387 }
03388
03389
03390
03391
03392
03393 static
03394 void
03395 EBO_Process ( BB *first_bb )
03396 {
03397 BB *bb;
03398
03399 rerun_cflow = FALSE;
03400
03401 EBO_Trace_Execution = Get_Trace(TP_EBO, 0x001);
03402 EBO_Trace_Optimization = Get_Trace(TP_EBO, 0x002);
03403 EBO_Trace_Block_Flow = Get_Trace(TP_EBO, 0x004);
03404 EBO_Trace_Data_Flow = Get_Trace(TP_EBO, 0x008);
03405 EBO_Trace_Hash_Search = Get_Trace(TP_EBO, 0x010);
03406
03407 FmtAssert(((EBO_first_tninfo == NULL) && (EBO_first_opinfo == NULL)),
03408 ("Initial pointers not NULL %o %o",EBO_first_tninfo,EBO_first_opinfo));
03409
03410 EBO_Start();
03411
03412 if (EBO_Trace_Data_Flow || EBO_Trace_Optimization) {
03413 #pragma mips_frequency_hint NEVER
03414 fprintf(TFile,">>>> Before EBO");
03415 if (EBO_in_peep) {
03416 fprintf(TFile," - in peep ");
03417 } else if (EBO_in_before_unrolling) {
03418 fprintf(TFile," - before unrolling ");
03419 } else if (EBO_in_after_unrolling) {
03420 fprintf(TFile," - after unrolling ");
03421 } else if (EBO_in_pre) {
03422 fprintf(TFile," - preprocessing ");
03423 } else {
03424 fprintf(TFile," - main ");
03425 }
03426 fprintf(TFile,"<<<<\n");
03427
03428 if (EBO_Trace_Data_Flow) {
03429 Print_All_BBs ();
03430 }
03431 }
03432
03433
03434 for (bb = first_bb; bb != NULL; bb = BB_next(bb)) {
03435 if (BB_rotating_kernel(bb)) Set_BB_visited(bb);
03436 }
03437
03438 #ifdef TARG_MIPS
03439 if (EBO_in_peep)
03440 Redundancy_Elimination();
03441 #endif
03442
03443 #if !defined(TARG_SL)
03444 for (bb = first_bb; bb != NULL; bb = BB_next(bb)) {
03445 RID *bbrid;
03446 if (( bbrid = BB_rid( bb )) &&
03447 ( RID_level( bbrid ) >= RL_CGSCHED ) ) {
03448
03449
03450
03451
03452 continue;
03453 }
03454 if (!BB_visited(bb)) {
03455 EBO_Add_BB_to_EB (bb);
03456 if (EBO_in_loop) break;
03457 }
03458 }
03459 #endif
03460
03461
03462 clear_bb_flag (first_bb);
03463
03464 if (rerun_cflow) {
03465 #ifdef TARG_IA64
03466
03467 if (RGN_Formed) {
03468
03469 CFLOW_Optimize(CFLOW_BRANCH | CFLOW_UNREACHABLE, "CFLOW (from second ebo)");
03470
03471 } else {
03472 CFLOW_Optimize(CFLOW_BRANCH | CFLOW_UNREACHABLE, "CFLOW (from ebo)");
03473 }
03474 #else
03475 CFLOW_Optimize(CFLOW_BRANCH | CFLOW_UNREACHABLE, "CFLOW (from ebo)");
03476 #endif
03477 }
03478
03479 EBO_Finish();
03480
03481 if (EBO_Trace_Data_Flow) {
03482 #pragma mips_frequency_hint NEVER
03483 fprintf(TFile,">>>> After EBO");
03484 if (EBO_in_peep) {
03485 fprintf(TFile," - in peep ");
03486 } else if (EBO_in_before_unrolling) {
03487 fprintf(TFile," - before unrolling ");
03488 } else if (EBO_in_after_unrolling) {
03489 fprintf(TFile," - after unrolling ");
03490 } else if (EBO_in_pre) {
03491 fprintf(TFile," - preprocessing ");
03492 } else {
03493 fprintf(TFile," - main ");
03494 }
03495 fprintf(TFile,"<<<<\n");
03496 fprintf(TFile,">>>> %d tninfo entries allocated and reused %d times\n",
03497 EBO_num_tninfo_entries,EBO_tninfo_entries_reused);
03498 fprintf(TFile,">>>> %d opinfo entries allocated and reused %d times\n",
03499 EBO_num_opinfo_entries,EBO_opinfo_entries_reused);
03500 Print_All_BBs ();
03501 }
03502
03503 }
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520 void
03521 EBO_Pre_Process_Region ( RID *rid )
03522 {
03523 BB *first_bb = (rid) ? CGRIN_first_bb(RID_cginfo( rid )) : REGION_First_BB;
03524
03525 EBO_in_pre = TRUE;
03526 EBO_in_before_unrolling = FALSE;
03527 EBO_in_after_unrolling = FALSE;
03528 EBO_in_peep = FALSE;
03529
03530 EBO_in_loop = FALSE;
03531 #ifdef KEY
03532 #if defined(TARG_MIPS) && !defined(TARG_SL)
03533 EBO_can_delete_branch_delay_OP = TRUE;
03534 #endif
03535 EBO_no_liveness_info_available = FALSE;
03536 EBO_optimize_single_BB = FALSE;
03537 #endif
03538
03539
03540 if ((EBO_Opt_Level < 5) && ((EBO_Opt_Level > 0) || (EBO_Opt_Level != -5))) return;
03541
03542 clear_bb_flag (first_bb);
03543 EBO_Process (first_bb);
03544 }
03545
03546
03547
03548
03549
03550 void
03551 EBO_before_unrolling(BB_REGION *bbr )
03552 {
03553 INT i;
03554 EBO_in_pre = FALSE;
03555 EBO_in_before_unrolling = TRUE;
03556 EBO_in_after_unrolling = FALSE;
03557 EBO_in_peep = FALSE;
03558
03559 EBO_in_loop = TRUE;
03560
03561 #ifdef KEY
03562 #if defined(TARG_MIPS) && !defined(TARG_SL)
03563 EBO_can_delete_branch_delay_OP = TRUE;
03564 #endif
03565 EBO_no_liveness_info_available = FALSE;
03566 EBO_optimize_single_BB = FALSE;
03567 #endif
03568
03569 if ((EBO_Opt_Level < 4) && ((EBO_Opt_Level > 0) || (EBO_Opt_Level != -4))) return;
03570
03571 #if defined(TARG_IA64) || defined(KEY)
03572 for (i = 0; i < bbr->entries.size(); i++) {
03573 clear_bb_flag (bbr->entries[i]);
03574 }
03575 for (i = 0; i < bbr->exits.size(); i++) {
03576 Set_BB_visited (bbr->exits[i]);
03577 }
03578 EBO_Process (bbr->entries[0]);
03579 #endif
03580 }
03581
03582
03583
03584
03585
03586 void
03587 EBO_after_unrolling(BB_REGION *bbr )
03588 {
03589 INT i;
03590
03591 EBO_in_pre = FALSE;
03592 EBO_in_before_unrolling = FALSE;
03593 EBO_in_after_unrolling = TRUE;
03594 EBO_in_peep = FALSE;
03595
03596 #ifdef KEY
03597 #if defined(TARG_MIPS) && !defined(TARG_SL)
03598 EBO_can_delete_branch_delay_OP = TRUE;
03599 #endif
03600 EBO_no_liveness_info_available = FALSE;
03601 EBO_optimize_single_BB = FALSE;
03602 #endif
03603 EBO_in_loop = TRUE;
03604
03605 if ((EBO_Opt_Level < 3) && ((EBO_Opt_Level > 0) || (EBO_Opt_Level != -3))) return;
03606
03607 #if defined(TARG_IA64) || defined(KEY)
03608 for (i = 0; i < bbr->entries.size(); i++) {
03609 clear_bb_flag (bbr->entries[i]);
03610 }
03611 for (i = 0; i < bbr->exits.size(); i++) {
03612 Set_BB_visited (bbr->exits[i]);
03613 }
03614 EBO_Process (bbr->entries[0]);
03615 #endif
03616 }
03617
03618
03619
03620
03621
03622 void
03623 EBO_Process_Region ( RID *rid )
03624 {
03625 BB *first_bb = (rid) ? CGRIN_first_bb(RID_cginfo( rid )) : REGION_First_BB;
03626
03627 EBO_in_pre = FALSE;
03628 EBO_in_before_unrolling = FALSE;
03629 EBO_in_after_unrolling = FALSE;
03630 EBO_in_peep = FALSE;
03631
03632 #ifdef KEY
03633 #if defined(TARG_MIPS) && !defined(TARG_SL)
03634 EBO_can_delete_branch_delay_OP = TRUE;
03635 #endif
03636 EBO_no_liveness_info_available = FALSE;
03637 EBO_optimize_single_BB = FALSE;
03638 #endif
03639 EBO_in_loop = FALSE;
03640
03641 if ((EBO_Opt_Level < 2) && ((EBO_Opt_Level > 0) || (EBO_Opt_Level != -2))) return;
03642
03643 clear_bb_flag (first_bb);
03644 EBO_Process (first_bb);
03645 }
03646
03647
03648
03649
03650
03651 void
03652 EBO_Post_Process_Region ( RID *rid )
03653 {
03654 BB *first_bb = (rid) ? CGRIN_first_bb(RID_cginfo( rid )) : REGION_First_BB;
03655
03656 EBO_in_pre = FALSE;
03657 EBO_in_before_unrolling = FALSE;
03658 EBO_in_after_unrolling = FALSE;
03659 EBO_in_peep = TRUE;
03660
03661 #ifdef KEY
03662 #if defined(TARG_MIPS) && !defined(TARG_SL)
03663 EBO_can_delete_branch_delay_OP = TRUE;
03664 #endif
03665 EBO_no_liveness_info_available = FALSE;
03666 EBO_optimize_single_BB = FALSE;
03667 #endif
03668 EBO_in_loop = FALSE;
03669
03670 if ((EBO_Opt_Level < 1) && ((EBO_Opt_Level >= 0) || (EBO_Opt_Level != -1))) return;
03671
03672
03673 MEM_POOL_Push(&MEM_local_pool);
03674 REG_LIVE_Analyze_Region();
03675
03676 clear_bb_flag (first_bb);
03677 #ifdef KEY
03678 removed_ops = 0;
03679 #endif
03680 EBO_Process (first_bb);
03681 REG_LIVE_Finish();
03682 #ifdef KEY
03683
03684
03685
03686
03687 {
03688 REG_LIVE_Analyze_Region();
03689 clear_bb_flag (first_bb);
03690 EBO_Process (first_bb);
03691 REG_LIVE_Finish();
03692 }
03693 #endif
03694 MEM_POOL_Pop(&MEM_local_pool);
03695 }
03696
03697 #ifdef KEY
03698
03699
03700 void
03701 EBO_Post_Process_Region_2 ( RID *rid )
03702 {
03703 BB *first_bb = (rid) ? CGRIN_first_bb(RID_cginfo( rid )) : REGION_First_BB;
03704
03705 EBO_in_pre = FALSE;
03706 EBO_in_before_unrolling = FALSE;
03707 EBO_in_after_unrolling = FALSE;
03708 EBO_in_peep = TRUE;
03709
03710 EBO_in_loop = FALSE;
03711
03712 #if defined(TARG_MIPS) && !defined(TARG_SL)
03713 EBO_can_delete_branch_delay_OP = TRUE;
03714 #endif
03715
03716 EBO_can_delete_branch_delay_OP = FALSE;
03717 EBO_no_liveness_info_available = TRUE;
03718 EBO_optimize_single_BB = TRUE;
03719
03720 if ((EBO_Opt_Level < 6) && ((EBO_Opt_Level >= 0) || (EBO_Opt_Level != -6)))
03721 return;
03722
03723
03724 MEM_POOL_Push(&MEM_local_pool);
03725 REG_LIVE_Analyze_Region();
03726
03727 clear_bb_flag (first_bb);
03728 removed_ops = 0;
03729 EBO_Process (first_bb);
03730 REG_LIVE_Finish();
03731
03732 MEM_POOL_Pop(&MEM_local_pool);
03733 }
03734
03735 #ifdef TARG_X8664
03736
03737
03738 static int
03739 Get_LRA_Spill_Temp_Number(OP *op)
03740 {
03741 int base_idx, offset_idx;
03742
03743 base_idx = OP_find_opnd_use(op, OU_base);
03744 if (base_idx >= 0 &&
03745 OP_opnd(op, base_idx) == SP_TN) {
03746 offset_idx = OP_find_opnd_use(op, OU_offset);
03747 if (offset_idx >= 0) {
03748 TN *offset_tn = OP_opnd(op, offset_idx);
03749 if (offset_tn != NULL &&
03750 TN_is_symbol(offset_tn)) {
03751 ST *st = TN_var(offset_tn);
03752 char *name = ST_name(st);
03753 if (strstr(name, "lra_spill_temp_") != NULL) {
03754 char *p = name + 15;
03755 int id = atoi(p);
03756 return id;
03757 }
03758 }
03759 }
03760 }
03761 return -1;
03762 }
03763
03764 static void
03765 Init_Remove_Dead_LRA_Stores(BS **bs, MEM_POOL *pool)
03766 {
03767
03768
03769 *bs = BS_Create_Empty(Spill_Var_Cnt + 1, pool);
03770 }
03771
03772 static BOOL
03773 Delete_Dead_LRA_Spill(OP *op, BS **bs)
03774 {
03775 if (!OP_store(op))
03776 return FALSE;
03777
03778 int id = Get_LRA_Spill_Temp_Number(op);
03779
03780
03781 if (id > 0 &&
03782 !BS_MemberP(*bs, id)) {
03783 OP_Change_To_Noop(op);
03784 return TRUE;
03785 }
03786 return FALSE;
03787 }
03788
03789
03790
03791 static void
03792 Mark_LRA_Spill_Reference(OP *op, BS **bs, MEM_POOL *pool)
03793 {
03794 if (OP_store(op))
03795 return;
03796
03797
03798 int id = Get_LRA_Spill_Temp_Number(op);
03799 if (id > 0) {
03800 *bs = BS_Union1D(*bs, id, pool);
03801 }
03802 }
03803 #endif // TARG_X8664
03804
03805 #if 0
03806
03807
03808
03809
03810
03811
03812
03813 void
03814 delete_useless_store_op (EBO_OP_INFO *opinfo)
03815 {
03816 EBO_TN_INFO *save_last_tninfo = EBO_last_tninfo;
03817
03818 BOOL found_dependent_op = FALSE;
03819
03820 OP *store_op = opinfo->in_op;
03821
03822
03823 BB *bb = opinfo->in_bb;
03824 EBO_TN_INFO *tninfo;
03825 TN *op_predicate_tn = NULL;
03826 EBO_TN_INFO *op_predicate_tninfo = NULL;
03827 BOOL check_omegas = FALSE;
03828 INT max_opnds = OP_MAX_FIXED_OPNDS;
03829 EBO_TN_INFO **opnd_tninfo = TYPE_ALLOCA_N(EBO_TN_INFO *, max_opnds);
03830 INT opndnum;
03831 mUINT8 operand_omega;
03832 check_omegas = (EBO_in_loop && _CG_LOOP_info(store_op))?TRUE:FALSE;
03833 TN *tn;
03834 for (opndnum = 0; opndnum < OP_opnds(store_op); opndnum ++) {
03835 tn = OP_opnd(store_op, opndnum);
03836 if (tn == NULL || TN_is_constant(tn) || TN_is_label(tn)) {
03837 opnd_tninfo[opndnum] = NULL;
03838 continue;
03839 }
03840 operand_omega = check_omegas ? OP_omega(store_op,opndnum) : 0;
03841 tninfo = tn_info_use (bb, store_op, tn,
03842 op_predicate_tn, op_predicate_tninfo,
03843 operand_omega);
03844 opnd_tninfo[opndnum] = tninfo;
03845 }
03846
03847
03848 INT store_base_idx = TOP_Find_Operand_Use(OP_code(store_op),OU_base);
03849 INT store_offset_idx = TOP_Find_Operand_Use(OP_code(store_op),OU_offset);
03850
03851
03852 TN *store_base_tn =
03853 (store_base_idx >= 0) ? OP_opnd(store_op, store_base_idx) : NULL;
03854 EBO_TN_INFO *store_base_tninfo =
03855 (store_base_idx >= 0) ? opnd_tninfo[store_base_idx] : NULL;
03856 TN *store_offset_tn =
03857 (store_offset_idx >= 0) ? OP_opnd(store_op, store_offset_idx) : NULL;
03858 EBO_TN_INFO *store_offset_tninfo =
03859 (store_offset_idx >= 0) ? opnd_tninfo[store_offset_idx] : NULL;
03860
03861 if ((store_offset_tn == NULL) && (store_base_tn != NULL)) {
03862 find_index_and_offset(store_base_tninfo,
03863 &store_base_tn, &store_base_tninfo,
03864 &store_offset_tn, &store_offset_tninfo);
03865 }
03866
03867 for (; bb != NULL; bb = BB_next(bb)) {
03868 OP *op;
03869 FOR_ALL_BB_OPs (bb, op) {
03870 if (!OP_load(op))
03871 continue;
03872 check_omegas = (EBO_in_loop && _CG_LOOP_info(op))?TRUE:FALSE;
03873 TN *tn;
03874 for (opndnum = 0; opndnum < OP_opnds(op); opndnum ++) {
03875 tn = OP_opnd(op, opndnum);
03876 if (tn == NULL || TN_is_constant(tn) || TN_is_label(tn)) {
03877 opnd_tninfo[opndnum] = NULL;
03878 continue;
03879 }
03880 operand_omega = check_omegas ? OP_omega(op,opndnum) : 0;
03881 tninfo = tn_info_use (bb, op, tn,
03882 op_predicate_tn, op_predicate_tninfo,
03883 operand_omega);
03884 opnd_tninfo[opndnum] = tninfo;
03885 }
03886 if (EBO_hash_op(op, opnd_tninfo) == opinfo->hash_index) {
03887 INT base_idx = 0;
03888 INT offset_idx = 0;
03889 TN *base_tn = NULL;
03890 EBO_TN_INFO *base_tninfo = NULL;
03891 TN *offset_tn = NULL;
03892 EBO_TN_INFO *offset_tninfo = NULL;
03893
03894
03895 base_idx = TOP_Find_Operand_Use(OP_code(op),OU_base);
03896 offset_idx = TOP_Find_Operand_Use(OP_code(op),OU_offset);
03897 base_tn = (base_idx >= 0) ? OP_opnd(op,base_idx) : NULL;
03898 base_tninfo = (base_idx >= 0) ? opnd_tninfo[base_idx] : NULL;
03899 offset_tn = (offset_idx >= 0) ? OP_opnd(op,offset_idx) : NULL;
03900 offset_tninfo = (offset_idx >= 0) ? opnd_tninfo[offset_idx] : NULL;
03901
03902 if ((offset_tn == NULL) && (base_tn != NULL)) {
03903 find_index_and_offset(base_tninfo,
03904 &base_tn, &base_tninfo,
03905 &offset_tn, &offset_tninfo);
03906 }
03907
03908 BOOL hash_op_matches = ((base_tn == store_base_tn) &&
03909 (base_tninfo == store_base_tninfo) &&
03910 (offset_tninfo == store_offset_tninfo))
03911 ? TRUE : FALSE;
03912 if (!hash_op_matches)
03913 continue;
03914 BOOL op_is_subset = FALSE;
03915 BOOL offsets_may_overlap = TRUE;
03916
03917 if (offset_tn == store_offset_tn) {
03918
03919 found_dependent_op = TRUE;
03920 break;
03921 }
03922
03923
03924 ST *symbol = ((offset_tn != NULL) && TN_is_symbol(offset_tn)) ?TN_var(offset_tn) : NULL;
03925 ST *symbol_store = ((store_offset_tn != NULL) && TN_is_symbol(store_offset_tn)) ?TN_var(store_offset_tn) : NULL;
03926 mUINT8 relocs = (offset_tn != NULL) ? TN_relocs(offset_tn) : 0;
03927 mUINT8 relocs_store = (store_offset_tn != NULL) ? TN_relocs(store_offset_tn) : 0;
03928 INT64 offset = 0;
03929 INT64 offset_store = 0;
03930 offset = (offset_tn != NULL) ? TN_offset(offset_tn) : 0;
03931 offset_store = (store_offset_tn != NULL) ? TN_offset(store_offset_tn) : 0;
03932
03933
03934 hash_op_matches = (symbol == symbol_store) && (relocs == relocs_store);
03935 if (!hash_op_matches)
03936 continue;
03937
03938
03939 INT size = CGTARG_Mem_Ref_Bytes(op);
03940 INT size_store = CGTARG_Mem_Ref_Bytes(store_op);
03941
03942 if ((offset == offset_store) &&
03943 (size == size_store)) {
03944
03945
03946 found_dependent_op = TRUE;
03947 break;
03948 } else if ((offset >= offset_store) &&
03949 ((offset + size) <= (offset_store + size_store))) {
03950
03951
03952 found_dependent_op = TRUE;
03953 break;
03954 } else if (((offset_store + size_store) <= offset) ||
03955 ((offset + size) <= offset_store)) {
03956
03957 } else {
03958
03959 hash_op_matches = FALSE;
03960 }
03961 }
03962 }
03963 if (found_dependent_op)
03964 break;
03965 }
03966 if (found_dependent_op == FALSE) {
03967 OP_Change_To_Noop(store_op);
03968 printf("store op %#x does not have any dep op\n", store_op);
03969 }
03970 backup_tninfo_list(save_last_tninfo);
03971 return;
03972 }
03973 #endif
03974 #endif
03975
03976
03977
03978 static void
03979 EBO_Adjust_Pred_Branch_Target (BB *bb)
03980 {
03981 BB *fall_thru_pred = BB_Fall_Thru_Predecessor(bb);
03982 BBLIST *edge;
03983
03984 FOR_ALL_BB_PREDS(bb, edge) {
03985 BB *pred = BBLIST_item(edge);
03986 if (pred != fall_thru_pred) {
03987 OP *xfer_op = BB_last_op(pred);
03988 if (!OP_xfer(xfer_op))
03989 xfer_op = OP_prev(xfer_op);
03990 Is_True(xfer_op != NULL && OP_xfer(xfer_op),
03991 ("EBO_Adjust_Pred_Branch_Target: cannot find xfer_op"));
03992 for (int i = 0; i < OP_opnds(xfer_op); i++) {
03993 TN *opnd_tn = OP_opnd(xfer_op, i);
03994 if (TN_is_label(opnd_tn) &&
03995 TN_offset(opnd_tn) > 0) {
03996 TN *new_label_tn = Gen_Adjusted_TN(opnd_tn, -4);
03997 Set_OP_opnd(xfer_op, i, new_label_tn);
03998 }
03999 }
04000 }
04001 }
04002 }