00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 #ifndef EBO_INFO_INCLUDED
00152 #define EBO_INFO_INCLUDED
00153
00154
00155
00156 typedef struct local_tn_info EBO_TN_INFO;
00157 typedef struct local_op_info EBO_OP_INFO;
00158
00159
00160
00161
00162
00163
00164
00165 typedef struct local_tn_info {
00166 INT sequence_num;
00167 TN *local_tn;
00168 TN *replacement_tn;
00169 EBO_TN_INFO *replacement_tninfo;
00170 EBO_TN_INFO *predicate_tninfo;
00171 BB *in_bb;
00172 OP *in_op;
00173 EBO_OP_INFO *in_opinfo;
00174 EBO_TN_INFO *same;
00175 EBO_TN_INFO *prior;
00176 EBO_TN_INFO *next;
00177 INT32 reference_count;
00178 mUINT8 omega;
00179 mBOOL redefined_before_block_end;
00180 } EBO_TN_INFO;
00181
00182
00183 extern INT EBO_tninfo_number;
00184 extern EBO_TN_INFO *EBO_free_tninfo;
00185 extern EBO_TN_INFO *EBO_first_tninfo;
00186 extern EBO_TN_INFO *EBO_last_tninfo;
00187
00188
00189
00190
00191
00192
00193
00194 typedef struct local_op_info {
00195 INT hash_index;
00196 mBOOL in_delay_slot;
00197 mBOOL op_must_not_be_removed;
00198 mBOOL op_must_not_be_moved;
00199 BB *in_bb;
00200 OP *in_op;
00201 #ifdef KEY
00202 int op_num;
00203 #endif
00204 EBO_OP_INFO *same;
00205 EBO_OP_INFO *prior;
00206 EBO_OP_INFO *next;
00207 EBO_TN_INFO **optimal_opnd;
00208 EBO_TN_INFO **actual_opnd;
00209 EBO_TN_INFO **actual_rslt;
00210 EBO_TN_INFO *tn_info[
00211 OP_MAX_FIXED_RESULTS +
00212 OP_MAX_FIXED_OPNDS +
00213 OP_MAX_FIXED_OPNDS];
00214 } EBO_OP_INFO;
00215
00216
00217
00218
00219
00220
00221
00222
00223 inline size_t EBO_OP_INFO_sizeof(OP *op)
00224 {
00225 size_t sizeof_info = sizeof(EBO_OP_INFO);
00226 INT extra_tns = OP_results(op) - OP_MAX_FIXED_RESULTS
00227 + OP_opnds(op) - OP_MAX_FIXED_OPNDS
00228 + OP_opnds(op) - OP_MAX_FIXED_OPNDS;
00229 if (extra_tns > 0) {
00230 sizeof_info += sizeof(EBO_TN_INFO *) * extra_tns;
00231 }
00232 return sizeof_info;
00233 }
00234
00235 #define EBO_DEFAULT_MEM_HASH 0
00236 #define EBO_NO_ALIAS_MEM_HASH 1
00237 #define EBO_SPILL_MEM_HASH 2
00238 #define EBO_MAX_MEM_OP_HASH 3
00239 #define EBO_COPY_OP_HASH 3
00240 #define EBO_RESERVED_OP_HASH 4
00241 #define EBO_MAX_EXP_OP_HASH 1024
00242 #define EBO_MAX_OP_HASH (EBO_RESERVED_OP_HASH + EBO_MAX_EXP_OP_HASH)
00243 #define EBO_EXP_OP_HASH(val) ((EBO_MAX_EXP_OP_HASH-1) & (val>>6))
00244
00245
00246 extern EBO_OP_INFO *EBO_free_opinfo;
00247 extern EBO_OP_INFO *EBO_first_opinfo;
00248 extern EBO_OP_INFO *EBO_last_opinfo;
00249 extern EBO_OP_INFO *EBO_opinfo_table[EBO_MAX_OP_HASH];
00250
00251 extern BOOL EBO_in_pre;
00252 extern BOOL EBO_in_loop;
00253 extern BOOL EBO_in_peep;
00254
00255 extern TN_MAP EBO_tninfo_table;
00256 extern MEM_POOL EBO_pool;
00257
00258 extern INT EBO_num_tninfo_entries;
00259 extern INT EBO_tninfo_entries_reused;
00260 extern INT EBO_num_opinfo_entries;
00261 extern INT EBO_opinfo_entries_reused;
00262
00263 extern const char *EBO_trace_pfx;
00264 extern BOOL EBO_Trace_Execution;
00265 extern BOOL EBO_Trace_Optimization;
00266 extern BOOL EBO_Trace_Block_Flow;
00267 extern BOOL EBO_Trace_Data_Flow;
00268 extern BOOL EBO_Trace_Hash_Search;
00269
00270
00271
00272 #define TN_Is_Constant(tn) (TN_is_const_reg(tn) ? TRUE : TN_is_constant(tn))
00273 #define TN_Has_Value(tn) (TN_is_const_reg(tn) ? TRUE : TN_has_value(tn))
00274 #define TN_Value(tn) ((tn == Zero_TN) ? 0 : TN_value(tn))
00275 #define has_assigned_reg(tn) (TN_is_register(tn) && \
00276 (TN_is_dedicated(tn) || \
00277 TN_register(tn) != REGISTER_UNDEFINED))
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 #define use_tn_or_reg(tn) (has_assigned_reg(tn) \
00291 ? Build_Dedicated_TN ( TN_register_class(tn), \
00292 TN_register(tn), \
00293 0) \
00294 : tn)
00295 #define get_tn_info(tn) ((EBO_TN_INFO *)TN_MAP_Get(EBO_tninfo_table, use_tn_or_reg(tn)))
00296 #define set_tn_info(tn, tninfo) (TN_MAP_Set(EBO_tninfo_table, use_tn_or_reg(tn), tninfo))
00297 #define inc_ref_count(tninfo) ((void)tninfo->reference_count++)
00298 #define dec_ref_count(tninfo) ((void)tninfo->reference_count--)
00299
00300
00301
00302
00303
00304 void tn_info_entry_dump (EBO_TN_INFO *tninfo);
00305 void tn_info_table_dump ();
00306 #ifdef KEY
00307 #if 0
00308 void delete_useless_store_op (EBO_OP_INFO *opinfo);
00309 #endif
00310 #endif
00311
00312 inline EBO_TN_INFO *
00313 get_new_tninfo (BB *current_bb, OP *current_op, TN *local_tn)
00314 {
00315 EBO_TN_INFO *tninfo;
00316
00317
00318 if (EBO_free_tninfo) {
00319 tninfo = EBO_free_tninfo;
00320 EBO_free_tninfo = tninfo->next;
00321 tninfo->next = NULL;
00322 EBO_tninfo_entries_reused++;
00323 } else {
00324 tninfo = TYPE_MEM_POOL_ALLOC (EBO_TN_INFO, &EBO_pool);
00325 EBO_num_tninfo_entries++;
00326 }
00327
00328
00329 tninfo->sequence_num = ++EBO_tninfo_number;
00330 tninfo->local_tn = local_tn;
00331 tninfo->replacement_tn = NULL;
00332 tninfo->replacement_tninfo = NULL;
00333 tninfo->predicate_tninfo = NULL;
00334 tninfo->omega = 0;
00335 tninfo->in_bb = current_bb;
00336 tninfo->in_op = current_op;
00337 tninfo->in_opinfo = NULL;
00338 tninfo->reference_count = 0;
00339 tninfo->redefined_before_block_end = FALSE;
00340 tninfo->same = NULL;
00341
00342
00343
00344 tninfo->prior = EBO_last_tninfo;
00345 if (EBO_first_tninfo == NULL) {
00346 EBO_first_tninfo = tninfo;
00347 } else {
00348 EBO_last_tninfo->next = tninfo;
00349 }
00350 EBO_last_tninfo = tninfo;
00351 tninfo->next = NULL;
00352
00353
00354 set_tn_info (local_tn, tninfo);
00355
00356 return tninfo;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 inline BOOL
00369 EBO_predicate_dominates (TN *pred1, EBO_TN_INFO *info1,
00370 TN *pred2, EBO_TN_INFO *info2)
00371 {
00372 if (pred1 == True_TN) {
00373
00374 return TRUE;
00375 }
00376 if (pred1 == pred2) {
00377
00378 return (info1 == info2);
00379 }
00380
00381 return FALSE;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 inline BOOL
00394 EBO_predicate_complements (TN *pred1, EBO_TN_INFO *info1,
00395 TN *pred2, EBO_TN_INFO *info2)
00396 {
00397 if ((pred1 == True_TN) && (pred2 == Zero_TN)) {
00398 return TRUE;
00399 }
00400 if ((pred1 == Zero_TN) && (pred2 == True_TN)) {
00401 return TRUE;
00402 }
00403 if ((info1 == NULL) || (info2 == NULL) ||
00404 (info1->in_op == NULL) || (info2->in_op == NULL)) {
00405 return FALSE;
00406 }
00407 #ifndef TARG_IA64
00408 if ((pred1 != pred2) && (info1->in_op == info2->in_op)) {
00409
00410 return TRUE;
00411 }
00412 #endif
00413
00414 return FALSE;
00415 }
00416
00417
00418
00419 inline EBO_TN_INFO *
00420 tn_info_def (BB *current_bb, OP *current_op, TN *local_tn,
00421 TN *predicate_tn, EBO_TN_INFO *predicate_info)
00422 {
00423 EBO_TN_INFO *tninfo;
00424 EBO_TN_INFO *tninfo_prev;
00425
00426
00427 tninfo_prev = get_tn_info (local_tn);
00428 tninfo = get_new_tninfo (current_bb, current_op, local_tn);
00429 tninfo->predicate_tninfo = predicate_info;
00430 tninfo->same = tninfo_prev;
00431
00432 if ((tninfo_prev != NULL) &&
00433 (tninfo_prev->in_bb == current_bb) &&
00434 ((predicate_tn == NULL) ||
00435 (EBO_predicate_dominates(predicate_tn,
00436 predicate_info,
00437 (tninfo_prev->predicate_tninfo != NULL)?
00438 tninfo_prev->predicate_tninfo->local_tn:True_TN,
00439 tninfo_prev->predicate_tninfo)))) {
00440
00441 #ifdef TARG_X8664
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 if (tninfo_prev->in_op != current_op)
00461 #endif
00462 tninfo_prev->redefined_before_block_end = TRUE;
00463 }
00464
00465 return tninfo;
00466 }
00467
00468
00469 inline EBO_TN_INFO *
00470 tn_info_use (BB *current_bb, OP *current_op, TN *local_tn,
00471 TN *predicate_tn, EBO_TN_INFO *predicate_info,
00472 mUINT8 associated_omega)
00473 {
00474 EBO_TN_INFO *tninfo;
00475 EBO_TN_INFO *tninfo_prev;
00476
00477 tninfo = get_tn_info (local_tn);
00478 tninfo_prev = tninfo;
00479
00480 while (tninfo != NULL) {
00481
00482 if (tninfo->omega == associated_omega) {
00483
00484
00485 if (predicate_tn != NULL) {
00486
00487
00488 #if defined(TARG_IA64)
00489 if ( EBO_in_peep ) {
00490
00491
00492 if (tninfo->predicate_tninfo == NULL ||
00493 (TN_is_global_reg(tninfo->predicate_tninfo->local_tn) &&
00494 TN_is_global_reg(predicate_tn)) &&
00495 (use_tn_or_reg(tninfo->predicate_tninfo->local_tn) == use_tn_or_reg(predicate_tn)))
00496
00497
00498
00499 break;
00500 }
00501 #endif
00502 if (EBO_predicate_dominates((tninfo->predicate_tninfo != NULL)?
00503 tninfo->predicate_tninfo->local_tn:True_TN,
00504 tninfo->predicate_tninfo,
00505 predicate_tn,
00506 predicate_info)) {
00507 break;
00508 } else if (EBO_predicate_complements((tninfo->predicate_tninfo != NULL)?
00509 tninfo->predicate_tninfo->local_tn:True_TN,
00510 tninfo->predicate_tninfo,
00511 predicate_tn,
00512 predicate_info)) {
00513
00514 } else if (tninfo->in_op != NULL) {
00515
00516
00517
00518 tninfo = NULL;
00519 break;
00520 }
00521 } else {
00522
00523 break;
00524 }
00525 }
00526
00527
00528 tninfo = tninfo->same;
00529 }
00530
00531 if (tninfo == NULL) {
00532 tninfo = get_new_tninfo (current_bb, NULL, local_tn);
00533 tninfo->predicate_tninfo = predicate_info;
00534 tninfo->same = tninfo_prev;
00535 tninfo->omega = associated_omega;
00536 }
00537 inc_ref_count(tninfo);
00538 return tninfo;
00539 }
00540
00541
00542 inline EBO_OP_INFO *
00543 get_new_opinfo (OP *op)
00544 {
00545 EBO_OP_INFO *opinfo;
00546 size_t sizeof_info = EBO_OP_INFO_sizeof(op);
00547
00548
00549
00550 if (EBO_free_opinfo && sizeof_info <= sizeof(EBO_OP_INFO)) {
00551 opinfo = EBO_free_opinfo;
00552 EBO_free_opinfo = opinfo->next;
00553 EBO_opinfo_entries_reused++;
00554 } else {
00555 opinfo = (EBO_OP_INFO *)MEM_POOL_Alloc(&EBO_pool, sizeof_info);
00556 EBO_num_opinfo_entries++;
00557 }
00558
00559
00560 const INT nopnds = OP_opnds(op);
00561 EBO_TN_INFO ** const tn_info = &opinfo->tn_info[0];
00562 opinfo->optimal_opnd = &tn_info[0];
00563 opinfo->actual_opnd = &tn_info[nopnds];
00564 opinfo->actual_rslt = &tn_info[nopnds + nopnds];
00565 opinfo->op_must_not_be_removed = FALSE;
00566 opinfo->op_must_not_be_moved = FALSE;
00567 opinfo->in_delay_slot = FALSE;
00568
00569
00570
00571 opinfo->prior = EBO_last_opinfo;
00572 if (EBO_first_opinfo == NULL) {
00573 EBO_first_opinfo = opinfo;
00574 } else {
00575 EBO_last_opinfo->next = opinfo;
00576 }
00577 EBO_last_opinfo = opinfo;
00578 opinfo->next = NULL;
00579
00580 return opinfo;
00581 }
00582
00583
00584 inline void backup_tninfo_list (EBO_TN_INFO *previous_last)
00585
00586
00587
00588
00589
00590
00591
00592 {
00593 EBO_TN_INFO *tninfo = EBO_last_tninfo;
00594
00595 if (EBO_last_tninfo != previous_last) {
00596
00597 while (tninfo != previous_last) {
00598 set_tn_info (tninfo->local_tn, tninfo->same);
00599 tninfo = tninfo->prior;
00600 }
00601
00602 if (previous_last != NULL) {
00603
00604 EBO_TN_INFO *new_free = previous_last->next;
00605 previous_last->next = NULL;
00606 EBO_last_tninfo->next = EBO_free_tninfo;
00607 EBO_free_tninfo = new_free;
00608
00609
00610 EBO_last_tninfo = previous_last;
00611 EBO_tninfo_number = previous_last->sequence_num;
00612 } else {
00613 EBO_last_tninfo->next = EBO_free_tninfo;
00614 EBO_free_tninfo = EBO_first_tninfo;
00615 EBO_first_tninfo = NULL;
00616 EBO_last_tninfo = NULL;
00617 EBO_tninfo_number = 0;
00618 }
00619 }
00620 }
00621
00622
00623 inline void backup_opinfo_list (EBO_OP_INFO *previous_last)
00624
00625
00626
00627
00628
00629
00630
00631 {
00632 EBO_OP_INFO *opinfo = EBO_last_opinfo;
00633
00634 if (EBO_last_opinfo != previous_last) {
00635
00636 while (opinfo != previous_last) {
00637 #ifdef KEY
00638 #if 0
00639 if (opinfo->in_op &&
00640 OP_store(opinfo->in_op))
00641 delete_useless_store_op(opinfo);
00642 #endif
00643 #endif
00644 EBO_opinfo_table[opinfo->hash_index] = opinfo->same;
00645 opinfo = opinfo->prior;
00646 }
00647
00648 if (previous_last != NULL) {
00649
00650 EBO_OP_INFO *new_free = previous_last->next;
00651 previous_last->next = NULL;
00652 EBO_last_opinfo->next = EBO_free_opinfo;
00653 EBO_free_opinfo = new_free;
00654
00655
00656 EBO_last_opinfo = previous_last;
00657 } else {
00658 EBO_last_opinfo->next = EBO_free_opinfo;
00659 EBO_free_opinfo = EBO_first_opinfo;
00660 EBO_first_opinfo = NULL;
00661 EBO_last_opinfo = NULL;
00662 }
00663 }
00664 }
00665
00666
00667
00668 inline void remove_uses (INT num_opnds,
00669 EBO_TN_INFO **actual_tninfo)
00670
00671
00672
00673
00674 {
00675 INT opndnum;
00676 EBO_TN_INFO *tninfo;
00677
00678
00679 for (opndnum = 0; opndnum < num_opnds; opndnum++) {
00680 tninfo = actual_tninfo[opndnum];
00681 if (tninfo != NULL) {
00682 dec_ref_count(tninfo);
00683 }
00684 }
00685
00686 }
00687
00688
00689
00690 inline void remove_op (EBO_OP_INFO *opinfo)
00691
00692
00693
00694
00695 {
00696 OP *op = opinfo->in_op;
00697 INT num_opnds = OP_opnds(op);
00698 INT opndnum;
00699 EBO_TN_INFO *tninfo;
00700
00701
00702 for (opndnum = 0; opndnum < num_opnds; opndnum++) {
00703 tninfo = opinfo->actual_opnd[opndnum];
00704 if (tninfo != NULL) {
00705 dec_ref_count(tninfo);
00706 }
00707 }
00708
00709 }
00710
00711 #endif