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 #ifdef USE_PCH
00071 #include "cg_pch.h"
00072 #endif // USE_PCH
00073 #pragma hdrstop
00074
00075 #ifdef _KEEP_RCS_ID
00076 static const char source_file[] = __FILE__;
00077 #endif
00078
00079 #include <stdarg.h>
00080 #include "defs.h"
00081 #include "config_targ_opt.h"
00082 #include "errors.h"
00083 #include "mempool.h"
00084 #include "tracing.h"
00085 #include "timing.h"
00086 #include "cgir.h"
00087 #include "tn_map.h"
00088 #include "cg_loop.h"
00089 #include "cg.h"
00090 #include "cgexp.h"
00091 #include "register.h"
00092 #include "cg_region.h"
00093 #include "wn.h"
00094 #include "region_util.h"
00095 #include "op_list.h"
00096 #include "cgprep.h"
00097 #include "gtn_universe.h"
00098 #include "gtn_set.h"
00099 #include "cg_db_op.h"
00100 #include "whirl2ops.h"
00101 #include "cgtarget.h"
00102 #include "gra_live.h"
00103 #include "reg_live.h"
00104 #include "cflow.h"
00105 #include "cg_spill.h"
00106 #include "cgexp_internals.h"
00107 #include "data_layout.h"
00108 #include "stblock.h"
00109 #include "cxx_hash.h"
00110 #include "op.h"
00111
00112 #include "ebo.h"
00113 #include "ebo_info.h"
00114 #include "ebo_special.h"
00115 #include "ebo_util.h"
00116 #include "cgtarget.h"
00117
00118 #include "config_lno.h"
00119
00120 extern BOOL TN_live_out_of( TN*, BB* );
00121
00122
00123
00124 #define TRUNC_32(val) (val & 0x00000000ffffffffll)
00125
00126
00127 #define SEXT_32(val) (((INT64)(val) << 32) >> 32)
00128
00129
00130
00131 typedef HASH_TABLE<ST_IDX, INITV_IDX> ST_TO_INITV_MAP;
00132 static ST_TO_INITV_MAP *st_initv_map = NULL;
00133 static BOOL st_initv_map_inited = FALSE;
00134 static GTN_SET *work_gtn_set = NULL;
00135 static BS *work_defined_set = NULL;
00136 static MEM_POOL *work_pool = NULL;
00137 static INT32 fixed_branch_cost, taken_branch_cost;
00138
00139 static BOOL Convert_Imm_And( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo );
00140 static BOOL Convert_Imm_Mul( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo );
00141 static BOOL Convert_Imm_Or( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo );
00142 static BOOL Convert_Imm_Add( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo );
00143 static BOOL Convert_Imm_Xor( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo );
00144 static BOOL Convert_Imm_Cmp( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo );
00145
00146 enum ADDR_MODE { REG_MODE = 0,
00147 BASE_MODE,
00148 BASE_INDEX_MODE,
00149 INDEX_MODE,
00150 N32_MODE,
00151 UNDEFINED_MODE
00152 };
00153
00154 static void Init_Addr_Modes();
00155 static TOP Get_Top_For_Addr_Mode (TOP, ADDR_MODE);
00156
00157 static OP *Compose_Mem_Op_And_Copy_Info (OP *op, TN *index, TN *offset,
00158 TN *scale, TN *base,
00159 EBO_TN_INFO **load_actual_tninfo);
00160
00161
00162 void
00163 EBO_Special_Start (MEM_POOL *pool)
00164 {
00165 #if 0
00166 st_initv_map = CXX_NEW(ST_TO_INITV_MAP(31, pool), pool);
00167 st_initv_map_inited = FALSE;
00168 work_gtn_set = GTN_SET_Create_Empty(Last_TN + 1, pool);
00169 work_defined_set = BS_Create_Empty(Last_TN + 1, pool);
00170 work_pool = pool;
00171
00172 INT32 idummy;
00173 double ddummy;
00174 CGTARG_Compute_Branch_Parameters(&idummy, &fixed_branch_cost,
00175 &taken_branch_cost, &ddummy);
00176 #endif
00177
00178 Init_Addr_Modes();
00179 }
00180
00181 void
00182 EBO_Special_Finish (void)
00183 {
00184 st_initv_map = NULL;
00185 st_initv_map_inited = FALSE;
00186 work_gtn_set = NULL;
00187 work_defined_set = NULL;
00188 work_pool = NULL;
00189 }
00190
00191
00192
00193
00194 static BOOL
00195 Pred_Opnd_Avail (OP *op, EBO_TN_INFO *tninfo, int pred_opnd_idx,
00196 EBO_TN_INFO **pred_tninfo_p = NULL)
00197 {
00198 EBO_OP_INFO *pred_opinfo;
00199 EBO_TN_INFO *pred_tninfo;
00200
00201 pred_opinfo = locate_opinfo_entry(tninfo);
00202 if (pred_opinfo == NULL)
00203 return FALSE;
00204 pred_tninfo = pred_opinfo->actual_opnd[pred_opnd_idx];
00205 if (pred_tninfo_p != NULL)
00206 *pred_tninfo_p = pred_tninfo;
00207 return EBO_tn_available(OP_bb(op), pred_tninfo);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 BOOL EBO_Can_Merge_Into_Offset (OP *op)
00217 {
00218 #if Is_True_On
00219 if (!(EBO_Opt_Mask & EBO_CAN_MERGE_INTO_OFFSET)) return FALSE;
00220 #endif
00221 TOP top = OP_code(op);
00222
00223 if( !OP_iadd( op ) && !OP_isub( op ) )
00224 return FALSE;
00225
00226 if ((op == BB_entry_sp_adj_op(OP_bb(op))) ||
00227 (op == BB_exit_sp_adj_op(OP_bb(op))))
00228 return FALSE;
00229
00230
00231
00232
00233
00234 if( MTYPE_is_size_double( Pointer_Mtype ) &&
00235 TN_size( OP_opnd(op,0) ) == 4 )
00236 return FALSE;
00237
00238 TN *tn = OP_opnd(op,1);
00239 if (TN_Is_Constant(tn))
00240 return TRUE;
00241
00242 return FALSE;
00243 }
00244
00245
00246 static
00247 void
00248 EBO_Set_OP_omega (OP *op, ...)
00249 {
00250 INT opnds = OP_opnds(op);
00251 INT i;
00252 va_list tninfos;
00253
00254 va_start(tninfos, op);
00255 CG_LOOP_Init_Op(op);
00256 for (i = 0; i < opnds; i++) {
00257 EBO_TN_INFO *tninfo = va_arg(tninfos, EBO_TN_INFO *);
00258 Set_OP_omega (op, i, ((tninfo != NULL) ? tninfo->omega : 0));
00259 }
00260
00261 va_end(tninfos);
00262 return;
00263 }
00264
00265
00266
00267 static
00268 void
00269 EBO_Copy_OP_omega (OP *new_op, OP *old_op)
00270 {
00271 INT opnds = OP_opnds(new_op);
00272 INT i;
00273
00274 CG_LOOP_Init_Op(new_op);
00275 for (i = 0; i < opnds; i++) {
00276 Set_OP_omega (new_op, i, OP_omega(old_op,i));
00277 }
00278
00279 return;
00280 }
00281
00282
00283 static
00284 void
00285 EBO_OPS_omega (OPS *ops)
00286 {
00287 OP *next_op = OPS_first(ops);
00288 while (next_op != NULL) {
00289 INT opnds = OP_opnds(next_op);
00290 INT i;
00291
00292 CG_LOOP_Init_Op(next_op);
00293 for (i = 0; i < opnds; i++) {
00294 Set_OP_omega (next_op, i, 0);
00295 }
00296
00297 next_op = OP_next(next_op);
00298 }
00299
00300 return;
00301 }
00302
00303
00304 BOOL Combine_L1_L2_Prefetches( OP* op, TN** opnd_tn, EBO_TN_INFO** opnd_tninfo )
00305 {
00306 #if Is_True_On
00307 if (!(EBO_Opt_Mask & EBO_COMBINE_L1_L2_PREFETCH)) return FALSE;
00308 #endif
00309 if( !OP_prefetch( op ) )
00310 return FALSE;
00311
00312
00313 const int hash_value = EBO_hash_op( op, opnd_tninfo );
00314
00315 if( EBO_Trace_Hash_Search ){
00316 #pragma mips_frequency_hint NEVER
00317 fprintf( TFile,"%sLook for redundant prefetch ops in hash chain %d for\n\t",
00318 EBO_trace_pfx,hash_value );
00319 Print_OP_No_SrcLine(op);
00320 }
00321
00322 BOOL replaced = FALSE;
00323 EBO_OP_INFO* opinfo = EBO_opinfo_table[hash_value];
00324
00325 while( opinfo != NULL ){
00326
00327 OP* pred_op = opinfo->in_op;
00328 if( pred_op == NULL ||
00329 !OP_prefetch(pred_op) ||
00330 OP_opnds(pred_op) != OP_opnds(op) ){
00331 opinfo = opinfo->same;
00332 continue;
00333 }
00334
00335
00336 int i = 1;
00337 for( ; i < OP_opnds(op); i++ ){
00338 if( OP_opnd( op, i ) != OP_opnd( pred_op, i ) )
00339 break;
00340 }
00341
00342 if( i < OP_opnds(op) ){
00343 opinfo = opinfo->same;
00344 continue;
00345 }
00346
00347
00348 const ISA_ENUM_CLASS_VALUE pfhint0 = TN_enum( OP_opnd(op,0) );
00349 const ISA_ENUM_CLASS_VALUE pfhint1 = TN_enum( OP_opnd(pred_op,0) );
00350
00351
00352 if( pfhint0 == pfhint1 ){
00353 replaced = TRUE;
00354 break;
00355 }
00356
00357
00358 if( pfhint0 == ECV_pfhint_L1_L2_load &&
00359 ( pfhint1 == ECV_pfhint_L1_load ||
00360 pfhint1 == ECV_pfhint_L2_load ) ){
00361
00362 remove_op( opinfo );
00363 OP_Change_To_Noop( opinfo->in_op );
00364 opinfo->in_op = NULL;
00365 opinfo->in_bb = NULL;
00366
00367 break;
00368 }
00369
00370 if( pfhint1 == ECV_pfhint_L1_L2_load &&
00371 ( pfhint0 == ECV_pfhint_L1_load ||
00372 pfhint0 == ECV_pfhint_L2_load ) ){
00373 replaced = TRUE;
00374 break;
00375 }
00376
00377
00378 if( ( pfhint0 == ECV_pfhint_L1_load &&
00379 pfhint1 == ECV_pfhint_L2_load ) ||
00380 ( pfhint0 == ECV_pfhint_L2_load &&
00381 pfhint1 == ECV_pfhint_L1_load ) ){
00382 ;
00383 } else {
00384 opinfo = opinfo->same;
00385 continue;
00386 }
00387
00388 OP* new_op = Dup_OP( op );
00389 Set_OP_opnd( new_op, 0 , Gen_Enum_TN( ECV_pfhint_L1_L2_load ) );
00390
00391
00392 BOOL nt = (OP_code(op)==TOP_prefetchnta);
00393 TOP new_top = nt?TOP_prefetchnta:TOP_prefetcht0;
00394
00395 if( OP_find_opnd_use( op, OU_base ) < 0 )
00396 new_top = nt?TOP_prefetchntaxx:TOP_prefetcht0xx;
00397 else if( OP_find_opnd_use( op, OU_index ) >= 0 )
00398 new_top = nt?TOP_prefetchntax:TOP_prefetcht0x;
00399
00400 OP_Change_Opcode( new_op, new_top );
00401
00402 if( EBO_Trace_Data_Flow ){
00403 fprintf( TFile, "%sReplace L1 and L2 prefetch OPs ",EBO_trace_pfx );
00404 Print_OP_No_SrcLine(pred_op);
00405 Print_OP_No_SrcLine(op);
00406 fprintf( TFile,"%swith ",EBO_trace_pfx );
00407 Print_OP_No_SrcLine(new_op);
00408 }
00409
00410 Copy_WN_For_Memory_OP( new_op, op);
00411 if ( OP_volatile( op ) )
00412 Set_OP_volatile( new_op );
00413 OP_srcpos( new_op ) = OP_srcpos( op );
00414
00415 if( EBO_in_loop ){
00416 EBO_Copy_OP_omega( new_op, op );
00417 }
00418
00419 BB_Insert_Op_After( OP_bb(op), op, new_op );
00420 replaced = TRUE;
00421
00422 remove_op( opinfo );
00423 OP_Change_To_Noop(opinfo->in_op);
00424 opinfo->in_op = NULL;
00425 opinfo->in_bb = NULL;
00426
00427 break;
00428 }
00429
00430 return replaced;
00431 }
00432
00433
00434 BOOL
00435 combine_adjacent_loads(OP *op,
00436 EBO_TN_INFO **opnd_tninfo,
00437 EBO_OP_INFO *opinfo,
00438 INT64 offset_pred,
00439 INT64 offset_succ)
00440 {
00441
00442 return FALSE;
00443 }
00444
00445 static void
00446 Expand_Extract_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset,
00447 UINT bit_size,
00448 TN *tgt_tn, TN *src_tn, OPS *ops)
00449 {
00450 BOOL is_double = MTYPE_is_size_double(rtype);
00451 FmtAssert(MTYPE_bit_size(rtype) == MTYPE_bit_size(desc),
00452 ("Expand_Extract_Bits: Handle this case (1)"));
00453 UINT pos = (Target_Byte_Sex != Host_Byte_Sex)
00454 ? MTYPE_bit_size(desc)-bit_offset-bit_size : bit_offset;
00455 if (pos == 0 && bit_size <= 16 && ! MTYPE_signed(rtype)) {
00456 Build_OP(is_double?TOP_andi64:TOP_andi32, tgt_tn, src_tn,
00457 Gen_Literal_TN((1 << bit_size)-1, is_double?8:4), ops);
00458 return;
00459 }
00460
00461 TN* tmp1_tn = EBO_in_peep
00462 ? Build_Dedicated_TN (TN_register_class(tgt_tn),
00463 TN_register(tgt_tn), TN_size(tgt_tn))
00464 : Build_TN_Of_Mtype(rtype);
00465
00466 if (EBO_in_peep) {
00467
00468 Exp_COPY(tmp1_tn, src_tn, ops);
00469 src_tn = tmp1_tn;
00470 }
00471 ISA_REGISTER_CLASS rclass = ISA_REGISTER_CLASS_integer;
00472 INT reg_size = is_double ? 64 : 32;
00473
00474 TOP left_shift_op = is_double?TOP_shli64:TOP_shli32;
00475 INT left_shift_amt = reg_size - pos - bit_size;
00476
00477 if( left_shift_amt == 0 ){
00478 Build_OP( MTYPE_bit_size(desc) == 64 ? TOP_mov64 : TOP_mov32,
00479 tmp1_tn, src_tn, ops );
00480
00481 } else if (left_shift_amt > 0){
00482 Build_OP(left_shift_op, tmp1_tn, src_tn, Gen_Literal_TN(left_shift_amt, 4),
00483 ops);
00484 }
00485
00486 TOP right_shift_op = is_double?TOP_sari64:TOP_sari32;
00487 INT right_shift_amt = reg_size - bit_size;
00488 if (! MTYPE_signed(rtype))
00489 right_shift_op = is_double ? TOP_shri64: TOP_shri32;
00490
00491 if( right_shift_amt == 0 ){
00492 Build_OP( MTYPE_bit_size(desc) == 64 ? TOP_mov64 : TOP_mov32,
00493 tgt_tn, tmp1_tn, ops );
00494
00495 } else if (right_shift_amt > 0){
00496 Build_OP(right_shift_op, tgt_tn, tmp1_tn,
00497 Gen_Literal_TN(right_shift_amt, 4),
00498 ops);
00499 }
00500
00501 else if (left_shift_amt < 0 && right_shift_amt < 0) {
00502 if (left_shift_amt < right_shift_amt)
00503 Build_OP(right_shift_op, tgt_tn, src_tn,
00504 Gen_Literal_TN(right_shift_amt-left_shift_amt, 4),
00505 ops);
00506 else
00507 Build_OP(left_shift_op, tgt_tn, src_tn,
00508 Gen_Literal_TN(left_shift_amt-right_shift_amt, 4),
00509 ops);
00510 } else
00511 FmtAssert( FALSE, ("Expand_Extract_Bits: Handle this case (2)"));
00512 }
00513
00514 struct SIZE_EXT_INFO {
00515 mUINT8 src_size;
00516 mUINT8 dest_size;
00517 bool sign_ext;
00518 };
00519
00520 #define SET_SIZE_EXT_INFO(o,s,d,sign) \
00521 do { \
00522 (o)->src_size = s; \
00523 (o)->dest_size = d; \
00524 (o)->sign_ext = sign; \
00525 } while(0)
00526
00527
00528 static void Get_Size_Ext_Info( TOP top, SIZE_EXT_INFO* info )
00529 {
00530 switch( top ){
00531 case TOP_movsbl: SET_SIZE_EXT_INFO( info, 1, 4, true ); break;
00532 case TOP_movzbl: SET_SIZE_EXT_INFO( info, 1, 4, false ); break;
00533 case TOP_movswl: SET_SIZE_EXT_INFO( info, 2, 4, true ); break;
00534 case TOP_movzwl: SET_SIZE_EXT_INFO( info, 2, 4, false ); break;
00535 case TOP_movsbq: SET_SIZE_EXT_INFO( info, 1, 8, true ); break;
00536 case TOP_movzbq: SET_SIZE_EXT_INFO( info, 1, 8, false ); break;
00537 case TOP_movswq: SET_SIZE_EXT_INFO( info, 2, 8, true ); break;
00538 case TOP_movzwq: SET_SIZE_EXT_INFO( info, 2, 8, false ); break;
00539 case TOP_movslq: SET_SIZE_EXT_INFO( info, 4, 8, true ); break;
00540 case TOP_movzlq: SET_SIZE_EXT_INFO( info, 4, 8, false ); break;
00541
00542 case TOP_ld32_n32:
00543 case TOP_ld32:
00544 case TOP_ldx32:
00545 case TOP_ldxx32:
00546 case TOP_ld32_abs:
00547 SET_SIZE_EXT_INFO( info, 4, 4, false );
00548 break;
00549 case TOP_ld64:
00550 case TOP_ldx64:
00551 case TOP_ldxx64:
00552 case TOP_ld64_abs:
00553 case TOP_ld64_off:
00554 SET_SIZE_EXT_INFO( info, 8, 8, false );
00555 break;
00556 case TOP_ld8_32_n32:
00557 case TOP_ld8_32:
00558 case TOP_ldx8_32:
00559 case TOP_ldxx8_32:
00560 SET_SIZE_EXT_INFO( info, 1, 4, true );
00561 break;
00562 case TOP_ldu8_32_n32:
00563 case TOP_ldu8_32:
00564 case TOP_ldxu8_32:
00565 case TOP_ldxxu8_32:
00566 SET_SIZE_EXT_INFO( info, 1, 4, false );
00567 break;
00568 case TOP_ld8_abs:
00569 SET_SIZE_EXT_INFO( info, 1, 1, false );
00570 break;
00571 case TOP_ld16_32_n32:
00572 case TOP_ld16_32:
00573 case TOP_ldx16_32:
00574 case TOP_ldxx16_32:
00575 SET_SIZE_EXT_INFO( info, 2, 4, true );
00576 break;
00577 case TOP_ldu16_32_n32:
00578 case TOP_ldu16_32:
00579 case TOP_ldxu16_32:
00580 case TOP_ldxxu16_32:
00581 SET_SIZE_EXT_INFO( info, 2, 4, false );
00582 break;
00583 case TOP_ld16_abs:
00584 SET_SIZE_EXT_INFO( info, 2, 2, false );
00585 break;
00586 case TOP_ld8_64:
00587 case TOP_ldx8_64:
00588 case TOP_ldxx8_64:
00589 case TOP_ld8_64_off:
00590 SET_SIZE_EXT_INFO( info, 1, 8, true );
00591 break;
00592 case TOP_ldu8_64:
00593 case TOP_ldxu8_64:
00594 case TOP_ldxxu8_64:
00595 case TOP_ldu8_64_off:
00596 SET_SIZE_EXT_INFO( info, 1, 8, false );
00597 break;
00598 case TOP_ld16_64:
00599 case TOP_ldx16_64:
00600 case TOP_ldxx16_64:
00601 case TOP_ld16_64_off:
00602 SET_SIZE_EXT_INFO( info, 2, 8, true );
00603 break;
00604 case TOP_ldu16_64:
00605 case TOP_ldxu16_64:
00606 case TOP_ldxxu16_64:
00607 case TOP_ldu16_64_off:
00608 SET_SIZE_EXT_INFO( info, 2, 8, false );
00609 break;
00610 case TOP_ld32_64:
00611 case TOP_ldx32_64:
00612 case TOP_ldxx32_64:
00613 case TOP_ld32_64_off:
00614 SET_SIZE_EXT_INFO( info, 4, 8, true );
00615 break;
00616
00617 default:
00618 FmtAssert( FALSE, ("Get_Size_Ext_Info: NYI") );
00619 }
00620
00621 return;
00622 }
00623
00624
00625 BOOL
00626 delete_subset_mem_op(OP *op,
00627 EBO_TN_INFO **opnd_tninfo,
00628 EBO_OP_INFO *opinfo,
00629 INT64 offset_pred,
00630 INT64 offset_succ)
00631 {
00632 #if Is_True_On
00633 if (!(EBO_Opt_Mask & EBO_DELETE_SUBSET_MEM_OP)) return FALSE;
00634 #endif
00635 OP *pred_op = opinfo->in_op;
00636 BB *bb = OP_bb(op);
00637 INT opcount = OP_opnds(op);
00638 TN *pred_result = OP_store(pred_op)
00639 ? OP_opnd(pred_op, OP_find_opnd_use(pred_op, OU_storeval))
00640 : OP_result(pred_op,0);
00641 TN *succ_result = OP_store(op)
00642 ? OP_opnd(op, OP_find_opnd_use(op,OU_storeval))
00643 : OP_result(op,0);
00644 BOOL succ_is_subset = FALSE;
00645 INT byte_offset;
00646 OPS ops = OPS_EMPTY;
00647
00648 if (EBO_Trace_Data_Flow) {
00649 fprintf(TFile,"%ssubset OP in BB:%d ",EBO_trace_pfx,BB_id(bb));
00650 Print_OP_No_SrcLine(op);
00651 fprintf(TFile," Matches OP in BB:%d ",BB_id(opinfo->in_bb));
00652 Print_OP_No_SrcLine(pred_op);
00653 }
00654
00655 if ((Opt_Level < 2) && (bb != opinfo->in_bb)) {
00656
00657 return FALSE;
00658 }
00659
00660 if (!EBO_in_peep &&
00661 (bb != opinfo->in_bb) &&
00662 !TN_Is_Constant(pred_result) &&
00663 has_assigned_reg(pred_result)) {
00664 if (EBO_Trace_Data_Flow) {
00665 #pragma mips_frequency_hint NEVER
00666 fprintf(TFile,"%sShouldn't move dedicated register references across blocks.\n",
00667 EBO_trace_pfx);
00668 }
00669 return FALSE;
00670 }
00671
00672 const INT size_pred = CGTARG_Mem_Ref_Bytes(pred_op);
00673 const INT size_succ = CGTARG_Mem_Ref_Bytes(op);
00674 if (size_pred < size_succ) return FALSE;
00675
00676 if ((offset_pred <= offset_succ) &&
00677 ((offset_pred + size_pred) >= (offset_succ + size_succ))) {
00678 succ_is_subset = TRUE;
00679 }
00680
00681 if (!succ_is_subset) {
00682 return FALSE;
00683 }
00684
00685 byte_offset = offset_succ - offset_pred;
00686
00687 if (!OP_store(pred_op) || !OP_load(op)) {
00688
00689 return FALSE;
00690 }
00691
00692 if (byte_offset > 8) return FALSE;
00693
00694 if ((TN_register_class(pred_result) != ISA_REGISTER_CLASS_integer) ||
00695 (TN_register_class(succ_result) != ISA_REGISTER_CLASS_integer)) {
00696
00697 return FALSE;
00698 }
00699
00700 if (size_succ == 1 &&
00701 EBO_in_peep){
00702
00703 if (Is_Target_32bit()) {
00704 const REGISTER reg = TN_register(pred_result);
00705 const REGISTER_SET regs =
00706 REGISTER_SUBCLASS_members(ISA_REGISTER_SUBCLASS_m32_8bit_regs);
00707 if (!REGISTER_SET_MemberP(regs, reg))
00708 return FALSE;
00709 }
00710 }
00711
00712 if (EBO_Trace_Optimization) {
00713 #pragma mips_frequency_hint NEVER
00714 fprintf(TFile,"%sReplace subset load with left/right shifts\n",EBO_trace_pfx);
00715 }
00716
00717 if (offset_succ == offset_pred &&
00718 size_pred == size_succ) {
00719 TOP top = OP_code(op);
00720 if (TOP_is_load_ext(top) &&
00721 top != OP_code(pred_op))
00722
00723 Exp_COPY_Ext(top, OP_result(op, 0), OP_opnd(pred_op,0), &ops );
00724 else
00725 Exp_COPY( OP_result(op,0), OP_opnd(pred_op,0), &ops );
00726 OP_srcpos(OPS_first(&ops)) = OP_srcpos(op);
00727 BB_Insert_Ops_After(OP_bb(op), op, &ops);
00728 return TRUE;
00729 }
00730
00731
00732
00733
00734
00735 for( OP* next_op = OP_next(op); next_op != NULL; next_op = OP_next( next_op ) ){
00736 if( OP_reads_rflags( next_op ) )
00737 return FALSE;
00738
00739 if( TOP_is_change_rflags( OP_code(next_op) ) )
00740 break;
00741 }
00742
00743 INT bit_size = size_succ*8;
00744 INT succ_offset = (offset_succ - offset_pred);
00745 INT bit_offset = succ_offset*8;
00746 TYPE_ID rtype = MTYPE_UNKNOWN, desc = MTYPE_UNKNOWN;
00747
00748 if( size_pred == 1 )
00749 desc = MTYPE_I1;
00750 else if( size_pred == 2 )
00751 desc = MTYPE_I2;
00752 else if( size_pred == 4 )
00753 desc = MTYPE_I4;
00754 else if( size_pred == 8 )
00755 desc = MTYPE_I8;
00756 else
00757 FmtAssert( false, ("delete_subset_mem_op: NYI (1)"));
00758
00759 struct SIZE_EXT_INFO op_size_ext_info;
00760 Get_Size_Ext_Info( OP_code(op), &op_size_ext_info );
00761 const BOOL unsigned_op = !op_size_ext_info.sign_ext;
00762
00763 if (desc == MTYPE_I1) {
00764 if (unsigned_op)
00765 rtype = MTYPE_U1;
00766 else
00767 rtype = desc;
00768 } else if (desc == MTYPE_I2) {
00769 if (unsigned_op)
00770 rtype = MTYPE_U2;
00771 else
00772 rtype = desc;
00773 } else if (desc == MTYPE_I4) {
00774 if (unsigned_op)
00775 rtype = MTYPE_U4;
00776 else
00777 rtype = desc;
00778 } else {
00779 if (unsigned_op)
00780 rtype = MTYPE_U8;
00781 else
00782 rtype = desc;
00783 }
00784
00785 Expand_Extract_Bits (rtype, desc,
00786 bit_offset, bit_size,
00787 OP_result(op, 0), OP_opnd(pred_op, 0), &ops);
00788
00789 OP_srcpos(OPS_first(&ops)) = OP_srcpos(op);
00790 BB_Insert_Ops_After(OP_bb(op), op, &ops);
00791 return TRUE;
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801 BOOL
00802 delete_reload_across_dependency (OP *op,
00803 EBO_TN_INFO **opnd_tninfo,
00804 EBO_OP_INFO *opinfo,
00805 EBO_OP_INFO *intervening_opinfo)
00806 {
00807 return FALSE;
00808
00809 BB *bb = OP_bb(op);
00810 OPS ops = OPS_EMPTY;
00811 OP *pred_op = opinfo->in_op;
00812 OP *intervening_op = intervening_opinfo->in_op;
00813 TOP pred_opcode = OP_code(pred_op);
00814 TOP intervening_opcode = OP_code(intervening_op);
00815 INT pred_base_idx = OP_find_opnd_use(pred_op, OU_base);
00816 INT intervening_base_idx =
00817 OP_find_opnd_use(intervening_op, OU_base);
00818 INT size_pred;
00819 INT size_succ;
00820 INT size_intervening;
00821
00822 TN *pred_result;
00823 TN *intervening_result;
00824 TN *pred_index;
00825 TN *intervening_index;
00826 TN *predicate1;
00827 TN *predicate2;
00828
00829
00830 if (EBO_in_loop) return FALSE;
00831 if (EBO_in_peep) return FALSE;
00832
00833 if (EBO_Trace_Execution) {
00834 #pragma mips_frequency_hint NEVER
00835 fprintf(TFile,"%sEnter delete_reload_across_dependency.\n",EBO_trace_pfx);
00836 Print_OP_No_SrcLine(pred_op);
00837 Print_OP_No_SrcLine(intervening_op);
00838 Print_OP_No_SrcLine(op);
00839 }
00840
00841
00842 if ((pred_op == NULL) ||
00843 (intervening_op == NULL) ||
00844 !OP_load(op) ||
00845 !(OP_load(pred_op) || OP_store(pred_op)) ||
00846 !OP_store(intervening_op)) return FALSE;
00847
00848 pred_op = opinfo->in_op;
00849 intervening_op = intervening_opinfo->in_op;
00850
00851 if (OP_prefetch(op) ||
00852 OP_prefetch(pred_op) ||
00853 OP_prefetch(intervening_op)) return FALSE;
00854
00855 if (OP_unalign_mem(op) ||
00856 OP_unalign_mem(pred_op) ||
00857 OP_unalign_mem(intervening_op)) return FALSE;
00858
00859 size_succ = CGTARG_Mem_Ref_Bytes(op);
00860 size_pred = CGTARG_Mem_Ref_Bytes(pred_op);
00861 size_intervening = CGTARG_Mem_Ref_Bytes(intervening_op);
00862
00863 if ((size_succ != size_pred) ||
00864 (size_succ != size_intervening)) return FALSE;
00865
00866
00867 pred_result = OP_store(pred_op) ?
00868 OP_opnd(pred_op, OP_find_opnd_use(pred_op, OU_storeval))
00869 : OP_result(pred_op,0);
00870 intervening_result = OP_opnd(intervening_op,
00871 OP_find_opnd_use(intervening_op,OU_storeval));
00872
00873 if ((TN_register_class(intervening_result) !=
00874 TN_register_class(pred_result)) ||
00875 (TN_register_class(intervening_result) !=
00876 TN_register_class(OP_result(op,0)))) {
00877 if (EBO_Trace_Data_Flow) {
00878 #pragma mips_frequency_hint NEVER
00879 fprintf(TFile,"%sInter-register copies are not supported\n",
00880 EBO_trace_pfx);
00881 }
00882 return FALSE;
00883 }
00884
00885 if (TNs_Are_Equivalent( pred_result, intervening_result)) {
00886
00887
00888 Is_True( false, ("delete_reload_across_dependency: NYI (1)"));
00889 return TRUE;
00890 }
00891
00892
00893
00894
00895
00896 pred_index = OP_opnd(pred_op, pred_base_idx);
00897 intervening_index = OP_opnd(intervening_op, intervening_base_idx);
00898
00899
00900 if (!EBO_tn_available (bb, opinfo->actual_opnd[pred_base_idx]) ||
00901 !EBO_tn_available (bb, intervening_opinfo->actual_opnd[intervening_base_idx])) {
00902 if (EBO_Trace_Data_Flow) {
00903 #pragma mips_frequency_hint NEVER
00904 fprintf(TFile,"%sBase address not available for compare\n",
00905 EBO_trace_pfx);
00906 }
00907 return FALSE;
00908 }
00909
00910
00911
00912
00913
00914
00915 return TRUE;
00916 }
00917
00918
00919
00920
00921
00922 static BOOL
00923 Special_Store_Load_Sequence (OP *load_op,
00924 EBO_TN_INFO **load_actual_tninfo,
00925 EBO_TN_INFO **load_opnd_tninfo,
00926 EBO_OP_INFO *store_opinfo)
00927 {
00928 Is_True(OP_store(store_opinfo->in_op) && OP_load(load_op),
00929 ("Special_Store_Load_Sequence: not store-load sequence"));
00930
00931 INT storeval_idx = OP_find_opnd_use(store_opinfo->in_op, OU_storeval);
00932 Is_True(storeval_idx >= 0,
00933 ("Special_Store_Load_Sequence: invalid storeval index"));
00934 TN *storeval_tn = OP_opnd(store_opinfo->in_op, storeval_idx);
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944 if (TN_register_class(OP_result(load_op,0)) == ISA_REGISTER_CLASS_integer &&
00945 TN_register_class(storeval_tn) == ISA_REGISTER_CLASS_float &&
00946 TN_size(OP_result(load_op, 0)) == TN_size(storeval_tn)) {
00947 OP *store_op = store_opinfo->in_op;
00948 EBO_TN_INFO *storeval_tninfo = store_opinfo->actual_opnd[storeval_idx];
00949 if (storeval_tninfo != NULL &&
00950 storeval_tninfo->in_op != NULL &&
00951 OP_load(storeval_tninfo->in_op)) {
00952 INT i;
00953 OP *first_load_op = storeval_tninfo->in_op;
00954 EBO_OP_INFO *first_load_opinfo = storeval_tninfo->in_opinfo;
00955 Is_True(first_load_opinfo != NULL,
00956 ("Special_Store_Load_Sequence: opinfo NULL"));
00957
00958
00959
00960 TN *base_tn = NULL;
00961 TN *index_tn = NULL;
00962 TN *offset_tn = NULL;
00963 TN *scale_tn = NULL;
00964
00965 INT base_idx = TOP_Find_Operand_Use(OP_code(first_load_op), OU_base);
00966 INT index_idx = TOP_Find_Operand_Use(OP_code(first_load_op), OU_index);
00967 INT offset_idx = TOP_Find_Operand_Use(OP_code(first_load_op),OU_offset);
00968 INT scale_idx = TOP_Find_Operand_Use(OP_code(first_load_op), OU_scale);
00969
00970 EBO_TN_INFO *base_tninfo = NULL, *index_tninfo = NULL;
00971
00972 if (base_idx >= 0) {
00973 base_tn = OP_opnd(first_load_op, base_idx);
00974 base_tninfo = first_load_opinfo->actual_opnd[base_idx];
00975 if (base_tninfo == NULL ||
00976 !EBO_tn_available(OP_bb(load_op), base_tninfo))
00977 return FALSE;
00978 }
00979 if (index_idx >= 0) {
00980 index_tn = OP_opnd(first_load_op, index_idx);
00981 index_tninfo = first_load_opinfo->actual_opnd[index_idx];
00982 if (index_tninfo == NULL ||
00983 !EBO_tn_available(OP_bb(load_op), index_tninfo))
00984 return FALSE;
00985 }
00986 offset_tn = offset_idx >= 0 ? OP_opnd(first_load_op, offset_idx) : NULL;
00987 scale_tn = scale_idx >= 0 ? OP_opnd(first_load_op, scale_idx) : NULL;
00988
00989
00990 EBO_OP_INFO *opinfo = EBO_opinfo_table[first_load_opinfo->hash_index];
00991 Is_True(opinfo != NULL,
00992 ("Special_Store_Load_Sequence: OP hash table empty"));
00993 for ( ; opinfo != first_load_opinfo; opinfo = opinfo->same) {
00994 if (opinfo->in_op &&
00995 OP_store(opinfo->in_op) &&
00996 opinfo->in_op != store_op) {
00997 return FALSE;
00998 }
00999 }
01000
01001
01002
01003 {
01004 INT load_op_base_idx = TOP_Find_Operand_Use(OP_code(first_load_op),
01005 OU_base);
01006 INT load_op_index_idx = TOP_Find_Operand_Use(OP_code(first_load_op),
01007 OU_index);
01008 INT load_op_offset_idx = TOP_Find_Operand_Use(OP_code(first_load_op),
01009 OU_offset);
01010 INT load_op_scale_idx = TOP_Find_Operand_Use(OP_code(first_load_op),
01011 OU_scale);
01012 TN *load_op_base_tn = load_op_base_idx >= 0 ?
01013 OP_opnd(load_op, base_idx) : NULL;
01014 TN *load_op_index_tn = load_op_index_idx >= 0 ?
01015 OP_opnd(load_op, index_idx) : NULL;
01016 TN *load_op_offset_tn = load_op_offset_idx >= 0 ?
01017 OP_opnd(load_op, offset_idx) : NULL;
01018 TN *load_op_scale_tn = load_op_scale_idx >= 0 ?
01019 OP_opnd(load_op, scale_idx) : NULL;
01020
01021 if (load_op_base_tn == base_tn &&
01022 load_op_index_tn == index_tn &&
01023 (load_op_offset_tn == offset_tn ||
01024 (TN_has_value(load_op_offset_tn) && TN_has_value(offset_tn) &&
01025 TN_value(load_op_offset_tn) == TN_value(offset_tn))) &&
01026 (load_op_scale_tn == scale_tn ||
01027 (TN_has_value(load_op_scale_tn) && TN_has_value(scale_tn) &&
01028 TN_value(load_op_scale_tn) == TN_value(scale_tn)))) {
01029 return FALSE;
01030 }
01031 }
01032
01033
01034 OP *new_op = Compose_Mem_Op_And_Copy_Info(load_op, index_tn, offset_tn,
01035 scale_tn, base_tn,
01036 load_actual_tninfo);
01037
01038 BB_Insert_Op_After(OP_bb(load_op), load_op, new_op);
01039
01040
01041 if (base_tninfo != NULL)
01042 inc_ref_count(base_tninfo);
01043 if (index_tninfo != NULL)
01044 inc_ref_count(index_tninfo);
01045
01046
01047 INT idx;
01048 idx = TOP_Find_Operand_Use(OP_code(load_op), OU_base);
01049 if (idx >= 0 &&
01050 load_actual_tninfo[idx] != NULL) {
01051 dec_ref_count(load_actual_tninfo[idx]);
01052 }
01053
01054 idx = TOP_Find_Operand_Use(OP_code(load_op), OU_index);
01055 if (idx >= 0 &&
01056 load_actual_tninfo[idx] != NULL) {
01057 dec_ref_count(load_actual_tninfo[idx]);
01058 }
01059
01060 return TRUE;
01061 }
01062 }
01063 return FALSE;
01064 }
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 static
01075 BOOL
01076 delete_memory_op (OP *op,
01077 EBO_TN_INFO **actual_tninfo,
01078 EBO_TN_INFO **opnd_tninfo,
01079 EBO_OP_INFO *opinfo)
01080 {
01081 #if Is_True_On
01082 if (!(EBO_Opt_Mask & EBO_DELETE_MEMORY_OP)) return FALSE;
01083 #endif
01084 OPS ops = OPS_EMPTY;
01085 INT size_pred;
01086 INT size_succ;
01087
01088
01089
01090
01091
01092
01093
01094 ISA_REGISTER_CLASS state_rc = ISA_REGISTER_CLASS_UNDEFINED;
01095 if (state_rc != ISA_REGISTER_CLASS_UNDEFINED)
01096 {
01097 INT results = OP_results(op);
01098 for (UINT i = 0; i < results; i++)
01099 {
01100 TN *tn = OP_result(op, i);
01101 if (TN_is_register(tn) && (TN_register_class(tn) == state_rc))
01102 return FALSE;
01103 }
01104 }
01105
01106
01107
01108
01109
01110
01111 if (OP_prefetch(op))
01112 {
01113 if (EBO_Trace_Optimization) {
01114 fprintf(TFile,"%sRemove following Prefetch combination\n",EBO_trace_pfx);
01115 }
01116
01117 return TRUE;
01118 }
01119
01120
01121
01122
01123
01124 if (OP_prefetch(opinfo->in_op))
01125 {
01126 return FALSE;
01127 }
01128
01129
01130 if (OP_unalign_mem(op) || OP_unalign_mem(opinfo->in_op))
01131 return FALSE;
01132
01133 size_pred = CGTARG_Mem_Ref_Bytes(opinfo->in_op);
01134 size_succ = CGTARG_Mem_Ref_Bytes(op);
01135
01136
01137
01138
01139 if (OP_load(op) && OP_load(opinfo->in_op))
01140 {
01141
01142
01143 if (TN_register_class(OP_result(op,0)) !=
01144 TN_register_class(OP_result(opinfo->in_op, 0)))
01145 {
01146 if (EBO_Trace_Optimization)
01147 fprintf(TFile,"%sRegclass mismatch for Load - Load combination\n",
01148 EBO_trace_pfx);
01149
01150 return FALSE;
01151 }
01152
01153
01154
01155
01156 if (OP_code(op) != OP_code(opinfo->in_op))
01157 {
01158 if (EBO_Trace_Optimization)
01159 fprintf(TFile,"%sMtype mismatch for Load - Load combination\n",
01160 EBO_trace_pfx);
01161
01162 return FALSE;
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 if ((size_pred != size_succ) ||
01175 (OP_results(op) != OP_results(opinfo->in_op)) ||
01176 ( TN_size(OP_result(opinfo->in_op, 0)) != TN_size(OP_result(op, 0)) &&
01177 ( size_pred < 4 || size_succ < 4 ) ) )
01178 {
01179 if (EBO_Trace_Optimization)
01180 {
01181 fprintf(TFile,"%sSize mismatch for Load - Load combination: %d:%d %d:%d \n",
01182 EBO_trace_pfx,size_pred,size_succ,
01183 TN_size(OP_result(opinfo->in_op, 0)),TN_size(OP_result(op, 0)));
01184 }
01185
01186 return delete_subset_mem_op (op, opnd_tninfo, opinfo, 0, 0);
01187 }
01188
01189 if (!EBO_in_peep &&
01190 (OP_bb(op) != OP_bb(opinfo->in_op)) &&
01191 !TN_Is_Constant(OP_result(opinfo->in_op, 0)) &&
01192 has_assigned_reg(OP_result(opinfo->in_op, 0)))
01193 {
01194 if (EBO_Trace_Data_Flow)
01195 {
01196 fprintf(TFile,"%sShouldn't move dedicated register references across blocks.\n",
01197 EBO_trace_pfx);
01198 }
01199
01200 return FALSE;
01201 }
01202
01203
01204
01205 if (EBO_Trace_Optimization)
01206 {
01207 fprintf(TFile,"%sRemove Load - Load combination\n",EBO_trace_pfx);
01208 }
01209
01210 TOP top = OP_code(op);
01211 if (TOP_is_load_ext(top) &&
01212 top != OP_code(opinfo->in_op)) {
01213
01214 for (UINT i = 0; i < OP_results(op); i++)
01215 Exp_COPY_Ext(top, OP_result(op, i),
01216 OP_result(opinfo->in_op, i), &ops);
01217 } else {
01218 for (UINT i = 0; i < OP_results(op); i++)
01219 EBO_Exp_COPY(NULL, OP_result(op, i),
01220 OP_result(opinfo->in_op, i), &ops);
01221 }
01222
01223 if (EBO_in_loop)
01224 EBO_OPS_omega (&ops);
01225
01226 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
01227 return TRUE;
01228 }
01229
01230
01231
01232 else if (OP_load(op) && OP_store(opinfo->in_op))
01233 {
01234 if( OP_side_effects( opinfo->in_op ) ){
01235 if( EBO_Trace_Optimization )
01236 fprintf(TFile,
01237 "%sStore has side effects for Load - Store combination\n",
01238 EBO_trace_pfx);
01239
01240 return FALSE;
01241 }
01242
01243 INT storeval_idx = OP_find_opnd_use(opinfo->in_op,OU_storeval);
01244 if (storeval_idx < 0)
01245 {
01246 if (EBO_Trace_Optimization)
01247 fprintf(TFile,
01248 "%sStore value TN unknown for Load - Store combination\n",
01249 EBO_trace_pfx);
01250
01251 return FALSE;
01252 }
01253
01254 TN *storeval_tn = OP_opnd(opinfo->in_op, storeval_idx);
01255 const int size_storeval = CGTARG_Mem_Ref_Bytes(opinfo->in_op);
01256
01257
01258
01259
01260
01261
01262
01263
01264 if (TN_register_class(OP_result(op,0)) !=
01265 TN_register_class(storeval_tn))
01266 {
01267 if (Special_Store_Load_Sequence(op, actual_tninfo, opnd_tninfo, opinfo))
01268 return TRUE;
01269
01270 if (EBO_Trace_Data_Flow)
01271 fprintf(TFile,"%sRegclass mismatch for Store - Load combination\n",
01272 EBO_trace_pfx);
01273
01274 return FALSE;
01275 }
01276
01277 if (!EBO_in_peep &&
01278 (OP_bb(op) != OP_bb(opinfo->in_op)) &&
01279 !TN_Is_Constant(storeval_tn) &&
01280 has_assigned_reg(storeval_tn))
01281 {
01282 if (EBO_Trace_Data_Flow)
01283 fprintf(TFile,"%sShouldn't move dedicated register references across blocks.\n",
01284 EBO_trace_pfx);
01285
01286 return FALSE;
01287 }
01288
01289 if (TN_is_dedicated(storeval_tn) &&
01290 (TN_register(storeval_tn) == RCX || TN_register(storeval_tn) == RDX))
01291 {
01292 if (EBO_Trace_Data_Flow)
01293 fprintf(TFile,"%sShould not move special dedicated registers RCX and RDX.\n",
01294 EBO_trace_pfx);
01295 return FALSE;
01296 }
01297
01298
01299
01300
01301
01302 if (size_pred == size_succ)
01303 {
01304 if (size_storeval > size_succ)
01305 {
01306 if (EBO_Trace_Data_Flow)
01307 fprintf(TFile,"%sSize mismatch for Store - Load combination: %d %d %d\n",
01308 EBO_trace_pfx,size_pred,size_storeval,size_succ);
01309
01310 return delete_subset_mem_op (op, opnd_tninfo, opinfo, 0, 0);
01311 }
01312
01313 if (EBO_Trace_Optimization)
01314 fprintf(TFile,"%sRemove Store - Load combination\n",EBO_trace_pfx);
01315
01316 TOP top = OP_code(op);
01317 if (TOP_is_load_ext(top) &&
01318 top != OP_code(opinfo->in_op))
01319
01320 Exp_COPY_Ext(top, OP_result(op, 0), storeval_tn, &ops);
01321 else
01322 EBO_Exp_COPY(NULL, OP_result(op, 0), storeval_tn, &ops);
01323
01324 if (EBO_in_loop) {
01325 CG_LOOP_Init_Op(OPS_first(&ops));
01326 Set_OP_omega (OPS_first(&ops), 0, opinfo->actual_opnd[storeval_idx]->omega);
01327 }
01328
01329 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
01330 return TRUE;
01331 }
01332
01333
01334
01335 else
01336 {
01337 return delete_subset_mem_op (op, opnd_tninfo, opinfo, 0, 0);
01338 }
01339 }
01340
01341
01342
01343 else if (OP_store(op) && OP_store(opinfo->in_op) &&
01344 (OP_bb(op) == OP_bb(opinfo->in_op)))
01345 {
01346 if (size_pred != size_succ)
01347 return FALSE;
01348
01349 if (opinfo->op_must_not_be_removed)
01350 return FALSE;
01351
01352 if (EBO_Trace_Optimization)
01353 fprintf(TFile,"%sRemove Store - Store combination\n",EBO_trace_pfx);
01354
01355 remove_op (opinfo);
01356 OP_Change_To_Noop(opinfo->in_op);
01357 opinfo->in_op = NULL;
01358 opinfo->in_bb = NULL;
01359 return FALSE;
01360 }
01361
01362
01363
01364 else {
01365 if( EBO_Trace_Optimization ){
01366 fprintf( TFile, "Load - Store combination is not optimized\n" );
01367 }
01368 #if 0
01369 if( OP_load( opinfo->in_op ) &&
01370 OP_prev(op) == opinfo->in_op &&
01371 OP_result( opinfo->in_op, 0 ) == OP_opnd( op, 0 ) ){
01372 return TRUE;
01373 }
01374 #endif
01375 return FALSE;
01376 }
01377
01378 return FALSE;
01379 }
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 BOOL
01390 delete_duplicate_op (OP *op,
01391 EBO_TN_INFO **opnd_tninfo,
01392 EBO_OP_INFO *opinfo,
01393 EBO_TN_INFO **actual_tninfo)
01394 {
01395 #if Is_True_On
01396 if (!(EBO_Opt_Mask & EBO_DELETE_DUPLICATE_OP)) return FALSE;
01397 #endif
01398 INT resnum;
01399 OPS ops = OPS_EMPTY;
01400
01401
01402
01403 if (OP_icmp(op))
01404 return FALSE;
01405
01406 if (EBO_Trace_Data_Flow) {
01407 fprintf(TFile,"%sDuplicate OP in BB:%d ",EBO_trace_pfx,BB_id(OP_bb(op)));
01408 Print_OP_No_SrcLine(op);
01409 fprintf(TFile," Matches OP in BB:%d ",BB_id(opinfo->in_bb));
01410 Print_OP_No_SrcLine(opinfo->in_op);
01411 }
01412
01413
01414
01415 if ((Opt_Level < 2) && (OP_bb(op) != opinfo->in_bb))
01416 return FALSE;
01417
01418
01419
01420 if (OP_memory(op))
01421 {
01422 return delete_memory_op (op, actual_tninfo, opnd_tninfo, opinfo);
01423 }
01424 else
01425 {
01426
01427
01428
01429 if( TOP_is_change_rflags( OP_code(op) ) ){
01430 for( OP* next_op = OP_next(op); next_op != NULL; next_op = OP_next( next_op ) ){
01431 if( OP_reads_rflags( next_op ) )
01432 return FALSE;
01433
01434 if( TOP_is_change_rflags( OP_code(next_op) ) )
01435 break;
01436 }
01437 }
01438
01439
01440
01441
01442 TOP top = OP_code(op);
01443
01444
01445 for (resnum = 0; resnum < OP_results(op); resnum++) {
01446 if (TOP_is_load_ext(top) &&
01447 top != OP_code(opinfo->in_op) )
01448
01449 Exp_COPY_Ext(top, OP_result(op, resnum),
01450 OP_result(opinfo->in_op, resnum), &ops);
01451 else
01452 EBO_Exp_COPY(NULL, OP_result(op, resnum),
01453 OP_result(opinfo->in_op, resnum), &ops);
01454 }
01455
01456 if (EBO_in_loop)
01457 EBO_OPS_omega (&ops);
01458
01459 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
01460 return TRUE;
01461 }
01462
01463 return FALSE;
01464 }
01465
01466
01467
01468
01469
01470 static TOP TOP_with_Imm_Opnd( OP* op, int opnd, INT64 imm_val )
01471 {
01472 const TOP top = OP_code(op);
01473 const ISA_OPERAND_INFO* oinfo = ISA_OPERAND_Info(top);
01474 const ISA_OPERAND_VALTYP* vtype = ISA_OPERAND_INFO_Operand(oinfo, 1);
01475
01476 if( ISA_OPERAND_VALTYP_Is_Literal(vtype) )
01477 return TOP_UNDEFINED;
01478
01479
01480 if( !ISA_LC_Value_In_Class( imm_val, LC_simm32 ) )
01481 return TOP_UNDEFINED;
01482
01483 return CGTARG_Immed_To_Reg( top );
01484 }
01485
01486
01487
01488
01489 static BOOL
01490 Convert_Imm_Add (OP *op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo)
01491 {
01492 #if Is_True_On
01493 if (!(EBO_Opt_Mask & EBO_CONVERT_IMM_ADD)) return FALSE;
01494 #endif
01495 OP *new_op = NULL;
01496 TOP new_opcode;
01497 BOOL is_64bit = (TN_size(tnr) == 8);
01498 if (imm_val == 0) {
01499 if( Is_Target_32bit() ){
01500 for( OP* next_op = OP_next(op); next_op != NULL; next_op = OP_next( next_op ) ){
01501 if( OP_reads_rflags( next_op ) ){
01502 return FALSE;
01503 }
01504
01505 if( TOP_is_change_rflags( OP_code(next_op) ) )
01506 break;
01507 }
01508 }
01509
01510 new_opcode = is_64bit ? TOP_mov64 : TOP_mov32;
01511 new_op = Mk_OP(new_opcode, tnr, tn);
01512
01513 } else if (ISA_LC_Value_In_Class ( imm_val, LC_simm32)) {
01514 if ( OP_code(op) == TOP_addi32 || OP_code(op) == TOP_addi64 ||
01515 OP_code(op) == TOP_lea32 || OP_code(op) == TOP_lea64 )
01516 return FALSE;
01517 new_opcode = is_64bit ? TOP_addi64 : TOP_addi32;
01518 BOOL rflags_read = FALSE;
01519
01520
01521 for( OP* next_op = OP_next(op); next_op != NULL;
01522 next_op = OP_next( next_op ) ){
01523 if( OP_reads_rflags( next_op ) )
01524 rflags_read = TRUE;
01525 if( TOP_is_change_rflags( OP_code(next_op) ) )
01526 break;
01527 }
01528 if( !rflags_read && EBO_in_peep &&
01529 !TNs_Are_Equivalent(tnr,tn) )
01530 new_opcode = is_64bit ? TOP_lea64 : TOP_lea32;
01531 else if ( imm_val == 1 && CG_use_incdec &&
01532 TN_is_register(tnr) && TN_is_register(tn) &&
01533 TNs_Are_Equivalent(tnr,tn) )
01534 new_opcode = is_64bit ? TOP_inc64 : TOP_inc32;
01535 else if ( imm_val == -1 && CG_use_incdec &&
01536 TN_is_register(tnr) && TN_is_register(tn) &&
01537 TNs_Are_Equivalent(tnr,tn) )
01538 new_opcode = is_64bit ? TOP_dec64 : TOP_dec32;
01539
01540 if (new_opcode == OP_code(op) ||
01541 (rflags_read &&
01542 ((TOP_is_change_rflags( new_opcode ) &&
01543 !TOP_is_change_rflags( OP_code(op) )) ||
01544 (!TOP_is_change_rflags( new_opcode ) &&
01545 TOP_is_change_rflags( OP_code(op) )))))
01546 return FALSE;
01547
01548 if (new_opcode != TOP_inc32 && new_opcode != TOP_inc64 &&
01549 new_opcode != TOP_dec32 && new_opcode != TOP_dec64)
01550 new_op = Mk_OP(new_opcode, tnr, tn, Gen_Literal_TN(imm_val, 4));
01551 else
01552 new_op = Mk_OP(new_opcode, tnr, tn);
01553 } else {
01554 return FALSE;
01555 TN *src1 = Gen_Literal_TN(imm_val, TN_size(tnr));
01556 TN *tmp = Build_TN_Like(tnr);
01557 new_op = Mk_OP(TOP_ldc64, tmp, src1);
01558 BB_Insert_Op_After(OP_bb(op), op, new_op);
01559 op = new_op;
01560 new_opcode = is_64bit ? TOP_add64 : TOP_add32;
01561 if( EBO_in_peep ){
01562 FmtAssert( TNs_Are_Equivalent(tnr,tn), ("Convert_Imm_Add: NYI"));
01563 }
01564 new_op = Mk_OP(new_opcode, tnr, tn, tmp);
01565 }
01566 BB_Insert_Op_After(OP_bb(op), op, new_op);
01567 return TRUE;
01568 }
01569
01570
01571
01572
01573
01574
01575 BOOL
01576 Constant_Operand0 (OP *op,
01577 TN **opnd_tn,
01578 EBO_TN_INFO **opnd_tninfo)
01579 {
01580 #if Is_True_On
01581 if (!(EBO_Opt_Mask & EBO_CONSTANT_OPERAND0)) return FALSE;
01582 #endif
01583 TOP opcode = OP_code(op);
01584 INT o0_idx = 0;
01585 INT o1_idx = (OP_opnds(op) > 1) ? 1 : -1;
01586
01587
01588 if (OP_opnds(op) < 1)
01589 return FALSE;
01590
01591 if (EBO_Trace_Execution)
01592 {
01593 fprintf(TFile, "%sin BB:%d constant0 OP :- %s",
01594 EBO_trace_pfx, BB_id(OP_bb(op)),TOP_Name(OP_code(op)));
01595 for (UINT i = 0; i < OP_opnds(op); i++)
01596 {
01597 fprintf(TFile," ");
01598 Print_TN(opnd_tn[i],FALSE);
01599 }
01600 fprintf(TFile,"\n");
01601 }
01602
01603 TN *tn0 = opnd_tn[o0_idx];
01604 TN *tn1 = (o1_idx >= 0) ? opnd_tn[o1_idx] : NULL;
01605 TN *tnr = OP_has_result(op) ? OP_result(op,0) : NULL;
01606
01607
01608 if (TN_is_symbol(tn0))
01609 return FALSE;
01610
01611
01612
01613
01614
01615
01616
01617
01618 if (TOP_is_cond_move(opcode))
01619 return FALSE;
01620
01621
01622 FmtAssert(TN_Is_Constant(tn0) &&
01623 ((OP_opnds(op) > 2) || !tn1 || !TN_Is_Constant(tn1)),
01624 ("Constant_Operand0: Unexpected constant/non-constant operands"));
01625
01626 if (opcode == TOP_add32 ||
01627 opcode == TOP_add64 ||
01628 opcode == TOP_lea32 ||
01629 opcode == TOP_lea64)
01630 return Convert_Imm_Add(op, tnr, tn1, TN_value(tn0), opnd_tninfo[o1_idx]);
01631
01632 return FALSE;
01633 }
01634
01635
01636
01637
01638
01639 static BOOL Convert_Imm_And( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo )
01640 {
01641 #if Is_True_On
01642 if (!(EBO_Opt_Mask & EBO_CONVERT_IMM_AND)) return FALSE;
01643 #endif
01644 TOP new_top = TOP_UNDEFINED;
01645 OPS ops = OPS_EMPTY;
01646
01647
01648
01649 if( imm_val == 0xff ){
01650
01651 if (Is_Target_32bit() &&
01652 EBO_in_peep) {
01653 const REGISTER reg = TN_register(tn);
01654 const REGISTER_SET regs =
01655 REGISTER_SUBCLASS_members(ISA_REGISTER_SUBCLASS_m32_8bit_regs);
01656 Is_True(TN_register_class(tn) == ISA_REGISTER_CLASS_integer,
01657 ("Convert_Imm_And: TN not integer register class"));
01658 if (!REGISTER_SET_MemberP(regs, reg))
01659 return FALSE;
01660 }
01661
01662 new_top = TN_size(tnr) == 8 ? TOP_movzbq : TOP_movzbl;
01663
01664 } else if( imm_val == 0xffff ){
01665 new_top = TN_size(tnr) == 8 ? TOP_movzwq : TOP_movzwl;
01666
01667 } else if( imm_val == 0xffffffff && TN_size(tnr) != 8){
01668 new_top = TOP_mov32;
01669 }
01670
01671 if( new_top != TOP_UNDEFINED ){
01672 Build_OP( new_top, tnr, tn, &ops );
01673 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01674
01675 return TRUE;
01676 }
01677
01678
01679
01680 new_top = TOP_with_Imm_Opnd( op, 1, imm_val );
01681
01682 if( new_top == TOP_UNDEFINED )
01683 return FALSE;
01684
01685 Build_OP( new_top, tnr, tn,
01686 Gen_Literal_TN(imm_val,4),
01687 &ops );
01688 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01689
01690 return TRUE;
01691 }
01692
01693
01694 static BOOL Convert_Imm_Or( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo )
01695 {
01696 #if Is_True_On
01697 if (!(EBO_Opt_Mask & EBO_CONVERT_IMM_OR)) return FALSE;
01698 #endif
01699 OPS ops = OPS_EMPTY;
01700
01701 if( imm_val == 0x0 ){
01702 Exp_COPY( tnr, tn, &ops );
01703 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01704 return TRUE;
01705 }
01706
01707 const TOP new_top = TOP_with_Imm_Opnd( op, 1, imm_val );
01708 if( new_top == TOP_UNDEFINED )
01709 return FALSE;
01710
01711 Build_OP( new_top, tnr, tn,
01712 Gen_Literal_TN(imm_val,4),
01713 &ops );
01714 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01715
01716 return TRUE;
01717 }
01718
01719
01720 static BOOL Convert_Imm_Xor( OP* op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo )
01721 {
01722 #if Is_True_On
01723 if (!(EBO_Opt_Mask & EBO_CONVERT_IMM_XOR)) return FALSE;
01724 #endif
01725 OPS ops = OPS_EMPTY;
01726
01727 if( imm_val == 0x0 ){
01728 Exp_COPY( tnr, tn, &ops );
01729 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01730 return TRUE;
01731 }
01732
01733 if( imm_val == -1 ){
01734 Build_OP( TN_size(tnr) == 4 ? TOP_not32 : TOP_not64, tnr, tn, &ops );
01735 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01736 return TRUE;
01737 }
01738
01739 const TOP new_top = TOP_with_Imm_Opnd( op, 1, imm_val );
01740
01741 if( new_top == TOP_UNDEFINED )
01742 return FALSE;
01743
01744 Build_OP( new_top, tnr, tn,
01745 Gen_Literal_TN(imm_val,4),
01746 &ops );
01747
01748 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01749
01750 return TRUE;
01751 }
01752
01753
01754 static BOOL Convert_Imm_Cmp( OP* op, TN *tnr, TN *tn, INT64 imm_val,
01755 EBO_TN_INFO *tninfo )
01756 {
01757 #if Is_True_On
01758 if (!(EBO_Opt_Mask & EBO_CONVERT_IMM_CMP)) return FALSE;
01759 #endif
01760 const TOP new_top = TOP_with_Imm_Opnd( op, 1, imm_val );
01761
01762 if( new_top == TOP_UNDEFINED )
01763 return FALSE;
01764
01765 OPS ops = OPS_EMPTY;
01766 Build_OP( new_top, tnr, tn, Gen_Literal_TN(imm_val,4), &ops );
01767
01768 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01769
01770 return TRUE;
01771 }
01772
01773
01774
01775
01776
01777 static BOOL Convert_Imm_Mul( OP *op, TN *tnr, TN *tn, INT64 imm_val, EBO_TN_INFO *tninfo )
01778 {
01779 #if Is_True_On
01780 if (!(EBO_Opt_Mask & EBO_CONVERT_IMM_MUL)) return FALSE;
01781 #endif
01782 TN* tnr1 = ( OP_results(op) == 2 ) ? OP_result( op, 1 ) : NULL;
01783
01784 OP *new_op = NULL;
01785 const BOOL is_64bit = (TN_size(tnr) == 8);
01786 const TYPE_ID mtype = is_64bit ? MTYPE_I8 : MTYPE_I4;
01787 INT64 val = imm_val < 0 ? -imm_val : imm_val;
01788 OPS ops = OPS_EMPTY;
01789
01790 if( imm_val == 0 ){
01791 Exp_Immediate( tnr, Gen_Literal_TN(0,4), false, &ops );
01792 if( tnr1 != NULL ){
01793 Exp_Immediate( tnr1, Gen_Literal_TN(0,4), false, &ops );
01794 }
01795 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01796 return TRUE;
01797 }
01798
01799 if( imm_val == 1 ){
01800 Exp_COPY( tnr, tn, &ops );
01801 if( tnr1 != NULL ){
01802 Exp_Immediate( tnr1, Gen_Literal_TN(0,4), false, &ops );
01803 }
01804 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01805 return TRUE;
01806 }
01807
01808 if( tnr1 != NULL )
01809 return FALSE;
01810
01811 bool need_an_add = false;
01812
01813 if( val >= 2 &&
01814 ( (val-1) & (val-2) ) == 0 ){
01815 val--;
01816 need_an_add = true;
01817 }
01818
01819
01820
01821 if( ( val & ( val - 1 ) ) != 0 ){
01822 const TOP new_top = TOP_with_Imm_Opnd( op, 1, imm_val );
01823
01824 if( new_top == TOP_UNDEFINED )
01825 return FALSE;
01826
01827 Build_OP( new_top, tnr, tn,
01828 Gen_Literal_TN(imm_val,4),
01829 &ops );
01830 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01831
01832 return TRUE;
01833 }
01834
01835 if( TNs_Are_Equivalent(tnr, tn ) && need_an_add ){
01836 if( TN_register(tn) != REGISTER_UNDEFINED )
01837 return FALSE;
01838
01839 TN* tmp = Build_TN_Like( tn );
01840 Exp_COPY( tmp, tn, &ops );
01841 tn = tmp;
01842 }
01843
01844 int power = 0;
01845 while( val != 1 ){
01846 power++;
01847 val >>= 1;
01848 }
01849
01850 Expand_Shift( tnr, tn, Gen_Literal_TN( power, 4 ), mtype, shift_left, &ops );
01851
01852 if( need_an_add ){
01853 Expand_Add( tnr, tnr, tn, mtype, &ops );
01854 }
01855
01856 if( imm_val < 0 )
01857 Expand_Neg( tnr, tnr, mtype, &ops );
01858
01859 BB_Insert_Ops_After( OP_bb(op), op, &ops );
01860 return TRUE;
01861 }
01862
01863
01864
01865
01866
01867
01868 BOOL
01869 Constant_Operand1 (OP *op,
01870 TN **opnd_tn,
01871 EBO_TN_INFO **opnd_tninfo)
01872 {
01873 #if Is_True_On
01874 if (!(EBO_Opt_Mask & EBO_CONSTANT_OPERAND1)) return FALSE;
01875 #endif
01876 BB *bb = OP_bb(op);
01877 TOP opcode = OP_code(op);
01878 INT o0_idx = 0;
01879 INT o1_idx = (OP_opnds(op) > 1) ? 1 : -1;
01880
01881
01882 if (OP_opnds(op) < 1)
01883 return FALSE;
01884
01885 if (EBO_Trace_Execution)
01886 {
01887 fprintf(TFile, "%sin BB:%d constant1 OP :- %s",
01888 EBO_trace_pfx, BB_id(OP_bb(op)), TOP_Name(OP_code(op)));
01889 for (UINT i = 0; i < OP_opnds(op); i++)
01890 {
01891 fprintf(TFile," ");
01892 Print_TN(opnd_tn[i],FALSE);
01893 }
01894 fprintf(TFile,"\n");
01895 }
01896
01897 TN *tn0 = opnd_tn[o0_idx];
01898 TN *tn1 = opnd_tn[o1_idx];
01899 TN *tnr = OP_has_result(op) ? OP_result(op,0) : NULL;
01900
01901
01902 if (TN_is_symbol(tn1))
01903 return FALSE;
01904
01905
01906 if( o1_idx > 0 &&
01907 ( OP_find_opnd_use( op, OU_base ) == o1_idx ||
01908 OP_find_opnd_use( op, OU_index ) == o1_idx ) ){
01909 return FALSE;
01910 }
01911
01912
01913 FmtAssert(TN_Is_Constant(tn1) && ((OP_opnds(op) > 2) || !TN_Is_Constant(tn0)),
01914 ("Constant_Operand1: Unexpected constant/non-constant operands"));
01915
01916
01917
01918
01919 const INT64 imm_val = TN_value(tn1);
01920
01921 if( OP_iand( op ) )
01922 return Convert_Imm_And(op, tnr, tn0, imm_val, opnd_tninfo[o0_idx]);
01923
01924 if( OP_ior( op ) )
01925 return Convert_Imm_Or( op, tnr, tn0, imm_val, opnd_tninfo[o0_idx] );
01926
01927 if( OP_ixor( op ) )
01928 return Convert_Imm_Xor(op, tnr, tn0, imm_val, opnd_tninfo[o0_idx]);
01929
01930 if (opcode == TOP_add32 ||
01931 opcode == TOP_add64 ||
01932 opcode == TOP_lea32 ||
01933 opcode == TOP_lea64 )
01934 return Convert_Imm_Add(op, tnr, tn0, imm_val, opnd_tninfo[o0_idx]);
01935
01936 if( OP_imul( op ) )
01937 return Convert_Imm_Mul( op, tnr, tn0, imm_val, opnd_tninfo[o0_idx] );
01938
01939 if( OP_icmp( op ) )
01940 return Convert_Imm_Cmp( op, tnr, tn0, imm_val, opnd_tninfo[o0_idx] );
01941
01942
01943
01944
01945
01946 if (opnd_tninfo[o0_idx] == NULL)
01947 return FALSE;
01948
01949 OP *pred_op = opnd_tninfo[o0_idx]->in_op;
01950 if (pred_op == NULL)
01951 return FALSE;
01952
01953 TOP pred_opcode = OP_code(pred_op);
01954
01955
01956 if (OP_iadd(op) && OP_iadd(pred_op))
01957 {
01958 INT ptn0_idx = 0;
01959 INT ptn1_idx = 1;
01960 TN *ptn0 = OP_opnd(pred_op, ptn0_idx);
01961 TN *ptn1 = OP_opnd(pred_op, ptn1_idx);
01962
01963 if (TN_is_constant(ptn1) && !TN_is_symbol(ptn1))
01964 {
01965 EBO_OP_INFO *pred_opinfo = locate_opinfo_entry(opnd_tninfo[o0_idx]);
01966 EBO_TN_INFO *ptn0_tninfo = pred_opinfo->actual_opnd[ptn0_idx];
01967
01968 if (EBO_tn_available(bb, ptn0_tninfo))
01969 {
01970 const INT64 new_val = imm_val + TN_value(ptn1);
01971 if (Convert_Imm_Add(op, tnr, ptn0, new_val, ptn0_tninfo))
01972 {
01973 if (EBO_Trace_Optimization)
01974 fprintf(TFile,"\tcombine immediate adds\n");
01975
01976 return TRUE;
01977 }
01978 }
01979 }
01980 }
01981
01982 return FALSE;
01983 }
01984
01985
01986
01987
01988
01989
01990
01991
01992 BOOL
01993 Resolve_Conditional_Branch (OP *op, TN **opnd_tn)
01994 {
01995 #if Is_True_On
01996 if (!(EBO_Opt_Mask & EBO_RESOLVE_CONDITIONAL_BRANCH)) return FALSE;
01997 #endif
01998 if( TOP_is_ijump( OP_code(op) ) )
01999 return FALSE;
02000
02001 Is_True( false, ("Resolve_Conditional_Branch: NYI") );
02002 return FALSE;
02003 }
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014 BOOL
02015 Fold_Constant_Expression (OP *op,
02016 TN **opnd_tn,
02017 EBO_TN_INFO **opnd_tninfo)
02018 {
02019 #if Is_True_On
02020 if (!(EBO_Opt_Mask & EBO_FOLD_CONSTANT_EXPRESSION)) return FALSE;
02021 #endif
02022 TOP opcode = OP_code(op);
02023 TN *tnr = OP_result(op,0);
02024
02025 if (OP_opnds(op) == 0)
02026 return FALSE;
02027
02028
02029
02030 if (TN_register_class(tnr) != ISA_REGISTER_CLASS_integer)
02031 return FALSE;
02032
02033
02034
02035
02036 if( TOP_is_change_rflags( OP_code(op) ) ){
02037 for( OP* next_op = OP_next(op); next_op != NULL; next_op = OP_next( next_op ) ){
02038 if( OP_reads_rflags( next_op ) )
02039 return FALSE;
02040
02041 if( TOP_is_change_rflags( OP_code(next_op) ) )
02042 break;
02043 }
02044 }
02045
02046 if (EBO_Trace_Execution)
02047 {
02048 fprintf(TFile, "%sin BB:%d Constant OP :- %s ",
02049 EBO_trace_pfx, BB_id(OP_bb(op)),TOP_Name(opcode));
02050
02051 for (UINT i = 0; i < OP_opnds(op); i++)
02052 {
02053 fprintf(TFile," ");
02054 Print_TN(opnd_tn[i],TRUE);
02055 }
02056
02057 fprintf(TFile,"\n");
02058 }
02059
02060 TN *tn0 = opnd_tn[0];
02061 TN *tn1 = opnd_tn[1];
02062
02063 INT64 result_val;
02064 INT64 tn0_val, tn1_val;
02065 UINT64 tn0_uval, tn1_uval;
02066
02067 ST *result_sym = NULL;
02068 INT32 result_relocs;
02069
02070
02071
02072 if (TN_is_symbol(tn0))
02073 {
02074
02075 if ((OP_opnds(op) == 2) && TN_is_symbol(tn1))
02076 return FALSE;
02077
02078 tn0_uval = TN_offset(tn0);
02079 tn0_val = TN_offset(tn0);
02080 result_sym = TN_var(tn0);
02081 result_relocs = TN_relocs(tn0);
02082 }
02083 else
02084 {
02085 tn0_val = tn0_uval = TN_value(tn0);
02086 }
02087
02088 if (OP_opnds(op) == 1)
02089 {
02090 tn1_val = 0;
02091 tn1_uval = 0;
02092 }
02093 else if (TN_is_symbol(tn1))
02094 {
02095 tn1_uval = TN_offset(tn1);
02096 tn1_val = TN_offset(tn1);
02097 result_sym = TN_var(tn1);
02098 result_relocs = TN_relocs(tn1);
02099 }
02100 else
02101 {
02102 tn1_val = tn1_uval = TN_value(tn1);
02103 }
02104
02105
02106
02107 if (OP_opnds(op) > 2)
02108 return FALSE;
02109
02110
02111
02112 if (TOP_is_iadd(opcode))
02113 {
02114 result_val = tn0_val + tn1_val;
02115 if( TN_size(tnr) == 4 && Get_TN_Pair(tnr) == NULL )
02116 result_val = (INT32)result_val;
02117 goto Constant_Created;
02118 }
02119
02120 if (OP_opnds(op) == 2 && !TN_is_symbol(tn1))
02121 {
02122
02123
02124 if (opcode == TOP_sub32 || opcode == TOP_sub64 ||
02125 opcode == TOP_subi32 || opcode == TOP_subi64)
02126 {
02127 result_val = tn0_val - tn1_val;
02128 goto Constant_Created;
02129 }
02130
02131
02132
02133 if( opcode == TOP_imuli32 ||
02134 opcode == TOP_imuli64 ){
02135 result_val = tn0_val * tn1_val;
02136 if( TN_size(tnr) == 4 && Get_TN_Pair(tnr) == NULL )
02137 result_val = (INT32)result_val;
02138 goto Constant_Created;
02139 }
02140 }
02141
02142
02143
02144 if (opcode == TOP_and32 || opcode == TOP_and64 ||
02145 opcode == TOP_andi32 || opcode == TOP_andi64)
02146 {
02147 result_val = tn0_uval & tn1_uval;
02148 goto Constant_Created;
02149 }
02150 else if (opcode == TOP_or32 || opcode == TOP_or64 ||
02151 opcode == TOP_ori32 || opcode == TOP_ori64)
02152 {
02153 result_val = tn0_uval | tn1_uval;
02154 goto Constant_Created;
02155 }
02156 else if (opcode == TOP_xor32 || opcode == TOP_xor64 ||
02157 opcode == TOP_xori32 || opcode == TOP_xori64)
02158 {
02159 result_val = tn0_uval ^ tn1_uval;
02160 goto Constant_Created;
02161 }
02162
02163
02164
02165 if (opcode == TOP_shl32 || opcode == TOP_shli32 )
02166 {
02167 result_val = TRUNC_32(tn0_uval << tn1_uval);
02168 goto Constant_Created;
02169 }
02170
02171 if ( opcode == TOP_shl64 || opcode == TOP_shli64)
02172 {
02173 result_val = tn0_uval << tn1_uval;
02174 goto Constant_Created;
02175 }
02176
02177 else if (opcode == TOP_sar32 || opcode == TOP_sar64 ||
02178 opcode == TOP_sari32 || opcode == TOP_sari64)
02179 {
02180 result_val = tn0_val >> tn1_uval;
02181
02182
02183 if ((opcode == TOP_sar32 ||
02184 opcode == TOP_sari32) &&
02185 (tn0_val & 0x80000000)) {
02186 result_val |= (~0 << (31 - tn1_uval)) & 0xffffffff;
02187 }
02188 goto Constant_Created;
02189 }
02190 else if (opcode == TOP_shr32 || opcode == TOP_shri32)
02191 {
02192 result_val = TRUNC_32(tn0_val) >> tn1_uval;
02193 goto Constant_Created;
02194 }
02195 else if (opcode == TOP_shr64 || opcode == TOP_shri64)
02196 {
02197 result_val = (UINT64)tn0_val >> tn1_uval;
02198 goto Constant_Created;
02199 }
02200
02201 return FALSE;
02202
02203
02204
02205 Constant_Created:
02206
02207 OPS ops = OPS_EMPTY;
02208 TN *tnc;
02209
02210 if (result_sym != NULL)
02211 {
02212
02213
02214 if( !ISA_LC_Value_In_Class(result_val, LC_simm32) )
02215 return FALSE;
02216
02217 tnc = Gen_Symbol_TN(result_sym, result_val, result_relocs);
02218 }
02219 else
02220 {
02221 const int size = Get_TN_Pair(tnr) == NULL ? TN_size(tnr) : 8;
02222 tnc = Gen_Literal_TN(result_val, size);
02223 }
02224
02225 Expand_Immediate (tnr, tnc, OP_result_is_signed(op,0), &ops);
02226
02227
02228
02229
02230
02231
02232 if (OP_next(OPS_first(&ops)) != NULL)
02233 return FALSE;
02234
02235 if (EBO_in_loop)
02236 EBO_OPS_omega (&ops);
02237
02238 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
02239
02240 if (EBO_Trace_Optimization)
02241 {
02242 fprintf(TFile, "%sin BB:%d Redefine ",
02243 EBO_trace_pfx, BB_id(OP_bb(op)));
02244 Print_TN(tnr,TRUE);
02245 fprintf(TFile," with load of ");
02246 Print_TN(tnc,FALSE);
02247 fprintf(TFile, "\n");
02248 }
02249
02250 return TRUE;
02251 }
02252
02253
02254 static TN *_tn_swap_tmp;
02255 static EBO_TN_INFO *_tninfo_swap_tmp;
02256
02257
02258
02259
02260 static EBO_OP_INFO *
02261 imm_sll (EBO_OP_INFO *sll_opinfo, INT32 *shift =NULL)
02262 {
02263 if (!sll_opinfo)
02264 return NULL;
02265
02266 OP *sll = sll_opinfo->in_op;
02267 TOP top = OP_code(sll);
02268 if (top != TOP_shl32 &&
02269 top != TOP_shl64 )
02270 return NULL;
02271
02272 TN *imm = OP_opnd(sll, 1);
02273 if (!TN_has_value(imm))
02274 return NULL;
02275
02276 if (shift)
02277 *shift = TN_value(imm);
02278
02279 return sll_opinfo;
02280 }
02281
02282
02283
02284
02285 static EBO_OP_INFO *
02286 imm_sra (EBO_OP_INFO *sar_opinfo, INT32 *shift =NULL)
02287 {
02288 if (!sar_opinfo)
02289 return NULL;
02290
02291 OP *sar = sar_opinfo->in_op;
02292 TOP top = OP_code(sar);
02293 if( top != TOP_sar32 &&
02294 top != TOP_sar64 )
02295 return NULL;
02296
02297 TN *imm = OP_opnd(sar, 1);
02298 if (!TN_has_value(imm))
02299 return NULL;
02300
02301 if (shift)
02302 *shift = TN_value(imm);
02303
02304 return sar_opinfo;
02305 }
02306
02307
02308
02309
02310 static EBO_OP_INFO *
02311 imm_srl (EBO_OP_INFO *srl_opinfo, INT32 *shift =NULL)
02312 {
02313 if (!srl_opinfo)
02314 return NULL;
02315
02316 OP *srl = srl_opinfo->in_op;
02317 TOP top = OP_code(srl);
02318 if (top != TOP_shl32 &&
02319 top != TOP_shl64 )
02320 return NULL;
02321
02322 TN *imm = OP_opnd(srl, 1);
02323 if (!TN_has_value(imm))
02324 return NULL;
02325
02326 if (shift)
02327 *shift = TN_value(imm);
02328
02329 return srl_opinfo;
02330 }
02331
02332
02333
02334
02335 static EBO_OP_INFO *
02336 index_add (EBO_OP_INFO *add_opinfo, TN *base, TN **index =NULL)
02337 {
02338 if (!add_opinfo)
02339 return NULL;
02340
02341 OP *add = add_opinfo->in_op;
02342 TOP top = OP_code(add);
02343 if (! TOP_is_iadd(top))
02344 return NULL;
02345
02346 TN *imm_tn = OP_opnd(add, 1);
02347 TN *other_tn = OP_opnd(add, 0);
02348
02349 if (imm_tn == base) {
02350 if (index)
02351 *index = other_tn;
02352 } else
02353 if (index)
02354 *index = imm_tn;
02355
02356 return add_opinfo;
02357 }
02358
02359
02360
02361
02362 static EBO_OP_INFO *
02363 decode_and (EBO_OP_INFO *and_opinfo, TN **left, TN **right)
02364 {
02365 if (!and_opinfo)
02366 return NULL;
02367
02368 OP *andd = and_opinfo->in_op;
02369 TOP top = OP_code(andd);
02370 if (top != TOP_and32 &&
02371 top != TOP_and64)
02372 return NULL;
02373
02374 TN *left_tn = OP_opnd(andd, 0);
02375 TN *right_tn = OP_opnd(andd, 1);
02376 if (!TN_is_register(left_tn) || !TN_is_register(right_tn))
02377 return NULL;
02378
02379 if (left)
02380 *left = left_tn;
02381 if (right)
02382 *right = right_tn;
02383
02384 return and_opinfo;
02385 }
02386
02387
02388
02389
02390
02391
02392 INT EBO_Copy_Operand (OP *op)
02393 {
02394 INT opnd;
02395
02396 if (OP_copy(op)) {
02397 TOP topcode = OP_code(op);
02398 if (topcode == TOP_add32 || topcode == TOP_add64 ||
02399 topcode == TOP_or32 || topcode == TOP_or64 ||
02400 topcode == TOP_mov32 || topcode== TOP_mov64 )
02401 return 0;
02402 }
02403
02404 opnd = CGTARG_Copy_Operand(op);
02405 if (opnd >= 0) {
02406 return opnd;
02407 }
02408
02409 return -1;
02410 }
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421 static OP *
02422 cmovable_op (BB *bb, UINT *len, TN *no_define,
02423 BS *in_defined_tns, BS **out_defined_tns)
02424 {
02425 *len = BB_length(bb);
02426 if (*len == 0)
02427 return NULL;
02428
02429 OP *jump = BB_xfer_op(bb);
02430 if (jump && ((*len == 1) || (OP_code(jump) != TOP_jmp)))
02431 return NULL;
02432
02433
02434
02435
02436 work_gtn_set = GTN_SET_ClearD(work_gtn_set);
02437
02438 OP *last = NULL;
02439 for (OP *op = BB_first_op(bb); op; op = OP_next(op))
02440 {
02441 if (OP_xfer(op))
02442 break;
02443
02444 last = op;
02445
02446 if (!CGTARG_Can_Be_Speculative(op))
02447 return NULL;
02448
02449 for (UINT i = 0; i < OP_results(op); i++)
02450 {
02451 TN *res = OP_result(op, i);
02452 if (TN_is_register(res) && !TN_is_const_reg(res))
02453 {
02454 if (TN_is_global_reg(res))
02455 work_gtn_set = GTN_SET_Union1D(work_gtn_set, res, work_pool);
02456
02457 if (out_defined_tns)
02458 *out_defined_tns = BS_Union1D(*out_defined_tns, TN_number(res), work_pool);
02459 }
02460 }
02461
02462 if (in_defined_tns)
02463 {
02464 for (UINT i = 0; i < OP_opnds(op); i++)
02465 {
02466 TN *opnd = OP_opnd(op, i);
02467 if (TN_is_register(opnd) && BS_MemberP(in_defined_tns, TN_number(opnd)))
02468 return NULL;
02469 }
02470 }
02471 }
02472
02473
02474
02475
02476
02477 if (!last ||
02478 (OP_results(last) != 1) ||
02479 ((no_define != NULL) && GTN_SET_MemberP(work_gtn_set, no_define)))
02480 return NULL;
02481
02482 work_gtn_set = GTN_SET_Difference1D(work_gtn_set, OP_result(last, 0));
02483 if (GTN_SET_IntersectsP(work_gtn_set, BB_live_out(bb)))
02484 return NULL;
02485
02486 if (out_defined_tns)
02487 *out_defined_tns = BS_Difference1D(*out_defined_tns,
02488 TN_number(OP_result(last, 0)));
02489
02490 if (OP_same_res(last))
02491 return NULL;
02492
02493 return last;
02494 }
02495
02496 static BOOL is_live_tn(OP *current_op, TN *current_tn)
02497 {
02498 OP *op;
02499 Is_True(GRA_LIVE_Phase_Invoked, ("Bad call to is_live_tn"));
02500 BOOL is_live = tn_has_live_def_into_BB(current_tn, OP_bb(current_op));
02501 BOOL past_current_op = FALSE;
02502
02503 FOR_ALL_BB_OPs(OP_bb(current_op), op) {
02504 INT num_opnds = OP_opnds(op);
02505 INT num_results = OP_results(op);
02506 if (op == current_op) {
02507 past_current_op = TRUE;
02508 if (!is_live)
02509 return FALSE;
02510 }
02511 if (past_current_op) {
02512 for (int opndnum = 0; opndnum < num_opnds; opndnum++) {
02513 if (tn_registers_identical(current_tn, OP_opnd(op,opndnum)))
02514 return TRUE;
02515 }
02516 }
02517 for (int resnum = 0; resnum < num_results; resnum++) {
02518 if (tn_registers_identical(current_tn, OP_result(op,resnum))) {
02519 if (past_current_op && !OP_cond_def(op))
02520 return FALSE;
02521 else
02522 is_live = TRUE;
02523 }
02524 }
02525 }
02526 Is_True(past_current_op && is_live, ("Bad call to is_live_tn"));
02527 return GTN_SET_MemberP(BB_live_out(OP_bb(current_op)), current_tn);
02528 }
02529
02530
02531 static BOOL test_is_replaced( OP* alu_op, OP* test_op, const EBO_TN_INFO* tninfo );
02532
02533
02534 static BOOL move_ext_is_replaced( OP* op, const EBO_TN_INFO* tninfo )
02535 {
02536 struct SIZE_EXT_INFO op_size_ext_info;
02537 struct SIZE_EXT_INFO pred_size_ext_info;
02538
02539 #if Is_True_On
02540 if (!(EBO_Opt_Mask & EBO_MOVE_EXT_IS_REPLACED)) return FALSE;
02541 #endif
02542 OP* pred = tninfo == NULL ? NULL : tninfo->in_op;
02543
02544 if( pred == NULL )
02545 return FALSE;
02546
02547 const TOP pred_top = OP_code(pred);
02548
02549 if( !TOP_is_move_ext( pred_top ) &&
02550 !TOP_is_load( pred_top ) ){
02551 return FALSE;
02552 }
02553
02554
02555
02556
02557
02558
02559 if (TOP_is_move_ext(OP_code(op)) &&
02560 (TOP_is_move_ext(pred_top) || TOP_is_load_ext(pred_top))) {
02561 Get_Size_Ext_Info(pred_top, &pred_size_ext_info );
02562 Get_Size_Ext_Info(OP_code(op), &op_size_ext_info );
02563 if (op_size_ext_info.dest_size >= pred_size_ext_info.dest_size &&
02564 op_size_ext_info.src_size >= pred_size_ext_info.src_size &&
02565 op_size_ext_info.sign_ext == FALSE &&
02566 pred_size_ext_info.sign_ext == FALSE) {
02567
02568
02569 OPS ops = OPS_EMPTY;
02570 Exp_COPY(OP_result(op, 0), OP_opnd(op, 0), &ops);
02571 BB_Insert_Ops(OP_bb(op), op, &ops, FALSE);
02572 }
02573 }
02574
02575 if( TOP_is_load( pred_top ) &&
02576 OP_find_opnd_use( pred, OU_index ) >= 0 )
02577 return FALSE;
02578
02579 Get_Size_Ext_Info( pred_top, &pred_size_ext_info );
02580 Get_Size_Ext_Info( OP_code(op), &op_size_ext_info );
02581
02582 if( pred_size_ext_info.sign_ext &&
02583 !op_size_ext_info.sign_ext ){
02584 return FALSE;
02585 }
02586
02587
02588
02589 OP* new_op = NULL;
02590 OPS ops = OPS_EMPTY;
02591
02592 if( TOP_is_move_ext( pred_top ) ){
02593 #if 0
02594 if( ( OP_bb( pred ) != OP_bb( op ) ) &&
02595 has_assigned_reg( OP_opnd(pred,0) ) )
02596 return FALSE;
02597 #endif
02598 EBO_TN_INFO* opnd_info = get_tn_info( OP_opnd(pred,0) );
02599 if( opnd_info != NULL && opnd_info->sequence_num > tninfo->sequence_num )
02600 return FALSE;
02601
02602 const TYPE_ID mtype = op_size_ext_info.dest_size == 4 ? MTYPE_I4 : MTYPE_I8;
02603
02604
02605
02606
02607
02608 const bool sign_ext =
02609 ( op_size_ext_info.src_size <= pred_size_ext_info.src_size ) ?
02610 op_size_ext_info.sign_ext : pred_size_ext_info.sign_ext;
02611
02612 const INT size =
02613 ( op_size_ext_info.src_size <= pred_size_ext_info.src_size ) ?
02614 op_size_ext_info.src_size : pred_size_ext_info.src_size;
02615
02616 Expand_Convert_Length( OP_result( op, 0 ), OP_opnd( pred, 0 ),
02617 Gen_Literal_TN( 8*size, 4 ),
02618 mtype,
02619 sign_ext,
02620 &ops );
02621
02622 new_op = OPS_first( &ops );
02623
02624 if( ( OP_code(new_op) == OP_code(op) ) &&
02625 TNs_Are_Equivalent( OP_result(pred,0), OP_opnd(pred,0) ) )
02626 return FALSE;
02627
02628
02629 } else if( TOP_is_load( pred_top ) ){
02630 return FALSE;
02631
02632 if( !TNs_Are_Equivalent( OP_result(op,0), OP_opnd(op,0) ) )
02633 return FALSE;
02634
02635 if( OP_find_opnd_use( pred, OU_index ) >= 0 )
02636 return FALSE;
02637
02638
02639 EBO_TN_INFO* opnd_info = get_tn_info( OP_result(pred,0) );
02640 if( opnd_info->reference_count > 1 )
02641 return FALSE;
02642
02643
02644 opnd_info = get_tn_info( OP_opnd( pred, 0 ) );
02645 if( opnd_info != NULL && opnd_info->sequence_num > tninfo->sequence_num )
02646 return FALSE;
02647
02648 EBO_OP_INFO* pred_opinfo = locate_opinfo_entry((EBO_TN_INFO*)tninfo);
02649 FmtAssert( pred_opinfo->in_op == pred, ("move_ext_is_replaced: NYI (1)") );
02650
02651 TOP new_top = TOP_UNDEFINED;
02652
02653 if( pred_size_ext_info.src_size == 1 ){
02654 if( op_size_ext_info.dest_size == 4 )
02655 new_top = pred_size_ext_info.sign_ext ? TOP_ld8_32 : TOP_ldu8_32;
02656 else if( op_size_ext_info.dest_size == 8 )
02657 new_top = pred_size_ext_info.sign_ext ? TOP_ld8_64 : TOP_ldu8_64;
02658
02659 } else if( pred_size_ext_info.src_size == 2 ){
02660 if( op_size_ext_info.dest_size == 4 )
02661 new_top = pred_size_ext_info.sign_ext ? TOP_ld16_32 : TOP_ldu16_32;
02662 else if( op_size_ext_info.dest_size == 8 )
02663 new_top = pred_size_ext_info.sign_ext ? TOP_ld16_64 : TOP_ldu16_64;
02664
02665 } else if( pred_size_ext_info.src_size == 4 ){
02666 if( op_size_ext_info.dest_size == 8 ){
02667 FmtAssert( op_size_ext_info.sign_ext,("move_ext_is_replaced: NYI (2)"));
02668 new_top = TOP_ld32_64;
02669 }
02670 }
02671
02672 Is_True( new_top != TOP_UNDEFINED, ("move_ext_is_replaced: NYI (3)") );
02673
02674 new_op = Mk_OP( new_top,
02675 OP_result( op, 0 ),
02676 OP_opnd( pred, 0 ),
02677 OP_opnd( pred, 1 ) );
02678
02679 remove_op( pred_opinfo );
02680 OP_Change_To_Noop( pred );
02681 }
02682
02683 if( new_op == NULL )
02684 return FALSE;
02685
02686 Set_OP_unrolling( new_op, OP_unrolling(op) );
02687 Set_OP_orig_idx( new_op, OP_map_idx(op) );
02688 Set_OP_unroll_bb( new_op, OP_unroll_bb(op) );
02689
02690 Copy_WN_For_Memory_OP( new_op, pred );
02691 if ( OP_volatile( pred ) )
02692 Set_OP_volatile( new_op );
02693 OP_srcpos( new_op ) = OP_srcpos( op );
02694 BB_Insert_Op_After( OP_bb(op), op, new_op );
02695
02696 if( EBO_Trace_Data_Flow ){
02697 #pragma mips_frequency_hint NEVER
02698 fprintf( TFile, "Special_Sequence merges " );
02699 Print_OP_No_SrcLine( pred );
02700 fprintf( TFile, " with " );
02701 Print_OP_No_SrcLine( op );
02702
02703 fprintf( TFile, " new op " );
02704 Print_OP_No_SrcLine( new_op );
02705 }
02706
02707 return TRUE;
02708 }
02709
02710 BOOL Delete_Unwanted_Prefetches ( OP* op )
02711 {
02712 #if Is_True_On
02713 if (!(EBO_Opt_Mask & EBO_DELETE_UNWANTED_PREFETCHES)) return FALSE;
02714 #endif
02715 WN *mem_wn = Get_WN_From_Memory_OP(op);
02716 TN* base;
02717
02718 OP *incr = NULL;
02719 OP *as_opnd = NULL;
02720 OP *as_result = NULL;
02721 OP *load_store = NULL;
02722 BB* bb = OP_bb( op );
02723 OP *next = BB_first_op( bb );
02724
02725 INT prefetch_offset = WN_offset(mem_wn);
02726
02727 #ifdef KEY
02728
02729 if(PF_GET_KEEP_ANYWAY(WN_prefetch_flag(mem_wn)))
02730 return FALSE;
02731 #endif
02732 if (OP_find_opnd_use( op, OU_base ) >= 0)
02733 base = OP_opnd( op, OP_find_opnd_use( op, OU_base ));
02734 else
02735 return FALSE;
02736
02737 while (next && !incr) {
02738
02739 if ((OP_code(next) == TOP_addi32 || OP_code(next) == TOP_addi64)) {
02740 if (OP_results(next) != 0 && OP_result(next, 0) == base &&
02741 OP_opnd(next, 0) == base)
02742 incr = next;
02743 else if (OP_results(next) != 0 && OP_result(next, 0) == base)
02744 as_result = next;
02745 else if (OP_opnd(next, 0) == base)
02746 as_opnd = next;
02747 }
02748
02749 next = OP_next(next);
02750 }
02751
02752 if (!incr) {
02753 if (!as_result && !as_opnd)
02754 return TRUE;
02755 else if (as_result)
02756 incr = as_result;
02757 else
02758 incr = as_opnd;
02759 }
02760
02761 INT delta_base = TN_value(OP_opnd(incr, 1));
02762
02763 next = BB_first_op( bb );
02764 while (next && !load_store) {
02765 if ((OP_memory(next) || OP_load_exe(next)) &&
02766 OP_find_opnd_use( next, OU_base ) >= 0 &&
02767 base == OP_opnd( next, OP_find_opnd_use( next, OU_base ))) {
02768 INT load_store_offset =
02769 TN_value(OP_opnd( next, OP_find_opnd_use( next, OU_offset )));
02770 INT prefetch_ahead = LNO_Prefetch_Ahead;
02771 INT Cache_Line_Size = 64 ;
02772 INT leeway = 3;
02773 if ((delta_base - prefetch_offset +load_store_offset) <
02774 (Cache_Line_Size*(prefetch_ahead+ leeway)))
02775 load_store = next;
02776 }
02777
02778 next = OP_next(next);
02779 }
02780
02781 if (!load_store)
02782 return TRUE;
02783
02784 return FALSE;
02785 }
02786
02787
02788
02789
02790
02791 BOOL Special_Sequence( OP *op, TN **opnd_tn, EBO_TN_INFO **opnd_tninfo )
02792 {
02793 #if Is_True_On
02794 if (!(EBO_Opt_Mask & EBO_SPECIAL_SEQUENCE)) return FALSE;
02795 #endif
02796 const TOP top = OP_code( op );
02797
02798 if( top == TOP_lea64 ||
02799 top == TOP_leax64 ||
02800 top == TOP_leaxx64 ){
02801 if( EBO_Merge_Memory_Addr( op, opnd_tn, opnd_tninfo, opnd_tninfo ) ){
02802 return TRUE;
02803 }
02804 }
02805
02806 if( OP_idiv(op) ){
02807
02808
02809
02810
02811
02812
02813 const TN* divisor = OP_opnd( op, 2 );
02814 const TN* dividend = OP_opnd( op, 0 );
02815
02816 if( divisor == dividend ){
02817 TN* quotient = OP_result( op, 0 );
02818 TN* remainder = OP_result( op , 1 );
02819
02820
02821 OPS ops = OPS_EMPTY;
02822 Expand_Immediate( quotient, Gen_Literal_TN( 1, 4 ), false, &ops );
02823 Expand_Immediate( remainder, Gen_Literal_TN( 0, 4 ), false, &ops );
02824 BB_Insert_Ops_After( OP_bb(op), op, &ops );
02825
02826 OP_srcpos(OPS_first(&ops)) = OP_srcpos(op);
02827 OP_srcpos(OPS_last(&ops)) = OP_srcpos(op);
02828
02829 if( EBO_Trace_Data_Flow ){
02830 fprintf( TFile, "Special_Sequence replaces " );
02831 Print_OP_No_SrcLine(op);
02832 fprintf( TFile, "with " );
02833 Print_OPS_No_SrcLines( (const OPS*)&ops);
02834 }
02835
02836 return TRUE;
02837 }
02838 }
02839
02840
02841
02842 if( TOP_is_move_ext( top ) ){
02843 if( move_ext_is_replaced( op, opnd_tninfo[0] ) )
02844 return TRUE;
02845 }
02846
02847 if( ( top == TOP_test32 || top == TOP_test64 ) &&
02848 TNs_Are_Equivalent( OP_opnd(op,0), OP_opnd(op,1) ) ){
02849
02850 const EBO_TN_INFO* tninfo = opnd_tninfo[0];
02851 OP* alu_op = tninfo == NULL ? NULL : tninfo->in_op;
02852
02853 if( test_is_replaced( alu_op, op, tninfo ) )
02854 return TRUE;
02855
02856 } else if ( top == TOP_movslq ) {
02857 const EBO_TN_INFO* tninfo = opnd_tninfo[0];
02858 OP* alu_op = tninfo == NULL ? NULL : tninfo->in_op;
02859
02860 if (alu_op == NULL || alu_op->bb != op->bb)
02861 return FALSE;
02862
02863 if (op->next != NULL &&
02864 is_live_tn(op->next, OP_result(alu_op, 0)))
02865 return FALSE;
02866 else if (op->next == NULL &&
02867 GTN_SET_MemberP(BB_live_out(OP_bb(op)), OP_result(alu_op, 0)))
02868 return FALSE;
02869
02870 if (!TN_is_register(OP_opnd(alu_op, 0)))
02871 return FALSE;
02872
02873
02874
02875 const EBO_TN_INFO* alu_opnd0_info = get_tn_info( OP_opnd( alu_op, 0 ) );
02876 if( alu_opnd0_info &&
02877 alu_opnd0_info->sequence_num >= tninfo->sequence_num )
02878 return FALSE;
02879
02880 if (OP_code(alu_op) == TOP_andi32 &&
02881 (unsigned int)TN_value( OP_opnd( alu_op, 1)) <= 0x7fffffff &&
02882 (!EBO_in_peep ||
02883 TN_is_register( OP_result( op, 0)) &&
02884 TN_is_register( OP_opnd( alu_op, 0)) &&
02885 TNs_Are_Equivalent( OP_result( op, 0), OP_opnd( alu_op, 0)))) {
02886 OP* new_op = Mk_OP( OP_code(alu_op), OP_result(op, 0),
02887 OP_opnd(alu_op, 0), OP_opnd(alu_op, 1));
02888 OP_srcpos( new_op ) = OP_srcpos( op );
02889 BB_Insert_Op_After( OP_bb(op), op, new_op );
02890
02891 if( EBO_Trace_Data_Flow ){
02892 fprintf( TFile, "Special_Sequence merges " );
02893 Print_OP_No_SrcLine(op);
02894 fprintf( TFile, "and " );
02895 Print_OP_No_SrcLine(alu_op);
02896 fprintf( TFile, "with ");
02897 Print_OP_No_SrcLine(new_op);
02898 }
02899 return TRUE;
02900 }
02901 } else if ( top == TOP_ldc32 || top == TOP_ldc64 ) {
02902 TN* tn0 = OP_opnd(op, 0);
02903 BOOL rflags_read = FALSE;
02904
02905
02906 if (TN_is_symbol(tn0))
02907 return FALSE;
02908
02909
02910 if( TN_value(tn0) != 0)
02911 return FALSE;
02912
02913
02914
02915 for( OP* next_op = OP_next(op); next_op != NULL;
02916 next_op = OP_next( next_op ) ){
02917 if( OP_reads_rflags( next_op ) )
02918 rflags_read = TRUE;
02919 if( TOP_is_change_rflags( OP_code(next_op) ) )
02920 break;
02921 }
02922 if (!rflags_read && CG_use_xortozero) {
02923 OP* new_op = Mk_OP(top == TOP_ldc32? TOP_zero32: TOP_zero64,
02924 OP_result(op, 0));
02925 BB_Insert_Op_After(OP_bb(op), op, new_op);
02926 return TRUE;
02927 }
02928 }
02929
02930 else if ( top == TOP_movdq ) {
02931 const EBO_TN_INFO* tninfo = opnd_tninfo[0];
02932 OP* alu_op = tninfo == NULL ? NULL : tninfo->in_op;
02933
02934 if (!alu_op)
02935 return FALSE;
02936
02937 if ( TOP_is_vector_packed_single ( OP_code (alu_op ) ) )
02938 op->opr = TOP_movaps;
02939 else if ( TOP_is_vector_packed_double ( OP_code (alu_op ) ) )
02940 op->opr = TOP_movapd;
02941 }
02942
02943 else if( top == TOP_jne || top == TOP_je ) {
02944
02945
02946
02947
02948
02949
02950
02951 const EBO_TN_INFO* tninfo = opnd_tninfo[0];
02952 OP* test_op = tninfo == NULL ? NULL : tninfo->in_op;
02953 if ( test_op &&
02954 ( OP_code( test_op ) == TOP_test32 ||
02955 OP_code( test_op ) == TOP_test64 ) &&
02956 TNs_Are_Equivalent( OP_opnd(test_op, 0), OP_opnd(test_op, 1) ) ) {
02957 const EBO_TN_INFO* test_tninfo = get_tn_info( OP_opnd(test_op, 0 ));
02958 OP* set_op = test_tninfo == NULL ? NULL : test_tninfo->in_op;
02959 if ( set_op && OP_code( set_op ) == TOP_sete &&
02960 !TN_live_out_of( OP_result(set_op,0), OP_bb(test_op) ) ){
02961
02962 BOOL skip = FALSE;
02963 if (OP_bb(set_op) != OP_bb(test_op))
02964 skip = TRUE;
02965 else {
02966 OP* next;
02967 for (next = OP_next(set_op); next != test_op; next = OP_next(next)) {
02968 if (!next ||
02969 TOP_is_change_rflags(OP_code(next))) {
02970 skip = TRUE;
02971 break;
02972 }
02973 }
02974 }
02975
02976 if (!skip) {
02977 OP_Change_To_Noop( test_op );
02978 op->opr = ( top == TOP_jne ) ? TOP_je : TOP_jne;
02979 }
02980 }
02981 }
02982
02983 OP* alu_op = tninfo == NULL ? NULL : tninfo->in_op;
02984
02985 if( test_is_replaced( alu_op, op, tninfo ) )
02986 return TRUE;
02987 }
02988
02989 else if (!EBO_in_peep &&
02990 top == TOP_shri64) {
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004 const EBO_TN_INFO* tninfo = opnd_tninfo[0];
03005 OP* alu_op = tninfo == NULL ? NULL : tninfo->in_op;
03006
03007 if (alu_op &&
03008 OP_code(alu_op) == TOP_shli64) {
03009 TN *left = OP_opnd(alu_op, 1);
03010 TN *right = OP_opnd(op, 1);
03011 Is_True(TN_Is_Constant(left) && TN_has_value(left) &&
03012 TN_Is_Constant(right) && TN_has_value(right),
03013 ("Special_Sequence: unexpected shift opnds"));
03014 int new_right_shift_val = TN_value(right) - TN_value(left);
03015 if (new_right_shift_val < 0)
03016 return FALSE;
03017 if (!Pred_Opnd_Avail(op, opnd_tninfo[0], 0))
03018 return FALSE;
03019
03020 TOP mov_opcode;
03021 int field_size = 64 - TN_value(right);
03022 if (field_size == 8) {
03023 mov_opcode = TOP_movzbq;
03024 } else if (field_size == 16) {
03025 mov_opcode = TOP_movzwq;
03026 } else if (field_size == 32) {
03027 mov_opcode = TOP_movzlq;
03028 } else {
03029 return FALSE;
03030 }
03031 OP *new_shift, *new_move;
03032 TN *tmp_tn = Dup_TN(OP_result(alu_op, 0));
03033 new_shift = Mk_OP(TOP_shri64, tmp_tn, OP_opnd(alu_op, 0),
03034 Gen_Literal_TN(new_right_shift_val, TN_size(right)));
03035 BB_Insert_Op_After(OP_bb(op), op, new_shift);
03036 new_move = Mk_OP(mov_opcode, OP_result(op, 0), tmp_tn);
03037 BB_Insert_Op_After(OP_bb(op), new_shift, new_move);
03038 return TRUE;
03039 }
03040 }
03041
03042 else if (top == TOP_shli32 ||
03043 top == TOP_shli64) {
03044
03045 if (EBO_in_peep)
03046 return FALSE;
03047
03048
03049
03050
03051
03052
03053
03054
03055 const EBO_TN_INFO* tninfo = opnd_tninfo[0];
03056 TN *left = OP_opnd(op, 1);
03057 Is_True(TN_Is_Constant(left) && TN_has_value(left),
03058 ("Special_Sequence: shift amount not integer constant"));
03059 int left_shift_amount = TN_value(left);
03060 OP* alu_op = tninfo == NULL ? NULL : tninfo->in_op;
03061 EBO_TN_INFO *alu_opnd0_tninfo = NULL;
03062
03063 if (alu_op &&
03064 ((OP_code(alu_op) == TOP_movzbl && left_shift_amount >= 31) ||
03065 (OP_code(alu_op) == TOP_movzwl && left_shift_amount >= 31) ||
03066 (OP_code(alu_op) == TOP_movzbq && left_shift_amount >= 63) ||
03067 (OP_code(alu_op) == TOP_movzwq && left_shift_amount >= 63) ||
03068 (OP_code(alu_op) == TOP_movzlq && left_shift_amount >= 63)) &&
03069 Pred_Opnd_Avail(op, opnd_tninfo[0], 0, &alu_opnd0_tninfo)) {
03070 Set_OP_opnd(op, 0, OP_opnd(alu_op, 0));
03071 dec_ref_count(opnd_tninfo[0]);
03072 inc_ref_count(alu_opnd0_tninfo);
03073 opnd_tninfo[0] = alu_opnd0_tninfo;
03074 return FALSE;
03075 }
03076 }
03077
03078 return FALSE;
03079 }
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089 void Redundancy_Elimination()
03090 {
03091 #if Is_True_On
03092 if (!(EBO_Opt_Mask & EBO_REDUNDANCY_ELIMINATION)) return;
03093 #endif
03094 for( BB* bb = REGION_First_BB; bb != NULL; bb = BB_next( bb ) ){
03095 if( BB_rid(bb) && (RID_level(BB_rid(bb)) >= RL_CGSCHED) ){
03096
03097 continue;
03098 }
03099 for( OP* op = BB_first_op( bb ); op != NULL; op = OP_next( op ) ){
03100 BOOL done = FALSE;
03101 INT copy_operand = CGTARG_Copy_Operand(op);
03102 if (copy_operand >= 0) {
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113 TN* src = OP_opnd( op, copy_operand );
03114 TN* result = OP_result( op, 0 );
03115
03116 FmtAssert( TN_is_register( src ) && TN_is_register( result ),
03117 ("Redundancy_Elimination: src/result not registers in EBO_in_peep (1)"));
03118
03119
03120 if (EBO_no_liveness_info_available ||
03121 REG_LIVE_Outof_BB (TN_register_class(result),
03122 TN_register(result), bb)) {
03123
03124
03125 BOOL redefined = FALSE;
03126 for( OP* dw_op = OP_next( op ); dw_op != NULL; dw_op = OP_next( dw_op ) ){
03127 if ((OP_code(dw_op) != TOP_asm) &&
03128 OP_results(dw_op) &&
03129 TN_is_register(OP_result(dw_op, 0)) &&
03130 (TN_register_class(OP_result(dw_op, 0)) ==
03131 TN_register_class(result)) &&
03132 (TN_register(OP_result(dw_op, 0)) == TN_register(result))) {
03133 redefined = TRUE;
03134 break;
03135 }
03136 }
03137 if (redefined == FALSE)
03138 continue;
03139 }
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149 BOOL cannot_be_removed = FALSE;
03150 for( OP* dw_op = OP_next( op ); dw_op != NULL; dw_op = OP_next( dw_op ) ){
03151 if ((OP_code(dw_op) != TOP_asm) &&
03152 OP_results(dw_op) &&
03153 TN_is_register( OP_result( dw_op, 0)) &&
03154 TNs_Are_Equivalent( OP_result( dw_op, 0), src)) {
03155
03156
03157 INT dw_op_copy_operand = CGTARG_Copy_Operand(dw_op);
03158 TN *dw_op_copy_operand_tn = (dw_op_copy_operand>=0)?OP_opnd(dw_op, dw_op_copy_operand):NULL;
03159 if ((dw_op_copy_operand >= 0) &&
03160 TN_is_register( dw_op_copy_operand_tn) &&
03161 TNs_Are_Equivalent(dw_op_copy_operand_tn, result))
03162 break;
03163
03164
03165 for( OP* dw1_op = OP_next( dw_op ); dw1_op != NULL; dw1_op = OP_next( dw1_op ) ){
03166 for( int i = 0; i < OP_opnds( dw1_op ); i++ ){
03167 if ( TN_is_register( OP_opnd( dw1_op, i)) &&
03168 TNs_Are_Equivalent( OP_opnd( dw1_op, i), result)) {
03169 cannot_be_removed = TRUE;
03170 break;
03171 }
03172 }
03173 }
03174 if (cannot_be_removed)
03175 break;
03176 }
03177 }
03178 if (cannot_be_removed)
03179 continue;
03180
03181
03182
03183 for( OP* dw_op = OP_next( op ); dw_op != NULL; dw_op = OP_next( dw_op ) ){
03184
03185 for( int i = 0; i < OP_opnds( dw_op ); i++ ){
03186 if ( TN_is_register( OP_opnd( dw_op, i)) &&
03187 TNs_Are_Equivalent( OP_opnd( dw_op, i), result)) {
03188 Set_OP_opnd( dw_op, i, src );
03189 done = TRUE;
03190 }
03191 }
03192
03193 if( OP_results( dw_op ) == 1 ){
03194 TN* tnr = OP_result( dw_op, 0 );
03195
03196 if( TN_is_register( tnr) &&
03197 TNs_Are_Equivalent( tnr, result ) ||
03198 TNs_Are_Equivalent( tnr, src ) )
03199 break;
03200 }
03201 }
03202
03203 if( done ){
03204 OP* dead = op;
03205 op = OP_prev( op );
03206
03207 if( EBO_Trace_Optimization ){
03208 fprintf( TFile, "Redundancy_Elimination removes simplified op - " );
03209 Print_OP_No_SrcLine( dead );
03210 }
03211
03212 BB_Remove_Op( bb, dead );
03213
03214 if( op == NULL )
03215 op = BB_first_op( bb );
03216 }
03217
03218 continue;
03219 }
03220
03221 if (OP_code( op ) != TOP_sar32 &&
03222 OP_code( op ) != TOP_sar64 &&
03223 OP_code( op ) != TOP_shl32 &&
03224 OP_code( op ) != TOP_shl64 &&
03225 OP_code( op ) != TOP_shr32 &&
03226 OP_code( op ) != TOP_shr64 )
03227 continue;
03228
03229
03230
03231 TN* src = OP_opnd( op, 0 );
03232 TN* result = OP_result( op, 0 );
03233
03234 FmtAssert( TN_is_register( src ) && TN_is_register( result ),
03235 ("Redundancy_Elimination: src/result not registers in EBO_in_peep (2)"));
03236
03237 FmtAssert( false, ("Redundancy_Elimination: UNIMPLEMENTED (1)") );
03238
03239
03240 if (EBO_no_liveness_info_available ||
03241 REG_LIVE_Outof_BB (TN_register_class(result),
03242 TN_register(result), bb)) {
03243
03244
03245 BOOL redefined = FALSE;
03246 for( OP* dw_op = OP_next( op ); dw_op != NULL; dw_op = OP_next( dw_op ) ){
03247 if (OP_has_result(dw_op) &&
03248 TN_is_register(OP_result(dw_op, 0)) &&
03249 (TN_register_class(OP_result(dw_op, 0)) ==
03250 TN_register_class(result)) &&
03251 (TN_register(OP_result(dw_op, 0)) == TN_register(result))) {
03252 redefined = TRUE;
03253 break;
03254 }
03255 }
03256 if (redefined == FALSE)
03257 continue;
03258 }
03259
03260
03261
03262 for( OP* dw_op = OP_next( op ); dw_op != NULL; dw_op = OP_next( dw_op ) ){
03263 for( int i = 0; i < OP_opnds( dw_op ); i++ ){
03264 if( TN_is_register(OP_opnd( dw_op, i)) &&
03265 (TN_register_class(OP_opnd(dw_op, i)) ==
03266 TN_register_class(result)) &&
03267 (TN_register(OP_opnd( dw_op, i )) == TN_register(result))) {
03268 FmtAssert( false, ("Redundancy_Elimination: UNIMPLEMENTED (2)") );
03269 done = TRUE;
03270 }
03271 }
03272
03273 if( OP_results( dw_op ) == 1 ){
03274 TN* tnr = OP_result( dw_op, 0 );
03275
03276 if( TN_is_register( tnr) &&
03277 TNs_Are_Equivalent( tnr, result ) )
03278 break;
03279 }
03280 }
03281
03282 if( done ){
03283 OP* dead = op;
03284 op = OP_prev( op );
03285
03286 if( EBO_Trace_Optimization ){
03287 fprintf( TFile, "Redundancy_Elimination removes simplified op - " );
03288 Print_OP_No_SrcLine( dead );
03289 }
03290
03291 BB_Remove_Op( bb, dead );
03292
03293 if( op == NULL )
03294 op = BB_first_op( bb );
03295 }
03296 }
03297 }
03298 }
03299
03300
03301 static inline TN* OP_opnd_use( OP* op, ISA_OPERAND_USE use )
03302 {
03303 const int indx = OP_find_opnd_use( op, use );
03304 return ( indx >= 0 ) ? OP_opnd( op, indx ) : NULL;
03305 }
03306
03307
03308
03309
03310 static TN* Compose_Addr_offset( TN* ofst1, TN* ofst2, TN* scale )
03311 {
03312 if( ofst1 == NULL )
03313 ofst1 = Gen_Literal_TN( 0, 4 );
03314
03315 if( ofst2 == NULL )
03316 ofst2 = Gen_Literal_TN( 0, 4 );
03317
03318 if( scale == NULL )
03319 scale = Gen_Literal_TN( 1, 4 );
03320
03321
03322 if( TN_is_symbol(ofst1) &&
03323 TN_is_symbol(ofst2) ){
03324 return NULL;
03325 }
03326
03327 if( TN_is_symbol(ofst1) ){
03328 ST* sym = TN_var(ofst1);
03329 const INT64 ofst = TN_value(ofst2) * TN_value(scale) + TN_offset(ofst1);
03330
03331 return Gen_Symbol_TN( sym, ofst, TN_RELOC_NONE );
03332 }
03333
03334 if( TN_is_symbol(ofst2) ){
03335 if( TN_value(scale) != 1 )
03336 return NULL;
03337
03338 ST* sym = TN_var(ofst2);
03339 const INT64 ofst = TN_value(ofst1) + TN_offset(ofst2);
03340
03341 return Gen_Symbol_TN( sym, ofst, TN_RELOC_NONE );
03342 }
03343
03344 const INT64 value = TN_value(ofst1) + TN_value(ofst2) * TN_value(scale);
03345
03346 if( !ISA_LC_Value_In_Class( value, LC_simm32 ) )
03347 return NULL;
03348
03349 return Gen_Literal_TN( value, 4 );
03350 }
03351
03352 #define IS_VALID_SCALE(s) ( (s)==1 || (s)==2 || (s)==4 || (s)==8 )
03353
03354 static BOOL Compose_Addr( OP* mem_op, EBO_TN_INFO* pt_tninfo,
03355 ISA_OPERAND_USE replace_opnd,
03356 TN** opnd_tn,
03357 TN** index, TN** offset, TN** scale, TN** base )
03358 {
03359 #if Is_True_On
03360 if (!(EBO_Opt_Mask & EBO_COMPOSE_ADDR)) return FALSE;
03361 #endif
03362
03363 struct ADDRESS_COMPONENT {
03364 TN* index;
03365 TN* base;
03366 TN* offset;
03367 TN* scale;
03368 } a, b;
03369
03370 bzero( &a, sizeof(a) );
03371 a.scale = Gen_Literal_TN( 1, 4 );
03372
03373
03374
03375
03376
03377 OP* addr_op = pt_tninfo->in_op;
03378 const TOP top = OP_code( addr_op );
03379
03380 switch( top ){
03381 case TOP_lea32:
03382 case TOP_lea64:
03383 a.base = OP_opnd_use( addr_op, OU_base );
03384 a.offset = OP_opnd_use( addr_op, OU_offset );
03385 break;
03386
03387 case TOP_leaxx32:
03388 case TOP_leaxx64:
03389 a.index = OP_opnd_use( addr_op, OU_index );
03390 a.offset = OP_opnd_use( addr_op, OU_offset );
03391 a.scale = OP_opnd_use( addr_op, OU_scale );
03392
03393 if( TN_value(a.scale) == 1 ){
03394 a.base = a.index;
03395 a.index = a.scale = NULL;
03396 }
03397
03398 break;
03399
03400 case TOP_leax32:
03401 case TOP_leax64:
03402 a.index = OP_opnd_use( addr_op, OU_index );
03403 a.offset = OP_opnd_use( addr_op, OU_offset );
03404 a.scale = OP_opnd_use( addr_op, OU_scale );
03405 a.base = OP_opnd_use( addr_op, OU_base );
03406 break;
03407
03408 case TOP_shli32:
03409 if( Is_Target_64bit() )
03410 return FALSE;
03411
03412 case TOP_shli64:
03413 {
03414 TN* tn = OP_opnd( addr_op, 1 );
03415 const INT64 val = TN_value(tn);
03416 if( val < 0 || val > 3 )
03417 return FALSE;
03418
03419 a.scale = Gen_Literal_TN( 1 << val, 4 );
03420 a.offset = Gen_Literal_TN( 0, 4 );
03421 a.index = OP_opnd( addr_op, 0 );
03422 }
03423 break;
03424
03425 case TOP_add32:
03426 if( Is_Target_64bit() )
03427 return FALSE;
03428
03429 case TOP_add64:
03430 a.base = OP_opnd( addr_op, 0 );
03431 a.index = OP_opnd( addr_op, 1 );
03432 a.offset = Gen_Literal_TN( 0, 4 );
03433 a.scale = Gen_Literal_TN( 1, 4 );
03434 break;
03435
03436 case TOP_addi32:
03437 if( Is_Target_64bit() )
03438 return FALSE;
03439
03440 case TOP_addi64:
03441 a.base = OP_opnd( addr_op, 0 );
03442 a.offset = OP_opnd( addr_op, 1 );
03443 break;
03444
03445 case TOP_mov32:
03446 if( Is_Target_64bit() )
03447 return FALSE;
03448
03449 case TOP_mov64:
03450 {
03451 TN* opnd = OP_opnd( addr_op, 0 );
03452 a.offset = Gen_Literal_TN( 0, 4 );
03453 a.base = opnd;
03454 }
03455 break;
03456
03457 case TOP_ldc32:
03458 case TOP_ldc64:
03459 a.offset = OP_opnd( addr_op, 0 );
03460 break;
03461
03462 default:
03463 return FALSE;
03464 }
03465
03466 const int op_offset_idx = OP_find_opnd_use( mem_op, OU_offset );
03467 TN* op_offset_tn = opnd_tn[op_offset_idx];
03468
03469
03470 if( a.index != NULL &&
03471 TN_value( a.scale ) == 1 ){
03472 const EBO_TN_INFO* tninfo = get_tn_info( a.index );
03473 if( tninfo != NULL &&
03474 tninfo->in_op != NULL &&
03475 tninfo->sequence_num < pt_tninfo->sequence_num &&
03476 ( OP_code(tninfo->in_op) == TOP_ldc64 ||
03477 OP_code(tninfo->in_op) == TOP_ldc32 ) ){
03478 TN* offset = Compose_Addr_offset( a.offset,
03479 OP_opnd( tninfo->in_op, 0 ),
03480 NULL );
03481 if( offset != NULL ){
03482 a.offset = offset;
03483 a.index = NULL;
03484 }
03485 }
03486 }
03487
03488
03489 if( a.base != NULL ){
03490 const EBO_TN_INFO* tninfo = get_tn_info( a.base );
03491 if( tninfo != NULL &&
03492 tninfo->in_op != NULL &&
03493 tninfo->sequence_num < pt_tninfo->sequence_num &&
03494 ( OP_code(tninfo->in_op) == TOP_ldc64 ||
03495 OP_code(tninfo->in_op) == TOP_ldc32 ) ){
03496 TN* offset = Compose_Addr_offset( a.offset,
03497 OP_opnd( tninfo->in_op, 0 ),
03498 NULL );
03499 if( offset != NULL ){
03500 a.offset = offset;
03501 a.base = NULL;
03502 }
03503 }
03504 }
03505
03506 if( !EBO_in_peep ){
03507 if( OP_bb( addr_op ) != OP_bb( mem_op ) ){
03508 for( int i = 0; i < OP_opnds(addr_op); i++ ){
03509 if( has_assigned_reg( OP_opnd(addr_op,i) ) )
03510 return FALSE;
03511 }
03512 }
03513
03514 if( a.index != NULL ){
03515 const REGISTER reg = TN_register( a.index );
03516 if( reg == RAX || reg == RCX || reg == RDX )
03517 return FALSE;
03518 }
03519
03520 if( a.base != NULL ){
03521 const REGISTER reg = TN_register( a.base );
03522 if( reg == RAX || reg == RCX || reg == RDX )
03523 return FALSE;
03524 }
03525 }
03526
03527
03528
03529
03530
03531 if( a.base != NULL ){
03532 EBO_TN_INFO* tninfo = get_tn_info( a.base );
03533 if( tninfo != NULL && tninfo->sequence_num >= pt_tninfo->sequence_num ){
03534 return FALSE;
03535 }
03536 }
03537
03538 if( a.index != NULL ){
03539 EBO_TN_INFO* tninfo = get_tn_info( a.index );
03540 if( tninfo != NULL && tninfo->sequence_num >= pt_tninfo->sequence_num ){
03541 return FALSE;
03542 }
03543 }
03544
03545
03546
03547
03548
03549 b.scale = OP_opnd_use( mem_op, OU_scale );
03550 b.base = OP_opnd_use( mem_op, OU_base );
03551 b.index = OP_opnd_use( mem_op, OU_index );
03552 b.offset = OP_opnd_use( mem_op, OU_offset );
03553
03554 if( b.scale == NULL )
03555 b.scale = Gen_Literal_TN( 1, 4 );
03556
03557
03558
03559
03560 *index = *offset = *base = *scale = NULL;
03561
03562 if( replace_opnd == OU_base ){
03563
03564 *offset = Compose_Addr_offset( b.offset, a.offset, NULL );
03565
03566
03567 *base = a.base;
03568
03569
03570 if( a.index == NULL &&
03571 b.index == NULL ){
03572 *index = *scale = NULL;
03573
03574 } else if( a.index == NULL ){
03575 *index = b.index;
03576 *scale = b.scale;
03577
03578 } else if( b.index == NULL ){
03579 *index = a.index;
03580 *scale = a.scale;
03581
03582 } else {
03583 if( TNs_Are_Equivalent( a.index, b.index ) ){
03584 *index = a.index;
03585 *scale = Gen_Literal_TN( TN_value(a.scale) + TN_value(b.scale), 4 );
03586
03587 } else {
03588 if( *base != NULL )
03589 return FALSE;
03590 if( TN_value(b.scale) == 1 ){
03591 *base = b.index;
03592 *index = a.index;
03593 *scale = a.scale;
03594
03595 } else if( TN_value(a.scale) == 1 ){
03596 *base = a.index;
03597 *index = b.index;
03598 *scale = b.scale;
03599
03600 } else
03601 return FALSE;
03602 }
03603 }
03604
03605 } else if( replace_opnd == OU_index ){
03606
03607 *offset = Compose_Addr_offset( b.offset, a.offset, b.scale );
03608
03609
03610 *index = a.index;
03611 *scale = Gen_Literal_TN( TN_value(a.scale) * TN_value(b.scale), 4 );
03612
03613
03614 if( b.base == NULL &&
03615 a.base == NULL ){
03616 *base = NULL;
03617
03618 } else if( b.base == NULL ){
03619 *base = a.base;
03620
03621 if( TN_value(b.scale) != 1 ){
03622 if( *index == NULL ){
03623 *scale = b.scale;
03624 *index = *base;
03625 *base = NULL;
03626
03627 } else {
03628 if( !TNs_Are_Equivalent( *index, a.base ) )
03629 return FALSE;
03630 *base = NULL;
03631 *scale = Gen_Literal_TN( TN_value(*scale) + TN_value(b.scale), 4 );
03632 }
03633 }
03634
03635 } else if( a.base == NULL ){
03636 *base = b.base;
03637
03638 } else {
03639 if( *index == NULL ){
03640 *index = a.base;
03641 *scale = b.scale;
03642 *base = b.base;
03643
03644 } else {
03645 if( !TNs_Are_Equivalent( b.base, a.base ) ) {
03646
03647
03648
03649 if ( !TNs_Are_Equivalent ( a.base, a.index ) )
03650 return FALSE;
03651 else {
03652 *index = b.base;
03653 }
03654 }
03655
03656 if( TN_value(*scale) != 1 )
03657 return FALSE;
03658
03659 *scale = Gen_Literal_TN( TN_value(b.scale) + 1, 4 );
03660 *base = *index;
03661 *index = a.base;
03662 }
03663 }
03664
03665 } else {
03666 return FALSE;
03667 }
03668
03669
03670
03671 if( *offset == NULL ||
03672 !ISA_LC_Value_In_Class( TN_value(*offset), LC_simm32 ) )
03673 return FALSE;
03674
03675
03676
03677
03678
03679 if (mcmodel == KERNEL &&
03680 TN_is_symbol(*offset) &&
03681 ST_sym_class(TN_var(*offset)) == CLASS_BLOCK &&
03682 !ISA_LC_Value_In_Class(TN_offset(*offset), LC_simm16))
03683 return FALSE;
03684
03685 if( *scale != NULL && !IS_VALID_SCALE( TN_value(*scale) ) ){
03686 if( *base != NULL ||
03687 TN_value(*scale) > 8 )
03688 return FALSE;
03689
03690 *base = *index;
03691 *scale = Gen_Literal_TN( TN_value(*scale) - 1, 4 );
03692
03693 if( !IS_VALID_SCALE( TN_value(*scale) ) )
03694 return FALSE;
03695 }
03696
03697
03698
03699 if( *index != NULL &&
03700 TN_register(*index) == RSP ){
03701 if( TN_value( *scale ) != 1 )
03702 return FALSE;
03703
03704 TN* tmp_tn = *index;
03705 *index = *base;
03706 *base = tmp_tn;
03707 }
03708
03709 if( *index == NULL ){
03710 if( *scale != NULL && TN_value(*scale) > 1 )
03711 return FALSE;
03712
03713 *scale = NULL;
03714 }
03715
03716 if( *base == NULL &&
03717 *index != NULL &&
03718 TN_value(*scale) == 1 ){
03719 *base = *index;
03720 *index = *scale = NULL;
03721 }
03722
03723 return TRUE;
03724 }
03725
03726
03727
03728
03729 typedef struct {
03730 TOP reg_mode;
03731 TOP base_mode;
03732 TOP base_index_mode;
03733 TOP index_mode;
03734 TOP n32_mode;
03735 } Addr_Mode_Group;
03736
03737
03738 static Addr_Mode_Group *Top_To_Addr_Mode_Group[TOP_count+1];
03739
03740
03741
03742
03743
03744 static Addr_Mode_Group Addr_Mode_Group_Table[] = {
03745
03746
03747
03748 {TOP_UNDEFINED, TOP_store8, TOP_storex8, TOP_storexx8, TOP_store8_n32},
03749 {TOP_UNDEFINED, TOP_store16, TOP_storex16, TOP_storexx16, TOP_store16_n32},
03750 {TOP_UNDEFINED, TOP_store32, TOP_storex32, TOP_storexx32, TOP_store32_n32},
03751 {TOP_UNDEFINED, TOP_store64, TOP_storex64, TOP_storexx64, TOP_store64_off},
03752 {TOP_UNDEFINED, TOP_stss, TOP_stssx, TOP_stssxx, TOP_stss_n32},
03753 {TOP_UNDEFINED, TOP_stsd, TOP_stsdx, TOP_stsdxx, TOP_stsd_n32},
03754 {TOP_UNDEFINED, TOP_stntss, TOP_stntssx, TOP_stntssxx, TOP_UNDEFINED},
03755 {TOP_UNDEFINED, TOP_stntsd, TOP_stntsdx, TOP_stntsdxx, TOP_UNDEFINED},
03756 {TOP_UNDEFINED, TOP_stdqa, TOP_stdqax, TOP_stdqaxx, TOP_stdqa_n32},
03757 {TOP_UNDEFINED, TOP_stntpd, TOP_stntpdx, TOP_stntpdxx, TOP_UNDEFINED},
03758 {TOP_UNDEFINED, TOP_stdqu, TOP_stdqux, TOP_stdquxx, TOP_UNDEFINED},
03759 {TOP_UNDEFINED, TOP_fmovsldupx, TOP_fmovsldupxx, TOP_fmovsldupxxx, TOP_UNDEFINED},
03760 {TOP_UNDEFINED, TOP_fmovshdupx, TOP_fmovshdupxx, TOP_fmovshdupxxx, TOP_UNDEFINED},
03761 {TOP_UNDEFINED, TOP_fmovddupx, TOP_fmovddupxx, TOP_fmovddupxxx, TOP_UNDEFINED},
03762 {TOP_UNDEFINED, TOP_ldss, TOP_ldssx, TOP_ldssxx, TOP_ldss_n32},
03763 {TOP_UNDEFINED, TOP_ldsd, TOP_ldsdx, TOP_ldsdxx, TOP_ldsd_n32},
03764 {TOP_UNDEFINED, TOP_lddqa, TOP_lddqax, TOP_lddqaxx, TOP_lddqa_n32},
03765 {TOP_UNDEFINED, TOP_lddqu, TOP_lddqux, TOP_lddquxx, TOP_UNDEFINED},
03766 {TOP_UNDEFINED, TOP_ldlps, TOP_ldlpsx, TOP_ldlpsxx, TOP_ldlps_n32},
03767 {TOP_UNDEFINED, TOP_ldlpd, TOP_ldlpdx, TOP_ldlpdxx, TOP_UNDEFINED},
03768 {TOP_UNDEFINED, TOP_ldaps, TOP_ldapsx, TOP_ldapsxx, TOP_ldaps_n32},
03769 {TOP_UNDEFINED, TOP_ldapd, TOP_ldapdx, TOP_ldapdxx, TOP_ldapd_n32},
03770 {TOP_UNDEFINED, TOP_stlps, TOP_stlpsx, TOP_stlpsxx, TOP_stlps_n32},
03771 {TOP_UNDEFINED, TOP_stlpd, TOP_stlpdx, TOP_stlpdxx, TOP_stlpd_n32},
03772 {TOP_UNDEFINED, TOP_staps, TOP_stapsx, TOP_stapsxx, TOP_staps_n32},
03773 {TOP_UNDEFINED, TOP_stapd, TOP_stapdx, TOP_stapdxx, TOP_stapd_n32},
03774 {TOP_UNDEFINED, TOP_ldhps, TOP_ldhpsx, TOP_ldhpsxx, TOP_UNDEFINED},
03775 {TOP_UNDEFINED, TOP_ldhpd, TOP_ldhpdx, TOP_ldhpdxx, TOP_ldhpd_n32},
03776 {TOP_UNDEFINED, TOP_sthps, TOP_sthpsx, TOP_sthpsxx, TOP_UNDEFINED},
03777 {TOP_UNDEFINED, TOP_sthpd, TOP_sthpdx, TOP_sthpdxx, TOP_sthpd_n32},
03778 {TOP_UNDEFINED, TOP_ld8_64, TOP_ldx8_64, TOP_ldxx8_64, TOP_ld8_64_off},
03779 {TOP_UNDEFINED, TOP_ldu8_64, TOP_ldxu8_64, TOP_ldxxu8_64, TOP_ldu8_64_off},
03780 {TOP_UNDEFINED, TOP_ld16_64, TOP_ldx16_64, TOP_ldxx16_64, TOP_ld16_64_off},
03781 {TOP_UNDEFINED, TOP_ldu16_64, TOP_ldxu16_64, TOP_ldxxu16_64, TOP_ldu16_64_off},
03782 {TOP_UNDEFINED, TOP_ld8_32, TOP_ldx8_32, TOP_ldxx8_32, TOP_ld8_32_n32},
03783 {TOP_UNDEFINED, TOP_ldu8_32, TOP_ldxu8_32, TOP_ldxxu8_32, TOP_ldu8_32_n32},
03784 {TOP_UNDEFINED, TOP_ld16_32, TOP_ldx16_32, TOP_ldxx16_32, TOP_ld16_32_n32},
03785 {TOP_UNDEFINED, TOP_ldu16_32, TOP_ldxu16_32, TOP_ldxxu16_32, TOP_ldu16_32_n32},
03786 {TOP_UNDEFINED, TOP_ld32, TOP_ldx32, TOP_ldxx32, TOP_ld32_n32},
03787 {TOP_UNDEFINED, TOP_ld32_64, TOP_ldx32_64, TOP_ldxx32_64, TOP_ld32_64_off},
03788 {TOP_UNDEFINED, TOP_ld64, TOP_ldx64, TOP_ldxx64, TOP_ld64_off},
03789 {TOP_UNDEFINED, TOP_prefetch, TOP_prefetchx, TOP_prefetchxx, TOP_UNDEFINED},
03790 {TOP_UNDEFINED, TOP_prefetchw, TOP_prefetchwx, TOP_prefetchwxx, TOP_UNDEFINED},
03791 {TOP_UNDEFINED, TOP_prefetcht0, TOP_prefetcht0x, TOP_prefetcht0xx, TOP_UNDEFINED},
03792 {TOP_UNDEFINED, TOP_prefetcht1, TOP_prefetcht1x, TOP_prefetcht1xx, TOP_UNDEFINED},
03793
03794
03795 {TOP_UNDEFINED, TOP_lea32, TOP_leax32, TOP_leaxx32, TOP_UNDEFINED},
03796 {TOP_UNDEFINED, TOP_lea64, TOP_leax64, TOP_leaxx64, TOP_UNDEFINED},
03797
03798
03799
03800 {TOP_add32, TOP_addx32, TOP_addxx32, TOP_addxxx32, TOP_UNDEFINED},
03801 {TOP_add64, TOP_addx64, TOP_addxx64, TOP_addxxx64, TOP_UNDEFINED},
03802 {TOP_addss, TOP_addxss, TOP_addxxss, TOP_addxxxss, TOP_UNDEFINED},
03803 {TOP_addsd, TOP_addxsd, TOP_addxxsd, TOP_addxxxsd, TOP_UNDEFINED},
03804 {TOP_add128v8, TOP_addx128v8, TOP_addxx128v8, TOP_addxxx128v8, TOP_UNDEFINED},
03805 {TOP_add128v16, TOP_addx128v16, TOP_addxx128v16, TOP_addxxx128v16, TOP_UNDEFINED},
03806 {TOP_add128v32, TOP_addx128v32, TOP_addxx128v32, TOP_addxxx128v32, TOP_UNDEFINED},
03807 {TOP_add128v64, TOP_addx128v64, TOP_addxx128v64, TOP_addxxx128v64, TOP_UNDEFINED},
03808 {TOP_fadd128v32, TOP_faddx128v32, TOP_faddxx128v32, TOP_faddxxx128v32, TOP_UNDEFINED},
03809 {TOP_fadd128v64, TOP_faddx128v64, TOP_faddxx128v64, TOP_faddxxx128v64, TOP_UNDEFINED},
03810 {TOP_fhadd128v32, TOP_fhaddx128v32, TOP_fhaddxx128v32, TOP_fhaddxxx128v32, TOP_UNDEFINED},
03811 {TOP_fhadd128v64, TOP_fhaddx128v64, TOP_fhaddxx128v64, TOP_fhaddxxx128v64, TOP_UNDEFINED},
03812 {TOP_faddsub128v32, TOP_faddsubx128v32, TOP_faddsubxx128v32, TOP_faddsubxxx128v32, TOP_UNDEFINED},
03813 {TOP_faddsub128v64, TOP_faddsubx128v64, TOP_faddsubxx128v64, TOP_faddsubxxx128v64, TOP_UNDEFINED},
03814 {TOP_fhsub128v32, TOP_fhsubx128v32, TOP_fhsubxx128v32, TOP_fhsubxxx128v32, TOP_UNDEFINED},
03815 {TOP_fhsub128v64, TOP_fhsubx128v64, TOP_fhsubxx128v64, TOP_fhsubxxx128v64, TOP_UNDEFINED},
03816
03817 {TOP_sub32, TOP_subx32, TOP_subxx32, TOP_subxxx32, TOP_UNDEFINED},
03818 {TOP_sub64, TOP_subx64, TOP_subxx64, TOP_subxxx64, TOP_UNDEFINED},
03819 {TOP_subss, TOP_subxss, TOP_subxxss, TOP_subxxxss, TOP_UNDEFINED},
03820 {TOP_subsd, TOP_subxsd, TOP_subxxsd, TOP_subxxxsd, TOP_UNDEFINED},
03821 {TOP_sub128v8, TOP_subx128v8, TOP_subxx128v8, TOP_subxxx128v8, TOP_UNDEFINED},
03822 {TOP_sub128v16, TOP_subx128v16, TOP_subxx128v16, TOP_subxxx128v16, TOP_UNDEFINED},
03823 {TOP_sub128v32, TOP_subx128v32, TOP_subxx128v32, TOP_subxxx128v32, TOP_UNDEFINED},
03824 {TOP_sub128v64, TOP_subx128v64, TOP_subxx128v64, TOP_subxxx128v64, TOP_UNDEFINED},
03825 {TOP_fsub128v32, TOP_fsubx128v32, TOP_fsubxx128v32, TOP_fsubxxx128v32, TOP_UNDEFINED},
03826 {TOP_fsub128v64, TOP_fsubx128v64, TOP_fsubxx128v64, TOP_fsubxxx128v64, TOP_UNDEFINED},
03827
03828 {TOP_mulss, TOP_mulxss, TOP_mulxxss, TOP_mulxxxss, TOP_UNDEFINED},
03829 {TOP_mulsd, TOP_mulxsd, TOP_mulxxsd, TOP_mulxxxsd, TOP_UNDEFINED},
03830 {TOP_fmul128v32, TOP_fmulx128v32, TOP_fmulxx128v32, TOP_fmulxxx128v32, TOP_UNDEFINED},
03831 {TOP_fmul128v64, TOP_fmulx128v64, TOP_fmulxx128v64, TOP_fmulxxx128v64, TOP_UNDEFINED},
03832 {TOP_cmpgt128v8, TOP_cmpgtx128v8, TOP_cmpgtxx128v8, TOP_cmpgtxxx128v8, TOP_UNDEFINED},
03833 {TOP_cmpgt128v16, TOP_cmpgtx128v16, TOP_cmpgtxx128v16, TOP_cmpgtxxx128v16, TOP_UNDEFINED},
03834 {TOP_cmpgt128v32, TOP_cmpgtx128v32, TOP_cmpgtxx128v32, TOP_cmpgtxxx128v32, TOP_UNDEFINED},
03835 {TOP_cmpeq128v8, TOP_cmpeqx128v8, TOP_cmpeqxx128v8, TOP_cmpeqxxx128v8, TOP_UNDEFINED},
03836 {TOP_cmpeq128v16, TOP_cmpeqx128v16, TOP_cmpeqxx128v16, TOP_cmpeqxxx128v16, TOP_UNDEFINED},
03837 {TOP_cmpeq128v32, TOP_cmpeqx128v32, TOP_cmpeqxx128v32, TOP_cmpeqxxx128v32, TOP_UNDEFINED},
03838 {TOP_max128v8, TOP_maxx128v8, TOP_maxxx128v8, TOP_maxxxx128v8, TOP_UNDEFINED},
03839 {TOP_max128v16, TOP_maxx128v16, TOP_maxxx128v16, TOP_maxxxx128v16, TOP_UNDEFINED},
03840 {TOP_min128v8, TOP_minx128v8, TOP_minxx128v8, TOP_minxxx128v8, TOP_UNDEFINED},
03841 {TOP_min128v16, TOP_minx128v16, TOP_minxx128v16, TOP_minxxx128v16, TOP_UNDEFINED},
03842 {TOP_divss, TOP_divxss, TOP_divxxss, TOP_divxxxss, TOP_UNDEFINED},
03843 {TOP_divsd, TOP_divxsd, TOP_divxxsd, TOP_divxxxsd, TOP_UNDEFINED},
03844 {TOP_fdiv128v32, TOP_fdivx128v32, TOP_fdivxx128v32, TOP_fdivxxx128v32, TOP_UNDEFINED},
03845 {TOP_fdiv128v64, TOP_fdivx128v64, TOP_fdivxx128v64, TOP_fdivxxx128v64, TOP_UNDEFINED},
03846
03847 {TOP_and8, TOP_andx8, TOP_andxx8, TOP_andxxx8, TOP_UNDEFINED},
03848 {TOP_and16, TOP_andx16, TOP_andxx16, TOP_andxxx16, TOP_UNDEFINED},
03849 {TOP_and32, TOP_andx32, TOP_andxx32, TOP_andxxx32, TOP_UNDEFINED},
03850 {TOP_and64, TOP_andx64, TOP_andxx64, TOP_andxxx64, TOP_UNDEFINED},
03851 {TOP_and128v8, TOP_andx128v8, TOP_andxx128v8, TOP_andxxx128v8, TOP_UNDEFINED},
03852 {TOP_and128v16, TOP_andx128v16, TOP_andxx128v16, TOP_andxxx128v16, TOP_UNDEFINED},
03853 {TOP_and128v32, TOP_andx128v32, TOP_andxx128v32, TOP_andxxx128v32, TOP_UNDEFINED },
03854 {TOP_and128v64, TOP_andx128v64, TOP_andxx128v64, TOP_andxxx128v64, TOP_UNDEFINED},
03855 {TOP_fand128v32, TOP_fandx128v32, TOP_fandxx128v32, TOP_fandxxx128v32, TOP_UNDEFINED},
03856 {TOP_fand128v64, TOP_fandx128v64, TOP_fandxx128v64, TOP_fandxxx128v64, TOP_UNDEFINED},
03857
03858
03859
03860 {TOP_andps, TOP_fandx128v32, TOP_fandxx128v32, TOP_fandxxx128v32, TOP_UNDEFINED},
03861 {TOP_andpd, TOP_fandx128v64, TOP_fandxx128v64, TOP_fandxxx128v64, TOP_UNDEFINED},
03862
03863 {TOP_or8, TOP_orx8, TOP_orxx8, TOP_orxxx8, TOP_UNDEFINED},
03864 {TOP_or16, TOP_orx16, TOP_orxx16, TOP_orxxx16, TOP_UNDEFINED},
03865 {TOP_or32, TOP_orx32, TOP_orxx32, TOP_orxxx32, TOP_UNDEFINED},
03866 {TOP_or64, TOP_orx64, TOP_orxx64, TOP_orxxx64, TOP_UNDEFINED},
03867 {TOP_or128v8, TOP_orx128v8, TOP_orxx128v8, TOP_orxxx128v8, TOP_UNDEFINED},
03868 {TOP_or128v16, TOP_orx128v16, TOP_orxx128v16, TOP_orxxx128v16, TOP_UNDEFINED},
03869 {TOP_or128v32, TOP_orx128v32, TOP_orxx128v32, TOP_orxxx128v32, TOP_UNDEFINED},
03870 {TOP_or128v64, TOP_orx128v64, TOP_orxx128v64, TOP_orxxx128v64, TOP_UNDEFINED},
03871 {TOP_for128v32, TOP_forx128v32, TOP_forxx128v32, TOP_forxxx128v32, TOP_UNDEFINED},
03872 {TOP_for128v64, TOP_forx128v64, TOP_forxx128v64, TOP_forxxx128v64, TOP_UNDEFINED},
03873
03874
03875
03876 {TOP_orps, TOP_forx128v32, TOP_forxx128v32, TOP_forxxx128v32, TOP_UNDEFINED},
03877 {TOP_orpd, TOP_forx128v64, TOP_forxx128v64, TOP_forxxx128v64, TOP_UNDEFINED},
03878
03879 {TOP_xor8, TOP_xorx8, TOP_xorxx8, TOP_xorxxx8, TOP_UNDEFINED},
03880 {TOP_xor16, TOP_xorx16, TOP_xorxx16, TOP_xorxxx16, TOP_UNDEFINED},
03881 {TOP_xor32, TOP_xorx32, TOP_xorxx32, TOP_xorxxx32, TOP_UNDEFINED},
03882 {TOP_xor64, TOP_xorx64, TOP_xorxx64, TOP_xorxxx64, TOP_UNDEFINED},
03883 {TOP_xor128v8, TOP_xorx128v8, TOP_xorxx128v8, TOP_xorxxx128v8, TOP_UNDEFINED},
03884 {TOP_xor128v16, TOP_xorx128v16, TOP_xorxx128v16, TOP_xorxxx128v16, TOP_UNDEFINED},
03885 {TOP_xor128v32, TOP_xorx128v32, TOP_xorxx128v32, TOP_xorxxx128v32, TOP_UNDEFINED},
03886 {TOP_xor128v64, TOP_xorx128v64, TOP_xorxx128v64, TOP_xorxxx128v64, TOP_UNDEFINED},
03887 {TOP_fxor128v32, TOP_fxorx128v32, TOP_fxorxx128v32, TOP_fxorxxx128v32, TOP_UNDEFINED},
03888 {TOP_fxor128v64, TOP_fxorx128v64, TOP_fxorxx128v64, TOP_fxorxxx128v64, TOP_UNDEFINED},
03889
03890
03891
03892 {TOP_xorps, TOP_fxorx128v32, TOP_fxorxx128v32, TOP_fxorxxx128v32, TOP_UNDEFINED},
03893 {TOP_xorpd, TOP_fxorx128v64, TOP_fxorxx128v64, TOP_fxorxxx128v64, TOP_UNDEFINED},
03894
03895 {TOP_fmax128v32, TOP_fmaxx128v32, TOP_fmaxxx128v32, TOP_fmaxxxx128v32, TOP_UNDEFINED},
03896 {TOP_fmax128v64, TOP_fmaxx128v64, TOP_fmaxxx128v64, TOP_fmaxxxx128v64, TOP_UNDEFINED},
03897 {TOP_fmin128v32, TOP_fminx128v32, TOP_fminxx128v32, TOP_fminxxx128v32, TOP_UNDEFINED},
03898 {TOP_fmin128v64, TOP_fminx128v64, TOP_fminxx128v64, TOP_fminxxx128v64, TOP_UNDEFINED},
03899
03900 {TOP_cmp8, TOP_cmpx8, TOP_cmpxx8, TOP_cmpxxx8, TOP_UNDEFINED},
03901 {TOP_cmp16, TOP_cmpx16, TOP_cmpxx16, TOP_cmpxxx16, TOP_UNDEFINED},
03902 {TOP_cmp32, TOP_cmpx32, TOP_cmpxx32, TOP_cmpxxx32, TOP_UNDEFINED},
03903 {TOP_cmp64, TOP_cmpx64, TOP_cmpxx64, TOP_cmpxxx64, TOP_UNDEFINED},
03904
03905 {TOP_cmpi8, TOP_cmpxi8, TOP_cmpxxi8, TOP_cmpxxxi8, TOP_UNDEFINED},
03906 {TOP_cmpi16, TOP_cmpxi16, TOP_cmpxxi16, TOP_cmpxxxi16, TOP_UNDEFINED},
03907 {TOP_cmpi32, TOP_cmpxi32, TOP_cmpxxi32, TOP_cmpxxxi32, TOP_UNDEFINED},
03908 {TOP_cmpi64, TOP_cmpxi64, TOP_cmpxxi64, TOP_cmpxxxi64, TOP_UNDEFINED},
03909
03910 {TOP_test32, TOP_testx32, TOP_testxx32, TOP_testxxx32, TOP_UNDEFINED},
03911 {TOP_test64, TOP_testx64, TOP_testxx64, TOP_testxxx64, TOP_UNDEFINED},
03912 {TOP_comiss, TOP_comixss, TOP_comixxss, TOP_comixxxss, TOP_UNDEFINED},
03913 {TOP_comisd, TOP_comixsd, TOP_comixxsd, TOP_comixxxsd, TOP_UNDEFINED},
03914
03915 {TOP_icall, TOP_icallx, TOP_icallxx, TOP_icallxxx, TOP_UNDEFINED},
03916 {TOP_ijmp, TOP_ijmpx, TOP_ijmpxx, TOP_ijmpxxx, TOP_UNDEFINED},
03917
03918 {TOP_cvtsd2ss, TOP_cvtsd2ss_x, TOP_cvtsd2ss_xx, TOP_cvtsd2ss_xxx, TOP_UNDEFINED},
03919 {TOP_cvtsi2ss, TOP_cvtsi2ss_x, TOP_cvtsi2ss_xx, TOP_cvtsi2ss_xxx, TOP_UNDEFINED},
03920 {TOP_cvtsi2ssq, TOP_cvtsi2ssq_x, TOP_cvtsi2ssq_xx, TOP_cvtsi2ssq_xxx, TOP_UNDEFINED},
03921 {TOP_cvtsi2sd, TOP_cvtsi2sd_x, TOP_cvtsi2sd_xx, TOP_cvtsi2sd_xxx, TOP_UNDEFINED},
03922 {TOP_cvtsi2sdq, TOP_cvtsi2sdq_x, TOP_cvtsi2sdq_xx, TOP_cvtsi2sdq_xxx, TOP_UNDEFINED},
03923
03924 {TOP_cvtdq2pd, TOP_cvtdq2pd_x, TOP_cvtdq2pd_xx, TOP_cvtdq2pd_xxx, TOP_UNDEFINED},
03925 {TOP_cvtdq2ps, TOP_cvtdq2ps_x, TOP_cvtdq2ps_xx, TOP_cvtdq2ps_xxx, TOP_UNDEFINED},
03926 {TOP_cvtps2pd, TOP_cvtps2pd_x, TOP_cvtps2pd_xx, TOP_cvtps2pd_xxx, TOP_UNDEFINED},
03927 {TOP_cvtpd2ps, TOP_cvtpd2ps_x, TOP_cvtpd2ps_xx, TOP_cvtpd2ps_xxx, TOP_UNDEFINED},
03928 {TOP_cvttps2dq, TOP_cvttps2dq_x, TOP_cvttps2dq_xx, TOP_cvttps2dq_xxx, TOP_UNDEFINED},
03929 {TOP_cvttpd2dq, TOP_cvttpd2dq_x, TOP_cvttpd2dq_xx, TOP_cvttpd2dq_xxx, TOP_UNDEFINED}
03930 };
03931
03932
03933 static void
03934 Add_Addr_Mode_Group (TOP top, Addr_Mode_Group *address_mode_group)
03935 {
03936 if (top == TOP_UNDEFINED)
03937 return;
03938
03939
03940
03941
03942 if (Top_To_Addr_Mode_Group[top] == NULL)
03943 Top_To_Addr_Mode_Group[top] = address_mode_group;
03944 }
03945
03946
03947 static void
03948 Init_Addr_Modes()
03949 {
03950 int i;
03951 ADDR_MODE mode;
03952 static bool table_is_initialized = false;
03953
03954 if( table_is_initialized )
03955 return;
03956
03957 table_is_initialized = true;
03958
03959 for (i = 0; i < TOP_UNDEFINED; i++) {
03960 Top_To_Addr_Mode_Group[i] = NULL;
03961 }
03962
03963
03964
03965 ADDR_MODE last_mode = N32_MODE;
03966 ADDR_MODE undefined_mode = UNDEFINED_MODE;
03967 FmtAssert(1 + (int)last_mode == (int) undefined_mode,
03968 ("Init_Addr_Modes: some address modes not handled"));
03969
03970 UINT table_size = sizeof(Addr_Mode_Group_Table) / sizeof(Addr_Mode_Group);
03971 for (i = 0; i < table_size; i++) {
03972 Addr_Mode_Group *group = &Addr_Mode_Group_Table[i];
03973
03974 Add_Addr_Mode_Group(group->reg_mode, group);
03975 Add_Addr_Mode_Group(group->base_mode, group);
03976 Add_Addr_Mode_Group(group->base_index_mode, group);
03977 Add_Addr_Mode_Group(group->index_mode, group);
03978 Add_Addr_Mode_Group(group->n32_mode, group);
03979 }
03980 }
03981
03982 static TOP
03983 Get_Top_For_Addr_Mode (TOP top, ADDR_MODE mode)
03984 {
03985 Addr_Mode_Group *group = Top_To_Addr_Mode_Group[top];
03986 if (group != NULL) {
03987 switch (mode) {
03988 case BASE_MODE: return group->base_mode;
03989 case BASE_INDEX_MODE: return group->base_index_mode;
03990 case INDEX_MODE: return group->index_mode;
03991 case N32_MODE: return group->n32_mode;
03992 }
03993 FmtAssert(FALSE, ("Get_Top_For_Addr_Mode: address mode not handled"));
03994 }
03995 return TOP_UNDEFINED;
03996 }
03997
03998 static OP *
03999 Compose_Mem_Op( OP* op, TN* index, TN* offset, TN* scale, TN* base )
04000 {
04001 Is_True( offset != NULL, ("Compose_Mem_Op: offset is NULL") );
04002
04003 OP* new_op = NULL;
04004 ADDR_MODE mode = N32_MODE;
04005
04006 if (index != NULL)
04007 mode = base == NULL ? INDEX_MODE : BASE_INDEX_MODE;
04008 else if (base != NULL)
04009 mode = BASE_MODE;
04010
04011 const TOP new_top = Get_Top_For_Addr_Mode(OP_code(op), mode);
04012
04013 FmtAssert( new_top != TOP_UNDEFINED, ("Compose_Mem_Op: unknown top") );
04014
04015 if( TOP_is_prefetch( new_top ) ){
04016 if( mode == INDEX_MODE )
04017 new_op = Mk_OP( new_top, OP_opnd( op, 0 ), index, scale, offset );
04018 else
04019 new_op = Mk_OP( new_top, OP_opnd( op, 0 ), base, offset, index, scale );
04020
04021 } else {
04022 TN* storeval = NULL;
04023
04024 if( TOP_is_store(new_top) ){
04025 storeval = OP_opnd( op, OP_find_opnd_use( op, OU_storeval ) );
04026 } else {
04027 storeval = OP_result( op, 0 );
04028 }
04029
04030 if( new_top == TOP_leax64 ){
04031 Is_True(mode != N32_MODE, ("Compose_Mem_Op: unexpected address mode"));
04032 if( mode == INDEX_MODE )
04033 new_op = Mk_OP( new_top, storeval, index, scale, offset );
04034 else
04035 new_op = Mk_OP( new_top, storeval, base, index, scale, offset );
04036 } else {
04037 if (mode == N32_MODE)
04038 new_op = Mk_OP( new_top, storeval, offset );
04039 else if (mode == INDEX_MODE)
04040 new_op = Mk_OP( new_top, storeval, index, scale, offset );
04041 else
04042 new_op = Mk_OP( new_top, storeval, base, offset, index, scale );
04043 }
04044 }
04045
04046 return new_op;
04047 }
04048
04049
04050
04051
04052 static OP *
04053 Compose_Mem_Op_And_Copy_Info(OP* op, TN* index_tn, TN* offset_tn, TN* scale_tn,
04054 TN* base_tn, EBO_TN_INFO **actual_tninfo)
04055 {
04056 OP *new_op = Compose_Mem_Op(op, index_tn, offset_tn, scale_tn, base_tn);
04057
04058 Copy_WN_For_Memory_OP(new_op, op);
04059 if (OP_volatile(op))
04060 Set_OP_volatile(new_op);
04061 OP_srcpos(new_op) = OP_srcpos(op);
04062
04063 Set_OP_unrolling(new_op, OP_unrolling(op));
04064 Set_OP_orig_idx(new_op, OP_map_idx(op));
04065 Set_OP_unroll_bb(new_op, OP_unroll_bb(op));
04066
04067 if (EBO_in_loop) {
04068 CG_LOOP_Init_Op(new_op);
04069 const INT op_base_idx = OP_find_opnd_use(op, OU_base);
04070 EBO_TN_INFO *base_tninfo = op_base_idx >= 0 ?
04071 actual_tninfo[op_base_idx] : NULL;
04072 if (base_tninfo != NULL && base_tninfo->omega != 0) {
04073 Set_OP_omega(new_op, OP_find_opnd_use(new_op, OU_base),
04074 base_tninfo->omega);
04075 }
04076
04077 if (index_tn != NULL) {
04078 EBO_TN_INFO *tninfo = get_tn_info(index_tn);
04079 if (tninfo != NULL && tninfo->omega != 0) {
04080 Set_OP_omega(new_op, OP_find_opnd_use(new_op, OU_index), tninfo->omega);
04081 }
04082 }
04083 }
04084
04085 return new_op;
04086 }
04087
04088
04089 BOOL EBO_Merge_Memory_Addr( OP* op,
04090 TN** opnd_tn,
04091 EBO_TN_INFO** opnd_tninfo,
04092 EBO_TN_INFO** actual_tninfo )
04093 {
04094 #if Is_True_On
04095 if (!(EBO_Opt_Mask & EBO_MERGE_MEMORY_ADDR)) return FALSE;
04096 #endif
04097 if( EBO_in_peep ){
04098 return FALSE;
04099 }
04100
04101 if (Get_Top_For_Addr_Mode(OP_code(op), BASE_MODE) == TOP_UNDEFINED) {
04102 return FALSE;
04103 }
04104
04105 const INT op_base_idx = OP_find_opnd_use( op, OU_base );
04106 EBO_TN_INFO* base_tninfo = op_base_idx >= 0 ? actual_tninfo[op_base_idx] : NULL;
04107 OP* addr_op = (base_tninfo != NULL) ? base_tninfo->in_op : NULL;
04108 bool pass = false;
04109 TN* index_tn = NULL;
04110 TN* offset_tn = NULL;
04111 TN* scale_tn = NULL;
04112 TN* base_tn = NULL;
04113
04114
04115 if( addr_op != NULL && !OP_load(addr_op) && !OP_simulated(addr_op) ){
04116 pass = Compose_Addr( op, base_tninfo, OU_base, opnd_tn,
04117 &index_tn, &offset_tn, &scale_tn, &base_tn );
04118 }
04119
04120
04121 if( !pass ){
04122 const INT op_index_idx = OP_find_opnd_use( op, OU_index );
04123 if( op_index_idx < 0 )
04124 return FALSE;
04125
04126 EBO_TN_INFO* index_tninfo = actual_tninfo[op_index_idx];
04127 if( index_tninfo == NULL || index_tninfo->in_op == NULL )
04128 return FALSE;
04129
04130 addr_op = index_tninfo->in_op;
04131
04132 if( addr_op == NULL || OP_load(addr_op) || OP_simulated(addr_op) )
04133 return FALSE;
04134
04135 if( !Compose_Addr( op, index_tninfo, OU_index, opnd_tn,
04136 &index_tn, &offset_tn, &scale_tn, &base_tn ) )
04137 return FALSE;
04138 }
04139
04140
04141 if( base_tn == NULL && index_tn == NULL )
04142 return FALSE;
04143
04144 TN* rip = Rip_TN();
04145 if ( index_tn == rip || base_tn == rip )
04146 return FALSE;
04147
04148 OP* new_op = Compose_Mem_Op_And_Copy_Info(op, index_tn, offset_tn, scale_tn,
04149 base_tn, actual_tninfo);
04150
04151 BB_Insert_Op_After( OP_bb(op), op, new_op);
04152
04153 if( EBO_Trace_Optimization ){
04154 #pragma mips_frequency_hint NEVER
04155 fprintf( TFile,
04156 "%sin BB:%d merge memory addr expression (from BB:%d) with offset (in BB:%d)\n",
04157 EBO_trace_pfx, BB_id(OP_bb(op)),BB_id(OP_bb(addr_op)),BB_id(OP_bb(op)) );
04158 Print_OP_No_SrcLine(addr_op);
04159 Print_OP_No_SrcLine(op);
04160
04161 fprintf(TFile, " to insert the new op:\n");
04162 Print_OP_No_SrcLine(new_op);
04163 fprintf( TFile, "\n" );
04164 }
04165
04166 return TRUE;
04167 }
04168
04169
04170
04171
04172
04173 static BOOL Check_loadbw_execute( int ld_bytes, OP* ex_op )
04174 {
04175 if( !CG_loadbw_execute ||
04176 ld_bytes > 2 ||
04177 OP_opnds( ex_op ) != 2 )
04178 return FALSE;
04179
04180 if( TN_size(OP_result(ex_op,0)) == ld_bytes )
04181 return TRUE;
04182
04183
04184
04185
04186
04187 OP* ld_op[] = { NULL, NULL };
04188
04189 for( int i = 0; i < OP_opnds( ex_op ); i++ ){
04190 TN* opnd = OP_opnd( ex_op, i );
04191 if( TN_is_register( opnd ) ){
04192 const EBO_TN_INFO* opnd_info = get_tn_info( opnd );
04193 if( opnd_info == NULL ||
04194 opnd_info->in_op == NULL )
04195 return FALSE;
04196
04197 OP* pred_op = opnd_info->in_op;
04198
04199 if( OP_icmp(ex_op) &&
04200 ( TOP_is_load_ext(OP_code(pred_op)) ||
04201 TOP_is_move_ext(OP_code(pred_op)) ) ){
04202
04203
04204
04205
04206
04207 struct SIZE_EXT_INFO pred_size_ext_info;
04208 Get_Size_Ext_Info( OP_code(pred_op), &pred_size_ext_info );
04209 if (!pred_size_ext_info.sign_ext) {
04210
04211
04212 OP *op;
04213 for (op = OP_next(ex_op); op != NULL; op = OP_next(op)) {
04214 TOP top = OP_code(op);
04215 if (OP_reads_rflags(op) &&
04216 top != TOP_je &&
04217 top != TOP_jne &&
04218 top != TOP_sete &&
04219 top != TOP_setne &&
04220 top != TOP_cmove &&
04221 top != TOP_cmovne) {
04222 return FALSE;
04223 }
04224 if (TOP_is_change_rflags(top))
04225 break;
04226 }
04227 }
04228 }
04229
04230 if( OP_load( pred_op ) ){
04231 if( CGTARG_Mem_Ref_Bytes( pred_op ) != ld_bytes )
04232 return FALSE;
04233 ld_op[i] = pred_op;
04234 }
04235
04236 } else if( TN_has_value( opnd ) ){
04237 const INT64 value = TN_value( opnd );
04238 if( ( ld_bytes == 1 &&
04239 !ISA_LC_Value_In_Class(value, LC_simm8) ) ||
04240 ( ld_bytes == 2 &&
04241 !ISA_LC_Value_In_Class(value, LC_simm16) ) )
04242 return FALSE;
04243 }
04244 }
04245
04246
04247
04248
04249 if( ld_op[0] != NULL &&
04250 ld_op[1] != NULL ){
04251 struct SIZE_EXT_INFO info0;
04252 struct SIZE_EXT_INFO info1;
04253
04254 Get_Size_Ext_Info( OP_code(ld_op[0]), &info0 );
04255 Get_Size_Ext_Info( OP_code(ld_op[1]), &info1 );
04256
04257 if( info0.sign_ext != info1.sign_ext )
04258 return FALSE;
04259 }
04260
04261 return TRUE;
04262 }
04263
04264
04265
04266
04267 static TOP
04268 Load_Execute_Format (OP *ld_op, OP *ex_op, ADDR_MODE mode)
04269 {
04270 TOP new_top = OP_code( ex_op );
04271 const int ld_bytes = CGTARG_Mem_Ref_Bytes( ld_op );
04272
04273 if( Check_loadbw_execute( ld_bytes, ex_op ) ){
04274
04275 switch( OP_code(ex_op) ){
04276 case TOP_cmp32:
04277 if( ld_bytes == 1 )
04278 new_top = TOP_cmp8;
04279 else if( ld_bytes == 2 )
04280 new_top = TOP_cmp16;
04281 break;
04282
04283 case TOP_cmpi32:
04284 if( ld_bytes == 1 )
04285 new_top = TOP_cmpi8;
04286 else if( ld_bytes == 2 )
04287 new_top = TOP_cmpi16;
04288 break;
04289
04290 case TOP_xor32:
04291 if( ld_bytes == 1 )
04292 new_top = TOP_xor8;
04293 else if( ld_bytes == 2 )
04294 new_top = TOP_xor16;
04295 break;
04296
04297 case TOP_and32:
04298 if( ld_bytes == 1 )
04299 new_top = TOP_and8;
04300 else if( ld_bytes == 2 )
04301 new_top = TOP_and16;
04302 break;
04303
04304 case TOP_or32:
04305 if( ld_bytes == 1 )
04306 new_top = TOP_or8;
04307 else if( ld_bytes == 2 )
04308 new_top = TOP_or16;
04309 break;
04310 }
04311 }
04312
04313 new_top = Get_Top_For_Addr_Mode(new_top, mode);
04314 Is_True( new_top != TOP_UNDEFINED, ("Load_Execute_Format: NYI (1)") );
04315 OP* fake_new_op = Mk_OP( new_top, NULL, NULL, NULL, NULL, NULL, NULL );
04316
04317 if( CGTARG_Mem_Ref_Bytes( fake_new_op ) > ld_bytes )
04318 new_top = TOP_UNDEFINED;
04319
04320
04321
04322 if (Is_Target_32bit() &&
04323 EBO_in_peep &&
04324 OP_opnd_size(fake_new_op, 0) == 8) {
04325 TN *opnd = OP_opnd(ex_op, 0);
04326 const REGISTER reg = TN_register(opnd);
04327 const REGISTER_SET regs =
04328 REGISTER_SUBCLASS_members(ISA_REGISTER_SUBCLASS_m32_8bit_regs);
04329 Is_True(TN_register_class(opnd) == ISA_REGISTER_CLASS_integer,
04330 ("Load_Execute_Format: opnd not integer register class"));
04331
04332 if (!REGISTER_SET_MemberP(regs, reg))
04333 new_top = TOP_UNDEFINED;
04334 }
04335
04336 return new_top;
04337 }
04338
04339
04340 static BOOL test_is_replaced( OP* alu_op, OP* test_op, const EBO_TN_INFO* tninfo )
04341 {
04342 #if Is_True_On
04343 if (!(EBO_Opt_Mask & EBO_TEST_IS_REPLACED)) return FALSE;
04344 #endif
04345 if( alu_op == NULL ||
04346 OP_bb( alu_op ) != OP_bb( test_op ) )
04347 return FALSE;
04348
04349 OP* new_op = NULL;
04350 TOP top = OP_code( alu_op );
04351
04352 if( !TOP_is_iadd( top ) &&
04353 !TOP_is_isub( top ) &&
04354 !TOP_is_ior( top ) &&
04355 !TOP_is_ixor( top ) &&
04356 !TOP_is_iand( top ) ){
04357
04358
04359
04360 if (CG_use_test)
04361 return FALSE;
04362
04363
04364
04365
04366 if( OP_load( alu_op ) &&
04367 !TN_live_out_of( OP_result(alu_op,0), OP_bb(test_op) ) ){
04368 new_op = Mk_OP( OP_code(test_op) == TOP_test64 ? TOP_cmpi64 : TOP_cmpi32,
04369 Rflags_TN(), OP_opnd(test_op,0), Gen_Literal_TN( 0, 4) );
04370 Set_OP_unrolling( new_op, OP_unrolling(test_op) );
04371 Set_OP_orig_idx( new_op, OP_map_idx(test_op) );
04372 Set_OP_unroll_bb( new_op, OP_unroll_bb(test_op) );
04373
04374 Copy_WN_For_Memory_OP( new_op, test_op );
04375 if ( OP_volatile( test_op ) )
04376 Set_OP_volatile( new_op );
04377 OP_srcpos( new_op ) = OP_srcpos( test_op );
04378 BB_Insert_Op_After( OP_bb(test_op), test_op, new_op );
04379
04380 return TRUE;
04381 }
04382
04383 return FALSE;
04384 }
04385
04386
04387
04388
04389
04390
04391 if( !TOP_is_iand( top ) )
04392 return FALSE;
04393
04394 if( !TOP_is_change_rflags(top) )
04395 return FALSE;
04396
04397
04398
04399
04400 if( OP_opnds( alu_op ) > 2 )
04401 return FALSE;
04402
04403 const TN* src1 = OP_opnd( alu_op, 0 );
04404 const TN* src2 = OP_opnd( alu_op, 1 );
04405
04406 bool test_is_redundant = false;
04407
04408
04409
04410 EBO_TN_INFO* src_info = get_tn_info( src1 );
04411 if( src_info != NULL ){
04412 if( src_info->sequence_num > tninfo->sequence_num )
04413 return FALSE;
04414
04415 if( EBO_in_loop )
04416 return FALSE;
04417
04418 OP* next = OP_next( alu_op );
04419 while( next != test_op ){
04420 const TOP top = OP_code(next);
04421 if( TOP_is_change_rflags( top ) )
04422 break;
04423 next = OP_next( next );
04424 }
04425
04426 test_is_redundant = next == test_op;
04427
04428
04429
04430
04431
04432
04433 if( src_info->sequence_num == tninfo->sequence_num )
04434 return test_is_redundant;
04435 }
04436
04437 if( TN_is_register( src2 ) ){
04438 src_info = get_tn_info( src2 );
04439 if( src_info != NULL && src_info->sequence_num >= tninfo->sequence_num ){
04440 return test_is_redundant;
04441 }
04442 }
04443
04444
04445 top = OP_code(test_op);
04446
04447 if( OP_iand( alu_op ) ){
04448 if( TN_has_value(src2) ){
04449 new_op = Mk_OP( top == TOP_test64 ? TOP_testi64 : TOP_testi32,
04450 Rflags_TN(), src1, src2 );
04451 } else
04452 new_op = Mk_OP( top, Rflags_TN(), src1, src2 );
04453
04454 } else if( OP_iadd( alu_op ) ){
04455 if( TN_has_value(src2) &&
04456 TN_value(src2) < 0 ){
04457 new_op = Mk_OP( top == TOP_test64 ? TOP_cmpi64 : TOP_cmpi32,
04458 Rflags_TN(), src1, Gen_Literal_TN( -TN_value(src2), 4) );
04459 }
04460
04461 } else if( OP_isub( alu_op ) ){
04462 Is_True( TN_is_register(src2), ("test_is_replaced: NYI (1)") );
04463 new_op = Mk_OP( top == TOP_test64 ? TOP_cmp64 : TOP_cmp32,
04464 Rflags_TN(), src1, src2 );
04465 }
04466
04467
04468
04469 if( new_op != NULL ){
04470 Set_OP_unrolling( new_op, OP_unrolling(test_op) );
04471 Set_OP_orig_idx( new_op, OP_map_idx(test_op) );
04472 Set_OP_unroll_bb( new_op, OP_unroll_bb(test_op) );
04473
04474 Copy_WN_For_Memory_OP( new_op, test_op );
04475 if ( OP_volatile( test_op ) )
04476 Set_OP_volatile( new_op );
04477 OP_srcpos( new_op ) = OP_srcpos( test_op );
04478 BB_Insert_Op_After( OP_bb(test_op), test_op, new_op );
04479
04480 if( EBO_Trace_Data_Flow ){
04481 #pragma mips_frequency_hint NEVER
04482 fprintf( TFile, "Special_Sequence replaces " );
04483 Print_OP_No_SrcLine( test_op );
04484 fprintf( TFile, " with " );
04485 Print_OP_No_SrcLine( new_op );
04486 }
04487
04488 return TRUE;
04489 }
04490
04491 return test_is_redundant;
04492 }
04493
04494
04495
04496
04497
04498
04499 void Update_op_must_not_be_moved( OP* store_op, EBO_TN_INFO** opnd_tninfo )
04500 {
04501 if( Alias_Manager == NULL )
04502 return;
04503
04504 if( OP_has_implicit_interactions(store_op) || OP_unalign_mem(store_op) )
04505 return;
04506
04507 Is_True( OP_store(store_op),
04508 ("Update_op_must_not_be_moved: must be a store operation") );
04509
04510 const INT hash_value = EBO_hash_op( store_op, opnd_tninfo );
04511 EBO_OP_INFO* opinfo = EBO_opinfo_table[hash_value];
04512
04513 while( opinfo != NULL ){
04514 OP* load_op = opinfo->in_op;
04515 if( !opinfo->op_must_not_be_moved &&
04516 load_op != NULL &&
04517 OP_load( load_op ) ){
04518 WN* pred_wn = OP_hoisted(load_op) ? NULL : Get_WN_From_Memory_OP(load_op);
04519 WN* succ_wn = OP_hoisted(store_op) ? NULL : Get_WN_From_Memory_OP(store_op);
04520
04521 if( (pred_wn != NULL) && (succ_wn != NULL) ){
04522 const ALIAS_RESULT result = Aliased( Alias_Manager, pred_wn, succ_wn );
04523 if( result == POSSIBLY_ALIASED || result == SAME_LOCATION ){
04524 opinfo->op_must_not_be_moved = TRUE;
04525 }
04526 }
04527 }
04528
04529 opinfo = opinfo->same;
04530 }
04531 }
04532
04533 static hTN_MAP32 _load_exec_map = NULL;
04534
04535
04536
04537
04538
04539
04540
04541 void Init_Load_Exec_Map( BB* bb, MEM_POOL* pool )
04542 {
04543 _load_exec_map = hTN_MAP32_Create( pool );
04544
04545 TN *last_TN[ISA_REGISTER_CLASS_MAX+1][REGISTER_MAX+1];
04546
04547 if (EBO_in_peep) {
04548 memset(last_TN, 0,
04549 sizeof(TN*) * (ISA_REGISTER_CLASS_MAX + 1) * (REGISTER_MAX + 1));
04550 }
04551
04552 OP* op = NULL;
04553 FOR_ALL_BB_OPs_FWD( bb, op ){
04554 if( OP_load( op ) ){
04555 TN* tn = OP_result( op, 0 );
04556
04557
04558
04559
04560 if (!EBO_in_peep &&
04561 TN_live_out_of(tn, bb)) {
04562 hTN_MAP32_Set( _load_exec_map, tn, CG_load_execute + 2 );
04563
04564 } else {
04565 const INT32 uses = hTN_MAP32_Get( _load_exec_map, tn ) - 1;
04566
04567
04568
04569
04570
04571 if( uses <= CG_load_execute ){
04572 hTN_MAP32_Set( _load_exec_map, tn, 1 );
04573 }
04574 }
04575 }
04576
04577 for( int i = 0; i < OP_opnds(op); i++ ){
04578 TN* opnd = OP_opnd( op, i );
04579 if( TN_is_register( opnd ) ){
04580 const INT32 uses = hTN_MAP32_Get( _load_exec_map, opnd );
04581 if( uses > 0 ){
04582 hTN_MAP32_Set( _load_exec_map, opnd, uses+1 );
04583 }
04584 }
04585 }
04586
04587
04588 if (EBO_in_peep) {
04589 for (int i = 0; i < OP_results(op); i++) {
04590 TN *tn = OP_result(op, i);
04591 last_TN[TN_register_class(tn)][TN_register(tn)] = tn;
04592 }
04593 }
04594 }
04595
04596
04597
04598 if (EBO_in_peep) {
04599 ISA_REGISTER_CLASS cl;
04600 FOR_ALL_ISA_REGISTER_CLASS(cl) {
04601 for (REGISTER reg = 0; reg <= REGISTER_MAX; reg++) {
04602 if (last_TN[cl][reg] &&
04603 (EBO_no_liveness_info_available ||
04604 REG_LIVE_Outof_BB(cl, reg, bb))) {
04605 hTN_MAP32_Set(_load_exec_map, last_TN[cl][reg], CG_load_execute + 2);
04606 }
04607 }
04608 }
04609 }
04610 }
04611
04612
04613 BOOL EBO_Load_Execution( OP* alu_op, TN** opnd_tn, EBO_TN_INFO** actual_tninfo )
04614 {
04615 #if Is_True_On
04616 if (!(EBO_Opt_Mask & EBO_LOAD_EXECUTION)) return FALSE;
04617 #endif
04618 const TOP top = OP_code(alu_op);
04619
04620 if( top == TOP_xor64 ||
04621 top == TOP_or64 ||
04622 top == TOP_and64 ||
04623 top == TOP_cmp64 ||
04624 top == TOP_test64 )
04625 return FALSE;
04626
04627 if (TOP_is_load_exe(top) ||
04628 Get_Top_For_Addr_Mode(top, BASE_MODE) == TOP_UNDEFINED ||
04629 !TOP_is_load_exe(Get_Top_For_Addr_Mode(top, BASE_MODE)))
04630 return FALSE;
04631
04632 if( OP_opnds(alu_op) == 2 &&
04633 TN_is_register( OP_opnd(alu_op,1) ) &&
04634 TNs_Are_Equivalent( OP_opnd(alu_op,0), OP_opnd(alu_op,1) ) )
04635 return FALSE;
04636
04637 EBO_TN_INFO* tninfo = NULL;
04638 int opnd0_indx = 0;
04639
04640 for( int i = OP_opnds(alu_op) - 1; i >= 0; i-- ){
04641 if( TN_is_register( OP_opnd( alu_op, i ) ) ){
04642 tninfo = actual_tninfo[i];
04643 opnd0_indx = OP_opnds(alu_op) - 1 - i;
04644 Is_True( opnd0_indx >= 0, ("NYI") );
04645 break;
04646 }
04647 }
04648
04649 OP* ld_op = tninfo == NULL ? NULL : tninfo->in_op;
04650 EBO_OP_INFO* ld_opinfo = tninfo == NULL ? NULL : tninfo->in_opinfo;
04651
04652 if( ld_op == NULL || !OP_load( ld_op ) ||
04653 ld_opinfo->op_must_not_be_moved ){
04654
04655
04656
04657 if( !TOP_is_commutative( OP_code(alu_op) ) )
04658 return FALSE;
04659
04660 tninfo = actual_tninfo[0];
04661 ld_op = tninfo == NULL ? NULL : tninfo->in_op;
04662 ld_opinfo = tninfo == NULL ? NULL : tninfo->in_opinfo;
04663
04664 if( ld_op == NULL || !OP_load( ld_op ) ||
04665 ld_opinfo->op_must_not_be_moved )
04666 return FALSE;
04667
04668
04669 TN* result = OP_result( alu_op, 0 );
04670 TN* opnd0 = OP_opnd( alu_op, 0 );
04671
04672 if( EBO_in_peep && TNs_Are_Equivalent( result, opnd0 ) )
04673 return FALSE;
04674
04675 opnd0_indx = 1;
04676 }
04677
04678 BB* bb = OP_bb( alu_op );
04679
04680 if( OP_bb( ld_op ) != bb )
04681 return FALSE;
04682
04683
04684
04685
04686
04687
04688
04689
04690 if( OP_unalign_mem( ld_op ) &&
04691 TOP_is_vector_op( OP_code(ld_op) ) ){
04692 return FALSE;
04693 }
04694
04695
04696
04697
04698
04699 const int index_reg = OP_find_opnd_use( ld_op, OU_index );
04700 const int base_reg = OP_find_opnd_use( ld_op, OU_base );
04701
04702 ADDR_MODE mode = BASE_MODE;
04703
04704 if( index_reg < 0 && base_reg < 0 )
04705 mode = N32_MODE;
04706
04707 else if( index_reg >= 0 )
04708 mode = base_reg < 0 ? INDEX_MODE : BASE_INDEX_MODE;
04709
04710 if( mode == N32_MODE ){
04711
04712
04713 return FALSE;
04714 }
04715
04716 if( index_reg >= 0 ){
04717 const TN* opnd = OP_opnd( ld_op, index_reg );
04718 const EBO_TN_INFO* ptinfo = get_tn_info( opnd );
04719 if( ptinfo != NULL && ptinfo->sequence_num >= tninfo->sequence_num ){
04720 return FALSE;
04721 }
04722 }
04723
04724 if( base_reg >= 0 ){
04725 const TN* opnd = OP_opnd( ld_op, base_reg );
04726 const EBO_TN_INFO* ptinfo = get_tn_info( opnd );
04727 if( ptinfo != NULL && ptinfo->sequence_num >= tninfo->sequence_num ){
04728 return FALSE;
04729 }
04730 }
04731
04732
04733
04734
04735
04736 {
04737 const INT hash_value = EBO_hash_op( ld_op, NULL );
04738 EBO_OP_INFO* opinfo = EBO_opinfo_table[hash_value];
04739
04740 while( opinfo != NULL ){
04741 OP* pred_op = opinfo->in_op;
04742
04743 if( pred_op == ld_op )
04744 break;
04745
04746
04747 if(
04748 #ifdef KEY
04749 pred_op &&
04750 #endif
04751 OP_store( pred_op ) )
04752 return FALSE;
04753
04754 opinfo = opinfo->same;
04755 }
04756 }
04757
04758 const TOP new_top = Load_Execute_Format( ld_op, alu_op, mode );
04759
04760 if( new_top == TOP_UNDEFINED )
04761 return FALSE;
04762
04763 const INT32 load_uses = hTN_MAP32_Get( _load_exec_map, OP_result(ld_op,0) ) - 1;
04764
04765
04766
04767 if( ( load_uses > CG_load_execute ) &&
04768 ( CGTARG_Latency(top) < CGTARG_Latency(new_top) ) ){
04769 return FALSE;
04770 }
04771
04772
04773
04774 if (OP_volatile(ld_op) &&
04775 load_uses != 1) {
04776 return FALSE;
04777 }
04778
04779 TN* offset = OP_opnd( ld_op, OP_find_opnd_use( ld_op, OU_offset ) );
04780 TN* base = base_reg >= 0 ? OP_opnd( ld_op, base_reg ) : NULL;
04781 TN* index = index_reg >= 0 ? OP_opnd( ld_op, index_reg ) : NULL;
04782 TN* result = OP_has_result( alu_op ) ? OP_result( alu_op, 0 ) : NULL;
04783 TN* scale = index_reg >= 0 ?
04784 OP_opnd( ld_op, OP_find_opnd_use( ld_op, OU_scale ) ) : NULL;
04785
04786 TN* opnd1 = NULL;
04787 TN* opnd0 = OP_opnd( alu_op, opnd0_indx );
04788
04789
04790 if( opnd0_indx == 1 && TN_has_value(opnd0) ){
04791 opnd1 = opnd0;
04792 opnd0 = NULL;
04793 }
04794
04795 OP* new_op = NULL;
04796
04797 if( mode == BASE_MODE ){
04798
04799 if( OP_opnds(alu_op) == 1 ){
04800 if( result == NULL )
04801 new_op = Mk_OP( new_top, base, offset );
04802 else
04803 new_op = Mk_OP( new_top, result, base, offset );
04804 } else if( opnd1 != NULL )
04805 new_op = Mk_OP( new_top, result, base, offset, opnd1 );
04806 else
04807 new_op = Mk_OP( new_top, result, opnd0, base, offset );
04808
04809 } else if( mode == BASE_INDEX_MODE ){
04810
04811 if( OP_opnds(alu_op) == 1 ){
04812 if( result == NULL )
04813 new_op = Mk_OP( new_top, base, index, scale, offset );
04814 else
04815 new_op = Mk_OP( new_top, result, base, index, scale, offset );
04816
04817 } else if( opnd1 != NULL )
04818 new_op = Mk_OP( new_top, result, base, index, scale, offset, opnd1 );
04819 else
04820 new_op = Mk_OP( new_top, result, opnd0, base, index, scale, offset );
04821
04822 } else {
04823
04824 if( OP_opnds(alu_op) == 1 ){
04825 if( result == NULL )
04826 new_op = Mk_OP( new_top, index, scale, offset );
04827 else
04828 new_op = Mk_OP( new_top, result, index, scale, offset );
04829 } else if( opnd1 != NULL )
04830 new_op = Mk_OP( new_top, result, index, scale, offset, opnd1 );
04831 else
04832 new_op = Mk_OP( new_top, result, opnd0, index, scale, offset );
04833 }
04834
04835 Is_True( !EBO_in_loop, ("EBO_Load_Execution: NYI (1)") );
04836
04837 Set_OP_unrolling( new_op, OP_unrolling(alu_op) );
04838 Set_OP_orig_idx( new_op, OP_map_idx(alu_op) );
04839 Set_OP_unroll_bb( new_op, OP_unroll_bb(alu_op) );
04840
04841 Copy_WN_For_Memory_OP( new_op, ld_op );
04842 if (OP_volatile(ld_op)) {
04843 Reset_OP_volatile(ld_op);
04844 Set_OP_volatile(new_op);
04845 }
04846 OP_srcpos( new_op ) = OP_srcpos( alu_op );
04847 BB_Insert_Op_After( bb, alu_op, new_op );
04848
04849
04850
04851 ST *spill_loc = CGSPILL_OP_Spill_Location(ld_op);
04852 if (spill_loc != (ST *)0) {
04853 SPILL_SYM_INFO &info = CGSPILL_Get_Spill_Sym_Info(spill_loc);
04854 info.Set_Used_By_Load_Exe();
04855 }
04856
04857 if( EBO_Trace_Data_Flow ){
04858 #pragma mips_frequency_hint NEVER
04859 fprintf( TFile, "EBO_Load_Execution merges " );
04860 Print_OP_No_SrcLine( ld_op );
04861 fprintf( TFile, " with " );
04862 Print_OP_No_SrcLine( alu_op );
04863
04864 fprintf( TFile, " new op " );
04865 Print_OP_No_SrcLine( new_op );
04866 }
04867
04868 return TRUE;
04869 }
04870
04871 static INT
04872 Get_Power_Of_2 (INT val)
04873 {
04874 INT i, pow2mask;
04875
04876 pow2mask = 1;
04877 for ( i = 0; i < 5; ++i ) {
04878 if (val == pow2mask) return i;
04879 pow2mask <<= 1;
04880 }
04881
04882 FmtAssert(FALSE, ("Get_Power_Of_2 unexpected value (%d)", val));
04883
04884 }
04885
04886 BOOL
04887 Check_No_Use_Between (OP* from, OP* to, TN* result)
04888 {
04889 if (!TN_is_register(result))
04890 return FALSE;
04891
04892 for (OP* op = from->next; op && op != to; op = op->next) {
04893 for (INT i = 0; i < OP_opnds(op); i ++) {
04894 TN* opnd = OP_opnd(op, i);
04895 if (TN_is_register(opnd)) {
04896 if (TNs_Are_Equivalent(result, opnd))
04897 return FALSE;
04898
04899
04900
04901
04902 if (result == SP_TN &&
04903 TNs_Are_Equivalent(FP_TN, opnd))
04904 return FALSE;
04905 }
04906 }
04907 }
04908
04909 return TRUE;
04910 }
04911
04912 static BOOL
04913 alu_op_defines_rflags_used (OP* alu_op, OP* op)
04914 {
04915
04916
04917 if (TOP_is_change_rflags( OP_code(alu_op) )) {
04918 BOOL rflags_read = FALSE;
04919 for( OP* next_op = OP_next(alu_op); next_op != NULL && next_op != op;
04920 next_op = OP_next( next_op ) ){
04921 if( OP_reads_rflags( next_op ) )
04922 rflags_read = TRUE;
04923 if( TOP_is_change_rflags( OP_code(next_op) ) )
04924 break;
04925 }
04926 if (rflags_read)
04927 return TRUE;
04928 }
04929
04930 return FALSE;
04931 }
04932
04933 BOOL
04934 EBO_Lea_Insertion( OP* op, TN** opnd_tn, EBO_TN_INFO** actual_tninfo )
04935 {
04936 #if Is_True_On
04937 if (!(EBO_Opt_Mask & EBO_LEA_INSERTION)) return FALSE;
04938 #endif
04939 TOP code = OP_code (op);
04940 OP* new_op = NULL;
04941 INT64 offset, offset_tmp;
04942 INT shift;
04943 ST *base, *base_tmp;
04944 BOOL rflags_read = FALSE;
04945
04946
04947
04948 for( OP* next_op = OP_next(op); next_op != NULL;
04949 next_op = OP_next( next_op ) ){
04950 if( OP_reads_rflags( next_op ) )
04951 rflags_read = TRUE;
04952 if( TOP_is_change_rflags( OP_code(next_op) ) )
04953 break;
04954 }
04955
04956 switch (code) {
04957 case TOP_imul32:
04958 case TOP_imul64:
04959 {
04960 if (!CG_fold_constimul)
04961 break;
04962
04963 OP* alu_op = actual_tninfo[1]->in_op;
04964 if (alu_op && alu_op->bb == op->bb &&
04965 (OP_code(alu_op) == TOP_ldc32 ||
04966 OP_code(alu_op) == TOP_ldc64) &&
04967 !TN_is_symbol(OP_opnd(alu_op, 0)) &&
04968 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
04969 ((op->next != NULL &&
04970 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
04971 (op->next == NULL &&
04972 !GTN_SET_MemberP(BB_live_out(OP_bb(op)),
04973 OP_result(alu_op, 0)))) &&
04974 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0))) {
04975 INT32 val = (INT32)TN_value(OP_opnd(alu_op, 0));
04976 INT64 val64 = TN_value(OP_opnd(alu_op, 0));
04977 BOOL is_double = (code == TOP_imul64);
04978
04979 val64 *= val64;
04980 if (TNs_Are_Equivalent(OP_opnd(op, 0), OP_opnd(op, 1)))
04981 new_op = Mk_OP (is_double?TOP_ldc64:TOP_ldc32,
04982 OP_result(op, 0),
04983 Gen_Literal_TN(is_double?(INT64)val64:(INT32)val*val,
04984 is_double?8:4));
04985 else if (OP_code(alu_op) == TOP_ldc64) {
04986 if (!ISA_LC_Value_In_Class (TN_value(OP_opnd(alu_op, 0)), LC_simm32))
04987 break;
04988 }
04989 if (!new_op)
04990 new_op = Mk_OP ((code == TOP_imul32)?TOP_imuli32:TOP_imuli64,
04991 OP_result(op, 0), OP_opnd(op, 0),
04992 Gen_Literal_TN(val, 4));
04993
04994 if (alu_op_defines_rflags_used(alu_op, op))
04995 return FALSE;
04996
04997 OP_srcpos( new_op ) = OP_srcpos( op );
04998 if( EBO_Trace_Data_Flow ){
04999 fprintf( TFile, "Lea_Insertion merges " );
05000 Print_OP_No_SrcLine(op);
05001 fprintf( TFile, "and " );
05002 Print_OP_No_SrcLine(alu_op);
05003 fprintf( TFile, "with " );
05004 Print_OP_No_SrcLine(new_op);
05005 }
05006 dec_ref_count(actual_tninfo[1]);
05007 break;
05008 }
05009 if (TN_is_register(OP_opnd(op, 0)) &&
05010 !TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0)) ) {
05011
05012
05013 OP* alu_op = actual_tninfo[0]->in_op;
05014 if (alu_op && alu_op->bb == op->bb &&
05015 (OP_code(alu_op) == TOP_ldc32 ||
05016 OP_code(alu_op) == TOP_ldc64) &&
05017 !TN_is_symbol(OP_opnd(alu_op, 0)) &&
05018 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05019 ((op->next != NULL &&
05020 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05021 (op->next == NULL &&
05022 !GTN_SET_MemberP(BB_live_out(OP_bb(op)),
05023 OP_result(alu_op, 0)))) &&
05024 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0))) {
05025 INT32 val = (INT32)TN_value(OP_opnd(alu_op, 0));
05026 if (OP_code(alu_op) == TOP_ldc64) {
05027 if (!ISA_LC_Value_In_Class (TN_value(OP_opnd(alu_op, 0)), LC_simm32))
05028 break;
05029 }
05030 new_op = Mk_OP ((code == TOP_imul32)?TOP_imuli32:TOP_imuli64,
05031 OP_result(op, 0), OP_opnd(op, 1),
05032 Gen_Literal_TN(val, 4));
05033
05034 if (alu_op_defines_rflags_used(alu_op, op))
05035 return FALSE;
05036
05037 OP_srcpos( new_op ) = OP_srcpos( op );
05038 if( EBO_Trace_Data_Flow ){
05039 fprintf( TFile, "Lea_Insertion merges " );
05040 Print_OP_No_SrcLine(op);
05041 fprintf( TFile, "and " );
05042 Print_OP_No_SrcLine(alu_op);
05043 fprintf( TFile, "with " );
05044 Print_OP_No_SrcLine(new_op);
05045 }
05046 dec_ref_count(actual_tninfo[0]);
05047 }
05048 }
05049 break;
05050 }
05051 case TOP_add32:
05052 case TOP_add64:
05053 {
05054 OP* alu_op = actual_tninfo[0]->in_op;
05055 if( TN_is_register(OP_opnd(op, 0)) &&
05056 TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0)) ) {
05057 if (alu_op && alu_op->bb == op->bb &&
05058 ((OP_code(alu_op) == TOP_leax32 && code == TOP_add32) ||
05059 (OP_code(alu_op) == TOP_leax64 && code == TOP_add64)) &&
05060 TN_value(OP_opnd(alu_op, 2)) == 1 &&
05061 !TN_is_symbol(OP_opnd(alu_op, 3)) &&
05062 TN_value(OP_opnd(alu_op, 3)) == 0 &&
05063 TN_is_register(OP_opnd(alu_op, 0)) &&
05064 TN_is_register(OP_opnd(alu_op, 1)) &&
05065 TN_is_register(OP_opnd(op, 1)) &&
05066 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(op, 1)) &&
05067 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(alu_op, 1)) &&
05068 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0)) &&
05069 Pred_Opnd_Avail(op, actual_tninfo[0], 0)) {
05070 new_op = Mk_OP ((code == TOP_add32)?TOP_leax32:TOP_leax64,
05071 OP_result(op, 0), OP_opnd(alu_op, 0),
05072 OP_opnd(alu_op, 1),
05073 Gen_Literal_TN(2, 4), Gen_Literal_TN(0, 4));
05074
05075 if (rflags_read &&
05076 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05077 !TOP_is_change_rflags( OP_code(op) )) ||
05078 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05079 TOP_is_change_rflags( OP_code(op) ))))
05080 return FALSE;
05081
05082 if (alu_op_defines_rflags_used(alu_op, op))
05083 return FALSE;
05084
05085 OP_srcpos( new_op ) = OP_srcpos( op );
05086 if( EBO_Trace_Data_Flow ){
05087 fprintf( TFile, "Lea_Insertion merges " );
05088 Print_OP_No_SrcLine(op);
05089 fprintf( TFile, "and " );
05090 Print_OP_No_SrcLine(alu_op);
05091 fprintf( TFile, "with " );
05092 Print_OP_No_SrcLine(new_op);
05093 }
05094 BB_Remove_Op(OP_bb(alu_op), alu_op);
05095 } else {
05096
05097
05098
05099 alu_op = actual_tninfo[1]->in_op;
05100 if (alu_op && alu_op->bb == op->bb &&
05101 ((OP_code(alu_op) == TOP_leaxx32 && code == TOP_add32) ||
05102 (OP_code(alu_op) == TOP_leaxx64 && code == TOP_add64)) &&
05103 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05104 ((op->next != NULL &&
05105 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05106 (op->next == NULL &&
05107 !GTN_SET_MemberP(BB_live_out(OP_bb(op)),
05108 OP_result(alu_op, 0)))) &&
05109 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0))) {
05110
05111 EBO_TN_INFO *src0_info, *src1_info;
05112 src0_info = get_tn_info( OP_opnd(op, 1));
05113 src1_info = get_tn_info( OP_result(alu_op, 0));
05114 if (src0_info->sequence_num > src1_info->sequence_num)
05115 break;
05116
05117
05118 if (!Pred_Opnd_Avail(op, actual_tninfo[1], 0))
05119 break;
05120
05121 new_op = Mk_OP ((code == TOP_add32)?TOP_leax32:TOP_leax64,
05122 OP_result(op, 0), OP_opnd(op, 0),
05123 OP_opnd(alu_op, 0), OP_opnd(alu_op, 1),
05124 OP_opnd(alu_op, 2));
05125
05126 if (rflags_read &&
05127 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05128 !TOP_is_change_rflags( OP_code(op) )) ||
05129 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05130 TOP_is_change_rflags( OP_code(op) ))))
05131 return FALSE;
05132
05133 if (alu_op_defines_rflags_used(alu_op, op))
05134 return FALSE;
05135
05136 OP_srcpos( new_op ) = OP_srcpos( op );
05137 if( EBO_Trace_Data_Flow ){
05138 fprintf( TFile, "Lea_Insertion merges " );
05139 Print_OP_No_SrcLine(op);
05140 fprintf( TFile, "and " );
05141 Print_OP_No_SrcLine(alu_op);
05142 fprintf( TFile, "with " );
05143 Print_OP_No_SrcLine(new_op);
05144 }
05145 BB_Remove_Op(OP_bb(alu_op), alu_op);
05146 }
05147 }
05148
05149 break;
05150 }
05151
05152
05153 if (alu_op && alu_op->bb == op->bb &&
05154 ((OP_code(alu_op) == TOP_leax32 && code == TOP_add32) ||
05155 (OP_code(alu_op) == TOP_leax64 && code == TOP_add64)) &&
05156 TN_value(OP_opnd(alu_op, 2)) == 1 &&
05157 !TN_is_symbol(OP_opnd(alu_op, 3)) &&
05158 TN_value(OP_opnd(alu_op, 3)) == 0 &&
05159 TN_is_register(OP_opnd(alu_op, 0)) &&
05160 TN_is_register(OP_opnd(alu_op, 1)) &&
05161 TN_is_register(OP_opnd(op, 1)) &&
05162 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(op, 1)) &&
05163 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(alu_op, 1)) &&
05164 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05165 ((op->next != NULL &&
05166 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05167 (op->next == NULL &&
05168 !GTN_SET_MemberP(BB_live_out(OP_bb(op)), OP_result(alu_op, 0)))) &&
05169 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0))) {
05170 EBO_TN_INFO *src0_info, *src1_info;
05171 src0_info = get_tn_info( OP_opnd(op, 1));
05172 src1_info = get_tn_info( OP_opnd(alu_op, 0));
05173
05174 if (src0_info && src1_info &&
05175 src0_info->sequence_num > src1_info->sequence_num) {
05176 new_op = Mk_OP ((code == TOP_add32)?TOP_leax32:TOP_leax64,
05177 OP_result(op, 0), OP_opnd(alu_op, 0),
05178 OP_opnd(alu_op, 1),
05179 Gen_Literal_TN(2, 4), Gen_Literal_TN(0, 4));
05180
05181 if (rflags_read &&
05182 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05183 !TOP_is_change_rflags( OP_code(op) )) ||
05184 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05185 TOP_is_change_rflags( OP_code(op) ))))
05186 return FALSE;
05187
05188 if (alu_op_defines_rflags_used(alu_op, op))
05189 return FALSE;
05190
05191 OP_srcpos( new_op ) = OP_srcpos( op );
05192 if( EBO_Trace_Data_Flow ){
05193 fprintf( TFile, "Lea_Insertion merges " );
05194 Print_OP_No_SrcLine(op);
05195 fprintf( TFile, "and " );
05196 Print_OP_No_SrcLine(alu_op);
05197 fprintf( TFile, "with " );
05198 Print_OP_No_SrcLine(new_op);
05199 }
05200 BB_Remove_Op(OP_bb(alu_op), alu_op);
05201 break;
05202 }
05203 }
05204
05205
05206 if (OP_opnd(op, 1) == SP_TN || OP_opnd(op, 1) == FP_TN) {
05207
05208 if (EBO_in_peep) break;
05209
05210 if (OP_opnd(op, 0) == SP_TN || OP_opnd(op, 0) == FP_TN) break;
05211 new_op = Mk_OP ((code == TOP_add32)?TOP_leax32:TOP_leax64,
05212 OP_result(op, 0), OP_opnd(op, 1), OP_opnd(op, 0),
05213 Gen_Literal_TN(1, 4), Gen_Literal_TN(0, 4));
05214 } else
05215 new_op = Mk_OP ((code == TOP_add32)?TOP_leax32:TOP_leax64,
05216 OP_result(op, 0), OP_opnd(op, 0), OP_opnd(op, 1),
05217 Gen_Literal_TN(1, 4), Gen_Literal_TN(0, 4));
05218
05219 if (rflags_read &&
05220 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05221 !TOP_is_change_rflags( OP_code(op) )) ||
05222 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05223 TOP_is_change_rflags( OP_code(op) ))))
05224 return FALSE;
05225
05226 OP_srcpos( new_op ) = OP_srcpos( op );
05227 if( EBO_Trace_Data_Flow ){
05228 fprintf( TFile, "Lea_Insertion removes " );
05229 Print_OP_No_SrcLine(op);
05230 fprintf( TFile, "Lea_Insertion inserts " );
05231 Print_OP_No_SrcLine(new_op);
05232 }
05233 break;
05234 }
05235 case TOP_addi32:
05236 case TOP_addi64:
05237 {
05238 base = base_tmp = NULL;
05239 offset = offset_tmp = 0;
05240 if (TN_is_symbol (OP_opnd(op, 1))) {
05241 if (!EBO_in_peep)
05242
05243 break;
05244 TN *t = OP_opnd(op, 1);
05245 Base_Symbol_And_Offset (TN_var(t), &base, &offset);
05246 if (base == SP_Sym || base == FP_Sym) {
05247 offset += TN_offset(t);
05248 if ( TN_is_reloc_neg(t) )
05249 offset = -offset;
05250 if ( TN_is_reloc_low16(t) )
05251 offset = offset & 0xffff;
05252 else if ( TN_is_reloc_high16(t) )
05253 offset = ( ( offset - (short)offset ) >> 16) & 0xffff;
05254 else if ( TN_is_reloc_higher(t) )
05255 offset = ( ( offset + 0x80008000LL ) >> 32 ) & 0xffff;
05256 else if ( TN_is_reloc_highest(t) )
05257 offset = ( ( offset + 0x800080008000LL ) >> 48 ) & 0xffff;
05258 }
05259
05260 } else
05261 offset = TN_value(OP_opnd(op, 1));
05262
05263 if( TN_is_register(OP_opnd(op, 0)) &&
05264 TN_is_register(OP_result(op, 0)) &&
05265 TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0)) ) {
05266 OP* alu_op = actual_tninfo[0]->in_op;
05267 if (alu_op && alu_op->bb && alu_op->bb == op->bb &&
05268 OP_code(alu_op) == code &&
05269 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0))) {
05270 if (TN_is_symbol (OP_opnd(alu_op, 1))) {
05271 if (!EBO_in_peep)
05272
05273 break;
05274 TN *tmp = OP_opnd(alu_op, 1);
05275 Base_Symbol_And_Offset (TN_var(tmp), &base_tmp, &offset_tmp);
05276 if (base != base_tmp)
05277 break;
05278 if (base_tmp == SP_Sym || base_tmp == FP_Sym) {
05279 offset_tmp += TN_offset(tmp);
05280 if ( TN_is_reloc_neg(tmp) )
05281 offset_tmp = -offset_tmp;
05282 if ( TN_is_reloc_low16(tmp) )
05283 offset_tmp = offset_tmp & 0xffff;
05284 else if ( TN_is_reloc_high16(tmp) )
05285 offset_tmp =
05286 ( ( offset_tmp - (short)offset_tmp ) >> 16) & 0xffff;
05287 else if ( TN_is_reloc_higher(tmp) )
05288 offset_tmp = ( ( offset_tmp + 0x80008000LL ) >> 32 ) & 0xffff;
05289 else if ( TN_is_reloc_highest(tmp) )
05290 offset_tmp =
05291 ( ( offset_tmp + 0x800080008000LL ) >> 48 ) & 0xffff;
05292 }
05293
05294 } else
05295 offset_tmp = TN_value(OP_opnd(alu_op, 1));
05296
05297
05298 if (ISA_LC_Value_In_Class (offset+offset_tmp, LC_simm32)) {
05299 TN* offset_tn = NULL;
05300 if (TN_is_symbol(OP_opnd(op, 1)) &&
05301 base && base != SP_Sym && base != FP_Sym)
05302 offset_tn = Gen_Symbol_TN( TN_var(OP_opnd(op, 0)),
05303 TN_offset(OP_opnd(op, 0))+
05304 offset+offset_tmp,0);
05305 new_op = Mk_OP ((code == TOP_addi32)?TOP_addi32:TOP_addi64,
05306 OP_result(op, 0), OP_opnd(op, 0),
05307 offset_tn? offset_tn:
05308 Gen_Literal_TN(offset+offset_tmp, 4));
05309
05310 if (rflags_read &&
05311 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05312 !TOP_is_change_rflags( OP_code(op) )) ||
05313 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05314 TOP_is_change_rflags( OP_code(op) ))))
05315 return FALSE;
05316
05317 if (alu_op_defines_rflags_used(alu_op, op))
05318 return FALSE;
05319
05320 OP_srcpos( new_op ) = OP_srcpos( op );
05321 if( EBO_Trace_Data_Flow ){
05322 fprintf( TFile, "Lea_Insertion merges " );
05323 Print_OP_No_SrcLine(op);
05324 fprintf( TFile, "and " );
05325 Print_OP_No_SrcLine(alu_op);
05326 fprintf( TFile, "with " );
05327 Print_OP_No_SrcLine(new_op);
05328 }
05329
05330 BB_Remove_Op(OP_bb(alu_op), alu_op);
05331 }
05332 }
05333 break;
05334 }
05335
05336
05337 if (ISA_LC_Value_In_Class (offset, LC_simm32))
05338 new_op = Mk_OP ((code == TOP_addi32)?TOP_lea32:TOP_lea64,
05339 OP_result(op, 0), OP_opnd(op, 0), OP_opnd(op, 1));
05340
05341 if (rflags_read && new_op &&
05342 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05343 !TOP_is_change_rflags( OP_code(op) )) ||
05344 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05345 TOP_is_change_rflags( OP_code(op) ))))
05346 return FALSE;
05347
05348 OP_srcpos( new_op ) = OP_srcpos( op );
05349 if (new_op) {
05350 if( EBO_Trace_Data_Flow ){
05351 fprintf( TFile, "Lea_Insertion removes " );
05352 Print_OP_No_SrcLine(op);
05353 fprintf( TFile, "Lea_Insertion inserts " );
05354 Print_OP_No_SrcLine(new_op);
05355 }
05356 }
05357 break;
05358 }
05359 case TOP_shli32:
05360 case TOP_shli64:
05361 {
05362
05363
05364 if( (TN_is_register(OP_opnd(op, 0)) &&
05365 !TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0)))) {
05366
05367 shift = TN_value(OP_opnd(op,1));
05368 if (shift != 0 && shift != 1 && shift != 2 && shift != 3)
05369 break;
05370
05371 shift = 1 << shift;
05372
05373
05374 new_op = Mk_OP ((code == TOP_shli32)?TOP_leaxx32:TOP_leaxx64,
05375 OP_result(op, 0), OP_opnd(op, 0),
05376 Gen_Literal_TN(shift, 4),
05377 Gen_Literal_TN(0, 4));
05378 }
05379
05380 if (rflags_read && new_op &&
05381 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05382 !TOP_is_change_rflags( OP_code(op) )) ||
05383 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05384 TOP_is_change_rflags( OP_code(op) ))))
05385 return FALSE;
05386
05387 if (new_op) {
05388 if( EBO_Trace_Data_Flow ){
05389 fprintf( TFile, "Lea_Insertion removes " );
05390 Print_OP_No_SrcLine(op);
05391 fprintf( TFile, "Lea_Insertion inserts " );
05392 Print_OP_No_SrcLine(new_op);
05393 }
05394 }
05395 break;
05396 }
05397 case TOP_lea32:
05398 case TOP_lea64:
05399 {
05400 if (TN_is_symbol (OP_opnd(op, 1))) {
05401 if (!EBO_in_peep)
05402
05403 break;
05404 TN *t = OP_opnd(op, 1);
05405 Base_Symbol_And_Offset (TN_var(t), &base, &offset);
05406 if (base == SP_Sym || base == FP_Sym) {
05407 offset += TN_offset(t);
05408 if ( TN_is_reloc_neg(t) )
05409 offset = -offset;
05410 if ( TN_is_reloc_low16(t) )
05411 offset = offset & 0xffff;
05412 else if ( TN_is_reloc_high16(t) )
05413 offset = ( ( offset - (short)offset ) >> 16) & 0xffff;
05414 else if ( TN_is_reloc_higher(t) )
05415 offset = ( ( offset + 0x80008000LL ) >> 32 ) & 0xffff;
05416 else if ( TN_is_reloc_highest(t) )
05417 offset = ( ( offset + 0x800080008000LL ) >> 48 ) & 0xffff;
05418 }
05419
05420 } else
05421 offset = TN_value(OP_opnd(op, 1));
05422
05423
05424 OP* alu_op = actual_tninfo[0]->in_op;
05425 if (alu_op && alu_op->bb == op->bb &&
05426 ((OP_code(op) == TOP_lea32 &&
05427 (OP_code(alu_op) == TOP_addi32 ||
05428 OP_code(alu_op) == TOP_lea32)) ||
05429 (OP_code(op) == TOP_lea64 &&
05430 (OP_code(alu_op) == TOP_addi64 ||
05431 OP_code(alu_op) == TOP_lea64))) &&
05432
05433 (!TN_is_symbol (OP_opnd(alu_op, 1)) || EBO_in_peep) &&
05434
05435 (!TN_is_symbol (OP_opnd(op, 1)) ||
05436 !TN_is_symbol (OP_opnd(alu_op, 1))) &&
05437 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05438 ((op->next != NULL &&
05439 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05440 (op->next == NULL &&
05441 !GTN_SET_MemberP(BB_live_out(OP_bb(op)), OP_result(alu_op, 0)))) &&
05442
05443 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0)) &&
05444
05445 Pred_Opnd_Avail(op, actual_tninfo[0], 0) &&
05446
05447
05448
05449
05450 !TN_live_out_of(OP_opnd(alu_op, 0), OP_bb(alu_op)) &&
05451 TN_is_register(OP_result(alu_op, 0)) &&
05452 TN_is_register(OP_opnd(alu_op, 0)) &&
05453 (!TNs_Are_Equivalent(OP_result(alu_op, 0), OP_opnd(alu_op, 0)) ||
05454 !is_live_tn(alu_op->next, OP_opnd(alu_op, 0)))) {
05455 INT64 tmp_offset, new_offset;
05456 TN* ofst_tn = NULL;
05457 if (TN_is_symbol (OP_opnd(alu_op, 1))) {
05458 TN *t = OP_opnd(alu_op, 1);
05459 Base_Symbol_And_Offset (TN_var(t), &base_tmp, &tmp_offset);
05460 if (base_tmp == SP_Sym || base_tmp == FP_Sym) {
05461 tmp_offset += TN_offset(t);
05462 if ( TN_is_reloc_neg(t) )
05463 tmp_offset = -tmp_offset;
05464 if ( TN_is_reloc_low16(t) )
05465 tmp_offset = tmp_offset & 0xffff;
05466 else if ( TN_is_reloc_high16(t) )
05467 tmp_offset =
05468 ( ( tmp_offset - (short)tmp_offset ) >> 16) & 0xffff;
05469 else if ( TN_is_reloc_higher(t) )
05470 tmp_offset = ( ( tmp_offset + 0x80008000LL ) >> 32 ) & 0xffff;
05471 else if ( TN_is_reloc_highest(t) )
05472 tmp_offset =
05473 ( ( tmp_offset + 0x800080008000LL ) >> 48 ) & 0xffff;
05474 }
05475
05476 } else
05477 tmp_offset = TN_value(OP_opnd(alu_op, 1));
05478
05479 new_offset = offset + tmp_offset;
05480
05481 if (base_tmp || base) {
05482 TN* t = OP_opnd(op, 1);
05483 if (TN_is_symbol(t) && base && base != SP_Sym && base != FP_Sym)
05484 ofst_tn = Gen_Symbol_TN( TN_var(t), TN_offset(t)+new_offset,0);
05485 t = OP_opnd(alu_op, 1);
05486 if (TN_is_symbol(t) &&
05487 base_tmp && base_tmp != SP_Sym && base_tmp != FP_Sym)
05488 ofst_tn =
05489 Gen_Symbol_TN( TN_var(t), TN_offset(t)+new_offset,0);
05490 }
05491
05492
05493 if (ISA_LC_Value_In_Class (new_offset, LC_simm32)) {
05494 new_op = Mk_OP ((code == TOP_lea32)?TOP_lea32:TOP_lea64,
05495 OP_result(op, 0), OP_opnd(alu_op, 0),
05496 ofst_tn ? ofst_tn : Gen_Literal_TN(new_offset, 4));
05497
05498 if (alu_op_defines_rflags_used(alu_op, op))
05499 return FALSE;
05500
05501 OP_srcpos( new_op ) = OP_srcpos( op );
05502 if( EBO_Trace_Data_Flow ){
05503 fprintf( TFile, "Lea_Insertion merges " );
05504 Print_OP_No_SrcLine(op);
05505 fprintf( TFile, "and " );
05506 Print_OP_No_SrcLine(alu_op);
05507 fprintf( TFile, "with " );
05508 Print_OP_No_SrcLine(new_op);
05509 }
05510 BB_Remove_Op(OP_bb(alu_op), alu_op);
05511 break;
05512 }
05513 }
05514
05515 if( TN_is_register(OP_opnd(op, 0)) &&
05516 TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0)) &&
05517
05518
05519 !TN_is_symbol(OP_opnd(op, 1))) {
05520 new_op = Mk_OP ((code == TOP_lea32)?TOP_addi32:TOP_addi64,
05521 OP_result(op, 0), OP_opnd(op, 0),
05522 OP_opnd(op, 1));
05523 }
05524
05525 else if (!TN_is_symbol (OP_opnd(op, 1)) &&
05526 TN_value(OP_opnd(op, 1)) == 0) {
05527 new_op = Mk_OP ((code == TOP_lea32)?TOP_mov32:TOP_mov64,
05528 OP_result(op, 0), OP_opnd(op, 0));
05529 }
05530
05531 else if (TN_is_symbol (OP_opnd(op, 1)) &&
05532 (base == SP_Sym || base == FP_Sym) &&
05533 EBO_in_peep &&
05534 offset == 0) {
05535 new_op = Mk_OP ((code == TOP_lea32)?TOP_mov32:TOP_mov64,
05536 OP_result(op, 0), OP_opnd(op, 0));
05537 }
05538
05539 if (rflags_read && new_op &&
05540 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05541 !TOP_is_change_rflags( OP_code(op) )) ||
05542 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05543 TOP_is_change_rflags( OP_code(op) ))))
05544 return FALSE;
05545
05546 if (new_op) {
05547 if( EBO_Trace_Data_Flow ){
05548 fprintf( TFile, "Lea_Insertion removes " );
05549 Print_OP_No_SrcLine(op);
05550 fprintf( TFile, "Lea_Insertion inserts " );
05551 Print_OP_No_SrcLine(new_op);
05552 }
05553 }
05554 break;
05555 }
05556 case TOP_leax32:
05557 case TOP_leax64:
05558 {
05559 OP* alu_op = actual_tninfo[0]->in_op;
05560 if( TN_is_register(OP_opnd(op, 0)) &&
05561 TN_is_register(OP_opnd(op, 1)) &&
05562 TN_is_register(OP_result(op, 0)) &&
05563 !TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0)) &&
05564 !TNs_Are_Equivalent(OP_opnd(op, 1),OP_result(op, 0))) {
05565
05566 if (alu_op && alu_op->bb == op->bb &&
05567 OP_code(alu_op) == code &&
05568 TN_value(OP_opnd(alu_op, 2)) == 1 &&
05569 !TN_is_symbol(OP_opnd(alu_op, 3)) &&
05570 TN_value(OP_opnd(alu_op, 3)) == 0 &&
05571 TN_value(OP_opnd(op, 2)) == 1 &&
05572 !TN_is_symbol(OP_opnd(op, 3)) &&
05573 TN_value(OP_opnd(op, 3)) == 0 &&
05574 TN_is_register(OP_opnd(alu_op, 0)) &&
05575 TN_is_register(OP_opnd(alu_op, 1)) &&
05576 TN_is_register(OP_opnd(op, 1)) &&
05577 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(op, 1)) &&
05578 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(alu_op, 1)) &&
05579 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05580 ((op->next != NULL &&
05581 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05582 (op->next == NULL &&
05583 !GTN_SET_MemberP(BB_live_out(OP_bb(op)), OP_result(alu_op, 0)))) &&
05584 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0)) &&
05585 Pred_Opnd_Avail(op, actual_tninfo[0], 0)) {
05586 EBO_TN_INFO *src0_info, *src1_info;
05587 src0_info = get_tn_info( OP_opnd(op, 1));
05588 src1_info = get_tn_info( OP_opnd(alu_op, 0));
05589
05590 if (src0_info && src1_info &&
05591 src0_info->sequence_num <= src1_info->sequence_num) {
05592 new_op = Mk_OP ((code == TOP_leax32)?TOP_leax32:TOP_leax64,
05593 OP_result(op, 0), OP_opnd(alu_op, 0),
05594 OP_opnd(alu_op, 1),
05595 Gen_Literal_TN(2, 4), Gen_Literal_TN(0, 4));
05596
05597 if (rflags_read &&
05598 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05599 !TOP_is_change_rflags( OP_code(op) )) ||
05600 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05601 TOP_is_change_rflags( OP_code(op) ))))
05602 return FALSE;
05603
05604 if (alu_op_defines_rflags_used(alu_op, op))
05605 return FALSE;
05606
05607 OP_srcpos( new_op ) = OP_srcpos( op );
05608 if( EBO_Trace_Data_Flow ){
05609 fprintf( TFile, "Lea_Insertion merges " );
05610 Print_OP_No_SrcLine(op);
05611 fprintf( TFile, "and " );
05612 Print_OP_No_SrcLine(alu_op);
05613 fprintf( TFile, "with " );
05614 Print_OP_No_SrcLine(new_op);
05615 }
05616 BB_Remove_Op(OP_bb(alu_op), alu_op);
05617 }
05618 } else if (CG_fold_shiftadd && alu_op && alu_op->bb == op->bb &&
05619 ((OP_code(alu_op) == TOP_leaxx64 &&
05620 code == TOP_lea64) ||
05621 (OP_code(alu_op) == TOP_leaxx32 &&
05622 code == TOP_lea32)) &&
05623 TN_value(OP_opnd(op, 2)) == 1 &&
05624 !TN_is_symbol(OP_opnd(alu_op, 2)) &&
05625 TN_value(OP_opnd(alu_op, 2)) == 0 &&
05626 !TN_is_symbol(OP_opnd(op, 3)) &&
05627 TN_value(OP_opnd(op, 3)) == 0 &&
05628 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05629 ((op->next != NULL &&
05630 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05631 (op->next == NULL &&
05632 !GTN_SET_MemberP(BB_live_out(OP_bb(op)),
05633 OP_result(alu_op, 0)))) &&
05634 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0))) {
05635
05636
05637
05638 new_op = Mk_OP ((code == TOP_leax32)?TOP_leax32:TOP_leax64,
05639 OP_result(op, 0), OP_opnd(op, 1),
05640 OP_opnd(alu_op, 0), OP_opnd(alu_op, 1),
05641 Gen_Literal_TN(0, 4));
05642
05643 if (alu_op_defines_rflags_used(alu_op, op))
05644 return FALSE;
05645
05646 OP_srcpos( new_op ) = OP_srcpos( op );
05647 if( EBO_Trace_Data_Flow ){
05648 fprintf( TFile, "Lea_Insertion merges " );
05649 Print_OP_No_SrcLine(op);
05650 fprintf( TFile, "and " );
05651 Print_OP_No_SrcLine(alu_op);
05652 fprintf( TFile, "with " );
05653 Print_OP_No_SrcLine(new_op);
05654 }
05655 BB_Remove_Op(OP_bb(alu_op), alu_op);
05656 } else {
05657
05658
05659 alu_op = actual_tninfo[1]->in_op;
05660 if (alu_op && alu_op->bb == op->bb &&
05661 OP_code(alu_op) == code &&
05662 TN_value(OP_opnd(alu_op, 2)) == 1 &&
05663 !TN_is_symbol(OP_opnd(alu_op, 3)) &&
05664 TN_value(OP_opnd(alu_op, 3)) == 0 &&
05665 TN_value(OP_opnd(op, 2)) == 1 &&
05666 !TN_is_symbol(OP_opnd(op, 3)) &&
05667 TN_value(OP_opnd(op, 3)) == 0 &&
05668 TN_is_register(OP_opnd(alu_op, 0)) &&
05669 TN_is_register(OP_opnd(alu_op, 1)) &&
05670 TN_is_register(OP_opnd(op, 0)) &&
05671 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(op, 0)) &&
05672 TNs_Are_Equivalent(OP_opnd(alu_op, 0),OP_opnd(alu_op, 1)) &&
05673 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05674 ((op->next != NULL &&
05675 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05676 (op->next == NULL &&
05677 !GTN_SET_MemberP(BB_live_out(OP_bb(op)), OP_result(alu_op, 0)))) &&
05678 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0)) &&
05679 Pred_Opnd_Avail(op, actual_tninfo[1], 0)) {
05680 new_op = Mk_OP ((code == TOP_leax32)?TOP_leax32:TOP_leax64,
05681 OP_result(op, 0), OP_opnd(op, 0),
05682 OP_opnd(alu_op, 1),
05683 Gen_Literal_TN(2, 4), Gen_Literal_TN(0, 4));
05684 if (rflags_read &&
05685 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05686 !TOP_is_change_rflags( OP_code(op) )) ||
05687 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05688 TOP_is_change_rflags( OP_code(op) ))))
05689 return FALSE;
05690
05691 if (alu_op_defines_rflags_used(alu_op, op))
05692 return FALSE;
05693
05694 OP_srcpos( new_op ) = OP_srcpos( op );
05695 if( EBO_Trace_Data_Flow ){
05696 fprintf( TFile, "Lea_Insertion merges " );
05697 Print_OP_No_SrcLine(op);
05698 fprintf( TFile, "and " );
05699 Print_OP_No_SrcLine(alu_op);
05700 fprintf( TFile, "with " );
05701 Print_OP_No_SrcLine(new_op);
05702 }
05703 BB_Remove_Op(OP_bb(alu_op), alu_op);
05704 } else if (CG_fold_shiftadd && alu_op && alu_op->bb == op->bb &&
05705 ((OP_code(alu_op) == TOP_leaxx64 &&
05706 code == TOP_leax64) ||
05707 (OP_code(alu_op) == TOP_leaxx32 &&
05708 code == TOP_leax32)) &&
05709 !TN_is_symbol(OP_opnd(alu_op, 2)) &&
05710 TN_value(OP_opnd(alu_op, 2)) == 0 &&
05711 TN_value(OP_opnd(op, 2)) == 1 &&
05712 !TN_is_symbol(OP_opnd(op, 3)) &&
05713 TN_value(OP_opnd(op, 3)) == 0 &&
05714 !TN_live_out_of(OP_result(alu_op, 0), OP_bb(alu_op)) &&
05715 ((op->next != NULL &&
05716 !is_live_tn(op->next, OP_result(alu_op, 0))) ||
05717 (op->next == NULL &&
05718 !GTN_SET_MemberP(BB_live_out(OP_bb(op)),
05719 OP_result(alu_op, 0)))) &&
05720 Check_No_Use_Between(alu_op, op, OP_result(alu_op, 0))) {
05721
05722
05723
05724 new_op = Mk_OP ((code == TOP_leax32)?TOP_leax32:TOP_leax64,
05725 OP_result(op, 0), OP_opnd(op, 0),
05726 OP_opnd(alu_op, 0), OP_opnd(alu_op, 1),
05727 Gen_Literal_TN(0, 4));
05728
05729 if (alu_op_defines_rflags_used(alu_op, op))
05730 return FALSE;
05731
05732 OP_srcpos( new_op ) = OP_srcpos( op );
05733 if( EBO_Trace_Data_Flow ){
05734 fprintf( TFile, "Lea_Insertion merges " );
05735 Print_OP_No_SrcLine(op);
05736 fprintf( TFile, "and " );
05737 Print_OP_No_SrcLine(alu_op);
05738 fprintf( TFile, "with " );
05739 Print_OP_No_SrcLine(new_op);
05740 }
05741 BB_Remove_Op(OP_bb(alu_op), alu_op);
05742 }
05743 }
05744 break;
05745 }
05746
05747 if( ((TN_is_register(OP_opnd(op, 0)) &&
05748 TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0))) ||
05749 (TN_is_register(OP_opnd(op, 1)) &&
05750 TNs_Are_Equivalent(OP_opnd(op, 1),OP_result(op, 0)))) &&
05751 TN_value(OP_opnd(op, 2)) == 1 &&
05752 !TN_is_symbol(OP_opnd(op, 3)) &&
05753 TN_value(OP_opnd(op, 3)) == 0) {
05754 TN *opnd1, *opnd2;
05755 if (TN_is_register(OP_opnd(op, 0)) &&
05756 TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0))) {
05757 opnd1 = OP_opnd(op, 0);
05758 opnd2 = OP_opnd(op, 1);
05759 } else {
05760 opnd2 = OP_opnd(op, 0);
05761 opnd1 = OP_opnd(op, 1);
05762 }
05763 new_op = Mk_OP ((code == TOP_leax32)?TOP_add32:TOP_add64,
05764 OP_result(op, 0), opnd1, opnd2);
05765 }
05766
05767 if (rflags_read && new_op &&
05768 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05769 !TOP_is_change_rflags( OP_code(op) )) ||
05770 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05771 TOP_is_change_rflags( OP_code(op) ))))
05772 return FALSE;
05773
05774 if (new_op) {
05775 if( EBO_Trace_Data_Flow ){
05776 fprintf( TFile, "Lea_Insertion removes " );
05777 Print_OP_No_SrcLine(op);
05778 fprintf( TFile, "Lea_Insertion inserts " );
05779 Print_OP_No_SrcLine(new_op);
05780 }
05781 }
05782 break;
05783 }
05784 case TOP_leaxx32:
05785 case TOP_leaxx64:
05786 {
05787 if( ((TN_is_register(OP_opnd(op, 0)) &&
05788 TNs_Are_Equivalent(OP_opnd(op, 0),OP_result(op, 0))))) {
05789 if (!TN_is_symbol(OP_opnd(op, 2)) &&
05790 TN_value(OP_opnd(op, 2)) == 0) {
05791 shift = Get_Power_Of_2(TN_value(OP_opnd(op, 1)));
05792 new_op = Mk_OP ((code == TOP_leaxx32)?TOP_shli32:TOP_shli64,
05793 OP_result(op, 0),
05794 OP_result(op, 0), Gen_Literal_TN(shift, 4));
05795 }
05796 else if (TN_is_symbol(OP_opnd(op, 2)) &&
05797 TN_value(OP_opnd(op, 1)) == 1) {
05798 new_op = Mk_OP ((code == TOP_leaxx32)?TOP_addi32:TOP_addi64,
05799 OP_result(op, 0),
05800 OP_result(op, 0), OP_opnd(op, 2));
05801 }
05802 }
05803
05804 if (rflags_read && new_op &&
05805 ((TOP_is_change_rflags( OP_code(new_op) ) &&
05806 !TOP_is_change_rflags( OP_code(op) )) ||
05807 (!TOP_is_change_rflags( OP_code(new_op) ) &&
05808 TOP_is_change_rflags( OP_code(op) ))))
05809 return FALSE;
05810
05811 if (new_op) {
05812 if( EBO_Trace_Data_Flow ){
05813 fprintf( TFile, "Lea_Insertion removes " );
05814 Print_OP_No_SrcLine(op);
05815 fprintf( TFile, "Lea_Insertion inserts " );
05816 Print_OP_No_SrcLine(new_op);
05817 }
05818 }
05819 break;
05820 }
05821
05822 default:
05823 break;
05824 }
05825 if (new_op) {
05826 OP_srcpos(new_op) = OP_srcpos(op);
05827 BB_Insert_Op_After(OP_bb(op), op, new_op);
05828 return TRUE;
05829 }
05830
05831 return FALSE;
05832 }
05833
05834 BOOL
05835 EBO_Fold_Load_Duplicate( OP* op, TN** opnd_tn, EBO_TN_INFO** actual_tninfo )
05836 {
05837 #if Is_True_On
05838 if (!(EBO_Opt_Mask & EBO_FOLD_LOAD_DUPLICATE)) return FALSE;
05839 #endif
05840
05841 if (OP_code(op) != TOP_fmovddup)
05842 return FALSE;
05843
05844 OP* shuf_op = actual_tninfo[0]->in_op;
05845 if (!shuf_op || shuf_op->bb != op->bb ||
05846 (OP_code(shuf_op) != TOP_shufpd &&
05847 OP_code(shuf_op) != TOP_ldhpd &&
05848 OP_code(shuf_op) != TOP_ldapd))
05849 return FALSE;
05850
05851 if (!TOP_is_load(OP_code(shuf_op)) &&
05852 (TN_live_out_of(OP_result(shuf_op, 0), OP_bb(shuf_op)) ||
05853 ((op->next != NULL &&
05854 is_live_tn(op->next, OP_result(shuf_op, 0))) ||
05855 (op->next == NULL &&
05856 GTN_SET_MemberP(BB_live_out(OP_bb(op)),
05857 OP_result(shuf_op, 0)))) ||
05858 !Check_No_Use_Between(shuf_op, op, OP_result(shuf_op, 0))))
05859 return FALSE;
05860
05861
05862 EBO_TN_INFO *src0_info, *src1_info;
05863 src0_info = get_tn_info( OP_opnd(op, 0));
05864 src1_info = get_tn_info( OP_result(shuf_op, 0));
05865 if (src0_info->sequence_num > src1_info->sequence_num)
05866 return FALSE;
05867
05868 if (!TOP_is_load(OP_code(shuf_op)) &&
05869 (!TN_is_register(OP_opnd(shuf_op, 0)) ||
05870 !TN_is_register(OP_opnd(shuf_op, 1)) ||
05871 !TNs_Are_Equivalent(OP_opnd(shuf_op, 0), OP_opnd(shuf_op, 1)) ||
05872 TN_is_symbol(OP_opnd(shuf_op, 2)) ||
05873 TN_value(OP_opnd(shuf_op, 2)) != 1))
05874 return FALSE;
05875
05876 if (TOP_is_load(OP_code(shuf_op)))
05877 shuf_op = op;
05878
05879 EBO_TN_INFO *loaded_tn_info = get_tn_info( OP_opnd(shuf_op, 0) );
05880 OP* load = loaded_tn_info->in_op;
05881 if (!load || load->bb != shuf_op->bb || !TOP_is_load(OP_code(load)))
05882 return FALSE;
05883
05884 EBO_TN_INFO *src_info = get_tn_info( OP_result(load, 0) );
05885 if (loaded_tn_info->sequence_num > src_info->sequence_num)
05886 return FALSE;
05887
05888 OP* new_op = NULL;
05889 INT base_loc = OP_find_opnd_use( load, OU_base );
05890 INT offset_loc = OP_find_opnd_use( load, OU_offset );
05891 INT index_loc = OP_find_opnd_use( load, OU_index );
05892 INT scale_loc = OP_find_opnd_use( load, OU_scale );
05893
05894 TN *base = NULL;
05895 TN *offset = NULL;
05896 TN *index = NULL;
05897 TN *scale = NULL;
05898 if (base_loc >= 0)
05899 base = OP_opnd( load, OP_find_opnd_use( load, OU_base ) );
05900 if (offset_loc >= 0)
05901 offset = OP_opnd( load, OP_find_opnd_use( load, OU_offset ) );
05902 if (index_loc >= 0)
05903 index = OP_opnd( load, OP_find_opnd_use( load, OU_index ) );
05904 if (scale_loc >= 0)
05905 scale = OP_opnd( load, OP_find_opnd_use( load, OU_scale ) );
05906
05907 if (!offset || TN_is_symbol(offset))
05908 return FALSE;
05909
05910
05911
05912 if (base_loc >= 0 && !Pred_Opnd_Avail(op, loaded_tn_info, base_loc))
05913 return FALSE;
05914 if (index_loc >= 0 && !Pred_Opnd_Avail(op, loaded_tn_info, index_loc))
05915 return FALSE;
05916
05917 if (base && offset && index && scale)
05918 new_op = Mk_OP (TOP_fmovddupxx,
05919 OP_result(op, 0),
05920 OP_opnd(load, 0),
05921 OP_opnd(load, 1),
05922 OP_opnd(load, 2),
05923 OP_opnd(load, 3));
05924 else if (base && offset)
05925 new_op = Mk_OP (TOP_fmovddupx,
05926 OP_result(op, 0),
05927 OP_opnd(load, 0),
05928 OP_opnd(load, 1));
05929 else if (index && scale && offset)
05930 new_op = Mk_OP (TOP_fmovddupxxx,
05931 OP_result(op, 0),
05932 OP_opnd(load, 0),
05933 OP_opnd(load, 1),
05934 OP_opnd(load, 2));
05935
05936 if ( op == shuf_op &&
05937 TOP_is_vector_high_loadstore( OP_code( load ) ) ) {
05938 INT offset_loc = OP_find_opnd_use( new_op, OU_offset );
05939 INT offset_value = TN_value( OP_opnd( new_op, offset_loc ) );
05940 Set_OP_opnd( new_op, offset_loc,
05941 Gen_Literal_TN( offset_value - 8,
05942 TN_size( OP_opnd( new_op, offset_loc ) ) ) );
05943 }
05944 else if ( !TOP_is_vector_high_loadstore( OP_code( load ) ) ) {
05945 INT offset_loc = OP_find_opnd_use( new_op, OU_offset );
05946 INT offset_value = TN_value( OP_opnd( new_op, offset_loc ) );
05947 Set_OP_opnd( new_op, offset_loc,
05948 Gen_Literal_TN( offset_value + 8,
05949 TN_size( OP_opnd( new_op, offset_loc ) ) ) );
05950 }
05951
05952 if (new_op) {
05953 if (shuf_op != op) {
05954 if( EBO_Trace_Data_Flow ){
05955 fprintf( TFile, "Fold_Load_Duplicate merges " );
05956 Print_OP_No_SrcLine(op);
05957 fprintf( TFile, "and " );
05958 Print_OP_No_SrcLine(shuf_op);
05959 fprintf( TFile, "Fold_Load_Duplicate inserts " );
05960 Print_OP_No_SrcLine(new_op);
05961 }
05962 OP_srcpos( new_op ) = OP_srcpos( op );
05963 BB_Remove_Op(OP_bb(shuf_op), shuf_op);
05964 BB_Insert_Op_After(OP_bb(op), op, new_op);
05965 } else {
05966 if( EBO_Trace_Data_Flow ){
05967 fprintf( TFile, "Fold_Load_Duplicate removes " );
05968 Print_OP_No_SrcLine(op);
05969 fprintf( TFile, "Fold_Load_Duplicate inserts " );
05970 Print_OP_No_SrcLine(new_op);
05971 }
05972 OP_srcpos( new_op ) = OP_srcpos( op );
05973 BB_Insert_Op_After(OP_bb(op), op, new_op);
05974 }
05975 return TRUE;
05976 }
05977
05978 return FALSE;
05979 }
05980
05981
05982
05983 BOOL
05984 EBO_Can_Eliminate_Zero_Opnd_OP (OP *op)
05985 {
05986 switch (OP_code(op)) {
05987 case TOP_zero32:
05988 case TOP_zero64:
05989 case TOP_xzero32:
05990 case TOP_xzero64:
05991 case TOP_xzero128v32:
05992 case TOP_xzero128v64:
05993 return TRUE;
05994 }
05995 return FALSE;
05996 }