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 #ifdef USE_PCH
00063 #include "cg_pch.h"
00064 #endif // USE_PCH
00065 #pragma hdrstop
00066
00067 #ifdef _KEEP_RCS_ID
00068 static const char source_file[] = __FILE__;
00069 #endif
00070
00071 #include <stdarg.h>
00072 #include "defs.h"
00073 #include "config_targ_opt.h"
00074 #include "errors.h"
00075 #include "mempool.h"
00076 #include "tracing.h"
00077 #include "timing.h"
00078 #include "cgir.h"
00079 #include "tn_map.h"
00080 #include "cg_loop.h"
00081 #include "cg.h"
00082 #include "cgexp.h"
00083 #include "register.h"
00084 #include "cg_region.h"
00085 #include "wn.h"
00086 #include "region_util.h"
00087 #include "op_list.h"
00088 #include "cgprep.h"
00089 #include "gtn_universe.h"
00090 #include "gtn_set.h"
00091 #include "cg_db_op.h"
00092 #include "whirl2ops.h"
00093 #include "cgtarget.h"
00094 #include "gra_live.h"
00095 #include "reg_live.h"
00096 #include "cflow.h"
00097 #include "cg_spill.h"
00098 #include "cgexp_internals.h"
00099 #include "data_layout.h"
00100 #include "stblock.h"
00101 #include "cxx_hash.h"
00102 #include "op.h"
00103
00104 #include "ebo.h"
00105 #include "ebo_info.h"
00106 #include "ebo_special.h"
00107 #include "ebo_util.h"
00108
00109
00110 #define TRUNC_32(val) (val & 0x00000000ffffffffll)
00111
00112
00113 #define SEXT_32(val) (((INT64)(val) << 32) >> 32)
00114
00115
00116
00117 typedef HASH_TABLE<ST_IDX, INITV_IDX> ST_TO_INITV_MAP;
00118 static ST_TO_INITV_MAP *st_initv_map = NULL;
00119 static BOOL st_initv_map_inited = FALSE;
00120 static GTN_SET *work_gtn_set = NULL;
00121 static BS *work_defined_set = NULL;
00122 static MEM_POOL *work_pool = NULL;
00123 static INT32 fixed_branch_cost, taken_branch_cost;
00124
00125
00126 void
00127 EBO_Special_Start (MEM_POOL *pool)
00128 {
00129 st_initv_map = CXX_NEW(ST_TO_INITV_MAP(31, pool), pool);
00130 st_initv_map_inited = FALSE;
00131 work_gtn_set = GTN_SET_Create_Empty(Last_TN + 1, pool);
00132 work_defined_set = BS_Create_Empty(Last_TN + 1, pool);
00133 work_pool = pool;
00134
00135 INT32 idummy;
00136 double ddummy;
00137 CGTARG_Compute_Branch_Parameters(&idummy, &fixed_branch_cost,
00138 &taken_branch_cost, &ddummy);
00139 }
00140
00141 void
00142 EBO_Special_Finish (void)
00143 {
00144 st_initv_map = NULL;
00145 st_initv_map_inited = FALSE;
00146 work_gtn_set = NULL;
00147 work_defined_set = NULL;
00148 work_pool = NULL;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 BOOL EBO_Can_Merge_Into_Offset (OP *op)
00158 {
00159 TOP top = OP_code(op);
00160
00161 if ((top != TOP_add) && (top != TOP_dadd) &&
00162 (top != TOP_addu) && (top != TOP_daddu) &&
00163 (top != TOP_addi) && (top != TOP_daddi) &&
00164 (top != TOP_addiu) && (top != TOP_daddiu) &&
00165 (top != TOP_sub) && (top != TOP_subu) &&
00166 (top != TOP_dsub) && (top != TOP_dsubu))
00167 return FALSE;
00168
00169 if ((op == BB_entry_sp_adj_op(OP_bb(op))) ||
00170 (op == BB_exit_sp_adj_op(OP_bb(op))))
00171 return FALSE;
00172
00173 TN *tn = OP_opnd(op,1);
00174 if (TN_Is_Constant(tn))
00175 return TRUE;
00176
00177 return FALSE;
00178 }
00179
00180
00181 static
00182 void
00183 EBO_Set_OP_omega (OP *op, ...)
00184 {
00185 INT opnds = OP_opnds(op);
00186 INT i;
00187 va_list tninfos;
00188
00189 va_start(tninfos, op);
00190 CG_LOOP_Init_Op(op);
00191 for (i = 0; i < opnds; i++) {
00192 EBO_TN_INFO *tninfo = va_arg(tninfos, EBO_TN_INFO *);
00193 Set_OP_omega (op, i, ((tninfo != NULL) ? tninfo->omega : 0));
00194 }
00195
00196 va_end(tninfos);
00197 return;
00198 }
00199
00200
00201
00202 static
00203 void
00204 EBO_Copy_OP_omega (OP *new_op, OP *old_op)
00205 {
00206 INT opnds = OP_opnds(new_op);
00207 INT i;
00208
00209 CG_LOOP_Init_Op(new_op);
00210 for (i = 0; i < opnds; i++) {
00211 Set_OP_omega (new_op, i, OP_omega(old_op,i));
00212 }
00213
00214 return;
00215 }
00216
00217
00218 static
00219 void
00220 EBO_OPS_omega (OPS *ops)
00221 {
00222 OP *next_op = OPS_first(ops);
00223 while (next_op != NULL) {
00224 INT opnds = OP_opnds(next_op);
00225 INT i;
00226
00227 CG_LOOP_Init_Op(next_op);
00228 for (i = 0; i < opnds; i++) {
00229 Set_OP_omega (next_op, i, 0);
00230 }
00231
00232 next_op = OP_next(next_op);
00233 }
00234
00235 return;
00236 }
00237
00238 BOOL
00239 combine_adjacent_loads(OP *op,
00240 EBO_TN_INFO **opnd_tninfo,
00241 EBO_OP_INFO *opinfo,
00242 INT64 offset_pred,
00243 INT64 offset_succ)
00244 {
00245
00246 return FALSE;
00247 }
00248
00249 static void
00250 Expand_Extract_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
00251 TN *tgt_tn, TN *src_tn, OPS *ops)
00252 {
00253 TN *tmp1_tn = tgt_tn;
00254 UINT pos = (Target_Byte_Sex != Host_Byte_Sex)
00255 ? MTYPE_bit_size(desc)-bit_offset-bit_size : bit_offset;
00256 if (pos == 0 && bit_size <= 16 && ! MTYPE_signed(rtype)) {
00257 Build_OP(TOP_andi, tgt_tn, src_tn,
00258 Gen_Literal_TN((1 << bit_size)-1, 4), ops);
00259 return;
00260 }
00261 ISA_REGISTER_CLASS rclass = ISA_REGISTER_CLASS_integer;
00262 INT reg_size =
00263 ISA_REGISTER_CLASS_INFO_Bit_Size(ISA_REGISTER_CLASS_Info(rclass));
00264 #if defined(TARG_SL)
00265 TOP left_shift_op = TOP_sll;
00266 #else
00267 TOP left_shift_op = TOP_dsll;
00268 #endif
00269 INT left_shift_amt = reg_size - pos - bit_size;
00270 if (left_shift_amt > 31) {
00271 #if defined(TARG_SL)
00272 Is_True(0,("shift > 31 bits"));
00273 #endif
00274 left_shift_op = TOP_dsll32;
00275 left_shift_amt -= 32;
00276 }
00277 if (left_shift_amt >= 0)
00278 Build_OP(left_shift_op, tmp1_tn, src_tn, Gen_Literal_TN(left_shift_amt, 4),
00279 ops);
00280 #if defined(TARG_SL)
00281 TOP right_shift_op = TOP_sra;
00282 #else
00283 TOP right_shift_op = TOP_dsra;
00284 #endif
00285 INT right_shift_amt = reg_size - bit_size;
00286 if (right_shift_amt > 31) {
00287 #if defined(TARG_SL)
00288 Is_True(0,("shift > 31 bits"));
00289 #endif
00290 right_shift_op = TOP_dsra32;
00291 right_shift_amt -= 32;
00292 }
00293 if (! MTYPE_signed(rtype)) {
00294 #if defined(TARG_SL)
00295 if (right_shift_op == TOP_sra)
00296 right_shift_op = TOP_srl;
00297 else
00298 right_shift_op = TOP_srl;
00299 #else
00300 if (right_shift_op == TOP_dsra)
00301 right_shift_op = TOP_dsrl;
00302 else right_shift_op = TOP_dsrl32;
00303 #endif
00304 }
00305 if (right_shift_amt >= 0)
00306 Build_OP(right_shift_op, tgt_tn, tmp1_tn,
00307 Gen_Literal_TN(right_shift_amt, 4),
00308 ops);
00309 else if (left_shift_amt < 0 && right_shift_amt < 0) {
00310 if (left_shift_amt < right_shift_amt)
00311 Build_OP(right_shift_op, tgt_tn, src_tn,
00312 Gen_Literal_TN(right_shift_amt-left_shift_amt, 4),
00313 ops);
00314 else
00315 Build_OP(left_shift_op, tgt_tn, src_tn,
00316 Gen_Literal_TN(left_shift_amt-right_shift_amt, 4),
00317 ops);
00318 } else
00319 FmtAssert( FALSE, ("Handle this case"));
00320 }
00321
00322 BOOL
00323 delete_subset_mem_op(OP *op,
00324 EBO_TN_INFO **opnd_tninfo,
00325 EBO_OP_INFO *opinfo,
00326 INT64 offset_pred,
00327 INT64 offset_succ)
00328 {
00329 OP *pred_op = opinfo->in_op;
00330 BB *bb = OP_bb(op);
00331 INT opcount = OP_opnds(op);
00332 TN *pred_result = OP_store(pred_op)
00333 ? OP_opnd(pred_op, TOP_Find_Operand_Use(OP_code(pred_op),OU_storeval))
00334 : OP_result(pred_op,0);
00335 TN *succ_result = OP_store(op)
00336 ? OP_opnd(op, TOP_Find_Operand_Use(OP_code(op),OU_storeval))
00337 : OP_result(op,0);
00338 INT size_pred;
00339 INT size_succ;
00340 BOOL succ_is_subset = FALSE;
00341 INT byte_offset;
00342 OPS ops = OPS_EMPTY;
00343
00344 if (EBO_Trace_Data_Flow) {
00345 fprintf(TFile,"%ssubset OP in BB:%d ",EBO_trace_pfx,BB_id(bb));
00346 Print_OP_No_SrcLine(op);
00347 fprintf(TFile," Matches OP in BB:%d ",BB_id(opinfo->in_bb));
00348 Print_OP_No_SrcLine(pred_op);
00349 }
00350
00351 if ((Opt_Level < 2) && (bb != opinfo->in_bb)) {
00352
00353 return FALSE;
00354 }
00355
00356 if (!EBO_in_peep &&
00357 (bb != opinfo->in_bb) &&
00358 !TN_Is_Constant(pred_result) &&
00359 has_assigned_reg(pred_result)) {
00360 if (EBO_Trace_Data_Flow) {
00361 #pragma mips_frequency_hint NEVER
00362 fprintf(TFile,"%sShouldn't move dedicated register references across blocks.\n",
00363 EBO_trace_pfx);
00364 }
00365 return FALSE;
00366 }
00367
00368 size_pred = CGTARG_Mem_Ref_Bytes(pred_op);
00369 size_succ = CGTARG_Mem_Ref_Bytes(op);
00370 if (size_pred < size_succ) return FALSE;
00371
00372 if ((offset_pred <= offset_succ) &&
00373 ((offset_pred + size_pred) >= (offset_succ + size_succ))) {
00374 succ_is_subset = TRUE;
00375 }
00376
00377 if (!succ_is_subset) {
00378 return FALSE;
00379 }
00380
00381 byte_offset = offset_succ - offset_pred;
00382
00383 if (!OP_store(pred_op) || !OP_load(op)) {
00384
00385 return FALSE;
00386 }
00387
00388 if (EBO_Trace_Optimization) {
00389 #pragma mips_frequency_hint NEVER
00390 fprintf(TFile,"%sReplace subset load with left/right shifts\n",EBO_trace_pfx);
00391 }
00392
00393 if (byte_offset > 8) return FALSE;
00394
00395 if ((TN_register_class(pred_result) != ISA_REGISTER_CLASS_integer) ||
00396 (TN_register_class(succ_result) != ISA_REGISTER_CLASS_integer)) {
00397
00398 return FALSE;
00399 }
00400
00401 if (offset_succ == offset_pred &&
00402 size_pred == size_succ) {
00403 Build_OP(TOP_or, OP_result(op, 0), OP_opnd(pred_op, 0), Zero_TN, &ops);
00404 OP_srcpos(OPS_first(&ops)) = OP_srcpos(op);
00405 BB_Insert_Ops_After(OP_bb(op), op, &ops);
00406 return TRUE;
00407 }
00408
00409 INT bit_size = size_succ*8;
00410 INT succ_offset = (offset_succ - offset_pred);
00411 INT bit_offset = succ_offset*8;
00412 TYPE_ID rtype, desc;
00413 if (OP_code(pred_op) == TOP_sb)
00414 desc = MTYPE_I1;
00415 else if (OP_code(pred_op) == TOP_sh)
00416 desc = MTYPE_I2;
00417 else if (OP_code(pred_op) == TOP_sw)
00418 desc = MTYPE_I4;
00419 else
00420 desc = MTYPE_I8;
00421 BOOL unsigned_op = (OP_code(op) == TOP_lbu ||
00422 OP_code(op) == TOP_lhu ||
00423 OP_code(op) == TOP_lwu);
00424 if (desc == MTYPE_I1) {
00425 if (unsigned_op)
00426 rtype = MTYPE_U1;
00427 else
00428 rtype = desc;
00429 } else if (desc == MTYPE_I2) {
00430 if (unsigned_op)
00431 rtype = MTYPE_U2;
00432 else
00433 rtype = desc;
00434 } else if (desc == MTYPE_I4) {
00435 if (unsigned_op)
00436 rtype = MTYPE_U4;
00437 else
00438 rtype = desc;
00439 } else {
00440 if (unsigned_op)
00441 rtype = MTYPE_U8;
00442 else
00443 rtype = desc;
00444 }
00445 Expand_Extract_Bits (rtype, desc,
00446 bit_offset, bit_size,
00447 OP_result(op, 0), OP_opnd(pred_op, 0), &ops);
00448 OP_srcpos(OPS_first(&ops)) = OP_srcpos(op);
00449 BB_Insert_Ops_After(OP_bb(op), op, &ops);
00450 return TRUE;
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460 BOOL
00461 delete_reload_across_dependency (OP *op,
00462 EBO_TN_INFO **opnd_tninfo,
00463 EBO_OP_INFO *opinfo,
00464 EBO_OP_INFO *intervening_opinfo)
00465 {
00466 return FALSE;
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 static
00478 BOOL
00479 delete_memory_op (OP *op,
00480 EBO_TN_INFO **opnd_tninfo,
00481 EBO_OP_INFO *opinfo)
00482 {
00483 OPS ops = OPS_EMPTY;
00484 INT size_pred;
00485 INT size_succ;
00486
00487
00488
00489
00490
00491
00492
00493 ISA_REGISTER_CLASS state_rc = ISA_REGISTER_CLASS_UNDEFINED;
00494 if (state_rc != ISA_REGISTER_CLASS_UNDEFINED)
00495 {
00496 INT results = OP_results(op);
00497 for (UINT i = 0; i < results; i++)
00498 {
00499 TN *tn = OP_result(op, i);
00500 if (TN_is_register(tn) && (TN_register_class(tn) == state_rc))
00501 return FALSE;
00502 }
00503 }
00504
00505
00506
00507
00508
00509
00510 if (OP_prefetch(op))
00511 {
00512 if (EBO_Trace_Optimization) {
00513 fprintf(TFile,"%sRemove following Prefetch combination\n",EBO_trace_pfx);
00514 }
00515
00516 return TRUE;
00517 }
00518
00519
00520
00521
00522
00523 if (OP_prefetch(opinfo->in_op))
00524 {
00525 return FALSE;
00526 }
00527
00528
00529 if (OP_unalign_mem(op) || OP_unalign_mem(opinfo->in_op))
00530 return FALSE;
00531
00532 size_pred = CGTARG_Mem_Ref_Bytes(opinfo->in_op);
00533 size_succ = CGTARG_Mem_Ref_Bytes(op);
00534
00535
00536
00537
00538 if (OP_load(op) && OP_load(opinfo->in_op))
00539 {
00540
00541
00542 if (TN_register_class(OP_result(op,0)) !=
00543 TN_register_class(OP_result(opinfo->in_op, 0)))
00544 {
00545 if (EBO_Trace_Optimization)
00546 fprintf(TFile,"%sRegclass mismatch for Load - Load combination\n",
00547 EBO_trace_pfx);
00548
00549 return FALSE;
00550 }
00551
00552
00553
00554
00555 if (OP_code(op) != OP_code(opinfo->in_op))
00556 {
00557 if (EBO_Trace_Optimization)
00558 fprintf(TFile,"%sMtype mismatch for Load - Load combination\n",
00559 EBO_trace_pfx);
00560
00561 return FALSE;
00562 }
00563
00564
00565
00566
00567
00568
00569 if ((size_pred != size_succ) ||
00570 (OP_results(op) != OP_results(opinfo->in_op)) ||
00571 (TN_size(OP_result(opinfo->in_op, 0)) != TN_size(OP_result(op, 0))))
00572 {
00573 if (EBO_Trace_Optimization)
00574 {
00575 fprintf(TFile,"%sSize mismatch for Load - Load combination: %d:%d %d:%d \n",
00576 EBO_trace_pfx,size_pred,size_succ,
00577 TN_size(OP_result(opinfo->in_op, 0)),TN_size(OP_result(op, 0)));
00578 }
00579
00580 return delete_subset_mem_op (op, opnd_tninfo, opinfo, 0, 0);
00581 }
00582
00583 if (!EBO_in_peep &&
00584 (OP_bb(op) != OP_bb(opinfo->in_op)) &&
00585 !TN_Is_Constant(OP_result(opinfo->in_op, 0)) &&
00586 has_assigned_reg(OP_result(opinfo->in_op, 0)))
00587 {
00588 if (EBO_Trace_Data_Flow)
00589 {
00590 fprintf(TFile,"%sShouldn't move dedicated register references across blocks.\n",
00591 EBO_trace_pfx);
00592 }
00593
00594 return FALSE;
00595 }
00596
00597
00598
00599 if (EBO_Trace_Optimization)
00600 {
00601 fprintf(TFile,"%sRemove Load - Load combination\n",EBO_trace_pfx);
00602 }
00603
00604 for (UINT i = 0; i < OP_results(op); i++)
00605 EBO_Exp_COPY(NULL, OP_result(op, i), OP_result(opinfo->in_op, i), &ops);
00606
00607 if (EBO_in_loop)
00608 EBO_OPS_omega (&ops);
00609
00610 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00611 return TRUE;
00612 }
00613
00614
00615
00616 else if (OP_load(op) && OP_store(opinfo->in_op))
00617 {
00618 INT storeval_idx = TOP_Find_Operand_Use(OP_code(opinfo->in_op),OU_storeval);
00619
00620 if (storeval_idx < 0)
00621 {
00622 if (EBO_Trace_Optimization)
00623 fprintf(TFile,
00624 "%sStore value TN unknown for Load - Store combination\n",
00625 EBO_trace_pfx);
00626
00627 return FALSE;
00628 }
00629
00630 TN *storeval_tn = OP_opnd(opinfo->in_op, storeval_idx);
00631
00632
00633
00634
00635
00636
00637
00638
00639 if (TN_register_class(OP_result(op,0)) !=
00640 TN_register_class(storeval_tn))
00641 {
00642 if (EBO_Trace_Data_Flow)
00643 fprintf(TFile,"%sRegclass mismatch for Store - Load combination\n",
00644 EBO_trace_pfx);
00645
00646 return FALSE;
00647 }
00648
00649 if (!EBO_in_peep &&
00650 (OP_bb(op) != OP_bb(opinfo->in_op)) &&
00651 !TN_Is_Constant(storeval_tn) &&
00652 has_assigned_reg(storeval_tn))
00653 {
00654 if (EBO_Trace_Data_Flow)
00655 fprintf(TFile,"%sShouldn't move dedicated register references across blocks.\n",
00656 EBO_trace_pfx);
00657
00658 return FALSE;
00659 }
00660
00661
00662
00663
00664
00665 if (size_pred == size_succ)
00666 {
00667 if (TN_size(storeval_tn) > size_succ)
00668 {
00669 if (EBO_Trace_Data_Flow)
00670 fprintf(TFile,"%sSize mismatch for Store - Load combination: %d %d %d\n",
00671 EBO_trace_pfx,size_pred,TN_size(storeval_tn),size_succ);
00672
00673 return delete_subset_mem_op (op, opnd_tninfo, opinfo, 0, 0);
00674 }
00675
00676 if (EBO_Trace_Optimization)
00677 fprintf(TFile,"%sRemove Store - Load combination\n",EBO_trace_pfx);
00678
00679 EBO_Exp_COPY(NULL, OP_result(op, 0), storeval_tn, &ops);
00680 if (EBO_in_loop) {
00681 CG_LOOP_Init_Op(OPS_first(&ops));
00682 Set_OP_omega (OPS_first(&ops), 0, opinfo->actual_opnd[storeval_idx]->omega);
00683 }
00684
00685 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00686 return TRUE;
00687 }
00688
00689
00690
00691 else
00692 {
00693 return delete_subset_mem_op (op, opnd_tninfo, opinfo, 0, 0);
00694 }
00695 }
00696
00697
00698
00699 else if (OP_store(op) && OP_store(opinfo->in_op) &&
00700 (OP_bb(op) == OP_bb(opinfo->in_op)))
00701 {
00702 if (size_pred != size_succ)
00703 return FALSE;
00704
00705 if (opinfo->op_must_not_be_removed)
00706 return FALSE;
00707
00708 if (EBO_Trace_Optimization)
00709 fprintf(TFile,"%sRemove Store - Store combination\n",EBO_trace_pfx);
00710
00711 remove_op (opinfo);
00712 OP_Change_To_Noop(opinfo->in_op);
00713 opinfo->in_op = NULL;
00714 opinfo->in_bb = NULL;
00715 return FALSE;
00716 }
00717
00718
00719
00720 else {
00721 return FALSE;
00722 }
00723
00724 return FALSE;
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 BOOL
00736 delete_duplicate_op (OP *op,
00737 EBO_TN_INFO **opnd_tninfo,
00738 EBO_OP_INFO *opinfo)
00739 {
00740 INT resnum;
00741 OPS ops = OPS_EMPTY;
00742
00743 if (EBO_Trace_Data_Flow) {
00744 fprintf(TFile,"%sDuplicate OP in BB:%d ",EBO_trace_pfx,BB_id(OP_bb(op)));
00745 Print_OP_No_SrcLine(op);
00746 fprintf(TFile," Matches OP in BB:%d ",BB_id(opinfo->in_bb));
00747 Print_OP_No_SrcLine(opinfo->in_op);
00748 }
00749
00750
00751
00752 if ((Opt_Level < 2) && (OP_bb(op) != opinfo->in_bb))
00753 return FALSE;
00754
00755
00756
00757 if (OP_memory(op))
00758 {
00759 return delete_memory_op (op, opnd_tninfo, opinfo);
00760 }
00761 else
00762 {
00763
00764
00765
00766 if (OP_results(op) == 1)
00767 if (TN_register_class(OP_result(op, 0)) == ISA_REGISTER_CLASS_fcc)
00768 return FALSE;
00769
00770
00771
00772 for (resnum = 0; resnum < OP_results(op); resnum++) {
00773 EBO_Exp_COPY(NULL, OP_result(op, resnum), OP_result(opinfo->in_op, resnum), &ops);
00774 }
00775
00776 if (EBO_in_loop)
00777 EBO_OPS_omega (&ops);
00778
00779 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
00780 return TRUE;
00781 }
00782
00783 return FALSE;
00784 }
00785
00786
00787
00788
00789
00790 static BOOL
00791 Convert_Imm_Add (OP *op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo)
00792 {
00793 TOP top;
00794 OP *new_op = NULL;
00795
00796 Is_True(TOP_is_iadd(OP_code(op)),
00797 ("Convert_Imm_Add: unexpected opcode"));
00798
00799
00800
00801 if (ISA_LC_Value_In_Class(imm_val, LC_simm16))
00802 top = TOP_is_iop64(OP_code(op)) ? TOP_daddiu : TOP_addiu;
00803 else
00804 return FALSE;
00805
00806 if (EBO_Trace_Optimization)
00807 fprintf(TFile,"\treplace %s with %s\n", TOP_Name(OP_code(op)), TOP_Name(top));
00808
00809 if (!new_op)
00810 new_op = Mk_OP(top, tnr, tn, Gen_Literal_TN(imm_val, TN_size(tnr)));
00811
00812 OP_srcpos(new_op) = OP_srcpos(op);
00813 if (EBO_in_loop)
00814 EBO_Set_OP_omega(new_op, tninfo, NULL);
00815
00816 BB_Insert_Op_After(OP_bb(op), op, new_op);
00817 return TRUE;
00818 }
00819
00820
00821
00822
00823
00824
00825
00826 BOOL
00827 Constant_Operand0 (OP *op,
00828 TN **opnd_tn,
00829 EBO_TN_INFO **opnd_tninfo)
00830 {
00831 TOP opcode = OP_code(op);
00832 INT o0_idx = 0;
00833 INT o1_idx = (OP_opnds(op) > 1) ? 1 : -1;
00834
00835
00836 if (OP_opnds(op) < 1)
00837 return FALSE;
00838
00839 if (EBO_Trace_Execution)
00840 {
00841 fprintf(TFile, "%sin BB:%d constant0 OP :- %s",
00842 EBO_trace_pfx, BB_id(OP_bb(op)),TOP_Name(OP_code(op)));
00843 for (UINT i = 0; i < OP_opnds(op); i++)
00844 {
00845 fprintf(TFile," ");
00846 Print_TN(opnd_tn[i],FALSE);
00847 }
00848 fprintf(TFile,"\n");
00849 }
00850
00851 TN *tn0 = opnd_tn[o0_idx];
00852 TN *tn1 = (o1_idx >= 0) ? opnd_tn[o1_idx] : NULL;
00853 TN *tnr = (OP_results(op) == 0) ? NULL : OP_result(op,0);
00854
00855
00856 if (TN_is_symbol(tn0))
00857 return FALSE;
00858
00859
00860
00861
00862
00863
00864
00865
00866 if (TOP_is_cond_move(opcode))
00867 return FALSE;
00868
00869
00870 FmtAssert(TN_Is_Constant(tn0) &&
00871 ((OP_opnds(op) > 2) || !tn1 || !TN_Is_Constant(tn1)),
00872 ("Unexpected constant/non-constant operands"));
00873
00874 const INT64 imm_val = TN_Value(tn0);
00875
00876 if (opcode == TOP_add)
00877 return Convert_Imm_Add(op, tnr, tn1, imm_val, opnd_tninfo[o1_idx]);
00878
00879 return FALSE;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888 BOOL
00889 Constant_Operand1 (OP *op,
00890 TN **opnd_tn,
00891 EBO_TN_INFO **opnd_tninfo)
00892 {
00893 BB *bb = OP_bb(op);
00894 TOP opcode = OP_code(op);
00895 INT o0_idx = 0;
00896 INT o1_idx = (OP_opnds(op) > 1) ? 1 : -1;
00897
00898
00899 if (OP_opnds(op) < 1)
00900 return FALSE;
00901
00902 if (EBO_Trace_Execution)
00903 {
00904 fprintf(TFile, "%sin BB:%d constant1 OP :- %s",
00905 EBO_trace_pfx, BB_id(OP_bb(op)), TOP_Name(OP_code(op)));
00906 for (UINT i = 0; i < OP_opnds(op); i++)
00907 {
00908 fprintf(TFile," ");
00909 Print_TN(opnd_tn[i],FALSE);
00910 }
00911 fprintf(TFile,"\n");
00912 }
00913
00914 TN *tn0 = opnd_tn[o0_idx];
00915 TN *tn1 = opnd_tn[o1_idx];
00916 TN *tnr = (OP_results(op) == 0) ? NULL : OP_result(op,0);
00917
00918
00919 if (TN_is_symbol(tn1))
00920 return FALSE;
00921
00922
00923 FmtAssert(TN_Is_Constant(tn1) && ((OP_opnds(op) > 2) || !TN_Is_Constant(tn0)),
00924 ("Unexpected constant/non-constant operands"));
00925
00926 const INT64 imm_val = TN_Value(tn1);
00927
00928 if (opcode == TOP_add)
00929 return Convert_Imm_Add(op, tnr, tn0, imm_val, opnd_tninfo[o0_idx]);
00930
00931
00932
00933
00934
00935 if (opnd_tninfo[o0_idx] == NULL)
00936 return FALSE;
00937
00938 OP *pred_op = opnd_tninfo[o0_idx]->in_op;
00939 if (pred_op == NULL)
00940 return FALSE;
00941
00942 TOP pred_opcode = OP_code(pred_op);
00943
00944
00945 if (OP_iadd(op) && OP_iadd(pred_op))
00946 {
00947 INT ptn0_idx = TOP_Find_Operand_Use(pred_opcode,OU_opnd1);
00948 INT ptn1_idx = TOP_Find_Operand_Use(pred_opcode,OU_opnd2);
00949 TN *ptn0 = OP_opnd(pred_op, ptn0_idx);
00950 TN *ptn1 = OP_opnd(pred_op, ptn1_idx);
00951
00952 if (TN_is_constant(ptn1) && !TN_is_symbol(ptn1))
00953 {
00954 EBO_OP_INFO *pred_opinfo = locate_opinfo_entry(opnd_tninfo[o0_idx]);
00955 EBO_TN_INFO *ptn0_tninfo = pred_opinfo->actual_opnd[ptn0_idx];
00956
00957 if (EBO_tn_available(bb, ptn0_tninfo))
00958 {
00959 const INT64 new_val = imm_val + TN_Value(ptn1);
00960 if (Convert_Imm_Add(op, tnr, ptn0, new_val, ptn0_tninfo))
00961 {
00962 if (EBO_Trace_Optimization)
00963 fprintf(TFile,"\tcombine immediate adds\n");
00964
00965 return TRUE;
00966 }
00967 }
00968 }
00969 }
00970
00971 return FALSE;
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981 BOOL
00982 Resolve_Conditional_Branch (OP *op, TN **opnd_tn)
00983 {
00984 BB *bb = OP_bb(op);
00985
00986
00987
00988 if ((BBlist_Len(BB_succs(bb)) != 2)
00989 || (TOP_Find_Operand_Use(OP_code(op),OU_target) < 0))
00990 return FALSE;
00991
00992
00993
00994
00995 TN *tn0 = opnd_tn[0];
00996 INT64 tn0_val = TN_Value (tn0);
00997 UINT64 tn0_uval = TN_Value (tn0);
00998
00999 TN *tn1;
01000 INT64 tn1_val;
01001 UINT64 tn1_uval;
01002
01003 if (OP_opnds(op) > 1)
01004 {
01005 tn1 = opnd_tn[1];
01006 tn1_val = TN_Value (tn1);
01007 tn1_uval = TN_Value (tn1);
01008 }
01009
01010
01011 BOOL taken;
01012 TOP top = OP_code(op);
01013
01014 if (top == TOP_beq)
01015 taken = (tn0_uval == tn1_uval);
01016 else if (top == TOP_bgez)
01017 taken = (tn0_val >= 0);
01018 else if (top == TOP_bltz)
01019 taken = (tn0_val < 0);
01020 else if (top == TOP_bne)
01021 taken = (tn0_uval != tn1_uval);
01022 else
01023 return FALSE;
01024
01025 if (EBO_Trace_Optimization)
01026 {
01027 INT opndnum = OP_opnds(op);
01028 fprintf(TFile, "%sin BB:%d Resolve conditional BR :- %s ",
01029 EBO_trace_pfx, BB_id(bb),TOP_Name(OP_code(op)));
01030 for (UINT i = 0; i < opndnum; i++)
01031 {
01032 fprintf(TFile," ");
01033 Print_TN(opnd_tn[i],FALSE);
01034 }
01035 fprintf(TFile,"\n");
01036 }
01037
01038
01039
01040
01041
01042
01043 BB *fall_bb;
01044 BB *branch_bb;
01045
01046 fall_bb = BB_next(bb);
01047 branch_bb = BBLIST_item(BB_succs(bb));
01048 if (branch_bb == fall_bb)
01049 branch_bb = BBLIST_item(BBLIST_next(BB_succs(bb)));
01050
01051 if (taken)
01052 {
01053 OPS ops = OPS_EMPTY;
01054
01055 Build_OP (TOP_j, OP_opnd(op,TOP_Find_Operand_Use(OP_code(op),OU_target)), &ops);
01056 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
01057 Unlink_Pred_Succ (bb, fall_bb);
01058 Change_Succ_Prob (bb, branch_bb, 1.0);
01059 }
01060 else
01061 {
01062 Unlink_Pred_Succ (bb, branch_bb);
01063 Change_Succ_Prob (bb, fall_bb, 1.0);
01064 }
01065
01066 return TRUE;
01067 }
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078 BOOL
01079 Fold_Constant_Expression (OP *op,
01080 TN **opnd_tn,
01081 EBO_TN_INFO **opnd_tninfo)
01082 {
01083 TOP opcode = OP_code(op);
01084 TN *tnr = OP_result(op,0);
01085
01086 if (OP_opnds(op) == 0)
01087 return FALSE;
01088
01089
01090
01091 if (TN_register_class(tnr) != ISA_REGISTER_CLASS_integer)
01092 return FALSE;
01093
01094 if (EBO_Trace_Execution)
01095 {
01096 fprintf(TFile, "%sin BB:%d Constant OP :- %s ",
01097 EBO_trace_pfx, BB_id(OP_bb(op)),TOP_Name(opcode));
01098
01099 for (UINT i = 0; i < OP_opnds(op); i++)
01100 {
01101 fprintf(TFile," ");
01102 Print_TN(opnd_tn[i],TRUE);
01103 }
01104
01105 fprintf(TFile,"\n");
01106 }
01107
01108 TN *tn0 = opnd_tn[0];
01109 TN *tn1 = opnd_tn[1];
01110
01111 if (tn0 == Zero_TN || tn1 == Zero_TN)
01112 return FALSE;
01113
01114 INT64 result_val;
01115 INT64 tn0_val, tn1_val;
01116 UINT64 tn0_uval, tn1_uval;
01117
01118 ST *result_sym = NULL;
01119 INT32 result_relocs;
01120
01121
01122
01123 if (TN_is_symbol(tn0))
01124 {
01125
01126 if ((OP_opnds(op) == 2) && TN_is_symbol(tn1))
01127 return FALSE;
01128
01129 tn0_uval = TN_offset(tn0);
01130 tn0_val = TN_offset(tn0);
01131 result_sym = TN_var(tn0);
01132 result_relocs = TN_relocs(tn0);
01133 }
01134 else
01135 {
01136 tn0_uval = TN_Value (tn0);
01137 tn0_val = TN_Value (tn0);
01138 }
01139
01140 if (OP_opnds(op) == 1)
01141 {
01142 tn1_val = 0;
01143 tn1_uval = 0;
01144 }
01145 else if (TN_is_symbol(tn1))
01146 {
01147 tn1_uval = TN_offset(tn1);
01148 tn1_val = TN_offset(tn1);
01149 result_sym = TN_var(tn1);
01150 result_relocs = TN_relocs(tn1);
01151 }
01152 else
01153 {
01154 tn1_uval = TN_Value (tn1);
01155 tn1_val = TN_Value (tn1);
01156 }
01157
01158
01159
01160 if (OP_opnds(op) > 2)
01161 return FALSE;
01162
01163
01164
01165 if (TOP_is_iadd(opcode))
01166 {
01167 result_val = tn0_val + tn1_val;
01168 goto Constant_Created;
01169 }
01170
01171
01172
01173 if (OP_opnds(op) > 1 && !TN_is_symbol(tn1))
01174 {
01175 if (opcode == TOP_sub)
01176 {
01177 result_val = tn0_val - tn1_val;
01178 goto Constant_Created;
01179 }
01180 }
01181
01182
01183
01184 if (opcode == TOP_and)
01185 {
01186 result_val = tn0_uval & tn1_uval;
01187 goto Constant_Created;
01188 }
01189 else if (opcode == TOP_or)
01190 {
01191 result_val = tn0_uval | tn1_uval;
01192 goto Constant_Created;
01193 }
01194 else if (opcode == TOP_xor)
01195 {
01196 result_val = tn0_uval ^ tn1_uval;
01197 goto Constant_Created;
01198 }
01199
01200
01201
01202 if (opcode == TOP_sll)
01203 {
01204 result_val = TRUNC_32(tn0_uval << tn1_uval);
01205 goto Constant_Created;
01206 }
01207 else if (opcode == TOP_sra)
01208 {
01209 result_val = tn0_val >> tn1_uval;
01210 goto Constant_Created;
01211 }
01212 else if (opcode == TOP_srl)
01213 {
01214 result_val = TRUNC_32(tn0_val) >> tn1_uval;
01215 goto Constant_Created;
01216 }
01217
01218 return FALSE;
01219
01220
01221
01222 Constant_Created:
01223
01224 OPS ops = OPS_EMPTY;
01225 TN *tnc;
01226
01227 if (result_sym != NULL)
01228 {
01229 tnc = Gen_Symbol_TN(result_sym, result_val, result_relocs);
01230 }
01231 else
01232 {
01233 tnc = Gen_Literal_TN(result_val, TN_size(tnr));
01234 }
01235
01236 Expand_Immediate (tnr, tnc, OP_result_is_signed(op,0), &ops);
01237
01238
01239
01240
01241
01242
01243 if (OP_next(OPS_first(&ops)) != NULL)
01244 return FALSE;
01245
01246 if (EBO_in_loop)
01247 EBO_OPS_omega (&ops);
01248
01249 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
01250
01251 if (EBO_Trace_Optimization)
01252 {
01253 fprintf(TFile, "%sin BB:%d Redefine ",
01254 EBO_trace_pfx, BB_id(OP_bb(op)));
01255 Print_TN(tnr,TRUE);
01256 fprintf(TFile," with load of ");
01257 Print_TN(tnc,FALSE);
01258 fprintf(TFile, "\n");
01259 }
01260
01261 return TRUE;
01262 }
01263
01264
01265 #define SWAP_TN(a, b) (_tn_swap_tmp = a, a = b, b = _tn_swap_tmp)
01266 #define SWAP_TNINFO(a, b) (_tninfo_swap_tmp = a, a = b, b = _tninfo_swap_tmp)
01267 static TN *_tn_swap_tmp;
01268 static EBO_TN_INFO *_tninfo_swap_tmp;
01269
01270
01271
01272
01273
01274 static EBO_OP_INFO *
01275 imm_sll (EBO_OP_INFO *sll_opinfo, INT32 *shift =NULL)
01276 {
01277 if (!sll_opinfo)
01278 return NULL;
01279
01280 OP *sll = sll_opinfo->in_op;
01281 TOP top = OP_code(sll);
01282 if (top != TOP_sll)
01283 return NULL;
01284
01285 TN *imm = OP_opnd(sll, 1);
01286 if (!TN_has_value(imm))
01287 return NULL;
01288
01289 if (shift)
01290 *shift = TN_value(imm);
01291
01292 return sll_opinfo;
01293 }
01294
01295
01296
01297
01298 static EBO_OP_INFO *
01299 imm_sra (EBO_OP_INFO *sra_opinfo, INT32 *shift =NULL)
01300 {
01301 if (!sra_opinfo)
01302 return NULL;
01303
01304 OP *sra = sra_opinfo->in_op;
01305 TOP top = OP_code(sra);
01306 if (top != TOP_sra)
01307 return NULL;
01308
01309 TN *imm = OP_opnd(sra, 1);
01310 if (!TN_has_value(imm))
01311 return NULL;
01312
01313 if (shift)
01314 *shift = TN_value(imm);
01315
01316 return sra_opinfo;
01317 }
01318
01319
01320
01321
01322 static EBO_OP_INFO *
01323 imm_srl (EBO_OP_INFO *srl_opinfo, INT32 *shift =NULL)
01324 {
01325 if (!srl_opinfo)
01326 return NULL;
01327
01328 OP *srl = srl_opinfo->in_op;
01329 TOP top = OP_code(srl);
01330 if (top != TOP_srl)
01331 return NULL;
01332
01333 TN *imm = OP_opnd(srl, 1);
01334 if (!TN_has_value(imm))
01335 return NULL;
01336
01337 if (shift)
01338 *shift = TN_value(imm);
01339
01340 return srl_opinfo;
01341 }
01342
01343
01344
01345
01346 static EBO_OP_INFO *
01347 index_add (EBO_OP_INFO *add_opinfo, TN *base, TN **index =NULL)
01348 {
01349 if (!add_opinfo)
01350 return NULL;
01351
01352 OP *add = add_opinfo->in_op;
01353 TOP top = OP_code(add);
01354 if (! TOP_is_iadd(top))
01355 return NULL;
01356
01357 TN *imm_tn = OP_opnd(add, 1);
01358 TN *other_tn = OP_opnd(add, 0);
01359
01360 if (imm_tn == base) {
01361 if (index)
01362 *index = other_tn;
01363 } else
01364 if (index)
01365 *index = imm_tn;
01366
01367 return add_opinfo;
01368 }
01369
01370
01371
01372
01373 static EBO_OP_INFO *
01374 decode_and (EBO_OP_INFO *and_opinfo, TN **left, TN **right)
01375 {
01376 if (!and_opinfo)
01377 return NULL;
01378
01379 OP *andd = and_opinfo->in_op;
01380 TOP top = OP_code(andd);
01381 if (top != TOP_and)
01382 return NULL;
01383
01384 TN *left_tn = OP_opnd(andd, 0);
01385 TN *right_tn = OP_opnd(andd, 1);
01386 if (!TN_is_register(left_tn) || !TN_is_register(right_tn))
01387 return NULL;
01388
01389 if (left)
01390 *left = left_tn;
01391 if (right)
01392 *right = right_tn;
01393
01394 return and_opinfo;
01395 }
01396
01397
01398
01399
01400
01401
01402 INT EBO_Copy_Operand (OP *op)
01403 {
01404 INT opnd;
01405
01406 if (OP_copy(op)) {
01407 TOP topcode = OP_code(op);
01408 if (topcode == TOP_add || topcode == TOP_dadd ||
01409 topcode == TOP_addu || topcode == TOP_daddu ||
01410 topcode == TOP_or ||
01411 topcode == TOP_mov_s || topcode== TOP_mov_d)
01412 return 0;
01413 }
01414
01415 opnd = CGTARG_Copy_Operand(op);
01416 if (opnd >= 0) {
01417 return opnd;
01418 }
01419
01420 return -1;
01421 }
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432 static OP *
01433 cmovable_op (BB *bb, UINT *len, TN *no_define,
01434 BS *in_defined_tns, BS **out_defined_tns)
01435 {
01436 *len = BB_length(bb);
01437 if (*len == 0)
01438 return NULL;
01439
01440 OP *jump = BB_xfer_op(bb);
01441 if (jump && ((*len == 1) || (OP_code(jump) != TOP_j)))
01442 return NULL;
01443
01444
01445
01446
01447 work_gtn_set = GTN_SET_ClearD(work_gtn_set);
01448
01449 OP *last = NULL;
01450 for (OP *op = BB_first_op(bb); op; op = OP_next(op))
01451 {
01452 if (OP_xfer(op))
01453 break;
01454
01455 last = op;
01456
01457 if (!CGTARG_Can_Be_Speculative(op))
01458 return NULL;
01459
01460 for (UINT i = 0; i < OP_results(op); i++)
01461 {
01462 TN *res = OP_result(op, i);
01463 if (TN_is_register(res) && !TN_is_const_reg(res))
01464 {
01465 if (TN_is_global_reg(res))
01466 work_gtn_set = GTN_SET_Union1D(work_gtn_set, res, work_pool);
01467
01468 if (out_defined_tns)
01469 *out_defined_tns = BS_Union1D(*out_defined_tns, TN_number(res), work_pool);
01470 }
01471 }
01472
01473 if (in_defined_tns)
01474 {
01475 for (UINT i = 0; i < OP_opnds(op); i++)
01476 {
01477 TN *opnd = OP_opnd(op, i);
01478 if (TN_is_register(opnd) && BS_MemberP(in_defined_tns, TN_number(opnd)))
01479 return NULL;
01480 }
01481 }
01482 }
01483
01484
01485
01486
01487
01488 if (!last ||
01489 (OP_results(last) != 1) ||
01490 ((no_define != NULL) && GTN_SET_MemberP(work_gtn_set, no_define)))
01491 return NULL;
01492
01493 work_gtn_set = GTN_SET_Difference1D(work_gtn_set, OP_result(last, 0));
01494 if (GTN_SET_IntersectsP(work_gtn_set, BB_live_out(bb)))
01495 return NULL;
01496
01497 if (out_defined_tns)
01498 *out_defined_tns = BS_Difference1D(*out_defined_tns,
01499 TN_number(OP_result(last, 0)));
01500
01501 if (OP_same_res(last))
01502 return NULL;
01503
01504 return last;
01505 }
01506
01507 static BOOL is_live_tn(OP *current_op, TN *current_tn)
01508 {
01509 OP *op;
01510 Is_True(GRA_LIVE_Phase_Invoked, ("Bad call to is_live_tn"));
01511 BOOL is_live = tn_has_live_def_into_BB(current_tn, OP_bb(current_op));
01512 BOOL past_current_op = FALSE;
01513
01514 FOR_ALL_BB_OPs(OP_bb(current_op), op) {
01515 INT num_opnds = OP_opnds(op);
01516 INT num_results = OP_results(op);
01517 if (op == current_op) {
01518 past_current_op = TRUE;
01519 if (!is_live)
01520 return FALSE;
01521 }
01522 if (past_current_op) {
01523 for (int opndnum = 0; opndnum < num_opnds; opndnum++) {
01524 if (tn_registers_identical(current_tn, OP_opnd(op,opndnum)))
01525 return TRUE;
01526 }
01527 }
01528 for (int resnum = 0; resnum < num_results; resnum++) {
01529 if (tn_registers_identical(current_tn, OP_result(op,resnum))) {
01530 if (past_current_op)
01531 return FALSE;
01532 else
01533 is_live = TRUE;
01534 }
01535 }
01536 }
01537 Is_True(past_current_op && is_live, ("Bad call to is_live_tn"));
01538 return GTN_SET_MemberP(BB_live_out(OP_bb(current_op)), current_tn);
01539 }
01540
01541
01542
01543
01544
01545
01546
01547 BOOL Special_Sequence (OP *op,
01548 TN **opnd_tn,
01549 EBO_TN_INFO **opnd_tninfo)
01550 {
01551 if (!EBO_in_peep)
01552 return FALSE;
01553 if (OP_code(op) == TOP_beq ||
01554 OP_code(op) == TOP_bne) {
01555 INT64 val = 0;
01556 TN *opnd0 = OP_opnd(op, 0);
01557 TN *opnd1 = OP_opnd(op, 1);
01558 EBO_TN_INFO *opnd1_tninfo = get_tn_info(opnd1);
01559 if (opnd1_tninfo &&
01560 EBO_tn_available(OP_bb(op), opnd1_tninfo) &&
01561 opnd1_tninfo->in_op &&
01562 (OP_code(opnd1_tninfo->in_op) == TOP_addiu)) {
01563 OP *op_in = opnd1_tninfo->in_op;
01564 if (TN_has_value(OP_opnd(op_in, 1)) &&
01565 (TN_value(OP_opnd(op_in, 1)) != -1))
01566 return FALSE;
01567 else if (TN_has_value(OP_opnd(op_in, 1)))
01568 val = -1;
01569 else
01570 return FALSE;
01571 } else if (opnd1 != Zero_TN) {
01572 return FALSE;
01573 }
01574
01575
01576 EBO_TN_INFO *opnd0_tninfo = get_tn_info(opnd0);
01577 if (opnd0_tninfo &&
01578 EBO_tn_available(OP_bb(op), opnd0_tninfo) &&
01579 opnd0_tninfo->in_op &&
01580 (OP_code(opnd0_tninfo->in_op) == TOP_sra ||
01581 OP_code(opnd0_tninfo->in_op) == TOP_dsra ||
01582 OP_code(opnd0_tninfo->in_op) == TOP_dsra32)) {
01583 EBO_TN_INFO *tninfo;
01584 OP *shift_op = opnd0_tninfo->in_op;
01585
01586
01587 TN *shift_res = OP_result(shift_op, 0);
01588 if (EBO_in_peep) {
01589 if (REG_LIVE_Outof_BB (TN_register_class(shift_res),
01590 TN_register(shift_res),
01591 OP_bb(shift_op)))
01592 return FALSE;
01593 } else {
01594 if (CG_localize_tns && (TN_is_dedicated(shift_res) ||
01595 TN_is_global_reg(shift_res)))
01596 return FALSE;
01597 else if (GRA_LIVE_TN_Live_Outof_BB (shift_res, OP_bb(shift_op)))
01598 return FALSE;
01599 }
01600
01601
01602 TN *shift_ctrl_opnd = OP_opnd(shift_op, 1);
01603 FmtAssert(TN_has_value(shift_ctrl_opnd),
01604 ("shift ctrl opnd is not a constant"));
01605 switch(shift_op->opr) {
01606 case TOP_sra:
01607 if (TN_value(shift_ctrl_opnd) != 31)
01608 return FALSE;
01609 break;
01610 case TOP_dsra32:
01611 if ((TN_value(shift_ctrl_opnd) % 32) != 31)
01612 return FALSE;
01613 break;
01614 case TOP_dsra:
01615 if (TN_value(shift_ctrl_opnd) == 63)
01616 FmtAssert(FALSE, ("shift of 63 with dsra encountered"));
01617 break;
01618 }
01619
01620 OP *new_op;
01621 OPS ops = OPS_EMPTY;
01622 if (OP_code(op) == TOP_bne)
01623 val = (val == 0)?-1:0;
01624 new_op = Mk_OP((val==0)?TOP_bgez:TOP_bltz,
01625 OP_opnd(shift_op, 0), OP_opnd(op, 2));
01626 OP_srcpos(new_op) = OP_srcpos(op);
01627 OPS_Append_Op(&ops, new_op);
01628 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
01629 OP_Change_To_Noop(op);
01630 OP_Change_To_Noop(shift_op);
01631 if (EBO_Trace_Optimization) {
01632 fprintf(TFile, "shift and beq combined to produce bgez.\n");
01633 }
01634 return TRUE;
01635 }
01636 }
01637
01638 TOP top = OP_code(op);
01639
01640 #ifdef Is_True_On
01641 if (EBO_Trace_Optimization)
01642 {
01643 fprintf(TFile, "OP: ");
01644 Print_OP_No_SrcLine(op);
01645 for (UINT i = 0; i < OP_opnds(op); i++)
01646 {
01647 fprintf(TFile, " local tn: ");
01648 Print_TN(OP_opnd(op, i), TRUE);
01649 fprintf(TFile, "\n ebo tn: ");
01650 Print_TN(opnd_tn[i], TRUE);
01651 fprintf(TFile, "\n local in_op: ");
01652 fprintf(TFile, "<null>\n");
01653 fprintf(TFile, " ebo in_op: ");
01654 if (opnd_tninfo[i] && opnd_tninfo[i]->in_op)
01655 Print_OP_No_SrcLine(opnd_tninfo[i]->in_op);
01656 else
01657 fprintf(TFile, "<null>\n");
01658
01659 if (opnd_tninfo[i] && opnd_tninfo[i]->replacement_tn)
01660 {
01661 fprintf(TFile, " replace tn: ");
01662 Print_TN(opnd_tninfo[i]->replacement_tn, TRUE);
01663 fprintf(TFile, "\n replace in_op: ");
01664 if (opnd_tninfo[i]->replacement_tninfo &&
01665 opnd_tninfo[i]->replacement_tninfo->in_op)
01666 Print_OP_No_SrcLine(opnd_tninfo[i]->replacement_tninfo->in_op);
01667 else
01668 fprintf(TFile, "<null>\n");
01669 }
01670 }
01671 }
01672 #endif
01673
01674 return FALSE;
01675 }
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685 void Redundancy_Elimination()
01686 {
01687 for( BB* bb = REGION_First_BB; bb != NULL; bb = BB_next( bb ) ){
01688 if( BB_rid(bb) && (RID_level(BB_rid(bb)) >= RL_CGSCHED) ){
01689
01690 continue;
01691 }
01692 if (CG_skip_local_ebo &&
01693 ((BB_id(bb) < CG_local_skip_before) ||
01694 (BB_id(bb) > CG_local_skip_after) ||
01695 (BB_id(bb) == CG_local_skip_equal)))
01696 continue;
01697 for( OP* op = BB_first_op( bb ); op != NULL; op = OP_next( op ) ){
01698 BOOL done = FALSE;
01699 INT copy_operand = CGTARG_Copy_Operand(op);
01700 if (copy_operand >= 0) {
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711 TN* src = OP_opnd( op, copy_operand );
01712 TN* result = OP_result( op, 0 );
01713
01714 FmtAssert( TN_is_register( src ) && TN_is_register( result ),
01715 ("src/result not registers in EBO_in_peep"));
01716
01717
01718 if (REG_LIVE_Outof_BB (TN_register_class(result),
01719 TN_register(result), bb)) {
01720
01721
01722 BOOL redefined = FALSE;
01723 for( OP* dw_op = OP_next( op ); dw_op != NULL; dw_op = OP_next( dw_op ) ){
01724 if ((OP_code(dw_op) != TOP_asm) &&
01725 OP_results(dw_op) &&
01726 TN_is_register(OP_result(dw_op, 0)) &&
01727 (TN_register_class(OP_result(dw_op, 0)) ==
01728 TN_register_class(result)) &&
01729 (TN_register(OP_result(dw_op, 0)) == TN_register(result))) {
01730 redefined = TRUE;
01731 break;
01732 }
01733 }
01734 if (redefined == FALSE)
01735 continue;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749 BOOL cannot_be_removed = FALSE;
01750 BOOL special_case = FALSE;
01751 for( OP* dw_op = OP_next( op ); dw_op != NULL;
01752 dw_op = OP_next( dw_op ) ){
01753 if ((OP_code(dw_op) != TOP_asm) &&
01754 OP_results(dw_op) &&
01755 TN_is_register( OP_result( dw_op, 0)) &&
01756 TNs_Are_Equivalent( OP_result( dw_op, 0), src)) {
01757
01758
01759 INT dw_op_copy_operand = CGTARG_Copy_Operand(dw_op);
01760 TN *dw_op_copy_operand_tn =
01761 (dw_op_copy_operand>=0)?OP_opnd(dw_op, dw_op_copy_operand):NULL;
01762 if ((dw_op_copy_operand >= 0) &&
01763 TN_is_register( dw_op_copy_operand_tn) &&
01764 TNs_Are_Equivalent(dw_op_copy_operand_tn, result)) {
01765 special_case = TRUE;
01766 break;
01767 }
01768
01769
01770 for( OP* dw1_op = OP_next( dw_op ); dw1_op != NULL;
01771 dw1_op = OP_next( dw1_op ) ){
01772 #ifdef TARG_SL2
01773
01774
01775
01776
01777
01778
01779
01780 BOOL redef = FALSE;
01781 for(int i = 0; i < OP_results(dw1_op); i++) {
01782 if(TN_is_register(OP_result(dw1_op, i)) &&
01783 TNs_Are_Equivalent(OP_result(dw1_op, i), result)) {
01784 redef = TRUE;
01785 cannot_be_removed=TRUE;
01786 break;
01787 }
01788 }
01789 if(redef)
01790 break;
01791 #endif
01792 for( int i = 0; i < OP_opnds( dw1_op ); i++ ){
01793 if ( TN_is_register( OP_opnd( dw1_op, i)) &&
01794 TNs_Are_Equivalent( OP_opnd( dw1_op, i), result)) {
01795 cannot_be_removed = TRUE;
01796 break;
01797 }
01798 }
01799 }
01800 if (cannot_be_removed)
01801 break;
01802 }
01803 #ifdef TARG_SL2
01804 if(OP_same_res(dw_op) || (OP_code(dw_op) == TOP_c2_satd ||
01805 OP_code(dw_op) == TOP_c2_sad) || OP_code(dw_op) == TOP_c2_muls) {
01806 for (INT i = 0; i < OP_results(dw_op); i++)
01807 if(TNs_Are_Equivalent(result, OP_result(dw_op, i))) {
01808 cannot_be_removed = TRUE;
01809 break;
01810 }
01811 }
01812 #endif
01813 }
01814 if (cannot_be_removed)
01815 continue;
01816
01817
01818
01819 for( OP* dw_op = OP_next( op ); dw_op != NULL;
01820 dw_op = OP_next( dw_op ) ){
01821
01822 for( int i = 0; i < OP_opnds( dw_op ); i++ ){
01823 if ( TN_is_register( OP_opnd( dw_op, i)) &&
01824 TNs_Are_Equivalent( OP_opnd( dw_op, i), result)) {
01825 Set_OP_opnd( dw_op, i, src );
01826 done = TRUE;
01827 }
01828 }
01829
01830 #ifdef TARG_SL2
01831 if( OP_results( dw_op ) > 0 ){
01832 #else
01833 if( OP_results( dw_op ) == 1 ){
01834 #endif
01835
01836 #ifdef TARG_SL2
01837 TN* tnr = OP_result( dw_op, 0 );
01838 if(OP_code(dw_op) == TOP_c2_sad || OP_code(dw_op) == TOP_c2_satd ||
01839 OP_code(dw_op) == TOP_c2_muls)
01840 tnr = OP_result(dw_op, 1);
01841 #else
01842 TN* tnr = OP_result( dw_op, 0 );
01843 #endif
01844
01845 if( TN_is_register( tnr) &&
01846 ( TNs_Are_Equivalent( tnr, result ) ||
01847 TNs_Are_Equivalent( tnr, src ) )) {
01848 if (special_case) {
01849 if (TNs_Are_Equivalent ( tnr, result ))
01850 break;
01851 } else {
01852 break;
01853 }
01854 }
01855 }
01856 }
01857
01858 if( done ){
01859 OP* dead = op;
01860 op = OP_prev( op );
01861
01862 if( EBO_Trace_Optimization ){
01863 fprintf( TFile,
01864 "Redundancy_Elimination removes simplified op - " );
01865 Print_OP_No_SrcLine( dead );
01866 }
01867
01868 BB_Remove_Op( bb, dead );
01869
01870 if( op == NULL )
01871 op = BB_first_op( bb );
01872 }
01873
01874 continue;
01875 }
01876
01877 if (OP_code( op ) != TOP_srl &&
01878 OP_code( op ) != TOP_sra &&
01879 OP_code( op ) != TOP_sll &&
01880 OP_code( op ) != TOP_dsrl &&
01881 OP_code( op ) != TOP_dsra &&
01882 OP_code( op ) != TOP_dsll &&
01883 OP_code( op ) != TOP_dsll32 &&
01884 OP_code( op ) != TOP_dsra32 &&
01885 OP_code( op ) != TOP_dsrl32)
01886 continue;
01887
01888
01889
01890 TN* src = OP_opnd( op, 0 );
01891 TN* result = OP_result( op, 0 );
01892
01893 FmtAssert( TN_is_register( src ) && TN_is_register( result ),
01894 ("src/result not registers in EBO_in_peep"));
01895
01896 if (OP_opnd( op, 0) != Zero_TN)
01897 continue;
01898
01899
01900 if (REG_LIVE_Outof_BB (TN_register_class(result),
01901 TN_register(result), bb)) {
01902
01903
01904 BOOL redefined = FALSE;
01905 for( OP* dw_op = OP_next( op ); dw_op != NULL;
01906 dw_op = OP_next( dw_op ) ){
01907 if (OP_results(dw_op) &&
01908 TN_is_register(OP_result(dw_op, 0)) &&
01909 (TN_register_class(OP_result(dw_op, 0)) ==
01910 TN_register_class(result)) &&
01911 (TN_register(OP_result(dw_op, 0)) == TN_register(result))) {
01912 redefined = TRUE;
01913 break;
01914 }
01915 }
01916 if (redefined == FALSE)
01917 continue;
01918 }
01919
01920
01921
01922 for( OP* dw_op = OP_next( op ); dw_op != NULL;
01923 dw_op = OP_next( dw_op ) ){
01924 for( int i = 0; i < OP_opnds( dw_op ); i++ ){
01925 if( TN_is_register(OP_opnd( dw_op, i)) &&
01926 (TN_register_class(OP_opnd(dw_op, i)) ==
01927 TN_register_class(result)) &&
01928 (TN_register(OP_opnd( dw_op, i )) == TN_register(result))) {
01929 Set_OP_opnd( dw_op, i, Zero_TN );
01930 done = TRUE;
01931 }
01932 }
01933
01934 if( OP_results( dw_op ) == 1 ){
01935 TN* tnr = OP_result( dw_op, 0 );
01936
01937 if( TN_is_register( tnr) &&
01938 TNs_Are_Equivalent( tnr, result ) )
01939 break;
01940 }
01941 }
01942
01943 if( done ){
01944 OP* dead = op;
01945 op = OP_prev( op );
01946
01947 if( EBO_Trace_Optimization ){
01948 fprintf( TFile, "Redundancy_Elimination removes simplified op - " );
01949 Print_OP_No_SrcLine( dead );
01950 }
01951
01952 BB_Remove_Op( bb, dead );
01953
01954 if( op == NULL )
01955 op = BB_first_op( bb );
01956 }
01957 }
01958 }
01959 }
01960