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 #ifdef USE_PCH
00058 #include "cg_pch.h"
00059 #endif // USE_PCH
00060 #pragma hdrstop
00061
00062 #include <alloca.h>
00063 #include <math.h>
00064 #include "defs.h"
00065 #include "config.h"
00066 #include "config_targ_opt.h"
00067 #include "config_asm.h"
00068 #include "mempool.h"
00069 #include "bb.h"
00070 #include "bb_set.h"
00071 #include "tracing.h"
00072 #include "timing.h"
00073 #include "cgir.h"
00074 #include "glob.h"
00075 #include "tn_map.h"
00076 #include "cg.h"
00077 #include "cg_flags.h"
00078 #include "ercg.h"
00079 #include "cgtarget.h"
00080 #include "cg_vector.h"
00081 #include "dominate.h"
00082 #include "findloops.h"
00083 #include "hb_hazards.h"
00084 #include "note.h"
00085 #include "lra.h"
00086 #include "gcm.h"
00087 #include "ti_res.h"
00088 #include "ti_res_res.h"
00089 #include "ti_latency.h"
00090 #include "ti_errors.h"
00091 #include "cg_region.h"
00092 #include "gtn_universe.h"
00093 #include "gtn_set.h"
00094 #include "cxx_memory.h"
00095 #include "targ_proc_properties.h"
00096 #include "targ_isa_bundle.h"
00097 #include "ti_bundle.h"
00098
00099
00100
00101
00102 static void Print_Scheduling_Note (
00103 NOTE_ACTION action,
00104 NOTE_INFO *info,
00105 FILE *file)
00106 {
00107 switch (action) {
00108 case NOTE_PRINT_TO_ANL_FILE:
00109 case NOTE_PRINT_TO_FILE:
00110 {
00111 NOTE_SCHED *note = (NOTE_SCHED *)info;
00112 const char *prefix = ASM_CMNT_LINE"<sched> ";
00113 const char *suffix = "\n";
00114 INT sched_length = note->schedule_length;
00115 INT blk_parallelism = note->block_parallelism;
00116 BOOL anl_note = action == NOTE_PRINT_TO_ANL_FILE;
00117
00118
00119 if (sched_length > 0 && !Get_Trace (TP_SCHED, 0x010)) return;
00120
00121 if (anl_note) {
00122 if (sched_length > 0) return;
00123 prefix = "\"";
00124 suffix = "\"\n";
00125 } else {
00126 fprintf (file, "%s\n", prefix);
00127 }
00128
00129 if (sched_length < 0) {
00130 sched_length = -sched_length;
00131 if (anl_note) {
00132 SRCPOS srcpos = note->loop_srcpos;
00133 INT32 lineno = SRCPOS_linenum(srcpos);
00134 INT32 fileno = SRCPOS_filenum(srcpos);
00135 INT32 colno = SRCPOS_column(srcpos);
00136 fprintf (file,
00137 "\nmsg sched lines [%d %d %d] ",
00138 fileno,
00139 lineno,
00140 colno);
00141 }
00142 fprintf (file,
00143 "%sLoop schedule length: %d cycles (ignoring nested loops)%s",
00144 prefix,
00145 sched_length,
00146 suffix);
00147 }
00148 else {
00149 fprintf (file, "%s bb schedule length: %d cycles\n", prefix, sched_length);
00150 fprintf (file, "%s bb parallelism : %d \n", prefix, blk_parallelism);
00151 }
00152 if (!anl_note) fprintf (file, "%s\n", prefix);
00153 CGTARG_Print_PRC_INFO (file, ¬e->prc_info, sched_length, prefix, suffix);
00154 if (!anl_note) fprintf (file, "%s\n", prefix);
00155 }
00156 break;
00157 case NOTE_PRINT_HANDLER_NAME_TO_FILE:
00158 fprintf(file, "Print_Scheduling_Note");
00159 break;
00160 }
00161 }
00162
00163
00164
00165
00166
00167 void
00168 Add_Scheduling_Note (BB *bb, void *bbsch)
00169 {
00170 NOTE_SCHED *info = NULL;
00171 BOOL new_note = FALSE;
00172
00173
00174 if (BB_has_note(bb)) {
00175 info = (NOTE_SCHED *)NOTE_Retrieve_Note_For_Handler (
00176 bb, Print_Scheduling_Note);
00177 }
00178 if (info == NULL) {
00179 info = TYPE_MEM_POOL_ALLOC (NOTE_SCHED, &MEM_pu_pool);
00180 new_note = TRUE;
00181 }
00182
00183
00184 info->schedule_length = OP_scycle(BB_last_op(bb))+1;
00185 info->block_parallelism = (bbsch != NULL) ?
00186 BBSCH_block_parallelism ((BBSCH*)bbsch) : 0;
00187
00188 CGTARG_Compute_PRC_INFO (bb, &(info->prc_info));
00189 FmtAssert (info->schedule_length > 0,
00190 ("illegal schedule length, BB:%d",BB_id(bb)));
00191 if (new_note)
00192 NOTE_Add_To_BB (bb, Print_Scheduling_Note, (NOTE_INFO *)info);
00193 }
00194
00195 void
00196 Add_Scheduling_Notes_For_Loops (void)
00197 {
00198 Calculate_Dominators ();
00199 L_Save ();
00200 LOOP_DESCR *loop_list = LOOP_DESCR_Detect_Loops (&MEM_local_pool);
00201 BB_SET *processed_bbs = BB_SET_Create_Empty (PU_BB_Count+2, &MEM_local_pool);
00202 for (LOOP_DESCR *cloop = loop_list;
00203 cloop != NULL;
00204 cloop = LOOP_DESCR_next(cloop))
00205 {
00206 BB *bb;
00207 NOTE_SCHED *info = TYPE_MEM_POOL_ALLOC (NOTE_SCHED, &MEM_pu_pool);
00208 BB *loop_head = LOOP_DESCR_loophead(cloop);
00209 info->loop_srcpos = BB_Loop_Srcpos(loop_head);
00210
00211 FOR_ALL_BB_SET_members (LOOP_DESCR_bbset(cloop), bb) {
00212
00213 if (BB_SET_MemberP (processed_bbs, bb)) continue;
00214 NOTE_SCHED *bbinfo = (NOTE_SCHED *)NOTE_Retrieve_Note_For_Handler (
00215 bb, Print_Scheduling_Note);
00216 #define FLOAT_INT_MUL(f,i) ((INT)(f * (float)i + (float)0.5))
00217 if (bbinfo != NULL) {
00218 float head_freq = BB_freq(loop_head);
00219 float freq_ratio = head_freq == 0.0 ? 0.0 : BB_freq(bb)/head_freq;
00220 info->schedule_length -=
00221 FLOAT_INT_MUL (freq_ratio, bbinfo->schedule_length);
00222 info->block_parallelism = bbinfo->block_parallelism;
00223 for (INT i = 0; i < PRC_LAST; i++) {
00224 info->prc_info.refs[i] +=
00225 FLOAT_INT_MUL (freq_ratio, bbinfo->prc_info.refs[i]);
00226 }
00227 }
00228 }
00229
00230 if (info->schedule_length < 0) {
00231 NOTE_Add_To_BB (loop_head, Print_Scheduling_Note, (NOTE_INFO *)info);
00232 }
00233
00234 processed_bbs = BB_SET_Union (processed_bbs, LOOP_DESCR_bbset(cloop),
00235 &MEM_local_pool);
00236 }
00237 L_Free ();
00238 Free_Dominators_Memory ();
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 #define OPND_RESULT -1
00255 #define OPND_NONE -2
00256
00257
00258
00259
00260
00261 BOOL
00262 Is_Delay_Slot_Op (OP *op, BB *bb)
00263 {
00264 if (op != BB_last_op(bb)) return FALSE;
00265 OP *xfer_op = OP_prev(op);
00266 #ifdef TARG_IA64
00267
00268 if (xfer_op == NULL || !TOP_is_xfer(OP_code(xfer_op))) return FALSE;
00269 #else
00270 if (xfer_op == NULL || !OP_xfer(xfer_op)) return FALSE;
00271 #endif
00272 return TRUE;
00273 }
00274
00275
00276
00277
00278
00279
00280 static BOOL
00281 Detect_Post_Hazard (OP *op1, INT opnd, OP *op2)
00282 {
00283 TN *tn;
00284 ISA_REGISTER_CLASS cl;
00285 REGISTER reg;
00286
00287 switch (opnd) {
00288 case OPND_NONE:
00289 return FALSE;
00290
00291 case OPND_RESULT:
00292
00293 tn = OP_result(op1,0 );
00294 cl = TN_register_class(tn);
00295 reg = TN_register(tn);
00296
00297
00298 if (TN_is_zero_reg (tn)) {
00299 return FALSE;
00300 }
00301
00302 return OP_Refs_Reg (op2, cl, reg) || CGTARG_OP_Refs_TN (op2, tn);
00303
00304 default:
00305
00306 tn = OP_opnd(op1, opnd);
00307 cl = TN_register_class(tn);
00308 reg = TN_register(tn);
00309
00310 return OP_Defs_Reg (op2, cl, reg) || CGTARG_OP_Defs_TN (op2, tn);
00311 }
00312
00313 }
00314
00315
00316
00317
00318
00319
00320 static BOOL
00321 Detect_Pre_Hazard (OP *op1, OP *op2, INT opnd)
00322 {
00323 TN *operand;
00324 ISA_REGISTER_CLASS cl;
00325 REGISTER reg;
00326
00327
00328 operand = OP_opnd(op2,opnd);
00329 cl = TN_register_class(operand);
00330 reg = TN_register(operand);
00331 return OP_Defs_Reg (op1, cl, reg) || CGTARG_OP_Defs_TN (op1, operand);
00332 }
00333
00334
00335
00336
00337
00338
00339 static void
00340 Handle_Pre_Hazard (OP *op, INT opnd, INT ops_to_check)
00341 {
00342 OP *scan_op = op;
00343 BOOL add_noops = FALSE;
00344
00345 while (ops_to_check > 0) {
00346 scan_op = OP_prev(scan_op);
00347 if (scan_op == NULL) {
00348 add_noops = TRUE;
00349 break;
00350 }
00351
00352 if (OP_dummy(scan_op)) continue;
00353
00354 if (Detect_Pre_Hazard (scan_op, op, opnd))
00355 {
00356 add_noops = TRUE;
00357 break;
00358 }
00359 ops_to_check-= OP_Real_Ops (scan_op);;
00360 }
00361
00362 if (add_noops) {
00363
00364 BB_Insert_Noops (op, ops_to_check, TRUE);
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373 static void
00374 Handle_Post_Hazard (OP *op, INT opnd, INT ops_to_check)
00375 {
00376 OP *scan_op = op;
00377 BOOL add_noops = FALSE;
00378
00379 while (ops_to_check > 0) {
00380 scan_op = OP_next(scan_op);
00381 if (scan_op == NULL) {
00382 add_noops = TRUE;
00383 break;
00384 }
00385
00386 if (OP_dummy(scan_op)) continue;
00387
00388 if (Detect_Post_Hazard (op, opnd, scan_op)) {
00389 add_noops = TRUE;
00390 break;
00391 }
00392 ops_to_check -= OP_Real_Ops (scan_op);
00393 #ifdef TARG_IA64
00394
00395 if (TOP_is_xfer(OP_code(scan_op))) ops_to_check -= 1;
00396 #else
00397 if (OP_xfer(scan_op)) ops_to_check -= 1;
00398 #endif
00399 }
00400 if (add_noops) {
00401
00402 BB_Insert_Noops (op, ops_to_check, FALSE);
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411 #define PQ_SIZE 4
00412 static struct {
00413 OP *op;
00414 mINT16 opnd;
00415 mINT16 numops;
00416 } post_Q[PQ_SIZE+1];
00417
00418
00419
00420
00421
00422
00423 static void
00424 Add_Post_Hazard_To_Q (OP *op, INT opnd, INT numops)
00425 {
00426 INT i;
00427
00428 for (i = PQ_SIZE; i > 0; i--) {
00429 post_Q[i] = post_Q[i-1];
00430 }
00431 post_Q[0].op = op;
00432 post_Q[0].opnd = opnd;
00433 post_Q[0].numops = numops;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 static void
00443 Handle_Additive_Hazards (OP *op, INT opnd, INT numops)
00444 {
00445 INT i;
00446
00447 for (i = 0; i < PQ_SIZE; i++) {
00448 OP *pq_op = post_Q[i].op;
00449 if (pq_op == NULL) break;
00450 if (Detect_Post_Hazard (pq_op, post_Q[i].opnd, op)) {
00451 OP *tmp_op;
00452 INT pq_noops = post_Q[i].numops;
00453
00454 if (Detect_Pre_Hazard (pq_op, op, opnd)) pq_noops += numops;
00455
00456 for (tmp_op = OP_next(pq_op); tmp_op != op; tmp_op = OP_next(tmp_op)) {
00457 pq_noops -= OP_Real_Ops (tmp_op);
00458 }
00459 if (pq_noops > 0) {
00460
00461 BB_Insert_Noops (op, pq_noops, TRUE);
00462 }
00463 }
00464 }
00465 }
00466
00467
00468
00469
00470
00471 BOOL
00472 Is_There_OP_Dependence(OP *op, OP *prev_op)
00473 {
00474
00475 INT j;
00476
00477 if (CGTARG_Dependence_Required(prev_op, op)) return TRUE;
00478
00479 for (j = 0; j < OP_results(prev_op); ++j) {
00480 TN *result_tn = OP_result(prev_op, j);
00481 ISA_REGISTER_CLASS cl = TN_register_class(result_tn);
00482 REGISTER reg = TN_register(result_tn);
00483
00484 BOOL read_dependence =
00485 OP_Refs_Reg (op, cl, reg) || CGTARG_OP_Refs_TN (op, result_tn);
00486
00487 BOOL write_dependence =
00488 OP_Defs_Reg (op, cl, reg) || CGTARG_OP_Defs_TN (op, result_tn);
00489
00490 if (read_dependence || write_dependence) {
00491
00492
00493
00494
00495
00496
00497 #ifdef TARG_IA64
00498
00499 if (OP_icmp(prev_op) && TOP_is_xfer(OP_code(op))) {
00500 #else
00501 if (OP_icmp(prev_op) && OP_xfer(op)) {
00502 #endif
00503
00504 TN *tn1, *tn2;
00505 OP *cmp_op;
00506
00507 CGTARG_Analyze_Compare(op, &tn1, &tn2, &cmp_op);
00508 if (prev_op == cmp_op) continue;
00509
00510 #ifdef TARG_IA64
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 if (read_dependence && OP_cond_def(prev_op) && !cmp_op) continue;
00521
00522 if (read_dependence) continue;
00523 #endif
00524 }
00525
00526
00527 if (TN_is_true_pred(result_tn)) continue;
00528
00529
00530 if (OP_has_disjoint_predicate(prev_op, op)) continue;
00531
00532
00533
00534
00535
00536
00537
00538 #ifdef TARG_IA64
00539 if (read_dependence && CGTARG_Is_OP_Check_Load(prev_op)) continue;
00540 #else
00541 if (read_dependence && CGTARG_Is_OP_Speculative(prev_op)) continue;
00542 #endif
00543
00544 #ifdef TARG_IA64
00545
00546 if (read_dependence && OP_code(prev_op)==TOP_mov_t_br && OP_xfer(op)) continue;
00547 #endif
00548 return TRUE;
00549 }
00550 }
00551
00552 return FALSE;
00553 }
00554
00555
00556
00557
00558
00559 static BOOL
00560 Is_There_Group_Dependence(OP *op, VECTOR *bundle_vector)
00561 {
00562
00563 for (INT i = 0; i < VECTOR_count(*bundle_vector); ++i) {
00564 OP *prev_op = (OP *) VECTOR_element(*bundle_vector, i);
00565 if (Is_There_OP_Dependence(op, prev_op)) return TRUE;
00566 }
00567
00568 return FALSE;
00569 }
00570
00571
00572
00573
00574
00575 static BOOL
00576 Delay_Scheduling_OP(OP *op, INT slot_pos, TI_BUNDLE *bundle)
00577 {
00578
00579
00580
00581
00582
00583
00584 #ifdef TARG_IA64
00585
00586 if (BB_last_op(OP_bb(op)) == op && TOP_is_xfer(OP_code(op)) &&
00587 #else
00588 if (BB_last_op(OP_bb(op)) == op && OP_xfer(op) &&
00589 #endif
00590 (slot_pos != (ISA_MAX_SLOTS - 1)))
00591 return TRUE;
00592
00593
00594
00595 if (OP_l_group(op) && (slot_pos != (ISA_MAX_SLOTS - 1)) &&
00596 !TI_BUNDLE_stop_bit(bundle, slot_pos))
00597 return TRUE;
00598
00599 return FALSE;
00600
00601 }
00602
00603
00604
00605
00606
00607
00608 static void
00609 Check_For_Bundle_Hazards(OP *op, TI_BUNDLE *bundle, VECTOR *bundle_vector)
00610 {
00611
00612 BOOL slot_avail = FALSE;
00613
00614
00615
00616
00617
00618
00619
00620 INT slot_pos = -1;
00621 INT stop_pos = -2;
00622
00623
00624 if (OP_bundled(op)) return;
00625
00626 INT i;
00627 ISA_EXEC_UNIT_PROPERTY prop;
00628 INT ti_err;
00629 BOOL stop_bit_reqd = FALSE;
00630
00631
00632
00633
00634
00635 BOOL bundling_reqd = (OP_code(op) != TOP_asm);
00636
00637 if (bundling_reqd) {
00638
00639
00640 stop_bit_reqd = Is_There_Group_Dependence(op, bundle_vector);
00641
00642 FOR_ALL_SLOT_MEMBERS (bundle, i) {
00643
00644
00645
00646 stop_bit_reqd |= (i > 0) && OP_f_group(op);
00647
00648
00649 if (CGTARG_Bundle_Slot_Available (bundle, op, i, &prop,
00650 stop_bit_reqd, NULL)) {
00651
00652
00653 if (Delay_Scheduling_OP(op, i, bundle)) continue;
00654 slot_avail = TRUE;
00655 slot_pos = i;
00656
00657 if (stop_bit_reqd) {
00658 if (i > 0) stop_pos = i - 1;
00659 else stop_pos = -1;
00660 }
00661 break;
00662 }
00663 }
00664 }
00665
00666
00667 if (slot_avail) {
00668 Set_OP_bundled (op);
00669 TI_BUNDLE_Reserve_Slot (bundle, slot_pos, prop);
00670
00671
00672 if (stop_pos >= 0) {
00673 TI_BUNDLE_Reserve_Stop_Bit (bundle, stop_pos);
00674 }
00675
00676
00677
00678
00679 if (stop_pos >= -1) {
00680 VECTOR_Reset (*bundle_vector);
00681 }
00682
00683 VECTOR_Add_Element (*bundle_vector, op);
00684
00685
00686 CGTARG_Handle_Bundle_Hazard(op, bundle, bundle_vector, slot_avail,
00687 slot_pos, slot_pos, stop_bit_reqd, prop);
00688
00689
00690
00691 if (stop_pos >= -1) {
00692 OP *last_real_op = Last_Real_OP(op);
00693 Set_OP_end_group(last_real_op);
00694 }
00695 }
00696
00697 BOOL bundle_full = TI_BUNDLE_Is_Full(bundle, &ti_err);
00698 FmtAssert(ti_err != TI_RC_ERROR, ("%s", TI_errmsg));
00699
00700
00701 if (!slot_avail || (BB_last_real_op(OP_bb(op)) == op) || bundle_full) {
00702
00703
00704 CGTARG_Handle_Bundle_Hazard (op, bundle, bundle_vector, slot_avail,
00705 slot_pos, ISA_MAX_SLOTS, stop_bit_reqd, prop);
00706
00707 TI_BUNDLE_Clear (bundle);
00708
00709
00710
00711
00712
00713
00714 if (OP_l_group(op)) {
00715 Set_OP_end_group(op);
00716 VECTOR_Reset (*bundle_vector);
00717 }
00718
00719 if (OP_f_group(op) && OP_prev(op)) {
00720 OP *last_real_op = Last_Real_OP (op);
00721 Set_OP_end_group(last_real_op);
00722 VECTOR_Reset (*bundle_vector);
00723 VECTOR_Add_Element (*bundle_vector, op);
00724 }
00725
00726
00727
00728
00729
00730 if (bundle_full && OP_next(op)) {
00731 OP *next_op = OP_next(op);
00732 if (Is_There_Group_Dependence(next_op, bundle_vector)) {
00733 Set_OP_end_group(op);
00734 VECTOR_Reset (*bundle_vector);
00735 }
00736 }
00737
00738
00739 if (!bundling_reqd) {
00740 Set_OP_end_group(op);
00741 return;
00742 }
00743
00744
00745 if (!slot_avail) {
00746 FOR_ALL_SLOT_MEMBERS (bundle, i) {
00747 stop_bit_reqd = (i > 0) && OP_f_group(op);
00748 if (CGTARG_Bundle_Slot_Available (bundle, op, i, &prop,
00749 stop_bit_reqd, NULL)) {
00750
00751
00752 if (Delay_Scheduling_OP(op, i, bundle)) continue;
00753 slot_pos = i;
00754 if (stop_bit_reqd) {
00755 if (i > 0) stop_pos = i - 1;
00756 else stop_pos = -1;
00757 }
00758 break;
00759 }
00760 }
00761
00762 FmtAssert(slot_pos != -1, ("Slot Position not a legal value"));
00763 Set_OP_bundled (op);
00764 TI_BUNDLE_Reserve_Slot (bundle, slot_pos, prop);
00765 if (stop_pos >= 0) TI_BUNDLE_Reserve_Stop_Bit (bundle, stop_pos);
00766 VECTOR_Add_Element (*bundle_vector, op);
00767
00768
00769 if ((BB_last_real_op((OP_bb(op))) == op) || (slot_pos != 0)) {
00770 INT max_pos = (BB_last_real_op((OP_bb(op))) == op &&
00771 ISA_PACK_Inst_Words(OP_code(op)) == 1) ?
00772 ISA_MAX_SLOTS : slot_pos;
00773 CGTARG_Handle_Bundle_Hazard (op, bundle, bundle_vector, TRUE,
00774 slot_pos, max_pos, stop_bit_reqd, prop);
00775 if (stop_pos >= -1) {
00776 OP *last_real_op = Last_Real_OP(op);
00777 Set_OP_end_group(last_real_op);
00778 VECTOR_Reset (*bundle_vector);
00779 VECTOR_Add_Element (*bundle_vector, op);
00780 }
00781
00782 if (TI_BUNDLE_Is_Full(bundle, &ti_err)) {
00783 TI_BUNDLE_Clear(bundle);
00784 }
00785 }
00786 }
00787 }
00788 }
00789
00790
00791
00792
00793
00794
00795 static void
00796 Check_For_Other_Hazards(OP *op)
00797 {
00798
00799 TOP opcode = OP_code(op);
00800 INT numops;
00801 INT opnd;
00802 INT result;
00803 INT errata_num;
00804 INT ti_err;
00805
00806
00807 numops = TI_LATENCY_Operand_Hazard (opcode, &opnd, &ti_err);
00808 FmtAssert(ti_err != TI_RC_ERROR, ("%s", TI_errmsg));
00809 if (numops < 0) {
00810
00811
00812
00813
00814 Handle_Additive_Hazards (op, opnd, -numops);
00815 Handle_Pre_Hazard (op, opnd, -numops);
00816 } else if (numops > 0) {
00817
00818 Handle_Post_Hazard (op, opnd, numops);
00819 Add_Post_Hazard_To_Q (op, opnd, numops);
00820 }
00821
00822
00823 numops = TI_LATENCY_Result_Hazard (opcode, &result, &ti_err);
00824 FmtAssert(ti_err != TI_RC_ERROR, ("%s", TI_errmsg));
00825 if (numops != 0) {
00826
00827 FmtAssert (numops > 0, ("Handle_All_Hazards: can't handle result pre-hazard"));
00828 Is_True(result == 0, ("can't handle hazard for result number %d", result));
00829 Handle_Post_Hazard (op, OPND_RESULT, numops);
00830 Add_Post_Hazard_To_Q (op, OPND_RESULT, numops);
00831 }
00832
00833 if (PROC_has_branch_delay_slot()) {
00834
00835 #ifdef TARG_IA64
00836
00837 if (TOP_is_xfer(OP_code(op))) {
00838 #else
00839 if (OP_xfer(op)) {
00840 #endif
00841 Handle_Post_Hazard (op, OPND_NONE, 1);
00842 Add_Post_Hazard_To_Q (op, OPND_NONE, 1);
00843 }
00844 }
00845
00846
00847 numops = TI_LATENCY_Errata_Hazard (opcode, &errata_num, &ti_err);
00848 FmtAssert(ti_err != TI_RC_ERROR, ("%s", TI_errmsg));
00849 if (numops != 0) {
00850 CGTARG_Handle_Errata_Hazard (op, errata_num, numops);
00851 }
00852 }
00853
00854
00855
00856
00857
00858 void
00859 Check_For_Delay_Slot_Hazards (BB *bb)
00860 {
00861
00862 OP *last_op = BB_last_op(bb);
00863
00864
00865 if (Is_Delay_Slot_Op (last_op, bb) && OP_has_hazard(last_op)) {
00866 BB_Move_Delay_Slot_Op (bb);
00867 }
00868
00869 #ifndef KEY
00870
00871
00872 if (Is_Delay_Slot_Op (last_op, bb) &&
00873 (OP_imul(last_op) || OP_idiv(last_op))) {
00874 OP *xfer_op = OP_prev(last_op);
00875 if (xfer_op && OP_uncond(last_op)) {
00876 BB_Move_Delay_Slot_Op (bb);
00877 BB_Insert_Noops(xfer_op, 1, FALSE);
00878 }
00879 }
00880 #endif
00881 }
00882
00883 #if defined(TARG_SL)
00884 void Repl_Tmp_TN(BB *bb)
00885 {
00886 OP *op;
00887 OP *prev_op;
00888 TN *tmp_tn;
00889
00890 prev_op = BB_first_op(bb);
00891 op = OP_next(prev_op);
00892 tmp_tn = TMP1_TN;
00893 while (op) {
00894 Is_True(prev_op, ("prev_op is null in BB %d",BB_id(bb)));
00895 for (INT j = 0; j < OP_results(prev_op); ++j) {
00896 TN *result_tn = OP_result(prev_op, j);
00897 ISA_REGISTER_CLASS cl = TN_register_class(result_tn);
00898
00899 if (!OP_cond_def(prev_op) && !OP_same_res(op) && !OP_same_res(prev_op)) {
00900
00901
00902 if (cl == ISA_REGISTER_CLASS_integer) {
00903 REGISTER reg = TN_register(result_tn);
00904 BOOL read_dep = CGTARG_OP_Refs_TN(op, result_tn);
00905 BOOL write_dep = CGTARG_OP_Defs_TN(op, result_tn);
00906 BOOL read_dep2 = OP_Refs_Reg(op, cl, reg);
00907 BOOL write_dep2 = OP_Defs_Reg(op, cl, reg);
00908
00909 if (CGTARG_OP_Refs_TN(prev_op, tmp_tn) || OP_Refs_Reg(prev_op, cl, TN_register(tmp_tn)))
00910 continue;
00911
00912 if ((read_dep && write_dep) || (read_dep2 && write_dep2)) {
00913
00914
00915
00916 Is_True(OP_has_result(prev_op), ("result to be repl conflict"));
00917 Set_OP_result(prev_op, j, tmp_tn);
00918
00919 BOOL mod = FALSE;
00920 for ( INT num = 0; num < OP_opnds(op); num++ ) {
00921 TN *opnd_tn = OP_opnd(op, num);
00922 if (opnd_tn == result_tn) {
00923 Set_OP_opnd(op, num, tmp_tn);
00924 mod = TRUE;
00925 }
00926 else if (TN_is_register(opnd_tn) && (TN_register_class(opnd_tn)==cl) &&
00927 TN_register(opnd_tn) == reg) {
00928 Set_OP_opnd(op, num, tmp_tn);
00929 mod = TRUE;
00930 }
00931
00932 }
00933 Is_True(mod, ("cannot find result tn to fix up"));
00934 if (tmp_tn == TMP1_TN) {
00935 tmp_tn = TMP2_TN;
00936 } else {
00937 tmp_tn = TMP1_TN;
00938 }
00939
00940
00941 continue;
00942 }
00943 }
00944 }
00945 }
00946 prev_op = op;
00947 op = OP_next(op);
00948 }
00949 }
00950
00951 #endif
00952
00953
00954
00955
00956
00957 void
00958 Handle_All_Hazards (BB *bb)
00959 {
00960 OP *op;
00961 OP *last_op = BB_last_op(bb);
00962
00963 if (last_op == NULL) return;
00964
00965
00966 if (PROC_has_branch_delay_slot())
00967 Check_For_Delay_Slot_Hazards(bb);
00968
00969 bzero (post_Q, sizeof(post_Q));
00970
00971 VECTOR bundle_vector = VECTOR_Init (BB_length(bb) + 1, &MEM_local_pool);
00972 TI_BUNDLE *bundle = TYPE_MEM_POOL_ALLOC (TI_BUNDLE, &MEM_local_pool);
00973 bzero (bundle, sizeof(bundle));
00974 bundle->bundle_info = TYPE_MEM_POOL_ALLOC (ISA_BUNDLE_INFO, &MEM_local_pool);
00975 TI_BUNDLE_Clear(bundle);
00976
00977 FOR_ALL_BB_OPs_FWD (bb, op) {
00978
00979
00980 if (PROC_has_bundles() && LOCS_Enable_Bundle_Formation) {
00981 #ifdef TARG_MIPS
00982
00983
00984 FmtAssert(FALSE, ("No support for bundle at KEY\n"));
00985 #endif
00986
00987
00988 if (!OP_dummy(op) && !OP_bundled(op))
00989 Check_For_Bundle_Hazards (op, bundle, &bundle_vector);
00990 }
00991
00992
00993 Check_For_Other_Hazards(op);
00994
00995 }
00996
00997 Insert_Stop_Bits(bb);
00998 #if defined(TARG_SL)
00999
01000 Repl_Tmp_TN(bb);
01001 #endif
01002 }